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