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