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