aboutsummaryrefslogtreecommitdiff
path: root/drivers/cdrom/sbpcd.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /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.c5978
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=