diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/cdrom/sbpcd.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/cdrom/sbpcd.c')
-rw-r--r-- | drivers/cdrom/sbpcd.c | 5978 |
1 files changed, 5978 insertions, 0 deletions
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c new file mode 100644 index 00000000000..fc2c433f6a2 --- /dev/null +++ b/drivers/cdrom/sbpcd.c @@ -0,0 +1,5978 @@ +/* + * sbpcd.c CD-ROM device driver for the whole family of traditional, + * non-ATAPI IDE-style Matsushita/Panasonic CR-5xx drives. + * Works with SoundBlaster compatible cards and with "no-sound" + * interface cards like Lasermate, Panasonic CI-101P, Teac, ... + * Also for the Longshine LCS-7260 drive. + * Also for the IBM "External ISA CD-Rom" drive. + * Also for the CreativeLabs CD200 drive. + * Also for the TEAC CD-55A drive. + * Also for the ECS-AT "Vertos 100" drive. + * Not for Sanyo drives (but for the H94A, sjcd is there...). + * Not for any other Funai drives than the CD200 types (sometimes + * labelled E2550UA or MK4015 or 2800F). + */ + +#define VERSION "v4.63 Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000" + +/* Copyright (C) 1993, 1994, 1995 Eberhard Moenkeberg <emoenke@gwdg.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * You should have received a copy of the GNU General Public License + * (for example /usr/src/linux/COPYING); if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * If you change this software, you should mail a .diff file with some + * description lines to emoenke@gwdg.de. I want to know about it. + * + * If you are the editor of a Linux CD, you should enable sbpcd.c within + * your boot floppy kernel and send me one of your CDs for free. + * + * If you would like to port the driver to an other operating system (f.e. + * FreeBSD or NetBSD) or use it as an information source, you shall not be + * restricted by the GPL under the following conditions: + * a) the source code of your work is freely available + * b) my part of the work gets mentioned at all places where your + * authorship gets mentioned + * c) I receive a copy of your code together with a full installation + * package of your operating system for free. + * + * + * VERSION HISTORY + * + * 0.1 initial release, April/May 93, after mcd.c (Martin Harriss) + * + * 0.2 thek "repeat:"-loop in do_sbpcd_request did not check for + * end-of-request_queue (resulting in kernel panic). + * Flow control seems stable, but throughput is not better. + * + * 0.3 interrupt locking totally eliminated (maybe "inb" and "outb" + * are still locking) - 0.2 made keyboard-type-ahead losses. + * check_sbpcd_media_change added (to use by isofs/inode.c) + * - but it detects almost nothing. + * + * 0.4 use MAJOR 25 definitely. + * Almost total re-design to support double-speed drives and + * "naked" (no sound) interface cards ("LaserMate" interface type). + * Flow control should be exact now. + * Don't occupy the SbPro IRQ line (not needed either); will + * live together with Hannu Savolainen's sndkit now. + * Speeded up data transfer to 150 kB/sec, with help from Kai + * Makisara, the "provider" of the "mt" tape utility. + * Give "SpinUp" command if necessary. + * First steps to support up to 4 drives (but currently only one). + * Implemented audio capabilities - workman should work, xcdplayer + * gives some problems. + * This version is still consuming too much CPU time, and + * sleeping still has to be worked on. + * During "long" implied seeks, it seems possible that a + * ReadStatus command gets ignored. That gives the message + * "ResponseStatus timed out" (happens about 6 times here during + * a "ls -alR" of the YGGDRASIL LGX-Beta CD). Such a case is + * handled without data error, but it should get done better. + * + * 0.5 Free CPU during waits (again with help from Kai Makisara). + * Made it work together with the LILO/kernel setup standard. + * Included auto-probing code, as suggested by YGGDRASIL. + * Formal redesign to add DDI debugging. + * There are still flaws in IOCTL (workman with double speed drive). + * + * 1.0 Added support for all drive IDs (0...3, no longer only 0) + * and up to 4 drives on one controller. + * Added "#define MANY_SESSION" for "old" multi session CDs. + * + * 1.1 Do SpinUp for new drives, too. + * Revised for clean compile under "old" kernels (0.99pl9). + * + * 1.2 Found the "workman with double-speed drive" bug: use the driver's + * audio_state, not what the drive is reporting with ReadSubQ. + * + * 1.3 Minor cleanups. + * Refinements regarding Workman. + * + * 1.4 Read XA disks (PhotoCDs) with "old" drives, too (but only the first + * session - no chance to fully access a "multi-session" CD). + * This currently still is too slow (50 kB/sec) - but possibly + * the old drives won't do it faster. + * Implemented "door (un)lock" for new drives (still does not work + * as wanted - no lock possible after an unlock). + * Added some debugging printout for the UPC/EAN code - but my drives + * return only zeroes. Is there no UPC/EAN code written? + * + * 1.5 Laborate with UPC/EAN code (not better yet). + * Adapt to kernel 1.1.8 change (have to explicitly include + * <linux/string.h> now). + * + * 1.6 Trying to read audio frames as data. Impossible with the current + * drive firmware levels, as it seems. Awaiting any hint. ;-) + * Changed "door unlock": repeat it until success. + * Changed CDROMSTOP routine (stop somewhat "softer" so that Workman + * won't get confused). + * Added a third interface type: Sequoia S-1000, as used with the SPEA + * Media FX sound card. This interface (usable for Sony and Mitsumi + * drives, too) needs a special configuration setup and behaves like a + * LaserMate type after that. Still experimental - I do not have such + * an interface. + * Use the "variable BLOCK_SIZE" feature (2048). But it does only work + * if you give the mount option "block=2048". + * The media_check routine is currently disabled; now that it gets + * called as it should I fear it must get synchronized for not to + * disturb the normal driver's activity. + * + * 2.0 Version number bumped - two reasons: + * - reading audio tracks as data works now with CR-562 and CR-563. We + * currently do it by an IOCTL (yet has to get standardized), one frame + * at a time; that is pretty slow. But it works. + * - we are maintaining now up to 4 interfaces (each up to 4 drives): + * did it the easy way - a different MAJOR (25, 26, ...) and a different + * copy of the driver (sbpcd.c, sbpcd2.c, sbpcd3.c, sbpcd4.c - only + * distinguished by the value of SBPCD_ISSUE and the driver's name), + * and a common sbpcd.h file. + * Bettered the "ReadCapacity error" problem with old CR-52x drives (the + * drives sometimes need a manual "eject/insert" before work): just + * reset the drive and do again. Needs lots of resets here and sometimes + * that does not cure, so this can't be the solution. + * + * 2.1 Found bug with multisession CDs (accessing frame 16). + * "read audio" works now with address type CDROM_MSF, too. + * Bigger audio frame buffer: allows reading max. 4 frames at time; this + * gives a significant speedup, but reading more than one frame at once + * gives missing chunks at each single frame boundary. + * + * 2.2 Kernel interface cleanups: timers, init, setup, media check. + * + * 2.3 Let "door lock" and "eject" live together. + * Implemented "close tray" (done automatically during open). + * + * 2.4 Use different names for device registering. + * + * 2.5 Added "#if EJECT" code (default: enabled) to automatically eject + * the tray during last call to "sbpcd_release". + * Added "#if JUKEBOX" code (default: disabled) to automatically eject + * the tray during call to "sbpcd_open" if no disk is in. + * Turn on the CD volume of "compatible" sound cards, too; just define + * SOUND_BASE (in sbpcd.h) accordingly (default: disabled). + * + * 2.6 Nothing new. + * + * 2.7 Added CDROMEJECT_SW ioctl to set the "EJECT" behavior on the fly: + * 0 disables, 1 enables auto-ejecting. Useful to keep the tray in + * during shutdown. + * + * 2.8 Added first support (still BETA, I need feedback or a drive) for + * the Longshine LCS-7260 drives. They appear as double-speed drives + * using the "old" command scheme, extended by tray control and door + * lock functions. + * Found (and fixed preliminary) a flaw with some multisession CDs: we + * have to re-direct not only the accesses to frame 16 (the isofs + * routines drive it up to max. 100), but also those to the continuation + * (repetition) frames (as far as they exist - currently set fix as + * 16..20). + * Changed default of the "JUKEBOX" define. If you use this default, + * your tray will eject if you try to mount without a disk in. Next + * mount command will insert the tray - so, just fill in a disk. ;-) + * + * 2.9 Fulfilled the Longshine LCS-7260 support; with great help and + * experiments by Serge Robyns. + * First attempts to support the TEAC CD-55A drives; but still not + * usable yet. + * Implemented the CDROMMULTISESSION ioctl; this is an attempt to handle + * multi session CDs more "transparent" (redirection handling has to be + * done within the isofs routines, and only for the special purpose of + * obtaining the "right" volume descriptor; accesses to the raw device + * should not get redirected). + * + * 3.0 Just a "normal" increment, with some provisions to do it better. ;-) + * Introduced "#define READ_AUDIO" to specify the maximum number of + * audio frames to grab with one request. This defines a buffer size + * within kernel space; a value of 0 will reserve no such space and + * disable the CDROMREADAUDIO ioctl. A value of 75 enables the reading + * of a whole second with one command, but will use a buffer of more + * than 172 kB. + * Started CD200 support. Drive detection should work, but nothing + * more. + * + * 3.1 Working to support the CD200 and the Teac CD-55A drives. + * AT-BUS style device numbering no longer used: use SCSI style now. + * So, the first "found" device has MINOR 0, regardless of the + * jumpered drive ID. This implies modifications to the /dev/sbpcd* + * entries for some people, but will help the DAU (german TLA, english: + * "newbie", maybe ;-) to install his "first" system from a CD. + * + * 3.2 Still testing with CD200 and CD-55A drives. + * + * 3.3 Working with CD200 support. + * + * 3.4 Auto-probing stops if an address of 0 is seen (to be entered with + * the kernel command line). + * Made the driver "loadable". If used as a module, "audio copy" is + * disabled, and the internal read ahead data buffer has a reduced size + * of 4 kB; so, throughput may be reduced a little bit with slow CPUs. + * + * 3.5 Provisions to handle weird photoCDs which have an interrupted + * "formatting" immediately after the last frames of some files: simply + * never "read ahead" with MultiSession CDs. By this, CPU usage may be + * increased with those CDs, and there may be a loss in speed. + * Re-structured the messaging system. + * The "loadable" version no longer has a limited READ_AUDIO buffer + * size. + * Removed "MANY_SESSION" handling for "old" multi session CDs. + * Added "private" IOCTLs CDROMRESET and CDROMVOLREAD. + * Started again to support the TEAC CD-55A drives, now that I found + * the money for "my own" drive. ;-) + * The TEAC CD-55A support is fairly working now. + * I have measured that the drive "delivers" at 600 kB/sec (even with + * bigger requests than the drive's 64 kB buffer can satisfy), but + * the "real" rate does not exceed 520 kB/sec at the moment. + * Caused by the various changes to build in TEAC support, the timed + * loops are de-optimized at the moment (less throughput with CR-52x + * drives, and the TEAC will give speed only with SBP_BUFFER_FRAMES 64). + * + * 3.6 Fixed TEAC data read problems with SbPro interfaces. + * Initial size of the READ_AUDIO buffer is 0. Can get set to any size + * during runtime. + * + * 3.7 Introduced MAX_DRIVES for some poor interface cards (seen with TEAC + * drives) which allow only one drive (ID 0); this avoids repetitive + * detection under IDs 1..3. + * Elongated cmd_out_T response waiting; necessary for photo CDs with + * a lot of sessions. + * Bettered the sbpcd_open() behavior with TEAC drives. + * + * 3.8 Elongated max_latency for CR-56x drives. + * + * 3.9 Finally fixed the long-known SoundScape/SPEA/Sequoia S-1000 interface + * configuration bug. + * Now Corey, Heiko, Ken, Leo, Vadim/Eric & Werner are invited to copy + * the config_spea() routine into their drivers. ;-) + * + * 4.0 No "big step" - normal version increment. + * Adapted the benefits from 1.3.33. + * Fiddled with CDROMREADAUDIO flaws. + * Avoid ReadCapacity command with CD200 drives (the MKE 1.01 version + * seems not to support it). + * Fulfilled "read audio" for CD200 drives, with help of Pete Heist + * (heistp@rpi.edu). + * + * 4.1 Use loglevel KERN_INFO with printk(). + * Added support for "Vertos 100" drive ("ECS-AT") - it is very similar + * to the Longshine LCS-7260. Give feedback if you can - I never saw + * such a drive, and I have no specs. + * + * 4.2 Support for Teac 16-bit interface cards. Can't get auto-detected, + * so you have to jumper your card to 0x2C0. Still not 100% - come + * in contact if you can give qualified feedback. + * Use loglevel KERN_NOTICE with printk(). If you get annoyed by a + * flood of unwanted messages and the accompanied delay, try to read + * my documentation. Especially the Linux CDROM drivers have to do an + * important job for the newcomers, so the "distributed" version has + * to fit some special needs. Since generations, the flood of messages + * is user-configurable (even at runtime), but to get aware of this, one + * needs a special mental quality: the ability to read. + * + * 4.3 CD200F does not like to receive a command while the drive is + * reading the ToC; still trying to solve it. + * Removed some redundant verify_area calls (yes, Heiko Eissfeldt + * is visiting all the Linux CDROM drivers ;-). + * + * 4.4 Adapted one idea from tiensivu@pilot.msu.edu's "stripping-down" + * experiments: "KLOGD_PAUSE". + * Inhibited "play audio" attempts with data CDs. Provisions for a + * "data-safe" handling of "mixed" (data plus audio) Cds. + * + * 4.5 Meanwhile Gonzalo Tornaria <tornaria@cmat.edu.uy> (GTL) built a + * special end_request routine: we seem to have to take care for not + * to have two processes working at the request list. My understanding + * was and is that ll_rw_blk should not call do_sbpcd_request as long + * as there is still one call active (the first call will care for all + * outstanding I/Os, and if a second call happens, that is a bug in + * ll_rw_blk.c). + * "Check media change" without touching any drive. + * + * 4.6 Use a semaphore to synchronize multi-activity; elaborated by Rob + * Riggs <rriggs@tesser.com>. At the moment, we simply block "read" + * against "ioctl" and vice versa. This could be refined further, but + * I guess with almost no performance increase. + * Experiments to speed up the CD-55A; again with help of Rob Riggs + * (to be true, he gave both, idea & code. ;-) + * + * 4.61 Ported to Uniform CD-ROM driver by + * Heiko Eissfeldt <heiko@colossus.escape.de> with additional + * changes by Erik Andersen <andersee@debian.org> + * + * 4.62 Fix a bug where playing audio left the drive in an unusable state. + * Heiko Eissfeldt <heiko@colossus.escape.de> + * + * November 1999 -- Make kernel-parameter implementation work with 2.3.x + * Removed init_module & cleanup_module in favor of + * module_init & module_exit. + * Torben Mathiasen <tmm@image.dk> + * + * 4.63 Bug fixes for audio annoyances, new legacy CDROM maintainer. + * Annoying things fixed: + * TOC reread on automated disk changes + * TOC reread on manual cd changes + * Play IOCTL tries to play CD before it's actually ready... sometimes. + * CD_AUDIO_COMPLETED state so workman (and other playes) can repeat play. + * Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000 + * + * 4.64 Fix module parameters - were being completely ignored. + * Can also specify max_drives=N as a setup int to get rid of + * "ghost" drives on crap hardware (aren't they all?) Paul Gortmaker + * + * TODO + * implement "read all subchannel data" (96 bytes per frame) + * remove alot of the virtual status bits and deal with hardware status + * move the change of cd for audio to a better place + * add debug levels to insmod parameters (trivial) + * + * special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine + * elaborated speed-up experiments (and the fabulous results!), for + * the "push" towards load-free wait loops, and for the extensive mail + * thread which brought additional hints and bug fixes. + * + */ + +/* + * Trying to merge requests breaks this driver horribly (as in it goes + * boom and apparently has done so since 2.3.41). As it is a legacy + * driver for a horribly slow double speed CD on a hideous interface + * designed for polled operation, I won't lose any sleep in simply + * disallowing merging. Paul G. 02/2001 + * + * Thu May 30 14:14:47 CEST 2002: + * + * I have presumably found the reson for the above - there was a bogous + * end_request substitute, which was manipulating the request queues + * incorrectly. If someone has access to the actual hardware, and it's + * still operations - well please free to test it. + * + * Marcin Dalecki + */ + +/* + * Add bio/kdev_t changes for 2.5.x required to make it work again. + * Still room for improvement in the request handling here if anyone + * actually cares. Bring your own chainsaw. Paul G. 02/2002 + */ + + +#include <linux/module.h> + +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/timer.h> +#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/cdrom.h> +#include <linux/ioport.h> +#include <linux/devfs_fs_kernel.h> +#include <linux/major.h> +#include <linux/string.h> +#include <linux/vmalloc.h> +#include <linux/init.h> +#include <linux/interrupt.h> + +#include <asm/system.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include <stdarg.h> +#include <linux/config.h> +#include "sbpcd.h" + +#define MAJOR_NR MATSUSHITA_CDROM_MAJOR +#include <linux/blkdev.h> + +/*==========================================================================*/ +#if SBPCD_DIS_IRQ +# define SBPCD_CLI cli() +# define SBPCD_STI sti() +#else +# define SBPCD_CLI +# define SBPCD_STI +#endif + +/*==========================================================================*/ +/* + * auto-probing address list + * inspired by Adam J. Richter from Yggdrasil + * + * still not good enough - can cause a hang. + * example: a NE 2000 ethernet card at 300 will cause a hang probing 310. + * if that happens, reboot and use the LILO (kernel) command line. + * The possibly conflicting ethernet card addresses get NOT probed + * by default - to minimize the hang possibilities. + * + * The SB Pro addresses get "mirrored" at 0x6xx and some more locations - to + * avoid a type error, the 0x2xx-addresses must get checked before 0x6xx. + * + * send mail to emoenke@gwdg.de if your interface card is not FULLY + * represented here. + */ +static int sbpcd[] = +{ + CDROM_PORT, SBPRO, /* probe with user's setup first */ +#if DISTRIBUTION + 0x230, 1, /* Soundblaster Pro and 16 (default) */ +#if 0 + 0x300, 0, /* CI-101P (default), WDH-7001C (default), + Galaxy (default), Reveal (one default) */ + 0x250, 1, /* OmniCD default, Soundblaster Pro and 16 */ + 0x2C0, 3, /* Teac 16-bit cards */ + 0x260, 1, /* OmniCD */ + 0x320, 0, /* Lasermate, CI-101P, WDH-7001C, Galaxy, Reveal (other default), + Longshine LCS-6853 (default) */ + 0x338, 0, /* Reveal Sound Wave 32 card model #SC600 */ + 0x340, 0, /* Mozart sound card (default), Lasermate, CI-101P */ + 0x360, 0, /* Lasermate, CI-101P */ + 0x270, 1, /* Soundblaster 16 */ + 0x670, 0, /* "sound card #9" */ + 0x690, 0, /* "sound card #9" */ + 0x338, 2, /* SPEA Media FX, Ensonic SoundScape (default) */ + 0x328, 2, /* SPEA Media FX */ + 0x348, 2, /* SPEA Media FX */ + 0x634, 0, /* some newer sound cards */ + 0x638, 0, /* some newer sound cards */ + 0x230, 1, /* some newer sound cards */ + /* due to incomplete address decoding of the SbPro card, these must be last */ + 0x630, 0, /* "sound card #9" (default) */ + 0x650, 0, /* "sound card #9" */ +#ifdef MODULE + /* + * some "hazardous" locations (no harm with the loadable version) + * (will stop the bus if a NE2000 ethernet card resides at offset -0x10) + */ + 0x330, 0, /* Lasermate, CI-101P, WDH-7001C */ + 0x350, 0, /* Lasermate, CI-101P */ + 0x358, 2, /* SPEA Media FX */ + 0x370, 0, /* Lasermate, CI-101P */ + 0x290, 1, /* Soundblaster 16 */ + 0x310, 0, /* Lasermate, CI-101P, WDH-7001C */ +#endif /* MODULE */ +#endif +#endif /* DISTRIBUTION */ +}; + +/* + * Protects access to global structures etc. + */ +static __cacheline_aligned DEFINE_SPINLOCK(sbpcd_lock); +static struct request_queue *sbpcd_queue; + +MODULE_PARM(sbpcd, "2i"); +MODULE_PARM(max_drives, "i"); + +#define NUM_PROBE (sizeof(sbpcd) / sizeof(int)) + +/*==========================================================================*/ + +#define INLINE inline + +/*==========================================================================*/ +/* + * the forward references: + */ +static void sbp_sleep(u_int); +static void mark_timeout_delay(u_long); +static void mark_timeout_data(u_long); +#if 0 +static void mark_timeout_audio(u_long); +#endif +static void sbp_read_cmd(struct request *req); +static int sbp_data(struct request *req); +static int cmd_out(void); +static int DiskInfo(void); + +/*==========================================================================*/ + +/* + * pattern for printk selection: + * + * (1<<DBG_INF) necessary information + * (1<<DBG_BSZ) BLOCK_SIZE trace + * (1<<DBG_REA) "read" status trace + * (1<<DBG_CHK) "media check" trace + * (1<<DBG_TIM) datarate timer test + * (1<<DBG_INI) initialization trace + * (1<<DBG_TOC) tell TocEntry values + * (1<<DBG_IOC) ioctl trace + * (1<<DBG_STA) "ResponseStatus" trace + * (1<<DBG_ERR) "cc_ReadError" trace + * (1<<DBG_CMD) "cmd_out" trace + * (1<<DBG_WRN) give explanation before auto-probing + * (1<<DBG_MUL) multi session code test + * (1<<DBG_IDX) "drive_id != 0" test code + * (1<<DBG_IOX) some special information + * (1<<DBG_DID) drive ID test + * (1<<DBG_RES) drive reset info + * (1<<DBG_SPI) SpinUp test info + * (1<<DBG_IOS) ioctl trace: "subchannel" + * (1<<DBG_IO2) ioctl trace: general + * (1<<DBG_UPC) show UPC info + * (1<<DBG_XA1) XA mode debugging + * (1<<DBG_LCK) door (un)lock info + * (1<<DBG_SQ1) dump SubQ frame + * (1<<DBG_AUD) "read audio" debugging + * (1<<DBG_SEQ) Sequoia interface configuration trace + * (1<<DBG_LCS) Longshine LCS-7260 debugging trace + * (1<<DBG_CD2) MKE/Funai CD200 debugging trace + * (1<<DBG_TEA) TEAC CD-55A debugging trace + * (1<<DBG_ECS) ECS-AT (Vertos-100) debugging trace + * (1<<DBG_000) unnecessary information + */ +#if DISTRIBUTION +static int sbpcd_debug = (1<<DBG_INF); +#else +static int sbpcd_debug = 0 & ((1<<DBG_INF) | + (1<<DBG_TOC) | + (1<<DBG_MUL) | + (1<<DBG_UPC)); +#endif /* DISTRIBUTION */ + +static int sbpcd_ioaddr = CDROM_PORT; /* default I/O base address */ +static int sbpro_type = SBPRO; +static unsigned char f_16bit; +static unsigned char do_16bit; +static int CDo_command, CDo_reset; +static int CDo_sel_i_d, CDo_enable; +static int CDi_info, CDi_status, CDi_data; +static struct cdrom_msf msf; +static struct cdrom_ti ti; +static struct cdrom_tochdr tochdr; +static struct cdrom_tocentry tocentry; +static struct cdrom_subchnl SC; +static struct cdrom_volctrl volctrl; +static struct cdrom_read_audio read_audio; + +static unsigned char msgnum; +static char msgbuf[80]; + +static int max_drives = MAX_DRIVES; +#ifndef MODULE +static unsigned char setup_done; +static const char *str_sb_l = "soundblaster"; +static const char *str_sp_l = "spea"; +static const char *str_ss_l = "soundscape"; +static const char *str_t16_l = "teac16bit"; +static const char *str_ss = "SoundScape"; +#endif +static const char *str_sb = "SoundBlaster"; +static const char *str_lm = "LaserMate"; +static const char *str_sp = "SPEA"; +static const char *str_t16 = "Teac16bit"; +static const char *type; +static const char *major_name="sbpcd"; + +/*==========================================================================*/ + +#ifdef FUTURE +static DECLARE_WAIT_QUEUE_HEAD(sbp_waitq); +#endif /* FUTURE */ + +static int teac=SBP_TEAC_SPEED; +static int buffers=SBP_BUFFER_FRAMES; + +static u_char family0[]="MATSHITA"; /* MKE CR-521, CR-522, CR-523 */ +static u_char family1[]="CR-56"; /* MKE CR-562, CR-563 */ +static u_char family2[]="CD200"; /* MKE CD200, Funai CD200F */ +static u_char familyL[]="LCS-7260"; /* Longshine LCS-7260 */ +static u_char familyT[]="CD-55"; /* TEAC CD-55A */ +static u_char familyV[]="ECS-AT"; /* ECS Vertos 100 */ + +static u_int recursion; /* internal testing only */ +static u_int fatal_err; /* internal testing only */ +static u_int response_count; +static u_int flags_cmd_out; +static u_char cmd_type; +static u_char drvcmd[10]; +static u_char infobuf[20]; +static u_char xa_head_buf[CD_XA_HEAD]; +static u_char xa_tail_buf[CD_XA_TAIL]; + +#if OLD_BUSY +static volatile u_char busy_data; +static volatile u_char busy_audio; /* true semaphores would be safer */ +#endif /* OLD_BUSY */ +static DECLARE_MUTEX(ioctl_read_sem); +static u_long timeout; +static volatile u_char timed_out_delay; +static volatile u_char timed_out_data; +#if 0 +static volatile u_char timed_out_audio; +#endif +static u_int datarate= 1000000; +static u_int maxtim16=16000000; +static u_int maxtim04= 4000000; +static u_int maxtim02= 2000000; +static u_int maxtim_8= 30000; +#if LONG_TIMING +static u_int maxtim_data= 9000; +#else +static u_int maxtim_data= 3000; +#endif /* LONG_TIMING */ +#if DISTRIBUTION +static int n_retries=6; +#else +static int n_retries=6; +#endif +/*==========================================================================*/ + +static int ndrives; +static u_char drv_pattern[NR_SBPCD]={speed_auto,speed_auto,speed_auto,speed_auto}; + +/*==========================================================================*/ +/* + * drive space begins here (needed separate for each unit) + */ +static struct sbpcd_drive { + char drv_id; /* "jumpered" drive ID or -1 */ + char drv_sel; /* drive select lines bits */ + + char drive_model[9]; + u_char firmware_version[4]; + char f_eject; /* auto-eject flag: 0 or 1 */ + u_char *sbp_buf; /* Pointer to internal data buffer, + space allocated during sbpcd_init() */ + u_int sbp_bufsiz; /* size of sbp_buf (# of frames) */ + int sbp_first_frame; /* First frame in buffer */ + int sbp_last_frame; /* Last frame in buffer */ + int sbp_read_frames; /* Number of frames being read to buffer */ + int sbp_current; /* Frame being currently read */ + + u_char mode; /* read_mode: READ_M1, READ_M2, READ_SC, READ_AU */ + u_char *aud_buf; /* Pointer to audio data buffer, + space allocated during sbpcd_init() */ + u_int sbp_audsiz; /* size of aud_buf (# of raw frames) */ + u_int drv_type; + u_char drv_options; + int status_bits; + u_char diskstate_flags; + u_char sense_byte; + + u_char CD_changed; + char open_count; + u_char error_byte; + + u_char f_multisession; + u_int lba_multi; + int first_session; + int last_session; + int track_of_last_session; + + u_char audio_state; + u_int pos_audio_start; + u_int pos_audio_end; + char vol_chan0; + u_char vol_ctrl0; + char vol_chan1; + u_char vol_ctrl1; +#if 000 /* no supported drive has it */ + char vol_chan2; + u_char vol_ctrl2; + char vol_chan3; + u_char vol_ctrl3; +#endif /*000 */ + u_char volume_control; /* TEAC on/off bits */ + + u_char SubQ_ctl_adr; + u_char SubQ_trk; + u_char SubQ_pnt_idx; + u_int SubQ_run_tot; + u_int SubQ_run_trk; + u_char SubQ_whatisthis; + + u_char UPC_ctl_adr; + u_char UPC_buf[7]; + + int frame_size; + int CDsize_frm; + + u_char xa_byte; /* 0x20: XA capabilities */ + u_char n_first_track; /* binary */ + u_char n_last_track; /* binary (not bcd), 0x01...0x63 */ + u_int size_msf; /* time of whole CD, position of LeadOut track */ + u_int size_blk; + + u_char TocEnt_nixbyte; /* em */ + u_char TocEnt_ctl_adr; + u_char TocEnt_number; + u_char TocEnt_format; /* em */ + u_int TocEnt_address; +#ifdef SAFE_MIXED + char has_data; +#endif /* SAFE_MIXED */ + u_char ored_ctl_adr; /* to detect if CDROM contains data tracks */ + + struct { + u_char nixbyte; /* em */ + u_char ctl_adr; /* 0x4x: data, 0x0x: audio */ + u_char number; + u_char format; /* em */ /* 0x00: lba, 0x01: msf */ + u_int address; + } TocBuffer[MAX_TRACKS+1]; /* last entry faked */ + + int in_SpinUp; /* CR-52x test flag */ + int n_bytes; /* TEAC awaited response count */ + u_char error_state, b3, b4; /* TEAC command error state */ + u_char f_drv_error; /* TEAC command error flag */ + u_char speed_byte; + int frmsiz; + u_char f_XA; /* 1: XA */ + u_char type_byte; /* 0, 1, 3 */ + u_char mode_xb_6; + u_char mode_yb_7; + u_char mode_xb_8; + u_char delay; + struct cdrom_device_info *sbpcd_infop; + struct gendisk *disk; +} D_S[NR_SBPCD]; + +static struct sbpcd_drive *current_drive = D_S; + +/* + * drive space ends here (needed separate for each unit) + */ +/*==========================================================================*/ +#if 0 +unsigned long cli_sti; /* for saving the processor flags */ +#endif +/*==========================================================================*/ +static struct timer_list delay_timer = + TIMER_INITIALIZER(mark_timeout_delay, 0, 0); +static struct timer_list data_timer = + TIMER_INITIALIZER(mark_timeout_data, 0, 0); +#if 0 +static struct timer_list audio_timer = + TIMER_INITIALIZER(mark_timeout_audio, 0, 0); +#endif +/*==========================================================================*/ +/* + * DDI interface + */ +static void msg(int level, const char *fmt, ...) +{ +#if DISTRIBUTION +#define MSG_LEVEL KERN_NOTICE +#else +#define MSG_LEVEL KERN_INFO +#endif /* DISTRIBUTION */ + + char buf[256]; + va_list args; + + if (!(sbpcd_debug&(1<<level))) return; + + msgnum++; + if (msgnum>99) msgnum=0; + sprintf(buf, MSG_LEVEL "%s-%d [%02d]: ", major_name, current_drive - D_S, msgnum); + va_start(args, fmt); + vsprintf(&buf[18], fmt, args); + va_end(args); + printk(buf); +#if KLOGD_PAUSE + sbp_sleep(KLOGD_PAUSE); /* else messages get lost */ +#endif /* KLOGD_PAUSE */ + return; +} +/*==========================================================================*/ +/* + * DDI interface: runtime trace bit pattern maintenance + */ +static int sbpcd_dbg_ioctl(unsigned long arg, int level) +{ + switch(arg) + { + case 0: /* OFF */ + sbpcd_debug = DBG_INF; + break; + + default: + if (arg>=128) sbpcd_debug &= ~(1<<(arg-128)); + else sbpcd_debug |= (1<<arg); + } + return (arg); +} +/*==========================================================================*/ +static void mark_timeout_delay(u_long i) +{ + timed_out_delay=1; +#if 0 + msg(DBG_TIM,"delay timer expired.\n"); +#endif +} +/*==========================================================================*/ +static void mark_timeout_data(u_long i) +{ + timed_out_data=1; +#if 0 + msg(DBG_TIM,"data timer expired.\n"); +#endif +} +/*==========================================================================*/ +#if 0 +static void mark_timeout_audio(u_long i) +{ + timed_out_audio=1; +#if 0 + msg(DBG_TIM,"audio timer expired.\n"); +#endif +} +#endif +/*==========================================================================*/ +/* + * Wait a little while (used for polling the drive). + */ +static void sbp_sleep(u_int time) +{ + sti(); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(time); + sti(); +} +/*==========================================================================*/ +#define RETURN_UP(rc) {up(&ioctl_read_sem); return(rc);} +/*==========================================================================*/ +/* + * convert logical_block_address to m-s-f_number (3 bytes only) + */ +static INLINE void lba2msf(int lba, u_char *msf) +{ + lba += CD_MSF_OFFSET; + msf[0] = lba / (CD_SECS*CD_FRAMES); + lba %= CD_SECS*CD_FRAMES; + msf[1] = lba / CD_FRAMES; + msf[2] = lba % CD_FRAMES; +} +/*==========================================================================*/ +/*==========================================================================*/ +/* + * convert msf-bin to msf-bcd + */ +static INLINE void bin2bcdx(u_char *p) /* must work only up to 75 or 99 */ +{ + *p=((*p/10)<<4)|(*p%10); +} +/*==========================================================================*/ +static INLINE u_int blk2msf(u_int blk) +{ + MSF msf; + u_int mm; + + msf.c[3] = 0; + msf.c[2] = (blk + CD_MSF_OFFSET) / (CD_SECS * CD_FRAMES); + mm = (blk + CD_MSF_OFFSET) % (CD_SECS * CD_FRAMES); + msf.c[1] = mm / CD_FRAMES; + msf.c[0] = mm % CD_FRAMES; + return (msf.n); +} +/*==========================================================================*/ +static INLINE u_int make16(u_char rh, u_char rl) +{ + return ((rh<<8)|rl); +} +/*==========================================================================*/ +static INLINE u_int make32(u_int rh, u_int rl) +{ + return ((rh<<16)|rl); +} +/*==========================================================================*/ +static INLINE u_char swap_nibbles(u_char i) +{ + return ((i<<4)|(i>>4)); +} +/*==========================================================================*/ +static INLINE u_char byt2bcd(u_char i) +{ + return (((i/10)<<4)+i%10); +} +/*==========================================================================*/ +static INLINE u_char bcd2bin(u_char bcd) +{ + return ((bcd>>4)*10+(bcd&0x0F)); +} +/*==========================================================================*/ +static INLINE int msf2blk(int msfx) +{ + MSF msf; + int i; + + msf.n=msfx; + i=(msf.c[2] * CD_SECS + msf.c[1]) * CD_FRAMES + msf.c[0] - CD_MSF_OFFSET; + if (i<0) return (0); + return (i); +} +/*==========================================================================*/ +/* + * convert m-s-f_number (3 bytes only) to logical_block_address + */ +static INLINE int msf2lba(u_char *msf) +{ + int i; + + i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_MSF_OFFSET; + if (i<0) return (0); + return (i); +} +/*==========================================================================*/ +/* evaluate cc_ReadError code */ +static int sta2err(int sta) +{ + if (famT_drive) + { + if (sta==0x00) return (0); + if (sta==0x01) return (-604); /* CRC error */ + if (sta==0x02) return (-602); /* drive not ready */ + if (sta==0x03) return (-607); /* unknown media */ + if (sta==0x04) return (-612); /* general failure */ + if (sta==0x05) return (0); + if (sta==0x06) return (-ERR_DISKCHANGE); /* disk change */ + if (sta==0x0b) return (-612); /* general failure */ + if (sta==0xff) return (-612); /* general failure */ + return (0); + } + else + { + if (sta<=2) return (sta); + if (sta==0x05) return (-604); /* CRC error */ + if (sta==0x06) return (-606); /* seek error */ + if (sta==0x0d) return (-606); /* seek error */ + if (sta==0x0e) return (-603); /* unknown command */ + if (sta==0x14) return (-603); /* unknown command */ + if (sta==0x0c) return (-611); /* read fault */ + if (sta==0x0f) return (-611); /* read fault */ + if (sta==0x10) return (-611); /* read fault */ + if (sta>=0x16) return (-612); /* general failure */ + if (sta==0x11) return (-ERR_DISKCHANGE); /* disk change (LCS: removed) */ + if (famL_drive) + if (sta= |