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