diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/cdrom/sbpcd.c |
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/cdrom/sbpcd.c')
-rw-r--r-- | drivers/cdrom/sbpcd.c | 5978 |
1 files changed, 5978 insertions, 0 deletions
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c new file mode 100644 index 00000000000..fc2c433f6a2 --- /dev/null +++ b/drivers/cdrom/sbpcd.c | |||
@@ -0,0 +1,5978 @@ | |||
1 | /* | ||
2 | * sbpcd.c CD-ROM device driver for the whole family of traditional, | ||
3 | * non-ATAPI IDE-style Matsushita/Panasonic CR-5xx drives. | ||
4 | * Works with SoundBlaster compatible cards and with "no-sound" | ||
5 | * interface cards like Lasermate, Panasonic CI-101P, Teac, ... | ||
6 | * Also for the Longshine LCS-7260 drive. | ||
7 | * Also for the IBM "External ISA CD-Rom" drive. | ||
8 | * Also for the CreativeLabs CD200 drive. | ||
9 | * Also for the TEAC CD-55A drive. | ||
10 | * Also for the ECS-AT "Vertos 100" drive. | ||
11 | * Not for Sanyo drives (but for the H94A, sjcd is there...). | ||
12 | * Not for any other Funai drives than the CD200 types (sometimes | ||
13 | * labelled E2550UA or MK4015 or 2800F). | ||
14 | */ | ||
15 | |||
16 | #define VERSION "v4.63 Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000" | ||
17 | |||
18 | /* Copyright (C) 1993, 1994, 1995 Eberhard Moenkeberg <emoenke@gwdg.de> | ||
19 | * | ||
20 | * This program is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU General Public License as published by | ||
22 | * the Free Software Foundation; either version 2, or (at your option) | ||
23 | * any later version. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * (for example /usr/src/linux/COPYING); if not, write to the Free | ||
27 | * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | * | ||
29 | * If you change this software, you should mail a .diff file with some | ||
30 | * description lines to emoenke@gwdg.de. I want to know about it. | ||
31 | * | ||
32 | * If you are the editor of a Linux CD, you should enable sbpcd.c within | ||
33 | * your boot floppy kernel and send me one of your CDs for free. | ||
34 | * | ||
35 | * If you would like to port the driver to an other operating system (f.e. | ||
36 | * FreeBSD or NetBSD) or use it as an information source, you shall not be | ||
37 | * restricted by the GPL under the following conditions: | ||
38 | * a) the source code of your work is freely available | ||
39 | * b) my part of the work gets mentioned at all places where your | ||
40 | * authorship gets mentioned | ||
41 | * c) I receive a copy of your code together with a full installation | ||
42 | * package of your operating system for free. | ||
43 | * | ||
44 | * | ||
45 | * VERSION HISTORY | ||
46 | * | ||
47 | * 0.1 initial release, April/May 93, after mcd.c (Martin Harriss) | ||
48 | * | ||
49 | * 0.2 thek "repeat:"-loop in do_sbpcd_request did not check for | ||
50 | * end-of-request_queue (resulting in kernel panic). | ||
51 | * Flow control seems stable, but throughput is not better. | ||
52 | * | ||
53 | * 0.3 interrupt locking totally eliminated (maybe "inb" and "outb" | ||
54 | * are still locking) - 0.2 made keyboard-type-ahead losses. | ||
55 | * check_sbpcd_media_change added (to use by isofs/inode.c) | ||
56 | * - but it detects almost nothing. | ||
57 | * | ||
58 | * 0.4 use MAJOR 25 definitely. | ||
59 | * Almost total re-design to support double-speed drives and | ||
60 | * "naked" (no sound) interface cards ("LaserMate" interface type). | ||
61 | * Flow control should be exact now. | ||
62 | * Don't occupy the SbPro IRQ line (not needed either); will | ||
63 | * live together with Hannu Savolainen's sndkit now. | ||
64 | * Speeded up data transfer to 150 kB/sec, with help from Kai | ||
65 | * Makisara, the "provider" of the "mt" tape utility. | ||
66 | * Give "SpinUp" command if necessary. | ||
67 | * First steps to support up to 4 drives (but currently only one). | ||
68 | * Implemented audio capabilities - workman should work, xcdplayer | ||
69 | * gives some problems. | ||
70 | * This version is still consuming too much CPU time, and | ||
71 | * sleeping still has to be worked on. | ||
72 | * During "long" implied seeks, it seems possible that a | ||
73 | * ReadStatus command gets ignored. That gives the message | ||
74 | * "ResponseStatus timed out" (happens about 6 times here during | ||
75 | * a "ls -alR" of the YGGDRASIL LGX-Beta CD). Such a case is | ||
76 | * handled without data error, but it should get done better. | ||
77 | * | ||
78 | * 0.5 Free CPU during waits (again with help from Kai Makisara). | ||
79 | * Made it work together with the LILO/kernel setup standard. | ||
80 | * Included auto-probing code, as suggested by YGGDRASIL. | ||
81 | * Formal redesign to add DDI debugging. | ||
82 | * There are still flaws in IOCTL (workman with double speed drive). | ||
83 | * | ||
84 | * 1.0 Added support for all drive IDs (0...3, no longer only 0) | ||
85 | * and up to 4 drives on one controller. | ||
86 | * Added "#define MANY_SESSION" for "old" multi session CDs. | ||
87 | * | ||
88 | * 1.1 Do SpinUp for new drives, too. | ||
89 | * Revised for clean compile under "old" kernels (0.99pl9). | ||
90 | * | ||
91 | * 1.2 Found the "workman with double-speed drive" bug: use the driver's | ||
92 | * audio_state, not what the drive is reporting with ReadSubQ. | ||
93 | * | ||
94 | * 1.3 Minor cleanups. | ||
95 | * Refinements regarding Workman. | ||
96 | * | ||
97 | * 1.4 Read XA disks (PhotoCDs) with "old" drives, too (but only the first | ||
98 | * session - no chance to fully access a "multi-session" CD). | ||
99 | * This currently still is too slow (50 kB/sec) - but possibly | ||
100 | * the old drives won't do it faster. | ||
101 | * Implemented "door (un)lock" for new drives (still does not work | ||
102 | * as wanted - no lock possible after an unlock). | ||
103 | * Added some debugging printout for the UPC/EAN code - but my drives | ||
104 | * return only zeroes. Is there no UPC/EAN code written? | ||
105 | * | ||
106 | * 1.5 Laborate with UPC/EAN code (not better yet). | ||
107 | * Adapt to kernel 1.1.8 change (have to explicitly include | ||
108 | * <linux/string.h> now). | ||
109 | * | ||
110 | * 1.6 Trying to read audio frames as data. Impossible with the current | ||
111 | * drive firmware levels, as it seems. Awaiting any hint. ;-) | ||
112 | * Changed "door unlock": repeat it until success. | ||
113 | * Changed CDROMSTOP routine (stop somewhat "softer" so that Workman | ||
114 | * won't get confused). | ||
115 | * Added a third interface type: Sequoia S-1000, as used with the SPEA | ||
116 | * Media FX sound card. This interface (usable for Sony and Mitsumi | ||
117 | * drives, too) needs a special configuration setup and behaves like a | ||
118 | * LaserMate type after that. Still experimental - I do not have such | ||
119 | * an interface. | ||
120 | * Use the "variable BLOCK_SIZE" feature (2048). But it does only work | ||
121 | * if you give the mount option "block=2048". | ||
122 | * The media_check routine is currently disabled; now that it gets | ||
123 | * called as it should I fear it must get synchronized for not to | ||
124 | * disturb the normal driver's activity. | ||
125 | * | ||
126 | * 2.0 Version number bumped - two reasons: | ||
127 | * - reading audio tracks as data works now with CR-562 and CR-563. We | ||
128 | * currently do it by an IOCTL (yet has to get standardized), one frame | ||
129 | * at a time; that is pretty slow. But it works. | ||
130 | * - we are maintaining now up to 4 interfaces (each up to 4 drives): | ||
131 | * did it the easy way - a different MAJOR (25, 26, ...) and a different | ||
132 | * copy of the driver (sbpcd.c, sbpcd2.c, sbpcd3.c, sbpcd4.c - only | ||
133 | * distinguished by the value of SBPCD_ISSUE and the driver's name), | ||
134 | * and a common sbpcd.h file. | ||
135 | * Bettered the "ReadCapacity error" problem with old CR-52x drives (the | ||
136 | * drives sometimes need a manual "eject/insert" before work): just | ||
137 | * reset the drive and do again. Needs lots of resets here and sometimes | ||
138 | * that does not cure, so this can't be the solution. | ||
139 | * | ||
140 | * 2.1 Found bug with multisession CDs (accessing frame 16). | ||
141 | * "read audio" works now with address type CDROM_MSF, too. | ||
142 | * Bigger audio frame buffer: allows reading max. 4 frames at time; this | ||
143 | * gives a significant speedup, but reading more than one frame at once | ||
144 | * gives missing chunks at each single frame boundary. | ||
145 | * | ||
146 | * 2.2 Kernel interface cleanups: timers, init, setup, media check. | ||
147 | * | ||
148 | * 2.3 Let "door lock" and "eject" live together. | ||
149 | * Implemented "close tray" (done automatically during open). | ||
150 | * | ||
151 | * 2.4 Use different names for device registering. | ||
152 | * | ||
153 | * 2.5 Added "#if EJECT" code (default: enabled) to automatically eject | ||
154 | * the tray during last call to "sbpcd_release". | ||
155 | * Added "#if JUKEBOX" code (default: disabled) to automatically eject | ||
156 | * the tray during call to "sbpcd_open" if no disk is in. | ||
157 | * Turn on the CD volume of "compatible" sound cards, too; just define | ||
158 | * SOUND_BASE (in sbpcd.h) accordingly (default: disabled). | ||
159 | * | ||
160 | * 2.6 Nothing new. | ||
161 | * | ||
162 | * 2.7 Added CDROMEJECT_SW ioctl to set the "EJECT" behavior on the fly: | ||
163 | * 0 disables, 1 enables auto-ejecting. Useful to keep the tray in | ||
164 | * during shutdown. | ||
165 | * | ||
166 | * 2.8 Added first support (still BETA, I need feedback or a drive) for | ||
167 | * the Longshine LCS-7260 drives. They appear as double-speed drives | ||
168 | * using the "old" command scheme, extended by tray control and door | ||
169 | * lock functions. | ||
170 | * Found (and fixed preliminary) a flaw with some multisession CDs: we | ||
171 | * have to re-direct not only the accesses to frame 16 (the isofs | ||
172 | * routines drive it up to max. 100), but also those to the continuation | ||
173 | * (repetition) frames (as far as they exist - currently set fix as | ||
174 | * 16..20). | ||
175 | * Changed default of the "JUKEBOX" define. If you use this default, | ||
176 | * your tray will eject if you try to mount without a disk in. Next | ||
177 | * mount command will insert the tray - so, just fill in a disk. ;-) | ||
178 | * | ||
179 | * 2.9 Fulfilled the Longshine LCS-7260 support; with great help and | ||
180 | * experiments by Serge Robyns. | ||
181 | * First attempts to support the TEAC CD-55A drives; but still not | ||
182 | * usable yet. | ||
183 | * Implemented the CDROMMULTISESSION ioctl; this is an attempt to handle | ||
184 | * multi session CDs more "transparent" (redirection handling has to be | ||
185 | * done within the isofs routines, and only for the special purpose of | ||
186 | * obtaining the "right" volume descriptor; accesses to the raw device | ||
187 | * should not get redirected). | ||
188 | * | ||
189 | * 3.0 Just a "normal" increment, with some provisions to do it better. ;-) | ||
190 | * Introduced "#define READ_AUDIO" to specify the maximum number of | ||
191 | * audio frames to grab with one request. This defines a buffer size | ||
192 | * within kernel space; a value of 0 will reserve no such space and | ||
193 | * disable the CDROMREADAUDIO ioctl. A value of 75 enables the reading | ||
194 | * of a whole second with one command, but will use a buffer of more | ||
195 | * than 172 kB. | ||
196 | * Started CD200 support. Drive detection should work, but nothing | ||
197 | * more. | ||
198 | * | ||
199 | * 3.1 Working to support the CD200 and the Teac CD-55A drives. | ||
200 | * AT-BUS style device numbering no longer used: use SCSI style now. | ||
201 | * So, the first "found" device has MINOR 0, regardless of the | ||
202 | * jumpered drive ID. This implies modifications to the /dev/sbpcd* | ||
203 | * entries for some people, but will help the DAU (german TLA, english: | ||
204 | * "newbie", maybe ;-) to install his "first" system from a CD. | ||
205 | * | ||
206 | * 3.2 Still testing with CD200 and CD-55A drives. | ||
207 | * | ||
208 | * 3.3 Working with CD200 support. | ||
209 | * | ||
210 | * 3.4 Auto-probing stops if an address of 0 is seen (to be entered with | ||
211 | * the kernel command line). | ||
212 | * Made the driver "loadable". If used as a module, "audio copy" is | ||
213 | * disabled, and the internal read ahead data buffer has a reduced size | ||
214 | * of 4 kB; so, throughput may be reduced a little bit with slow CPUs. | ||
215 | * | ||
216 | * 3.5 Provisions to handle weird photoCDs which have an interrupted | ||
217 | * "formatting" immediately after the last frames of some files: simply | ||
218 | * never "read ahead" with MultiSession CDs. By this, CPU usage may be | ||
219 | * increased with those CDs, and there may be a loss in speed. | ||
220 | * Re-structured the messaging system. | ||
221 | * The "loadable" version no longer has a limited READ_AUDIO buffer | ||
222 | * size. | ||
223 | * Removed "MANY_SESSION" handling for "old" multi session CDs. | ||
224 | * Added "private" IOCTLs CDROMRESET and CDROMVOLREAD. | ||
225 | * Started again to support the TEAC CD-55A drives, now that I found | ||
226 | * the money for "my own" drive. ;-) | ||
227 | * The TEAC CD-55A support is fairly working now. | ||
228 | * I have measured that the drive "delivers" at 600 kB/sec (even with | ||
229 | * bigger requests than the drive's 64 kB buffer can satisfy), but | ||
230 | * the "real" rate does not exceed 520 kB/sec at the moment. | ||
231 | * Caused by the various changes to build in TEAC support, the timed | ||
232 | * loops are de-optimized at the moment (less throughput with CR-52x | ||
233 | * drives, and the TEAC will give speed only with SBP_BUFFER_FRAMES 64). | ||
234 | * | ||
235 | * 3.6 Fixed TEAC data read problems with SbPro interfaces. | ||
236 | * Initial size of the READ_AUDIO buffer is 0. Can get set to any size | ||
237 | * during runtime. | ||
238 | * | ||
239 | * 3.7 Introduced MAX_DRIVES for some poor interface cards (seen with TEAC | ||
240 | * drives) which allow only one drive (ID 0); this avoids repetitive | ||
241 | * detection under IDs 1..3. | ||
242 | * Elongated cmd_out_T response waiting; necessary for photo CDs with | ||
243 | * a lot of sessions. | ||
244 | * Bettered the sbpcd_open() behavior with TEAC drives. | ||
245 | * | ||
246 | * 3.8 Elongated max_latency for CR-56x drives. | ||
247 | * | ||
248 | * 3.9 Finally fixed the long-known SoundScape/SPEA/Sequoia S-1000 interface | ||
249 | * configuration bug. | ||
250 | * Now Corey, Heiko, Ken, Leo, Vadim/Eric & Werner are invited to copy | ||
251 | * the config_spea() routine into their drivers. ;-) | ||
252 | * | ||
253 | * 4.0 No "big step" - normal version increment. | ||
254 | * Adapted the benefits from 1.3.33. | ||
255 | * Fiddled with CDROMREADAUDIO flaws. | ||
256 | * Avoid ReadCapacity command with CD200 drives (the MKE 1.01 version | ||
257 | * seems not to support it). | ||
258 | * Fulfilled "read audio" for CD200 drives, with help of Pete Heist | ||
259 | * (heistp@rpi.edu). | ||
260 | * | ||
261 | * 4.1 Use loglevel KERN_INFO with printk(). | ||
262 | * Added support for "Vertos 100" drive ("ECS-AT") - it is very similar | ||
263 | * to the Longshine LCS-7260. Give feedback if you can - I never saw | ||
264 | * such a drive, and I have no specs. | ||
265 | * | ||
266 | * 4.2 Support for Teac 16-bit interface cards. Can't get auto-detected, | ||
267 | * so you have to jumper your card to 0x2C0. Still not 100% - come | ||
268 | * in contact if you can give qualified feedback. | ||
269 | * Use loglevel KERN_NOTICE with printk(). If you get annoyed by a | ||
270 | * flood of unwanted messages and the accompanied delay, try to read | ||
271 | * my documentation. Especially the Linux CDROM drivers have to do an | ||
272 | * important job for the newcomers, so the "distributed" version has | ||
273 | * to fit some special needs. Since generations, the flood of messages | ||
274 | * is user-configurable (even at runtime), but to get aware of this, one | ||
275 | * needs a special mental quality: the ability to read. | ||
276 | * | ||
277 | * 4.3 CD200F does not like to receive a command while the drive is | ||
278 | * reading the ToC; still trying to solve it. | ||
279 | * Removed some redundant verify_area calls (yes, Heiko Eissfeldt | ||
280 | * is visiting all the Linux CDROM drivers ;-). | ||
281 | * | ||
282 | * 4.4 Adapted one idea from tiensivu@pilot.msu.edu's "stripping-down" | ||
283 | * experiments: "KLOGD_PAUSE". | ||
284 | * Inhibited "play audio" attempts with data CDs. Provisions for a | ||
285 | * "data-safe" handling of "mixed" (data plus audio) Cds. | ||
286 | * | ||
287 | * 4.5 Meanwhile Gonzalo Tornaria <tornaria@cmat.edu.uy> (GTL) built a | ||
288 | * special end_request routine: we seem to have to take care for not | ||
289 | * to have two processes working at the request list. My understanding | ||
290 | * was and is that ll_rw_blk should not call do_sbpcd_request as long | ||
291 | * as there is still one call active (the first call will care for all | ||
292 | * outstanding I/Os, and if a second call happens, that is a bug in | ||
293 | * ll_rw_blk.c). | ||
294 | * "Check media change" without touching any drive. | ||
295 | * | ||
296 | * 4.6 Use a semaphore to synchronize multi-activity; elaborated by Rob | ||
297 | * Riggs <rriggs@tesser.com>. At the moment, we simply block "read" | ||
298 | * against "ioctl" and vice versa. This could be refined further, but | ||
299 | * I guess with almost no performance increase. | ||
300 | * Experiments to speed up the CD-55A; again with help of Rob Riggs | ||
301 | * (to be true, he gave both, idea & code. ;-) | ||
302 | * | ||
303 | * 4.61 Ported to Uniform CD-ROM driver by | ||
304 | * Heiko Eissfeldt <heiko@colossus.escape.de> with additional | ||
305 | * changes by Erik Andersen <andersee@debian.org> | ||
306 | * | ||
307 | * 4.62 Fix a bug where playing audio left the drive in an unusable state. | ||
308 | * Heiko Eissfeldt <heiko@colossus.escape.de> | ||
309 | * | ||
310 | * November 1999 -- Make kernel-parameter implementation work with 2.3.x | ||
311 | * Removed init_module & cleanup_module in favor of | ||
312 | * module_init & module_exit. | ||
313 | * Torben Mathiasen <tmm@image.dk> | ||
314 | * | ||
315 | * 4.63 Bug fixes for audio annoyances, new legacy CDROM maintainer. | ||
316 | * Annoying things fixed: | ||
317 | * TOC reread on automated disk changes | ||
318 | * TOC reread on manual cd changes | ||
319 | * Play IOCTL tries to play CD before it's actually ready... sometimes. | ||
320 | * CD_AUDIO_COMPLETED state so workman (and other playes) can repeat play. | ||
321 | * Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000 | ||
322 | * | ||
323 | * 4.64 Fix module parameters - were being completely ignored. | ||
324 | * Can also specify max_drives=N as a setup int to get rid of | ||
325 | * "ghost" drives on crap hardware (aren't they all?) Paul Gortmaker | ||
326 | * | ||
327 | * TODO | ||
328 | * implement "read all subchannel data" (96 bytes per frame) | ||
329 | * remove alot of the virtual status bits and deal with hardware status | ||
330 | * move the change of cd for audio to a better place | ||
331 | * add debug levels to insmod parameters (trivial) | ||
332 | * | ||
333 | * special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine | ||
334 | * elaborated speed-up experiments (and the fabulous results!), for | ||
335 | * the "push" towards load-free wait loops, and for the extensive mail | ||
336 | * thread which brought additional hints and bug fixes. | ||
337 | * | ||
338 | */ | ||
339 | |||
340 | /* | ||
341 | * Trying to merge requests breaks this driver horribly (as in it goes | ||
342 | * boom and apparently has done so since 2.3.41). As it is a legacy | ||
343 | * driver for a horribly slow double speed CD on a hideous interface | ||
344 | * designed for polled operation, I won't lose any sleep in simply | ||
345 | * disallowing merging. Paul G. 02/2001 | ||
346 | * | ||
347 | * Thu May 30 14:14:47 CEST 2002: | ||
348 | * | ||
349 | * I have presumably found the reson for the above - there was a bogous | ||
350 | * end_request substitute, which was manipulating the request queues | ||
351 | * incorrectly. If someone has access to the actual hardware, and it's | ||
352 | * still operations - well please free to test it. | ||
353 | * | ||
354 | * Marcin Dalecki | ||
355 | */ | ||
356 | |||
357 | /* | ||
358 | * Add bio/kdev_t changes for 2.5.x required to make it work again. | ||
359 | * Still room for improvement in the request handling here if anyone | ||
360 | * actually cares. Bring your own chainsaw. Paul G. 02/2002 | ||
361 | */ | ||
362 | |||
363 | |||
364 | #include <linux/module.h> | ||
365 | |||
366 | #include <linux/errno.h> | ||
367 | #include <linux/sched.h> | ||
368 | #include <linux/mm.h> | ||
369 | #include <linux/timer.h> | ||
370 | #include <linux/fs.h> | ||
371 | #include <linux/kernel.h> | ||
372 | #include <linux/cdrom.h> | ||
373 | #include <linux/ioport.h> | ||
374 | #include <linux/devfs_fs_kernel.h> | ||
375 | #include <linux/major.h> | ||
376 | #include <linux/string.h> | ||
377 | #include <linux/vmalloc.h> | ||
378 | #include <linux/init.h> | ||
379 | #include <linux/interrupt.h> | ||
380 | |||
381 | #include <asm/system.h> | ||
382 | #include <asm/io.h> | ||
383 | #include <asm/uaccess.h> | ||
384 | #include <stdarg.h> | ||
385 | #include <linux/config.h> | ||
386 | #include "sbpcd.h" | ||
387 | |||
388 | #define MAJOR_NR MATSUSHITA_CDROM_MAJOR | ||
389 | #include <linux/blkdev.h> | ||
390 | |||
391 | /*==========================================================================*/ | ||
392 | #if SBPCD_DIS_IRQ | ||
393 | # define SBPCD_CLI cli() | ||
394 | # define SBPCD_STI sti() | ||
395 | #else | ||
396 | # define SBPCD_CLI | ||
397 | # define SBPCD_STI | ||
398 | #endif | ||
399 | |||
400 | /*==========================================================================*/ | ||
401 | /* | ||
402 | * auto-probing address list | ||
403 | * inspired by Adam J. Richter from Yggdrasil | ||
404 | * | ||
405 | * still not good enough - can cause a hang. | ||
406 | * example: a NE 2000 ethernet card at 300 will cause a hang probing 310. | ||
407 | * if that happens, reboot and use the LILO (kernel) command line. | ||
408 | * The possibly conflicting ethernet card addresses get NOT probed | ||
409 | * by default - to minimize the hang possibilities. | ||
410 | * | ||
411 | * The SB Pro addresses get "mirrored" at 0x6xx and some more locations - to | ||
412 | * avoid a type error, the 0x2xx-addresses must get checked before 0x6xx. | ||
413 | * | ||
414 | * send mail to emoenke@gwdg.de if your interface card is not FULLY | ||
415 | * represented here. | ||
416 | */ | ||
417 | static int sbpcd[] = | ||
418 | { | ||
419 | CDROM_PORT, SBPRO, /* probe with user's setup first */ | ||
420 | #if DISTRIBUTION | ||
421 | 0x230, 1, /* Soundblaster Pro and 16 (default) */ | ||
422 | #if 0 | ||
423 | 0x300, 0, /* CI-101P (default), WDH-7001C (default), | ||
424 | Galaxy (default), Reveal (one default) */ | ||
425 | 0x250, 1, /* OmniCD default, Soundblaster Pro and 16 */ | ||
426 | 0x2C0, 3, /* Teac 16-bit cards */ | ||
427 | 0x260, 1, /* OmniCD */ | ||
428 | 0x320, 0, /* Lasermate, CI-101P, WDH-7001C, Galaxy, Reveal (other default), | ||
429 | Longshine LCS-6853 (default) */ | ||
430 | 0x338, 0, /* Reveal Sound Wave 32 card model #SC600 */ | ||
431 | 0x340, 0, /* Mozart sound card (default), Lasermate, CI-101P */ | ||
432 | 0x360, 0, /* Lasermate, CI-101P */ | ||
433 | 0x270, 1, /* Soundblaster 16 */ | ||
434 | 0x670, 0, /* "sound card #9" */ | ||
435 | 0x690, 0, /* "sound card #9" */ | ||
436 | 0x338, 2, /* SPEA Media FX, Ensonic SoundScape (default) */ | ||
437 | 0x328, 2, /* SPEA Media FX */ | ||
438 | 0x348, 2, /* SPEA Media FX */ | ||
439 | 0x634, 0, /* some newer sound cards */ | ||
440 | 0x638, 0, /* some newer sound cards */ | ||
441 | 0x230, 1, /* some newer sound cards */ | ||
442 | /* due to incomplete address decoding of the SbPro card, these must be last */ | ||
443 | 0x630, 0, /* "sound card #9" (default) */ | ||
444 | 0x650, 0, /* "sound card #9" */ | ||
445 | #ifdef MODULE | ||
446 | /* | ||
447 | * some "hazardous" locations (no harm with the loadable version) | ||
448 | * (will stop the bus if a NE2000 ethernet card resides at offset -0x10) | ||
449 | */ | ||
450 | 0x330, 0, /* Lasermate, CI-101P, WDH-7001C */ | ||
451 | 0x350, 0, /* Lasermate, CI-101P */ | ||
452 | 0x358, 2, /* SPEA Media FX */ | ||
453 | 0x370, 0, /* Lasermate, CI-101P */ | ||
454 | 0x290, 1, /* Soundblaster 16 */ | ||
455 | 0x310, 0, /* Lasermate, CI-101P, WDH-7001C */ | ||
456 | #endif /* MODULE */ | ||
457 | #endif | ||
458 | #endif /* DISTRIBUTION */ | ||
459 | }; | ||
460 | |||
461 | /* | ||
462 | * Protects access to global structures etc. | ||
463 | */ | ||
464 | static __cacheline_aligned DEFINE_SPINLOCK(sbpcd_lock); | ||
465 | static struct request_queue *sbpcd_queue; | ||
466 | |||
467 | MODULE_PARM(sbpcd, "2i"); | ||
468 | MODULE_PARM(max_drives, "i"); | ||
469 | |||
470 | #define NUM_PROBE (sizeof(sbpcd) / sizeof(int)) | ||
471 | |||
472 | /*==========================================================================*/ | ||
473 | |||
474 | #define INLINE inline | ||
475 | |||
476 | /*==========================================================================*/ | ||
477 | /* | ||
478 | * the forward references: | ||
479 | */ | ||
480 | static void sbp_sleep(u_int); | ||
481 | static void mark_timeout_delay(u_long); | ||
482 | static void mark_timeout_data(u_long); | ||
483 | #if 0 | ||
484 | static void mark_timeout_audio(u_long); | ||
485 | #endif | ||
486 | static void sbp_read_cmd(struct request *req); | ||
487 | static int sbp_data(struct request *req); | ||
488 | static int cmd_out(void); | ||
489 | static int DiskInfo(void); | ||
490 | |||
491 | /*==========================================================================*/ | ||
492 | |||
493 | /* | ||
494 | * pattern for printk selection: | ||
495 | * | ||
496 | * (1<<DBG_INF) necessary information | ||
497 | * (1<<DBG_BSZ) BLOCK_SIZE trace | ||
498 | * (1<<DBG_REA) "read" status trace | ||
499 | * (1<<DBG_CHK) "media check" trace | ||
500 | * (1<<DBG_TIM) datarate timer test | ||
501 | * (1<<DBG_INI) initialization trace | ||
502 | * (1<<DBG_TOC) tell TocEntry values | ||
503 | * (1<<DBG_IOC) ioctl trace | ||
504 | * (1<<DBG_STA) "ResponseStatus" trace | ||
505 | * (1<<DBG_ERR) "cc_ReadError" trace | ||
506 | * (1<<DBG_CMD) "cmd_out" trace | ||
507 | * (1<<DBG_WRN) give explanation before auto-probing | ||
508 | * (1<<DBG_MUL) multi session code test | ||
509 | * (1<<DBG_IDX) "drive_id != 0" test code | ||
510 | * (1<<DBG_IOX) some special information | ||
511 | * (1<<DBG_DID) drive ID test | ||
512 | * (1<<DBG_RES) drive reset info | ||
513 | * (1<<DBG_SPI) SpinUp test info | ||
514 | * (1<<DBG_IOS) ioctl trace: "subchannel" | ||
515 | * (1<<DBG_IO2) ioctl trace: general | ||
516 | * (1<<DBG_UPC) show UPC info | ||
517 | * (1<<DBG_XA1) XA mode debugging | ||
518 | * (1<<DBG_LCK) door (un)lock info | ||
519 | * (1<<DBG_SQ1) dump SubQ frame | ||
520 | * (1<<DBG_AUD) "read audio" debugging | ||
521 | * (1<<DBG_SEQ) Sequoia interface configuration trace | ||
522 | * (1<<DBG_LCS) Longshine LCS-7260 debugging trace | ||
523 | * (1<<DBG_CD2) MKE/Funai CD200 debugging trace | ||
524 | * (1<<DBG_TEA) TEAC CD-55A debugging trace | ||
525 | * (1<<DBG_ECS) ECS-AT (Vertos-100) debugging trace | ||
526 | * (1<<DBG_000) unnecessary information | ||
527 | */ | ||
528 | #if DISTRIBUTION | ||
529 | static int sbpcd_debug = (1<<DBG_INF); | ||
530 | #else | ||
531 | static int sbpcd_debug = 0 & ((1<<DBG_INF) | | ||
532 | (1<<DBG_TOC) | | ||
533 | (1<<DBG_MUL) | | ||
534 | (1<<DBG_UPC)); | ||
535 | #endif /* DISTRIBUTION */ | ||
536 | |||
537 | static int sbpcd_ioaddr = CDROM_PORT; /* default I/O base address */ | ||
538 | static int sbpro_type = SBPRO; | ||
539 | static unsigned char f_16bit; | ||
540 | static unsigned char do_16bit; | ||
541 | static int CDo_command, CDo_reset; | ||
542 | static int CDo_sel_i_d, CDo_enable; | ||
543 | static int CDi_info, CDi_status, CDi_data; | ||
544 | static struct cdrom_msf msf; | ||
545 | static struct cdrom_ti ti; | ||
546 | static struct cdrom_tochdr tochdr; | ||
547 | static struct cdrom_tocentry tocentry; | ||
548 | static struct cdrom_subchnl SC; | ||
549 | static struct cdrom_volctrl volctrl; | ||
550 | static struct cdrom_read_audio read_audio; | ||
551 | |||
552 | static unsigned char msgnum; | ||
553 | static char msgbuf[80]; | ||
554 | |||
555 | static int max_drives = MAX_DRIVES; | ||
556 | #ifndef MODULE | ||
557 | static unsigned char setup_done; | ||
558 | static const char *str_sb_l = "soundblaster"; | ||
559 | static const char *str_sp_l = "spea"; | ||
560 | static const char *str_ss_l = "soundscape"; | ||
561 | static const char *str_t16_l = "teac16bit"; | ||
562 | static const char *str_ss = "SoundScape"; | ||
563 | #endif | ||
564 | static const char *str_sb = "SoundBlaster"; | ||
565 | static const char *str_lm = "LaserMate"; | ||
566 | static const char *str_sp = "SPEA"; | ||
567 | static const char *str_t16 = "Teac16bit"; | ||
568 | static const char *type; | ||
569 | static const char *major_name="sbpcd"; | ||
570 | |||
571 | /*==========================================================================*/ | ||
572 | |||
573 | #ifdef FUTURE | ||
574 | static DECLARE_WAIT_QUEUE_HEAD(sbp_waitq); | ||
575 | #endif /* FUTURE */ | ||
576 | |||
577 | static int teac=SBP_TEAC_SPEED; | ||
578 | static int buffers=SBP_BUFFER_FRAMES; | ||
579 | |||
580 | static u_char family0[]="MATSHITA"; /* MKE CR-521, CR-522, CR-523 */ | ||
581 | static u_char family1[]="CR-56"; /* MKE CR-562, CR-563 */ | ||
582 | static u_char family2[]="CD200"; /* MKE CD200, Funai CD200F */ | ||
583 | static u_char familyL[]="LCS-7260"; /* Longshine LCS-7260 */ | ||
584 | static u_char familyT[]="CD-55"; /* TEAC CD-55A */ | ||
585 | static u_char familyV[]="ECS-AT"; /* ECS Vertos 100 */ | ||
586 | |||
587 | static u_int recursion; /* internal testing only */ | ||
588 | static u_int fatal_err; /* internal testing only */ | ||
589 | static u_int response_count; | ||
590 | static u_int flags_cmd_out; | ||
591 | static u_char cmd_type; | ||
592 | static u_char drvcmd[10]; | ||
593 | static u_char infobuf[20]; | ||
594 | static u_char xa_head_buf[CD_XA_HEAD]; | ||
595 | static u_char xa_tail_buf[CD_XA_TAIL]; | ||
596 | |||
597 | #if OLD_BUSY | ||
598 | static volatile u_char busy_data; | ||
599 | static volatile u_char busy_audio; /* true semaphores would be safer */ | ||
600 | #endif /* OLD_BUSY */ | ||
601 | static DECLARE_MUTEX(ioctl_read_sem); | ||
602 | static u_long timeout; | ||
603 | static volatile u_char timed_out_delay; | ||
604 | static volatile u_char timed_out_data; | ||
605 | #if 0 | ||
606 | static volatile u_char timed_out_audio; | ||
607 | #endif | ||
608 | static u_int datarate= 1000000; | ||
609 | static u_int maxtim16=16000000; | ||
610 | static u_int maxtim04= 4000000; | ||
611 | static u_int maxtim02= 2000000; | ||
612 | static u_int maxtim_8= 30000; | ||
613 | #if LONG_TIMING | ||
614 | static u_int maxtim_data= 9000; | ||
615 | #else | ||
616 | static u_int maxtim_data= 3000; | ||
617 | #endif /* LONG_TIMING */ | ||
618 | #if DISTRIBUTION | ||
619 | static int n_retries=6; | ||
620 | #else | ||
621 | static int n_retries=6; | ||
622 | #endif | ||
623 | /*==========================================================================*/ | ||
624 | |||
625 | static int ndrives; | ||
626 | static u_char drv_pattern[NR_SBPCD]={speed_auto,speed_auto,speed_auto,speed_auto}; | ||
627 | |||
628 | /*==========================================================================*/ | ||
629 | /* | ||
630 | * drive space begins here (needed separate for each unit) | ||
631 | */ | ||
632 | static struct sbpcd_drive { | ||
633 | char drv_id; /* "jumpered" drive ID or -1 */ | ||
634 | char drv_sel; /* drive select lines bits */ | ||
635 | |||
636 | char drive_model[9]; | ||
637 | u_char firmware_version[4]; | ||
638 | char f_eject; /* auto-eject flag: 0 or 1 */ | ||
639 | u_char *sbp_buf; /* Pointer to internal data buffer, | ||
640 | space allocated during sbpcd_init() */ | ||
641 | u_int sbp_bufsiz; /* size of sbp_buf (# of frames) */ | ||
642 | int sbp_first_frame; /* First frame in buffer */ | ||
643 | int sbp_last_frame; /* Last frame in buffer */ | ||
644 | int sbp_read_frames; /* Number of frames being read to buffer */ | ||
645 | int sbp_current; /* Frame being currently read */ | ||
646 | |||
647 | u_char mode; /* read_mode: READ_M1, READ_M2, READ_SC, READ_AU */ | ||
648 | u_char *aud_buf; /* Pointer to audio data buffer, | ||
649 | space allocated during sbpcd_init() */ | ||
650 | u_int sbp_audsiz; /* size of aud_buf (# of raw frames) */ | ||
651 | u_int drv_type; | ||
652 | u_char drv_options; | ||
653 | int status_bits; | ||
654 | u_char diskstate_flags; | ||
655 | u_char sense_byte; | ||
656 | |||
657 | u_char CD_changed; | ||
658 | char open_count; | ||
659 | u_char error_byte; | ||
660 | |||
661 | u_char f_multisession; | ||
662 | u_int lba_multi; | ||
663 | int first_session; | ||
664 | int last_session; | ||
665 | int track_of_last_session; | ||
666 | |||
667 | u_char audio_state; | ||
668 | u_int pos_audio_start; | ||
669 | u_int pos_audio_end; | ||
670 | char vol_chan0; | ||
671 | u_char vol_ctrl0; | ||
672 | char vol_chan1; | ||
673 | u_char vol_ctrl1; | ||
674 | #if 000 /* no supported drive has it */ | ||
675 | char vol_chan2; | ||
676 | u_char vol_ctrl2; | ||
677 | char vol_chan3; | ||
678 | u_char vol_ctrl3; | ||
679 | #endif /*000 */ | ||
680 | u_char volume_control; /* TEAC on/off bits */ | ||
681 | |||
682 | u_char SubQ_ctl_adr; | ||
683 | u_char SubQ_trk; | ||
684 | u_char SubQ_pnt_idx; | ||
685 | u_int SubQ_run_tot; | ||
686 | u_int SubQ_run_trk; | ||
687 | u_char SubQ_whatisthis; | ||
688 | |||
689 | u_char UPC_ctl_adr; | ||
690 | u_char UPC_buf[7]; | ||
691 | |||
692 | int frame_size; | ||
693 | int CDsize_frm; | ||
694 | |||
695 | u_char xa_byte; /* 0x20: XA capabilities */ | ||
696 | u_char n_first_track; /* binary */ | ||
697 | u_char n_last_track; /* binary (not bcd), 0x01...0x63 */ | ||
698 | u_int size_msf; /* time of whole CD, position of LeadOut track */ | ||
699 | u_int size_blk; | ||
700 | |||
701 | u_char TocEnt_nixbyte; /* em */ | ||
702 | u_char TocEnt_ctl_adr; | ||
703 | u_char TocEnt_number; | ||
704 | u_char TocEnt_format; /* em */ | ||
705 | u_int TocEnt_address; | ||
706 | #ifdef SAFE_MIXED | ||
707 | char has_data; | ||
708 | #endif /* SAFE_MIXED */ | ||
709 | u_char ored_ctl_adr; /* to detect if CDROM contains data tracks */ | ||
710 | |||
711 | struct { | ||
712 | u_char nixbyte; /* em */ | ||
713 | u_char ctl_adr; /* 0x4x: data, 0x0x: audio */ | ||
714 | u_char number; | ||
715 | u_char format; /* em */ /* 0x00: lba, 0x01: msf */ | ||
716 | u_int address; | ||
717 | } TocBuffer[MAX_TRACKS+1]; /* last entry faked */ | ||
718 | |||
719 | int in_SpinUp; /* CR-52x test flag */ | ||
720 | int n_bytes; /* TEAC awaited response count */ | ||
721 | u_char error_state, b3, b4; /* TEAC command error state */ | ||
722 | u_char f_drv_error; /* TEAC command error flag */ | ||
723 | u_char speed_byte; | ||
724 | int frmsiz; | ||
725 | u_char f_XA; /* 1: XA */ | ||
726 | u_char type_byte; /* 0, 1, 3 */ | ||
727 | u_char mode_xb_6; | ||
728 | u_char mode_yb_7; | ||
729 | u_char mode_xb_8; | ||
730 | u_char delay; | ||
731 | struct cdrom_device_info *sbpcd_infop; | ||
732 | struct gendisk *disk; | ||
733 | } D_S[NR_SBPCD]; | ||
734 | |||
735 | static struct sbpcd_drive *current_drive = D_S; | ||
736 | |||
737 | /* | ||
738 | * drive space ends here (needed separate for each unit) | ||
739 | */ | ||
740 | /*==========================================================================*/ | ||
741 | #if 0 | ||
742 | unsigned long cli_sti; /* for saving the processor flags */ | ||
743 | #endif | ||
744 | /*==========================================================================*/ | ||
745 | static struct timer_list delay_timer = | ||
746 | TIMER_INITIALIZER(mark_timeout_delay, 0, 0); | ||
747 | static struct timer_list data_timer = | ||
748 | TIMER_INITIALIZER(mark_timeout_data, 0, 0); | ||
749 | #if 0 | ||
750 | static struct timer_list audio_timer = | ||
751 | TIMER_INITIALIZER(mark_timeout_audio, 0, 0); | ||
752 | #endif | ||
753 | /*==========================================================================*/ | ||
754 | /* | ||
755 | * DDI interface | ||
756 | */ | ||
757 | static void msg(int level, const char *fmt, ...) | ||
758 | { | ||
759 | #if DISTRIBUTION | ||
760 | #define MSG_LEVEL KERN_NOTICE | ||
761 | #else | ||
762 | #define MSG_LEVEL KERN_INFO | ||
763 | #endif /* DISTRIBUTION */ | ||
764 | |||
765 | char buf[256]; | ||
766 | va_list args; | ||
767 | |||
768 | if (!(sbpcd_debug&(1<<level))) return; | ||
769 | |||
770 | msgnum++; | ||
771 | if (msgnum>99) msgnum=0; | ||
772 | sprintf(buf, MSG_LEVEL "%s-%d [%02d]: ", major_name, current_drive - D_S, msgnum); | ||
773 | va_start(args, fmt); | ||
774 | vsprintf(&buf[18], fmt, args); | ||
775 | va_end(args); | ||
776 | printk(buf); | ||
777 | #if KLOGD_PAUSE | ||
778 | sbp_sleep(KLOGD_PAUSE); /* else messages get lost */ | ||
779 | #endif /* KLOGD_PAUSE */ | ||
780 | return; | ||
781 | } | ||
782 | /*==========================================================================*/ | ||
783 | /* | ||
784 | * DDI interface: runtime trace bit pattern maintenance | ||
785 | */ | ||
786 | static int sbpcd_dbg_ioctl(unsigned long arg, int level) | ||
787 | { | ||
788 | switch(arg) | ||
789 | { | ||
790 | case 0: /* OFF */ | ||
791 | sbpcd_debug = DBG_INF; | ||
792 | break; | ||
793 | |||
794 | default: | ||
795 | if (arg>=128) sbpcd_debug &= ~(1<<(arg-128)); | ||
796 | else sbpcd_debug |= (1<<arg); | ||
797 | } | ||
798 | return (arg); | ||
799 | } | ||
800 | /*==========================================================================*/ | ||
801 | static void mark_timeout_delay(u_long i) | ||
802 | { | ||
803 | timed_out_delay=1; | ||
804 | #if 0 | ||
805 | msg(DBG_TIM,"delay timer expired.\n"); | ||
806 | #endif | ||
807 | } | ||
808 | /*==========================================================================*/ | ||
809 | static void mark_timeout_data(u_long i) | ||
810 | { | ||
811 | timed_out_data=1; | ||
812 | #if 0 | ||
813 | msg(DBG_TIM,"data timer expired.\n"); | ||
814 | #endif | ||
815 | } | ||
816 | /*==========================================================================*/ | ||
817 | #if 0 | ||
818 | static void mark_timeout_audio(u_long i) | ||
819 | { | ||
820 | timed_out_audio=1; | ||
821 | #if 0 | ||
822 | msg(DBG_TIM,"audio timer expired.\n"); | ||
823 | #endif | ||
824 | } | ||
825 | #endif | ||
826 | /*==========================================================================*/ | ||
827 | /* | ||
828 | * Wait a little while (used for polling the drive). | ||
829 | */ | ||
830 | static void sbp_sleep(u_int time) | ||
831 | { | ||
832 | sti(); | ||
833 | current->state = TASK_INTERRUPTIBLE; | ||
834 | schedule_timeout(time); | ||
835 | sti(); | ||
836 | } | ||
837 | /*==========================================================================*/ | ||
838 | #define RETURN_UP(rc) {up(&ioctl_read_sem); return(rc);} | ||
839 | /*==========================================================================*/ | ||
840 | /* | ||
841 | * convert logical_block_address to m-s-f_number (3 bytes only) | ||
842 | */ | ||
843 | static INLINE void lba2msf(int lba, u_char *msf) | ||
844 | { | ||
845 | lba += CD_MSF_OFFSET; | ||
846 | msf[0] = lba / (CD_SECS*CD_FRAMES); | ||
847 | lba %= CD_SECS*CD_FRAMES; | ||
848 | msf[1] = lba / CD_FRAMES; | ||
849 | msf[2] = lba % CD_FRAMES; | ||
850 | } | ||
851 | /*==========================================================================*/ | ||
852 | /*==========================================================================*/ | ||
853 | /* | ||
854 | * convert msf-bin to msf-bcd | ||
855 | */ | ||
856 | static INLINE void bin2bcdx(u_char *p) /* must work only up to 75 or 99 */ | ||
857 | { | ||
858 | *p=((*p/10)<<4)|(*p%10); | ||
859 | } | ||
860 | /*==========================================================================*/ | ||
861 | static INLINE u_int blk2msf(u_int blk) | ||
862 | { | ||
863 | MSF msf; | ||
864 | u_int mm; | ||
865 | |||
866 | msf.c[3] = 0; | ||
867 | msf.c[2] = (blk + CD_MSF_OFFSET) / (CD_SECS * CD_FRAMES); | ||
868 | mm = (blk + CD_MSF_OFFSET) % (CD_SECS * CD_FRAMES); | ||
869 | msf.c[1] = mm / CD_FRAMES; | ||
870 | msf.c[0] = mm % CD_FRAMES; | ||
871 | return (msf.n); | ||
872 | } | ||
873 | /*==========================================================================*/ | ||
874 | static INLINE u_int make16(u_char rh, u_char rl) | ||
875 | { | ||
876 | return ((rh<<8)|rl); | ||
877 | } | ||
878 | /*==========================================================================*/ | ||
879 | static INLINE u_int make32(u_int rh, u_int rl) | ||
880 | { | ||
881 | return ((rh<<16)|rl); | ||
882 | } | ||
883 | /*==========================================================================*/ | ||
884 | static INLINE u_char swap_nibbles(u_char i) | ||
885 | { | ||
886 | return ((i<<4)|(i>>4)); | ||
887 | } | ||
888 | /*==========================================================================*/ | ||
889 | static INLINE u_char byt2bcd(u_char i) | ||
890 | { | ||
891 | return (((i/10)<<4)+i%10); | ||
892 | } | ||
893 | /*==========================================================================*/ | ||
894 | static INLINE u_char bcd2bin(u_char bcd) | ||
895 | { | ||
896 | return ((bcd>>4)*10+(bcd&0x0F)); | ||
897 | } | ||
898 | /*==========================================================================*/ | ||
899 | static INLINE int msf2blk(int msfx) | ||
900 | { | ||
901 | MSF msf; | ||
902 | int i; | ||
903 | |||
904 | msf.n=msfx; | ||
905 | i=(msf.c[2] * CD_SECS + msf.c[1]) * CD_FRAMES + msf.c[0] - CD_MSF_OFFSET; | ||
906 | if (i<0) return (0); | ||
907 | return (i); | ||
908 | } | ||
909 | /*==========================================================================*/ | ||
910 | /* | ||
911 | * convert m-s-f_number (3 bytes only) to logical_block_address | ||
912 | */ | ||
913 | static INLINE int msf2lba(u_char *msf) | ||
914 | { | ||
915 | int i; | ||
916 | |||
917 | i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_MSF_OFFSET; | ||
918 | if (i<0) return (0); | ||
919 | return (i); | ||
920 | } | ||
921 | /*==========================================================================*/ | ||
922 | /* evaluate cc_ReadError code */ | ||
923 | static int sta2err(int sta) | ||
924 | { | ||
925 | if (famT_drive) | ||
926 | { | ||
927 | if (sta==0x00) return (0); | ||
928 | if (sta==0x01) return (-604); /* CRC error */ | ||
929 | if (sta==0x02) return (-602); /* drive not ready */ | ||
930 | if (sta==0x03) return (-607); /* unknown media */ | ||
931 | if (sta==0x04) return (-612); /* general failure */ | ||
932 | if (sta==0x05) return (0); | ||
933 | if (sta==0x06) return (-ERR_DISKCHANGE); /* disk change */ | ||
934 | if (sta==0x0b) return (-612); /* general failure */ | ||
935 | if (sta==0xff) return (-612); /* general failure */ | ||
936 | return (0); | ||
937 | } | ||
938 | else | ||
939 | { | ||
940 | if (sta<=2) return (sta); | ||
941 | if (sta==0x05) return (-604); /* CRC error */ | ||
942 | if (sta==0x06) return (-606); /* seek error */ | ||
943 | if (sta==0x0d) return (-606); /* seek error */ | ||
944 | if (sta==0x0e) return (-603); /* unknown command */ | ||
945 | if (sta==0x14) return (-603); /* unknown command */ | ||
946 | if (sta==0x0c) return (-611); /* read fault */ | ||
947 | if (sta==0x0f) return (-611); /* read fault */ | ||
948 | if (sta==0x10) return (-611); /* read fault */ | ||
949 | if (sta>=0x16) return (-612); /* general failure */ | ||
950 | if (sta==0x11) return (-ERR_DISKCHANGE); /* disk change (LCS: removed) */ | ||
951 | if (famL_drive) | ||
952 | if (sta==0x12) return (-ERR_DISKCHANGE); /* disk change (inserted) */ | ||
953 | return (-602); /* drive not ready */ | ||
954 | } | ||
955 | } | ||
956 | /*==========================================================================*/ | ||
957 | static INLINE void clr_cmdbuf(void) | ||
958 | { | ||
959 | int i; | ||
960 | |||
961 | for (i=0;i<10;i++) drvcmd[i]=0; | ||
962 | cmd_type=0; | ||
963 | } | ||
964 | /*==========================================================================*/ | ||
965 | static void flush_status(void) | ||
966 | { | ||
967 | int i; | ||
968 | |||
969 | sbp_sleep(15*HZ/10); | ||
970 | for (i=maxtim_data;i!=0;i--) inb(CDi_status); | ||
971 | } | ||
972 | /*====================================================================*/ | ||
973 | /* | ||
974 | * CDi status loop for Teac CD-55A (Rob Riggs) | ||
975 | * | ||
976 | * This is needed because for some strange reason | ||
977 | * the CD-55A can take a real long time to give a | ||
978 | * status response. This seems to happen after we | ||
979 | * issue a READ command where a long seek is involved. | ||
980 | * | ||
981 | * I tried to ensure that we get max throughput with | ||
982 | * minimal busy waiting. We busy wait at first, then | ||
983 | * "switch gears" and start sleeping. We sleep for | ||
984 | * longer periods of time the longer we wait. | ||
985 | * | ||
986 | */ | ||
987 | static int CDi_stat_loop_T(void) | ||
988 | { | ||
989 | int i, gear=1; | ||
990 | u_long timeout_1, timeout_2, timeout_3, timeout_4; | ||
991 | |||
992 | timeout_1 = jiffies + HZ / 50; /* sbp_sleep(0) for a short period */ | ||
993 | timeout_2 = jiffies + HZ / 5; /* nap for no more than 200ms */ | ||
994 | timeout_3 = jiffies + 5 * HZ; /* sleep for up to 5s */ | ||
995 | timeout_4 = jiffies + 45 * HZ; /* long sleep for up to 45s. */ | ||
996 | do | ||
997 | { | ||
998 | i = inb(CDi_status); | ||
999 | if (!(i&s_not_data_ready)) return (i); | ||
1000 | if (!(i&s_not_result_ready)) return (i); | ||
1001 | switch(gear) | ||
1002 | { | ||
1003 | case 4: | ||
1004 | sbp_sleep(HZ); | ||
1005 | if (time_after(jiffies, timeout_4)) gear++; | ||
1006 | msg(DBG_TEA, "CDi_stat_loop_T: long sleep active.\n"); | ||
1007 | break; | ||
1008 | case 3: | ||
1009 | sbp_sleep(HZ/10); | ||
1010 | if (time_after(jiffies, timeout_3)) gear++; | ||
1011 | break; | ||
1012 | case 2: | ||
1013 | sbp_sleep(HZ/100); | ||
1014 | if (time_after(jiffies, timeout_2)) gear++; | ||
1015 | break; | ||
1016 | case 1: | ||
1017 | sbp_sleep(0); | ||
1018 | if (time_after(jiffies, timeout_1)) gear++; | ||
1019 | } | ||
1020 | } while (gear < 5); | ||
1021 | return -1; | ||
1022 | } | ||
1023 | /*==========================================================================*/ | ||
1024 | static int CDi_stat_loop(void) | ||
1025 | { | ||
1026 | int i,j; | ||
1027 | |||
1028 | for(timeout = jiffies + 10*HZ, i=maxtim_data; time_before(jiffies, timeout); ) | ||
1029 | { | ||
1030 | for ( ;i!=0;i--) | ||
1031 | { | ||
1032 | j=inb(CDi_status); | ||
1033 | if (!(j&s_not_data_ready)) return (j); | ||
1034 | if (!(j&s_not_result_ready)) return (j); | ||
1035 | if (fam0L_drive) if (j&s_attention) return (j); | ||
1036 | } | ||
1037 | sbp_sleep(1); | ||
1038 | i = 1; | ||
1039 | } | ||
1040 | msg(DBG_LCS,"CDi_stat_loop failed in line %d\n", __LINE__); | ||
1041 | return (-1); | ||
1042 | } | ||
1043 | /*==========================================================================*/ | ||
1044 | #if 00000 | ||
1045 | /*==========================================================================*/ | ||
1046 | static int tst_DataReady(void) | ||
1047 | { | ||
1048 | int i; | ||
1049 | |||
1050 | i=inb(CDi_status); | ||
1051 | if (i&s_not_data_ready) return (0); | ||
1052 | return (1); | ||
1053 | } | ||
1054 | /*==========================================================================*/ | ||
1055 | static int tst_ResultReady(void) | ||
1056 | { | ||
1057 | int i; | ||
1058 | |||
1059 | i=inb(CDi_status); | ||
1060 | if (i&s_not_result_ready) return (0); | ||
1061 | return (1); | ||
1062 | } | ||
1063 | /*==========================================================================*/ | ||
1064 | static int tst_Attention(void) | ||
1065 | { | ||
1066 | int i; | ||
1067 | |||
1068 | i=inb(CDi_status); | ||
1069 | if (i&s_attention) return (1); | ||
1070 | return (0); | ||
1071 | } | ||
1072 | /*==========================================================================*/ | ||
1073 | #endif | ||
1074 | /*==========================================================================*/ | ||
1075 | static int ResponseInfo(void) | ||
1076 | { | ||
1077 | int i,j,st=0; | ||
1078 | u_long timeout; | ||
1079 | |||
1080 | for (i=0,timeout=jiffies+HZ;i<response_count;i++) | ||
1081 | { | ||
1082 | for (j=maxtim_data; ; ) | ||
1083 | { | ||
1084 | for ( ;j!=0;j-- ) | ||
1085 | { | ||
1086 | st=inb(CDi_status); | ||
1087 | if (!(st&s_not_result_ready)) break; | ||
1088 | } | ||
1089 | if ((j!=0)||time_after_eq(jiffies, timeout)) break; | ||
1090 | sbp_sleep(1); | ||
1091 | j = 1; | ||
1092 | } | ||
1093 | if (time_after_eq(jiffies, timeout)) break; | ||
1094 | infobuf[i]=inb(CDi_info); | ||
1095 | } | ||
1096 | #if 000 | ||
1097 | while (!(inb(CDi_status)&s_not_result_ready)) | ||
1098 | { | ||
1099 | infobuf[i++]=inb(CDi_info); | ||
1100 | } | ||
1101 | j=i-response_count; | ||
1102 | if (j>0) msg(DBG_INF,"ResponseInfo: got %d trailing bytes.\n",j); | ||
1103 | #endif /* 000 */ | ||
1104 | for (j=0;j<i;j++) | ||
1105 | sprintf(&msgbuf[j*3]," %02X",infobuf[j]); | ||
1106 | msgbuf[j*3]=0; | ||
1107 | msg(DBG_CMD,"ResponseInfo:%s (%d,%d)\n",msgbuf,response_count,i); | ||
1108 | j=response_count-i; | ||
1109 | if (j>0) return (-j); | ||
1110 | else return (i); | ||
1111 | } | ||
1112 | /*==========================================================================*/ | ||
1113 | static void EvaluateStatus(int st) | ||
1114 | { | ||
1115 | current_drive->status_bits=0; | ||
1116 | if (fam1_drive) current_drive->status_bits=st|p_success; | ||
1117 | else if (fam0_drive) | ||
1118 | { | ||
1119 | if (st&p_caddin_old) current_drive->status_bits |= p_door_closed|p_caddy_in; | ||
1120 | if (st&p_spinning) current_drive->status_bits |= p_spinning; | ||
1121 | if (st&p_check) current_drive->status_bits |= p_check; | ||
1122 | if (st&p_success_old) current_drive->status_bits |= p_success; | ||
1123 | if (st&p_busy_old) current_drive->status_bits |= p_busy_new; | ||
1124 | if (st&p_disk_ok) current_drive->status_bits |= p_disk_ok; | ||
1125 | } | ||
1126 | else if (famLV_drive) | ||
1127 | { | ||
1128 | current_drive->status_bits |= p_success; | ||
1129 | if (st&p_caddin_old) current_drive->status_bits |= p_disk_ok|p_caddy_in; | ||
1130 | if (st&p_spinning) current_drive->status_bits |= p_spinning; | ||
1131 | if (st&p_check) current_drive->status_bits |= p_check; | ||
1132 | if (st&p_busy_old) current_drive->status_bits |= p_busy_new; | ||
1133 | if (st&p_lcs_door_closed) current_drive->status_bits |= p_door_closed; | ||
1134 | if (st&p_lcs_door_locked) current_drive->status_bits |= p_door_locked; | ||
1135 | } | ||
1136 | else if (fam2_drive) | ||
1137 | { | ||
1138 | current_drive->status_bits |= p_success; | ||
1139 | if (st&p2_check) current_drive->status_bits |= p1_check; | ||
1140 | if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed; | ||
1141 | if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in; | ||
1142 | if (st&p2_busy1) current_drive->status_bits |= p1_busy; | ||
1143 | if (st&p2_busy2) current_drive->status_bits |= p1_busy; | ||
1144 | if (st&p2_spinning) current_drive->status_bits |= p1_spinning; | ||
1145 | if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked; | ||
1146 | if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok; | ||
1147 | } | ||
1148 | else if (famT_drive) | ||
1149 | { | ||
1150 | return; /* still needs to get coded */ | ||
1151 | current_drive->status_bits |= p_success; | ||
1152 | if (st&p2_check) current_drive->status_bits |= p1_check; | ||
1153 | if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed; | ||
1154 | if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in; | ||
1155 | if (st&p2_busy1) current_drive->status_bits |= p1_busy; | ||
1156 | if (st&p2_busy2) current_drive->status_bits |= p1_busy; | ||
1157 | if (st&p2_spinning) current_drive->status_bits |= p1_spinning; | ||
1158 | if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked; | ||
1159 | if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok; | ||
1160 | } | ||
1161 | return; | ||
1162 | } | ||
1163 | /*==========================================================================*/ | ||
1164 | static int cmd_out_T(void); | ||
1165 | |||
1166 | static int get_state_T(void) | ||
1167 | { | ||
1168 | int i; | ||
1169 | |||
1170 | clr_cmdbuf(); | ||
1171 | current_drive->n_bytes=1; | ||
1172 | drvcmd[0]=CMDT_STATUS; | ||
1173 | i=cmd_out_T(); | ||
1174 | if (i>=0) i=infobuf[0]; | ||
1175 | else | ||
1176 | { | ||
1177 | msg(DBG_TEA,"get_state_T error %d\n", i); | ||
1178 | return (i); | ||
1179 | } | ||
1180 | if (i>=0) | ||
1181 | /* 2: closed, disk in */ | ||
1182 | current_drive->status_bits=p1_door_closed|p1_disk_in|p1_spinning|p1_disk_ok; | ||
1183 | else if (current_drive->error_state==6) | ||
1184 | { | ||
1185 | /* 3: closed, disk in, changed ("06 xx xx") */ | ||
1186 | current_drive->status_bits=p1_door_closed|p1_disk_in; | ||
1187 | current_drive->CD_changed=0xFF; | ||
1188 | current_drive->diskstate_flags &= ~toc_bit; | ||
1189 | } | ||
1190 | else if ((current_drive->error_state!=2)||(current_drive->b3!=0x3A)||(current_drive->b4==0x00)) | ||
1191 | { | ||
1192 | /* 1: closed, no disk ("xx yy zz"or "02 3A 00") */ | ||
1193 | current_drive->status_bits=p1_door_closed; | ||
1194 | current_drive->open_count=0; | ||
1195 | } | ||
1196 | else if (current_drive->b4==0x01) | ||
1197 | { | ||
1198 | /* 0: open ("02 3A 01") */ | ||
1199 | current_drive->status_bits=0; | ||
1200 | current_drive->open_count=0; | ||
1201 | } | ||
1202 | else | ||
1203 | { | ||
1204 | /* 1: closed, no disk ("02 3A xx") */ | ||
1205 | current_drive->status_bits=p1_door_closed; | ||
1206 | current_drive->open_count=0; | ||
1207 | } | ||
1208 | return (current_drive->status_bits); | ||
1209 | } | ||
1210 | /*==========================================================================*/ | ||
1211 | static int ResponseStatus(void) | ||
1212 | { | ||
1213 | int i,j; | ||
1214 | u_long timeout; | ||
1215 | |||
1216 | msg(DBG_STA,"doing ResponseStatus...\n"); | ||
1217 | if (famT_drive) return (get_state_T()); | ||
1218 | if (flags_cmd_out & f_respo3) timeout = jiffies; | ||
1219 | else if (flags_cmd_out & f_respo2) timeout = jiffies + 16*HZ; | ||
1220 | else timeout = jiffies + 4*HZ; | ||
1221 | j=maxtim_8; | ||
1222 | do | ||
1223 | { | ||
1224 | for ( ;j!=0;j--) | ||
1225 | { | ||
1226 | i=inb(CDi_status); | ||
1227 | if (!(i&s_not_result_ready)) break; | ||
1228 | } | ||
1229 | if ((j!=0)||time_after(jiffies, timeout)) break; | ||
1230 | sbp_sleep(1); | ||
1231 | j = 1; | ||
1232 | } | ||
1233 | while (1); | ||
1234 | if (j==0) | ||
1235 | { | ||
1236 | if ((flags_cmd_out & f_respo3) == 0) | ||
1237 | msg(DBG_STA,"ResponseStatus: timeout.\n"); | ||
1238 | current_drive->status_bits=0; | ||
1239 | return (-401); | ||
1240 | } | ||
1241 | i=inb(CDi_info); | ||
1242 | msg(DBG_STA,"ResponseStatus: response %02X.\n", i); | ||
1243 | EvaluateStatus(i); | ||
1244 | msg(DBG_STA,"status_bits=%02X, i=%02X\n",current_drive->status_bits,i); | ||
1245 | return (current_drive->status_bits); | ||
1246 | } | ||
1247 | /*==========================================================================*/ | ||
1248 | static void cc_ReadStatus(void) | ||
1249 | { | ||
1250 | int i; | ||
1251 | |||
1252 | msg(DBG_STA,"giving cc_ReadStatus command\n"); | ||
1253 | if (famT_drive) return; | ||
1254 | SBPCD_CLI; | ||
1255 | if (fam0LV_drive) OUT(CDo_command,CMD0_STATUS); | ||
1256 | else if (fam1_drive) OUT(CDo_command,CMD1_STATUS); | ||
1257 | else if (fam2_drive) OUT(CDo_command,CMD2_STATUS); | ||
1258 | if (!fam0LV_drive) for (i=0;i<6;i++) OUT(CDo_command,0); | ||
1259 | SBPCD_STI; | ||
1260 | } | ||
1261 | /*==========================================================================*/ | ||
1262 | static int cc_ReadError(void) | ||
1263 | { | ||
1264 | int i; | ||
1265 | |||
1266 | clr_cmdbuf(); | ||
1267 | msg(DBG_ERR,"giving cc_ReadError command.\n"); | ||
1268 | if (fam1_drive) | ||
1269 | { | ||
1270 | drvcmd[0]=CMD1_READ_ERR; | ||
1271 | response_count=8; | ||
1272 | flags_cmd_out=f_putcmd|f_ResponseStatus; | ||
1273 | } | ||
1274 | else if (fam0LV_drive) | ||
1275 | { | ||
1276 | drvcmd[0]=CMD0_READ_ERR; | ||
1277 | response_count=6; | ||
1278 | if (famLV_drive) | ||
1279 | flags_cmd_out=f_putcmd; | ||
1280 | else | ||
1281 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus; | ||
1282 | } | ||
1283 | else if (fam2_drive) | ||
1284 | { | ||
1285 | drvcmd[0]=CMD2_READ_ERR; | ||
1286 | response_count=6; | ||
1287 | flags_cmd_out=f_putcmd; | ||
1288 | } | ||
1289 | else if (famT_drive) | ||
1290 | { | ||
1291 | response_count=5; | ||
1292 | drvcmd[0]=CMDT_READ_ERR; | ||
1293 | } | ||
1294 | i=cmd_out(); | ||
1295 | current_drive->error_byte=0; | ||
1296 | msg(DBG_ERR,"cc_ReadError: cmd_out(CMDx_READ_ERR) returns %d (%02X)\n",i,i); | ||
1297 | if (i<0) return (i); | ||
1298 | if (fam0V_drive) i=1; | ||
1299 | else i=2; | ||
1300 | current_drive->error_byte=infobuf[i]; | ||
1301 | msg(DBG_ERR,"cc_ReadError: infobuf[%d] is %d (%02X)\n",i,current_drive->error_byte,current_drive->error_byte); | ||
1302 | i=sta2err(infobuf[i]); | ||
1303 | if (i==-ERR_DISKCHANGE) | ||
1304 | { | ||
1305 | current_drive->CD_changed=0xFF; | ||
1306 | current_drive->diskstate_flags &= ~toc_bit; | ||
1307 | } | ||
1308 | return (i); | ||
1309 | } | ||
1310 | /*==========================================================================*/ | ||
1311 | static int cc_DriveReset(void); | ||
1312 | |||
1313 | static int cmd_out_T(void) | ||
1314 | { | ||
1315 | #undef CMDT_TRIES | ||
1316 | #define CMDT_TRIES 1000 | ||
1317 | #define TEST_FALSE_FF 1 | ||
1318 | |||
1319 | int i, j, l=0, m, ntries; | ||
1320 | unsigned long flags; | ||
1321 | |||
1322 | current_drive->error_state=0; | ||
1323 | current_drive->b3=0; | ||
1324 | current_drive->b4=0; | ||
1325 | current_drive->f_drv_error=0; | ||
1326 | for (i=0;i<10;i++) sprintf(&msgbuf[i*3]," %02X",drvcmd[i]); | ||
1327 | msgbuf[i*3]=0; | ||
1328 | msg(DBG_CMD,"cmd_out_T:%s\n",msgbuf); | ||
1329 | |||
1330 | OUT(CDo_sel_i_d,0); | ||
1331 | OUT(CDo_enable,current_drive->drv_sel); | ||
1332 | i=inb(CDi_status); | ||
1333 | do_16bit=0; | ||
1334 | if ((f_16bit)&&(!(i&0x80))) | ||
1335 | { | ||
1336 | do_16bit=1; | ||
1337 | msg(DBG_TEA,"cmd_out_T: do_16bit set.\n"); | ||
1338 | } | ||
1339 | if (!(i&s_not_result_ready)) | ||
1340 | do | ||
1341 | { | ||
1342 | j=inb(CDi_info); | ||
1343 | i=inb(CDi_status); | ||
1344 | sbp_sleep(0); | ||
1345 | msg(DBG_TEA,"cmd_out_T: spurious !s_not_result_ready. (%02X)\n", j); | ||
1346 | } | ||
1347 | while (!(i&s_not_result_ready)); | ||
1348 | save_flags(flags); cli(); | ||
1349 | for (i=0;i<10;i++) OUT(CDo_command,drvcmd[i]); | ||
1350 | restore_flags(flags); | ||
1351 | for (ntries=CMDT_TRIES;ntries>0;ntries--) | ||
1352 | { | ||
1353 | if (drvcmd[0]==CMDT_READ_VER) sbp_sleep(HZ); /* fixme */ | ||
1354 | #if 01 | ||
1355 | OUT(CDo_sel_i_d,1); | ||
1356 | #endif /* 01 */ | ||
1357 | if (teac==2) | ||
1358 | { | ||
1359 | if ((i=CDi_stat_loop_T()) == -1) break; | ||
1360 | } | ||
1361 | else | ||
1362 | { | ||
1363 | #if 0 | ||
1364 | OUT(CDo_sel_i_d,1); | ||
1365 | #endif /* 0 */ | ||
1366 | i=inb(CDi_status); | ||
1367 | } | ||
1368 | if (!(i&s_not_data_ready)) /* f.e. CMDT_DISKINFO */ | ||
1369 | { | ||
1370 | OUT(CDo_sel_i_d,1); | ||
1371 | if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */ | ||
1372 | if (drvcmd[0]==CMDT_DISKINFO) | ||
1373 | { | ||
1374 | l=0; | ||
1375 | do | ||
1376 | { | ||
1377 | if (do_16bit) | ||
1378 | { | ||
1379 | i=inw(CDi_data); | ||
1380 | infobuf[l++]=i&0x0ff; | ||
1381 | infobuf[l++]=i>>8; | ||
1382 | #if TEST_FALSE_FF | ||
1383 | if ((l==2)&&(infobuf[0]==0x0ff)) | ||
1384 | { | ||
1385 | infobuf[0]=infobuf[1]; | ||
1386 | l=1; | ||
1387 | msg(DBG_TEA,"cmd_out_T: do_16bit: false first byte!\n"); | ||
1388 | } | ||
1389 | #endif /* TEST_FALSE_FF */ | ||
1390 | } | ||
1391 | else infobuf[l++]=inb(CDi_data); | ||
1392 | i=inb(CDi_status); | ||
1393 | } | ||
1394 | while (!(i&s_not_data_ready)); | ||
1395 | for (j=0;j<l;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]); | ||
1396 | msgbuf[j*3]=0; | ||
1397 | msg(DBG_CMD,"cmd_out_T data response:%s\n", msgbuf); | ||
1398 | } | ||
1399 | else | ||
1400 | { | ||
1401 | msg(DBG_TEA,"cmd_out_T: data response with cmd_%02X!\n", | ||
1402 | drvcmd[0]); | ||
1403 | j=0; | ||
1404 | do | ||
1405 | { | ||
1406 | if (do_16bit) i=inw(CDi_data); | ||
1407 | else i=inb(CDi_data); | ||
1408 | j++; | ||
1409 | i=inb(CDi_status); | ||
1410 | } | ||
1411 | while (!(i&s_not_data_ready)); | ||
1412 | msg(DBG_TEA,"cmd_out_T: data response: discarded %d bytes/words.\n", j); | ||
1413 | fatal_err++; | ||
1414 | } | ||
1415 | } | ||
1416 | i=inb(CDi_status); | ||
1417 | if (!(i&s_not_result_ready)) | ||
1418 | { | ||
1419 | OUT(CDo_sel_i_d,0); | ||
1420 | if (drvcmd[0]==CMDT_DISKINFO) m=l; | ||
1421 | else m=0; | ||
1422 | do | ||
1423 | { | ||
1424 | infobuf[m++]=inb(CDi_info); | ||
1425 | i=inb(CDi_status); | ||
1426 | } | ||
1427 | while (!(i&s_not_result_ready)); | ||
1428 | for (j=0;j<m;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]); | ||
1429 | msgbuf[j*3]=0; | ||
1430 | msg(DBG_CMD,"cmd_out_T info response:%s\n", msgbuf); | ||
1431 | if (drvcmd[0]==CMDT_DISKINFO) | ||
1432 | { | ||
1433 | infobuf[0]=infobuf[l]; | ||
1434 | if (infobuf[0]!=0x02) return (l); /* data length */ | ||
1435 | } | ||
1436 | else if (infobuf[0]!=0x02) return (m); /* info length */ | ||
1437 | do | ||
1438 | { | ||
1439 | ++recursion; | ||
1440 | if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (%02X): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", drvcmd[0], recursion); | ||
1441 | clr_cmdbuf(); | ||
1442 | drvcmd[0]=CMDT_READ_ERR; | ||
1443 | j=cmd_out_T(); /* !!! recursive here !!! */ | ||
1444 | --recursion; | ||
1445 | sbp_sleep(1); | ||
1446 | } | ||
1447 | while (j<0); | ||
1448 | current_drive->error_state=infobuf[2]; | ||
1449 | current_drive->b3=infobuf[3]; | ||
1450 | current_drive->b4=infobuf[4]; | ||
1451 | if (current_drive->f_drv_error) | ||
1452 | { | ||
1453 | current_drive->f_drv_error=0; | ||
1454 | cc_DriveReset(); | ||
1455 | current_drive->error_state=2; | ||
1456 | } | ||
1457 | return (-current_drive->error_state-400); | ||
1458 | } | ||
1459 | if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */ | ||
1460 | if ((teac==0)||(ntries<(CMDT_TRIES-5))) sbp_sleep(HZ/10); | ||
1461 | else sbp_sleep(HZ/100); | ||
1462 | if (ntries>(CMDT_TRIES-50)) continue; | ||
1463 | msg(DBG_TEA,"cmd_out_T: next CMDT_TRIES (%02X): %d.\n", drvcmd[0], ntries-1); | ||
1464 | } | ||
1465 | current_drive->f_drv_error=1; | ||
1466 | cc_DriveReset(); | ||
1467 | current_drive->error_state=2; | ||
1468 | return (-99); | ||
1469 | } | ||
1470 | /*==========================================================================*/ | ||
1471 | static int cmd_out(void) | ||
1472 | { | ||
1473 | int i=0; | ||
1474 | |||
1475 | if (famT_drive) return(cmd_out_T()); | ||
1476 | |||
1477 | if (flags_cmd_out&f_putcmd) | ||
1478 | { | ||
1479 | unsigned long flags; | ||
1480 | for (i=0;i<7;i++) | ||
1481 | sprintf(&msgbuf[i*3], " %02X", drvcmd[i]); | ||
1482 | msgbuf[i*3]=0; | ||
1483 | msg(DBG_CMD,"cmd_out:%s\n", msgbuf); | ||
1484 | save_flags(flags); cli(); | ||
1485 | for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]); | ||
1486 | restore_flags(flags); | ||
1487 | } | ||
1488 | if (response_count!=0) | ||
1489 | { | ||
1490 | if (cmd_type!=0) | ||
1491 | { | ||
1492 | if (sbpro_type==1) OUT(CDo_sel_i_d,1); | ||
1493 | msg(DBG_INF,"misleaded to try ResponseData.\n"); | ||
1494 | if (sbpro_type==1) OUT(CDo_sel_i_d,0); | ||
1495 | return (-22); | ||
1496 | } | ||
1497 | else i=ResponseInfo(); | ||
1498 | if (i<0) return (i); | ||
1499 | } | ||
1500 | if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to CDi_stat_loop.\n"); | ||
1501 | if (flags_cmd_out&f_lopsta) | ||
1502 | { | ||
1503 | i=CDi_stat_loop(); | ||
1504 | if ((i<0)||!(i&s_attention)) return (-8); | ||
1505 | } | ||
1506 | if (!(flags_cmd_out&f_getsta)) goto LOC_229; | ||
1507 | |||
1508 | LOC_228: | ||
1509 | if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadStatus.\n"); | ||
1510 | cc_ReadStatus(); | ||
1511 | |||
1512 | LOC_229: | ||
1513 | if (flags_cmd_out&f_ResponseStatus) | ||
1514 | { | ||
1515 | if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to ResponseStatus.\n"); | ||
1516 | i=ResponseStatus(); | ||
1517 | /* builds status_bits, returns orig. status or p_busy_new */ | ||
1518 | if (i<0) return (i); | ||
1519 | if (flags_cmd_out&(f_bit1|f_wait_if_busy)) | ||
1520 | { | ||
1521 | if (!st_check) | ||
1522 | { | ||
1523 | if ((flags_cmd_out&f_bit1)&&(i&p_success)) goto LOC_232; | ||
1524 | if ((!(flags_cmd_out&f_wait_if_busy))||(!st_busy)) goto LOC_228; | ||
1525 | } | ||
1526 | } | ||
1527 | } | ||
1528 | LOC_232: | ||
1529 | if (!(flags_cmd_out&f_obey_p_check)) return (0); | ||
1530 | if (!st_check) return (0); | ||
1531 | if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadError.\n"); | ||
1532 | i=cc_ReadError(); | ||
1533 | if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cmd_out OK.\n"); | ||
1534 | msg(DBG_000,"cmd_out: cc_ReadError=%d\n", i); | ||
1535 | return (i); | ||
1536 | } | ||
1537 | /*==========================================================================*/ | ||
1538 | static int cc_Seek(u_int pos, char f_blk_msf) | ||
1539 | { | ||
1540 | int i; | ||
1541 | |||
1542 | clr_cmdbuf(); | ||
1543 | if (f_blk_msf>1) return (-3); | ||
1544 | if (fam0V_drive) | ||
1545 | { | ||
1546 | drvcmd[0]=CMD0_SEEK; | ||
1547 | if (f_blk_msf==1) pos=msf2blk(pos); | ||
1548 | drvcmd[2]=(pos>>16)&0x00FF; | ||
1549 | drvcmd[3]=(pos>>8)&0x00FF; | ||
1550 | drvcmd[4]=pos&0x00FF; | ||
1551 | if (fam0_drive) | ||
1552 | flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta | | ||
1553 | f_ResponseStatus | f_obey_p_check | f_bit1; | ||
1554 | else | ||
1555 | flags_cmd_out = f_putcmd; | ||
1556 | } | ||
1557 | else if (fam1L_drive) | ||
1558 | { | ||
1559 | drvcmd[0]=CMD1_SEEK; /* same as CMD1_ and CMDL_ */ | ||
1560 | if (f_blk_msf==0) pos=blk2msf(pos); | ||
1561 | drvcmd[1]=(pos>>16)&0x00FF; | ||
1562 | drvcmd[2]=(pos>>8)&0x00FF; | ||
1563 | drvcmd[3]=pos&0x00FF; | ||
1564 | if (famL_drive) | ||
1565 | flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; | ||
1566 | else | ||
1567 | flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; | ||
1568 | } | ||
1569 | else if (fam2_drive) | ||
1570 | { | ||
1571 | drvcmd[0]=CMD2_SEEK; | ||
1572 | if (f_blk_msf==0) pos=blk2msf(pos); | ||
1573 | drvcmd[2]=(pos>>24)&0x00FF; | ||
1574 | drvcmd[3]=(pos>>16)&0x00FF; | ||
1575 | drvcmd[4]=(pos>>8)&0x00FF; | ||
1576 | drvcmd[5]=pos&0x00FF; | ||
1577 | flags_cmd_out=f_putcmd|f_ResponseStatus; | ||
1578 | } | ||
1579 | else if (famT_drive) | ||
1580 | { | ||
1581 | drvcmd[0]=CMDT_SEEK; | ||
1582 | if (f_blk_msf==1) pos=msf2blk(pos); | ||
1583 | drvcmd[2]=(pos>>24)&0x00FF; | ||
1584 | drvcmd[3]=(pos>>16)&0x00FF; | ||
1585 | drvcmd[4]=(pos>>8)&0x00FF; | ||
1586 | drvcmd[5]=pos&0x00FF; | ||
1587 | current_drive->n_bytes=1; | ||
1588 | } | ||
1589 | response_count=0; | ||
1590 | i=cmd_out(); | ||
1591 | return (i); | ||
1592 | } | ||
1593 | /*==========================================================================*/ | ||
1594 | static int cc_SpinUp(void) | ||
1595 | { | ||
1596 | int i; | ||
1597 | |||
1598 | msg(DBG_SPI,"SpinUp.\n"); | ||
1599 | current_drive->in_SpinUp = 1; | ||
1600 | clr_cmdbuf(); | ||
1601 | if (fam0LV_drive) | ||
1602 | { | ||
1603 | drvcmd[0]=CMD0_SPINUP; | ||
1604 | if (fam0L_drive) | ||
1605 | flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta| | ||
1606 | f_ResponseStatus|f_obey_p_check|f_bit1; | ||
1607 | else | ||
1608 | flags_cmd_out=f_putcmd; | ||
1609 | } | ||
1610 | else if (fam1_drive) | ||
1611 | { | ||
1612 | drvcmd[0]=CMD1_SPINUP; | ||
1613 | flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; | ||
1614 | } | ||
1615 | else if (fam2_drive) | ||
1616 | { | ||
1617 | drvcmd[0]=CMD2_TRAY_CTL; | ||
1618 | drvcmd[4]=0x01; /* "spinup" */ | ||
1619 | flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; | ||
1620 | } | ||
1621 | else if (famT_drive) | ||
1622 | { | ||
1623 | drvcmd[0]=CMDT_TRAY_CTL; | ||
1624 | drvcmd[4]=0x03; /* "insert", it hopefully spins the drive up */ | ||
1625 | } | ||
1626 | response_count=0; | ||
1627 | i=cmd_out(); | ||
1628 | current_drive->in_SpinUp = 0; | ||
1629 | return (i); | ||
1630 | } | ||
1631 | /*==========================================================================*/ | ||
1632 | static int cc_SpinDown(void) | ||
1633 | { | ||
1634 | int i; | ||
1635 | |||
1636 | if (fam0_drive) return (0); | ||
1637 | clr_cmdbuf(); | ||
1638 | response_count=0; | ||
1639 | if (fam1_drive) | ||
1640 | { | ||
1641 | drvcmd[0]=CMD1_SPINDOWN; | ||
1642 | flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; | ||
1643 | } | ||
1644 | else if (fam2_drive) | ||
1645 | { | ||
1646 | drvcmd[0]=CMD2_TRAY_CTL; | ||
1647 | drvcmd[4]=0x02; /* "eject" */ | ||
1648 | flags_cmd_out=f_putcmd|f_ResponseStatus; | ||
1649 | } | ||
1650 | else if (famL_drive) | ||
1651 | { | ||
1652 | drvcmd[0]=CMDL_SPINDOWN; | ||
1653 | drvcmd[1]=1; | ||
1654 | flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; | ||
1655 | } | ||
1656 | else if (famV_drive) | ||
1657 | { | ||
1658 | drvcmd[0]=CMDV_SPINDOWN; | ||
1659 | flags_cmd_out=f_putcmd; | ||
1660 | } | ||
1661 | else if (famT_drive) | ||
1662 | { | ||
1663 | drvcmd[0]=CMDT_TRAY_CTL; | ||
1664 | drvcmd[4]=0x02; /* "eject" */ | ||
1665 | } | ||
1666 | i=cmd_out(); | ||
1667 | return (i); | ||
1668 | } | ||
1669 | /*==========================================================================*/ | ||
1670 | static int cc_get_mode_T(void) | ||
1671 | { | ||
1672 | int i; | ||
1673 | |||
1674 | clr_cmdbuf(); | ||
1675 | response_count=10; | ||
1676 | drvcmd[0]=CMDT_GETMODE; | ||
1677 | drvcmd[4]=response_count; | ||
1678 | i=cmd_out_T(); | ||
1679 | return (i); | ||
1680 | } | ||
1681 | /*==========================================================================*/ | ||
1682 | static int cc_set_mode_T(void) | ||
1683 | { | ||
1684 | int i; | ||
1685 | |||
1686 | clr_cmdbuf(); | ||
1687 | response_count=1; | ||
1688 | drvcmd[0]=CMDT_SETMODE; | ||
1689 | drvcmd[1]=current_drive->speed_byte; | ||
1690 | drvcmd[2]=current_drive->frmsiz>>8; | ||
1691 | drvcmd[3]=current_drive->frmsiz&0x0FF; | ||
1692 | drvcmd[4]=current_drive->f_XA; /* 1: XA */ | ||
1693 | drvcmd[5]=current_drive->type_byte; /* 0, 1, 3 */ | ||
1694 | drvcmd[6]=current_drive->mode_xb_6; | ||
1695 | drvcmd[7]=current_drive->mode_yb_7|current_drive->volume_control; | ||
1696 | drvcmd[8]=current_drive->mode_xb_8; | ||
1697 | drvcmd[9]=current_drive->delay; | ||
1698 | i=cmd_out_T(); | ||
1699 | return (i); | ||
1700 | } | ||
1701 | /*==========================================================================*/ | ||
1702 | static int cc_prep_mode_T(void) | ||
1703 | { | ||
1704 | int i, j; | ||
1705 | |||
1706 | i=cc_get_mode_T(); | ||
1707 | if (i<0) return (i); | ||
1708 | for (i=0;i<10;i++) | ||
1709 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
1710 | msgbuf[i*3]=0; | ||
1711 | msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf); | ||
1712 | current_drive->speed_byte=0x02; /* 0x02: auto quad, 0x82: quad, 0x81: double, 0x80: single */ | ||
1713 | current_drive->frmsiz=make16(infobuf[2],infobuf[3]); | ||
1714 | current_drive->f_XA=infobuf[4]; | ||
1715 | if (current_drive->f_XA==0) current_drive->type_byte=0; | ||
1716 | else current_drive->type_byte=1; | ||
1717 | current_drive->mode_xb_6=infobuf[6]; | ||
1718 | current_drive->mode_yb_7=1; | ||
1719 | current_drive->mode_xb_8=infobuf[8]; | ||
1720 | current_drive->delay=0; /* 0, 1, 2, 3 */ | ||
1721 | j=cc_set_mode_T(); | ||
1722 | i=cc_get_mode_T(); | ||
1723 | for (i=0;i<10;i++) | ||
1724 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
1725 | msgbuf[i*3]=0; | ||
1726 | msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf); | ||
1727 | return (j); | ||
1728 | } | ||
1729 | /*==========================================================================*/ | ||
1730 | static int cc_SetSpeed(u_char speed, u_char x1, u_char x2) | ||
1731 | { | ||
1732 | int i; | ||
1733 | |||
1734 | if (fam0LV_drive) return (0); | ||
1735 | clr_cmdbuf(); | ||
1736 | response_count=0; | ||
1737 | if (fam1_drive) | ||
1738 | { | ||
1739 | drvcmd[0]=CMD1_SETMODE; | ||
1740 | drvcmd[1]=0x03; | ||
1741 | drvcmd[2]=speed; | ||
1742 | drvcmd[3]=x1; | ||
1743 | drvcmd[4]=x2; | ||
1744 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
1745 | } | ||
1746 | else if (fam2_drive) | ||
1747 | { | ||
1748 | drvcmd[0]=CMD2_SETSPEED; | ||
1749 | if (speed&speed_auto) | ||
1750 | { | ||
1751 | drvcmd[2]=0xFF; | ||
1752 | drvcmd[3]=0xFF; | ||
1753 | } | ||
1754 | else | ||
1755 | { | ||
1756 | drvcmd[2]=0; | ||
1757 | drvcmd[3]=150; | ||
1758 | } | ||
1759 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
1760 | } | ||
1761 | else if (famT_drive) | ||
1762 | { | ||
1763 | return (0); | ||
1764 | } | ||
1765 | i=cmd_out(); | ||
1766 | return (i); | ||
1767 | } | ||
1768 | /*==========================================================================*/ | ||
1769 | static int cc_SetVolume(void) | ||
1770 | { | ||
1771 | int i; | ||
1772 | u_char channel0,channel1,volume0,volume1; | ||
1773 | u_char control0,value0,control1,value1; | ||
1774 | |||
1775 | current_drive->diskstate_flags &= ~volume_bit; | ||
1776 | clr_cmdbuf(); | ||
1777 | channel0=current_drive->vol_chan0; | ||
1778 | volume0=current_drive->vol_ctrl0; | ||
1779 | channel1=control1=current_drive->vol_chan1; | ||
1780 | volume1=value1=current_drive->vol_ctrl1; | ||
1781 | control0=value0=0; | ||
1782 | |||
1783 | if (famV_drive) return (0); | ||
1784 | |||
1785 | if (((current_drive->drv_options&audio_mono)!=0)&&(current_drive->drv_type>=drv_211)) | ||
1786 | { | ||
1787 | if ((volume0!=0)&&(volume1==0)) | ||
1788 | { | ||
1789 | volume1=volume0; | ||
1790 | channel1=channel0; | ||
1791 | } | ||
1792 | else if ((volume0==0)&&(volume1!=0)) | ||
1793 | { | ||
1794 | volume0=volume1; | ||
1795 | channel0=channel1; | ||
1796 | } | ||
1797 | } | ||
1798 | if (channel0>1) | ||
1799 | { | ||
1800 | channel0=0; | ||
1801 | volume0=0; | ||
1802 | } | ||
1803 | if (channel1>1) | ||
1804 | { | ||
1805 | channel1=1; | ||
1806 | volume1=0; | ||
1807 | } | ||
1808 | |||
1809 | if (fam1_drive) | ||
1810 | { | ||
1811 | control0=channel0+1; | ||
1812 | control1=channel1+1; | ||
1813 | value0=(volume0>volume1)?volume0:volume1; | ||
1814 | value1=value0; | ||
1815 | if (volume0==0) control0=0; | ||
1816 | if (volume1==0) control1=0; | ||
1817 | drvcmd[0]=CMD1_SETMODE; | ||
1818 | drvcmd[1]=0x05; | ||
1819 | drvcmd[3]=control0; | ||
1820 | drvcmd[4]=value0; | ||
1821 | drvcmd[5]=control1; | ||
1822 | drvcmd[6]=value1; | ||
1823 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
1824 | } | ||
1825 | else if (fam2_drive) | ||
1826 | { | ||
1827 | control0=channel0+1; | ||
1828 | control1=channel1+1; | ||
1829 | value0=(volume0>volume1)?volume0:volume1; | ||
1830 | value1=value0; | ||
1831 | if (volume0==0) control0=0; | ||
1832 | if (volume1==0) control1=0; | ||
1833 | drvcmd[0]=CMD2_SETMODE; | ||
1834 | drvcmd[1]=0x0E; | ||
1835 | drvcmd[3]=control0; | ||
1836 | drvcmd[4]=value0; | ||
1837 | drvcmd[5]=control1; | ||
1838 | drvcmd[6]=value1; | ||
1839 | flags_cmd_out=f_putcmd|f_ResponseStatus; | ||
1840 | } | ||
1841 | else if (famL_drive) | ||
1842 | { | ||
1843 | if ((volume0==0)||(channel0!=0)) control0 |= 0x80; | ||
1844 | if ((volume1==0)||(channel1!=1)) control0 |= 0x40; | ||
1845 | if (volume0|volume1) value0=0x80; | ||
1846 | drvcmd[0]=CMDL_SETMODE; | ||
1847 | drvcmd[1]=0x03; | ||
1848 | drvcmd[4]=control0; | ||
1849 | drvcmd[5]=value0; | ||
1850 | flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; | ||
1851 | } | ||
1852 | else if (fam0_drive) /* different firmware levels */ | ||
1853 | { | ||
1854 | if (current_drive->drv_type>=drv_300) | ||
1855 | { | ||
1856 | control0=volume0&0xFC; | ||
1857 | value0=volume1&0xFC; | ||
1858 | if ((volume0!=0)&&(volume0<4)) control0 |= 0x04; | ||
1859 | if ((volume1!=0)&&(volume1<4)) value0 |= 0x04; | ||
1860 | if (channel0!=0) control0 |= 0x01; | ||
1861 | if (channel1==1) value0 |= 0x01; | ||
1862 | } | ||
1863 | else | ||
1864 | { | ||
1865 | value0=(volume0>volume1)?volume0:volume1; | ||
1866 | if (current_drive->drv_type<drv_211) | ||
1867 | { | ||
1868 | if (channel0!=0) | ||
1869 | { | ||
1870 | i=channel1; | ||
1871 | channel1=channel0; | ||
1872 | channel0=i; | ||
1873 | i=volume1; | ||
1874 | volume1=volume0; | ||
1875 | volume0=i; | ||
1876 | } | ||
1877 | if (channel0==channel1) | ||
1878 | { | ||
1879 | if (channel0==0) | ||
1880 | { | ||
1881 | channel1=1; | ||
1882 | volume1=0; | ||
1883 | volume0=value0; | ||
1884 | } | ||
1885 | else | ||
1886 | { | ||
1887 | channel0=0; | ||
1888 | volume0=0; | ||
1889 | volume1=value0; | ||
1890 | } | ||
1891 | } | ||
1892 | } | ||
1893 | |||
1894 | if ((volume0!=0)&&(volume1!=0)) | ||
1895 | { | ||
1896 | if (volume0==0xFF) volume1=0xFF; | ||
1897 | else if (volume1==0xFF) volume0=0xFF; | ||
1898 | } | ||
1899 | else if (current_drive->drv_type<drv_201) volume0=volume1=value0; | ||
1900 | |||
1901 | if (current_drive->drv_type>=drv_201) | ||
1902 | { | ||
1903 | if (volume0==0) control0 |= 0x80; | ||
1904 | if (volume1==0) control0 |= 0x40; | ||
1905 | } | ||
1906 | if (current_drive->drv_type>=drv_211) | ||
1907 | { | ||
1908 | if (channel0!=0) control0 |= 0x20; | ||
1909 | if (channel1!=1) control0 |= 0x10; | ||
1910 | } | ||
1911 | } | ||
1912 | drvcmd[0]=CMD0_SETMODE; | ||
1913 | drvcmd[1]=0x83; | ||
1914 | drvcmd[4]=control0; | ||
1915 | drvcmd[5]=value0; | ||
1916 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
1917 | } | ||
1918 | else if (famT_drive) | ||
1919 | { | ||
1920 | current_drive->volume_control=0; | ||
1921 | if (!volume0) current_drive->volume_control|=0x10; | ||
1922 | if (!volume1) current_drive->volume_control|=0x20; | ||
1923 | i=cc_prep_mode_T(); | ||
1924 | if (i<0) return (i); | ||
1925 | } | ||
1926 | if (!famT_drive) | ||
1927 | { | ||
1928 | response_count=0; | ||
1929 | i=cmd_out(); | ||
1930 | if (i<0) return (i); | ||
1931 | } | ||
1932 | current_drive->diskstate_flags |= volume_bit; | ||
1933 | return (0); | ||
1934 | } | ||
1935 | /*==========================================================================*/ | ||
1936 | static int GetStatus(void) | ||
1937 | { | ||
1938 | int i; | ||
1939 | |||
1940 | if (famT_drive) return (0); | ||
1941 | flags_cmd_out=f_getsta|f_ResponseStatus|f_obey_p_check; | ||
1942 | response_count=0; | ||
1943 | cmd_type=0; | ||
1944 | i=cmd_out(); | ||
1945 | return (i); | ||
1946 | } | ||
1947 | /*==========================================================================*/ | ||
1948 | static int cc_DriveReset(void) | ||
1949 | { | ||
1950 | int i; | ||
1951 | |||
1952 | msg(DBG_RES,"cc_DriveReset called.\n"); | ||
1953 | clr_cmdbuf(); | ||
1954 | response_count=0; | ||
1955 | if (fam0LV_drive) OUT(CDo_reset,0x00); | ||
1956 | else if (fam1_drive) | ||
1957 | { | ||
1958 | drvcmd[0]=CMD1_RESET; | ||
1959 | flags_cmd_out=f_putcmd; | ||
1960 | i=cmd_out(); | ||
1961 | } | ||
1962 | else if (fam2_drive) | ||
1963 | { | ||
1964 | drvcmd[0]=CMD2_RESET; | ||
1965 | flags_cmd_out=f_putcmd; | ||
1966 | i=cmd_out(); | ||
1967 | OUT(CDo_reset,0x00); | ||
1968 | } | ||
1969 | else if (famT_drive) | ||
1970 | { | ||
1971 | OUT(CDo_sel_i_d,0); | ||
1972 | OUT(CDo_enable,current_drive->drv_sel); | ||
1973 | OUT(CDo_command,CMDT_RESET); | ||
1974 | for (i=1;i<10;i++) OUT(CDo_command,0); | ||
1975 | } | ||
1976 | if (fam0LV_drive) sbp_sleep(5*HZ); /* wait 5 seconds */ | ||
1977 | else sbp_sleep(1*HZ); /* wait a second */ | ||
1978 | #if 1 | ||
1979 | if (famT_drive) | ||
1980 | { | ||
1981 | msg(DBG_TEA, "================CMDT_RESET given=================.\n"); | ||
1982 | sbp_sleep(3*HZ); | ||
1983 | } | ||
1984 | #endif /* 1 */ | ||
1985 | flush_status(); | ||
1986 | i=GetStatus(); | ||
1987 | if (i<0) return i; | ||
1988 | if (!famT_drive) | ||
1989 | if (current_drive->error_byte!=aud_12) return -501; | ||
1990 | return (0); | ||
1991 | } | ||
1992 | |||
1993 | /*==========================================================================*/ | ||
1994 | static int SetSpeed(void) | ||
1995 | { | ||
1996 | int i, speed; | ||
1997 | |||
1998 | if (!(current_drive->drv_options&(speed_auto|speed_300|speed_150))) return (0); | ||
1999 | speed=speed_auto; | ||
2000 | if (!(current_drive->drv_options&speed_auto)) | ||
2001 | { | ||
2002 | speed |= speed_300; | ||
2003 | if (!(current_drive->drv_options&speed_300)) speed=0; | ||
2004 | } | ||
2005 | i=cc_SetSpeed(speed,0,0); | ||
2006 | return (i); | ||
2007 | } | ||
2008 | |||
2009 | static void switch_drive(struct sbpcd_drive *); | ||
2010 | |||
2011 | static int sbpcd_select_speed(struct cdrom_device_info *cdi, int speed) | ||
2012 | { | ||
2013 | struct sbpcd_drive *p = cdi->handle; | ||
2014 | if (p != current_drive) | ||
2015 | switch_drive(p); | ||
2016 | |||
2017 | return cc_SetSpeed(speed == 2 ? speed_300 : speed_150, 0, 0); | ||
2018 | } | ||
2019 | |||
2020 | /*==========================================================================*/ | ||
2021 | static int DriveReset(void) | ||
2022 | { | ||
2023 | int i; | ||
2024 | |||
2025 | i=cc_DriveReset(); | ||
2026 | if (i<0) return (-22); | ||
2027 | do | ||
2028 | { | ||
2029 | i=GetStatus(); | ||
2030 | if ((i<0)&&(i!=-ERR_DISKCHANGE)) { | ||
2031 | return (-2); /* from sta2err */ | ||
2032 | } | ||
2033 | if (!st_caddy_in) break; | ||
2034 | sbp_sleep(1); | ||
2035 | } | ||
2036 | while (!st_diskok); | ||
2037 | #if 000 | ||
2038 | current_drive->CD_changed=1; | ||
2039 | #endif | ||
2040 | if ((st_door_closed) && (st_caddy_in)) | ||
2041 | { | ||
2042 | i=DiskInfo(); | ||
2043 | if (i<0) return (-23); | ||
2044 | } | ||
2045 | return (0); | ||
2046 | } | ||
2047 | |||
2048 | static int sbpcd_reset(struct cdrom_device_info *cdi) | ||
2049 | { | ||
2050 | struct sbpcd_drive *p = cdi->handle; | ||
2051 | if (p != current_drive) | ||
2052 | switch_drive(p); | ||
2053 | return DriveReset(); | ||
2054 | } | ||
2055 | |||
2056 | /*==========================================================================*/ | ||
2057 | static int cc_PlayAudio(int pos_audio_start,int pos_audio_end) | ||
2058 | { | ||
2059 | int i, j, n; | ||
2060 | |||
2061 | if (current_drive->audio_state==audio_playing) return (-EINVAL); | ||
2062 | clr_cmdbuf(); | ||
2063 | response_count=0; | ||
2064 | if (famLV_drive) | ||
2065 | { | ||
2066 | drvcmd[0]=CMDL_PLAY; | ||
2067 | i=msf2blk(pos_audio_start); | ||
2068 | n=msf2blk(pos_audio_end)+1-i; | ||
2069 | drvcmd[1]=(i>>16)&0x00FF; | ||
2070 | drvcmd[2]=(i>>8)&0x00FF; | ||
2071 | drvcmd[3]=i&0x00FF; | ||
2072 | drvcmd[4]=(n>>16)&0x00FF; | ||
2073 | drvcmd[5]=(n>>8)&0x00FF; | ||
2074 | drvcmd[6]=n&0x00FF; | ||
2075 | if (famL_drive) | ||
2076 | flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta | | ||
2077 | f_ResponseStatus | f_obey_p_check | f_wait_if_busy; | ||
2078 | else | ||
2079 | flags_cmd_out = f_putcmd; | ||
2080 | } | ||
2081 | else | ||
2082 | { | ||
2083 | j=1; | ||
2084 | if (fam1_drive) | ||
2085 | { | ||
2086 | drvcmd[0]=CMD1_PLAY_MSF; | ||
2087 | flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | | ||
2088 | f_obey_p_check | f_wait_if_busy; | ||
2089 | } | ||
2090 | else if (fam2_drive) | ||
2091 | { | ||
2092 | drvcmd[0]=CMD2_PLAY_MSF; | ||
2093 | flags_cmd_out = f_putcmd | f_ResponseStatus | f_obey_p_check; | ||
2094 | } | ||
2095 | else if (famT_drive) | ||
2096 | { | ||
2097 | drvcmd[0]=CMDT_PLAY_MSF; | ||
2098 | j=3; | ||
2099 | response_count=1; | ||
2100 | } | ||
2101 | else if (fam0_drive) | ||
2102 | { | ||
2103 | drvcmd[0]=CMD0_PLAY_MSF; | ||
2104 | flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta | | ||
2105 | f_ResponseStatus | f_obey_p_check | f_wait_if_busy; | ||
2106 | } | ||
2107 | drvcmd[j]=(pos_audio_start>>16)&0x00FF; | ||
2108 | drvcmd[j+1]=(pos_audio_start>>8)&0x00FF; | ||
2109 | drvcmd[j+2]=pos_audio_start&0x00FF; | ||
2110 | drvcmd[j+3]=(pos_audio_end>>16)&0x00FF; | ||
2111 | drvcmd[j+4]=(pos_audio_end>>8)&0x00FF; | ||
2112 | drvcmd[j+5]=pos_audio_end&0x00FF; | ||
2113 | } | ||
2114 | i=cmd_out(); | ||
2115 | return (i); | ||
2116 | } | ||
2117 | /*==========================================================================*/ | ||
2118 | static int cc_Pause_Resume(int pau_res) | ||
2119 | { | ||
2120 | int i; | ||
2121 | |||
2122 | clr_cmdbuf(); | ||
2123 | response_count=0; | ||
2124 | if (fam1_drive) | ||
2125 | { | ||
2126 | drvcmd[0]=CMD1_PAU_RES; | ||
2127 | if (pau_res!=1) drvcmd[1]=0x80; | ||
2128 | flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; | ||
2129 | } | ||
2130 | else if (fam2_drive) | ||
2131 | { | ||
2132 | drvcmd[0]=CMD2_PAU_RES; | ||
2133 | if (pau_res!=1) drvcmd[2]=0x01; | ||
2134 | flags_cmd_out=f_putcmd|f_ResponseStatus; | ||
2135 | } | ||
2136 | else if (fam0LV_drive) | ||
2137 | { | ||
2138 | drvcmd[0]=CMD0_PAU_RES; | ||
2139 | if (pau_res!=1) drvcmd[1]=0x80; | ||
2140 | if (famL_drive) | ||
2141 | flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus| | ||
2142 | f_obey_p_check|f_bit1; | ||
2143 | else if (famV_drive) | ||
2144 | flags_cmd_out=f_putcmd; | ||
2145 | else | ||
2146 | flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus| | ||
2147 | f_obey_p_check; | ||
2148 | } | ||
2149 | else if (famT_drive) | ||
2150 | { | ||
2151 | if (pau_res==3) return (cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end)); | ||
2152 | else if (pau_res==1) drvcmd[0]=CMDT_PAUSE; | ||
2153 | else return (-56); | ||
2154 | } | ||
2155 | i=cmd_out(); | ||
2156 | return (i); | ||
2157 | } | ||
2158 | /*==========================================================================*/ | ||
2159 | static int cc_LockDoor(char lock) | ||
2160 | { | ||
2161 | int i; | ||
2162 | |||
2163 | if (fam0_drive) return (0); | ||
2164 | msg(DBG_LCK,"cc_LockDoor: %d (drive %d)\n", lock, current_drive - D_S); | ||
2165 | msg(DBG_LCS,"p_door_locked bit %d before\n", st_door_locked); | ||
2166 | clr_cmdbuf(); | ||
2167 | response_count=0; | ||
2168 | if (fam1_drive) | ||
2169 | { | ||
2170 | drvcmd[0]=CMD1_LOCK_CTL; | ||
2171 | if (lock==1) drvcmd[1]=0x01; | ||
2172 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2173 | } | ||
2174 | else if (fam2_drive) | ||
2175 | { | ||
2176 | drvcmd[0]=CMD2_LOCK_CTL; | ||
2177 | if (lock==1) drvcmd[4]=0x01; | ||
2178 | flags_cmd_out=f_putcmd|f_ResponseStatus; | ||
2179 | } | ||
2180 | else if (famLV_drive) | ||
2181 | { | ||
2182 | drvcmd[0]=CMDL_LOCK_CTL; | ||
2183 | if (lock==1) drvcmd[1]=0x01; | ||
2184 | if (famL_drive) | ||
2185 | flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; | ||
2186 | else | ||
2187 | flags_cmd_out=f_putcmd; | ||
2188 | } | ||
2189 | else if (famT_drive) | ||
2190 | { | ||
2191 | drvcmd[0]=CMDT_LOCK_CTL; | ||
2192 | if (lock==1) drvcmd[4]=0x01; | ||
2193 | } | ||
2194 | i=cmd_out(); | ||
2195 | msg(DBG_LCS,"p_door_locked bit %d after\n", st_door_locked); | ||
2196 | return (i); | ||
2197 | } | ||
2198 | /*==========================================================================*/ | ||
2199 | /*==========================================================================*/ | ||
2200 | static int UnLockDoor(void) | ||
2201 | { | ||
2202 | int i,j; | ||
2203 | |||
2204 | j=20; | ||
2205 | do | ||
2206 | { | ||
2207 | i=cc_LockDoor(0); | ||
2208 | --j; | ||
2209 | sbp_sleep(1); | ||
2210 | } | ||
2211 | while ((i<0)&&(j)); | ||
2212 | if (i<0) | ||
2213 | { | ||
2214 | cc_DriveReset(); | ||
2215 | return -84; | ||
2216 | } | ||
2217 | return (0); | ||
2218 | } | ||
2219 | /*==========================================================================*/ | ||
2220 | static int LockDoor(void) | ||
2221 | { | ||
2222 | int i,j; | ||
2223 | |||
2224 | j=20; | ||
2225 | do | ||
2226 | { | ||
2227 | i=cc_LockDoor(1); | ||
2228 | --j; | ||
2229 | sbp_sleep(1); | ||
2230 | } | ||
2231 | while ((i<0)&&(j)); | ||
2232 | if (j==0) | ||
2233 | { | ||
2234 | cc_DriveReset(); | ||
2235 | j=20; | ||
2236 | do | ||
2237 | { | ||
2238 | i=cc_LockDoor(1); | ||
2239 | --j; | ||
2240 | sbp_sleep(1); | ||
2241 | } | ||
2242 | while ((i<0)&&(j)); | ||
2243 | } | ||
2244 | return (i); | ||
2245 | } | ||
2246 | |||
2247 | static int sbpcd_lock_door(struct cdrom_device_info *cdi, int lock) | ||
2248 | { | ||
2249 | return lock ? LockDoor() : UnLockDoor(); | ||
2250 | } | ||
2251 | |||
2252 | /*==========================================================================*/ | ||
2253 | static int cc_CloseTray(void) | ||
2254 | { | ||
2255 | int i; | ||
2256 | |||
2257 | if (fam0_drive) return (0); | ||
2258 | msg(DBG_LCK,"cc_CloseTray (drive %d)\n", current_drive - D_S); | ||
2259 | msg(DBG_LCS,"p_door_closed bit %d before\n", st_door_closed); | ||
2260 | |||
2261 | clr_cmdbuf(); | ||
2262 | response_count=0; | ||
2263 | if (fam1_drive) | ||
2264 | { | ||
2265 | drvcmd[0]=CMD1_TRAY_CTL; | ||
2266 | flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; | ||
2267 | } | ||
2268 | else if (fam2_drive) | ||
2269 | { | ||
2270 | drvcmd[0]=CMD2_TRAY_CTL; | ||
2271 | drvcmd[1]=0x01; | ||
2272 | drvcmd[4]=0x03; /* "insert" */ | ||
2273 | flags_cmd_out=f_putcmd|f_ResponseStatus; | ||
2274 | } | ||
2275 | else if (famLV_drive) | ||
2276 | { | ||
2277 | drvcmd[0]=CMDL_TRAY_CTL; | ||
2278 | if (famLV_drive) | ||
2279 | flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta| | ||
2280 | f_ResponseStatus|f_obey_p_check|f_bit1; | ||
2281 | else | ||
2282 | flags_cmd_out=f_putcmd; | ||
2283 | } | ||
2284 | else if (famT_drive) | ||
2285 | { | ||
2286 | drvcmd[0]=CMDT_TRAY_CTL; | ||
2287 | drvcmd[4]=0x03; /* "insert" */ | ||
2288 | } | ||
2289 | i=cmd_out(); | ||
2290 | msg(DBG_LCS,"p_door_closed bit %d after\n", st_door_closed); | ||
2291 | |||
2292 | i=cc_ReadError(); | ||
2293 | flags_cmd_out |= f_respo2; | ||
2294 | cc_ReadStatus(); /* command: give 1-byte status */ | ||
2295 | i=ResponseStatus(); | ||
2296 | if (famT_drive&&(i<0)) | ||
2297 | { | ||
2298 | cc_DriveReset(); | ||
2299 | i=ResponseStatus(); | ||
2300 | #if 0 | ||
2301 | sbp_sleep(HZ); | ||
2302 | #endif /* 0 */ | ||
2303 | i=ResponseStatus(); | ||
2304 | } | ||
2305 | if (i<0) | ||
2306 | { | ||
2307 | msg(DBG_INF,"sbpcd cc_CloseTray: ResponseStatus timed out (%d).\n",i); | ||
2308 | } | ||
2309 | if (!(famT_drive)) | ||
2310 | { | ||
2311 | if (!st_spinning) | ||
2312 | { | ||
2313 | cc_SpinUp(); | ||
2314 | if (st_check) i=cc_ReadError(); | ||
2315 | flags_cmd_out |= f_respo2; | ||
2316 | cc_ReadStatus(); | ||
2317 | i=ResponseStatus(); | ||
2318 | } else { | ||
2319 | } | ||
2320 | } | ||
2321 | i=DiskInfo(); | ||
2322 | return (i); | ||
2323 | } | ||
2324 | |||
2325 | static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position) | ||
2326 | { | ||
2327 | int retval=0; | ||
2328 | switch_drive(cdi->handle); | ||
2329 | /* DUH! --AJK */ | ||
2330 | if(current_drive->CD_changed != 0xFF) { | ||
2331 | current_drive->CD_changed=0xFF; | ||
2332 | current_drive->diskstate_flags &= ~cd_size_bit; | ||
2333 | } | ||
2334 | if (position == 1) { | ||
2335 | cc_SpinDown(); | ||
2336 | } else { | ||
2337 | retval=cc_CloseTray(); | ||
2338 | } | ||
2339 | return retval; | ||
2340 | } | ||
2341 | |||
2342 | /*==========================================================================*/ | ||
2343 | static int cc_ReadSubQ(void) | ||
2344 | { | ||
2345 | int i,j; | ||
2346 | |||
2347 | current_drive->diskstate_flags &= ~subq_bit; | ||
2348 | for (j=255;j>0;j--) | ||
2349 | { | ||
2350 | clr_cmdbuf(); | ||
2351 | if (fam1_drive) | ||
2352 | { | ||
2353 | drvcmd[0]=CMD1_READSUBQ; | ||
2354 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2355 | response_count=11; | ||
2356 | } | ||
2357 | else if (fam2_drive) | ||
2358 | { | ||
2359 | drvcmd[0]=CMD2_READSUBQ; | ||
2360 | drvcmd[1]=0x02; | ||
2361 | drvcmd[3]=0x01; | ||
2362 | flags_cmd_out=f_putcmd; | ||
2363 | response_count=10; | ||
2364 | } | ||
2365 | else if (fam0LV_drive) | ||
2366 | { | ||
2367 | drvcmd[0]=CMD0_READSUBQ; | ||
2368 | drvcmd[1]=0x02; | ||
2369 | if (famLV_drive) | ||
2370 | flags_cmd_out=f_putcmd; | ||
2371 | else | ||
2372 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2373 | response_count=13; | ||
2374 | } | ||
2375 | else if (famT_drive) | ||
2376 | { | ||
2377 | response_count=12; | ||
2378 | drvcmd[0]=CMDT_READSUBQ; | ||
2379 | drvcmd[1]=0x02; | ||
2380 | drvcmd[2]=0x40; | ||
2381 | drvcmd[3]=0x01; | ||
2382 | drvcmd[8]=response_count; | ||
2383 | } | ||
2384 | i=cmd_out(); | ||
2385 | if (i<0) return (i); | ||
2386 | for (i=0;i<response_count;i++) | ||
2387 | { | ||
2388 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
2389 | msgbuf[i*3]=0; | ||
2390 | msg(DBG_SQ1,"cc_ReadSubQ:%s\n", msgbuf); | ||
2391 | } | ||
2392 | if (famT_drive) break; | ||
2393 | if (infobuf[0]!=0) break; | ||
2394 | if ((!st_spinning) || (j==1)) | ||
2395 | { | ||
2396 | current_drive->SubQ_ctl_adr=current_drive->SubQ_trk=current_drive->SubQ_pnt_idx=current_drive->SubQ_whatisthis=0; | ||
2397 | current_drive->SubQ_run_tot=current_drive->SubQ_run_trk=0; | ||
2398 | return (0); | ||
2399 | } | ||
2400 | } | ||
2401 | if (famT_drive) current_drive->SubQ_ctl_adr=infobuf[1]; | ||
2402 | else current_drive->SubQ_ctl_adr=swap_nibbles(infobuf[1]); | ||
2403 | current_drive->SubQ_trk=byt2bcd(infobuf[2]); | ||
2404 | current_drive->SubQ_pnt_idx=byt2bcd(infobuf[3]); | ||
2405 | if (fam0LV_drive) i=5; | ||
2406 | else if (fam12_drive) i=4; | ||
2407 | else if (famT_drive) i=8; | ||
2408 | current_drive->SubQ_run_tot=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */ | ||
2409 | i=7; | ||
2410 | if (fam0LV_drive) i=9; | ||
2411 | else if (fam12_drive) i=7; | ||
2412 | else if (famT_drive) i=4; | ||
2413 | current_drive->SubQ_run_trk=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */ | ||
2414 | current_drive->SubQ_whatisthis=infobuf[i+3]; | ||
2415 | current_drive->diskstate_flags |= subq_bit; | ||
2416 | return (0); | ||
2417 | } | ||
2418 | /*==========================================================================*/ | ||
2419 | static int cc_ModeSense(void) | ||
2420 | { | ||
2421 | int i; | ||
2422 | |||
2423 | if (fam2_drive) return (0); | ||
2424 | if (famV_drive) return (0); | ||
2425 | current_drive->diskstate_flags &= ~frame_size_bit; | ||
2426 | clr_cmdbuf(); | ||
2427 | if (fam1_drive) | ||
2428 | { | ||
2429 | response_count=5; | ||
2430 | drvcmd[0]=CMD1_GETMODE; | ||
2431 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2432 | } | ||
2433 | else if (fam0L_drive) | ||
2434 | { | ||
2435 | response_count=2; | ||
2436 | drvcmd[0]=CMD0_GETMODE; | ||
2437 | if (famL_drive) flags_cmd_out=f_putcmd; | ||
2438 | else flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2439 | } | ||
2440 | else if (famT_drive) | ||
2441 | { | ||
2442 | response_count=10; | ||
2443 | drvcmd[0]=CMDT_GETMODE; | ||
2444 | drvcmd[4]=response_count; | ||
2445 | } | ||
2446 | i=cmd_out(); | ||
2447 | if (i<0) return (i); | ||
2448 | i=0; | ||
2449 | current_drive->sense_byte=0; | ||
2450 | if (fam1_drive) current_drive->sense_byte=infobuf[i++]; | ||
2451 | else if (famT_drive) | ||
2452 | { | ||
2453 | if (infobuf[4]==0x01) current_drive->xa_byte=0x20; | ||
2454 | else current_drive->xa_byte=0; | ||
2455 | i=2; | ||
2456 | } | ||
2457 | current_drive->frame_size=make16(infobuf[i],infobuf[i+1]); | ||
2458 | for (i=0;i<response_count;i++) | ||
2459 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
2460 | msgbuf[i*3]=0; | ||
2461 | msg(DBG_XA1,"cc_ModeSense:%s\n", msgbuf); | ||
2462 | |||
2463 | current_drive->diskstate_flags |= frame_size_bit; | ||
2464 | return (0); | ||
2465 | } | ||
2466 | /*==========================================================================*/ | ||
2467 | /*==========================================================================*/ | ||
2468 | static int cc_ModeSelect(int framesize) | ||
2469 | { | ||
2470 | int i; | ||
2471 | |||
2472 | if (fam2_drive) return (0); | ||
2473 | if (famV_drive) return (0); | ||
2474 | current_drive->diskstate_flags &= ~frame_size_bit; | ||
2475 | clr_cmdbuf(); | ||
2476 | current_drive->frame_size=framesize; | ||
2477 | if (framesize==CD_FRAMESIZE_RAW) current_drive->sense_byte=0x82; | ||
2478 | else current_drive->sense_byte=0x00; | ||
2479 | |||
2480 | msg(DBG_XA1,"cc_ModeSelect: %02X %04X\n", | ||
2481 | current_drive->sense_byte, current_drive->frame_size); | ||
2482 | |||
2483 | if (fam1_drive) | ||
2484 | { | ||
2485 | drvcmd[0]=CMD1_SETMODE; | ||
2486 | drvcmd[1]=0x00; | ||
2487 | drvcmd[2]=current_drive->sense_byte; | ||
2488 | drvcmd[3]=(current_drive->frame_size>>8)&0xFF; | ||
2489 | drvcmd[4]=current_drive->frame_size&0xFF; | ||
2490 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2491 | } | ||
2492 | else if (fam0L_drive) | ||
2493 | { | ||
2494 | drvcmd[0]=CMD0_SETMODE; | ||
2495 | drvcmd[1]=0x00; | ||
2496 | drvcmd[2]=(current_drive->frame_size>>8)&0xFF; | ||
2497 | drvcmd[3]=current_drive->frame_size&0xFF; | ||
2498 | drvcmd[4]=0x00; | ||
2499 | if(famL_drive) | ||
2500 | flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2501 | else | ||
2502 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2503 | } | ||
2504 | else if (famT_drive) | ||
2505 | { | ||
2506 | return (-1); | ||
2507 | } | ||
2508 | response_count=0; | ||
2509 | i=cmd_out(); | ||
2510 | if (i<0) return (i); | ||
2511 | current_drive->diskstate_flags |= frame_size_bit; | ||
2512 | return (0); | ||
2513 | } | ||
2514 | /*==========================================================================*/ | ||
2515 | static int cc_GetVolume(void) | ||
2516 | { | ||
2517 | int i; | ||
2518 | u_char switches; | ||
2519 | u_char chan0=0; | ||
2520 | u_char vol0=0; | ||
2521 | u_char chan1=1; | ||
2522 | u_char vol1=0; | ||
2523 | |||
2524 | if (famV_drive) return (0); | ||
2525 | current_drive->diskstate_flags &= ~volume_bit; | ||
2526 | clr_cmdbuf(); | ||
2527 | if (fam1_drive) | ||
2528 | { | ||
2529 | drvcmd[0]=CMD1_GETMODE; | ||
2530 | drvcmd[1]=0x05; | ||
2531 | response_count=5; | ||
2532 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2533 | } | ||
2534 | else if (fam2_drive) | ||
2535 | { | ||
2536 | drvcmd[0]=CMD2_GETMODE; | ||
2537 | drvcmd[1]=0x0E; | ||
2538 | response_count=5; | ||
2539 | flags_cmd_out=f_putcmd; | ||
2540 | } | ||
2541 | else if (fam0L_drive) | ||
2542 | { | ||
2543 | drvcmd[0]=CMD0_GETMODE; | ||
2544 | drvcmd[1]=0x03; | ||
2545 | response_count=2; | ||
2546 | if(famL_drive) | ||
2547 | flags_cmd_out=f_putcmd; | ||
2548 | else | ||
2549 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2550 | } | ||
2551 | else if (famT_drive) | ||
2552 | { | ||
2553 | i=cc_get_mode_T(); | ||
2554 | if (i<0) return (i); | ||
2555 | } | ||
2556 | if (!famT_drive) | ||
2557 | { | ||
2558 | i=cmd_out(); | ||
2559 | if (i<0) return (i); | ||
2560 | } | ||
2561 | if (fam1_drive) | ||
2562 | { | ||
2563 | chan0=infobuf[1]&0x0F; | ||
2564 | vol0=infobuf[2]; | ||
2565 | chan1=infobuf[3]&0x0F; | ||
2566 | vol1=infobuf[4]; | ||
2567 | if (chan0==0) | ||
2568 | { | ||
2569 | chan0=1; | ||
2570 | vol0=0; | ||
2571 | } | ||
2572 | if (chan1==0) | ||
2573 | { | ||
2574 | chan1=2; | ||
2575 | vol1=0; | ||
2576 | } | ||
2577 | chan0 >>= 1; | ||
2578 | chan1 >>= 1; | ||
2579 | } | ||
2580 | else if (fam2_drive) | ||
2581 | { | ||
2582 | chan0=infobuf[1]; | ||
2583 | vol0=infobuf[2]; | ||
2584 | chan1=infobuf[3]; | ||
2585 | vol1=infobuf[4]; | ||
2586 | } | ||
2587 | else if (famL_drive) | ||
2588 | { | ||
2589 | chan0=0; | ||
2590 | chan1=1; | ||
2591 | vol0=vol1=infobuf[1]; | ||
2592 | switches=infobuf[0]; | ||
2593 | if ((switches&0x80)!=0) chan0=1; | ||
2594 | if ((switches&0x40)!=0) chan1=0; | ||
2595 | } | ||
2596 | else if (fam0_drive) /* different firmware levels */ | ||
2597 | { | ||
2598 | chan0=0; | ||
2599 | chan1=1; | ||
2600 | vol0=vol1=infobuf[1]; | ||
2601 | if (current_drive->drv_type>=drv_201) | ||
2602 | { | ||
2603 | if (current_drive->drv_type<drv_300) | ||
2604 | { | ||
2605 | switches=infobuf[0]; | ||
2606 | if ((switches&0x80)!=0) vol0=0; | ||
2607 | if ((switches&0x40)!=0) vol1=0; | ||
2608 | if (current_drive->drv_type>=drv_211) | ||
2609 | { | ||
2610 | if ((switches&0x20)!=0) chan0=1; | ||
2611 | if ((switches&0x10)!=0) chan1=0; | ||
2612 | } | ||
2613 | } | ||
2614 | else | ||
2615 | { | ||
2616 | vol0=infobuf[0]; | ||
2617 | if ((vol0&0x01)!=0) chan0=1; | ||
2618 | if ((vol1&0x01)==0) chan1=0; | ||
2619 | vol0 &= 0xFC; | ||
2620 | vol1 &= 0xFC; | ||
2621 | if (vol0!=0) vol0 += 3; | ||
2622 | if (vol1!=0) vol1 += 3; | ||
2623 | } | ||
2624 | } | ||
2625 | } | ||
2626 | else if (famT_drive) | ||
2627 | { | ||
2628 | current_drive->volume_control=infobuf[7]; | ||
2629 | chan0=0; | ||
2630 | chan1=1; | ||
2631 | if (current_drive->volume_control&0x10) vol0=0; | ||
2632 | else vol0=0xff; | ||
2633 | if (current_drive->volume_control&0x20) vol1=0; | ||
2634 | else vol1=0xff; | ||
2635 | } | ||
2636 | current_drive->vol_chan0=chan0; | ||
2637 | current_drive->vol_ctrl0=vol0; | ||
2638 | current_drive->vol_chan1=chan1; | ||
2639 | current_drive->vol_ctrl1=vol1; | ||
2640 | #if 000 | ||
2641 | current_drive->vol_chan2=2; | ||
2642 | current_drive->vol_ctrl2=0xFF; | ||
2643 | current_drive->vol_chan3=3; | ||
2644 | current_drive->vol_ctrl3=0xFF; | ||
2645 | #endif /* 000 */ | ||
2646 | current_drive->diskstate_flags |= volume_bit; | ||
2647 | return (0); | ||
2648 | } | ||
2649 | /*==========================================================================*/ | ||
2650 | static int cc_ReadCapacity(void) | ||
2651 | { | ||
2652 | int i, j; | ||
2653 | |||
2654 | if (fam2_drive) return (0); /* some firmware lacks this command */ | ||
2655 | if (famLV_drive) return (0); /* some firmware lacks this command */ | ||
2656 | if (famT_drive) return (0); /* done with cc_ReadTocDescr() */ | ||
2657 | current_drive->diskstate_flags &= ~cd_size_bit; | ||
2658 | for (j=3;j>0;j--) | ||
2659 | { | ||
2660 | clr_cmdbuf(); | ||
2661 | if (fam1_drive) | ||
2662 | { | ||
2663 | drvcmd[0]=CMD1_CAPACITY; | ||
2664 | response_count=5; | ||
2665 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2666 | } | ||
2667 | #if 00 | ||
2668 | else if (fam2_drive) | ||
2669 | { | ||
2670 | drvcmd[0]=CMD2_CAPACITY; | ||
2671 | response_count=8; | ||
2672 | flags_cmd_out=f_putcmd; | ||
2673 | } | ||
2674 | #endif | ||
2675 | else if (fam0_drive) | ||
2676 | { | ||
2677 | drvcmd[0]=CMD0_CAPACITY; | ||
2678 | response_count=5; | ||
2679 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2680 | } | ||
2681 | i=cmd_out(); | ||
2682 | if (i>=0) break; | ||
2683 | msg(DBG_000,"cc_ReadCapacity: cmd_out: err %d\n", i); | ||
2684 | cc_ReadError(); | ||
2685 | } | ||
2686 | if (j==0) return (i); | ||
2687 | if (fam1_drive) current_drive->CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_MSF_OFFSET; | ||
2688 | else if (fam0_drive) current_drive->CDsize_frm=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])); | ||
2689 | #if 00 | ||
2690 | else if (fam2_drive) current_drive->CDsize_frm=make32(make16(infobuf[0],infobuf[1]),make16(infobuf[2],infobuf[3])); | ||
2691 | #endif | ||
2692 | current_drive->diskstate_flags |= cd_size_bit; | ||
2693 | msg(DBG_000,"cc_ReadCapacity: %d frames.\n", current_drive->CDsize_frm); | ||
2694 | return (0); | ||
2695 | } | ||
2696 | /*==========================================================================*/ | ||
2697 | static int cc_ReadTocDescr(void) | ||
2698 | { | ||
2699 | int i; | ||
2700 | |||
2701 | current_drive->diskstate_flags &= ~toc_bit; | ||
2702 | clr_cmdbuf(); | ||
2703 | if (fam1_drive) | ||
2704 | { | ||
2705 | drvcmd[0]=CMD1_DISKINFO; | ||
2706 | response_count=6; | ||
2707 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2708 | } | ||
2709 | else if (fam0LV_drive) | ||
2710 | { | ||
2711 | drvcmd[0]=CMD0_DISKINFO; | ||
2712 | response_count=6; | ||
2713 | if(famLV_drive) | ||
2714 | flags_cmd_out=f_putcmd; | ||
2715 | else | ||
2716 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2717 | } | ||
2718 | else if (fam2_drive) | ||
2719 | { | ||
2720 | /* possibly longer timeout periods necessary */ | ||
2721 | current_drive->f_multisession=0; | ||
2722 | drvcmd[0]=CMD2_DISKINFO; | ||
2723 | drvcmd[1]=0x02; | ||
2724 | drvcmd[2]=0xAB; | ||
2725 | drvcmd[3]=0xFF; /* session */ | ||
2726 | response_count=8; | ||
2727 | flags_cmd_out=f_putcmd; | ||
2728 | } | ||
2729 | else if (famT_drive) | ||
2730 | { | ||
2731 | current_drive->f_multisession=0; | ||
2732 | response_count=12; | ||
2733 | drvcmd[0]=CMDT_DISKINFO; | ||
2734 | drvcmd[1]=0x02; | ||
2735 | drvcmd[6]=CDROM_LEADOUT; | ||
2736 | drvcmd[8]=response_count; | ||
2737 | drvcmd[9]=0x00; | ||
2738 | } | ||
2739 | i=cmd_out(); | ||
2740 | if (i<0) return (i); | ||
2741 | if ((famT_drive)&&(i<response_count)) return (-100-i); | ||
2742 | if ((fam1_drive)||(fam2_drive)||(fam0LV_drive)) | ||
2743 | current_drive->xa_byte=infobuf[0]; | ||
2744 | if (fam2_drive) | ||
2745 | { | ||
2746 | current_drive->first_session=infobuf[1]; | ||
2747 | current_drive->last_session=infobuf[2]; | ||
2748 | current_drive->n_first_track=infobuf[3]; | ||
2749 | current_drive->n_last_track=infobuf[4]; | ||
2750 | if (current_drive->first_session!=current_drive->last_session) | ||
2751 | { | ||
2752 | current_drive->f_multisession=1; | ||
2753 | current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7]))); | ||
2754 | } | ||
2755 | #if 0 | ||
2756 | if (current_drive->first_session!=current_drive->last_session) | ||
2757 | { | ||
2758 | if (current_drive->last_session<=20) | ||
2759 | zwanzig=current_drive->last_session+1; | ||
2760 | else zwanzig=20; | ||
2761 | for (count=current_drive->first_session;count<zwanzig;count++) | ||
2762 | { | ||
2763 | drvcmd[0]=CMD2_DISKINFO; | ||
2764 | drvcmd[1]=0x02; | ||
2765 | drvcmd[2]=0xAB; | ||
2766 | drvcmd[3]=count; | ||
2767 | response_count=8; | ||
2768 | flags_cmd_out=f_putcmd; | ||
2769 | i=cmd_out(); | ||
2770 | if (i<0) return (i); | ||
2771 | current_drive->msf_multi_n[count]=make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7])); | ||
2772 | } | ||
2773 | current_drive->diskstate_flags |= multisession_bit; | ||
2774 | } | ||
2775 | #endif | ||
2776 | drvcmd[0]=CMD2_DISKINFO; | ||
2777 | drvcmd[1]=0x02; | ||
2778 | drvcmd[2]=0xAA; | ||
2779 | drvcmd[3]=0xFF; | ||
2780 | response_count=5; | ||
2781 | flags_cmd_out=f_putcmd; | ||
2782 | i=cmd_out(); | ||
2783 | if (i<0) return (i); | ||
2784 | current_drive->size_msf=make32(make16(0,infobuf[2]),make16(infobuf[3],infobuf[4])); | ||
2785 | current_drive->size_blk=msf2blk(current_drive->size_msf); | ||
2786 | current_drive->CDsize_frm=current_drive->size_blk+1; | ||
2787 | } | ||
2788 | else if (famT_drive) | ||
2789 | { | ||
2790 | current_drive->size_msf=make32(make16(infobuf[8],infobuf[9]),make16(infobuf[10],infobuf[11])); | ||
2791 | current_drive->size_blk=msf2blk(current_drive->size_msf); | ||
2792 | current_drive->CDsize_frm=current_drive->size_blk+1; | ||
2793 | current_drive->n_first_track=infobuf[2]; | ||
2794 | current_drive->n_last_track=infobuf[3]; | ||
2795 | } | ||
2796 | else | ||
2797 | { | ||
2798 | current_drive->n_first_track=infobuf[1]; | ||
2799 | current_drive->n_last_track=infobuf[2]; | ||
2800 | current_drive->size_msf=make32(make16(0,infobuf[3]),make16(infobuf[4],infobuf[5])); | ||
2801 | current_drive->size_blk=msf2blk(current_drive->size_msf); | ||
2802 | if (famLV_drive) current_drive->CDsize_frm=current_drive->size_blk+1; | ||
2803 | } | ||
2804 | current_drive->diskstate_flags |= toc_bit; | ||
2805 | msg(DBG_TOC,"TocDesc: xa %02X firstt %02X lastt %02X size %08X firstses %02X lastsess %02X\n", | ||
2806 | current_drive->xa_byte, | ||
2807 | current_drive->n_first_track, | ||
2808 | current_drive->n_last_track, | ||
2809 | current_drive->size_msf, | ||
2810 | current_drive->first_session, | ||
2811 | current_drive->last_session); | ||
2812 | return (0); | ||
2813 | } | ||
2814 | /*==========================================================================*/ | ||
2815 | static int cc_ReadTocEntry(int num) | ||
2816 | { | ||
2817 | int i; | ||
2818 | |||
2819 | clr_cmdbuf(); | ||
2820 | if (fam1_drive) | ||
2821 | { | ||
2822 | drvcmd[0]=CMD1_READTOC; | ||
2823 | drvcmd[2]=num; | ||
2824 | response_count=8; | ||
2825 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2826 | } | ||
2827 | else if (fam2_drive) | ||
2828 | { | ||
2829 | /* possibly longer timeout periods necessary */ | ||
2830 | drvcmd[0]=CMD2_DISKINFO; | ||
2831 | drvcmd[1]=0x02; | ||
2832 | drvcmd[2]=num; | ||
2833 | response_count=5; | ||
2834 | flags_cmd_out=f_putcmd; | ||
2835 | } | ||
2836 | else if (fam0LV_drive) | ||
2837 | { | ||
2838 | drvcmd[0]=CMD0_READTOC; | ||
2839 | drvcmd[1]=0x02; | ||
2840 | drvcmd[2]=num; | ||
2841 | response_count=8; | ||
2842 | if (famLV_drive) | ||
2843 | flags_cmd_out=f_putcmd; | ||
2844 | else | ||
2845 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2846 | } | ||
2847 | else if (famT_drive) | ||
2848 | { | ||
2849 | response_count=12; | ||
2850 | drvcmd[0]=CMDT_DISKINFO; | ||
2851 | drvcmd[1]=0x02; | ||
2852 | drvcmd[6]=num; | ||
2853 | drvcmd[8]=response_count; | ||
2854 | drvcmd[9]=0x00; | ||
2855 | } | ||
2856 | i=cmd_out(); | ||
2857 | if (i<0) return (i); | ||
2858 | if ((famT_drive)&&(i<response_count)) return (-100-i); | ||
2859 | if ((fam1_drive)||(fam0LV_drive)) | ||
2860 | { | ||
2861 | current_drive->TocEnt_nixbyte=infobuf[0]; | ||
2862 | i=1; | ||
2863 | } | ||
2864 | else if (fam2_drive) i=0; | ||
2865 | else if (famT_drive) i=5; | ||
2866 | current_drive->TocEnt_ctl_adr=swap_nibbles(infobuf[i++]); | ||
2867 | if ((fam1_drive)||(fam0L_drive)) | ||
2868 | { | ||
2869 | current_drive->TocEnt_number=infobuf[i++]; | ||
2870 | current_drive->TocEnt_format=infobuf[i]; | ||
2871 | } | ||
2872 | else | ||
2873 | { | ||
2874 | current_drive->TocEnt_number=num; | ||
2875 | current_drive->TocEnt_format=0; | ||
2876 | } | ||
2877 | if (fam1_drive) i=4; | ||
2878 | else if (fam0LV_drive) i=5; | ||
2879 | else if (fam2_drive) i=2; | ||
2880 | else if (famT_drive) i=9; | ||
2881 | current_drive->TocEnt_address=make32(make16(0,infobuf[i]), | ||
2882 | make16(infobuf[i+1],infobuf[i+2])); | ||
2883 | for (i=0;i<response_count;i++) | ||
2884 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
2885 | msgbuf[i*3]=0; | ||
2886 | msg(DBG_ECS,"TocEntry:%s\n", msgbuf); | ||
2887 | msg(DBG_TOC,"TocEntry: %02X %02X %02X %02X %08X\n", | ||
2888 | current_drive->TocEnt_nixbyte, current_drive->TocEnt_ctl_adr, | ||
2889 | current_drive->TocEnt_number, current_drive->TocEnt_format, | ||
2890 | current_drive->TocEnt_address); | ||
2891 | return (0); | ||
2892 | } | ||
2893 | /*==========================================================================*/ | ||
2894 | static int cc_ReadPacket(void) | ||
2895 | { | ||
2896 | int i; | ||
2897 | |||
2898 | clr_cmdbuf(); | ||
2899 | drvcmd[0]=CMD0_PACKET; | ||
2900 | drvcmd[1]=response_count; | ||
2901 | if(famL_drive) flags_cmd_out=f_putcmd; | ||
2902 | else if (fam01_drive) | ||
2903 | flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; | ||
2904 | else if (fam2_drive) return (-1); /* not implemented yet */ | ||
2905 | else if (famT_drive) | ||
2906 | { | ||
2907 | return (-1); | ||
2908 | } | ||
2909 | i=cmd_out(); | ||
2910 | return (i); | ||
2911 | } | ||
2912 | /*==========================================================================*/ | ||
2913 | static int convert_UPC(u_char *p) | ||
2914 | { | ||
2915 | int i; | ||
2916 | |||
2917 | p++; | ||
2918 | if (fam0L_drive) p[13]=0; | ||
2919 | for (i=0;i<7;i++) | ||
2920 | { | ||
2921 | if (fam1_drive) current_drive->UPC_buf[i]=swap_nibbles(*p++); | ||
2922 | else if (fam0L_drive) | ||
2923 | { | ||
2924 | current_drive->UPC_buf[i]=((*p++)<<4)&0xFF; | ||
2925 | current_drive->UPC_buf[i] |= *p++; | ||
2926 | } | ||
2927 | else if (famT_drive) | ||
2928 | { | ||
2929 | return (-1); | ||
2930 | } | ||
2931 | else /* CD200 */ | ||
2932 | { | ||
2933 | return (-1); | ||
2934 | } | ||
2935 | } | ||
2936 | current_drive->UPC_buf[6] &= 0xF0; | ||
2937 | return (0); | ||
2938 | } | ||
2939 | /*==========================================================================*/ | ||
2940 | static int cc_ReadUPC(void) | ||
2941 | { | ||
2942 | int i; | ||
2943 | #if TEST_UPC | ||
2944 | int block, checksum; | ||
2945 | #endif /* TEST_UPC */ | ||
2946 | |||
2947 | if (fam2_drive) return (0); /* not implemented yet */ | ||
2948 | if (famT_drive) return (0); /* not implemented yet */ | ||
2949 | if (famV_drive) return (0); /* not implemented yet */ | ||
2950 | #if 1 | ||
2951 | if (fam0_drive) return (0); /* but it should work */ | ||
2952 | #endif | ||
2953 | |||
2954 | current_drive->diskstate_flags &= ~upc_bit; | ||
2955 | #if TEST_UPC | ||
2956 | for (block=CD_MSF_OFFSET+1;block<CD_MSF_OFFSET+200;block++) | ||
2957 | { | ||
2958 | #endif /* TEST_UPC */ | ||
2959 | clr_cmdbuf(); | ||
2960 | if (fam1_drive) | ||
2961 | { | ||
2962 | drvcmd[0]=CMD1_READ_UPC; | ||
2963 | #if TEST_UPC | ||
2964 | drvcmd[1]=(block>>16)&0xFF; | ||
2965 | drvcmd[2]=(block>>8)&0xFF; | ||
2966 | drvcmd[3]=block&0xFF; | ||
2967 | #endif /* TEST_UPC */ | ||
2968 | response_count=8; | ||
2969 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
2970 | } | ||
2971 | else if (fam0L_drive) | ||
2972 | { | ||
2973 | drvcmd[0]=CMD0_READ_UPC; | ||
2974 | #if TEST_UPC | ||
2975 | drvcmd[2]=(block>>16)&0xFF; | ||
2976 | drvcmd[3]=(block>>8)&0xFF; | ||
2977 | drvcmd[4]=block&0xFF; | ||
2978 | #endif /* TEST_UPC */ | ||
2979 | response_count=0; | ||
2980 | flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; | ||
2981 | } | ||
2982 | else if (fam2_drive) | ||
2983 | { | ||
2984 | return (-1); | ||
2985 | } | ||
2986 | else if (famT_drive) | ||
2987 | { | ||
2988 | return (-1); | ||
2989 | } | ||
2990 | i=cmd_out(); | ||
2991 | if (i<0) | ||
2992 | { | ||
2993 | msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i); | ||
2994 | return (i); | ||
2995 | } | ||
2996 | if (fam0L_drive) | ||
2997 | { | ||
2998 | response_count=16; | ||
2999 | if (famL_drive) flags_cmd_out=f_putcmd; | ||
3000 | i=cc_ReadPacket(); | ||
3001 | if (i<0) | ||
3002 | { | ||
3003 | msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i); | ||
3004 | return (i); | ||
3005 | } | ||
3006 | } | ||
3007 | #if TEST_UPC | ||
3008 | checksum=0; | ||
3009 | #endif /* TEST_UPC */ | ||
3010 | for (i=0;i<(fam1_drive?8:16);i++) | ||
3011 | { | ||
3012 | #if TEST_UPC | ||
3013 | checksum |= infobuf[i]; | ||
3014 | #endif /* TEST_UPC */ | ||
3015 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
3016 | } | ||
3017 | msgbuf[i*3]=0; | ||
3018 | msg(DBG_UPC,"UPC info:%s\n", msgbuf); | ||
3019 | #if TEST_UPC | ||
3020 | if ((checksum&0x7F)!=0) break; | ||
3021 | } | ||
3022 | #endif /* TEST_UPC */ | ||
3023 | current_drive->UPC_ctl_adr=0; | ||
3024 | if (fam1_drive) i=0; | ||
3025 | else i=2; | ||
3026 | if ((infobuf[i]&0x80)!=0) | ||
3027 | { | ||
3028 | convert_UPC(&infobuf[i]); | ||
3029 | current_drive->UPC_ctl_adr = (current_drive->TocEnt_ctl_adr & 0xF0) | 0x02; | ||
3030 | } | ||
3031 | for (i=0;i<7;i++) | ||
3032 | sprintf(&msgbuf[i*3], " %02X", current_drive->UPC_buf[i]); | ||
3033 | sprintf(&msgbuf[i*3], " (%02X)", current_drive->UPC_ctl_adr); | ||
3034 | msgbuf[i*3+5]=0; | ||
3035 | msg(DBG_UPC,"UPC code:%s\n", msgbuf); | ||
3036 | current_drive->diskstate_flags |= upc_bit; | ||
3037 | return (0); | ||
3038 | } | ||
3039 | |||
3040 | static int sbpcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) | ||
3041 | { | ||
3042 | int i; | ||
3043 | unsigned char *mcnp = mcn->medium_catalog_number; | ||
3044 | unsigned char *resp; | ||
3045 | |||
3046 | current_drive->diskstate_flags &= ~upc_bit; | ||
3047 | clr_cmdbuf(); | ||
3048 | if (fam1_drive) | ||
3049 | { | ||
3050 | drvcmd[0]=CMD1_READ_UPC; | ||
3051 | response_count=8; | ||
3052 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
3053 | } | ||
3054 | else if (fam0L_drive) | ||
3055 | { | ||
3056 | drvcmd[0]=CMD0_READ_UPC; | ||
3057 | response_count=0; | ||
3058 | flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; | ||
3059 | } | ||
3060 | else if (fam2_drive) | ||
3061 | { | ||
3062 | return (-1); | ||
3063 | } | ||
3064 | else if (famT_drive) | ||
3065 | { | ||
3066 | return (-1); | ||
3067 | } | ||
3068 | i=cmd_out(); | ||
3069 | if (i<0) | ||
3070 | { | ||
3071 | msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i); | ||
3072 | return (i); | ||
3073 | } | ||
3074 | if (fam0L_drive) | ||
3075 | { | ||
3076 | response_count=16; | ||
3077 | if (famL_drive) flags_cmd_out=f_putcmd; | ||
3078 | i=cc_ReadPacket(); | ||
3079 | if (i<0) | ||
3080 | { | ||
3081 | msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i); | ||
3082 | return (i); | ||
3083 | } | ||
3084 | } | ||
3085 | current_drive->UPC_ctl_adr=0; | ||
3086 | if (fam1_drive) i=0; | ||
3087 | else i=2; | ||
3088 | |||
3089 | resp = infobuf + i; | ||
3090 | if (*resp++ == 0x80) { | ||
3091 | /* packed bcd to single ASCII digits */ | ||
3092 | *mcnp++ = (*resp >> 4) + '0'; | ||
3093 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
3094 | *mcnp++ = (*resp >> 4) + '0'; | ||
3095 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
3096 | *mcnp++ = (*resp >> 4) + '0'; | ||
3097 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
3098 | *mcnp++ = (*resp >> 4) + '0'; | ||
3099 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
3100 | *mcnp++ = (*resp >> 4) + '0'; | ||
3101 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
3102 | *mcnp++ = (*resp >> 4) + '0'; | ||
3103 | *mcnp++ = (*resp++ & 0x0f) + '0'; | ||
3104 | *mcnp++ = (*resp >> 4) + '0'; | ||
3105 | } | ||
3106 | *mcnp = '\0'; | ||
3107 | |||
3108 | current_drive->diskstate_flags |= upc_bit; | ||
3109 | return (0); | ||
3110 | } | ||
3111 | |||
3112 | /*==========================================================================*/ | ||
3113 | static int cc_CheckMultiSession(void) | ||
3114 | { | ||
3115 | int i; | ||
3116 | |||
3117 | if (fam2_drive) return (0); | ||
3118 | current_drive->f_multisession=0; | ||
3119 | current_drive->lba_multi=0; | ||
3120 | if (fam0_drive) return (0); | ||
3121 | clr_cmdbuf(); | ||
3122 | if (fam1_drive) | ||
3123 | { | ||
3124 | drvcmd[0]=CMD1_MULTISESS; | ||
3125 | response_count=6; | ||
3126 | flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; | ||
3127 | i=cmd_out(); | ||
3128 | if (i<0) return (i); | ||
3129 | if ((infobuf[0]&0x80)!=0) | ||
3130 | { | ||
3131 | current_drive->f_multisession=1; | ||
3132 | current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[1]), | ||
3133 | make16(infobuf[2],infobuf[3]))); | ||
3134 | } | ||
3135 | } | ||
3136 | else if (famLV_drive) | ||
3137 | { | ||
3138 | drvcmd[0]=CMDL_MULTISESS; | ||
3139 | drvcmd[1]=3; | ||
3140 | drvcmd[2]=1; | ||
3141 | response_count=8; | ||
3142 | flags_cmd_out=f_putcmd; | ||
3143 | i=cmd_out(); | ||
3144 | if (i<0) return (i); | ||
3145 | current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]), | ||
3146 | make16(infobuf[6],infobuf[7]))); | ||
3147 | } | ||
3148 | else if (famT_drive) | ||
3149 | { | ||
3150 | response_count=12; | ||
3151 | drvcmd[0]=CMDT_DISKINFO; | ||
3152 | drvcmd[1]=0x02; | ||
3153 | drvcmd[6]=0; | ||
3154 | drvcmd[8]=response_count; | ||
3155 | drvcmd[9]=0x40; | ||
3156 | i=cmd_out(); | ||
3157 | if (i<0) return (i); | ||
3158 | if (i<response_count) return (-100-i); | ||
3159 | current_drive->first_session=infobuf[2]; | ||
3160 | current_drive->last_session=infobuf[3]; | ||
3161 | current_drive->track_of_last_session=infobuf[6]; | ||
3162 | if (current_drive->first_session!=current_drive->last_session) | ||
3163 | { | ||
3164 | current_drive->f_multisession=1; | ||
3165 | current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[9]),make16(infobuf[10],infobuf[11]))); | ||
3166 | } | ||
3167 | } | ||
3168 | for (i=0;i<response_count;i++) | ||
3169 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
3170 | msgbuf[i*3]=0; | ||
3171 | msg(DBG_MUL,"MultiSession Info:%s (%d)\n", msgbuf, current_drive->lba_multi); | ||
3172 | if (current_drive->lba_multi>200) | ||
3173 | { | ||
3174 | current_drive->f_multisession=1; | ||
3175 | msg(DBG_MUL,"MultiSession base: %06X\n", current_drive->lba_multi); | ||
3176 | } | ||
3177 | return (0); | ||
3178 | } | ||
3179 | /*==========================================================================*/ | ||
3180 | #ifdef FUTURE | ||
3181 | static int cc_SubChanInfo(int frame, int count, u_char *buffer) | ||
3182 | /* "frame" is a RED BOOK (msf-bin) address */ | ||
3183 | { | ||
3184 | int i; | ||
3185 | |||
3186 | if (fam0LV_drive) return (-ENOSYS); /* drive firmware lacks it */ | ||
3187 | if (famT_drive) | ||
3188 | { | ||
3189 | return (-1); | ||
3190 | } | ||
3191 | #if 0 | ||
3192 | if (current_drive->audio_state!=audio_playing) return (-ENODATA); | ||
3193 | #endif | ||
3194 | clr_cmdbuf(); | ||
3195 | drvcmd[0]=CMD1_SUBCHANINF; | ||
3196 | drvcmd[1]=(frame>>16)&0xFF; | ||
3197 | drvcmd[2]=(frame>>8)&0xFF; | ||
3198 | drvcmd[3]=frame&0xFF; | ||
3199 | drvcmd[5]=(count>>8)&0xFF; | ||
3200 | drvcmd[6]=count&0xFF; | ||
3201 | flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; | ||
3202 | cmd_type=READ_SC; | ||
3203 | current_drive->frame_size=CD_FRAMESIZE_SUB; | ||
3204 | i=cmd_out(); /* which buffer to use? */ | ||
3205 | return (i); | ||
3206 | } | ||
3207 | #endif /* FUTURE */ | ||
3208 | /*==========================================================================*/ | ||
3209 | static void __init check_datarate(void) | ||
3210 | { | ||
3211 | int i=0; | ||
3212 | |||
3213 | msg(DBG_IOX,"check_datarate entered.\n"); | ||
3214 | datarate=0; | ||
3215 | #if TEST_STI | ||
3216 | for (i=0;i<=1000;i++) printk("."); | ||
3217 | #endif | ||
3218 | /* set a timer to make (timed_out_delay!=0) after 1.1 seconds */ | ||
3219 | #if 1 | ||
3220 | del_timer(&delay_timer); | ||
3221 | #endif | ||
3222 | delay_timer.expires=jiffies+11*HZ/10; | ||
3223 | timed_out_delay=0; | ||
3224 | add_timer(&delay_timer); | ||
3225 | #if 0 | ||
3226 | msg(DBG_TIM,"delay timer started (11*HZ/10).\n"); | ||
3227 | #endif | ||
3228 | do | ||
3229 | { | ||
3230 | i=inb(CDi_status); | ||
3231 | datarate++; | ||
3232 | #if 1 | ||
3233 | if (datarate>0x6FFFFFFF) break; | ||
3234 | #endif | ||
3235 | } | ||
3236 | while (!timed_out_delay); | ||
3237 | del_timer(&delay_timer); | ||
3238 | #if 0 | ||
3239 | msg(DBG_TIM,"datarate: %04X\n", datarate); | ||
3240 | #endif | ||
3241 | if (datarate<65536) datarate=65536; | ||
3242 | maxtim16=datarate*16; | ||
3243 | maxtim04=datarate*4; | ||
3244 | maxtim02=datarate*2; | ||
3245 | maxtim_8=datarate/32; | ||
3246 | #if LONG_TIMING | ||
3247 | maxtim_data=datarate/100; | ||
3248 | #else | ||
3249 | maxtim_data=datarate/300; | ||
3250 | #endif /* LONG_TIMING */ | ||
3251 | #if 0 | ||
3252 | msg(DBG_TIM,"maxtim_8 %d, maxtim_data %d.\n", maxtim_8, maxtim_data); | ||
3253 | #endif | ||
3254 | } | ||
3255 | /*==========================================================================*/ | ||
3256 | #if 0 | ||
3257 | static int c2_ReadError(int fam) | ||
3258 | { | ||
3259 | int i; | ||
3260 | |||
3261 | clr_cmdbuf(); | ||
3262 | response_count=9; | ||
3263 | clr_respo_buf(9); | ||
3264 | if (fam==1) | ||
3265 | { | ||
3266 | drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */ | ||
3267 | i=do_cmd(f_putcmd|f_lopsta|f_getsta|f_ResponseStatus); | ||
3268 | } | ||
3269 | else if (fam==2) | ||
3270 | { | ||
3271 | drvcmd[0]=CMD2_READ_ERR; | ||
3272 | i=do_cmd(f_putcmd); | ||
3273 | } | ||
3274 | else return (-1); | ||
3275 | return (i); | ||
3276 | } | ||
3277 | #endif | ||
3278 | /*==========================================================================*/ | ||
3279 | static void __init ask_mail(void) | ||
3280 | { | ||
3281 | int i; | ||
3282 | |||
3283 | msg(DBG_INF, "please mail the following lines to emoenke@gwdg.de\n"); | ||
3284 | msg(DBG_INF, "(don't mail if you are not using the actual kernel):\n"); | ||
3285 | msg(DBG_INF, "%s\n", VERSION); | ||
3286 | msg(DBG_INF, "address %03X, type %s, drive %s (ID %d)\n", | ||
3287 | CDo_command, type, current_drive->drive_model, current_drive->drv_id); | ||
3288 | for (i=0;i<12;i++) | ||
3289 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
3290 | msgbuf[i*3]=0; | ||
3291 | msg(DBG_INF,"infobuf =%s\n", msgbuf); | ||
3292 | for (i=0;i<12;i++) | ||
3293 | sprintf(&msgbuf[i*3], " %c ", infobuf[i]); | ||
3294 | msgbuf[i*3]=0; | ||
3295 | msg(DBG_INF,"infobuf =%s\n", msgbuf); | ||
3296 | } | ||
3297 | /*==========================================================================*/ | ||
3298 | static int __init check_version(void) | ||
3299 | { | ||
3300 | int i, j, l; | ||
3301 | int teac_possible=0; | ||
3302 | |||
3303 | msg(DBG_INI,"check_version: id=%d, d=%d.\n", current_drive->drv_id, current_drive - D_S); | ||
3304 | current_drive->drv_type=0; | ||
3305 | |||
3306 | /* check for CR-52x, CR-56x, LCS-7260 and ECS-AT */ | ||
3307 | /* clear any pending error state */ | ||
3308 | clr_cmdbuf(); | ||
3309 | drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */ | ||
3310 | response_count=9; | ||
3311 | flags_cmd_out=f_putcmd; | ||
3312 | i=cmd_out(); | ||
3313 | if (i<0) msg(DBG_INI,"CMD0_READ_ERR returns %d (ok anyway).\n",i); | ||
3314 | /* read drive version */ | ||
3315 | clr_cmdbuf(); | ||
3316 | for (i=0;i<12;i++) infobuf[i]=0; | ||
3317 | drvcmd[0]=CMD0_READ_VER; /* same as CMD1_ and CMDL_ */ | ||
3318 | response_count=12; /* fam1: only 11 */ | ||
3319 | flags_cmd_out=f_putcmd; | ||
3320 | i=cmd_out(); | ||
3321 | if (i<-1) msg(DBG_INI,"CMD0_READ_VER returns %d\n",i); | ||
3322 | if (i==-11) teac_possible++; | ||
3323 | j=0; | ||
3324 | for (i=0;i<12;i++) j+=infobuf[i]; | ||
3325 | if (j) | ||
3326 | { | ||
3327 | for (i=0;i<12;i++) | ||
3328 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
3329 | msgbuf[i*3]=0; | ||
3330 | msg(DBG_ECS,"infobuf =%s\n", msgbuf); | ||
3331 | for (i=0;i<12;i++) | ||
3332 | sprintf(&msgbuf[i*3], " %c ", infobuf[i]); | ||
3333 | msgbuf[i*3]=0; | ||
3334 | msg(DBG_ECS,"infobuf =%s\n", msgbuf); | ||
3335 | } | ||
3336 | for (i=0;i<4;i++) if (infobuf[i]!=family1[i]) break; | ||
3337 | if (i==4) | ||
3338 | { | ||
3339 | current_drive->drive_model[0]='C'; | ||
3340 | current_drive->drive_model[1]='R'; | ||
3341 | current_drive->drive_model[2]='-'; | ||
3342 | current_drive->drive_model[3]='5'; | ||
3343 | current_drive->drive_model[4]=infobuf[i++]; | ||
3344 | current_drive->drive_model[5]=infobuf[i++]; | ||
3345 | current_drive->drive_model[6]=0; | ||
3346 | current_drive->drv_type=drv_fam1; | ||
3347 | } | ||
3348 | if (!current_drive->drv_type) | ||
3349 | { | ||
3350 | for (i=0;i<8;i++) if (infobuf[i]!=family0[i]) break; | ||
3351 | if (i==8) | ||
3352 | { | ||
3353 | current_drive->drive_model[0]='C'; | ||
3354 | current_drive->drive_model[1]='R'; | ||
3355 | current_drive->drive_model[2]='-'; | ||
3356 | current_drive->drive_model[3]='5'; | ||
3357 | current_drive->drive_model[4]='2'; | ||
3358 | current_drive->drive_model[5]='x'; | ||
3359 | current_drive->drive_model[6]=0; | ||
3360 | current_drive->drv_type=drv_fam0; | ||
3361 | } | ||
3362 | } | ||
3363 | if (!current_drive->drv_type) | ||
3364 | { | ||
3365 | for (i=0;i<8;i++) if (infobuf[i]!=familyL[i]) break; | ||
3366 | if (i==8) | ||
3367 | { | ||
3368 | for (j=0;j<8;j++) | ||
3369 | current_drive->drive_model[j]=infobuf[j]; | ||
3370 | current_drive->drive_model[8]=0; | ||
3371 | current_drive->drv_type=drv_famL; | ||
3372 | } | ||
3373 | } | ||
3374 | if (!current_drive->drv_type) | ||
3375 | { | ||
3376 | for (i=0;i<6;i++) if (infobuf[i]!=familyV[i]) break; | ||
3377 | if (i==6) | ||
3378 | { | ||
3379 | for (j=0;j<6;j++) | ||
3380 | current_drive->drive_model[j]=infobuf[j]; | ||
3381 | current_drive->drive_model[6]=0; | ||
3382 | current_drive->drv_type=drv_famV; | ||
3383 | i+=2; /* 2 blanks before version */ | ||
3384 | } | ||
3385 | } | ||
3386 | if (!current_drive->drv_type) | ||
3387 | { | ||
3388 | /* check for CD200 */ | ||
3389 | clr_cmdbuf(); | ||
3390 | drvcmd[0]=CMD2_READ_ERR; | ||
3391 | response_count=9; | ||
3392 | flags_cmd_out=f_putcmd; | ||
3393 | i=cmd_out(); | ||
3394 | if (i<0) msg(DBG_INI,"CMD2_READERR returns %d (ok anyway).\n",i); | ||
3395 | if (i<0) msg(DBG_000,"CMD2_READERR returns %d (ok anyway).\n",i); | ||
3396 | /* read drive version */ | ||
3397 | clr_cmdbuf(); | ||
3398 | for (i=0;i<12;i++) infobuf[i]=0; | ||
3399 | if (sbpro_type==1) OUT(CDo_sel_i_d,0); | ||
3400 | #if 0 | ||
3401 | OUT(CDo_reset,0); | ||
3402 | sbp_sleep(6*HZ); | ||
3403 | OUT(CDo_enable,current_drive->drv_sel); | ||
3404 | #endif | ||
3405 | drvcmd[0]=CMD2_READ_VER; | ||
3406 | response_count=12; | ||
3407 | flags_cmd_out=f_putcmd; | ||
3408 | i=cmd_out(); | ||
3409 | if (i<0) msg(DBG_INI,"CMD2_READ_VER returns %d\n",i); | ||
3410 | if (i==-7) teac_possible++; | ||
3411 | j=0; | ||
3412 | for (i=0;i<12;i++) j+=infobuf[i]; | ||
3413 | if (j) | ||
3414 | { | ||
3415 | for (i=0;i<12;i++) | ||
3416 | sprintf(&msgbuf[i*3], " %02X", infobuf[i]); | ||
3417 | msgbuf[i*3]=0; | ||
3418 | msg(DBG_IDX,"infobuf =%s\n", msgbuf); | ||
3419 | for (i=0;i<12;i++) | ||
3420 | sprintf(&msgbuf[i*3], " %c ", infobuf[i]); | ||
3421 | msgbuf[i*3]=0; | ||
3422 | msg(DBG_IDX,"infobuf =%s\n", msgbuf); | ||
3423 | } | ||
3424 | if (i>=0) | ||
3425 | { | ||
3426 | for (i=0;i<5;i++) if (infobuf[i]!=family2[i]) break; | ||
3427 | if (i==5) | ||
3428 | { | ||
3429 | current_drive->drive_model[0]='C'; | ||
3430 | current_drive->drive_model[1]='D'; | ||
3431 | current_drive->drive_model[2]='2'; | ||
3432 | current_drive->drive_model[3]='0'; | ||
3433 | current_drive->drive_model[4]='0'; | ||
3434 | current_drive->drive_model[5]=infobuf[i++]; | ||
3435 | current_drive->drive_model[6]=infobuf[i++]; | ||
3436 | current_drive->drive_model[7]=0; | ||
3437 | current_drive->drv_type=drv_fam2; | ||
3438 | } | ||
3439 | } | ||
3440 | } | ||
3441 | if (!current_drive->drv_type) | ||
3442 | { | ||
3443 | /* check for TEAC CD-55A */ | ||
3444 | msg(DBG_TEA,"teac_possible: %d\n",teac_possible); | ||
3445 | for (j=1;j<=((current_drive->drv_id==0)?3:1);j++) | ||
3446 | { | ||
3447 | for (l=1;l<=((current_drive->drv_id==0)?10:1);l++) | ||
3448 | { | ||
3449 | msg(DBG_TEA,"TEAC reset #%d-%d.\n", j, l); | ||
3450 | if (sbpro_type==1) OUT(CDo_reset,0); | ||
3451 | else | ||
3452 | { | ||
3453 | OUT(CDo_enable,current_drive->drv_sel); | ||
3454 | OUT(CDo_sel_i_d,0); | ||
3455 | OUT(CDo_command,CMDT_RESET); | ||
3456 | for (i=0;i<9;i++) OUT(CDo_command,0); | ||
3457 | } | ||
3458 | sbp_sleep(5*HZ/10); | ||
3459 | OUT(CDo_enable,current_drive->drv_sel); | ||
3460 | OUT(CDo_sel_i_d,0); | ||
3461 | i=inb(CDi_status); | ||
3462 | msg(DBG_TEA,"TEAC CDi_status: %02X.\n",i); | ||
3463 | #if 0 | ||
3464 | if (i&s_not_result_ready) continue; /* drive not present or ready */ | ||
3465 | #endif | ||
3466 | i=inb(CDi_info); | ||
3467 | msg(DBG_TEA,"TEAC CDi_info: %02X.\n",i); | ||
3468 | if (i==0x55) break; /* drive found */ | ||
3469 | } | ||
3470 | if (i==0x55) break; /* drive found */ | ||
3471 | } | ||
3472 | if (i==0x55) /* drive found */ | ||
3473 | { | ||
3474 | msg(DBG_TEA,"TEAC drive found.\n"); | ||
3475 | clr_cmdbuf(); | ||
3476 | flags_cmd_out=f_putcmd; | ||
3477 | response_count=12; | ||
3478 | drvcmd[0]=CMDT_READ_VER; | ||
3479 | drvcmd[4]=response_count; | ||
3480 | for (i=0;i<12;i++) infobuf[i]=0; | ||
3481 | i=cmd_out_T(); | ||
3482 | if (i!=0) msg(DBG_TEA,"cmd_out_T(CMDT_READ_VER) returns %d.\n",i); | ||
3483 | for (i=1;i<6;i++) if (infobuf[i]!=familyT[i-1]) break; | ||
3484 | if (i==6) | ||
3485 | { | ||
3486 | current_drive->drive_model[0]='C'; | ||
3487 | current_drive->drive_model[1]='D'; | ||
3488 | current_drive->drive_model[2]='-'; | ||
3489 | current_drive->drive_model[3]='5'; | ||
3490 | current_drive->drive_model[4]='5'; | ||
3491 | current_drive->drive_model[5]=0; | ||
3492 | current_drive->drv_type=drv_famT; | ||
3493 | } | ||
3494 | } | ||
3495 | } | ||
3496 | if (!current_drive->drv_type) | ||
3497 | { | ||
3498 | msg(DBG_TEA,"no drive found at address %03X under ID %d.\n",CDo_command,current_drive->drv_id); | ||
3499 | return (-522); | ||
3500 | } | ||
3501 | for (j=0;j<4;j++) current_drive->firmware_version[j]=infobuf[i+j]; | ||
3502 | if (famL_drive) | ||
3503 | { | ||
3504 | u_char lcs_firm_e1[]="A E1"; | ||
3505 | u_char lcs_firm_f4[]="A4F4"; | ||
3506 | |||
3507 | for (j=0;j<4;j++) | ||
3508 | if (current_drive->firmware_version[j]!=lcs_firm_e1[j]) break; | ||
3509 | if (j==4) current_drive->drv_type=drv_e1; | ||
3510 | |||
3511 | for (j=0;j<4;j++) | ||
3512 | if (current_drive->firmware_version[j]!=lcs_firm_f4[j]) break; | ||
3513 | if (j==4) current_drive->drv_type=drv_f4; | ||
3514 | |||
3515 | if (current_drive->drv_type==drv_famL) ask_mail(); | ||
3516 | } | ||
3517 | else if (famT_drive) | ||
3518 | { | ||
3519 | j=infobuf[4]; /* one-byte version??? - here: 0x15 */ | ||
3520 | if (j=='5') | ||
3521 | { | ||
3522 | current_drive->firmware_version[0]=infobuf[7]; | ||
3523 | current_drive->firmware_version[1]=infobuf[8]; | ||
3524 | current_drive->firmware_version[2]=infobuf[10]; | ||
3525 | current_drive->firmware_version[3]=infobuf[11]; | ||
3526 | } | ||
3527 | else | ||
3528 | { | ||
3529 | if (j!=0x15) ask_mail(); | ||
3530 | current_drive->firmware_version[0]='0'; | ||
3531 | current_drive->firmware_version[1]='.'; | ||
3532 | current_drive->firmware_version[2]='0'+(j>>4); | ||
3533 | current_drive->firmware_version[3]='0'+(j&0x0f); | ||
3534 | } | ||
3535 | } | ||
3536 | else /* CR-52x, CR-56x, CD200, ECS-AT */ | ||
3537 | { | ||
3538 | j = (current_drive->firmware_version[0] & 0x0F) * 100 + | ||
3539 | (current_drive->firmware_version[2] & 0x0F) *10 + | ||
3540 | (current_drive->firmware_version[3] & 0x0F); | ||
3541 | if (fam0_drive) | ||
3542 | { | ||
3543 | if (j<200) current_drive->drv_type=drv_199; | ||
3544 | else if (j<201) current_drive->drv_type=drv_200; | ||
3545 | else if (j<210) current_drive->drv_type=drv_201; | ||
3546 | else if (j<211) current_drive->drv_type=drv_210; | ||
3547 | else if (j<300) current_drive->drv_type=drv_211; | ||
3548 | else if (j>=300) current_drive->drv_type=drv_300; | ||
3549 | } | ||
3550 | else if (fam1_drive) | ||
3551 | { | ||
3552 | if (j<100) current_drive->drv_type=drv_099; | ||
3553 | else | ||
3554 | { | ||
3555 | current_drive->drv_type=drv_100; | ||
3556 | if ((j!=500)&&(j!=102)) ask_mail(); | ||
3557 | } | ||
3558 | } | ||
3559 | else if (fam2_drive) | ||
3560 | { | ||
3561 | if (current_drive->drive_model[5]=='F') | ||
3562 | { | ||
3563 | if ((j!=1)&&(j!=35)&&(j!=200)&&(j!=210)) | ||
3564 | ask_mail(); /* unknown version at time */ | ||
3565 | } | ||
3566 | else | ||
3567 | { | ||
3568 | msg(DBG_INF,"this CD200 drive is not fully supported yet - only audio will work.\n"); | ||
3569 | if ((j!=101)&&(j!=35)) | ||
3570 | ask_mail(); /* unknown version at time */ | ||
3571 | } | ||
3572 | } | ||
3573 | else if (famV_drive) | ||
3574 | { | ||
3575 | if ((j==100)||(j==150)) current_drive->drv_type=drv_at; | ||
3576 | ask_mail(); /* hopefully we get some feedback by this */ | ||
3577 | } | ||
3578 | } | ||
3579 | msg(DBG_LCS,"drive type %02X\n",current_drive->drv_type); | ||
3580 | msg(DBG_INI,"check_version done.\n"); | ||
3581 | return (0); | ||
3582 | } | ||
3583 | /*==========================================================================*/ | ||
3584 | static void switch_drive(struct sbpcd_drive *p) | ||
3585 | { | ||
3586 | current_drive = p; | ||
3587 | OUT(CDo_enable,current_drive->drv_sel); | ||
3588 | msg(DBG_DID,"drive %d (ID=%d) activated.\n", | ||
3589 | current_drive - D_S, current_drive->drv_id); | ||
3590 | return; | ||
3591 | } | ||
3592 | /*==========================================================================*/ | ||
3593 | #ifdef PATH_CHECK | ||
3594 | /* | ||
3595 | * probe for the presence of an interface card | ||
3596 | */ | ||
3597 | static int __init check_card(int port) | ||
3598 | { | ||
3599 | #undef N_RESPO | ||
3600 | #define N_RESPO 20 | ||
3601 | int i, j, k; | ||
3602 | u_char response[N_RESPO]; | ||
3603 | u_char save_port0; | ||
3604 | u_char save_port3; | ||
3605 | |||
3606 | msg(DBG_INI,"check_card entered.\n"); | ||
3607 | save_port0=inb(port+0); | ||
3608 | save_port3=inb(port+3); | ||
3609 | |||
3610 | for (j=0;j<NR_SBPCD;j++) | ||
3611 | { | ||
3612 | OUT(port+3,j) ; /* enable drive #j */ | ||
3613 | OUT(port+0,CMD0_PATH_CHECK); | ||
3614 | for (i=10;i>0;i--) OUT(port+0,0); | ||
3615 | for (k=0;k<N_RESPO;k++) response[k]=0; | ||
3616 | for (k=0;k<N_RESPO;k++) | ||
3617 | { | ||
3618 | for (i=10000;i>0;i--) | ||
3619 | { | ||
3620 | if (inb(port+1)&s_not_result_ready) continue; | ||
3621 | response[k]=inb(port+0); | ||
3622 | break; | ||
3623 | } | ||
3624 | } | ||
3625 | for (i=0;i<N_RESPO;i++) | ||
3626 | sprintf(&msgbuf[i*3], " %02X", response[i]); | ||
3627 | msgbuf[i*3]=0; | ||
3628 | msg(DBG_TEA,"path check 00 (%d): %s\n", j, msgbuf); | ||
3629 | OUT(port+0,CMD0_PATH_CHECK); | ||
3630 | for (i=10;i>0;i--) OUT(port+0,0); | ||
3631 | for (k=0;k<N_RESPO;k++) response[k]=0xFF; | ||
3632 | for (k=0;k<N_RESPO;k++) | ||
3633 | { | ||
3634 | for (i=10000;i>0;i--) | ||
3635 | { | ||
3636 | if (inb(port+1)&s_not_result_ready) continue; | ||
3637 | response[k]=inb(port+0); | ||
3638 | break; | ||
3639 | } | ||
3640 | } | ||
3641 | for (i=0;i<N_RESPO;i++) | ||
3642 | sprintf(&msgbuf[i*3], " %02X", response[i]); | ||
3643 | msgbuf[i*3]=0; | ||
3644 | msg(DBG_TEA,"path check 00 (%d): %s\n", j, msgbuf); | ||
3645 | |||
3646 | if (response[0]==0xAA) | ||
3647 | if (response[1]==0x55) | ||
3648 | return (0); | ||
3649 | } | ||
3650 | for (j=0;j<NR_SBPCD;j++) | ||
3651 | { | ||
3652 | OUT(port+3,j) ; /* enable drive #j */ | ||
3653 | OUT(port+0,CMD2_READ_VER); | ||
3654 | for (i=10;i>0;i--) OUT(port+0,0); | ||
3655 | for (k=0;k<N_RESPO;k++) response[k]=0; | ||
3656 | for (k=0;k<N_RESPO;k++) | ||
3657 | { | ||
3658 | for (i=1000000;i>0;i--) | ||
3659 | { | ||
3660 | if (inb(port+1)&s_not_result_ready) continue; | ||
3661 | response[k]=inb(port+0); | ||
3662 | break; | ||
3663 | } | ||
3664 | } | ||
3665 | for (i=0;i<N_RESPO;i++) | ||
3666 | sprintf(&msgbuf[i*3], " %02X", response[i]); | ||
3667 | msgbuf[i*3]=0; | ||
3668 | msg(DBG_TEA,"path check 12 (%d): %s\n", j, msgbuf); | ||
3669 | |||
3670 | OUT(port+0,CMD2_READ_VER); | ||
3671 | for (i=10;i>0;i--) OUT(port+0,0); | ||
3672 | for (k=0;k<N_RESPO;k++) response[k]=0xFF; | ||
3673 | for (k=0;k<N_RESPO;k++) | ||
3674 | { | ||
3675 | for (i=1000000;i>0;i--) | ||
3676 | { | ||
3677 | if (inb(port+1)&s_not_result_ready) continue; | ||
3678 | response[k]=inb(port+0); | ||
3679 | break; | ||
3680 | } | ||
3681 | } | ||
3682 | for (i=0;i<N_RESPO;i++) | ||
3683 | sprintf(&msgbuf[i*3], " %02X", response[i]); | ||
3684 | msgbuf[i*3]=0; | ||
3685 | msg(DBG_TEA,"path check 12 (%d): %s\n", j, msgbuf); | ||
3686 | |||
3687 | if (response[0]==0xAA) | ||
3688 | if (response[1]==0x55) | ||
3689 | return (0); | ||
3690 | } | ||
3691 | OUT(port+0,save_port0); | ||
3692 | OUT(port+3,save_port3); | ||
3693 | return (0); /* in any case - no real "function" at time */ | ||
3694 | } | ||
3695 | #endif /* PATH_CHECK */ | ||
3696 | /*==========================================================================*/ | ||
3697 | /*==========================================================================*/ | ||
3698 | /* | ||
3699 | * probe for the presence of drives on the selected controller | ||
3700 | */ | ||
3701 | static int __init check_drives(void) | ||
3702 | { | ||
3703 | int i, j; | ||
3704 | |||
3705 | msg(DBG_INI,"check_drives entered.\n"); | ||
3706 | ndrives=0; | ||
3707 | for (j=0;j<max_drives;j++) | ||
3708 | { | ||
3709 | struct sbpcd_drive *p = D_S + ndrives; | ||
3710 | p->drv_id=j; | ||
3711 | if (sbpro_type==1) p->drv_sel=(j&0x01)<<1|(j&0x02)>>1; | ||
3712 | else p->drv_sel=j; | ||
3713 | switch_drive(p); | ||
3714 | msg(DBG_INI,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j); | ||
3715 | msg(DBG_000,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j); | ||
3716 | i=check_version(); | ||
3717 | if (i<0) msg(DBG_INI,"check_version returns %d.\n",i); | ||
3718 | else | ||
3719 | { | ||
3720 | current_drive->drv_options=drv_pattern[j]; | ||
3721 | if (fam0L_drive) current_drive->drv_options&=~(speed_auto|speed_300|speed_150); | ||
3722 | msg(DBG_INF, "Drive %d (ID=%d): %.9s (%.4s) at 0x%03X (type %d)\n", | ||
3723 | current_drive - D_S, | ||
3724 | current_drive->drv_id, | ||
3725 | current_drive->drive_model, | ||
3726 | current_drive->firmware_version, | ||
3727 | CDo_command, | ||
3728 | sbpro_type); | ||
3729 | ndrives++; | ||
3730 | } | ||
3731 | } | ||
3732 | for (j=ndrives;j<NR_SBPCD;j++) D_S[j].drv_id=-1; | ||
3733 | if (ndrives==0) return (-1); | ||
3734 | return (0); | ||
3735 | } | ||
3736 | /*==========================================================================*/ | ||
3737 | #ifdef FUTURE | ||
3738 | /* | ||
3739 | * obtain if requested service disturbs current audio state | ||
3740 | */ | ||
3741 | static int obey_audio_state(u_char audio_state, u_char func,u_char subfunc) | ||
3742 | { | ||
3743 | switch (audio_state) /* audio status from controller */ | ||
3744 | { | ||
3745 | case aud_11: /* "audio play in progress" */ | ||
3746 | case audx11: | ||
3747 | switch (func) /* DOS command code */ | ||
3748 | { | ||
3749 | case cmd_07: /* input flush */ | ||
3750 | case cmd_0d: /* open device */ | ||
3751 | case cmd_0e: /* close device */ | ||
3752 | case cmd_0c: /* ioctl output */ | ||
3753 | return (1); | ||
3754 | case cmd_03: /* ioctl input */ | ||
3755 | switch (subfunc) | ||
3756 | /* DOS ioctl input subfunction */ | ||
3757 | { | ||
3758 | case cxi_00: | ||
3759 | case cxi_06: | ||
3760 | case cxi_09: | ||
3761 | return (1); | ||
3762 | default: | ||
3763 | return (ERROR15); | ||
3764 | } | ||
3765 | return (1); | ||
3766 | default: | ||
3767 | return (ERROR15); | ||
3768 | } | ||
3769 | return (1); | ||
3770 | case aud_12: /* "audio play paused" */ | ||
3771 | case audx12: | ||
3772 | return (1); | ||
3773 | default: | ||
3774 | return (2); | ||
3775 | } | ||
3776 | } | ||
3777 | /*==========================================================================*/ | ||
3778 | /* allowed is only | ||
3779 | * ioctl_o, flush_input, open_device, close_device, | ||
3780 | * tell_address, tell_volume, tell_capabiliti, | ||
3781 | * tell_framesize, tell_CD_changed, tell_audio_posi | ||
3782 | */ | ||
3783 | static int check_allowed1(u_char func1, u_char func2) | ||
3784 | { | ||
3785 | #if 000 | ||
3786 | if (func1==ioctl_o) return (0); | ||
3787 | if (func1==read_long) return (-1); | ||
3788 | if (func1==read_long_prefetch) return (-1); | ||
3789 | if (func1==seek) return (-1); | ||
3790 | if (func1==audio_play) return (-1); | ||
3791 | if (func1==audio_pause) return (-1); | ||
3792 | if (func1==audio_resume) return (-1); | ||
3793 | if (func1!=ioctl_i) return (0); | ||
3794 | if (func2==tell_SubQ_run_tot) return (-1); | ||
3795 | if (func2==tell_cdsize) return (-1); | ||
3796 | if (func2==tell_TocDescrip) return (-1); | ||
3797 | if (func2==tell_TocEntry) return (-1); | ||
3798 | if (func2==tell_subQ_info) return (-1); | ||
3799 | if (fam1_drive) if (func2==tell_SubChanInfo) return (-1); | ||
3800 | if (func2==tell_UPC) return (-1); | ||
3801 | #else | ||
3802 | return (0); | ||
3803 | #endif | ||
3804 | } | ||
3805 | /*==========================================================================*/ | ||
3806 | static int check_allowed2(u_char func1, u_char func2) | ||
3807 | { | ||
3808 | #if 000 | ||
3809 | if (func1==read_long) return (-1); | ||
3810 | if (func1==read_long_prefetch) return (-1); | ||
3811 | if (func1==seek) return (-1); | ||
3812 | if (func1==audio_play) return (-1); | ||
3813 | if (func1!=ioctl_o) return (0); | ||
3814 | if (fam1_drive) | ||
3815 | { | ||
3816 | if (func2==EjectDisk) return (-1); | ||
3817 | if (func2==CloseTray) return (-1); | ||
3818 | } | ||
3819 | #else | ||
3820 | return (0); | ||
3821 | #endif | ||
3822 | } | ||
3823 | /*==========================================================================*/ | ||
3824 | static int check_allowed3(u_char func1, u_char func2) | ||
3825 | { | ||
3826 | #if 000 | ||
3827 | if (func1==ioctl_i) | ||
3828 | { | ||
3829 | if (func2==tell_address) return (0); | ||
3830 | if (func2==tell_capabiliti) return (0); | ||
3831 | if (func2==tell_CD_changed) return (0); | ||
3832 | if (fam0L_drive) if (func2==tell_SubChanInfo) return (0); | ||
3833 | return (-1); | ||
3834 | } | ||
3835 | if (func1==ioctl_o) | ||
3836 | { | ||
3837 | if (func2==DriveReset) return (0); | ||
3838 | if (fam0L_drive) | ||
3839 | { | ||
3840 | if (func2==EjectDisk) return (0); | ||
3841 | if (func2==LockDoor) return (0); | ||
3842 | if (func2==CloseTray) return (0); | ||
3843 | } | ||
3844 | return (-1); | ||
3845 | } | ||
3846 | if (func1==flush_input) return (-1); | ||
3847 | if (func1==read_long) return (-1); | ||
3848 | if (func1==read_long_prefetch) return (-1); | ||
3849 | if (func1==seek) return (-1); | ||
3850 | if (func1==audio_play) return (-1); | ||
3851 | if (func1==audio_pause) return (-1); | ||
3852 | if (func1==audio_resume) return (-1); | ||
3853 | #else | ||
3854 | return (0); | ||
3855 | #endif | ||
3856 | } | ||
3857 | /*==========================================================================*/ | ||
3858 | static int seek_pos_audio_end(void) | ||
3859 | { | ||
3860 | int i; | ||
3861 | |||
3862 | i=msf2blk(current_drive->pos_audio_end)-1; | ||
3863 | if (i<0) return (-1); | ||
3864 | i=cc_Seek(i,0); | ||
3865 | return (i); | ||
3866 | } | ||
3867 | #endif /* FUTURE */ | ||
3868 | /*==========================================================================*/ | ||
3869 | static int ReadToC(void) | ||
3870 | { | ||
3871 | int i, j; | ||
3872 | current_drive->diskstate_flags &= ~toc_bit; | ||
3873 | current_drive->ored_ctl_adr=0; | ||
3874 | /* special handling of CD-I HE */ | ||
3875 | if ((current_drive->n_first_track == 2 && current_drive->n_last_track == 2) || | ||
3876 | current_drive->xa_byte == 0x10) | ||
3877 | { | ||
3878 | current_drive->TocBuffer[1].nixbyte=0; | ||
3879 | current_drive->TocBuffer[1].ctl_adr=0x40; | ||
3880 | current_drive->TocBuffer[1].number=1; | ||
3881 | current_drive->TocBuffer[1].format=0; | ||
3882 | current_drive->TocBuffer[1].address=blk2msf(0); | ||
3883 | current_drive->ored_ctl_adr |= 0x40; | ||
3884 | current_drive->n_first_track = 1; | ||
3885 | current_drive->n_last_track = 1; | ||
3886 | current_drive->xa_byte = 0x10; | ||
3887 | j = 2; | ||
3888 | } else | ||
3889 | for (j=current_drive->n_first_track;j<=current_drive->n_last_track;j++) | ||
3890 | { | ||
3891 | i=cc_ReadTocEntry(j); | ||
3892 | if (i<0) | ||
3893 | { | ||
3894 | msg(DBG_INF,"cc_ReadTocEntry(%d) returns %d.\n",j,i); | ||
3895 | return (i); | ||
3896 | } | ||
3897 | current_drive->TocBuffer[j].nixbyte=current_drive->TocEnt_nixbyte; | ||
3898 | current_drive->TocBuffer[j].ctl_adr=current_drive->TocEnt_ctl_adr; | ||
3899 | current_drive->TocBuffer[j].number=current_drive->TocEnt_number; | ||
3900 | current_drive->TocBuffer[j].format=current_drive->TocEnt_format; | ||
3901 | current_drive->TocBuffer[j].address=current_drive->TocEnt_address; | ||
3902 | current_drive->ored_ctl_adr |= current_drive->TocEnt_ctl_adr; | ||
3903 | } | ||
3904 | /* fake entry for LeadOut Track */ | ||
3905 | current_drive->TocBuffer[j].nixbyte=0; | ||
3906 | current_drive->TocBuffer[j].ctl_adr=0; | ||
3907 | current_drive->TocBuffer[j].number=CDROM_LEADOUT; | ||
3908 | current_drive->TocBuffer[j].format=0; | ||
3909 | current_drive->TocBuffer[j].address=current_drive->size_msf; | ||
3910 | |||
3911 | current_drive->diskstate_flags |= toc_bit; | ||
3912 | return (0); | ||
3913 | } | ||
3914 | /*==========================================================================*/ | ||
3915 | static int DiskInfo(void) | ||
3916 | { | ||
3917 | int i, j; | ||
3918 | |||
3919 | current_drive->mode=READ_M1; | ||
3920 | |||
3921 | #undef LOOP_COUNT | ||
3922 | #define LOOP_COUNT 10 /* needed for some "old" drives */ | ||
3923 | |||
3924 | msg(DBG_000,"DiskInfo entered.\n"); | ||
3925 | for (j=1;j<LOOP_COUNT;j++) | ||
3926 | { | ||
3927 | #if 0 | ||
3928 | i=SetSpeed(); | ||
3929 | if (i<0) | ||
3930 | { | ||
3931 | msg(DBG_INF,"DiskInfo: SetSpeed returns %d\n", i); | ||
3932 | continue; | ||
3933 | } | ||
3934 | i=cc_ModeSense(); | ||
3935 | if (i<0) | ||
3936 | { | ||
3937 | msg(DBG_INF,"DiskInfo: cc_ModeSense returns %d\n", i); | ||
3938 | continue; | ||
3939 | } | ||
3940 | #endif | ||
3941 | i=cc_ReadCapacity(); | ||
3942 | if (i>=0) break; | ||
3943 | msg(DBG_INF,"DiskInfo: ReadCapacity #%d returns %d\n", j, i); | ||
3944 | #if 0 | ||
3945 | i=cc_DriveReset(); | ||
3946 | #endif | ||
3947 | if (!fam0_drive && j == 2) break; | ||
3948 | } | ||
3949 | if (j==LOOP_COUNT) return (-33); /* give up */ | ||
3950 | |||
3951 | i=cc_ReadTocDescr(); | ||
3952 | if (i<0) | ||
3953 | { | ||
3954 | msg(DBG_INF,"DiskInfo: ReadTocDescr returns %d\n", i); | ||
3955 | return (i); | ||
3956 | } | ||
3957 | i=ReadToC(); | ||
3958 | if (i<0) | ||
3959 | { | ||
3960 | msg(DBG_INF,"DiskInfo: ReadToC returns %d\n", i); | ||
3961 | return (i); | ||
3962 | } | ||
3963 | i=cc_CheckMultiSession(); | ||
3964 | if (i<0) | ||
3965 | { | ||
3966 | msg(DBG_INF,"DiskInfo: cc_CheckMultiSession returns %d\n", i); | ||
3967 | return (i); | ||
3968 | } | ||
3969 | if (current_drive->f_multisession) current_drive->sbp_bufsiz=1; /* possibly a weird PhotoCD */ | ||
3970 | else current_drive->sbp_bufsiz=buffers; | ||
3971 | i=cc_ReadTocEntry(current_drive->n_first_track); | ||
3972 | if (i<0) | ||
3973 | { | ||
3974 | msg(DBG_INF,"DiskInfo: cc_ReadTocEntry(1) returns %d\n", i); | ||
3975 | return (i); | ||
3976 | } | ||
3977 | i=cc_ReadUPC(); | ||
3978 | if (i<0) msg(DBG_INF,"DiskInfo: cc_ReadUPC returns %d\n", i); | ||
3979 | if ((fam0L_drive) && (current_drive->xa_byte==0x20 || current_drive->xa_byte == 0x10)) | ||
3980 | { | ||
3981 | /* XA disk with old drive */ | ||
3982 | cc_ModeSelect(CD_FRAMESIZE_RAW1); | ||
3983 | cc_ModeSense(); | ||
3984 | } | ||
3985 | if (famT_drive) cc_prep_mode_T(); | ||
3986 | msg(DBG_000,"DiskInfo done.\n"); | ||
3987 | return (0); | ||
3988 | } | ||
3989 | |||
3990 | static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr) | ||
3991 | { | ||
3992 | struct sbpcd_drive *p = cdi->handle; | ||
3993 | int st; | ||
3994 | |||
3995 | if (CDSL_CURRENT != slot_nr) { | ||
3996 | /* we have no changer support */ | ||
3997 | return -EINVAL; | ||
3998 | } | ||
3999 | |||
4000 | cc_ReadStatus(); | ||
4001 | st=ResponseStatus(); | ||
4002 | if (st<0) | ||
4003 | { | ||
4004 | msg(DBG_INF,"sbpcd_drive_status: timeout.\n"); | ||
4005 | return (0); | ||
4006 | } | ||
4007 | msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked); | ||
4008 | msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed); | ||
4009 | msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in); | ||
4010 | msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok); | ||
4011 | msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning); | ||
4012 | msg(DBG_000,"Drive Status: busy =%d.\n", st_busy); | ||
4013 | |||
4014 | #if 0 | ||
4015 | if (!(p->status_bits & p_door_closed)) return CDS_TRAY_OPEN; | ||
4016 | if (p->status_bits & p_disk_ok) return CDS_DISC_OK; | ||
4017 | if (p->status_bits & p_disk_in) return CDS_DRIVE_NOT_READY; | ||
4018 | |||
4019 | return CDS_NO_DISC; | ||
4020 | #else | ||
4021 | if (p->status_bits & p_spinning) return CDS_DISC_OK; | ||
4022 | /* return CDS_TRAY_OPEN; */ | ||
4023 | return CDS_NO_DISC; | ||
4024 | |||
4025 | #endif | ||
4026 | |||
4027 | } | ||
4028 | |||
4029 | |||
4030 | /*==========================================================================*/ | ||
4031 | #ifdef FUTURE | ||
4032 | /* | ||
4033 | * called always if driver gets entered | ||
4034 | * returns 0 or ERROR2 or ERROR15 | ||
4035 | */ | ||
4036 | static int prepare(u_char func, u_char subfunc) | ||
4037 | { | ||
4038 | int i; | ||
4039 | |||
4040 | if (fam0L_drive) | ||
4041 | { | ||
4042 | i=inb(CDi_status); | ||
4043 | if (i&s_attention) GetStatus(); | ||
4044 | } | ||
4045 | else if (fam1_drive) GetStatus(); | ||
4046 | else if (fam2_drive) GetStatus(); | ||
4047 | else if (famT_drive) GetStatus(); | ||
4048 | if (current_drive->CD_changed==0xFF) | ||
4049 | { | ||
4050 | current_drive->diskstate_flags=0; | ||
4051 | current_drive->audio_state=0; | ||
4052 | if (!st_diskok) | ||
4053 | { | ||
4054 | i=check_allowed1(func,subfunc); | ||
4055 | if (i<0) return (-2); | ||
4056 | } | ||
4057 | else | ||
4058 | { | ||
4059 | i=check_allowed3(func,subfunc); | ||
4060 | if (i<0) | ||
4061 | { | ||
4062 | current_drive->CD_changed=1; | ||
4063 | return (-15); | ||
4064 | } | ||
4065 | } | ||
4066 | } | ||
4067 | else | ||
4068 | { | ||
4069 | if (!st_diskok) | ||
4070 | { | ||
4071 | current_drive->diskstate_flags=0; | ||
4072 | current_drive->audio_state=0; | ||
4073 | i=check_allowed1(func,subfunc); | ||
4074 | if (i<0) return (-2); | ||
4075 | } | ||
4076 | else | ||
4077 | { | ||
4078 | if (st_busy) | ||
4079 | { | ||
4080 | if (current_drive->audio_state!=audio_pausing) | ||
4081 | { | ||
4082 | i=check_allowed2(func,subfunc); | ||
4083 | if (i<0) return (-2); | ||
4084 | } | ||
4085 | } | ||
4086 | else | ||
4087 | { | ||
4088 | if (current_drive->audio_state==audio_playing) seek_pos_audio_end(); | ||
4089 | current_drive->audio_state=0; | ||
4090 | } | ||
4091 | if (!frame_size_valid) | ||
4092 | { | ||
4093 | i=DiskInfo(); | ||
4094 | if (i<0) | ||
4095 | { | ||
4096 | current_drive->diskstate_flags=0; | ||
4097 | current_drive->audio_state=0; | ||
4098 | i=check_allowed1(func,subfunc); | ||
4099 | if (i<0) return (-2); | ||
4100 | } | ||
4101 | } | ||
4102 | } | ||
4103 | } | ||
4104 | return (0); | ||
4105 | } | ||
4106 | #endif /* FUTURE */ | ||
4107 | /*==========================================================================*/ | ||
4108 | /*==========================================================================*/ | ||
4109 | /* | ||
4110 | * Check the results of the "get status" command. | ||
4111 | */ | ||
4112 | static int sbp_status(void) | ||
4113 | { | ||
4114 | int st; | ||
4115 | |||
4116 | st=ResponseStatus(); | ||
4117 | if (st<0) | ||
4118 | { | ||
4119 | msg(DBG_INF,"sbp_status: timeout.\n"); | ||
4120 | return (0); | ||
4121 | } | ||
4122 | |||
4123 | if (!st_spinning) msg(DBG_SPI,"motor got off - ignoring.\n"); | ||
4124 | |||
4125 | if (st_check) | ||
4126 | { | ||
4127 | msg(DBG_INF,"st_check detected - retrying.\n"); | ||
4128 | return (0); | ||
4129 | } | ||
4130 | if (!st_door_closed) | ||
4131 | { | ||
4132 | msg(DBG_INF,"door is open - retrying.\n"); | ||
4133 | return (0); | ||
4134 | } | ||
4135 | if (!st_caddy_in) | ||
4136 | { | ||
4137 | msg(DBG_INF,"disk removed - retrying.\n"); | ||
4138 | return (0); | ||
4139 | } | ||
4140 | if (!st_diskok) | ||
4141 | { | ||
4142 | msg(DBG_INF,"!st_diskok detected - retrying.\n"); | ||
4143 | return (0); | ||
4144 | } | ||
4145 | if (st_busy) | ||
4146 | { | ||
4147 | msg(DBG_INF,"st_busy detected - retrying.\n"); | ||
4148 | return (0); | ||
4149 | } | ||
4150 | return (1); | ||
4151 | } | ||
4152 | /*==========================================================================*/ | ||
4153 | |||
4154 | static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_multisession *ms_infp) | ||
4155 | { | ||
4156 | struct sbpcd_drive *p = cdi->handle; | ||
4157 | ms_infp->addr_format = CDROM_LBA; | ||
4158 | ms_infp->addr.lba = p->lba_multi; | ||
4159 | if (p->f_multisession) | ||
4160 | ms_infp->xa_flag=1; /* valid redirection address */ | ||
4161 | else | ||
4162 | ms_infp->xa_flag=0; /* invalid redirection address */ | ||
4163 | |||
4164 | return 0; | ||
4165 | } | ||
4166 | |||
4167 | /*==========================================================================*/ | ||
4168 | /*==========================================================================*/ | ||
4169 | /* | ||
4170 | * ioctl support | ||
4171 | */ | ||
4172 | static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, | ||
4173 | u_long arg) | ||
4174 | { | ||
4175 | struct sbpcd_drive *p = cdi->handle; | ||
4176 | int i; | ||
4177 | |||
4178 | msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg); | ||
4179 | if (p->drv_id==-1) { | ||
4180 | msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name); | ||
4181 | return (-ENXIO); /* no such drive */ | ||
4182 | } | ||
4183 | down(&ioctl_read_sem); | ||
4184 | if (p != current_drive) | ||
4185 | switch_drive(p); | ||
4186 | |||
4187 | msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd); | ||
4188 | switch (cmd) /* Sun-compatible */ | ||
4189 | { | ||
4190 | case DDIOCSDBG: /* DDI Debug */ | ||
4191 | if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM); | ||
4192 | i=sbpcd_dbg_ioctl(arg,1); | ||
4193 | RETURN_UP(i); | ||
4194 | case CDROMRESET: /* hard reset the drive */ | ||
4195 | msg(DBG_IOC,"ioctl: CDROMRESET entered.\n"); | ||
4196 | i=DriveReset(); | ||
4197 | current_drive->audio_state=0; | ||
4198 | RETURN_UP(i); | ||
4199 | |||
4200 | case CDROMREADMODE1: | ||
4201 | msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n"); | ||
4202 | #ifdef SAFE_MIXED | ||
4203 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
4204 | #endif /* SAFE_MIXED */ | ||
4205 | cc_ModeSelect(CD_FRAMESIZE); | ||
4206 | cc_ModeSense(); | ||
4207 | current_drive->mode=READ_M1; | ||
4208 | RETURN_UP(0); | ||
4209 | |||
4210 | case CDROMREADMODE2: /* not usable at the moment */ | ||
4211 | msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n"); | ||
4212 | #ifdef SAFE_MIXED | ||
4213 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
4214 | #endif /* SAFE_MIXED */ | ||
4215 | cc_ModeSelect(CD_FRAMESIZE_RAW1); | ||
4216 | cc_ModeSense(); | ||
4217 | current_drive->mode=READ_M2; | ||
4218 | RETURN_UP(0); | ||
4219 | |||
4220 | case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */ | ||
4221 | msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n"); | ||
4222 | if (current_drive->sbp_audsiz>0) vfree(current_drive->aud_buf); | ||
4223 | current_drive->aud_buf=NULL; | ||
4224 | current_drive->sbp_audsiz=arg; | ||
4225 | |||
4226 | if (current_drive->sbp_audsiz>16) | ||
4227 | { | ||
4228 | current_drive->sbp_audsiz = 0; | ||
4229 | RETURN_UP(current_drive->sbp_audsiz); | ||
4230 | } | ||
4231 | |||
4232 | if (current_drive->sbp_audsiz>0) | ||
4233 | { | ||
4234 | current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW); | ||
4235 | if (current_drive->aud_buf==NULL) | ||
4236 | { | ||
4237 | msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz); | ||
4238 | current_drive->sbp_audsiz=0; | ||
4239 | } | ||
4240 | else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz); | ||
4241 | } | ||
4242 | RETURN_UP(current_drive->sbp_audsiz); | ||
4243 | |||
4244 | case CDROMREADAUDIO: | ||
4245 | { /* start of CDROMREADAUDIO */ | ||
4246 | int i=0, j=0, frame, block=0; | ||
4247 | u_int try=0; | ||
4248 | u_long timeout; | ||
4249 | u_char *p; | ||
4250 | u_int data_tries = 0; | ||
4251 | u_int data_waits = 0; | ||
4252 | u_int data_retrying = 0; | ||
4253 | int status_tries; | ||
4254 | int error_flag; | ||
4255 | |||
4256 | msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n"); | ||
4257 | if (fam0_drive) RETURN_UP(-EINVAL); | ||
4258 | if (famL_drive) RETURN_UP(-EINVAL); | ||
4259 | if (famV_drive) RETURN_UP(-EINVAL); | ||
4260 | if (famT_drive) RETURN_UP(-EINVAL); | ||
4261 | #ifdef SAFE_MIXED | ||
4262 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
4263 | #endif /* SAFE_MIXED */ | ||
4264 | if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL); | ||
4265 | if (copy_from_user(&read_audio, (void __user *)arg, | ||
4266 | sizeof(struct cdrom_read_audio))) | ||
4267 | RETURN_UP(-EFAULT); | ||
4268 | if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL); | ||
4269 | if (!access_ok(VERIFY_WRITE, read_audio.buf, | ||
4270 | read_audio.nframes*CD_FRAMESIZE_RAW)) | ||
4271 | RETURN_UP(-EFAULT); | ||
4272 | |||
4273 | if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */ | ||
4274 | block=msf2lba(&read_audio.addr.msf.minute); | ||
4275 | else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */ | ||
4276 | block=read_audio.addr.lba; | ||
4277 | else RETURN_UP(-EINVAL); | ||
4278 | #if 000 | ||
4279 | i=cc_SetSpeed(speed_150,0,0); | ||
4280 | if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i); | ||
4281 | #endif | ||
4282 | msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n", | ||
4283 | block, blk2msf(block)); | ||
4284 | msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n"); | ||
4285 | #if OLD_BUSY | ||
4286 | while (busy_data) sbp_sleep(HZ/10); /* wait a bit */ | ||
4287 | busy_audio=1; | ||
4288 | #endif /* OLD_BUSY */ | ||
4289 | error_flag=0; | ||
4290 | for (data_tries=5; data_tries>0; data_tries--) | ||
4291 | { | ||
4292 | msg(DBG_AUD,"data_tries=%d ...\n", data_tries); | ||
4293 | current_drive->mode=READ_AU; | ||
4294 | cc_ModeSelect(CD_FRAMESIZE_RAW); | ||
4295 | cc_ModeSense(); | ||
4296 | for (status_tries=3; status_tries > 0; status_tries--) | ||
4297 | { | ||
4298 | flags_cmd_out |= f_respo3; | ||
4299 | cc_ReadStatus(); | ||
4300 | if (sbp_status() != 0) break; | ||
4301 | if (st_check) cc_ReadError(); | ||
4302 | sbp_sleep(1); /* wait a bit, try again */ | ||
4303 | } | ||
4304 | if (status_tries == 0) | ||
4305 | { | ||
4306 | msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__); | ||
4307 | continue; | ||
4308 | } | ||
4309 | msg(DBG_AUD,"read_audio: sbp_status: ok.\n"); | ||
4310 | |||
4311 | flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; | ||
4312 | if (fam0L_drive) | ||
4313 | { | ||
4314 | flags_cmd_out |= f_lopsta | f_getsta | f_bit1; | ||
4315 | cmd_type=READ_M2; | ||
4316 | drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ | ||
4317 | drvcmd[1]=(block>>16)&0x000000ff; | ||
4318 | drvcmd[2]=(block>>8)&0x000000ff; | ||
4319 | drvcmd[3]=block&0x000000ff; | ||
4320 | drvcmd[4]=0; | ||
4321 | drvcmd[5]=read_audio.nframes; /* # of frames */ | ||
4322 | drvcmd[6]=0; | ||
4323 | } | ||
4324 | else if (fam1_drive) | ||
4325 | { | ||
4326 | drvcmd[0]=CMD1_READ; /* "read frames", new drives */ | ||
4327 | lba2msf(block,&drvcmd[1]); /* msf-bin format required */ | ||
4328 | drvcmd[4]=0; | ||
4329 | drvcmd[5]=0; | ||
4330 | drvcmd[6]=read_audio.nframes; /* # of frames */ | ||
4331 | } | ||
4332 | else if (fam2_drive) | ||
4333 | { | ||
4334 | drvcmd[0]=CMD2_READ_XA2; | ||
4335 | lba2msf(block,&drvcmd[1]); /* msf-bin format required */ | ||
4336 | drvcmd[4]=0; | ||
4337 | drvcmd[5]=read_audio.nframes; /* # of frames */ | ||
4338 | drvcmd[6]=0x11; /* raw mode */ | ||
4339 | } | ||
4340 | else if (famT_drive) /* CD-55A: not tested yet */ | ||
4341 | { | ||
4342 | } | ||
4343 | msg(DBG_AUD,"read_audio: before giving \"read\" command.\n"); | ||
4344 | flags_cmd_out=f_putcmd; | ||
4345 | response_count=0; | ||
4346 | i=cmd_out(); | ||
4347 | if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0d\n", i); | ||
4348 | sbp_sleep(0); | ||
4349 | msg(DBG_AUD,"read_audio: after giving \"read\" command.\n"); | ||
4350 | for (frame=1;frame<2 && !error_flag; frame++) | ||
4351 | { | ||
4352 | try=maxtim_data; | ||
4353 | for (timeout=jiffies+9*HZ; ; ) | ||
4354 | { | ||
4355 | for ( ; try!=0;try--) | ||
4356 | { | ||
4357 | j=inb(CDi_status); | ||
4358 | if (!(j&s_not_data_ready)) break; | ||
4359 | if (!(j&s_not_result_ready)) break; | ||
4360 | if (fam0L_drive) if (j&s_attention) break; | ||
4361 | } | ||
4362 | if (try != 0 || time_after_eq(jiffies, timeout)) break; | ||
4363 | if (data_retrying == 0) data_waits++; | ||
4364 | data_retrying = 1; | ||
4365 | sbp_sleep(1); | ||
4366 | try = 1; | ||
4367 | } | ||
4368 | if (try==0) | ||
4369 | { | ||
4370 | msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n"); | ||
4371 | error_flag++; | ||
4372 | break; | ||
4373 | } | ||
4374 | msg(DBG_AUD,"read_audio: sbp_data: CDi_status ok.\n"); | ||
4375 | if (j&s_not_data_ready) | ||
4376 | { | ||
4377 | msg(DBG_INF, "read_audio: sbp_data: DATA_READY timeout.\n"); | ||
4378 | error_flag++; | ||
4379 | break; | ||
4380 | } | ||
4381 | msg(DBG_AUD,"read_audio: before reading data.\n"); | ||
4382 | error_flag=0; | ||
4383 | p = current_drive->aud_buf; | ||
4384 | if (sbpro_type==1) OUT(CDo_sel_i_d,1); | ||
4385 | if (do_16bit) | ||
4386 | { | ||
4387 | u_short *p2 = (u_short *) p; | ||
4388 | |||
4389 | for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) | ||
4390 | { | ||
4391 | if ((inb_p(CDi_status)&s_not_data_ready)) continue; | ||
4392 | |||
4393 | /* get one sample */ | ||
4394 | *p2++ = inw_p(CDi_data); | ||
4395 | *p2++ = inw_p(CDi_data); | ||
4396 | } | ||
4397 | } else { | ||
4398 | for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) | ||
4399 | { | ||
4400 | if ((inb_p(CDi_status)&s_not_data_ready)) continue; | ||
4401 | |||
4402 | /* get one sample */ | ||
4403 | *p++ = inb_p(CDi_data); | ||
4404 | *p++ = inb_p(CDi_data); | ||
4405 | *p++ = inb_p(CDi_data); | ||
4406 | *p++ = inb_p(CDi_data); | ||
4407 | } | ||
4408 | } | ||
4409 | if (sbpro_type==1) OUT(CDo_sel_i_d,0); | ||
4410 | data_retrying = 0; | ||
4411 | } | ||
4412 | msg(DBG_AUD,"read_audio: after reading data.\n"); | ||
4413 | if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ | ||
4414 | { | ||
4415 | msg(DBG_AUD,"read_audio: read aborted by drive\n"); | ||
4416 | #if 0000 | ||
4417 | i=cc_DriveReset(); /* ugly fix to prevent a hang */ | ||
4418 | #else | ||
4419 | i=cc_ReadError(); | ||
4420 | #endif | ||
4421 | continue; | ||
4422 | } | ||
4423 | if (fam0L_drive) | ||
4424 | { | ||
4425 | i=maxtim_data; | ||
4426 | for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--) | ||
4427 | { | ||
4428 | for ( ;i!=0;i--) | ||
4429 | { | ||
4430 | j=inb(CDi_status); | ||
4431 | if (!(j&s_not_data_ready)) break; | ||
4432 | if (!(j&s_not_result_ready)) break; | ||
4433 | if (j&s_attention) break; | ||
4434 | } | ||
4435 | if (i != 0 || time_after_eq(jiffies, timeout)) break; | ||
4436 | sbp_sleep(0); | ||
4437 | i = 1; | ||
4438 | } | ||
4439 | if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ"); | ||
4440 | if (!(j&s_attention)) | ||
4441 | { | ||
4442 | msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n"); | ||
4443 | i=cc_DriveReset(); /* ugly fix to prevent a hang */ | ||
4444 | continue; | ||
4445 | } | ||
4446 | } | ||
4447 | do | ||
4448 | { | ||
4449 | if (fam0L_drive) cc_ReadStatus(); | ||
4450 | i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ | ||
4451 | if (i<0) { msg(DBG_AUD, | ||
4452 | "read_audio: cc_ReadStatus error after read: %02X\n", | ||
4453 | current_drive->status_bits); | ||
4454 | continue; /* FIXME */ | ||
4455 | } | ||
4456 | } | ||
4457 | while ((fam0L_drive)&&(!st_check)&&(!(i&p_success))); | ||
4458 | if (st_check) | ||
4459 | { | ||
4460 | i=cc_ReadError(); | ||
4461 | msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i); | ||
4462 | continue; | ||
4463 | } | ||
4464 | if (copy_to_user(read_audio.buf, | ||
4465 | current_drive->aud_buf, | ||
4466 | read_audio.nframes * CD_FRAMESIZE_RAW)) | ||
4467 | RETURN_UP(-EFAULT); | ||
4468 | msg(DBG_AUD,"read_audio: copy_to_user done.\n"); | ||
4469 | break; | ||
4470 | } | ||
4471 | cc_ModeSelect(CD_FRAMESIZE); | ||
4472 | cc_ModeSense(); | ||
4473 | current_drive->mode=READ_M1; | ||
4474 | #if OLD_BUSY | ||
4475 | busy_audio=0; | ||
4476 | #endif /* OLD_BUSY */ | ||
4477 | if (data_tries == 0) | ||
4478 | { | ||
4479 | msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__); | ||
4480 | RETURN_UP(-EIO); | ||
4481 | } | ||
4482 | msg(DBG_AUD,"read_audio: successful return.\n"); | ||
4483 | RETURN_UP(0); | ||
4484 | } /* end of CDROMREADAUDIO */ | ||
4485 | |||
4486 | default: | ||
4487 | msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); | ||
4488 | RETURN_UP(-EINVAL); | ||
4489 | } /* end switch(cmd) */ | ||
4490 | } | ||
4491 | |||
4492 | static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, | ||
4493 | void * arg) | ||
4494 | { | ||
4495 | struct sbpcd_drive *p = cdi->handle; | ||
4496 | int i, st, j; | ||
4497 | |||
4498 | msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08p)\n", cdi->name, cmd, arg); | ||
4499 | if (p->drv_id==-1) { | ||
4500 | msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name); | ||
4501 | return (-ENXIO); /* no such drive */ | ||
4502 | } | ||
4503 | down(&ioctl_read_sem); | ||
4504 | if (p != current_drive) | ||
4505 | switch_drive(p); | ||
4506 | |||
4507 | msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd); | ||
4508 | switch (cmd) /* Sun-compatible */ | ||
4509 | { | ||
4510 | |||
4511 | case CDROMPAUSE: /* Pause the drive */ | ||
4512 | msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n"); | ||
4513 | /* pause the drive unit when it is currently in PLAY mode, */ | ||
4514 | /* or reset the starting and ending locations when in PAUSED mode. */ | ||
4515 | /* If applicable, at the next stopping point it reaches */ | ||
4516 | /* the drive will discontinue playing. */ | ||
4517 | switch (current_drive->audio_state) | ||
4518 | { | ||
4519 | case audio_playing: | ||
4520 | if (famL_drive) i=cc_ReadSubQ(); | ||
4521 | else i=cc_Pause_Resume(1); | ||
4522 | if (i<0) RETURN_UP(-EIO); | ||
4523 | if (famL_drive) i=cc_Pause_Resume(1); | ||
4524 | else i=cc_ReadSubQ(); | ||
4525 | if (i<0) RETURN_UP(-EIO); | ||
4526 | current_drive->pos_audio_start=current_drive->SubQ_run_tot; | ||
4527 | current_drive->audio_state=audio_pausing; | ||
4528 | RETURN_UP(0); | ||
4529 | case audio_pausing: | ||
4530 | i=cc_Seek(current_drive->pos_audio_start,1); | ||
4531 | if (i<0) RETURN_UP(-EIO); | ||
4532 | RETURN_UP(0); | ||
4533 | default: | ||
4534 | RETURN_UP(-EINVAL); | ||
4535 | } | ||
4536 | |||
4537 | case CDROMRESUME: /* resume paused audio play */ | ||
4538 | msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n"); | ||
4539 | /* resume playing audio tracks when a previous PLAY AUDIO call has */ | ||
4540 | /* been paused with a PAUSE command. */ | ||
4541 | /* It will resume playing from the location saved in SubQ_run_tot. */ | ||
4542 | if (current_drive->audio_state!=audio_pausing) RETURN_UP(-EINVAL); | ||
4543 | if (famL_drive) | ||
4544 | i=cc_PlayAudio(current_drive->pos_audio_start, | ||
4545 | current_drive->pos_audio_end); | ||
4546 | else i=cc_Pause_Resume(3); | ||
4547 | if (i<0) RETURN_UP(-EIO); | ||
4548 | current_drive->audio_state=audio_playing; | ||
4549 | RETURN_UP(0); | ||
4550 | |||
4551 | case CDROMPLAYMSF: | ||
4552 | msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n"); | ||
4553 | #ifdef SAFE_MIXED | ||
4554 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
4555 | #endif /* SAFE_MIXED */ | ||
4556 | if (current_drive->audio_state==audio_playing) | ||
4557 | { | ||
4558 | i=cc_Pause_Resume(1); | ||
4559 | if (i<0) RETURN_UP(-EIO); | ||
4560 | i=cc_ReadSubQ(); | ||
4561 | if (i<0) RETURN_UP(-EIO); | ||
4562 | current_drive->pos_audio_start=current_drive->SubQ_run_tot; | ||
4563 | i=cc_Seek(current_drive->pos_audio_start,1); | ||
4564 | } | ||
4565 | memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf)); | ||
4566 | /* values come as msf-bin */ | ||
4567 | current_drive->pos_audio_start = (msf.cdmsf_min0<<16) | | ||
4568 | (msf.cdmsf_sec0<<8) | | ||
4569 | msf.cdmsf_frame0; | ||
4570 | current_drive->pos_audio_end = (msf.cdmsf_min1<<16) | | ||
4571 | (msf.cdmsf_sec1<<8) | | ||
4572 | msf.cdmsf_frame1; | ||
4573 | msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n", | ||
4574 | current_drive->pos_audio_start,current_drive->pos_audio_end); | ||
4575 | i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end); | ||
4576 | if (i<0) | ||
4577 | { | ||
4578 | msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); | ||
4579 | DriveReset(); | ||
4580 | current_drive->audio_state=0; | ||
4581 | RETURN_UP(-EIO); | ||
4582 | } | ||
4583 | current_drive->audio_state=audio_playing; | ||
4584 | RETURN_UP(0); | ||
4585 | |||
4586 | case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ | ||
4587 | msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n"); | ||
4588 | #ifdef SAFE_MIXED | ||
4589 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
4590 | #endif /* SAFE_MIXED */ | ||
4591 | if (current_drive->audio_state==audio_playing) | ||
4592 | { | ||
4593 | msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n"); | ||
4594 | #if 1 | ||
4595 | RETURN_UP(0); /* just let us play on */ | ||
4596 | #else | ||
4597 | RETURN_UP(-EINVAL); /* play on, but say "error" */ | ||
4598 | #endif | ||
4599 | } | ||
4600 | memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti)); | ||
4601 | msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n", | ||
4602 | ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1); | ||
4603 | if (ti.cdti_trk0<current_drive->n_first_track) RETURN_UP(-EINVAL); | ||
4604 | if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL); | ||
4605 | if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0; | ||
4606 | if (ti.cdti_trk1>current_drive->n_last_track) ti.cdti_trk1=current_drive->n_last_track; | ||
4607 | current_drive->pos_audio_start=current_drive->TocBuffer[ti.cdti_trk0].address; | ||
4608 | current_drive->pos_audio_end=current_drive->TocBuffer[ti.cdti_trk1+1].address; | ||
4609 | i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end); | ||
4610 | if (i<0) | ||
4611 | { | ||
4612 | msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); | ||
4613 | DriveReset(); | ||
4614 | current_drive->audio_state=0; | ||
4615 | RETURN_UP(-EIO); | ||
4616 | } | ||
4617 | current_drive->audio_state=audio_playing; | ||
4618 | RETURN_UP(0); | ||
4619 | |||
4620 | case CDROMREADTOCHDR: /* Read the table of contents header */ | ||
4621 | msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n"); | ||
4622 | tochdr.cdth_trk0=current_drive->n_first_track; | ||
4623 | tochdr.cdth_trk1=current_drive->n_last_track; | ||
4624 | memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr)); | ||
4625 | RETURN_UP(0); | ||
4626 | |||
4627 | case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ | ||
4628 | msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n"); | ||
4629 | memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry)); | ||
4630 | i=tocentry.cdte_track; | ||
4631 | if (i==CDROM_LEADOUT) i=current_drive->n_last_track+1; | ||
4632 | else if (i<current_drive->n_first_track||i>current_drive->n_last_track) | ||
4633 | RETURN_UP(-EINVAL); | ||
4634 | tocentry.cdte_adr=current_drive->TocBuffer[i].ctl_adr&0x0F; | ||
4635 | tocentry.cdte_ctrl=(current_drive->TocBuffer[i].ctl_adr>>4)&0x0F; | ||
4636 | tocentry.cdte_datamode=current_drive->TocBuffer[i].format; | ||
4637 | if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */ | ||
4638 | { | ||
4639 | tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF; | ||
4640 | tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF; | ||
4641 | tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF; | ||
4642 | } | ||
4643 | else if (tocentry.cdte_format==CDROM_LBA) /* blk required */ | ||
4644 | tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address); | ||
4645 | else RETURN_UP(-EINVAL); | ||
4646 | memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry)); | ||
4647 | RETURN_UP(0); | ||
4648 | |||
4649 | case CDROMSTOP: /* Spin down the drive */ | ||
4650 | msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n"); | ||
4651 | #ifdef SAFE_MIXED | ||
4652 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
4653 | #endif /* SAFE_MIXED */ | ||
4654 | i=cc_Pause_Resume(1); | ||
4655 | current_drive->audio_state=0; | ||
4656 | #if 0 | ||
4657 | cc_DriveReset(); | ||
4658 | #endif | ||
4659 | RETURN_UP(i); | ||
4660 | |||
4661 | case CDROMSTART: /* Spin up the drive */ | ||
4662 | msg(DBG_IOC,"ioctl: CDROMSTART entered.\n"); | ||
4663 | cc_SpinUp(); | ||
4664 | current_drive->audio_state=0; | ||
4665 | RETURN_UP(0); | ||
4666 | |||
4667 | case CDROMVOLCTRL: /* Volume control */ | ||
4668 | msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n"); | ||
4669 | memcpy(&volctrl,(char *) arg,sizeof(volctrl)); | ||
4670 | current_drive->vol_chan0=0; | ||
4671 | current_drive->vol_ctrl0=volctrl.channel0; | ||
4672 | current_drive->vol_chan1=1; | ||
4673 | current_drive->vol_ctrl1=volctrl.channel1; | ||
4674 | i=cc_SetVolume(); | ||
4675 | RETURN_UP(0); | ||
4676 | |||
4677 | case CDROMVOLREAD: /* read Volume settings from drive */ | ||
4678 | msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n"); | ||
4679 | st=cc_GetVolume(); | ||
4680 | if (st<0) RETURN_UP(st); | ||
4681 | volctrl.channel0=current_drive->vol_ctrl0; | ||
4682 | volctrl.channel1=current_drive->vol_ctrl1; | ||
4683 | volctrl.channel2=0; | ||
4684 | volctrl.channel2=0; | ||
4685 | memcpy((void *)arg,&volctrl,sizeof(volctrl)); | ||
4686 | RETURN_UP(0); | ||
4687 | |||
4688 | case CDROMSUBCHNL: /* Get subchannel info */ | ||
4689 | msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n"); | ||
4690 | /* Bogus, I can do better than this! --AJK | ||
4691 | if ((st_spinning)||(!subq_valid)) { | ||
4692 | i=cc_ReadSubQ(); | ||
4693 | if (i<0) RETURN_UP(-EIO); | ||
4694 | } | ||
4695 | */ | ||
4696 | i=cc_ReadSubQ(); | ||
4697 | if (i<0) { | ||
4698 | j=cc_ReadError(); /* clear out error status from drive */ | ||
4699 | current_drive->audio_state=CDROM_AUDIO_NO_STATUS; | ||
4700 | /* get and set the disk state here, | ||
4701 | probably not the right place, but who cares! | ||
4702 | It makes it work properly! --AJK */ | ||
4703 | if (current_drive->CD_changed==0xFF) { | ||
4704 | msg(DBG_000,"Disk changed detect\n"); | ||
4705 | current_drive->diskstate_flags &= ~cd_size_bit; | ||
4706 | } | ||
4707 | RETURN_UP(-EIO); | ||
4708 | } | ||
4709 | if (current_drive->CD_changed==0xFF) { | ||
4710 | /* reread the TOC because the disk has changed! --AJK */ | ||
4711 | msg(DBG_000,"Disk changed STILL detected, rereading TOC!\n"); | ||
4712 | i=DiskInfo(); | ||
4713 | if(i==0) { | ||
4714 | current_drive->CD_changed=0x00; /* cd has changed, procede, */ | ||
4715 | RETURN_UP(-EIO); /* and get TOC, etc on next try! --AJK */ | ||
4716 | } else { | ||
4717 | RETURN_UP(-EIO); /* we weren't ready yet! --AJK */ | ||
4718 | } | ||
4719 | } | ||
4720 | memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl)); | ||
4721 | /* | ||
4722 | This virtual crap is very bogus! | ||
4723 | It doesn't detect when the cd is done playing audio! | ||
4724 | Lets do this right with proper hardware register reading! | ||
4725 | */ | ||
4726 | cc_ReadStatus(); | ||
4727 | i=ResponseStatus(); | ||
4728 | msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked); | ||
4729 | msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed); | ||
4730 | msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in); | ||
4731 | msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok); | ||
4732 | msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning); | ||
4733 | msg(DBG_000,"Drive Status: busy =%d.\n", st_busy); | ||
4734 | /* st_busy indicates if it's _ACTUALLY_ playing audio */ | ||
4735 | switch (current_drive->audio_state) | ||
4736 | { | ||
4737 | case audio_playing: | ||
4738 | if(st_busy==0) { | ||
4739 | /* CD has stopped playing audio --AJK */ | ||
4740 | current_drive->audio_state=audio_completed; | ||
4741 | SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED; | ||
4742 | } else { | ||
4743 | SC.cdsc_audiostatus=CDROM_AUDIO_PLAY; | ||
4744 | } | ||
4745 | break; | ||
4746 | case audio_pausing: | ||
4747 | SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED; | ||
4748 | break; | ||
4749 | case audio_completed: | ||
4750 | SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED; | ||
4751 | break; | ||
4752 | default: | ||
4753 | SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS; | ||
4754 | break; | ||
4755 | } | ||
4756 | SC.cdsc_adr=current_drive->SubQ_ctl_adr; | ||
4757 | SC.cdsc_ctrl=current_drive->SubQ_ctl_adr>>4; | ||
4758 | SC.cdsc_trk=bcd2bin(current_drive->SubQ_trk); | ||
4759 | SC.cdsc_ind=bcd2bin(current_drive->SubQ_pnt_idx); | ||
4760 | if (SC.cdsc_format==CDROM_LBA) | ||
4761 | { | ||
4762 | SC.cdsc_absaddr.lba=msf2blk(current_drive->SubQ_run_tot); | ||
4763 | SC.cdsc_reladdr.lba=msf2blk(current_drive->SubQ_run_trk); | ||
4764 | } | ||
4765 | else /* not only if (SC.cdsc_format==CDROM_MSF) */ | ||
4766 | { | ||
4767 | SC.cdsc_absaddr.msf.minute=(current_drive->SubQ_run_tot>>16)&0x00FF; | ||
4768 | SC.cdsc_absaddr.msf.second=(current_drive->SubQ_run_tot>>8)&0x00FF; | ||
4769 | SC.cdsc_absaddr.msf.frame=current_drive->SubQ_run_tot&0x00FF; | ||
4770 | SC.cdsc_reladdr.msf.minute=(current_drive->SubQ_run_trk>>16)&0x00FF; | ||
4771 | SC.cdsc_reladdr.msf.second=(current_drive->SubQ_run_trk>>8)&0x00FF; | ||
4772 | SC.cdsc_reladdr.msf.frame=current_drive->SubQ_run_trk&0x00FF; | ||
4773 | } | ||
4774 | memcpy((void *) arg, &SC, sizeof(struct cdrom_subchnl)); | ||
4775 | msg(DBG_IOS,"CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n", | ||
4776 | SC.cdsc_format,SC.cdsc_audiostatus, | ||
4777 | SC.cdsc_adr,SC.cdsc_ctrl, | ||
4778 | SC.cdsc_trk,SC.cdsc_ind, | ||
4779 | SC.cdsc_absaddr,SC.cdsc_reladdr); | ||
4780 | RETURN_UP(0); | ||
4781 | |||
4782 | default: | ||
4783 | msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); | ||
4784 | RETURN_UP(-EINVAL); | ||
4785 | } /* end switch(cmd) */ | ||
4786 | } | ||
4787 | /*==========================================================================*/ | ||
4788 | /* | ||
4789 | * Take care of the different block sizes between cdrom and Linux. | ||
4790 | */ | ||
4791 | static void sbp_transfer(struct request *req) | ||
4792 | { | ||
4793 | long offs; | ||
4794 | |||
4795 | while ( (req->nr_sectors > 0) && | ||
4796 | (req->sector/4 >= current_drive->sbp_first_frame) && | ||
4797 | (req->sector/4 <= current_drive->sbp_last_frame) ) | ||
4798 | { | ||
4799 | offs = (req->sector - current_drive->sbp_first_frame * 4) * 512; | ||
4800 | memcpy(req->buffer, current_drive->sbp_buf + offs, 512); | ||
4801 | req->nr_sectors--; | ||
4802 | req->sector++; | ||
4803 | req->buffer += 512; | ||
4804 | } | ||
4805 | } | ||
4806 | /*==========================================================================*/ | ||
4807 | /* | ||
4808 | * special end_request for sbpcd to solve CURRENT==NULL bug. (GTL) | ||
4809 | * GTL = Gonzalo Tornaria <tornaria@cmat.edu.uy> | ||
4810 | * | ||
4811 | * This is a kludge so we don't need to modify end_request. | ||
4812 | * We put the req we take out after INIT_REQUEST in the requests list, | ||
4813 | * so that end_request will discard it. | ||
4814 | * | ||
4815 | * The bug could be present in other block devices, perhaps we | ||
4816 | * should modify INIT_REQUEST and end_request instead, and | ||
4817 | * change every block device.. | ||
4818 | * | ||
4819 | * Could be a race here?? Could e.g. a timer interrupt schedule() us? | ||
4820 | * If so, we should copy end_request here, and do it right.. (or | ||
4821 | * modify end_request and the block devices). | ||
4822 | * | ||
4823 | * In any case, the race here would be much small than it was, and | ||
4824 | * I couldn't reproduce.. | ||
4825 | * | ||
4826 | * The race could be: suppose CURRENT==NULL. We put our req in the list, | ||
4827 | * and we are scheduled. Other process takes over, and gets into | ||
4828 | * do_sbpcd_request. It sees CURRENT!=NULL (it is == to our req), so | ||
4829 | * proceeds. It ends, so CURRENT is now NULL.. Now we awake somewhere in | ||
4830 | * end_request, but now CURRENT==NULL... oops! | ||
4831 | * | ||
4832 | */ | ||
4833 | #undef DEBUG_GTL | ||
4834 | |||
4835 | /*==========================================================================*/ | ||
4836 | /* | ||
4837 | * I/O request routine, called from Linux kernel. | ||
4838 | */ | ||
4839 | static void do_sbpcd_request(request_queue_t * q) | ||
4840 | { | ||
4841 | u_int block; | ||
4842 | u_int nsect; | ||
4843 | int status_tries, data_tries; | ||
4844 | struct request *req; | ||
4845 | struct sbpcd_drive *p; | ||
4846 | #ifdef DEBUG_GTL | ||
4847 | static int xx_nr=0; | ||
4848 | int xnr; | ||
4849 | #endif | ||
4850 | |||
4851 | request_loop: | ||
4852 | #ifdef DEBUG_GTL | ||
4853 | xnr=++xx_nr; | ||
4854 | |||
4855 | req = elv_next_request(q); | ||
4856 | |||
4857 | if (!req) | ||
4858 | { | ||
4859 | printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%li\n", | ||
4860 | xnr, current->pid, jiffies); | ||
4861 | printk( "do_sbpcd_request[%do](NULL) end 0 (null), Time:%li\n", | ||
4862 | xnr, jiffies); | ||
4863 | return; | ||
4864 | } | ||
4865 | |||
4866 | printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%li\n", | ||
4867 | xnr, req, req->sector, req->nr_sectors, current->pid, jiffies); | ||
4868 | #endif | ||
4869 | |||
4870 | req = elv_next_request(q); /* take out our request so no other */ | ||
4871 | if (!req) | ||
4872 | return; | ||
4873 | |||
4874 | if (req -> sector == -1) | ||
4875 | end_request(req, 0); | ||
4876 | spin_unlock_irq(q->queue_lock); | ||
4877 | |||
4878 | down(&ioctl_read_sem); | ||
4879 | if (rq_data_dir(elv_next_request(q)) != READ) | ||
4880 | { | ||
4881 | msg(DBG_INF, "bad cmd %d\n", req->cmd[0]); | ||
4882 | goto err_done; | ||
4883 | } | ||
4884 | p = req->rq_disk->private_data; | ||
4885 | #if OLD_BUSY | ||
4886 | while (busy_audio) sbp_sleep(HZ); /* wait a bit */ | ||
4887 | busy_data=1; | ||
4888 | #endif /* OLD_BUSY */ | ||
4889 | |||
4890 | if (p->audio_state==audio_playing) goto err_done; | ||
4891 | if (p != current_drive) | ||
4892 | switch_drive(p); | ||
4893 | |||
4894 | block = req->sector; /* always numbered as 512-byte-pieces */ | ||
4895 | nsect = req->nr_sectors; /* always counted as 512-byte-pieces */ | ||
4896 | |||
4897 | msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect); | ||
4898 | #if 0 | ||
4899 | msg(DBG_MUL,"read LBA %d\n", block/4); | ||
4900 | #endif | ||
4901 | |||
4902 | sbp_transfer(req); | ||
4903 | /* if we satisfied the request from the buffer, we're done. */ | ||
4904 | if (req->nr_sectors == 0) | ||
4905 | { | ||
4906 | #ifdef DEBUG_GTL | ||
4907 | printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 2, Time:%li\n", | ||
4908 | xnr, req, req->sector, req->nr_sectors, jiffies); | ||
4909 | #endif | ||
4910 | up(&ioctl_read_sem); | ||
4911 | spin_lock_irq(q->queue_lock); | ||
4912 | end_request(req, 1); | ||
4913 | goto request_loop; | ||
4914 | } | ||
4915 | |||
4916 | #ifdef FUTURE | ||
4917 | i=prepare(0,0); /* at moment not really a hassle check, but ... */ | ||
4918 | if (i!=0) | ||
4919 | msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i); | ||
4920 | #endif /* FUTURE */ | ||
4921 | |||
4922 | if (!st_spinning) cc_SpinUp(); | ||
4923 | |||
4924 | for (data_tries=n_retries; data_tries > 0; data_tries--) | ||
4925 | { | ||
4926 | for (status_tries=3; status_tries > 0; status_tries--) | ||
4927 | { | ||
4928 | flags_cmd_out |= f_respo3; | ||
4929 | cc_ReadStatus(); | ||
4930 | if (sbp_status() != 0) break; | ||
4931 | if (st_check) cc_ReadError(); | ||
4932 | sbp_sleep(1); /* wait a bit, try again */ | ||
4933 | } | ||
4934 | if (status_tries == 0) | ||
4935 | { | ||
4936 | msg(DBG_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__); | ||
4937 | break; | ||
4938 | } | ||
4939 | |||
4940 | sbp_read_cmd(req); | ||
4941 | sbp_sleep(0); | ||
4942 | if (sbp_data(req) != 0) | ||
4943 | { | ||
4944 | #ifdef SAFE_MIXED | ||
4945 | current_drive->has_data=2; /* is really a data disk */ | ||
4946 | #endif /* SAFE_MIXED */ | ||
4947 | #ifdef DEBUG_GTL | ||
4948 | printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n", | ||
4949 | xnr, req, req->sector, req->nr_sectors, jiffies); | ||
4950 | #endif | ||
4951 | up(&ioctl_read_sem); | ||
4952 | spin_lock_irq(q->queue_lock); | ||
4953 | end_request(req, 1); | ||
4954 | goto request_loop; | ||
4955 | } | ||
4956 | } | ||
4957 | |||
4958 | err_done: | ||
4959 | #if OLD_BUSY | ||
4960 | busy_data=0; | ||
4961 | #endif /* OLD_BUSY */ | ||
4962 | #ifdef DEBUG_GTL | ||
4963 | printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%li\n", | ||
4964 | xnr, req, req->sector, req->nr_sectors, jiffies); | ||
4965 | #endif | ||
4966 | up(&ioctl_read_sem); | ||
4967 | sbp_sleep(0); /* wait a bit, try again */ | ||
4968 | spin_lock_irq(q->queue_lock); | ||
4969 | end_request(req, 0); | ||
4970 | goto request_loop; | ||
4971 | } | ||
4972 | /*==========================================================================*/ | ||
4973 | /* | ||
4974 | * build and send the READ command. | ||
4975 | */ | ||
4976 | static void sbp_read_cmd(struct request *req) | ||
4977 | { | ||
4978 | #undef OLD | ||
4979 | |||
4980 | int i; | ||
4981 | int block; | ||
4982 | |||
4983 | current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ | ||
4984 | current_drive->sbp_current = 0; | ||
4985 | block=req->sector/4; | ||
4986 | if (block+current_drive->sbp_bufsiz <= current_drive->CDsize_frm) | ||
4987 | current_drive->sbp_read_frames = current_drive->sbp_bufsiz; | ||
4988 | else | ||
4989 | { | ||
4990 | current_drive->sbp_read_frames=current_drive->CDsize_frm-block; | ||
4991 | /* avoid reading past end of data */ | ||
4992 | if (current_drive->sbp_read_frames < 1) | ||
4993 | { | ||
4994 | msg(DBG_INF,"requested frame %d, CD size %d ???\n", | ||
4995 | block, current_drive->CDsize_frm); | ||
4996 | current_drive->sbp_read_frames=1; | ||
4997 | } | ||
4998 | } | ||
4999 | |||
5000 | flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; | ||
5001 | clr_cmdbuf(); | ||
5002 | if (famV_drive) | ||
5003 | { | ||
5004 | drvcmd[0]=CMDV_READ; | ||
5005 | lba2msf(block,&drvcmd[1]); /* msf-bcd format required */ | ||
5006 | bin2bcdx(&drvcmd[1]); | ||
5007 | bin2bcdx(&drvcmd[2]); | ||
5008 | bin2bcdx(&drvcmd[3]); | ||
5009 | drvcmd[4]=current_drive->sbp_read_frames>>8; | ||
5010 | drvcmd[5]=current_drive->sbp_read_frames&0xff; | ||
5011 | drvcmd[6]=0x02; /* flag "msf-bcd" */ | ||
5012 | } | ||
5013 | else if (fam0L_drive) | ||
5014 | { | ||
5015 | flags_cmd_out |= f_lopsta | f_getsta | f_bit1; | ||
5016 | if (current_drive->xa_byte==0x20) | ||
5017 | { | ||
5018 | cmd_type=READ_M2; | ||
5019 | drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ | ||
5020 | drvcmd[1]=(block>>16)&0x0ff; | ||
5021 | drvcmd[2]=(block>>8)&0x0ff; | ||
5022 | drvcmd[3]=block&0x0ff; | ||
5023 | drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; | ||
5024 | drvcmd[5]=current_drive->sbp_read_frames&0x0ff; | ||
5025 | } | ||
5026 | else | ||
5027 | { | ||
5028 | drvcmd[0]=CMD0_READ; /* "read frames", old drives */ | ||
5029 | if (current_drive->drv_type>=drv_201) | ||
5030 | { | ||
5031 | lba2msf(block,&drvcmd[1]); /* msf-bcd format required */ | ||
5032 | bin2bcdx(&drvcmd[1]); | ||
5033 | bin2bcdx(&drvcmd[2]); | ||
5034 | bin2bcdx(&drvcmd[3]); | ||
5035 | } | ||
5036 | else | ||
5037 | { | ||
5038 | drvcmd[1]=(block>>16)&0x0ff; | ||
5039 | drvcmd[2]=(block>>8)&0x0ff; | ||
5040 | drvcmd[3]=block&0x0ff; | ||
5041 | } | ||
5042 | drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; | ||
5043 | drvcmd[5]=current_drive->sbp_read_frames&0x0ff; | ||
5044 | drvcmd[6]=(current_drive->drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */ | ||
5045 | } | ||
5046 | } | ||
5047 | else if (fam1_drive) | ||
5048 | { | ||
5049 | drvcmd[0]=CMD1_READ; | ||
5050 | lba2msf(block,&drvcmd[1]); /* msf-bin format required */ | ||
5051 | drvcmd[5]=(current_drive->sbp_read_frames>>8)&0x0ff; | ||
5052 | drvcmd[6]=current_drive->sbp_read_frames&0x0ff; | ||
5053 | } | ||
5054 | else if (fam2_drive) | ||
5055 | { | ||
5056 | drvcmd[0]=CMD2_READ; | ||
5057 | lba2msf(block,&drvcmd[1]); /* msf-bin format required */ | ||
5058 | drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; | ||
5059 | drvcmd[5]=current_drive->sbp_read_frames&0x0ff; | ||
5060 | drvcmd[6]=0x02; | ||
5061 | } | ||
5062 | else if (famT_drive) | ||
5063 | { | ||
5064 | drvcmd[0]=CMDT_READ; | ||
5065 | drvcmd[2]=(block>>24)&0x0ff; | ||
5066 | drvcmd[3]=(block>>16)&0x0ff; | ||
5067 | drvcmd[4]=(block>>8)&0x0ff; | ||
5068 | drvcmd[5]=block&0x0ff; | ||
5069 | drvcmd[7]=(current_drive->sbp_read_frames>>8)&0x0ff; | ||
5070 | drvcmd[8]=current_drive->sbp_read_frames&0x0ff; | ||
5071 | } | ||
5072 | flags_cmd_out=f_putcmd; | ||
5073 | response_count=0; | ||
5074 | i=cmd_out(); | ||
5075 | if (i<0) msg(DBG_INF,"error giving READ command: %0d\n", i); | ||
5076 | return; | ||
5077 | } | ||
5078 | /*==========================================================================*/ | ||
5079 | /* | ||
5080 | * Check the completion of the read-data command. On success, read | ||
5081 | * the current_drive->sbp_bufsiz * 2048 bytes of data from the disk into buffer. | ||
5082 | */ | ||
5083 | static int sbp_data(struct request *req) | ||
5084 | { | ||
5085 | int i=0, j=0, l, frame; | ||
5086 | u_int try=0; | ||
5087 | u_long timeout; | ||
5088 | u_char *p; | ||
5089 | u_int data_tries = 0; | ||
5090 | u_int data_waits = 0; | ||
5091 | u_int data_retrying = 0; | ||
5092 | int error_flag; | ||
5093 | int xa_count; | ||
5094 | int max_latency; | ||
5095 | int success; | ||
5096 | int wait; | ||
5097 | int duration; | ||
5098 | |||
5099 | error_flag=0; | ||
5100 | success=0; | ||
5101 | #if LONG_TIMING | ||
5102 | max_latency=9*HZ; | ||
5103 | #else | ||
5104 | if (current_drive->f_multisession) max_latency=15*HZ; | ||
5105 | else max_latency=5*HZ; | ||
5106 | #endif | ||
5107 | duration=jiffies; | ||
5108 | for (frame=0;frame<current_drive->sbp_read_frames&&!error_flag; frame++) | ||
5109 | { | ||
5110 | SBPCD_CLI; | ||
5111 | |||
5112 | del_timer(&data_timer); | ||
5113 | data_timer.expires=jiffies+max_latency; | ||
5114 | timed_out_data=0; | ||
5115 | add_timer(&data_timer); | ||
5116 | while (!timed_out_data) | ||
5117 | { | ||
5118 | if (current_drive->f_multisession) try=maxtim_data*4; | ||
5119 | else try=maxtim_data; | ||
5120 | msg(DBG_000,"sbp_data: CDi_status loop: try=%d.\n",try); | ||
5121 | for ( ; try!=0;try--) | ||
5122 | { | ||
5123 | j=inb(CDi_status); | ||
5124 | if (!(j&s_not_data_ready)) break; | ||
5125 | if (!(j&s_not_result_ready)) break; | ||
5126 | if (fam0LV_drive) if (j&s_attention) break; | ||
5127 | } | ||
5128 | if (!(j&s_not_data_ready)) goto data_ready; | ||
5129 | if (try==0) | ||
5130 | { | ||
5131 | if (data_retrying == 0) data_waits++; | ||
5132 | data_retrying = 1; | ||
5133 | msg(DBG_000,"sbp_data: CDi_status loop: sleeping.\n"); | ||
5134 | sbp_sleep(1); | ||
5135 | try = 1; | ||
5136 | } | ||
5137 | } | ||
5138 | msg(DBG_INF,"sbp_data: CDi_status loop expired.\n"); | ||
5139 | data_ready: | ||
5140 | del_timer(&data_timer); | ||
5141 | |||
5142 | if (timed_out_data) | ||
5143 | { | ||
5144 | msg(DBG_INF,"sbp_data: CDi_status timeout (timed_out_data) (%02X).\n", j); | ||
5145 | error_flag++; | ||
5146 | } | ||
5147 | if (try==0) | ||
5148 | { | ||
5149 | msg(DBG_INF,"sbp_data: CDi_status timeout (try=0) (%02X).\n", j); | ||
5150 | error_flag++; | ||
5151 | } | ||
5152 | if (!(j&s_not_result_ready)) | ||
5153 | { | ||
5154 | msg(DBG_INF, "sbp_data: RESULT_READY where DATA_READY awaited (%02X).\n", j); | ||
5155 | response_count=20; | ||
5156 | j=ResponseInfo(); | ||
5157 | j=inb(CDi_status); | ||
5158 | } | ||
5159 | if (j&s_not_data_ready) | ||
5160 | { | ||
5161 | if ((current_drive->ored_ctl_adr&0x40)==0) | ||
5162 | msg(DBG_INF, "CD contains no data tracks.\n"); | ||
5163 | else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).\n", j); | ||
5164 | error_flag++; | ||
5165 | } | ||
5166 | SBPCD_STI; | ||
5167 | if (error_flag) break; | ||
5168 | |||
5169 | msg(DBG_000, "sbp_data: beginning to read.\n"); | ||
5170 | p = current_drive->sbp_buf + frame * CD_FRAMESIZE; | ||
5171 | if (sbpro_type==1) OUT(CDo_sel_i_d,1); | ||
5172 | if (cmd_type==READ_M2) { | ||
5173 | if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1); | ||
5174 | else insb(CDi_data, xa_head_buf, CD_XA_HEAD); | ||
5175 | } | ||
5176 | if (do_16bit) insw(CDi_data, p, CD_FRAMESIZE>>1); | ||
5177 | else insb(CDi_data, p, CD_FRAMESIZE); | ||
5178 | if (cmd_type==READ_M2) { | ||
5179 | if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1); | ||
5180 | else insb(CDi_data, xa_tail_buf, CD_XA_TAIL); | ||
5181 | } | ||
5182 | current_drive->sbp_current++; | ||
5183 | if (sbpro_type==1) OUT(CDo_sel_i_d,0); | ||
5184 | if (cmd_type==READ_M2) | ||
5185 | { | ||
5186 | for (xa_count=0;xa_count<CD_XA_HEAD;xa_count++) | ||
5187 | sprintf(&msgbuf[xa_count*3], " %02X", xa_head_buf[xa_count]); | ||
5188 | msgbuf[xa_count*3]=0; | ||
5189 | msg(DBG_XA1,"xa head:%s\n", msgbuf); | ||
5190 | } | ||
5191 | data_retrying = 0; | ||
5192 | data_tries++; | ||
5193 | if (data_tries >= 1000) | ||
5194 | { | ||
5195 | msg(DBG_INF,"sbp_data() statistics: %d waits in %d frames.\n", data_waits, data_tries); | ||
5196 | data_waits = data_tries = 0; | ||
5197 | } | ||
5198 | } | ||
5199 | duration=jiffies-duration; | ||
5200 | msg(DBG_TEA,"time to read %d frames: %d jiffies .\n",frame,duration); | ||
5201 | if (famT_drive) | ||
5202 | { | ||
5203 | wait=8; | ||
5204 | do | ||
5205 | { | ||
5206 | if (teac==2) | ||
5207 | { | ||
5208 | if ((i=CDi_stat_loop_T()) == -1) break; | ||
5209 | } | ||
5210 | else | ||
5211 | { | ||
5212 | sbp_sleep(1); | ||
5213 | OUT(CDo_sel_i_d,0); | ||
5214 | i=inb(CDi_status); | ||
5215 | } | ||
5216 | if (!(i&s_not_data_ready)) | ||
5217 | { | ||
5218 | OUT(CDo_sel_i_d,1); | ||
5219 | j=0; | ||
5220 | do | ||
5221 | { | ||
5222 | if (do_16bit) i=inw(CDi_data); | ||
5223 | else i=inb(CDi_data); | ||
5224 | j++; | ||
5225 | i=inb(CDi_status); | ||
5226 | } | ||
5227 | while (!(i&s_not_data_ready)); | ||
5228 | msg(DBG_TEA, "==========too much data (%d bytes/words)==============.\n", j); | ||
5229 | } | ||
5230 | if (!(i&s_not_result_ready)) | ||
5231 | { | ||
5232 | OUT(CDo_sel_i_d,0); | ||
5233 | l=0; | ||
5234 | do | ||
5235 | { | ||
5236 | infobuf[l++]=inb(CDi_info); | ||
5237 | i=inb(CDi_status); | ||
5238 | } | ||
5239 | while (!(i&s_not_result_ready)); | ||
5240 | if (infobuf[0]==0x00) success=1; | ||
5241 | #if 1 | ||
5242 | for (j=0;j<l;j++) sprintf(&msgbuf[j*3], " %02X", infobuf[j]); | ||
5243 | msgbuf[j*3]=0; | ||
5244 | msg(DBG_TEA,"sbp_data info response:%s\n", msgbuf); | ||
5245 | #endif | ||
5246 | if (infobuf[0]==0x02) | ||
5247 | { | ||
5248 | error_flag++; | ||
5249 | do | ||
5250 | { | ||
5251 | ++recursion; | ||
5252 | if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",recursion); | ||
5253 | else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.\n"); | ||
5254 | clr_cmdbuf(); | ||
5255 | drvcmd[0]=CMDT_READ_ERR; | ||
5256 | j=cmd_out_T(); /* !!! recursive here !!! */ | ||
5257 | --recursion; | ||
5258 | sbp_sleep(1); | ||
5259 | } | ||
5260 | while (j<0); | ||
5261 | current_drive->error_state=infobuf[2]; | ||
5262 | current_drive->b3=infobuf[3]; | ||
5263 | current_drive->b4=infobuf[4]; | ||
5264 | } | ||
5265 | break; | ||
5266 | } | ||
5267 | else | ||
5268 | { | ||
5269 | #if 0 | ||
5270 | msg(DBG_TEA, "============= waiting for result=================.\n"); | ||
5271 | sbp_sleep(1); | ||
5272 | #endif | ||
5273 | } | ||
5274 | } | ||
5275 | while (wait--); | ||
5276 | } | ||
5277 | |||
5278 | if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ | ||
5279 | { | ||
5280 | msg(DBG_TEA, "================error flag: %d=================.\n", error_flag); | ||
5281 | msg(DBG_INF,"sbp_data: read aborted by drive.\n"); | ||
5282 | #if 1 | ||
5283 | i=cc_DriveReset(); /* ugly fix to prevent a hang */ | ||
5284 | #else | ||
5285 | i=cc_ReadError(); | ||
5286 | #endif | ||
5287 | return (0); | ||
5288 | } | ||
5289 | |||
5290 | if (fam0LV_drive) | ||
5291 | { | ||
5292 | SBPCD_CLI; | ||
5293 | i=maxtim_data; | ||
5294 | for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--) | ||
5295 | { | ||
5296 | for ( ;i!=0;i--) | ||
5297 | { | ||
5298 | j=inb(CDi_status); | ||
5299 | if (!(j&s_not_data_ready)) break; | ||
5300 | if (!(j&s_not_result_ready)) break; | ||
5301 | if (j&s_attention) break; | ||
5302 | } | ||
5303 | if (i != 0 || time_after_eq(jiffies, timeout)) break; | ||
5304 | sbp_sleep(0); | ||
5305 | i = 1; | ||
5306 | } | ||
5307 | if (i==0) msg(DBG_INF,"status timeout after READ.\n"); | ||
5308 | if (!(j&s_attention)) | ||
5309 | { | ||
5310 | msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n"); | ||
5311 | i=cc_DriveReset(); /* ugly fix to prevent a hang */ | ||
5312 | SBPCD_STI; | ||
5313 | return (0); | ||
5314 | } | ||
5315 | SBPCD_STI; | ||
5316 | } | ||
5317 | |||
5318 | #if 0 | ||
5319 | if (!success) | ||
5320 | #endif | ||
5321 | do | ||
5322 | { | ||
5323 | if (fam0LV_drive) cc_ReadStatus(); | ||
5324 | #if 1 | ||
5325 | if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.\n", i); | ||
5326 | #endif | ||
5327 | i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ | ||
5328 | #if 1 | ||
5329 | if (famT_drive) msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i); | ||
5330 | #endif | ||
5331 | if (i<0) | ||
5332 | { | ||
5333 | msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits); | ||
5334 | return (0); | ||
5335 | } | ||
5336 | } | ||
5337 | while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success))); | ||
5338 | if (st_check) | ||
5339 | { | ||
5340 | i=cc_ReadError(); | ||
5341 | msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i); | ||
5342 | return (0); | ||
5343 | } | ||
5344 | if (fatal_err) | ||
5345 | { | ||
5346 | fatal_err=0; | ||
5347 | current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ | ||
5348 | current_drive->sbp_current = 0; | ||
5349 | msg(DBG_INF,"sbp_data: fatal_err - retrying.\n"); | ||
5350 | return (0); | ||
5351 | } | ||
5352 | |||
5353 | current_drive->sbp_first_frame = req -> sector / 4; | ||
5354 | current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1; | ||
5355 | sbp_transfer(req); | ||
5356 | return (1); | ||
5357 | } | ||
5358 | /*==========================================================================*/ | ||
5359 | |||
5360 | static int sbpcd_block_open(struct inode *inode, struct file *file) | ||
5361 | { | ||
5362 | struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; | ||
5363 | return cdrom_open(p->sbpcd_infop, inode, file); | ||
5364 | } | ||
5365 | |||
5366 | static int sbpcd_block_release(struct inode *inode, struct file *file) | ||
5367 | { | ||
5368 | struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; | ||
5369 | return cdrom_release(p->sbpcd_infop, file); | ||
5370 | } | ||
5371 | |||
5372 | static int sbpcd_block_ioctl(struct inode *inode, struct file *file, | ||
5373 | unsigned cmd, unsigned long arg) | ||
5374 | { | ||
5375 | struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; | ||
5376 | return cdrom_ioctl(file, p->sbpcd_infop, inode, cmd, arg); | ||
5377 | } | ||
5378 | |||
5379 | static int sbpcd_block_media_changed(struct gendisk *disk) | ||
5380 | { | ||
5381 | struct sbpcd_drive *p = disk->private_data; | ||
5382 | return cdrom_media_changed(p->sbpcd_infop); | ||
5383 | } | ||
5384 | |||
5385 | static struct block_device_operations sbpcd_bdops = | ||
5386 | { | ||
5387 | .owner = THIS_MODULE, | ||
5388 | .open = sbpcd_block_open, | ||
5389 | .release = sbpcd_block_release, | ||
5390 | .ioctl = sbpcd_block_ioctl, | ||
5391 | .media_changed = sbpcd_block_media_changed, | ||
5392 | }; | ||
5393 | /*==========================================================================*/ | ||
5394 | /* | ||
5395 | * Open the device special file. Check that a disk is in. Read TOC. | ||
5396 | */ | ||
5397 | static int sbpcd_open(struct cdrom_device_info *cdi, int purpose) | ||
5398 | { | ||
5399 | struct sbpcd_drive *p = cdi->handle; | ||
5400 | |||
5401 | down(&ioctl_read_sem); | ||
5402 | switch_drive(p); | ||
5403 | |||
5404 | /* | ||
5405 | * try to keep an "open" counter here and lock the door if 0->1. | ||
5406 | */ | ||
5407 | msg(DBG_LCK,"open_count: %d -> %d\n", | ||
5408 | current_drive->open_count,current_drive->open_count+1); | ||
5409 | if (++current_drive->open_count<=1) | ||
5410 | { | ||
5411 | int i; | ||
5412 | i=LockDoor(); | ||
5413 | current_drive->open_count=1; | ||
5414 | if (famT_drive) msg(DBG_TEA,"sbpcd_open: before i=DiskInfo();.\n"); | ||
5415 | i=DiskInfo(); | ||
5416 | if (famT_drive) msg(DBG_TEA,"sbpcd_open: after i=DiskInfo();.\n"); | ||
5417 | if ((current_drive->ored_ctl_adr&0x40)==0) | ||
5418 | { | ||
5419 | msg(DBG_INF,"CD contains no data tracks.\n"); | ||
5420 | #ifdef SAFE_MIXED | ||
5421 | current_drive->has_data=0; | ||
5422 | #endif /* SAFE_MIXED */ | ||
5423 | } | ||
5424 | #ifdef SAFE_MIXED | ||
5425 | else if (current_drive->has_data<1) current_drive->has_data=1; | ||
5426 | #endif /* SAFE_MIXED */ | ||
5427 | } | ||
5428 | if (!st_spinning) cc_SpinUp(); | ||
5429 | RETURN_UP(0); | ||
5430 | } | ||
5431 | /*==========================================================================*/ | ||
5432 | /* | ||
5433 | * On close, we flush all sbp blocks from the buffer cache. | ||
5434 | */ | ||
5435 | static void sbpcd_release(struct cdrom_device_info * cdi) | ||
5436 | { | ||
5437 | struct sbpcd_drive *p = cdi->handle; | ||
5438 | |||
5439 | if (p->drv_id==-1) { | ||
5440 | msg(DBG_INF, "release: bad device: %s\n", cdi->name); | ||
5441 | return; | ||
5442 | } | ||
5443 | down(&ioctl_read_sem); | ||
5444 | switch_drive(p); | ||
5445 | /* | ||
5446 | * try to keep an "open" counter here and unlock the door if 1->0. | ||
5447 | */ | ||
5448 | msg(DBG_LCK,"open_count: %d -> %d\n", | ||
5449 | p->open_count,p->open_count-1); | ||
5450 | if (p->open_count>-2) /* CDROMEJECT may have been done */ | ||
5451 | { | ||
5452 | if (--p->open_count<=0) | ||
5453 | { | ||
5454 | p->sbp_first_frame=p->sbp_last_frame=-1; | ||
5455 | if (p->audio_state!=audio_playing) | ||
5456 | if (p->f_eject) cc_SpinDown(); | ||
5457 | p->diskstate_flags &= ~cd_size_bit; | ||
5458 | p->open_count=0; | ||
5459 | #ifdef SAFE_MIXED | ||
5460 | p->has_data=0; | ||
5461 | #endif /* SAFE_MIXED */ | ||
5462 | } | ||
5463 | } | ||
5464 | up(&ioctl_read_sem); | ||
5465 | return ; | ||
5466 | } | ||
5467 | /*==========================================================================*/ | ||
5468 | /* | ||
5469 | * | ||
5470 | */ | ||
5471 | static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr); | ||
5472 | static struct cdrom_device_ops sbpcd_dops = { | ||
5473 | .open = sbpcd_open, | ||
5474 | .release = sbpcd_release, | ||
5475 | .drive_status = sbpcd_drive_status, | ||
5476 | .media_changed = sbpcd_media_changed, | ||
5477 | .tray_move = sbpcd_tray_move, | ||
5478 | .lock_door = sbpcd_lock_door, | ||
5479 | .select_speed = sbpcd_select_speed, | ||
5480 | .get_last_session = sbpcd_get_last_session, | ||
5481 | .get_mcn = sbpcd_get_mcn, | ||
5482 | .reset = sbpcd_reset, | ||
5483 | .audio_ioctl = sbpcd_audio_ioctl, | ||
5484 | .dev_ioctl = sbpcd_dev_ioctl, | ||
5485 | .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | | ||
5486 | CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | | ||
5487 | CDC_MCN | CDC_PLAY_AUDIO | CDC_IOCTLS, | ||
5488 | .n_minors = 1, | ||
5489 | }; | ||
5490 | |||
5491 | /*==========================================================================*/ | ||
5492 | /* | ||
5493 | * accept "kernel command line" parameters | ||
5494 | * (suggested by Peter MacDonald with SLS 1.03) | ||
5495 | * | ||
5496 | * This is only implemented for the first controller. Should be enough to | ||
5497 | * allow installing with a "strange" distribution kernel. | ||
5498 | * | ||
5499 | * use: tell LILO: | ||
5500 | * sbpcd=0x230,SoundBlaster | ||
5501 | * or | ||
5502 | * sbpcd=0x300,LaserMate | ||
5503 | * or | ||
5504 | * sbpcd=0x338,SoundScape | ||
5505 | * or | ||
5506 | * sbpcd=0x2C0,Teac16bit | ||
5507 | * | ||
5508 | * (upper/lower case sensitive here - but all-lowercase is ok!!!). | ||
5509 | * | ||
5510 | * the address value has to be the CDROM PORT ADDRESS - | ||
5511 | * not the soundcard base address. | ||
5512 | * For the SPEA/SoundScape setup, DO NOT specify the "configuration port" | ||
5513 | * address, but the address which is really used for the CDROM (usually 8 | ||
5514 | * bytes above). | ||
5515 | * | ||
5516 | */ | ||
5517 | |||
5518 | int sbpcd_setup(char *s) | ||
5519 | { | ||
5520 | #ifndef MODULE | ||
5521 | int p[4]; | ||
5522 | (void)get_options(s, ARRAY_SIZE(p), p); | ||
5523 | setup_done++; | ||
5524 | msg(DBG_INI,"sbpcd_setup called with %04X,%s\n",p[1], s); | ||
5525 | sbpro_type=0; /* default: "LaserMate" */ | ||
5526 | if (p[0]>1) sbpro_type=p[2]; | ||
5527 | else if (!strcmp(s,str_sb)) sbpro_type=1; | ||
5528 | else if (!strcmp(s,str_sb_l)) sbpro_type=1; | ||
5529 | else if (!strcmp(s,str_sp)) sbpro_type=2; | ||
5530 | else if (!strcmp(s,str_sp_l)) sbpro_type=2; | ||
5531 | else if (!strcmp(s,str_ss)) sbpro_type=2; | ||
5532 | else if (!strcmp(s,str_ss_l)) sbpro_type=2; | ||
5533 | else if (!strcmp(s,str_t16)) sbpro_type=3; | ||
5534 | else if (!strcmp(s,str_t16_l)) sbpro_type=3; | ||
5535 | if (p[0]>0) sbpcd_ioaddr=p[1]; | ||
5536 | if (p[0]>2) max_drives=p[3]; | ||
5537 | #else | ||
5538 | sbpcd_ioaddr = sbpcd[0]; | ||
5539 | sbpro_type = sbpcd[1]; | ||
5540 | #endif | ||
5541 | |||
5542 | CDo_command=sbpcd_ioaddr; | ||
5543 | CDi_info=sbpcd_ioaddr; | ||
5544 | CDi_status=sbpcd_ioaddr+1; | ||
5545 | CDo_sel_i_d=sbpcd_ioaddr+1; | ||
5546 | CDo_reset=sbpcd_ioaddr+2; | ||
5547 | CDo_enable=sbpcd_ioaddr+3; | ||
5548 | f_16bit=0; | ||
5549 | if ((sbpro_type==1)||(sbpro_type==3)) | ||
5550 | { | ||
5551 | CDi_data=sbpcd_ioaddr; | ||
5552 | if (sbpro_type==3) | ||
5553 | { | ||
5554 | f_16bit=1; | ||
5555 | sbpro_type=1; | ||
5556 | } | ||
5557 | } | ||
5558 | else CDi_data=sbpcd_ioaddr+2; | ||
5559 | |||
5560 | return 1; | ||
5561 | } | ||
5562 | |||
5563 | __setup("sbpcd=", sbpcd_setup); | ||
5564 | |||
5565 | |||
5566 | /*==========================================================================*/ | ||
5567 | /* | ||
5568 | * Sequoia S-1000 CD-ROM Interface Configuration | ||
5569 | * as used within SPEA Media FX, Ensonic SoundScape and some Reveal cards | ||
5570 | * The soundcard has to get jumpered for the interface type "Panasonic" | ||
5571 | * (not Sony or Mitsumi) and to get soft-configured for | ||
5572 | * -> configuration port address | ||
5573 | * -> CDROM port offset (num_ports): has to be 8 here. Possibly this | ||
5574 | * offset value determines the interface type (none, Panasonic, | ||
5575 | * Mitsumi, Sony). | ||
5576 | * The interface uses a configuration port (0x320, 0x330, 0x340, 0x350) | ||
5577 | * some bytes below the real CDROM address. | ||
5578 | * | ||
5579 | * For the Panasonic style (LaserMate) interface and the configuration | ||
5580 | * port 0x330, we have to use an offset of 8; so, the real CDROM port | ||
5581 | * address is 0x338. | ||
5582 | */ | ||
5583 | static int __init config_spea(void) | ||
5584 | { | ||
5585 | /* | ||
5586 | * base address offset between configuration port and CDROM port, | ||
5587 | * this probably defines the interface type | ||
5588 | * 2 (type=??): 0x00 | ||
5589 | * 8 (type=LaserMate):0x10 | ||
5590 | * 16 (type=??):0x20 | ||
5591 | * 32 (type=??):0x30 | ||
5592 | */ | ||
5593 | int n_ports=0x10; | ||
5594 | |||
5595 | int irq_number=0; /* off:0x00, 2/9:0x01, 7:0x03, 12:0x05, 15:0x07 */ | ||
5596 | int dma_channel=0; /* off: 0x00, 0:0x08, 1:0x18, 3:0x38, 5:0x58, 6:0x68 */ | ||
5597 | int dack_polarity=0; /* L:0x00, H:0x80 */ | ||
5598 | int drq_polarity=0x40; /* L:0x00, H:0x40 */ | ||
5599 | int i; | ||
5600 | |||
5601 | #define SPEA_REG_1 sbpcd_ioaddr-0x08+4 | ||
5602 | #define SPEA_REG_2 sbpcd_ioaddr-0x08+5 | ||
5603 | |||
5604 | OUT(SPEA_REG_1,0xFF); | ||
5605 | i=inb(SPEA_REG_1); | ||
5606 | if (i!=0x0F) | ||
5607 | { | ||
5608 | msg(DBG_SEQ,"no SPEA interface at %04X present.\n", sbpcd_ioaddr); | ||
5609 | return (-1); /* no interface found */ | ||
5610 | } | ||
5611 | OUT(SPEA_REG_1,0x04); | ||
5612 | OUT(SPEA_REG_2,0xC0); | ||
5613 | |||
5614 | OUT(SPEA_REG_1,0x05); | ||
5615 | OUT(SPEA_REG_2,0x10|drq_polarity|dack_polarity); | ||
5616 | |||
5617 | #if 1 | ||
5618 | #define SPEA_PATTERN 0x80 | ||
5619 | #else | ||
5620 | #define SPEA_PATTERN 0x00 | ||
5621 | #endif | ||
5622 | OUT(SPEA_REG_1,0x06); | ||
5623 | OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN); | ||
5624 | OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN); | ||
5625 | |||
5626 | OUT(SPEA_REG_1,0x09); | ||
5627 | i=(inb(SPEA_REG_2)&0xCF)|n_ports; | ||
5628 | OUT(SPEA_REG_2,i); | ||
5629 | |||
5630 | sbpro_type = 0; /* acts like a LaserMate interface now */ | ||
5631 | msg(DBG_SEQ,"found SoundScape interface at %04X.\n", sbpcd_ioaddr); | ||
5632 | return (0); | ||
5633 | } | ||
5634 | |||
5635 | /*==========================================================================*/ | ||
5636 | /* | ||
5637 | * Test for presence of drive and initialize it. | ||
5638 | * Called once at boot or load time. | ||
5639 | */ | ||
5640 | |||
5641 | /* FIXME: cleanups after failed allocations are too ugly for words */ | ||
5642 | #ifdef MODULE | ||
5643 | int __init __sbpcd_init(void) | ||
5644 | #else | ||
5645 | int __init sbpcd_init(void) | ||
5646 | #endif | ||
5647 | { | ||
5648 | int i=0, j=0; | ||
5649 | int addr[2]={1, CDROM_PORT}; | ||
5650 | int port_index; | ||
5651 | |||
5652 | sti(); | ||
5653 | |||
5654 | msg(DBG_INF,"sbpcd.c %s\n", VERSION); | ||
5655 | #ifndef MODULE | ||
5656 | #if DISTRIBUTION | ||
5657 | if (!setup_done) | ||
5658 | { | ||
5659 | msg(DBG_INF,"Looking for Matsushita/Panasonic, CreativeLabs, Longshine, TEAC CD-ROM drives\n"); | ||
5660 | msg(DBG_INF,"= = = = = = = = = = W A R N I N G = = = = = = = = = =\n"); | ||
5661 | msg(DBG_INF,"Auto-Probing can cause a hang (f.e. touching an NE2000 card).\n"); | ||
5662 | msg(DBG_INF,"If that happens, you have to reboot and use the\n"); | ||
5663 | msg(DBG_INF,"LILO (kernel) command line feature like:\n"); | ||
5664 | msg(DBG_INF," LILO boot: ... sbpcd=0x230,SoundBlaster\n"); | ||
5665 | msg(DBG_INF,"or like:\n"); | ||
5666 | msg(DBG_INF," LILO boot: ... sbpcd=0x300,LaserMate\n"); | ||
5667 | msg(DBG_INF,"or like:\n"); | ||
5668 | msg(DBG_INF," LILO boot: ... sbpcd=0x338,SoundScape\n"); | ||
5669 | msg(DBG_INF,"with your REAL address.\n"); | ||
5670 | msg(DBG_INF,"= = = = = = = = = = END of WARNING = = = = = == = = =\n"); | ||
5671 | } | ||
5672 | #endif /* DISTRIBUTION */ | ||
5673 | sbpcd[0]=sbpcd_ioaddr; /* possibly changed by kernel command line */ | ||
5674 | sbpcd[1]=sbpro_type; /* possibly changed by kernel command line */ | ||
5675 | #endif /* MODULE */ | ||
5676 | |||
5677 | for (port_index=0;port_index<NUM_PROBE;port_index+=2) | ||
5678 | { | ||
5679 | addr[1]=sbpcd[port_index]; | ||
5680 | if (addr[1]==0) break; | ||
5681 | if (check_region(addr[1],4)) | ||
5682 | { | ||
5683 | msg(DBG_INF,"check_region: %03X is not free.\n",addr[1]); | ||
5684 | continue; | ||
5685 | } | ||
5686 | if (sbpcd[port_index+1]==2) type=str_sp; | ||
5687 | else if (sbpcd[port_index+1]==1) type=str_sb; | ||
5688 | else if (sbpcd[port_index+1]==3) type=str_t16; | ||
5689 | else type=str_lm; | ||
5690 | sbpcd_setup((char *)type); | ||
5691 | #if DISTRIBUTION | ||
5692 | msg(DBG_INF,"Scanning 0x%X (%s)...\n", CDo_command, type); | ||
5693 | #endif /* DISTRIBUTION */ | ||
5694 | if (sbpcd[port_index+1]==2) | ||
5695 | { | ||
5696 | i=config_spea(); | ||
5697 | if (i<0) continue; | ||
5698 | } | ||
5699 | #ifdef PATH_CHECK | ||
5700 | if (check_card(addr[1])) continue; | ||
5701 | #endif /* PATH_CHECK */ | ||
5702 | i=check_drives(); | ||
5703 | msg(DBG_INI,"check_drives done.\n"); | ||
5704 | if (i>=0) break; /* drive found */ | ||
5705 | } /* end of cycling through the set of possible I/O port addresses */ | ||
5706 | |||
5707 | if (ndrives==0) | ||
5708 | { | ||
5709 | msg(DBG_INF, "No drive found.\n"); | ||
5710 | #ifdef MODULE | ||
5711 | return -EIO; | ||
5712 | #else | ||
5713 | goto init_done; | ||
5714 | #endif /* MODULE */ | ||
5715 | } | ||
5716 | |||
5717 | if (port_index>0) | ||
5718 | { | ||
5719 | msg(DBG_INF, "You should read Documentation/cdrom/sbpcd\n"); | ||
5720 | msg(DBG_INF, "and then configure sbpcd.h for your hardware.\n"); | ||
5721 | } | ||
5722 | check_datarate(); | ||
5723 | msg(DBG_INI,"check_datarate done.\n"); | ||
5724 | |||
5725 | for (j=0;j<NR_SBPCD;j++) | ||
5726 | { | ||
5727 | struct sbpcd_drive *p = D_S + j; | ||
5728 | if (p->drv_id==-1) | ||
5729 | continue; | ||
5730 | switch_drive(p); | ||
5731 | #if 1 | ||
5732 | if (!famL_drive) cc_DriveReset(); | ||
5733 | #endif | ||
5734 | if (!st_spinning) cc_SpinUp(); | ||
5735 | p->sbp_first_frame = -1; /* First frame in buffer */ | ||
5736 | p->sbp_last_frame = -1; /* Last frame in buffer */ | ||
5737 | p->sbp_read_frames = 0; /* Number of frames being read to buffer */ | ||
5738 | p->sbp_current = 0; /* Frame being currently read */ | ||
5739 | p->CD_changed=1; | ||
5740 | p->frame_size=CD_FRAMESIZE; | ||
5741 | p->f_eject=0; | ||
5742 | #if EJECT | ||
5743 | if (!fam0_drive) p->f_eject=1; | ||
5744 | #endif /* EJECT */ | ||
5745 | cc_ReadStatus(); | ||
5746 | i=ResponseStatus(); /* returns orig. status or p_busy_new */ | ||
5747 | if (famT_drive) i=ResponseStatus(); /* returns orig. status or p_busy_new */ | ||
5748 | if (i<0) | ||
5749 | { | ||
5750 | if (i!=-402) | ||
5751 | msg(DBG_INF,"init: ResponseStatus returns %d.\n",i); | ||
5752 | } | ||
5753 | else | ||
5754 | { | ||
5755 | if (st_check) | ||
5756 | { | ||
5757 | i=cc_ReadError(); | ||
5758 | msg(DBG_INI,"init: cc_ReadError returns %d\n",i); | ||
5759 | } | ||
5760 | } | ||
5761 | msg(DBG_INI,"init: first GetStatus: %d\n",i); | ||
5762 | msg(DBG_LCS,"init: first GetStatus: error_byte=%d\n", | ||
5763 | p->error_byte); | ||
5764 | if (p->error_byte==aud_12) | ||
5765 | { | ||
5766 | timeout=jiffies+2*HZ; | ||
5767 | do | ||
5768 | { | ||
5769 | i=GetStatus(); | ||
5770 | msg(DBG_INI,"init: second GetStatus: %02X\n",i); | ||
5771 | msg(DBG_LCS, | ||
5772 | "init: second GetStatus: error_byte=%d\n", | ||
5773 | p->error_byte); | ||
5774 | if (i<0) break; | ||
5775 | if (!st_caddy_in) break; | ||
5776 | } | ||
5777 | while ((!st_diskok)||time_after(jiffies, timeout)); | ||
5778 | } | ||
5779 | i=SetSpeed(); | ||
5780 | if (i>=0) p->CD_changed=1; | ||
5781 | } | ||
5782 | |||
5783 | if (!request_region(CDo_command,4,major_name)) | ||
5784 | { | ||
5785 | printk(KERN_WARNING "sbpcd: Unable to request region 0x%x\n", CDo_command); | ||
5786 | return -EIO; | ||
5787 | } | ||
5788 | |||
5789 | /* | ||
5790 | * Turn on the CD audio channels. | ||
5791 | * The addresses are obtained from SOUND_BASE (see sbpcd.h). | ||
5792 | */ | ||
5793 | #if SOUND_BASE | ||
5794 | OUT(MIXER_addr,MIXER_CD_Volume); /* select SB Pro mixer register */ | ||
5795 | OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */ | ||
5796 | #endif /* SOUND_BASE */ | ||
5797 | |||
5798 | if (register_blkdev(MAJOR_NR, major_name)) { | ||
5799 | #ifdef MODULE | ||
5800 | return -EIO; | ||
5801 | #else | ||
5802 | goto init_done; | ||
5803 | #endif /* MODULE */ | ||
5804 | } | ||
5805 | |||
5806 | /* | ||
5807 | * init error handling is broken beyond belief in this driver... | ||
5808 | */ | ||
5809 | sbpcd_queue = blk_init_queue(do_sbpcd_request, &sbpcd_lock); | ||
5810 | if (!sbpcd_queue) { | ||
5811 | release_region(CDo_command,4); | ||
5812 | unregister_blkdev(MAJOR_NR, major_name); | ||
5813 | return -ENOMEM; | ||
5814 | } | ||
5815 | |||
5816 | devfs_mk_dir("sbp"); | ||
5817 | |||
5818 | for (j=0;j<NR_SBPCD;j++) | ||
5819 | { | ||
5820 | struct cdrom_device_info * sbpcd_infop; | ||
5821 | struct gendisk *disk; | ||
5822 | struct sbpcd_drive *p = D_S + j; | ||
5823 | |||
5824 | if (p->drv_id==-1) continue; | ||
5825 | switch_drive(p); | ||
5826 | #ifdef SAFE_MIXED | ||
5827 | p->has_data=0; | ||
5828 | #endif /* SAFE_MIXED */ | ||
5829 | /* | ||
5830 | * allocate memory for the frame buffers | ||
5831 | */ | ||
5832 | p->aud_buf=NULL; | ||
5833 | p->sbp_audsiz=0; | ||
5834 | p->sbp_bufsiz=buffers; | ||
5835 | if (p->drv_type&drv_fam1) | ||
5836 | if (READ_AUDIO>0) | ||
5837 | p->sbp_audsiz = READ_AUDIO; | ||
5838 | p->sbp_buf=(u_char *) vmalloc(buffers*CD_FRAMESIZE); | ||
5839 | if (!p->sbp_buf) { | ||
5840 | msg(DBG_INF,"data buffer (%d frames) not available.\n", | ||
5841 | buffers); | ||
5842 | if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL)) | ||
5843 | { | ||
5844 | printk("Can't unregister %s\n", major_name); | ||
5845 | } | ||
5846 | release_region(CDo_command,4); | ||
5847 | blk_cleanup_queue(sbpcd_queue); | ||
5848 | return -EIO; | ||
5849 | } | ||
5850 | #ifdef MODULE | ||
5851 | msg(DBG_INF,"data buffer size: %d frames.\n",buffers); | ||
5852 | #endif /* MODULE */ | ||
5853 | if (p->sbp_audsiz>0) | ||
5854 | { | ||
5855 | p->aud_buf=(u_char *) vmalloc(p->sbp_audsiz*CD_FRAMESIZE_RAW); | ||
5856 | if (p->aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.\n",p->sbp_audsiz); | ||
5857 | else msg(DBG_INF,"audio buffer size: %d frames.\n",p->sbp_audsiz); | ||
5858 | } | ||
5859 | sbpcd_infop = vmalloc(sizeof (struct cdrom_device_info)); | ||
5860 | if (sbpcd_infop == NULL) | ||
5861 | { | ||
5862 | release_region(CDo_command,4); | ||
5863 | blk_cleanup_queue(sbpcd_queue); | ||
5864 | return -ENOMEM; | ||
5865 | } | ||
5866 | memset(sbpcd_infop, 0, sizeof(struct cdrom_device_info)); | ||
5867 | sbpcd_infop->ops = &sbpcd_dops; | ||
5868 | sbpcd_infop->speed = 2; | ||
5869 | sbpcd_infop->capacity = 1; | ||
5870 | sprintf(sbpcd_infop->name, "sbpcd%d", j); | ||
5871 | sbpcd_infop->handle = p; | ||
5872 | p->sbpcd_infop = sbpcd_infop; | ||
5873 | disk = alloc_disk(1); | ||
5874 | disk->major = MAJOR_NR; | ||
5875 | disk->first_minor = j; | ||
5876 | disk->fops = &sbpcd_bdops; | ||
5877 | strcpy(disk->disk_name, sbpcd_infop->name); | ||
5878 | disk->flags = GENHD_FL_CD; | ||
5879 | sprintf(disk->devfs_name, "sbp/c0t%d", p->drv_id); | ||
5880 | p->disk = disk; | ||
5881 | if (register_cdrom(sbpcd_infop)) | ||
5882 | { | ||
5883 | printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n"); | ||
5884 | } | ||
5885 | disk->private_data = p; | ||
5886 | disk->queue = sbpcd_queue; | ||
5887 | add_disk(disk); | ||
5888 | } | ||
5889 | blk_queue_hardsect_size(sbpcd_queue, CD_FRAMESIZE); | ||
5890 | |||
5891 | #ifndef MODULE | ||
5892 | init_done: | ||
5893 | #endif | ||
5894 | return 0; | ||
5895 | } | ||
5896 | /*==========================================================================*/ | ||
5897 | #ifdef MODULE | ||
5898 | void sbpcd_exit(void) | ||
5899 | { | ||
5900 | int j; | ||
5901 | |||
5902 | if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL)) | ||
5903 | { | ||
5904 | msg(DBG_INF, "What's that: can't unregister %s.\n", major_name); | ||
5905 | return; | ||
5906 | } | ||
5907 | release_region(CDo_command,4); | ||
5908 | blk_cleanup_queue(sbpcd_queue); | ||
5909 | for (j=0;j<NR_SBPCD;j++) | ||
5910 | { | ||
5911 | if (D_S[j].drv_id==-1) continue; | ||
5912 | del_gendisk(D_S[j].disk); | ||
5913 | put_disk(D_S[j].disk); | ||
5914 | devfs_remove("sbp/c0t%d", j); | ||
5915 | vfree(D_S[j].sbp_buf); | ||
5916 | if (D_S[j].sbp_audsiz>0) vfree(D_S[j].aud_buf); | ||
5917 | if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL)) | ||
5918 | { | ||
5919 | msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name); | ||
5920 | return; | ||
5921 | } | ||
5922 | vfree(D_S[j].sbpcd_infop); | ||
5923 | } | ||
5924 | devfs_remove("sbp"); | ||
5925 | msg(DBG_INF, "%s module released.\n", major_name); | ||
5926 | } | ||
5927 | |||
5928 | |||
5929 | module_init(__sbpcd_init) /*HACK!*/; | ||
5930 | module_exit(sbpcd_exit); | ||
5931 | |||
5932 | |||
5933 | #endif /* MODULE */ | ||
5934 | static int sbpcd_media_changed(struct cdrom_device_info *cdi, int disc_nr) | ||
5935 | { | ||
5936 | struct sbpcd_drive *p = cdi->handle; | ||
5937 | msg(DBG_CHK,"media_check (%s) called\n", cdi->name); | ||
5938 | |||
5939 | if (p->CD_changed==0xFF) | ||
5940 | { | ||
5941 | p->CD_changed=0; | ||
5942 | msg(DBG_CHK,"medium changed (drive %s)\n", cdi->name); | ||
5943 | current_drive->diskstate_flags &= ~toc_bit; | ||
5944 | /* we *don't* need invalidate here, it's done by caller */ | ||
5945 | current_drive->diskstate_flags &= ~cd_size_bit; | ||
5946 | #ifdef SAFE_MIXED | ||
5947 | current_drive->has_data=0; | ||
5948 | #endif /* SAFE_MIXED */ | ||
5949 | |||
5950 | return (1); | ||
5951 | } | ||
5952 | else | ||
5953 | return (0); | ||
5954 | } | ||
5955 | |||
5956 | MODULE_LICENSE("GPL"); | ||
5957 | /* FIXME: Old modules.conf claims MATSUSHITA_CDROM2_MAJOR and CDROM3, but | ||
5958 | AFAICT this doesn't support those majors, so why? --RR 30 Jul 2003 */ | ||
5959 | MODULE_ALIAS_BLOCKDEV_MAJOR(MATSUSHITA_CDROM_MAJOR); | ||
5960 | |||
5961 | /*==========================================================================*/ | ||
5962 | /* | ||
5963 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
5964 | * Emacs will notice this stuff at the end of the file and automatically | ||
5965 | * adjust the settings for this buffer only. This must remain at the end | ||
5966 | * of the file. | ||
5967 | * --------------------------------------------------------------------------- | ||
5968 | * Local variables: | ||
5969 | * c-indent-level: 8 | ||
5970 | * c-brace-imaginary-offset: 0 | ||
5971 | * c-brace-offset: -8 | ||
5972 | * c-argdecl-indent: 8 | ||
5973 | * c-label-offset: -8 | ||
5974 | * c-continued-statement-offset: 8 | ||
5975 | * c-continued-brace-offset: 0 | ||
5976 | * End: | ||
5977 | */ | ||
5978 | |||