Remove legacy CDROM drivers
authorJens Axboe <jens.axboe@oracle.com>
Thu, 21 Jun 2007 06:29:34 +0000 (08:29 +0200)
committerJens Axboe <jens.axboe@oracle.com>
Tue, 10 Jul 2007 06:03:34 +0000 (08:03 +0200)
They are all broken beyond repair. Given that nobody has complained
about them (most haven't worked in 2.6 AT ALL), remove them from the
tree.

A new mitsumi driver that actually works is in progress, it'll get
added when completed.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
23 files changed:
drivers/Kconfig
drivers/cdrom/Kconfig [deleted file]
drivers/cdrom/Makefile
drivers/cdrom/aztcd.c [deleted file]
drivers/cdrom/aztcd.h [deleted file]
drivers/cdrom/cdu31a.c [deleted file]
drivers/cdrom/cdu31a.h [deleted file]
drivers/cdrom/cm206.c [deleted file]
drivers/cdrom/cm206.h [deleted file]
drivers/cdrom/gscd.c [deleted file]
drivers/cdrom/gscd.h [deleted file]
drivers/cdrom/isp16.c [deleted file]
drivers/cdrom/isp16.h [deleted file]
drivers/cdrom/mcdx.c [deleted file]
drivers/cdrom/mcdx.h [deleted file]
drivers/cdrom/optcd.c [deleted file]
drivers/cdrom/optcd.h [deleted file]
drivers/cdrom/sbpcd.c [deleted file]
drivers/cdrom/sbpcd.h [deleted file]
drivers/cdrom/sjcd.c [deleted file]
drivers/cdrom/sjcd.h [deleted file]
drivers/cdrom/sonycd535.c [deleted file]
drivers/cdrom/sonycd535.h [deleted file]

index 050323f..4e6487d 100644 (file)
@@ -24,8 +24,6 @@ source "drivers/scsi/Kconfig"
 
 source "drivers/ata/Kconfig"
 
-source "drivers/cdrom/Kconfig"
-
 source "drivers/md/Kconfig"
 
 source "drivers/message/fusion/Kconfig"
diff --git a/drivers/cdrom/Kconfig b/drivers/cdrom/Kconfig
deleted file mode 100644 (file)
index 4b12e90..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-#
-# CDROM driver configuration
-#
-
-menu "Old CD-ROM drivers (not SCSI, not IDE)"
-       depends on ISA && BLOCK
-
-config CD_NO_IDESCSI
-       bool "Support non-SCSI/IDE/ATAPI CDROM drives"
-       ---help---
-         If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y
-         here, otherwise N. Read the CD-ROM-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         Note that the answer to this question doesn't directly affect the
-         kernel: saying N will just cause the configurator to skip all
-         the questions about these CD-ROM drives. If you are unsure what you
-         have, say Y and find out whether you have one of the following
-         drives.
-
-         For each of these drivers, a <file:Documentation/cdrom/{driver_name}>
-         exists. Especially in cases where you do not know exactly which kind
-         of drive you have you should read there. Most of these drivers use a
-         file drivers/cdrom/{driver_name}.h where you can define your
-         interface parameters and switch some internal goodies.
-
-         To compile these CD-ROM drivers as a module, choose M instead of Y.
-
-         If you want to use any of these CD-ROM drivers, you also have to
-         answer Y or M to "ISO 9660 CD-ROM file system support" below (this
-         answer will get "defaulted" for you if you enable any of the Linux
-         CD-ROM drivers).
-
-config AZTCD
-       tristate "Aztech/Orchid/Okano/Wearnes/TXC/CyDROM  CDROM support"
-       depends on CD_NO_IDESCSI
-       ---help---
-         This is your driver if you have an Aztech CDA268-01A, Orchid
-         CD-3110, Okano or Wearnes CDD110, Conrad TXC, or CyCD-ROM CR520 or
-         CR540 CD-ROM drive.  This driver -- just like all these CD-ROM
-         drivers -- is NOT for CD-ROM drives with IDE/ATAPI interfaces, such
-         as Aztech CDA269-031SE. Please read the file
-         <file:Documentation/cdrom/aztcd>.
-
-         If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-         file system support" below, because that's the file system used on
-         CD-ROMs.
-
-         To compile this driver as a module, choose M here: the
-         module will be called aztcd.
-
-config GSCD
-       tristate "Goldstar R420 CDROM support"
-       depends on CD_NO_IDESCSI
-       ---help---
-         If this is your CD-ROM drive, say Y here.  As described in the file
-         <file:Documentation/cdrom/gscd>, you might have to change a setting
-         in the file <file:drivers/cdrom/gscd.h> before compiling the
-         kernel.  Please read the file <file:Documentation/cdrom/gscd>.
-
-         If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-         file system support" below, because that's the file system used on
-         CD-ROMs.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gscd.
-
-config SBPCD
-       tristate "Matsushita/Panasonic/Creative, Longshine, TEAC CDROM support"
-       depends on CD_NO_IDESCSI && BROKEN_ON_SMP
-       ---help---
-         This driver supports most of the drives which use the Panasonic or
-         Sound Blaster interface.  Please read the file
-         <file:Documentation/cdrom/sbpcd>.
-
-         The Matsushita CR-521, CR-522, CR-523, CR-562, CR-563 drives
-         (sometimes labeled "Creative"), the Creative Labs CD200, the
-         Longshine LCS-7260, the "IBM External ISA CD-ROM" (in fact a CR-56x
-         model), the TEAC CD-55A fall under this category.  Some other
-         "electrically compatible" drives (Vertos, Genoa, some Funai models)
-         are currently not supported; for the Sanyo H94A drive currently a
-         separate driver (asked later) is responsible.  Most drives have a
-         uniquely shaped faceplate, with a caddyless motorized drawer, but
-         without external brand markings.  The older CR-52x drives have a
-         caddy and manual loading/eject, but still no external markings.  The
-         driver is able to do an extended auto-probing for interface
-         addresses and drive types; this can help to find facts in cases you
-         are not sure, but can consume some time during the boot process if
-         none of the supported drives gets found.  Once your drive got found,
-         you should enter the reported parameters into
-         <file:drivers/cdrom/sbpcd.h> and set "DISTRIBUTION 0" there.
-
-         This driver can support up to four CD-ROM controller cards, and each
-         card can support up to four CD-ROM drives; if you say Y here, you
-         will be asked how many controller cards you have.  If compiled as a
-         module, only one controller card (but with up to four drives) is
-         usable.
-
-         If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-         file system support" below, because that's the file system used on
-         CD-ROMs.
-
-         To compile this driver as a module, choose M here: the
-         module will be called sbpcd.
-
-config MCDX
-       tristate "Mitsumi CDROM support"
-       depends on CD_NO_IDESCSI
-       ---help---
-         Use this driver if you want to be able to use your Mitsumi LU-005,
-         FX-001 or FX-001D CD-ROM drive.
-
-         Please read the file <file:Documentation/cdrom/mcdx>.
-
-         If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-         file system support" below, because that's the file system used on
-         CD-ROMs.
-
-         To compile this driver as a module, choose M here: the
-         module will be called mcdx.
-
-config OPTCD
-       tristate "Optics Storage DOLPHIN 8000AT CDROM support"
-       depends on CD_NO_IDESCSI
-       ---help---
-         This is the driver for the 'DOLPHIN' drive with a 34-pin Sony
-         compatible interface. It also works with the Lasermate CR328A. If
-         you have one of those, say Y. This driver does not work for the
-         Optics Storage 8001 drive; use the IDE-ATAPI CD-ROM driver for that
-         one. Please read the file <file:Documentation/cdrom/optcd>.
-
-         If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-         file system support" below, because that's the file system used on
-         CD-ROMs.
-
-         To compile this driver as a module, choose M here: the
-         module will be called optcd.
-
-config CM206
-       tristate "Philips/LMS CM206 CDROM support"
-       depends on CD_NO_IDESCSI && BROKEN_ON_SMP
-       ---help---
-         If you have a Philips/LMS CD-ROM drive cm206 in combination with a
-         cm260 host adapter card, say Y here. Please also read the file
-         <file:Documentation/cdrom/cm206>.
-
-         If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-         file system support" below, because that's the file system used on
-         CD-ROMs.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cm206.
-
-config SJCD
-       tristate "Sanyo CDR-H94A CDROM support"
-       depends on CD_NO_IDESCSI
-       help
-         If this is your CD-ROM drive, say Y here and read the file
-         <file:Documentation/cdrom/sjcd>. You should then also say Y or M to
-         "ISO 9660 CD-ROM file system support" below, because that's the
-         file system used on CD-ROMs.
-
-         To compile this driver as a module, choose M here: the
-         module will be called sjcd.
-
-config ISP16_CDI
-       tristate "ISP16/MAD16/Mozart soft configurable cdrom interface support"
-       depends on CD_NO_IDESCSI
-       ---help---
-         These are sound cards with built-in cdrom interfaces using the OPTi
-         82C928 or 82C929 chips. Say Y here to have them detected and
-         possibly configured at boot time. In addition, You'll have to say Y
-         to a driver for the particular cdrom drive you have attached to the
-         card. Read <file:Documentation/cdrom/isp16> for details.
-
-         To compile this driver as a module, choose M here: the
-         module will be called isp16.
-
-config CDU31A
-       tristate "Sony CDU31A/CDU33A CDROM support"
-       depends on CD_NO_IDESCSI && BROKEN_ON_SMP
-       ---help---
-         These CD-ROM drives have a spring-pop-out caddyless drawer, and a
-         rectangular green LED centered beneath it.  NOTE: these CD-ROM
-         drives will not be auto detected by the kernel at boot time; you
-         have to provide the interface address as an option to the kernel at
-         boot time as described in <file:Documentation/cdrom/cdu31a> or fill
-         in your parameters into <file:drivers/cdrom/cdu31a.c>.  Try "man
-         bootparam" or see the documentation of your boot loader (lilo or
-         loadlin) about how to pass options to the kernel.
-
-         If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-         file system support" below, because that's the file system used on
-         CD-ROMs.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cdu31a.
-
-config CDU535
-       tristate "Sony CDU535 CDROM support"
-       depends on CD_NO_IDESCSI
-       ---help---
-         This is the driver for the older Sony CDU-535 and CDU-531 CD-ROM
-         drives. Please read the file <file:Documentation/cdrom/sonycd535>.
-
-         If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-         file system support" below, because that's the file system used on
-         CD-ROMs.
-
-         To compile this driver as a module, choose M here: the
-         module will be called sonycd535.
-
-endmenu
index d1d1e5a..774c180 100644 (file)
@@ -10,14 +10,4 @@ obj-$(CONFIG_BLK_DEV_SR)     +=              cdrom.o
 obj-$(CONFIG_PARIDE_PCD)       +=              cdrom.o
 obj-$(CONFIG_CDROM_PKTCDVD)    +=              cdrom.o
 
-obj-$(CONFIG_AZTCD)            += aztcd.o
-obj-$(CONFIG_CDU31A)           += cdu31a.o     cdrom.o
-obj-$(CONFIG_CM206)            += cm206.o      cdrom.o
-obj-$(CONFIG_GSCD)             += gscd.o
-obj-$(CONFIG_ISP16_CDI)                += isp16.o
-obj-$(CONFIG_MCDX)             += mcdx.o       cdrom.o
-obj-$(CONFIG_OPTCD)            += optcd.o
-obj-$(CONFIG_SBPCD)            += sbpcd.o      cdrom.o
-obj-$(CONFIG_SJCD)             += sjcd.o
-obj-$(CONFIG_CDU535)           += sonycd535.o
 obj-$(CONFIG_VIOCD)            += viocd.o      cdrom.o
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
deleted file mode 100644 (file)
index d7fbfaa..0000000
+++ /dev/null
@@ -1,2492 +0,0 @@
-#define AZT_VERSION "2.60"
-
-/*      $Id: aztcd.c,v 2.60 1997/11/29 09:51:19 root Exp root $
-       linux/drivers/block/aztcd.c - Aztech CD268 CDROM driver
-
-       Copyright (C) 1994-98 Werner Zimmermann(Werner.Zimmermann@fht-esslingen.de)
-
-       based on Mitsumi CDROM driver by  Martin Hariss and preworks by
-       Eberhard Moenkeberg; contains contributions by Joe Nardone and Robby 
-       Schirmer.
-
-       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.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, write to the Free Software
-       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-       HISTORY
-       V0.0    Adaption to Aztech CD268-01A Version 1.3
-               Version is PRE_ALPHA, unresolved points:
-               1. I use busy wait instead of timer wait in STEN_LOW,DTEN_LOW
-                  thus driver causes CPU overhead and is very slow 
-               2. could not find a way to stop the drive, when it is
-                  in data read mode, therefore I had to set
-                  msf.end.min/sec/frame to 0:0:1 (in azt_poll); so only one
-                  frame can be read in sequence, this is also the reason for
-               3. getting 'timeout in state 4' messages, but nevertheless
-                  it works
-               W.Zimmermann, Oct. 31, 1994
-       V0.1    Version is ALPHA, problems #2 and #3 resolved.  
-               W.Zimmermann, Nov. 3, 1994
-       V0.2    Modification to some comments, debugging aids for partial test
-               with Borland C under DOS eliminated. Timer interrupt wait 
-               STEN_LOW_WAIT additionally to busy wait for STEN_LOW implemented; 
-               use it only for the 'slow' commands (ACMD_GET_Q_CHANNEL, ACMD_
-               SEEK_TO_LEAD_IN), all other commands are so 'fast', that busy 
-               waiting seems better to me than interrupt rescheduling.
-               Besides that, when used in the wrong place, STEN_LOW_WAIT causes
-               kernel panic.
-               In function aztPlay command ACMD_PLAY_AUDIO added, should make
-               audio functions work. The Aztech drive needs different commands
-               to read data tracks and play audio tracks.
-               W.Zimmermann, Nov. 8, 1994
-       V0.3    Recognition of missing drive during boot up improved (speeded up).
-               W.Zimmermann, Nov. 13, 1994
-       V0.35   Rewrote the control mechanism in azt_poll (formerly mcd_poll) 
-               including removal of all 'goto' commands. :-); 
-               J. Nardone, Nov. 14, 1994
-       V0.4    Renamed variables and constants to 'azt' instead of 'mcd'; had
-               to make some "compatibility" defines in azt.h; please note,
-               that the source file was renamed to azt.c, the include file to
-               azt.h                
-               Speeded up drive recognition during init (will be a little bit 
-               slower than before if no drive is installed!); suggested by
-               Robby Schirmer.
-               read_count declared volatile and set to AZT_BUF_SIZ to make
-               drive faster (now 300kB/sec, was 60kB/sec before, measured
-               by 'time dd if=/dev/cdrom of=/dev/null bs=2048 count=4096';
-               different AZT_BUF_SIZes were test, above 16 no further im-
-               provement seems to be possible; suggested by E.Moenkeberg.
-               W.Zimmermann, Nov. 18, 1994
-       V0.42   Included getAztStatus command in GetQChannelInfo() to allow
-               reading Q-channel info on audio disks, if drive is stopped, 
-               and some other bug fixes in the audio stuff, suggested by 
-               Robby Schirmer.
-               Added more ioctls (reading data in mode 1 and mode 2).
-               Completely removed the old azt_poll() routine.
-               Detection of ORCHID CDS-3110 in aztcd_init implemented.
-               Additional debugging aids (see the readme file).
-               W.Zimmermann, Dec. 9, 1994  
-       V0.50   Autodetection of drives implemented.
-               W.Zimmermann, Dec. 12, 1994
-       V0.52   Prepared for including in the standard kernel, renamed most
-               variables to contain 'azt', included autoconf.h
-               W.Zimmermann, Dec. 16, 1994        
-       V0.6    Version for being included in the standard Linux kernel.
-               Renamed source and header file to aztcd.c and aztcd.h
-               W.Zimmermann, Dec. 24, 1994
-       V0.7    Changed VERIFY_READ to VERIFY_WRITE in aztcd_ioctl, case
-               CDROMREADMODE1 and CDROMREADMODE2; bug fix in the ioctl,
-               which causes kernel crashes when playing audio, changed 
-               include-files (config.h instead of autoconf.h, removed
-               delay.h)
-               W.Zimmermann, Jan. 8, 1995
-       V0.72   Some more modifications for adaption to the standard kernel.
-               W.Zimmermann, Jan. 16, 1995
-        V0.80   aztcd is now part of the standard kernel since version 1.1.83.
-                Modified the SET_TIMER and CLEAR_TIMER macros to comply with
-                the new timer scheme.
-                W.Zimmermann, Jan. 21, 1995
-        V0.90   Included CDROMVOLCTRL, but with my Aztech drive I can only turn
-                the channels on and off. If it works better with your drive, 
-                please mail me. Also implemented ACMD_CLOSE for CDROMSTART.
-                W.Zimmermann, Jan. 24, 1995
-        V1.00   Implemented close and lock tray commands. Patches supplied by
-               Frank Racis        
-                Added support for loadable MODULEs, so aztcd can now also be
-                loaded by insmod and removed by rmmod during run time
-                Werner Zimmermann, Mar. 24, 95
-        V1.10   Implemented soundcard configuration for Orchid CDS-3110 drives
-                connected to Soundwave32 cards. Release for LST 2.1.
-                (still experimental)
-                Werner Zimmermann, May 8, 95
-        V1.20   Implemented limited support for DOSEMU0.60's cdrom.c. Now it works, but
-                sometimes DOSEMU may hang for 30 seconds or so. A fully functional ver-
-                sion needs an update of Dosemu0.60's cdrom.c, which will come with the 
-                next revision of Dosemu.
-                Also Soundwave32 support now works.
-                Werner Zimmermann, May 22, 95
-       V1.30   Auto-eject feature. Inspired by Franc Racis (racis@psu.edu)
-               Werner Zimmermann, July 4, 95
-       V1.40   Started multisession support. Implementation copied from mcdx.c
-               by Heiko Schlittermann. Not tested yet.
-               Werner Zimmermann, July 15, 95
-        V1.50   Implementation of ioctl CDROMRESET, continued multisession, began
-                XA, but still untested. Heavy modifications to drive status de-
-                tection.
-                Werner Zimmermann, July 25, 95
-        V1.60   XA support now should work. Speeded up drive recognition in cases, 
-                where no drive is installed.
-                Werner Zimmermann, August 8, 1995
-        V1.70   Multisession support now is completed, but there is still not 
-                enough testing done. If you can test it, please contact me. For
-                details please read Documentation/cdrom/aztcd
-                Werner Zimmermann, August 19, 1995
-        V1.80   Modification to suit the new kernel boot procedure introduced
-                with kernel 1.3.33. Will definitely not work with older kernels.
-                Programming done by Linus himself.
-                Werner Zimmermann, October 11, 1995
-       V1.90   Support for Conrad TXC drives, thank's to Jochen Kunz and Olaf Kaluza.
-               Werner Zimmermann, October 21, 1995
-        V2.00   Changed #include "blk.h" to <linux/blk.h> as the directory
-                structure was changed. README.aztcd is now /usr/src/docu-
-                mentation/cdrom/aztcd
-                Werner Zimmermann, November 10, 95
-        V2.10   Started to modify azt_poll to prevent reading beyond end of
-                tracks.
-                Werner Zimmermann, December 3, 95
-        V2.20   Changed some comments
-                Werner Zimmermann, April 1, 96
-        V2.30   Implemented support for CyCDROM CR520, CR940, Code for CR520 
-               delivered by H.Berger with preworks by E.Moenkeberg.
-                Werner Zimmermann, April 29, 96
-        V2.40   Reorganized the placement of functions in the source code file
-                to reflect the layered approach; did not actually change code
-                Werner Zimmermann, May 1, 96
-        V2.50   Heiko Eissfeldt suggested to remove some VERIFY_READs in 
-                aztcd_ioctl; check_aztcd_media_change modified 
-                Werner Zimmermann, May 16, 96       
-       V2.60   Implemented Auto-Probing; made changes for kernel's 2.1.xx blocksize
-                Adaption to linux kernel > 2.1.0
-               Werner Zimmermann, Nov 29, 97
-               
-        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>
-*/
-
-#include <linux/blkdev.h>
-#include "aztcd.h"
-
-#include <linux/module.h>
-#include <linux/errno.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/string.h>
-#include <linux/major.h>
-
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include <asm/uaccess.h>
-
-/*###########################################################################
-  Defines
-  ###########################################################################
-*/
-
-#define MAJOR_NR AZTECH_CDROM_MAJOR
-#define QUEUE (azt_queue)
-#define CURRENT elv_next_request(azt_queue)
-#define SET_TIMER(func, jifs)   delay_timer.expires = jiffies + (jifs); \
-                                delay_timer.function = (void *) (func); \
-                                add_timer(&delay_timer);
-
-#define CLEAR_TIMER             del_timer(&delay_timer);
-
-#define RETURNM(message,value) {printk("aztcd: Warning: %s failed\n",message);\
-                                return value;}
-#define RETURN(message)        {printk("aztcd: Warning: %s failed\n",message);\
-                                return;}
-
-/* Macros to switch the IDE-interface to the slave device and back to the master*/
-#define SWITCH_IDE_SLAVE  outb_p(0xa0,azt_port+6); \
-                         outb_p(0x10,azt_port+6); \
-                         outb_p(0x00,azt_port+7); \
-                         outb_p(0x10,azt_port+6);
-#define SWITCH_IDE_MASTER outb_p(0xa0,azt_port+6);
-
-
-#if 0
-#define AZT_TEST
-#define AZT_TEST1              /* <int-..> */
-#define AZT_TEST2              /* do_aztcd_request */
-#define AZT_TEST3              /* AZT_S_state */
-#define AZT_TEST4              /* QUICK_LOOP-counter */
-#define AZT_TEST5              /* port(1) state */
-#define AZT_DEBUG
-#define AZT_DEBUG_MULTISESSION
-#endif
-
-static struct request_queue *azt_queue;
-
-static int current_valid(void)
-{
-        return CURRENT &&
-               rq_data_dir(CURRENT) == READ &&
-               CURRENT->sector != -1;
-}
-
-#define AFL_STATUSorDATA (AFL_STATUS | AFL_DATA)
-#define AZT_BUF_SIZ 16
-
-#define READ_TIMEOUT 3000
-
-#define azt_port aztcd         /*needed for the modutils */
-
-/*##########################################################################
-  Type Definitions
-  ##########################################################################
-*/
-enum azt_state_e { AZT_S_IDLE, /* 0 */
-       AZT_S_START,            /* 1 */
-       AZT_S_MODE,             /* 2 */
-       AZT_S_READ,             /* 3 */
-       AZT_S_DATA,             /* 4 */
-       AZT_S_STOP,             /* 5 */
-       AZT_S_STOPPING          /* 6 */
-};
-enum azt_read_modes { AZT_MODE_0,      /*read mode for audio disks, not supported by Aztech firmware */
-       AZT_MODE_1,             /*read mode for normal CD-ROMs */
-       AZT_MODE_2              /*read mode for XA CD-ROMs */
-};
-
-/*##########################################################################
-  Global Variables
-  ##########################################################################
-*/
-static int aztPresent = 0;
-
-static volatile int azt_transfer_is_active = 0;
-
-static char azt_buf[CD_FRAMESIZE_RAW * AZT_BUF_SIZ];   /*buffer for block size conversion */
-#if AZT_PRIVATE_IOCTLS
-static char buf[CD_FRAMESIZE_RAW];     /*separate buffer for the ioctls */
-#endif
-
-static volatile int azt_buf_bn[AZT_BUF_SIZ], azt_next_bn;
-static volatile int azt_buf_in, azt_buf_out = -1;
-static volatile int azt_error = 0;
-static int azt_open_count = 0;
-static volatile enum azt_state_e azt_state = AZT_S_IDLE;
-#ifdef AZT_TEST3
-static volatile enum azt_state_e azt_state_old = AZT_S_STOP;
-static volatile int azt_st_old = 0;
-#endif
-static volatile enum azt_read_modes azt_read_mode = AZT_MODE_1;
-
-static int azt_mode = -1;
-static volatile int azt_read_count = 1;
-
-static int azt_port = AZT_BASE_ADDR;
-
-module_param(azt_port, int, 0);
-
-static int azt_port_auto[16] = AZT_BASE_AUTO;
-
-static char azt_cont = 0;
-static char azt_init_end = 0;
-static char azt_auto_eject = AZT_AUTO_EJECT;
-
-static int AztTimeout, AztTries;
-static DECLARE_WAIT_QUEUE_HEAD(azt_waitq);
-static DEFINE_TIMER(delay_timer, NULL, 0, 0);
-
-static struct azt_DiskInfo DiskInfo;
-static struct azt_Toc Toc[MAX_TRACKS];
-static struct azt_Play_msf azt_Play;
-
-static int aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-static char aztDiskChanged = 1;
-static char aztTocUpToDate = 0;
-
-static unsigned char aztIndatum;
-static unsigned long aztTimeOutCount;
-static int aztCmd = 0;
-
-static DEFINE_SPINLOCK(aztSpin);
-
-/*###########################################################################
-   Function Prototypes
-  ###########################################################################
-*/
-/* CDROM Drive Low Level I/O Functions */
-static void aztStatTimer(void);
-
-/* CDROM Drive Command Functions */
-static int aztGetDiskInfo(void);
-#if AZT_MULTISESSION
-static int aztGetMultiDiskInfo(void);
-#endif
-static int aztGetToc(int multi);
-
-/* Kernel Interface Functions */
-static int check_aztcd_media_change(struct gendisk *disk);
-static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
-                      unsigned long arg);
-static int aztcd_open(struct inode *ip, struct file *fp);
-static int aztcd_release(struct inode *inode, struct file *file);
-
-static struct block_device_operations azt_fops = {
-       .owner          = THIS_MODULE,
-       .open           = aztcd_open,
-       .release        = aztcd_release,
-       .ioctl          = aztcd_ioctl,
-       .media_changed  = check_aztcd_media_change,
-};
-
-/* Aztcd State Machine: Controls Drive Operating State */
-static void azt_poll(void);
-
-/* Miscellaneous support functions */
-static void azt_hsg2msf(long hsg, struct msf *msf);
-static long azt_msf2hsg(struct msf *mp);
-static void azt_bin2bcd(unsigned char *p);
-static int azt_bcd2bin(unsigned char bcd);
-
-/*##########################################################################
-  CDROM Drive Low Level I/O Functions
-  ##########################################################################
-*/
-/* Macros for the drive hardware interface handshake, these macros use
-   busy waiting */
-/* Wait for OP_OK = drive answers with AFL_OP_OK after receiving a command*/
-# define OP_OK op_ok()
-static void op_ok(void)
-{
-       aztTimeOutCount = 0;
-       do {
-               aztIndatum = inb(DATA_PORT);
-               aztTimeOutCount++;
-               if (aztTimeOutCount >= AZT_TIMEOUT) {
-                       printk("aztcd: Error Wait OP_OK\n");
-                       break;
-               }
-       } while (aztIndatum != AFL_OP_OK);
-}
-
-/* Wait for PA_OK = drive answers with AFL_PA_OK after receiving parameters*/
-#if 0
-# define PA_OK pa_ok()
-static void pa_ok(void)
-{
-       aztTimeOutCount = 0;
-       do {
-               aztIndatum = inb(DATA_PORT);
-               aztTimeOutCount++;
-               if (aztTimeOutCount >= AZT_TIMEOUT) {
-                       printk("aztcd: Error Wait PA_OK\n");
-                       break;
-               }
-       } while (aztIndatum != AFL_PA_OK);
-}
-#endif
-
-/* Wait for STEN=Low = handshake signal 'AFL_.._OK available or command executed*/
-# define STEN_LOW  sten_low()
-static void sten_low(void)
-{
-       aztTimeOutCount = 0;
-       do {
-               aztIndatum = inb(STATUS_PORT);
-               aztTimeOutCount++;
-               if (aztTimeOutCount >= AZT_TIMEOUT) {
-                       if (azt_init_end)
-                               printk
-                                   ("aztcd: Error Wait STEN_LOW commands:%x\n",
-                                    aztCmd);
-                       break;
-               }
-       } while (aztIndatum & AFL_STATUS);
-}
-
-/* Wait for DTEN=Low = handshake signal 'Data available'*/
-# define DTEN_LOW dten_low()
-static void dten_low(void)
-{
-       aztTimeOutCount = 0;
-       do {
-               aztIndatum = inb(STATUS_PORT);
-               aztTimeOutCount++;
-               if (aztTimeOutCount >= AZT_TIMEOUT) {
-                       printk("aztcd: Error Wait DTEN_OK\n");
-                       break;
-               }
-       } while (aztIndatum & AFL_DATA);
-}
-
-/* 
- * Macro for timer wait on STEN=Low, should only be used for 'slow' commands;
- * may cause kernel panic when used in the wrong place
-*/
-#define STEN_LOW_WAIT   statusAzt()
-static void statusAzt(void)
-{
-       AztTimeout = AZT_STATUS_DELAY;
-       SET_TIMER(aztStatTimer, HZ / 100);
-       sleep_on(&azt_waitq);
-       if (AztTimeout <= 0)
-               printk("aztcd: Error Wait STEN_LOW_WAIT command:%x\n",
-                      aztCmd);
-       return;
-}
-
-static void aztStatTimer(void)
-{
-       if (!(inb(STATUS_PORT) & AFL_STATUS)) {
-               wake_up(&azt_waitq);
-               return;
-       }
-       AztTimeout--;
-       if (AztTimeout <= 0) {
-               wake_up(&azt_waitq);
-               printk("aztcd: Error aztStatTimer: Timeout\n");
-               return;
-       }
-       SET_TIMER(aztStatTimer, HZ / 100);
-}
-
-/*##########################################################################
-  CDROM Drive Command Functions
-  ##########################################################################
-*/
-/* 
- * Send a single command, return -1 on error, else 0
-*/
-static int aztSendCmd(int cmd)
-{
-       unsigned char data;
-       int retry;
-
-#ifdef AZT_DEBUG
-       printk("aztcd: Executing command %x\n", cmd);
-#endif
-
-       if ((azt_port == 0x1f0) || (azt_port == 0x170))
-               SWITCH_IDE_SLAVE;       /*switch IDE interface to slave configuration */
-
-       aztCmd = cmd;
-       outb(POLLED, MODE_PORT);
-       do {
-               if (inb(STATUS_PORT) & AFL_STATUS)
-                       break;
-               inb(DATA_PORT); /* if status left from last command, read and */
-       } while (1);            /* discard it */
-       do {
-               if (inb(STATUS_PORT) & AFL_DATA)
-                       break;
-               inb(DATA_PORT); /* if data left from last command, read and */
-       } while (1);            /* discard it */
-       for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
-               outb((unsigned char) cmd, CMD_PORT);
-               STEN_LOW;
-               data = inb(DATA_PORT);
-               if (data == AFL_OP_OK) {
-                       return 0;
-               }               /*OP_OK? */
-               if (data == AFL_OP_ERR) {
-                       STEN_LOW;
-                       data = inb(DATA_PORT);
-                       printk
-                           ("### Error 1 aztcd: aztSendCmd %x  Error Code %x\n",
-                            cmd, data);
-               }
-       }
-       if (retry >= AZT_RETRY_ATTEMPTS) {
-               printk("### Error 2 aztcd: aztSendCmd %x \n", cmd);
-               azt_error = 0xA5;
-       }
-       RETURNM("aztSendCmd", -1);
-}
-
-/*
- * Send a play or read command to the drive, return -1 on error, else 0
-*/
-static int sendAztCmd(int cmd, struct azt_Play_msf *params)
-{
-       unsigned char data;
-       int retry;
-
-#ifdef AZT_DEBUG
-       printk("aztcd: play start=%02x:%02x:%02x  end=%02x:%02x:%02x\n",
-              params->start.min, params->start.sec, params->start.frame,
-              params->end.min, params->end.sec, params->end.frame);
-#endif
-       for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
-               aztSendCmd(cmd);
-               outb(params->start.min, CMD_PORT);
-               outb(params->start.sec, CMD_PORT);
-               outb(params->start.frame, CMD_PORT);
-               outb(params->end.min, CMD_PORT);
-               outb(params->end.sec, CMD_PORT);
-               outb(params->end.frame, CMD_PORT);
-               STEN_LOW;
-               data = inb(DATA_PORT);
-               if (data == AFL_PA_OK) {
-                       return 0;
-               }               /*PA_OK ? */
-               if (data == AFL_PA_ERR) {
-                       STEN_LOW;
-                       data = inb(DATA_PORT);
-                       printk
-                           ("### Error 1 aztcd: sendAztCmd %x  Error Code %x\n",
-                            cmd, data);
-               }
-       }
-       if (retry >= AZT_RETRY_ATTEMPTS) {
-               printk("### Error 2 aztcd: sendAztCmd %x\n ", cmd);
-               azt_error = 0xA5;
-       }
-       RETURNM("sendAztCmd", -1);
-}
-
-/*
- * Send a seek command to the drive, return -1 on error, else 0
-*/
-static int aztSeek(struct azt_Play_msf *params)
-{
-       unsigned char data;
-       int retry;
-
-#ifdef AZT_DEBUG
-       printk("aztcd: aztSeek %02x:%02x:%02x\n",
-              params->start.min, params->start.sec, params->start.frame);
-#endif
-       for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
-               aztSendCmd(ACMD_SEEK);
-               outb(params->start.min, CMD_PORT);
-               outb(params->start.sec, CMD_PORT);
-               outb(params->start.frame, CMD_PORT);
-               STEN_LOW;
-               data = inb(DATA_PORT);
-               if (data == AFL_PA_OK) {
-                       return 0;
-               }               /*PA_OK ? */
-               if (data == AFL_PA_ERR) {
-                       STEN_LOW;
-                       data = inb(DATA_PORT);
-                       printk("### Error 1 aztcd: aztSeek\n");
-               }
-       }
-       if (retry >= AZT_RETRY_ATTEMPTS) {
-               printk("### Error 2 aztcd: aztSeek\n ");
-               azt_error = 0xA5;
-       }
-       RETURNM("aztSeek", -1);
-}
-
-/* Send a Set Disk Type command
-   does not seem to work with Aztech drives, behavior is completely indepen-
-   dent on which mode is set ???
-*/
-static int aztSetDiskType(int type)
-{
-       unsigned char data;
-       int retry;
-
-#ifdef AZT_DEBUG
-       printk("aztcd: set disk type command: type= %i\n", type);
-#endif
-       for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
-               aztSendCmd(ACMD_SET_DISK_TYPE);
-               outb(type, CMD_PORT);
-               STEN_LOW;
-               data = inb(DATA_PORT);
-               if (data == AFL_PA_OK) {        /*PA_OK ? */
-                       azt_read_mode = type;
-                       return 0;
-               }
-               if (data == AFL_PA_ERR) {
-                       STEN_LOW;
-                       data = inb(DATA_PORT);
-                       printk
-                           ("### Error 1 aztcd: aztSetDiskType %x Error Code %x\n",
-                            type, data);
-               }
-       }
-       if (retry >= AZT_RETRY_ATTEMPTS) {
-               printk("### Error 2 aztcd: aztSetDiskType %x\n ", type);
-               azt_error = 0xA5;
-       }
-       RETURNM("aztSetDiskType", -1);
-}
-
-
-/* used in azt_poll to poll the status, expects another program to issue a 
- * ACMD_GET_STATUS directly before 
- */
-static int aztStatus(void)
-{
-       int st;
-/*     int i;
-
-       i = inb(STATUS_PORT) & AFL_STATUS;    is STEN=0?    ???
-       if (!i)
-*/ STEN_LOW;
-       if (aztTimeOutCount < AZT_TIMEOUT) {
-               st = inb(DATA_PORT) & 0xFF;
-               return st;
-       } else
-               RETURNM("aztStatus", -1);
-}
-
-/*
- * Get the drive status
- */
-static int getAztStatus(void)
-{
-       int st;
-
-       if (aztSendCmd(ACMD_GET_STATUS))
-               RETURNM("getAztStatus 1", -1);
-       STEN_LOW;
-       st = inb(DATA_PORT) & 0xFF;
-#ifdef AZT_DEBUG
-       printk("aztcd: Status = %x\n", st);
-#endif
-       if ((st == 0xFF) || (st & AST_CMD_CHECK)) {
-               printk
-                   ("aztcd: AST_CMD_CHECK error or no status available\n");
-               return -1;
-       }
-
-       if (((st & AST_MODE_BITS) != AST_BUSY)
-           && (aztAudioStatus == CDROM_AUDIO_PLAY))
-               /* XXX might be an error? look at q-channel? */
-               aztAudioStatus = CDROM_AUDIO_COMPLETED;
-
-       if ((st & AST_DSK_CHG) || (st & AST_NOT_READY)) {
-               aztDiskChanged = 1;
-               aztTocUpToDate = 0;
-               aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-       }
-       return st;
-}
-
-
-/*
- * Send a 'Play' command and get the status.  Use only from the top half.
- */
-static int aztPlay(struct azt_Play_msf *arg)
-{
-       if (sendAztCmd(ACMD_PLAY_AUDIO, arg) < 0)
-               RETURNM("aztPlay", -1);
-       return 0;
-}
-
-/*
- * Subroutines to automatically close the door (tray) and 
- * lock it closed when the cd is mounted.  Leave the tray
- * locking as an option
- */
-static void aztCloseDoor(void)
-{
-       aztSendCmd(ACMD_CLOSE);
-       STEN_LOW;
-       return;
-}
-
-static void aztLockDoor(void)
-{
-#if AZT_ALLOW_TRAY_LOCK
-       aztSendCmd(ACMD_LOCK);
-       STEN_LOW;
-#endif
-       return;
-}
-
-static void aztUnlockDoor(void)
-{
-#if AZT_ALLOW_TRAY_LOCK
-       aztSendCmd(ACMD_UNLOCK);
-       STEN_LOW;
-#endif
-       return;
-}
-
-/*
- * Read a value from the drive.  Should return quickly, so a busy wait
- * is used to avoid excessive rescheduling. The read command itself must
- * be issued with aztSendCmd() directly before
- */
-static int aztGetValue(unsigned char *result)
-{
-       int s;
-
-       STEN_LOW;
-       if (aztTimeOutCount >= AZT_TIMEOUT) {
-               printk("aztcd: aztGetValue timeout\n");
-               return -1;
-       }
-       s = inb(DATA_PORT) & 0xFF;
-       *result = (unsigned char) s;
-       return 0;
-}
-
-/*
- * Read the current Q-channel info.  Also used for reading the
- * table of contents.
- */
-static int aztGetQChannelInfo(struct azt_Toc *qp)
-{
-       unsigned char notUsed;
-       int st;
-
-#ifdef AZT_DEBUG
-       printk("aztcd: starting aztGetQChannelInfo  Time:%li\n", jiffies);
-#endif
-       if ((st = getAztStatus()) == -1)
-               RETURNM("aztGetQChannelInfo 1", -1);
-       if (aztSendCmd(ACMD_GET_Q_CHANNEL))
-               RETURNM("aztGetQChannelInfo 2", -1);
-       /*STEN_LOW_WAIT; ??? Dosemu0.60's cdrom.c does not like STEN_LOW_WAIT here */
-       if (aztGetValue(&notUsed))
-               RETURNM("aztGetQChannelInfo 3", -1);    /*??? Nullbyte einlesen */
-       if ((st & AST_MODE_BITS) == AST_INITIAL) {
-               qp->ctrl_addr = 0;      /* when audio stop ACMD_GET_Q_CHANNEL returns */
-               qp->track = 0;  /* only one byte with Aztech drives */
-               qp->pointIndex = 0;
-               qp->trackTime.min = 0;
-               qp->trackTime.sec = 0;
-               qp->trackTime.frame = 0;
-               qp->diskTime.min = 0;
-               qp->diskTime.sec = 0;
-               qp->diskTime.frame = 0;
-               return 0;
-       } else {
-               if (aztGetValue(&qp->ctrl_addr) < 0)
-                       RETURNM("aztGetQChannelInfo 4", -1);
-               if (aztGetValue(&qp->track) < 0)
-                       RETURNM("aztGetQChannelInfo 4", -1);
-               if (aztGetValue(&qp->pointIndex) < 0)
-                       RETURNM("aztGetQChannelInfo 4", -1);
-               if (aztGetValue(&qp->trackTime.min) < 0)
-                       RETURNM("aztGetQChannelInfo 4", -1);
-               if (aztGetValue(&qp->trackTime.sec) < 0)
-                       RETURNM("aztGetQChannelInfo 4", -1);
-               if (aztGetValue(&qp->trackTime.frame) < 0)
-                       RETURNM("aztGetQChannelInfo 4", -1);
-               if (aztGetValue(&notUsed) < 0)
-                       RETURNM("aztGetQChannelInfo 4", -1);
-               if (aztGetValue(&qp->diskTime.min) < 0)
-                       RETURNM("aztGetQChannelInfo 4", -1);
-               if (aztGetValue(&qp->diskTime.sec) < 0)
-                       RETURNM("aztGetQChannelInfo 4", -1);
-               if (aztGetValue(&qp->diskTime.frame) < 0)
-                       RETURNM("aztGetQChannelInfo 4", -1);
-       }
-#ifdef AZT_DEBUG
-       printk("aztcd: exiting aztGetQChannelInfo  Time:%li\n", jiffies);
-#endif
-       return 0;
-}
-
-/*
- * Read the table of contents (TOC) and TOC header if necessary
- */
-static int aztUpdateToc(void)
-{
-       int st;
-
-#ifdef AZT_DEBUG
-       printk("aztcd: starting aztUpdateToc  Time:%li\n", jiffies);
-#endif
-       if (aztTocUpToDate)
-               return 0;
-
-       if (aztGetDiskInfo() < 0)
-               return -EIO;
-
-       if (aztGetToc(0) < 0)
-               return -EIO;
-
-       /*audio disk detection
-          with my Aztech drive there is no audio status bit, so I use the copy
-          protection bit of the first track. If this track is copy protected 
-          (copy bit = 0), I assume, it's an audio  disk. Strange, but works ??? */
-       if (!(Toc[DiskInfo.first].ctrl_addr & 0x40))
-               DiskInfo.audio = 1;
-       else
-               DiskInfo.audio = 0;
-
-       /* XA detection */
-       if (!DiskInfo.audio) {
-               azt_Play.start.min = 0; /*XA detection only seems to work */
-               azt_Play.start.sec = 2; /*when we play a track */
-               azt_Play.start.frame = 0;
-               azt_Play.end.min = 0;
-               azt_Play.end.sec = 0;
-               azt_Play.end.frame = 1;
-               if (sendAztCmd(ACMD_PLAY_READ, &azt_Play))
-                       return -1;
-               DTEN_LOW;
-               for (st = 0; st < CD_FRAMESIZE; st++)
-                       inb(DATA_PORT);
-       }
-       DiskInfo.xa = getAztStatus() & AST_MODE;
-       if (DiskInfo.xa) {
-               printk
-                   ("aztcd: XA support experimental - mail results to Werner.Zimmermann@fht-esslingen.de\n");
-       }
-
-       /*multisession detection
-          support for multisession CDs is done automatically with Aztech drives,
-          we don't have to take care about TOC redirection; if we want the isofs
-          to take care about redirection, we have to set AZT_MULTISESSION to 1 */
-       DiskInfo.multi = 0;
-#if AZT_MULTISESSION
-       if (DiskInfo.xa) {
-               aztGetMultiDiskInfo();  /*here Disk.Info.multi is set */
-       }
-#endif
-       if (DiskInfo.multi) {
-               DiskInfo.lastSession.min = Toc[DiskInfo.next].diskTime.min;
-               DiskInfo.lastSession.sec = Toc[DiskInfo.next].diskTime.sec;
-               DiskInfo.lastSession.frame =
-                   Toc[DiskInfo.next].diskTime.frame;
-               printk("aztcd: Multisession support experimental\n");
-       } else {
-               DiskInfo.lastSession.min =
-                   Toc[DiskInfo.first].diskTime.min;
-               DiskInfo.lastSession.sec =
-                   Toc[DiskInfo.first].diskTime.sec;
-               DiskInfo.lastSession.frame =
-                   Toc[DiskInfo.first].diskTime.frame;
-       }
-
-       aztTocUpToDate = 1;
-#ifdef AZT_DEBUG
-       printk("aztcd: exiting aztUpdateToc  Time:%li\n", jiffies);
-#endif
-       return 0;
-}
-
-
-/* Read the table of contents header, i.e. no. of tracks and start of first 
- * track
- */
-static int aztGetDiskInfo(void)
-{
-       int limit;
-       unsigned char test;
-       struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
-       printk("aztcd: starting aztGetDiskInfo  Time:%li\n", jiffies);
-#endif
-       if (aztSendCmd(ACMD_SEEK_TO_LEADIN))
-               RETURNM("aztGetDiskInfo 1", -1);
-       STEN_LOW_WAIT;
-       test = 0;
-       for (limit = 300; limit > 0; limit--) {
-               if (aztGetQChannelInfo(&qInfo) < 0)
-                       RETURNM("aztGetDiskInfo 2", -1);
-               if (qInfo.pointIndex == 0xA0) { /*Number of FirstTrack */
-                       DiskInfo.first = qInfo.diskTime.min;
-                       DiskInfo.first = azt_bcd2bin(DiskInfo.first);
-                       test = test | 0x01;
-               }
-               if (qInfo.pointIndex == 0xA1) { /*Number of LastTrack */
-                       DiskInfo.last = qInfo.diskTime.min;
-                       DiskInfo.last = azt_bcd2bin(DiskInfo.last);
-                       test = test | 0x02;
-               }
-               if (qInfo.pointIndex == 0xA2) { /*DiskLength */
-                       DiskInfo.diskLength.min = qInfo.diskTime.min;
-                       DiskInfo.diskLength.sec = qInfo.diskTime.sec;
-                       DiskInfo.diskLength.frame = qInfo.diskTime.frame;
-                       test = test | 0x04;
-               }
-               if ((qInfo.pointIndex == DiskInfo.first) && (test & 0x01)) {    /*StartTime of First Track */
-                       DiskInfo.firstTrack.min = qInfo.diskTime.min;
-                       DiskInfo.firstTrack.sec = qInfo.diskTime.sec;
-                       DiskInfo.firstTrack.frame = qInfo.diskTime.frame;
-                       test = test | 0x08;
-               }
-               if (test == 0x0F)
-                       break;
-       }
-#ifdef AZT_DEBUG
-       printk("aztcd: exiting aztGetDiskInfo  Time:%li\n", jiffies);
-       printk
-           ("Disk Info: first %d last %d length %02X:%02X.%02X dez  first %02X:%02X.%02X dez\n",
-            DiskInfo.first, DiskInfo.last, DiskInfo.diskLength.min,
-            DiskInfo.diskLength.sec, DiskInfo.diskLength.frame,
-            DiskInfo.firstTrack.min, DiskInfo.firstTrack.sec,
-            DiskInfo.firstTrack.frame);
-#endif
-       if (test != 0x0F)
-               return -1;
-       return 0;
-}
-
-#if AZT_MULTISESSION
-/*
- * Get Multisession Disk Info
- */
-static int aztGetMultiDiskInfo(void)
-{
-       int limit, k = 5;
-       unsigned char test;
-       struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
-       printk("aztcd: starting aztGetMultiDiskInfo\n");
-#endif
-
-       do {
-               azt_Play.start.min = Toc[DiskInfo.last + 1].diskTime.min;
-               azt_Play.start.sec = Toc[DiskInfo.last + 1].diskTime.sec;
-               azt_Play.start.frame =
-                   Toc[DiskInfo.last + 1].diskTime.frame;
-               test = 0;
-
-               for (limit = 30; limit > 0; limit--) {  /*Seek for LeadIn of next session */
-                       if (aztSeek(&azt_Play))
-                               RETURNM("aztGetMultiDiskInfo 1", -1);
-                       if (aztGetQChannelInfo(&qInfo) < 0)
-                               RETURNM("aztGetMultiDiskInfo 2", -1);
-                       if ((qInfo.track == 0) && (qInfo.pointIndex))
-                               break;  /*LeadIn found */
-                       if ((azt_Play.start.sec += 10) > 59) {
-                               azt_Play.start.sec = 0;
-                               azt_Play.start.min++;
-                       }
-               }
-               if (!limit)
-                       break;  /*Check, if a leadin track was found, if not we're
-                                  at the end of the disk */
-#ifdef AZT_DEBUG_MULTISESSION
-               printk("leadin found track %d  pointIndex %x  limit %d\n",
-                      qInfo.track, qInfo.pointIndex, limit);
-#endif
-               for (limit = 300; limit > 0; limit--) {
-                       if (++azt_Play.start.frame > 74) {
-                               azt_Play.start.frame = 0;
-                               if (azt_Play.start.sec > 59) {
-                                       azt_Play.start.sec = 0;
-                                       azt_Play.start.min++;
-                               }
-                       }
-                       if (aztSeek(&azt_Play))
-                               RETURNM("aztGetMultiDiskInfo 3", -1);
-                       if (aztGetQChannelInfo(&qInfo) < 0)
-                               RETURNM("aztGetMultiDiskInfo 4", -1);
-                       if (qInfo.pointIndex == 0xA0) { /*Number of NextTrack */
-                               DiskInfo.next = qInfo.diskTime.min;
-                               DiskInfo.next = azt_bcd2bin(DiskInfo.next);
-                               test = test | 0x01;
-                       }
-                       if (qInfo.pointIndex == 0xA1) { /*Number of LastTrack */
-                               DiskInfo.last = qInfo.diskTime.min;
-                               DiskInfo.last = azt_bcd2bin(DiskInfo.last);
-                               test = test | 0x02;
-                       }
-                       if (qInfo.pointIndex == 0xA2) { /*DiskLength */
-                               DiskInfo.diskLength.min =
-                                   qInfo.diskTime.min;
-                               DiskInfo.diskLength.sec =
-                                   qInfo.diskTime.sec;
-                               DiskInfo.diskLength.frame =
-                                   qInfo.diskTime.frame;
-                               test = test | 0x04;
-                       }
-                       if ((qInfo.pointIndex == DiskInfo.next) && (test & 0x01)) {     /*StartTime of Next Track */
-                               DiskInfo.nextSession.min =
-                                   qInfo.diskTime.min;
-                               DiskInfo.nextSession.sec =
-                                   qInfo.diskTime.sec;
-                               DiskInfo.nextSession.frame =
-                                   qInfo.diskTime.frame;
-                               test = test | 0x08;
-                       }
-                       if (test == 0x0F)
-                               break;
-               }
-#ifdef AZT_DEBUG_MULTISESSION
-               printk
-                   ("MultiDisk Info: first %d next %d last %d length %02x:%02x.%02x dez  first %02x:%02x.%02x dez  next %02x:%02x.%02x dez\n",
-                    DiskInfo.first, DiskInfo.next, DiskInfo.last,
-                    DiskInfo.diskLength.min, DiskInfo.diskLength.sec,
-                    DiskInfo.diskLength.frame, DiskInfo.firstTrack.min,
-                    DiskInfo.firstTrack.sec, DiskInfo.firstTrack.frame,
-                    DiskInfo.nextSession.min, DiskInfo.nextSession.sec,
-                    DiskInfo.nextSession.frame);
-#endif
-               if (test != 0x0F)
-                       break;
-               else
-                       DiskInfo.multi = 1;     /*found TOC of more than one session */
-               aztGetToc(1);
-       } while (--k);
-
-#ifdef AZT_DEBUG
-       printk("aztcd: exiting aztGetMultiDiskInfo  Time:%li\n", jiffies);
-#endif
-       return 0;
-}
-#endif
-
-/*
- * Read the table of contents (TOC)
- */
-static int aztGetToc(int multi)
-{
-       int i, px;
-       int limit;
-       struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
-       printk("aztcd: starting aztGetToc  Time:%li\n", jiffies);
-#endif
-       if (!multi) {
-               for (i = 0; i < MAX_TRACKS; i++)
-                       Toc[i].pointIndex = 0;
-               i = DiskInfo.last + 3;
-       } else {
-               for (i = DiskInfo.next; i < MAX_TRACKS; i++)
-                       Toc[i].pointIndex = 0;
-               i = DiskInfo.last + 4 - DiskInfo.next;
-       }
-
-/*Is there a good reason to stop motor before TOC read?
-  if (aztSendCmd(ACMD_STOP)) RETURNM("aztGetToc 1",-1);
-      STEN_LOW_WAIT;
-*/
-
-       if (!multi) {
-               azt_mode = 0x05;
-               if (aztSendCmd(ACMD_SEEK_TO_LEADIN))
-                       RETURNM("aztGetToc 2", -1);
-               STEN_LOW_WAIT;
-       }
-       for (limit = 300; limit > 0; limit--) {
-               if (multi) {
-                       if (++azt_Play.start.sec > 59) {
-                               azt_Play.start.sec = 0;
-                               azt_Play.start.min++;
-                       }
-                       if (aztSeek(&azt_Play))
-                               RETURNM("aztGetToc 3", -1);
-               }
-               if (aztGetQChannelInfo(&qInfo) < 0)
-                       break;
-
-               px = azt_bcd2bin(qInfo.pointIndex);
-
-               if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
-                       if (Toc[px].pointIndex == 0) {
-                               Toc[px] = qInfo;
-                               i--;
-                       }
-
-               if (i <= 0)
-                       break;
-       }
-
-       Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
-       Toc[DiskInfo.last].trackTime = DiskInfo.diskLength;
-
-#ifdef AZT_DEBUG_MULTISESSION
-       printk("aztcd: exiting aztGetToc\n");
-       for (i = 1; i <= DiskInfo.last + 1; i++)
-               printk
-                   ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez  %02X:%02X.%02X dez\n",
-                    i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
-                    Toc[i].trackTime.min, Toc[i].trackTime.sec,
-                    Toc[i].trackTime.frame, Toc[i].diskTime.min,
-                    Toc[i].diskTime.sec, Toc[i].diskTime.frame);
-       for (i = 100; i < 103; i++)
-               printk
-                   ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez  %02X:%02X.%02X dez\n",
-                    i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
-                    Toc[i].trackTime.min, Toc[i].trackTime.sec,
-                    Toc[i].trackTime.frame, Toc[i].diskTime.min,
-                    Toc[i].diskTime.sec, Toc[i].diskTime.frame);
-#endif
-
-       return limit > 0 ? 0 : -1;
-}
-
-
-/*##########################################################################
-  Kernel Interface Functions
-  ##########################################################################
-*/
-
-#ifndef MODULE
-static int __init aztcd_setup(char *str)
-{
-       int ints[4];
-
-       (void) get_options(str, ARRAY_SIZE(ints), ints);
-
-       if (ints[0] > 0)
-               azt_port = ints[1];
-       if (ints[1] > 1)
-               azt_cont = ints[2];
-       return 1;
-}
-
-__setup("aztcd=", aztcd_setup);
-
-#endif                         /* !MODULE */
-
-/* 
- * Checking if the media has been changed
-*/
-static int check_aztcd_media_change(struct gendisk *disk)
-{
-       if (aztDiskChanged) {   /* disk changed */
-               aztDiskChanged = 0;
-               return 1;
-       } else
-               return 0;       /* no change */
-}
-
-/*
- * Kernel IO-controls
-*/
-static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
-                      unsigned long arg)
-{
-       int i;
-       struct azt_Toc qInfo;
-       struct cdrom_ti ti;
-       struct cdrom_tochdr tocHdr;
-       struct cdrom_msf msf;
-       struct cdrom_tocentry entry;
-       struct azt_Toc *tocPtr;
-       struct cdrom_subchnl subchnl;
-       struct cdrom_volctrl volctrl;
-       void __user *argp = (void __user *)arg;
-
-#ifdef AZT_DEBUG
-       printk("aztcd: starting aztcd_ioctl - Command:%x   Time: %li\n",
-              cmd, jiffies);
-       printk("aztcd Status %x\n", getAztStatus());
-#endif
-       if (!ip)
-               RETURNM("aztcd_ioctl 1", -EINVAL);
-       if (getAztStatus() < 0)
-               RETURNM("aztcd_ioctl 2", -EIO);
-       if ((!aztTocUpToDate) || (aztDiskChanged)) {
-               if ((i = aztUpdateToc()) < 0)
-                       RETURNM("aztcd_ioctl 3", i);    /* error reading TOC */
-       }
-
-       switch (cmd) {
-       case CDROMSTART:        /* Spin up the drive. Don't know, what to do,
-                                  at least close the tray */
-#if AZT_PRIVATE_IOCTLS
-               if (aztSendCmd(ACMD_CLOSE))
-                       RETURNM("aztcd_ioctl 4", -1);
-               STEN_LOW_WAIT;
-#endif
-               break;
-       case CDROMSTOP: /* Spin down the drive */
-               if (aztSendCmd(ACMD_STOP))
-                       RETURNM("aztcd_ioctl 5", -1);
-               STEN_LOW_WAIT;
-               /* should we do anything if it fails? */
-               aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-               break;
-       case CDROMPAUSE:        /* Pause the drive */
-               if (aztAudioStatus != CDROM_AUDIO_PLAY)
-                       return -EINVAL;
-
-               if (aztGetQChannelInfo(&qInfo) < 0) {   /* didn't get q channel info */
-                       aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-                       RETURNM("aztcd_ioctl 7", 0);
-               }
-               azt_Play.start = qInfo.diskTime;        /* remember restart point */
-
-               if (aztSendCmd(ACMD_PAUSE))
-                       RETURNM("aztcd_ioctl 8", -1);
-               STEN_LOW_WAIT;
-               aztAudioStatus = CDROM_AUDIO_PAUSED;
-               break;
-       case CDROMRESUME:       /* Play it again, Sam */
-               if (aztAudioStatus != CDROM_AUDIO_PAUSED)
-                       return -EINVAL;
-               /* restart the drive at the saved position. */
-               i = aztPlay(&azt_Play);
-               if (i < 0) {
-                       aztAudioStatus = CDROM_AUDIO_ERROR;
-                       return -EIO;
-               }
-               aztAudioStatus = CDROM_AUDIO_PLAY;
-               break;
-       case CDROMMULTISESSION: /*multisession support -- experimental */
-               {
-                       struct cdrom_multisession ms;
-#ifdef AZT_DEBUG
-                       printk("aztcd ioctl MULTISESSION\n");
-#endif
-                       if (copy_from_user(&ms, argp,
-                            sizeof(struct cdrom_multisession)))
-                               return -EFAULT;
-                       if (ms.addr_format == CDROM_MSF) {
-                               ms.addr.msf.minute =
-                                   azt_bcd2bin(DiskInfo.lastSession.min);
-                               ms.addr.msf.second =
-                                   azt_bcd2bin(DiskInfo.lastSession.sec);
-                               ms.addr.msf.frame =
-                                   azt_bcd2bin(DiskInfo.lastSession.
-                                               frame);
-                       } else if (ms.addr_format == CDROM_LBA)
-                               ms.addr.lba =
-                                   azt_msf2hsg(&DiskInfo.lastSession);
-                       else
-                               return -EINVAL;
-                       ms.xa_flag = DiskInfo.xa;
-                       if (copy_to_user(argp, &ms,
-                            sizeof(struct cdrom_multisession)))
-                               return -EFAULT;
-#ifdef AZT_DEBUG
-                       if (ms.addr_format == CDROM_MSF)
-                               printk
-                                   ("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n",
-                                    ms.xa_flag, ms.addr.msf.minute,
-                                    ms.addr.msf.second, ms.addr.msf.frame,
-                                    DiskInfo.lastSession.min,
-                                    DiskInfo.lastSession.sec,
-                                    DiskInfo.lastSession.frame);
-                       else
-                               printk
-                                   ("aztcd multisession %d, lba:0x%08x [%02x:%02x.%02x])\n",
-                                    ms.xa_flag, ms.addr.lba,
-                                    DiskInfo.lastSession.min,
-                                    DiskInfo.lastSession.sec,
-                                    DiskInfo.lastSession.frame);
-#endif
-                       return 0;
-               }
-       case CDROMPLAYTRKIND:   /* Play a track.  This currently ignores index. */
-               if (copy_from_user(&ti, argp, sizeof ti))
-                       return -EFAULT;
-               if (ti.cdti_trk0 < DiskInfo.first
-                   || ti.cdti_trk0 > DiskInfo.last
-                   || ti.cdti_trk1 < ti.cdti_trk0) {
-                       return -EINVAL;
-               }
-               if (ti.cdti_trk1 > DiskInfo.last)
-                       ti.cdti_trk1 = DiskInfo.last;
-               azt_Play.start = Toc[ti.cdti_trk0].diskTime;
-               azt_Play.end = Toc[ti.cdti_trk1 + 1].diskTime;
-#ifdef AZT_DEBUG
-               printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
-                      azt_Play.start.min, azt_Play.start.sec,
-                      azt_Play.start.frame, azt_Play.end.min,
-                      azt_Play.end.sec, azt_Play.end.frame);
-#endif
-               i = aztPlay(&azt_Play);
-               if (i < 0) {
-                       aztAudioStatus = CDROM_AUDIO_ERROR;
-                       return -EIO;
-               }
-               aztAudioStatus = CDROM_AUDIO_PLAY;
-               break;
-       case CDROMPLAYMSF:      /* Play starting at the given MSF address. */
-/*              if (aztAudioStatus == CDROM_AUDIO_PLAY) 
-               { if (aztSendCmd(ACMD_STOP)) RETURNM("aztcd_ioctl 9",-1);
-                 STEN_LOW;
-                 aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-               }
-*/
-               if (copy_from_user(&msf, argp, sizeof msf))
-                       return -EFAULT;
-               /* convert to bcd */
-               azt_bin2bcd(&msf.cdmsf_min0);
-               azt_bin2bcd(&msf.cdmsf_sec0);
-               azt_bin2bcd(&msf.cdmsf_frame0);
-               azt_bin2bcd(&msf.cdmsf_min1);
-               azt_bin2bcd(&msf.cdmsf_sec1);
-               azt_bin2bcd(&msf.cdmsf_frame1);
-               azt_Play.start.min = msf.cdmsf_min0;
-               azt_Play.start.sec = msf.cdmsf_sec0;
-               azt_Play.start.frame = msf.cdmsf_frame0;
-               azt_Play.end.min = msf.cdmsf_min1;
-               azt_Play.end.sec = msf.cdmsf_sec1;
-               azt_Play.end.frame = msf.cdmsf_frame1;
-#ifdef AZT_DEBUG
-               printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
-                      azt_Play.start.min, azt_Play.start.sec,
-                      azt_Play.start.frame, azt_Play.end.min,
-                      azt_Play.end.sec, azt_Play.end.frame);
-#endif
-               i = aztPlay(&azt_Play);
-               if (i < 0) {
-                       aztAudioStatus = CDROM_AUDIO_ERROR;
-                       return -EIO;
-               }
-               aztAudioStatus = CDROM_AUDIO_PLAY;
-               break;
-
-       case CDROMREADTOCHDR:   /* Read the table of contents header */
-               tocHdr.cdth_trk0 = DiskInfo.first;
-               tocHdr.cdth_trk1 = DiskInfo.last;
-               if (copy_to_user(argp, &tocHdr, sizeof tocHdr))
-                       return -EFAULT;
-               break;
-       case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
-               if (copy_from_user(&entry, argp, sizeof entry))
-                       return -EFAULT;
-               if ((!aztTocUpToDate) || aztDiskChanged)
-                       aztUpdateToc();
-               if (entry.cdte_track == CDROM_LEADOUT)
-                       tocPtr = &Toc[DiskInfo.last + 1];
-               else if (entry.cdte_track > DiskInfo.last
-                        || entry.cdte_track < DiskInfo.first) {
-                       return -EINVAL;
-               } else
-                       tocPtr = &Toc[entry.cdte_track];
-               entry.cdte_adr = tocPtr->ctrl_addr;
-               entry.cdte_ctrl = tocPtr->ctrl_addr >> 4;
-               if (entry.cdte_format == CDROM_LBA)
-                       entry.cdte_addr.lba =
-                           azt_msf2hsg(&tocPtr->diskTime);
-               else if (entry.cdte_format == CDROM_MSF) {
-                       entry.cdte_addr.msf.minute =
-                           azt_bcd2bin(tocPtr->diskTime.min);
-                       entry.cdte_addr.msf.second =
-                           azt_bcd2bin(tocPtr->diskTime.sec);
-                       entry.cdte_addr.msf.frame =
-                           azt_bcd2bin(tocPtr->diskTime.frame);
-               } else {
-                       return -EINVAL;
-               }
-               if (copy_to_user(argp, &entry, sizeof entry))
-                       return -EFAULT;
-               break;
-       case CDROMSUBCHNL:      /* Get subchannel info */
-               if (copy_from_user
-                   (&subchnl, argp, sizeof(struct cdrom_subchnl)))
-                       return -EFAULT;
-               if (aztGetQChannelInfo(&qInfo) < 0) {
-#ifdef AZT_DEBUG
-                       printk
-                           ("aztcd: exiting aztcd_ioctl - Error 3 - Command:%x\n",
-                            cmd);
-#endif
-                       return -EIO;
-               }
-               subchnl.cdsc_audiostatus = aztAudioStatus;
-               subchnl.cdsc_adr = qInfo.ctrl_addr;
-               subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
-               subchnl.cdsc_trk = azt_bcd2bin(qInfo.track);
-               subchnl.cdsc_ind = azt_bcd2bin(qInfo.pointIndex);
-               if (subchnl.cdsc_format == CDROM_LBA) {
-                       subchnl.cdsc_absaddr.lba =
-                           azt_msf2hsg(&qInfo.diskTime);
-                       subchnl.cdsc_reladdr.lba =
-                           azt_msf2hsg(&qInfo.trackTime);
-               } else {        /*default */
-                       subchnl.cdsc_format = CDROM_MSF;
-                       subchnl.cdsc_absaddr.msf.minute =
-                           azt_bcd2bin(qInfo.diskTime.min);
-                       subchnl.cdsc_absaddr.msf.second =
-                           azt_bcd2bin(qInfo.diskTime.sec);
-                       subchnl.cdsc_absaddr.msf.frame =
-                           azt_bcd2bin(qInfo.diskTime.frame);
-                       subchnl.cdsc_reladdr.msf.minute =
-                           azt_bcd2bin(qInfo.trackTime.min);
-                       subchnl.cdsc_reladdr.msf.second =
-                           azt_bcd2bin(qInfo.trackTime.sec);
-                       subchnl.cdsc_reladdr.msf.frame =
-                           azt_bcd2bin(qInfo.trackTime.frame);
-               }
-               if (copy_to_user(argp, &subchnl, sizeof(struct cdrom_subchnl)))
-                       return -EFAULT;
-               break;
-       case CDROMVOLCTRL:      /* Volume control 
-                                  * With my Aztech CD268-01A volume control does not work, I can only
-                                  turn the channels on (any value !=0) or off (value==0). Maybe it
-                                  works better with your drive */
-               if (copy_from_user(&volctrl, argp, sizeof(volctrl)))
-                       return -EFAULT;
-               azt_Play.start.min = 0x21;
-               azt_Play.start.sec = 0x84;
-               azt_Play.start.frame = volctrl.channel0;
-               azt_Play.end.min = volctrl.channel1;
-               azt_Play.end.sec = volctrl.channel2;
-               azt_Play.end.frame = volctrl.channel3;
-               sendAztCmd(ACMD_SET_VOLUME, &azt_Play);
-               STEN_LOW_WAIT;
-               break;
-       case CDROMEJECT:
-               aztUnlockDoor();        /* Assume user knows what they're doing */
-               /* all drives can at least stop! */
-               if (aztAudioStatus == CDROM_AUDIO_PLAY) {
-                       if (aztSendCmd(ACMD_STOP))
-                               RETURNM("azt_ioctl 10", -1);
-                       STEN_LOW_WAIT;
-               }
-               if (aztSendCmd(ACMD_EJECT))
-                       RETURNM("azt_ioctl 11", -1);
-               STEN_LOW_WAIT;
-               aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-               break;
-       case CDROMEJECT_SW:
-               azt_auto_eject = (char) arg;
-               break;
-       case CDROMRESET:
-               outb(ACMD_SOFT_RESET, CMD_PORT);        /*send reset */
-               STEN_LOW;
-               if (inb(DATA_PORT) != AFL_OP_OK) {      /*OP_OK? */
-                       printk
-                           ("aztcd: AZTECH CD-ROM drive does not respond\n");
-               }
-               break;
-/*Take care, the following code is not compatible with other CD-ROM drivers,
-  use it at your own risk with cdplay.c. Set AZT_PRIVATE_IOCTLS to 0 in aztcd.h,
-  if you do not want to use it!
-*/
-#if AZT_PRIVATE_IOCTLS
-       case CDROMREADCOOKED:   /*read data in mode 1 (2048 Bytes) */
-       case CDROMREADRAW:      /*read data in mode 2 (2336 Bytes) */
-               {
-                       if (copy_from_user(&msf, argp, sizeof msf))
-                               return -EFAULT;
-                       /* convert to bcd */
-                       azt_bin2bcd(&msf.cdmsf_min0);
-                       azt_bin2bcd(&msf.cdmsf_sec0);
-                       azt_bin2bcd(&msf.cdmsf_frame0);
-                       msf.cdmsf_min1 = 0;
-                       msf.cdmsf_sec1 = 0;
-                       msf.cdmsf_frame1 = 1;   /*read only one frame */
-                       azt_Play.start.min = msf.cdmsf_min0;
-                       azt_Play.start.sec = msf.cdmsf_sec0;
-                       azt_Play.start.frame = msf.cdmsf_frame0;
-                       azt_Play.end.min = msf.cdmsf_min1;
-                       azt_Play.end.sec = msf.cdmsf_sec1;
-                       azt_Play.end.frame = msf.cdmsf_frame1;
-                       if (cmd == CDROMREADRAW) {
-                               if (DiskInfo.xa) {
-                                       return -1;      /*XA Disks can't be read raw */
-                               } else {
-                                       if (sendAztCmd(ACMD_PLAY_READ_RAW, &azt_Play))
-                                               return -1;
-                                       DTEN_LOW;
-                                       insb(DATA_PORT, buf, CD_FRAMESIZE_RAW);
-                                       if (copy_to_user(argp, &buf, CD_FRAMESIZE_RAW))
-                                               return -EFAULT;
-                               }
-                       } else
-                               /*CDROMREADCOOKED*/ {
-                               if (sendAztCmd(ACMD_PLAY_READ, &azt_Play))
-                                       return -1;
-                               DTEN_LOW;
-                               insb(DATA_PORT, buf, CD_FRAMESIZE);
-                               if (copy_to_user(argp, &buf, CD_FRAMESIZE))
-                                       return -EFAULT;
-                               }
-               }
-               break;
-       case CDROMSEEK: /*seek msf address */
-               if (copy_from_user(&msf, argp, sizeof msf))
-                       return -EFAULT;
-               /* convert to bcd */
-               azt_bin2bcd(&msf.cdmsf_min0);
-               azt_bin2bcd(&msf.cdmsf_sec0);
-               azt_bin2bcd(&msf.cdmsf_frame0);
-               azt_Play.start.min = msf.cdmsf_min0;
-               azt_Play.start.sec = msf.cdmsf_sec0;
-               azt_Play.start.frame = msf.cdmsf_frame0;
-               if (aztSeek(&azt_Play))
-                       return -1;
-               break;
-#endif                         /*end of incompatible code */
-       case CDROMREADMODE1:    /*set read data in mode 1 */
-               return aztSetDiskType(AZT_MODE_1);
-       case CDROMREADMODE2:    /*set read data in mode 2 */
-               return aztSetDiskType(AZT_MODE_2);
-       default:
-               return -EINVAL;
-       }
-#ifdef AZT_DEBUG
-       printk("aztcd: exiting aztcd_ioctl Command:%x  Time:%li\n", cmd,
-              jiffies);
-#endif
-       return 0;
-}
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-static void azt_transfer(void)
-{
-#ifdef AZT_TEST
-       printk("aztcd: executing azt_transfer Time:%li\n", jiffies);
-#endif
-       if (!current_valid())
-               return;
-
-       while (CURRENT->nr_sectors) {
-               int bn = CURRENT->sector / 4;
-               int i;
-               for (i = 0; i < AZT_BUF_SIZ && azt_buf_bn[i] != bn; ++i);
-               if (i < AZT_BUF_SIZ) {
-                       int offs = (i * 4 + (CURRENT->sector & 3)) * 512;
-                       int nr_sectors = 4 - (CURRENT->sector & 3);
-                       if (azt_buf_out != i) {
-                               azt_buf_out = i;
-                               if (azt_buf_bn[i] != bn) {
-                                       azt_buf_out = -1;
-                                       continue;
-                               }
-                       }
-                       if (nr_sectors > CURRENT->nr_sectors)
-                           nr_sectors = CURRENT->nr_sectors;
-                       memcpy(CURRENT->buffer, azt_buf + offs,
-                               nr_sectors * 512);
-                       CURRENT->nr_sectors -= nr_sectors;
-                       CURRENT->sector += nr_sectors;
-                       CURRENT->buffer += nr_sectors * 512;
-               } else {
-                       azt_buf_out = -1;
-                       break;
-               }
-       }
-}
-
-static void do_aztcd_request(request_queue_t * q)
-{
-#ifdef AZT_TEST
-       printk(" do_aztcd_request(%ld+%ld) Time:%li\n", CURRENT->sector,
-              CURRENT->nr_sectors, jiffies);
-#endif
-       if (DiskInfo.audio) {
-               printk("aztcd: Error, tried to mount an Audio CD\n");
-               end_request(CURRENT, 0);
-               return;
-       }
-       azt_transfer_is_active = 1;
-       while (current_valid()) {
-               azt_transfer();
-               if (CURRENT->nr_sectors == 0) {
-                       end_request(CURRENT, 1);
-               } else {
-                       azt_buf_out = -1;       /* Want to read a block not in buffer */
-                       if (azt_state == AZT_S_IDLE) {
-                               if ((!aztTocUpToDate) || aztDiskChanged) {
-                                       if (aztUpdateToc() < 0) {
-                                               while (current_valid())
-                                                       end_request(CURRENT, 0);
-                                               break;
-                                       }
-                               }
-                               azt_state = AZT_S_START;
-                               AztTries = 5;
-                               SET_TIMER(azt_poll, HZ / 100);
-                       }
-                       break;
-               }
-       }
-       azt_transfer_is_active = 0;
-#ifdef AZT_TEST2
-       printk
-           ("azt_next_bn:%x  azt_buf_in:%x azt_buf_out:%x  azt_buf_bn:%x\n",
-            azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]);
-       printk(" do_aztcd_request ends  Time:%li\n", jiffies);
-#endif
-}
-
-
-static void azt_invalidate_buffers(void)
-{
-       int i;
-
-#ifdef AZT_DEBUG
-       printk("aztcd: executing azt_invalidate_buffers\n");
-#endif
-       for (i = 0; i < AZT_BUF_SIZ; ++i)
-               azt_buf_bn[i] = -1;
-       azt_buf_out = -1;
-}
-
-/*
- * Open the device special file.  Check that a disk is in.
- */
-static int aztcd_open(struct inode *ip, struct file *fp)
-{
-       int st;
-
-#ifdef AZT_DEBUG
-       printk("aztcd: starting aztcd_open\n");
-#endif
-
-       if (aztPresent == 0)
-               return -ENXIO;  /* no hardware */
-
-       if (!azt_open_count && azt_state == AZT_S_IDLE) {
-               azt_invalidate_buffers();
-
-               st = getAztStatus();    /* check drive status */
-               if (st == -1)
-                       goto err_out;   /* drive doesn't respond */
-
-               if (st & AST_DOOR_OPEN) {       /* close door, then get the status again. */
-                       printk("aztcd: Door Open?\n");
-                       aztCloseDoor();
-                       st = getAztStatus();
-               }
-
-               if ((st & AST_NOT_READY) || (st & AST_DSK_CHG)) {       /*no disk in drive or changed */
-                       printk
-                           ("aztcd: Disk Changed or No Disk in Drive?\n");
-                       aztTocUpToDate = 0;
-               }
-               if (aztUpdateToc())
-                       goto err_out;
-
-       }
-       ++azt_open_count;
-       aztLockDoor();
-
-#ifdef AZT_DEBUG
-       printk("aztcd: exiting aztcd_open\n");
-#endif
-       return 0;
-
-      err_out:
-       return -EIO;
-}
-
-
-/*
- * On close, we flush all azt blocks from the buffer cache.
- */
-static int aztcd_release(struct inode *inode, struct file *file)
-{
-#ifdef AZT_DEBUG
-       printk("aztcd: executing aztcd_release\n");
-       printk("inode: %p, device: %s    file: %p\n", inode,
-              inode->i_bdev->bd_disk->disk_name, file);
-#endif
-       if (!--azt_open_count) {
-               azt_invalidate_buffers();
-               aztUnlockDoor();
-               if (azt_auto_eject)
-                       aztSendCmd(ACMD_EJECT);
-               CLEAR_TIMER;
-       }
-       return 0;
-}
-
-static struct gendisk *azt_disk;
-
-/*
- * Test for presence of drive and initialize it.  Called at boot time.
- */
-
-static int __init aztcd_init(void)
-{
-       long int count, max_count;
-       unsigned char result[50];
-       int st;
-       void* status = NULL;
-       int i = 0;
-       int ret = 0;
-
-       if (azt_port == 0) {
-               printk(KERN_INFO "aztcd: no Aztech CD-ROM Initialization");
-               return -EIO;
-       }
-
-       printk(KERN_INFO "aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM "
-              "CD-ROM Driver\n");
-       printk(KERN_INFO "aztcd: (C) 1994-98 W.Zimmermann\n");
-       if (azt_port == -1) {
-               printk
-                   ("aztcd: DriverVersion=%s For IDE/ATAPI-drives use ide-cd.c\n",
-                    AZT_VERSION);
-       } else
-               printk
-                   ("aztcd: DriverVersion=%s BaseAddress=0x%x  For IDE/ATAPI-drives use ide-cd.c\n",
-                    AZT_VERSION, azt_port);
-       printk(KERN_INFO "aztcd: If you have problems, read /usr/src/linux/"
-              "Documentation/cdrom/aztcd\n");
-
-
-#ifdef AZT_SW32                        /*CDROM connected to Soundwave32 card */
-       if ((0xFF00 & inw(AZT_SW32_ID_REG)) != 0x4500) {
-               printk
-                   ("aztcd: no Soundwave32 card detected at base:%x init:%x config:%x id:%x\n",
-                    AZT_SW32_BASE_ADDR, AZT_SW32_INIT,
-                    AZT_SW32_CONFIG_REG, AZT_SW32_ID_REG);
-               return -EIO;
-       } else {
-               printk(KERN_INFO
-                      "aztcd: Soundwave32 card detected at %x  Version %x\n",
-                      AZT_SW32_BASE_ADDR, inw(AZT_SW32_ID_REG));
-               outw(AZT_SW32_INIT, AZT_SW32_CONFIG_REG);
-               for (count = 0; count < 10000; count++);        /*delay a bit */
-       }
-#endif
-
-       /* check for presence of drive */
-
-       if (azt_port == -1) {   /* autoprobing for proprietary interface  */
-               for (i = 0; (azt_port_auto[i] != 0) && (i < 16); i++) {
-                       azt_port = azt_port_auto[i];
-                       printk(KERN_INFO "aztcd: Autoprobing BaseAddress=0x%x"
-                              "\n", azt_port);
-                        /*proprietary interfaces need 4 bytes */
-                       if (!request_region(azt_port, 4, "aztcd")) {
-                               continue;
-                       }
-                       outb(POLLED, MODE_PORT);
-                       inb(CMD_PORT);
-                       inb(CMD_PORT);
-                       outb(ACMD_GET_VERSION, CMD_PORT);       /*Try to get version info */
-
-                       aztTimeOutCount = 0;
-                       do {
-                               aztIndatum = inb(STATUS_PORT);
-                               aztTimeOutCount++;
-                               if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
-                                       break;
-                       } while (aztIndatum & AFL_STATUS);
-                       if (inb(DATA_PORT) == AFL_OP_OK) { /* OK drive found */
-                               break;
-                       }
-                       else {  /* Drive not found on this port - try next one */
-                               release_region(azt_port, 4);
-                       }
-               }
-               if ((i == 16) || (azt_port_auto[i] == 0)) {
-                       printk(KERN_INFO "aztcd: no AZTECH CD-ROM drive found\n");
-                       return -EIO;
-               }
-       } else {                /* no autoprobing */
-               if ((azt_port == 0x1f0) || (azt_port == 0x170))
-                       status = request_region(azt_port, 8, "aztcd");  /*IDE-interfaces need 8 bytes */
-               else
-                       status = request_region(azt_port, 4, "aztcd");  /*proprietary interfaces need 4 bytes */
-               if (!status) {
-                       printk(KERN_WARNING "aztcd: conflict, I/O port (%X) "
-                              "already used\n", azt_port);
-                       return -EIO;
-               }
-
-               if ((azt_port == 0x1f0) || (azt_port == 0x170))
-                       SWITCH_IDE_SLAVE;       /*switch IDE interface to slave configuration */
-
-               outb(POLLED, MODE_PORT);
-               inb(CMD_PORT);
-               inb(CMD_PORT);
-               outb(ACMD_GET_VERSION, CMD_PORT);       /*Try to get version info */
-
-               aztTimeOutCount = 0;
-               do {
-                       aztIndatum = inb(STATUS_PORT);
-                       aztTimeOutCount++;
-                       if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
-                               break;
-               } while (aztIndatum & AFL_STATUS);
-
-               if (inb(DATA_PORT) != AFL_OP_OK) {      /*OP_OK? If not, reset and try again */
-#ifndef MODULE
-                       if (azt_cont != 0x79) {
-                               printk(KERN_WARNING "aztcd: no AZTECH CD-ROM "
-                                      "drive found-Try boot parameter aztcd="
-                                      "<BaseAddress>,0x79\n");
-                               ret = -EIO;
-                               goto err_out;
-                       }
-#else
-                       if (0) {
-                       }
-#endif
-                       else {
-                               printk(KERN_INFO "aztcd: drive reset - "
-                                      "please wait\n");
-                               for (count = 0; count < 50; count++) {
-                                       inb(STATUS_PORT);       /*removing all data from earlier tries */
-                                       inb(DATA_PORT);
-                               }
-                               outb(POLLED, MODE_PORT);
-                               inb(CMD_PORT);
-                               inb(CMD_PORT);
-                               getAztStatus(); /*trap errors */
-                               outb(ACMD_SOFT_RESET, CMD_PORT);        /*send reset */
-                               STEN_LOW;
-                               if (inb(DATA_PORT) != AFL_OP_OK) {      /*OP_OK? */
-                                       printk(KERN_WARNING "aztcd: no AZTECH "
-                                              "CD-ROM drive found\n");
-                                       ret = -EIO;
-                                       goto err_out;
-                               }
-
-                               for (count = 0; count < AZT_TIMEOUT;
-                                    count++)
-                                       barrier();      /* Stop gcc 2.96 being smart */
-                               /* use udelay(), damnit -- AV */
-
-                               if ((st = getAztStatus()) == -1) {
-                                       printk(KERN_WARNING "aztcd: Drive Status"
-                                              " Error Status=%x\n", st);
-                                       ret = -EIO;
-                                       goto err_out;
-                               }
-#ifdef AZT_DEBUG
-                               printk(KERN_DEBUG "aztcd: Status = %x\n", st);
-#endif
-                               outb(POLLED, MODE_PORT);
-                               inb(CMD_PORT);
-                               inb(CMD_PORT);
-                               outb(ACMD_GET_VERSION, CMD_PORT);       /*GetVersion */
-                               STEN_LOW;
-                               OP_OK;
-                       }
-               }
-       }
-
-       azt_init_end = 1;
-       STEN_LOW;
-       result[0] = inb(DATA_PORT);     /*reading in a null byte??? */
-       for (count = 1; count < 50; count++) {  /*Reading version string */
-               aztTimeOutCount = 0;    /*here we must implement STEN_LOW differently */
-               do {
-                       aztIndatum = inb(STATUS_PORT);  /*because we want to exit by timeout */
-                       aztTimeOutCount++;
-                       if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
-                               break;
-               } while (aztIndatum & AFL_STATUS);
-               if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
-                       break;  /*all chars read? */
-               result[count] = inb(DATA_PORT);
-       }
-       if (count > 30)
-               max_count = 30; /*print max.30 chars of the version string */
-       else
-               max_count = count;
-       printk(KERN_INFO "aztcd: FirmwareVersion=");
-       for (count = 1; count < max_count; count++)
-               printk("%c", result[count]);
-       printk("<<>> ");
-
-       if ((result[1] == 'A') && (result[2] == 'Z') && (result[3] == 'T')) {
-               printk("AZTECH drive detected\n");
-       /*AZTECH*/}
-               else if ((result[2] == 'C') && (result[3] == 'D')
-                        && (result[4] == 'D')) {
-               printk("ORCHID or WEARNES drive detected\n");   /*ORCHID or WEARNES */
-       } else if ((result[1] == 0x03) && (result[2] == '5')) {
-               printk("TXC or CyCDROM drive detected\n");      /*Conrad TXC, CyCDROM */
-       } else {                /*OTHERS or none */
-               printk("\nunknown drive or firmware version detected\n");
-               printk
-                   ("aztcd may not run stable, if you want to try anyhow,\n");
-               printk("boot with: aztcd=<BaseAddress>,0x79\n");
-               if ((azt_cont != 0x79)) {
-                       printk("aztcd: FirmwareVersion=");
-                       for (count = 1; count < 5; count++)
-                               printk("%c", result[count]);
-                       printk("<<>> ");
-                       printk("Aborted\n");
-                       ret = -EIO;
-                       goto err_out;
-               }
-       }
-       azt_disk = alloc_disk(1);
-       if (!azt_disk)
-               goto err_out;
-
-       if (register_blkdev(MAJOR_NR, "aztcd")) {
-               ret = -EIO;
-               goto err_out2;
-       }
-
-       azt_queue = blk_init_queue(do_aztcd_request, &aztSpin);
-       if (!azt_queue) {
-               ret = -ENOMEM;
-               goto err_out3;
-       }
-
-       blk_queue_hardsect_size(azt_queue, 2048);
-       azt_disk->major = MAJOR_NR;
-       azt_disk->first_minor = 0;
-       azt_disk->fops = &azt_fops;
-       sprintf(azt_disk->disk_name, "aztcd");
-       azt_disk->queue = azt_queue;
-       add_disk(azt_disk);
-       azt_invalidate_buffers();
-       aztPresent = 1;
-       aztCloseDoor();
-       return 0;
-err_out3:
-       unregister_blkdev(MAJOR_NR, "aztcd");
-err_out2:
-       put_disk(azt_disk);
-err_out:
-       if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
-               SWITCH_IDE_MASTER;
-               release_region(azt_port, 8);    /*IDE-interface */
-       } else
-               release_region(azt_port, 4);    /*proprietary interface */
-       return ret;
-
-}
-
-static void __exit aztcd_exit(void)
-{
-       del_gendisk(azt_disk);
-       put_disk(azt_disk);
-       if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) {
-               printk("What's that: can't unregister aztcd\n");
-               return;
-       }
-       blk_cleanup_queue(azt_queue);
-       if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
-               SWITCH_IDE_MASTER;
-               release_region(azt_port, 8);    /*IDE-interface */
-       } else
-               release_region(azt_port, 4);    /*proprietary interface */
-       printk(KERN_INFO "aztcd module released.\n");
-}
-
-module_init(aztcd_init);
-module_exit(aztcd_exit);
-
-/*##########################################################################
-  Aztcd State Machine: Controls Drive Operating State
-  ##########################################################################
-*/
-static void azt_poll(void)
-{
-       int st = 0;
-       int loop_ctl = 1;
-       int skip = 0;
-
-       if (azt_error) {
-               if (aztSendCmd(ACMD_GET_ERROR))
-                       RETURN("azt_poll 1");
-               STEN_LOW;
-               azt_error = inb(DATA_PORT) & 0xFF;
-               printk("aztcd: I/O error 0x%02x\n", azt_error);
-               azt_invalidate_buffers();
-#ifdef WARN_IF_READ_FAILURE
-               if (AztTries == 5)
-                       printk
-                           ("aztcd: Read of Block %d Failed - Maybe Audio Disk?\n",
-                            azt_next_bn);
-#endif
-               if (!AztTries--) {
-                       printk
-                           ("aztcd: Read of Block %d Failed, Maybe Audio Disk? Giving up\n",
-                            azt_next_bn);
-                       if (azt_transfer_is_active) {
-                               AztTries = 0;
-                               loop_ctl = 0;
-                       }
-                       if (current_valid())
-                               end_request(CURRENT, 0);
-                       AztTries = 5;
-               }
-               azt_error = 0;
-               azt_state = AZT_S_STOP;
-       }
-
-       while (loop_ctl) {
-               loop_ctl = 0;   /* each case must flip this back to 1 if we want
-                                  to come back up here */
-               switch (azt_state) {
-
-               case AZT_S_IDLE:
-#ifdef AZT_TEST3
-                       if (azt_state != azt_state_old) {
-                               azt_state_old = azt_state;
-                               printk("AZT_S_IDLE\n");
-                       }
-#endif
-                       return;
-
-               case AZT_S_START:
-#ifdef AZT_TEST3
-                       if (azt_state != azt_state_old) {
-                               azt_state_old = azt_state;
-                               printk("AZT_S_START\n");
-                       }
-#endif
-                       if (aztSendCmd(ACMD_GET_STATUS))
-                               RETURN("azt_poll 2");   /*result will be checked by aztStatus() */
-                       azt_state =
-                           azt_mode == 1 ? AZT_S_READ : AZT_S_MODE;
-                       AztTimeout = 3000;
-                       break;
-
-               case AZT_S_MODE:
-#ifdef AZT_TEST3
-                       if (azt_state != azt_state_old) {
-                               azt_state_old = azt_state;
-                               printk("AZT_S_MODE\n");
-                       }
-#endif
-                       if (!skip) {
-                               if ((st = aztStatus()) != -1) {
-                                       if ((st & AST_DSK_CHG)
-                                           || (st & AST_NOT_READY)) {
-                                               aztDiskChanged = 1;
-                                               aztTocUpToDate = 0;
-                                               azt_invalidate_buffers();
-                                               end_request(CURRENT, 0);
-                                               printk
-                                                   ("aztcd: Disk Changed or Not Ready 1 - Unmount Disk!\n");
-                                       }
-                               } else
-                                       break;
-                       }
-                       skip = 0;
-
-                       if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) {
-                               aztDiskChanged = 1;
-                               aztTocUpToDate = 0;
-                               printk
-                                   ("aztcd: Disk Changed or Not Ready 2 - Unmount Disk!\n");
-                               end_request(CURRENT, 0);
-                               printk((st & AST_DOOR_OPEN) ?
-                                      "aztcd: door open\n" :
-                                      "aztcd: disk removed\n");
-                               if (azt_transfer_is_active) {
-                                       azt_state = AZT_S_START;
-                                       loop_ctl = 1;   /* goto immediately */
-                                       break;
-                               }
-                               azt_state = AZT_S_IDLE;
-                               while (current_valid())
-                                       end_request(CURRENT, 0);
-                               return;
-                       }
-
-/*       if (aztSendCmd(ACMD_SET_MODE)) RETURN("azt_poll 3");
-         outb(0x01, DATA_PORT);
-         PA_OK;
-         STEN_LOW;
-*/
-                       if (aztSendCmd(ACMD_GET_STATUS))
-                               RETURN("azt_poll 4");
-                       STEN_LOW;
-                       azt_mode = 1;
-                       azt_state = AZT_S_READ;
-                       AztTimeout = 3000;
-
-                       break;
-
-
-               case AZT_S_READ:
-#ifdef AZT_TEST3
-                       if (azt_state != azt_state_old) {
-                               azt_state_old = azt_state;
-                               printk("AZT_S_READ\n");
-                       }
-#endif
-                       if (!skip) {
-                               if ((st = aztStatus()) != -1) {
-                                       if ((st & AST_DSK_CHG)
-                                           || (st & AST_NOT_READY)) {
-                                               aztDiskChanged = 1;
-                                               aztTocUpToDate = 0;
-                                               azt_invalidate_buffers();
-                                               printk
-                                                   ("aztcd: Disk Changed or Not Ready 3 - Unmount Disk!\n");
-                                               end_request(CURRENT, 0);
-                                       }
-                               } else
-                                       break;
-                       }
-
-                       skip = 0;
-                       if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) {
-                               aztDiskChanged = 1;
-                               aztTocUpToDate = 0;
-                               printk((st & AST_DOOR_OPEN) ?
-                                      "aztcd: door open\n" :
-                                      "aztcd: disk removed\n");
-                               if (azt_transfer_is_active) {
-                                       azt_state = AZT_S_START;
-                                       loop_ctl = 1;
-                                       break;
-                               }
-                               azt_state = AZT_S_IDLE;
-                               while (current_valid())
-                                       end_request(CURRENT, 0);
-                               return;
-                       }
-
-                       if (current_valid()) {
-                               struct azt_Play_msf msf;
-                               int i;
-                               azt_next_bn = CURRENT->sector / 4;
-                               azt_hsg2msf(azt_next_bn, &msf.start);
-                               i = 0;
-                               /* find out in which track we are */
-                               while (azt_msf2hsg(&msf.start) >
-                                      azt_msf2hsg(&Toc[++i].trackTime)) {
-                               };
-                               if (azt_msf2hsg(&msf.start) <
-                                   azt_msf2hsg(&Toc[i].trackTime) -
-                                   AZT_BUF_SIZ) {
-                                       azt_read_count = AZT_BUF_SIZ;   /*fast, because we read ahead */
-                                       /*azt_read_count=CURRENT->nr_sectors;    slow, no read ahead */
-                               } else  /* don't read beyond end of track */
-#if AZT_MULTISESSION
-                               {
-                                       azt_read_count =
-                                           (azt_msf2hsg(&Toc[i].trackTime)
-                                            / 4) * 4 -
-                                           azt_msf2hsg(&msf.start);
-                                       if (azt_read_count < 0)
-                                               azt_read_count = 0;
-                                       if (azt_read_count > AZT_BUF_SIZ)
-                                               azt_read_count =
-                                                   AZT_BUF_SIZ;
-                                       printk
-                                           ("aztcd: warning - trying to read beyond end of track\n");
-/*               printk("%i %i %li %li\n",i,azt_read_count,azt_msf2hsg(&msf.start),azt_msf2hsg(&Toc[i].trackTime));
-*/ }
-#else
-                               {
-                                       azt_read_count = AZT_BUF_SIZ;
-                               }
-#endif
-                               msf.end.min = 0;
-                               msf.end.sec = 0;
-                               msf.end.frame = azt_read_count; /*Mitsumi here reads 0xffffff sectors */
-#ifdef AZT_TEST3
-                               printk
-                                   ("---reading msf-address %x:%x:%x  %x:%x:%x\n",
-                                    msf.start.min, msf.start.sec,
-                                    msf.start.frame, msf.end.min,
-                                    msf.end.sec, msf.end.frame);
-                               printk
-                                   ("azt_next_bn:%x  azt_buf_in:%x azt_buf_out:%x  azt_buf_bn:%x\n",
-                                    azt_next_bn, azt_buf_in, azt_buf_out,
-                                    azt_buf_bn[azt_buf_in]);
-#endif
-                               if (azt_read_mode == AZT_MODE_2) {
-                                       sendAztCmd(ACMD_PLAY_READ_RAW, &msf);   /*XA disks in raw mode */
-                               } else {
-                                       sendAztCmd(ACMD_PLAY_READ, &msf);       /*others in cooked mode */
-                               }
-                               azt_state = AZT_S_DATA;
-                               AztTimeout = READ_TIMEOUT;
-                       } else {
-                               azt_state = AZT_S_STOP;
-                               loop_ctl = 1;
-                               break;
-                       }
-
-                       break;
-
-
-               case AZT_S_DATA:
-#ifdef AZT_TEST3
-                       if (azt_state != azt_state_old) {
-                               azt_state_old = azt_state;
-                               printk("AZT_S_DATA\n");
-                       }
-#endif
-
-                       st = inb(STATUS_PORT) & AFL_STATUSorDATA;
-
-                       switch (st) {
-
-                       case AFL_DATA:
-#ifdef AZT_TEST3
-                               if (st != azt_st_old) {
-                                       azt_st_old = st;
-                                       printk("---AFL_DATA st:%x\n", st);
-                               }
-#endif
-                               if (!AztTries--) {
-                                       printk
-                                           ("aztcd: Read of Block %d Failed, Maybe Audio Disk ? Giving up\n",
-                                            azt_next_bn);
-                                       if (azt_transfer_is_active) {
-                                               AztTries = 0;
-                                               break;
-                                       }
-                                       if (current_valid())
-                                               end_request(CURRENT, 0);
-                                       AztTries = 5;
-                               }
-                               azt_state = AZT_S_START;
-                               AztTimeout = READ_TIMEOUT;
-                               loop_ctl = 1;
-                               break;
-
-                       case AFL_STATUSorDATA:
-#ifdef AZT_TEST3
-                               if (st != azt_st_old) {
-                                       azt_st_old = st;
-                                       printk
-                                           ("---AFL_STATUSorDATA st:%x\n",
-                                            st);
-                               }
-#endif
-                               break;
-
-                       default:
-#ifdef AZT_TEST3
-                               if (st != azt_st_old) {
-                                       azt_st_old = st;
-                                       printk("---default: st:%x\n", st);
-                               }
-#endif
-                               AztTries = 5;
-                               if (!current_valid() && azt_buf_in == azt_buf_out) {
-                                       azt_state = AZT_S_STOP;
-                                       loop_ctl = 1;
-                                       break;
-                               }
-                               if (azt_read_count <= 0)
-                                       printk
-                                           ("aztcd: warning - try to read 0 frames\n");
-                               while (azt_read_count) {        /*??? fast read ahead loop */
-                                       azt_buf_bn[azt_buf_in] = -1;
-                                       DTEN_LOW;       /*??? unsolved problem, very
-                                                          seldom we get timeouts
-                                                          here, don't now the real
-                                                          reason. With my drive this
-                                                          sometimes also happens with
-                                                          Aztech's original driver under
-                                                          DOS. Is it a hardware bug? 
-                                                          I tried to recover from such
-                                                          situations here. Zimmermann */
-                                       if (aztTimeOutCount >= AZT_TIMEOUT) {
-                                               printk
-                                                   ("read_count:%d CURRENT->nr_sectors:%ld azt_buf_in:%d\n",
-                                                    azt_read_count,
-                                                    CURRENT->nr_sectors,
-                                                    azt_buf_in);
-                                               printk
-                                                   ("azt_transfer_is_active:%x\n",
-                                                    azt_transfer_is_active);
-                                               azt_read_count = 0;
-                                               azt_state = AZT_S_STOP;
-                                               loop_ctl = 1;
-                                               end_request(CURRENT, 1);        /*should we have here (1) or (0)? */
-                                       } else {
-                                               if (azt_read_mode ==
-                                                   AZT_MODE_2) {
-                                                       insb(DATA_PORT,
-                                                            azt_buf +
-                                                            CD_FRAMESIZE_RAW
-                                                            * azt_buf_in,
-                                                            CD_FRAMESIZE_RAW);
-                                               } else {
-                                                       insb(DATA_PORT,
-                                                            azt_buf +
-                                                            CD_FRAMESIZE *
-                                                            azt_buf_in,
-                                                            CD_FRAMESIZE);
-                                               }
-                                               azt_read_count--;
-#ifdef AZT_TEST3
-                                               printk
-                                                   ("AZT_S_DATA; ---I've read data- read_count: %d\n",
-                                                    azt_read_count);
-                                               printk
-                                                   ("azt_next_bn:%d  azt_buf_in:%d azt_buf_out:%d  azt_buf_bn:%d\n",
-                                                    azt_next_bn,
-                                                    azt_buf_in,
-                                                    azt_buf_out,
-                                                    azt_buf_bn
-                                                    [azt_buf_in]);
-#endif
-                                               azt_buf_bn[azt_buf_in] =
-                                                   azt_next_bn++;
-                                               if (azt_buf_out == -1)
-                                                       azt_buf_out =
-                                                           azt_buf_in;
-                                               azt_buf_in =
-                                                   azt_buf_in + 1 ==
-                                                   AZT_BUF_SIZ ? 0 :
-                                                   azt_buf_in + 1;
-                                       }
-                               }
-                               if (!azt_transfer_is_active) {
-                                       while (current_valid()) {
-                                               azt_transfer();
-                                               if (CURRENT->nr_sectors ==
-                                                   0)
-                                                       end_request(CURRENT, 1);
-                                               else
-                                                       break;
-                                       }
-                               }
-
-                               if (current_valid()
-                                   && (CURRENT->sector / 4 < azt_next_bn
-                                       || CURRENT->sector / 4 >
-                                       azt_next_bn + AZT_BUF_SIZ)) {
-                                       azt_state = AZT_S_STOP;
-                                       loop_ctl = 1;
-                                       break;
-                               }
-                               AztTimeout = READ_TIMEOUT;
-                               if (azt_read_count == 0) {
-                                       azt_state = AZT_S_STOP;
-                                       loop_ctl = 1;
-                                       break;
-                               }
-                               break;
-                       }
-                       break;
-
-
-               case AZT_S_STOP:
-#ifdef AZT_TEST3
-                       if (azt_state != azt_state_old) {
-                               azt_state_old = azt_state;
-                               printk("AZT_S_STOP\n");
-                       }
-#endif
-                       if (azt_read_count != 0)
-                               printk("aztcd: discard data=%x frames\n",
-                                      azt_read_count);
-                       while (azt_read_count != 0) {
-                               int i;
-                               if (!(inb(STATUS_PORT) & AFL_DATA)) {
-                                       if (azt_read_mode == AZT_MODE_2)
-                                               for (i = 0;
-                                                    i < CD_FRAMESIZE_RAW;
-                                                    i++)
-                                                       inb(DATA_PORT);
-                                       else
-                                               for (i = 0;
-                                                    i < CD_FRAMESIZE; i++)
-                                                       inb(DATA_PORT);
-                               }
-                               azt_read_count--;
-                       }
-                       if (aztSendCmd(ACMD_GET_STATUS))
-                               RETURN("azt_poll 5");
-                       azt_state = AZT_S_STOPPING;
-                       AztTimeout = 1000;
-                       break;
-
-               case AZT_S_STOPPING:
-#ifdef AZT_TEST3
-                       if (azt_state != azt_state_old) {
-                               azt_state_old = azt_state;
-                               printk("AZT_S_STOPPING\n");
-                       }
-#endif
-
-                       if ((st = aztStatus()) == -1 && AztTimeout)
-                               break;
-
-                       if ((st != -1)
-                           && ((st & AST_DSK_CHG)
-                               || (st & AST_NOT_READY))) {
-                               aztDiskChanged = 1;
-                               aztTocUpToDate = 0;
-                               azt_invalidate_buffers();
-                               printk
-                                   ("aztcd: Disk Changed or Not Ready 4 - Unmount Disk!\n");
-                               end_request(CURRENT, 0);
-                       }
-
-#ifdef AZT_TEST3
-                       printk("CURRENT_VALID %d azt_mode %d\n",
-                              current_valid(), azt_mode);
-#endif
-
-                       if (current_valid()) {
-                               if (st != -1) {
-                                       if (azt_mode == 1) {
-                                               azt_state = AZT_S_READ;
-                                               loop_ctl = 1;
-                                               skip = 1;
-                                               break;
-                                       } else {
-                                               azt_state = AZT_S_MODE;
-                                               loop_ctl = 1;
-                                               skip = 1;
-                                               break;
-                                       }
-                               } else {
-                                       azt_state = AZT_S_START;
-                                       AztTimeout = 1;
-                               }
-                       } else {
-                               azt_state = AZT_S_IDLE;
-                               return;
-                       }
-                       break;
-
-               default:
-                       printk("aztcd: invalid state %d\n", azt_state);
-                       return;
-               }               /* case */
-       }                       /* while */
-
-
-       if (!AztTimeout--) {
-               printk("aztcd: timeout in state %d\n", azt_state);
-               azt_state = AZT_S_STOP;
-               if (aztSendCmd(ACMD_STOP))
-                       RETURN("azt_poll 6");
-               STEN_LOW_WAIT;
-       };
-
-       SET_TIMER(azt_poll, HZ / 100);
-}
-
-
-/*###########################################################################
- * Miscellaneous support functions
-  ###########################################################################
-*/
-static void azt_hsg2msf(long hsg, struct msf *msf)
-{
-       hsg += 150;
-       msf->min = hsg / 4500;
-       hsg %= 4500;
-       msf->sec = hsg / 75;
-       msf->frame = hsg % 75;
-#ifdef AZT_DEBUG
-       if (msf->min >= 70)
-               printk("aztcd: Error hsg2msf address Minutes\n");
-       if (msf->sec >= 60)
-               printk("aztcd: Error hsg2msf address Seconds\n");
-       if (msf->frame >= 75)
-               printk("aztcd: Error hsg2msf address Frames\n");
-#endif
-       azt_bin2bcd(&msf->min); /* convert to BCD */
-       azt_bin2bcd(&msf->sec);
-       azt_bin2bcd(&msf->frame);
-}
-
-static long azt_msf2hsg(struct msf *mp)
-{
-       return azt_bcd2bin(mp->frame) + azt_bcd2bin(mp->sec) * 75
-           + azt_bcd2bin(mp->min) * 4500 - CD_MSF_OFFSET;
-}
-
-static void azt_bin2bcd(unsigned char *p)
-{
-       int u, t;
-
-       u = *p % 10;
-       t = *p / 10;
-       *p = u | (t << 4);
-}
-
-static int azt_bcd2bin(unsigned char bcd)
-{
-       return (bcd >> 4) * 10 + (bcd & 0xF);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(AZTECH_CDROM_MAJOR);
diff --git a/drivers/cdrom/aztcd.h b/drivers/cdrom/aztcd.h
deleted file mode 100644 (file)
index 057501e..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/* $Id: aztcd.h,v 2.60 1997/11/29 09:51:22 root Exp root $
- *
- * Definitions for a AztechCD268 CD-ROM interface
- *     Copyright (C) 1994-98  Werner Zimmermann
- *
- *     based on Mitsumi CDROM driver by Martin Harriss
- *
- *  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 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  History:   W.Zimmermann adaption to Aztech CD268-01A Version 1.3
- *             October 1994 Email: Werner.Zimmermann@fht-esslingen.de
- */
-
-/* *** change this to set the I/O port address of your CD-ROM drive,
-       set to '-1', if you want autoprobing */
-#define AZT_BASE_ADDR          -1
-
-/* list of autoprobing addresses (not more than 15), last value must be 0x000
-   Note: Autoprobing is only enabled, if AZT_BASE_ADDR is set to '-1' ! */
-#define AZT_BASE_AUTO          { 0x320, 0x300, 0x310, 0x330, 0x000 }
-
-/* Uncomment this, if your CDROM is connected to a Soundwave32-soundcard
-   and configure AZT_BASE_ADDR and AZT_SW32_BASE_ADDR */
-/*#define AZT_SW32 1
-*/
-
-#ifdef AZT_SW32 
-#define AZT_SW32_BASE_ADDR      0x220  /*I/O port base address of your soundcard*/
-#endif
-
-/* Set this to 1, if you want your tray to be locked, set to 0 to prevent tray 
-   from locking */
-#define AZT_ALLOW_TRAY_LOCK    1
-
-/*Set this to 1 to allow auto-eject when unmounting a disk, set to 0, if you 
-  don't want the auto-eject feature*/
-#define AZT_AUTO_EJECT          0
-
-/*Set this to 1, if you want to use incompatible ioctls for reading in raw and
-  cooked mode */
-#define AZT_PRIVATE_IOCTLS      1
-
-/*Set this to 1, if you want multisession support by the ISO fs. Even if you set 
-  this value to '0' you can use multisession CDs. In that case the drive's firm-
-  ware will do the appropriate redirection automatically. The CD will then look
-  like a single session CD (but nevertheless all data may be read). Please read 
-  chapter '5.1 Multisession support' in README.aztcd for details. Normally it's 
-  uncritical to leave this setting untouched */
-#define AZT_MULTISESSION        1
-
-/*Uncomment this, if you are using a linux kernel version prior to 2.1.0 */
-/*#define AZT_KERNEL_PRIOR_2_1 */
-
-/*---------------------------------------------------------------------------*/
-/*-----nothing to be configured for normal applications below this line------*/
-
-
-/* Increase this if you get lots of timeouts; if you get kernel panic, replace
-   STEN_LOW_WAIT by STEN_LOW in the source code */
-#define AZT_STATUS_DELAY       400       /*for timer wait, STEN_LOW_WAIT*/
-#define AZT_TIMEOUT            8000000   /*for busy wait STEN_LOW, DTEN_LOW*/
-#define AZT_FAST_TIMEOUT       10000     /*for reading the version string*/
-
-/* number of times to retry a command before giving up */
-#define AZT_RETRY_ATTEMPTS     3
-
-/* port access macros */
-#define CMD_PORT               azt_port
-#define DATA_PORT              azt_port
-#define STATUS_PORT            azt_port+1
-#define MODE_PORT              azt_port+2
-#ifdef  AZT_SW32                
- #define AZT_SW32_INIT          (unsigned int) (0xFF00 & (AZT_BASE_ADDR*16))
- #define AZT_SW32_CONFIG_REG    AZT_SW32_BASE_ADDR+0x16  /*Soundwave32 Config. Register*/
- #define AZT_SW32_ID_REG        AZT_SW32_BASE_ADDR+0x04  /*Soundwave32 ID Version Register*/
-#endif
-
-/* status bits */
-#define AST_CMD_CHECK          0x80            /* 1 = command error */
-#define AST_DOOR_OPEN          0x40            /* 1 = door is open */
-#define AST_NOT_READY          0x20            /* 1 = no disk in the drive */
-#define AST_DSK_CHG            0x02            /* 1 = disk removed or changed */
-#define AST_MODE                0x01            /* 0=MODE1, 1=MODE2 */
-#define AST_MODE_BITS          0x1C            /* Mode Bits */
-#define AST_INITIAL            0x0C            /* initial, only valid ... */
-#define AST_BUSY               0x04            /* now playing, only valid
-                                                  in combination with mode
-                                                  bits */
-/* flag bits */
-#define AFL_DATA               0x02            /* data available if low */
-#define AFL_STATUS             0x04            /* status available if low */
-#define AFL_OP_OK              0x01            /* OP_OK command correct*/
-#define AFL_PA_OK              0x02            /* PA_OK parameter correct*/
-#define AFL_OP_ERR             0x05            /* error in command*/
-#define AFL_PA_ERR             0x06            /* error in parameters*/
-#define POLLED                 0x04            /* polled mode */
-
-/* commands */
-#define ACMD_SOFT_RESET                0x10            /* reset drive */
-#define ACMD_PLAY_READ         0x20            /* read data track in cooked mode */
-#define ACMD_PLAY_READ_RAW      0x21           /* reading in raw mode*/
-#define ACMD_SEEK               0x30            /* seek msf address*/
-#define ACMD_SEEK_TO_LEADIN     0x31           /* seek to leadin track*/
-#define ACMD_GET_ERROR         0x40            /* get error code */
-#define ACMD_GET_STATUS                0x41            /* get status */
-#define ACMD_GET_Q_CHANNEL      0x50           /* read info from q channel */
-#define ACMD_EJECT             0x60            /* eject/open tray */
-#define ACMD_CLOSE              0x61            /* close tray */
-#define ACMD_LOCK              0x71            /* lock tray closed */
-#define ACMD_UNLOCK            0x72            /* unlock tray */
-#define ACMD_PAUSE             0x80            /* pause */
-#define ACMD_STOP              0x81            /* stop play */
-#define ACMD_PLAY_AUDIO                0x90            /* play audio track */
-#define ACMD_SET_VOLUME                0x93            /* set audio level */
-#define ACMD_GET_VERSION       0xA0            /* get firmware version */
-#define ACMD_SET_DISK_TYPE     0xA1            /* set disk data mode */
-
-#define MAX_TRACKS             104
-
-struct msf {
-       unsigned char   min;
-       unsigned char   sec;
-       unsigned char   frame;
-};
-
-struct azt_Play_msf {
-       struct msf      start;
-       struct msf      end;
-};
-
-struct azt_DiskInfo {
-       unsigned char   first;
-        unsigned char   next;
-       unsigned char   last;
-       struct msf      diskLength;
-       struct msf      firstTrack;
-        unsigned char   multi;
-        struct msf      nextSession;
-        struct msf      lastSession;
-        unsigned char   xa;
-        unsigned char   audio;
-};
-
-struct azt_Toc {
-       unsigned char   ctrl_addr;
-       unsigned char   track;
-       unsigned char   pointIndex;
-       struct msf      trackTime;
-       struct msf      diskTime;
-};
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
deleted file mode 100644 (file)
index 2157c58..0000000
+++ /dev/null
@@ -1,3251 +0,0 @@
-/*
-* Sony CDU-31A CDROM interface device driver.
-*
-* Corey Minyard (minyard@wf-rch.cirr.com)
-*
-* Colossians 3:17
-*
-*  See Documentation/cdrom/cdu31a for additional details about this driver.
-* 
-* The Sony interface device driver handles Sony interface CDROM
-* drives and provides a complete block-level interface as well as an
-* ioctl() interface compatible with the Sun (as specified in
-* include/linux/cdrom.h).  With this interface, CDROMs can be
-* accessed and standard audio CDs can be played back normally.
-*
-* WARNING -    All autoprobes have been removed from the driver.
-*              You MUST configure the CDU31A via a LILO config
-*              at boot time or in lilo.conf.  I have the
-*              following in my lilo.conf:
-*
-*                append="cdu31a=0x1f88,0,PAS"
-*
-*              The first number is the I/O base address of the
-*              card.  The second is the interrupt (0 means none).
- *             The third should be "PAS" if on a Pro-Audio
- *             spectrum, or nothing if on something else.
- *
- * This interface is (unfortunately) a polled interface.  This is
- * because most Sony interfaces are set up with DMA and interrupts
- * disables.  Some (like mine) do not even have the capability to
- * handle interrupts or DMA.  For this reason you will see a lot of
- * the following:
- *
- *   retry_count = jiffies+ SONY_JIFFIES_TIMEOUT;
- *   while (time_before(jiffies, retry_count) && (! <some condition to wait for))
- *   {
- *      while (handle_sony_cd_attention())
- *         ;
- *
- *      sony_sleep();
- *   }
- *   if (the condition not met)
- *   {
- *      return an error;
- *   }
- *
- * This ugly hack waits for something to happen, sleeping a little
- * between every try.  it also handles attentions, which are
- * asynchronous events from the drive informing the driver that a disk
- * has been inserted, removed, etc.
- *
- * NEWS FLASH - The driver now supports interrupts but they are
- * turned off by default.  Use of interrupts is highly encouraged, it
- * cuts CPU usage down to a reasonable level.  I had DMA in for a while
- * but PC DMA is just too slow.  Better to just insb() it.
- *
- * One thing about these drives: They talk in MSF (Minute Second Frame) format.
- * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a
- * disk.  The funny thing is that these are sent to the drive in BCD, but the
- * interface wants to see them in decimal.  A lot of conversion goes on.
- *
- * DRIVER SPECIAL FEATURES
- * -----------------------
- *
- * This section describes features beyond the normal audio and CD-ROM
- * functions of the drive.
- *
- * XA compatibility
- *
- * The driver should support XA disks for both the CDU31A and CDU33A.
- * It does this transparently, the using program doesn't need to set it.
- *
- * Multi-Session
- *
- * A multi-session disk looks just like a normal disk to the user.
- * Just mount one normally, and all the data should be there.
- * A special thanks to Koen for help with this!
- * 
- * Raw sector I/O
- *
- * Using the CDROMREADAUDIO it is possible to read raw audio and data
- * tracks.  Both operations return 2352 bytes per sector.  On the data
- * tracks, the first 12 bytes is not returned by the drive and the value
- * of that data is indeterminate.
- *
- *
- *  Copyright (C) 1993  Corey Minyard
- *
- *  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 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * TODO: 
- *       CDs with form1 and form2 sectors cause problems
- *       with current read-ahead strategy.
- *
- * Credits:
- *    Heiko Eissfeldt <heiko@colossus.escape.de>
- *         For finding abug in the return of the track numbers.
- *         TOC processing redone for proper multisession support.
- *
- *
- *  It probably a little late to be adding a history, but I guess I
- *  will start.
- *
- *  10/24/95 - Added support for disabling the eject button when the
- *             drive is open.  Note that there is a small problem
- *             still here, if the eject button is pushed while the
- *             drive light is flashing, the drive will return a bad
- *             status and be reset.  It recovers, though.
- *
- *  03/07/97 - Fixed a problem with timers.
- *
- *
- *  18 Spetember 1997 -- Ported to Uniform CD-ROM driver by 
- *                 Heiko Eissfeldt <heiko@colossus.escape.de> with additional
- *                 changes by Erik Andersen <andersee@debian.org>
- *
- *  24 January 1998 -- Removed the scd_disc_status() function, which was now
- *                     just dead code left over from the port.
- *                          Erik Andersen <andersee@debian.org>
- *
- *  16 July 1998 -- Drive donated to Erik Andersen by John Kodis
- *                   <kodis@jagunet.com>.  Work begun on fixing driver to
- *                   work under 2.1.X.  Added temporary extra printks
- *                   which seem to slow it down enough to work.
- *
- *  9 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>
- *
- * 22 October 2004 -- Make the driver work in 2.6.X
- *                   Added workaround to fix hard lockups on eject
- *                   Fixed door locking problem after mounting empty drive
- *                   Set double-speed drives to double speed by default
- *                   Removed all readahead things - not needed anymore
- *                     Ondrej Zary <rainbow@rainbow-software.org>
-*/
-
-#define DEBUG 1
-
-#include <linux/major.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/hdreg.h>
-#include <linux/genhd.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/cdrom.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/dma.h>
-
-#include "cdu31a.h"
-
-#define MAJOR_NR CDU31A_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#define CDU31A_MAX_CONSECUTIVE_ATTENTIONS 10
-
-#define PFX "CDU31A: "
-
-/*
-** Edit the following data to change interrupts, DMA channels, etc.
-** Default is polled and no DMA.  DMA is not recommended for double-speed
-** drives.
-*/
-static struct {
-       unsigned short base;    /* I/O Base Address */
-       short int_num;          /* Interrupt Number (-1 means scan for it,
-                                  0 means don't use) */
-} cdu31a_addresses[] __initdata = {
-       {0}
-};
-
-static int handle_sony_cd_attention(void);
-static int read_subcode(void);
-static void sony_get_toc(void);
-static int scd_spinup(void);
-/*static int scd_open(struct inode *inode, struct file *filp);*/
-static int scd_open(struct cdrom_device_info *, int);
-static void do_sony_cd_cmd(unsigned char cmd,
-                          unsigned char *params,
-                          unsigned int num_params,
-                          unsigned char *result_buffer,
-                          unsigned int *result_size);
-static void size_to_buf(unsigned int size, unsigned char *buf);
-
-/* Parameters for the read-ahead. */
-static unsigned int sony_next_block;   /* Next 512 byte block offset */
-static unsigned int sony_blocks_left = 0;      /* Number of 512 byte blocks left
-                                                  in the current read command. */
-
-
-/* The base I/O address of the Sony Interface.  This is a variable (not a
-   #define) so it can be easily changed via some future ioctl() */
-static unsigned int cdu31a_port = 0;
-module_param(cdu31a_port, uint, 0);
-
-/*
- * The following are I/O addresses of the various registers for the drive.  The
- * comment for the base address also applies here.
- */
-static volatile unsigned short sony_cd_cmd_reg;
-static volatile unsigned short sony_cd_param_reg;
-static volatile unsigned short sony_cd_write_reg;
-static volatile unsigned short sony_cd_control_reg;
-static volatile unsigned short sony_cd_status_reg;
-static volatile unsigned short sony_cd_result_reg;
-static volatile unsigned short sony_cd_read_reg;
-static volatile unsigned short sony_cd_fifost_reg;
-
-static struct request_queue *cdu31a_queue;
-static DEFINE_SPINLOCK(cdu31a_lock); /* queue lock */
-
-static int sony_spun_up = 0;   /* Has the drive been spun up? */
-
-static int sony_speed = 0;     /* Last wanted speed */
-
-static int sony_xa_mode = 0;   /* Is an XA disk in the drive
-                                  and the drive a CDU31A? */
-
-static int sony_raw_data_mode = 1;     /* 1 if data tracks, 0 if audio.
-                                          For raw data reads. */
-
-static unsigned int sony_usage = 0;    /* How many processes have the
-                                          drive open. */
-
-static int sony_pas_init = 0;  /* Initialize the Pro-Audio
-                                  Spectrum card? */
-
-static struct s_sony_session_toc single_toc;   /* Holds the
-                                                  table of
-                                                  contents. */
-
-static struct s_all_sessions_toc sony_toc;     /* entries gathered from all
-                                                  sessions */
-
-static int sony_toc_read = 0;  /* Has the TOC been read for
-                                  the drive? */
-
-static struct s_sony_subcode last_sony_subcode;        /* Points to the last
-                                                  subcode address read */
-
-static DECLARE_MUTEX(sony_sem);                /* Semaphore for drive hardware access */
-
-static int is_double_speed = 0;        /* does the drive support double speed ? */
-
-static int is_auto_eject = 1;  /* Door has been locked? 1=No/0=Yes */
-
-/*
- * The audio status uses the values from read subchannel data as specified
- * in include/linux/cdrom.h.
- */
-static volatile int sony_audio_status = CDROM_AUDIO_NO_STATUS;
-
-/*
- * The following are a hack for pausing and resuming audio play.  The drive
- * does not work as I would expect it, if you stop it then start it again,
- * the drive seeks back to the beginning and starts over.  This holds the
- * position during a pause so a resume can restart it.  It uses the
- * audio status variable above to tell if it is paused.
- */
-static unsigned volatile char cur_pos_msf[3] = { 0, 0, 0 };
-static unsigned volatile char final_pos_msf[3] = { 0, 0, 0 };
-
-/* What IRQ is the drive using?  0 if none. */
-static int cdu31a_irq = 0;
-module_param(cdu31a_irq, int, 0);
-
-/* The interrupt handler will wake this queue up when it gets an
-   interrupts. */
-static DECLARE_WAIT_QUEUE_HEAD(cdu31a_irq_wait);
-static int irq_flag = 0;
-
-static int curr_control_reg = 0;       /* Current value of the control register */
-
-/* A disk changed variable.  When a disk change is detected, it will
-   all be set to TRUE.  As the upper layers ask for disk_changed status
-   it will be cleared. */
-static char disk_changed;
-
-/* This was readahead_buffer once... Now it's used only for audio reads */
-static char audio_buffer[CD_FRAMESIZE_RAW];
-
-/* Used to time a short period to abort an operation after the
-   drive has been idle for a while.  This keeps the light on
-   the drive from flashing for very long. */
-static struct timer_list cdu31a_abort_timer;
-
-/* Marks if the timeout has started an abort read.  This is used
-   on entry to the drive to tell the code to read out the status
-   from the abort read. */
-static int abort_read_started = 0;
-
-/*
- * Uniform cdrom interface function
- * report back, if disc has changed from time of last request.
- */
-static int scd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
-       int retval;
-
-       retval = disk_changed;
-       disk_changed = 0;
-
-       return retval;
-}
-
-/*
- * Uniform cdrom interface function
- * report back, if drive is ready
- */
-static int scd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
-       if (CDSL_CURRENT != slot_nr)
-               /* we have no changer support */
-               return -EINVAL;
-       if (sony_spun_up)
-               return CDS_DISC_OK;
-       if (down_interruptible(&sony_sem))
-               return -ERESTARTSYS;
-       if (scd_spinup() == 0)
-               sony_spun_up = 1;
-       up(&sony_sem);
-       return sony_spun_up ? CDS_DISC_OK : CDS_DRIVE_NOT_READY;
-}
-
-static inline void enable_interrupts(void)
-{
-       curr_control_reg |= (SONY_ATTN_INT_EN_BIT
-                            | SONY_RES_RDY_INT_EN_BIT
-                            | SONY_DATA_RDY_INT_EN_BIT);
-       outb(curr_control_reg, sony_cd_control_reg);
-}
-
-static inline void disable_interrupts(void)
-{
-       curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT
-                             | SONY_RES_RDY_INT_EN_BIT
-                             | SONY_DATA_RDY_INT_EN_BIT);
-       outb(curr_control_reg, sony_cd_control_reg);
-}
-
-/*
- * Wait a little while (used for polling the drive).  If in initialization,
- * setting a timeout doesn't work, so just loop for a while.
- */
-static inline void sony_sleep(void)
-{
-       if (cdu31a_irq <= 0) {
-               yield();
-       } else {                /* Interrupt driven */
-               DEFINE_WAIT(w);
-               int first = 1;
-
-               while (1) {
-                       prepare_to_wait(&cdu31a_irq_wait, &w,
-                                       TASK_INTERRUPTIBLE);
-                       if (first) {
-                               enable_interrupts();
-                               first = 0;
-                       }
-
-                       if (irq_flag != 0)
-                               break;
-                       if (!signal_pending(current)) {
-                               schedule();
-                               continue;
-                       } else
-                               disable_interrupts();
-                       break;
-               }
-               finish_wait(&cdu31a_irq_wait, &w);
-               irq_flag = 0;
-       }
-}
-
-
-/*
- * The following are convenience routine to read various status and set
- * various conditions in the drive.
- */
-static inline int is_attention(void)
-{
-       return (inb(sony_cd_status_reg) & SONY_ATTN_BIT) != 0;
-}
-
-static inline int is_busy(void)
-{
-       return (inb(sony_cd_status_reg) & SONY_BUSY_BIT) != 0;
-}
-
-static inline int is_data_ready(void)
-{
-       return (inb(sony_cd_status_reg) & SONY_DATA_RDY_BIT) != 0;
-}
-
-static inline int is_data_requested(void)
-{
-       return (inb(sony_cd_status_reg) & SONY_DATA_REQUEST_BIT) != 0;
-}
-
-static inline int is_result_ready(void)
-{
-       return (inb(sony_cd_status_reg) & SONY_RES_RDY_BIT) != 0;
-}
-
-static inline int is_param_write_rdy(void)
-{
-       return (inb(sony_cd_fifost_reg) & SONY_PARAM_WRITE_RDY_BIT) != 0;
-}
-
-static inline int is_result_reg_not_empty(void)
-{
-       return (inb(sony_cd_fifost_reg) & SONY_RES_REG_NOT_EMP_BIT) != 0;
-}
-
-static inline void reset_drive(void)
-{
-       curr_control_reg = 0;
-       sony_toc_read = 0;
-       outb(SONY_DRIVE_RESET_BIT, sony_cd_control_reg);
-}
-
-/*
- * Uniform cdrom interface function
- * reset drive and return when it is ready
- */
-static int scd_reset(struct cdrom_device_info *cdi)
-{
-       unsigned long retry_count;
-
-       if (down_interruptible(&sony_sem))
-               return -ERESTARTSYS;
-       reset_drive();
-
-       retry_count = jiffies + SONY_RESET_TIMEOUT;
-       while (time_before(jiffies, retry_count) && (!is_attention())) {
-               sony_sleep();
-       }
-
-       up(&sony_sem);
-       return 0;
-}
-
-static inline void clear_attention(void)
-{
-       outb(curr_control_reg | SONY_ATTN_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline void clear_result_ready(void)
-{
-       outb(curr_control_reg | SONY_RES_RDY_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline void clear_data_ready(void)
-{
-       outb(curr_control_reg | SONY_DATA_RDY_CLR_BIT,
-            sony_cd_control_reg);
-}
-
-static inline void clear_param_reg(void)
-{
-       outb(curr_control_reg | SONY_PARAM_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline unsigned char read_status_register(void)
-{
-       return inb(sony_cd_status_reg);
-}
-
-static inline unsigned char read_result_register(void)
-{
-       return inb(sony_cd_result_reg);
-}
-
-static inline unsigned char read_data_register(void)
-{
-       return inb(sony_cd_read_reg);
-}
-
-static inline void write_param(unsigned char param)
-{
-       outb(param, sony_cd_param_reg);
-}
-
-static inline void write_cmd(unsigned char cmd)
-{
-       outb(curr_control_reg | SONY_RES_RDY_INT_EN_BIT,
-            sony_cd_control_reg);
-       outb(cmd, sony_cd_cmd_reg);
-}
-
-static irqreturn_t cdu31a_interrupt(int irq, void *dev_id)
-{
-       unsigned char val;
-
-       if (abort_read_started) {
-               /* We might be waiting for an abort to finish.  Don't
-                  disable interrupts yet, though, because we handle
-                  this one here. */
-               /* Clear out the result registers. */
-               while (is_result_reg_not_empty()) {
-                       val = read_result_register();
-               }
-               clear_data_ready();
-               clear_result_ready();
-
-               /* Clear out the data */
-               while (is_data_requested()) {
-                       val = read_data_register();
-               }
-               abort_read_started = 0;
-
-               /* If something was waiting, wake it up now. */
-               if (waitqueue_active(&cdu31a_irq_wait)) {
-                       disable_interrupts();
-                       irq_flag = 1;
-                       wake_up_interruptible(&cdu31a_irq_wait);
-               }
-       } else if (waitqueue_active(&cdu31a_irq_wait)) {
-               disable_interrupts();
-               irq_flag = 1;
-               wake_up_interruptible(&cdu31a_irq_wait);
-       } else {
-               disable_interrupts();
-               printk(KERN_NOTICE PFX
-                               "Got an interrupt but nothing was waiting\n");
-       }
-       return IRQ_HANDLED;
-}
-
-/*
- * give more verbose error messages
- */
-static unsigned char *translate_error(unsigned char err_code)
-{
-       static unsigned char errbuf[80];
-
-       switch (err_code) {
-               case 0x10: return "illegal command ";
-               case 0x11: return "illegal parameter ";
-
-               case 0x20: return "not loaded ";
-               case 0x21: return "no disc ";
-               case 0x22: return "not spinning ";
-               case 0x23: return "spinning ";
-               case 0x25: return "spindle servo ";
-               case 0x26: return "focus servo ";
-               case 0x29: return "eject mechanism ";
-               case 0x2a: return "audio playing ";
-               case 0x2c: return "emergency eject ";
-
-               case 0x30: return "focus ";
-               case 0x31: return "frame sync ";
-               case 0x32: return "subcode address ";
-               case 0x33: return "block sync ";
-               case 0x34: return "header address ";
-
-               case 0x40: return "illegal track read ";
-               case 0x41: return "mode 0 read ";
-               case 0x42: return "illegal mode read ";
-               case 0x43: return "illegal block size read ";
-               case 0x44: return "mode read ";
-               case 0x45: return "form read ";
-               case 0x46: return "leadout read ";
-               case 0x47: return "buffer overrun ";
-
-               case 0x53: return "unrecoverable CIRC ";
-               case 0x57: return "unrecoverable LECC ";
-
-               case 0x60: return "no TOC ";
-               case 0x61: return "invalid subcode data ";
-               case 0x63: return "focus on TOC read ";
-               case 0x64: return "frame sync on TOC read ";
-               case 0x65: return "TOC data ";
-
-               case 0x70: return "hardware failure ";
-               case 0x91: return "leadin ";
-               case 0x92: return "leadout ";
-               case 0x93: return "data track ";
-       }
-       sprintf(errbuf, "unknown 0x%02x ", err_code);
-       return errbuf;
-}
-
-/*
- * Set the drive parameters so the drive will auto-spin-up when a
- * disk is inserted.
- */
-static void set_drive_params(int want_doublespeed)
-{
-       unsigned char res_reg[12];
-       unsigned int res_size;
-       unsigned char params[3];
-
-
-       params[0] = SONY_SD_AUTO_SPIN_DOWN_TIME;
-       params[1] = 0x00;       /* Never spin down the drive. */
-       do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-                      params, 2, res_reg, &res_size);
-       if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
-               printk(KERN_NOTICE PFX
-                       "Unable to set spin-down time: 0x%2.2x\n", res_reg[1]);
-       }
-
-       params[0] = SONY_SD_MECH_CONTROL;
-       params[1] = SONY_AUTO_SPIN_UP_BIT;      /* Set auto spin up */
-
-       if (is_auto_eject)
-               params[1] |= SONY_AUTO_EJECT_BIT;
-
-       if (is_double_speed && want_doublespeed) {
-               params[1] |= SONY_DOUBLE_SPEED_BIT;     /* Set the drive to double speed if 
-                                                          possible */
-       }
-       do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-                      params, 2, res_reg, &res_size);
-       if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
-               printk(KERN_NOTICE PFX "Unable to set mechanical "
-                               "parameters: 0x%2.2x\n", res_reg[1]);
-       }
-}
-
-/*
- * Uniform cdrom interface function
- * select reading speed for data access
- */
-static int scd_select_speed(struct cdrom_device_info *cdi, int speed)
-{
-       if (speed == 0)
-               sony_speed = 1;
-       else
-               sony_speed = speed - 1;
-
-       if (down_interruptible(&sony_sem))
-               return -ERESTARTSYS;
-       set_drive_params(sony_speed);
-       up(&sony_sem);
-       return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * lock or unlock eject button
- */
-static int scd_lock_door(struct cdrom_device_info *cdi, int lock)
-{
-       if (lock == 0) {
-               is_auto_eject = 1;
-       } else {
-               is_auto_eject = 0;
-       }
-       if (down_interruptible(&sony_sem))
-               return -ERESTARTSYS;
-       set_drive_params(sony_speed);
-       up(&sony_sem);
-       return 0;
-}
-
-/*
- * This code will reset the drive and attempt to restore sane parameters.
- */
-static void restart_on_error(void)
-{
-       unsigned char res_reg[12];
-       unsigned int res_size;
-       unsigned long retry_count;
-
-
-       printk(KERN_NOTICE PFX "Resetting drive on error\n");
-       reset_drive();
-       retry_count = jiffies + SONY_RESET_TIMEOUT;
-       while (time_before(jiffies, retry_count) && (!is_attention())) {
-               sony_sleep();
-       }
-       set_drive_params(sony_speed);
-       do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
-       if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
-               printk(KERN_NOTICE PFX "Unable to spin up drive: 0x%2.2x\n",
-                      res_reg[1]);
-       }
-
-       msleep(2000);
-
-       sony_get_toc();
-}
-
-/*
- * This routine writes data to the parameter register.  Since this should
- * happen fairly fast, it is polled with no OS waits between.
- */
-static int write_params(unsigned char *params, int num_params)
-{
-       unsigned int retry_count;
-
-
-       retry_count = SONY_READY_RETRIES;
-       while ((retry_count > 0) && (!is_param_write_rdy())) {
-               retry_count--;
-       }
-       if (!is_param_write_rdy()) {
-               return -EIO;
-       }
-
-       while (num_params > 0) {
-               write_param(*params);
-               params++;
-               num_params--;
-       }
-
-       return 0;
-}
-
-
-/*
- * The following reads data from the command result register.  It is a
- * fairly complex routine, all status info flows back through this
- * interface.  The algorithm is stolen directly from the flowcharts in
- * the drive manual.
- */
-static void
-get_result(unsigned char *result_buffer, unsigned int *result_size)
-{
-       unsigned char a, b;
-       int i;
-       unsigned long retry_count;
-
-
-       while (handle_sony_cd_attention());
-       /* Wait for the result data to be ready */
-       retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-       while (time_before(jiffies, retry_count)
-              && (is_busy() || (!(is_result_ready())))) {
-               sony_sleep();
-
-               while (handle_sony_cd_attention());
-       }
-       if (is_busy() || (!(is_result_ready()))) {
-               pr_debug(PFX "timeout out %d\n", __LINE__);
-               result_buffer[0] = 0x20;
-               result_buffer[1] = SONY_TIMEOUT_OP_ERR;
-               *result_size = 2;
-               return;
-       }
-
-       /*
-        * Get the first two bytes.  This determines what else needs
-        * to be done.
-        */
-       clear_result_ready();
-       a = read_result_register();
-       *result_buffer = a;
-       result_buffer++;
-
-       /* Check for block error status result. */
-       if ((a & 0xf0) == 0x50) {
-               *result_size = 1;
-               return;
-       }
-
-       b = read_result_register();
-       *result_buffer = b;
-       result_buffer++;
-       *result_size = 2;
-
-       /*
-        * 0x20 means an error occurred.  Byte 2 will have the error code.
-        * Otherwise, the command succeeded, byte 2 will have the count of
-        * how many more status bytes are coming.
-        *
-        * The result register can be read 10 bytes at a time, a wait for
-        * result ready to be asserted must be done between every 10 bytes.
-        */
-       if ((a & 0xf0) != 0x20) {
-               if (b > 8) {
-                       for (i = 0; i < 8; i++) {
-                               *result_buffer = read_result_register();
-                               result_buffer++;
-                               (*result_size)++;
-                       }
-                       b = b - 8;
-
-                       while (b > 10) {
-                               retry_count = SONY_READY_RETRIES;
-                               while ((retry_count > 0)
-                                      && (!is_result_ready())) {
-                                       retry_count--;
-                               }
-                               if (!is_result_ready()) {
-                                       pr_debug(PFX "timeout out %d\n",
-                                              __LINE__);
-                                       result_buffer[0] = 0x20;
-                                       result_buffer[1] =
-                                           SONY_TIMEOUT_OP_ERR;
-                                       *result_size = 2;
-                                       return;
-                               }
-
-                               clear_result_ready();
-
-                               for (i = 0; i < 10; i++) {
-                                       *result_buffer =
-                                           read_result_register();
-                                       result_buffer++;
-                                       (*result_size)++;
-                               }
-                               b = b - 10;
-                       }
-
-                       if (b > 0) {
-                               retry_count = SONY_READY_RETRIES;
-                               while ((retry_count > 0)
-                                      && (!is_result_ready())) {
-                                       retry_count--;
-                               }
-                               if (!is_result_ready()) {
-                                       pr_debug(PFX "timeout out %d\n",
-                                              __LINE__);
-                                       result_buffer[0] = 0x20;
-                                       result_buffer[1] =
-                                           SONY_TIMEOUT_OP_ERR;
-                                       *result_size = 2;
-                                       return;
-                               }
-                       }
-               }
-
-               while (b > 0) {
-                       *result_buffer = read_result_register();
-                       result_buffer++;
-                       (*result_size)++;
-                       b--;
-               }
-       }
-}
-
-/*
- * Do a command that does not involve data transfer.  This routine must
- * be re-entrant from the same task to support being called from the
- * data operation code when an error occurs.
- */
-static void
-do_sony_cd_cmd(unsigned char cmd,
-              unsigned char *params,
-              unsigned int num_params,
-              unsigned char *result_buffer, unsigned int *result_size)
-{
-       unsigned long retry_count;
-       int num_retries = 0;
-
-retry_cd_operation:
-
-       while (handle_sony_cd_attention());
-
-       retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-       while (time_before(jiffies, retry_count) && (is_busy())) {
-               sony_sleep();
-
-               while (handle_sony_cd_attention());
-       }
-       if (is_busy()) {
-               pr_debug(PFX "timeout out %d\n", __LINE__);
-               result_buffer[0] = 0x20;
-               result_buffer[1] = SONY_TIMEOUT_OP_ERR;
-               *result_size = 2;
-       } else {
-               clear_result_ready();
-               clear_param_reg();
-
-               write_params(params, num_params);
-               write_cmd(cmd);
-
-               get_result(result_buffer, result_size);
-       }
-
-       if (((result_buffer[0] & 0xf0) == 0x20)
-           && (num_retries < MAX_CDU31A_RETRIES)) {
-               num_retries++;
-               msleep(100);
-               goto retry_cd_operation;
-       }
-}
-
-
-/*
- * Handle an attention from the drive.  This will return 1 if it found one
- * or 0 if not (if one is found, the caller might want to call again).
- *
- * This routine counts the number of consecutive times it is called
- * (since this is always called from a while loop until it returns
- * a 0), and returns a 0 if it happens too many times.  This will help
- * prevent a lockup.
- */
-static int handle_sony_cd_attention(void)
-{
-       unsigned char atten_code;
-       static int num_consecutive_attentions = 0;
-       volatile int val;
-
-
-#if 0
-       pr_debug(PFX "Entering %s\n", __FUNCTION__);
-#endif
-       if (is_attention()) {
-               if (num_consecutive_attentions >
-                   CDU31A_MAX_CONSECUTIVE_ATTENTIONS) {
-                       printk(KERN_NOTICE PFX "Too many consecutive "
-                               "attentions: %d\n", num_consecutive_attentions);
-                       num_consecutive_attentions = 0;
-                       pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__,
-                              __LINE__);
-                       return 0;
-               }
-
-               clear_attention();
-               atten_code = read_result_register();
-
-               switch (atten_code) {
-                       /* Someone changed the CD.  Mark it as changed */
-               case SONY_MECH_LOADED_ATTN:
-                       disk_changed = 1;
-                       sony_toc_read = 0;
-                       sony_audio_status = CDROM_AUDIO_NO_STATUS;
-                       sony_blocks_left = 0;
-                       break;
-
-               case SONY_SPIN_DOWN_COMPLETE_ATTN:
-                       /* Mark the disk as spun down. */
-                       sony_spun_up = 0;
-                       break;
-
-               case SONY_AUDIO_PLAY_DONE_ATTN:
-                       sony_audio_status = CDROM_AUDIO_COMPLETED;
-                       read_subcode();
-                       break;
-
-               case SONY_EJECT_PUSHED_ATTN:
-                       if (is_auto_eject) {
-                               sony_audio_status = CDROM_AUDIO_INVALID;
-                       }
-                       break;
-
-               case SONY_LEAD_IN_ERR_ATTN:
-               case SONY_LEAD_OUT_ERR_ATTN:
-               case SONY_DATA_TRACK_ERR_ATTN:
-               case SONY_AUDIO_PLAYBACK_ERR_ATTN:
-                       sony_audio_status = CDROM_AUDIO_ERROR;
-                       break;
-               }
-
-               num_consecutive_attentions++;
-               pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-               return 1;
-       } else if (abort_read_started) {
-               while (is_result_reg_not_empty()) {
-                       val = read_result_register();
-               }
-               clear_data_ready();
-               clear_result_ready();
-               /* Clear out the data */
-               while (is_data_requested()) {
-                       val = read_data_register();
-               }
-               abort_read_started = 0;
-               pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-               return 1;
-       }
-
-       num_consecutive_attentions = 0;
-#if 0
-       pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-#endif
-       return 0;
-}
-
-
-/* Convert from an integer 0-99 to BCD */
-static inline unsigned int int_to_bcd(unsigned int val)
-{
-       int retval;
-
-
-       retval = (val / 10) << 4;
-       retval = retval | val % 10;
-       return retval;
-}
-
-
-/* Convert from BCD to an integer from 0-99 */
-static unsigned int bcd_to_int(unsigned int bcd)
-{
-       return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
-}
-
-
-/*
- * Convert a logical sector value (like the OS would want to use for
- * a block device) to an MSF format.
- */
-static void log_to_msf(unsigned int log, unsigned char *msf)
-{
-       log = log + LOG_START_OFFSET;
-       msf[0] = int_to_bcd(log / 4500);
-       log = log % 4500;
-       msf[1] = int_to_bcd(log / 75);
-       msf[2] = int_to_bcd(log % 75);
-}
-
-
-/*
- * Convert an MSF format to a logical sector.
- */
-static unsigned int msf_to_log(unsigned char *msf)
-{
-       unsigned int log;
-
-
-       log = msf[2];
-       log += msf[1] * 75;
-       log += msf[0] * 4500;
-       log = log - LOG_START_OFFSET;
-
-       return log;
-}
-
-
-/*
- * Take in integer size value and put it into a buffer like
- * the drive would want to see a number-of-sector value.
- */
-static void size_to_buf(unsigned int size, unsigned char *buf)
-{
-       buf[0] = size / 65536;
-       size = size % 65536;
-       buf[1] = size / 256;
-       buf[2] = size % 256;
-}
-
-/* Starts a read operation. Returns 0 on success and 1 on failure. 
-   The read operation used here allows multiple sequential sectors 
-   to be read and status returned for each sector.  The driver will
-   read the output one at a time as the requests come and abort the
-   operation if the requested sector is not the next one from the
-   drive. */
-static int
-start_request(unsigned int sector, unsigned int nsect)
-{
-       unsigned char params[6];
-       unsigned long retry_count;
-
-
-       pr_debug(PFX "Entering %s\n", __FUNCTION__);
-       log_to_msf(sector, params);
-       size_to_buf(nsect, &params[3]);
-
-       /*
-        * Clear any outstanding attentions and wait for the drive to
-        * complete any pending operations.
-        */
-       while (handle_sony_cd_attention());
-
-       retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-       while (time_before(jiffies, retry_count) && (is_busy())) {
-               sony_sleep();
-
-               while (handle_sony_cd_attention());
-       }
-
-       if (is_busy()) {
-               printk(KERN_NOTICE PFX "Timeout while waiting "
-                               "to issue command\n");
-               pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-               return 1;
-       } else {
-               /* Issue the command */
-               clear_result_ready();
-               clear_param_reg();
-
-               write_params(params, 6);
-               write_cmd(SONY_READ_BLKERR_STAT_CMD);
-
-               sony_blocks_left = nsect * 4;
-               sony_next_block = sector * 4;
-               pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-               return 0;
-       }
-       pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-/* Abort a pending read operation.  Clear all the drive status variables. */
-static void abort_read(void)
-{
-       unsigned char result_reg[2];
-       int result_size;
-       volatile int val;
-
-
-       do_sony_cd_cmd(SONY_ABORT_CMD, NULL, 0, result_reg, &result_size);
-       if ((result_reg[0] & 0xf0) == 0x20) {
-               printk(KERN_ERR PFX "Aborting read, %s error\n",
-                      translate_error(result_reg[1]));
-       }
-
-       while (is_result_reg_not_empty()) {
-               val = read_result_register();
-       }
-       clear_data_ready();
-       clear_result_ready();
-       /* Clear out the data */
-       while (is_data_requested()) {
-               val = read_data_register();
-       }
-
-       sony_blocks_left = 0;
-}
-
-/* Called when the timer times out.  This will abort the
-   pending read operation. */
-static void handle_abort_timeout(unsigned long data)
-{
-       pr_debug(PFX "Entering %s\n", __FUNCTION__);
-       /* If it is in use, ignore it. */
-       if (down_trylock(&sony_sem) == 0) {
-               /* We can't use abort_read(), because it will sleep
-                  or schedule in the timer interrupt.  Just start
-                  the operation, finish it on the next access to
-                  the drive. */
-               clear_result_ready();
-               clear_param_reg();
-               write_cmd(SONY_ABORT_CMD);
-
-               sony_blocks_left = 0;
-               abort_read_started = 1;
-               up(&sony_sem);
-       }
-       pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-/* Actually get one sector of data from the drive. */
-static void
-input_data_sector(char *buffer)
-{
-       pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
-       /* If an XA disk on a CDU31A, skip the first 12 bytes of data from
-          the disk.  The real data is after that. We can use audio_buffer. */
-       if (sony_xa_mode)
-               insb(sony_cd_read_reg, audio_buffer, CD_XA_HEAD);
-
-       clear_data_ready();
-
-       insb(sony_cd_read_reg, buffer, 2048);
-
-       /* If an XA disk, we have to clear out the rest of the unused
-          error correction data. We can use audio_buffer for that. */
-       if (sony_xa_mode)
-               insb(sony_cd_read_reg, audio_buffer, CD_XA_TAIL);
-
-       pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-/* read data from the drive.  Note the nsect must be <= 4. */
-static void
-read_data_block(char *buffer,
-               unsigned int block,
-               unsigned int nblocks,
-               unsigned char res_reg[], int *res_size)
-{
-       unsigned long retry_count;
-
-       pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
-       res_reg[0] = 0;
-       res_reg[1] = 0;
-       *res_size = 0;
-
-       /* Wait for the drive to tell us we have something */
-       retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-       while (time_before(jiffies, retry_count) && !(is_data_ready())) {
-               while (handle_sony_cd_attention());
-
-               sony_sleep();
-       }
-       if (!(is_data_ready())) {
-               if (is_result_ready()) {
-                       get_result(res_reg, res_size);
-                       if ((res_reg[0] & 0xf0) != 0x20) {
-                               printk(KERN_NOTICE PFX "Got result that should"
-                                       " have been error: %d\n", res_reg[0]);
-                               res_reg[0] = 0x20;
-                               res_reg[1] = SONY_BAD_DATA_ERR;
-                               *res_size = 2;
-                       }
-                       abort_read();
-               } else {
-                       pr_debug(PFX "timeout out %d\n", __LINE__);
-                       res_reg[0] = 0x20;
-                       res_reg[1] = SONY_TIMEOUT_OP_ERR;
-                       *res_size = 2;
-                       abort_read();
-               }
-       } else {
-               input_data_sector(buffer);
-               sony_blocks_left -= nblocks;
-               sony_next_block += nblocks;
-
-               /* Wait for the status from the drive. */
-               retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-               while (time_before(jiffies, retry_count)
-                      && !(is_result_ready())) {
-                       while (handle_sony_cd_attention());
-
-                       sony_sleep();
-               }
-
-               if (!is_result_ready()) {
-                       pr_debug(PFX "timeout out %d\n", __LINE__);
-                       res_reg[0] = 0x20;
-                       res_reg[1] = SONY_TIMEOUT_OP_ERR;
-                       *res_size = 2;
-                       abort_read();
-               } else {
-                       get_result(res_reg, res_size);
-
-                       /* If we got a buffer status, handle that. */
-                       if ((res_reg[0] & 0xf0) == 0x50) {
-
-                               if ((res_reg[0] ==
-                                    SONY_NO_CIRC_ERR_BLK_STAT)
-                                   || (res_reg[0] ==
-                                       SONY_NO_LECC_ERR_BLK_STAT)
-                                   || (res_reg[0] ==
-                                       SONY_RECOV_LECC_ERR_BLK_STAT)) {
-                                       /* nothing here */
-                               } else {
-                                       printk(KERN_ERR PFX "Data block "
-                                               "error: 0x%x\n", res_reg[0]);
-                                       res_reg[0] = 0x20;
-                                       res_reg[1] = SONY_BAD_DATA_ERR;
-                                       *res_size = 2;
-                               }
-
-                               /* Final transfer is done for read command, get final result. */
-                               if (sony_blocks_left == 0) {
-                                       get_result(res_reg, res_size);
-                               }
-                       } else if ((res_reg[0] & 0xf0) != 0x20) {
-                               /* The drive gave me bad status, I don't know what to do.
-                                  Reset the driver and return an error. */
-                               printk(KERN_ERR PFX "Invalid block "
-                                       "status: 0x%x\n", res_reg[0]);
-                               restart_on_error();
-                               res_reg[0] = 0x20;
-                               res_reg[1] = SONY_BAD_DATA_ERR;
-                               *res_size = 2;
-                       }
-               }
-       }
-       pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-
-/*
- * The OS calls this to perform a read or write operation to the drive.
- * Write obviously fail.  Reads to a read ahead of sony_buffer_size
- * bytes to help speed operations.  This especially helps since the OS
- * uses 1024 byte blocks and the drive uses 2048 byte blocks.  Since most
- * data access on a CD is done sequentially, this saves a lot of operations.
- */
-static void do_cdu31a_request(request_queue_t * q)
-{
-       struct request *req;
-       int block, nblock, num_retries;
-       unsigned char res_reg[12];
-       unsigned int res_size;
-
-       pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
-       spin_unlock_irq(q->queue_lock);
-       if (down_interruptible(&sony_sem)) {
-               spin_lock_irq(q->queue_lock);
-               return;
-       }
-
-       /* Get drive status before doing anything. */
-       while (handle_sony_cd_attention());
-
-       /* Make sure we have a valid TOC. */
-       sony_get_toc();
-
-
-       /* Make sure the timer is cancelled. */
-       del_timer(&cdu31a_abort_timer);
-
-       while (1) {
-               /*
-                * The beginning here is stolen from the hard disk driver.  I hope
-                * it's right.
-                */
-               req = elv_next_request(q);
-               if (!req)
-                       goto end_do_cdu31a_request;
-
-               if (!sony_spun_up)
-                       scd_spinup();
-
-               block = req->sector;
-               nblock = req->nr_sectors;
-               pr_debug(PFX "request at block %d, length %d blocks\n",
-                       block, nblock);
-               if (!sony_toc_read) {
-                       printk(KERN_NOTICE PFX "TOC not read\n");
-                       end_request(req, 0);
-                       continue;
-               }
-
-               /* WTF??? */
-               if (!blk_fs_request(req)) {
-                       end_request(req, 0);
-                       continue;
-               }
-               if (rq_data_dir(req) == WRITE) {
-                       end_request(req, 0);
-                       continue;
-               }
-
-               /*
-                * If the block address is invalid or the request goes beyond the end of
-                * the media, return an error.
-                */
-               if (((block + nblock) / 4) >= sony_toc.lead_out_start_lba) {
-                       printk(KERN_NOTICE PFX "Request past end of media\n");
-                       end_request(req, 0);
-                       continue;
-               }
-
-               if (nblock > 4)
-                       nblock = 4;
-               num_retries = 0;
-
-       try_read_again:
-               while (handle_sony_cd_attention());
-
-               if (!sony_toc_read) {
-                       printk(KERN_NOTICE PFX "TOC not read\n");
-                       end_request(req, 0);
-                       continue;
-               }
-
-               /* If no data is left to be read from the drive, start the
-                  next request. */
-               if (sony_blocks_left == 0) {
-                       if (start_request(block / 4, nblock / 4)) {
-                               end_request(req, 0);
-                               continue;
-                       }
-               }
-               /* If the requested block is not the next one waiting in
-                  the driver, abort the current operation and start a
-                  new one. */
-               else if (block != sony_next_block) {
-                       pr_debug(PFX "Read for block %d, expected %d\n",
-                                block, sony_next_block);
-                       abort_read();
-                       if (!sony_toc_read) {
-                               printk(KERN_NOTICE PFX "TOC not read\n");
-                               end_request(req, 0);
-                               continue;
-                       }
-                       if (start_request(block / 4, nblock / 4)) {
-                               printk(KERN_NOTICE PFX "start request failed\n");
-                               end_request(req, 0);
-                               continue;
-                       }
-               }
-
-               read_data_block(req->buffer, block, nblock, res_reg, &res_size);
-
-               if (res_reg[0] != 0x20) {
-                       if (!end_that_request_first(req, 1, nblock)) {
-                               spin_lock_irq(q->queue_lock);
-                               blkdev_dequeue_request(req);
-                               end_that_request_last(req, 1);
-                               spin_unlock_irq(q->queue_lock);
-                       }
-                       continue;
-               }
-
-               if (num_retries > MAX_CDU31A_RETRIES) {
-                       end_request(req, 0);
-                       continue;
-               }
-
-               num_retries++;
-               if (res_reg[1] == SONY_NOT_SPIN_ERR) {
-                       do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
-                                       &res_size);
-               } else {
-                       printk(KERN_NOTICE PFX "%s error for block %d, nblock %d\n",
-                                translate_error(res_reg[1]), block, nblock);
-               }
-               goto try_read_again;
-       }
-      end_do_cdu31a_request:
-#if 0
-       /* After finished, cancel any pending operations. */
-       abort_read();
-#else
-       /* Start a timer to time out after a while to disable
-          the read. */
-       cdu31a_abort_timer.expires = jiffies + 2 * HZ;  /* Wait 2 seconds */
-       add_timer(&cdu31a_abort_timer);
-#endif
-
-       up(&sony_sem);
-       spin_lock_irq(q->queue_lock);
-       pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-
-/*
- * Read the table of contents from the drive and set up TOC if
- * successful.
- */
-static void sony_get_toc(void)
-{
-       unsigned char res_reg[2];
-       unsigned int res_size;
-       unsigned char parms[1];
-       int session;
-       int num_spin_ups;
-       int totaltracks = 0;
-       int mint = 99;
-       int maxt = 0;
-
-       pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
-       num_spin_ups = 0;
-       if (!sony_toc_read) {
-             respinup_on_gettoc:
-               /* Ignore the result, since it might error if spinning already. */
-               do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
-                              &res_size);
-
-               do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg,
-                              &res_size);
-
-               /* The drive sometimes returns error 0.  I don't know why, but ignore
-                  it.  It seems to mean the drive has already done the operation. */
-               if ((res_size < 2)
-                   || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
-                       /* If the drive is already playing, it's ok.  */
-                       if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR)
-                           || (res_reg[1] == 0)) {
-                               goto gettoc_drive_spinning;
-                       }
-
-                       /* If the drive says it is not spun up (even though we just did it!)
-                          then retry the operation at least a few times. */
-                       if ((res_reg[1] == SONY_NOT_SPIN_ERR)
-                           && (num_spin_ups < MAX_CDU31A_RETRIES)) {
-                               num_spin_ups++;
-                               goto respinup_on_gettoc;
-                       }
-
-                       printk("cdu31a: Error reading TOC: %x %s\n",
-                              res_reg[0], translate_error(res_reg[1]));
-                       return;
-               }
-
-             gettoc_drive_spinning:
-
-               /* The idea here is we keep asking for sessions until the command
-                  fails.  Then we know what the last valid session on the disk is.
-                  No need to check session 0, since session 0 is the same as session
-                  1; the command returns different information if you give it 0. 
-                */
-#if DEBUG
-               memset(&sony_toc, 0x0e, sizeof(sony_toc));
-               memset(&single_toc, 0x0f, sizeof(single_toc));
-#endif
-               session = 1;
-               while (1) {
-/* This seems to slow things down enough to make it work.  This
- * appears to be a problem in do_sony_cd_cmd.  This printk seems 
- * to address the symptoms...  -Erik */
-                       pr_debug(PFX "Trying session %d\n", session);
-                       parms[0] = session;
-                       do_sony_cd_cmd(SONY_READ_TOC_SPEC_CMD,
-                                      parms, 1, res_reg, &res_size);
-
-                       pr_debug(PFX "%2.2x %2.2x\n", res_reg[0], res_reg[1]);
-
-                       if ((res_size < 2)
-                           || ((res_reg[0] & 0xf0) == 0x20)) {
-                               /* An error reading the TOC, this must be past the last session. */
-                               if (session == 1)
-                                       printk
-                                           ("Yikes! Couldn't read any sessions!");
-                               break;
-                       }
-                       pr_debug(PFX "Reading session %d\n", session);
-
-                       parms[0] = session;
-                       do_sony_cd_cmd(SONY_REQ_TOC_DATA_SPEC_CMD,
-                                      parms,
-                                      1,
-                                      (unsigned char *) &single_toc,
-                                      &res_size);
-                       if ((res_size < 2)
-                           || ((single_toc.exec_status[0] & 0xf0) ==
-                               0x20)) {
-                               printk(KERN_ERR PFX "Error reading "
-                                               "session %d: %x %s\n",
-                                    session, single_toc.exec_status[0],
-                                    translate_error(single_toc.
-                                                    exec_status[1]));
-                               /* An error reading the TOC.  Return without sony_toc_read
-                                  set. */
-                               return;
-                       }
-                       pr_debug(PFX "add0 %01x, con0 %01x, poi0 %02x, "
-                                       "1st trk %d, dsktyp %x, dum0 %x\n",
-                            single_toc.address0, single_toc.control0,
-                            single_toc.point0,
-                            bcd_to_int(single_toc.first_track_num),
-                            single_toc.disk_type, single_toc.dummy0);
-                       pr_debug(PFX "add1 %01x, con1 %01x, poi1 %02x, "
-                                       "lst trk %d, dummy1 %x, dum2 %x\n",
-                            single_toc.address1, single_toc.control1,
-                            single_toc.point1,
-                            bcd_to_int(single_toc.last_track_num),
-                            single_toc.dummy1, single_toc.dummy2);
-                       pr_debug(PFX "add2 %01x, con2 %01x, poi2 %02x "
-                               "leadout start min %d, sec %d, frame %d\n",
-                            single_toc.address2, single_toc.control2,
-                            single_toc.point2,
-                            bcd_to_int(single_toc.lead_out_start_msf[0]),
-                            bcd_to_int(single_toc.lead_out_start_msf[1]),
-                            bcd_to_int(single_toc.lead_out_start_msf[2]));
-                       if (res_size > 18 && single_toc.pointb0 > 0xaf)
-                               pr_debug(PFX "addb0 %01x, conb0 %01x, poib0 %02x, nextsession min %d, sec %d, frame %d\n"
-                                    "#mode5_ptrs %02d, max_start_outer_leadout_msf min %d, sec %d, frame %d\n",
-                                    single_toc.addressb0,
-                                    single_toc.controlb0,
-                                    single_toc.pointb0,
-                                    bcd_to_int(single_toc.
-                                               next_poss_prog_area_msf
-                                               [0]),
-                                    bcd_to_int(single_toc.
-                                               next_poss_prog_area_msf
-                                               [1]),
-                                    bcd_to_int(single_toc.
-                                               next_poss_prog_area_msf
-                                               [2]),
-                                    single_toc.num_mode_5_pointers,
-                                    bcd_to_int(single_toc.
-                                               max_start_outer_leadout_msf
-                                               [0]),
-                                    bcd_to_int(single_toc.
-                                               max_start_outer_leadout_msf
-                                               [1]),
-                                    bcd_to_int(single_toc.
-                                               max_start_outer_leadout_msf
-                                               [2]));
-                       if (res_size > 27 && single_toc.pointb1 > 0xaf)
-                               pr_debug(PFX "addb1 %01x, conb1 %01x, poib1 %02x, %x %x %x %x #skipint_ptrs %d, #skiptrkassign %d %x\n",
-                                    single_toc.addressb1,
-                                    single_toc.controlb1,
-                                    single_toc.pointb1,
-                                    single_toc.dummyb0_1[0],
-                                    single_toc.dummyb0_1[1],
-                                    single_toc.dummyb0_1[2],
-                                    single_toc.dummyb0_1[3],
-                                    single_toc.num_skip_interval_pointers,
-                                    single_toc.num_skip_track_assignments,
-                                    single_toc.dummyb0_2);
-                       if (res_size > 36 && single_toc.pointb2 > 0xaf)
-                               pr_debug(PFX "addb2 %01x, conb2 %01x, poib2 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
-                                    single_toc.addressb2,
-                                    single_toc.controlb2,
-                                    single_toc.pointb2,
-                                    single_toc.tracksb2[0],
-                                    single_toc.tracksb2[1],
-                                    single_toc.tracksb2[2],
-                                    single_toc.tracksb2[3],
-                                    single_toc.tracksb2[4],
-                                    single_toc.tracksb2[5],
-                                    single_toc.tracksb2[6]);
-                       if (res_size > 45 && single_toc.pointb3 > 0xaf)
-                               pr_debug(PFX "addb3 %01x, conb3 %01x, poib3 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
-                                    single_toc.addressb3,
-                                    single_toc.controlb3,
-                                    single_toc.pointb3,
-                                    single_toc.tracksb3[0],
-                                    single_toc.tracksb3[1],
-                                    single_toc.tracksb3[2],
-                                    single_toc.tracksb3[3],
-                                    single_toc.tracksb3[4],
-                                    single_toc.tracksb3[5],
-                                    single_toc.tracksb3[6]);
-                       if (res_size > 54 && single_toc.pointb4 > 0xaf)
-                               pr_debug(PFX "addb4 %01x, conb4 %01x, poib4 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
-                                    single_toc.addressb4,
-                                    single_toc.controlb4,
-                                    single_toc.pointb4,
-                                    single_toc.tracksb4[0],
-                                    single_toc.tracksb4[1],
-                                    single_toc.tracksb4[2],
-                                    single_toc.tracksb4[3],
-                                    single_toc.tracksb4[4],
-                                    single_toc.tracksb4[5],
-                                    single_toc.tracksb4[6]);
-                       if (res_size > 63 && single_toc.pointc0 > 0xaf)
-                               pr_debug(PFX "addc0 %01x, conc0 %01x, poic0 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
-                                    single_toc.addressc0,
-                                    single_toc.controlc0,
-                                    single_toc.pointc0,
-                                    single_toc.dummyc0[0],
-                                    single_toc.dummyc0[1],
-                                    single_toc.dummyc0[2],
-                                    single_toc.dummyc0[3],
-                                    single_toc.dummyc0[4],
-                                    single_toc.dummyc0[5],
-                                    single_toc.dummyc0[6]);
-#undef DEBUG
-#define DEBUG 0
-
-                       sony_toc.lead_out_start_msf[0] =
-                           bcd_to_int(single_toc.lead_out_start_msf[0]);
-                       sony_toc.lead_out_start_msf[1] =
-                           bcd_to_int(single_toc.lead_out_start_msf[1]);
-                       sony_toc.lead_out_start_msf[2] =
-                           bcd_to_int(single_toc.lead_out_start_msf[2]);
-                       sony_toc.lead_out_start_lba =
-                           single_toc.lead_out_start_lba =
-                           msf_to_log(sony_toc.lead_out_start_msf);
-
-                       /* For points that do not exist, move the data over them
-                          to the right location. */
-                       if (single_toc.pointb0 != 0xb0) {
-                               memmove(((char *) &single_toc) + 27,
-                                       ((char *) &single_toc) + 18,
-                                       res_size - 18);
-                               res_size += 9;
-                       } else if (res_size > 18) {
-                               sony_toc.lead_out_start_msf[0] =
-                                   bcd_to_int(single_toc.
-                                              max_start_outer_leadout_msf
-                                              [0]);
-                               sony_toc.lead_out_start_msf[1] =
-                                   bcd_to_int(single_toc.
-                                              max_start_outer_leadout_msf
-                                              [1]);
-                               sony_toc.lead_out_start_msf[2] =
-                                   bcd_to_int(single_toc.
-                                              max_start_outer_leadout_msf
-                                              [2]);
-                               sony_toc.lead_out_start_lba =
-                                   msf_to_log(sony_toc.
-                                              lead_out_start_msf);
-                       }
-                       if (single_toc.pointb1 != 0xb1) {
-                               memmove(((char *) &single_toc) + 36,
-                                       ((char *) &single_toc) + 27,
-                                       res_size - 27);
-                               res_size += 9;
-                       }
-                       if (single_toc.pointb2 != 0xb2) {
-                               memmove(((char *) &single_toc) + 45,
-                                       ((char *) &single_toc) + 36,
-                                       res_size - 36);
-                               res_size += 9;
-                       }
-                       if (single_toc.pointb3 != 0xb3) {
-                               memmove(((char *) &single_toc) + 54,
-                                       ((char *) &single_toc) + 45,
-                                       res_size - 45);
-                               res_size += 9;
-                       }
-                       if (single_toc.pointb4 != 0xb4) {
-                               memmove(((char *) &single_toc) + 63,
-                                       ((char *) &single_toc) + 54,
-                                       res_size - 54);
-                               res_size += 9;
-                       }
-                       if (single_toc.pointc0 != 0xc0) {
-                               memmove(((char *) &single_toc) + 72,
-                                       ((char *) &single_toc) + 63,
-                                       res_size - 63);
-                               res_size += 9;
-                       }
-#if DEBUG
-                       printk(PRINT_INFO PFX "start track lba %u,  "
-                                       "leadout start lba %u\n",
-                            single_toc.start_track_lba,
-                            single_toc.lead_out_start_lba);
-                       {
-                               int i;
-                               for (i = 0;
-                                    i <
-                                    1 +
-                                    bcd_to_int(single_toc.last_track_num)
-                                    -
-                                    bcd_to_int(single_toc.
-                                               first_track_num); i++) {
-                                       printk(KERN_INFO PFX "trk %02d: add 0x%01x, con 0x%01x,  track %02d, start min %02d, sec %02d, frame %02d\n",
-                                            i,
-                                            single_toc.tracks[i].address,
-                                            single_toc.tracks[i].control,
-                                            bcd_to_int(single_toc.
-                                                       tracks[i].track),
-                                            bcd_to_int(single_toc.
-                                                       tracks[i].
-                                                       track_start_msf
-                                                       [0]),
-                                            bcd_to_int(single_toc.
-                                                       tracks[i].
-                                                       track_start_msf
-                                                       [1]),
-                                            bcd_to_int(single_toc.
-                                                       tracks[i].
-                                                       track_start_msf
-                                                       [2]));
-                                       if (mint >
-                                           bcd_to_int(single_toc.
-                                                      tracks[i].track))
-                                               mint =
-                                                   bcd_to_int(single_toc.
-                                                              tracks[i].
-                                                              track);
-                                       if (maxt <
-                                           bcd_to_int(single_toc.
-                                                      tracks[i].track))
-                                               maxt =
-                                                   bcd_to_int(single_toc.
-                                                              tracks[i].
-                                                              track);
-                               }
-                               printk(KERN_INFO PFX "min track number %d,  "
-                                               "max track number %d\n",
-                                    mint, maxt);
-                       }
-#endif
-
-                       /* prepare a special table of contents for a CD-I disc. They don't have one. */
-                       if (single_toc.disk_type == 0x10 &&
-                           single_toc.first_track_num == 2 &&
-                           single_toc.last_track_num == 2 /* CD-I */ ) {
-                               sony_toc.tracks[totaltracks].address = 1;
-                               sony_toc.tracks[totaltracks].control = 4;       /* force data tracks */
-                               sony_toc.tracks[totaltracks].track = 1;
-                               sony_toc.tracks[totaltracks].
-                                   track_start_msf[0] = 0;
-                               sony_toc.tracks[totaltracks].
-                                   track_start_msf[1] = 2;
-                               sony_toc.tracks[totaltracks].
-                                   track_start_msf[2] = 0;
-                               mint = maxt = 1;
-                               totaltracks++;
-                       } else
-                               /* gather track entries from this session */
-                       {
-                               int i;
-                               for (i = 0;
-                                    i <
-                                    1 +
-                                    bcd_to_int(single_toc.last_track_num)
-                                    -
-                                    bcd_to_int(single_toc.
-                                               first_track_num);
-                                    i++, totaltracks++) {
-                                       sony_toc.tracks[totaltracks].
-                                           address =
-                                           single_toc.tracks[i].address;
-                                       sony_toc.tracks[totaltracks].
-                                           control =
-                                           single_toc.tracks[i].control;
-                                       sony_toc.tracks[totaltracks].
-                                           track =
-                                           bcd_to_int(single_toc.
-                                                      tracks[i].track);
-                                       sony_toc.tracks[totaltracks].
-                                           track_start_msf[0] =
-                                           bcd_to_int(single_toc.
-                                                      tracks[i].
-                                                      track_start_msf[0]);
-                                       sony_toc.tracks[totaltracks].
-                                           track_start_msf[1] =
-                                           bcd_to_int(single_toc.
-                                                      tracks[i].
-                                                      track_start_msf[1]);
-                                       sony_toc.tracks[totaltracks].
-                                           track_start_msf[2] =
-                                           bcd_to_int(single_toc.
-                                                      tracks[i].
-                                                      track_start_msf[2]);
-                                       if (i == 0)
-                                               single_toc.
-                                                   start_track_lba =
-                                                   msf_to_log(sony_toc.
-                                                              tracks
-                                                              [totaltracks].
-                                                              track_start_msf);
-                                       if (mint >
-                                           sony_toc.tracks[totaltracks].
-                                           track)
-                                               mint =
-                                                   sony_toc.
-                                                   tracks[totaltracks].
-                                                   track;
-                                       if (maxt <
-                                           sony_toc.tracks[totaltracks].
-                                           track)
-                                               maxt =
-                                                   sony_toc.
-                                                   tracks[totaltracks].
-                                                   track;
-                               }
-                       }
-                       sony_toc.first_track_num = mint;
-                       sony_toc.last_track_num = maxt;
-                       /* Disk type of last session wins. For example:
-                          CD-Extra has disk type 0 for the first session, so
-                          a dumb HiFi CD player thinks it is a plain audio CD.
-                          We are interested in the disk type of the last session,
-                          which is 0x20 (XA) for CD-Extra, so we can access the
-                          data track ... */
-                       sony_toc.disk_type = single_toc.disk_type;
-                       sony_toc.sessions = session;
-
-                       /* don't believe everything :-) */
-                       if (session == 1)
-                               single_toc.start_track_lba = 0;
-                       sony_toc.start_track_lba =
-                           single_toc.start_track_lba;
-
-                       if (session > 1 && single_toc.pointb0 == 0xb0 &&
-                           sony_toc.lead_out_start_lba ==
-                           single_toc.lead_out_start_lba) {
-                               break;
-                       }
-
-                       /* Let's not get carried away... */
-                       if (session > 40) {
-                               printk(KERN_NOTICE PFX "too many sessions: "
-                                               "%d\n", session);
-                               break;
-                       }
-                       session++;
-               }
-               sony_toc.track_entries = totaltracks;
-               /* add one entry for the LAST track with track number CDROM_LEADOUT */
-               sony_toc.tracks[totaltracks].address = single_toc.address2;
-               sony_toc.tracks[totaltracks].control = single_toc.control2;
-               sony_toc.tracks[totaltracks].track = CDROM_LEADOUT;
-               sony_toc.tracks[totaltracks].track_start_msf[0] =
-                   sony_toc.lead_out_start_msf[0];
-               sony_toc.tracks[totaltracks].track_start_msf[1] =
-                   sony_toc.lead_out_start_msf[1];
-               sony_toc.tracks[totaltracks].track_start_msf[2] =
-                   sony_toc.lead_out_start_msf[2];
-
-               sony_toc_read = 1;
-
-               pr_debug(PFX "Disk session %d, start track: %d, "
-                               "stop track: %d\n",
-                    session, single_toc.start_track_lba,
-                    single_toc.lead_out_start_lba);
-       }
-       pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-
-/*
- * Uniform cdrom interface function
- * return multisession offset and sector information
- */
-static int scd_get_last_session(struct cdrom_device_info *cdi,
-                               struct cdrom_multisession *ms_info)
-{
-       if (ms_info == NULL)
-               return 1;
-
-       if (!sony_toc_read) {
-               if (down_interruptible(&sony_sem))
-                       return -ERESTARTSYS;
-               sony_get_toc();
-               up(&sony_sem);
-       }
-
-       ms_info->addr_format = CDROM_LBA;
-       ms_info->addr.lba = sony_toc.start_track_lba;
-       ms_info->xa_flag = sony_toc.disk_type == SONY_XA_DISK_TYPE ||
-           sony_toc.disk_type == 0x10 /* CDI */ ;
-
-       return 0;
-}
-
-/*
- * Search for a specific track in the table of contents.
- */
-static int find_track(int track)
-{
-       int i;
-
-       for (i = 0; i <= sony_toc.track_entries; i++) {
-               if (sony_toc.tracks[i].track == track) {
-                       return i;
-               }
-       }
-
-       return -1;
-}
-
-
-/*
- * Read the subcode and put it in last_sony_subcode for future use.
- */
-static int read_subcode(void)
-{
-       unsigned int res_size;
-
-
-       do_sony_cd_cmd(SONY_REQ_SUBCODE_ADDRESS_CMD,
-                      NULL,
-                      0, (unsigned char *) &last_sony_subcode, &res_size);
-       if ((res_size < 2)
-           || ((last_sony_subcode.exec_status[0] & 0xf0) == 0x20)) {
-               printk(KERN_ERR PFX "Sony CDROM error %s (read_subcode)\n",
-                      translate_error(last_sony_subcode.exec_status[1]));
-               return -EIO;
-       }
-
-       last_sony_subcode.track_num =
-           bcd_to_int(last_sony_subcode.track_num);
-       last_sony_subcode.index_num =
-           bcd_to_int(last_sony_subcode.index_num);
-       last_sony_subcode.abs_msf[0] =
-           bcd_to_int(last_sony_subcode.abs_msf[0]);
-       last_sony_subcode.abs_msf[1] =
-           bcd_to_int(last_sony_subcode.abs_msf[1]);
-       last_sony_subcode.abs_msf[2] =
-           bcd_to_int(last_sony_subcode.abs_msf[2]);
-
-       last_sony_subcode.rel_msf[0] =
-           bcd_to_int(last_sony_subcode.rel_msf[0]);
-       last_sony_subcode.rel_msf[1] =
-           bcd_to_int(last_sony_subcode.rel_msf[1]);
-       last_sony_subcode.rel_msf[2] =
-           bcd_to_int(last_sony_subcode.rel_msf[2]);
-       return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * return the media catalog number found on some older audio cds
- */
-static int
-scd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
-       unsigned char resbuffer[2 + 14];
-       unsigned char *mcnp = mcn->medium_catalog_number;
-       unsigned char *resp = resbuffer + 3;
-       unsigned int res_size;
-
-       memset(mcn->medium_catalog_number, 0, 14);
-       if (down_interruptible(&sony_sem))
-               return -ERESTARTSYS;
-       do_sony_cd_cmd(SONY_REQ_UPC_EAN_CMD,
-                      NULL, 0, resbuffer, &res_size);
-       up(&sony_sem);
-       if ((res_size < 2) || ((resbuffer[0] & 0xf0) == 0x20));
-       else {
-               /* packed bcd to single ASCII digits */
-               *mcnp++ = (*resp >> 4) + '0';
-               *mcnp++ = (*resp++ & 0x0f) + '0';
-               *mcnp++ = (*resp >> 4) + '0';
-               *mcnp++ = (*resp++ & 0x0f) + '0';
-               *mcnp++ = (*resp >> 4) + '0';
-               *mcnp++ = (*resp++ & 0x0f) + '0';
-               *mcnp++ = (*resp >> 4) + '0';
-               *mcnp++ = (*resp++ & 0x0f) + '0';
-               *mcnp++ = (*resp >> 4) + '0';
-               *mcnp++ = (*resp++ & 0x0f) + '0';
-               *mcnp++ = (*resp >> 4) + '0';
-               *mcnp++ = (*resp++ & 0x0f) + '0';
-               *mcnp++ = (*resp >> 4) + '0';
-       }
-       *mcnp = '\0';
-       return 0;
-}
-
-
-/*
- * Get the subchannel info like the CDROMSUBCHNL command wants to see it.  If
- * the drive is playing, the subchannel needs to be read (since it would be
- * changing).  If the drive is paused or completed, the subcode information has
- * already been stored, just use that.  The ioctl call wants things in decimal
- * (not BCD), so all the conversions are done.
- */
-static int sony_get_subchnl_info(struct cdrom_subchnl *schi)
-{
-       /* Get attention stuff */
-       while (handle_sony_cd_attention());
-
-       sony_get_toc();
-       if (!sony_toc_read) {
-               return -EIO;
-       }
-
-       switch (sony_audio_status) {
-       case CDROM_AUDIO_NO_STATUS:
-       case CDROM_AUDIO_PLAY:
-               if (read_subcode() < 0) {
-                       return -EIO;
-               }
-               break;
-
-       case CDROM_AUDIO_PAUSED:
-       case CDROM_AUDIO_COMPLETED:
-               break;
-
-#if 0
-       case CDROM_AUDIO_NO_STATUS:
-               schi->cdsc_audiostatus = sony_audio_status;
-               return 0;
-               break;
-#endif
-       case CDROM_AUDIO_INVALID:
-       case CDROM_AUDIO_ERROR:
-       default:
-               return -EIO;
-       }
-
-       schi->cdsc_audiostatus = sony_audio_status;
-       schi->cdsc_adr = last_sony_subcode.address;
-       schi->cdsc_ctrl = last_sony_subcode.control;
-       schi->cdsc_trk = last_sony_subcode.track_num;
-       schi->cdsc_ind = last_sony_subcode.index_num;
-       if (schi->cdsc_format == CDROM_MSF) {
-               schi->cdsc_absaddr.msf.minute =
-                   last_sony_subcode.abs_msf[0];
-               schi->cdsc_absaddr.msf.second =
-                   last_sony_subcode.abs_msf[1];
-               schi->cdsc_absaddr.msf.frame =
-                   last_sony_subcode.abs_msf[2];
-
-               schi->cdsc_reladdr.msf.minute =
-                   last_sony_subcode.rel_msf[0];
-               schi->cdsc_reladdr.msf.second =
-                   last_sony_subcode.rel_msf[1];
-               schi->cdsc_reladdr.msf.frame =
-                   last_sony_subcode.rel_msf[2];
-       } else if (schi->cdsc_format == CDROM_LBA) {
-               schi->cdsc_absaddr.lba =
-                   msf_to_log(last_sony_subcode.abs_msf);
-               schi->cdsc_reladdr.lba =
-                   msf_to_log(last_sony_subcode.rel_msf);
-       }
-
-       return 0;
-}
-
-/* Get audio data from the drive.  This is fairly complex because I
-   am looking for status and data at the same time, but if I get status
-   then I just look for data.  I need to get the status immediately so
-   the switch from audio to data tracks will happen quickly. */
-static void
-read_audio_data(char *buffer, unsigned char res_reg[], int *res_size)
-{
-       unsigned long retry_count;
-       int result_read;
-
-
-       res_reg[0] = 0;
-       res_reg[1] = 0;
-       *res_size = 0;
-       result_read = 0;
-
-       /* Wait for the drive to tell us we have something */
-       retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-      continue_read_audio_wait:
-       while (time_before(jiffies, retry_count) && !(is_data_ready())
-              && !(is_result_ready() || result_read)) {
-               while (handle_sony_cd_attention());
-
-               sony_sleep();
-       }
-       if (!(is_data_ready())) {
-               if (is_result_ready() && !result_read) {
-                       get_result(res_reg, res_size);
-
-                       /* Read block status and continue waiting for data. */
-                       if ((res_reg[0] & 0xf0) == 0x50) {
-                               result_read = 1;
-                               goto continue_read_audio_wait;
-                       }
-                       /* Invalid data from the drive.  Shut down the operation. */
-                       else if ((res_reg[0] & 0xf0) != 0x20) {
-                               printk(KERN_WARNING PFX "Got result that "
-                                               "should have been error: %d\n",
-                                    res_reg[0]);
-                               res_reg[0] = 0x20;
-                               res_reg[1] = SONY_BAD_DATA_ERR;
-                               *res_size = 2;
-                       }
-                       abort_read();
-               } else {
-                       pr_debug(PFX "timeout out %d\n", __LINE__);
-                       res_reg[0] = 0x20;
-                       res_reg[1] = SONY_TIMEOUT_OP_ERR;
-                       *res_size = 2;
-                       abort_read();
-               }
-       } else {
-               clear_data_ready();
-
-               /* If data block, then get 2340 bytes offset by 12. */
-               if (sony_raw_data_mode) {
-                       insb(sony_cd_read_reg, buffer + CD_XA_HEAD,
-                            CD_FRAMESIZE_RAW1);
-               } else {
-                       /* Audio gets the whole 2352 bytes. */
-                       insb(sony_cd_read_reg, buffer, CD_FRAMESIZE_RAW);
-               }
-
-               /* If I haven't already gotten the result, get it now. */
-               if (!result_read) {
-                       /* Wait for the drive to tell us we have something */
-                       retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-                       while (time_before(jiffies, retry_count)
-                              && !(is_result_ready())) {
-                               while (handle_sony_cd_attention());
-
-                               sony_sleep();
-                       }
-
-                       if (!is_result_ready()) {
-                               pr_debug(PFX "timeout out %d\n", __LINE__);
-                               res_reg[0] = 0x20;
-                               res_reg[1] = SONY_TIMEOUT_OP_ERR;
-                               *res_size = 2;
-                               abort_read();
-                               return;
-                       } else {
-                               get_result(res_reg, res_size);
-                       }
-               }
-
-               if ((res_reg[0] & 0xf0) == 0x50) {
-                       if ((res_reg[0] == SONY_NO_CIRC_ERR_BLK_STAT)
-                           || (res_reg[0] == SONY_NO_LECC_ERR_BLK_STAT)
-                           || (res_reg[0] == SONY_RECOV_LECC_ERR_BLK_STAT)
-                           || (res_reg[0] == SONY_NO_ERR_DETECTION_STAT)) {
-                               /* Ok, nothing to do. */
-                       } else {
-                               printk(KERN_ERR PFX "Data block error: 0x%x\n",
-                                      res_reg[0]);
-                               res_reg[0] = 0x20;
-                               res_reg[1] = SONY_BAD_DATA_ERR;
-                               *res_size = 2;
-                       }
-               } else if ((res_reg[0] & 0xf0) != 0x20) {
-                       /* The drive gave me bad status, I don't know what to do.
-                          Reset the driver and return an error. */
-                       printk(KERN_NOTICE PFX "Invalid block status: 0x%x\n",
-                              res_reg[0]);
-                       restart_on_error();
-                       res_reg[0] = 0x20;
-                       res_reg[1] = SONY_BAD_DATA_ERR;
-                       *res_size = 2;
-               }
-       }
-}
-
-/* Perform a raw data read.  This will automatically detect the
-   track type and read the proper data (audio or data). */
-static int read_audio(struct cdrom_read_audio *ra)
-{
-       int retval;
-       unsigned char params[2];
-       unsigned char res_reg[12];
-       unsigned int res_size;
-       unsigned int cframe;
-
-       if (down_interruptible(&sony_sem))
-               return -ERESTARTSYS;
-       if (!sony_spun_up)
-               scd_spinup();
-
-       /* Set the drive to do raw operations. */
-       params[0] = SONY_SD_DECODE_PARAM;
-       params[1] = 0x06 | sony_raw_data_mode;
-       do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-                      params, 2, res_reg, &res_size);
-       if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
-               printk(KERN_ERR PFX "Unable to set decode params: 0x%2.2x\n",
-                      res_reg[1]);
-               retval = -EIO;
-               goto out_up;
-       }
-
-       /* From here down, we have to goto exit_read_audio instead of returning
-          because the drive parameters have to be set back to data before
-          return. */
-
-       retval = 0;
-       if (start_request(ra->addr.lba, ra->nframes)) {
-               retval = -EIO;
-               goto exit_read_audio;
-       }
-
-       /* For every requested frame. */
-       cframe = 0;
-       while (cframe < ra->nframes) {
-               read_audio_data(audio_buffer, res_reg, &res_size);
-               if ((res_reg[0] & 0xf0) == 0x20) {
-                       if (res_reg[1] == SONY_BAD_DATA_ERR) {
-                               printk(KERN_ERR PFX "Data error on audio "
-                                               "sector %d\n",
-                                    ra->addr.lba + cframe);
-                       } else if (res_reg[1] == SONY_ILL_TRACK_R_ERR) {
-                               /* Illegal track type, change track types and start over. */
-                               sony_raw_data_mode =
-                                   (sony_raw_data_mode) ? 0 : 1;
-
-                               /* Set the drive mode. */
-                               params[0] = SONY_SD_DECODE_PARAM;
-                               params[1] = 0x06 | sony_raw_data_mode;
-                               do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-                                              params,
-                                              2, res_reg, &res_size);
-                               if ((res_size < 2)
-                                   || ((res_reg[0] & 0xf0) == 0x20)) {
-                                       printk(KERN_ERR PFX "Unable to set "
-                                               "decode params: 0x%2.2x\n",
-                                            res_reg[1]);
-                                       retval = -EIO;
-                                       goto exit_read_audio;
-                               }
-
-                               /* Restart the request on the current frame. */
-                               if (start_request
-                                   (ra->addr.lba + cframe,
-                                    ra->nframes - cframe)) {
-                                       retval = -EIO;
-                                       goto exit_read_audio;
-                               }
-
-                               /* Don't go back to the top because don't want to get into
-                                  and infinite loop.  A lot of code gets duplicated, but
-                                  that's no big deal, I don't guess. */
-                               read_audio_data(audio_buffer, res_reg,
-                                               &res_size);
-                               if ((res_reg[0] & 0xf0) == 0x20) {
-                                       if (res_reg[1] ==
-                                           SONY_BAD_DATA_ERR) {
-                                               printk(KERN_ERR PFX "Data error"
-                                                       " on audio sector %d\n",
-                                                    ra->addr.lba +
-                                                    cframe);
-                                       } else {
-                                               printk(KERN_ERR PFX "Error reading audio data on sector %d: %s\n",
-                                                    ra->addr.lba + cframe,
-                                                    translate_error
-                                                    (res_reg[1]));
-                                               retval = -EIO;
-                                               goto exit_read_audio;
-                                       }
-                               } else if (copy_to_user(ra->buf +
-                                                              (CD_FRAMESIZE_RAW
-                                                               * cframe),
-                                                       audio_buffer,
-                                                       CD_FRAMESIZE_RAW)) {
-                                       retval = -EFAULT;
-                                       goto exit_read_audio;
-                               }
-                       } else {
-                               printk(KERN_ERR PFX "Error reading audio "
-                                               "data on sector %d: %s\n",
-                                    ra->addr.lba + cframe,
-                                    translate_error(res_reg[1]));
-                               retval = -EIO;
-                               goto exit_read_audio;
-                       }
-               } else if (copy_to_user(ra->buf + (CD_FRAMESIZE_RAW * cframe),
-                                       (char *)audio_buffer,
-                                       CD_FRAMESIZE_RAW)) {
-                       retval = -EFAULT;
-                       goto exit_read_audio;
-               }
-
-               cframe++;
-       }
-
-       get_result(res_reg, &res_size);
-       if ((res_reg[0] & 0xf0) == 0x20) {
-               printk(KERN_ERR PFX "Error return from audio read: %s\n",
-                      translate_error(res_reg[1]));
-               retval = -EIO;
-               goto exit_read_audio;
-       }
-
-      exit_read_audio:
-
-       /* Set the drive mode back to the proper one for the disk. */
-       params[0] = SONY_SD_DECODE_PARAM;
-       if (!sony_xa_mode) {
-               params[1] = 0x0f;
-       } else {
-               params[1] = 0x07;
-       }
-       do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-                      params, 2, res_reg, &res_size);
-       if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
-               printk(KERN_ERR PFX "Unable to reset decode params: 0x%2.2x\n",
-                      res_reg[1]);
-               retval = -EIO;
-       }
-
- out_up:
-       up(&sony_sem);
-
-       return retval;
-}
-
-static int
-do_sony_cd_cmd_chk(const char *name,
-                  unsigned char cmd,
-                  unsigned char *params,
-                  unsigned int num_params,
-                  unsigned char *result_buffer, unsigned int *result_size)
-{
-       do_sony_cd_cmd(cmd, params, num_params, result_buffer,
-                      result_size);
-       if ((*result_size < 2) || ((result_buffer[0] & 0xf0) == 0x20)) {
-               printk(KERN_ERR PFX "Error %s (CDROM%s)\n",
-                      translate_error(result_buffer[1]), name);
-               return -EIO;
-       }
-       return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * open the tray
- */
-static int scd_tray_move(struct cdrom_device_info *cdi, int position)
-{
-       int retval;
-
-       if (down_interruptible(&sony_sem))
-               return -ERESTARTSYS;
-       if (position == 1 /* open tray */ ) {
-               unsigned char res_reg[12];
-               unsigned int res_size;
-
-               do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
-                              &res_size);
-               do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
-                              &res_size);
-
-               sony_audio_status = CDROM_AUDIO_INVALID;
-               retval = do_sony_cd_cmd_chk("EJECT", SONY_EJECT_CMD, NULL, 0,
-                                         res_reg, &res_size);
-       } else {
-               if (0 == scd_spinup())
-                       sony_spun_up = 1;
-               retval = 0;
-       }
-       up(&sony_sem);
-       return retval;
-}
-
-/*
- * The big ugly ioctl handler.
- */
-static int scd_audio_ioctl(struct cdrom_device_info *cdi,
-                          unsigned int cmd, void *arg)
-{
-       unsigned char res_reg[12];
-       unsigned int res_size;
-       unsigned char params[7];
-       int i, retval;
-
-       if (down_interruptible(&sony_sem))
-               return -ERESTARTSYS;
-       switch (cmd) {
-       case CDROMSTART:        /* Spin up the drive */
-               retval = do_sony_cd_cmd_chk("START", SONY_SPIN_UP_CMD, NULL,
-                                         0, res_reg, &res_size);
-               break;
-
-       case CDROMSTOP: /* Spin down the drive */
-               do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
-                              &res_size);
-
-               /*
-                * Spin the drive down, ignoring the error if the disk was
-                * already not spinning.
-                */
-               sony_audio_status = CDROM_AUDIO_NO_STATUS;
-               retval = do_sony_cd_cmd_chk("STOP", SONY_SPIN_DOWN_CMD, NULL,
-                                         0, res_reg, &res_size);
-               break;
-
-       case CDROMPAUSE:        /* Pause the drive */
-               if (do_sony_cd_cmd_chk
-                   ("PAUSE", SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
-                    &res_size)) {
-                       retval = -EIO;
-                       break;
-               }
-               /* Get the current position and save it for resuming */
-               if (read_subcode() < 0) {
-                       retval = -EIO;
-                       break;
-               }
-               cur_pos_msf[0] = last_sony_subcode.abs_msf[0];
-               cur_pos_msf[1] = last_sony_subcode.abs_msf[1];
-               cur_pos_msf[2] = last_sony_subcode.abs_msf[2];
-               sony_audio_status = CDROM_AUDIO_PAUSED;
-               retval = 0;
-               break;
-
-       case CDROMRESUME:       /* Start the drive after being paused */
-               if (sony_audio_status != CDROM_AUDIO_PAUSED) {
-                       retval = -EINVAL;
-                       break;
-               }
-
-               do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
-                              &res_size);
-
-               /* Start the drive at the saved position. */
-               params[1] = int_to_bcd(cur_pos_msf[0]);
-               params[2] = int_to_bcd(cur_pos_msf[1]);
-               params[3] = int_to_bcd(cur_pos_msf[2]);
-               params[4] = int_to_bcd(final_pos_msf[0]);
-               params[5] = int_to_bcd(final_pos_msf[1]);
-               params[6] = int_to_bcd(final_pos_msf[2]);
-               params[0] = 0x03;
-               if (do_sony_cd_cmd_chk
-                   ("RESUME", SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg,
-                    &res_size) < 0) {
-                       retval = -EIO;
-                       break;
-               }
-               sony_audio_status = CDROM_AUDIO_PLAY;
-               retval = 0;
-               break;
-
-       case CDROMPLAYMSF:      /* Play starting at the given MSF address. */
-               do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
-                              &res_size);
-
-               /* The parameters are given in int, must be converted */
-               for (i = 1; i < 7; i++) {
-                       params[i] =
-                           int_to_bcd(((unsigned char *) arg)[i - 1]);
-               }
-               params[0] = 0x03;
-               if (do_sony_cd_cmd_chk
-                   ("PLAYMSF", SONY_AUDIO_PLAYBACK_CMD, params, 7,
-                    res_reg, &res_size) < 0) {
-                       retval = -EIO;
-                       break;
-               }
-
-               /* Save the final position for pauses and resumes */
-               final_pos_msf[0] = bcd_to_int(params[4]);
-               final_pos_msf[1] = bcd_to_int(params[5]);
-               final_pos_msf[2] = bcd_to_int(params[6]);
-               sony_audio_status = CDROM_AUDIO_PLAY;
-               retval = 0;
-               break;
-
-       case CDROMREADTOCHDR:   /* Read the table of contents header */
-               {
-                       struct cdrom_tochdr *hdr;
-
-                       sony_get_toc();
-                       if (!sony_toc_read) {
-                               retval = -EIO;
-                               break;
-                       }
-
-                       hdr = (struct cdrom_tochdr *) arg;
-                       hdr->cdth_trk0 = sony_toc.first_track_num;
-                       hdr->cdth_trk1 = sony_toc.last_track_num;
-               }
-               retval = 0;
-               break;
-
-       case CDROMREADTOCENTRY: /* Read a given table of contents entry */
-               {
-                       struct cdrom_tocentry *entry;
-                       int track_idx;
-                       unsigned char *msf_val = NULL;
-
-                       sony_get_toc();
-                       if (!sony_toc_read) {
-                               retval = -EIO;
-                               break;
-                       }
-
-                       entry = (struct cdrom_tocentry *) arg;
-
-                       track_idx = find_track(entry->cdte_track);
-                       if (track_idx < 0) {
-                               retval = -EINVAL;
-                               break;
-                       }
-
-                       entry->cdte_adr =
-                           sony_toc.tracks[track_idx].address;
-                       entry->cdte_ctrl =
-                           sony_toc.tracks[track_idx].control;
-                       msf_val =
-                           sony_toc.tracks[track_idx].track_start_msf;
-
-                       /* Logical buffer address or MSF format requested? */
-                       if (entry->cdte_format == CDROM_LBA) {
-                               entry->cdte_addr.lba = msf_to_log(msf_val);
-                       } else if (entry->cdte_format == CDROM_MSF) {
-                               entry->cdte_addr.msf.minute = *msf_val;
-                               entry->cdte_addr.msf.second =
-                                   *(msf_val + 1);
-                               entry->cdte_addr.msf.frame =
-                                   *(msf_val + 2);
-                       }
-               }
-               retval = 0;
-               break;
-
-       case CDROMPLAYTRKIND:   /* Play a track.  This currently ignores index. */
-               {
-                       struct cdrom_ti *ti = (struct cdrom_ti *) arg;
-                       int track_idx;
-
-                       sony_get_toc();
-                       if (!sony_toc_read) {
-                               retval = -EIO;
-                               break;
-                       }
-
-                       if ((ti->cdti_trk0 < sony_toc.first_track_num)
-                           || (ti->cdti_trk0 > sony_toc.last_track_num)
-                           || (ti->cdti_trk1 < ti->cdti_trk0)) {
-                               retval = -EINVAL;
-                               break;
-                       }
-
-                       track_idx = find_track(ti->cdti_trk0);
-                       if (track_idx < 0) {
-                               retval = -EINVAL;
-                               break;
-                       }
-                       params[1] =
-                           int_to_bcd(sony_toc.tracks[track_idx].
-                                      track_start_msf[0]);
-                       params[2] =
-                           int_to_bcd(sony_toc.tracks[track_idx].
-                                      track_start_msf[1]);
-                       params[3] =
-                           int_to_bcd(sony_toc.tracks[track_idx].
-                                      track_start_msf[2]);
-
-                       /*
-                        * If we want to stop after the last track, use the lead-out
-                        * MSF to do that.
-                        */
-                       if (ti->cdti_trk1 >= sony_toc.last_track_num) {
-                               track_idx = find_track(CDROM_LEADOUT);
-                       } else {
-                               track_idx = find_track(ti->cdti_trk1 + 1);
-                       }
-                       if (track_idx < 0) {
-                               retval = -EINVAL;
-                               break;
-                       }
-                       params[4] =
-                           int_to_bcd(sony_toc.tracks[track_idx].
-                                      track_start_msf[0]);
-                       params[5] =
-                           int_to_bcd(sony_toc.tracks[track_idx].
-                                      track_start_msf[1]);
-                       params[6] =
-                           int_to_bcd(sony_toc.tracks[track_idx].
-                                      track_start_msf[2]);
-                       params[0] = 0x03;
-
-                       do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
-                                      &res_size);
-
-                       do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7,
-                                      res_reg, &res_size);
-
-                       if ((res_size < 2)
-                           || ((res_reg[0] & 0xf0) == 0x20)) {
-                               printk(KERN_ERR PFX
-                                       "Params: %x %x %x %x %x %x %x\n",
-                                      params[0], params[1], params[2],
-                                      params[3], params[4], params[5],
-                                      params[6]);
-                               printk(KERN_ERR PFX
-                                       "Error %s (CDROMPLAYTRKIND)\n",
-                                    translate_error(res_reg[1]));
-                               retval = -EIO;
-                               break;
-                       }
-
-                       /* Save the final position for pauses and resumes */
-                       final_pos_msf[0] = bcd_to_int(params[4]);
-                       final_pos_msf[1] = bcd_to_int(params[5]);
-                       final_pos_msf[2] = bcd_to_int(params[6]);
-                       sony_audio_status = CDROM_AUDIO_PLAY;
-                       retval = 0;
-                       break;
-               }
-
-       case CDROMVOLCTRL:      /* Volume control.  What volume does this change, anyway? */
-               {
-                       struct cdrom_volctrl *volctrl =
-                           (struct cdrom_volctrl *) arg;
-
-                       params[0] = SONY_SD_AUDIO_VOLUME;
-                       params[1] = volctrl->channel0;
-                       params[2] = volctrl->channel1;
-                       retval = do_sony_cd_cmd_chk("VOLCTRL",
-                                                 SONY_SET_DRIVE_PARAM_CMD,
-                                                 params, 3, res_reg,
-                                                 &res_size);
-                       break;
-               }
-       case CDROMSUBCHNL:      /* Get subchannel info */
-               retval = sony_get_subchnl_info((struct cdrom_subchnl *) arg);
-               break;
-
-       default:
-               retval = -EINVAL;
-               break;
-       }
-       up(&sony_sem);
-       return retval;
-}
-
-static int scd_read_audio(struct cdrom_device_info *cdi,
-                        unsigned int cmd, unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int retval;
-
-       if (down_interruptible(&sony_sem))
-               return -ERESTARTSYS;
-       switch (cmd) {
-       case CDROMREADAUDIO:    /* Read 2352 byte audio tracks and 2340 byte
-                                  raw data tracks. */
-               {
-                       struct cdrom_read_audio ra;
-
-
-                       sony_get_toc();
-                       if (!sony_toc_read) {
-                               retval = -EIO;
-                               break;
-                       }
-
-                       if (copy_from_user(&ra, argp, sizeof(ra))) {
-                               retval = -EFAULT;
-                               break;
-                       }
-
-                       if (ra.nframes == 0) {
-                               retval = 0;
-                               break;
-                       }
-
-                       if (!access_ok(VERIFY_WRITE, ra.buf,
-                                       CD_FRAMESIZE_RAW * ra.nframes))
-                               return -EFAULT;
-
-                       if (ra.addr_format == CDROM_LBA) {
-                               if ((ra.addr.lba >=
-                                    sony_toc.lead_out_start_lba)
-                                   || (ra.addr.lba + ra.nframes >=
-                                       sony_toc.lead_out_start_lba)) {
-                                       retval = -EINVAL;
-                                       break;
-                               }
-                       } else if (ra.addr_format == CDROM_MSF) {
-                               if ((ra.addr.msf.minute >= 75)
-                                   || (ra.addr.msf.second >= 60)
-                                   || (ra.addr.msf.frame >= 75)) {
-                                       retval = -EINVAL;
-                                       break;
-                               }
-
-                               ra.addr.lba = ((ra.addr.msf.minute * 4500)
-                                              + (ra.addr.msf.second * 75)
-                                              + ra.addr.msf.frame);
-                               if ((ra.addr.lba >=
-                                    sony_toc.lead_out_start_lba)
-                                   || (ra.addr.lba + ra.nframes >=
-                                       sony_toc.lead_out_start_lba)) {
-                                       retval = -EINVAL;
-                                       break;
-                               }
-
-                               /* I know, this can go negative on an unsigned.  However,
-                                  the first thing done to the data is to add this value,
-                                  so this should compensate and allow direct msf access. */
-                               ra.addr.lba -= LOG_START_OFFSET;
-                       } else {
-                               retval = -EINVAL;
-                               break;
-                       }
-
-                       retval = read_audio(&ra);
-                       break;
-               }
-               retval = 0;
-               break;
-
-       default:
-               retval = -EINVAL;
-       }
-       up(&sony_sem);
-       return retval;
-}
-
-static int scd_spinup(void)
-{
-       unsigned char res_reg[12];
-       unsigned int res_size;
-       int num_spin_ups;
-
-       num_spin_ups = 0;
-
-      respinup_on_open:
-       do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
-
-       /* The drive sometimes returns error 0.  I don't know why, but ignore
-          it.  It seems to mean the drive has already done the operation. */
-       if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
-               printk(KERN_ERR PFX "%s error (scd_open, spin up)\n",
-                      translate_error(res_reg[1]));
-               return 1;
-       }
-
-       do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size);
-
-       /* The drive sometimes returns error 0.  I don't know why, but ignore
-          it.  It seems to mean the drive has already done the operation. */
-       if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
-               /* If the drive is already playing, it's ok.  */
-               if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR)
-                   || (res_reg[1] == 0)) {
-                       return 0;
-               }
-
-               /* If the drive says it is not spun up (even though we just did it!)
-                  then retry the operation at least a few times. */
-               if ((res_reg[1] == SONY_NOT_SPIN_ERR)
-                   && (num_spin_ups < MAX_CDU31A_RETRIES)) {
-                       num_spin_ups++;
-                       goto respinup_on_open;
-               }
-
-               printk(KERN_ERR PFX "Error %s (scd_open, read toc)\n",
-                      translate_error(res_reg[1]));
-               do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
-                              &res_size);
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * Open the drive for operations.  Spin the drive up and read the table of
- * contents if these have not already been done.
- */
-static int scd_open(struct cdrom_device_info *cdi, int purpose)
-{
-       unsigned char res_reg[12];
-       unsigned int res_size;
-       unsigned char params[2];
-
-       if (purpose == 1) {
-               /* Open for IOCTLs only - no media check */
-               sony_usage++;
-               return 0;
-       }
-
-       if (sony_usage == 0) {
-               if (scd_spinup() != 0)
-                       return -EIO;
-               sony_get_toc();
-               if (!sony_toc_read) {
-                       do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0,
-                                      res_reg, &res_size);
-                       return -EIO;
-               }
-
-               /* For XA on the CDU31A only, we have to do special reads.
-                  The CDU33A handles XA automagically. */
-               /* if (   (sony_toc.disk_type == SONY_XA_DISK_TYPE) */
-               if ((sony_toc.disk_type != 0x00)
-                   && (!is_double_speed)) {
-                       params[0] = SONY_SD_DECODE_PARAM;
-                       params[1] = 0x07;
-                       do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-                                      params, 2, res_reg, &res_size);
-                       if ((res_size < 2)
-                           || ((res_reg[0] & 0xf0) == 0x20)) {
-                               printk(KERN_WARNING PFX "Unable to set "
-                                       "XA params: 0x%2.2x\n", res_reg[1]);
-                       }
-                       sony_xa_mode = 1;
-               }
-               /* A non-XA disk.  Set the parms back if necessary. */
-               else if (sony_xa_mode) {
-                       params[0] = SONY_SD_DECODE_PARAM;
-                       params[1] = 0x0f;
-                       do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-                                      params, 2, res_reg, &res_size);
-                       if ((res_size < 2)
-                           || ((res_reg[0] & 0xf0) == 0x20)) {
-                               printk(KERN_WARNING PFX "Unable to reset "
-                                       "XA params: 0x%2.2x\n", res_reg[1]);
-                       }
-                       sony_xa_mode = 0;
-               }
-
-               sony_spun_up = 1;
-       }
-
-       sony_usage++;
-
-       return 0;
-}
-
-
-/*
- * Close the drive.  Spin it down if no task is using it.  The spin
- * down will fail if playing audio, so audio play is OK.
- */
-static void scd_release(struct cdrom_device_info *cdi)
-{
-       if (sony_usage == 1) {
-               unsigned char res_reg[12];
-               unsigned int res_size;
-
-               do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
-                              &res_size);
-
-               sony_spun_up = 0;
-       }
-       sony_usage--;
-}
-
-static struct cdrom_device_ops scd_dops = {
-       .open                   = scd_open,
-       .release                = scd_release,
-       .drive_status           = scd_drive_status,
-       .media_changed          = scd_media_changed,
-       .tray_move              = scd_tray_move,
-       .lock_door              = scd_lock_door,
-       .select_speed           = scd_select_speed,
-       .get_last_session       = scd_get_last_session,
-       .get_mcn                = scd_get_mcn,
-       .reset                  = scd_reset,
-       .audio_ioctl            = scd_audio_ioctl,
-       .capability             = CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK |
-                                 CDC_SELECT_SPEED | CDC_MULTI_SESSION |
-                                 CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
-                                 CDC_RESET | CDC_DRIVE_STATUS,
-       .n_minors               = 1,
-};
-
-static struct cdrom_device_info scd_info = {
-       .ops            = &scd_dops,
-       .speed          = 2,
-       .capacity       = 1,
-       .name           = "cdu31a"
-};
-
-static int scd_block_open(struct inode *inode, struct file *file)
-{
-       return cdrom_open(&scd_info, inode, file);
-}
-
-static int scd_block_release(struct inode *inode, struct file *file)
-{
-       return cdrom_release(&scd_info, file);
-}
-
-static int scd_block_ioctl(struct inode *inode, struct file *file,
-                               unsigned cmd, unsigned long arg)
-{
-       int retval;
-
-       /* The eject and close commands should be handled by Uniform CD-ROM
-        * driver - but I always got hard lockup instead of eject
-        * until I put this here.
-        */
-       switch (cmd) {
-               case CDROMEJECT:
-                       scd_lock_door(&scd_info, 0);
-                       retval = scd_tray_move(&scd_info, 1);
-                       break;
-               case CDROMCLOSETRAY:
-                       retval = scd_tray_move(&scd_info, 0);
-                       break;
-               case CDROMREADAUDIO:
-                       retval = scd_read_audio(&scd_info, CDROMREADAUDIO, arg);
-                       break;
-               default:
-                       retval = cdrom_ioctl(file, &scd_info, inode, cmd, arg);
-       }
-       return retval;
-}
-
-static int scd_block_media_changed(struct gendisk *disk)
-{
-       return cdrom_media_changed(&scd_info);
-}
-
-static struct block_device_operations scd_bdops =
-{
-       .owner          = THIS_MODULE,
-       .open           = scd_block_open,
-       .release        = scd_block_release,
-       .ioctl          = scd_block_ioctl,
-       .media_changed  = scd_block_media_changed,
-};
-
-static struct gendisk *scd_gendisk;
-
-/* The different types of disc loading mechanisms supported */
-static char *load_mech[] __initdata =
-    { "caddy", "tray", "pop-up", "unknown" };
-
-static int __init
-get_drive_configuration(unsigned short base_io,
-                       unsigned char res_reg[], unsigned int *res_size)
-{
-       unsigned long retry_count;
-
-
-       if (!request_region(base_io, 4, "cdu31a"))
-               return 0;
-
-       /* Set the base address */
-       cdu31a_port = base_io;
-
-       /* Set up all the register locations */
-       sony_cd_cmd_reg = cdu31a_port + SONY_CMD_REG_OFFSET;
-       sony_cd_param_reg = cdu31a_port + SONY_PARAM_REG_OFFSET;
-       sony_cd_write_reg = cdu31a_port + SONY_WRITE_REG_OFFSET;
-       sony_cd_control_reg = cdu31a_port + SONY_CONTROL_REG_OFFSET;
-       sony_cd_status_reg = cdu31a_port + SONY_STATUS_REG_OFFSET;
-       sony_cd_result_reg = cdu31a_port + SONY_RESULT_REG_OFFSET;
-       sony_cd_read_reg = cdu31a_port + SONY_READ_REG_OFFSET;
-       sony_cd_fifost_reg = cdu31a_port + SONY_FIFOST_REG_OFFSET;
-
-       /*
-        * Check to see if anything exists at the status register location.
-        * I don't know if this is a good way to check, but it seems to work
-        * ok for me.
-        */
-       if (read_status_register() != 0xff) {
-               /*
-                * Reset the drive and wait for attention from it (to say it's reset).
-                * If you don't wait, the next operation will probably fail.
-                */
-               reset_drive();
-               retry_count = jiffies + SONY_RESET_TIMEOUT;
-               while (time_before(jiffies, retry_count)
-                      && (!is_attention())) {
-                       sony_sleep();
-               }
-
-#if 0
-               /* If attention is never seen probably not a CDU31a present */
-               if (!is_attention()) {
-                       res_reg[0] = 0x20;
-                       goto out_err;
-               }
-#endif
-
-               /*
-                * Get the drive configuration.
-                */
-               do_sony_cd_cmd(SONY_REQ_DRIVE_CONFIG_CMD,
-                              NULL,
-                              0, (unsigned char *) res_reg, res_size);
-               if (*res_size <= 2 || (res_reg[0] & 0xf0) != 0)
-                       goto out_err;
-               return 1;
-       }
-
-       /* Return an error */
-       res_reg[0] = 0x20;
-out_err:
-       release_region(cdu31a_port, 4);
-       cdu31a_port = 0;
-       return 0;
-}
-
-#ifndef MODULE
-/*
- * Set up base I/O and interrupts, called from main.c.
- */
-
-static int __init cdu31a_setup(char *strings)
-{
-       int ints[4];
-
-       (void) get_options(strings, ARRAY_SIZE(ints), ints);
-
-       if (ints[0] > 0) {
-               cdu31a_port = ints[1];
-       }
-       if (ints[0] > 1) {
-               cdu31a_irq = ints[2];
-       }
-       if ((strings != NULL) && (*strings != '\0')) {
-               if (strcmp(strings, "PAS") == 0) {
-                       sony_pas_init = 1;
-               } else {
-                       printk(KERN_NOTICE PFX "Unknown interface type: %s\n",
-                              strings);
-               }
-       }
-
-       return 1;
-}
-
-__setup("cdu31a=", cdu31a_setup);
-
-#endif
-
-/*
- * Initialize the driver.
- */
-int __init cdu31a_init(void)
-{
-       struct s_sony_drive_config drive_config;
-       struct gendisk *disk;
-       int deficiency = 0;
-       unsigned int res_size;
-       char msg[255];
-       char buf[40];
-       int i;
-       int tmp_irq;
-
-       /*
-        * According to Alex Freed (freed@europa.orion.adobe.com), this is
-        * required for the Fusion CD-16 package.  If the sound driver is
-        * loaded, it should work fine, but just in case...
-        *
-        * The following turn on the CD-ROM interface for a Fusion CD-16.
-        */
-       if (sony_pas_init) {
-               outb(0xbc, 0x9a01);
-               outb(0xe2, 0x9a01);
-       }
-
-       /* Setting the base I/O address to 0xffff will disable it. */
-       if (cdu31a_port == 0xffff)
-               goto errout3;
-
-       if (cdu31a_port != 0) {
-               /* Need IRQ 0 because we can't sleep here. */
-               tmp_irq = cdu31a_irq;
-               cdu31a_irq = 0;
-               if (!get_drive_configuration(cdu31a_port,
-                                           drive_config.exec_status,
-                                           &res_size))
-                       goto errout3;
-               cdu31a_irq = tmp_irq;
-       } else {
-               cdu31a_irq = 0;
-               for (i = 0; cdu31a_addresses[i].base; i++) {
-                       if (get_drive_configuration(cdu31a_addresses[i].base,
-                                                    drive_config.exec_status,
-                                                    &res_size)) {
-                               cdu31a_irq = cdu31a_addresses[i].int_num;
-                               break;
-                       }
-               }
-               if (!cdu31a_port)
-                       goto errout3;
-       }
-
-       if (register_blkdev(MAJOR_NR, "cdu31a"))
-               goto errout2;
-
-       disk = alloc_disk(1);
-       if (!disk)
-               goto errout1;
-       disk->major = MAJOR_NR;
-       disk->first_minor = 0;
-       sprintf(disk->disk_name, "cdu31a");
-       disk->fops = &scd_bdops;
-       disk->flags = GENHD_FL_CD;
-
-       if (SONY_HWC_DOUBLE_SPEED(drive_config))
-               is_double_speed = 1;
-
-       tmp_irq = cdu31a_irq;   /* Need IRQ 0 because we can't sleep here. */
-       cdu31a_irq = 0;
-
-       sony_speed = is_double_speed; /* Set 2X drives to 2X by default */
-       set_drive_params(sony_speed);
-
-       cdu31a_irq = tmp_irq;
-
-       if (cdu31a_irq > 0) {
-               if (request_irq
-                   (cdu31a_irq, cdu31a_interrupt, IRQF_DISABLED,
-                    "cdu31a", NULL)) {
-                       printk(KERN_WARNING PFX "Unable to grab IRQ%d for "
-                                       "the CDU31A driver\n", cdu31a_irq);
-                       cdu31a_irq = 0;
-               }
-       }
-
-       sprintf(msg, "Sony I/F CDROM : %8.8s %16.16s %8.8s\n",
-               drive_config.vendor_id,
-               drive_config.product_id,
-               drive_config.product_rev_level);
-       sprintf(buf, "  Capabilities: %s",
-               load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]);
-       strcat(msg, buf);
-       if (SONY_HWC_AUDIO_PLAYBACK(drive_config))
-               strcat(msg, ", audio");
-       else
-               deficiency |= CDC_PLAY_AUDIO;
-       if (SONY_HWC_EJECT(drive_config))
-               strcat(msg, ", eject");
-       else
-               deficiency |= CDC_OPEN_TRAY;
-       if (SONY_HWC_LED_SUPPORT(drive_config))
-               strcat(msg, ", LED");
-       if (SONY_HWC_ELECTRIC_VOLUME(drive_config))
-               strcat(msg, ", elec. Vol");
-       if (SONY_HWC_ELECTRIC_VOLUME_CTL(drive_config))
-               strcat(msg, ", sep. Vol");
-       if (is_double_speed)
-               strcat(msg, ", double speed");
-       else
-               deficiency |= CDC_SELECT_SPEED;
-       if (cdu31a_irq > 0) {
-               sprintf(buf, ", irq %d", cdu31a_irq);
-               strcat(msg, buf);
-       }
-       strcat(msg, "\n");
-       printk(KERN_INFO PFX "%s",msg);
-
-       cdu31a_queue = blk_init_queue(do_cdu31a_request, &cdu31a_lock);
-       if (!cdu31a_queue)
-               goto errout0;
-       blk_queue_hardsect_size(cdu31a_queue, 2048);
-
-       init_timer(&cdu31a_abort_timer);
-       cdu31a_abort_timer.function = handle_abort_timeout;
-
-       scd_info.mask = deficiency;
-       scd_gendisk = disk;
-       if (register_cdrom(&scd_info))
-               goto err;
-       disk->queue = cdu31a_queue;
-       add_disk(disk);
-
-       disk_changed = 1;
-       return 0;
-
-err:
-       blk_cleanup_queue(cdu31a_queue);
-errout0:
-       if (cdu31a_irq)
-               free_irq(cdu31a_irq, NULL);
-       printk(KERN_ERR PFX "Unable to register with Uniform cdrom driver\n");
-       put_disk(disk);
-errout1:
-       if (unregister_blkdev(MAJOR_NR, "cdu31a")) {
-               printk(KERN_WARNING PFX "Can't unregister block device\n");
-       }
-errout2:
-       release_region(cdu31a_port, 4);
-errout3:
-       return -EIO;
-}
-
-
-static void __exit cdu31a_exit(void)
-{
-       del_gendisk(scd_gendisk);
-       put_disk(scd_gendisk);
-       if (unregister_cdrom(&scd_info)) {
-               printk(KERN_WARNING PFX "Can't unregister from Uniform "
-                               "cdrom driver\n");
-               return;
-       }
-       if ((unregister_blkdev(MAJOR_NR, "cdu31a") == -EINVAL)) {
-               printk(KERN_WARNING PFX "Can't unregister\n");
-               return;
-       }
-
-       blk_cleanup_queue(cdu31a_queue);
-
-       if (cdu31a_irq > 0)
-               free_irq(cdu31a_irq, NULL);
-
-       release_region(cdu31a_port, 4);
-       printk(KERN_INFO PFX "module released.\n");
-}
-
-#ifdef MODULE
-module_init(cdu31a_init);
-#endif
-module_exit(cdu31a_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(CDU31A_CDROM_MAJOR);
diff --git a/drivers/cdrom/cdu31a.h b/drivers/cdrom/cdu31a.h
deleted file mode 100644 (file)
index 61d4768..0000000
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Definitions for a Sony interface CDROM drive.
- *
- * Corey Minyard (minyard@wf-rch.cirr.com)
- *
- *  Copyright (C) 1993  Corey Minyard
- *
- *  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 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-/*
- * General defines.
- */
-#define SONY_XA_DISK_TYPE 0x20
-
-/*
- * Offsets (from the base address) and bits for the various write registers
- * of the drive.
- */
-#define SONY_CMD_REG_OFFSET     0
-#define SONY_PARAM_REG_OFFSET   1
-#define SONY_WRITE_REG_OFFSET   2
-#define SONY_CONTROL_REG_OFFSET 3
-#       define SONY_ATTN_CLR_BIT        0x01
-#       define SONY_RES_RDY_CLR_BIT     0x02
-#       define SONY_DATA_RDY_CLR_BIT    0x04
-#       define SONY_ATTN_INT_EN_BIT     0x08
-#       define SONY_RES_RDY_INT_EN_BIT  0x10
-#       define SONY_DATA_RDY_INT_EN_BIT 0x20
-#       define SONY_PARAM_CLR_BIT       0x40
-#       define SONY_DRIVE_RESET_BIT     0x80
-
-/*
- * Offsets (from the base address) and bits for the various read registers
- * of the drive.
- */
-#define SONY_STATUS_REG_OFFSET  0
-#       define SONY_ATTN_BIT            0x01
-#       define SONY_RES_RDY_BIT         0x02
-#       define SONY_DATA_RDY_BIT        0x04
-#       define SONY_ATTN_INT_ST_BIT     0x08
-#       define SONY_RES_RDY_INT_ST_BIT  0x10
-#       define SONY_DATA_RDY_INT_ST_BIT 0x20
-#       define SONY_DATA_REQUEST_BIT    0x40
-#       define SONY_BUSY_BIT            0x80
-#define SONY_RESULT_REG_OFFSET  1
-#define SONY_READ_REG_OFFSET    2
-#define SONY_FIFOST_REG_OFFSET  3
-#       define SONY_PARAM_WRITE_RDY_BIT 0x01
-#       define SONY_PARAM_REG_EMPTY_BIT 0x02
-#       define SONY_RES_REG_NOT_EMP_BIT 0x04
-#       define SONY_RES_REG_FULL_BIT    0x08
-
-#define LOG_START_OFFSET        150     /* Offset of first logical sector */
-
-#define SONY_DETECT_TIMEOUT    (8*HZ/10) /* Maximum amount of time
-                                           that drive detection code
-                                           will wait for response
-                                           from drive (in 1/100th's
-                                           of seconds). */
-#define SONY_JIFFIES_TIMEOUT    (10*HZ)        /* Maximum number of times the
-                                           drive will wait/try for an
-                                           operation */
-#define SONY_RESET_TIMEOUT      HZ     /* Maximum number of times the
-                                           drive will wait/try a reset
-                                           operation */
-#define SONY_READY_RETRIES      20000   /* How many times to retry a
-                                           spin waiting for a register
-                                           to come ready */
-
-#define MAX_CDU31A_RETRIES      3       /* How many times to retry an
-                                           operation */
-
-/* Commands to request or set drive control parameters and disc information */
-#define SONY_REQ_DRIVE_CONFIG_CMD       0x00    /* Returns s_sony_drive_config */
-#define SONY_REQ_DRIVE_MODE_CMD         0x01
-#define SONY_REQ_DRIVE_PARAM_CMD        0x02
-#define SONY_REQ_MECH_STATUS_CMD        0x03
-#define SONY_REQ_AUDIO_STATUS_CMD       0x04
-#define SONY_SET_DRIVE_PARAM_CMD        0x10
-#define SONY_REQ_TOC_DATA_CMD           0x20    /* Returns s_sony_toc */
-#define SONY_REQ_SUBCODE_ADDRESS_CMD    0x21    /* Returns s_sony_subcode */
-#define SONY_REQ_UPC_EAN_CMD            0x22
-#define SONY_REQ_ISRC_CMD               0x23
-#define SONY_REQ_TOC_DATA_SPEC_CMD      0x24    /* Returns s_sony_session_toc */
-
-/* Commands to request information from the drive */
-#define SONY_READ_TOC_CMD               0x30    /* let the drive firmware grab the TOC */
-#define SONY_SEEK_CMD                   0x31
-#define SONY_READ_CMD                   0x32
-#define SONY_READ_BLKERR_STAT_CMD       0x34
-#define SONY_ABORT_CMD                  0x35
-#define SONY_READ_TOC_SPEC_CMD          0x36
-
-/* Commands to control audio */
-#define SONY_AUDIO_PLAYBACK_CMD         0x40
-#define SONY_AUDIO_STOP_CMD             0x41
-#define SONY_AUDIO_SCAN_CMD             0x42
-
-/* Miscellaneous control commands */
-#define SONY_EJECT_CMD                  0x50
-#define SONY_SPIN_UP_CMD                0x51
-#define SONY_SPIN_DOWN_CMD              0x52
-
-/* Diagnostic commands */
-#define SONY_WRITE_BUFFER_CMD           0x60
-#define SONY_READ_BUFFER_CMD            0x61
-#define SONY_DIAGNOSTICS_CMD            0x62
-
-
-/*
- * The following are command parameters for the set drive parameter command
- */
-#define SONY_SD_DECODE_PARAM            0x00
-#define SONY_SD_INTERFACE_PARAM         0x01
-#define SONY_SD_BUFFERING_PARAM         0x02
-#define SONY_SD_AUDIO_PARAM             0x03
-#define SONY_SD_AUDIO_VOLUME            0x04
-#define SONY_SD_MECH_CONTROL            0x05
-#define SONY_SD_AUTO_SPIN_DOWN_TIME     0x06
-
-/*
- * The following are parameter bits for the mechanical control command
- */
-#define SONY_AUTO_SPIN_UP_BIT           0x01
-#define SONY_AUTO_EJECT_BIT             0x02
-#define SONY_DOUBLE_SPEED_BIT           0x04
-
-/*
- * The following extract information from the drive configuration about
- * the drive itself.
- */
-#define SONY_HWC_GET_LOAD_MECH(c)       (c.hw_config[0] & 0x03)
-#define SONY_HWC_EJECT(c)               (c.hw_config[0] & 0x04)
-#define SONY_HWC_LED_SUPPORT(c)         (c.hw_config[0] & 0x08)
-#define SONY_HWC_DOUBLE_SPEED(c)        (c.hw_config[0] & 0x10)
-#define SONY_HWC_GET_BUF_MEM_SIZE(c)    ((c.hw_config[0] & 0xc0) >> 6)
-#define SONY_HWC_AUDIO_PLAYBACK(c)      (c.hw_config[1] & 0x01)
-#define SONY_HWC_ELECTRIC_VOLUME(c)     (c.hw_config[1] & 0x02)
-#define SONY_HWC_ELECTRIC_VOLUME_CTL(c) (c.hw_config[1] & 0x04)
-
-#define SONY_HWC_CADDY_LOAD_MECH        0x00
-#define SONY_HWC_TRAY_LOAD_MECH         0x01
-#define SONY_HWC_POPUP_LOAD_MECH        0x02
-#define SONY_HWC_UNKWN_LOAD_MECH        0x03
-
-#define SONY_HWC_8KB_BUFFER             0x00
-#define SONY_HWC_32KB_BUFFER            0x01
-#define SONY_HWC_64KB_BUFFER            0x02
-#define SONY_HWC_UNKWN_BUFFER           0x03
-
-/*
- * This is the complete status returned from the drive configuration request
- * command.
- */
-struct s_sony_drive_config
-{
-   unsigned char exec_status[2];
-   char vendor_id[8];
-   char product_id[16];
-   char product_rev_level[8];
-   unsigned char hw_config[2];
-};
-
-/* The following is returned from the request subcode address command */
-struct s_sony_subcode
-{
-   unsigned char exec_status[2];
-   unsigned char address        :4;
-   unsigned char control        :4;
-   unsigned char track_num;
-   unsigned char index_num;
-   unsigned char rel_msf[3];
-   unsigned char reserved1;
-   unsigned char abs_msf[3];
-};
-
-#define MAX_TRACKS 100 /* The maximum tracks a disk may have. */
-/*
- * The following is returned from the request TOC (Table Of Contents) command.
- * (last_track_num-first_track_num+1) values are valid in tracks.
- */
-struct s_sony_toc
-{
-   unsigned char exec_status[2];
-   unsigned char address0       :4;
-   unsigned char control0       :4;
-   unsigned char point0;
-   unsigned char first_track_num;
-   unsigned char disk_type;
-   unsigned char dummy0;
-   unsigned char address1       :4;
-   unsigned char control1       :4;
-   unsigned char point1;
-   unsigned char last_track_num;
-   unsigned char dummy1;
-   unsigned char dummy2;
-   unsigned char address2       :4;
-   unsigned char control2       :4;
-   unsigned char point2;
-   unsigned char lead_out_start_msf[3];
-   struct
-   {
-      unsigned char address     :4;
-      unsigned char control     :4;
-      unsigned char track;
-      unsigned char track_start_msf[3];
-   } tracks[MAX_TRACKS];
-
-   unsigned int lead_out_start_lba;
-};
-
-struct s_sony_session_toc
-{
-   unsigned char exec_status[2];
-   unsigned char session_number;
-   unsigned char address0       :4;
-   unsigned char control0       :4;
-   unsigned char point0;
-   unsigned char first_track_num;
-   unsigned char disk_type;
-   unsigned char dummy0;
-   unsigned char address1       :4;
-   unsigned char control1       :4;
-   unsigned char point1;
-   unsigned char last_track_num;
-   unsigned char dummy1;
-   unsigned char dummy2;
-   unsigned char address2       :4;
-   unsigned char control2       :4;
-   unsigned char point2;
-   unsigned char lead_out_start_msf[3];
-   unsigned char addressb0      :4;
-   unsigned char controlb0      :4;
-   unsigned char pointb0;
-   unsigned char next_poss_prog_area_msf[3];
-   unsigned char num_mode_5_pointers;
-   unsigned char max_start_outer_leadout_msf[3];
-   unsigned char addressb1      :4;
-   unsigned char controlb1      :4;
-   unsigned char pointb1;
-   unsigned char dummyb0_1[4];
-   unsigned char num_skip_interval_pointers;
-   unsigned char num_skip_track_assignments;
-   unsigned char dummyb0_2;
-   unsigned char addressb2      :4;
-   unsigned char controlb2      :4;
-   unsigned char pointb2;
-   unsigned char tracksb2[7];
-   unsigned char addressb3      :4;
-   unsigned char controlb3      :4;
-   unsigned char pointb3;
-   unsigned char tracksb3[7];
-   unsigned char addressb4      :4;
-   unsigned char controlb4      :4;
-   unsigned char pointb4;
-   unsigned char tracksb4[7];
-   unsigned char addressc0      :4;
-   unsigned char controlc0      :4;
-   unsigned char pointc0;
-   unsigned char dummyc0[7];
-   struct
-   {
-      unsigned char address     :4;
-      unsigned char control     :4;
-      unsigned char track;
-      unsigned char track_start_msf[3];
-   } tracks[MAX_TRACKS];
-
-   unsigned int start_track_lba;
-   unsigned int lead_out_start_lba;
-   unsigned int mint;
-   unsigned int maxt;
-};
-
-struct s_all_sessions_toc
-{
-   unsigned char sessions;
-   unsigned int track_entries;
-   unsigned char first_track_num;
-   unsigned char last_track_num;
-   unsigned char disk_type;
-   unsigned char lead_out_start_msf[3];
-   struct
-   {
-      unsigned char address     :4;
-      unsigned char control     :4;
-      unsigned char track;
-      unsigned char track_start_msf[3];
-   } tracks[MAX_TRACKS];
-
-   unsigned int start_track_lba;
-   unsigned int lead_out_start_lba;
-};
-
-
-/*
- * The following are errors returned from the drive.
- */
-
-/* Command error group */
-#define SONY_ILL_CMD_ERR                0x10
-#define SONY_ILL_PARAM_ERR              0x11
-
-/* Mechanism group */
-#define SONY_NOT_LOAD_ERR               0x20
-#define SONY_NO_DISK_ERR                0x21
-#define SONY_NOT_SPIN_ERR               0x22
-#define SONY_SPIN_ERR                   0x23
-#define SONY_SPINDLE_SERVO_ERR          0x25
-#define SONY_FOCUS_SERVO_ERR            0x26
-#define SONY_EJECT_MECH_ERR             0x29
-#define SONY_AUDIO_PLAYING_ERR          0x2a
-#define SONY_EMERGENCY_EJECT_ERR        0x2c
-
-/* Seek error group */
-#define SONY_FOCUS_ERR                  0x30
-#define SONY_FRAME_SYNC_ERR             0x31
-#define SONY_SUBCODE_ADDR_ERR           0x32
-#define SONY_BLOCK_SYNC_ERR             0x33
-#define SONY_HEADER_ADDR_ERR            0x34
-
-/* Read error group */
-#define SONY_ILL_TRACK_R_ERR            0x40
-#define SONY_MODE_0_R_ERR               0x41
-#define SONY_ILL_MODE_R_ERR             0x42
-#define SONY_ILL_BLOCK_SIZE_R_ERR       0x43
-#define SONY_MODE_R_ERR                 0x44
-#define SONY_FORM_R_ERR                 0x45
-#define SONY_LEAD_OUT_R_ERR             0x46
-#define SONY_BUFFER_OVERRUN_R_ERR       0x47
-
-/* Data error group */
-#define SONY_UNREC_CIRC_ERR             0x53
-#define SONY_UNREC_LECC_ERR             0x57
-
-/* Subcode error group */
-#define SONY_NO_TOC_ERR                 0x60
-#define SONY_SUBCODE_DATA_NVAL_ERR      0x61
-#define SONY_FOCUS_ON_TOC_READ_ERR      0x63
-#define SONY_FRAME_SYNC_ON_TOC_READ_ERR 0x64
-#define SONY_TOC_DATA_ERR               0x65
-
-/* Hardware failure group */
-#define SONY_HW_FAILURE_ERR             0x70
-#define SONY_LEAD_IN_A_ERR              0x91
-#define SONY_LEAD_OUT_A_ERR             0x92
-#define SONY_DATA_TRACK_A_ERR           0x93
-
-/*
- * The following are returned from the Read With Block Error Status command.
- * They are not errors but information (Errors from the 0x5x group above may
- * also be returned
- */
-#define SONY_NO_CIRC_ERR_BLK_STAT       0x50
-#define SONY_NO_LECC_ERR_BLK_STAT       0x54
-#define SONY_RECOV_LECC_ERR_BLK_STAT    0x55
-#define SONY_NO_ERR_DETECTION_STAT      0x59
-
-/* 
- * The following is not an error returned by the drive, but by the code
- * that talks to the drive.  It is returned because of a timeout.
- */
-#define SONY_TIMEOUT_OP_ERR             0x01
-#define SONY_SIGNAL_OP_ERR              0x02
-#define SONY_BAD_DATA_ERR               0x03
-
-
-/*
- * The following are attention code for asynchronous events from the drive.
- */
-
-/* Standard attention group */
-#define SONY_EMER_EJECT_ATTN            0x2c
-#define SONY_HW_FAILURE_ATTN            0x70
-#define SONY_MECH_LOADED_ATTN           0x80
-#define SONY_EJECT_PUSHED_ATTN          0x81
-
-/* Audio attention group */
-#define SONY_AUDIO_PLAY_DONE_ATTN       0x90
-#define SONY_LEAD_IN_ERR_ATTN           0x91
-#define SONY_LEAD_OUT_ERR_ATTN          0x92
-#define SONY_DATA_TRACK_ERR_ATTN        0x93
-#define SONY_AUDIO_PLAYBACK_ERR_ATTN    0x94
-
-/* Auto spin up group */
-#define SONY_SPIN_UP_COMPLETE_ATTN      0x24
-#define SONY_SPINDLE_SERVO_ERR_ATTN     0x25
-#define SONY_FOCUS_SERVO_ERR_ATTN       0x26
-#define SONY_TOC_READ_DONE_ATTN         0x62
-#define SONY_FOCUS_ON_TOC_READ_ERR_ATTN 0x63
-#define SONY_SYNC_ON_TOC_READ_ERR_ATTN  0x65
-
-/* Auto eject group */
-#define SONY_SPIN_DOWN_COMPLETE_ATTN    0x27
-#define SONY_EJECT_COMPLETE_ATTN        0x28
-#define SONY_EJECT_MECH_ERR_ATTN        0x29
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
deleted file mode 100644 (file)
index 2f8fe3b..0000000
+++ /dev/null
@@ -1,1594 +0,0 @@
-/* cm206.c. A linux-driver for the cm206 cdrom player with cm260 adapter card.
-   Copyright (c) 1995--1997 David A. van Leeuwen.
-   $Id: cm206.c,v 1.5 1997/12/26 11:02:51 david Exp $
-   
-     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 of the License, or
-     (at your option) any later version.
-     
-     This program is distributed in the hope that it will be useful,
-     but WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-     GNU General Public License for more details.
-     
-     You should have received a copy of the GNU General Public License
-     along with this program; if not, write to the Free Software
-     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-History:
- Started 25 jan 1994. Waiting for documentation...
- 22 feb 1995: 0.1a first reasonably safe polling driver.
-             Two major bugs, one in read_sector and one in 
-             do_cm206_request, happened to cancel!
- 25 feb 1995: 0.2a first reasonable interrupt driven version of above.
-              uart writes are still done in polling mode. 
- 25 feb 1995: 0.21a writes also in interrupt mode, still some
-             small bugs to be found... Larger buffer. 
-  2 mrt 1995: 0.22 Bug found (cd-> nowhere, interrupt was called in
-              initialization), read_ahead of 16. Timeouts implemented.
-             unclear if they do something...
-  7 mrt 1995: 0.23 Start of background read-ahead.
- 18 mrt 1995: 0.24 Working background read-ahead. (still problems)
- 26 mrt 1995: 0.25 Multi-session ioctl added (kernel v1.2).
-              Statistics implemented, though separate stats206.h.
-             Accessible through ioctl 0x1000 (just a number).
-             Hard to choose between v1.2 development and 1.1.75.
-             Bottom-half doesn't work with 1.2...
-             0.25a: fixed... typo. Still problems...
-  1 apr 1995: 0.26 Module support added. Most bugs found. Use kernel 1.2.n.
-  5 apr 1995: 0.27 Auto-probe for the adapter card base address.
-              Auto-probe for the adaptor card irq line.
-  7 apr 1995: 0.28 Added lilo setup support for base address and irq.
-              Use major number 32 (not in this source), officially
-             assigned to this driver.
-  9 apr 1995: 0.29 Added very limited audio support. Toc_header, stop, pause,
-              resume, eject. Play_track ignores track info, because we can't 
-             read a table-of-contents entry. Toc_entry is implemented
-             as a `placebo' function: always returns start of disc. 
-  3 may 1995: 0.30 Audio support completed. The get_toc_entry function
-              is implemented as a binary search. 
- 15 may 1995: 0.31 More work on audio stuff. Workman is not easy to 
-              satisfy; changed binary search into linear search.
-             Auto-probe for base address somewhat relaxed.
-  1 jun 1995: 0.32 Removed probe_irq_on/off for module version.
- 10 jun 1995: 0.33 Workman still behaves funny, but you should be
-              able to eject and substitute another disc.
-
- An adaptation of 0.33 is included in linux-1.3.7 by Eberhard Moenkeberg
-
- 18 jul 1995: 0.34 Patch by Heiko Eissfeldt included, mainly considering 
-              verify_area's in the ioctls. Some bugs introduced by 
-             EM considering the base port and irq fixed. 
-
- 18 dec 1995: 0.35 Add some code for error checking... no luck...
-
- We jump to reach our goal: version 1.0 in the next stable linux kernel.
-
- 19 mar 1996: 0.95 Different implementation of CDROM_GET_UPC, on
-             request of Thomas Quinot. 
- 25 mar 1996: 0.96 Interpretation of opening with O_WRONLY or O_RDWR:
-             open only for ioctl operation, e.g., for operation of
-             tray etc.
- 4 apr 1996:  0.97 First implementation of layer between VFS and cdrom
-              driver, a generic interface. Much of the functionality
-             of cm206_open() and cm206_ioctl() is transferred to a
-             new file cdrom.c and its header ucdrom.h. 
-
-             Upgrade to Linux kernel 1.3.78. 
-
- 11 apr 1996  0.98 Upgrade to Linux kernel 1.3.85
-              More code moved to cdrom.c
-             0.99 Some more small changes to decrease number
-             of oopses at module load; 
- 27 jul 1996  0.100 Many hours of debugging, kernel change from 1.2.13
-             to 2.0.7 seems to have introduced some weird behavior
-             in (interruptible_)sleep_on(&cd->data): the process
-             seems to be woken without any explicit wake_up in my own
-             code. Patch to try 100x in case such untriggered wake_up's 
-             occur. 
-
- 28 jul 1996  0.101 Rewriting of the code that receives the command echo,
-             using a fifo to store echoed bytes. 
-
-             Branch from 0.99:
-             0.99.1.0 Update to kernel release 2.0.10 dev_t -> kdev_t
-             (emoenke) various typos found by others.  extra
-             module-load oops protection.
-             0.99.1.1 Initialization constant cdrom_dops.speed
-             changed from float (2.0) to int (2); Cli()-sti() pair
-             around cm260_reset() in module initialization code.
-             0.99.1.2 Changes literally as proposed by Scott Snyder
-             <snyder@d0sgif.fnal.gov> for the 2.1 kernel line, which
-             have to do mainly with the poor minor support i had. The
-             major new concept is to change a cdrom driver's
-             operations struct from the capabilities struct. This
-             reflects the fact that there is one major for a driver,
-             whilst there can be many minors whith completely
-             different capabilities.
-
-             0.99.1.3 More changes for operations/info separation.
-
-             0.99.1.4 Added speed selection (someone had to do this
-             first).
-
-  23 jan 1997 0.99.1.5 MODULE_PARMS call added.
-
-  23 jan 1997 0.100.1.2--0.100.1.5 following similar lines as 
-             0.99.1.1--0.99.1.5. I get too many complaints about the
-             drive making read errors. What't wrong with the 2.0+
-             kernel line? Why get i (and othe cm206 owners) weird
-             results? Why were things good in the good old 1.1--1.2 
-             era? Why don't i throw away the drive?
-
- 2 feb 1997   0.102 Added `volatile' to values in cm206_struct. Seems to 
-             reduce many of the problems. Rewrote polling routines
-             to use fixed delays between polls. 
-             0.103 Changed printk behavior. 
-             0.104 Added a 0.100 -> 0.100.1.1 change
-
-11 feb 1997   0.105 Allow auto_probe during module load, disable
-              with module option "auto_probe=0". Moved some debugging
-             statements to lower priority. Implemented select_speed()
-             function. 
-
-13 feb 1997   1.0 Final version for 2.0 kernel line. 
-
-             All following changes will be for the 2.1 kernel line. 
-
-15 feb 1997   1.1 Keep up with kernel 2.1.26, merge in changes from 
-              cdrom.c 0.100.1.1--1.0. Add some more MODULE_PARMS. 
-
-14 sep 1997   1.2 Upgrade to Linux 2.1.55.  Added blksize_size[], patch
-              sent by James Bottomley <James.Bottomley@columbiasc.ncr.com>.
-
-21 dec 1997   1.4 Upgrade to Linux 2.1.72.  
-
-24 jan 1998   Removed the cm206_disc_status() function, as it was now dead
-              code.  The Uniform CDROM driver now provides this functionality.
-             
-9 Nov. 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>
- * 
- * Parts of the code are based upon lmscd.c written by Kai Petzke,
- * sbpcd.c written by Eberhard Moenkeberg, and mcd.c by Martin
- * Harriss, but any off-the-shelf dynamic programming algorithm won't
- * be able to find them.
- *
- * The cm206 drive interface and the cm260 adapter card seem to be 
- * sufficiently different from their cm205/cm250 counterparts
- * in order to write a complete new driver.
- * 
- * I call all routines connected to the Linux kernel something
- * with `cm206' in it, as this stuff is too series-dependent. 
- * 
- * Currently, my limited knowledge is based on:
- * - The Linux Kernel Hacker's guide, v. 0.5, by Michael K. Johnson
- * - Linux Kernel Programmierung, by Michael Beck and others
- * - Philips/LMS cm206 and cm226 product specification
- * - Philips/LMS cm260 product specification
- *
- * David van Leeuwen, david@tm.tno.nl.  */
-#define REVISION "$Revision: 1.5 $"
-
-#include <linux/module.h>
-
-#include <linux/errno.h>       /* These include what we really need */
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-/* #include <linux/ucdrom.h> */
-
-#include <asm/io.h>
-
-#define MAJOR_NR CM206_CDROM_MAJOR
-
-#include <linux/blkdev.h>
-
-#undef DEBUG
-#define STATISTICS             /* record times and frequencies of events */
-#define AUTO_PROBE_MODULE
-#define USE_INSW
-
-#include "cm206.h"
-
-/* This variable defines whether or not to probe for adapter base port 
-   address and interrupt request. It can be overridden by the boot 
-   parameter `auto'.
-*/
-static int auto_probe = 1;     /* Yes, why not? */
-
-static int cm206_base = CM206_BASE;
-static int cm206_irq = CM206_IRQ;
-#ifdef MODULE
-static int cm206[2] = { 0, 0 };        /* for compatible `insmod' parameter passing */
-module_param_array(cm206, int, NULL, 0);       /* base,irq or irq,base */
-#endif
-
-module_param(cm206_base, int, 0);      /* base */
-module_param(cm206_irq, int, 0);       /* irq */
-module_param(auto_probe, bool, 0);     /* auto probe base and irq */
-MODULE_LICENSE("GPL");
-
-#define POLLOOP 100            /* milliseconds */
-#define READ_AHEAD 1           /* defines private buffer, waste! */
-#define BACK_AHEAD 1           /* defines adapter-read ahead */
-#define DATA_TIMEOUT (3*HZ)    /* measured in jiffies (10 ms) */
-#define UART_TIMEOUT (5*HZ/100)
-#define DSB_TIMEOUT (7*HZ)     /* time for the slowest command to finish */
-#define UR_SIZE 4              /* uart receive buffer fifo size */
-
-#define LINUX_BLOCK_SIZE 512   /* WHERE is this defined? */
-#define RAW_SECTOR_SIZE 2352   /* ok, is also defined in cdrom.h */
-#define ISO_SECTOR_SIZE 2048
-#define BLOCKS_ISO (ISO_SECTOR_SIZE/LINUX_BLOCK_SIZE)  /* 4 */
-#define CD_SYNC_HEAD 16                /* CD_SYNC + CD_HEAD */
-
-#ifdef STATISTICS              /* keep track of errors in counters */
-#define stats(i) { ++cd->stats[st_ ## i]; \
-                    cd->last_stat[st_ ## i] = cd->stat_counter++; \
-                }
-#else
-#define stats(i) (void) 0;
-#endif
-
-#define Debug(a) {printk (KERN_DEBUG); printk a;}
-#ifdef DEBUG
-#define debug(a) Debug(a)
-#else
-#define debug(a) (void) 0;
-#endif
-
-typedef unsigned char uch;     /* 8-bits */
-typedef unsigned short ush;    /* 16-bits */
-
-struct toc_struct {            /* private copy of Table of Contents */
-       uch track, fsm[3], q0;
-};
-
-struct cm206_struct {
-       volatile ush intr_ds;   /* data status read on last interrupt */
-       volatile ush intr_ls;   /* uart line status read on last interrupt */
-       volatile uch ur[UR_SIZE];       /* uart receive buffer fifo */
-       volatile uch ur_w, ur_r;        /* write/read buffer index */
-       volatile uch dsb, cc;   /* drive status byte and condition (error) code */
-       int command;            /* command to be written to the uart */
-       int openfiles;
-       ush sector[READ_AHEAD * RAW_SECTOR_SIZE / 2];   /* buffered cd-sector */
-       int sector_first, sector_last;  /* range of these sectors */
-       wait_queue_head_t uart; /* wait queues for interrupt */
-       wait_queue_head_t data;
-       struct timer_list timer;        /* time-out */
-       char timed_out;
-       signed char max_sectors;        /* number of sectors that fit in adapter mem */
-       char wait_back;         /* we're waiting for a background-read */
-       char background;        /* is a read going on in the background? */
-       int adapter_first;      /* if so, that's the starting sector */
-       int adapter_last;
-       char fifo_overflowed;
-       uch disc_status[7];     /* result of get_disc_status command */
-#ifdef STATISTICS
-       int stats[NR_STATS];
-       int last_stat[NR_STATS];        /* `time' at which stat was stat */
-       int stat_counter;
-#endif
-       struct toc_struct toc[101];     /* The whole table of contents + lead-out */
-       uch q[10];              /* Last read q-channel info */
-       uch audio_status[5];    /* last read position on pause */
-       uch media_changed;      /* record if media changed */
-};
-
-#define DISC_STATUS cd->disc_status[0]
-#define FIRST_TRACK cd->disc_status[1]
-#define LAST_TRACK cd->disc_status[2]
-#define PAUSED cd->audio_status[0]     /* misuse this memory byte! */
-#define PLAY_TO cd->toc[0]     /* toc[0] records end-time in play */
-
-static struct cm206_struct *cd;        /* the main memory structure */
-static struct request_queue *cm206_queue;
-static DEFINE_SPINLOCK(cm206_lock);
-
-/* First, we define some polling functions. These are actually
-   only being used in the initialization. */
-
-static void send_command_polled(int command)
-{
-       int loop = POLLOOP;
-       while (!(inw(r_line_status) & ls_transmitter_buffer_empty)
-              && loop > 0) {
-               mdelay(1);      /* one millisec delay */
-               --loop;
-       }
-       outw(command, r_uart_transmit);
-}
-
-static uch receive_echo_polled(void)
-{
-       int loop = POLLOOP;
-       while (!(inw(r_line_status) & ls_receive_buffer_full) && loop > 0) {
-               mdelay(1);
-               --loop;
-       }
-       return ((uch) inw(r_uart_receive));
-}
-
-static uch send_receive_polled(int command)
-{
-       send_command_polled(command);
-       return receive_echo_polled();
-}
-
-static inline void clear_ur(void)
-{
-       if (cd->ur_r != cd->ur_w) {
-               debug(("Deleting bytes from fifo:"));
-               for (; cd->ur_r != cd->ur_w;
-                    cd->ur_r++, cd->ur_r %= UR_SIZE)
-                       debug((" 0x%x", cd->ur[cd->ur_r]));
-               debug(("\n"));
-       }
-}
-
-static struct tasklet_struct cm206_tasklet;
-
-/* The interrupt handler. When the cm260 generates an interrupt, very
-   much care has to be taken in reading out the registers in the right
-   order; in case of a receive_buffer_full interrupt, first the
-   uart_receive must be read, and then the line status again to
-   de-assert the interrupt line. It took me a couple of hours to find
-   this out:-( 
-
-   The function reset_cm206 appears to cause an interrupt, because
-   pulling up the INIT line clears both the uart-write-buffer /and/
-   the uart-write-buffer-empty mask. We call this a `lost interrupt,'
-   as there seems so reason for this to happen.
-*/
-
-static irqreturn_t cm206_interrupt(int sig, void *dev_id)
-{
-       volatile ush fool;
-       cd->intr_ds = inw(r_data_status);       /* resets data_ready, data_error,
-                                                  crc_error, sync_error, toc_ready 
-                                                  interrupts */
-       cd->intr_ls = inw(r_line_status);       /* resets overrun bit */
-       debug(("Intr, 0x%x 0x%x, %d\n", cd->intr_ds, cd->intr_ls,
-              cd->background));
-       if (cd->intr_ls & ls_attention)
-               stats(attention);
-       /* receive buffer full? */
-       if (cd->intr_ls & ls_receive_buffer_full) {
-               cd->ur[cd->ur_w] = inb(r_uart_receive); /* get order right! */
-               cd->intr_ls = inw(r_line_status);       /* resets rbf interrupt */
-               debug(("receiving #%d: 0x%x\n", cd->ur_w,
-                      cd->ur[cd->ur_w]));
-               cd->ur_w++;
-               cd->ur_w %= UR_SIZE;
-               if (cd->ur_w == cd->ur_r)
-                       debug(("cd->ur overflow!\n"));
-               if (waitqueue_active(&cd->uart) && cd->background < 2) {
-                       del_timer(&cd->timer);
-                       wake_up_interruptible(&cd->uart);
-               }
-       }
-       /* data ready in fifo? */
-       else if (cd->intr_ds & ds_data_ready) {
-               if (cd->background)
-                       ++cd->adapter_last;
-               if (waitqueue_active(&cd->data)
-                   && (cd->wait_back || !cd->background)) {
-                       del_timer(&cd->timer);
-                       wake_up_interruptible(&cd->data);
-               }
-               stats(data_ready);
-       }
-       /* ready to issue a write command? */
-       else if (cd->command && cd->intr_ls & ls_transmitter_buffer_empty) {
-               outw(dc_normal | (inw(r_data_status) & 0x7f),
-                    r_data_control);
-               outw(cd->command, r_uart_transmit);
-               cd->command = 0;
-               if (!cd->background)
-                       wake_up_interruptible(&cd->uart);
-       }
-       /* now treat errors (at least, identify them for debugging) */
-       else if (cd->intr_ds & ds_fifo_overflow) {
-               debug(("Fifo overflow at sectors 0x%x\n",
-                      cd->sector_first));
-               fool = inw(r_fifo_output_buffer);       /* de-assert the interrupt */
-               cd->fifo_overflowed = 1;        /* signal one word less should be read */
-               stats(fifo_overflow);
-       } else if (cd->intr_ds & ds_data_error) {
-               debug(("Data error at sector 0x%x\n", cd->sector_first));
-               stats(data_error);
-       } else if (cd->intr_ds & ds_crc_error) {
-               debug(("CRC error at sector 0x%x\n", cd->sector_first));
-               stats(crc_error);
-       } else if (cd->intr_ds & ds_sync_error) {
-               debug(("Sync at sector 0x%x\n", cd->sector_first));
-               stats(sync_error);
-       } else if (cd->intr_ds & ds_toc_ready) {
-               /* do something appropriate */
-       }
-       /* couldn't see why this interrupt, maybe due to init */
-       else {
-               outw(dc_normal | READ_AHEAD, r_data_control);
-               stats(lost_intr);
-       }
-       if (cd->background
-           && (cd->adapter_last - cd->adapter_first == cd->max_sectors
-               || cd->fifo_overflowed))
-               tasklet_schedule(&cm206_tasklet);       /* issue a stop read command */
-       stats(interrupt);
-       return IRQ_HANDLED;
-}
-
-/* we have put the address of the wait queue in who */
-static void cm206_timeout(unsigned long who)
-{
-       cd->timed_out = 1;
-       debug(("Timing out\n"));
-       wake_up_interruptible((wait_queue_head_t *) who);
-}
-
-/* This function returns 1 if a timeout occurred, 0 if an interrupt
-   happened */
-static int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
-{
-       cd->timed_out = 0;
-       init_timer(&cd->timer);
-       cd->timer.data = (unsigned long) wait;
-       cd->timer.expires = jiffies + timeout;
-       add_timer(&cd->timer);
-       debug(("going to sleep\n"));
-       interruptible_sleep_on(wait);
-       del_timer(&cd->timer);
-       if (cd->timed_out) {
-               cd->timed_out = 0;
-               return 1;
-       } else
-               return 0;
-}
-
-static void send_command(int command)
-{
-       debug(("Sending 0x%x\n", command));
-       if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) {
-               cd->command = command;
-               cli();          /* don't interrupt before sleep */
-               outw(dc_mask_sync_error | dc_no_stop_on_error |
-                    (inw(r_data_status) & 0x7f), r_data_control);
-               /* interrupt routine sends command */
-               if (sleep_or_timeout(&cd->uart, UART_TIMEOUT)) {
-                       debug(("Time out on write-buffer\n"));
-                       stats(write_timeout);
-                       outw(command, r_uart_transmit);
-               }
-               debug(("Write commmand delayed\n"));
-       } else
-               outw(command, r_uart_transmit);
-}
-
-static uch receive_byte(int timeout)
-{
-       uch ret;
-       cli();
-       debug(("cli\n"));
-       ret = cd->ur[cd->ur_r];
-       if (cd->ur_r != cd->ur_w) {
-               sti();
-               debug(("returning #%d: 0x%x\n", cd->ur_r,
-                      cd->ur[cd->ur_r]));
-               cd->ur_r++;
-               cd->ur_r %= UR_SIZE;
-               return ret;
-       } else if (sleep_or_timeout(&cd->uart, timeout)) {      /* does sti() */
-               debug(("Time out on receive-buffer\n"));
-#ifdef STATISTICS
-               if (timeout == UART_TIMEOUT)
-                       stats(receive_timeout)  /* no `;'! */
-                           else
-                       stats(dsb_timeout);
-#endif
-               return 0xda;
-       }
-       ret = cd->ur[cd->ur_r];
-       debug(("slept; returning #%d: 0x%x\n", cd->ur_r,
-              cd->ur[cd->ur_r]));
-       cd->ur_r++;
-       cd->ur_r %= UR_SIZE;
-       return ret;
-}
-
-static inline uch receive_echo(void)
-{
-       return receive_byte(UART_TIMEOUT);
-}
-
-static inline uch send_receive(int command)
-{
-       send_command(command);
-       return receive_echo();
-}
-
-static inline uch wait_dsb(void)
-{
-       return receive_byte(DSB_TIMEOUT);
-}
-
-static int type_0_command(int command, int expect_dsb)
-{
-       int e;
-       clear_ur();
-       if (command != (e = send_receive(command))) {
-               debug(("command 0x%x echoed as 0x%x\n", command, e));
-               stats(echo);
-               return -1;
-       }
-       if (expect_dsb) {
-               cd->dsb = wait_dsb();   /* wait for command to finish */
-       }
-       return 0;
-}
-
-static int type_1_command(int command, int bytes, uch * status)
-{                              /* returns info */
-       int i;
-       if (type_0_command(command, 0))
-               return -1;
-       for (i = 0; i < bytes; i++)
-               status[i] = send_receive(c_gimme);
-       return 0;
-}
-
-/* This function resets the adapter card. We'd better not do this too
- * often, because it tends to generate `lost interrupts.' */
-static void reset_cm260(void)
-{
-       outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control);
-       udelay(10);             /* 3.3 mu sec minimum */
-       outw(dc_normal | READ_AHEAD, r_data_control);
-}
-
-/* fsm: frame-sec-min from linear address; one of many */
-static void fsm(int lba, uch * fsm)
-{
-       fsm[0] = lba % 75;
-       lba /= 75;
-       lba += 2;
-       fsm[1] = lba % 60;
-       fsm[2] = lba / 60;
-}
-
-static inline int fsm2lba(uch * fsm)
-{
-       return fsm[0] + 75 * (fsm[1] - 2 + 60 * fsm[2]);
-}
-
-static inline int f_s_m2lba(uch f, uch s, uch m)
-{
-       return f + 75 * (s - 2 + 60 * m);
-}
-
-static int start_read(int start)
-{
-       uch read_sector[4] = { c_read_data, };
-       int i, e;
-
-       fsm(start, &read_sector[1]);
-       clear_ur();
-       for (i = 0; i < 4; i++)
-               if (read_sector[i] != (e = send_receive(read_sector[i]))) {
-                       debug(("read_sector: %x echoes %x\n",
-                              read_sector[i], e));
-                       stats(echo);
-                       if (e == 0xff) {        /* this seems to happen often */
-                               e = receive_echo();
-                               debug(("Second try %x\n", e));
-                               if (e != read_sector[i])
-                                       return -1;
-                       }
-               }
-       return 0;
-}
-
-static int stop_read(void)
-{
-       int e;
-       type_0_command(c_stop, 0);
-       if ((e = receive_echo()) != 0xff) {
-               debug(("c_stop didn't send 0xff, but 0x%x\n", e));
-               stats(stop_0xff);
-               return -1;
-       }
-       return 0;
-}
-
-/* This function starts to read sectors in adapter memory, the
-   interrupt routine should stop the read. In fact, the bottom_half
-   routine takes care of this. Set a flag `background' in the cd
-   struct to indicate the process. */
-
-static int read_background(int start, int reading)
-{
-       if (cd->background)
-               return -1;      /* can't do twice */
-       outw(dc_normal | BACK_AHEAD, r_data_control);
-       if (!reading && start_read(start))
-               return -2;
-       cd->adapter_first = cd->adapter_last = start;
-       cd->background = 1;     /* flag a read is going on */
-       return 0;
-}
-
-#ifdef USE_INSW
-#define transport_data insw
-#else
-/* this routine implements insw(,,). There was a time i had the
-   impression that there would be any difference in error-behaviour. */
-void transport_data(int port, ush * dest, int count)
-{
-       int i;
-       ush *d;
-       for (i = 0, d = dest; i < count; i++, d++)
-               *d = inw(port);
-}
-#endif
-
-
-#define MAX_TRIES 100
-static int read_sector(int start)
-{
-       int tries = 0;
-       if (cd->background) {
-               cd->background = 0;
-               cd->adapter_last = -1;  /* invalidate adapter memory */
-               stop_read();
-       }
-       cd->fifo_overflowed = 0;
-       reset_cm260();          /* empty fifo etc. */
-       if (start_read(start))
-               return -1;
-       do {
-               if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
-                       debug(("Read timed out sector 0x%x\n", start));
-                       stats(read_timeout);
-                       stop_read();
-                       return -3;
-               }
-               tries++;
-       } while (cd->intr_ds & ds_fifo_empty && tries < MAX_TRIES);
-       if (tries > 1)
-               debug(("Took me some tries\n"))
-                   else
-       if (tries == MAX_TRIES)
-               debug(("MAX_TRIES tries for read sector\n"));
-       transport_data(r_fifo_output_buffer, cd->sector,
-                      READ_AHEAD * RAW_SECTOR_SIZE / 2);
-       if (read_background(start + READ_AHEAD, 1))
-               stats(read_background);
-       cd->sector_first = start;
-       cd->sector_last = start + READ_AHEAD;
-       stats(read_restarted);
-       return 0;
-}
-
-/* The function of bottom-half is to send a stop command to the drive
-   This isn't easy because the routine is not `owned' by any process;
-   we can't go to sleep! The variable cd->background gives the status:
-   0 no read pending
-   1 a read is pending
-   2 c_stop waits for write_buffer_empty
-   3 c_stop waits for receive_buffer_full: echo
-   4 c_stop waits for receive_buffer_full: 0xff
-*/
-
-static void cm206_tasklet_func(unsigned long ignore)
-{
-       debug(("bh: %d\n", cd->background));
-       switch (cd->background) {
-       case 1:
-               stats(bh);
-               if (!(cd->intr_ls & ls_transmitter_buffer_empty)) {
-                       cd->command = c_stop;
-                       outw(dc_mask_sync_error | dc_no_stop_on_error |
-                            (inw(r_data_status) & 0x7f), r_data_control);
-                       cd->background = 2;
-                       break;  /* we'd better not time-out here! */
-               } else
-                       outw(c_stop, r_uart_transmit);
-               /* fall into case 2: */
-       case 2:
-               /* the write has been satisfied by interrupt routine */
-               cd->background = 3;
-               break;
-       case 3:
-               if (cd->ur_r != cd->ur_w) {
-                       if (cd->ur[cd->ur_r] != c_stop) {
-                               debug(("cm206_bh: c_stop echoed 0x%x\n",
-                                      cd->ur[cd->ur_r]));
-                               stats(echo);
-                       }
-                       cd->ur_r++;
-                       cd->ur_r %= UR_SIZE;
-               }
-               cd->background++;
-               break;
-       case 4:
-               if (cd->ur_r != cd->ur_w) {
-                       if (cd->ur[cd->ur_r] != 0xff) {
-                               debug(("cm206_bh: c_stop reacted with 0x%x\n", cd->ur[cd->ur_r]));
-                               stats(stop_0xff);
-                       }
-                       cd->ur_r++;
-                       cd->ur_r %= UR_SIZE;
-               }
-               cd->background = 0;
-       }
-}
-
-static DECLARE_TASKLET(cm206_tasklet, cm206_tasklet_func, 0);
-
-/* This command clears the dsb_possible_media_change flag, so we must 
- * retain it.
- */
-static void get_drive_status(void)
-{
-       uch status[2];
-       type_1_command(c_drive_status, 2, status);      /* this might be done faster */
-       cd->dsb = status[0];
-       cd->cc = status[1];
-       cd->media_changed |=
-           !!(cd->dsb & (dsb_possible_media_change |
-                         dsb_drive_not_ready | dsb_tray_not_closed));
-}
-
-static void get_disc_status(void)
-{
-       if (type_1_command(c_disc_status, 7, cd->disc_status)) {
-               debug(("get_disc_status: error\n"));
-       }
-}
-
-/* The new open. The real opening strategy is defined in cdrom.c. */
-
-static int cm206_open(struct cdrom_device_info *cdi, int purpose)
-{
-       if (!cd->openfiles) {   /* reset only first time */
-               cd->background = 0;
-               reset_cm260();
-               cd->adapter_last = -1;  /* invalidate adapter memory */
-               cd->sector_last = -1;
-       }
-       ++cd->openfiles;
-       stats(open);
-       return 0;
-}
-
-static void cm206_release(struct cdrom_device_info *cdi)
-{
-       if (cd->openfiles == 1) {
-               if (cd->background) {
-                       cd->background = 0;
-                       stop_read();
-               }
-               cd->sector_last = -1;   /* Make our internal buffer invalid */
-               FIRST_TRACK = 0;        /* No valid disc status */
-       }
-       --cd->openfiles;
-}
-
-/* Empty buffer empties $sectors$ sectors of the adapter card buffer,
- * and then reads a sector in kernel memory.  */
-static void empty_buffer(int sectors)
-{
-       while (sectors >= 0) {
-               transport_data(r_fifo_output_buffer,
-                              cd->sector + cd->fifo_overflowed,
-                              RAW_SECTOR_SIZE / 2 - cd->fifo_overflowed);
-               --sectors;
-               ++cd->adapter_first;    /* update the current adapter sector */
-               cd->fifo_overflowed = 0;        /* reset overflow bit */
-               stats(sector_transferred);
-       }
-       cd->sector_first = cd->adapter_first - 1;
-       cd->sector_last = cd->adapter_first;    /* update the buffer sector */
-}
-
-/* try_adapter. This function determines if the requested sector is
-   in adapter memory, or will appear there soon. Returns 0 upon
-   success */
-static int try_adapter(int sector)
-{
-       if (cd->adapter_first <= sector && sector < cd->adapter_last) {
-               /* sector is in adapter memory */
-               empty_buffer(sector - cd->adapter_first);
-               return 0;
-       } else if (cd->background == 1 && cd->adapter_first <= sector
-                  && sector < cd->adapter_first + cd->max_sectors) {
-               /* a read is going on, we can wait for it */
-               cd->wait_back = 1;
-               while (sector >= cd->adapter_last) {
-                       if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
-                               debug(("Timed out during background wait: %d %d %d %d\n", sector, cd->adapter_last, cd->adapter_first, cd->background));
-                               stats(back_read_timeout);
-                               cd->wait_back = 0;
-                               return -1;
-                       }
-               }
-               cd->wait_back = 0;
-               empty_buffer(sector - cd->adapter_first);
-               return 0;
-       } else
-               return -2;
-}
-
-/* This is not a very smart implementation. We could optimize for 
-   consecutive block numbers. I'm not convinced this would really
-   bring down the processor load. */
-static void do_cm206_request(request_queue_t * q)
-{
-       long int i, cd_sec_no;
-       int quarter, error;
-       uch *source, *dest;
-       struct request *req;
-
-       while (1) {     /* repeat until all requests have been satisfied */
-               req = elv_next_request(q);
-               if (!req)
-                       return;
-
-               if (rq_data_dir(req) != READ) {
-                       debug(("Non-read command %d on cdrom\n", req->cmd));
-                       end_request(req, 0);
-                       continue;
-               }
-               spin_unlock_irq(q->queue_lock);
-               error = 0;
-               for (i = 0; i < req->nr_sectors; i++) {
-                       int e1, e2;
-                       cd_sec_no = (req->sector + i) / BLOCKS_ISO;     /* 4 times 512 bytes */
-                       quarter = (req->sector + i) % BLOCKS_ISO;
-                       dest = req->buffer + i * LINUX_BLOCK_SIZE;
-                       /* is already in buffer memory? */
-                       if (cd->sector_first <= cd_sec_no
-                           && cd_sec_no < cd->sector_last) {
-                               source =
-                                   ((uch *) cd->sector) + 16 +
-                                   quarter * LINUX_BLOCK_SIZE +
-                                   (cd_sec_no -
-                                    cd->sector_first) * RAW_SECTOR_SIZE;
-                               memcpy(dest, source, LINUX_BLOCK_SIZE);
-                       } else if (!(e1 = try_adapter(cd_sec_no)) ||
-                                  !(e2 = read_sector(cd_sec_no))) {
-                               source =
-                                   ((uch *) cd->sector) + 16 +
-                                   quarter * LINUX_BLOCK_SIZE;
-                               memcpy(dest, source, LINUX_BLOCK_SIZE);
-                       } else {
-                               error = 1;
-                               debug(("cm206_request: %d %d\n", e1, e2));
-                       }
-               }
-               spin_lock_irq(q->queue_lock);
-               end_request(req, !error);
-       }
-}
-
-/* Audio support. I've tried very hard, but the cm206 drive doesn't 
-   seem to have a get_toc (table-of-contents) function, while i'm
-   pretty sure it must read the toc upon disc insertion. Therefore
-   this function has been implemented through a binary search 
-   strategy. All track starts that happen to be found are stored in
-   cd->toc[], for future use. 
-
-   I've spent a whole day on a bug that only shows under Workman---
-   I don't get it. Tried everything, nothing works. If workman asks
-   for track# 0xaa, it'll get the wrong time back. Any other program
-   receives the correct value. I'm stymied.
-*/
-
-/* seek seeks to address lba. It does wait to arrive there. */
-static void seek(int lba)
-{
-       int i;
-       uch seek_command[4] = { c_seek, };
-
-       fsm(lba, &seek_command[1]);
-       for (i = 0; i < 4; i++)
-               type_0_command(seek_command[i], 0);
-       cd->dsb = wait_dsb();
-}
-
-static uch bcdbin(unsigned char bcd)
-{                              /* stolen from mcd.c! */
-       return (bcd >> 4) * 10 + (bcd & 0xf);
-}
-
-static inline uch normalize_track(uch track)
-{
-       if (track < 1)
-               return 1;
-       if (track > LAST_TRACK)
-               return LAST_TRACK + 1;
-       return track;
-}
-
-/* This function does a binary search for track start. It records all
- * tracks seen in the process. Input $track$ must be between 1 and
- * #-of-tracks+1.  Note that the start of the disc must be in toc[1].fsm. 
- */
-static int get_toc_lba(uch track)
-{
-       int max = 74 * 60 * 75 - 150, min = fsm2lba(cd->toc[1].fsm);
-       int i, lba, l, old_lba = 0;
-       uch *q = cd->q;
-       uch ct;                 /* current track */
-       int binary = 0;
-       const int skip = 3 * 60 * 75;   /* 3 minutes */
-
-       for (i = track; i > 0; i--)
-               if (cd->toc[i].track) {
-                       min = fsm2lba(cd->toc[i].fsm);
-                       break;
-               }
-       lba = min + skip;
-       do {
-               seek(lba);
-               type_1_command(c_read_current_q, 10, q);
-               ct = normalize_track(q[1]);
-               if (!cd->toc[ct].track) {
-                       l = q[9] - bcdbin(q[5]) + 75 * (q[8] -
-                                                       bcdbin(q[4]) - 2 +
-                                                       60 * (q[7] -
-                                                             bcdbin(q
-                                                                    [3])));
-                       cd->toc[ct].track = q[1];       /* lead out still 0xaa */
-                       fsm(l, cd->toc[ct].fsm);
-                       cd->toc[ct].q0 = q[0];  /* contains adr and ctrl info */
-                       if (ct == track)
-                               return l;
-               }
-               old_lba = lba;
-               if (binary) {
-                       if (ct < track)
-                               min = lba;
-                       else
-                               max = lba;
-                       lba = (min + max) / 2;
-               } else {
-                       if (ct < track)
-                               lba += skip;
-                       else {
-                               binary = 1;
-                               max = lba;
-                               min = lba - skip;
-                               lba = (min + max) / 2;
-                       }
-               }
-       } while (lba != old_lba);
-       return lba;
-}
-
-static void update_toc_entry(uch track)
-{
-       track = normalize_track(track);
-       if (!cd->toc[track].track)
-               get_toc_lba(track);
-}
-
-/* return 0 upon success */
-static int read_toc_header(struct cdrom_tochdr *hp)
-{
-       if (!FIRST_TRACK)
-               get_disc_status();
-       if (hp) {
-               int i;
-               hp->cdth_trk0 = FIRST_TRACK;
-               hp->cdth_trk1 = LAST_TRACK;
-               /* fill in first track position */
-               for (i = 0; i < 3; i++)
-                       cd->toc[1].fsm[i] = cd->disc_status[3 + i];
-               update_toc_entry(LAST_TRACK + 1);       /* find most entries */
-               return 0;
-       }
-       return -1;
-}
-
-static void play_from_to_msf(struct cdrom_msf *msfp)
-{
-       uch play_command[] = { c_play,
-               msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0,
-               msfp->cdmsf_frame1, msfp->cdmsf_sec1, msfp->cdmsf_min1, 2,
-                   2
-       };
-       int i;
-       for (i = 0; i < 9; i++)
-               type_0_command(play_command[i], 0);
-       for (i = 0; i < 3; i++)
-               PLAY_TO.fsm[i] = play_command[i + 4];
-       PLAY_TO.track = 0;      /* say no track end */
-       cd->dsb = wait_dsb();
-}
-
-static void play_from_to_track(int from, int to)
-{
-       uch play_command[8] = { c_play, };
-       int i;
-
-       if (from == 0) {        /* continue paused play */
-               for (i = 0; i < 3; i++) {
-                       play_command[i + 1] = cd->audio_status[i + 2];
-                       play_command[i + 4] = PLAY_TO.fsm[i];
-               }
-       } else {
-               update_toc_entry(from);
-               update_toc_entry(to + 1);
-               for (i = 0; i < 3; i++) {
-                       play_command[i + 1] = cd->toc[from].fsm[i];
-                       PLAY_TO.fsm[i] = play_command[i + 4] =
-                           cd->toc[to + 1].fsm[i];
-               }
-               PLAY_TO.track = to;
-       }
-       for (i = 0; i < 7; i++)
-               type_0_command(play_command[i], 0);
-       for (i = 0; i < 2; i++)
-               type_0_command(0x2, 0); /* volume */
-       cd->dsb = wait_dsb();
-}
-
-static int get_current_q(struct cdrom_subchnl *qp)
-{
-       int i;
-       uch *q = cd->q;
-       if (type_1_command(c_read_current_q, 10, q))
-               return 0;
-/*  q[0] = bcdbin(q[0]); Don't think so! */
-       for (i = 2; i < 6; i++)
-               q[i] = bcdbin(q[i]);
-       qp->cdsc_adr = q[0] & 0xf;
-       qp->cdsc_ctrl = q[0] >> 4;      /* from mcd.c */
-       qp->cdsc_trk = q[1];
-       qp->cdsc_ind = q[2];
-       if (qp->cdsc_format == CDROM_MSF) {
-               qp->cdsc_reladdr.msf.minute = q[3];
-               qp->cdsc_reladdr.msf.second = q[4];
-               qp->cdsc_reladdr.msf.frame = q[5];
-               qp->cdsc_absaddr.msf.minute = q[7];
-               qp->cdsc_absaddr.msf.second = q[8];
-               qp->cdsc_absaddr.msf.frame = q[9];
-       } else {
-               qp->cdsc_reladdr.lba = f_s_m2lba(q[5], q[4], q[3]);
-               qp->cdsc_absaddr.lba = f_s_m2lba(q[9], q[8], q[7]);
-       }
-       get_drive_status();
-       if (cd->dsb & dsb_play_in_progress)
-               qp->cdsc_audiostatus = CDROM_AUDIO_PLAY;
-       else if (PAUSED)
-               qp->cdsc_audiostatus = CDROM_AUDIO_PAUSED;
-       else
-               qp->cdsc_audiostatus = CDROM_AUDIO_NO_STATUS;
-       return 0;
-}
-
-static void invalidate_toc(void)
-{
-       memset(cd->toc, 0, sizeof(cd->toc));
-       memset(cd->disc_status, 0, sizeof(cd->disc_status));
-}
-
-/* cdrom.c guarantees that cdte_format == CDROM_MSF */
-static void get_toc_entry(struct cdrom_tocentry *ep)
-{
-       uch track = normalize_track(ep->cdte_track);
-       update_toc_entry(track);
-       ep->cdte_addr.msf.frame = cd->toc[track].fsm[0];
-       ep->cdte_addr.msf.second = cd->toc[track].fsm[1];
-       ep->cdte_addr.msf.minute = cd->toc[track].fsm[2];
-       ep->cdte_adr = cd->toc[track].q0 & 0xf;
-       ep->cdte_ctrl = cd->toc[track].q0 >> 4;
-       ep->cdte_datamode = 0;
-}
-
-/* Audio ioctl.  Ioctl commands connected to audio are in such an
- * idiosyncratic i/o format, that we leave these untouched. Return 0
- * upon success. Memory checking has been done by cdrom_ioctl(), the
- * calling function, as well as LBA/MSF sanitization.
-*/
-static int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
-                            void *arg)
-{
-       switch (cmd) {
-       case CDROMREADTOCHDR:
-               return read_toc_header((struct cdrom_tochdr *) arg);
-       case CDROMREADTOCENTRY:
-               get_toc_entry((struct cdrom_tocentry *) arg);
-               return 0;
-       case CDROMPLAYMSF:
-               play_from_to_msf((struct cdrom_msf *) arg);
-               return 0;
-       case CDROMPLAYTRKIND:   /* admittedly, not particularly beautiful */
-               play_from_to_track(((struct cdrom_ti *) arg)->cdti_trk0,
-                                  ((struct cdrom_ti *) arg)->cdti_trk1);
-               return 0;
-       case CDROMSTOP:
-               PAUSED = 0;
-               if (cd->dsb & dsb_play_in_progress)
-                       return type_0_command(c_stop, 1);
-               else
-                       return 0;
-       case CDROMPAUSE:
-               get_drive_status();
-               if (cd->dsb & dsb_play_in_progress) {
-                       type_0_command(c_stop, 1);
-                       type_1_command(c_audio_status, 5,
-                                      cd->audio_status);
-                       PAUSED = 1;     /* say we're paused */
-               }
-               return 0;
-       case CDROMRESUME:
-               if (PAUSED)
-                       play_from_to_track(0, 0);
-               PAUSED = 0;
-               return 0;
-       case CDROMSTART:
-       case CDROMVOLCTRL:
-               return 0;
-       case CDROMSUBCHNL:
-               return get_current_q((struct cdrom_subchnl *) arg);
-       default:
-               return -EINVAL;
-       }
-}
-
-static int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
-       if (cd != NULL) {
-               int r;
-               get_drive_status();     /* ensure cd->media_changed OK */
-               r = cd->media_changed;
-               cd->media_changed = 0;  /* clear bit */
-               return r;
-       } else
-               return -EIO;
-}
-
-/* The new generic cdrom support. Routines should be concise, most of
-   the logic should be in cdrom.c */
-
-
-/* controls tray movement */
-static int cm206_tray_move(struct cdrom_device_info *cdi, int position)
-{
-       if (position) {         /* 1: eject */
-               type_0_command(c_open_tray, 1);
-               invalidate_toc();
-       } else
-               type_0_command(c_close_tray, 1);        /* 0: close */
-       return 0;
-}
-
-/* gives current state of the drive */
-static int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
-       get_drive_status();
-       if (cd->dsb & dsb_tray_not_closed)
-               return CDS_TRAY_OPEN;
-       if (!(cd->dsb & dsb_disc_present))
-               return CDS_NO_DISC;
-       if (cd->dsb & dsb_drive_not_ready)
-               return CDS_DRIVE_NOT_READY;
-       return CDS_DISC_OK;
-}
-
-/* locks or unlocks door lock==1: lock; return 0 upon success */
-static int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
-{
-       uch command = (lock) ? c_lock_tray : c_unlock_tray;
-       type_0_command(command, 1);     /* wait and get dsb */
-       /* the logic calculates the success, 0 means successful */
-       return lock ^ ((cd->dsb & dsb_tray_locked) != 0);
-}
-
-/* Although a session start should be in LBA format, we return it in 
-   MSF format because it is slightly easier, and the new generic ioctl
-   will take care of the necessary conversion. */
-static int cm206_get_last_session(struct cdrom_device_info *cdi,
-                                 struct cdrom_multisession *mssp)
-{
-       if (!FIRST_TRACK)
-               get_disc_status();
-       if (mssp != NULL) {
-               if (DISC_STATUS & cds_multi_session) {  /* multi-session */
-                       mssp->addr.msf.frame = cd->disc_status[3];
-                       mssp->addr.msf.second = cd->disc_status[4];
-                       mssp->addr.msf.minute = cd->disc_status[5];
-                       mssp->addr_format = CDROM_MSF;
-                       mssp->xa_flag = 1;
-               } else {
-                       mssp->xa_flag = 0;
-               }
-               return 1;
-       }
-       return 0;
-}
-
-static int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
-       uch upc[10];
-       char *ret = mcn->medium_catalog_number;
-       int i;
-
-       if (type_1_command(c_read_upc, 10, upc))
-               return -EIO;
-       for (i = 0; i < 13; i++) {
-               int w = i / 2 + 1, r = i % 2;
-               if (r)
-                       ret[i] = 0x30 | (upc[w] & 0x0f);
-               else
-                       ret[i] = 0x30 | ((upc[w] >> 4) & 0x0f);
-       }
-       ret[13] = '\0';
-       return 0;
-}
-
-static int cm206_reset(struct cdrom_device_info *cdi)
-{
-       stop_read();
-       reset_cm260();
-       outw(dc_normal | dc_break | READ_AHEAD, r_data_control);
-       mdelay(1);              /* 750 musec minimum */
-       outw(dc_normal | READ_AHEAD, r_data_control);
-       cd->sector_last = -1;   /* flag no data buffered */
-       cd->adapter_last = -1;
-       invalidate_toc();
-       return 0;
-}
-
-static int cm206_select_speed(struct cdrom_device_info *cdi, int speed)
-{
-       int r;
-       switch (speed) {
-       case 0:
-               r = type_0_command(c_auto_mode, 1);
-               break;
-       case 1:
-               r = type_0_command(c_force_1x, 1);
-               break;
-       case 2:
-               r = type_0_command(c_force_2x, 1);
-               break;
-       default:
-               return -1;
-       }
-       if (r < 0)
-               return r;
-       else
-               return 1;
-}
-
-static struct cdrom_device_ops cm206_dops = {
-       .open                   = cm206_open,
-       .release                = cm206_release,
-       .drive_status           = cm206_drive_status,
-       .media_changed          = cm206_media_changed,
-       .tray_move              = cm206_tray_move,
-       .lock_door              = cm206_lock_door,
-       .select_speed           = cm206_select_speed,
-       .get_last_session       = cm206_get_last_session,
-       .get_mcn                = cm206_get_upc,
-       .reset                  = cm206_reset,
-       .audio_ioctl            = cm206_audio_ioctl,
-       .capability             = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
-                                 CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
-                                 CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED |
-                                 CDC_DRIVE_STATUS,
-       .n_minors               = 1,
-};
-
-
-static struct cdrom_device_info cm206_info = {
-       .ops            = &cm206_dops,
-       .speed          = 2,
-       .capacity       = 1,
-       .name           = "cm206",
-};
-
-static int cm206_block_open(struct inode *inode, struct file *file)
-{
-       return cdrom_open(&cm206_info, inode, file);
-}
-
-static int cm206_block_release(struct inode *inode, struct file *file)
-{
-       return cdrom_release(&cm206_info, file);
-}
-
-static int cm206_block_ioctl(struct inode *inode, struct file *file,
-                               unsigned cmd, unsigned long arg)
-{
-       switch (cmd) {
-#ifdef STATISTICS
-       case CM206CTL_GET_STAT:
-               if (arg >= NR_STATS)
-                       return -EINVAL;
-               return cd->stats[arg];
-       case CM206CTL_GET_LAST_STAT:
-               if (arg >= NR_STATS)
-                       return -EINVAL;
-               return cd->last_stat[arg];
-#endif
-       default:
-               break;
-       }
-
-       return cdrom_ioctl(file, &cm206_info, inode, cmd, arg);
-}
-
-static int cm206_block_media_changed(struct gendisk *disk)
-{
-       return cdrom_media_changed(&cm206_info);
-}
-
-static struct block_device_operations cm206_bdops =
-{
-       .owner          = THIS_MODULE,
-       .open           = cm206_block_open,
-       .release        = cm206_block_release,
-       .ioctl          = cm206_block_ioctl,
-       .media_changed  = cm206_block_media_changed,
-};
-
-static struct gendisk *cm206_gendisk;
-
-/* This function probes for the adapter card. It returns the base
-   address if it has found the adapter card. One can specify a base 
-   port to probe specifically, or 0 which means span all possible
-   bases. 
-
-   Linus says it is too dangerous to use writes for probing, so we
-   stick with pure reads for a while. Hope that 8 possible ranges,
-   request_region, 15 bits of one port and 6 of another make things
-   likely enough to accept the region on the first hit...
- */
-static int __init probe_base_port(int base)
-{
-       int b = 0x300, e = 0x370;       /* this is the range of start addresses */
-       volatile int fool, i;
-
-       if (base)
-               b = e = base;
-       for (base = b; base <= e; base += 0x10) {
-               if (!request_region(base, 0x10,"cm206"))
-                       continue;
-               for (i = 0; i < 3; i++)
-                       fool = inw(base + 2);   /* empty possibly uart_receive_buffer */
-               if ((inw(base + 6) & 0xffef) != 0x0001 ||       /* line_status */
-                   (inw(base) & 0xad00) != 0)  { /* data status */
-                       release_region(base,0x10);
-                       continue;
-               }
-               return (base);
-       }
-       return 0;
-}
-
-#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
-/* Probe for irq# nr. If nr==0, probe for all possible irq's. */
-static int __init probe_irq(int nr)
-{
-       int irqs, irq;
-       outw(dc_normal | READ_AHEAD, r_data_control);   /* disable irq-generation */
-       sti();
-       irqs = probe_irq_on();
-       reset_cm260();          /* causes interrupt */
-       udelay(100);            /* wait for it */
-       irq = probe_irq_off(irqs);
-       outw(dc_normal | READ_AHEAD, r_data_control);   /* services interrupt */
-       if (nr && irq != nr && irq > 0)
-               return 0;       /* wrong interrupt happened */
-       else
-               return irq;
-}
-#endif
-
-int __init cm206_init(void)
-{
-       uch e = 0;
-       long int size = sizeof(struct cm206_struct);
-       struct gendisk *disk;
-
-       printk(KERN_INFO "cm206 cdrom driver " REVISION);
-       cm206_base = probe_base_port(auto_probe ? 0 : cm206_base);
-       if (!cm206_base) {
-               printk(" can't find adapter!\n");
-               return -EIO;
-       }
-       printk(" adapter at 0x%x", cm206_base);
-       cd = kmalloc(size, GFP_KERNEL);
-       if (!cd)
-               goto out_base;
-       /* Now we have found the adaptor card, try to reset it. As we have
-        * found out earlier, this process generates an interrupt as well,
-        * so we might just exploit that fact for irq probing! */
-#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
-       cm206_irq = probe_irq(auto_probe ? 0 : cm206_irq);
-       if (cm206_irq <= 0) {
-               printk("can't find IRQ!\n");
-               goto out_probe;
-       } else
-               printk(" IRQ %d found\n", cm206_irq);
-#else
-       cli();
-       reset_cm260();
-       /* Now, the problem here is that reset_cm260 can generate an
-          interrupt. It seems that this can cause a kernel oops some time
-          later. So we wait a while and `service' this interrupt. */
-       mdelay(1);
-       outw(dc_normal | READ_AHEAD, r_data_control);
-       sti();
-       printk(" using IRQ %d\n", cm206_irq);
-#endif
-       if (send_receive_polled(c_drive_configuration) !=
-           c_drive_configuration) {
-               printk(KERN_INFO " drive not there\n");
-               goto out_probe;
-       }
-       e = send_receive_polled(c_gimme);
-       printk(KERN_INFO "Firmware revision %d", e & dcf_revision_code);
-       if (e & dcf_transfer_rate)
-               printk(" double");
-       else
-               printk(" single");
-       printk(" speed drive");
-       if (e & dcf_motorized_tray)
-               printk(", motorized tray");
-       if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206", NULL)) {
-               printk("\nUnable to reserve IRQ---aborted\n");
-               goto out_probe;
-       }
-       printk(".\n");
-
-       if (register_blkdev(MAJOR_NR, "cm206"))
-               goto out_blkdev;
-
-       disk = alloc_disk(1);
-       if (!disk)
-               goto out_disk;
-       disk->major = MAJOR_NR;
-       disk->first_minor = 0;
-       sprintf(disk->disk_name, "cm206cd");
-       disk->fops = &cm206_bdops;
-       disk->flags = GENHD_FL_CD;
-       cm206_gendisk = disk;
-       if (register_cdrom(&cm206_info) != 0) {
-               printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR);
-               goto out_cdrom;
-       }
-       cm206_queue = blk_init_queue(do_cm206_request, &cm206_lock);
-       if (!cm206_queue)
-               goto out_queue;
-               
-       blk_queue_hardsect_size(cm206_queue, 2048);
-       disk->queue = cm206_queue;
-       add_disk(disk);
-
-       memset(cd, 0, sizeof(*cd));     /* give'm some reasonable value */
-       cd->sector_last = -1;   /* flag no data buffered */
-       cd->adapter_last = -1;
-       init_timer(&cd->timer);
-       cd->timer.function = cm206_timeout;
-       cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97;
-       printk(KERN_INFO "%d kB adapter memory available, "
-              " %ld bytes kernel memory used.\n", cd->max_sectors * 2,
-              size);
-       return 0;
-
-out_queue:
-       unregister_cdrom(&cm206_info);
-out_cdrom:
-       put_disk(disk);
-out_disk:
-       unregister_blkdev(MAJOR_NR, "cm206");
-out_blkdev:
-       free_irq(cm206_irq, NULL);
-out_probe:
-       kfree(cd);
-out_base:
-       release_region(cm206_base, 16);
-       return -EIO;
-}
-
-#ifdef MODULE
-
-
-static void __init parse_options(void)
-{
-       int i;
-       for (i = 0; i < 2; i++) {
-               if (0x300 <= cm206[i] && i <= 0x370
-                   && cm206[i] % 0x10 == 0) {
-                       cm206_base = cm206[i];
-                       auto_probe = 0;
-               } else if (3 <= cm206[i] && cm206[i] <= 15) {
-                       cm206_irq = cm206[i];
-                       auto_probe = 0;
-               }
-       }
-}
-
-static int __init __cm206_init(void)
-{
-       parse_options();
-#if !defined(AUTO_PROBE_MODULE)
-       auto_probe = 0;
-#endif
-       return cm206_init();
-}
-
-static void __exit cm206_exit(void)
-{
-       del_gendisk(cm206_gendisk);
-       put_disk(cm206_gendisk);
-       if (unregister_cdrom(&cm206_info)) {
-               printk("Can't unregister cdrom cm206\n");
-               return;
-       }
-       if (unregister_blkdev(MAJOR_NR, "cm206")) {
-               printk("Can't unregister major cm206\n");
-               return;
-       }
-       blk_cleanup_queue(cm206_queue);
-       free_irq(cm206_irq, NULL);
-       kfree(cd);
-       release_region(cm206_base, 16);
-       printk(KERN_INFO "cm206 removed\n");
-}
-
-module_init(__cm206_init);
-module_exit(cm206_exit);
-
-#else                          /* !MODULE */
-
-/* This setup function accepts either `auto' or numbers in the range
- * 3--11 (for irq) or 0x300--0x370 (for base port) or both. */
-
-static int __init cm206_setup(char *s)
-{
-       int i, p[4];
-
-       (void) get_options(s, ARRAY_SIZE(p), p);
-
-       if (!strcmp(s, "auto"))
-               auto_probe = 1;
-       for (i = 1; i <= p[0]; i++) {
-               if (0x300 <= p[i] && i <= 0x370 && p[i] % 0x10 == 0) {
-                       cm206_base = p[i];
-                       auto_probe = 0;
-               } else if (3 <= p[i] && p[i] <= 15) {
-                       cm206_irq = p[i];
-                       auto_probe = 0;
-               }
-       }
-       return 1;
-}
-
-__setup("cm206=", cm206_setup);
-
-#endif                         /* !MODULE */
-MODULE_ALIAS_BLOCKDEV_MAJOR(CM206_CDROM_MAJOR);
-
diff --git a/drivers/cdrom/cm206.h b/drivers/cdrom/cm206.h
deleted file mode 100644 (file)
index 0ae51c1..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/* cm206.h Header file for cm206.c.
-   Copyright (c) 1995 David van Leeuwen 
-*/
-
-#ifndef LINUX_CM206_H
-#define LINUX_CM206_H
-
-#include <linux/ioctl.h>
-
-/* First, the cm260 stuff */
-/* The ports and irq used. Although CM206_BASE and CM206_IRQ are defined
-   below, the values are not used unless autoprobing is turned off and 
-   no LILO boot options or module command line options are given. Change
-   these values to your own as last resort if autoprobing and options
-   don't work. */
-
-#define CM206_BASE 0x340
-#define CM206_IRQ 11
-
-#define r_data_status (cm206_base)
-#define r_uart_receive (cm206_base+0x2)
-#define r_fifo_output_buffer (cm206_base+0x4)
-#define r_line_status (cm206_base+0x6)
-#define r_data_control (cm206_base+0x8)
-#define r_uart_transmit (cm206_base+0xa)
-#define r_test_clock (cm206_base+0xc)
-#define r_test_control (cm206_base+0xe)
-
-/* the data_status flags */
-#define ds_ram_size 0x4000
-#define ds_toc_ready 0x2000
-#define ds_fifo_empty 0x1000
-#define ds_sync_error 0x800
-#define ds_crc_error 0x400
-#define ds_data_error 0x200
-#define ds_fifo_overflow 0x100
-#define ds_data_ready 0x80
-
-/* the line_status flags */
-#define ls_attention 0x10
-#define ls_parity_error 0x8
-#define ls_overrun 0x4
-#define ls_receive_buffer_full 0x2
-#define ls_transmitter_buffer_empty 0x1
-
-/* the data control register flags */
-#define dc_read_q_channel 0x4000
-#define dc_mask_sync_error 0x2000
-#define dc_toc_enable 0x1000
-#define dc_no_stop_on_error 0x800
-#define dc_break 0x400
-#define dc_initialize 0x200
-#define dc_mask_transmit_ready 0x100
-#define dc_flag_enable 0x80
-
-/* Define the default data control register flags here */
-#define dc_normal (dc_mask_sync_error | dc_no_stop_on_error | \
-                  dc_mask_transmit_ready)
-
-/* now some constants related to the cm206 */
-/* another drive status byte, echoed by the cm206 on most commands */
-
-#define dsb_error_condition 0x1
-#define dsb_play_in_progress 0x4
-#define dsb_possible_media_change 0x8
-#define dsb_disc_present 0x10
-#define dsb_drive_not_ready 0x20
-#define dsb_tray_locked 0x40
-#define dsb_tray_not_closed 0x80
-
-#define dsb_not_useful (dsb_drive_not_ready | dsb_tray_not_closed)
-
-/* the cm206 command set */
-
-#define c_close_tray 0
-#define c_lock_tray 0x01
-#define c_unlock_tray 0x04
-#define c_open_tray 0x05
-#define c_seek 0x10
-#define c_read_data 0x20
-#define c_force_1x 0x21
-#define c_force_2x 0x22
-#define c_auto_mode 0x23
-#define c_play 0x30
-#define c_set_audio_mode 0x31
-#define c_read_current_q 0x41
-#define c_stream_q 0x42
-#define c_drive_status 0x50
-#define c_disc_status 0x51
-#define c_audio_status 0x52
-#define c_drive_configuration 0x53
-#define c_read_upc 0x60
-#define c_stop 0x70
-#define c_calc_checksum 0xe5
-
-#define c_gimme 0xf8
-
-/* finally, the (error) condition that the drive can be in      *
- * OK, this is not always an error, but let's prefix it with e_ */
-
-#define e_none 0
-#define e_illegal_command 0x01
-#define e_sync 0x02
-#define e_seek 0x03
-#define e_parity 0x04
-#define e_focus 0x05
-#define e_header_sync 0x06
-#define e_code_incompatibility 0x07
-#define e_reset_done 0x08
-#define e_bad_parameter 0x09
-#define e_radial 0x0a
-#define e_sub_code 0x0b
-#define e_no_data_track 0x0c
-#define e_scan 0x0d
-#define e_tray_open 0x0f
-#define e_no_disc 0x10
-#define e_tray stalled 0x11
-
-/* drive configuration masks */
-
-#define dcf_revision_code 0x7
-#define dcf_transfer_rate 0x60
-#define dcf_motorized_tray 0x80
-
-/* disc status byte */
-
-#define cds_multi_session 0x2
-#define cds_all_audio 0x8
-#define cds_xa_mode 0xf0
-
-/* finally some ioctls for the driver */
-
-#define CM206CTL_GET_STAT _IO( 0x20, 0 )
-#define CM206CTL_GET_LAST_STAT _IO( 0x20, 1 )
-
-#ifdef STATISTICS
-
-/* This is an ugly way to guarantee that the names of the statistics
- * are the same in the code and in the diagnostics program.  */
-
-#ifdef __KERNEL__
-#define x(a) st_ ## a
-#define y enum
-#else
-#define x(a) #a
-#define y char * stats_name[] = 
-#endif
-
-y {x(interrupt), x(data_ready), x(fifo_overflow), x(data_error),
-     x(crc_error), x(sync_error), x(lost_intr), x(echo),
-     x(write_timeout), x(receive_timeout), x(read_timeout),
-     x(dsb_timeout), x(stop_0xff), x(back_read_timeout),
-     x(sector_transferred), x(read_restarted), x(read_background),
-     x(bh), x(open), x(ioctl_multisession), x(attention)
-#ifdef __KERNEL__
-     , x(last_entry)
-#endif
- };
-
-#ifdef __KERNEL__
-#define NR_STATS st_last_entry
-#else
-#define NR_STATS (sizeof(stats_name)/sizeof(char*))
-#endif
-
-#undef y
-#undef x
-
-#endif /* STATISTICS */
-
-#endif /* LINUX_CM206_H */
diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
deleted file mode 100644 (file)
index 176742e..0000000
+++ /dev/null
@@ -1,1029 +0,0 @@
-#define GSCD_VERSION "0.4a Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>"
-
-/*
-       linux/drivers/block/gscd.c - GoldStar R420 CDROM driver
-
-        Copyright (C) 1995  Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>
-        based upon pre-works by   Eberhard Moenkeberg <emoenke@gwdg.de>
-        
-
-        For all kind of other information about the GoldStar CDROM
-        and this Linux device driver I installed a WWW-URL:
-        http://linux.rz.fh-hannover.de/~raupach        
-
-
-             If you are the editor of a Linux CD, you should
-             enable gscd.c within your boot floppy kernel and
-             send me one of your CDs for free.
-
-
-        --------------------------------------------------------------------
-       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.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, write to the Free Software
-       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-       
-       --------------------------------------------------------------------
-       
-       9 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>
-
-*/
-
-/* These settings are for various debug-level. Leave they untouched ... */
-#define  NO_GSCD_DEBUG
-#define  NO_IOCTL_DEBUG
-#define  NO_MODULE_DEBUG
-#define  NO_FUTURE_WORK
-/*------------------------*/
-
-#include <linux/module.h>
-
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#define MAJOR_NR GOLDSTAR_CDROM_MAJOR
-#include <linux/blkdev.h>
-#include "gscd.h"
-
-static int gscdPresent = 0;
-
-static unsigned char gscd_buf[2048];   /* buffer for block size conversion */
-static int gscd_bn = -1;
-static short gscd_port = GSCD_BASE_ADDR;
-module_param_named(gscd, gscd_port, short, 0);
-
-/* Kommt spaeter vielleicht noch mal dran ...
- *    static DECLARE_WAIT_QUEUE_HEAD(gscd_waitq);
- */
-
-static void gscd_read_cmd(struct request *req);
-static void gscd_hsg2msf(long hsg, struct msf *msf);
-static void gscd_bin2bcd(unsigned char *p);
-
-/* Schnittstellen zum Kern/FS */
-
-static void __do_gscd_request(unsigned long dummy);
-static int gscd_ioctl(struct inode *, struct file *, unsigned int,
-                     unsigned long);
-static int gscd_open(struct inode *, struct file *);
-static int gscd_release(struct inode *, struct file *);
-static int check_gscd_med_chg(struct gendisk *disk);
-
-/*      GoldStar Funktionen    */
-
-static void cmd_out(int, char *, char *, int);
-static void cmd_status(void);
-static void init_cd_drive(int);
-
-static int get_status(void);
-static void clear_Audio(void);
-static void cc_invalidate(void);
-
-/* some things for the next version */
-#ifdef FUTURE_WORK
-static void update_state(void);
-static long gscd_msf2hsg(struct msf *mp);
-static int gscd_bcd2bin(unsigned char bcd);
-#endif
-
-
-/*      lo-level cmd-Funktionen    */
-
-static void cmd_info_in(char *, int);
-static void cmd_end(void);
-static void cmd_read_b(char *, int, int);
-static void cmd_read_w(char *, int, int);
-static int cmd_unit_alive(void);
-static void cmd_write_cmd(char *);
-
-
-/*      GoldStar Variablen     */
-
-static int curr_drv_state;
-static int drv_states[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-static int drv_mode;
-static int disk_state;
-static int speed;
-static int ndrives;
-
-static unsigned char drv_num_read;
-static unsigned char f_dsk_valid;
-static unsigned char current_drive;
-static unsigned char f_drv_ok;
-
-
-static char f_AudioPlay;
-static char f_AudioPause;
-static int AudioStart_m;
-static int AudioStart_f;
-static int AudioEnd_m;
-static int AudioEnd_f;
-
-static DEFINE_TIMER(gscd_timer, NULL, 0, 0);
-static DEFINE_SPINLOCK(gscd_lock);
-static struct request_queue *gscd_queue;
-
-static struct block_device_operations gscd_fops = {
-       .owner          = THIS_MODULE,
-       .open           = gscd_open,
-       .release        = gscd_release,
-       .ioctl          = gscd_ioctl,
-       .media_changed  = check_gscd_med_chg,
-};
-
-/* 
- * Checking if the media has been changed
- * (not yet implemented)
- */
-static int check_gscd_med_chg(struct gendisk *disk)
-{
-#ifdef GSCD_DEBUG
-       printk("gscd: check_med_change\n");
-#endif
-       return 0;
-}
-
-
-#ifndef MODULE
-/* Using new interface for kernel-parameters */
-
-static int __init gscd_setup(char *str)
-{
-       int ints[2];
-       (void) get_options(str, ARRAY_SIZE(ints), ints);
-
-       if (ints[0] > 0) {
-               gscd_port = ints[1];
-       }
-       return 1;
-}
-
-__setup("gscd=", gscd_setup);
-
-#endif
-
-static int gscd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
-                     unsigned long arg)
-{
-       unsigned char to_do[10];
-       unsigned char dummy;
-
-
-       switch (cmd) {
-       case CDROMSTART:        /* Spin up the drive */
-               /* Don't think we can do this.  Even if we could,
-                * I think the drive times out and stops after a while
-                * anyway.  For now, ignore it.
-                */
-               return 0;
-
-       case CDROMRESUME:       /* keine Ahnung was das ist */
-               return 0;
-
-
-       case CDROMEJECT:
-               cmd_status();
-               to_do[0] = CMD_TRAY_CTL;
-               cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-
-               return 0;
-
-       default:
-               return -EINVAL;
-       }
-
-}
-
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-
-static void gscd_transfer(struct request *req)
-{
-       while (req->nr_sectors > 0 && gscd_bn == req->sector / 4) {
-               long offs = (req->sector & 3) * 512;
-               memcpy(req->buffer, gscd_buf + offs, 512);
-               req->nr_sectors--;
-               req->sector++;
-               req->buffer += 512;
-       }
-}
-
-
-/*
- * I/O request routine called from Linux kernel.
- */
-
-static void do_gscd_request(request_queue_t * q)
-{
-       __do_gscd_request(0);
-}
-
-static void __do_gscd_request(unsigned long dummy)
-{
-       struct request *req;
-       unsigned int block;
-       unsigned int nsect;
-
-repeat:
-       req = elv_next_request(gscd_queue);
-       if (!req)
-               return;
-
-       block = req->sector;
-       nsect = req->nr_sectors;
-
-       if (req->sector == -1)
-               goto out;
-
-       if (rq_data_dir(req) != READ) {
-               printk("GSCD: bad cmd %u\n", rq_data_dir(req));
-               end_request(req, 0);
-               goto repeat;
-       }
-
-       gscd_transfer(req);
-
-       /* if we satisfied the request from the buffer, we're done. */
-
-       if (req->nr_sectors == 0) {
-               end_request(req, 1);
-               goto repeat;
-       }
-#ifdef GSCD_DEBUG
-       printk("GSCD: block %d, nsect %d\n", block, nsect);
-#endif
-       gscd_read_cmd(req);
-out:
-       return;
-}
-
-
-
-/*
- * Check the result of the set-mode command.  On success, send the
- * read-data command.
- */
-
-static void gscd_read_cmd(struct request *req)
-{
-       long block;
-       struct gscd_Play_msf gscdcmd;
-       char cmd[] = { CMD_READ, 0x80, 0, 0, 0, 0, 1 }; /* cmd mode M-S-F secth sectl */
-
-       cmd_status();
-       if (disk_state & (ST_NO_DISK | ST_DOOR_OPEN)) {
-               printk("GSCD: no disk or door open\n");
-               end_request(req, 0);
-       } else {
-               if (disk_state & ST_INVALID) {
-                       printk("GSCD: disk invalid\n");
-                       end_request(req, 0);
-               } else {
-                       gscd_bn = -1;   /* purge our buffer */
-                       block = req->sector / 4;
-                       gscd_hsg2msf(block, &gscdcmd.start);    /* cvt to msf format */
-
-                       cmd[2] = gscdcmd.start.min;
-                       cmd[3] = gscdcmd.start.sec;
-                       cmd[4] = gscdcmd.start.frame;
-
-#ifdef GSCD_DEBUG
-                       printk("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3],
-                              cmd[4]);
-#endif
-                       cmd_out(TYPE_DATA, (char *) &cmd,
-                               (char *) &gscd_buf[0], 1);
-
-                       gscd_bn = req->sector / 4;
-                       gscd_transfer(req);
-                       end_request(req, 1);
-               }
-       }
-       SET_TIMER(__do_gscd_request, 1);
-}
-
-
-/*
- * Open the device special file.  Check that a disk is in.
- */
-
-static int gscd_open(struct inode *ip, struct file *fp)
-{
-       int st;
-
-#ifdef GSCD_DEBUG
-       printk("GSCD: open\n");
-#endif
-
-       if (gscdPresent == 0)
-               return -ENXIO;  /* no hardware */
-
-       get_status();
-       st = disk_state & (ST_NO_DISK | ST_DOOR_OPEN);
-       if (st) {
-               printk("GSCD: no disk or door open\n");
-               return -ENXIO;
-       }
-
-/*     if (updateToc() < 0)
-               return -EIO;
-*/
-
-       return 0;
-}
-
-
-/*
- * On close, we flush all gscd blocks from the buffer cache.
- */
-
-static int gscd_release(struct inode *inode, struct file *file)
-{
-
-#ifdef GSCD_DEBUG
-       printk("GSCD: release\n");
-#endif
-
-       gscd_bn = -1;
-
-       return 0;
-}
-
-
-static int get_status(void)
-{
-       int status;
-
-       cmd_status();
-       status = disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01);
-
-       if (status == (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) {
-               cc_invalidate();
-               return 1;
-       } else {
-               return 0;
-       }
-}
-
-
-static void cc_invalidate(void)
-{
-       drv_num_read = 0xFF;
-       f_dsk_valid = 0xFF;
-       current_drive = 0xFF;
-       f_drv_ok = 0xFF;
-
-       clear_Audio();
-
-}
-
-static void clear_Audio(void)
-{
-
-       f_AudioPlay = 0;
-       f_AudioPause = 0;
-       AudioStart_m = 0;
-       AudioStart_f = 0;
-       AudioEnd_m = 0;
-       AudioEnd_f = 0;
-
-}
-
-/*
- *   waiting ?  
- */
-
-static int wait_drv_ready(void)
-{
-       int found, read;
-
-       do {
-               found = inb(GSCDPORT(0));
-               found &= 0x0f;
-               read = inb(GSCDPORT(0));
-               read &= 0x0f;
-       } while (read != found);
-
-#ifdef GSCD_DEBUG
-       printk("Wait for: %d\n", read);
-#endif
-
-       return read;
-}
-
-static void cc_Ident(char *respons)
-{
-       char to_do[] = { CMD_IDENT, 0, 0 };
-
-       cmd_out(TYPE_INFO, (char *) &to_do, (char *) respons, (int) 0x1E);
-
-}
-
-static void cc_SetSpeed(void)
-{
-       char to_do[] = { CMD_SETSPEED, 0, 0 };
-       char dummy;
-
-       if (speed > 0) {
-               to_do[1] = speed & 0x0F;
-               cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-       }
-}
-
-static void cc_Reset(void)
-{
-       char to_do[] = { CMD_RESET, 0 };
-       char dummy;
-
-       cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-}
-
-static void cmd_status(void)
-{
-       char to_do[] = { CMD_STATUS, 0 };
-       char dummy;
-
-       cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-
-#ifdef GSCD_DEBUG
-       printk("GSCD: Status: %d\n", disk_state);
-#endif
-
-}
-
-static void cmd_out(int cmd_type, char *cmd, char *respo_buf, int respo_count)
-{
-       int result;
-
-
-       result = wait_drv_ready();
-       if (result != drv_mode) {
-               unsigned long test_loops = 0xFFFF;
-               int i, dummy;
-
-               outb(curr_drv_state, GSCDPORT(0));
-
-               /* LOCLOOP_170 */
-               do {
-                       result = wait_drv_ready();
-                       test_loops--;
-               } while ((result != drv_mode) && (test_loops > 0));
-
-               if (result != drv_mode) {
-                       disk_state = ST_x08 | ST_x04 | ST_INVALID;
-                       return;
-               }
-
-               /* ...and waiting */
-               for (i = 1, dummy = 1; i < 0xFFFF; i++) {
-                       dummy *= i;
-               }
-       }
-
-       /* LOC_172 */
-       /* check the unit */
-       /* and wake it up */
-       if (cmd_unit_alive() != 0x08) {
-               /* LOC_174 */
-               /* game over for this unit */
-               disk_state = ST_x08 | ST_x04 | ST_INVALID;
-               return;
-       }
-
-       /* LOC_176 */
-#ifdef GSCD_DEBUG
-       printk("LOC_176 ");
-#endif
-       if (drv_mode == 0x09) {
-               /* magic... */
-               printk("GSCD: magic ...\n");
-               outb(result, GSCDPORT(2));
-       }
-
-       /* write the command to the drive */
-       cmd_write_cmd(cmd);
-
-       /* LOC_178 */
-       for (;;) {
-               result = wait_drv_ready();
-               if (result != drv_mode) {
-                       /* LOC_179 */
-                       if (result == 0x04) {   /* Mode 4 */
-                               /* LOC_205 */
-#ifdef GSCD_DEBUG
-                               printk("LOC_205 ");
-#endif
-                               disk_state = inb(GSCDPORT(2));
-
-                               do {
-                                       result = wait_drv_ready();
-                               } while (result != drv_mode);
-                               return;
-
-                       } else {
-                               if (result == 0x06) {   /* Mode 6 */
-                                       /* LOC_181 */
-#ifdef GSCD_DEBUG
-                                       printk("LOC_181 ");
-#endif
-
-                                       if (cmd_type == TYPE_DATA) {
-                                               /* read data */
-                                               /* LOC_184 */
-                                               if (drv_mode == 9) {
-                                                       /* read the data to the buffer (word) */
-
-                                                       /* (*(cmd+1))?(CD_FRAMESIZE/2):(CD_FRAMESIZE_RAW/2) */
-                                                       cmd_read_w
-                                                           (respo_buf,
-                                                            respo_count,
-                                                            CD_FRAMESIZE /
-                                                            2);
-                                                       return;
-                                               } else {
-                                                       /* read the data to the buffer (byte) */
-
-                                                       /* (*(cmd+1))?(CD_FRAMESIZE):(CD_FRAMESIZE_RAW)    */
-                                                       cmd_read_b
-                                                           (respo_buf,
-                                                            respo_count,
-                                                            CD_FRAMESIZE);
-                                                       return;
-                                               }
-                                       } else {
-                                               /* read the info to the buffer */
-                                               cmd_info_in(respo_buf,
-                                                           respo_count);
-                                               return;
-                                       }
-
-                                       return;
-                               }
-                       }
-
-               } else {
-                       disk_state = ST_x08 | ST_x04 | ST_INVALID;
-                       return;
-               }
-       }                       /* for (;;) */
-
-
-#ifdef GSCD_DEBUG
-       printk("\n");
-#endif
-}
-
-
-static void cmd_write_cmd(char *pstr)
-{
-       int i, j;
-
-       /* LOC_177 */
-#ifdef GSCD_DEBUG
-       printk("LOC_177 ");
-#endif
-
-       /* calculate the number of parameter */
-       j = *pstr & 0x0F;
-
-       /* shift it out */
-       for (i = 0; i < j; i++) {
-               outb(*pstr, GSCDPORT(2));
-               pstr++;
-       }
-}
-
-
-static int cmd_unit_alive(void)
-{
-       int result;
-       unsigned long max_test_loops;
-
-
-       /* LOC_172 */
-#ifdef GSCD_DEBUG
-       printk("LOC_172 ");
-#endif
-
-       outb(curr_drv_state, GSCDPORT(0));
-       max_test_loops = 0xFFFF;
-
-       do {
-               result = wait_drv_ready();
-               max_test_loops--;
-       } while ((result != 0x08) && (max_test_loops > 0));
-
-       return result;
-}
-
-
-static void cmd_info_in(char *pb, int count)
-{
-       int result;
-       char read;
-
-
-       /* read info */
-       /* LOC_182 */
-#ifdef GSCD_DEBUG
-       printk("LOC_182 ");
-#endif
-
-       do {
-               read = inb(GSCDPORT(2));
-               if (count > 0) {
-                       *pb = read;
-                       pb++;
-                       count--;
-               }
-
-               /* LOC_183 */
-               do {
-                       result = wait_drv_ready();
-               } while (result == 0x0E);
-       } while (result == 6);
-
-       cmd_end();
-       return;
-}
-
-
-static void cmd_read_b(char *pb, int count, int size)
-{
-       int result;
-       int i;
-
-
-       /* LOC_188 */
-       /* LOC_189 */
-#ifdef GSCD_DEBUG
-       printk("LOC_189 ");
-#endif
-
-       do {
-               do {
-                       result = wait_drv_ready();
-               } while (result != 6 || result == 0x0E);
-
-               if (result != 6) {
-                       cmd_end();
-                       return;
-               }
-#ifdef GSCD_DEBUG
-               printk("LOC_191 ");
-#endif
-
-               for (i = 0; i < size; i++) {
-                       *pb = inb(GSCDPORT(2));
-                       pb++;
-               }
-               count--;
-       } while (count > 0);
-
-       cmd_end();
-       return;
-}
-
-
-static void cmd_end(void)
-{
-       int result;
-
-
-       /* LOC_204 */
-#ifdef GSCD_DEBUG
-       printk("LOC_204 ");
-#endif
-
-       do {
-               result = wait_drv_ready();
-               if (result == drv_mode) {
-                       return;
-               }
-       } while (result != 4);
-
-       /* LOC_205 */
-#ifdef GSCD_DEBUG
-       printk("LOC_205 ");
-#endif
-
-       disk_state = inb(GSCDPORT(2));
-
-       do {
-               result = wait_drv_ready();
-       } while (result != drv_mode);
-       return;
-
-}
-
-
-static void cmd_read_w(char *pb, int count, int size)
-{
-       int result;
-       int i;
-
-
-#ifdef GSCD_DEBUG
-       printk("LOC_185 ");
-#endif
-
-       do {
-               /* LOC_185 */
-               do {
-                       result = wait_drv_ready();
-               } while (result != 6 || result == 0x0E);
-
-               if (result != 6) {
-                       cmd_end();
-                       return;
-               }
-
-               for (i = 0; i < size; i++) {
-                       /* na, hier muss ich noch mal drueber nachdenken */
-                       *pb = inw(GSCDPORT(2));
-                       pb++;
-               }
-               count--;
-       } while (count > 0);
-
-       cmd_end();
-       return;
-}
-
-static int __init find_drives(void)
-{
-       int *pdrv;
-       int drvnum;
-       int subdrv;
-       int i;
-
-       speed = 0;
-       pdrv = (int *) &drv_states;
-       curr_drv_state = 0xFE;
-       subdrv = 0;
-       drvnum = 0;
-
-       for (i = 0; i < 8; i++) {
-               subdrv++;
-               cmd_status();
-               disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01;
-               if (disk_state != (ST_x08 | ST_x04 | ST_INVALID)) {
-                       /* LOC_240 */
-                       *pdrv = curr_drv_state;
-                       init_cd_drive(drvnum);
-                       pdrv++;
-                       drvnum++;
-               } else {
-                       if (subdrv < 2) {
-                               continue;
-                       } else {
-                               subdrv = 0;
-                       }
-               }
-
-/*       curr_drv_state<<1;         <-- das geht irgendwie nicht */
-/* muss heissen:    curr_drv_state <<= 1; (ist ja Wert-Zuweisung) */
-               curr_drv_state *= 2;
-               curr_drv_state |= 1;
-#ifdef GSCD_DEBUG
-               printk("DriveState: %d\n", curr_drv_state);
-#endif
-       }
-
-       ndrives = drvnum;
-       return drvnum;
-}
-
-static void __init init_cd_drive(int num)
-{
-       char resp[50];
-       int i;
-
-       printk("GSCD: init unit %d\n", num);
-       cc_Ident((char *) &resp);
-
-       printk("GSCD: identification: ");
-       for (i = 0; i < 0x1E; i++) {
-               printk("%c", resp[i]);
-       }
-       printk("\n");
-
-       cc_SetSpeed();
-
-}
-
-#ifdef FUTURE_WORK
-/* return_done */
-static void update_state(void)
-{
-       unsigned int AX;
-
-
-       if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0) {
-               if (disk_state == (ST_x08 | ST_x04 | ST_INVALID)) {
-                       AX = ST_INVALID;
-               }
-
-               if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01))
-                   == 0) {
-                       invalidate();
-                       f_drv_ok = 0;
-               }
-
-               AX |= 0x8000;
-       }
-
-       if (disk_state & ST_PLAYING) {
-               AX |= 0x200;
-       }
-
-       AX |= 0x100;
-       /* pkt_esbx = AX; */
-
-       disk_state = 0;
-
-}
-#endif
-
-static struct gendisk *gscd_disk;
-
-static void __exit gscd_exit(void)
-{
-       CLEAR_TIMER;
-
-       del_gendisk(gscd_disk);
-       put_disk(gscd_disk);
-       if ((unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) {
-               printk("What's that: can't unregister GoldStar-module\n");
-               return;
-       }
-       blk_cleanup_queue(gscd_queue);
-       release_region(gscd_port, GSCD_IO_EXTENT);
-       printk(KERN_INFO "GoldStar-module released.\n");
-}
-
-/* This is the common initialisation for the GoldStar drive. */
-/* It is called at boot time AND for module init.           */
-static int __init gscd_init(void)
-{
-       int i;
-       int result;
-       int ret=0;
-
-       printk(KERN_INFO "GSCD: version %s\n", GSCD_VERSION);
-       printk(KERN_INFO
-              "GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n",
-              gscd_port);
-
-       if (!request_region(gscd_port, GSCD_IO_EXTENT, "gscd")) {
-               printk(KERN_WARNING "GSCD: Init failed, I/O port (%X) already"
-                      " in use.\n", gscd_port);
-               return -EIO;
-       }
-
-
-       /* check for card */
-       result = wait_drv_ready();
-       if (result == 0x09) {
-               printk(KERN_WARNING "GSCD: DMA kann ich noch nicht!\n");
-               ret = -EIO;
-               goto err_out1;
-       }
-
-       if (result == 0x0b) {
-               drv_mode = result;
-               i = find_drives();
-               if (i == 0) {
-                       printk(KERN_WARNING "GSCD: GoldStar CD-ROM Drive is"
-                              " not found.\n");
-                       ret = -EIO;
-                       goto err_out1;
-               }
-       }
-
-       if ((result != 0x0b) && (result != 0x09)) {
-               printk(KERN_WARNING "GSCD: GoldStar Interface Adapter does not "
-                      "exist or H/W error\n");
-               ret = -EIO;
-               goto err_out1;
-       }
-
-       /* reset all drives */
-       i = 0;
-       while (drv_states[i] != 0) {
-               curr_drv_state = drv_states[i];
-               printk(KERN_INFO "GSCD: Reset unit %d ... ", i);
-               cc_Reset();
-               printk("done\n");
-               i++;
-       }
-
-       gscd_disk = alloc_disk(1);
-       if (!gscd_disk)
-               goto err_out1;
-       gscd_disk->major = MAJOR_NR;
-       gscd_disk->first_minor = 0;
-       gscd_disk->fops = &gscd_fops;
-       sprintf(gscd_disk->disk_name, "gscd");
-
-       if (register_blkdev(MAJOR_NR, "gscd")) {
-               ret = -EIO;
-               goto err_out2;
-       }
-
-       gscd_queue = blk_init_queue(do_gscd_request, &gscd_lock);
-       if (!gscd_queue) {
-               ret = -ENOMEM;
-               goto err_out3;
-       }
-
-       disk_state = 0;
-       gscdPresent = 1;
-
-       gscd_disk->queue = gscd_queue;
-       add_disk(gscd_disk);
-
-       printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n");
-       return 0;
-
-err_out3:
-       unregister_blkdev(MAJOR_NR, "gscd");
-err_out2:
-       put_disk(gscd_disk);
-err_out1:
-       release_region(gscd_port, GSCD_IO_EXTENT);
-       return ret;
-}
-
-static void gscd_hsg2msf(long hsg, struct msf *msf)
-{
-       hsg += CD_MSF_OFFSET;
-       msf->min = hsg / (CD_FRAMES * CD_SECS);
-       hsg %= CD_FRAMES * CD_SECS;
-       msf->sec = hsg / CD_FRAMES;
-       msf->frame = hsg % CD_FRAMES;
-
-       gscd_bin2bcd(&msf->min);        /* convert to BCD */
-       gscd_bin2bcd(&msf->sec);
-       gscd_bin2bcd(&msf->frame);
-}
-
-
-static void gscd_bin2bcd(unsigned char *p)
-{
-       int u, t;
-
-       u = *p % 10;
-       t = *p / 10;
-       *p = u | (t << 4);
-}
-
-
-#ifdef FUTURE_WORK
-static long gscd_msf2hsg(struct msf *mp)
-{
-       return gscd_bcd2bin(mp->frame)
-           + gscd_bcd2bin(mp->sec) * CD_FRAMES
-           + gscd_bcd2bin(mp->min) * CD_FRAMES * CD_SECS - CD_MSF_OFFSET;
-}
-
-static int gscd_bcd2bin(unsigned char bcd)
-{
-       return (bcd >> 4) * 10 + (bcd & 0xF);
-}
-#endif
-
-MODULE_AUTHOR("Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>");
-MODULE_LICENSE("GPL");
-module_init(gscd_init);
-module_exit(gscd_exit);
-MODULE_ALIAS_BLOCKDEV_MAJOR(GOLDSTAR_CDROM_MAJOR);
diff --git a/drivers/cdrom/gscd.h b/drivers/cdrom/gscd.h
deleted file mode 100644 (file)
index a41e64b..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Definitions for a GoldStar R420 CD-ROM interface
- *
- *   Copyright (C) 1995  Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>
- *                       Eberhard Moenkeberg <emoenke@gwdg.de>
- *
- *  Published under the GPL.
- *
- */
-
-
-/* The Interface Card default address is 0x340. This will work for most
-   applications. Address selection is accomplished by jumpers PN801-1 to
-   PN801-4 on the GoldStar Interface Card.
-   Appropriate settings are: 0x300, 0x310, 0x320, 0x330, 0x340, 0x350, 0x360
-   0x370, 0x380, 0x390, 0x3A0, 0x3B0, 0x3C0, 0x3D0, 0x3E0, 0x3F0             */
-
-/* insert here the I/O port address and extent */
-#define GSCD_BASE_ADDR         0x340
-#define GSCD_IO_EXTENT          4
-
-
-/************** nothing to set up below here *********************/
-
-/* port access macro */
-#define GSCDPORT(x)            (gscd_port + (x))
-
-/*
- * commands
- * the lower nibble holds the command length
- */
-#define CMD_STATUS     0x01
-#define CMD_READSUBQ   0x02 /* 1: ?, 2: UPC, 5: ? */
-#define CMD_SEEK       0x05 /* read_mode M-S-F */
-#define CMD_READ       0x07 /* read_mode M-S-F nsec_h nsec_l */
-#define CMD_RESET      0x11
-#define CMD_SETMODE    0x15
-#define CMD_PLAY       0x17 /* M-S-F M-S-F */
-#define CMD_LOCK_CTL   0x22 /* 0: unlock, 1: lock */
-#define CMD_IDENT      0x31
-#define CMD_SETSPEED   0x32 /* 0: auto */ /* ??? */
-#define CMD_GETMODE    0x41
-#define CMD_PAUSE      0x51
-#define CMD_READTOC    0x61
-#define CMD_DISKINFO   0x71
-#define CMD_TRAY_CTL   0x81
-
-/*
- * disk_state:
- */
-#define ST_PLAYING     0x80
-#define ST_UNLOCKED    0x40
-#define ST_NO_DISK     0x20
-#define ST_DOOR_OPEN   0x10
-#define ST_x08  0x08
-#define ST_x04 0x04
-#define ST_INVALID     0x02
-#define ST_x01 0x01
-
-/*
- * cmd_type:
- */
-#define TYPE_INFO      0x01
-#define TYPE_DATA      0x02
-
-/*
- * read_mode:
- */
-#define MOD_POLLED     0x80
-#define MOD_x08        0x08
-#define MOD_RAW        0x04
-
-#define READ_DATA(port, buf, nr) insb(port, buf, nr)
-
-#define SET_TIMER(func, jifs) \
-       ((mod_timer(&gscd_timer, jiffies + jifs)), \
-       (gscd_timer.function = func))
-
-#define CLEAR_TIMER            del_timer_sync(&gscd_timer)
-
-#define MAX_TRACKS             104
-
-struct msf {
-       unsigned char   min;
-       unsigned char   sec;
-       unsigned char   frame;
-};
-
-struct gscd_Play_msf {
-       struct msf      start;
-       struct msf      end;
-};
-
-struct gscd_DiskInfo {
-       unsigned char   first;
-       unsigned char   last;
-       struct msf      diskLength;
-       struct msf      firstTrack;
-};
-
-struct gscd_Toc {
-       unsigned char   ctrl_addr;
-       unsigned char   track;
-       unsigned char   pointIndex;
-       struct msf      trackTime;
-       struct msf      diskTime;
-};
-
diff --git a/drivers/cdrom/isp16.c b/drivers/cdrom/isp16.c
deleted file mode 100644 (file)
index db0fd9a..0000000
+++ /dev/null
@@ -1,374 +0,0 @@
-/* -- ISP16 cdrom detection and configuration
- *
- *    Copyright (c) 1995,1996 Eric van der Maarel <H.T.M.v.d.Maarel@marin.nl>
- *
- *    Version 0.6
- *
- *    History:
- *    0.5 First release.
- *        Was included in the sjcd and optcd cdrom drivers.
- *    0.6 First "stand-alone" version.
- *        Removed sound configuration.
- *        Added "module" support.
- *
- *      9 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>
- *
- *     19 June 2004     -- check_region() converted to request_region()
- *                         and return statement cleanups.
- *                          - Jesper Juhl
- *
- *    Detect cdrom interface on ISP16 sound card.
- *    Configure cdrom interface.
- *
- *    Algorithm for the card with OPTi 82C928 taken
- *    from the CDSETUP.SYS driver for MSDOS,
- *    by OPTi Computers, version 2.03.
- *    Algorithm for the card with OPTi 82C929 as communicated
- *    to me by Vadim Model and Leo Spiekman.
- *
- *    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 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define ISP16_VERSION_MAJOR 0
-#define ISP16_VERSION_MINOR 6
-
-#include <linux/module.h>
-
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include "isp16.h"
-
-static short isp16_detect(void);
-static short isp16_c928__detect(void);
-static short isp16_c929__detect(void);
-static short isp16_cdi_config(int base, u_char drive_type, int irq,
-                             int dma);
-static short isp16_type;       /* dependent on type of interface card */
-static u_char isp16_ctrl;
-static u_short isp16_enable_port;
-
-static int isp16_cdrom_base = ISP16_CDROM_IO_BASE;
-static int isp16_cdrom_irq = ISP16_CDROM_IRQ;
-static int isp16_cdrom_dma = ISP16_CDROM_DMA;
-static char *isp16_cdrom_type = ISP16_CDROM_TYPE;
-
-module_param(isp16_cdrom_base, int, 0);
-module_param(isp16_cdrom_irq, int, 0);
-module_param(isp16_cdrom_dma, int, 0);
-module_param(isp16_cdrom_type, charp, 0);
-
-#define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
-#define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
-
-#ifndef MODULE
-
-static int
-__init isp16_setup(char *str)
-{
-       int ints[4];
-
-       (void) get_options(str, ARRAY_SIZE(ints), ints);
-       if (ints[0] > 0)
-               isp16_cdrom_base = ints[1];
-       if (ints[0] > 1)
-               isp16_cdrom_irq = ints[2];
-       if (ints[0] > 2)
-               isp16_cdrom_dma = ints[3];
-       if (str)
-               isp16_cdrom_type = str;
-
-       return 1;
-}
-
-__setup("isp16=", isp16_setup);
-
-#endif                         /* MODULE */
-
-/*
- *  ISP16 initialisation.
- *
- */
-static int __init isp16_init(void)
-{
-       u_char expected_drive;
-
-       printk(KERN_INFO
-              "ISP16: configuration cdrom interface, version %d.%d.\n",
-              ISP16_VERSION_MAJOR, ISP16_VERSION_MINOR);
-
-       if (!strcmp(isp16_cdrom_type, "noisp16")) {
-               printk("ISP16: no cdrom interface configured.\n");
-               return 0;
-       }
-
-       if (!request_region(ISP16_IO_BASE, ISP16_IO_SIZE, "isp16")) {
-               printk("ISP16: i/o ports already in use.\n");
-               goto out;
-       }
-
-       if ((isp16_type = isp16_detect()) < 0) {
-               printk("ISP16: no cdrom interface found.\n");
-               goto cleanup_out;
-       }
-
-       printk(KERN_INFO
-              "ISP16: cdrom interface (with OPTi 82C92%d chip) detected.\n",
-              (isp16_type == 2) ? 9 : 8);
-
-       if (!strcmp(isp16_cdrom_type, "Sanyo"))
-               expected_drive =
-                   (isp16_type ? ISP16_SANYO1 : ISP16_SANYO0);
-       else if (!strcmp(isp16_cdrom_type, "Sony"))
-               expected_drive = ISP16_SONY;
-       else if (!strcmp(isp16_cdrom_type, "Panasonic"))
-               expected_drive =
-                   (isp16_type ? ISP16_PANASONIC1 : ISP16_PANASONIC0);
-       else if (!strcmp(isp16_cdrom_type, "Mitsumi"))
-               expected_drive = ISP16_MITSUMI;
-       else {
-               printk("ISP16: %s not supported by cdrom interface.\n",
-                      isp16_cdrom_type);
-               goto cleanup_out;
-       }
-
-       if (isp16_cdi_config(isp16_cdrom_base, expected_drive,
-                            isp16_cdrom_irq, isp16_cdrom_dma) < 0) {
-               printk
-                   ("ISP16: cdrom interface has not been properly configured.\n");
-               goto cleanup_out;
-       }
-       printk(KERN_INFO
-              "ISP16: cdrom interface set up with io base 0x%03X, irq %d, dma %d,"
-              " type %s.\n", isp16_cdrom_base, isp16_cdrom_irq,
-              isp16_cdrom_dma, isp16_cdrom_type);
-       return 0;
-
-cleanup_out:
-       release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
-out:
-       return -EIO;
-}
-
-static short __init isp16_detect(void)
-{
-
-       if (isp16_c929__detect() >= 0)
-               return 2;
-       else
-               return (isp16_c928__detect());
-}
-
-static short __init isp16_c928__detect(void)
-{
-       u_char ctrl;
-       u_char enable_cdrom;
-       u_char io;
-       short i = -1;
-
-       isp16_ctrl = ISP16_C928__CTRL;
-       isp16_enable_port = ISP16_C928__ENABLE_PORT;
-
-       /* read' and write' are a special read and write, respectively */
-
-       /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */
-       ctrl = ISP16_IN(ISP16_CTRL_PORT) & 0xFC;
-       ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
-       /* read' 3,4 and 5-bit from the cdrom enable port */
-       enable_cdrom = ISP16_IN(ISP16_C928__ENABLE_PORT) & 0x38;
-
-       if (!(enable_cdrom & 0x20)) {   /* 5-bit not set */
-               /* read' last 2 bits of ISP16_IO_SET_PORT */
-               io = ISP16_IN(ISP16_IO_SET_PORT) & 0x03;
-               if (((io & 0x01) << 1) == (io & 0x02)) {        /* bits are the same */
-                       if (io == 0) {  /* ...the same and 0 */
-                               i = 0;
-                               enable_cdrom |= 0x20;
-                       } else {        /* ...the same and 1 *//* my card, first time 'round */
-                               i = 1;
-                               enable_cdrom |= 0x28;
-                       }
-                       ISP16_OUT(ISP16_C928__ENABLE_PORT, enable_cdrom);
-               } else {        /* bits are not the same */
-                       ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-                       return i;       /* -> not detected: possibly incorrect conclusion */
-               }
-       } else if (enable_cdrom == 0x20)
-               i = 0;
-       else if (enable_cdrom == 0x28)  /* my card, already initialised */
-               i = 1;
-
-       ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
-       return i;
-}
-
-static short __init isp16_c929__detect(void)
-{
-       u_char ctrl;
-       u_char tmp;
-
-       isp16_ctrl = ISP16_C929__CTRL;
-       isp16_enable_port = ISP16_C929__ENABLE_PORT;
-
-       /* read' and write' are a special read and write, respectively */
-
-       /* read' ISP16_CTRL_PORT and save */
-       ctrl = ISP16_IN(ISP16_CTRL_PORT);
-
-       /* write' zero to the ctrl port and get response */
-       ISP16_OUT(ISP16_CTRL_PORT, 0);
-       tmp = ISP16_IN(ISP16_CTRL_PORT);
-
-       if (tmp != 2)           /* isp16 with 82C929 not detected */
-               return -1;
-
-       /* restore ctrl port value */
-       ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
-       return 2;
-}
-
-static short __init
-isp16_cdi_config(int base, u_char drive_type, int irq, int dma)
-{
-       u_char base_code;
-       u_char irq_code;
-       u_char dma_code;
-       u_char i;
-
-       if ((drive_type == ISP16_MITSUMI) && (dma != 0))
-               printk("ISP16: Mitsumi cdrom drive has no dma support.\n");
-
-       switch (base) {
-       case 0x340:
-               base_code = ISP16_BASE_340;
-               break;
-       case 0x330:
-               base_code = ISP16_BASE_330;
-               break;
-       case 0x360:
-               base_code = ISP16_BASE_360;
-               break;
-       case 0x320:
-               base_code = ISP16_BASE_320;
-               break;
-       default:
-               printk
-                   ("ISP16: base address 0x%03X not supported by cdrom interface.\n",
-                    base);
-               return -1;
-       }
-       switch (irq) {
-       case 0:
-               irq_code = ISP16_IRQ_X;
-               break;          /* disable irq */
-       case 5:
-               irq_code = ISP16_IRQ_5;
-               printk("ISP16: irq 5 shouldn't be used by cdrom interface,"
-                      " due to possible conflicts with the sound card.\n");
-               break;
-       case 7:
-               irq_code = ISP16_IRQ_7;
-               printk("ISP16: irq 7 shouldn't be used by cdrom interface,"
-                      " due to possible conflicts with the sound card.\n");
-               break;
-       case 3:
-               irq_code = ISP16_IRQ_3;
-               break;
-       case 9:
-               irq_code = ISP16_IRQ_9;
-               break;
-       case 10:
-               irq_code = ISP16_IRQ_10;
-               break;
-       case 11:
-               irq_code = ISP16_IRQ_11;
-               break;
-       default:
-               printk("ISP16: irq %d not supported by cdrom interface.\n",
-                      irq);
-               return -1;
-       }
-       switch (dma) {
-       case 0:
-               dma_code = ISP16_DMA_X;
-               break;          /* disable dma */
-       case 1:
-               printk("ISP16: dma 1 cannot be used by cdrom interface,"
-                      " due to conflict with the sound card.\n");
-               return -1;
-               break;
-       case 3:
-               dma_code = ISP16_DMA_3;
-               break;
-       case 5:
-               dma_code = ISP16_DMA_5;
-               break;
-       case 6:
-               dma_code = ISP16_DMA_6;
-               break;
-       case 7:
-               dma_code = ISP16_DMA_7;
-               break;
-       default:
-               printk("ISP16: dma %d not supported by cdrom interface.\n",
-                      dma);
-               return -1;
-       }
-
-       if (drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
-           drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 &&
-           drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI &&
-           drive_type != ISP16_DRIVE_X) {
-               printk
-                   ("ISP16: drive type (code 0x%02X) not supported by cdrom"
-                    " interface.\n", drive_type);
-               return -1;
-       }
-
-       /* set type of interface */
-       i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK;      /* clear some bits */
-       ISP16_OUT(ISP16_DRIVE_SET_PORT, i | drive_type);
-
-       /* enable cdrom on interface with 82C929 chip */
-       if (isp16_type > 1)
-               ISP16_OUT(isp16_enable_port, ISP16_ENABLE_CDROM);
-
-       /* set base address, irq and dma */
-       i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK;    /* keep some bits */
-       ISP16_OUT(ISP16_IO_SET_PORT, i | base_code | irq_code | dma_code);
-
-       return 0;
-}
-
-static void __exit isp16_exit(void)
-{
-       release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
-       printk(KERN_INFO "ISP16: module released.\n");
-}
-
-module_init(isp16_init);
-module_exit(isp16_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/cdrom/isp16.h b/drivers/cdrom/isp16.h
deleted file mode 100644 (file)
index 5bd22c8..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -- isp16.h
- *
- *  Header for detection and initialisation of cdrom interface (only) on
- *  ISP16 (MAD16, Mozart) sound card.
- *
- *  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 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-/* These are the default values */
-#define ISP16_CDROM_TYPE "Sanyo"
-#define ISP16_CDROM_IO_BASE 0x340
-#define ISP16_CDROM_IRQ 0
-#define ISP16_CDROM_DMA 0
-
-/* Some (Media)Magic */
-/* define types of drive the interface on an ISP16 card may be looking at */
-#define ISP16_DRIVE_X 0x00
-#define ISP16_SONY  0x02
-#define ISP16_PANASONIC0 0x02
-#define ISP16_SANYO0 0x02
-#define ISP16_MITSUMI  0x04
-#define ISP16_PANASONIC1 0x06
-#define ISP16_SANYO1 0x06
-#define ISP16_DRIVE_NOT_USED 0x08  /* not used */
-#define ISP16_DRIVE_SET_MASK 0xF1  /* don't change 0-bit or 4-7-bits*/
-/* ...for port */
-#define ISP16_DRIVE_SET_PORT 0xF8D
-/* set io parameters */
-#define ISP16_BASE_340  0x00
-#define ISP16_BASE_330  0x40
-#define ISP16_BASE_360  0x80
-#define ISP16_BASE_320  0xC0
-#define ISP16_IRQ_X  0x00
-#define ISP16_IRQ_5  0x04  /* shouldn't be used to avoid sound card conflicts */
-#define ISP16_IRQ_7  0x08  /* shouldn't be used to avoid sound card conflicts */
-#define ISP16_IRQ_3  0x0C
-#define ISP16_IRQ_9  0x10
-#define ISP16_IRQ_10  0x14
-#define ISP16_IRQ_11  0x18
-#define ISP16_DMA_X  0x03
-#define ISP16_DMA_3  0x00
-#define ISP16_DMA_5  0x00
-#define ISP16_DMA_6  0x01
-#define ISP16_DMA_7  0x02
-#define ISP16_IO_SET_MASK  0x20  /* don't change 5-bit */
-/* ...for port */
-#define ISP16_IO_SET_PORT  0xF8E
-/* enable the card */
-#define ISP16_C928__ENABLE_PORT  0xF90  /* ISP16 with OPTi 82C928 chip */
-#define ISP16_C929__ENABLE_PORT  0xF91  /* ISP16 with OPTi 82C929 chip */
-#define ISP16_ENABLE_CDROM  0x80  /* seven bit */
-
-/* the magic stuff */
-#define ISP16_CTRL_PORT  0xF8F
-#define ISP16_C928__CTRL  0xE2  /* ISP16 with OPTi 82C928 chip */
-#define ISP16_C929__CTRL  0xE3  /* ISP16 with OPTi 82C929 chip */
-
-#define ISP16_IO_BASE 0xF8D
-#define ISP16_IO_SIZE 5  /* ports used from 0xF8D up to 0xF91 */
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
deleted file mode 100644 (file)
index 972ee9c..0000000
+++ /dev/null
@@ -1,1943 +0,0 @@
-/*
- * The Mitsumi CDROM interface
- * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: 2.14(hs)
- *
- * ... anyway, I'm back again, thanks to Marcin, he adopted
- * large portions of my code (at least the parts containing
- * my main thoughts ...)
- *
- ****************** H E L P *********************************
- * If you ever plan to update your CD ROM drive and perhaps
- * want to sell or simply give away your Mitsumi FX-001[DS]
- * -- Please --
- * mail me (heiko@lotte.sax.de).  When my last drive goes
- * ballistic no more driver support will be available from me!
- *************************************************************
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.  If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Thanks to
- *  The Linux Community at all and ...
- *  Martin Harriss (he wrote the first Mitsumi Driver)
- *  Eberhard Moenkeberg (he gave me much support and the initial kick)
- *  Bernd Huebner, Ruediger Helsch (Unifix-Software GmbH, they
- *      improved the original driver)
- *  Jon Tombs, Bjorn Ekwall (module support)
- *  Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
- *  Gerd Knorr (he lent me his PhotoCD)
- *  Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
- *  Andreas Kies (testing the mysterious hang-ups)
- *  Heiko Eissfeldt (VERIFY_READ/WRITE)
- *  Marcin Dalecki (improved performance, shortened code)
- *  ... somebody forgotten?
- *
- *  9 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>
- */
-
-
-#ifdef RCS
-static const char *mcdx_c_version
-    = "$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $";
-#endif
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <asm/current.h>
-#include <asm/uaccess.h>
-
-#include <linux/major.h>
-#define MAJOR_NR MITSUMI_X_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#include "mcdx.h"
-
-#ifndef HZ
-#error HZ not defined
-#endif
-
-#define xwarn(fmt, args...) printk(KERN_WARNING MCDX " " fmt, ## args)
-
-#if !MCDX_QUIET
-#define xinfo(fmt, args...) printk(KERN_INFO MCDX " " fmt, ## args)
-#else
-#define xinfo(fmt, args...) { ; }
-#endif
-
-#if MCDX_DEBUG
-#define xtrace(lvl, fmt, args...) \
-               { if (lvl > 0) \
-                       { printk(KERN_DEBUG MCDX ":: " fmt, ## args); } }
-#define xdebug(fmt, args...) printk(KERN_DEBUG MCDX ":: " fmt, ## args)
-#else
-#define xtrace(lvl, fmt, args...) { ; }
-#define xdebug(fmt, args...) { ; }
-#endif
-
-/* CONSTANTS *******************************************************/
-
-/* Following are the number of sectors we _request_ from the drive
-   every time an access outside the already requested range is done.
-   The _direct_ size is the number of sectors we're allowed to skip
-   directly (performing a read instead of requesting the new sector
-   needed */
-static const int REQUEST_SIZE = 800;   /* should be less then 255 * 4 */
-static const int DIRECT_SIZE = 400;    /* should be less then REQUEST_SIZE */
-
-enum drivemodes { TOC, DATA, RAW, COOKED };
-enum datamodes { MODE0, MODE1, MODE2 };
-enum resetmodes { SOFT, HARD };
-
-static const int SINGLE = 0x01;                /* single speed drive (FX001S, LU) */
-static const int DOUBLE = 0x02;                /* double speed drive (FX001D, ..? */
-static const int DOOR = 0x04;          /* door locking capability */
-static const int MULTI = 0x08;         /* multi session capability */
-
-static const unsigned char READ1X = 0xc0;
-static const unsigned char READ2X = 0xc1;
-
-
-/* DECLARATIONS ****************************************************/
-struct s_subqcode {
-       unsigned char control;
-       unsigned char tno;
-       unsigned char index;
-       struct cdrom_msf0 tt;
-       struct cdrom_msf0 dt;
-};
-
-struct s_diskinfo {
-       unsigned int n_first;
-       unsigned int n_last;
-       struct cdrom_msf0 msf_leadout;
-       struct cdrom_msf0 msf_first;
-};
-
-struct s_multi {
-       unsigned char multi;
-       struct cdrom_msf0 msf_last;
-};
-
-struct s_version {
-       unsigned char code;
-       unsigned char ver;
-};
-
-/* Per drive/controller stuff **************************************/
-
-struct s_drive_stuff {
-       /* waitqueues */
-       wait_queue_head_t busyq;
-       wait_queue_head_t lockq;
-       wait_queue_head_t sleepq;
-
-       /* flags */
-       volatile int introk;    /* status of last irq operation */
-       volatile int busy;      /* drive performs an operation */
-       volatile int lock;      /* exclusive usage */
-
-       /* cd infos */
-       struct s_diskinfo di;
-       struct s_multi multi;
-       struct s_subqcode *toc; /* first entry of the toc array */
-       struct s_subqcode start;
-       struct s_subqcode stop;
-       int xa;                 /* 1 if xa disk */
-       int audio;              /* 1 if audio disk */
-       int audiostatus;
-
-       /* `buffer' control */
-       volatile int valid;     /* pending, ..., values are valid */
-       volatile int pending;   /* next sector to be read */
-       volatile int low_border;        /* first sector not to be skipped direct */
-       volatile int high_border;       /* first sector `out of area' */
-#ifdef AK2
-       volatile int int_err;
-#endif                         /* AK2 */
-
-       /* adds and odds */
-       unsigned wreg_data;     /* w data */
-       unsigned wreg_reset;    /* w hardware reset */
-       unsigned wreg_hcon;     /* w hardware conf */
-       unsigned wreg_chn;      /* w channel */
-       unsigned rreg_data;     /* r data */
-       unsigned rreg_status;   /* r status */
-
-       int irq;                /* irq used by this drive */
-       int present;            /* drive present and its capabilities */
-       unsigned char readcmd;  /* read cmd depends on single/double speed */
-       unsigned char playcmd;  /* play should always be single speed */
-       unsigned int xxx;       /* set if changed, reset while open */
-       unsigned int yyy;       /* set if changed, reset by media_changed */
-       int users;              /* keeps track of open/close */
-       int lastsector;         /* last block accessible */
-       int status;             /* last operation's error / status */
-       int readerrs;           /* # of blocks read w/o error */
-       struct cdrom_device_info info;
-       struct gendisk *disk;
-};
-
-
-/* Prototypes ******************************************************/
-
-/*     The following prototypes are already declared elsewhere.  They are
-       repeated here to show what's going on.  And to sense, if they're
-       changed elsewhere. */
-
-static int mcdx_init(void);
-
-static int mcdx_block_open(struct inode *inode, struct file *file)
-{
-       struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
-       return cdrom_open(&p->info, inode, file);
-}
-
-static int mcdx_block_release(struct inode *inode, struct file *file)
-{
-       struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
-       return cdrom_release(&p->info, file);
-}
-
-static int mcdx_block_ioctl(struct inode *inode, struct file *file,
-                               unsigned cmd, unsigned long arg)
-{
-       struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
-       return cdrom_ioctl(file, &p->info, inode, cmd, arg);
-}
-
-static int mcdx_block_media_changed(struct gendisk *disk)
-{
-       struct s_drive_stuff *p = disk->private_data;
-       return cdrom_media_changed(&p->info);
-}
-
-static struct block_device_operations mcdx_bdops =
-{
-       .owner          = THIS_MODULE,
-       .open           = mcdx_block_open,
-       .release        = mcdx_block_release,
-       .ioctl          = mcdx_block_ioctl,
-       .media_changed  = mcdx_block_media_changed,
-};
-
-
-/*     Indirect exported functions. These functions are exported by their
-       addresses, such as mcdx_open and mcdx_close in the
-       structure mcdx_dops. */
-
-/* exported by file_ops */
-static int mcdx_open(struct cdrom_device_info *cdi, int purpose);
-static void mcdx_close(struct cdrom_device_info *cdi);
-static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr);
-static int mcdx_tray_move(struct cdrom_device_info *cdi, int position);
-static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock);
-static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
-                           unsigned int cmd, void *arg);
-
-/* misc internal support functions */
-static void log2msf(unsigned int, struct cdrom_msf0 *);
-static unsigned int msf2log(const struct cdrom_msf0 *);
-static unsigned int uint2bcd(unsigned int);
-static unsigned int bcd2uint(unsigned char);
-static unsigned port(int *);
-static int irq(int *);
-static void mcdx_delay(struct s_drive_stuff *, long jifs);
-static int mcdx_transfer(struct s_drive_stuff *, char *buf, int sector,
-                        int nr_sectors);
-static int mcdx_xfer(struct s_drive_stuff *, char *buf, int sector,
-                    int nr_sectors);
-
-static int mcdx_config(struct s_drive_stuff *, int);
-static int mcdx_requestversion(struct s_drive_stuff *, struct s_version *,
-                              int);
-static int mcdx_stop(struct s_drive_stuff *, int);
-static int mcdx_hold(struct s_drive_stuff *, int);
-static int mcdx_reset(struct s_drive_stuff *, enum resetmodes, int);
-static int mcdx_setdrivemode(struct s_drive_stuff *, enum drivemodes, int);
-static int mcdx_setdatamode(struct s_drive_stuff *, enum datamodes, int);
-static int mcdx_requestsubqcode(struct s_drive_stuff *,
-                               struct s_subqcode *, int);
-static int mcdx_requestmultidiskinfo(struct s_drive_stuff *,
-                                    struct s_multi *, int);
-static int mcdx_requesttocdata(struct s_drive_stuff *, struct s_diskinfo *,
-                              int);
-static int mcdx_getstatus(struct s_drive_stuff *, int);
-static int mcdx_getval(struct s_drive_stuff *, int to, int delay, char *);
-static int mcdx_talk(struct s_drive_stuff *,
-                    const unsigned char *cmd, size_t,
-                    void *buffer, size_t size, unsigned int timeout, int);
-static int mcdx_readtoc(struct s_drive_stuff *);
-static int mcdx_playtrk(struct s_drive_stuff *, const struct cdrom_ti *);
-static int mcdx_playmsf(struct s_drive_stuff *, const struct cdrom_msf *);
-static int mcdx_setattentuator(struct s_drive_stuff *,
-                              struct cdrom_volctrl *, int);
-
-/* static variables ************************************************/
-
-static int mcdx_drive_map[][2] = MCDX_DRIVEMAP;
-static struct s_drive_stuff *mcdx_stuffp[MCDX_NDRIVES];
-static DEFINE_SPINLOCK(mcdx_lock);
-static struct request_queue *mcdx_queue;
-
-/* You can only set the first two pairs, from old MODULE_PARM code.  */
-static int mcdx_set(const char *val, struct kernel_param *kp)
-{
-       get_options((char *)val, 4, (int *)mcdx_drive_map);
-       return 0;
-}
-module_param_call(mcdx, mcdx_set, NULL, NULL, 0);
-
-static struct cdrom_device_ops mcdx_dops = {
-       .open           = mcdx_open,
-       .release        = mcdx_close,
-       .media_changed  = mcdx_media_changed,
-       .tray_move      = mcdx_tray_move,
-       .lock_door      = mcdx_lockdoor,
-       .audio_ioctl    = mcdx_audio_ioctl,
-       .capability     = CDC_OPEN_TRAY | CDC_LOCK | CDC_MEDIA_CHANGED |
-                         CDC_PLAY_AUDIO | CDC_DRIVE_STATUS,
-};
-
-/* KERNEL INTERFACE FUNCTIONS **************************************/
-
-
-static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
-                           unsigned int cmd, void *arg)
-{
-       struct s_drive_stuff *stuffp = cdi->handle;
-
-       if (!stuffp->present)
-               return -ENXIO;
-
-       if (stuffp->xxx) {
-               if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
-                       stuffp->lastsector = -1;
-               } else {
-                       stuffp->lastsector = (CD_FRAMESIZE / 512)
-                           * msf2log(&stuffp->di.msf_leadout) - 1;
-               }
-
-               if (stuffp->toc) {
-                       kfree(stuffp->toc);
-                       stuffp->toc = NULL;
-                       if (-1 == mcdx_readtoc(stuffp))
-                               return -1;
-               }
-
-               stuffp->xxx = 0;
-       }
-
-       switch (cmd) {
-       case CDROMSTART:{
-                       xtrace(IOCTL, "ioctl() START\n");
-                       /* Spin up the drive.  Don't think we can do this.
-                          * For now, ignore it.
-                        */
-                       return 0;
-               }
-
-       case CDROMSTOP:{
-                       xtrace(IOCTL, "ioctl() STOP\n");
-                       stuffp->audiostatus = CDROM_AUDIO_INVALID;
-                       if (-1 == mcdx_stop(stuffp, 1))
-                               return -EIO;
-                       return 0;
-               }
-
-       case CDROMPLAYTRKIND:{
-                       struct cdrom_ti *ti = (struct cdrom_ti *) arg;
-
-                       xtrace(IOCTL, "ioctl() PLAYTRKIND\n");
-                       if ((ti->cdti_trk0 < stuffp->di.n_first)
-                           || (ti->cdti_trk0 > stuffp->di.n_last)
-                           || (ti->cdti_trk1 < stuffp->di.n_first))
-                               return -EINVAL;
-                       if (ti->cdti_trk1 > stuffp->di.n_last)
-                               ti->cdti_trk1 = stuffp->di.n_last;
-                       xtrace(PLAYTRK, "ioctl() track %d to %d\n",
-                              ti->cdti_trk0, ti->cdti_trk1);
-                       return mcdx_playtrk(stuffp, ti);
-               }
-
-       case CDROMPLAYMSF:{
-                       struct cdrom_msf *msf = (struct cdrom_msf *) arg;
-
-                       xtrace(IOCTL, "ioctl() PLAYMSF\n");
-
-                       if ((stuffp->audiostatus == CDROM_AUDIO_PLAY)
-                           && (-1 == mcdx_hold(stuffp, 1)))
-                               return -EIO;
-
-                       msf->cdmsf_min0 = uint2bcd(msf->cdmsf_min0);
-                       msf->cdmsf_sec0 = uint2bcd(msf->cdmsf_sec0);
-                       msf->cdmsf_frame0 = uint2bcd(msf->cdmsf_frame0);
-
-                       msf->cdmsf_min1 = uint2bcd(msf->cdmsf_min1);
-                       msf->cdmsf_sec1 = uint2bcd(msf->cdmsf_sec1);
-                       msf->cdmsf_frame1 = uint2bcd(msf->cdmsf_frame1);
-
-                       stuffp->stop.dt.minute = msf->cdmsf_min1;
-                       stuffp->stop.dt.second = msf->cdmsf_sec1;
-                       stuffp->stop.dt.frame = msf->cdmsf_frame1;
-
-                       return mcdx_playmsf(stuffp, msf);
-               }
-
-       case CDROMRESUME:{
-                       xtrace(IOCTL, "ioctl() RESUME\n");
-                       return mcdx_playtrk(stuffp, NULL);
-               }
-
-       case CDROMREADTOCENTRY:{
-                       struct cdrom_tocentry *entry =
-                           (struct cdrom_tocentry *) arg;
-                       struct s_subqcode *tp = NULL;
-                       xtrace(IOCTL, "ioctl() READTOCENTRY\n");
-
-                       if (-1 == mcdx_readtoc(stuffp))
-                               return -1;
-                       if (entry->cdte_track == CDROM_LEADOUT)
-                               tp = &stuffp->toc[stuffp->di.n_last -
-                                                 stuffp->di.n_first + 1];
-                       else if (entry->cdte_track > stuffp->di.n_last
-                                || entry->cdte_track < stuffp->di.n_first)
-                               return -EINVAL;
-                       else
-                               tp = &stuffp->toc[entry->cdte_track -
-                                                 stuffp->di.n_first];
-
-                       if (NULL == tp)
-                               return -EIO;
-                       entry->cdte_adr = tp->control;
-                       entry->cdte_ctrl = tp->control >> 4;
-                       /* Always return stuff in MSF, and let the Uniform cdrom driver
-                          worry about what the user actually wants */
-                       entry->cdte_addr.msf.minute =
-                           bcd2uint(tp->dt.minute);
-                       entry->cdte_addr.msf.second =
-                           bcd2uint(tp->dt.second);
-                       entry->cdte_addr.msf.frame =
-                           bcd2uint(tp->dt.frame);
-                       return 0;
-               }
-
-       case CDROMSUBCHNL:{
-                       struct cdrom_subchnl *sub =
-                           (struct cdrom_subchnl *) arg;
-                       struct s_subqcode q;
-
-                       xtrace(IOCTL, "ioctl() SUBCHNL\n");
-
-                       if (-1 == mcdx_requestsubqcode(stuffp, &q, 2))
-                               return -EIO;
-
-                       xtrace(SUBCHNL, "audiostatus: %x\n",
-                              stuffp->audiostatus);
-                       sub->cdsc_audiostatus = stuffp->audiostatus;
-                       sub->cdsc_adr = q.control;
-                       sub->cdsc_ctrl = q.control >> 4;
-                       sub->cdsc_trk = bcd2uint(q.tno);
-                       sub->cdsc_ind = bcd2uint(q.index);
-
-                       xtrace(SUBCHNL, "trk %d, ind %d\n",
-                              sub->cdsc_trk, sub->cdsc_ind);
-                       /* Always return stuff in MSF, and let the Uniform cdrom driver
-                          worry about what the user actually wants */
-                       sub->cdsc_absaddr.msf.minute =
-                           bcd2uint(q.dt.minute);
-                       sub->cdsc_absaddr.msf.second =
-                           bcd2uint(q.dt.second);
-                       sub->cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame);
-                       sub->cdsc_reladdr.msf.minute =
-                           bcd2uint(q.tt.minute);
-                       sub->cdsc_reladdr.msf.second =
-                           bcd2uint(q.tt.second);
-                       sub->cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame);
-                       xtrace(SUBCHNL,
-                              "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n",
-                              sub->cdsc_absaddr.msf.minute,
-                              sub->cdsc_absaddr.msf.second,
-                              sub->cdsc_absaddr.msf.frame,
-                              sub->cdsc_reladdr.msf.minute,
-                              sub->cdsc_reladdr.msf.second,
-                              sub->cdsc_reladdr.msf.frame);
-
-                       return 0;
-               }
-
-       case CDROMREADTOCHDR:{
-                       struct cdrom_tochdr *toc =
-                           (struct cdrom_tochdr *) arg;
-
-                       xtrace(IOCTL, "ioctl() READTOCHDR\n");
-                       toc->cdth_trk0 = stuffp->di.n_first;
-                       toc->cdth_trk1 = stuffp->di.n_last;
-                       xtrace(TOCHDR,
-                              "ioctl() track0 = %d, track1 = %d\n",
-                              stuffp->di.n_first, stuffp->di.n_last);
-                       return 0;
-               }
-
-       case CDROMPAUSE:{
-                       xtrace(IOCTL, "ioctl() PAUSE\n");
-                       if (stuffp->audiostatus != CDROM_AUDIO_PLAY)
-                               return -EINVAL;
-                       if (-1 == mcdx_stop(stuffp, 1))
-                               return -EIO;
-                       stuffp->audiostatus = CDROM_AUDIO_PAUSED;
-                       if (-1 ==
-                           mcdx_requestsubqcode(stuffp, &stuffp->start,
-                                                1))
-                               return -EIO;
-                       return 0;
-               }
-
-       case CDROMMULTISESSION:{
-                       struct cdrom_multisession *ms =
-                           (struct cdrom_multisession *) arg;
-                       xtrace(IOCTL, "ioctl() MULTISESSION\n");
-                       /* Always return stuff in LBA, and let the Uniform cdrom driver
-                          worry about what the user actually wants */
-                       ms->addr.lba = msf2log(&stuffp->multi.msf_last);
-                       ms->xa_flag = !!stuffp->multi.multi;
-                       xtrace(MS,
-                              "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n",
-                              ms->xa_flag, ms->addr.lba,
-                              stuffp->multi.msf_last.minute,
-                              stuffp->multi.msf_last.second,
-                              stuffp->multi.msf_last.frame);
-
-                       return 0;
-               }
-
-       case CDROMEJECT:{
-                       xtrace(IOCTL, "ioctl() EJECT\n");
-                       if (stuffp->users > 1)
-                               return -EBUSY;
-                       return (mcdx_tray_move(cdi, 1));
-               }
-
-       case CDROMCLOSETRAY:{
-                       xtrace(IOCTL, "ioctl() CDROMCLOSETRAY\n");
-                       return (mcdx_tray_move(cdi, 0));
-               }
-
-       case CDROMVOLCTRL:{
-                       struct cdrom_volctrl *volctrl =
-                           (struct cdrom_volctrl *) arg;
-                       xtrace(IOCTL, "ioctl() VOLCTRL\n");
-
-#if 0                          /* not tested! */
-                       /* adjust for the weirdness of workman (md) */
-                       /* can't test it (hs) */
-                       volctrl.channel2 = volctrl.channel1;
-                       volctrl.channel1 = volctrl.channel3 = 0x00;
-#endif
-                       return mcdx_setattentuator(stuffp, volctrl, 2);
-               }
-
-       default:
-               return -EINVAL;
-       }
-}
-
-static void do_mcdx_request(request_queue_t * q)
-{
-       struct s_drive_stuff *stuffp;
-       struct request *req;
-
-      again:
-
-       req = elv_next_request(q);
-       if (!req)
-               return;
-
-       stuffp = req->rq_disk->private_data;
-
-       if (!stuffp->present) {
-               xwarn("do_request(): bad device: %s\n",req->rq_disk->disk_name);
-               xtrace(REQUEST, "end_request(0): bad device\n");
-               end_request(req, 0);
-               return;
-       }
-
-       if (stuffp->audio) {
-               xwarn("do_request() attempt to read from audio cd\n");
-               xtrace(REQUEST, "end_request(0): read from audio\n");
-               end_request(req, 0);
-               return;
-       }
-
-       xtrace(REQUEST, "do_request() (%lu + %lu)\n",
-              req->sector, req->nr_sectors);
-
-       if (rq_data_dir(req) != READ) {
-               xwarn("do_request(): non-read command to cd!!\n");
-               xtrace(REQUEST, "end_request(0): write\n");
-               end_request(req, 0);
-               return;
-       }
-       else {
-               stuffp->status = 0;
-               while (req->nr_sectors) {
-                       int i;
-
-                       i = mcdx_transfer(stuffp,
-                                         req->buffer,
-                                         req->sector,
-                                         req->nr_sectors);
-
-                       if (i == -1) {
-                               end_request(req, 0);
-                               goto again;
-                       }
-                       req->sector += i;
-                       req->nr_sectors -= i;
-                       req->buffer += (i * 512);
-               }
-               end_request(req, 1);
-               goto again;
-
-               xtrace(REQUEST, "end_request(1)\n");
-               end_request(req, 1);
-       }
-
-       goto again;
-}
-
-static int mcdx_open(struct cdrom_device_info *cdi, int purpose)
-{
-       struct s_drive_stuff *stuffp;
-       xtrace(OPENCLOSE, "open()\n");
-       stuffp = cdi->handle;
-       if (!stuffp->present)
-               return -ENXIO;
-
-       /* Make the modules looking used ... (thanx bjorn).
-        * But we shouldn't forget to decrement the module counter
-        * on error return */
-
-       /* this is only done to test if the drive talks with us */
-       if (-1 == mcdx_getstatus(stuffp, 1))
-               return -EIO;
-
-       if (stuffp->xxx) {
-
-               xtrace(OPENCLOSE, "open() media changed\n");
-               stuffp->audiostatus = CDROM_AUDIO_INVALID;
-               stuffp->readcmd = 0;
-               xtrace(OPENCLOSE, "open() Request multisession info\n");
-               if (-1 ==
-                   mcdx_requestmultidiskinfo(stuffp, &stuffp->multi, 6))
-                       xinfo("No multidiskinfo\n");
-       } else {
-               /* multisession ? */
-               if (!stuffp->multi.multi)
-                       stuffp->multi.msf_last.second = 2;
-
-               xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n",
-                      stuffp->multi.multi,
-                      stuffp->multi.msf_last.minute,
-                      stuffp->multi.msf_last.second,
-                      stuffp->multi.msf_last.frame);
-
-               {;
-               }               /* got multisession information */
-               /* request the disks table of contents (aka diskinfo) */
-               if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
-
-                       stuffp->lastsector = -1;
-
-               } else {
-
-                       stuffp->lastsector = (CD_FRAMESIZE / 512)
-                           * msf2log(&stuffp->di.msf_leadout) - 1;
-
-                       xtrace(OPENCLOSE,
-                              "open() start %d (%02x:%02x.%02x) %d\n",
-                              stuffp->di.n_first,
-                              stuffp->di.msf_first.minute,
-                              stuffp->di.msf_first.second,
-                              stuffp->di.msf_first.frame,
-                              msf2log(&stuffp->di.msf_first));
-                       xtrace(OPENCLOSE,
-                              "open() last %d (%02x:%02x.%02x) %d\n",
-                              stuffp->di.n_last,
-                              stuffp->di.msf_leadout.minute,
-                              stuffp->di.msf_leadout.second,
-                              stuffp->di.msf_leadout.frame,
-                              msf2log(&stuffp->di.msf_leadout));
-               }
-
-               if (stuffp->toc) {
-                       xtrace(MALLOC, "open() free old toc @ %p\n",
-                              stuffp->toc);
-                       kfree(stuffp->toc);
-
-                       stuffp->toc = NULL;
-               }
-
-               xtrace(OPENCLOSE, "open() init irq generation\n");
-               if (-1 == mcdx_config(stuffp, 1))
-                       return -EIO;
-#ifdef FALLBACK
-               /* Set the read speed */
-               xwarn("AAA %x AAA\n", stuffp->readcmd);
-               if (stuffp->readerrs)
-                       stuffp->readcmd = READ1X;
-               else
-                       stuffp->readcmd =
-                           stuffp->present | SINGLE ? READ1X : READ2X;
-               xwarn("XXX %x XXX\n", stuffp->readcmd);
-#else
-               stuffp->readcmd =
-                   stuffp->present | SINGLE ? READ1X : READ2X;
-#endif
-
-               /* try to get the first sector, iff any ... */
-               if (stuffp->lastsector >= 0) {
-                       char buf[512];
-                       int ans;
-                       int tries;
-
-                       stuffp->xa = 0;
-                       stuffp->audio = 0;
-
-                       for (tries = 6; tries; tries--) {
-
-                               stuffp->introk = 1;
-
-                               xtrace(OPENCLOSE, "open() try as %s\n",
-                                      stuffp->xa ? "XA" : "normal");
-                               /* set data mode */
-                               if (-1 == (ans = mcdx_setdatamode(stuffp,
-                                                                 stuffp->
-                                                                 xa ?
-                                                                 MODE2 :
-                                                                 MODE1,
-                                                                 1))) {
-                                       /* return -EIO; */
-                                       stuffp->xa = 0;
-                                       break;
-                               }
-
-                               if ((stuffp->audio = e_audio(ans)))
-                                       break;
-
-                               while (0 ==
-                                      (ans =
-                                       mcdx_transfer(stuffp, buf, 0, 1)));
-
-                               if (ans == 1)
-                                       break;
-                               stuffp->xa = !stuffp->xa;
-                       }
-               }
-               /* xa disks will be read in raw mode, others not */
-               if (-1 == mcdx_setdrivemode(stuffp,
-                                           stuffp->xa ? RAW : COOKED,
-                                           1))
-                       return -EIO;
-               if (stuffp->audio) {
-                       xinfo("open() audio disk found\n");
-               } else if (stuffp->lastsector >= 0) {
-                       xinfo("open() %s%s disk found\n",
-                             stuffp->xa ? "XA / " : "",
-                             stuffp->multi.
-                             multi ? "Multi Session" : "Single Session");
-               }
-       }
-       stuffp->xxx = 0;
-       stuffp->users++;
-       return 0;
-}
-
-static void mcdx_close(struct cdrom_device_info *cdi)
-{
-       struct s_drive_stuff *stuffp;
-
-       xtrace(OPENCLOSE, "close()\n");
-
-       stuffp = cdi->handle;
-
-       --stuffp->users;
-}
-
-static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-/*     Return: 1 if media changed since last call to this function
-                       0 otherwise */
-{
-       struct s_drive_stuff *stuffp;
-
-       xinfo("mcdx_media_changed called for device %s\n", cdi->name);
-
-       stuffp = cdi->handle;
-       mcdx_getstatus(stuffp, 1);
-
-       if (stuffp->yyy == 0)
-               return 0;
-
-       stuffp->yyy = 0;
-       return 1;
-}
-
-#ifndef MODULE
-static int __init mcdx_setup(char *str)
-{
-       int pi[4];
-       (void) get_options(str, ARRAY_SIZE(pi), pi);
-
-       if (pi[0] > 0)
-               mcdx_drive_map[0][0] = pi[1];
-       if (pi[0] > 1)
-               mcdx_drive_map[0][1] = pi[2];
-       return 1;
-}
-
-__setup("mcdx=", mcdx_setup);
-
-#endif
-
-/* DIRTY PART ******************************************************/
-
-static void mcdx_delay(struct s_drive_stuff *stuff, long jifs)
-/* This routine is used for sleeping.
- * A jifs value <0 means NO sleeping,
- *              =0 means minimal sleeping (let the kernel
- *                 run for other processes)
- *              >0 means at least sleep for that amount.
- *     May be we could use a simple count loop w/ jumps to itself, but
- *     I wanna make this independent of cpu speed. [1 jiffy is 1/HZ] sec */
-{
-       if (jifs < 0)
-               return;
-
-       xtrace(SLEEP, "*** delay: sleepq\n");
-       interruptible_sleep_on_timeout(&stuff->sleepq, jifs);
-       xtrace(SLEEP, "delay awoken\n");
-       if (signal_pending(current)) {
-               xtrace(SLEEP, "got signal\n");
-       }
-}
-
-static irqreturn_t mcdx_intr(int irq, void *dev_id)
-{
-       struct s_drive_stuff *stuffp = dev_id;
-       unsigned char b;
-
-#ifdef AK2
-       if (!stuffp->busy && stuffp->pending)
-               stuffp->int_err = 1;
-
-#endif                         /* AK2 */
-       /* get the interrupt status */
-       b = inb(stuffp->rreg_status);
-       stuffp->introk = ~b & MCDX_RBIT_DTEN;
-
-       /* NOTE: We only should get interrupts if the data we
-        * requested are ready to transfer.
-        * But the drive seems to generate ``asynchronous'' interrupts
-        * on several error conditions too.  (Despite the err int enable
-        * setting during initialisation) */
-
-       /* if not ok, read the next byte as the drives status */
-       if (!stuffp->introk) {
-               xtrace(IRQ, "intr() irq %d hw status 0x%02x\n", irq, b);
-               if (~b & MCDX_RBIT_STEN) {
-                       xinfo("intr() irq %d    status 0x%02x\n",
-                             irq, inb(stuffp->rreg_data));
-               } else {
-                       xinfo("intr() irq %d ambiguous hw status\n", irq);
-               }
-       } else {
-               xtrace(IRQ, "irq() irq %d ok, status %02x\n", irq, b);
-       }
-
-       stuffp->busy = 0;
-       wake_up_interruptible(&stuffp->busyq);
-       return IRQ_HANDLED;
-}
-
-
-static int mcdx_talk(struct s_drive_stuff *stuffp,
-         const unsigned char *cmd, size_t cmdlen,
-         void *buffer, size_t size, unsigned int timeout, int tries)
-/* Send a command to the drive, wait for the result.
- * returns -1 on timeout, drive status otherwise
- * If buffer is not zero, the result (length size) is stored there.
- * If buffer is zero the size should be the number of bytes to read
- * from the drive.  These bytes are discarded.
- */
-{
-       int st;
-       char c;
-       int discard;
-
-       /* Somebody wants the data read? */
-       if ((discard = (buffer == NULL)))
-               buffer = &c;
-
-       while (stuffp->lock) {
-               xtrace(SLEEP, "*** talk: lockq\n");
-               interruptible_sleep_on(&stuffp->lockq);
-               xtrace(SLEEP, "talk: awoken\n");
-       }
-
-       stuffp->lock = 1;
-
-       /* An operation other then reading data destroys the
-          * data already requested and remembered in stuffp->request, ... */
-       stuffp->valid = 0;
-
-#if MCDX_DEBUG & TALK
-       {
-               unsigned char i;
-               xtrace(TALK,
-                      "talk() %d / %d tries, res.size %d, command 0x%02x",
-                      tries, timeout, size, (unsigned char) cmd[0]);
-               for (i = 1; i < cmdlen; i++)
-                       xtrace(TALK, " 0x%02x", cmd[i]);
-               xtrace(TALK, "\n");
-       }
-#endif
-
-       /*  give up if all tries are done (bad) or if the status
-        *  st != -1 (good) */
-       for (st = -1; st == -1 && tries; tries--) {
-
-               char *bp = (char *) buffer;
-               size_t sz = size;
-
-               outsb(stuffp->wreg_data, cmd, cmdlen);
-               xtrace(TALK, "talk() command sent\n");
-
-               /* get the status byte */
-               if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
-                       xinfo("talk() %02x timed out (status), %d tr%s left\n",
-                            cmd[0], tries - 1, tries == 2 ? "y" : "ies");
-                       continue;
-               }
-               st = *bp;
-               sz--;
-               if (!discard)
-                       bp++;
-
-               xtrace(TALK, "talk() got status 0x%02x\n", st);
-
-               /* command error? */
-               if (e_cmderr(st)) {
-                       xwarn("command error cmd = %02x %s \n",
-                             cmd[0], cmdlen > 1 ? "..." : "");
-                       st = -1;
-                       continue;
-               }
-
-               /* audio status? */
-               if (stuffp->audiostatus == CDROM_AUDIO_INVALID)
-                       stuffp->audiostatus =
-                           e_audiobusy(st) ? CDROM_AUDIO_PLAY :
-                           CDROM_AUDIO_NO_STATUS;
-               else if (stuffp->audiostatus == CDROM_AUDIO_PLAY
-                        && e_audiobusy(st) == 0)
-                       stuffp->audiostatus = CDROM_AUDIO_COMPLETED;
-
-               /* media change? */
-               if (e_changed(st)) {
-                       xinfo("talk() media changed\n");
-                       stuffp->xxx = stuffp->yyy = 1;
-               }
-
-               /* now actually get the data */
-               while (sz--) {
-                       if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
-                               xinfo("talk() %02x timed out (data), %d tr%s left\n",
-                                    cmd[0], tries - 1,
-                                    tries == 2 ? "y" : "ies");
-                               st = -1;
-                               break;
-                       }
-                       if (!discard)
-                               bp++;
-                       xtrace(TALK, "talk() got 0x%02x\n", *(bp - 1));
-               }
-       }
-
-#if !MCDX_QUIET
-       if (!tries && st == -1)
-               xinfo("talk() giving up\n");
-#endif
-
-       stuffp->lock = 0;
-       wake_up_interruptible(&stuffp->lockq);
-
-       xtrace(TALK, "talk() done with 0x%02x\n", st);
-       return st;
-}
-
-/* MODULE STUFF ***********************************************************/
-
-static int __init __mcdx_init(void)
-{
-       int i;
-       int drives = 0;
-
-       mcdx_init();
-       for (i = 0; i < MCDX_NDRIVES; i++) {
-               if (mcdx_stuffp[i]) {
-                       xtrace(INIT, "init_module() drive %d stuff @ %p\n",
-                              i, mcdx_stuffp[i]);
-                       drives++;
-               }
-       }
-
-       if (!drives)
-               return -EIO;
-
-       return 0;
-}
-
-static void __exit mcdx_exit(void)
-{
-       int i;
-
-       xinfo("cleanup_module called\n");
-
-       for (i = 0; i < MCDX_NDRIVES; i++) {
-               struct s_drive_stuff *stuffp = mcdx_stuffp[i];
-               if (!stuffp)
-                       continue;
-               del_gendisk(stuffp->disk);
-               if (unregister_cdrom(&stuffp->info)) {
-                       printk(KERN_WARNING "Can't unregister cdrom mcdx\n");
-                       continue;
-               }
-               put_disk(stuffp->disk);
-               release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-               free_irq(stuffp->irq, NULL);
-               if (stuffp->toc) {
-                       xtrace(MALLOC, "cleanup_module() free toc @ %p\n",
-                              stuffp->toc);
-                       kfree(stuffp->toc);
-               }
-               xtrace(MALLOC, "cleanup_module() free stuffp @ %p\n",
-                      stuffp);
-               mcdx_stuffp[i] = NULL;
-               kfree(stuffp);
-       }
-
-       if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
-               xwarn("cleanup() unregister_blkdev() failed\n");
-       }
-#if !MCDX_QUIET
-       else
-       xinfo("cleanup() succeeded\n");
-#endif
-       blk_cleanup_queue(mcdx_queue);
-}
-
-#ifdef MODULE
-module_init(__mcdx_init);
-#endif
-module_exit(mcdx_exit);
-
-
-/* Support functions ************************************************/
-
-static int __init mcdx_init_drive(int drive)
-{
-       struct s_version version;
-       struct gendisk *disk;
-       struct s_drive_stuff *stuffp;
-       int size = sizeof(*stuffp);
-       char msg[80];
-
-       xtrace(INIT, "init() try drive %d\n", drive);
-
-       xtrace(INIT, "kmalloc space for stuffpt's\n");
-       xtrace(MALLOC, "init() malloc %d bytes\n", size);
-       if (!(stuffp = kzalloc(size, GFP_KERNEL))) {
-               xwarn("init() malloc failed\n");
-               return 1;
-       }
-
-       disk = alloc_disk(1);
-       if (!disk) {
-               xwarn("init() malloc failed\n");
-               kfree(stuffp);
-               return 1;
-       }
-
-       xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n",
-              sizeof(*stuffp), stuffp);
-
-       /* set default values */
-       stuffp->present = 0;    /* this should be 0 already */
-       stuffp->toc = NULL;     /* this should be NULL already */
-
-       /* setup our irq and i/o addresses */
-       stuffp->irq = irq(mcdx_drive_map[drive]);
-       stuffp->wreg_data = stuffp->rreg_data = port(mcdx_drive_map[drive]);
-       stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1;
-       stuffp->wreg_hcon = stuffp->wreg_reset + 1;
-       stuffp->wreg_chn = stuffp->wreg_hcon + 1;
-
-       init_waitqueue_head(&stuffp->busyq);
-       init_waitqueue_head(&stuffp->lockq);
-       init_waitqueue_head(&stuffp->sleepq);
-
-       /* check if i/o addresses are available */
-       if (!request_region(stuffp->wreg_data, MCDX_IO_SIZE, "mcdx")) {
-               xwarn("0x%03x,%d: Init failed. "
-                     "I/O ports (0x%03x..0x%03x) already in use.\n",
-                     stuffp->wreg_data, stuffp->irq,
-                     stuffp->wreg_data,
-                     stuffp->wreg_data + MCDX_IO_SIZE - 1);
-               xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
-               kfree(stuffp);
-               put_disk(disk);
-               xtrace(INIT, "init() continue at next drive\n");
-               return 0;       /* next drive */
-       }
-
-       xtrace(INIT, "init() i/o port is available at 0x%03x\n"
-              stuffp->wreg_data);
-       xtrace(INIT, "init() hardware reset\n");
-       mcdx_reset(stuffp, HARD, 1);
-
-       xtrace(INIT, "init() get version\n");
-       if (-1 == mcdx_requestversion(stuffp, &version, 4)) {
-               /* failed, next drive */
-               release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-               xwarn("%s=0x%03x,%d: Init failed. Can't get version.\n",
-                     MCDX, stuffp->wreg_data, stuffp->irq);
-               xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
-               kfree(stuffp);
-               put_disk(disk);
-               xtrace(INIT, "init() continue at next drive\n");
-               return 0;
-       }
-
-       switch (version.code) {
-       case 'D':
-               stuffp->readcmd = READ2X;
-               stuffp->present = DOUBLE | DOOR | MULTI;
-               break;
-       case 'F':
-               stuffp->readcmd = READ1X;
-               stuffp->present = SINGLE | DOOR | MULTI;
-               break;
-       case 'M':
-               stuffp->readcmd = READ1X;
-               stuffp->present = SINGLE;
-               break;
-       default:
-               stuffp->present = 0;
-               break;
-       }
-
-       stuffp->playcmd = READ1X;
-
-       if (!stuffp->present) {
-               release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-               xwarn("%s=0x%03x,%d: Init failed. No Mitsumi CD-ROM?.\n",
-                     MCDX, stuffp->wreg_data, stuffp->irq);
-               kfree(stuffp);
-               put_disk(disk);
-               return 0;       /* next drive */
-       }
-
-       xtrace(INIT, "init() register blkdev\n");
-       if (register_blkdev(MAJOR_NR, "mcdx")) {
-               release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-               kfree(stuffp);
-               put_disk(disk);
-               return 1;
-       }
-
-       mcdx_queue = blk_init_queue(do_mcdx_request, &mcdx_lock);
-       if (!mcdx_queue) {
-               unregister_blkdev(MAJOR_NR, "mcdx");
-               release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-               kfree(stuffp);
-               put_disk(disk);
-               return 1;
-       }
-
-       xtrace(INIT, "init() subscribe irq and i/o\n");
-       if (request_irq(stuffp->irq, mcdx_intr, IRQF_DISABLED, "mcdx", stuffp)) {
-               release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-               xwarn("%s=0x%03x,%d: Init failed. Can't get irq (%d).\n",
-                     MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq);
-               stuffp->irq = 0;
-               blk_cleanup_queue(mcdx_queue);
-               kfree(stuffp);
-               put_disk(disk);
-               return 0;
-       }
-
-       xtrace(INIT, "init() get garbage\n");
-       {
-               int i;
-               mcdx_delay(stuffp, HZ / 2);
-               for (i = 100; i; i--)
-                       (void) inb(stuffp->rreg_status);
-       }
-
-
-#ifdef WE_KNOW_WHY
-       /* irq 11 -> channel register */
-       outb(0x50, stuffp->wreg_chn);
-#endif
-
-       xtrace(INIT, "init() set non dma but irq mode\n");
-       mcdx_config(stuffp, 1);
-
-       stuffp->info.ops = &mcdx_dops;
-       stuffp->info.speed = 2;
-       stuffp->info.capacity = 1;
-       stuffp->info.handle = stuffp;
-       sprintf(stuffp->info.name, "mcdx%d", drive);
-       disk->major = MAJOR_NR;
-       disk->first_minor = drive;
-       strcpy(disk->disk_name, stuffp->info.name);
-       disk->fops = &mcdx_bdops;
-       disk->flags = GENHD_FL_CD;
-       stuffp->disk = disk;
-
-       sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%03x, irq %d."
-               " (Firmware version %c %x)\n",
-               stuffp->wreg_data, stuffp->irq, version.code, version.ver);
-       mcdx_stuffp[drive] = stuffp;
-       xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);
-       if (register_cdrom(&stuffp->info) != 0) {
-               printk("Cannot register Mitsumi CD-ROM!\n");
-               free_irq(stuffp->irq, NULL);
-               release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-               kfree(stuffp);
-               put_disk(disk);
-               if (unregister_blkdev(MAJOR_NR, "mcdx") != 0)
-                       xwarn("cleanup() unregister_blkdev() failed\n");
-               blk_cleanup_queue(mcdx_queue);
-               return 2;
-       }
-       disk->private_data = stuffp;
-       disk->queue = mcdx_queue;
-       add_disk(disk);
-       printk(msg);
-       return 0;
-}
-
-static int __init mcdx_init(void)
-{
-       int drive;
-       xwarn("Version 2.14(hs) \n");
-
-       xwarn("$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $\n");
-
-       /* zero the pointer array */
-       for (drive = 0; drive < MCDX_NDRIVES; drive++)
-               mcdx_stuffp[drive] = NULL;
-
-       /* do the initialisation */
-       for (drive = 0; drive < MCDX_NDRIVES; drive++) {
-               switch (mcdx_init_drive(drive)) {
-               case 2:
-                       return -EIO;
-               case 1:
-                       break;
-               }
-       }
-       return 0;
-}
-
-static int mcdx_transfer(struct s_drive_stuff *stuffp,
-             char *p, int sector, int nr_sectors)
-/*     This seems to do the actually transfer.  But it does more.  It
-       keeps track of errors occurred and will (if possible) fall back
-       to single speed on error.
-       Return: -1 on timeout or other error
-                       else status byte (as in stuff->st) */
-{
-       int ans;
-
-       ans = mcdx_xfer(stuffp, p, sector, nr_sectors);
-       return ans;
-#ifdef FALLBACK
-       if (-1 == ans)
-               stuffp->readerrs++;
-       else
-               return ans;
-
-       if (stuffp->readerrs && stuffp->readcmd == READ1X) {
-               xwarn("XXX Already reading 1x -- no chance\n");
-               return -1;
-       }
-
-       xwarn("XXX Fallback to 1x\n");
-
-       stuffp->readcmd = READ1X;
-       return mcdx_transfer(stuffp, p, sector, nr_sectors);
-#endif
-
-}
-
-
-static int mcdx_xfer(struct s_drive_stuff *stuffp,
-                    char *p, int sector, int nr_sectors)
-/*     This does actually the transfer from the drive.
-       Return: -1 on timeout or other error
-                       else status byte (as in stuff->st) */
-{
-       int border;
-       int done = 0;
-       long timeout;
-
-       if (stuffp->audio) {
-               xwarn("Attempt to read from audio CD.\n");
-               return -1;
-       }
-
-       if (!stuffp->readcmd) {
-               xinfo("Can't transfer from missing disk.\n");
-               return -1;
-       }
-
-       while (stuffp->lock) {
-               interruptible_sleep_on(&stuffp->lockq);
-       }
-
-       if (stuffp->valid && (sector >= stuffp->pending)
-           && (sector < stuffp->low_border)) {
-
-               /* All (or at least a part of the sectors requested) seems
-                  * to be already requested, so we don't need to bother the
-                  * drive with new requests ...
-                  * Wait for the drive become idle, but first
-                  * check for possible occurred errors --- the drive
-                  * seems to report them asynchronously */
-
-
-               border = stuffp->high_border < (border =
-                                               sector + nr_sectors)
-                   ? stuffp->high_border : border;
-
-               stuffp->lock = current->pid;
-
-               do {
-
-                       while (stuffp->busy) {
-
-                               timeout =
-                                   interruptible_sleep_on_timeout
-                                   (&stuffp->busyq, 5 * HZ);
-
-                               if (!stuffp->introk) {
-                                       xtrace(XFER,
-                                              "error via interrupt\n");
-                               } else if (!timeout) {
-                                       xtrace(XFER, "timeout\n");
-                               } else if (signal_pending(current)) {
-                                       xtrace(XFER, "signal\n");
-                               } else
-                                       continue;
-
-                               stuffp->lock = 0;
-                               stuffp->busy = 0;
-                               stuffp->valid = 0;
-
-                               wake_up_interruptible(&stuffp->lockq);
-                               xtrace(XFER, "transfer() done (-1)\n");
-                               return -1;
-                       }
-
-                       /* check if we need to set the busy flag (as we
-                        * expect an interrupt */
-                       stuffp->busy = (3 == (stuffp->pending & 3));
-
-                       /* Test if it's the first sector of a block,
-                        * there we have to skip some bytes as we read raw data */
-                       if (stuffp->xa && (0 == (stuffp->pending & 3))) {
-                               const int HEAD =
-                                   CD_FRAMESIZE_RAW - CD_XA_TAIL -
-                                   CD_FRAMESIZE;
-                               insb(stuffp->rreg_data, p, HEAD);
-                       }
-
-                       /* now actually read the data */
-                       insb(stuffp->rreg_data, p, 512);
-
-                       /* test if it's the last sector of a block,
-                        * if so, we have to handle XA special */
-                       if ((3 == (stuffp->pending & 3)) && stuffp->xa) {
-                               char dummy[CD_XA_TAIL];
-                               insb(stuffp->rreg_data, &dummy[0], CD_XA_TAIL);
-                       }
-
-                       if (stuffp->pending == sector) {
-                               p += 512;
-                               done++;
-                               sector++;
-                       }
-               } while (++(stuffp->pending) < border);
-
-               stuffp->lock = 0;
-               wake_up_interruptible(&stuffp->lockq);
-
-       } else {
-
-               /* The requested sector(s) is/are out of the
-                * already requested range, so we have to bother the drive
-                * with a new request. */
-
-               static unsigned char cmd[] = {
-                       0,
-                       0, 0, 0,
-                       0, 0, 0
-               };
-
-               cmd[0] = stuffp->readcmd;
-
-               /* The numbers held in ->pending, ..., should be valid */
-               stuffp->valid = 1;
-               stuffp->pending = sector & ~3;
-
-               /* do some sanity checks */
-               if (stuffp->pending > stuffp->lastsector) {
-                       xwarn
-                           ("transfer() sector %d from nirvana requested.\n",
-                            stuffp->pending);
-                       stuffp->status = MCDX_ST_EOM;
-                       stuffp->valid = 0;
-                       xtrace(XFER, "transfer() done (-1)\n");
-                       return -1;
-               }
-
-               if ((stuffp->low_border = stuffp->pending + DIRECT_SIZE)
-                   > stuffp->lastsector + 1) {
-                       xtrace(XFER, "cut low_border\n");
-                       stuffp->low_border = stuffp->lastsector + 1;
-               }
-               if ((stuffp->high_border = stuffp->pending + REQUEST_SIZE)
-                   > stuffp->lastsector + 1) {
-                       xtrace(XFER, "cut high_border\n");
-                       stuffp->high_border = stuffp->lastsector + 1;
-               }
-
-               {               /* Convert the sector to be requested to MSF format */
-                       struct cdrom_msf0 pending;
-                       log2msf(stuffp->pending / 4, &pending);
-                       cmd[1] = pending.minute;
-                       cmd[2] = pending.second;
-                       cmd[3] = pending.frame;
-               }
-
-               cmd[6] =
-                   (unsigned
-                    char) ((stuffp->high_border - stuffp->pending) / 4);
-               xtrace(XFER, "[%2d]\n", cmd[6]);
-
-               stuffp->busy = 1;
-               /* Now really issue the request command */
-               outsb(stuffp->wreg_data, cmd, sizeof cmd);
-
-       }
-#ifdef AK2
-       if (stuffp->int_err) {
-               stuffp->valid = 0;
-               stuffp->int_err = 0;
-               return -1;
-       }
-#endif                         /* AK2 */
-
-       stuffp->low_border = (stuffp->low_border +=
-                             done) <
-           stuffp->high_border ? stuffp->low_border : stuffp->high_border;
-
-       return done;
-}
-
-
-/*     Access to elements of the mcdx_drive_map members */
-
-static unsigned port(int *ip)
-{
-       return ip[0];
-}
-static int irq(int *ip)
-{
-       return ip[1];
-}
-
-/*     Misc number converters */
-
-static unsigned int bcd2uint(unsigned char c)
-{
-       return (c >> 4) * 10 + (c & 0x0f);
-}
-
-static unsigned int uint2bcd(unsigned int ival)
-{
-       return ((ival / 10) << 4) | (ival % 10);
-}
-
-static void log2msf(unsigned int l, struct cdrom_msf0 *pmsf)
-{
-       l += CD_MSF_OFFSET;
-       pmsf->minute = uint2bcd(l / 4500), l %= 4500;
-       pmsf->second = uint2bcd(l / 75);
-       pmsf->frame = uint2bcd(l % 75);
-}
-
-static unsigned int msf2log(const struct cdrom_msf0 *pmsf)
-{
-       return bcd2uint(pmsf->frame)
-           + bcd2uint(pmsf->second) * 75
-           + bcd2uint(pmsf->minute) * 4500 - CD_MSF_OFFSET;
-}
-
-int mcdx_readtoc(struct s_drive_stuff *stuffp)
-/*  Read the toc entries from the CD,
- *  Return: -1 on failure, else 0 */
-{
-
-       if (stuffp->toc) {
-               xtrace(READTOC, "ioctl() toc already read\n");
-               return 0;
-       }
-
-       xtrace(READTOC, "ioctl() readtoc for %d tracks\n",
-              stuffp->di.n_last - stuffp->di.n_first + 1);
-
-       if (-1 == mcdx_hold(stuffp, 1))
-               return -1;
-
-       xtrace(READTOC, "ioctl() tocmode\n");
-       if (-1 == mcdx_setdrivemode(stuffp, TOC, 1))
-               return -EIO;
-
-       /* all seems to be ok so far ... malloc */
-       {
-               int size;
-               size =
-                   sizeof(struct s_subqcode) * (stuffp->di.n_last -
-                                                stuffp->di.n_first + 2);
-
-               xtrace(MALLOC, "ioctl() malloc %d bytes\n", size);
-               stuffp->toc = kmalloc(size, GFP_KERNEL);
-               if (!stuffp->toc) {
-                       xwarn("Cannot malloc %d bytes for toc\n", size);
-                       mcdx_setdrivemode(stuffp, DATA, 1);
-                       return -EIO;
-               }
-       }
-
-       /* now read actually the index */
-       {
-               int trk;
-               int retries;
-
-               for (trk = 0;
-                    trk < (stuffp->di.n_last - stuffp->di.n_first + 1);
-                    trk++)
-                       stuffp->toc[trk].index = 0;
-
-               for (retries = 300; retries; retries--) {       /* why 300? */
-                       struct s_subqcode q;
-                       unsigned int idx;
-
-                       if (-1 == mcdx_requestsubqcode(stuffp, &q, 1)) {
-                               mcdx_setdrivemode(stuffp, DATA, 1);
-                               return -EIO;
-                       }
-
-                       idx = bcd2uint(q.index);
-
-                       if ((idx > 0)
-                           && (idx <= stuffp->di.n_last)
-                           && (q.tno == 0)
-                           && (stuffp->toc[idx - stuffp->di.n_first].
-                               index == 0)) {
-                               stuffp->toc[idx - stuffp->di.n_first] = q;
-                               xtrace(READTOC,
-                                      "ioctl() toc idx %d (trk %d)\n",
-                                      idx, trk);
-                               trk--;
-                       }
-                       if (trk == 0)
-                               break;
-               }
-               memset(&stuffp->
-                      toc[stuffp->di.n_last - stuffp->di.n_first + 1], 0,
-                      sizeof(stuffp->toc[0]));
-               stuffp->toc[stuffp->di.n_last - stuffp->di.n_first +
-                           1].dt = stuffp->di.msf_leadout;
-       }
-
-       /* unset toc mode */
-       xtrace(READTOC, "ioctl() undo toc mode\n");
-       if (-1 == mcdx_setdrivemode(stuffp, DATA, 2))
-               return -EIO;
-
-#if MCDX_DEBUG && READTOC
-       {
-               int trk;
-               for (trk = 0;
-                    trk < (stuffp->di.n_last - stuffp->di.n_first + 2);
-                    trk++)
-                       xtrace(READTOC, "ioctl() %d readtoc %02x %02x %02x"
-                              "  %02x:%02x.%02x  %02x:%02x.%02x\n",
-                              trk + stuffp->di.n_first,
-                              stuffp->toc[trk].control,
-                              stuffp->toc[trk].tno,
-                              stuffp->toc[trk].index,
-                              stuffp->toc[trk].tt.minute,
-                              stuffp->toc[trk].tt.second,
-                              stuffp->toc[trk].tt.frame,
-                              stuffp->toc[trk].dt.minute,
-                              stuffp->toc[trk].dt.second,
-                              stuffp->toc[trk].dt.frame);
-       }
-#endif
-
-       return 0;
-}
-
-static int
-mcdx_playmsf(struct s_drive_stuff *stuffp, const struct cdrom_msf *msf)
-{
-       unsigned char cmd[7] = {
-               0, 0, 0, 0, 0, 0, 0
-       };
-
-       if (!stuffp->readcmd) {
-               xinfo("Can't play from missing disk.\n");
-               return -1;
-       }
-
-       cmd[0] = stuffp->playcmd;
-
-       cmd[1] = msf->cdmsf_min0;
-       cmd[2] = msf->cdmsf_sec0;
-       cmd[3] = msf->cdmsf_frame0;
-       cmd[4] = msf->cdmsf_min1;
-       cmd[5] = msf->cdmsf_sec1;
-       cmd[6] = msf->cdmsf_frame1;
-
-       xtrace(PLAYMSF, "ioctl(): play %x "
-              "%02x:%02x:%02x -- %02x:%02x:%02x\n",
-              cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]);
-
-       outsb(stuffp->wreg_data, cmd, sizeof cmd);
-
-       if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) {
-               xwarn("playmsf() timeout\n");
-               return -1;
-       }
-
-       stuffp->audiostatus = CDROM_AUDIO_PLAY;
-       return 0;
-}
-
-static int
-mcdx_playtrk(struct s_drive_stuff *stuffp, const struct cdrom_ti *ti)
-{
-       struct s_subqcode *p;
-       struct cdrom_msf msf;
-
-       if (-1 == mcdx_readtoc(stuffp))
-               return -1;
-
-       if (ti)
-               p = &stuffp->toc[ti->cdti_trk0 - stuffp->di.n_first];
-       else
-               p = &stuffp->start;
-
-       msf.cdmsf_min0 = p->dt.minute;
-       msf.cdmsf_sec0 = p->dt.second;
-       msf.cdmsf_frame0 = p->dt.frame;
-
-       if (ti) {
-               p = &stuffp->toc[ti->cdti_trk1 - stuffp->di.n_first + 1];
-               stuffp->stop = *p;
-       } else
-               p = &stuffp->stop;
-
-       msf.cdmsf_min1 = p->dt.minute;
-       msf.cdmsf_sec1 = p->dt.second;
-       msf.cdmsf_frame1 = p->dt.frame;
-
-       return mcdx_playmsf(stuffp, &msf);
-}
-
-
-/* Drive functions ************************************************/
-
-static int mcdx_tray_move(struct cdrom_device_info *cdi, int position)
-{
-       struct s_drive_stuff *stuffp = cdi->handle;
-
-       if (!stuffp->present)
-               return -ENXIO;
-       if (!(stuffp->present & DOOR))
-               return -ENOSYS;
-
-       if (position)           /* 1: eject */
-               return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, 3);
-       else                    /* 0: close */
-               return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, 3);
-       return 1;
-}
-
-static int mcdx_stop(struct s_drive_stuff *stuffp, int tries)
-{
-       return mcdx_talk(stuffp, "\xf0", 1, NULL, 1, 2 * HZ, tries);
-}
-
-static int mcdx_hold(struct s_drive_stuff *stuffp, int tries)
-{
-       return mcdx_talk(stuffp, "\x70", 1, NULL, 1, 2 * HZ, tries);
-}
-
-static int mcdx_requestsubqcode(struct s_drive_stuff *stuffp,
-                    struct s_subqcode *sub, int tries)
-{
-       char buf[11];
-       int ans;
-
-       if (-1 == (ans = mcdx_talk(stuffp, "\x20", 1, buf, sizeof(buf),
-                                  2 * HZ, tries)))
-               return -1;
-       sub->control = buf[1];
-       sub->tno = buf[2];
-       sub->index = buf[3];
-       sub->tt.minute = buf[4];
-       sub->tt.second = buf[5];
-       sub->tt.frame = buf[6];
-       sub->dt.minute = buf[8];
-       sub->dt.second = buf[9];
-       sub->dt.frame = buf[10];
-
-       return ans;
-}
-
-static int mcdx_requestmultidiskinfo(struct s_drive_stuff *stuffp,
-                         struct s_multi *multi, int tries)
-{
-       char buf[5];
-       int ans;
-
-       if (stuffp->present & MULTI) {
-               ans =
-                   mcdx_talk(stuffp, "\x11", 1, buf, sizeof(buf), 2 * HZ,
-                             tries);
-               multi->multi = buf[1];
-               multi->msf_last.minute = buf[2];
-               multi->msf_last.second = buf[3];
-               multi->msf_last.frame = buf[4];
-               return ans;
-       } else {
-               multi->multi = 0;
-               return 0;
-       }
-}
-
-static int mcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info,
-                   int tries)
-{
-       char buf[9];
-       int ans;
-       ans =
-           mcdx_talk(stuffp, "\x10", 1, buf, sizeof(buf), 2 * HZ, tries);
-       if (ans == -1) {
-               info->n_first = 0;
-               info->n_last = 0;
-       } else {
-               info->n_first = bcd2uint(buf[1]);
-               info->n_last = bcd2uint(buf[2]);
-               info->msf_leadout.minute = buf[3];
-               info->msf_leadout.second = buf[4];
-               info->msf_leadout.frame = buf[5];
-               info->msf_first.minute = buf[6];
-               info->msf_first.second = buf[7];
-               info->msf_first.frame = buf[8];
-       }
-       return ans;
-}
-
-static int mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode,
-                 int tries)
-{
-       char cmd[2];
-       int ans;
-
-       xtrace(HW, "setdrivemode() %d\n", mode);
-
-       if (-1 == (ans = mcdx_talk(stuffp, "\xc2", 1, cmd, sizeof(cmd), 5 * HZ, tries)))
-               return -1;
-
-       switch (mode) {
-       case TOC:
-               cmd[1] |= 0x04;
-               break;
-       case DATA:
-               cmd[1] &= ~0x04;
-               break;
-       case RAW:
-               cmd[1] |= 0x40;
-               break;
-       case COOKED:
-               cmd[1] &= ~0x40;
-               break;
-       default:
-               break;
-       }
-       cmd[0] = 0x50;
-       return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode,
-                int tries)
-{
-       unsigned char cmd[2] = { 0xa0 };
-       xtrace(HW, "setdatamode() %d\n", mode);
-       switch (mode) {
-       case MODE0:
-               cmd[1] = 0x00;
-               break;
-       case MODE1:
-               cmd[1] = 0x01;
-               break;
-       case MODE2:
-               cmd[1] = 0x02;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_config(struct s_drive_stuff *stuffp, int tries)
-{
-       char cmd[4];
-
-       xtrace(HW, "config()\n");
-
-       cmd[0] = 0x90;
-
-       cmd[1] = 0x10;          /* irq enable */
-       cmd[2] = 0x05;          /* pre, err irq enable */
-
-       if (-1 == mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries))
-               return -1;
-
-       cmd[1] = 0x02;          /* dma select */
-       cmd[2] = 0x00;          /* no dma */
-
-       return mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries);
-}
-
-static int mcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *ver,
-                   int tries)
-{
-       char buf[3];
-       int ans;
-
-       if (-1 == (ans = mcdx_talk(stuffp, "\xdc",
-                                  1, buf, sizeof(buf), 2 * HZ, tries)))
-               return ans;
-
-       ver->code = buf[1];
-       ver->ver = buf[2];
-
-       return ans;
-}
-
-static int mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries)
-{
-       if (mode == HARD) {
-               outb(0, stuffp->wreg_chn);      /* no dma, no irq -> hardware */
-               outb(0, stuffp->wreg_reset);    /* hw reset */
-               return 0;
-       } else
-               return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock)
-{
-       struct s_drive_stuff *stuffp = cdi->handle;
-       char cmd[2] = { 0xfe };
-
-       if (!(stuffp->present & DOOR))
-               return -ENOSYS;
-       if (stuffp->present & DOOR) {
-               cmd[1] = lock ? 0x01 : 0x00;
-               return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, 3);
-       } else
-               return 0;
-}
-
-static int mcdx_getstatus(struct s_drive_stuff *stuffp, int tries)
-{
-       return mcdx_talk(stuffp, "\x40", 1, NULL, 1, 5 * HZ, tries);
-}
-
-static int
-mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char *buf)
-{
-       unsigned long timeout = to + jiffies;
-       char c;
-
-       if (!buf)
-               buf = &c;
-
-       while (inb(stuffp->rreg_status) & MCDX_RBIT_STEN) {
-               if (time_after(jiffies, timeout))
-                       return -1;
-               mcdx_delay(stuffp, delay);
-       }
-
-       *buf = (unsigned char) inb(stuffp->rreg_data) & 0xff;
-
-       return 0;
-}
-
-static int mcdx_setattentuator(struct s_drive_stuff *stuffp,
-                   struct cdrom_volctrl *vol, int tries)
-{
-       char cmd[5];
-       cmd[0] = 0xae;
-       cmd[1] = vol->channel0;
-       cmd[2] = 0;
-       cmd[3] = vol->channel1;
-       cmd[4] = 0;
-
-       return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 5, 200, tries);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(MITSUMI_X_CDROM_MAJOR);
diff --git a/drivers/cdrom/mcdx.h b/drivers/cdrom/mcdx.h
deleted file mode 100644 (file)
index 83c364a..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Definitions for the Mitsumi CDROM interface
- * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: @VERSION@
- * 
- * 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.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.  If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Thanks to
- *  The Linux Community at all and ...
- *  Martin Harris (he wrote the first Mitsumi Driver)
- *  Eberhard Moenkeberg (he gave me much support and the initial kick)
- *  Bernd Huebner, Ruediger Helsch (Unifix-Software Gmbh, they
- *      improved the original driver)
- *  Jon Tombs, Bjorn Ekwall (module support)
- *  Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
- *  Gerd Knorr (he lent me his PhotoCD)
- *  Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
- *  Andreas Kies (testing the mysterious hang up's)
- *  ... somebody forgotten?
- *  Marcin Dalecki
- *  
- */
-
-/*
- *     The following lines are for user configuration
- *     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *     {0|1} -- 1 if you want the driver detect your drive, may crash and
- *     needs a long time to seek.  The higher the address the longer the
- *     seek.
- *
- *  WARNING: AUTOPROBE doesn't work.
- */
-#define MCDX_AUTOPROBE 0
-
-/*
- *     Drive specific settings according to the jumpers on the controller
- *     board(s).
- *     o       MCDX_NDRIVES  :  number of used entries of the following table
- *     o       MCDX_DRIVEMAP :  table of {i/o base, irq} per controller
- *
- *     NOTE: I didn't get a drive at irq 9(2) working.  Not even alone.
- */
-#if MCDX_AUTOPROBE == 0
-       #define MCDX_NDRIVES 1
-       #define MCDX_DRIVEMAP {         \
-                       {0x300, 11},    \
-                       {0x304, 05},    \
-                       {0x000, 00},    \
-                       {0x000, 00},    \
-                       {0x000, 00},    \
-               }
-#else
-       #error Autoprobing is not implemented yet.
-#endif
-
-#ifndef MCDX_QUIET
-#define MCDX_QUIET   1
-#endif
-
-#ifndef MCDX_DEBUG
-#define MCDX_DEBUG   0
-#endif
-
-/* *** make the following line uncommented, if you're sure,
- * *** all configuration is done */
-/* #define I_WAS_HERE */
-
-/*     The name of the device */
-#define MCDX "mcdx"    
-
-/* Flags for DEBUGGING */
-#define INIT           0
-#define MALLOC                 0
-#define IOCTL          0
-#define PLAYTRK     0
-#define SUBCHNL     0
-#define TOCHDR      0
-#define MS          0
-#define PLAYMSF     0
-#define READTOC     0
-#define OPENCLOSE      0
-#define HW                 0
-#define TALK           0
-#define IRQ            0
-#define XFER           0
-#define REQUEST                0
-#define SLEEP          0
-
-/*     The following addresses are taken from the Mitsumi Reference 
- *  and describe the possible i/o range for the controller.
- */
-#define MCDX_IO_BEGIN  ((char*) 0x300) /* first base of i/o addr */
-#define MCDX_IO_END            ((char*) 0x3fc) /* last base of i/o addr */
-
-/*     Per controller 4 bytes i/o are needed. */
-#define MCDX_IO_SIZE           4
-
-/*
- *     Bits
- */
-
-/* The status byte, returned from every command, set if
- * the description is true */
-#define MCDX_RBIT_OPEN       0x80      /* door is open */
-#define MCDX_RBIT_DISKSET    0x40      /* disk set (recognised) */
-#define MCDX_RBIT_CHANGED    0x20      /* disk was changed */
-#define MCDX_RBIT_CHECK      0x10      /* disk rotates, servo is on */
-#define MCDX_RBIT_AUDIOTR    0x08   /* current track is audio */
-#define MCDX_RBIT_RDERR      0x04      /* read error, refer SENSE KEY */
-#define MCDX_RBIT_AUDIOBS    0x02      /* currently playing audio */
-#define MCDX_RBIT_CMDERR     0x01      /* command, param or format error */
-
-/* The I/O Register holding the h/w status of the drive,
- * can be read at i/o base + 1 */
-#define MCDX_RBIT_DOOR       0x10      /* door is open */
-#define MCDX_RBIT_STEN       0x04      /* if 0, i/o base contains drive status */
-#define MCDX_RBIT_DTEN       0x02      /* if 0, i/o base contains data */
-
-/*
- *     The commands.
- */
-
-#define OPCODE 1               /* offset of opcode */
-#define MCDX_CMD_REQUEST_TOC           1, 0x10
-#define MCDX_CMD_REQUEST_STATUS                1, 0x40 
-#define MCDX_CMD_RESET                         1, 0x60
-#define MCDX_CMD_REQUEST_DRIVE_MODE    1, 0xc2
-#define MCDX_CMD_SET_INTERLEAVE                2, 0xc8, 0
-#define MCDX_CMD_DATAMODE_SET          2, 0xa0, 0
-       #define MCDX_DATAMODE1          0x01
-       #define MCDX_DATAMODE2          0x02
-#define MCDX_CMD_LOCK_DOOR             2, 0xfe, 0
-
-#define READ_AHEAD                     4       /* 8 Sectors (4K) */
-
-/*     Useful macros */
-#define e_door(x)              ((x) & MCDX_RBIT_OPEN)
-#define e_check(x)             (~(x) & MCDX_RBIT_CHECK)
-#define e_notset(x)            (~(x) & MCDX_RBIT_DISKSET)
-#define e_changed(x)   ((x) & MCDX_RBIT_CHANGED)
-#define e_audio(x)             ((x) & MCDX_RBIT_AUDIOTR)
-#define e_audiobusy(x) ((x) & MCDX_RBIT_AUDIOBS)
-#define e_cmderr(x)            ((x) & MCDX_RBIT_CMDERR)
-#define e_readerr(x)   ((x) & MCDX_RBIT_RDERR)
-
-/**    no drive specific */
-#define MCDX_CDBLK     2048    /* 2048 cooked data each blk */
-
-#define MCDX_DATA_TIMEOUT      (HZ/10) /* 0.1 second */
-
-/*
- * Access to the msf array
- */
-#define MSF_MIN                0                       /* minute */
-#define MSF_SEC                1                       /* second */
-#define MSF_FRM                2                       /* frame  */
-
-/*
- * Errors
- */
-#define MCDX_E         1                       /* unspec error */
-#define MCDX_ST_EOM 0x0100             /* end of media */
-#define MCDX_ST_DRV 0x00ff             /* mask to query the drive status */
-
-#ifndef I_WAS_HERE
-#ifndef MODULE
-#warning You have not edited mcdx.h
-#warning Perhaps irq and i/o settings are wrong.
-#endif
-#endif
-
-/* ex:set ts=4 sw=4: */
diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
deleted file mode 100644 (file)
index efd619c..0000000
+++ /dev/null
@@ -1,2105 +0,0 @@
-/*     linux/drivers/cdrom/optcd.c - Optics Storage 8000 AT CDROM driver
-       $Id: optcd.c,v 1.11 1997/01/26 07:13:00 davem Exp $
-
-       Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
-
-
-       Based on Aztech CD268 CDROM driver by Werner Zimmermann and preworks
-       by 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.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, write to the Free Software
-       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-\f
-/*     Revision history
-
-
-       14-5-95         v0.0    Plays sound tracks. No reading of data CDs yet.
-                               Detection of disk change doesn't work.
-       21-5-95         v0.1    First ALPHA version. CD can be mounted. The
-                               device major nr is borrowed from the Aztech
-                               driver. Speed is around 240 kb/s, as measured
-                               with "time dd if=/dev/cdrom of=/dev/null \
-                               bs=2048 count=4096".
-       24-6-95         v0.2    Reworked the #defines for the command codes
-                               and the like, as well as the structure of
-                               the hardware communication protocol, to
-                               reflect the "official" documentation, kindly
-                               supplied by C.K. Tan, Optics Storage Pte. Ltd.
-                               Also tidied up the state machine somewhat.
-       28-6-95         v0.3    Removed the ISP-16 interface code, as this
-                               should go into its own driver. The driver now
-                               has its own major nr.
-                               Disk change detection now seems to work, too.
-                               This version became part of the standard
-                               kernel as of version 1.3.7
-       24-9-95         v0.4    Re-inserted ISP-16 interface code which I
-                               copied from sjcd.c, with a few changes.
-                               Updated README.optcd. Submitted for
-                               inclusion in 1.3.21
-       29-9-95         v0.4a   Fixed bug that prevented compilation as module
-       25-10-95        v0.5    Started multisession code. Implementation
-                               copied from Werner Zimmermann, who copied it
-                               from Heiko Schlittermann's mcdx.
-       17-1-96         v0.6    Multisession works; some cleanup too.
-       18-4-96         v0.7    Increased some timing constants;
-                               thanks to Luke McFarlane. Also tidied up some
-                               printk behaviour. ISP16 initialization
-                               is now handled by a separate driver.
-                               
-       09-11-99                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>
-*/
-\f
-/* Includes */
-
-
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <linux/blkdev.h>
-
-#include <linux/cdrom.h>
-#include "optcd.h"
-
-#include <asm/uaccess.h>
-
-#define MAJOR_NR OPTICS_CDROM_MAJOR
-#define QUEUE (opt_queue)
-#define CURRENT elv_next_request(opt_queue)
-
-\f
-/* Debug support */
-
-
-/* Don't forget to add new debug flags here. */
-#if DEBUG_DRIVE_IF | DEBUG_VFS | DEBUG_CONV | DEBUG_TOC | \
-    DEBUG_BUFFERS | DEBUG_REQUEST | DEBUG_STATE | DEBUG_MULTIS
-#define DEBUG(x) debug x
-static void debug(int debug_this, const char* fmt, ...)
-{
-       char s[1024];
-       va_list args;
-
-       if (!debug_this)
-               return;
-
-       va_start(args, fmt);
-       vsnprintf(s, sizeof(s), fmt, args);
-       printk(KERN_DEBUG "optcd: %s\n", s);
-       va_end(args);
-}
-#else
-#define DEBUG(x)
-#endif
-
-\f
-/* Drive hardware/firmware characteristics
-   Identifiers in accordance with Optics Storage documentation */
-
-
-#define optcd_port optcd                       /* Needed for the modutils. */
-static short optcd_port = OPTCD_PORTBASE;      /* I/O base of drive. */
-module_param(optcd_port, short, 0);
-/* Drive registers, read */
-#define DATA_PORT      optcd_port      /* Read data/status */
-#define STATUS_PORT    optcd_port+1    /* Indicate data/status availability */
-
-/* Drive registers, write */
-#define COMIN_PORT     optcd_port      /* For passing command/parameter */
-#define RESET_PORT     optcd_port+1    /* Write anything and wait 0.5 sec */
-#define HCON_PORT      optcd_port+2    /* Host Xfer Configuration */
-
-
-/* Command completion/status read from DATA register */
-#define ST_DRVERR              0x80
-#define ST_DOOR_OPEN           0x40
-#define ST_MIXEDMODE_DISK      0x20
-#define ST_MODE_BITS           0x1c
-#define ST_M_STOP              0x00
-#define ST_M_READ              0x04
-#define ST_M_AUDIO             0x04
-#define ST_M_PAUSE             0x08
-#define ST_M_INITIAL           0x0c
-#define ST_M_ERROR             0x10
-#define ST_M_OTHERS            0x14
-#define        ST_MODE2TRACK           0x02
-#define        ST_DSK_CHG              0x01
-#define ST_L_LOCK              0x01
-#define ST_CMD_OK              0x00
-#define ST_OP_OK               0x01
-#define ST_PA_OK               0x02
-#define ST_OP_ERROR            0x05
-#define ST_PA_ERROR            0x06
-
-
-/* Error codes (appear as command completion code from DATA register) */
-/* Player related errors */
-#define ERR_ILLCMD     0x11    /* Illegal command to player module */
-#define ERR_ILLPARM    0x12    /* Illegal parameter to player module */
-#define ERR_SLEDGE     0x13
-#define ERR_FOCUS      0x14
-#define ERR_MOTOR      0x15
-#define ERR_RADIAL     0x16
-#define ERR_PLL                0x17    /* PLL lock error */
-#define ERR_SUB_TIM    0x18    /* Subcode timeout error */
-#define ERR_SUB_NF     0x19    /* Subcode not found error */
-#define ERR_TRAY       0x1a
-#define ERR_TOC                0x1b    /* Table of Contents read error */
-#define ERR_JUMP       0x1c
-/* Data errors */
-#define ERR_MODE       0x21
-#define ERR_FORM       0x22
-#define ERR_HEADADDR   0x23    /* Header Address not found */
-#define ERR_CRC                0x24
-#define ERR_ECC                0x25    /* Uncorrectable ECC error */
-#define ERR_CRC_UNC    0x26    /* CRC error and uncorrectable error */
-#define ERR_ILLBSYNC   0x27    /* Illegal block sync error */
-#define ERR_VDST       0x28    /* VDST not found */
-/* Timeout errors */
-#define ERR_READ_TIM   0x31    /* Read timeout error */
-#define ERR_DEC_STP    0x32    /* Decoder stopped */
-#define ERR_DEC_TIM    0x33    /* Decoder interrupt timeout error */
-/* Function abort codes */
-#define ERR_KEY                0x41    /* Key -Detected abort */
-#define ERR_READ_FINISH        0x42    /* Read Finish */
-/* Second Byte diagnostic codes */
-#define ERR_NOBSYNC    0x01    /* No block sync */
-#define ERR_SHORTB     0x02    /* Short block */
-#define ERR_LONGB      0x03    /* Long block */
-#define ERR_SHORTDSP   0x04    /* Short DSP word */
-#define ERR_LONGDSP    0x05    /* Long DSP word */
-
-
-/* Status availability flags read from STATUS register */
-#define FL_EJECT       0x20
-#define FL_WAIT                0x10    /* active low */
-#define FL_EOP         0x08    /* active low */
-#define FL_STEN                0x04    /* Status available when low */
-#define FL_DTEN                0x02    /* Data available when low */
-#define FL_DRQ         0x01    /* active low */
-#define FL_RESET       0xde    /* These bits are high after a reset */
-#define FL_STDT                (FL_STEN|FL_DTEN)
-
-
-/* Transfer mode, written to HCON register */
-#define HCON_DTS       0x08
-#define HCON_SDRQB     0x04
-#define HCON_LOHI      0x02
-#define HCON_DMA16     0x01
-
-
-/* Drive command set, written to COMIN register */
-/* Quick response commands */
-#define COMDRVST       0x20    /* Drive Status Read */
-#define COMERRST       0x21    /* Error Status Read */
-#define COMIOCTLISTAT  0x22    /* Status Read; reset disk changed bit */
-#define COMINITSINGLE  0x28    /* Initialize Single Speed */
-#define COMINITDOUBLE  0x29    /* Initialize Double Speed */
-#define COMUNLOCK      0x30    /* Unlock */
-#define COMLOCK                0x31    /* Lock */
-#define COMLOCKST      0x32    /* Lock/Unlock Status */
-#define COMVERSION     0x40    /* Get Firmware Revision */
-#define COMVOIDREADMODE        0x50    /* Void Data Read Mode */
-/* Read commands */
-#define COMFETCH       0x60    /* Prefetch Data */
-#define COMREAD                0x61    /* Read */
-#define COMREADRAW     0x62    /* Read Raw Data */
-#define COMREADALL     0x63    /* Read All 2646 Bytes */
-/* Player control commands */
-#define COMLEADIN      0x70    /* Seek To Lead-in */
-#define COMSEEK                0x71    /* Seek */
-#define COMPAUSEON     0x80    /* Pause On */
-#define COMPAUSEOFF    0x81    /* Pause Off */
-#define COMSTOP                0x82    /* Stop */
-#define COMOPEN                0x90    /* Open Tray Door */
-#define COMCLOSE       0x91    /* Close Tray Door */
-#define COMPLAY                0xa0    /* Audio Play */
-#define COMPLAY_TNO    0xa2    /* Audio Play By Track Number */
-#define COMSUBQ                0xb0    /* Read Sub-q Code */
-#define COMLOCATION    0xb1    /* Read Head Position */
-/* Audio control commands */
-#define COMCHCTRL      0xc0    /* Audio Channel Control */
-/* Miscellaneous (test) commands */
-#define COMDRVTEST     0xd0    /* Write Test Bytes */
-#define COMTEST                0xd1    /* Diagnostic Test */
-\f
-/* Low level drive interface. Only here we do actual I/O
-   Waiting for status / data available */
-
-
-/* Busy wait until FLAG goes low. Return 0 on timeout. */
-static inline int flag_low(int flag, unsigned long timeout)
-{
-       int flag_high;
-       unsigned long count = 0;
-
-       while ((flag_high = (inb(STATUS_PORT) & flag)))
-               if (++count >= timeout)
-                       break;
-
-       DEBUG((DEBUG_DRIVE_IF, "flag_low 0x%x count %ld%s",
-               flag, count, flag_high ? " timeout" : ""));
-       return !flag_high;
-}
-
-
-/* Timed waiting for status or data */
-static int sleep_timeout;      /* max # of ticks to sleep */
-static DECLARE_WAIT_QUEUE_HEAD(waitq);
-static void sleep_timer(unsigned long data);
-static DEFINE_TIMER(delay_timer, sleep_timer, 0, 0);
-static DEFINE_SPINLOCK(optcd_lock);
-static struct request_queue *opt_queue;
-
-/* Timer routine: wake up when desired flag goes low,
-   or when timeout expires. */
-static void sleep_timer(unsigned long data)
-{
-       int flags = inb(STATUS_PORT) & FL_STDT;
-
-       if (flags == FL_STDT && --sleep_timeout > 0) {
-               mod_timer(&delay_timer, jiffies + HZ/100); /* multi-statement macro */
-       } else
-               wake_up(&waitq);
-}
-
-
-/* Sleep until FLAG goes low. Return 0 on timeout or wrong flag low. */
-static int sleep_flag_low(int flag, unsigned long timeout)
-{
-       int flag_high;
-
-       DEBUG((DEBUG_DRIVE_IF, "sleep_flag_low"));
-
-       sleep_timeout = timeout;
-       flag_high = inb(STATUS_PORT) & flag;
-       if (flag_high && sleep_timeout > 0) {
-               mod_timer(&delay_timer, jiffies + HZ/100);
-               sleep_on(&waitq);
-               flag_high = inb(STATUS_PORT) & flag;
-       }
-
-       DEBUG((DEBUG_DRIVE_IF, "flag 0x%x count %ld%s",
-               flag, timeout, flag_high ? " timeout" : ""));
-       return !flag_high;
-}
-\f
-/* Low level drive interface. Only here we do actual I/O
-   Sending commands and parameters */
-
-
-/* Errors in the command protocol */
-#define ERR_IF_CMD_TIMEOUT     0x100
-#define ERR_IF_ERR_TIMEOUT     0x101
-#define ERR_IF_RESP_TIMEOUT    0x102
-#define ERR_IF_DATA_TIMEOUT    0x103
-#define ERR_IF_NOSTAT          0x104
-
-
-/* Send command code. Return <0 indicates error */
-static int send_cmd(int cmd)
-{
-       unsigned char ack;
-
-       DEBUG((DEBUG_DRIVE_IF, "sending command 0x%02x\n", cmd));
-
-       outb(HCON_DTS, HCON_PORT);      /* Enable Suspend Data Transfer */
-       outb(cmd, COMIN_PORT);          /* Send command code */
-       if (!flag_low(FL_STEN, BUSY_TIMEOUT))   /* Wait for status */
-               return -ERR_IF_CMD_TIMEOUT;
-       ack = inb(DATA_PORT);           /* read command acknowledge */
-       outb(HCON_SDRQB, HCON_PORT);    /* Disable Suspend Data Transfer */
-       return ack==ST_OP_OK ? 0 : -ack;
-}
-
-
-/* Send command parameters. Return <0 indicates error */
-static int send_params(struct cdrom_msf *params)
-{
-       unsigned char ack;
-
-       DEBUG((DEBUG_DRIVE_IF, "sending parameters"
-               " %02x:%02x:%02x"
-               " %02x:%02x:%02x",
-               params->cdmsf_min0,
-               params->cdmsf_sec0,
-               params->cdmsf_frame0,
-               params->cdmsf_min1,
-               params->cdmsf_sec1,
-               params->cdmsf_frame1));
-
-       outb(params->cdmsf_min0, COMIN_PORT);
-       outb(params->cdmsf_sec0, COMIN_PORT);
-       outb(params->cdmsf_frame0, COMIN_PORT);
-       outb(params->cdmsf_min1, COMIN_PORT);
-       outb(params->cdmsf_sec1, COMIN_PORT);
-       outb(params->cdmsf_frame1, COMIN_PORT);
-       if (!flag_low(FL_STEN, BUSY_TIMEOUT))   /* Wait for status */
-               return -ERR_IF_CMD_TIMEOUT;
-       ack = inb(DATA_PORT);           /* read command acknowledge */
-       return ack==ST_PA_OK ? 0 : -ack;
-}
-
-
-/* Send parameters for SEEK command. Return <0 indicates error */
-static int send_seek_params(struct cdrom_msf *params)
-{
-       unsigned char ack;
-
-       DEBUG((DEBUG_DRIVE_IF, "sending seek parameters"
-               " %02x:%02x:%02x",
-               params->cdmsf_min0,
-               params->cdmsf_sec0,
-               params->cdmsf_frame0));
-
-       outb(params->cdmsf_min0, COMIN_PORT);
-       outb(params->cdmsf_sec0, COMIN_PORT);
-       outb(params->cdmsf_frame0, COMIN_PORT);
-       if (!flag_low(FL_STEN, BUSY_TIMEOUT))   /* Wait for status */
-               return -ERR_IF_CMD_TIMEOUT;
-       ack = inb(DATA_PORT);           /* read command acknowledge */
-       return ack==ST_PA_OK ? 0 : -ack;
-}
-
-
-/* Wait for command execution status. Choice between busy waiting
-   and sleeping. Return value <0 indicates timeout. */
-static inline int get_exec_status(int busy_waiting)
-{
-       unsigned char exec_status;
-
-       if (busy_waiting
-           ? !flag_low(FL_STEN, BUSY_TIMEOUT)
-           : !sleep_flag_low(FL_STEN, SLEEP_TIMEOUT))
-               return -ERR_IF_CMD_TIMEOUT;
-
-       exec_status = inb(DATA_PORT);
-       DEBUG((DEBUG_DRIVE_IF, "returned exec status 0x%02x", exec_status));
-       return exec_status;
-}
-
-
-/* Wait busy for extra byte of data that a command returns.
-   Return value <0 indicates timeout. */
-static inline int get_data(int short_timeout)
-{
-       unsigned char data;
-
-       if (!flag_low(FL_STEN, short_timeout ? FAST_TIMEOUT : BUSY_TIMEOUT))
-               return -ERR_IF_DATA_TIMEOUT;
-
-       data = inb(DATA_PORT);
-       DEBUG((DEBUG_DRIVE_IF, "returned data 0x%02x", data));
-       return data;
-}
-
-
-/* Returns 0 if failed */
-static int reset_drive(void)
-{
-       unsigned long count = 0;
-       int flags;
-
-       DEBUG((DEBUG_DRIVE_IF, "reset drive"));
-
-       outb(0, RESET_PORT);
-       while (++count < RESET_WAIT)
-               inb(DATA_PORT);
-
-       count = 0;
-       while ((flags = (inb(STATUS_PORT) & FL_RESET)) != FL_RESET)
-               if (++count >= BUSY_TIMEOUT)
-                       break;
-
-       DEBUG((DEBUG_DRIVE_IF, "reset %s",
-               flags == FL_RESET ? "succeeded" : "failed"));
-
-       if (flags != FL_RESET)
-               return 0;               /* Reset failed */
-       outb(HCON_SDRQB, HCON_PORT);    /* Disable Suspend Data Transfer */
-       return 1;                       /* Reset succeeded */
-}
-
-
-/* Facilities for asynchronous operation */
-
-/* Read status/data availability flags FL_STEN and FL_DTEN */
-static inline int stdt_flags(void)
-{
-       return inb(STATUS_PORT) & FL_STDT;
-}
-
-
-/* Fetch status that has previously been waited for. <0 means not available */
-static inline int fetch_status(void)
-{
-       unsigned char status;
-
-       if (inb(STATUS_PORT) & FL_STEN)
-               return -ERR_IF_NOSTAT;
-
-       status = inb(DATA_PORT);
-       DEBUG((DEBUG_DRIVE_IF, "fetched exec status 0x%02x", status));
-       return status;
-}
-
-
-/* Fetch data that has previously been waited for. */
-static inline void fetch_data(char *buf, int n)
-{
-       insb(DATA_PORT, buf, n);
-       DEBUG((DEBUG_DRIVE_IF, "fetched 0x%x bytes", n));
-}
-
-
-/* Flush status and data fifos */
-static inline void flush_data(void)
-{
-       while ((inb(STATUS_PORT) & FL_STDT) != FL_STDT)
-               inb(DATA_PORT);
-       DEBUG((DEBUG_DRIVE_IF, "flushed fifos"));
-}
-\f
-/* Command protocol */
-
-
-/* Send a simple command and wait for response. Command codes < COMFETCH
-   are quick response commands */
-static inline int exec_cmd(int cmd)
-{
-       int ack = send_cmd(cmd);
-       if (ack < 0)
-               return ack;
-       return get_exec_status(cmd < COMFETCH);
-}
-
-
-/* Send a command with parameters. Don't wait for the response,
- * which consists of data blocks read from the CD. */
-static inline int exec_read_cmd(int cmd, struct cdrom_msf *params)
-{
-       int ack = send_cmd(cmd);
-       if (ack < 0)
-               return ack;
-       return send_params(params);
-}
-
-
-/* Send a seek command with parameters and wait for response */
-static inline int exec_seek_cmd(int cmd, struct cdrom_msf *params)
-{
-       int ack = send_cmd(cmd);
-       if (ack < 0)
-               return ack;
-       ack = send_seek_params(params);
-       if (ack < 0)
-               return ack;
-       return 0;
-}
-
-
-/* Send a command with parameters and wait for response */
-static inline int exec_long_cmd(int cmd, struct cdrom_msf *params)
-{
-       int ack = exec_read_cmd(cmd, params);
-       if (ack < 0)
-               return ack;
-       return get_exec_status(0);
-}
-\f
-/* Address conversion routines */
-
-
-/* Binary to BCD (2 digits) */
-static inline void single_bin2bcd(u_char *p)
-{
-       DEBUG((DEBUG_CONV, "bin2bcd %02d", *p));
-       *p = (*p % 10) | ((*p / 10) << 4);
-}
-
-
-/* Convert entire msf struct */
-static void bin2bcd(struct cdrom_msf *msf)
-{
-       single_bin2bcd(&msf->cdmsf_min0);
-       single_bin2bcd(&msf->cdmsf_sec0);
-       single_bin2bcd(&msf->cdmsf_frame0);
-       single_bin2bcd(&msf->cdmsf_min1);
-       single_bin2bcd(&msf->cdmsf_sec1);
-       single_bin2bcd(&msf->cdmsf_frame1);
-}
-
-
-/* Linear block address to minute, second, frame form */
-#define CD_FPM (CD_SECS * CD_FRAMES)   /* frames per minute */
-
-static void lba2msf(int lba, struct cdrom_msf *msf)
-{
-       DEBUG((DEBUG_CONV, "lba2msf %d", lba));
-       lba += CD_MSF_OFFSET;
-       msf->cdmsf_min0 = lba / CD_FPM; lba %= CD_FPM;
-       msf->cdmsf_sec0 = lba / CD_FRAMES;
-       msf->cdmsf_frame0 = lba % CD_FRAMES;
-       msf->cdmsf_min1 = 0;
-       msf->cdmsf_sec1 = 0;
-       msf->cdmsf_frame1 = 0;
-       bin2bcd(msf);
-}
-
-
-/* Two BCD digits to binary */
-static inline u_char bcd2bin(u_char bcd)
-{
-       DEBUG((DEBUG_CONV, "bcd2bin %x%02x", bcd));
-       return (bcd >> 4) * 10 + (bcd & 0x0f);
-}
-
-
-static void msf2lba(union cdrom_addr *addr)
-{
-       addr->lba = addr->msf.minute * CD_FPM
-                   + addr->msf.second * CD_FRAMES
-                   + addr->msf.frame - CD_MSF_OFFSET;
-}
-
-
-/* Minute, second, frame address BCD to binary or to linear address,
-   depending on MODE */
-static void msf_bcd2bin(union cdrom_addr *addr)
-{
-       addr->msf.minute = bcd2bin(addr->msf.minute);
-       addr->msf.second = bcd2bin(addr->msf.second);
-       addr->msf.frame = bcd2bin(addr->msf.frame);
-}
-\f
-/* High level drive commands */
-
-
-static int audio_status = CDROM_AUDIO_NO_STATUS;
-static char toc_uptodate = 0;
-static char disk_changed = 1;
-
-/* Get drive status, flagging completion of audio play and disk changes. */
-static int drive_status(void)
-{
-       int status;
-
-       status = exec_cmd(COMIOCTLISTAT);
-       DEBUG((DEBUG_DRIVE_IF, "IOCTLISTAT: %03x", status));
-       if (status < 0)
-               return status;
-       if (status == 0xff)     /* No status available */
-               return -ERR_IF_NOSTAT;
-
-       if (((status & ST_MODE_BITS) != ST_M_AUDIO) &&
-               (audio_status == CDROM_AUDIO_PLAY)) {
-               audio_status = CDROM_AUDIO_COMPLETED;
-       }
-
-       if (status & ST_DSK_CHG) {
-               toc_uptodate = 0;
-               disk_changed = 1;
-               audio_status = CDROM_AUDIO_NO_STATUS;
-       }
-
-       return status;
-}
-
-
-/* Read the current Q-channel info. Also used for reading the
-   table of contents. qp->cdsc_format must be set on entry to
-   indicate the desired address format */
-static int get_q_channel(struct cdrom_subchnl *qp)
-{
-       int status, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10;
-
-       status = drive_status();
-       if (status < 0)
-               return status;
-       qp->cdsc_audiostatus = audio_status;
-
-       status = exec_cmd(COMSUBQ);
-       if (status < 0)
-               return status;
-
-       d1 = get_data(0);
-       if (d1 < 0)
-               return d1;
-       qp->cdsc_adr = d1;
-       qp->cdsc_ctrl = d1 >> 4;
-
-       d2 = get_data(0);
-       if (d2 < 0)
-               return d2;
-       qp->cdsc_trk = bcd2bin(d2);
-
-       d3 = get_data(0);
-       if (d3 < 0)
-               return d3;
-       qp->cdsc_ind = bcd2bin(d3);
-
-       d4 = get_data(0);
-       if (d4 < 0)
-               return d4;
-       qp->cdsc_reladdr.msf.minute = d4;
-
-       d5 = get_data(0);
-       if (d5 < 0)
-               return d5;
-       qp->cdsc_reladdr.msf.second = d5;
-
-       d6 = get_data(0);
-       if (d6 < 0)
-               return d6;
-       qp->cdsc_reladdr.msf.frame = d6;
-
-       d7 = get_data(0);
-       if (d7 < 0)
-               return d7;
-       /* byte not used */
-
-       d8 = get_data(0);
-       if (d8 < 0)
-               return d8;
-       qp->cdsc_absaddr.msf.minute = d8;
-
-       d9 = get_data(0);
-       if (d9 < 0)
-               return d9;
-       qp->cdsc_absaddr.msf.second = d9;
-
-       d10 = get_data(0);
-       if (d10 < 0)
-               return d10;
-       qp->cdsc_absaddr.msf.frame = d10;
-
-       DEBUG((DEBUG_TOC, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
-               d1, d2, d3, d4, d5, d6, d7, d8, d9, d10));
-
-       msf_bcd2bin(&qp->cdsc_absaddr);
-       msf_bcd2bin(&qp->cdsc_reladdr);
-       if (qp->cdsc_format == CDROM_LBA) {
-               msf2lba(&qp->cdsc_absaddr);
-               msf2lba(&qp->cdsc_reladdr);
-       }
-
-       return 0;
-}
-\f
-/* Table of contents handling */
-
-
-/* Errors in table of contents */
-#define ERR_TOC_MISSINGINFO    0x120
-#define ERR_TOC_MISSINGENTRY   0x121
-
-
-struct cdrom_disk_info {
-       unsigned char           first;
-       unsigned char           last;
-       struct cdrom_msf0       disk_length;
-       struct cdrom_msf0       first_track;
-       /* Multisession info: */
-       unsigned char           next;
-       struct cdrom_msf0       next_session;
-       struct cdrom_msf0       last_session;
-       unsigned char           multi;
-       unsigned char           xa;
-       unsigned char           audio;
-};
-static struct cdrom_disk_info disk_info;
-
-#define MAX_TRACKS             111
-static struct cdrom_subchnl toc[MAX_TRACKS];
-
-#define QINFO_FIRSTTRACK       100 /* bcd2bin(0xa0) */
-#define QINFO_LASTTRACK                101 /* bcd2bin(0xa1) */
-#define QINFO_DISKLENGTH       102 /* bcd2bin(0xa2) */
-#define QINFO_NEXTSESSION      110 /* bcd2bin(0xb0) */
-
-#define I_FIRSTTRACK   0x01
-#define I_LASTTRACK    0x02
-#define I_DISKLENGTH   0x04
-#define I_NEXTSESSION  0x08
-#define I_ALL  (I_FIRSTTRACK | I_LASTTRACK | I_DISKLENGTH)
-
-
-#if DEBUG_TOC
-static void toc_debug_info(int i)
-{
-       printk(KERN_DEBUG "#%3d ctl %1x, adr %1x, track %2d index %3d"
-               "  %2d:%02d.%02d %2d:%02d.%02d\n",
-               i, toc[i].cdsc_ctrl, toc[i].cdsc_adr,
-               toc[i].cdsc_trk, toc[i].cdsc_ind,
-               toc[i].cdsc_reladdr.msf.minute,
-               toc[i].cdsc_reladdr.msf.second,
-               toc[i].cdsc_reladdr.msf.frame,
-               toc[i].cdsc_absaddr.msf.minute,
-               toc[i].cdsc_absaddr.msf.second,
-               toc[i].cdsc_absaddr.msf.frame);
-}
-#endif
-
-
-static int read_toc(void)
-{
-       int status, limit, count;
-       unsigned char got_info = 0;
-       struct cdrom_subchnl q_info;
-#if DEBUG_TOC
-       int i;
-#endif
-
-       DEBUG((DEBUG_TOC, "starting read_toc"));
-
-       count = 0;
-       for (limit = 60; limit > 0; limit--) {
-               int index;
-
-               q_info.cdsc_format = CDROM_MSF;
-               status = get_q_channel(&q_info);
-               if (status < 0)
-                       return status;
-
-               index = q_info.cdsc_ind;
-               if (index > 0 && index < MAX_TRACKS
-                   && q_info.cdsc_trk == 0 && toc[index].cdsc_ind == 0) {
-                       toc[index] = q_info;
-                       DEBUG((DEBUG_TOC, "got %d", index));
-                       if (index < 100)
-                               count++;
-
-                       switch (q_info.cdsc_ind) {
-                       case QINFO_FIRSTTRACK:
-                               got_info |= I_FIRSTTRACK;
-                               break;
-                       case QINFO_LASTTRACK:
-                               got_info |= I_LASTTRACK;
-                               break;
-                       case QINFO_DISKLENGTH:
-                               got_info |= I_DISKLENGTH;
-                               break;
-                       case QINFO_NEXTSESSION:
-                               got_info |= I_NEXTSESSION;
-                               break;
-                       }
-               }
-
-               if ((got_info & I_ALL) == I_ALL
-                   && toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
-                      >= toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
-                       break;
-       }
-
-       /* Construct disk_info from TOC */
-       if (disk_info.first == 0) {
-               disk_info.first = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
-               disk_info.first_track.minute =
-                       toc[disk_info.first].cdsc_absaddr.msf.minute;
-               disk_info.first_track.second =
-                       toc[disk_info.first].cdsc_absaddr.msf.second;
-               disk_info.first_track.frame =
-                       toc[disk_info.first].cdsc_absaddr.msf.frame;
-       }
-       disk_info.last = toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute;
-       disk_info.disk_length.minute =
-                       toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.minute;
-       disk_info.disk_length.second =
-                       toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.second-2;
-       disk_info.disk_length.frame =
-                       toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.frame;
-       disk_info.next_session.minute =
-                       toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.minute;
-       disk_info.next_session.second =
-                       toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.second;
-       disk_info.next_session.frame =
-                       toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.frame;
-       disk_info.next = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
-       disk_info.last_session.minute =
-                       toc[disk_info.next].cdsc_absaddr.msf.minute;
-       disk_info.last_session.second =
-                       toc[disk_info.next].cdsc_absaddr.msf.second;
-       disk_info.last_session.frame =
-                       toc[disk_info.next].cdsc_absaddr.msf.frame;
-       toc[disk_info.last + 1].cdsc_absaddr.msf.minute =
-                       disk_info.disk_length.minute;
-       toc[disk_info.last + 1].cdsc_absaddr.msf.second =
-                       disk_info.disk_length.second;
-       toc[disk_info.last + 1].cdsc_absaddr.msf.frame =
-                       disk_info.disk_length.frame;
-#if DEBUG_TOC
-       for (i = 1; i <= disk_info.last + 1; i++)
-               toc_debug_info(i);
-       toc_debug_info(QINFO_FIRSTTRACK);
-       toc_debug_info(QINFO_LASTTRACK);
-       toc_debug_info(QINFO_DISKLENGTH);
-       toc_debug_info(QINFO_NEXTSESSION);
-#endif
-
-       DEBUG((DEBUG_TOC, "exiting read_toc, got_info %x, count %d",
-               got_info, count));
-       if ((got_info & I_ALL) != I_ALL
-           || toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
-              < toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
-               return -ERR_TOC_MISSINGINFO;
-       return 0;
-}
-
-
-#ifdef MULTISESSION
-static int get_multi_disk_info(void)
-{
-       int sessions, status;
-       struct cdrom_msf multi_index;
-
-
-       for (sessions = 2; sessions < 10 /* %%for now */; sessions++) {
-               int count;
-
-               for (count = 100; count < MAX_TRACKS; count++) 
-                       toc[count].cdsc_ind = 0;
-
-               multi_index.cdmsf_min0 = disk_info.next_session.minute;
-               multi_index.cdmsf_sec0 = disk_info.next_session.second;
-               multi_index.cdmsf_frame0 = disk_info.next_session.frame;
-               if (multi_index.cdmsf_sec0 >= 20)
-                       multi_index.cdmsf_sec0 -= 20;
-               else {
-                       multi_index.cdmsf_sec0 += 40;
-                       multi_index.cdmsf_min0--;
-               }
-               DEBUG((DEBUG_MULTIS, "Try %d: %2d:%02d.%02d", sessions,
-                       multi_index.cdmsf_min0,
-                       multi_index.cdmsf_sec0,
-                       multi_index.cdmsf_frame0));
-               bin2bcd(&multi_index);
-               multi_index.cdmsf_min1 = 0;
-               multi_index.cdmsf_sec1 = 0;
-               multi_index.cdmsf_frame1 = 1;
-
-               status = exec_read_cmd(COMREAD, &multi_index);
-               if (status < 0) {
-                       DEBUG((DEBUG_TOC, "exec_read_cmd COMREAD: %02x",
-                               -status));
-                       break;
-               }
-               status = sleep_flag_low(FL_DTEN, MULTI_SEEK_TIMEOUT) ?
-                               0 : -ERR_TOC_MISSINGINFO;
-               flush_data();
-               if (status < 0) {
-                       DEBUG((DEBUG_TOC, "sleep_flag_low: %02x", -status));
-                       break;
-               }
-
-               status = read_toc();
-               if (status < 0) {
-                       DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
-                       break;
-               }
-
-               disk_info.multi = 1;
-       }
-
-       exec_cmd(COMSTOP);
-
-       if (status < 0)
-               return -EIO;
-       return 0;
-}
-#endif /* MULTISESSION */
-
-
-static int update_toc(void)
-{
-       int status, count;
-
-       if (toc_uptodate)
-               return 0;
-
-       DEBUG((DEBUG_TOC, "starting update_toc"));
-
-       disk_info.first = 0;
-       for (count = 0; count < MAX_TRACKS; count++) 
-               toc[count].cdsc_ind = 0;
-
-       status = exec_cmd(COMLEADIN);
-       if (status < 0)
-               return -EIO;
-
-       status = read_toc();
-       if (status < 0) {
-               DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
-               return -EIO;
-       }
-
-        /* Audio disk detection. Look at first track. */
-       disk_info.audio =
-               (toc[disk_info.first].cdsc_ctrl & CDROM_DATA_TRACK) ? 0 : 1;
-
-       /* XA detection */
-       disk_info.xa = drive_status() & ST_MODE2TRACK;
-
-       /* Multisession detection: if we want this, define MULTISESSION */
-       disk_info.multi = 0;
-#ifdef MULTISESSION
-       if (disk_info.xa)
-               get_multi_disk_info();  /* Here disk_info.multi is set */
-#endif /* MULTISESSION */
-       if (disk_info.multi)
-               printk(KERN_WARNING "optcd: Multisession support experimental, "
-                       "see Documentation/cdrom/optcd\n");
-
-       DEBUG((DEBUG_TOC, "exiting update_toc"));
-
-       toc_uptodate = 1;
-       return 0;
-}
-\f
-/* Request handling */
-
-static int current_valid(void)
-{
-        return CURRENT &&
-               rq_data_dir(CURRENT) == READ &&
-               CURRENT->sector != -1;
-}
-
-/* Buffers for block size conversion. */
-#define NOBUF          -1
-
-static char buf[CD_FRAMESIZE * N_BUFS];
-static volatile int buf_bn[N_BUFS], next_bn;
-static volatile int buf_in = 0, buf_out = NOBUF;
-
-static inline void opt_invalidate_buffers(void)
-{
-       int i;
-
-       DEBUG((DEBUG_BUFFERS, "executing opt_invalidate_buffers"));
-
-       for (i = 0; i < N_BUFS; i++)
-               buf_bn[i] = NOBUF;
-       buf_out = NOBUF;
-}
-
-
-/* Take care of the different block sizes between cdrom and Linux.
-   When Linux gets variable block sizes this will probably go away. */
-static void transfer(void)
-{
-#if DEBUG_BUFFERS | DEBUG_REQUEST
-       printk(KERN_DEBUG "optcd: executing transfer\n");
-#endif
-
-       if (!current_valid())
-               return;
-       while (CURRENT -> nr_sectors) {
-               int bn = CURRENT -> sector / 4;
-               int i, offs, nr_sectors;
-               for (i = 0; i < N_BUFS && buf_bn[i] != bn; ++i);
-
-               DEBUG((DEBUG_REQUEST, "found %d", i));
-
-               if (i >= N_BUFS) {
-                       buf_out = NOBUF;
-                       break;
-               }
-
-               offs = (i * 4 + (CURRENT -> sector & 3)) * 512;
-               nr_sectors = 4 - (CURRENT -> sector & 3);
-
-               if (buf_out != i) {
-                       buf_out = i;
-                       if (buf_bn[i] != bn) {
-                               buf_out = NOBUF;
-                               continue;
-                       }
-               }
-
-               if (nr_sectors > CURRENT -> nr_sectors)
-                       nr_sectors = CURRENT -> nr_sectors;
-               memcpy(CURRENT -> buffer, buf + offs, nr_sectors * 512);
-               CURRENT -> nr_sectors -= nr_sectors;
-               CURRENT -> sector += nr_sectors;
-               CURRENT -> buffer += nr_sectors * 512;
-       }
-}
-
-
-/* State machine for reading disk blocks */
-
-enum state_e {
-       S_IDLE,         /* 0 */
-       S_START,        /* 1 */
-       S_READ,         /* 2 */
-       S_DATA,         /* 3 */
-       S_STOP,         /* 4 */
-       S_STOPPING      /* 5 */
-};
-
-static volatile enum state_e state = S_IDLE;
-#if DEBUG_STATE
-static volatile enum state_e state_old = S_STOP;
-static volatile int flags_old = 0;
-static volatile long state_n = 0;
-#endif
-
-
-/* Used as mutex to keep do_optcd_request (and other processes calling
-   ioctl) out while some process is inside a VFS call.
-   Reverse is accomplished by checking if state = S_IDLE upon entry
-   of opt_ioctl and opt_media_change. */
-static int in_vfs = 0;
-
-
-static volatile int transfer_is_active = 0;
-static volatile int error = 0; /* %% do something with this?? */
-static int tries;              /* ibid?? */
-static int timeout = 0;
-
-static void poll(unsigned long data);
-static struct timer_list req_timer = {.function = poll};
-
-
-static void poll(unsigned long data)
-{
-       static volatile int read_count = 1;
-       int flags;
-       int loop_again = 1;
-       int status = 0;
-       int skip = 0;
-
-       if (error) {
-               printk(KERN_ERR "optcd: I/O error 0x%02x\n", error);
-               opt_invalidate_buffers();
-               if (!tries--) {
-                       printk(KERN_ERR "optcd: read block %d failed;"
-                               " Giving up\n", next_bn);
-                       if (transfer_is_active)
-                               loop_again = 0;
-                       if (current_valid())
-                               end_request(CURRENT, 0);
-                       tries = 5;
-               }
-               error = 0;
-               state = S_STOP;
-       }
-
-       while (loop_again)
-       {
-               loop_again = 0; /* each case must flip this back to 1 if we want
-                                to come back up here */
-
-#if DEBUG_STATE
-               if (state == state_old)
-                       state_n++;
-               else {
-                       state_old = state;
-                       if (++state_n > 1)
-                               printk(KERN_DEBUG "optcd: %ld times "
-                                       "in previous state\n", state_n);
-                       printk(KERN_DEBUG "optcd: state %d\n", state);
-                       state_n = 0;
-               }
-#endif
-
-               switch (state) {
-               case S_IDLE:
-                       return;
-               case S_START:
-                       if (in_vfs)
-                               break;
-                       if (send_cmd(COMDRVST)) {
-                               state = S_IDLE;
-                               while (current_valid())
-                                       end_request(CURRENT, 0);
-                               return;
-                       }
-                       state = S_READ;
-                       timeout = READ_TIMEOUT;
-                       break;
-               case S_READ: {
-                       struct cdrom_msf msf;
-                       if (!skip) {
-                               status = fetch_status();
-                               if (status < 0)
-                                       break;
-                               if (status & ST_DSK_CHG) {
-                                       toc_uptodate = 0;
-                                       opt_invalidate_buffers();
-                               }
-                       }
-                       skip = 0;
-                       if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
-                               toc_uptodate = 0;
-                               opt_invalidate_buffers();
-                               printk(KERN_WARNING "optcd: %s\n",
-                                       (status & ST_DOOR_OPEN)
-                                       ? "door open"
-                                       : "disk removed");
-                               state = S_IDLE;
-                               while (current_valid())
-                                       end_request(CURRENT, 0);
-                               return;
-                       }
-                       if (!current_valid()) {
-                               state = S_STOP;
-                               loop_again = 1;
-                               break;
-                       }
-                       next_bn = CURRENT -> sector / 4;
-                       lba2msf(next_bn, &msf);
-                       read_count = N_BUFS;
-                       msf.cdmsf_frame1 = read_count; /* Not BCD! */
-
-                       DEBUG((DEBUG_REQUEST, "reading %x:%x.%x %x:%x.%x",
-                               msf.cdmsf_min0,
-                               msf.cdmsf_sec0,
-                               msf.cdmsf_frame0,
-                               msf.cdmsf_min1,
-                               msf.cdmsf_sec1,
-                               msf.cdmsf_frame1));
-                       DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d"
-                               " buf_out:%d buf_bn:%d",
-                               next_bn,
-                               buf_in,
-                               buf_out,
-                               buf_bn[buf_in]));
-
-                       exec_read_cmd(COMREAD, &msf);
-                       state = S_DATA;
-                       timeout = READ_TIMEOUT;
-                       break;
-               }
-               case S_DATA:
-                       flags = stdt_flags() & (FL_STEN|FL_DTEN);
-
-#if DEBUG_STATE
-                       if (flags != flags_old) {
-                               flags_old = flags;
-                               printk(KERN_DEBUG "optcd: flags:%x\n", flags);
-                       }
-                       if (flags == FL_STEN)
-                               printk(KERN_DEBUG "timeout cnt: %d\n", timeout);
-#endif
-
-                       switch (flags) {
-                       case FL_DTEN:           /* only STEN low */
-                               if (!tries--) {
-                                       printk(KERN_ERR
-                                               "optcd: read block %d failed; "
-                                               "Giving up\n", next_bn);
-                                       if (transfer_is_active) {
-                                               tries = 0;
-                                               break;
-                                       }
-                                       if (current_valid())
-                                               end_request(CURRENT, 0);
-                                       tries = 5;
-                               }
-                               state = S_START;
-                               timeout = READ_TIMEOUT;
-                               loop_again = 1;
-                       case (FL_STEN|FL_DTEN):  /* both high */
-                               break;
-                       default:        /* DTEN low */
-                               tries = 5;
-                               if (!current_valid() && buf_in == buf_out) {
-                                       state = S_STOP;
-                                       loop_again = 1;
-                                       break;
-                               }
-                               if (read_count<=0)
-                                       printk(KERN_WARNING
-                                               "optcd: warning - try to read"
-                                               " 0 frames\n");
-                               while (read_count) {
-                                       buf_bn[buf_in] = NOBUF;
-                                       if (!flag_low(FL_DTEN, BUSY_TIMEOUT)) {
-                                       /* should be no waiting here!?? */
-                                               printk(KERN_ERR
-                                                  "read_count:%d "
-                                                  "CURRENT->nr_sectors:%ld "
-                                                  "buf_in:%d\n",
-                                                       read_count,
-                                                       CURRENT->nr_sectors,
-                                                       buf_in);
-                                               printk(KERN_ERR
-                                                       "transfer active: %x\n",
-                                                       transfer_is_active);
-                                               read_count = 0;
-                                               state = S_STOP;
-                                               loop_again = 1;
-                                               end_request(CURRENT, 0);
-                                               break;
-                                       }
-                                       fetch_data(buf+
-                                           CD_FRAMESIZE*buf_in,
-                                           CD_FRAMESIZE);
-                                       read_count--;
-
-                                       DEBUG((DEBUG_REQUEST,
-                                               "S_DATA; ---I've read data- "
-                                               "read_count: %d",
-                                               read_count));
-                                       DEBUG((DEBUG_REQUEST,
-                                               "next_bn:%d  buf_in:%d "
-                                               "buf_out:%d  buf_bn:%d",
-                                               next_bn,
-                                               buf_in,
-                                               buf_out,
-                                               buf_bn[buf_in]));
-
-                                       buf_bn[buf_in] = next_bn++;
-                                       if (buf_out == NOBUF)
-                                               buf_out = buf_in;
-                                       buf_in = buf_in + 1 ==
-                                               N_BUFS ? 0 : buf_in + 1;
-                               }
-                               if (!transfer_is_active) {
-                                       while (current_valid()) {
-                                               transfer();
-                                               if (CURRENT -> nr_sectors == 0)
-                                                       end_request(CURRENT, 1);
-                                               else
-                                                       break;
-                                       }
-                               }
-
-                               if (current_valid()
-                                   && (CURRENT -> sector / 4 < next_bn ||
-                                   CURRENT -> sector / 4 >
-                                    next_bn + N_BUFS)) {
-                                       state = S_STOP;
-                                       loop_again = 1;
-                                       break;
-                               }
-                               timeout = READ_TIMEOUT;
-                               if (read_count == 0) {
-                                       state = S_STOP;
-                                       loop_again = 1;
-                                       break;
-                               }
-                       }
-                       break;
-               case S_STOP:
-                       if (read_count != 0)
-                               printk(KERN_ERR
-                                       "optcd: discard data=%x frames\n",
-                                       read_count);
-                       flush_data();
-                       if (send_cmd(COMDRVST)) {
-                               state = S_IDLE;
-                               while (current_valid())
-                                       end_request(CURRENT, 0);
-                               return;
-                       }
-                       state = S_STOPPING;
-                       timeout = STOP_TIMEOUT;
-                       break;
-               case S_STOPPING:
-                       status = fetch_status();
-                       if (status < 0 && timeout)
-                                       break;
-                       if ((status >= 0) && (status & ST_DSK_CHG)) {
-                               toc_uptodate = 0;
-                               opt_invalidate_buffers();
-                       }
-                       if (current_valid()) {
-                               if (status >= 0) {
-                                       state = S_READ;
-                                       loop_again = 1;
-                                       skip = 1;
-                                       break;
-                               } else {
-                                       state = S_START;
-                                       timeout = 1;
-                               }
-                       } else {
-                               state = S_IDLE;
-                               return;
-                       }
-                       break;
-               default:
-                       printk(KERN_ERR "optcd: invalid state %d\n", state);
-                       return;
-               } /* case */
-       } /* while */
-
-       if (!timeout--) {
-               printk(KERN_ERR "optcd: timeout in state %d\n", state);
-               state = S_STOP;
-               if (exec_cmd(COMSTOP) < 0) {
-                       state = S_IDLE;
-                       while (current_valid())
-                               end_request(CURRENT, 0);
-                       return;
-               }
-       }
-
-       mod_timer(&req_timer, jiffies + HZ/100);
-}
-
-
-static void do_optcd_request(request_queue_t * q)
-{
-       DEBUG((DEBUG_REQUEST, "do_optcd_request(%ld+%ld)",
-              CURRENT -> sector, CURRENT -> nr_sectors));
-
-       if (disk_info.audio) {
-               printk(KERN_WARNING "optcd: tried to mount an Audio CD\n");
-               end_request(CURRENT, 0);
-               return;
-       }
-
-       transfer_is_active = 1;
-       while (current_valid()) {
-               transfer();     /* First try to transfer block from buffers */
-               if (CURRENT -> nr_sectors == 0) {
-                       end_request(CURRENT, 1);
-               } else {        /* Want to read a block not in buffer */
-                       buf_out = NOBUF;
-                       if (state == S_IDLE) {
-                               /* %% Should this block the request queue?? */
-                               if (update_toc() < 0) {
-                                       while (current_valid())
-                                               end_request(CURRENT, 0);
-                                       break;
-                               }
-                               /* Start state machine */
-                               state = S_START;
-                               timeout = READ_TIMEOUT;
-                               tries = 5;
-                               /* %% why not start right away?? */
-                               mod_timer(&req_timer, jiffies + HZ/100);
-                       }
-                       break;
-               }
-       }
-       transfer_is_active = 0;
-
-       DEBUG((DEBUG_REQUEST, "next_bn:%d  buf_in:%d buf_out:%d  buf_bn:%d",
-              next_bn, buf_in, buf_out, buf_bn[buf_in]));
-       DEBUG((DEBUG_REQUEST, "do_optcd_request ends"));
-}
-\f
-/* IOCTLs */
-
-
-static char auto_eject = 0;
-
-static int cdrompause(void)
-{
-       int status;
-
-       if (audio_status != CDROM_AUDIO_PLAY)
-               return -EINVAL;
-
-       status = exec_cmd(COMPAUSEON);
-       if (status < 0) {
-               DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEON: %02x", -status));
-               return -EIO;
-       }
-       audio_status = CDROM_AUDIO_PAUSED;
-       return 0;
-}
-
-
-static int cdromresume(void)
-{
-       int status;
-
-       if (audio_status != CDROM_AUDIO_PAUSED)
-               return -EINVAL;
-
-       status = exec_cmd(COMPAUSEOFF);
-       if (status < 0) {
-               DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEOFF: %02x", -status));
-               audio_status = CDROM_AUDIO_ERROR;
-               return -EIO;
-       }
-       audio_status = CDROM_AUDIO_PLAY;
-       return 0;
-}
-
-
-static int cdromplaymsf(void __user *arg)
-{
-       int status;
-       struct cdrom_msf msf;
-
-       if (copy_from_user(&msf, arg, sizeof msf))
-               return -EFAULT;
-
-       bin2bcd(&msf);
-       status = exec_long_cmd(COMPLAY, &msf);
-       if (status < 0) {
-               DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
-               audio_status = CDROM_AUDIO_ERROR;
-               return -EIO;
-       }
-
-       audio_status = CDROM_AUDIO_PLAY;
-       return 0;
-}
-
-
-static int cdromplaytrkind(void __user *arg)
-{
-       int status;
-       struct cdrom_ti ti;
-       struct cdrom_msf msf;
-
-       if (copy_from_user(&ti, arg, sizeof ti))
-               return -EFAULT;
-
-       if (ti.cdti_trk0 < disk_info.first
-           || ti.cdti_trk0 > disk_info.last
-           || ti.cdti_trk1 < ti.cdti_trk0)
-               return -EINVAL;
-       if (ti.cdti_trk1 > disk_info.last)
-               ti.cdti_trk1 = disk_info.last;
-
-       msf.cdmsf_min0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.minute;
-       msf.cdmsf_sec0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.second;
-       msf.cdmsf_frame0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.frame;
-       msf.cdmsf_min1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.minute;
-       msf.cdmsf_sec1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.second;
-       msf.cdmsf_frame1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.frame;
-
-       DEBUG((DEBUG_VFS, "play %02d:%02d.%02d to %02d:%02d.%02d",
-               msf.cdmsf_min0,
-               msf.cdmsf_sec0,
-               msf.cdmsf_frame0,
-               msf.cdmsf_min1,
-               msf.cdmsf_sec1,
-               msf.cdmsf_frame1));
-
-       bin2bcd(&msf);
-       status = exec_long_cmd(COMPLAY, &msf);
-       if (status < 0) {
-               DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
-               audio_status = CDROM_AUDIO_ERROR;
-               return -EIO;
-       }
-
-       audio_status = CDROM_AUDIO_PLAY;
-       return 0;
-}
-
-
-static int cdromreadtochdr(void __user *arg)
-{
-       struct cdrom_tochdr tochdr;
-
-       tochdr.cdth_trk0 = disk_info.first;
-       tochdr.cdth_trk1 = disk_info.last;
-
-       return copy_to_user(arg, &tochdr, sizeof tochdr) ? -EFAULT : 0;
-}
-
-
-static int cdromreadtocentry(void __user *arg)
-{
-       struct cdrom_tocentry entry;
-       struct cdrom_subchnl *tocptr;
-
-       if (copy_from_user(&entry, arg, sizeof entry))
-               return -EFAULT;
-
-       if (entry.cdte_track == CDROM_LEADOUT)
-               tocptr = &toc[disk_info.last + 1];
-       else if (entry.cdte_track > disk_info.last
-               || entry.cdte_track < disk_info.first)
-               return -EINVAL;
-       else
-               tocptr = &toc[entry.cdte_track];
-
-       entry.cdte_adr = tocptr->cdsc_adr;
-       entry.cdte_ctrl = tocptr->cdsc_ctrl;
-       entry.cdte_addr.msf.minute = tocptr->cdsc_absaddr.msf.minute;
-       entry.cdte_addr.msf.second = tocptr->cdsc_absaddr.msf.second;
-       entry.cdte_addr.msf.frame = tocptr->cdsc_absaddr.msf.frame;
-       /* %% What should go into entry.cdte_datamode? */
-
-       if (entry.cdte_format == CDROM_LBA)
-               msf2lba(&entry.cdte_addr);
-       else if (entry.cdte_format != CDROM_MSF)
-               return -EINVAL;
-
-       return copy_to_user(arg, &entry, sizeof entry) ? -EFAULT : 0;
-}
-
-
-static int cdromvolctrl(void __user *arg)
-{
-       int status;
-       struct cdrom_volctrl volctrl;
-       struct cdrom_msf msf;
-
-       if (copy_from_user(&volctrl, arg, sizeof volctrl))
-               return -EFAULT;
-
-       msf.cdmsf_min0 = 0x10;
-       msf.cdmsf_sec0 = 0x32;
-       msf.cdmsf_frame0 = volctrl.channel0;
-       msf.cdmsf_min1 = volctrl.channel1;
-       msf.cdmsf_sec1 = volctrl.channel2;
-       msf.cdmsf_frame1 = volctrl.channel3;
-
-       status = exec_long_cmd(COMCHCTRL, &msf);
-       if (status < 0) {
-               DEBUG((DEBUG_VFS, "exec_long_cmd COMCHCTRL: %02x", -status));
-               return -EIO;
-       }
-       return 0;
-}
-
-
-static int cdromsubchnl(void __user *arg)
-{
-       int status;
-       struct cdrom_subchnl subchnl;
-
-       if (copy_from_user(&subchnl, arg, sizeof subchnl))
-               return -EFAULT;
-
-       if (subchnl.cdsc_format != CDROM_LBA
-           && subchnl.cdsc_format != CDROM_MSF)
-               return -EINVAL;
-
-       status = get_q_channel(&subchnl);
-       if (status < 0) {
-               DEBUG((DEBUG_VFS, "get_q_channel: %02x", -status));
-               return -EIO;
-       }
-
-       if (copy_to_user(arg, &subchnl, sizeof subchnl))
-               return -EFAULT;
-       return 0;
-}
-
-
-static struct gendisk *optcd_disk;
-
-
-static int cdromread(void __user *arg, int blocksize, int cmd)
-{
-       int status;
-       struct cdrom_msf msf;
-
-       if (copy_from_user(&msf, arg, sizeof msf))
-               return -EFAULT;
-
-       bin2bcd(&msf);
-       msf.cdmsf_min1 = 0;
-       msf.cdmsf_sec1 = 0;
-       msf.cdmsf_frame1 = 1;   /* read only one frame */
-       status = exec_read_cmd(cmd, &msf);
-
-       DEBUG((DEBUG_VFS, "read cmd status 0x%x", status));
-
-       if (!sleep_flag_low(FL_DTEN, SLEEP_TIMEOUT))
-               return -EIO;
-
-       fetch_data(optcd_disk->private_data, blocksize);
-
-       if (copy_to_user(arg, optcd_disk->private_data, blocksize))
-               return -EFAULT;
-
-       return 0;
-}
-
-
-static int cdromseek(void __user *arg)
-{
-       int status;
-       struct cdrom_msf msf;
-
-       if (copy_from_user(&msf, arg, sizeof msf))
-               return -EFAULT;
-
-       bin2bcd(&msf);
-       status = exec_seek_cmd(COMSEEK, &msf);
-
-       DEBUG((DEBUG_VFS, "COMSEEK status 0x%x", status));
-
-       if (status < 0)
-               return -EIO;
-       return 0;
-}
-
-
-#ifdef MULTISESSION
-static int cdrommultisession(void __user *arg)
-{
-       struct cdrom_multisession ms;
-
-       if (copy_from_user(&ms, arg, sizeof ms))
-               return -EFAULT;
-
-       ms.addr.msf.minute = disk_info.last_session.minute;
-       ms.addr.msf.second = disk_info.last_session.second;
-       ms.addr.msf.frame = disk_info.last_session.frame;
-
-       if (ms.addr_format != CDROM_LBA
-          && ms.addr_format != CDROM_MSF)
-               return -EINVAL;
-       if (ms.addr_format == CDROM_LBA)
-               msf2lba(&ms.addr);
-
-       ms.xa_flag = disk_info.xa;
-
-       if (copy_to_user(arg, &ms, sizeof(struct cdrom_multisession)))
-               return -EFAULT;
-
-#if DEBUG_MULTIS
-       if (ms.addr_format == CDROM_MSF)
-                       printk(KERN_DEBUG
-                       "optcd: multisession xa:%d, msf:%02d:%02d.%02d\n",
-                       ms.xa_flag,
-                       ms.addr.msf.minute,
-                       ms.addr.msf.second,
-                       ms.addr.msf.frame);
-       else
-               printk(KERN_DEBUG
-                   "optcd: multisession %d, lba:0x%08x [%02d:%02d.%02d])\n",
-                       ms.xa_flag,
-                       ms.addr.lba,
-                       disk_info.last_session.minute,
-                       disk_info.last_session.second,
-                       disk_info.last_session.frame);
-#endif /* DEBUG_MULTIS */
-
-       return 0;
-}
-#endif /* MULTISESSION */
-
-
-static int cdromreset(void)
-{
-       if (state != S_IDLE) {
-               error = 1;
-               tries = 0;
-       }
-
-       toc_uptodate = 0;
-       disk_changed = 1;
-       opt_invalidate_buffers();
-       audio_status = CDROM_AUDIO_NO_STATUS;
-
-       if (!reset_drive())
-               return -EIO;
-       return 0;
-}
-\f
-/* VFS calls */
-
-
-static int opt_ioctl(struct inode *ip, struct file *fp,
-                     unsigned int cmd, unsigned long arg)
-{
-       int status, err, retval = 0;
-       void __user *argp = (void __user *)arg;
-
-       DEBUG((DEBUG_VFS, "starting opt_ioctl"));
-
-       if (!ip)
-               return -EINVAL;
-
-       if (cmd == CDROMRESET)
-               return cdromreset();
-
-       /* is do_optcd_request or another ioctl busy? */
-       if (state != S_IDLE || in_vfs)
-               return -EBUSY;
-
-       in_vfs = 1;
-
-       status = drive_status();
-       if (status < 0) {
-               DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
-               in_vfs = 0;
-               return -EIO;
-       }
-
-       if (status & ST_DOOR_OPEN)
-               switch (cmd) {  /* Actions that can be taken with door open */
-               case CDROMCLOSETRAY:
-                       /* We do this before trying to read the toc. */
-                       err = exec_cmd(COMCLOSE);
-                       if (err < 0) {
-                               DEBUG((DEBUG_VFS,
-                                      "exec_cmd COMCLOSE: %02x", -err));
-                               in_vfs = 0;
-                               return -EIO;
-                       }
-                       break;
-               default:        in_vfs = 0;
-                               return -EBUSY;
-               }
-
-       err = update_toc();
-       if (err < 0) {
-               DEBUG((DEBUG_VFS, "update_toc: %02x", -err));
-               in_vfs = 0;
-               return -EIO;
-       }
-
-       DEBUG((DEBUG_VFS, "ioctl cmd 0x%x", cmd));
-
-       switch (cmd) {
-       case CDROMPAUSE:        retval = cdrompause(); break;
-       case CDROMRESUME:       retval = cdromresume(); break;
-       case CDROMPLAYMSF:      retval = cdromplaymsf(argp); break;
-       case CDROMPLAYTRKIND:   retval = cdromplaytrkind(argp); break;
-       case CDROMREADTOCHDR:   retval = cdromreadtochdr(argp); break;
-       case CDROMREADTOCENTRY: retval = cdromreadtocentry(argp); break;
-
-       case CDROMSTOP:         err = exec_cmd(COMSTOP);
-                               if (err < 0) {
-                                       DEBUG((DEBUG_VFS,
-                                               "exec_cmd COMSTOP: %02x",
-                                               -err));
-                                       retval = -EIO;
-                               } else
-                                       audio_status = CDROM_AUDIO_NO_STATUS;
-                               break;
-       case CDROMSTART:        break;  /* This is a no-op */
-       case CDROMEJECT:        err = exec_cmd(COMUNLOCK);
-                               if (err < 0) {
-                                       DEBUG((DEBUG_VFS,
-                                               "exec_cmd COMUNLOCK: %02x",
-                                               -err));
-                                       retval = -EIO;
-                                       break;
-                               }
-                               err = exec_cmd(COMOPEN);
-                               if (err < 0) {
-                                       DEBUG((DEBUG_VFS,
-                                               "exec_cmd COMOPEN: %02x",
-                                               -err));
-                                       retval = -EIO;
-                               }
-                               break;
-
-       case CDROMVOLCTRL:      retval = cdromvolctrl(argp); break;
-       case CDROMSUBCHNL:      retval = cdromsubchnl(argp); break;
-
-       /* The drive detects the mode and automatically delivers the
-          correct 2048 bytes, so we don't need these IOCTLs */
-       case CDROMREADMODE2:    retval = -EINVAL; break;
-       case CDROMREADMODE1:    retval = -EINVAL; break;
-
-       /* Drive doesn't support reading audio */
-       case CDROMREADAUDIO:    retval = -EINVAL; break;
-
-       case CDROMEJECT_SW:     auto_eject = (char) arg;
-                               break;
-
-#ifdef MULTISESSION
-       case CDROMMULTISESSION: retval = cdrommultisession(argp); break;
-#endif
-
-       case CDROM_GET_MCN:     retval = -EINVAL; break; /* not implemented */
-       case CDROMVOLREAD:      retval = -EINVAL; break; /* not implemented */
-
-       case CDROMREADRAW:
-                       /* this drive delivers 2340 bytes in raw mode */
-                       retval = cdromread(argp, CD_FRAMESIZE_RAW1, COMREADRAW);
-                       break;
-       case CDROMREADCOOKED:
-                       retval = cdromread(argp, CD_FRAMESIZE, COMREAD);
-                       break;
-       case CDROMREADALL:
-                       retval = cdromread(argp, CD_FRAMESIZE_RAWER, COMREADALL);
-                       break;
-
-       case CDROMSEEK:         retval = cdromseek(argp); break;
-       case CDROMPLAYBLK:      retval = -EINVAL; break; /* not implemented */
-       case CDROMCLOSETRAY:    break;  /* The action was taken earlier */
-       default:                retval = -EINVAL;
-       }
-       in_vfs = 0;
-       return retval;
-}
-
-
-static int open_count = 0;
-
-/* Open device special file; check that a disk is in. */
-static int opt_open(struct inode *ip, struct file *fp)
-{
-       DEBUG((DEBUG_VFS, "starting opt_open"));
-
-       if (!open_count && state == S_IDLE) {
-               int status;
-               char *buf;
-
-               buf = kmalloc(CD_FRAMESIZE_RAWER, GFP_KERNEL);
-               if (!buf) {
-                       printk(KERN_INFO "optcd: cannot allocate read buffer\n");
-                       return -ENOMEM;
-               }
-               optcd_disk->private_data = buf;         /* save read buffer */
-
-               toc_uptodate = 0;
-               opt_invalidate_buffers();
-
-               status = exec_cmd(COMCLOSE);    /* close door */
-               if (status < 0) {
-                       DEBUG((DEBUG_VFS, "exec_cmd COMCLOSE: %02x", -status));
-               }
-
-               status = drive_status();
-               if (status < 0) {
-                       DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
-                       goto err_out;
-               }
-               DEBUG((DEBUG_VFS, "status: %02x", status));
-               if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
-                       printk(KERN_INFO "optcd: no disk or door open\n");
-                       goto err_out;
-               }
-               status = exec_cmd(COMLOCK);             /* Lock door */
-               if (status < 0) {
-                       DEBUG((DEBUG_VFS, "exec_cmd COMLOCK: %02x", -status));
-               }
-               status = update_toc();  /* Read table of contents */
-               if (status < 0) {
-                       DEBUG((DEBUG_VFS, "update_toc: %02x", -status));
-                       status = exec_cmd(COMUNLOCK);   /* Unlock door */
-                       if (status < 0) {
-                               DEBUG((DEBUG_VFS,
-                                      "exec_cmd COMUNLOCK: %02x", -status));
-                       }
-                       goto err_out;
-               }
-               open_count++;
-       }
-
-       DEBUG((DEBUG_VFS, "exiting opt_open"));
-
-       return 0;
-
-err_out:
-       return -EIO;
-}
-
-
-/* Release device special file; flush all blocks from the buffer cache */
-static int opt_release(struct inode *ip, struct file *fp)
-{
-       int status;
-
-       DEBUG((DEBUG_VFS, "executing opt_release"));
-       DEBUG((DEBUG_VFS, "inode: %p, device: %s, file: %p\n",
-               ip, ip->i_bdev->bd_disk->disk_name, fp));
-
-       if (!--open_count) {
-               toc_uptodate = 0;
-               opt_invalidate_buffers();
-               status = exec_cmd(COMUNLOCK);   /* Unlock door */
-               if (status < 0) {
-                       DEBUG((DEBUG_VFS, "exec_cmd COMUNLOCK: %02x", -status));
-               }
-               if (auto_eject) {
-                       status = exec_cmd(COMOPEN);
-                       DEBUG((DEBUG_VFS, "exec_cmd COMOPEN: %02x", -status));
-               }
-               kfree(optcd_disk->private_data);
-               del_timer(&delay_timer);
-               del_timer(&req_timer);
-       }
-       return 0;
-}
-
-
-/* Check if disk has been changed */
-static int opt_media_change(struct gendisk *disk)
-{
-       DEBUG((DEBUG_VFS, "executing opt_media_change"));
-       DEBUG((DEBUG_VFS, "dev: %s; disk_changed = %d\n",
-                       disk->disk_name, disk_changed));
-
-       if (disk_changed) {
-               disk_changed = 0;
-               return 1;
-       }
-       return 0;
-}
-\f
-/* Driver initialisation */
-
-
-/* Returns 1 if a drive is detected with a version string
-   starting with "DOLPHIN". Otherwise 0. */
-static int __init version_ok(void)
-{
-       char devname[100];
-       int count, i, ch, status;
-
-       status = exec_cmd(COMVERSION);
-       if (status < 0) {
-               DEBUG((DEBUG_VFS, "exec_cmd COMVERSION: %02x", -status));
-               return 0;
-       }
-       if ((count = get_data(1)) < 0) {
-               DEBUG((DEBUG_VFS, "get_data(1): %02x", -count));
-               return 0;
-       }
-       for (i = 0, ch = -1; count > 0; count--) {
-               if ((ch = get_data(1)) < 0) {
-                       DEBUG((DEBUG_VFS, "get_data(1): %02x", -ch));
-                       break;
-               }
-               if (i < 99)
-                       devname[i++] = ch;
-       }
-       devname[i] = '\0';
-       if (ch < 0)
-               return 0;
-
-       printk(KERN_INFO "optcd: Device %s detected\n", devname);
-       return ((devname[0] == 'D')
-            && (devname[1] == 'O')
-            && (devname[2] == 'L')
-            && (devname[3] == 'P')
-            && (devname[4] == 'H')
-            && (devname[5] == 'I')
-            && (devname[6] == 'N'));
-}
-
-
-static struct block_device_operations opt_fops = {
-       .owner          = THIS_MODULE,
-       .open           = opt_open,
-       .release        = opt_release,
-       .ioctl          = opt_ioctl,
-       .media_changed  = opt_media_change,
-};
-
-#ifndef MODULE
-/* Get kernel parameter when used as a kernel driver */
-static int optcd_setup(char *str)
-{
-       int ints[4];
-       (void)get_options(str, ARRAY_SIZE(ints), ints);
-       
-       if (ints[0] > 0)
-               optcd_port = ints[1];
-
-       return 1;
-}
-
-__setup("optcd=", optcd_setup);
-
-#endif /* MODULE */
-
-/* Test for presence of drive and initialize it. Called at boot time
-   or during module initialisation. */
-static int __init optcd_init(void)
-{
-       int status;
-
-       if (optcd_port <= 0) {
-               printk(KERN_INFO
-                       "optcd: no Optics Storage CDROM Initialization\n");
-               return -EIO;
-       }
-       optcd_disk = alloc_disk(1);
-       if (!optcd_disk) {
-               printk(KERN_ERR "optcd: can't allocate disk\n");
-               return -ENOMEM;
-       }
-       optcd_disk->major = MAJOR_NR;
-       optcd_disk->first_minor = 0;
-       optcd_disk->fops = &opt_fops;
-       sprintf(optcd_disk->disk_name, "optcd");
-
-       if (!request_region(optcd_port, 4, "optcd")) {
-               printk(KERN_ERR "optcd: conflict, I/O port 0x%x already used\n",
-                       optcd_port);
-               put_disk(optcd_disk);
-               return -EIO;
-       }
-
-       if (!reset_drive()) {
-               printk(KERN_ERR "optcd: drive at 0x%x not ready\n", optcd_port);
-               release_region(optcd_port, 4);
-               put_disk(optcd_disk);
-               return -EIO;
-       }
-       if (!version_ok()) {
-               printk(KERN_ERR "optcd: unknown drive detected; aborting\n");
-               release_region(optcd_port, 4);
-               put_disk(optcd_disk);
-               return -EIO;
-       }
-       status = exec_cmd(COMINITDOUBLE);
-       if (status < 0) {
-               printk(KERN_ERR "optcd: cannot init double speed mode\n");
-               release_region(optcd_port, 4);
-               DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status));
-               put_disk(optcd_disk);
-               return -EIO;
-       }
-       if (register_blkdev(MAJOR_NR, "optcd")) {
-               release_region(optcd_port, 4);
-               put_disk(optcd_disk);
-               return -EIO;
-       }
-
-
-       opt_queue = blk_init_queue(do_optcd_request, &optcd_lock);
-       if (!opt_queue) {
-               unregister_blkdev(MAJOR_NR, "optcd");
-               release_region(optcd_port, 4);
-               put_disk(optcd_disk);
-               return -ENOMEM;
-       }
-
-       blk_queue_hardsect_size(opt_queue, 2048);
-       optcd_disk->queue = opt_queue;
-       add_disk(optcd_disk);
-
-       printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
-       return 0;
-}
-
-
-static void __exit optcd_exit(void)
-{
-       del_gendisk(optcd_disk);
-       put_disk(optcd_disk);
-       if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
-               printk(KERN_ERR "optcd: what's that: can't unregister\n");
-               return;
-       }
-       blk_cleanup_queue(opt_queue);
-       release_region(optcd_port, 4);
-       printk(KERN_INFO "optcd: module released.\n");
-}
-
-module_init(optcd_init);
-module_exit(optcd_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(OPTICS_CDROM_MAJOR);
diff --git a/drivers/cdrom/optcd.h b/drivers/cdrom/optcd.h
deleted file mode 100644 (file)
index 1911bb9..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*     linux/include/linux/optcd.h - Optics Storage 8000 AT CDROM driver
-       $Id: optcd.h,v 1.2 1996/01/15 18:43:44 root Exp root $
-
-       Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
-
-
-       Configuration file for linux/drivers/cdrom/optcd.c
-*/
-
-#ifndef _LINUX_OPTCD_H
-#define _LINUX_OPTCD_H
-
-
-/* I/O base of drive. Drive uses base to base+2.
-   This setting can be overridden with the kernel or insmod command
-   line option 'optcd=<portbase>'. Use address of 0 to disable driver. */
-#define OPTCD_PORTBASE 0x340
-
-
-/* enable / disable parts of driver by define / undef */
-#define        MULTISESSION            /* multisession support (ALPHA) */
-
-
-/* Change 0 to 1 to debug various parts of the driver */
-#define        DEBUG_DRIVE_IF  0       /* Low level drive interface */
-#define        DEBUG_CONV      0       /* Address conversions */
-#define        DEBUG_BUFFERS   0       /* Buffering and block size conversion */
-#define        DEBUG_REQUEST   0       /* Request mechanism */
-#define        DEBUG_STATE     0       /* State machine */
-#define        DEBUG_TOC       0       /* Q-channel and Table of Contents */
-#define        DEBUG_MULTIS    0       /* Multisession code */
-#define        DEBUG_VFS       0       /* VFS interface */
-
-
-/* Don't touch these unless you know what you're doing. */
-
-/* Various timeout loop repetition counts. */
-#define BUSY_TIMEOUT           10000000        /* for busy wait */
-#define FAST_TIMEOUT           100000          /* ibid. for probing */
-#define SLEEP_TIMEOUT          6000            /* for timer wait */
-#define MULTI_SEEK_TIMEOUT     1000            /* for timer wait */
-#define READ_TIMEOUT           6000            /* for poll wait */
-#define STOP_TIMEOUT           2000            /* for poll wait */
-#define RESET_WAIT             5000            /* busy wait at drive reset */
-
-/* # of buffers for block size conversion. 6 is optimal for my setup (P75),
-   giving 280 kb/s, with 0.4% CPU usage. Experiment to find your optimal
-   setting */
-#define N_BUFS         6
-
-
-#endif /* _LINUX_OPTCD_H */
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
deleted file mode 100644 (file)
index a1283b1..0000000
+++ /dev/null
@@ -1,5966 +0,0 @@
-/*
- *  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/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 "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;
-
-/* You can only set the first pair, from old MODULE_PARM code.  */
-static int sbpcd_set(const char *val, struct kernel_param *kp)
-{
-       get_options((char *)val, 2, (int *)sbpcd);
-       return 0;
-}
-module_param_call(sbpcd, sbpcd_set, NULL, NULL, 0);
-
-#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;
-module_param(max_drives, int, 0);
-#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 DEFINE_TIMER(delay_timer, mark_timeout_delay, 0, 0);
-static DEFINE_TIMER(data_timer, mark_timeout_data, 0, 0);
-#if 0
-static DEFINE_TIMER(audio_timer, 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;
-       va_start(args, fmt);
-       vsnprintf(buf, sizeof(buf), fmt, args);
-       va_end(args);
-       printk(MSG_LEVEL "%s-%d [%02d]:  %s", major_name, current_drive - D_S, msgnum, 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();
-       schedule_timeout_interruptible(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==0x12) return (-ERR_DISKCHANGE); /* disk change (inserted) */
-               return (-602); /* drive not ready */
-       }
-}
-/*==========================================================================*/
-static INLINE void clr_cmdbuf(void)
-{
-       int i;
-       
-       for (i=0;i<10;i++) drvcmd[i]=0;
-       cmd_type=0;
-}
-/*==========================================================================*/
-static void flush_status(void)
-{
-       int i;
-       
-       sbp_sleep(15*HZ/10);
-       for (i=maxtim_data;i!=0;i--) inb(CDi_status);
-}
-/*====================================================================*/
-/*
- * CDi status loop for Teac CD-55A (Rob Riggs)
- *
- * This is needed because for some strange reason
- * the CD-55A can take a real long time to give a
- * status response. This seems to happen after we
- * issue a READ command where a long seek is involved.
- *
- * I tried to ensure that we get max throughput with
- * minimal busy waiting. We busy wait at first, then
- * "switch gears" and start sleeping. We sleep for
- * longer periods of time the longer we wait.
- *
- */
-static int CDi_stat_loop_T(void)
-{
-       int     i, gear=1;
-       u_long  timeout_1, timeout_2, timeout_3, timeout_4;
-
-       timeout_1 = jiffies + HZ / 50;  /* sbp_sleep(0) for a short period */
-       timeout_2 = jiffies + HZ / 5;   /* nap for no more than 200ms */
-       timeout_3 = jiffies + 5 * HZ;   /* sleep for up to 5s */
-       timeout_4 = jiffies + 45 * HZ;  /* long sleep for up to 45s. */
-       do
-          {
-            i = inb(CDi_status);
-            if (!(i&s_not_data_ready)) return (i);
-            if (!(i&s_not_result_ready)) return (i);
-            switch(gear)
-              {
-              case 4:
-                sbp_sleep(HZ);
-                if (time_after(jiffies, timeout_4)) gear++;
-                msg(DBG_TEA, "CDi_stat_loop_T: long sleep active.\n");
-                break;
-              case 3:
-                sbp_sleep(HZ/10);
-                if (time_after(jiffies, timeout_3)) gear++;
-                break;
-              case 2:
-                sbp_sleep(HZ/100);
-                if (time_after(jiffies, timeout_2)) gear++;
-                break;
-              case 1:
-                sbp_sleep(0);
-                if (time_after(jiffies, timeout_1)) gear++;
-              }
-          } while (gear < 5);
-       return -1;
-}
-/*==========================================================================*/
-static int CDi_stat_loop(void)
-{
-       int i,j;
-       
-       for(timeout = jiffies + 10*HZ, i=maxtim_data; time_before(jiffies, timeout); )
-       {
-               for ( ;i!=0;i--)
-               {
-                       j=inb(CDi_status);
-                       if (!(j&s_not_data_ready)) return (j);
-                       if (!(j&s_not_result_ready)) return (j);
-                       if (fam0L_drive) if (j&s_attention) return (j);
-               }
-               sbp_sleep(1);
-               i = 1;
-       }
-       msg(DBG_LCS,"CDi_stat_loop failed in line %d\n", __LINE__);
-       return (-1);
-}
-/*==========================================================================*/
-#if 00000
-/*==========================================================================*/
-static int tst_DataReady(void)
-{
-       int i;
-       
-       i=inb(CDi_status);
-       if (i&s_not_data_ready) return (0);
-       return (1);
-}
-/*==========================================================================*/
-static int tst_ResultReady(void)
-{
-       int i;
-       
-       i=inb(CDi_status);
-       if (i&s_not_result_ready) return (0);
-       return (1);
-}
-/*==========================================================================*/
-static int tst_Attention(void)
-{
-       int i;
-       
-       i=inb(CDi_status);
-       if (i&s_attention) return (1);
-       return (0);
-}
-/*==========================================================================*/
-#endif
-/*==========================================================================*/
-static int ResponseInfo(void)
-{
-       int i,j,st=0;
-       u_long timeout;
-       
-       for (i=0,timeout=jiffies+HZ;i<response_count;i++) 
-       {
-               for (j=maxtim_data; ; )
-               {
-                       for ( ;j!=0;j-- )
-                       {
-                               st=inb(CDi_status);
-                               if (!(st&s_not_result_ready)) break;
-                       }
-                       if ((j!=0)||time_after_eq(jiffies, timeout)) break;
-                       sbp_sleep(1);
-                       j = 1;
-               }
-               if (time_after_eq(jiffies, timeout)) break;
-               infobuf[i]=inb(CDi_info);
-       }
-#if 000
-       while (!(inb(CDi_status)&s_not_result_ready))
-       {
-               infobuf[i++]=inb(CDi_info);
-       }
-       j=i-response_count;
-       if (j>0) msg(DBG_INF,"ResponseInfo: got %d trailing bytes.\n",j);
-#endif /* 000 */
-       for (j=0;j<i;j++)
-               sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
-       msgbuf[j*3]=0;
-       msg(DBG_CMD,"ResponseInfo:%s (%d,%d)\n",msgbuf,response_count,i);
-       j=response_count-i;
-       if (j>0) return (-j);
-       else return (i);
-}
-/*==========================================================================*/
-static void EvaluateStatus(int st)
-{
-       current_drive->status_bits=0;
-       if (fam1_drive) current_drive->status_bits=st|p_success;
-       else if (fam0_drive)
-       {
-               if (st&p_caddin_old) current_drive->status_bits |= p_door_closed|p_caddy_in;
-               if (st&p_spinning) current_drive->status_bits |= p_spinning;
-               if (st&p_check) current_drive->status_bits |= p_check;
-               if (st&p_success_old) current_drive->status_bits |= p_success;
-               if (st&p_busy_old) current_drive->status_bits |= p_busy_new;
-               if (st&p_disk_ok) current_drive->status_bits |= p_disk_ok;
-       }
-       else if (famLV_drive)
-       {
-               current_drive->status_bits |= p_success;
-               if (st&p_caddin_old) current_drive->status_bits |= p_disk_ok|p_caddy_in;
-               if (st&p_spinning) current_drive->status_bits |= p_spinning;
-               if (st&p_check) current_drive->status_bits |= p_check;
-               if (st&p_busy_old) current_drive->status_bits |= p_busy_new;
-               if (st&p_lcs_door_closed) current_drive->status_bits |= p_door_closed;
-               if (st&p_lcs_door_locked) current_drive->status_bits |= p_door_locked;
-       }
-       else if (fam2_drive)
-       {
-               current_drive->status_bits |= p_success;
-               if (st&p2_check) current_drive->status_bits |= p1_check;
-               if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed;
-               if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in;
-               if (st&p2_busy1) current_drive->status_bits |= p1_busy;
-               if (st&p2_busy2) current_drive->status_bits |= p1_busy;
-               if (st&p2_spinning) current_drive->status_bits |= p1_spinning;
-               if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked;
-               if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok;
-       }
-       else if (famT_drive)
-       {
-               return; /* still needs to get coded */
-               current_drive->status_bits |= p_success;
-               if (st&p2_check) current_drive->status_bits |= p1_check;
-               if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed;
-               if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in;
-               if (st&p2_busy1) current_drive->status_bits |= p1_busy;
-               if (st&p2_busy2) current_drive->status_bits |= p1_busy;
-               if (st&p2_spinning) current_drive->status_bits |= p1_spinning;
-               if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked;
-               if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok;
-       }
-       return;
-}
-/*==========================================================================*/
-static int cmd_out_T(void);
-
-static int get_state_T(void)
-{
-       int i;
-
-       clr_cmdbuf();
-       current_drive->n_bytes=1;
-       drvcmd[0]=CMDT_STATUS;
-       i=cmd_out_T();
-       if (i>=0) i=infobuf[0];
-       else
-       {
-               msg(DBG_TEA,"get_state_T error %d\n", i);
-               return (i);
-       }
-       if (i>=0)
-               /* 2: closed, disk in */
-               current_drive->status_bits=p1_door_closed|p1_disk_in|p1_spinning|p1_disk_ok;
-       else if (current_drive->error_state==6)
-       {
-               /* 3: closed, disk in, changed ("06 xx xx") */
-               current_drive->status_bits=p1_door_closed|p1_disk_in;
-               current_drive->CD_changed=0xFF;
-               current_drive->diskstate_flags &= ~toc_bit;
-       }
-       else if ((current_drive->error_state!=2)||(current_drive->b3!=0x3A)||(current_drive->b4==0x00))
-       {
-               /* 1: closed, no disk ("xx yy zz"or "02 3A 00") */
-               current_drive->status_bits=p1_door_closed;
-               current_drive->open_count=0;
-       }
-       else if (current_drive->b4==0x01)
-       {
-               /* 0: open ("02 3A 01") */
-               current_drive->status_bits=0;
-               current_drive->open_count=0;
-       }
-       else
-       {
-               /* 1: closed, no disk ("02 3A xx") */
-               current_drive->status_bits=p1_door_closed;
-               current_drive->open_count=0;
-       }
-       return (current_drive->status_bits);
-}
-/*==========================================================================*/
-static int ResponseStatus(void)
-{
-       int i,j;
-       u_long timeout;
-       
-       msg(DBG_STA,"doing ResponseStatus...\n");
-       if (famT_drive) return (get_state_T());
-       if (flags_cmd_out & f_respo3) timeout = jiffies;
-       else if (flags_cmd_out & f_respo2) timeout = jiffies + 16*HZ;
-       else timeout = jiffies + 4*HZ;
-       j=maxtim_8;
-       do
-       {
-               for ( ;j!=0;j--)
-               { 
-                       i=inb(CDi_status);
-                       if (!(i&s_not_result_ready)) break;
-               }
-               if ((j!=0)||time_after(jiffies, timeout)) break;
-               sbp_sleep(1);
-               j = 1;
-       }
-       while (1);
-       if (j==0) 
-       {
-               if ((flags_cmd_out & f_respo3) == 0)
-                       msg(DBG_STA,"ResponseStatus: timeout.\n");
-               current_drive->status_bits=0;
-               return (-401);
-       }
-       i=inb(CDi_info);
-       msg(DBG_STA,"ResponseStatus: response %02X.\n", i);
-       EvaluateStatus(i);
-       msg(DBG_STA,"status_bits=%02X, i=%02X\n",current_drive->status_bits,i);
-       return (current_drive->status_bits);
-}
-/*==========================================================================*/
-static void cc_ReadStatus(void)
-{
-       int i;
-       
-       msg(DBG_STA,"giving cc_ReadStatus command\n");
-       if (famT_drive) return;
-       SBPCD_CLI;
-       if (fam0LV_drive) OUT(CDo_command,CMD0_STATUS);
-       else if (fam1_drive) OUT(CDo_command,CMD1_STATUS);
-       else if (fam2_drive) OUT(CDo_command,CMD2_STATUS);
-       if (!fam0LV_drive) for (i=0;i<6;i++) OUT(CDo_command,0);
-       SBPCD_STI;
-}
-/*==========================================================================*/
-static int cc_ReadError(void)
-{
-       int i;
-
-       clr_cmdbuf();
-       msg(DBG_ERR,"giving cc_ReadError command.\n");
-       if (fam1_drive)
-       {
-               drvcmd[0]=CMD1_READ_ERR;
-               response_count=8;
-               flags_cmd_out=f_putcmd|f_ResponseStatus;
-       }
-       else if (fam0LV_drive)
-       {
-               drvcmd[0]=CMD0_READ_ERR;
-               response_count=6;
-               if (famLV_drive)
-                       flags_cmd_out=f_putcmd;
-               else
-                       flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus;
-       }
-       else if (fam2_drive)
-       {
-               drvcmd[0]=CMD2_READ_ERR;
-               response_count=6;
-               flags_cmd_out=f_putcmd;
-       }
-       else if (famT_drive)
-       {
-               response_count=5;
-               drvcmd[0]=CMDT_READ_ERR;
-       }
-       i=cmd_out();
-       current_drive->error_byte=0;
-       msg(DBG_ERR,"cc_ReadError: cmd_out(CMDx_READ_ERR) returns %d (%02X)\n",i,i);
-       if (i<0) return (i);
-       if (fam0V_drive) i=1;
-       else i=2;
-       current_drive->error_byte=infobuf[i];
-       msg(DBG_ERR,"cc_ReadError: infobuf[%d] is %d (%02X)\n",i,current_drive->error_byte,current_drive->error_byte);
-       i=sta2err(infobuf[i]);
-        if (i==-ERR_DISKCHANGE)
-        {
-                current_drive->CD_changed=0xFF;
-                current_drive->diskstate_flags &= ~toc_bit;
-        }
-       return (i);
-}
-/*==========================================================================*/
-static int cc_DriveReset(void);
-
-static int cmd_out_T(void)
-{
-#undef CMDT_TRIES
-#define CMDT_TRIES 1000
-#define TEST_FALSE_FF 1
-
-       int i, j, l=0, m, ntries;
-       unsigned long flags;
-
-       current_drive->error_state=0;
-       current_drive->b3=0;
-       current_drive->b4=0;
-       current_drive->f_drv_error=0;
-       for (i=0;i<10;i++) sprintf(&msgbuf[i*3]," %02X",drvcmd[i]);
-       msgbuf[i*3]=0;
-       msg(DBG_CMD,"cmd_out_T:%s\n",msgbuf);
-
-       OUT(CDo_sel_i_d,0);
-       OUT(CDo_enable,current_drive->drv_sel);
-       i=inb(CDi_status);
-       do_16bit=0;
-       if ((f_16bit)&&(!(i&0x80)))
-       {
-               do_16bit=1;
-               msg(DBG_TEA,"cmd_out_T: do_16bit set.\n");
-       }
-       if (!(i&s_not_result_ready))
-       do
-       {
-               j=inb(CDi_info);
-               i=inb(CDi_status);
-               sbp_sleep(0);
-               msg(DBG_TEA,"cmd_out_T: spurious !s_not_result_ready. (%02X)\n", j);
-       }
-       while (!(i&s_not_result_ready));
-       save_flags(flags); cli();
-       for (i=0;i<10;i++) OUT(CDo_command,drvcmd[i]);
-       restore_flags(flags);
-       for (ntries=CMDT_TRIES;ntries>0;ntries--)
-       {
-               if (drvcmd[0]==CMDT_READ_VER) sbp_sleep(HZ); /* fixme */
-#if 01
-               OUT(CDo_sel_i_d,1);
-#endif /* 01 */
-               if (teac==2)
-                  {
-                    if ((i=CDi_stat_loop_T()) == -1) break;
-                  }
-               else
-                  {
-#if 0
-                    OUT(CDo_sel_i_d,1);
-#endif /* 0 */ 
-                    i=inb(CDi_status);
-                  }
-               if (!(i&s_not_data_ready)) /* f.e. CMDT_DISKINFO */
-               {
-                       OUT(CDo_sel_i_d,1);
-                       if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */
-                       if (drvcmd[0]==CMDT_DISKINFO)
-                       {
-                               l=0;
-                               do
-                                {
-                                        if (do_16bit)
-                                        {
-                                                i=inw(CDi_data);
-                                                infobuf[l++]=i&0x0ff;
-                                                infobuf[l++]=i>>8;
-#if TEST_FALSE_FF
-                                                if ((l==2)&&(infobuf[0]==0x0ff))
-                                                {
-                                                        infobuf[0]=infobuf[1];
-                                                        l=1;
-                                                        msg(DBG_TEA,"cmd_out_T: do_16bit: false first byte!\n");
-                                                }
-#endif /* TEST_FALSE_FF */ 
-                                        }
-                                        else infobuf[l++]=inb(CDi_data);
-                                        i=inb(CDi_status);
-                                }
-                               while (!(i&s_not_data_ready));
-                               for (j=0;j<l;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
-                               msgbuf[j*3]=0;
-                               msg(DBG_CMD,"cmd_out_T data response:%s\n", msgbuf);
-                       }
-                       else
-                       {
-                               msg(DBG_TEA,"cmd_out_T: data response with cmd_%02X!\n",
-                                    drvcmd[0]);
-                               j=0;
-                               do
-                               {
-                                        if (do_16bit) i=inw(CDi_data);
-                                        else i=inb(CDi_data);
-                                        j++;
-                                        i=inb(CDi_status);
-                               }
-                               while (!(i&s_not_data_ready));
-                               msg(DBG_TEA,"cmd_out_T: data response: discarded %d bytes/words.\n", j);
-                               fatal_err++;
-                       }
-               }
-               i=inb(CDi_status);
-               if (!(i&s_not_result_ready))
-               {
-                       OUT(CDo_sel_i_d,0);
-                       if (drvcmd[0]==CMDT_DISKINFO) m=l;
-                       else m=0;
-                       do
-                       {
-                               infobuf[m++]=inb(CDi_info);
-                               i=inb(CDi_status);
-                       }
-                       while (!(i&s_not_result_ready));
-                       for (j=0;j<m;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
-                       msgbuf[j*3]=0;
-                       msg(DBG_CMD,"cmd_out_T info response:%s\n", msgbuf);
-                       if (drvcmd[0]==CMDT_DISKINFO)
-                        {
-                                infobuf[0]=infobuf[l];
-                                if (infobuf[0]!=0x02) return (l); /* data length */
-                        }
-                       else if (infobuf[0]!=0x02) return (m); /* info length */
-                       do
-                       {
-                               ++recursion;
-                               if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (%02X): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", drvcmd[0], recursion);
-                               clr_cmdbuf();
-                               drvcmd[0]=CMDT_READ_ERR;
-                               j=cmd_out_T(); /* !!! recursive here !!! */
-                               --recursion;
-                               sbp_sleep(1);
-                       }
-                       while (j<0);
-                       current_drive->error_state=infobuf[2];
-                       current_drive->b3=infobuf[3];
-                       current_drive->b4=infobuf[4];
-                       if (current_drive->f_drv_error)
-                       {
-                               current_drive->f_drv_error=0;
-                               cc_DriveReset();
-                               current_drive->error_state=2;
-                       }
-                       return (-current_drive->error_state-400);
-               }
-               if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */
-               if ((teac==0)||(ntries<(CMDT_TRIES-5))) sbp_sleep(HZ/10);
-               else sbp_sleep(HZ/100);
-               if (ntries>(CMDT_TRIES-50)) continue;
-               msg(DBG_TEA,"cmd_out_T: next CMDT_TRIES (%02X): %d.\n", drvcmd[0], ntries-1);
-       }
-       current_drive->f_drv_error=1;
-       cc_DriveReset();
-       current_drive->error_state=2;
-       return (-99);
-}
-/*==========================================================================*/
-static int cmd_out(void)
-{
-       int i=0;
-       
-       if (famT_drive) return(cmd_out_T());
-       
-       if (flags_cmd_out&f_putcmd)
-       { 
-               unsigned long flags;
-               for (i=0;i<7;i++)
-                       sprintf(&msgbuf[i*3], " %02X", drvcmd[i]);
-               msgbuf[i*3]=0;
-               msg(DBG_CMD,"cmd_out:%s\n", msgbuf);
-               save_flags(flags); cli();
-               for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]);
-               restore_flags(flags);
-       }
-       if (response_count!=0)
-       {
-               if (cmd_type!=0)
-               {
-                       if (sbpro_type==1) OUT(CDo_sel_i_d,1);
-                       msg(DBG_INF,"misleaded to try ResponseData.\n");
-                       if (sbpro_type==1) OUT(CDo_sel_i_d,0);
-                       return (-22);
-               }
-               else i=ResponseInfo();
-               if (i<0) return (i);
-       }
-       if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to CDi_stat_loop.\n");
-       if (flags_cmd_out&f_lopsta)
-       {
-               i=CDi_stat_loop();
-               if ((i<0)||!(i&s_attention)) return (-8);
-       }
-       if (!(flags_cmd_out&f_getsta)) goto LOC_229;
-       
- LOC_228:
-       if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadStatus.\n");
-       cc_ReadStatus();
-       
- LOC_229:
-       if (flags_cmd_out&f_ResponseStatus) 
-       {
-               if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to ResponseStatus.\n");
-               i=ResponseStatus();
-               /* builds status_bits, returns orig. status or p_busy_new */
-               if (i<0) return (i);
-               if (flags_cmd_out&(f_bit1|f_wait_if_busy))
-               {
-                       if (!st_check)
-                       {
-                               if ((flags_cmd_out&f_bit1)&&(i&p_success)) goto LOC_232;
-                               if ((!(flags_cmd_out&f_wait_if_busy))||(!st_busy)) goto LOC_228;
-                       }
-               }
-       }
- LOC_232:
-       if (!(flags_cmd_out&f_obey_p_check)) return (0);
-       if (!st_check) return (0);
-       if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadError.\n");
-       i=cc_ReadError();
-       if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cmd_out OK.\n");
-       msg(DBG_000,"cmd_out: cc_ReadError=%d\n", i);
-       return (i);
-}
-/*==========================================================================*/
-static int cc_Seek(u_int pos, char f_blk_msf)
-{
-       int i;
-       
-  clr_cmdbuf();
-       if (f_blk_msf>1) return (-3);
-       if (fam0V_drive)
-       {
-               drvcmd[0]=CMD0_SEEK;
-               if (f_blk_msf==1) pos=msf2blk(pos);
-               drvcmd[2]=(pos>>16)&0x00FF;
-               drvcmd[3]=(pos>>8)&0x00FF;
-               drvcmd[4]=pos&0x00FF;
-               if (fam0_drive)
-                 flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
-                       f_ResponseStatus | f_obey_p_check | f_bit1;
-               else
-                 flags_cmd_out = f_putcmd;
-       }
-       else if (fam1L_drive)
-       {
-               drvcmd[0]=CMD1_SEEK; /* same as CMD1_ and CMDL_ */
-               if (f_blk_msf==0) pos=blk2msf(pos);
-               drvcmd[1]=(pos>>16)&0x00FF;
-               drvcmd[2]=(pos>>8)&0x00FF;
-               drvcmd[3]=pos&0x00FF;
-               if (famL_drive)
-                       flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-               else
-                       flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (fam2_drive)
-       {
-               drvcmd[0]=CMD2_SEEK;
-               if (f_blk_msf==0) pos=blk2msf(pos);
-               drvcmd[2]=(pos>>24)&0x00FF;
-               drvcmd[3]=(pos>>16)&0x00FF;
-               drvcmd[4]=(pos>>8)&0x00FF;
-               drvcmd[5]=pos&0x00FF;
-               flags_cmd_out=f_putcmd|f_ResponseStatus;
-       }
-       else if (famT_drive)
-       {
-               drvcmd[0]=CMDT_SEEK;
-               if (f_blk_msf==1) pos=msf2blk(pos);
-               drvcmd[2]=(pos>>24)&0x00FF;
-               drvcmd[3]=(pos>>16)&0x00FF;
-               drvcmd[4]=(pos>>8)&0x00FF;
-               drvcmd[5]=pos&0x00FF;
-               current_drive->n_bytes=1;
-       }
-       response_count=0;
-       i=cmd_out();
-       return (i);
-}
-/*==========================================================================*/
-static int cc_SpinUp(void)
-{
-       int i;
-       
-       msg(DBG_SPI,"SpinUp.\n");
-       current_drive->in_SpinUp = 1;
-       clr_cmdbuf();
-       if (fam0LV_drive)
-       {
-               drvcmd[0]=CMD0_SPINUP;
-               if (fam0L_drive)
-                 flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|
-                   f_ResponseStatus|f_obey_p_check|f_bit1;
-               else
-                 flags_cmd_out=f_putcmd;
-       }
-       else if (fam1_drive)
-       {
-               drvcmd[0]=CMD1_SPINUP;
-               flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (fam2_drive)
-       {
-               drvcmd[0]=CMD2_TRAY_CTL;
-               drvcmd[4]=0x01; /* "spinup" */
-               flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (famT_drive)
-       {
-               drvcmd[0]=CMDT_TRAY_CTL;
-               drvcmd[4]=0x03; /* "insert", it hopefully spins the drive up */
-       }
-       response_count=0;
-       i=cmd_out();
-       current_drive->in_SpinUp = 0;
-       return (i);
-}
-/*==========================================================================*/
-static int cc_SpinDown(void)
-{
-       int i;
-       
-       if (fam0_drive) return (0);
-       clr_cmdbuf();
-       response_count=0;
-       if (fam1_drive)
-       {
-               drvcmd[0]=CMD1_SPINDOWN;
-               flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (fam2_drive)
-       {
-               drvcmd[0]=CMD2_TRAY_CTL;
-               drvcmd[4]=0x02; /* "eject" */
-               flags_cmd_out=f_putcmd|f_ResponseStatus;
-       }
-       else if (famL_drive)
-       {
-               drvcmd[0]=CMDL_SPINDOWN;
-               drvcmd[1]=1;
-               flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-       }
-       else if (famV_drive)
-       {
-               drvcmd[0]=CMDV_SPINDOWN;
-               flags_cmd_out=f_putcmd;
-       }
-       else if (famT_drive)
-       {
-               drvcmd[0]=CMDT_TRAY_CTL;
-               drvcmd[4]=0x02; /* "eject" */
-       }
-       i=cmd_out();
-       return (i);
-}
-/*==========================================================================*/
-static int cc_get_mode_T(void)
-{
-       int i;
-       
-       clr_cmdbuf();
-       response_count=10;
-       drvcmd[0]=CMDT_GETMODE;
-       drvcmd[4]=response_count;
-       i=cmd_out_T();
-       return (i);
-}
-/*==========================================================================*/
-static int cc_set_mode_T(void)
-{
-       int i;
-       
-       clr_cmdbuf();
-       response_count=1;
-       drvcmd[0]=CMDT_SETMODE;
-       drvcmd[1]=current_drive->speed_byte;
-       drvcmd[2]=current_drive->frmsiz>>8;
-       drvcmd[3]=current_drive->frmsiz&0x0FF;
-       drvcmd[4]=current_drive->f_XA; /* 1: XA */
-       drvcmd[5]=current_drive->type_byte; /* 0, 1, 3 */
-       drvcmd[6]=current_drive->mode_xb_6;
-       drvcmd[7]=current_drive->mode_yb_7|current_drive->volume_control;
-       drvcmd[8]=current_drive->mode_xb_8;
-       drvcmd[9]=current_drive->delay;
-       i=cmd_out_T();
-       return (i);
-}
-/*==========================================================================*/
-static int cc_prep_mode_T(void)
-{
-       int i, j;
-       
-       i=cc_get_mode_T();
-       if (i<0) return (i);
-       for (i=0;i<10;i++)
-               sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-       msgbuf[i*3]=0;
-       msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf);
-       current_drive->speed_byte=0x02; /* 0x02: auto quad, 0x82: quad, 0x81: double, 0x80: single */
-       current_drive->frmsiz=make16(infobuf[2],infobuf[3]);
-       current_drive->f_XA=infobuf[4];
-       if (current_drive->f_XA==0) current_drive->type_byte=0;
-       else current_drive->type_byte=1;
-       current_drive->mode_xb_6=infobuf[6];
-       current_drive->mode_yb_7=1;
-       current_drive->mode_xb_8=infobuf[8];
-       current_drive->delay=0; /* 0, 1, 2, 3 */
-       j=cc_set_mode_T();
-       i=cc_get_mode_T();
-       for (i=0;i<10;i++)
-               sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-       msgbuf[i*3]=0;
-       msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf);
-       return (j);
-}
-/*==========================================================================*/
-static int cc_SetSpeed(u_char speed, u_char x1, u_char x2)
-{
-       int i;
-       
-       if (fam0LV_drive) return (0);
-       clr_cmdbuf();
-       response_count=0;
-       if (fam1_drive)
-       {
-               drvcmd[0]=CMD1_SETMODE;
-               drvcmd[1]=0x03;
-               drvcmd[2]=speed;
-               drvcmd[3]=x1;
-               drvcmd[4]=x2;
-               flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (fam2_drive)
-       {
-               drvcmd[0]=CMD2_SETSPEED;
-               if (speed&speed_auto)
-               {
-                       drvcmd[2]=0xFF;
-                       drvcmd[3]=0xFF;
-               }
-               else
-               {
-                       drvcmd[2]=0;
-                       drvcmd[3]=150;
-               }
-               flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (famT_drive)
-       {
-               return (0);
-       }
-       i=cmd_out();
-       return (i);
-}
-/*==========================================================================*/
-static int cc_SetVolume(void)
-{
-       int i;
-       u_char channel0,channel1,volume0,volume1;
-       u_char control0,value0,control1,value1;
-       
-       current_drive->diskstate_flags &= ~volume_bit;
-       clr_cmdbuf();
-       channel0=current_drive->vol_chan0;
-       volume0=current_drive->vol_ctrl0;
-       channel1=control1=current_drive->vol_chan1;
-       volume1=value1=current_drive->vol_ctrl1;
-       control0=value0=0;
-       
-       if (famV_drive) return (0);
-
-       if (((current_drive->drv_options&audio_mono)!=0)&&(current_drive->drv_type>=drv_211))
-       {
-               if ((volume0!=0)&&(volume1==0))
-               {
-                       volume1=volume0;
-                       channel1=channel0;
-               }
-               else if ((volume0==0)&&(volume1!=0))
-               {
-                       volume0=volume1;
-                       channel0=channel1;
-               }
-       }
-       if (channel0>1)
-       {
-               channel0=0;
-               volume0=0;
-       }
-       if (channel1>1)
-       {
-               channel1=1;
-               volume1=0;
-       }
-       
-       if (fam1_drive)
-       {
-               control0=channel0+1;
-               control1=channel1+1;
-               value0=(volume0>volume1)?volume0:volume1;
-               value1=value0;
-               if (volume0==0) control0=0;
-               if (volume1==0) control1=0;
-               drvcmd[0]=CMD1_SETMODE;
-               drvcmd[1]=0x05;
-               drvcmd[3]=control0;
-               drvcmd[4]=value0;
-               drvcmd[5]=control1;
-               drvcmd[6]=value1;
-               flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (fam2_drive)
-       {
-               control0=channel0+1;
-               control1=channel1+1;
-               value0=(volume0>volume1)?volume0:volume1;
-               value1=value0;
-               if (volume0==0) control0=0;
-               if (volume1==0) control1=0;
-               drvcmd[0]=CMD2_SETMODE;
-               drvcmd[1]=0x0E;
-               drvcmd[3]=control0;
-               drvcmd[4]=value0;
-               drvcmd[5]=control1;
-               drvcmd[6]=value1;
-               flags_cmd_out=f_putcmd|f_ResponseStatus;
-       }
-       else if (famL_drive)
-       {
-               if ((volume0==0)||(channel0!=0)) control0 |= 0x80;
-               if ((volume1==0)||(channel1!=1)) control0 |= 0x40;
-               if (volume0|volume1) value0=0x80;
-               drvcmd[0]=CMDL_SETMODE;
-               drvcmd[1]=0x03;
-               drvcmd[4]=control0;
-               drvcmd[5]=value0;
-               flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-       }
-       else if (fam0_drive) /* different firmware levels */
-       {
-               if (current_drive->drv_type>=drv_300)
-               {
-                       control0=volume0&0xFC;
-                       value0=volume1&0xFC;
-                       if ((volume0!=0)&&(volume0<4)) control0 |= 0x04;
-                       if ((volume1!=0)&&(volume1<4)) value0 |= 0x04;
-                       if (channel0!=0) control0 |= 0x01;
-                       if (channel1==1) value0 |= 0x01;
-               }
-               else
-               {
-                       value0=(volume0>volume1)?volume0:volume1;
-                       if (current_drive->drv_type<drv_211)
-                       {
-                               if (channel0!=0)
-                               {
-                                       i=channel1;
-                                       channel1=channel0;
-                                       channel0=i;
-                                       i=volume1;
-                                       volume1=volume0;
-                                       volume0=i;
-                               }
-                               if (channel0==channel1)
-                               {
-                                       if (channel0==0)
-                                       {
-                                               channel1=1;
-                                               volume1=0;
-                                               volume0=value0;
-                                       }
-                                       else
-                                       {
-                                               channel0=0;
-                                               volume0=0;
-                                               volume1=value0;
-                                       }
-                               }
-                       }
-                       
-                       if ((volume0!=0)&&(volume1!=0))
-                       {
-                               if (volume0==0xFF) volume1=0xFF;
-                               else if (volume1==0xFF) volume0=0xFF;
-                       }
-                       else if (current_drive->drv_type<drv_201) volume0=volume1=value0;
-                       
-                       if (current_drive->drv_type>=drv_201)
-                       {
-                               if (volume0==0) control0 |= 0x80;
-                               if (volume1==0) control0 |= 0x40;
-                       }
-                       if (current_drive->drv_type>=drv_211)
-                       {
-                               if (channel0!=0) control0 |= 0x20;
-                               if (channel1!=1) control0 |= 0x10;
-                       }
-               }
-               drvcmd[0]=CMD0_SETMODE;
-               drvcmd[1]=0x83;
-               drvcmd[4]=control0;
-               drvcmd[5]=value0;
-               flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (famT_drive)
-       {
-               current_drive->volume_control=0;
-               if (!volume0) current_drive->volume_control|=0x10;
-               if (!volume1) current_drive->volume_control|=0x20;
-               i=cc_prep_mode_T();
-               if (i<0) return (i);
-       }
-       if (!famT_drive)
-       {
-               response_count=0;
-               i=cmd_out();
-               if (i<0) return (i);
-       }
-       current_drive->diskstate_flags |= volume_bit;
-       return (0);
-}
-/*==========================================================================*/
-static int GetStatus(void)
-{
-       int i;
-       
-       if (famT_drive) return (0);
-       flags_cmd_out=f_getsta|f_ResponseStatus|f_obey_p_check;
-       response_count=0;
-       cmd_type=0;
-       i=cmd_out();
-       return (i);
-}
-/*==========================================================================*/
-static int cc_DriveReset(void)
-{
-       int i;
-       
-       msg(DBG_RES,"cc_DriveReset called.\n");
-       clr_cmdbuf();
-       response_count=0;
-       if (fam0LV_drive) OUT(CDo_reset,0x00);
-       else if (fam1_drive)
-       {
-               drvcmd[0]=CMD1_RESET;
-               flags_cmd_out=f_putcmd;
-               i=cmd_out();
-       }
-       else if (fam2_drive)
-       {
-               drvcmd[0]=CMD2_RESET;
-               flags_cmd_out=f_putcmd;
-               i=cmd_out();
-               OUT(CDo_reset,0x00);
-       }
-       else if (famT_drive)
-       {
-               OUT(CDo_sel_i_d,0);
-               OUT(CDo_enable,current_drive->drv_sel);
-               OUT(CDo_command,CMDT_RESET);
-               for (i=1;i<10;i++) OUT(CDo_command,0);
-       }
-       if (fam0LV_drive) sbp_sleep(5*HZ); /* wait 5 seconds */
-       else sbp_sleep(1*HZ); /* wait a second */
-#if 1
-       if (famT_drive)
-       {
-               msg(DBG_TEA, "================CMDT_RESET given=================.\n");
-               sbp_sleep(3*HZ);
-       }
-#endif /* 1 */ 
-       flush_status();
-       i=GetStatus();
-       if (i<0) return i;
-       if (!famT_drive)
-               if (current_drive->error_byte!=aud_12) return -501;
-       return (0);
-}
-
-/*==========================================================================*/
-static int SetSpeed(void)
-{
-       int i, speed;
-       
-       if (!(current_drive->drv_options&(speed_auto|speed_300|speed_150))) return (0);
-       speed=speed_auto;
-       if (!(current_drive->drv_options&speed_auto))
-       {
-               speed |= speed_300;
-               if (!(current_drive->drv_options&speed_300)) speed=0;
-       }
-       i=cc_SetSpeed(speed,0,0);
-       return (i);
-}
-
-static void switch_drive(struct sbpcd_drive *);
-
-static int sbpcd_select_speed(struct cdrom_device_info *cdi, int speed)
-{
-       struct sbpcd_drive *p = cdi->handle;
-       if (p != current_drive)
-               switch_drive(p);
-
-       return cc_SetSpeed(speed == 2 ? speed_300 : speed_150, 0, 0);
-}
-
-/*==========================================================================*/
-static int DriveReset(void)
-{
-       int i;
-       
-       i=cc_DriveReset();
-       if (i<0) return (-22);
-       do
-       {
-               i=GetStatus();
-               if ((i<0)&&(i!=-ERR_DISKCHANGE)) {
-                       return (-2); /* from sta2err */
-               }
-               if (!st_caddy_in) break;
-               sbp_sleep(1);
-       }
-       while (!st_diskok);
-#if 000
-       current_drive->CD_changed=1;
-#endif
-       if ((st_door_closed) && (st_caddy_in))
-       {
-               i=DiskInfo();
-               if (i<0) return (-23);
-       }
-       return (0);
-}
-
-static int sbpcd_reset(struct cdrom_device_info *cdi)
-{
-       struct sbpcd_drive *p = cdi->handle;
-       if (p != current_drive)
-               switch_drive(p);
-       return DriveReset();
-}
-
-/*==========================================================================*/
-static int cc_PlayAudio(int pos_audio_start,int pos_audio_end)
-{
-       int i, j, n;
-       
-       if (current_drive->audio_state==audio_playing) return (-EINVAL);
-       clr_cmdbuf();
-       response_count=0;
-       if (famLV_drive)
-       {
-               drvcmd[0]=CMDL_PLAY;
-               i=msf2blk(pos_audio_start);
-               n=msf2blk(pos_audio_end)+1-i;
-               drvcmd[1]=(i>>16)&0x00FF;
-               drvcmd[2]=(i>>8)&0x00FF;
-               drvcmd[3]=i&0x00FF;
-               drvcmd[4]=(n>>16)&0x00FF;
-               drvcmd[5]=(n>>8)&0x00FF;
-               drvcmd[6]=n&0x00FF;
-               if (famL_drive)
-               flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
-                       f_ResponseStatus | f_obey_p_check | f_wait_if_busy;
-               else
-                 flags_cmd_out = f_putcmd;
-       }
-       else
-       {
-               j=1;
-               if (fam1_drive)
-               {
-                       drvcmd[0]=CMD1_PLAY_MSF;
-                       flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus |
-                               f_obey_p_check | f_wait_if_busy;
-               }
-               else if (fam2_drive)
-               {
-                       drvcmd[0]=CMD2_PLAY_MSF;
-                       flags_cmd_out = f_putcmd | f_ResponseStatus | f_obey_p_check;
-               }
-               else if (famT_drive)
-               {
-                       drvcmd[0]=CMDT_PLAY_MSF;
-                       j=3;
-                       response_count=1;
-               }
-               else if (fam0_drive)
-               {
-                       drvcmd[0]=CMD0_PLAY_MSF;
-                       flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
-                               f_ResponseStatus | f_obey_p_check | f_wait_if_busy;
-               }
-               drvcmd[j]=(pos_audio_start>>16)&0x00FF;
-               drvcmd[j+1]=(pos_audio_start>>8)&0x00FF;
-               drvcmd[j+2]=pos_audio_start&0x00FF;
-               drvcmd[j+3]=(pos_audio_end>>16)&0x00FF;
-               drvcmd[j+4]=(pos_audio_end>>8)&0x00FF;
-               drvcmd[j+5]=pos_audio_end&0x00FF;
-       }
-       i=cmd_out();
-       return (i);
-}
-/*==========================================================================*/
-static int cc_Pause_Resume(int pau_res)
-{
-       int i;
-       
-       clr_cmdbuf();
-       response_count=0;
-       if (fam1_drive)
-       {
-               drvcmd[0]=CMD1_PAU_RES;
-               if (pau_res!=1) drvcmd[1]=0x80;
-               flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (fam2_drive)
-       {
-               drvcmd[0]=CMD2_PAU_RES;
-               if (pau_res!=1) drvcmd[2]=0x01;
-               flags_cmd_out=f_putcmd|f_ResponseStatus;
-       }
-       else if (fam0LV_drive)
-       {
-               drvcmd[0]=CMD0_PAU_RES;
-               if (pau_res!=1) drvcmd[1]=0x80;
-               if (famL_drive)
-                       flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|
-                               f_obey_p_check|f_bit1;
-               else if (famV_drive)
-                 flags_cmd_out=f_putcmd;
-               else
-                       flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|
-                               f_obey_p_check;
-       }
-       else if (famT_drive)
-       {
-               if (pau_res==3) return (cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end));
-               else if (pau_res==1) drvcmd[0]=CMDT_PAUSE;
-               else return (-56);
-       }
-       i=cmd_out();
-       return (i);
-}
-/*==========================================================================*/
-static int cc_LockDoor(char lock)
-{
-       int i;
-       
-       if (fam0_drive) return (0);
-       msg(DBG_LCK,"cc_LockDoor: %d (drive %d)\n", lock, current_drive - D_S);
-       msg(DBG_LCS,"p_door_locked bit %d before\n", st_door_locked);
-       clr_cmdbuf();
-       response_count=0;
-       if (fam1_drive)
-       {
-               drvcmd[0]=CMD1_LOCK_CTL;
-               if (lock==1) drvcmd[1]=0x01;
-               flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (fam2_drive)
-       {
-               drvcmd[0]=CMD2_LOCK_CTL;
-               if (lock==1) drvcmd[4]=0x01;
-               flags_cmd_out=f_putcmd|f_ResponseStatus;
-       }
-       else if (famLV_drive)
-       {
-               drvcmd[0]=CMDL_LOCK_CTL;
-               if (lock==1) drvcmd[1]=0x01;
-               if (famL_drive)
-                 flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-               else
-                 flags_cmd_out=f_putcmd;
-       }
-       else if (famT_drive)
-       {
-               drvcmd[0]=CMDT_LOCK_CTL;
-               if (lock==1) drvcmd[4]=0x01;
-       }
-       i=cmd_out();
-       msg(DBG_LCS,"p_door_locked bit %d after\n", st_door_locked);
-       return (i);
-}
-/*==========================================================================*/
-/*==========================================================================*/
-static int UnLockDoor(void)
-{
-       int i,j;
-       
-       j=20;
-       do
-       {
-               i=cc_LockDoor(0);
-               --j;
-               sbp_sleep(1);
-       }
-       while ((i<0)&&(j));
-       if (i<0)
-       {
-               cc_DriveReset();
-               return -84;
-       }
-       return (0);
-}
-/*==========================================================================*/
-static int LockDoor(void)
-{
-       int i,j;
-       
-       j=20;
-       do
-       {
-               i=cc_LockDoor(1);
-               --j;
-               sbp_sleep(1);
-       }
-       while ((i<0)&&(j));
-       if (j==0)
-       {               
-               cc_DriveReset();
-               j=20;
-               do
-               {
-                       i=cc_LockDoor(1);
-                       --j;
-                       sbp_sleep(1);
-               }
-               while ((i<0)&&(j));
-       }
-       return (i);
-}
-
-static int sbpcd_lock_door(struct cdrom_device_info *cdi, int lock)
-{
-  return lock ? LockDoor() : UnLockDoor();
-}
-
-/*==========================================================================*/
-static int cc_CloseTray(void)
-{
-       int i;
-       
-       if (fam0_drive) return (0);
-       msg(DBG_LCK,"cc_CloseTray (drive %d)\n", current_drive - D_S);
-       msg(DBG_LCS,"p_door_closed bit %d before\n", st_door_closed);
-       
-       clr_cmdbuf();
-       response_count=0;
-       if (fam1_drive)
-       {
-               drvcmd[0]=CMD1_TRAY_CTL;
-               flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (fam2_drive)
-       {
-               drvcmd[0]=CMD2_TRAY_CTL;
-               drvcmd[1]=0x01;
-               drvcmd[4]=0x03; /* "insert" */
-               flags_cmd_out=f_putcmd|f_ResponseStatus;
-       }
-       else if (famLV_drive)
-       {
-               drvcmd[0]=CMDL_TRAY_CTL;
-               if (famLV_drive)
-                 flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|
-                       f_ResponseStatus|f_obey_p_check|f_bit1;
-               else
-                 flags_cmd_out=f_putcmd;
-       }
-       else if (famT_drive)
-       {
-               drvcmd[0]=CMDT_TRAY_CTL;
-               drvcmd[4]=0x03; /* "insert" */
-       }
-       i=cmd_out();
-       msg(DBG_LCS,"p_door_closed bit %d after\n", st_door_closed);
-
-       i=cc_ReadError();
-       flags_cmd_out |= f_respo2;
-       cc_ReadStatus(); /* command: give 1-byte status */
-       i=ResponseStatus();
-       if (famT_drive&&(i<0))
-       {
-               cc_DriveReset();
-               i=ResponseStatus();
-#if 0
-                sbp_sleep(HZ);
-#endif /* 0 */ 
-               i=ResponseStatus();
-       }
-       if (i<0)
-       {
-               msg(DBG_INF,"sbpcd cc_CloseTray: ResponseStatus timed out (%d).\n",i);
-       }
-       if (!(famT_drive))
-       {
-               if (!st_spinning)
-               {
-                       cc_SpinUp();
-                       if (st_check) i=cc_ReadError();
-                       flags_cmd_out |= f_respo2;
-                       cc_ReadStatus();
-                       i=ResponseStatus();
-               } else {
-               }
-       }
-       i=DiskInfo();
-       return (i);
-}
-
-static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position)
-{
-       int retval=0;
-       switch_drive(cdi->handle);
-       /* DUH! --AJK */
-       if(current_drive->CD_changed != 0xFF) {
-               current_drive->CD_changed=0xFF;
-               current_drive->diskstate_flags &= ~cd_size_bit;
-       }
-       if (position == 1) {
-               cc_SpinDown();
-       } else {
-               retval=cc_CloseTray();
-       }
-  return retval;
-}
-
-/*==========================================================================*/
-static int cc_ReadSubQ(void)
-{
-       int i,j;
-
-       current_drive->diskstate_flags &= ~subq_bit;
-       for (j=255;j>0;j--)
-       {
-               clr_cmdbuf();
-               if (fam1_drive)
-               {
-                       drvcmd[0]=CMD1_READSUBQ;
-                       flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-                       response_count=11;
-               }
-               else if (fam2_drive)
-               {
-                       drvcmd[0]=CMD2_READSUBQ;
-                       drvcmd[1]=0x02;
-                       drvcmd[3]=0x01;
-                       flags_cmd_out=f_putcmd;
-                       response_count=10;
-               }
-               else if (fam0LV_drive)
-               {
-                       drvcmd[0]=CMD0_READSUBQ;
-                       drvcmd[1]=0x02;
-                       if (famLV_drive)
-                               flags_cmd_out=f_putcmd;
-                       else
-                               flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-                       response_count=13;
-               }
-               else if (famT_drive)
-               {
-                       response_count=12;
-                       drvcmd[0]=CMDT_READSUBQ;
-                       drvcmd[1]=0x02;
-                       drvcmd[2]=0x40;
-                       drvcmd[3]=0x01;
-                       drvcmd[8]=response_count;
-               }
-               i=cmd_out();
-               if (i<0) return (i);
-               for (i=0;i<response_count;i++)
-               {
-                       sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-                       msgbuf[i*3]=0;
-                       msg(DBG_SQ1,"cc_ReadSubQ:%s\n", msgbuf);
-               }
-               if (famT_drive) break;
-               if (infobuf[0]!=0) break;
-               if ((!st_spinning) || (j==1))
-               {
-                       current_drive->SubQ_ctl_adr=current_drive->SubQ_trk=current_drive->SubQ_pnt_idx=current_drive->SubQ_whatisthis=0;
-                       current_drive->SubQ_run_tot=current_drive->SubQ_run_trk=0;
-                       return (0);
-               }
-       }
-       if (famT_drive) current_drive->SubQ_ctl_adr=infobuf[1];
-       else current_drive->SubQ_ctl_adr=swap_nibbles(infobuf[1]);
-       current_drive->SubQ_trk=byt2bcd(infobuf[2]);
-       current_drive->SubQ_pnt_idx=byt2bcd(infobuf[3]);
-       if (fam0LV_drive) i=5;
-       else if (fam12_drive) i=4;
-       else if (famT_drive) i=8;
-       current_drive->SubQ_run_tot=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
-       i=7;
-       if (fam0LV_drive) i=9;
-       else if (fam12_drive) i=7;
-       else if (famT_drive) i=4;
-       current_drive->SubQ_run_trk=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
-       current_drive->SubQ_whatisthis=infobuf[i+3];
-       current_drive->diskstate_flags |= subq_bit;
-       return (0);
-}
-/*==========================================================================*/
-static int cc_ModeSense(void)
-{
-       int i;
-       
-       if (fam2_drive) return (0);
-       if (famV_drive) return (0);
-       current_drive->diskstate_flags &= ~frame_size_bit;
-       clr_cmdbuf();
-       if (fam1_drive)
-       {
-               response_count=5;
-               drvcmd[0]=CMD1_GETMODE;
-               flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (fam0L_drive)
-       {
-               response_count=2;
-               drvcmd[0]=CMD0_GETMODE;
-               if (famL_drive) flags_cmd_out=f_putcmd;
-               else flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (famT_drive)
-       {
-               response_count=10;
-               drvcmd[0]=CMDT_GETMODE;
-               drvcmd[4]=response_count;
-       }
-       i=cmd_out();
-       if (i<0) return (i);
-       i=0;
-       current_drive->sense_byte=0;
-       if (fam1_drive) current_drive->sense_byte=infobuf[i++];
-       else if (famT_drive)
-       {
-               if (infobuf[4]==0x01) current_drive->xa_byte=0x20;
-               else current_drive->xa_byte=0;
-               i=2;
-       }
-       current_drive->frame_size=make16(infobuf[i],infobuf[i+1]);
-       for (i=0;i<response_count;i++)
-               sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-       msgbuf[i*3]=0;
-       msg(DBG_XA1,"cc_ModeSense:%s\n", msgbuf);
-       
-       current_drive->diskstate_flags |= frame_size_bit;
-       return (0);
-}
-/*==========================================================================*/
-/*==========================================================================*/
-static int cc_ModeSelect(int framesize)
-{
-       int i;
-       
-       if (fam2_drive) return (0);
-       if (famV_drive) return (0);
-       current_drive->diskstate_flags &= ~frame_size_bit;
-       clr_cmdbuf();
-       current_drive->frame_size=framesize;
-       if (framesize==CD_FRAMESIZE_RAW) current_drive->sense_byte=0x82;
-       else current_drive->sense_byte=0x00;
-       
-       msg(DBG_XA1,"cc_ModeSelect: %02X %04X\n",
-           current_drive->sense_byte, current_drive->frame_size);
-       
-       if (fam1_drive)
-       {
-               drvcmd[0]=CMD1_SETMODE;
-               drvcmd[1]=0x00;
-               drvcmd[2]=current_drive->sense_byte;
-               drvcmd[3]=(current_drive->frame_size>>8)&0xFF;
-               drvcmd[4]=current_drive->frame_size&0xFF;
-               flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (fam0L_drive)
-       {
-               drvcmd[0]=CMD0_SETMODE;
-               drvcmd[1]=0x00;
-               drvcmd[2]=(current_drive->frame_size>>8)&0xFF;
-               drvcmd[3]=current_drive->frame_size&0xFF;
-               drvcmd[4]=0x00;
-               if(famL_drive)
-                       flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check;
-               else
-                       flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (famT_drive)
-       {
-               return (-1);
-       }
-       response_count=0;
-       i=cmd_out();
-       if (i<0) return (i);
-       current_drive->diskstate_flags |= frame_size_bit;
-       return (0);
-}
-/*==========================================================================*/
-static int cc_GetVolume(void)
-{
-       int i;
-       u_char switches;
-       u_char chan0=0;
-       u_char vol0=0;
-       u_char chan1=1;
-       u_char vol1=0;
-       
-       if (famV_drive) return (0);
-       current_drive->diskstate_flags &= ~volume_bit;
-       clr_cmdbuf();
-       if (fam1_drive)
-       {
-               drvcmd[0]=CMD1_GETMODE;
-               drvcmd[1]=0x05;
-               response_count=5;
-               flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (fam2_drive)
-       {
-               drvcmd[0]=CMD2_GETMODE;
-               drvcmd[1]=0x0E;
-               response_count=5;
-               flags_cmd_out=f_putcmd;
-       }
-       else if (fam0L_drive)
-       {
-               drvcmd[0]=CMD0_GETMODE;
-               drvcmd[1]=0x03;
-               response_count=2;
-               if(famL_drive)
-                       flags_cmd_out=f_putcmd;
-               else
-                       flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (famT_drive)
-       {
-               i=cc_get_mode_T();
-               if (i<0) return (i);
-       }
-       if (!famT_drive)
-       {
-               i=cmd_out();
-               if (i<0) return (i);
-       }
-       if (fam1_drive)
-       {
-               chan0=infobuf[1]&0x0F;
-               vol0=infobuf[2];
-               chan1=infobuf[3]&0x0F;
-               vol1=infobuf[4];
-               if (chan0==0)
-               {
-                       chan0=1;
-                       vol0=0;
-               }
-               if (chan1==0)
-               {
-                       chan1=2;
-                       vol1=0;
-               }
-               chan0 >>= 1;
-               chan1 >>= 1;
-       }
-       else if (fam2_drive)
-       {
-               chan0=infobuf[1];
-               vol0=infobuf[2];
-               chan1=infobuf[3];
-               vol1=infobuf[4];
-       }
-       else if (famL_drive)
-       {
-               chan0=0;
-               chan1=1;
-               vol0=vol1=infobuf[1];
-               switches=infobuf[0];
-               if ((switches&0x80)!=0) chan0=1;
-               if ((switches&0x40)!=0) chan1=0;
-       }
-       else if (fam0_drive) /* different firmware levels */
-       {
-               chan0=0;
-               chan1=1;
-               vol0=vol1=infobuf[1];
-               if (current_drive->drv_type>=drv_201)
-               {
-                       if (current_drive->drv_type<drv_300)
-                       {
-                               switches=infobuf[0];
-                               if ((switches&0x80)!=0) vol0=0;
-                               if ((switches&0x40)!=0) vol1=0;
-                               if (current_drive->drv_type>=drv_211)
-                               {
-                                       if ((switches&0x20)!=0) chan0=1;
-                                       if ((switches&0x10)!=0) chan1=0;
-                               }
-                       }
-                       else
-                       {
-                               vol0=infobuf[0];
-                               if ((vol0&0x01)!=0) chan0=1;
-                               if ((vol1&0x01)==0) chan1=0;
-                               vol0 &= 0xFC;
-                               vol1 &= 0xFC;
-                               if (vol0!=0) vol0 += 3;
-                               if (vol1!=0) vol1 += 3;
-                       }
-               }
-       }
-       else if (famT_drive)
-       {
-               current_drive->volume_control=infobuf[7];
-               chan0=0;
-               chan1=1;
-               if (current_drive->volume_control&0x10) vol0=0;
-               else vol0=0xff;
-               if (current_drive->volume_control&0x20) vol1=0;
-               else vol1=0xff;
-       }
-       current_drive->vol_chan0=chan0;
-       current_drive->vol_ctrl0=vol0;
-       current_drive->vol_chan1=chan1;
-       current_drive->vol_ctrl1=vol1;
-#if 000
-       current_drive->vol_chan2=2;
-       current_drive->vol_ctrl2=0xFF;
-       current_drive->vol_chan3=3;
-       current_drive->vol_ctrl3=0xFF;
-#endif /*  000 */
-       current_drive->diskstate_flags |= volume_bit;
-       return (0);
-}
-/*==========================================================================*/
-static int cc_ReadCapacity(void)
-{
-       int i, j;
-       
-       if (fam2_drive) return (0); /* some firmware lacks this command */
-       if (famLV_drive) return (0); /* some firmware lacks this command */
-       if (famT_drive) return (0); /* done with cc_ReadTocDescr() */
-       current_drive->diskstate_flags &= ~cd_size_bit;
-       for (j=3;j>0;j--)
-       {
-               clr_cmdbuf();
-               if (fam1_drive)
-               {
-                       drvcmd[0]=CMD1_CAPACITY;
-                       response_count=5;
-                       flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-               }
-#if 00
-               else if (fam2_drive)
-               {
-                       drvcmd[0]=CMD2_CAPACITY;
-                       response_count=8;
-                       flags_cmd_out=f_putcmd;
-               }
-#endif
-               else if (fam0_drive)
-               {
-                       drvcmd[0]=CMD0_CAPACITY;
-                       response_count=5;
-                       flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-               }
-               i=cmd_out();
-               if (i>=0) break;
-               msg(DBG_000,"cc_ReadCapacity: cmd_out: err %d\n", i);
-               cc_ReadError();
-       }
-       if (j==0) return (i);
-       if (fam1_drive) current_drive->CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_MSF_OFFSET;
-       else if (fam0_drive) current_drive->CDsize_frm=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2]));
-#if 00
-       else if (fam2_drive) current_drive->CDsize_frm=make32(make16(infobuf[0],infobuf[1]),make16(infobuf[2],infobuf[3]));
-#endif
-       current_drive->diskstate_flags |= cd_size_bit;
-       msg(DBG_000,"cc_ReadCapacity: %d frames.\n", current_drive->CDsize_frm);
-       return (0);
-}
-/*==========================================================================*/
-static int cc_ReadTocDescr(void)
-{
-       int i;
-       
-       current_drive->diskstate_flags &= ~toc_bit;
-       clr_cmdbuf();
-       if (fam1_drive)
-       {
-               drvcmd[0]=CMD1_DISKINFO;
-               response_count=6;
-               flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (fam0LV_drive)
-       {
-               drvcmd[0]=CMD0_DISKINFO;
-               response_count=6;
-               if(famLV_drive)
-                       flags_cmd_out=f_putcmd;
-               else
-                       flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (fam2_drive)
-       {
-               /* possibly longer timeout periods necessary */
-               current_drive->f_multisession=0;
-               drvcmd[0]=CMD2_DISKINFO;
-               drvcmd[1]=0x02;
-               drvcmd[2]=0xAB;
-               drvcmd[3]=0xFF; /* session */
-               response_count=8;
-               flags_cmd_out=f_putcmd;
-       }
-       else if (famT_drive)
-       {
-               current_drive->f_multisession=0;
-               response_count=12;
-               drvcmd[0]=CMDT_DISKINFO;
-               drvcmd[1]=0x02;
-               drvcmd[6]=CDROM_LEADOUT;
-               drvcmd[8]=response_count;
-               drvcmd[9]=0x00;
-       }
-       i=cmd_out();
-       if (i<0) return (i);
-       if ((famT_drive)&&(i<response_count)) return (-100-i);
-       if ((fam1_drive)||(fam2_drive)||(fam0LV_drive))
-               current_drive->xa_byte=infobuf[0];
-       if (fam2_drive)
-       {
-               current_drive->first_session=infobuf[1];
-               current_drive->last_session=infobuf[2];
-               current_drive->n_first_track=infobuf[3];
-               current_drive->n_last_track=infobuf[4];
-               if (current_drive->first_session!=current_drive->last_session)
-               {
-                       current_drive->f_multisession=1;
-                       current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7])));
-               }
-#if 0
-               if (current_drive->first_session!=current_drive->last_session)
-               {
-                       if (current_drive->last_session<=20)
-                               zwanzig=current_drive->last_session+1;
-                       else zwanzig=20;
-                       for (count=current_drive->first_session;count<zwanzig;count++)
-                       {
-                               drvcmd[0]=CMD2_DISKINFO;
-                               drvcmd[1]=0x02;
-                               drvcmd[2]=0xAB;
-                               drvcmd[3]=count;
-                               response_count=8;
-                               flags_cmd_out=f_putcmd;
-                               i=cmd_out();
-                               if (i<0) return (i);
-                               current_drive->msf_multi_n[count]=make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7]));
-                       }
-                       current_drive->diskstate_flags |= multisession_bit;
-               }
-#endif
-               drvcmd[0]=CMD2_DISKINFO;
-               drvcmd[1]=0x02;
-               drvcmd[2]=0xAA;
-               drvcmd[3]=0xFF;
-               response_count=5;
-               flags_cmd_out=f_putcmd;
-               i=cmd_out();
-               if (i<0) return (i);
-               current_drive->size_msf=make32(make16(0,infobuf[2]),make16(infobuf[3],infobuf[4]));
-               current_drive->size_blk=msf2blk(current_drive->size_msf);
-               current_drive->CDsize_frm=current_drive->size_blk+1;
-       }
-       else if (famT_drive)
-       {
-               current_drive->size_msf=make32(make16(infobuf[8],infobuf[9]),make16(infobuf[10],infobuf[11]));
-               current_drive->size_blk=msf2blk(current_drive->size_msf);
-               current_drive->CDsize_frm=current_drive->size_blk+1;
-               current_drive->n_first_track=infobuf[2];
-               current_drive->n_last_track=infobuf[3];
-       }
-       else
-       {
-               current_drive->n_first_track=infobuf[1];
-               current_drive->n_last_track=infobuf[2];
-               current_drive->size_msf=make32(make16(0,infobuf[3]),make16(infobuf[4],infobuf[5]));
-               current_drive->size_blk=msf2blk(current_drive->size_msf);
-               if (famLV_drive) current_drive->CDsize_frm=current_drive->size_blk+1;
-       }
-       current_drive->diskstate_flags |= toc_bit;
-       msg(DBG_TOC,"TocDesc: xa %02X firstt %02X lastt %02X size %08X firstses %02X lastsess %02X\n",
-           current_drive->xa_byte,
-           current_drive->n_first_track,
-           current_drive->n_last_track,
-           current_drive->size_msf,
-           current_drive->first_session,
-           current_drive->last_session);
-       return (0);
-}
-/*==========================================================================*/
-static int cc_ReadTocEntry(int num)
-{
-       int i;
-       
-       clr_cmdbuf();
-       if (fam1_drive)
-       {
-               drvcmd[0]=CMD1_READTOC;
-               drvcmd[2]=num;
-               response_count=8;
-               flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (fam2_drive)
-       {
-               /* possibly longer timeout periods necessary */
-               drvcmd[0]=CMD2_DISKINFO;
-               drvcmd[1]=0x02;
-               drvcmd[2]=num;
-               response_count=5;
-               flags_cmd_out=f_putcmd;
-       }
-       else if (fam0LV_drive)
-       {
-               drvcmd[0]=CMD0_READTOC;
-               drvcmd[1]=0x02;
-               drvcmd[2]=num;
-               response_count=8;
-               if (famLV_drive)
-                       flags_cmd_out=f_putcmd;
-               else
-                 flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (famT_drive)
-       {
-               response_count=12;
-               drvcmd[0]=CMDT_DISKINFO;
-               drvcmd[1]=0x02;
-               drvcmd[6]=num;
-               drvcmd[8]=response_count;
-               drvcmd[9]=0x00;
-       }
-       i=cmd_out();
-       if (i<0) return (i);
-       if ((famT_drive)&&(i<response_count)) return (-100-i);
-       if ((fam1_drive)||(fam0LV_drive))
-       {
-               current_drive->TocEnt_nixbyte=infobuf[0];
-               i=1;
-       }
-       else if (fam2_drive) i=0;
-       else if (famT_drive) i=5;
-       current_drive->TocEnt_ctl_adr=swap_nibbles(infobuf[i++]);
-       if ((fam1_drive)||(fam0L_drive))
-       {
-               current_drive->TocEnt_number=infobuf[i++];
-               current_drive->TocEnt_format=infobuf[i];
-       }
-       else
-         {
-           current_drive->TocEnt_number=num;
-           current_drive->TocEnt_format=0;
-         }
-       if (fam1_drive) i=4;
-       else if (fam0LV_drive) i=5;
-       else if (fam2_drive) i=2;
-       else if (famT_drive) i=9;
-       current_drive->TocEnt_address=make32(make16(0,infobuf[i]),
-                                    make16(infobuf[i+1],infobuf[i+2]));
-       for (i=0;i<response_count;i++)
-               sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-       msgbuf[i*3]=0;
-       msg(DBG_ECS,"TocEntry:%s\n", msgbuf);
-       msg(DBG_TOC,"TocEntry: %02X %02X %02X %02X %08X\n",
-           current_drive->TocEnt_nixbyte, current_drive->TocEnt_ctl_adr,
-           current_drive->TocEnt_number, current_drive->TocEnt_format,
-           current_drive->TocEnt_address);
-       return (0);
-}
-/*==========================================================================*/
-static int cc_ReadPacket(void)
-{
-       int i;
-       
-       clr_cmdbuf();
-       drvcmd[0]=CMD0_PACKET;
-       drvcmd[1]=response_count;
-       if(famL_drive) flags_cmd_out=f_putcmd;
-       else if (fam01_drive)
-               flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-       else if (fam2_drive) return (-1); /* not implemented yet */
-       else if (famT_drive)
-       {
-               return (-1);
-       }
-       i=cmd_out();
-       return (i);
-}
-/*==========================================================================*/
-static int convert_UPC(u_char *p)
-{
-       int i;
-       
-       p++;
-       if (fam0L_drive) p[13]=0;
-       for (i=0;i<7;i++)
-       {
-               if (fam1_drive) current_drive->UPC_buf[i]=swap_nibbles(*p++);
-               else if (fam0L_drive)
-               {
-                       current_drive->UPC_buf[i]=((*p++)<<4)&0xFF;
-                       current_drive->UPC_buf[i] |= *p++;
-               }
-               else if (famT_drive)
-               {
-                       return (-1);
-               }
-               else /* CD200 */
-               {
-                       return (-1);
-               }
-       }
-       current_drive->UPC_buf[6] &= 0xF0;
-       return (0);
-}
-/*==========================================================================*/
-static int cc_ReadUPC(void)
-{
-       int i;
-#if TEST_UPC
-       int block, checksum;
-#endif /* TEST_UPC */ 
-       
-       if (fam2_drive) return (0); /* not implemented yet */
-       if (famT_drive) return (0); /* not implemented yet */
-       if (famV_drive) return (0); /* not implemented yet */
-#if 1
-       if (fam0_drive) return (0); /* but it should work */
-#endif
-       
-       current_drive->diskstate_flags &= ~upc_bit;
-#if TEST_UPC
-       for (block=CD_MSF_OFFSET+1;block<CD_MSF_OFFSET+200;block++)
-       {
-#endif /* TEST_UPC */ 
-               clr_cmdbuf();
-               if (fam1_drive)
-               {
-                       drvcmd[0]=CMD1_READ_UPC;
-#if TEST_UPC
-                       drvcmd[1]=(block>>16)&0xFF;
-                       drvcmd[2]=(block>>8)&0xFF;
-                       drvcmd[3]=block&0xFF;
-#endif /* TEST_UPC */ 
-                       response_count=8;
-                       flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-               }
-               else if (fam0L_drive)
-               {
-                       drvcmd[0]=CMD0_READ_UPC;
-#if TEST_UPC
-                       drvcmd[2]=(block>>16)&0xFF;
-                       drvcmd[3]=(block>>8)&0xFF;
-                       drvcmd[4]=block&0xFF;
-#endif /* TEST_UPC */ 
-                       response_count=0;
-                       flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-               }
-               else if (fam2_drive)
-               {
-                       return (-1);
-               }
-               else if (famT_drive)
-               {
-                       return (-1);
-               }
-               i=cmd_out();
-               if (i<0)
-               {
-                       msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i);
-                       return (i);
-               }
-               if (fam0L_drive)
-               {
-                       response_count=16;
-                       if (famL_drive) flags_cmd_out=f_putcmd;
-                       i=cc_ReadPacket();
-                       if (i<0)
-                       {
-                               msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i);
-                               return (i);
-                       }
-               }
-#if TEST_UPC
-               checksum=0;
-#endif /* TEST_UPC */ 
-               for (i=0;i<(fam1_drive?8:16);i++)
-               {
-#if TEST_UPC
-                       checksum |= infobuf[i];
-#endif /* TEST_UPC */ 
-                       sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-               }
-               msgbuf[i*3]=0;
-               msg(DBG_UPC,"UPC info:%s\n", msgbuf);
-#if TEST_UPC
-               if ((checksum&0x7F)!=0) break;
-       }
-#endif /* TEST_UPC */ 
-       current_drive->UPC_ctl_adr=0;
-       if (fam1_drive) i=0;
-       else i=2;
-       if ((infobuf[i]&0x80)!=0)
-       {
-               convert_UPC(&infobuf[i]);
-               current_drive->UPC_ctl_adr = (current_drive->TocEnt_ctl_adr & 0xF0) | 0x02;
-       }
-       for (i=0;i<7;i++)
-               sprintf(&msgbuf[i*3], " %02X", current_drive->UPC_buf[i]);
-       sprintf(&msgbuf[i*3], " (%02X)", current_drive->UPC_ctl_adr);
-       msgbuf[i*3+5]=0;
-       msg(DBG_UPC,"UPC code:%s\n", msgbuf);
-       current_drive->diskstate_flags |= upc_bit;
-       return (0);
-}
-
-static int sbpcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
-       int i;
-       unsigned char *mcnp = mcn->medium_catalog_number;
-       unsigned char *resp;
-
-       current_drive->diskstate_flags &= ~upc_bit;
-       clr_cmdbuf();
-       if (fam1_drive)
-       {
-               drvcmd[0]=CMD1_READ_UPC;
-               response_count=8;
-               flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-       }
-       else if (fam0L_drive)
-       {
-               drvcmd[0]=CMD0_READ_UPC;
-               response_count=0;
-               flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-       }
-       else if (fam2_drive)
-       {
-               return (-1);
-       }
-       else if (famT_drive)
-       {
-               return (-1);
-       }
-       i=cmd_out();
-       if (i<0)
-       {
-               msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i);
-               return (i);
-       }
-       if (fam0L_drive)
-       {
-               response_count=16;
-               if (famL_drive) flags_cmd_out=f_putcmd;
-               i=cc_ReadPacket();
-               if (i<0)
-               {
-                       msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i);
-                       return (i);
-               }
-       }
-       current_drive->UPC_ctl_adr=0;
-       if (fam1_drive) i=0;
-       else i=2;
-
-       resp = infobuf + i;
-       if (*resp++ == 0x80) {
-               /* packed bcd to single ASCII digits */
-               *mcnp++ = (*resp >> 4)     + '0';
-               *mcnp++ = (*resp++ & 0x0f) + '0';
-               *mcnp++ = (*resp >> 4)     + '0';
-               *mcnp++ = (*resp++ & 0x0f) + '0';
-               *mcnp++ = (*resp >> 4)     + '0';
-               *mcnp++ = (*resp++ & 0x0f) + '0';
-               *mcnp++ = (*resp >> 4)     + '0';
-               *mcnp++ = (*resp++ & 0x0f) + '0';
-               *mcnp++ = (*resp >> 4)     + '0';
-               *mcnp++ = (*resp++ & 0x0f) + '0';
-               *mcnp++ = (*resp >> 4)     + '0';
-               *mcnp++ = (*resp++ & 0x0f) + '0';
-               *mcnp++ = (*resp >> 4)     + '0';
-       }
-       *mcnp = '\0';
-
-       current_drive->diskstate_flags |= upc_bit;
-       return (0);
-}
-
-/*==========================================================================*/
-static int cc_CheckMultiSession(void)
-{
-       int i;
-       
-       if (fam2_drive) return (0);
-       current_drive->f_multisession=0;
-       current_drive->lba_multi=0;
-       if (fam0_drive) return (0);
-       clr_cmdbuf();
-       if (fam1_drive)
-       {
-               drvcmd[0]=CMD1_MULTISESS;
-               response_count=6;
-               flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-               i=cmd_out();
-               if (i<0) return (i);
-               if ((infobuf[0]&0x80)!=0)
-               {
-                       current_drive->f_multisession=1;
-                       current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[1]),
-                                                       make16(infobuf[2],infobuf[3])));
-               }
-       }
-       else if (famLV_drive)
-       {
-               drvcmd[0]=CMDL_MULTISESS;
-               drvcmd[1]=3;
-               drvcmd[2]=1;
-               response_count=8;
-               flags_cmd_out=f_putcmd;
-               i=cmd_out();
-               if (i<0) return (i);
-               current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),
-                                               make16(infobuf[6],infobuf[7])));
-       }
-       else if (famT_drive)
-       {
-               response_count=12;
-               drvcmd[0]=CMDT_DISKINFO;
-               drvcmd[1]=0x02;
-               drvcmd[6]=0;
-               drvcmd[8]=response_count;
-               drvcmd[9]=0x40;
-               i=cmd_out();
-               if (i<0) return (i);
-               if (i<response_count) return (-100-i);
-               current_drive->first_session=infobuf[2];
-               current_drive->last_session=infobuf[3];
-               current_drive->track_of_last_session=infobuf[6];
-               if (current_drive->first_session!=current_drive->last_session)
-               {
-                       current_drive->f_multisession=1;
-                       current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[9]),make16(infobuf[10],infobuf[11])));
-               }
-       }
-       for (i=0;i<response_count;i++)
-               sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-       msgbuf[i*3]=0;
-       msg(DBG_MUL,"MultiSession Info:%s (%d)\n", msgbuf, current_drive->lba_multi);
-       if (current_drive->lba_multi>200)
-       {
-               current_drive->f_multisession=1;
-               msg(DBG_MUL,"MultiSession base: %06X\n", current_drive->lba_multi);
-       }
-       return (0);
-}
-/*==========================================================================*/
-#ifdef FUTURE
-static int cc_SubChanInfo(int frame, int count, u_char *buffer)
-       /* "frame" is a RED BOOK (msf-bin) address */
-{
-       int i;
-       
-       if (fam0LV_drive) return (-ENOSYS); /* drive firmware lacks it */
-       if (famT_drive)
-       {
-               return (-1);
-       }
-#if 0
-       if (current_drive->audio_state!=audio_playing) return (-ENODATA);
-#endif
-       clr_cmdbuf();
-       drvcmd[0]=CMD1_SUBCHANINF;
-       drvcmd[1]=(frame>>16)&0xFF;
-       drvcmd[2]=(frame>>8)&0xFF;
-       drvcmd[3]=frame&0xFF;
-       drvcmd[5]=(count>>8)&0xFF;
-       drvcmd[6]=count&0xFF;
-       flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-       cmd_type=READ_SC;
-       current_drive->frame_size=CD_FRAMESIZE_SUB;
-       i=cmd_out(); /* which buffer to use? */
-       return (i);
-}
-#endif /* FUTURE */ 
-/*==========================================================================*/
-static void __init check_datarate(void)
-{
-       int i=0;
-       
-       msg(DBG_IOX,"check_datarate entered.\n");
-       datarate=0;
-#if TEST_STI
-       for (i=0;i<=1000;i++) printk(".");
-#endif
-       /* set a timer to make (timed_out_delay!=0) after 1.1 seconds */
-#if 1
-       del_timer(&delay_timer);
-#endif
-       delay_timer.expires=jiffies+11*HZ/10;
-       timed_out_delay=0;
-       add_timer(&delay_timer);
-#if 0
-       msg(DBG_TIM,"delay timer started (11*HZ/10).\n");
-#endif
-       do
-       {
-               i=inb(CDi_status);
-               datarate++;
-#if 1
-               if (datarate>0x6FFFFFFF) break;
-#endif 
-       }
-       while (!timed_out_delay);
-       del_timer(&delay_timer);
-#if 0
-       msg(DBG_TIM,"datarate: %04X\n", datarate);
-#endif
-       if (datarate<65536) datarate=65536;
-       maxtim16=datarate*16;
-       maxtim04=datarate*4;
-       maxtim02=datarate*2;
-       maxtim_8=datarate/32;
-#if LONG_TIMING
-       maxtim_data=datarate/100;
-#else
-       maxtim_data=datarate/300;
-#endif /* LONG_TIMING */ 
-#if 0
-       msg(DBG_TIM,"maxtim_8 %d, maxtim_data %d.\n", maxtim_8, maxtim_data);
-#endif
-}
-/*==========================================================================*/
-#if 0
-static int c2_ReadError(int fam)
-{
-       int i;
-       
-       clr_cmdbuf();
-       response_count=9;
-       clr_respo_buf(9);
-       if (fam==1)
-       {
-               drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */
-               i=do_cmd(f_putcmd|f_lopsta|f_getsta|f_ResponseStatus);
-       }
-       else if (fam==2)
-       {
-               drvcmd[0]=CMD2_READ_ERR;
-               i=do_cmd(f_putcmd);
-       }
-       else return (-1);
-       return (i);
-}
-#endif
-/*==========================================================================*/
-static void __init ask_mail(void)
-{
-       int i;
-       
-       msg(DBG_INF, "please mail the following lines to emoenke@gwdg.de\n");
-       msg(DBG_INF, "(don't mail if you are not using the actual kernel):\n");
-       msg(DBG_INF, "%s\n", VERSION);
-       msg(DBG_INF, "address %03X, type %s, drive %s (ID %d)\n",
-           CDo_command, type, current_drive->drive_model, current_drive->drv_id);
-       for (i=0;i<12;i++)
-               sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-       msgbuf[i*3]=0;
-       msg(DBG_INF,"infobuf =%s\n", msgbuf);
-       for (i=0;i<12;i++)
-               sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
-       msgbuf[i*3]=0;
-       msg(DBG_INF,"infobuf =%s\n", msgbuf);
-}
-/*==========================================================================*/
-static int __init check_version(void)
-{
-       int i, j, l;
-       int teac_possible=0;
-       
-       msg(DBG_INI,"check_version: id=%d, d=%d.\n", current_drive->drv_id, current_drive - D_S);
-       current_drive->drv_type=0;
-
-       /* check for CR-52x, CR-56x, LCS-7260 and ECS-AT */
-       /* clear any pending error state */
-       clr_cmdbuf();
-       drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */
-       response_count=9;
-       flags_cmd_out=f_putcmd;
-       i=cmd_out();
-       if (i<0) msg(DBG_INI,"CMD0_READ_ERR returns %d (ok anyway).\n",i);
-       /* read drive version */
-       clr_cmdbuf();
-       for (i=0;i<12;i++) infobuf[i]=0;
-       drvcmd[0]=CMD0_READ_VER; /* same as CMD1_ and CMDL_ */
-       response_count=12; /* fam1: only 11 */
-       flags_cmd_out=f_putcmd;
-       i=cmd_out();
-       if (i<-1) msg(DBG_INI,"CMD0_READ_VER returns %d\n",i);
-       if (i==-11) teac_possible++;
-       j=0;
-       for (i=0;i<12;i++) j+=infobuf[i];
-       if (j)
-       {
-               for (i=0;i<12;i++)
-                       sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-               msgbuf[i*3]=0;
-               msg(DBG_ECS,"infobuf =%s\n", msgbuf);
-               for (i=0;i<12;i++)
-                       sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
-               msgbuf[i*3]=0;
-               msg(DBG_ECS,"infobuf =%s\n", msgbuf);
-       }
-       for (i=0;i<4;i++) if (infobuf[i]!=family1[i]) break;
-       if (i==4)
-       {
-               current_drive->drive_model[0]='C';
-               current_drive->drive_model[1]='R';
-               current_drive->drive_model[2]='-';
-               current_drive->drive_model[3]='5';
-               current_drive->drive_model[4]=infobuf[i++];
-               current_drive->drive_model[5]=infobuf[i++];
-               current_drive->drive_model[6]=0;
-               current_drive->drv_type=drv_fam1;
-       }
-       if (!current_drive->drv_type)
-       {
-               for (i=0;i<8;i++) if (infobuf[i]!=family0[i]) break;
-               if (i==8)
-               {
-                       current_drive->drive_model[0]='C';
-                       current_drive->drive_model[1]='R';
-                       current_drive->drive_model[2]='-';
-                       current_drive->drive_model[3]='5';
-                       current_drive->drive_model[4]='2';
-                       current_drive->drive_model[5]='x';
-                       current_drive->drive_model[6]=0;
-                       current_drive->drv_type=drv_fam0;
-               }
-       }
-       if (!current_drive->drv_type)
-       {
-               for (i=0;i<8;i++) if (infobuf[i]!=familyL[i]) break;
-               if (i==8)
-               {
-                       for (j=0;j<8;j++)
-                               current_drive->drive_model[j]=infobuf[j];
-                       current_drive->drive_model[8]=0;
-                       current_drive->drv_type=drv_famL;
-               }
-       }
-       if (!current_drive->drv_type)
-       {
-               for (i=0;i<6;i++) if (infobuf[i]!=familyV[i]) break;
-               if (i==6)
-               {
-                       for (j=0;j<6;j++)
-                               current_drive->drive_model[j]=infobuf[j];
-                       current_drive->drive_model[6]=0;
-                       current_drive->drv_type=drv_famV;
-                       i+=2; /* 2 blanks before version */
-               }
-       }
-       if (!current_drive->drv_type)
-       {
-               /* check for CD200 */
-               clr_cmdbuf();
-               drvcmd[0]=CMD2_READ_ERR;
-               response_count=9;
-               flags_cmd_out=f_putcmd;
-               i=cmd_out();
-               if (i<0) msg(DBG_INI,"CMD2_READERR returns %d (ok anyway).\n",i);
-               if (i<0) msg(DBG_000,"CMD2_READERR returns %d (ok anyway).\n",i);
-               /* read drive version */
-               clr_cmdbuf();
-               for (i=0;i<12;i++) infobuf[i]=0;
-               if (sbpro_type==1) OUT(CDo_sel_i_d,0);
-#if 0
-               OUT(CDo_reset,0);
-               sbp_sleep(6*HZ);
-               OUT(CDo_enable,current_drive->drv_sel);
-#endif
-               drvcmd[0]=CMD2_READ_VER;
-               response_count=12;
-               flags_cmd_out=f_putcmd;
-               i=cmd_out();
-               if (i<0) msg(DBG_INI,"CMD2_READ_VER returns %d\n",i);
-               if (i==-7) teac_possible++;
-               j=0;
-               for (i=0;i<12;i++) j+=infobuf[i];
-               if (j)
-               {
-                       for (i=0;i<12;i++)
-                               sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-                       msgbuf[i*3]=0;
-                       msg(DBG_IDX,"infobuf =%s\n", msgbuf);
-                       for (i=0;i<12;i++)
-                               sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
-                       msgbuf[i*3]=0;
-                       msg(DBG_IDX,"infobuf =%s\n", msgbuf);
-               }
-               if (i>=0)
-               {
-                       for (i=0;i<5;i++) if (infobuf[i]!=family2[i]) break;
-                       if (i==5)
-                       {
-                               current_drive->drive_model[0]='C';
-                               current_drive->drive_model[1]='D';
-                               current_drive->drive_model[2]='2';
-                               current_drive->drive_model[3]='0';
-                               current_drive->drive_model[4]='0';
-                               current_drive->drive_model[5]=infobuf[i++];
-                               current_drive->drive_model[6]=infobuf[i++];
-                               current_drive->drive_model[7]=0;
-                               current_drive->drv_type=drv_fam2;
-                       }
-               }
-       }
-       if (!current_drive->drv_type)
-       {
-               /* check for TEAC CD-55A */
-               msg(DBG_TEA,"teac_possible: %d\n",teac_possible);
-               for (j=1;j<=((current_drive->drv_id==0)?3:1);j++)
-               {
-                       for (l=1;l<=((current_drive->drv_id==0)?10:1);l++)
-                       {
-                               msg(DBG_TEA,"TEAC reset #%d-%d.\n", j, l);
-                               if (sbpro_type==1) OUT(CDo_reset,0);
-                               else
-                               {
-                                       OUT(CDo_enable,current_drive->drv_sel);
-                                       OUT(CDo_sel_i_d,0);
-                                       OUT(CDo_command,CMDT_RESET);
-                                       for (i=0;i<9;i++) OUT(CDo_command,0);
-                               }
-                               sbp_sleep(5*HZ/10);
-                               OUT(CDo_enable,current_drive->drv_sel);
-                               OUT(CDo_sel_i_d,0);
-                               i=inb(CDi_status);
-                               msg(DBG_TEA,"TEAC CDi_status: %02X.\n",i);
-#if 0
-                               if (i&s_not_result_ready) continue; /* drive not present or ready */
-#endif
-                               i=inb(CDi_info);
-                               msg(DBG_TEA,"TEAC CDi_info: %02X.\n",i);
-                               if (i==0x55) break; /* drive found */
-                       }
-                       if (i==0x55) break; /* drive found */
-               }
-               if (i==0x55) /* drive found */
-               {
-                       msg(DBG_TEA,"TEAC drive found.\n");
-                       clr_cmdbuf();
-                       flags_cmd_out=f_putcmd;
-                       response_count=12;
-                       drvcmd[0]=CMDT_READ_VER;
-                       drvcmd[4]=response_count;
-                       for (i=0;i<12;i++) infobuf[i]=0;
-                       i=cmd_out_T();
-                       if (i!=0) msg(DBG_TEA,"cmd_out_T(CMDT_READ_VER) returns %d.\n",i);
-                       for (i=1;i<6;i++) if (infobuf[i]!=familyT[i-1]) break;
-                       if (i==6)
-                       {
-                               current_drive->drive_model[0]='C';
-                               current_drive->drive_model[1]='D';
-                               current_drive->drive_model[2]='-';
-                               current_drive->drive_model[3]='5';
-                               current_drive->drive_model[4]='5';
-                               current_drive->drive_model[5]=0;
-                               current_drive->drv_type=drv_famT;
-                       }
-               }
-       }
-       if (!current_drive->drv_type)
-       {
-               msg(DBG_TEA,"no drive found at address %03X under ID %d.\n",CDo_command,current_drive->drv_id);
-               return (-522);
-       }
-       for (j=0;j<4;j++) current_drive->firmware_version[j]=infobuf[i+j];
-       if (famL_drive)
-       {
-         u_char lcs_firm_e1[]="A E1";
-         u_char lcs_firm_f4[]="A4F4";
-               
-         for (j=0;j<4;j++)
-           if (current_drive->firmware_version[j]!=lcs_firm_e1[j]) break;
-         if (j==4) current_drive->drv_type=drv_e1;
-         
-         for (j=0;j<4;j++)
-           if (current_drive->firmware_version[j]!=lcs_firm_f4[j]) break;
-         if (j==4) current_drive->drv_type=drv_f4;
-
-         if (current_drive->drv_type==drv_famL) ask_mail();
-       }
-       else if (famT_drive)
-       {
-               j=infobuf[4]; /* one-byte version??? - here: 0x15 */
-               if (j=='5')
-               {
-                       current_drive->firmware_version[0]=infobuf[7];
-                       current_drive->firmware_version[1]=infobuf[8];
-                       current_drive->firmware_version[2]=infobuf[10];
-                       current_drive->firmware_version[3]=infobuf[11];
-               }
-               else
-               {
-                       if (j!=0x15) ask_mail();
-                       current_drive->firmware_version[0]='0';
-                       current_drive->firmware_version[1]='.';
-                       current_drive->firmware_version[2]='0'+(j>>4);
-                       current_drive->firmware_version[3]='0'+(j&0x0f);
-               }
-       }
-       else /* CR-52x, CR-56x, CD200, ECS-AT */
-       {
-               j = (current_drive->firmware_version[0] & 0x0F) * 100 +
-                       (current_drive->firmware_version[2] & 0x0F) *10 +
-                               (current_drive->firmware_version[3] & 0x0F);
-               if (fam0_drive)
-               {
-                       if (j<200) current_drive->drv_type=drv_199;
-                       else if (j<201) current_drive->drv_type=drv_200;
-                       else if (j<210) current_drive->drv_type=drv_201;
-                       else if (j<211) current_drive->drv_type=drv_210;
-                       else if (j<300) current_drive->drv_type=drv_211;
-                       else if (j>=300) current_drive->drv_type=drv_300;
-               }
-               else if (fam1_drive)
-               {
-                       if (j<100) current_drive->drv_type=drv_099;
-                       else
-                       {
-                               current_drive->drv_type=drv_100;
-                               if ((j!=500)&&(j!=102)) ask_mail();
-                       }
-               }
-               else if (fam2_drive)
-               {
-                       if (current_drive->drive_model[5]=='F')
-                       {
-                               if ((j!=1)&&(j!=35)&&(j!=200)&&(j!=210))
-                                 ask_mail(); /* unknown version at time */
-                       }
-                       else
-                       {
-                               msg(DBG_INF,"this CD200 drive is not fully supported yet - only audio will work.\n");
-                               if ((j!=101)&&(j!=35))
-                                 ask_mail(); /* unknown version at time */
-                       }
-               }
-               else if (famV_drive)
-                 {
-                   if ((j==100)||(j==150)) current_drive->drv_type=drv_at;
-                   ask_mail(); /* hopefully we get some feedback by this */
-                 }
-       }
-       msg(DBG_LCS,"drive type %02X\n",current_drive->drv_type);
-       msg(DBG_INI,"check_version done.\n");
-       return (0);
-}
-/*==========================================================================*/
-static void switch_drive(struct sbpcd_drive *p)
-{
-       current_drive = p;
-       OUT(CDo_enable,current_drive->drv_sel);
-       msg(DBG_DID,"drive %d (ID=%d) activated.\n",
-               current_drive - D_S, current_drive->drv_id);
-       return;
-}
-/*==========================================================================*/
-#ifdef PATH_CHECK
-/*
- * probe for the presence of an interface card
- */
-static int __init check_card(int port)
-{
-#undef N_RESPO
-#define N_RESPO 20
-       int i, j, k;
-       u_char response[N_RESPO];
-       u_char save_port0;
-       u_char save_port3;
-       
-       msg(DBG_INI,"check_card entered.\n");
-       save_port0=inb(port+0);
-       save_port3=inb(port+3);
-       
-       for (j=0;j<NR_SBPCD;j++)
-       {
-               OUT(port+3,j) ; /* enable drive #j */
-               OUT(port+0,CMD0_PATH_CHECK);
-               for (i=10;i>0;i--) OUT(port+0,0);
-               for (k=0;k<N_RESPO;k++) response[k]=0;
-               for (k=0;k<N_RESPO;k++)
-               {
-                       for (i=10000;i>0;i--)
-                       {
-                               if (inb(port+1)&s_not_result_ready) continue;
-                               response[k]=inb(port+0);
-                               break;
-                       }
-               }
-               for (i=0;i<N_RESPO;i++)
-                       sprintf(&msgbuf[i*3], " %02X", response[i]);
-               msgbuf[i*3]=0;
-               msg(DBG_TEA,"path check 00 (%d): %s\n", j, msgbuf);
-               OUT(port+0,CMD0_PATH_CHECK);
-               for (i=10;i>0;i--) OUT(port+0,0);
-               for (k=0;k<N_RESPO;k++) response[k]=0xFF;
-               for (k=0;k<N_RESPO;k++)
-               {
-                       for (i=10000;i>0;i--)
-                       {
-                               if (inb(port+1)&s_not_result_ready) continue;
-                               response[k]=inb(port+0);
-                               break;
-                       }
-               }
-               for (i=0;i<N_RESPO;i++)
-                       sprintf(&msgbuf[i*3], " %02X", response[i]);
-               msgbuf[i*3]=0;
-               msg(DBG_TEA,"path check 00 (%d): %s\n", j, msgbuf);
-
-               if (response[0]==0xAA)
-                       if (response[1]==0x55)
-                               return (0);
-       }
-       for (j=0;j<NR_SBPCD;j++)
-       {
-               OUT(port+3,j) ; /* enable drive #j */
-               OUT(port+0,CMD2_READ_VER);
-               for (i=10;i>0;i--) OUT(port+0,0);
-               for (k=0;k<N_RESPO;k++) response[k]=0;
-               for (k=0;k<N_RESPO;k++)
-               {
-                       for (i=1000000;i>0;i--)
-                       {
-                               if (inb(port+1)&s_not_result_ready) continue;
-                               response[k]=inb(port+0);
-                               break;
-                       }
-               }
-               for (i=0;i<N_RESPO;i++)
-                       sprintf(&msgbuf[i*3], " %02X", response[i]);
-               msgbuf[i*3]=0;
-               msg(DBG_TEA,"path check 12 (%d): %s\n", j, msgbuf);
-
-               OUT(port+0,CMD2_READ_VER);
-               for (i=10;i>0;i--) OUT(port+0,0);
-               for (k=0;k<N_RESPO;k++) response[k]=0xFF;
-               for (k=0;k<N_RESPO;k++)
-               {
-                       for (i=1000000;i>0;i--)
-                       {
-                               if (inb(port+1)&s_not_result_ready) continue;
-                               response[k]=inb(port+0);
-                               break;
-                       }
-               }
-               for (i=0;i<N_RESPO;i++)
-                       sprintf(&msgbuf[i*3], " %02X", response[i]);
-               msgbuf[i*3]=0;
-               msg(DBG_TEA,"path check 12 (%d): %s\n", j, msgbuf);
-
-               if (response[0]==0xAA)
-                       if (response[1]==0x55)
-                               return (0);
-       }
-       OUT(port+0,save_port0);
-       OUT(port+3,save_port3);
-       return (0); /* in any case - no real "function" at time */
-}
-#endif /* PATH_CHECK */ 
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * probe for the presence of drives on the selected controller
- */
-static int __init check_drives(void)
-{
-       int i, j;
-       
-       msg(DBG_INI,"check_drives entered.\n");
-       ndrives=0;
-       for (j=0;j<max_drives;j++)
-       {
-               struct sbpcd_drive *p = D_S + ndrives;
-               p->drv_id=j;
-               if (sbpro_type==1) p->drv_sel=(j&0x01)<<1|(j&0x02)>>1;
-               else p->drv_sel=j;
-               switch_drive(p);
-               msg(DBG_INI,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j);
-               msg(DBG_000,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j);
-               i=check_version();
-               if (i<0) msg(DBG_INI,"check_version returns %d.\n",i);
-               else
-               {
-                       current_drive->drv_options=drv_pattern[j];
-                       if (fam0L_drive) current_drive->drv_options&=~(speed_auto|speed_300|speed_150);
-                       msg(DBG_INF, "Drive %d (ID=%d): %.9s (%.4s) at 0x%03X (type %d)\n",
-                           current_drive - D_S,
-                           current_drive->drv_id,
-                           current_drive->drive_model,
-                           current_drive->firmware_version,
-                           CDo_command,
-                           sbpro_type);
-                       ndrives++;
-               }
-       }
-       for (j=ndrives;j<NR_SBPCD;j++) D_S[j].drv_id=-1;
-       if (ndrives==0) return (-1);
-       return (0);
-}
-/*==========================================================================*/
-#ifdef FUTURE
-/*
- *  obtain if requested service disturbs current audio state
- */            
-static int obey_audio_state(u_char audio_state, u_char func,u_char subfunc)
-{
-       switch (audio_state)                   /* audio status from controller  */
-       {
-       case aud_11: /* "audio play in progress" */
-       case audx11:
-               switch (func)                      /* DOS command code */
-               {
-               case cmd_07: /* input flush  */
-               case cmd_0d: /* open device  */
-               case cmd_0e: /* close device */
-               case cmd_0c: /* ioctl output */
-                       return (1);
-               case cmd_03: /* ioctl input  */
-                       switch (subfunc)
-                               /* DOS ioctl input subfunction */
-                       {
-                       case cxi_00:
-                       case cxi_06:
-                       case cxi_09:
-                               return (1);
-                       default:
-                               return (ERROR15);
-                       }
-                       return (1);
-               default:
-                       return (ERROR15);
-               }
-               return (1);
-       case aud_12:                  /* "audio play paused"      */
-       case audx12:
-               return (1);
-       default:
-               return (2);
-       }
-}
-/*==========================================================================*/
-/* allowed is only
- * ioctl_o, flush_input, open_device, close_device, 
- * tell_address, tell_volume, tell_capabiliti,
- * tell_framesize, tell_CD_changed, tell_audio_posi
- */
-static int check_allowed1(u_char func1, u_char func2)
-{
-#if 000
-       if (func1==ioctl_o) return (0);
-       if (func1==read_long) return (-1);
-       if (func1==read_long_prefetch) return (-1);
-       if (func1==seek) return (-1);
-       if (func1==audio_play) return (-1);
-       if (func1==audio_pause) return (-1);
-       if (func1==audio_resume) return (-1);
-       if (func1!=ioctl_i) return (0);
-       if (func2==tell_SubQ_run_tot) return (-1);
-       if (func2==tell_cdsize) return (-1);
-       if (func2==tell_TocDescrip) return (-1);
-       if (func2==tell_TocEntry) return (-1);
-       if (func2==tell_subQ_info) return (-1);
-       if (fam1_drive) if (func2==tell_SubChanInfo) return (-1);
-       if (func2==tell_UPC) return (-1);
-#else
-       return (0);
-#endif
-}
-/*==========================================================================*/
-static int check_allowed2(u_char func1, u_char func2)
-{
-#if 000
-       if (func1==read_long) return (-1);
-       if (func1==read_long_prefetch) return (-1);
-       if (func1==seek) return (-1);
-       if (func1==audio_play) return (-1);
-  if (func1!=ioctl_o) return (0);
-       if (fam1_drive)
-       {
-               if (func2==EjectDisk) return (-1);
-               if (func2==CloseTray) return (-1);
-       }
-#else
-       return (0);
-#endif
-}
-/*==========================================================================*/
-static int check_allowed3(u_char func1, u_char func2)
-{
-#if 000
-       if (func1==ioctl_i)
-       {
-               if (func2==tell_address) return (0);
-               if (func2==tell_capabiliti) return (0);
-               if (func2==tell_CD_changed) return (0);
-               if (fam0L_drive) if (func2==tell_SubChanInfo) return (0);
-               return (-1);
-       }
-       if (func1==ioctl_o)
-       {
-               if (func2==DriveReset) return (0);
-               if (fam0L_drive)
-               {
-                       if (func2==EjectDisk) return (0);
-                       if (func2==LockDoor) return (0);
-         if (func2==CloseTray) return (0);
-               }
-               return (-1);
-    }
-       if (func1==flush_input) return (-1);
-       if (func1==read_long) return (-1);
-       if (func1==read_long_prefetch) return (-1);
-       if (func1==seek) return (-1);
-       if (func1==audio_play) return (-1);
-       if (func1==audio_pause) return (-1);
-       if (func1==audio_resume) return (-1);
-#else
-       return (0);
-#endif
-}
-/*==========================================================================*/
-static int seek_pos_audio_end(void)
-{
-       int i;
-
-       i=msf2blk(current_drive->pos_audio_end)-1;
-       if (i<0) return (-1);
-       i=cc_Seek(i,0);
-       return (i);
-}
-#endif /* FUTURE */ 
-/*==========================================================================*/
-static int ReadToC(void)
-{
-       int i, j;
-       current_drive->diskstate_flags &= ~toc_bit;
-       current_drive->ored_ctl_adr=0;
-       /* special handling of CD-I HE */
-       if ((current_drive->n_first_track == 2 && current_drive->n_last_track == 2) ||
-             current_drive->xa_byte == 0x10)
-        {
-               current_drive->TocBuffer[1].nixbyte=0;
-               current_drive->TocBuffer[1].ctl_adr=0x40;
-               current_drive->TocBuffer[1].number=1;
-               current_drive->TocBuffer[1].format=0;
-               current_drive->TocBuffer[1].address=blk2msf(0);
-               current_drive->ored_ctl_adr |= 0x40;
-               current_drive->n_first_track = 1;
-               current_drive->n_last_track = 1;
-               current_drive->xa_byte = 0x10;
-                j = 2;
-        } else
-       for (j=current_drive->n_first_track;j<=current_drive->n_last_track;j++)
-       {
-               i=cc_ReadTocEntry(j);
-               if (i<0)
-               {
-                       msg(DBG_INF,"cc_ReadTocEntry(%d) returns %d.\n",j,i);
-                       return (i);
-               }
-               current_drive->TocBuffer[j].nixbyte=current_drive->TocEnt_nixbyte;
-               current_drive->TocBuffer[j].ctl_adr=current_drive->TocEnt_ctl_adr;
-               current_drive->TocBuffer[j].number=current_drive->TocEnt_number;
-               current_drive->TocBuffer[j].format=current_drive->TocEnt_format;
-               current_drive->TocBuffer[j].address=current_drive->TocEnt_address;
-               current_drive->ored_ctl_adr |= current_drive->TocEnt_ctl_adr;
-       }
-       /* fake entry for LeadOut Track */
-       current_drive->TocBuffer[j].nixbyte=0;
-       current_drive->TocBuffer[j].ctl_adr=0;
-       current_drive->TocBuffer[j].number=CDROM_LEADOUT;
-       current_drive->TocBuffer[j].format=0;
-       current_drive->TocBuffer[j].address=current_drive->size_msf;
-       
-       current_drive->diskstate_flags |= toc_bit;
-       return (0);
-}
-/*==========================================================================*/
-static int DiskInfo(void)
-{
-       int i, j;
-       
-       current_drive->mode=READ_M1;
-       
-#undef LOOP_COUNT
-#define LOOP_COUNT 10 /* needed for some "old" drives */
-       
-       msg(DBG_000,"DiskInfo entered.\n");
-       for (j=1;j<LOOP_COUNT;j++)
-       {
-#if 0
-               i=SetSpeed();
-               if (i<0)
-               {
-                       msg(DBG_INF,"DiskInfo: SetSpeed returns %d\n", i);
-                       continue;
-               }
-               i=cc_ModeSense();
-               if (i<0)
-               {
-                       msg(DBG_INF,"DiskInfo: cc_ModeSense returns %d\n", i);
-                       continue;
-               }
-#endif
-               i=cc_ReadCapacity();
-               if (i>=0) break;
-               msg(DBG_INF,"DiskInfo: ReadCapacity #%d returns %d\n", j, i);
-#if 0
-               i=cc_DriveReset();
-#endif
-               if (!fam0_drive && j == 2) break;
-       }
-       if (j==LOOP_COUNT) return (-33); /* give up */
-       
-       i=cc_ReadTocDescr();
-       if (i<0)
-       {
-               msg(DBG_INF,"DiskInfo: ReadTocDescr returns %d\n", i);
-               return (i);
-       }
-       i=ReadToC();
-       if (i<0)
-       {
-               msg(DBG_INF,"DiskInfo: ReadToC returns %d\n", i);
-               return (i);
-       }
-       i=cc_CheckMultiSession();
-       if (i<0)
-       {
-               msg(DBG_INF,"DiskInfo: cc_CheckMultiSession returns %d\n", i);
-               return (i);
-       }
-       if (current_drive->f_multisession) current_drive->sbp_bufsiz=1;  /* possibly a weird PhotoCD */
-       else current_drive->sbp_bufsiz=buffers;
-       i=cc_ReadTocEntry(current_drive->n_first_track);
-       if (i<0)
-       {
-               msg(DBG_INF,"DiskInfo: cc_ReadTocEntry(1) returns %d\n", i);
-               return (i);
-       }
-       i=cc_ReadUPC();
-       if (i<0) msg(DBG_INF,"DiskInfo: cc_ReadUPC returns %d\n", i);
-       if ((fam0L_drive) && (current_drive->xa_byte==0x20 || current_drive->xa_byte == 0x10))
-       {
-               /* XA disk with old drive */
-               cc_ModeSelect(CD_FRAMESIZE_RAW1);
-               cc_ModeSense();
-       }
-       if (famT_drive) cc_prep_mode_T();
-       msg(DBG_000,"DiskInfo done.\n");
-       return (0);
-}
-
-static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
-       struct sbpcd_drive *p = cdi->handle;
-       int st;
-
-       if (CDSL_CURRENT != slot_nr) {
-                /* we have no changer support */
-                return -EINVAL;
-       }
-
-        cc_ReadStatus();
-       st=ResponseStatus();
-       if (st<0)
-       {
-               msg(DBG_INF,"sbpcd_drive_status: timeout.\n");
-               return (0);
-       }
-       msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked);
-       msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed);
-       msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in);
-       msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
-       msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
-       msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
-
-#if 0
-  if (!(p->status_bits & p_door_closed)) return CDS_TRAY_OPEN;
-  if (p->status_bits & p_disk_ok) return CDS_DISC_OK;
-  if (p->status_bits & p_disk_in) return CDS_DRIVE_NOT_READY;
-
-  return CDS_NO_DISC;
-#else
-  if (p->status_bits & p_spinning) return CDS_DISC_OK;
-/*  return CDS_TRAY_OPEN; */
-  return CDS_NO_DISC;
-  
-#endif
-
-}
-
-
-/*==========================================================================*/
-#ifdef FUTURE
-/*
- *  called always if driver gets entered
- *  returns 0 or ERROR2 or ERROR15
- */
-static int prepare(u_char func, u_char subfunc)
-{
-       int i;
-       
-       if (fam0L_drive)
-       {
-               i=inb(CDi_status);
-               if (i&s_attention) GetStatus();
-       }
-       else if (fam1_drive) GetStatus();
-       else if (fam2_drive) GetStatus();
-       else if (famT_drive) GetStatus();
-       if (current_drive->CD_changed==0xFF)
-       {
-               current_drive->diskstate_flags=0;
-               current_drive->audio_state=0;
-               if (!st_diskok)
-               {
-                       i=check_allowed1(func,subfunc);
-                       if (i<0) return (-2);
-               }
-               else 
-               {
-                       i=check_allowed3(func,subfunc);
-                       if (i<0)
-                       {
-                               current_drive->CD_changed=1;
-                               return (-15);
-                       }
-               }
-       }
-       else
-       {
-               if (!st_diskok)
-               {
-                       current_drive->diskstate_flags=0;
-                       current_drive->audio_state=0;
-                       i=check_allowed1(func,subfunc);
-                       if (i<0) return (-2);
-               }
-               else
-               { 
-                       if (st_busy)
-                       {
-                               if (current_drive->audio_state!=audio_pausing)
-                               {
-                                       i=check_allowed2(func,subfunc);
-                                       if (i<0) return (-2);
-                               }
-                       }
-                       else
-                       {
-                               if (current_drive->audio_state==audio_playing) seek_pos_audio_end();
-                               current_drive->audio_state=0;
-                       }
-                       if (!frame_size_valid)
-                       {
-                               i=DiskInfo();
-                               if (i<0)
-                               {
-                                       current_drive->diskstate_flags=0;
-                                       current_drive->audio_state=0;
-                                       i=check_allowed1(func,subfunc);
-                                       if (i<0) return (-2);
-                               }
-                       }
-               }
-    }
-       return (0);
-}
-#endif /* FUTURE */ 
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * Check the results of the "get status" command.
- */
-static int sbp_status(void)
-{
-       int st;
-       
-       st=ResponseStatus();
-       if (st<0)
-       {
-               msg(DBG_INF,"sbp_status: timeout.\n");
-               return (0);
-       }
-       
-       if (!st_spinning) msg(DBG_SPI,"motor got off - ignoring.\n");
-       
-       if (st_check) 
-       {
-               msg(DBG_INF,"st_check detected - retrying.\n");
-               return (0);
-       }
-       if (!st_door_closed)
-       {
-               msg(DBG_INF,"door is open - retrying.\n");
-               return (0);
-       }
-       if (!st_caddy_in)
-       {
-               msg(DBG_INF,"disk removed - retrying.\n");
-               return (0);
-       }
-       if (!st_diskok) 
-       {
-               msg(DBG_INF,"!st_diskok detected - retrying.\n");
-               return (0);
-       }
-       if (st_busy) 
-       {
-               msg(DBG_INF,"st_busy detected - retrying.\n");
-               return (0);
-       }
-       return (1);
-}
-/*==========================================================================*/
-               
-static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_multisession *ms_infp)
-{
-       struct sbpcd_drive *p = cdi->handle;
-       ms_infp->addr_format = CDROM_LBA;
-       ms_infp->addr.lba    = p->lba_multi;
-       if (p->f_multisession)
-               ms_infp->xa_flag=1; /* valid redirection address */
-       else
-               ms_infp->xa_flag=0; /* invalid redirection address */
-
-       return  0;
-}
-
-static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
-                      void * arg)
-{
-       struct sbpcd_drive *p = cdi->handle;
-       int i, st, j;
-       
-       msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08p)\n", cdi->name, cmd, arg);
-       if (p->drv_id==-1) {
-               msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
-               return (-ENXIO);             /* no such drive */
-       }
-       down(&ioctl_read_sem);
-       if (p != current_drive)
-               switch_drive(p);
-       
-       msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
-       switch (cmd)            /* Sun-compatible */
-       {
-               
-       case CDROMPAUSE:     /* Pause the drive */
-               msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n");
-               /* pause the drive unit when it is currently in PLAY mode,         */
-               /* or reset the starting and ending locations when in PAUSED mode. */
-               /* If applicable, at the next stopping point it reaches            */
-               /* the drive will discontinue playing.                             */
-               switch (current_drive->audio_state)
-               {
-               case audio_playing:
-                       if (famL_drive) i=cc_ReadSubQ();
-                       else i=cc_Pause_Resume(1);
-                       if (i<0) RETURN_UP(-EIO);
-                       if (famL_drive) i=cc_Pause_Resume(1);
-                       else i=cc_ReadSubQ();
-                       if (i<0) RETURN_UP(-EIO);
-                       current_drive->pos_audio_start=current_drive->SubQ_run_tot;
-                       current_drive->audio_state=audio_pausing;
-                       RETURN_UP(0);
-               case audio_pausing:
-                       i=cc_Seek(current_drive->pos_audio_start,1);
-                       if (i<0) RETURN_UP(-EIO);
-                       RETURN_UP(0);
-               default:
-                       RETURN_UP(-EINVAL);
-               }
-
-       case CDROMRESUME: /* resume paused audio play */
-               msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n");
-               /* resume playing audio tracks when a previous PLAY AUDIO call has  */
-               /* been paused with a PAUSE command.                                */
-               /* It will resume playing from the location saved in SubQ_run_tot.  */
-               if (current_drive->audio_state!=audio_pausing) RETURN_UP(-EINVAL);
-               if (famL_drive)
-                       i=cc_PlayAudio(current_drive->pos_audio_start,
-                                      current_drive->pos_audio_end);
-               else i=cc_Pause_Resume(3);
-               if (i<0) RETURN_UP(-EIO);
-               current_drive->audio_state=audio_playing;
-               RETURN_UP(0);
-
-       case CDROMPLAYMSF:
-               msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n");
-#ifdef SAFE_MIXED
-               if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
-               if (current_drive->audio_state==audio_playing)
-               {
-                       i=cc_Pause_Resume(1);
-                       if (i<0) RETURN_UP(-EIO);
-                       i=cc_ReadSubQ();
-                       if (i<0) RETURN_UP(-EIO);
-                       current_drive->pos_audio_start=current_drive->SubQ_run_tot;
-                       i=cc_Seek(current_drive->pos_audio_start,1);
-               }
-               memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf));
-               /* values come as msf-bin */
-               current_drive->pos_audio_start = (msf.cdmsf_min0<<16) |
-                        (msf.cdmsf_sec0<<8) |
-                               msf.cdmsf_frame0;
-               current_drive->pos_audio_end = (msf.cdmsf_min1<<16) |
-                       (msf.cdmsf_sec1<<8) |
-                               msf.cdmsf_frame1;
-               msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n",
-                   current_drive->pos_audio_start,current_drive->pos_audio_end);
-               i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
-               if (i<0)
-               {
-                       msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
-                       DriveReset();
-                       current_drive->audio_state=0;
-                       RETURN_UP(-EIO);
-               }
-               current_drive->audio_state=audio_playing;
-               RETURN_UP(0);
-               
-       case CDROMPLAYTRKIND: /* Play a track.  This currently ignores index. */
-               msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n");
-#ifdef SAFE_MIXED
-               if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
-               if (current_drive->audio_state==audio_playing)
-               {
-                       msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n");
-#if 1
-                       RETURN_UP(0); /* just let us play on */
-#else
-                       RETURN_UP(-EINVAL); /* play on, but say "error" */
-#endif
-               }
-               memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti));
-               msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n",
-                   ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1);
-               if (ti.cdti_trk0<current_drive->n_first_track) RETURN_UP(-EINVAL);
-               if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL);
-               if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0;
-               if (ti.cdti_trk1>current_drive->n_last_track) ti.cdti_trk1=current_drive->n_last_track;
-               current_drive->pos_audio_start=current_drive->TocBuffer[ti.cdti_trk0].address;
-               current_drive->pos_audio_end=current_drive->TocBuffer[ti.cdti_trk1+1].address;
-               i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
-               if (i<0)
-               {
-                       msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
-                       DriveReset();
-                       current_drive->audio_state=0;
-                       RETURN_UP(-EIO);
-               }
-               current_drive->audio_state=audio_playing;
-               RETURN_UP(0);
-               
-       case CDROMREADTOCHDR:        /* Read the table of contents header */
-               msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n");
-               tochdr.cdth_trk0=current_drive->n_first_track;
-               tochdr.cdth_trk1=current_drive->n_last_track;
-               memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
-               RETURN_UP(0);
-               
-       case CDROMREADTOCENTRY:      /* Read an entry in the table of contents */
-               msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n");
-               memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
-               i=tocentry.cdte_track;
-               if (i==CDROM_LEADOUT) i=current_drive->n_last_track+1;
-               else if (i<current_drive->n_first_track||i>current_drive->n_last_track)
-                  RETURN_UP(-EINVAL);
-               tocentry.cdte_adr=current_drive->TocBuffer[i].ctl_adr&0x0F;
-               tocentry.cdte_ctrl=(current_drive->TocBuffer[i].ctl_adr>>4)&0x0F;
-               tocentry.cdte_datamode=current_drive->TocBuffer[i].format;
-               if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */
-               {
-                       tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF;
-                       tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF;
-                       tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF;
-               }
-               else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
-                       tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address);
-               else RETURN_UP(-EINVAL);
-               memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
-               RETURN_UP(0);
-               
-       case CDROMSTOP:      /* Spin down the drive */
-               msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n");
-#ifdef SAFE_MIXED
-               if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */ 
-               i=cc_Pause_Resume(1);
-               current_drive->audio_state=0;
-#if 0
-               cc_DriveReset();
-#endif
-               RETURN_UP(i);
-
-       case CDROMSTART:  /* Spin up the drive */
-               msg(DBG_IOC,"ioctl: CDROMSTART entered.\n");
-               cc_SpinUp();
-               current_drive->audio_state=0;
-               RETURN_UP(0);
-
-       case CDROMVOLCTRL:   /* Volume control */
-               msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n");
-               memcpy(&volctrl,(char *) arg,sizeof(volctrl));
-               current_drive->vol_chan0=0;
-               current_drive->vol_ctrl0=volctrl.channel0;
-               current_drive->vol_chan1=1;
-               current_drive->vol_ctrl1=volctrl.channel1;
-               i=cc_SetVolume();
-               RETURN_UP(0);
-
-       case CDROMVOLREAD:   /* read Volume settings from drive */
-               msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n");
-               st=cc_GetVolume();
-               if (st<0) RETURN_UP(st);
-               volctrl.channel0=current_drive->vol_ctrl0;
-               volctrl.channel1=current_drive->vol_ctrl1;
-               volctrl.channel2=0;
-               volctrl.channel2=0;
-               memcpy((void *)arg,&volctrl,sizeof(volctrl));
-               RETURN_UP(0);
-
-       case CDROMSUBCHNL:   /* Get subchannel info */
-               msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n");
-               /* Bogus, I can do better than this! --AJK
-               if ((st_spinning)||(!subq_valid)) {
-                       i=cc_ReadSubQ();
-                       if (i<0) RETURN_UP(-EIO);
-               }
-               */
-               i=cc_ReadSubQ();
-               if (i<0) {
-                       j=cc_ReadError(); /* clear out error status from drive */
-                       current_drive->audio_state=CDROM_AUDIO_NO_STATUS;
-                       /* get and set the disk state here,
-                       probably not the right place, but who cares!
-                       It makes it work properly! --AJK */
-                       if (current_drive->CD_changed==0xFF) {
-                               msg(DBG_000,"Disk changed detect\n");
-                               current_drive->diskstate_flags &= ~cd_size_bit;
-                       }
-                       RETURN_UP(-EIO);
-               }
-               if (current_drive->CD_changed==0xFF) {
-                       /* reread the TOC because the disk has changed! --AJK */
-                       msg(DBG_000,"Disk changed STILL detected, rereading TOC!\n");
-                       i=DiskInfo();
-                       if(i==0) {
-                               current_drive->CD_changed=0x00; /* cd has changed, procede, */
-                               RETURN_UP(-EIO); /* and get TOC, etc on next try! --AJK */
-                       } else {
-                               RETURN_UP(-EIO); /* we weren't ready yet! --AJK */
-                       }
-               }
-               memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
-               /*
-                       This virtual crap is very bogus!
-                       It doesn't detect when the cd is done playing audio!
-                       Lets do this right with proper hardware register reading!
-               */
-               cc_ReadStatus();
-               i=ResponseStatus();
-               msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked);
-               msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed);
-               msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in);
-               msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
-               msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
-               msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
-               /* st_busy indicates if it's _ACTUALLY_ playing audio */
-               switch (current_drive->audio_state)
-               {
-               case audio_playing:
-                       if(st_busy==0) {
-                               /* CD has stopped playing audio --AJK */
-                               current_drive->audio_state=audio_completed;
-                               SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
-                       } else {
-                               SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
-                       }
-                       break;
-               case audio_pausing:
-                       SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED;
-                       break;
-               case audio_completed:
-                       SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
-                       break;
-               default:
-                       SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS;
-                       break;
-               }
-               SC.cdsc_adr=current_drive->SubQ_ctl_adr;
-               SC.cdsc_ctrl=current_drive->SubQ_ctl_adr>>4;
-               SC.cdsc_trk=bcd2bin(current_drive->SubQ_trk);
-               SC.cdsc_ind=bcd2bin(current_drive->SubQ_pnt_idx);
-               if (SC.cdsc_format==CDROM_LBA)
-               {
-                       SC.cdsc_absaddr.lba=msf2blk(current_drive->SubQ_run_tot);
-                       SC.cdsc_reladdr.lba=msf2blk(current_drive->SubQ_run_trk);
-               }
-               else /* not only if (SC.cdsc_format==CDROM_MSF) */
-               {
-                       SC.cdsc_absaddr.msf.minute=(current_drive->SubQ_run_tot>>16)&0x00FF;
-                       SC.cdsc_absaddr.msf.second=(current_drive->SubQ_run_tot>>8)&0x00FF;
-                       SC.cdsc_absaddr.msf.frame=current_drive->SubQ_run_tot&0x00FF;
-                       SC.cdsc_reladdr.msf.minute=(current_drive->SubQ_run_trk>>16)&0x00FF;
-                       SC.cdsc_reladdr.msf.second=(current_drive->SubQ_run_trk>>8)&0x00FF;
-                       SC.cdsc_reladdr.msf.frame=current_drive->SubQ_run_trk&0x00FF;
-               }
-               memcpy((void *) arg, &SC, sizeof(struct cdrom_subchnl));
-               msg(DBG_IOS,"CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n",
-                   SC.cdsc_format,SC.cdsc_audiostatus,
-                   SC.cdsc_adr,SC.cdsc_ctrl,
-                   SC.cdsc_trk,SC.cdsc_ind,
-                   SC.cdsc_absaddr,SC.cdsc_reladdr);
-               RETURN_UP(0);
-
-       default:
-               msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
-               RETURN_UP(-EINVAL);
-       } /* end switch(cmd) */
-}
-/*==========================================================================*/
-/*
- *  Take care of the different block sizes between cdrom and Linux.
- */
-static void sbp_transfer(struct request *req)
-{
-       long offs;
-
-       while ( (req->nr_sectors > 0) &&
-              (req->sector/4 >= current_drive->sbp_first_frame) &&
-              (req->sector/4 <= current_drive->sbp_last_frame) )
-       {
-               offs = (req->sector - current_drive->sbp_first_frame * 4) * 512;
-               memcpy(req->buffer, current_drive->sbp_buf + offs, 512);
-               req->nr_sectors--;
-               req->sector++;
-               req->buffer += 512;
-       }
-}
-/*==========================================================================*/
-/*
- *  special end_request for sbpcd to solve CURRENT==NULL bug. (GTL)
- *  GTL = Gonzalo Tornaria <tornaria@cmat.edu.uy>
- *
- *  This is a kludge so we don't need to modify end_request.
- *  We put the req we take out after INIT_REQUEST in the requests list,
- *  so that end_request will discard it.
- *
- *  The bug could be present in other block devices, perhaps we
- *  should modify INIT_REQUEST and end_request instead, and
- *  change every block device..
- *
- *  Could be a race here?? Could e.g. a timer interrupt schedule() us?
- *  If so, we should copy end_request here, and do it right.. (or
- *  modify end_request and the block devices).
- *
- *  In any case, the race here would be much small than it was, and
- *  I couldn't reproduce..
- *
- *  The race could be: suppose CURRENT==NULL. We put our req in the list,
- *  and we are scheduled. Other process takes over, and gets into
- *  do_sbpcd_request. It sees CURRENT!=NULL (it is == to our req), so
- *  proceeds. It ends, so CURRENT is now NULL.. Now we awake somewhere in
- *  end_request, but now CURRENT==NULL... oops!
- *
- */
-#undef DEBUG_GTL
-
-/*==========================================================================*/
-/*
- *  I/O request routine, called from Linux kernel.
- */
-static void do_sbpcd_request(request_queue_t * q)
-{
-       u_int block;
-       u_int nsect;
-       int status_tries, data_tries;
-       struct request *req;
-       struct sbpcd_drive *p;
-#ifdef DEBUG_GTL
-       static int xx_nr=0;
-       int xnr;
-#endif
-
- request_loop:
-#ifdef DEBUG_GTL
-       xnr=++xx_nr;
-
-       req = elv_next_request(q);
-
-       if (!req)
-       {
-               printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%li\n",
-                       xnr, current->pid, jiffies);
-               printk( "do_sbpcd_request[%do](NULL) end 0 (null), Time:%li\n",
-                       xnr, jiffies);
-               return;
-       }
-
-       printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%li\n",
-               xnr, req, req->sector, req->nr_sectors, current->pid, jiffies);
-#endif
-
-       req = elv_next_request(q);      /* take out our request so no other */
-       if (!req)
-               return;
-
-       if (req -> sector == -1)
-               end_request(req, 0);
-       spin_unlock_irq(q->queue_lock);
-
-       down(&ioctl_read_sem);
-       if (rq_data_dir(elv_next_request(q)) != READ)
-       {
-               msg(DBG_INF, "bad cmd %d\n", req->cmd[0]);
-               goto err_done;
-       }
-       p = req->rq_disk->private_data;
-#if OLD_BUSY
-       while (busy_audio) sbp_sleep(HZ); /* wait a bit */
-       busy_data=1;
-#endif /* OLD_BUSY */
-
-       if (p->audio_state==audio_playing) goto err_done;
-       if (p != current_drive)
-               switch_drive(p);
-
-       block = req->sector; /* always numbered as 512-byte-pieces */
-       nsect = req->nr_sectors; /* always counted as 512-byte-pieces */
-
-       msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect);
-#if 0
-       msg(DBG_MUL,"read LBA %d\n", block/4);
-#endif
-
-       sbp_transfer(req);
-       /* if we satisfied the request from the buffer, we're done. */
-       if (req->nr_sectors == 0)
-       {
-#ifdef DEBUG_GTL
-               printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 2, Time:%li\n",
-                       xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
-               up(&ioctl_read_sem);
-               spin_lock_irq(q->queue_lock);
-               end_request(req, 1);
-               goto request_loop;
-       }
-
-#ifdef FUTURE
-       i=prepare(0,0); /* at moment not really a hassle check, but ... */
-       if (i!=0)
-               msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i);
-#endif /* FUTURE */
-
-       if (!st_spinning) cc_SpinUp();
-
-       for (data_tries=n_retries; data_tries > 0; data_tries--)
-       {
-               for (status_tries=3; status_tries > 0; status_tries--)
-               {
-                       flags_cmd_out |= f_respo3;
-                       cc_ReadStatus();
-                       if (sbp_status() != 0) break;
-                       if (st_check) cc_ReadError();
-                       sbp_sleep(1);    /* wait a bit, try again */
-               }
-               if (status_tries == 0)
-               {
-                       msg(DBG_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__);
-                       break;
-               }
-               
-               sbp_read_cmd(req);
-               sbp_sleep(0);
-               if (sbp_data(req) != 0)
-               {
-#ifdef SAFE_MIXED
-                       current_drive->has_data=2; /* is really a data disk */
-#endif /* SAFE_MIXED */
-#ifdef DEBUG_GTL
-                       printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n",
-                               xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
-                       up(&ioctl_read_sem);
-                       spin_lock_irq(q->queue_lock);
-                       end_request(req, 1);
-                       goto request_loop;
-               }
-       }
-
- err_done:
-#if OLD_BUSY
-       busy_data=0;
-#endif /* OLD_BUSY */
-#ifdef DEBUG_GTL
-       printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%li\n",
-               xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
-       up(&ioctl_read_sem);
-       sbp_sleep(0);    /* wait a bit, try again */
-       spin_lock_irq(q->queue_lock);
-       end_request(req, 0);
-       goto request_loop;
-}
-/*==========================================================================*/
-/*
- *  build and send the READ command.
- */
-static void sbp_read_cmd(struct request *req)
-{
-#undef OLD
-
-       int i;
-       int block;
-
-       current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1;      /* purge buffer */
-       current_drive->sbp_current = 0;
-       block=req->sector/4;
-       if (block+current_drive->sbp_bufsiz <= current_drive->CDsize_frm)
-               current_drive->sbp_read_frames = current_drive->sbp_bufsiz;
-       else
-       {
-               current_drive->sbp_read_frames=current_drive->CDsize_frm-block;
-               /* avoid reading past end of data */
-               if (current_drive->sbp_read_frames < 1)
-               {
-                       msg(DBG_INF,"requested frame %d, CD size %d ???\n",
-                           block, current_drive->CDsize_frm);
-                       current_drive->sbp_read_frames=1;
-               }
-       }
-
-       flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
-       clr_cmdbuf();
-       if (famV_drive)
-         {
-           drvcmd[0]=CMDV_READ;
-           lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
-           bin2bcdx(&drvcmd[1]);
-           bin2bcdx(&drvcmd[2]);
-           bin2bcdx(&drvcmd[3]);
-           drvcmd[4]=current_drive->sbp_read_frames>>8;
-           drvcmd[5]=current_drive->sbp_read_frames&0xff;
-           drvcmd[6]=0x02; /* flag "msf-bcd" */
-       }
-       else if (fam0L_drive)
-       {
-               flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
-               if (current_drive->xa_byte==0x20)
-               {
-                       cmd_type=READ_M2;
-                       drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
-                       drvcmd[1]=(block>>16)&0x0ff;
-                       drvcmd[2]=(block>>8)&0x0ff;
-                       drvcmd[3]=block&0x0ff;
-                       drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
-                       drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
-               }
-               else
-               {
-                       drvcmd[0]=CMD0_READ; /* "read frames", old drives */
-                       if (current_drive->drv_type>=drv_201)
-                       {
-                               lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
-                               bin2bcdx(&drvcmd[1]);
-                               bin2bcdx(&drvcmd[2]);
-                               bin2bcdx(&drvcmd[3]);
-                       }
-                       else
-                       {
-                               drvcmd[1]=(block>>16)&0x0ff;
-                               drvcmd[2]=(block>>8)&0x0ff;
-                               drvcmd[3]=block&0x0ff;
-                       }
-                       drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
-                       drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
-                       drvcmd[6]=(current_drive->drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */
-               }
-       }
-       else if (fam1_drive)
-       {
-               drvcmd[0]=CMD1_READ;
-               lba2msf(block,&drvcmd[1]); /* msf-bin format required */
-               drvcmd[5]=(current_drive->sbp_read_frames>>8)&0x0ff;
-               drvcmd[6]=current_drive->sbp_read_frames&0x0ff;
-       }
-       else if (fam2_drive)
-       {
-               drvcmd[0]=CMD2_READ;
-               lba2msf(block,&drvcmd[1]); /* msf-bin format required */
-               drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
-               drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
-               drvcmd[6]=0x02;
-       }
-       else if (famT_drive)
-       {
-               drvcmd[0]=CMDT_READ;
-               drvcmd[2]=(block>>24)&0x0ff;
-               drvcmd[3]=(block>>16)&0x0ff;
-               drvcmd[4]=(block>>8)&0x0ff;
-               drvcmd[5]=block&0x0ff;
-               drvcmd[7]=(current_drive->sbp_read_frames>>8)&0x0ff;
-               drvcmd[8]=current_drive->sbp_read_frames&0x0ff;
-       }
-       flags_cmd_out=f_putcmd;
-       response_count=0;
-       i=cmd_out();
-       if (i<0) msg(DBG_INF,"error giving READ command: %0d\n", i);
-       return;
-}
-/*==========================================================================*/
-/*
- *  Check the completion of the read-data command.  On success, read
- *  the current_drive->sbp_bufsiz * 2048 bytes of data from the disk into buffer.
- */
-static int sbp_data(struct request *req)
-{
-       int i=0, j=0, l, frame;
-       u_int try=0;
-       u_long timeout;
-       u_char *p;
-       u_int data_tries = 0;
-       u_int data_waits = 0;
-       u_int data_retrying = 0;
-       int error_flag;
-       int xa_count;
-       int max_latency;
-       int success;
-       int wait;
-       int duration;
-
-       error_flag=0;
-       success=0;
-#if LONG_TIMING
-       max_latency=9*HZ;
-#else
-       if (current_drive->f_multisession) max_latency=15*HZ;
-       else max_latency=5*HZ;
-#endif
-       duration=jiffies;
-       for (frame=0;frame<current_drive->sbp_read_frames&&!error_flag; frame++)
-       {
-               SBPCD_CLI;
-
-               del_timer(&data_timer);
-               data_timer.expires=jiffies+max_latency;
-               timed_out_data=0;
-               add_timer(&data_timer);
-               while (!timed_out_data)
-               {
-                       if (current_drive->f_multisession) try=maxtim_data*4;
-                       else try=maxtim_data;
-                       msg(DBG_000,"sbp_data: CDi_status loop: try=%d.\n",try);
-                       for ( ; try!=0;try--)
-                       {
-                               j=inb(CDi_status);
-                               if (!(j&s_not_data_ready)) break;
-                               if (!(j&s_not_result_ready)) break;
-                               if (fam0LV_drive) if (j&s_attention) break;
-                       }
-                       if (!(j&s_not_data_ready)) goto data_ready;
-                       if (try==0)
-                       {
-                               if (data_retrying == 0) data_waits++;
-                               data_retrying = 1;
-                               msg(DBG_000,"sbp_data: CDi_status loop: sleeping.\n");
-                               sbp_sleep(1);
-                               try = 1;
-                       }
-               }
-               msg(DBG_INF,"sbp_data: CDi_status loop expired.\n");
-       data_ready:
-               del_timer(&data_timer);
-
-               if (timed_out_data)
-               {
-                       msg(DBG_INF,"sbp_data: CDi_status timeout (timed_out_data) (%02X).\n", j);
-                       error_flag++;
-               }
-               if (try==0)
-               {
-                       msg(DBG_INF,"sbp_data: CDi_status timeout (try=0) (%02X).\n", j);
-                       error_flag++;
-               }
-               if (!(j&s_not_result_ready))
-               {
-                       msg(DBG_INF, "sbp_data: RESULT_READY where DATA_READY awaited (%02X).\n", j);
-                       response_count=20;
-                       j=ResponseInfo();
-                       j=inb(CDi_status);
-               }
-               if (j&s_not_data_ready)
-               {
-                       if ((current_drive->ored_ctl_adr&0x40)==0)
-                               msg(DBG_INF, "CD contains no data tracks.\n");
-                       else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).\n", j);
-                       error_flag++;
-               }
-               SBPCD_STI;
-               if (error_flag) break;
-
-               msg(DBG_000, "sbp_data: beginning to read.\n");
-               p = current_drive->sbp_buf + frame *  CD_FRAMESIZE;
-               if (sbpro_type==1) OUT(CDo_sel_i_d,1);
-               if (cmd_type==READ_M2) {
-                        if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1);
-                        else insb(CDi_data, xa_head_buf, CD_XA_HEAD);
-               }
-               if (do_16bit) insw(CDi_data, p, CD_FRAMESIZE>>1);
-               else insb(CDi_data, p, CD_FRAMESIZE);
-               if (cmd_type==READ_M2) {
-                        if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1);
-                        else insb(CDi_data, xa_tail_buf, CD_XA_TAIL);
-               }
-               current_drive->sbp_current++;
-               if (sbpro_type==1) OUT(CDo_sel_i_d,0);
-               if (cmd_type==READ_M2)
-               {
-                       for (xa_count=0;xa_count<CD_XA_HEAD;xa_count++)
-                               sprintf(&msgbuf[xa_count*3], " %02X", xa_head_buf[xa_count]);
-                       msgbuf[xa_count*3]=0;
-                       msg(DBG_XA1,"xa head:%s\n", msgbuf);
-               }
-               data_retrying = 0;
-               data_tries++;
-               if (data_tries >= 1000)
-               {
-                       msg(DBG_INF,"sbp_data() statistics: %d waits in %d frames.\n", data_waits, data_tries);
-                       data_waits = data_tries = 0;
-               }
-       }
-       duration=jiffies-duration;
-       msg(DBG_TEA,"time to read %d frames: %d jiffies .\n",frame,duration);
-       if (famT_drive)
-       {
-               wait=8;
-               do
-               {
-                       if (teac==2)
-                          {
-                            if ((i=CDi_stat_loop_T()) == -1) break;
-                          }
-                        else
-                          {
-                            sbp_sleep(1);
-                            OUT(CDo_sel_i_d,0);
-                            i=inb(CDi_status);
-                          }
-                       if (!(i&s_not_data_ready))
-                       {
-                               OUT(CDo_sel_i_d,1);
-                               j=0;
-                               do
-                               {
-                                       if (do_16bit) i=inw(CDi_data);
-                                       else i=inb(CDi_data);
-                                       j++;
-                                       i=inb(CDi_status);
-                               }
-                               while (!(i&s_not_data_ready));
-                               msg(DBG_TEA, "==========too much data (%d bytes/words)==============.\n", j);
-                       }
-                       if (!(i&s_not_result_ready))
-                       {
-                               OUT(CDo_sel_i_d,0);
-                               l=0;
-                               do
-                               {
-                                       infobuf[l++]=inb(CDi_info);
-                                       i=inb(CDi_status);
-                               }
-                               while (!(i&s_not_result_ready));
-                               if (infobuf[0]==0x00) success=1;
-#if 1
-                               for (j=0;j<l;j++) sprintf(&msgbuf[j*3], " %02X", infobuf[j]);
-                               msgbuf[j*3]=0;
-                               msg(DBG_TEA,"sbp_data info response:%s\n", msgbuf);
-#endif
-                               if (infobuf[0]==0x02)
-                               {
-                                       error_flag++;
-                                       do
-                                       {
-                                               ++recursion;
-                                               if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",recursion);
-                                               else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.\n");
-                                               clr_cmdbuf();
-                                               drvcmd[0]=CMDT_READ_ERR;
-                                               j=cmd_out_T(); /* !!! recursive here !!! */
-                                               --recursion;
-                                               sbp_sleep(1);
-                                       }
-                                       while (j<0);
-                                       current_drive->error_state=infobuf[2];
-                                       current_drive->b3=infobuf[3];
-                                       current_drive->b4=infobuf[4];
-                               }
-                               break;
-                       }
-                       else
-                       {
-#if 0
-                               msg(DBG_TEA, "============= waiting for result=================.\n");
-                               sbp_sleep(1);
-#endif
-                       }
-               }
-               while (wait--);
-       }
-
-       if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
-       {
-               msg(DBG_TEA, "================error flag: %d=================.\n", error_flag);
-               msg(DBG_INF,"sbp_data: read aborted by drive.\n");
-#if 1
-               i=cc_DriveReset(); /* ugly fix to prevent a hang */
-#else
-               i=cc_ReadError();
-#endif
-               return (0);
-       }
-       
-       if (fam0LV_drive)
-       {
-               SBPCD_CLI;
-               i=maxtim_data;
-               for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--)
-               {
-                       for ( ;i!=0;i--)
-                       {
-                               j=inb(CDi_status);
-                               if (!(j&s_not_data_ready)) break;
-                               if (!(j&s_not_result_ready)) break;
-                               if (j&s_attention) break;
-                       }
-                       if (i != 0 || time_after_eq(jiffies, timeout)) break;
-                       sbp_sleep(0);
-                       i = 1;
-               }
-               if (i==0) msg(DBG_INF,"status timeout after READ.\n");
-               if (!(j&s_attention))
-               {
-                       msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n");
-                       i=cc_DriveReset();  /* ugly fix to prevent a hang */
-                       SBPCD_STI;
-                       return (0);
-               }
-               SBPCD_STI;
-       }
-
-#if 0
-       if (!success)
-#endif
-               do
-               {
-                       if (fam0LV_drive) cc_ReadStatus();
-#if 1
-                       if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.\n", i);
-#endif
-                       i=ResponseStatus();  /* builds status_bits, returns orig. status (old) or faked p_success (new) */
-#if 1
-                       if (famT_drive) msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i);
-#endif
-                       if (i<0)
-                       {
-                               msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits);
-                               return (0);
-                       }
-               }
-               while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success)));
-       if (st_check)
-       {
-               i=cc_ReadError();
-               msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i);
-               return (0);
-       }
-       if (fatal_err)
-       {
-               fatal_err=0;
-               current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1;      /* purge buffer */
-               current_drive->sbp_current = 0;
-               msg(DBG_INF,"sbp_data: fatal_err - retrying.\n");
-               return (0);
-       }
-       
-       current_drive->sbp_first_frame = req -> sector / 4;
-       current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1;
-       sbp_transfer(req);
-       return (1);
-}
-/*==========================================================================*/
-
-static int sbpcd_block_open(struct inode *inode, struct file *file)
-{
-       struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
-       return cdrom_open(p->sbpcd_infop, inode, file);
-}
-
-static int sbpcd_block_release(struct inode *inode, struct file *file)
-{
-       struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
-       return cdrom_release(p->sbpcd_infop, file);
-}
-
-static int sbpcd_block_ioctl(struct inode *inode, struct file *file,
-                               unsigned cmd, unsigned long arg)
-{
-       struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
-       struct cdrom_device_info *cdi = p->sbpcd_infop;
-       int ret, i;
-
-       ret = cdrom_ioctl(file, p->sbpcd_infop, inode, cmd, arg);
-       if (ret != -ENOSYS)
-               return ret;
-
-       msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg);
-       if (p->drv_id==-1) {
-               msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
-               return (-ENXIO);             /* no such drive */
-       }
-       down(&ioctl_read_sem);
-       if (p != current_drive)
-               switch_drive(p);
-       
-       msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
-       switch (cmd)            /* Sun-compatible */
-       {
-       case DDIOCSDBG:         /* DDI Debug */
-               if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM);
-               i=sbpcd_dbg_ioctl(arg,1);
-               RETURN_UP(i);
-       case CDROMRESET:      /* hard reset the drive */
-               msg(DBG_IOC,"ioctl: CDROMRESET entered.\n");
-               i=DriveReset();
-               current_drive->audio_state=0;
-               RETURN_UP(i);
-
-       case CDROMREADMODE1:
-               msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n");
-#ifdef SAFE_MIXED
-               if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
-               cc_ModeSelect(CD_FRAMESIZE);
-               cc_ModeSense();
-               current_drive->mode=READ_M1;
-               RETURN_UP(0);
-
-       case CDROMREADMODE2: /* not usable at the moment */
-               msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n");
-#ifdef SAFE_MIXED
-               if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
-               cc_ModeSelect(CD_FRAMESIZE_RAW1);
-               cc_ModeSense();
-               current_drive->mode=READ_M2;
-               RETURN_UP(0);
-
-       case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */
-               msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n");
-               if (current_drive->sbp_audsiz>0)
-                       vfree(current_drive->aud_buf);
-               current_drive->aud_buf=NULL;
-               current_drive->sbp_audsiz=arg;
-
-               if (current_drive->sbp_audsiz>16)
-               {
-                       current_drive->sbp_audsiz = 0;
-                       RETURN_UP(current_drive->sbp_audsiz);
-               }
-       
-               if (current_drive->sbp_audsiz>0)
-               {
-                       current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW);
-                       if (current_drive->aud_buf==NULL)
-                       {
-                               msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz);
-                               current_drive->sbp_audsiz=0;
-                       }
-                       else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz);
-               }
-               RETURN_UP(current_drive->sbp_audsiz);
-
-       case CDROMREADAUDIO:
-       { /* start of CDROMREADAUDIO */
-               int i=0, j=0, frame, block=0;
-               u_int try=0;
-               u_long timeout;
-               u_char *p;
-               u_int data_tries = 0;
-               u_int data_waits = 0;
-               u_int data_retrying = 0;
-               int status_tries;
-               int error_flag;
-
-               msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n");
-               if (fam0_drive) RETURN_UP(-EINVAL);
-               if (famL_drive) RETURN_UP(-EINVAL);
-               if (famV_drive) RETURN_UP(-EINVAL);
-               if (famT_drive) RETURN_UP(-EINVAL);
-#ifdef SAFE_MIXED
-               if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
-               if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL);
-               if (copy_from_user(&read_audio, (void __user *)arg,
-                                  sizeof(struct cdrom_read_audio)))
-                       RETURN_UP(-EFAULT);
-               if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL);
-               if (!access_ok(VERIFY_WRITE, read_audio.buf,
-                             read_audio.nframes*CD_FRAMESIZE_RAW))
-                       RETURN_UP(-EFAULT);
-
-               if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */
-                       block=msf2lba(&read_audio.addr.msf.minute);
-               else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */
-                       block=read_audio.addr.lba;
-               else RETURN_UP(-EINVAL);
-#if 000
-               i=cc_SetSpeed(speed_150,0,0);
-               if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i);
-#endif
-               msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n",
-                   block, blk2msf(block));
-               msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n");
-#if OLD_BUSY
-               while (busy_data) sbp_sleep(HZ/10); /* wait a bit */
-               busy_audio=1;
-#endif /* OLD_BUSY */
-               error_flag=0;
-               for (data_tries=5; data_tries>0; data_tries--)
-               {
-                       msg(DBG_AUD,"data_tries=%d ...\n", data_tries);
-                       current_drive->mode=READ_AU;
-                       cc_ModeSelect(CD_FRAMESIZE_RAW);
-                       cc_ModeSense();
-                       for (status_tries=3; status_tries > 0; status_tries--)
-                       {
-                               flags_cmd_out |= f_respo3;
-                               cc_ReadStatus();
-                               if (sbp_status() != 0) break;
-                               if (st_check) cc_ReadError();
-                               sbp_sleep(1);    /* wait a bit, try again */
-                       }
-                       if (status_tries == 0)
-                       {
-                               msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__);
-                               continue;
-                       }
-                       msg(DBG_AUD,"read_audio: sbp_status: ok.\n");
-
-                       flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
-                       if (fam0L_drive)
-                       {
-                               flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
-                               cmd_type=READ_M2;
-                               drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
-                               drvcmd[1]=(block>>16)&0x000000ff;
-                               drvcmd[2]=(block>>8)&0x000000ff;
-                               drvcmd[3]=block&0x000000ff;
-                               drvcmd[4]=0;
-                               drvcmd[5]=read_audio.nframes; /* # of frames */
-                               drvcmd[6]=0;
-                       }
-                       else if (fam1_drive)
-                       {
-                               drvcmd[0]=CMD1_READ; /* "read frames", new drives */
-                               lba2msf(block,&drvcmd[1]); /* msf-bin format required */
-                               drvcmd[4]=0;
-                               drvcmd[5]=0;
-                               drvcmd[6]=read_audio.nframes; /* # of frames */
-                       }
-                       else if (fam2_drive)
-                       {
-                               drvcmd[0]=CMD2_READ_XA2;
-                               lba2msf(block,&drvcmd[1]); /* msf-bin format required */
-                               drvcmd[4]=0;
-                               drvcmd[5]=read_audio.nframes; /* # of frames */
-                               drvcmd[6]=0x11; /* raw mode */
-                       }
-                       else if (famT_drive) /* CD-55A: not tested yet */
-                       {
-                       }
-                       msg(DBG_AUD,"read_audio: before giving \"read\" command.\n");
-                       flags_cmd_out=f_putcmd;
-                       response_count=0;
-                       i=cmd_out();
-                       if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0d\n", i);
-                       sbp_sleep(0);
-                       msg(DBG_AUD,"read_audio: after giving \"read\" command.\n");
-                       for (frame=1;frame<2 && !error_flag; frame++)
-                       {
-                               try=maxtim_data;
-                               for (timeout=jiffies+9*HZ; ; )
-                               {
-                                       for ( ; try!=0;try--)
-                                       {
-                                               j=inb(CDi_status);
-                                               if (!(j&s_not_data_ready)) break;
-                                               if (!(j&s_not_result_ready)) break;
-                                               if (fam0L_drive) if (j&s_attention) break;
-                                       }
-                                       if (try != 0 || time_after_eq(jiffies, timeout)) break;
-                                       if (data_retrying == 0) data_waits++;
-                                       data_retrying = 1;
-                                       sbp_sleep(1);
-                                       try = 1;
-                               }
-                               if (try==0)
-                               {
-                                       msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n");
-                                       error_flag++;
-                                       break;
-                               }
-                               msg(DBG_AUD,"read_audio: sbp_data: CDi_status ok.\n");
-                               if (j&s_not_data_ready)
-                               {
-                                       msg(DBG_INF, "read_audio: sbp_data: DATA_READY timeout.\n");
-                                       error_flag++;
-                                       break;
-                               }
-                               msg(DBG_AUD,"read_audio: before reading data.\n");
-                               error_flag=0;
-                               p = current_drive->aud_buf;
-                               if (sbpro_type==1) OUT(CDo_sel_i_d,1);
-                               if (do_16bit)
-                               {
-                                       u_short *p2 = (u_short *) p;
-
-                                       for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
-                                       {
-                                               if ((inb_p(CDi_status)&s_not_data_ready)) continue;
-
-                                               /* get one sample */
-                                               *p2++ = inw_p(CDi_data);
-                                               *p2++ = inw_p(CDi_data);
-                                       }
-                               } else {
-                                       for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
-                                       {
-                                               if ((inb_p(CDi_status)&s_not_data_ready)) continue;
-
-                                               /* get one sample */
-                                               *p++ = inb_p(CDi_data);
-                                               *p++ = inb_p(CDi_data);
-                                               *p++ = inb_p(CDi_data);
-                                               *p++ = inb_p(CDi_data);
-                                       }
-                               }
-                               if (sbpro_type==1) OUT(CDo_sel_i_d,0);
-                               data_retrying = 0;
-                       }
-                       msg(DBG_AUD,"read_audio: after reading data.\n");
-                       if (error_flag)    /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
-                       {
-                               msg(DBG_AUD,"read_audio: read aborted by drive\n");
-#if 0000
-                               i=cc_DriveReset();                /* ugly fix to prevent a hang */
-#else
-                               i=cc_ReadError();
-#endif
-                               continue;
-                       }
-                       if (fam0L_drive)
-                       {
-                               i=maxtim_data;
-                               for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--)
-                               {
-                                       for ( ;i!=0;i--)
-                                       {
-                                               j=inb(CDi_status);
-                                               if (!(j&s_not_data_ready)) break;
-                                               if (!(j&s_not_result_ready)) break;
-                                               if (j&s_attention) break;
-                                       }
-                                       if (i != 0 || time_after_eq(jiffies, timeout)) break;
-                                       sbp_sleep(0);
-                                       i = 1;
-                               }
-                               if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ");
-                               if (!(j&s_attention))
-                               {
-                                       msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n");
-                                       i=cc_DriveReset();  /* ugly fix to prevent a hang */
-                                       continue;
-                               }
-                       }
-                       do
-                       {
-                               if (fam0L_drive) cc_ReadStatus();
-                               i=ResponseStatus();  /* builds status_bits, returns orig. status (old) or faked p_success (new) */
-                               if (i<0) { msg(DBG_AUD,
-                                              "read_audio: cc_ReadStatus error after read: %02X\n",
-                                              current_drive->status_bits);
-                                          continue; /* FIXME */
-                                  }
-                       }
-                       while ((fam0L_drive)&&(!st_check)&&(!(i&p_success)));
-                       if (st_check)
-                       {
-                               i=cc_ReadError();
-                               msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i);
-                               continue;
-                       }
-                       if (copy_to_user(read_audio.buf,
-                                        current_drive->aud_buf,
-                                        read_audio.nframes * CD_FRAMESIZE_RAW))
-                               RETURN_UP(-EFAULT);
-                       msg(DBG_AUD,"read_audio: copy_to_user done.\n");
-                       break;
-               }
-               cc_ModeSelect(CD_FRAMESIZE);
-               cc_ModeSense();
-               current_drive->mode=READ_M1;
-#if OLD_BUSY
-               busy_audio=0;
-#endif /* OLD_BUSY */
-               if (data_tries == 0)
-               {
-                       msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__);
-                       RETURN_UP(-EIO);
-               }
-               msg(DBG_AUD,"read_audio: successful return.\n");
-               RETURN_UP(0);
-       } /* end of CDROMREADAUDIO */
-
-       default:
-               msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
-               RETURN_UP(-EINVAL);
-       } /* end switch(cmd) */
-}
-
-static int sbpcd_block_media_changed(struct gendisk *disk)
-{
-       struct sbpcd_drive *p = disk->private_data;
-       return cdrom_media_changed(p->sbpcd_infop);
-}
-
-static struct block_device_operations sbpcd_bdops =
-{
-       .owner          = THIS_MODULE,
-       .open           = sbpcd_block_open,
-       .release        = sbpcd_block_release,
-       .ioctl          = sbpcd_block_ioctl,
-       .media_changed  = sbpcd_block_media_changed,
-};
-/*==========================================================================*/
-/*
- *  Open the device special file.  Check that a disk is in. Read TOC.
- */
-static int sbpcd_open(struct cdrom_device_info *cdi, int purpose)
-{
-       struct sbpcd_drive *p = cdi->handle;
-
-       down(&ioctl_read_sem);
-       switch_drive(p);
-
-       /*
-        * try to keep an "open" counter here and lock the door if 0->1.
-        */
-       msg(DBG_LCK,"open_count: %d -> %d\n",
-           current_drive->open_count,current_drive->open_count+1);
-       if (++current_drive->open_count<=1)
-       {
-               int i;
-               i=LockDoor();
-               current_drive->open_count=1;
-               if (famT_drive) msg(DBG_TEA,"sbpcd_open: before i=DiskInfo();.\n");
-               i=DiskInfo();
-               if (famT_drive) msg(DBG_TEA,"sbpcd_open: after i=DiskInfo();.\n");
-               if ((current_drive->ored_ctl_adr&0x40)==0)
-               {               
-                       msg(DBG_INF,"CD contains no data tracks.\n");
-#ifdef SAFE_MIXED
-                       current_drive->has_data=0;
-#endif /* SAFE_MIXED */
-               }
-#ifdef SAFE_MIXED
-               else if (current_drive->has_data<1) current_drive->has_data=1;
-#endif /* SAFE_MIXED */ 
-       }
-       if (!st_spinning) cc_SpinUp();
-       RETURN_UP(0);
-}
-/*==========================================================================*/
-/*
- *  On close, we flush all sbp blocks from the buffer cache.
- */
-static void sbpcd_release(struct cdrom_device_info * cdi)
-{
-       struct sbpcd_drive *p = cdi->handle;
-
-       if (p->drv_id==-1) {
-               msg(DBG_INF, "release: bad device: %s\n", cdi->name);
-               return;
-       }
-       down(&ioctl_read_sem);
-       switch_drive(p);
-       /*
-        * try to keep an "open" counter here and unlock the door if 1->0.
-        */
-       msg(DBG_LCK,"open_count: %d -> %d\n",
-           p->open_count,p->open_count-1);
-       if (p->open_count>-2) /* CDROMEJECT may have been done */
-       {
-               if (--p->open_count<=0) 
-               {
-                       p->sbp_first_frame=p->sbp_last_frame=-1;
-                       if (p->audio_state!=audio_playing)
-                               if (p->f_eject) cc_SpinDown();
-                       p->diskstate_flags &= ~cd_size_bit;
-                       p->open_count=0; 
-#ifdef SAFE_MIXED
-                       p->has_data=0;
-#endif /* SAFE_MIXED */ 
-               }
-       }
-       up(&ioctl_read_sem);
-       return ;
-}
-/*==========================================================================*/
-/*
- *
- */
-static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr);
-static struct cdrom_device_ops sbpcd_dops = {
-       .open                   = sbpcd_open,
-       .release                = sbpcd_release,
-       .drive_status           = sbpcd_drive_status,
-       .media_changed          = sbpcd_media_changed,
-       .tray_move              = sbpcd_tray_move,
-       .lock_door              = sbpcd_lock_door,
-       .select_speed           = sbpcd_select_speed,
-       .get_last_session       = sbpcd_get_last_session,
-       .get_mcn                = sbpcd_get_mcn,
-       .reset                  = sbpcd_reset,
-       .audio_ioctl            = sbpcd_audio_ioctl,
-       .capability             = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
-                               CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
-                               CDC_MCN | CDC_PLAY_AUDIO,
-       .n_minors               = 1,
-};
-
-/*==========================================================================*/
-/*
- * accept "kernel command line" parameters 
- * (suggested by Peter MacDonald with SLS 1.03)
- *
- * This is only implemented for the first controller. Should be enough to
- * allow installing with a "strange" distribution kernel.
- *
- * use: tell LILO:
- *                 sbpcd=0x230,SoundBlaster
- *             or
- *                 sbpcd=0x300,LaserMate
- *             or
- *                 sbpcd=0x338,SoundScape
- *             or
- *                 sbpcd=0x2C0,Teac16bit
- *
- * (upper/lower case sensitive here - but all-lowercase is ok!!!).
- *
- * the address value has to be the CDROM PORT ADDRESS -
- * not the soundcard base address.
- * For the SPEA/SoundScape setup, DO NOT specify the "configuration port"
- * address, but the address which is really used for the CDROM (usually 8
- * bytes above).
- *
- */
-
-int sbpcd_setup(char *s)
-{
-#ifndef MODULE
-       int p[4];
-       (void)get_options(s, ARRAY_SIZE(p), p);
-       setup_done++;
-       msg(DBG_INI,"sbpcd_setup called with %04X,%s\n",p[1], s);
-       sbpro_type=0; /* default: "LaserMate" */
-       if (p[0]>1) sbpro_type=p[2];
-       else if (!strcmp(s,str_sb)) sbpro_type=1;
-       else if (!strcmp(s,str_sb_l)) sbpro_type=1;
-       else if (!strcmp(s,str_sp)) sbpro_type=2;
-       else if (!strcmp(s,str_sp_l)) sbpro_type=2;
-       else if (!strcmp(s,str_ss)) sbpro_type=2;
-       else if (!strcmp(s,str_ss_l)) sbpro_type=2;
-       else if (!strcmp(s,str_t16)) sbpro_type=3;
-       else if (!strcmp(s,str_t16_l)) sbpro_type=3;
-       if (p[0]>0) sbpcd_ioaddr=p[1];
-       if (p[0]>2) max_drives=p[3];
-#else
-       sbpcd_ioaddr = sbpcd[0];
-       sbpro_type = sbpcd[1];
-#endif
-       
-       CDo_command=sbpcd_ioaddr;
-       CDi_info=sbpcd_ioaddr;
-       CDi_status=sbpcd_ioaddr+1;
-       CDo_sel_i_d=sbpcd_ioaddr+1;
-       CDo_reset=sbpcd_ioaddr+2;
-       CDo_enable=sbpcd_ioaddr+3; 
-       f_16bit=0;
-       if ((sbpro_type==1)||(sbpro_type==3))
-       {
-               CDi_data=sbpcd_ioaddr;
-               if (sbpro_type==3)
-                {
-                        f_16bit=1;
-                        sbpro_type=1;
-                }
-       }
-       else CDi_data=sbpcd_ioaddr+2;
-
-       return 1;
-}
-
-__setup("sbpcd=", sbpcd_setup);
-
-
-/*==========================================================================*/
-/*
- * Sequoia S-1000 CD-ROM Interface Configuration
- * as used within SPEA Media FX, Ensonic SoundScape and some Reveal cards
- * The soundcard has to get jumpered for the interface type "Panasonic"
- * (not Sony or Mitsumi) and to get soft-configured for
- *     -> configuration port address
- *     -> CDROM port offset (num_ports): has to be 8 here. Possibly this
- *        offset value determines the interface type (none, Panasonic,
- *        Mitsumi, Sony).
- *        The interface uses a configuration port (0x320, 0x330, 0x340, 0x350)
- *        some bytes below the real CDROM address.
- *         
- *        For the Panasonic style (LaserMate) interface and the configuration
- *        port 0x330, we have to use an offset of 8; so, the real CDROM port
- *        address is 0x338.
- */
-static int __init config_spea(void)
-{
-       /*
-         * base address offset between configuration port and CDROM port,
-        * this probably defines the interface type
-         *   2 (type=??): 0x00
-         *   8 (type=LaserMate):0x10
-         *  16 (type=??):0x20
-         *  32 (type=??):0x30
-         */
-       int n_ports=0x10;
-
-       int irq_number=0; /* off:0x00, 2/9:0x01, 7:0x03, 12:0x05, 15:0x07 */
-       int dma_channel=0; /* off: 0x00, 0:0x08, 1:0x18, 3:0x38, 5:0x58, 6:0x68 */
-       int dack_polarity=0; /* L:0x00, H:0x80 */
-       int drq_polarity=0x40; /* L:0x00, H:0x40 */
-       int i;
-
-#define SPEA_REG_1 sbpcd_ioaddr-0x08+4
-#define SPEA_REG_2 sbpcd_ioaddr-0x08+5
-       
-       OUT(SPEA_REG_1,0xFF);
-       i=inb(SPEA_REG_1);
-       if (i!=0x0F)
-       {
-               msg(DBG_SEQ,"no SPEA interface at %04X present.\n", sbpcd_ioaddr);
-               return (-1); /* no interface found */
-       }
-       OUT(SPEA_REG_1,0x04);
-       OUT(SPEA_REG_2,0xC0);
-       
-       OUT(SPEA_REG_1,0x05);
-       OUT(SPEA_REG_2,0x10|drq_polarity|dack_polarity);
-       
-#if 1
-#define SPEA_PATTERN 0x80
-#else
-#define SPEA_PATTERN 0x00
-#endif
-       OUT(SPEA_REG_1,0x06);
-       OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN);
-       OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN);
-       
-       OUT(SPEA_REG_1,0x09);
-       i=(inb(SPEA_REG_2)&0xCF)|n_ports;
-       OUT(SPEA_REG_2,i);
-       
-       sbpro_type = 0; /* acts like a LaserMate interface now */
-       msg(DBG_SEQ,"found SoundScape interface at %04X.\n", sbpcd_ioaddr);
-       return (0);
-}
-
-/*==========================================================================*/
-/*
- *  Test for presence of drive and initialize it.
- *  Called once at boot or load time.
- */
-
-/* FIXME: cleanups after failed allocations are too ugly for words */
-#ifdef MODULE
-int __init __sbpcd_init(void)
-#else
-int __init sbpcd_init(void)
-#endif
-{
-       int i=0, j=0;
-       int addr[2]={1, CDROM_PORT};
-       int port_index;
-
-       sti();
-       
-       msg(DBG_INF,"sbpcd.c %s\n", VERSION);
-#ifndef MODULE
-#if DISTRIBUTION
-       if (!setup_done)
-       {
-               msg(DBG_INF,"Looking for Matsushita/Panasonic, CreativeLabs, Longshine, TEAC CD-ROM drives\n");
-               msg(DBG_INF,"= = = = = = = = = = W A R N I N G = = = = = = = = = =\n");
-               msg(DBG_INF,"Auto-Probing can cause a hang (f.e. touching an NE2000 card).\n");
-               msg(DBG_INF,"If that happens, you have to reboot and use the\n");
-               msg(DBG_INF,"LILO (kernel) command line feature like:\n");
-               msg(DBG_INF,"   LILO boot: ... sbpcd=0x230,SoundBlaster\n");
-               msg(DBG_INF,"or like:\n");
-               msg(DBG_INF,"   LILO boot: ... sbpcd=0x300,LaserMate\n");
-               msg(DBG_INF,"or like:\n");
-               msg(DBG_INF,"   LILO boot: ... sbpcd=0x338,SoundScape\n");
-               msg(DBG_INF,"with your REAL address.\n");
-               msg(DBG_INF,"= = = = = = = = = = END of WARNING = = = = = == = = =\n");
-       }
-#endif /* DISTRIBUTION */
-       sbpcd[0]=sbpcd_ioaddr; /* possibly changed by kernel command line */
-       sbpcd[1]=sbpro_type; /* possibly changed by kernel command line */
-#endif /* MODULE */
-       
-       for (port_index=0;port_index<NUM_PROBE;port_index+=2)
-       {
-               addr[1]=sbpcd[port_index];
-               if (addr[1]==0) break;
-               if (check_region(addr[1],4))
-               {
-                       msg(DBG_INF,"check_region: %03X is not free.\n",addr[1]);
-                       continue;
-               }
-               if (sbpcd[port_index+1]==2) type=str_sp;
-               else if (sbpcd[port_index+1]==1) type=str_sb;
-               else if (sbpcd[port_index+1]==3) type=str_t16;
-               else type=str_lm;
-               sbpcd_setup((char *)type);
-#if DISTRIBUTION
-               msg(DBG_INF,"Scanning 0x%X (%s)...\n", CDo_command, type);
-#endif /* DISTRIBUTION */
-               if (sbpcd[port_index+1]==2)
-               {
-                       i=config_spea();
-                       if (i<0) continue;
-               }
-#ifdef PATH_CHECK
-               if (check_card(addr[1])) continue;
-#endif /* PATH_CHECK */ 
-               i=check_drives();
-               msg(DBG_INI,"check_drives done.\n");
-               if (i>=0) break; /* drive found */
-       } /* end of cycling through the set of possible I/O port addresses */
-       
-       if (ndrives==0)
-       {
-               msg(DBG_INF, "No drive found.\n");
-#ifdef MODULE
-               return -EIO;
-#else
-               goto init_done;
-#endif /* MODULE */
-       }
-       
-       if (port_index>0)
-          {
-            msg(DBG_INF, "You should read Documentation/cdrom/sbpcd\n");
-            msg(DBG_INF, "and then configure sbpcd.h for your hardware.\n");
-          }
-       check_datarate();
-       msg(DBG_INI,"check_datarate done.\n");
-       
-       for (j=0;j<NR_SBPCD;j++)
-       {
-               struct sbpcd_drive *p = D_S + j;
-               if (p->drv_id==-1)
-                       continue;
-               switch_drive(p);
-#if 1
-               if (!famL_drive) cc_DriveReset();
-#endif
-               if (!st_spinning) cc_SpinUp();
-               p->sbp_first_frame = -1;  /* First frame in buffer */
-               p->sbp_last_frame = -1;   /* Last frame in buffer  */
-               p->sbp_read_frames = 0;   /* Number of frames being read to buffer */
-               p->sbp_current = 0;       /* Frame being currently read */
-               p->CD_changed=1;
-               p->frame_size=CD_FRAMESIZE;
-               p->f_eject=0;
-#if EJECT
-               if (!fam0_drive) p->f_eject=1;
-#endif /* EJECT */ 
-               cc_ReadStatus();
-               i=ResponseStatus();  /* returns orig. status or p_busy_new */
-               if (famT_drive) i=ResponseStatus();  /* returns orig. status or p_busy_new */
-               if (i<0)
-               {
-                       if (i!=-402)
-                               msg(DBG_INF,"init: ResponseStatus returns %d.\n",i);
-               }
-               else
-               {
-                       if (st_check)
-                       {
-                               i=cc_ReadError();
-                               msg(DBG_INI,"init: cc_ReadError returns %d\n",i);
-                       }
-               }
-               msg(DBG_INI,"init: first GetStatus: %d\n",i);
-               msg(DBG_LCS,"init: first GetStatus: error_byte=%d\n",
-                   p->error_byte);
-               if (p->error_byte==aud_12)
-               {
-                       timeout=jiffies+2*HZ;
-                       do
-                       {
-                               i=GetStatus();
-                               msg(DBG_INI,"init: second GetStatus: %02X\n",i);
-                               msg(DBG_LCS,
-                                   "init: second GetStatus: error_byte=%d\n",
-                                   p->error_byte);
-                               if (i<0) break;
-                               if (!st_caddy_in) break;
-                               }
-                       while ((!st_diskok)||time_after(jiffies, timeout));
-               }
-               i=SetSpeed();
-               if (i>=0) p->CD_changed=1;
-       }
-
-       if (!request_region(CDo_command,4,major_name))
-       {
-               printk(KERN_WARNING "sbpcd: Unable to request region 0x%x\n", CDo_command);
-               return -EIO;
-       }
-
-       /*
-        * Turn on the CD audio channels.
-        * The addresses are obtained from SOUND_BASE (see sbpcd.h).
-        */
-#if SOUND_BASE
-       OUT(MIXER_addr,MIXER_CD_Volume); /* select SB Pro mixer register */
-       OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */
-#endif /* SOUND_BASE */
-
-       if (register_blkdev(MAJOR_NR, major_name)) {
-#ifdef MODULE
-               return -EIO;
-#else
-               goto init_done;
-#endif /* MODULE */
-       }
-
-       /*
-        * init error handling is broken beyond belief in this driver...
-        */
-       sbpcd_queue = blk_init_queue(do_sbpcd_request, &sbpcd_lock);
-       if (!sbpcd_queue) {
-               release_region(CDo_command,4);
-               unregister_blkdev(MAJOR_NR, major_name);
-               return -ENOMEM;
-       }
-
-       for (j=0;j<NR_SBPCD;j++)
-       {
-               struct cdrom_device_info * sbpcd_infop;
-               struct gendisk *disk;
-               struct sbpcd_drive *p = D_S + j;
-
-               if (p->drv_id==-1) continue;
-               switch_drive(p);
-#ifdef SAFE_MIXED
-               p->has_data=0;
-#endif /* SAFE_MIXED */ 
-               /*
-                * allocate memory for the frame buffers
-                */
-               p->aud_buf=NULL;
-               p->sbp_audsiz=0;
-               p->sbp_bufsiz=buffers;
-               if (p->drv_type&drv_fam1)
-                       if (READ_AUDIO>0)
-                               p->sbp_audsiz = READ_AUDIO;
-               p->sbp_buf=(u_char *) vmalloc(buffers*CD_FRAMESIZE);
-               if (!p->sbp_buf) {
-                       msg(DBG_INF,"data buffer (%d frames) not available.\n",
-                               buffers);
-                       if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
-                       {
-                               printk("Can't unregister %s\n", major_name);
-                       }
-                       release_region(CDo_command,4);
-                       blk_cleanup_queue(sbpcd_queue);
-                       return -EIO;
-               }
-#ifdef MODULE
-               msg(DBG_INF,"data buffer size: %d frames.\n",buffers);
-#endif /* MODULE */
-               if (p->sbp_audsiz>0)
-               {
-                       p->aud_buf=(u_char *) vmalloc(p->sbp_audsiz*CD_FRAMESIZE_RAW);
-                       if (p->aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.\n",p->sbp_audsiz);
-                       else msg(DBG_INF,"audio buffer size: %d frames.\n",p->sbp_audsiz);
-               }
-                sbpcd_infop = vmalloc(sizeof (struct cdrom_device_info));
-               if (sbpcd_infop == NULL)
-               {
-                        release_region(CDo_command,4);
-                       blk_cleanup_queue(sbpcd_queue);
-                        return -ENOMEM;
-               }
-               memset(sbpcd_infop, 0, sizeof(struct cdrom_device_info));
-               sbpcd_infop->ops = &sbpcd_dops;
-               sbpcd_infop->speed = 2;
-               sbpcd_infop->capacity = 1;
-               sprintf(sbpcd_infop->name, "sbpcd%d", j);
-               sbpcd_infop->handle = p;
-               p->sbpcd_infop = sbpcd_infop;
-               disk = alloc_disk(1);
-               disk->major = MAJOR_NR;
-               disk->first_minor = j;
-               disk->fops = &sbpcd_bdops;
-               strcpy(disk->disk_name, sbpcd_infop->name);
-               disk->flags = GENHD_FL_CD;
-               p->disk = disk;
-               if (register_cdrom(sbpcd_infop))
-               {
-                       printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n");
-               }
-               disk->private_data = p;
-               disk->queue = sbpcd_queue;
-               add_disk(disk);
-       }
-       blk_queue_hardsect_size(sbpcd_queue, CD_FRAMESIZE);
-
-#ifndef MODULE
- init_done:
-#endif
-       return 0;
-}
-/*==========================================================================*/
-#ifdef MODULE
-static void sbpcd_exit(void)
-{
-       int j;
-       
-       if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
-       {
-               msg(DBG_INF, "What's that: can't unregister %s.\n", major_name);
-               return;
-       }
-       release_region(CDo_command,4);
-       blk_cleanup_queue(sbpcd_queue);
-       for (j=0;j<NR_SBPCD;j++)
-       {
-               if (D_S[j].drv_id==-1) continue;
-               del_gendisk(D_S[j].disk);
-               put_disk(D_S[j].disk);
-               vfree(D_S[j].sbp_buf);
-               if (D_S[j].sbp_audsiz>0)
-                       vfree(D_S[j].aud_buf);
-               if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL))
-               {
-                       msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name);
-                       return;
-               }
-               vfree(D_S[j].sbpcd_infop);
-       }
-       msg(DBG_INF, "%s module released.\n", major_name);
-}
-
-
-module_init(__sbpcd_init) /*HACK!*/;
-module_exit(sbpcd_exit);
-
-
-#endif /* MODULE */
-static int sbpcd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
-       struct sbpcd_drive *p = cdi->handle;
-       msg(DBG_CHK,"media_check (%s) called\n", cdi->name);
-       
-       if (p->CD_changed==0xFF)
-        {
-                p->CD_changed=0;
-                msg(DBG_CHK,"medium changed (drive %s)\n", cdi->name);
-               current_drive->diskstate_flags &= ~toc_bit;
-               /* we *don't* need invalidate here, it's done by caller */
-               current_drive->diskstate_flags &= ~cd_size_bit;
-#ifdef SAFE_MIXED
-               current_drive->has_data=0;
-#endif /* SAFE_MIXED */ 
-
-                return (1);
-        }
-        else
-                return (0);
-}
-
-MODULE_LICENSE("GPL");
-/* FIXME: Old modules.conf claims MATSUSHITA_CDROM2_MAJOR and CDROM3, but
-   AFAICT this doesn't support those majors, so why? --RR 30 Jul 2003 */
-MODULE_ALIAS_BLOCKDEV_MAJOR(MATSUSHITA_CDROM_MAJOR);
-
-/*==========================================================================*/
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file. 
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 8
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -8
- * c-argdecl-indent: 8
- * c-label-offset: -8
- * c-continued-statement-offset: 8
- * c-continued-brace-offset: 0
- * End:
- */
-
diff --git a/drivers/cdrom/sbpcd.h b/drivers/cdrom/sbpcd.h
deleted file mode 100644 (file)
index 2f2225f..0000000
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
- * sbpcd.h   Specify interface address and interface type here.
- */
-
-/*
- * Attention! This file contains user-serviceable parts!
- * I recommend to make use of it...
- * If you feel helpless, look into Documentation/cdrom/sbpcd
- * (good idea anyway, at least before mailing me).
- *
- * The definitions for the first controller can get overridden by
- * the kernel command line ("lilo boot option").
- * Examples:
- *                                 sbpcd=0x300,LaserMate
- *                             or
- *                                 sbpcd=0x230,SoundBlaster
- *                             or
- *                                 sbpcd=0x338,SoundScape
- *                             or
- *                                 sbpcd=0x2C0,Teac16bit
- *
- * If sbpcd gets used as a module, you can load it with
- *     insmod sbpcd.o sbpcd=0x300,0
- * or
- *     insmod sbpcd.o sbpcd=0x230,1
- * or
- *     insmod sbpcd.o sbpcd=0x338,2
- * or
- *     insmod sbpcd.o sbpcd=0x2C0,3
- * respective to override the configured address and type.
- */
-
-/*
- * define your CDROM port base address as CDROM_PORT
- * and specify the type of your interface card as SBPRO.
- *
- * address:
- * ========
- * SBPRO type addresses typically are 0x0230 (=0x220+0x10), 0x0250, ...
- * LASERMATE type (CI-101P, WDH-7001C) addresses typically are 0x0300, ...
- * SOUNDSCAPE addresses are from the LASERMATE type and range. You have to
- * specify the REAL address here, not the configuration port address. Look
- * at the CDROM driver's invoking line within your DOS CONFIG.SYS, or let
- * sbpcd auto-probe, if you are not firm with the address.
- * There are some soundcards on the market with 0x0630, 0x0650, ...; their
- * type is not obvious (both types are possible).
- *
- * example: if your SBPRO audio address is 0x220, specify 0x230 and SBPRO 1.
- *          if your soundcard has its CDROM port above 0x300, specify
- *          that address and try SBPRO 0 first.
- *          if your SoundScape configuration port is at 0x330, specify
- *          0x338 and SBPRO 2.
- *
- * interface type:
- * ===============
- * set SBPRO to 1 for "true" SoundBlaster card
- * set SBPRO to 0 for "compatible" soundcards and
- *                for "poor" (no sound) interface cards.
- * set SBPRO to 2 for Ensonic SoundScape or SPEA Media FX cards
- * set SBPRO to 3 for Teac 16bit interface cards
- *
- * Almost all "compatible" sound boards need to set SBPRO to 0.
- * If SBPRO is set wrong, the drives will get found - but any
- * data access will give errors (audio access will work).
- * The "OmniCD" no-sound interface card from CreativeLabs and most Teac
- * interface cards need SBPRO 1.
- *
- * sound base:
- * ===========
- * The SOUND_BASE definition tells if we should try to turn the CD sound
- * channels on. It will only be of use regarding soundcards with a SbPro
- * compatible mixer.
- *
- * Example: #define SOUND_BASE 0x220 enables the sound card's CD channels
- *          #define SOUND_BASE 0     leaves the soundcard untouched
- */
-#define CDROM_PORT 0x340 /* <-----------<< port address                      */
-#define SBPRO      0     /* <-----------<< interface type                    */
-#define MAX_DRIVES 4     /* set to 1 if the card does not use "drive select" */
-#define SOUND_BASE 0x220 /* <-----------<< sound address of this card or 0   */
-
-/*
- * some more or less user dependent definitions - service them!
- */
-
-/* Set this to 0 once you have configured your interface definitions right. */
-#define DISTRIBUTION 1
-
-/*
- * Time to wait after giving a message.
- * This gets important if you enable non-standard DBG_xxx flags.
- * You will see what happens if you omit the pause or make it
- * too short. Be warned!
- */
-#define KLOGD_PAUSE 1
-
-/* tray control: eject tray if no disk is in */
-#if DISTRIBUTION
-#define JUKEBOX 0
-#else
-#define JUKEBOX 1
-#endif /* DISTRIBUTION */
-
-/* tray control: eject tray after last use */
-#if DISTRIBUTION
-#define EJECT 0
-#else
-#define EJECT 1
-#endif /* DISTRIBUTION */
-
-/* max. number of audio frames to read with one     */
-/* request (allocates n* 2352 bytes kernel memory!) */
-/* may be freely adjusted, f.e. 75 (= 1 sec.), at   */
-/* runtime by use of the CDROMAUDIOBUFSIZ ioctl.    */
-#define READ_AUDIO 0
-
-/* Optimizations for the Teac CD-55A drive read performance.
- * SBP_TEAC_SPEED can be changed here, or one can set the 
- * variable "teac" when loading as a module.
- * Valid settings are:
- *   0 - very slow - the recommended "DISTRIBUTION 1" setup.
- *   1 - 2x performance with little overhead. No busy waiting.
- *   2 - 4x performance with 5ms overhead per read. Busy wait.
- *
- * Setting SBP_TEAC_SPEED or the variable 'teac' to anything
- * other than 0 may cause problems. If you run into them, first
- * change SBP_TEAC_SPEED back to 0 and see if your drive responds
- * normally. If yes, you are "allowed" to report your case - to help
- * me with the driver, not to solve your hassle. Don´t mail if you
- * simply are stuck into your own "tuning" experiments, you know?
- */
-#define SBP_TEAC_SPEED 1
-
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * nothing to change below here if you are not fully aware what you're doing
- */
-#ifndef _LINUX_SBPCD_H
-
-#define _LINUX_SBPCD_H
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * driver's own read_ahead, data mode
- */
-#define SBP_BUFFER_FRAMES 8 
-
-#define LONG_TIMING 0 /* test against timeouts with "gold" CDs on CR-521 */
-#undef  FUTURE
-#undef SAFE_MIXED
-
-#define TEST_UPC 0
-#define SPEA_TEST 0
-#define TEST_STI 0
-#define OLD_BUSY 0
-#undef PATH_CHECK
-#ifndef SOUND_BASE
-#define SOUND_BASE 0
-#endif
-#if DISTRIBUTION
-#undef SBP_TEAC_SPEED
-#define SBP_TEAC_SPEED 0
-#endif
-/*==========================================================================*/
-/*
- * DDI interface definitions
- * "invented" by Fred N. van Kempen..
- */
-#define DDIOCSDBG      0x9000
-
-/*==========================================================================*/
-/*
- * "private" IOCTL functions
- */
-#define CDROMAUDIOBUFSIZ       0x5382 /* set the audio buffer size */
-
-/*==========================================================================*/
-/*
- * Debug output levels
- */
-#define DBG_INF        1       /* necessary information */
-#define DBG_BSZ        2       /* BLOCK_SIZE trace */
-#define DBG_REA        3       /* READ status trace */
-#define DBG_CHK        4       /* MEDIA CHECK trace */
-#define DBG_TIM        5       /* datarate timer test */
-#define DBG_INI        6       /* initialization trace */
-#define DBG_TOC        7       /* tell TocEntry values */
-#define DBG_IOC        8       /* ioctl trace */
-#define DBG_STA        9       /* ResponseStatus() trace */
-#define DBG_ERR        10      /* cc_ReadError() trace */
-#define DBG_CMD        11      /* cmd_out() trace */
-#define DBG_WRN        12      /* give explanation before auto-probing */
-#define DBG_MUL        13      /* multi session code test */
-#define DBG_IDX        14      /* test code for drive_id !=0 */
-#define DBG_IOX        15      /* some special information */
-#define DBG_DID        16      /* drive ID test */
-#define DBG_RES        17      /* drive reset info */
-#define DBG_SPI        18      /* SpinUp test */
-#define DBG_IOS        19      /* ioctl trace: subchannel functions */
-#define DBG_IO2        20      /* ioctl trace: general */
-#define DBG_UPC        21      /* show UPC information */
-#define DBG_XA1        22      /* XA mode debugging */
-#define DBG_LCK        23      /* door (un)lock info */
-#define DBG_SQ1        24      /* dump SubQ frame */
-#define DBG_AUD        25      /* READ AUDIO debugging */
-#define DBG_SEQ        26      /* Sequoia interface configuration trace */
-#define DBG_LCS        27      /* Longshine LCS-7260 debugging trace */
-#define DBG_CD2        28      /* MKE/Funai CD200 debugging trace */
-#define DBG_TEA        29      /* TEAC CD-55A debugging trace */
-#define DBG_ECS        30      /* ECS-AT (Vertos 100) debugging trace */
-#define DBG_000        31      /* unnecessary information */
-
-/*==========================================================================*/
-/*==========================================================================*/
-
-/*
- * bits of flags_cmd_out:
- */
-#define f_respo3               0x100
-#define f_putcmd               0x80
-#define f_respo2               0x40
-#define f_lopsta               0x20
-#define f_getsta               0x10
-#define f_ResponseStatus       0x08
-#define f_obey_p_check         0x04
-#define f_bit1                 0x02
-#define f_wait_if_busy         0x01
-
-/*
- * diskstate_flags:
- */
-#define x80_bit                        0x80
-#define upc_bit                        0x40
-#define volume_bit             0x20
-#define toc_bit                        0x10
-#define multisession_bit       0x08
-#define cd_size_bit            0x04
-#define subq_bit               0x02
-#define frame_size_bit         0x01
-
-/*
- * disk states (bits of diskstate_flags):
- */
-#define upc_valid              (current_drive->diskstate_flags&upc_bit)
-#define volume_valid           (current_drive->diskstate_flags&volume_bit)
-#define toc_valid              (current_drive->diskstate_flags&toc_bit)
-#define cd_size_valid          (current_drive->diskstate_flags&cd_size_bit)
-#define subq_valid             (current_drive->diskstate_flags&subq_bit)
-#define frame_size_valid       (current_drive->diskstate_flags&frame_size_bit)
-
-/*
- * the status_bits variable
- */
-#define p_success      0x100
-#define p_door_closed  0x80
-#define p_caddy_in     0x40
-#define p_spinning     0x20
-#define p_check                0x10
-#define p_busy_new     0x08
-#define p_door_locked  0x04
-#define p_disk_ok      0x01
-
-/*
- * LCS-7260 special status result bits:
- */
-#define p_lcs_door_locked      0x02
-#define p_lcs_door_closed      0x01 /* probably disk_in */
-
-/*
- * CR-52x special status result bits:
- */
-#define p_caddin_old   0x40
-#define p_success_old  0x08
-#define p_busy_old     0x04
-#define p_bit_1                0x02    /* hopefully unused now */
-
-/*
- * "generation specific" defs of the status result bits:
- */
-#define p0_door_closed 0x80
-#define p0_caddy_in    0x40
-#define p0_spinning    0x20
-#define p0_check       0x10
-#define p0_success     0x08 /* unused */
-#define p0_busy                0x04
-#define p0_bit_1       0x02 /* unused */
-#define p0_disk_ok     0x01
-
-#define pL_disk_in     0x40
-#define pL_spinning    0x20
-#define pL_check       0x10
-#define pL_success     0x08 /* unused ?? */
-#define pL_busy                0x04
-#define pL_door_locked 0x02
-#define pL_door_closed 0x01
-
-#define pV_door_closed 0x40
-#define pV_spinning    0x20
-#define pV_check       0x10
-#define pV_success     0x08
-#define pV_busy                0x04
-#define pV_door_locked 0x02
-#define pV_disk_ok     0x01
-
-#define p1_door_closed 0x80
-#define p1_disk_in     0x40
-#define p1_spinning    0x20
-#define p1_check       0x10
-#define p1_busy                0x08
-#define p1_door_locked 0x04
-#define p1_bit_1       0x02 /* unused */
-#define p1_disk_ok     0x01
-
-#define p2_disk_ok     0x80
-#define p2_door_locked 0x40
-#define p2_spinning    0x20
-#define p2_busy2       0x10
-#define p2_busy1       0x08
-#define p2_door_closed 0x04
-#define p2_disk_in     0x02
-#define p2_check       0x01
-
-/*
- * used drive states:
- */
-#define st_door_closed (current_drive->status_bits&p_door_closed)
-#define st_caddy_in    (current_drive->status_bits&p_caddy_in)
-#define st_spinning    (current_drive->status_bits&p_spinning)
-#define st_check       (current_drive->status_bits&p_check)
-#define st_busy                (current_drive->status_bits&p_busy_new)
-#define st_door_locked (current_drive->status_bits&p_door_locked)
-#define st_diskok      (current_drive->status_bits&p_disk_ok)
-
-/*
- * bits of the CDi_status register:
- */
-#define s_not_result_ready     0x04 /* 0: "result ready" */
-#define s_not_data_ready       0x02 /* 0: "data ready"   */
-#define s_attention            0x01 /* 1: "attention required" */
-/*
- * usable as:
- */
-#define DRV_ATTN       ((inb(CDi_status)&s_attention)!=0)
-#define DATA_READY     ((inb(CDi_status)&s_not_data_ready)==0)
-#define RESULT_READY   ((inb(CDi_status)&s_not_result_ready)==0)
-
-/*
- * drive families and types (firmware versions):
- */
-#define drv_fam0       0x0100          /* CR-52x family */
-#define drv_199                (drv_fam0+0x01) /* <200 */
-#define drv_200                (drv_fam0+0x02) /* <201 */
-#define drv_201                (drv_fam0+0x03) /* <210 */
-#define drv_210                (drv_fam0+0x04) /* <211 */
-#define drv_211                (drv_fam0+0x05) /* <300 */
-#define drv_300                (drv_fam0+0x06) /* >=300 */
-
-#define drv_fam1       0x0200          /* CR-56x family */
-#define drv_099                (drv_fam1+0x01) /* <100 */
-#define drv_100                (drv_fam1+0x02) /* >=100, only 1.02 and 5.00 known */
-
-#define drv_fam2       0x0400          /* CD200 family */
-
-#define drv_famT       0x0800          /* TEAC CD-55A */
-
-#define drv_famL       0x1000          /* Longshine family */
-#define drv_260                (drv_famL+0x01) /* LCS-7260 */
-#define drv_e1         (drv_famL+0x01) /* LCS-7260, firmware "A E1" */
-#define drv_f4         (drv_famL+0x02) /* LCS-7260, firmware "A4F4" */
-
-#define drv_famV       0x2000          /* ECS-AT (vertos-100) family */
-#define drv_at         (drv_famV+0x01) /* ECS-AT, firmware "1.00" */
-
-#define fam0_drive     (current_drive->drv_type&drv_fam0)
-#define famL_drive     (current_drive->drv_type&drv_famL)
-#define famV_drive     (current_drive->drv_type&drv_famV)
-#define fam1_drive     (current_drive->drv_type&drv_fam1)
-#define fam2_drive     (current_drive->drv_type&drv_fam2)
-#define famT_drive     (current_drive->drv_type&drv_famT)
-#define fam0L_drive    (current_drive->drv_type&(drv_fam0|drv_famL))
-#define fam0V_drive    (current_drive->drv_type&(drv_fam0|drv_famV))
-#define famLV_drive    (current_drive->drv_type&(drv_famL|drv_famV))
-#define fam0LV_drive   (current_drive->drv_type&(drv_fam0|drv_famL|drv_famV))
-#define fam1L_drive    (current_drive->drv_type&(drv_fam1|drv_famL))
-#define fam1V_drive    (current_drive->drv_type&(drv_fam1|drv_famV))
-#define fam1LV_drive   (current_drive->drv_type&(drv_fam1|drv_famL|drv_famV))
-#define fam01_drive    (current_drive->drv_type&(drv_fam0|drv_fam1))
-#define fam12_drive    (current_drive->drv_type&(drv_fam1|drv_fam2))
-#define fam2T_drive    (current_drive->drv_type&(drv_fam2|drv_famT))
-
-/*
- * audio states:
- */
-#define audio_completed        3 /* Forgot this one! --AJK */
-#define audio_playing  2
-#define audio_pausing  1
-
-/*
- * drv_pattern, drv_options:
- */
-#define speed_auto     0x80
-#define speed_300      0x40
-#define speed_150      0x20
-#define audio_mono     0x04
-
-/*
- * values of cmd_type (0 else):
- */
-#define READ_M1        0x01    /* "data mode 1": 2048 bytes per frame */
-#define READ_M2        0x02    /* "data mode 2": 12+2048+280 bytes per frame */
-#define READ_SC        0x04    /* "subchannel info": 96 bytes per frame */
-#define READ_AU        0x08    /* "audio frame": 2352 bytes per frame */
-
-/*
- * sense_byte:
- *
- *          values: 00
- *                  01
- *                  81
- *                  82 "raw audio" mode
- *                  xx from infobuf[0] after 85 00 00 00 00 00 00
- */
-
-/* audio status (bin) */
-#define aud_00 0x00 /* Audio status byte not supported or not valid */
-#define audx11 0x0b /* Audio play operation in progress             */
-#define audx12 0x0c /* Audio play operation paused                  */
-#define audx13 0x0d /* Audio play operation successfully completed  */
-#define audx14 0x0e /* Audio play operation stopped due to error    */
-#define audx15 0x0f /* No current audio status to return            */
-/* audio status (bcd) */
-#define aud_11 0x11 /* Audio play operation in progress             */
-#define aud_12 0x12 /* Audio play operation paused                  */
-#define aud_13 0x13 /* Audio play operation successfully completed  */
-#define aud_14 0x14 /* Audio play operation stopped due to error    */
-#define aud_15 0x15 /* No current audio status to return            */
-
-/*
- * highest allowed drive number (MINOR+1)
- */
-#define NR_SBPCD       4
-
-/*
- * we try to never disable interrupts - seems to work
- */
-#define SBPCD_DIS_IRQ  0
-
-/*
- * "write byte to port"
- */
-#define OUT(x,y)       outb(y,x)
-
-/*==========================================================================*/
-
-#define MIXER_addr SOUND_BASE+4 /* sound card's address register */
-#define MIXER_data SOUND_BASE+5 /* sound card's data register */
-#define MIXER_CD_Volume        0x28    /* internal SB Pro register address */
-
-/*==========================================================================*/
-
-#define MAX_TRACKS     99
-
-#define ERR_DISKCHANGE 615
-
-/*==========================================================================*/
-/*
- * To make conversions easier (machine dependent!)
- */
-typedef union _msf
-{
-       u_int n;
-       u_char c[4];
-} MSF;
-
-typedef union _blk
-{
-       u_int n;
-       u_char c[4];
-} BLK;
-
-/*==========================================================================*/
-
-/*============================================================================
-==============================================================================
-
-COMMAND SET of "old" drives like CR-521, CR-522
-               (the CR-562 family is different):
-
-No.    Command                        Code
---------------------------------------------
-
-Drive Commands:
- 1     Seek                            01      
- 2     Read Data                       02
- 3     Read XA-Data                    03
- 4     Read Header                     04
- 5     Spin Up                         05
- 6     Spin Down                       06
- 7     Diagnostic                      07
- 8     Read UPC                        08
- 9     Read ISRC                       09
-10     Play Audio                      0A
-11     Play Audio MSF                  0B
-12     Play Audio Track/Index          0C
-
-Status Commands:
-13     Read Status                     81      
-14     Read Error                      82
-15     Read Drive Version              83
-16     Mode Select                     84
-17     Mode Sense                      85
-18     Set XA Parameter                86
-19     Read XA Parameter               87
-20     Read Capacity                   88
-21     Read SUB_Q                      89
-22     Read Disc Code                  8A
-23     Read Disc Information           8B
-24     Read TOC                        8C
-25     Pause/Resume                    8D
-26     Read Packet                     8E
-27     Read Path Check                 00
-all numbers (lba, msf-bin, msf-bcd, counts) to transfer high byte first
-
-mnemo     7-byte command        #bytes response (r0...rn)
-________ ____________________  ____ 
-
-Read Status:
-status:  81.                    (1)  one-byte command, gives the main
-                                                          status byte
-Read Error:
-check1:  82 00 00 00 00 00 00.  (6)  r1: audio status
-
-Read Packet:
-check2:  8e xx 00 00 00 00 00. (xx)  gets xx bytes response, relating
-                                        to commands 01 04 05 07 08 09
-
-Play Audio:
-play:    0a ll-bb-aa nn-nn-nn.  (0)  play audio, ll-bb-aa: starting block (lba),
-                                                 nn-nn-nn: #blocks
-Play Audio MSF:
-         0b mm-ss-ff mm-ss-ff   (0)  play audio from/to
-
-Play Audio Track/Index:
-         0c ...
-
-Pause/Resume:
-pause:   8d pr 00 00 00 00 00.  (0)  pause (pr=00) 
-                                     resume (pr=80) audio playing
-
-Mode Select:
-         84 00 nn-nn ??.?? 00   (0)  nn-nn: 2048 or 2340
-                                     possibly defines transfer size
-
-set_vol: 84 83 00 00 sw le 00.  (0)  sw(itch): lrxxxxxx (off=1)
-                                     le(vel): min=0, max=FF, else half
-                                    (firmware 2.11)
-
-Mode Sense:
-get_vol: 85 03 00 00 00 00 00.  (2)  tell current audio volume setting
-
-Read Disc Information:
-tocdesc: 8b 00 00 00 00 00 00.  (6)  read the toc descriptor ("msf-bin"-format)
-
-Read TOC:
-tocent:  8c fl nn 00 00 00 00.  (8)  read toc entry #nn
-                                       (fl=0:"lba"-, =2:"msf-bin"-format)
-
-Read Capacity:
-capacit: 88 00 00 00 00 00 00.  (5)  "read CD-ROM capacity"
-
-
-Read Path Check:
-ping:    00 00 00 00 00 00 00.  (2)  r0=AA, r1=55
-                                     ("ping" if the drive is connected)
-
-Read Drive Version:
-ident:   83 00 00 00 00 00 00. (12)  gives "MATSHITAn.nn" 
-                                     (n.nn = 2.01, 2.11., 3.00, ...)
-
-Seek:
-seek:    01 00 ll-bb-aa 00 00.  (0)  
-seek:    01 02 mm-ss-ff 00 00.  (0)  
-
-Read Data:
-read:    02 xx-xx-xx nn-nn fl.  (?)  read nn-nn blocks of 2048 bytes,
-                                     starting at block xx-xx-xx  
-                                     fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
-
-Read XA-Data:
-read:    03 xx-xx-xx nn-nn fl.  (?)  read nn-nn blocks of 2340 bytes, 
-                                     starting at block xx-xx-xx
-                                     fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
-
-Read SUB_Q:
-         89 fl 00 00 00 00 00. (13)  r0: audio status, r4-r7: lba/msf, 
-                                       fl=0: "lba", fl=2: "msf"
-
-Read Disc Code:
-         8a 00 00 00 00 00 00. (14)  possibly extended "check condition"-info
-
-Read Header:
-         04 00 ll-bb-aa 00 00.  (0)   4 bytes response with "check2"
-         04 02 mm-ss-ff 00 00.  (0)   4 bytes response with "check2"
-
-Spin Up:
-         05 00 ll-bb-aa 00 00.  (0)  possibly implies a "seek"
-
-Spin Down:
-         06 ...
-
-Diagnostic:
-         07 00 ll-bb-aa 00 00.  (2)   2 bytes response with "check2"
-         07 02 mm-ss-ff 00 00.  (2)   2 bytes response with "check2"
-
-Read UPC:
-         08 00 ll-bb-aa 00 00. (16)  
-         08 02 mm-ss-ff 00 00. (16)  
-
-Read ISRC:
-         09 00 ll-bb-aa 00 00. (15)  15 bytes response with "check2"
-         09 02 mm-ss-ff 00 00. (15)  15 bytes response with "check2"
-
-Set XA Parameter:
-         86 ...
-
-Read XA Parameter:
-         87 ...
-
-==============================================================================
-============================================================================*/
-
-/*
- * commands
- *
- * CR-52x:      CMD0_
- * CR-56x:      CMD1_
- * CD200:       CMD2_
- * LCS-7260:    CMDL_
- * TEAC CD-55A: CMDT_
- * ECS-AT:      CMDV_
- */
-#define CMD1_RESET     0x0a
-#define CMD2_RESET     0x01
-#define CMDT_RESET     0xc0
-
-#define CMD1_LOCK_CTL  0x0c
-#define CMD2_LOCK_CTL  0x1e
-#define CMDT_LOCK_CTL  CMD2_LOCK_CTL
-#define CMDL_LOCK_CTL  0x0e
-#define CMDV_LOCK_CTL  CMDL_LOCK_CTL
-
-#define CMD1_TRAY_CTL  0x07
-#define CMD2_TRAY_CTL  0x1b
-#define CMDT_TRAY_CTL  CMD2_TRAY_CTL
-#define CMDL_TRAY_CTL  0x0d
-#define CMDV_TRAY_CTL  CMDL_TRAY_CTL
-
-#define CMD1_MULTISESS 0x8d
-#define CMDL_MULTISESS 0x8c
-#define CMDV_MULTISESS CMDL_MULTISESS
-
-#define CMD1_SUBCHANINF        0x11
-#define CMD2_SUBCHANINF        0x??
-
-#define CMD1_ABORT     0x08
-#define CMD2_ABORT     0x08
-#define CMDT_ABORT     0x08
-
-#define CMD2_x02       0x02
-
-#define CMD2_SETSPEED  0xda
-
-#define CMD0_PATH_CHECK        0x00
-#define CMD1_PATH_CHECK        0x???
-#define CMD2_PATH_CHECK        0x???
-#define CMDT_PATH_CHECK        0x???
-#define CMDL_PATH_CHECK        CMD0_PATH_CHECK
-#define CMDV_PATH_CHECK        CMD0_PATH_CHECK
-
-#define CMD0_SEEK      0x01
-#define CMD1_SEEK      CMD0_SEEK
-#define CMD2_SEEK      0x2b
-#define CMDT_SEEK      CMD2_SEEK
-#define CMDL_SEEK      CMD0_SEEK
-#define CMDV_SEEK      CMD0_SEEK
-
-#define CMD0_READ      0x02
-#define CMD1_READ      0x10
-#define CMD2_READ      0x28
-#define CMDT_READ      CMD2_READ
-#define CMDL_READ      CMD0_READ
-#define CMDV_READ      CMD0_READ
-
-#define CMD0_READ_XA   0x03
-#define CMD2_READ_XA   0xd4
-#define CMD2_READ_XA2  0xd5
-#define CMDL_READ_XA   CMD0_READ_XA /* really ?? */
-#define CMDV_READ_XA   CMD0_READ_XA
-
-#define CMD0_READ_HEAD 0x04
-
-#define CMD0_SPINUP    0x05
-#define CMD1_SPINUP    0x02
-#define CMD2_SPINUP    CMD2_TRAY_CTL
-#define CMDL_SPINUP    CMD0_SPINUP
-#define CMDV_SPINUP    CMD0_SPINUP
-
-#define CMD0_SPINDOWN  0x06 /* really??? */
-#define CMD1_SPINDOWN  0x06
-#define CMD2_SPINDOWN  CMD2_TRAY_CTL
-#define CMDL_SPINDOWN  0x0d
-#define CMDV_SPINDOWN  CMD0_SPINDOWN
-
-#define CMD0_DIAG      0x07
-
-#define CMD0_READ_UPC  0x08
-#define CMD1_READ_UPC  0x88
-#define CMD2_READ_UPC  0x???
-#define CMDL_READ_UPC  CMD0_READ_UPC
-#define CMDV_READ_UPC  0x8f
-
-#define CMD0_READ_ISRC 0x09
-
-#define CMD0_PLAY      0x0a
-#define CMD1_PLAY      0x???
-#define CMD2_PLAY      0x???
-#define CMDL_PLAY      CMD0_PLAY
-#define CMDV_PLAY      CMD0_PLAY
-
-#define CMD0_PLAY_MSF  0x0b
-#define CMD1_PLAY_MSF  0x0e
-#define CMD2_PLAY_MSF  0x47
-#define CMDT_PLAY_MSF  CMD2_PLAY_MSF
-#define CMDL_PLAY_MSF  0x???
-
-#define CMD0_PLAY_TI   0x0c
-#define CMD1_PLAY_TI   0x0f
-
-#define CMD0_STATUS    0x81
-#define CMD1_STATUS    0x05
-#define CMD2_STATUS    0x00
-#define CMDT_STATUS    CMD2_STATUS
-#define CMDL_STATUS    CMD0_STATUS
-#define CMDV_STATUS    CMD0_STATUS
-#define CMD2_SEEK_LEADIN 0x00
-
-#define CMD0_READ_ERR  0x82
-#define CMD1_READ_ERR  CMD0_READ_ERR
-#define CMD2_READ_ERR  0x03
-#define CMDT_READ_ERR  CMD2_READ_ERR /* get audio status */
-#define CMDL_READ_ERR  CMD0_READ_ERR
-#define CMDV_READ_ERR  CMD0_READ_ERR
-
-#define CMD0_READ_VER  0x83
-#define CMD1_READ_VER  CMD0_READ_VER
-#define CMD2_READ_VER  0x12
-#define CMDT_READ_VER  CMD2_READ_VER /* really ?? */
-#define CMDL_READ_VER  CMD0_READ_VER
-#define CMDV_READ_VER  CMD0_READ_VER
-
-#define CMD0_SETMODE   0x84
-#define CMD1_SETMODE   0x09
-#define CMD2_SETMODE   0x55
-#define CMDT_SETMODE   CMD2_SETMODE
-#define CMDL_SETMODE   CMD0_SETMODE
-
-#define CMD0_GETMODE   0x85
-#define CMD1_GETMODE   0x84
-#define CMD2_GETMODE   0x5a
-#define CMDT_GETMODE   CMD2_GETMODE
-#define CMDL_GETMODE   CMD0_GETMODE
-
-#define CMD0_SET_XA    0x86
-
-#define CMD0_GET_XA    0x87
-
-#define CMD0_CAPACITY  0x88
-#define CMD1_CAPACITY  0x85
-#define CMD2_CAPACITY  0x25
-#define CMDL_CAPACITY  CMD0_CAPACITY /* missing in some firmware versions */
-
-#define CMD0_READSUBQ  0x89
-#define CMD1_READSUBQ  0x87
-#define CMD2_READSUBQ  0x42
-#define CMDT_READSUBQ  CMD2_READSUBQ
-#define CMDL_READSUBQ  CMD0_READSUBQ
-#define CMDV_READSUBQ  CMD0_READSUBQ
-
-#define CMD0_DISKCODE  0x8a
-
-#define CMD0_DISKINFO  0x8b
-#define CMD1_DISKINFO  CMD0_DISKINFO
-#define CMD2_DISKINFO  0x43
-#define CMDT_DISKINFO  CMD2_DISKINFO
-#define CMDL_DISKINFO  CMD0_DISKINFO
-#define CMDV_DISKINFO  CMD0_DISKINFO
-
-#define CMD0_READTOC   0x8c
-#define CMD1_READTOC   CMD0_READTOC
-#define CMD2_READTOC   0x???
-#define CMDL_READTOC   CMD0_READTOC
-#define CMDV_READTOC   CMD0_READTOC
-
-#define CMD0_PAU_RES   0x8d
-#define CMD1_PAU_RES   0x0d
-#define CMD2_PAU_RES   0x4b
-#define CMDT_PAUSE     CMD2_PAU_RES
-#define CMDL_PAU_RES   CMD0_PAU_RES
-#define CMDV_PAUSE     CMD0_PAU_RES
-
-#define CMD0_PACKET    0x8e
-#define CMD1_PACKET    CMD0_PACKET
-#define CMD2_PACKET    0x???
-#define CMDL_PACKET    CMD0_PACKET
-#define CMDV_PACKET    0x???
-
-/*==========================================================================*/
-/*==========================================================================*/
-#endif /* _LINUX_SBPCD_H */
-/*==========================================================================*/
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file. 
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 8
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -8
- * c-argdecl-indent: 8
- * c-label-offset: -8
- * c-continued-statement-offset: 8
- * c-continued-brace-offset: 0
- * End:
- */
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
deleted file mode 100644 (file)
index 76c24e6..0000000
+++ /dev/null
@@ -1,1815 +0,0 @@
-/* -- sjcd.c
- *
- *   Sanyo CD-ROM device driver implementation, Version 1.6
- *   Copyright (C) 1995  Vadim V. Model
- *
- *   model@cecmow.enet.dec.com
- *   vadim@rbrf.ru
- *   vadim@ipsun.ras.ru
- *
- *
- *  This driver is based on pre-works by Eberhard Moenkeberg (emoenke@gwdg.de);
- *  it was developed under use of mcd.c from Martin Harriss, with help of
- *  Eric van der Maarel (H.T.M.v.d.Maarel@marin.nl).
- *
- *  It is planned to include these routines into sbpcd.c later - to make
- *  a "mixed use" on one cable possible for all kinds of drives which use
- *  the SoundBlaster/Panasonic style CDROM interface. But today, the
- *  ability to install directly from CDROM is more important than flexibility.
- *
- *  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 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  History:
- *  1.1 First public release with kernel version 1.3.7.
- *      Written by Vadim Model.
- *  1.2 Added detection and configuration of cdrom interface
- *      on ISP16 soundcard.
- *      Allow for command line options: sjcd=<io_base>,<irq>,<dma>
- *  1.3 Some minor changes to README.sjcd.
- *  1.4 MSS Sound support!! Listen to a CD through the speakers.
- *  1.5 Module support and bugfixes.
- *      Tray locking.
- *  1.6 Removed ISP16 code from this driver.
- *      Allow only to set io base address on command line: sjcd=<io_base>
- *      Changes to Documentation/cdrom/sjcd
- *      Added cleanup after any error in the initialisation.
- *  1.7 Added code to set the sector size tables to prevent the bug present in 
- *      the previous version of this driver.  Coded added by Anthony Barbachan 
- *      from bugfix tip originally suggested by Alan Cox.
- *
- *  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>
- */
-
-#define SJCD_VERSION_MAJOR 1
-#define SJCD_VERSION_MINOR 7
-
-#include <linux/module.h>
-#include <linux/errno.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/string.h>
-#include <linux/major.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/blkdev.h>
-#include "sjcd.h"
-
-static int sjcd_present = 0;
-static struct request_queue *sjcd_queue;
-
-#define MAJOR_NR SANYO_CDROM_MAJOR
-#define QUEUE (sjcd_queue)
-#define CURRENT elv_next_request(sjcd_queue)
-
-#define SJCD_BUF_SIZ 32                /* cdr-h94a has internal 64K buffer */
-
-/*
- * buffer for block size conversion
- */
-static char sjcd_buf[2048 * SJCD_BUF_SIZ];
-static volatile int sjcd_buf_bn[SJCD_BUF_SIZ], sjcd_next_bn;
-static volatile int sjcd_buf_in, sjcd_buf_out = -1;
-
-/*
- * Status.
- */
-static unsigned short sjcd_status_valid = 0;
-static unsigned short sjcd_door_closed;
-static unsigned short sjcd_door_was_open;
-static unsigned short sjcd_media_is_available;
-static unsigned short sjcd_media_is_changed;
-static unsigned short sjcd_toc_uptodate = 0;
-static unsigned short sjcd_command_failed;
-static volatile unsigned char sjcd_completion_status = 0;
-static volatile unsigned char sjcd_completion_error = 0;
-static unsigned short sjcd_command_is_in_progress = 0;
-static unsigned short sjcd_error_reported = 0;
-static DEFINE_SPINLOCK(sjcd_lock);
-
-static int sjcd_open_count;
-
-static int sjcd_audio_status;
-static struct sjcd_play_msf sjcd_playing;
-
-static int sjcd_base = SJCD_BASE_ADDR;
-
-module_param(sjcd_base, int, 0);
-
-static DECLARE_WAIT_QUEUE_HEAD(sjcd_waitq);
-
-/*
- * Data transfer.
- */
-static volatile unsigned short sjcd_transfer_is_active = 0;
-
-enum sjcd_transfer_state {
-       SJCD_S_IDLE = 0,
-       SJCD_S_START = 1,
-       SJCD_S_MODE = 2,
-       SJCD_S_READ = 3,
-       SJCD_S_DATA = 4,
-       SJCD_S_STOP = 5,
-       SJCD_S_STOPPING = 6
-};
-static enum sjcd_transfer_state sjcd_transfer_state = SJCD_S_IDLE;
-static long sjcd_transfer_timeout = 0;
-static int sjcd_read_count = 0;
-static unsigned char sjcd_mode = 0;
-
-#define SJCD_READ_TIMEOUT 5000
-
-#if defined( SJCD_GATHER_STAT )
-/*
- * Statistic.
- */
-static struct sjcd_stat statistic;
-#endif
-
-/*
- * Timer.
- */
-static DEFINE_TIMER(sjcd_delay_timer, NULL, 0, 0);
-
-#define SJCD_SET_TIMER( func, tmout )           \
-    ( sjcd_delay_timer.expires = jiffies+tmout,         \
-      sjcd_delay_timer.function = ( void * )func, \
-      add_timer( &sjcd_delay_timer ) )
-
-#define CLEAR_TIMER del_timer( &sjcd_delay_timer )
-
-/*
- * Set up device, i.e., use command line data to set
- * base address.
- */
-#ifndef MODULE
-static int __init sjcd_setup(char *str)
-{
-       int ints[2];
-       (void) get_options(str, ARRAY_SIZE(ints), ints);
-       if (ints[0] > 0)
-               sjcd_base = ints[1];
-
-       return 1;
-}
-
-__setup("sjcd=", sjcd_setup);
-
-#endif
-
-/*
- * Special converters.
- */
-static unsigned char bin2bcd(int bin)
-{
-       int u, v;
-
-       u = bin % 10;
-       v = bin / 10;
-       return (u | (v << 4));
-}
-
-static int bcd2bin(unsigned char bcd)
-{
-       return ((bcd >> 4) * 10 + (bcd & 0x0F));
-}
-
-static long msf2hsg(struct msf *mp)
-{
-       return (bcd2bin(mp->frame) + bcd2bin(mp->sec) * 75
-               + bcd2bin(mp->min) * 4500 - 150);
-}
-
-static void hsg2msf(long hsg, struct msf *msf)
-{
-       hsg += 150;
-       msf->min = hsg / 4500;
-       hsg %= 4500;
-       msf->sec = hsg / 75;
-       msf->frame = hsg % 75;
-       msf->min = bin2bcd(msf->min);   /* convert to BCD */
-       msf->sec = bin2bcd(msf->sec);
-       msf->frame = bin2bcd(msf->frame);
-}
-
-/*
- * Send a command to cdrom. Invalidate status.
- */
-static void sjcd_send_cmd(unsigned char cmd)
-{
-#if defined( SJCD_TRACE )
-       printk("SJCD: send_cmd( 0x%x )\n", cmd);
-#endif
-       outb(cmd, SJCDPORT(0));
-       sjcd_command_is_in_progress = 1;
-       sjcd_status_valid = 0;
-       sjcd_command_failed = 0;
-}
-
-/*
- * Send a command with one arg to cdrom. Invalidate status.
- */
-static void sjcd_send_1_cmd(unsigned char cmd, unsigned char a)
-{
-#if defined( SJCD_TRACE )
-       printk("SJCD: send_1_cmd( 0x%x, 0x%x )\n", cmd, a);
-#endif
-       outb(cmd, SJCDPORT(0));
-       outb(a, SJCDPORT(0));
-       sjcd_command_is_in_progress = 1;
-       sjcd_status_valid = 0;
-       sjcd_command_failed = 0;
-}
-
-/*
- * Send a command with four args to cdrom. Invalidate status.
- */
-static void sjcd_send_4_cmd(unsigned char cmd, unsigned char a,
-                           unsigned char b, unsigned char c,
-                           unsigned char d)
-{
-#if defined( SJCD_TRACE )
-       printk("SJCD: send_4_cmd( 0x%x )\n", cmd);
-#endif
-       outb(cmd, SJCDPORT(0));
-       outb(a, SJCDPORT(0));
-       outb(b, SJCDPORT(0));
-       outb(c, SJCDPORT(0));
-       outb(d, SJCDPORT(0));
-       sjcd_command_is_in_progress = 1;
-       sjcd_status_valid = 0;
-       sjcd_command_failed = 0;
-}
-
-/*
- * Send a play or read command to cdrom. Invalidate Status.
- */
-static void sjcd_send_6_cmd(unsigned char cmd, struct sjcd_play_msf *pms)
-{
-#if defined( SJCD_TRACE )
-       printk("SJCD: send_long_cmd( 0x%x )\n", cmd);
-#endif
-       outb(cmd, SJCDPORT(0));
-       outb(pms->start.min, SJCDPORT(0));
-       outb(pms->start.sec, SJCDPORT(0));
-       outb(pms->start.frame, SJCDPORT(0));
-       outb(pms->end.min, SJCDPORT(0));
-       outb(pms->end.sec, SJCDPORT(0));
-       outb(pms->end.frame, SJCDPORT(0));
-       sjcd_command_is_in_progress = 1;
-       sjcd_status_valid = 0;
-       sjcd_command_failed = 0;
-}
-
-/*
- * Get a value from the data port. Should not block, so we use a little
- * wait for a while. Returns 0 if OK.
- */
-static int sjcd_load_response(void *buf, int len)
-{
-       unsigned char *resp = (unsigned char *) buf;
-
-       for (; len; --len) {
-               int i;
-               for (i = 200;
-                    i-- && !SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1))););
-               if (i > 0)
-                       *resp++ = (unsigned char) inb(SJCDPORT(0));
-               else
-                       break;
-       }
-       return (len);
-}
-
-/*
- * Load and parse command completion status (drive info byte and maybe error).
- * Sorry, no error classification yet.
- */
-static void sjcd_load_status(void)
-{
-       sjcd_media_is_changed = 0;
-       sjcd_completion_error = 0;
-       sjcd_completion_status = inb(SJCDPORT(0));
-       if (sjcd_completion_status & SST_DOOR_OPENED) {
-               sjcd_door_closed = sjcd_media_is_available = 0;
-       } else {
-               sjcd_door_closed = 1;
-               if (sjcd_completion_status & SST_MEDIA_CHANGED)
-                       sjcd_media_is_available = sjcd_media_is_changed =
-                           1;
-               else if (sjcd_completion_status & 0x0F) {
-                       /*
-                        * OK, we seem to catch an error ...
-                        */
-                       while (!SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1))));
-                       sjcd_completion_error = inb(SJCDPORT(0));
-                       if ((sjcd_completion_status & 0x08) &&
-                           (sjcd_completion_error & 0x40))
-                               sjcd_media_is_available = 0;
-                       else
-                               sjcd_command_failed = 1;
-               } else
-                       sjcd_media_is_available = 1;
-       }
-       /*
-        * Ok, status loaded successfully.
-        */
-       sjcd_status_valid = 1, sjcd_error_reported = 0;
-       sjcd_command_is_in_progress = 0;
-
-       /*
-        * If the disk is changed, the TOC is not valid.
-        */
-       if (sjcd_media_is_changed)
-               sjcd_toc_uptodate = 0;
-#if defined( SJCD_TRACE )
-       printk("SJCD: status %02x.%02x loaded.\n",
-              (int) sjcd_completion_status, (int) sjcd_completion_error);
-#endif
-}
-
-/*
- * Read status from cdrom. Check to see if the status is available.
- */
-static int sjcd_check_status(void)
-{
-       /*
-        * Try to load the response from cdrom into buffer.
-        */
-       if (SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)))) {
-               sjcd_load_status();
-               return (1);
-       } else {
-               /*
-                * No status is available.
-                */
-               return (0);
-       }
-}
-
-/*
- * This is just timeout counter, and nothing more. Surprised ? :-)
- */
-static volatile long sjcd_status_timeout;
-
-/*
- * We need about 10 seconds to wait. The longest command takes about 5 seconds
- * to probe the disk (usually after tray closed or drive reset). Other values
- * should be thought of for other commands.
- */
-#define SJCD_WAIT_FOR_STATUS_TIMEOUT 1000
-
-static void sjcd_status_timer(void)
-{
-       if (sjcd_check_status()) {
-               /*
-                * The command completed and status is loaded, stop waiting.
-                */
-               wake_up(&sjcd_waitq);
-       } else if (--sjcd_status_timeout <= 0) {
-               /*
-                * We are timed out. 
-                */
-               wake_up(&sjcd_waitq);
-       } else {
-               /*
-                * We have still some time to wait. Try again.
-                */
-               SJCD_SET_TIMER(sjcd_status_timer, 1);
-       }
-}
-
-/*
- * Wait for status for 10 sec approx. Returns non-positive when timed out.
- * Should not be used while reading data CDs.
- */
-static int sjcd_wait_for_status(void)
-{
-       sjcd_status_timeout = SJCD_WAIT_FOR_STATUS_TIMEOUT;
-       SJCD_SET_TIMER(sjcd_status_timer, 1);
-       sleep_on(&sjcd_waitq);
-#if defined( SJCD_DIAGNOSTIC ) || defined ( SJCD_TRACE )
-       if (sjcd_status_timeout <= 0)
-               printk("SJCD: Error Wait For Status.\n");
-#endif
-       return (sjcd_status_timeout);
-}
-
-static int sjcd_receive_status(void)
-{
-       int i;
-#if defined( SJCD_TRACE )
-       printk("SJCD: receive_status\n");
-#endif
-       /*
-        * Wait a bit for status available.
-        */
-       for (i = 200; i-- && (sjcd_check_status() == 0););
-       if (i < 0) {
-#if defined( SJCD_TRACE )
-               printk("SJCD: long wait for status\n");
-#endif
-               if (sjcd_wait_for_status() <= 0)
-                       printk("SJCD: Timeout when read status.\n");
-               else
-                       i = 0;
-       }
-       return (i);
-}
-
-/*
- * Load the status. Issue get status command and wait for status available.
- */
-static void sjcd_get_status(void)
-{
-#if defined( SJCD_TRACE )
-       printk("SJCD: get_status\n");
-#endif
-       sjcd_send_cmd(SCMD_GET_STATUS);
-       sjcd_receive_status();
-}
-
-/*
- * Check the drive if the disk is changed. Should be revised.
- */
-static int sjcd_disk_change(struct gendisk *disk)
-{
-#if 0
-       printk("SJCD: sjcd_disk_change(%s)\n", disk->disk_name);
-#endif
-       if (!sjcd_command_is_in_progress)
-               sjcd_get_status();
-       return (sjcd_status_valid ? sjcd_media_is_changed : 0);
-}
-
-/*
- * Read the table of contents (TOC) and TOC header if necessary.
- * We assume that the drive contains no more than 99 toc entries.
- */
-static struct sjcd_hw_disk_info sjcd_table_of_contents[SJCD_MAX_TRACKS];
-static unsigned char sjcd_first_track_no, sjcd_last_track_no;
-#define sjcd_disk_length  sjcd_table_of_contents[0].un.track_msf
-
-static int sjcd_update_toc(void)
-{
-       struct sjcd_hw_disk_info info;
-       int i;
-#if defined( SJCD_TRACE )
-       printk("SJCD: update toc:\n");
-#endif
-       /*
-        * check to see if we need to do anything
-        */
-       if (sjcd_toc_uptodate)
-               return (0);
-
-       /*
-        * Get the TOC start information.
-        */
-       sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_1_TRACK);
-       sjcd_receive_status();
-
-       if (!sjcd_status_valid) {
-               printk("SJCD: cannot load status.\n");
-               return (-1);
-       }
-
-       if (!sjcd_media_is_available) {
-               printk("SJCD: no disk in drive\n");
-               return (-1);
-       }
-
-       if (!sjcd_command_failed) {
-               if (sjcd_load_response(&info, sizeof(info)) != 0) {
-                       printk
-                           ("SJCD: cannot load response about TOC start.\n");
-                       return (-1);
-               }
-               sjcd_first_track_no = bcd2bin(info.un.track_no);
-       } else {
-               printk("SJCD: get first failed\n");
-               return (-1);
-       }
-#if defined( SJCD_TRACE )
-       printk("SJCD: TOC start 0x%02x ", sjcd_first_track_no);
-#endif
-       /*
-        * Get the TOC finish information.
-        */
-       sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_L_TRACK);
-       sjcd_receive_status();
-
-       if (!sjcd_status_valid) {
-               printk("SJCD: cannot load status.\n");
-               return (-1);
-       }
-
-       if (!sjcd_media_is_available) {
-               printk("SJCD: no disk in drive\n");
-               return (-1);
-       }
-
-       if (!sjcd_command_failed) {
-               if (sjcd_load_response(&info, sizeof(info)) != 0) {
-                       printk
-                           ("SJCD: cannot load response about TOC finish.\n");
-                       return (-1);
-               }
-               sjcd_last_track_no = bcd2bin(info.un.track_no);
-       } else {
-               printk("SJCD: get last failed\n");
-               return (-1);
-       }
-#if defined( SJCD_TRACE )
-       printk("SJCD: TOC finish 0x%02x ", sjcd_last_track_no);
-#endif
-       for (i = sjcd_first_track_no; i <= sjcd_last_track_no; i++) {
-               /*
-                * Get the first track information.
-                */
-               sjcd_send_1_cmd(SCMD_GET_DISK_INFO, bin2bcd(i));
-               sjcd_receive_status();
-
-               if (!sjcd_status_valid) {
-                       printk("SJCD: cannot load status.\n");
-                       return (-1);
-               }
-
-               if (!sjcd_media_is_available) {
-                       printk("SJCD: no disk in drive\n");
-                       return (-1);
-               }
-
-               if (!sjcd_command_failed) {
-                       if (sjcd_load_response(&sjcd_table_of_contents[i],
-                                              sizeof(struct
-                                                     sjcd_hw_disk_info))
-                           != 0) {
-                               printk
-                                   ("SJCD: cannot load info for %d track\n",
-                                    i);
-                               return (-1);
-                       }
-               } else {
-                       printk("SJCD: get info %d failed\n", i);
-                       return (-1);
-               }
-       }
-
-       /*
-        * Get the disk length info.
-        */
-       sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_D_SIZE);
-       sjcd_receive_status();
-
-       if (!sjcd_status_valid) {
-               printk("SJCD: cannot load status.\n");
-               return (-1);
-       }
-
-       if (!sjcd_media_is_available) {
-               printk("SJCD: no disk in drive\n");
-               return (-1);
-       }
-
-       if (!sjcd_command_failed) {
-               if (sjcd_load_response(&info, sizeof(info)) != 0) {
-                       printk
-                           ("SJCD: cannot load response about disk size.\n");
-                       return (-1);
-               }
-               sjcd_disk_length.min = info.un.track_msf.min;
-               sjcd_disk_length.sec = info.un.track_msf.sec;
-               sjcd_disk_length.frame = info.un.track_msf.frame;
-       } else {
-               printk("SJCD: get size failed\n");
-               return (1);
-       }
-#if defined( SJCD_TRACE )
-       printk("SJCD: (%02x:%02x.%02x)\n", sjcd_disk_length.min,
-              sjcd_disk_length.sec, sjcd_disk_length.frame);
-#endif
-       return (0);
-}
-
-/*
- * Load subchannel information.
- */
-static int sjcd_get_q_info(struct sjcd_hw_qinfo *qp)
-{
-       int s;
-#if defined( SJCD_TRACE )
-       printk("SJCD: load sub q\n");
-#endif
-       sjcd_send_cmd(SCMD_GET_QINFO);
-       s = sjcd_receive_status();
-       if (s < 0 || sjcd_command_failed || !sjcd_status_valid) {
-               sjcd_send_cmd(0xF2);
-               s = sjcd_receive_status();
-               if (s < 0 || sjcd_command_failed || !sjcd_status_valid)
-                       return (-1);
-               sjcd_send_cmd(SCMD_GET_QINFO);
-               s = sjcd_receive_status();
-               if (s < 0 || sjcd_command_failed || !sjcd_status_valid)
-                       return (-1);
-       }
-       if (sjcd_media_is_available)
-               if (sjcd_load_response(qp, sizeof(*qp)) == 0)
-                       return (0);
-       return (-1);
-}
-
-/*
- * Start playing from the specified position.
- */
-static int sjcd_play(struct sjcd_play_msf *mp)
-{
-       struct sjcd_play_msf msf;
-
-       /*
-        * Turn the device to play mode.
-        */
-       sjcd_send_1_cmd(SCMD_SET_MODE, SCMD_MODE_PLAY);
-       if (sjcd_receive_status() < 0)
-               return (-1);
-
-       /*
-        * Seek to the starting point.
-        */
-       msf.start = mp->start;
-       msf.end.min = msf.end.sec = msf.end.frame = 0x00;
-       sjcd_send_6_cmd(SCMD_SEEK, &msf);
-       if (sjcd_receive_status() < 0)
-               return (-1);
-
-       /*
-        * Start playing.
-        */
-       sjcd_send_6_cmd(SCMD_PLAY, mp);
-       return (sjcd_receive_status());
-}
-
-/*
- * Tray control functions.
- */
-static int sjcd_tray_close(void)
-{
-#if defined( SJCD_TRACE )
-       printk("SJCD: tray_close\n");
-#endif
-       sjcd_send_cmd(SCMD_CLOSE_TRAY);
-       return (sjcd_receive_status());
-}
-
-static int sjcd_tray_lock(void)
-{
-#if defined( SJCD_TRACE )
-       printk("SJCD: tray_lock\n");
-#endif
-       sjcd_send_cmd(SCMD_LOCK_TRAY);
-       return (sjcd_receive_status());
-}
-
-static int sjcd_tray_unlock(void)
-{
-#if defined( SJCD_TRACE )
-       printk("SJCD: tray_unlock\n");
-#endif
-       sjcd_send_cmd(SCMD_UNLOCK_TRAY);
-       return (sjcd_receive_status());
-}
-
-static int sjcd_tray_open(void)
-{
-#if defined( SJCD_TRACE )
-       printk("SJCD: tray_open\n");
-#endif
-       sjcd_send_cmd(SCMD_EJECT_TRAY);
-       return (sjcd_receive_status());
-}
-
-/*
- * Do some user commands.
- */
-static int sjcd_ioctl(struct inode *ip, struct file *fp,
-                     unsigned int cmd, unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-#if defined( SJCD_TRACE )
-       printk("SJCD:ioctl\n");
-#endif
-
-       sjcd_get_status();
-       if (!sjcd_status_valid)
-               return (-EIO);
-       if (sjcd_update_toc() < 0)
-               return (-EIO);
-
-       switch (cmd) {
-       case CDROMSTART:{
-#if defined( SJCD_TRACE )
-                       printk("SJCD: ioctl: start\n");
-#endif
-                       return (0);
-               }
-
-       case CDROMSTOP:{
-#if defined( SJCD_TRACE )
-                       printk("SJCD: ioctl: stop\n");
-#endif
-                       sjcd_send_cmd(SCMD_PAUSE);
-                       (void) sjcd_receive_status();
-                       sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
-                       return (0);
-               }
-
-       case CDROMPAUSE:{
-                       struct sjcd_hw_qinfo q_info;
-#if defined( SJCD_TRACE )
-                       printk("SJCD: ioctl: pause\n");
-#endif
-                       if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
-                               sjcd_send_cmd(SCMD_PAUSE);
-                               (void) sjcd_receive_status();
-                               if (sjcd_get_q_info(&q_info) < 0) {
-                                       sjcd_audio_status =
-                                           CDROM_AUDIO_NO_STATUS;
-                               } else {
-                                       sjcd_audio_status =
-                                           CDROM_AUDIO_PAUSED;
-                                       sjcd_playing.start = q_info.abs;
-                               }
-                               return (0);
-                       } else
-                               return (-EINVAL);
-               }
-
-       case CDROMRESUME:{
-#if defined( SJCD_TRACE )
-                       printk("SJCD: ioctl: resume\n");
-#endif
-                       if (sjcd_audio_status == CDROM_AUDIO_PAUSED) {
-                               /*
-                                * continue play starting at saved location
-                                */
-                               if (sjcd_play(&sjcd_playing) < 0) {
-                                       sjcd_audio_status =
-                                           CDROM_AUDIO_ERROR;
-                                       return (-EIO);
-                               } else {
-                                       sjcd_audio_status =
-                                           CDROM_AUDIO_PLAY;
-                                       return (0);
-                               }
-                       } else
-                               return (-EINVAL);
-               }
-
-       case CDROMPLAYTRKIND:{
-                       struct cdrom_ti ti;
-                       int s = -EFAULT;
-#if defined( SJCD_TRACE )
-                       printk("SJCD: ioctl: playtrkind\n");
-#endif
-                       if (!copy_from_user(&ti, argp, sizeof(ti))) {
-                               s = 0;
-                               if (ti.cdti_trk0 < sjcd_first_track_no)
-                                       return (-EINVAL);
-                               if (ti.cdti_trk1 > sjcd_last_track_no)
-                                       ti.cdti_trk1 = sjcd_last_track_no;
-                               if (ti.cdti_trk0 > ti.cdti_trk1)
-                                       return (-EINVAL);
-
-                               sjcd_playing.start =
-                                   sjcd_table_of_contents[ti.cdti_trk0].
-                                   un.track_msf;
-                               sjcd_playing.end =
-                                   (ti.cdti_trk1 <
-                                    sjcd_last_track_no) ?
-                                   sjcd_table_of_contents[ti.cdti_trk1 +
-                                                          1].un.
-                                   track_msf : sjcd_table_of_contents[0].
-                                   un.track_msf;
-
-                               if (sjcd_play(&sjcd_playing) < 0) {
-                                       sjcd_audio_status =
-                                           CDROM_AUDIO_ERROR;
-                                       return (-EIO);
-                               } else
-                                       sjcd_audio_status =
-                                           CDROM_AUDIO_PLAY;
-                       }
-                       return (s);
-               }
-
-       case CDROMPLAYMSF:{
-                       struct cdrom_msf sjcd_msf;
-                       int s;
-#if defined( SJCD_TRACE )
-                       printk("SJCD: ioctl: playmsf\n");
-#endif
-                       if ((s =
-                            access_ok(VERIFY_READ, argp, sizeof(sjcd_msf))
-                                       ? 0 : -EFAULT) == 0) {
-                               if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
-                                       sjcd_send_cmd(SCMD_PAUSE);
-                                       (void) sjcd_receive_status();
-                                       sjcd_audio_status =
-                                           CDROM_AUDIO_NO_STATUS;
-                               }
-
-                               if (copy_from_user(&sjcd_msf, argp,
-                                              sizeof(sjcd_msf)))
-                                       return (-EFAULT);
-
-                               sjcd_playing.start.min =
-                                   bin2bcd(sjcd_msf.cdmsf_min0);
-                               sjcd_playing.start.sec =
-                                   bin2bcd(sjcd_msf.cdmsf_sec0);
-                               sjcd_playing.start.frame =
-                                   bin2bcd(sjcd_msf.cdmsf_frame0);
-                               sjcd_playing.end.min =
-                                   bin2bcd(sjcd_msf.cdmsf_min1);
-                               sjcd_playing.end.sec =
-                                   bin2bcd(sjcd_msf.cdmsf_sec1);
-                               sjcd_playing.end.frame =
-                                   bin2bcd(sjcd_msf.cdmsf_frame1);
-
-                               if (sjcd_play(&sjcd_playing) < 0) {
-                                       sjcd_audio_status =
-                                           CDROM_AUDIO_ERROR;
-                                       return (-EIO);
-                               } else
-                                       sjcd_audio_status =
-                                           CDROM_AUDIO_PLAY;
-                       }
-                       return (s);
-               }
-
-       case CDROMREADTOCHDR:{
-                       struct cdrom_tochdr toc_header;
-#if defined (SJCD_TRACE )
-                       printk("SJCD: ioctl: readtocheader\n");
-#endif
-                       toc_header.cdth_trk0 = sjcd_first_track_no;
-                       toc_header.cdth_trk1 = sjcd_last_track_no;
-                       if (copy_to_user(argp, &toc_header,
-                                        sizeof(toc_header)))
-                               return -EFAULT;
-                       return 0;
-               }
-
-       case CDROMREADTOCENTRY:{
-                       struct cdrom_tocentry toc_entry;
-                       int s;
-#if defined( SJCD_TRACE )
-                       printk("SJCD: ioctl: readtocentry\n");
-#endif
-                       if ((s =
-                            access_ok(VERIFY_WRITE, argp, sizeof(toc_entry))
-                                       ? 0 : -EFAULT) == 0) {
-                               struct sjcd_hw_disk_info *tp;
-
-                               if (copy_from_user(&toc_entry, argp,
-                                              sizeof(toc_entry)))
-                                       return (-EFAULT);
-                               if (toc_entry.cdte_track == CDROM_LEADOUT)
-                                       tp = &sjcd_table_of_contents[0];
-                               else if (toc_entry.cdte_track <
-                                        sjcd_first_track_no)
-                                       return (-EINVAL);
-                               else if (toc_entry.cdte_track >
-                                        sjcd_last_track_no)
-                                       return (-EINVAL);
-                               else
-                                       tp = &sjcd_table_of_contents
-                                           [toc_entry.cdte_track];
-
-                               toc_entry.cdte_adr =
-                                   tp->track_control & 0x0F;
-                               toc_entry.cdte_ctrl =
-                                   tp->track_control >> 4;
-
-                               switch (toc_entry.cdte_format) {
-                               case CDROM_LBA:
-                                       toc_entry.cdte_addr.lba =
-                                           msf2hsg(&(tp->un.track_msf));
-                                       break;
-                               case CDROM_MSF:
-                                       toc_entry.cdte_addr.msf.minute =
-                                           bcd2bin(tp->un.track_msf.min);
-                                       toc_entry.cdte_addr.msf.second =
-                                           bcd2bin(tp->un.track_msf.sec);
-                                       toc_entry.cdte_addr.msf.frame =
-                                           bcd2bin(tp->un.track_msf.
-                                                   frame);
-                                       break;
-                               default:
-                                       return (-EINVAL);
-                               }
-                               if (copy_to_user(argp, &toc_entry,
-                                                sizeof(toc_entry)))
-                                       s = -EFAULT;
-                       }
-                       return (s);
-               }
-
-       case CDROMSUBCHNL:{
-                       struct cdrom_subchnl subchnl;
-                       int s;
-#if defined( SJCD_TRACE )
-                       printk("SJCD: ioctl: subchnl\n");
-#endif
-                       if ((s =
-                            access_ok(VERIFY_WRITE, argp, sizeof(subchnl))
-                                       ? 0 : -EFAULT) == 0) {
-                               struct sjcd_hw_qinfo q_info;
-
-                               if (copy_from_user(&subchnl, argp,
-                                              sizeof(subchnl)))
-                                       return (-EFAULT);
-
-                               if (sjcd_get_q_info(&q_info) < 0)
-                                       return (-EIO);
-
-                               subchnl.cdsc_audiostatus =
-                                   sjcd_audio_status;
-                               subchnl.cdsc_adr =
-                                   q_info.track_control & 0x0F;
-                               subchnl.cdsc_ctrl =
-                                   q_info.track_control >> 4;
-                               subchnl.cdsc_trk =
-                                   bcd2bin(q_info.track_no);
-                               subchnl.cdsc_ind = bcd2bin(q_info.x);
-
-                               switch (subchnl.cdsc_format) {
-                               case CDROM_LBA:
-                                       subchnl.cdsc_absaddr.lba =
-                                           msf2hsg(&(q_info.abs));
-                                       subchnl.cdsc_reladdr.lba =
-                                           msf2hsg(&(q_info.rel));
-                                       break;
-                               case CDROM_MSF:
-                                       subchnl.cdsc_absaddr.msf.minute =
-                                           bcd2bin(q_info.abs.min);
-                                       subchnl.cdsc_absaddr.msf.second =
-                                           bcd2bin(q_info.abs.sec);
-                                       subchnl.cdsc_absaddr.msf.frame =
-                                           bcd2bin(q_info.abs.frame);
-                                       subchnl.cdsc_reladdr.msf.minute =
-                                           bcd2bin(q_info.rel.min);
-                                       subchnl.cdsc_reladdr.msf.second =
-                                           bcd2bin(q_info.rel.sec);
-                                       subchnl.cdsc_reladdr.msf.frame =
-                                           bcd2bin(q_info.rel.frame);
-                                       break;
-                               default:
-                                       return (-EINVAL);
-                               }
-                               if (copy_to_user(argp, &subchnl,
-                                                sizeof(subchnl)))
-                                       s = -EFAULT;
-                       }
-                       return (s);
-               }
-
-       case CDROMVOLCTRL:{
-                       struct cdrom_volctrl vol_ctrl;
-                       int s;
-#if defined( SJCD_TRACE )
-                       printk("SJCD: ioctl: volctrl\n");
-#endif
-                       if ((s =
-                            access_ok(VERIFY_READ, argp, sizeof(vol_ctrl))
-                                       ? 0 : -EFAULT) == 0) {
-                               unsigned char dummy[4];
-
-                               if (copy_from_user(&vol_ctrl, argp,
-                                              sizeof(vol_ctrl)))
-                                       return (-EFAULT);
-                               sjcd_send_4_cmd(SCMD_SET_VOLUME,
-                                               vol_ctrl.channel0, 0xFF,
-                                               vol_ctrl.channel1, 0xFF);
-                               if (sjcd_receive_status() < 0)
-                                       return (-EIO);
-                               (void) sjcd_load_response(dummy, 4);
-                       }
-                       return (s);
-               }
-
-       case CDROMEJECT:{
-#if defined( SJCD_TRACE )
-                       printk("SJCD: ioctl: eject\n");
-#endif
-                       if (!sjcd_command_is_in_progress) {
-                               sjcd_tray_unlock();
-                               sjcd_send_cmd(SCMD_EJECT_TRAY);
-                               (void) sjcd_receive_status();
-                       }
-                       return (0);
-               }
-
-#if defined( SJCD_GATHER_STAT )
-       case 0xABCD:{
-#if defined( SJCD_TRACE )
-                       printk("SJCD: ioctl: statistic\n");
-#endif
-                       if (copy_to_user(argp, &statistic, sizeof(statistic)))
-                               return -EFAULT;
-                       return 0;
-               }
-#endif
-
-       default:
-               return (-EINVAL);
-       }
-}
-
-/*
- * Invalidate internal buffers of the driver.
- */
-static void sjcd_invalidate_buffers(void)
-{
-       int i;
-       for (i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[i++] = -1);
-       sjcd_buf_out = -1;
-}
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-
-static int current_valid(void)
-{
-        return CURRENT &&
-               rq_data_dir(CURRENT) == READ &&
-               CURRENT->sector != -1;
-}
-
-static void sjcd_transfer(void)
-{
-#if defined( SJCD_TRACE )
-       printk("SJCD: transfer:\n");
-#endif
-       if (current_valid()) {
-               while (CURRENT->nr_sectors) {
-                       int i, bn = CURRENT->sector / 4;
-                       for (i = 0;
-                            i < SJCD_BUF_SIZ && sjcd_buf_bn[i] != bn;
-                            i++);
-                       if (i < SJCD_BUF_SIZ) {
-                               int offs =
-                                   (i * 4 + (CURRENT->sector & 3)) * 512;
-                               int nr_sectors = 4 - (CURRENT->sector & 3);
-                               if (sjcd_buf_out != i) {
-                                       sjcd_buf_out = i;
-                                       if (sjcd_buf_bn[i] != bn) {
-                                               sjcd_buf_out = -1;
-                                               continue;
-                                       }
-                               }
-                               if (nr_sectors > CURRENT->nr_sectors)
-                                       nr_sectors = CURRENT->nr_sectors;
-#if defined( SJCD_TRACE )
-                               printk("SJCD: copy out\n");
-#endif
-                               memcpy(CURRENT->buffer, sjcd_buf + offs,
-                                      nr_sectors * 512);
-                               CURRENT->nr_sectors -= nr_sectors;
-                               CURRENT->sector += nr_sectors;
-                               CURRENT->buffer += nr_sectors * 512;
-                       } else {
-                               sjcd_buf_out = -1;
-                               break;
-                       }
-               }
-       }
-#if defined( SJCD_TRACE )
-       printk("SJCD: transfer: done\n");
-#endif
-}
-
-static void sjcd_poll(void)
-{
-#if defined( SJCD_GATHER_STAT )
-       /*
-        * Update total number of ticks.
-        */
-       statistic.ticks++;
-       statistic.tticks[sjcd_transfer_state]++;
-#endif
-
-      ReSwitch:switch (sjcd_transfer_state) {
-
-       case SJCD_S_IDLE:{
-#if defined( SJCD_GATHER_STAT )
-                       statistic.idle_ticks++;
-#endif
-#if defined( SJCD_TRACE )
-                       printk("SJCD_S_IDLE\n");
-#endif
-                       return;
-               }
-
-       case SJCD_S_START:{
-#if defined( SJCD_GATHER_STAT )
-                       statistic.start_ticks++;
-#endif
-                       sjcd_send_cmd(SCMD_GET_STATUS);
-                       sjcd_transfer_state =
-                           sjcd_mode ==
-                           SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE;
-                       sjcd_transfer_timeout = 500;
-#if defined( SJCD_TRACE )
-                       printk("SJCD_S_START: goto SJCD_S_%s mode\n",
-                              sjcd_transfer_state ==
-                              SJCD_S_READ ? "READ" : "MODE");
-#endif
-                       break;
-               }
-
-       case SJCD_S_MODE:{
-                       if (sjcd_check_status()) {
-                               /*
-                                * Previous command is completed.
-                                */
-                               if (!sjcd_status_valid
-                                   || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
-                                       printk
-                                           ("SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n");
-#endif
-                                       sjcd_transfer_state = SJCD_S_STOP;
-                                       goto ReSwitch;
-                               }
-
-                               sjcd_mode = 0;  /* unknown mode; should not be valid when failed */
-                               sjcd_send_1_cmd(SCMD_SET_MODE,
-                                               SCMD_MODE_COOKED);
-                               sjcd_transfer_state = SJCD_S_READ;
-                               sjcd_transfer_timeout = 1000;
-#if defined( SJCD_TRACE )
-                               printk
-                                   ("SJCD_S_MODE: goto SJCD_S_READ mode\n");
-#endif
-                       }
-#if defined( SJCD_GATHER_STAT )
-                       else
-                               statistic.mode_ticks++;
-#endif
-                       break;
-               }
-
-       case SJCD_S_READ:{
-                       if (sjcd_status_valid ? 1 : sjcd_check_status()) {
-                               /*
-                                * Previous command is completed.
-                                */
-                               if (!sjcd_status_valid
-                                   || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
-                                       printk
-                                           ("SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n");
-#endif
-                                       sjcd_transfer_state = SJCD_S_STOP;
-                                       goto ReSwitch;
-                               }
-                               if (!sjcd_media_is_available) {
-#if defined( SJCD_TRACE )
-                                       printk
-                                           ("SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n");
-#endif
-                                       sjcd_transfer_state = SJCD_S_STOP;
-                                       goto ReSwitch;
-                               }
-                               if (sjcd_mode != SCMD_MODE_COOKED) {
-                                       /*
-                                        * We seem to come from set mode. So discard one byte of result.
-                                        */
-                                       if (sjcd_load_response
-                                           (&sjcd_mode, 1) != 0) {
-#if defined( SJCD_TRACE )
-                                               printk
-                                                   ("SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n");
-#endif
-                                               sjcd_transfer_state =
-                                                   SJCD_S_STOP;
-                                               goto ReSwitch;
-                                       }
-                                       if (sjcd_mode != SCMD_MODE_COOKED) {
-#if defined( SJCD_TRACE )
-                                               printk
-                                                   ("SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n");
-#endif
-                                               sjcd_transfer_state =
-                                                   SJCD_S_STOP;
-                                               goto ReSwitch;
-                                       }
-                               }
-
-                               if (current_valid()) {
-                                       struct sjcd_play_msf msf;
-
-                                       sjcd_next_bn = CURRENT->sector / 4;
-                                       hsg2msf(sjcd_next_bn, &msf.start);
-                                       msf.end.min = 0;
-                                       msf.end.sec = 0;
-                                       msf.end.frame = sjcd_read_count =
-                                           SJCD_BUF_SIZ;
-#if defined( SJCD_TRACE )
-                                       printk
-                                           ("SJCD: ---reading msf-address %x:%x:%x  %x:%x:%x\n",
-                                            msf.start.min, msf.start.sec,
-                                            msf.start.frame, msf.end.min,
-                                            msf.end.sec, msf.end.frame);
-                                       printk
-                                           ("sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n",
-                                            sjcd_next_bn, sjcd_buf_in,
-                                            sjcd_buf_out,
-                                            sjcd_buf_bn[sjcd_buf_in]);
-#endif
-                                       sjcd_send_6_cmd(SCMD_DATA_READ,
-                                                       &msf);
-                                       sjcd_transfer_state = SJCD_S_DATA;
-                                       sjcd_transfer_timeout = 500;
-#if defined( SJCD_TRACE )
-                                       printk
-                                           ("SJCD_S_READ: go to SJCD_S_DATA mode\n");
-#endif
-                               } else {
-#if defined( SJCD_TRACE )
-                                       printk
-                                           ("SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n");
-#endif
-                                       sjcd_transfer_state = SJCD_S_STOP;
-                                       goto ReSwitch;
-                               }
-                       }
-#if defined( SJCD_GATHER_STAT )
-                       else
-                               statistic.read_ticks++;
-#endif
-                       break;
-               }
-
-       case SJCD_S_DATA:{
-                       unsigned char stat;
-
-                     sjcd_s_data:stat =
-                           inb(SJCDPORT
-                               (1));
-#if defined( SJCD_TRACE )
-                       printk("SJCD_S_DATA: status = 0x%02x\n", stat);
-#endif
-                       if (SJCD_STATUS_AVAILABLE(stat)) {
-                               /*
-                                * No data is waiting for us in the drive buffer. Status of operation
-                                * completion is available. Read and parse it.
-                                */
-                               sjcd_load_status();
-
-                               if (!sjcd_status_valid
-                                   || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
-                                       printk
-                                           ("SJCD: read block %d failed, maybe audio disk? Giving up\n",
-                                            sjcd_next_bn);
-#endif
-                                       if (current_valid())
-                                               end_request(CURRENT, 0);
-#if defined( SJCD_TRACE )
-                                       printk
-                                           ("SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n");
-#endif
-                                       sjcd_transfer_state = SJCD_S_STOP;
-                                       goto ReSwitch;
-                               }
-
-                               if (!sjcd_media_is_available) {
-                                       printk
-                                           ("SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n");
-                                       sjcd_transfer_state = SJCD_S_STOP;
-                                       goto ReSwitch;
-                               }
-
-                               sjcd_transfer_state = SJCD_S_READ;
-                               goto ReSwitch;
-                       } else if (SJCD_DATA_AVAILABLE(stat)) {
-                               /*
-                                * One frame is read into device buffer. We must copy it to our memory.
-                                * Otherwise cdrom hangs up. Check to see if we have something to copy
-                                * to.
-                                */
-                               if (!current_valid()
-                                   && sjcd_buf_in == sjcd_buf_out) {
-#if defined( SJCD_TRACE )
-                                       printk
-                                           ("SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n");
-                                       printk
-                                           (" ... all the date would be discarded\n");
-#endif
-                                       sjcd_transfer_state = SJCD_S_STOP;
-                                       goto ReSwitch;
-                               }
-
-                               /*
-                                * Everything seems to be OK. Just read the frame and recalculate
-                                * indices.
-                                */
-                               sjcd_buf_bn[sjcd_buf_in] = -1;  /* ??? */
-                               insb(SJCDPORT(2),
-                                    sjcd_buf + 2048 * sjcd_buf_in, 2048);
-#if defined( SJCD_TRACE )
-                               printk
-                                   ("SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n",
-                                    sjcd_next_bn, sjcd_buf_in,
-                                    sjcd_buf_out,
-                                    sjcd_buf_bn[sjcd_buf_in]);
-#endif
-                               sjcd_buf_bn[sjcd_buf_in] = sjcd_next_bn++;
-                               if (sjcd_buf_out == -1)
-                                       sjcd_buf_out = sjcd_buf_in;
-                               if (++sjcd_buf_in == SJCD_BUF_SIZ)
-                                       sjcd_buf_in = 0;
-
-                               /*
-                                * Only one frame is ready at time. So we should turn over to wait for
-                                * another frame. If we need that, of course.
-                                */
-                               if (--sjcd_read_count == 0) {
-                                       /*
-                                        * OK, request seems to be precessed. Continue transferring...
-                                        */
-                                       if (!sjcd_transfer_is_active) {
-                                               while (current_valid()) {
-                                                       /*
-                                                        * Continue transferring.
-                                                        */
-                                                       sjcd_transfer();
-                                                       if (CURRENT->
-                                                           nr_sectors ==
-                                                           0)
-                                                               end_request
-                                                                   (CURRENT, 1);
-                                                       else
-                                                               break;
-                                               }
-                                       }
-                                       if (current_valid() &&
-                                           (CURRENT->sector / 4 <
-                                            sjcd_next_bn
-                                            || CURRENT->sector / 4 >
-                                            sjcd_next_bn +
-                                            SJCD_BUF_SIZ)) {
-#if defined( SJCD_TRACE )
-                                               printk
-                                                   ("SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n");
-#endif
-                                               sjcd_transfer_state =
-                                                   SJCD_S_STOP;
-                                               goto ReSwitch;
-                                       }
-                               }
-                               /*
-                                * Now we should turn around rather than wait for while.
-                                */
-                               goto sjcd_s_data;
-                       }
-#if defined( SJCD_GATHER_STAT )
-                       else
-                               statistic.data_ticks++;
-#endif
-                       break;
-               }
-
-       case SJCD_S_STOP:{
-                       sjcd_read_count = 0;
-                       sjcd_send_cmd(SCMD_STOP);
-                       sjcd_transfer_state = SJCD_S_STOPPING;
-                       sjcd_transfer_timeout = 500;
-#if defined( SJCD_GATHER_STAT )
-                       statistic.stop_ticks++;
-#endif
-                       break;
-               }
-
-       case SJCD_S_STOPPING:{
-                       unsigned char stat;
-
-                       stat = inb(SJCDPORT(1));
-#if defined( SJCD_TRACE )
-                       printk("SJCD_S_STOP: status = 0x%02x\n", stat);
-#endif
-                       if (SJCD_DATA_AVAILABLE(stat)) {
-                               int i;
-#if defined( SJCD_TRACE )
-                               printk("SJCD_S_STOP: discard data\n");
-#endif
-                               /*
-                                * Discard all the data from the pipe. Foolish method.
-                                */
-                               for (i = 2048; i--;
-                                    (void) inb(SJCDPORT(2)));
-                               sjcd_transfer_timeout = 500;
-                       } else if (SJCD_STATUS_AVAILABLE(stat)) {
-                               sjcd_load_status();
-                               if (sjcd_status_valid
-                                   && sjcd_media_is_changed) {
-                                       sjcd_toc_uptodate = 0;
-                                       sjcd_invalidate_buffers();
-                               }
-                               if (current_valid()) {
-                                       if (sjcd_status_valid)
-                                               sjcd_transfer_state =
-                                                   SJCD_S_READ;
-                                       else
-                                               sjcd_transfer_state =
-                                                   SJCD_S_START;
-                               } else
-                                       sjcd_transfer_state = SJCD_S_IDLE;
-                               goto ReSwitch;
-                       }
-#if defined( SJCD_GATHER_STAT )
-                       else
-                               statistic.stopping_ticks++;
-#endif
-                       break;
-               }
-
-       default:
-               printk("SJCD: poll: invalid state %d\n",
-                      sjcd_transfer_state);
-               return;
-       }
-
-       if (--sjcd_transfer_timeout == 0) {
-               printk("SJCD: timeout in state %d\n", sjcd_transfer_state);
-               while (current_valid())
-                       end_request(CURRENT, 0);
-               sjcd_send_cmd(SCMD_STOP);
-               sjcd_transfer_state = SJCD_S_IDLE;
-               goto ReSwitch;
-       }
-
-       /*
-        * Get back in some time. 1 should be replaced with count variable to
-        * avoid unnecessary testings.
-        */
-       SJCD_SET_TIMER(sjcd_poll, 1);
-}
-
-static void do_sjcd_request(request_queue_t * q)
-{
-#if defined( SJCD_TRACE )
-       printk("SJCD: do_sjcd_request(%ld+%ld)\n",
-              CURRENT->sector, CURRENT->nr_sectors);
-#endif
-       sjcd_transfer_is_active = 1;
-       while (current_valid()) {
-               sjcd_transfer();
-               if (CURRENT->nr_sectors == 0)
-                       end_request(CURRENT, 1);
-               else {
-                       sjcd_buf_out = -1;      /* Want to read a block not in buffer */
-                       if (sjcd_transfer_state == SJCD_S_IDLE) {
-                               if (!sjcd_toc_uptodate) {
-                                       if (sjcd_update_toc() < 0) {
-                                               printk
-                                                   ("SJCD: transfer: discard\n");
-                                               while (current_valid())
-                                                       end_request(CURRENT, 0);
-                                               break;
-                                       }
-                               }
-                               sjcd_transfer_state = SJCD_S_START;
-                               SJCD_SET_TIMER(sjcd_poll, HZ / 100);
-                       }
-                       break;
-               }
-       }
-       sjcd_transfer_is_active = 0;
-#if defined( SJCD_TRACE )
-       printk
-           ("sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n",
-            sjcd_next_bn, sjcd_buf_in, sjcd_buf_out,
-            sjcd_buf_bn[sjcd_buf_in]);
-       printk("do_sjcd_request ends\n");
-#endif
-}
-
-/*
- * Open the device special file. Check disk is in.
- */
-static int sjcd_open(struct inode *ip, struct file *fp)
-{
-       /*
-        * Check the presence of device.
-        */
-       if (!sjcd_present)
-               return (-ENXIO);
-
-       /*
-        * Only read operations are allowed. Really? (:-)
-        */
-       if (fp->f_mode & 2)
-               return (-EROFS);
-
-       if (sjcd_open_count == 0) {
-               int s, sjcd_open_tries;
-/* We don't know that, do we? */
-/*
-    sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
-*/
-               sjcd_mode = 0;
-               sjcd_door_was_open = 0;
-               sjcd_transfer_state = SJCD_S_IDLE;
-               sjcd_invalidate_buffers();
-               sjcd_status_valid = 0;
-
-               /*
-                * Strict status checking.
-                */
-               for (sjcd_open_tries = 4; --sjcd_open_tries;) {
-                       if (!sjcd_status_valid)
-                               sjcd_get_status();
-                       if (!sjcd_status_valid) {
-#if defined( SJCD_DIAGNOSTIC )
-                               printk
-                                   ("SJCD: open: timed out when check status.\n");
-#endif
-                               goto err_out;
-                       } else if (!sjcd_media_is_available) {
-#if defined( SJCD_DIAGNOSTIC )
-                               printk("SJCD: open: no disk in drive\n");
-#endif
-                               if (!sjcd_door_closed) {
-                                       sjcd_door_was_open = 1;
-#if defined( SJCD_TRACE )
-                                       printk
-                                           ("SJCD: open: close the tray\n");
-#endif
-                                       s = sjcd_tray_close();
-                                       if (s < 0 || !sjcd_status_valid
-                                           || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
-                                               printk
-                                                   ("SJCD: open: tray close attempt failed\n");
-#endif
-                                               goto err_out;
-                                       }
-                                       continue;
-                               } else
-                                       goto err_out;
-                       }
-                       break;
-               }
-               s = sjcd_tray_lock();
-               if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
-                       printk("SJCD: open: tray lock attempt failed\n");
-#endif
-                       goto err_out;
-               }
-#if defined( SJCD_TRACE )
-               printk("SJCD: open: done\n");
-#endif
-       }
-
-       ++sjcd_open_count;
-       return (0);
-
-      err_out:
-       return (-EIO);
-}
-
-/*
- * On close, we flush all sjcd blocks from the buffer cache.
- */
-static int sjcd_release(struct inode *inode, struct file *file)
-{
-       int s;
-
-#if defined( SJCD_TRACE )
-       printk("SJCD: release\n");
-#endif
-       if (--sjcd_open_count == 0) {
-               sjcd_invalidate_buffers();
-               s = sjcd_tray_unlock();
-               if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
-                       printk
-                           ("SJCD: release: tray unlock attempt failed.\n");
-#endif
-               }
-               if (sjcd_door_was_open) {
-                       s = sjcd_tray_open();
-                       if (s < 0 || !sjcd_status_valid
-                           || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
-                               printk
-                                   ("SJCD: release: tray unload attempt failed.\n");
-#endif
-                       }
-               }
-       }
-       return 0;
-}
-
-/*
- * A list of file operations allowed for this cdrom.
- */
-static struct block_device_operations sjcd_fops = {
-       .owner          = THIS_MODULE,
-       .open           = sjcd_open,
-       .release        = sjcd_release,
-       .ioctl          = sjcd_ioctl,
-       .media_changed  = sjcd_disk_change,
-};
-
-/*
- * Following stuff is intended for initialization of the cdrom. It
- * first looks for presence of device. If the device is present, it
- * will be reset. Then read the version of the drive and load status.
- * The version is two BCD-coded bytes.
- */
-static struct {
-       unsigned char major, minor;
-} sjcd_version;
-
-static struct gendisk *sjcd_disk;
-
-/*
- * Test for presence of drive and initialize it. Called at boot time.
- * Probe cdrom, find out version and status.
- */
-static int __init sjcd_init(void)
-{
-       int i;
-
-       printk(KERN_INFO
-              "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n",
-              SJCD_VERSION_MAJOR, SJCD_VERSION_MINOR);
-
-#if defined( SJCD_TRACE )
-       printk("SJCD: sjcd=0x%x: ", sjcd_base);
-#endif
-
-       if (register_blkdev(MAJOR_NR, "sjcd"))
-               return -EIO;
-
-       sjcd_queue = blk_init_queue(do_sjcd_request, &sjcd_lock);
-       if (!sjcd_queue)
-               goto out0;
-
-       blk_queue_hardsect_size(sjcd_queue, 2048);
-
-       sjcd_disk = alloc_disk(1);
-       if (!sjcd_disk) {
-               printk(KERN_ERR "SJCD: can't allocate disk");
-               goto out1;
-       }
-       sjcd_disk->major = MAJOR_NR,
-       sjcd_disk->first_minor = 0,
-       sjcd_disk->fops = &sjcd_fops,
-       sprintf(sjcd_disk->disk_name, "sjcd");
-
-       if (!request_region(sjcd_base, 4,"sjcd")) {
-               printk
-                   ("SJCD: Init failed, I/O port (%X) is already in use\n",
-                    sjcd_base);
-               goto out2;
-       }
-
-       /*
-        * Check for card. Since we are booting now, we can't use standard
-        * wait algorithm.
-        */
-       printk(KERN_INFO "SJCD: Resetting: ");
-       sjcd_send_cmd(SCMD_RESET);
-       for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
-               unsigned long timer;
-
-               /*
-                * Wait 10ms approx.
-                */
-               for (timer = jiffies; time_before_eq(jiffies, timer););
-               if ((i % 100) == 0)
-                       printk(".");
-               (void) sjcd_check_status();
-       }
-       if (i == 0 || sjcd_command_failed) {
-               printk(" reset failed, no drive found.\n");
-               goto out3;
-       } else
-               printk("\n");
-
-       /*
-        * Get and print out cdrom version.
-        */
-       printk(KERN_INFO "SJCD: Getting version: ");
-       sjcd_send_cmd(SCMD_GET_VERSION);
-       for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
-               unsigned long timer;
-
-               /*
-                * Wait 10ms approx.
-                */
-               for (timer = jiffies; time_before_eq(jiffies, timer););
-               if ((i % 100) == 0)
-                       printk(".");
-               (void) sjcd_check_status();
-       }
-       if (i == 0 || sjcd_command_failed) {
-               printk(" get version failed, no drive found.\n");
-               goto out3;
-       }
-
-       if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) {
-               printk(" %1x.%02x\n", (int) sjcd_version.major,
-                      (int) sjcd_version.minor);
-       } else {
-               printk(" read version failed, no drive found.\n");
-               goto out3;
-       }
-
-       /*
-        * Check and print out the tray state. (if it is needed?).
-        */
-       if (!sjcd_status_valid) {
-               printk(KERN_INFO "SJCD: Getting status: ");
-               sjcd_send_cmd(SCMD_GET_STATUS);
-               for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
-                       unsigned long timer;
-
-                       /*
-                        * Wait 10ms approx.
-                        */
-                       for (timer = jiffies;
-                            time_before_eq(jiffies, timer););
-                       if ((i % 100) == 0)
-                               printk(".");
-                       (void) sjcd_check_status();
-               }
-               if (i == 0 || sjcd_command_failed) {
-                       printk(" get status failed, no drive found.\n");
-                       goto out3;
-               } else
-                       printk("\n");
-       }
-
-       printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base);
-       sjcd_disk->queue = sjcd_queue;
-       add_disk(sjcd_disk);
-
-       sjcd_present++;
-       return (0);
-out3:
-       release_region(sjcd_base, 4);
-out2:
-       put_disk(sjcd_disk);
-out1:
-       blk_cleanup_queue(sjcd_queue);
-out0:
-       if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
-               printk("SJCD: cannot unregister device.\n");
-       return (-EIO);
-}
-
-static void __exit sjcd_exit(void)
-{
-       del_gendisk(sjcd_disk);
-       put_disk(sjcd_disk);
-       release_region(sjcd_base, 4);
-       blk_cleanup_queue(sjcd_queue);
-       if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
-               printk("SJCD: cannot unregister device.\n");
-       printk(KERN_INFO "SJCD: module: removed.\n");
-}
-
-module_init(sjcd_init);
-module_exit(sjcd_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(SANYO_CDROM_MAJOR);
diff --git a/drivers/cdrom/sjcd.h b/drivers/cdrom/sjcd.h
deleted file mode 100644 (file)
index 0aa5e71..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Definitions for a Sanyo CD-ROM interface.
- *
- *   Copyright (C) 1995  Vadim V. Model
- *                                       model@cecmow.enet.dec.com
- *                                       vadim@rbrf.msk.su
- *                                       vadim@ipsun.ras.ru
- *                       Eric van der Maarel
- *                                       H.T.M.v.d.Maarel@marin.nl
- *
- *  This information is based on mcd.c from M. Harriss and sjcd102.lst from
- *  E. Moenkeberg.
- *
- *  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 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __SJCD_H__
-#define __SJCD_H__
-
-/*
- * Change this to set the I/O port address as default. More flexibility
- * come with setup implementation.
- */
-#define SJCD_BASE_ADDR      0x340
-
-/*
- * Change this to set the irq as default. Really SANYO do not use interrupts
- * at all.
- */
-#define SJCD_INTR_NR        0
-
-/*
- * Change this to set the dma as default value. really SANYO does not use
- * direct memory access at all.
- */
-#define SJCD_DMA_NR         0
-
-/*
- * Macros which allow us to find out the status of the drive.
- */
-#define SJCD_STATUS_AVAILABLE( x ) (((x)&0x02)==0)
-#define SJCD_DATA_AVAILABLE( x )   (((x)&0x01)==0)
-
-/*
- * Port access macro. Three ports are available: S-data port (command port),
- * status port (read only) and D-data port (read only).
- */
-#define SJCDPORT( x )       ( sjcd_base + ( x ) )
-#define SJCD_STATUS_PORT    SJCDPORT( 1 )
-#define SJCD_S_DATA_PORT    SJCDPORT( 0 )
-#define SJCD_COMMAND_PORT   SJCDPORT( 0 )
-#define SJCD_D_DATA_PORT    SJCDPORT( 2 )
-
-/*
- * Drive info bits. Drive info available as first (mandatory) byte of
- * command completion status.
- */
-#define SST_NOT_READY       0x10        /* no disk in the drive (???) */
-#define SST_MEDIA_CHANGED   0x20        /* disk is changed */
-#define SST_DOOR_OPENED     0x40        /* door is open */
-
-/* commands */
-
-#define SCMD_EJECT_TRAY     0xD0        /* eject tray if not locked */
-#define SCMD_LOCK_TRAY      0xD2        /* lock tray when in */
-#define SCMD_UNLOCK_TRAY    0xD4        /* unlock tray when in */
-#define SCMD_CLOSE_TRAY     0xD6        /* load tray in */
-
-#define SCMD_RESET          0xFA        /* soft reset */
-#define SCMD_GET_STATUS     0x80
-#define SCMD_GET_VERSION    0xCC
-
-#define SCMD_DATA_READ      0xA0        /* are the same, depend on mode&args */
-#define SCMD_SEEK           0xA0
-#define SCMD_PLAY           0xA0
-
-#define SCMD_GET_QINFO      0xA8
-
-#define SCMD_SET_MODE       0xC4
-#define SCMD_MODE_PLAY      0xE0
-#define SCMD_MODE_COOKED    (0xF8 & ~0x20)
-#define SCMD_MODE_RAW       0xF9
-#define SCMD_MODE_x20_BIT   0x20        /* What is it for ? */
-
-#define SCMD_SET_VOLUME     0xAE
-#define SCMD_PAUSE          0xE0
-#define SCMD_STOP           0xE0
-
-#define SCMD_GET_DISK_INFO  0xAA
-
-/*
- * Some standard arguments for SCMD_GET_DISK_INFO.
- */
-#define SCMD_GET_1_TRACK    0xA0    /* get the first track information */
-#define SCMD_GET_L_TRACK    0xA1    /* get the last track information */
-#define SCMD_GET_D_SIZE     0xA2    /* get the whole disk information */
-
-/*
- * Borrowed from hd.c. Allows to optimize multiple port read commands.
- */
-#define S_READ_DATA( port, buf, nr )      insb( port, buf, nr )
-
-/*
- * We assume that there are no audio disks with TOC length more than this
- * number (I personally have never seen disks with more than 20 fragments).
- */
-#define SJCD_MAX_TRACKS                100
-
-struct msf {
-  unsigned char   min;
-  unsigned char   sec;
-  unsigned char   frame;
-};
-
-struct sjcd_hw_disk_info {
-  unsigned char track_control;
-  unsigned char track_no;
-  unsigned char x, y, z;
-  union {
-    unsigned char track_no;
-    struct msf track_msf;
-  } un;
-};
-
-struct sjcd_hw_qinfo {
-  unsigned char track_control;
-  unsigned char track_no;
-  unsigned char x;
-  struct msf rel;
-  struct msf abs;
-};
-
-struct sjcd_play_msf {
-  struct msf  start;
-  struct msf  end;
-};
-
-struct sjcd_disk_info {
-  unsigned char   first;
-  unsigned char   last;
-  struct msf      disk_length;
-  struct msf      first_track;
-};
-
-struct sjcd_toc {
-  unsigned char   ctrl_addr;
-  unsigned char   track;
-  unsigned char   point_index;
-  struct msf      track_time;
-  struct msf      disk_time;
-};
-
-#if defined( SJCD_GATHER_STAT )
-
-struct sjcd_stat {
-  int ticks;
-  int tticks[ 8 ];
-  int idle_ticks;
-  int start_ticks;
-  int mode_ticks;
-  int read_ticks;
-  int data_ticks;
-  int stop_ticks;
-  int stopping_ticks;
-};
-
-#endif
-
-#endif
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
deleted file mode 100644 (file)
index f77ada9..0000000
+++ /dev/null
@@ -1,1689 +0,0 @@
-/*
- * Sony CDU-535 interface device driver
- *
- * This is a modified version of the CDU-31A device driver (see below).
- * Changes were made using documentation for the CDU-531 (which Sony
- * assures me is very similar to the 535) and partial disassembly of the
- * DOS driver.  I used Minyard's driver and replaced the CDU-31A
- * commands with the CDU-531 commands.  This was complicated by a different
- * interface protocol with the drive.  The driver is still polled.
- *
- * Data transfer rate is about 110 Kb/sec, theoretical maximum is 150 Kb/sec.
- * I tried polling without the sony_sleep during the data transfers but
- * it did not speed things up any.
- *
- * 1993-05-23 (rgj) changed the major number to 21 to get rid of conflict
- * with CDU-31A driver.  This is the also the number from the Linux
- * Device Driver Registry for the Sony Drive.  Hope nobody else is using it.
- *
- * 1993-08-29 (rgj) remove the configuring of the interface board address
- * from the top level configuration, you have to modify it in this file.
- *
- * 1995-01-26 Made module-capable (Joel Katz <Stimpson@Panix.COM>)
- *
- * 1995-05-20
- *  Modified to support CDU-510/515 series
- *      (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>)
- *  Fixed to report verify_area() failures
- *      (Heiko Eissfeldt <heiko@colossus.escape.de>)
- *
- * 1995-06-01
- *  More changes to support CDU-510/515 series
- *      (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>)
- *
- * 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>
- *
- * September 2003 - Fix SMP support by removing cli/sti calls.
- *                  Using spinlocks with a wait_queue instead.
- *                  Felipe Damasio <felipewd@terra.com.br>
- *
- * Things to do:
- *  - handle errors and status better, put everything into a single word
- *  - use interrupts (code mostly there, but a big hole still missing)
- *  - handle multi-session CDs?
- *  - use DMA?
- *
- *  Known Bugs:
- *  -
- *
- *   Ken Pizzini (ken@halcyon.com)
- *
- * Original by:
- *   Ron Jeppesen (ronj.an@site007.saic.com)
- *
- *
- *------------------------------------------------------------------------
- * Sony CDROM interface device driver.
- *
- * Corey Minyard (minyard@wf-rch.cirr.com) (CDU-535 complaints to Ken above)
- *
- * Colossians 3:17
- *
- * The Sony interface device driver handles Sony interface CDROM
- * drives and provides a complete block-level interface as well as an
- * ioctl() interface compatible with the Sun (as specified in
- * include/linux/cdrom.h).  With this interface, CDROMs can be
- * accessed and standard audio CDs can be played back normally.
- *
- * This interface is (unfortunately) a polled interface.  This is
- * because most Sony interfaces are set up with DMA and interrupts
- * disables.  Some (like mine) do not even have the capability to
- * handle interrupts or DMA.  For this reason you will see a bit of
- * the following:
- *
- *   snap = jiffies;
- *   while (jiffies-snap < SONY_JIFFIES_TIMEOUT)
- *   {
- *             if (some_condition())
- *         break;
- *      sony_sleep();
- *   }
- *   if (some_condition not met)
- *   {
- *      return an_error;
- *   }
- *
- * This ugly hack waits for something to happen, sleeping a little
- * between every try.  (The conditional is written so that jiffies
- * wrap-around is handled properly.)
- *
- * One thing about these drives: They talk in MSF (Minute Second Frame) format.
- * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a
- * disk.  The funny thing is that these are sent to the drive in BCD, but the
- * interface wants to see them in decimal.  A lot of conversion goes on.
- *
- *  Copyright (C) 1993  Corey Minyard
- *
- *  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 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-
-# include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/hdreg.h>
-#include <linux/genhd.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#define REALLY_SLOW_IO
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <linux/cdrom.h>
-
-#define MAJOR_NR CDU535_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */
-#include "sonycd535.h"
-
-/*
- * this is the base address of the interface card for the Sony CDU-535
- * CDROM drive.  If your jumpers are set for an address other than
- * this one (the default), change the following line to the
- * proper address.
- */
-#ifndef CDU535_ADDRESS
-# define CDU535_ADDRESS                        0x340
-#endif
-#ifndef CDU535_INTERRUPT
-# define CDU535_INTERRUPT              0
-#endif
-#ifndef CDU535_HANDLE
-# define CDU535_HANDLE                 "cdu535"
-#endif
-#ifndef CDU535_MESSAGE_NAME
-# define CDU535_MESSAGE_NAME   "Sony CDU-535"
-#endif
-
-#define CDU535_BLOCK_SIZE      2048 
-#ifndef MAX_SPINUP_RETRY
-# define MAX_SPINUP_RETRY              3       /* 1 is sufficient for most drives... */
-#endif
-#ifndef RETRY_FOR_BAD_STATUS
-# define RETRY_FOR_BAD_STATUS  100     /* in 10th of second */
-#endif
-
-#ifndef DEBUG
-# define DEBUG 1
-#endif
-
-/*
- *  SONY535_BUFFER_SIZE determines the size of internal buffer used
- *  by the drive.  It must be at least 2K and the larger the buffer
- *  the better the transfer rate.  It does however take system memory.
- *  On my system I get the following transfer rates using dd to read
- *  10 Mb off /dev/cdrom.
- *
- *    8K buffer      43 Kb/sec
- *   16K buffer      66 Kb/sec
- *   32K buffer      91 Kb/sec
- *   64K buffer     111 Kb/sec
- *  128K buffer     123 Kb/sec
- *  512K buffer     123 Kb/sec
- */
-#define SONY535_BUFFER_SIZE    (64*1024)
-
-/*
- *  if LOCK_DOORS is defined then the eject button is disabled while
- * the device is open.
- */
-#ifndef NO_LOCK_DOORS
-# define LOCK_DOORS
-#endif
-
-static int read_subcode(void);
-static void sony_get_toc(void);
-static int cdu_open(struct inode *inode, struct file *filp);
-static inline unsigned int int_to_bcd(unsigned int val);
-static unsigned int bcd_to_int(unsigned int bcd);
-static int do_sony_cmd(Byte * cmd, int nCmd, Byte status[2],
-                                          Byte * response, int n_response, int ignoreStatusBit7);
-
-/* The base I/O address of the Sony Interface.  This is a variable (not a
-   #define) so it can be easily changed via some future ioctl() */
-static unsigned int sony535_cd_base_io = CDU535_ADDRESS;
-module_param(sony535_cd_base_io, int, 0);
-
-/*
- * The following are I/O addresses of the various registers for the drive.  The
- * comment for the base address also applies here.
- */
-static unsigned short select_unit_reg;
-static unsigned short result_reg;
-static unsigned short command_reg;
-static unsigned short read_status_reg;
-static unsigned short data_reg;
-
-static DEFINE_SPINLOCK(sonycd535_lock); /* queue lock */
-static struct request_queue *sonycd535_queue;
-
-static int initialized;                        /* Has the drive been initialized? */
-static int sony_disc_changed = 1;      /* Has the disk been changed
-                                          since the last check? */
-static int sony_toc_read;              /* Has the table of contents been
-                                          read? */
-static unsigned int sony_buffer_size;  /* Size in bytes of the read-ahead
-                                          buffer. */
-static unsigned int sony_buffer_sectors;       /* Size (in 2048 byte records) of
-                                                  the read-ahead buffer. */
-static unsigned int sony_usage;                /* How many processes have the
-                                          drive open. */
-
-static int sony_first_block = -1;      /* First OS block (512 byte) in
-                                          the read-ahead buffer */
-static int sony_last_block = -1;       /* Last OS block (512 byte) in
-                                          the read-ahead buffer */
-
-static struct s535_sony_toc *sony_toc; /* Points to the table of
-                                          contents. */
-
-static struct s535_sony_subcode *last_sony_subcode;            /* Points to the last
-                                                                  subcode address read */
-static Byte **sony_buffer;             /* Points to the pointers
-                                          to the sector buffers */
-
-static int sony_inuse;                 /* is the drive in use? Only one
-                                          open at a time allowed */
-
-/*
- * The audio status uses the values from read subchannel data as specified
- * in include/linux/cdrom.h.
- */
-static int sony_audio_status = CDROM_AUDIO_NO_STATUS;
-
-/*
- * The following are a hack for pausing and resuming audio play.  The drive
- * does not work as I would expect it, if you stop it then start it again,
- * the drive seeks back to the beginning and starts over.  This holds the
- * position during a pause so a resume can restart it.  It uses the
- * audio status variable above to tell if it is paused.
- *   I just kept the CDU-31A driver behavior rather than using the PAUSE
- * command on the CDU-535.
- */
-static Byte cur_pos_msf[3];
-static Byte final_pos_msf[3];
-
-/* What IRQ is the drive using?  0 if none. */
-static int sony535_irq_used = CDU535_INTERRUPT;
-
-/* The interrupt handler will wake this queue up when it gets an interrupt. */
-static DECLARE_WAIT_QUEUE_HEAD(cdu535_irq_wait);
-
-
-/*
- * This routine returns 1 if the disk has been changed since the last
- * check or 0 if it hasn't.  Setting flag to 0 resets the changed flag.
- */
-static int
-cdu535_check_media_change(struct gendisk *disk)
-{
-       /* if driver is not initialized, always return 0 */
-       int retval = initialized ? sony_disc_changed : 0;
-       sony_disc_changed = 0;
-       return retval;
-}
-
-static inline void
-enable_interrupts(void)
-{
-#ifdef USE_IRQ
-       /*
-        * This code was taken from cdu31a.c; it will not
-        * directly work for the cdu535 as written...
-        */
-       curr_control_reg |= ( SONY_ATTN_INT_EN_BIT
-                                               | SONY_RES_RDY_INT_EN_BIT
-                                               | SONY_DATA_RDY_INT_EN_BIT);
-       outb(curr_control_reg, sony_cd_control_reg);
-#endif
-}
-
-static inline void
-disable_interrupts(void)
-{
-#ifdef USE_IRQ
-       /*
-        * This code was taken from cdu31a.c; it will not
-        * directly work for the cdu535 as written...
-        */
-       curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT
-                                               | SONY_RES_RDY_INT_EN_BIT
-                                               | SONY_DATA_RDY_INT_EN_BIT);
-       outb(curr_control_reg, sony_cd_control_reg);
-#endif
-}
-
-static irqreturn_t
-cdu535_interrupt(int irq, void *dev_id)
-{
-       disable_interrupts();
-       if (waitqueue_active(&cdu535_irq_wait)) {
-               wake_up(&cdu535_irq_wait);
-               return IRQ_HANDLED;
-       }
-       printk(CDU535_MESSAGE_NAME
-                       ": Got an interrupt but nothing was waiting\n");
-       return IRQ_NONE;
-}
-
-
-/*
- * Wait a little while.
- */
-static inline void
-sony_sleep(void)
-{
-       if (sony535_irq_used <= 0) {    /* poll */
-               yield();
-       } else {        /* Interrupt driven */
-               DEFINE_WAIT(wait);
-               
-               spin_lock_irq(&sonycd535_lock);
-               enable_interrupts();
-               prepare_to_wait(&cdu535_irq_wait, &wait, TASK_INTERRUPTIBLE);
-               spin_unlock_irq(&sonycd535_lock);
-               schedule();
-               finish_wait(&cdu535_irq_wait, &wait);
-       }
-}
-
-/*------------------start of SONY CDU535 very specific ---------------------*/
-
-/****************************************************************************
- * void select_unit( int unit_no )
- *
- *  Select the specified unit (0-3) so that subsequent commands reference it
- ****************************************************************************/
-static void
-select_unit(int unit_no)
-{
-       unsigned int select_mask = ~(1 << unit_no);
-       outb(select_mask, select_unit_reg);
-}
-
-/***************************************************************************
- * int read_result_reg( Byte *data_ptr )
- *
- *  Read a result byte from the Sony CDU controller, store in location pointed
- * to by data_ptr.  Return zero on success, TIME_OUT if we did not receive
- * data.
- ***************************************************************************/
-static int
-read_result_reg(Byte *data_ptr)
-{
-       unsigned long snap;
-       int read_status;
-
-       snap = jiffies;
-       while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
-               read_status = inb(read_status_reg);
-               if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {
-#if DEBUG > 1
-                       printk(CDU535_MESSAGE_NAME
-                                       ": read_result_reg(): readStatReg = 0x%x\n", read_status);
-#endif
-                       *data_ptr = inb(result_reg);
-                       return 0;
-               } else {
-                       sony_sleep();
-               }
-       }
-       printk(CDU535_MESSAGE_NAME " read_result_reg: TIME OUT!\n");
-       return TIME_OUT;
-}
-
-/****************************************************************************
- * int read_exec_status( Byte status[2] )
- *
- *  Read the execution status of the last command and put into status.
- * Handles reading second status word if available.  Returns 0 on success,
- * TIME_OUT on failure.
- ****************************************************************************/
-static int
-read_exec_status(Byte status[2])
-{
-       status[1] = 0;
-       if (read_result_reg(&(status[0])) != 0)
-               return TIME_OUT;
-       if ((status[0] & 0x80) != 0) {  /* byte two follows */
-               if (read_result_reg(&(status[1])) != 0)
-                       return TIME_OUT;
-       }
-#if DEBUG > 1
-       printk(CDU535_MESSAGE_NAME ": read_exec_status: read 0x%x 0x%x\n",
-                       status[0], status[1]);
-#endif
-       return 0;
-}
-
-/****************************************************************************
- * int check_drive_status( void )
- *
- *  Check the current drive status.  Using this before executing a command
- * takes care of the problem of unsolicited drive status-2 messages.
- * Add a check of the audio status if we think the disk is playing.
- ****************************************************************************/
-static int
-check_drive_status(void)
-{
-       Byte status, e_status[2];
-       int  CDD, ATN;
-       Byte cmd;
-
-       select_unit(0);
-       if (sony_audio_status == CDROM_AUDIO_PLAY) {    /* check status */
-               outb(SONY535_REQUEST_AUDIO_STATUS, command_reg);
-               if (read_result_reg(&status) == 0) {
-                       switch (status) {
-                       case 0x0:
-                               break;          /* play in progress */
-                       case 0x1:
-                               break;          /* paused */
-                       case 0x3:               /* audio play completed */
-                       case 0x5:               /* play not requested */
-                               sony_audio_status = CDROM_AUDIO_COMPLETED;
-                               read_subcode();
-                               break;
-                       case 0x4:               /* error during play */
-                               sony_audio_status = CDROM_AUDIO_ERROR;
-                               break;
-                       }
-               }
-       }
-       /* now check drive status */
-       outb(SONY535_REQUEST_DRIVE_STATUS_2, command_reg);
-       if (read_result_reg(&status) != 0)
-               return TIME_OUT;
-
-#if DEBUG > 1
-       printk(CDU535_MESSAGE_NAME ": check_drive_status() got 0x%x\n", status);
-#endif
-
-       if (status == 0)
-               return 0;
-
-       ATN = status & 0xf;
-       CDD = (status >> 4) & 0xf;
-
-       switch (ATN) {
-       case 0x0:
-               break;                                  /* go on to CDD stuff */
-       case SONY535_ATN_BUSY:
-               if (initialized)
-                       printk(CDU535_MESSAGE_NAME " error: drive busy\n");
-               return CD_BUSY;
-       case SONY535_ATN_EJECT_IN_PROGRESS:
-               printk(CDU535_MESSAGE_NAME " error: eject in progress\n");
-               sony_audio_status = CDROM_AUDIO_INVALID;
-               return CD_BUSY;
-       case SONY535_ATN_RESET_OCCURRED:
-       case SONY535_ATN_DISC_CHANGED:
-       case SONY535_ATN_RESET_AND_DISC_CHANGED:
-#if DEBUG > 0
-               printk(CDU535_MESSAGE_NAME " notice: reset occurred or disc changed\n");
-#endif
-               sony_disc_changed = 1;
-               sony_toc_read = 0;
-               sony_audio_status = CDROM_AUDIO_NO_STATUS;
-               sony_first_block = -1;
-               sony_last_block = -1;
-               if (initialized) {
-                       cmd = SONY535_SPIN_UP;
-                       do_sony_cmd(&cmd, 1, e_status, NULL, 0, 0);
-                       sony_get_toc();
-               }
-               return 0;
-       default:
-               printk(CDU535_MESSAGE_NAME " error: drive busy (ATN=0x%x)\n", ATN);
-               return CD_BUSY;
-       }
-       switch (CDD) {                  /* the 531 docs are not helpful in decoding this */
-       case 0x0:                               /* just use the values from the DOS driver */
-       case 0x2:
-       case 0xa:
-               break;                          /* no error */
-       case 0xc:
-               printk(CDU535_MESSAGE_NAME
-                               ": check_drive_status(): CDD = 0xc! Not properly handled!\n");
-               return CD_BUSY;         /* ? */
-       default:
-               return CD_BUSY;
-       }
-       return 0;
-}      /* check_drive_status() */
-
-/*****************************************************************************
- * int do_sony_cmd( Byte *cmd, int n_cmd, Byte status[2],
- *                Byte *response, int n_response, int ignore_status_bit7 )
- *
- *  Generic routine for executing commands.  The command and its parameters
- *  should be placed in the cmd[] array, number of bytes in the command is
- *  stored in nCmd.  The response from the command will be stored in the
- *  response array.  The number of bytes you expect back (excluding status)
- *  should be passed in n_response.  Finally, some
- *  commands set bit 7 of the return status even when there is no second
- *  status byte, on these commands set ignoreStatusBit7 TRUE.
- *    If the command was sent and data received back, then we return 0,
- *  else we return TIME_OUT.  You still have to check the status yourself.
- *    You should call check_drive_status() before calling this routine
- *  so that you do not lose notifications of disk changes, etc.
- ****************************************************************************/
-static int
-do_sony_cmd(Byte * cmd, int n_cmd, Byte status[2],
-                       Byte * response, int n_response, int ignore_status_bit7)
-{
-       int i;
-
-       /* write out the command */
-       for (i = 0; i < n_cmd; i++)
-               outb(cmd[i], command_reg);
-
-       /* read back the status */
-       if (read_result_reg(status) != 0)
-               return TIME_OUT;
-       if (!ignore_status_bit7 && ((status[0] & 0x80) != 0)) {
-               /* get second status byte */
-               if (read_result_reg(status + 1) != 0)
-                       return TIME_OUT;
-       } else {
-               status[1] = 0;
-       }
-#if DEBUG > 2
-       printk(CDU535_MESSAGE_NAME ": do_sony_cmd %x: %x %x\n",
-                       *cmd, status[0], status[1]);
-#endif
-
-       /* do not know about when I should read set of data and when not to */
-       if ((status[0] & ((ignore_status_bit7 ? 0x7f : 0xff) & 0x8f)) != 0)
-               return 0;
-
-       /* else, read in rest of data */
-       for (i = 0; 0 < n_response; n_response--, i++)
-               if (read_result_reg(response + i) != 0)
-                       return TIME_OUT;
-       return 0;
-}      /* do_sony_cmd() */
-
-/**************************************************************************
- * int set_drive_mode( int mode, Byte status[2] )
- *
- *  Set the drive mode to the specified value (mode=0 is audio, mode=e0
- * is mode-1 CDROM
- **************************************************************************/
-static int
-set_drive_mode(int mode, Byte status[2])
-{
-       Byte cmd_buff[2];
-       Byte ret_buff[1];
-
-       cmd_buff[0] = SONY535_SET_DRIVE_MODE;
-       cmd_buff[1] = mode;
-       return do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1);
-}
-
-/***************************************************************************
- * int seek_and_read_N_blocks( Byte params[], int n_blocks, Byte status[2],
- *                             Byte *data_buff, int buff_size )
- *
- *  Read n_blocks of data from the CDROM starting at position params[0:2],
- *  number of blocks in stored in params[3:5] -- both these are already
- *  int bcd format.
- *  Transfer the data into the buffer pointed at by data_buff.  buff_size
- *  gives the number of bytes available in the buffer.
- *    The routine returns number of bytes read in if successful, otherwise
- *  it returns one of the standard error returns.
- ***************************************************************************/
-static int
-seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
-                                          Byte **buff, int buf_size)
-{
-       Byte cmd_buff[7];
-       int  i;
-       int  read_status;
-       unsigned long snap;
-       Byte *data_buff;
-       int  sector_count = 0;
-
-       if (buf_size < CDU535_BLOCK_SIZE * n_blocks)
-               return NO_ROOM;
-
-       set_drive_mode(SONY535_CDROM_DRIVE_MODE, status);
-
-       /* send command to read the data */
-       cmd_buff[0] = SONY535_SEEK_AND_READ_N_BLOCKS_1;
-       for (i = 0; i < 6; i++)
-               cmd_buff[i + 1] = params[i];
-       for (i = 0; i < 7; i++)
-               outb(cmd_buff[i], command_reg);
-
-       /* read back the data one block at a time */
-       while (0 < n_blocks--) {
-               /* wait for data to be ready */
-               int data_valid = 0;
-               snap = jiffies;
-               while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
-                       read_status = inb(read_status_reg);
-                       if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {
-                               read_exec_status(status);
-                               return BAD_STATUS;
-                       }
-                       if ((read_status & SONY535_DATA_NOT_READY_BIT) == 0) {
-                               /* data is ready, read it */
-                               data_buff = buff[sector_count++];
-                               for (i = 0; i < CDU535_BLOCK_SIZE; i++)
-                                       *data_buff++ = inb(data_reg);   /* unrolling this loop does not seem to help */
-                               data_valid = 1;
-                               break;                  /* exit the timeout loop */
-                       }
-                       sony_sleep();           /* data not ready, sleep a while */
-               }
-               if (!data_valid)
-                       return TIME_OUT;        /* if we reach this stage */
-       }
-
-       /* read all the data, now read the status */
-       if ((i = read_exec_status(status)) != 0)
-               return i;
-       return CDU535_BLOCK_SIZE * sector_count;
-}      /* seek_and_read_N_blocks() */
-
-/****************************************************************************
- * int request_toc_data( Byte status[2], struct s535_sony_toc *toc )
- *
- *  Read in the table of contents data.  Converts all the bcd data
- * into integers in the toc structure.
- ****************************************************************************/
-static int
-request_toc_data(Byte status[2], struct s535_sony_toc *toc)
-{
-       int  to_status;
-       int  i, j, n_tracks, track_no;
-       int  first_track_num, last_track_num;
-       Byte cmd_no = 0xb2;
-       Byte track_address_buffer[5];
-
-       /* read the fixed portion of the table of contents */
-       if ((to_status = do_sony_cmd(&cmd_no, 1, status, (Byte *) toc, 15, 1)) != 0)
-               return to_status;
-
-       /* convert the data into integers so we can use them */
-       first_track_num = bcd_to_int(toc->first_track_num);
-       last_track_num = bcd_to_int(toc->last_track_num);
-       n_tracks = last_track_num - first_track_num + 1;
-
-       /* read each of the track address descriptors */
-       for (i = 0; i < n_tracks; i++) {
-               /* read the descriptor into a temporary buffer */
-               for (j = 0; j < 5; j++) {
-                       if (read_result_reg(track_address_buffer + j) != 0)
-                               return TIME_OUT;
-                       if (j == 1)             /* need to convert from bcd */
-                               track_no = bcd_to_int(track_address_buffer[j]);
-               }
-               /* copy the descriptor to proper location - sonycd.c just fills */
-               memcpy(toc->tracks + i, track_address_buffer, 5);
-       }
-       return 0;
-}      /* request_toc_data() */
-
-/***************************************************************************
- * int spin_up_drive( Byte status[2] )
- *
- *  Spin up the drive (unless it is already spinning).
- ***************************************************************************/
-static int
-spin_up_drive(Byte status[2])
-{
-       Byte cmd;
-
-       /* first see if the drive is already spinning */
-       cmd = SONY535_REQUEST_DRIVE_STATUS_1;
-       if (do_sony_cmd(&cmd, 1, status, NULL, 0, 0) != 0)
-               return TIME_OUT;
-       if ((status[0] & SONY535_STATUS1_NOT_SPINNING) == 0)
-               return 0;       /* it's already spinning */
-
-       /* otherwise, give the spin-up command */
-       cmd = SONY535_SPIN_UP;
-       return do_sony_cmd(&cmd, 1, status, NULL, 0, 0);
-}
-
-/*--------------------end of SONY CDU535 very specific ---------------------*/
-
-/* Convert from an integer 0-99 to BCD */
-static inline unsigned int
-int_to_bcd(unsigned int val)
-{
-       int retval;
-
-       retval = (val / 10) << 4;
-       retval = retval | val % 10;
-       return retval;
-}
-
-
-/* Convert from BCD to an integer from 0-99 */
-static unsigned int
-bcd_to_int(unsigned int bcd)
-{
-       return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
-}
-
-
-/*
- * Convert a logical sector value (like the OS would want to use for
- * a block device) to an MSF format.
- */
-static void
-log_to_msf(unsigned int log, Byte *msf)
-{
-       log = log + LOG_START_OFFSET;
-       msf[0] = int_to_bcd(log / 4500);
-       log = log % 4500;
-       msf[1] = int_to_bcd(log / 75);
-       msf[2] = int_to_bcd(log % 75);
-}
-
-
-/*
- * Convert an MSF format to a logical sector.
- */
-static unsigned int
-msf_to_log(Byte *msf)
-{
-       unsigned int log;
-
-
-       log = bcd_to_int(msf[2]);
-       log += bcd_to_int(msf[1]) * 75;
-       log += bcd_to_int(msf[0]) * 4500;
-       log = log - LOG_START_OFFSET;
-
-       return log;
-}
-
-
-/*
- * Take in integer size value and put it into a buffer like
- * the drive would want to see a number-of-sector value.
- */
-static void
-size_to_buf(unsigned int size, Byte *buf)
-{
-       buf[0] = size / 65536;
-       size = size % 65536;
-       buf[1] = size / 256;
-       buf[2] = size % 256;
-}
-
-
-/*
- * The OS calls this to perform a read or write operation to the drive.
- * Write obviously fail.  Reads to a read ahead of sony_buffer_size
- * bytes to help speed operations.  This especially helps since the OS
- * may use 1024 byte blocks and the drive uses 2048 byte blocks.  Since most
- * data access on a CD is done sequentially, this saves a lot of operations.
- */
-static void
-do_cdu535_request(request_queue_t * q)
-{
-       struct request *req;
-       unsigned int read_size;
-       int  block;
-       int  nsect;
-       int  copyoff;
-       int  spin_up_retry;
-       Byte params[10];
-       Byte status[2];
-       Byte cmd[2];
-
-       while (1) {
-               req = elv_next_request(q);
-               if (!req)
-                       return;
-
-               block = req->sector;
-               nsect = req->nr_sectors;
-               if (!blk_fs_request(req)) {
-                       end_request(req, 0);
-                       continue;
-               }
-               if (rq_data_dir(req) == WRITE) {
-                       end_request(req, 0);
-                       continue;
-               }
-               /*
-                * If the block address is invalid or the request goes beyond
-                * the end of the media, return an error.
-                */
-               if (sony_toc->lead_out_start_lba <= (block/4)) {
-                       end_request(req, 0);
-                       return;
-               }
-               if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
-                       end_request(req, 0);
-                       return;
-               }
-               while (0 < nsect) {
-                       /*
-                        * If the requested sector is not currently in
-                        * the read-ahead buffer, it must be read in.
-                        */
-                       if ((block < sony_first_block) || (sony_last_block < block)) {
-                               sony_first_block = (block / 4) * 4;
-                               log_to_msf(block / 4, params);
-                               
-                               /*
-                                * If the full read-ahead would go beyond the end of the media, trim
-                                * it back to read just till the end of the media.
-                                */
-                               if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
-                                       sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
-                                       read_size = sony_toc->lead_out_start_lba - (block / 4);
-                               } else {
-                                       sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
-                                       read_size = sony_buffer_sectors;
-                               }
-                               size_to_buf(read_size, &params[3]);
-                               
-                               /*
-                                * Read the data.  If the drive was not spinning,
-                                * spin it up and try some more.
-                                */
-                               for (spin_up_retry=0 ;; ++spin_up_retry) {
-                                       /* This loop has been modified to support the Sony
-                                        * CDU-510/515 series, thanks to Claudio Porfiri 
-                                        * <C.Porfiri@nisms.tei.ericsson.se>.
-                                        */
-                                       /*
-                                        * This part is to deal with very slow hardware.  We
-                                        * try at most MAX_SPINUP_RETRY times to read the same
-                                        * block.  A check for seek_and_read_N_blocks' result is
-                                        * performed; if the result is wrong, the CDROM's engine
-                                        * is restarted and the operation is tried again.
-                                        */
-                                       /*
-                                        * 1995-06-01: The system got problems when downloading
-                                        * from Slackware CDROM, the problem seems to be:
-                                        * seek_and_read_N_blocks returns BAD_STATUS and we
-                                        * should wait for a while before retrying, so a new
-                                        * part was added to discriminate the return value from
-                                        * seek_and_read_N_blocks for the various cases.
-                                        */
-                                       int readStatus = seek_and_read_N_blocks(params, read_size,
-                                                                               status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
-                                       if (0 <= readStatus)    /* Good data; common case, placed first */
-                                               break;
-                                       if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
-                                               /* give up */
-                                               if (readStatus == NO_ROOM)
-                                                       printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
-                                               else
-                                                       printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
-                                                              status[0]);
-                                               sony_first_block = -1;
-                                               sony_last_block = -1;
-                                               end_request(req, 0);
-                                               return;
-                                       }
-                                       if (readStatus == BAD_STATUS) {
-                                               /* Sleep for a while, then retry */
-                                               set_current_state(TASK_INTERRUPTIBLE);
-                                               spin_unlock_irq(&sonycd535_lock);
-                                               schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
-                                               spin_lock_irq(&sonycd535_lock);
-                                       }
-#if DEBUG > 0
-                                       printk(CDU535_MESSAGE_NAME
-                                              " debug: calling spin up when reading data!\n");
-#endif
-                                       cmd[0] = SONY535_SPIN_UP;
-                                       do_sony_cmd(cmd, 1, status, NULL, 0, 0);
-                               }
-                       }
-                       /*
-                        * The data is in memory now, copy it to the buffer and advance to the
-                        * next block to read.
-                        */
-                       copyoff = block - sony_first_block;
-                       memcpy(req->buffer,
-                              sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
-                       
-                       block += 1;
-                       nsect -= 1;
-                       req->buffer += 512;
-               }
-
-               end_request(req, 1);
-       }
-}
-
-/*
- * Read the table of contents from the drive and set sony_toc_read if
- * successful.
- */
-static void
-sony_get_toc(void)
-{
-       Byte status[2];
-       if (!sony_toc_read) {
-               /* do not call check_drive_status() from here since it can call this routine */
-               if (request_toc_data(status, sony_toc) < 0)
-                       return;
-               sony_toc->lead_out_start_lba = msf_to_log(sony_toc->lead_out_start_msf);
-               sony_toc_read = 1;
-       }
-}
-
-
-/*
- * Search for a specific track in the table of contents.  track is
- * passed in bcd format
- */
-static int
-find_track(int track)
-{
-       int i;
-       int num_tracks;
-
-
-       num_tracks = bcd_to_int(sony_toc->last_track_num) -
-               bcd_to_int(sony_toc->first_track_num) + 1;
-       for (i = 0; i < num_tracks; i++) {
-               if (sony_toc->tracks[i].track == track) {
-                       return i;
-               }
-       }
-
-       return -1;
-}
-
-/*
- * Read the subcode and put it int last_sony_subcode for future use.
- */
-static int
-read_subcode(void)
-{
-       Byte cmd = SONY535_REQUEST_SUB_Q_DATA;
-       Byte status[2];
-       int  dsc_status;
-
-       if (check_drive_status() != 0)
-               return -EIO;
-
-       if ((dsc_status = do_sony_cmd(&cmd, 1, status, (Byte *) last_sony_subcode,
-                                                          sizeof(struct s535_sony_subcode), 1)) != 0) {
-               printk(CDU535_MESSAGE_NAME " error 0x%.2x, %d (read_subcode)\n",
-                               status[0], dsc_status);
-               return -EIO;
-       }
-       return 0;
-}
-
-
-/*
- * Get the subchannel info like the CDROMSUBCHNL command wants to see it.  If
- * the drive is playing, the subchannel needs to be read (since it would be
- * changing).  If the drive is paused or completed, the subcode information has
- * already been stored, just use that.  The ioctl call wants things in decimal
- * (not BCD), so all the conversions are done.
- */
-static int
-sony_get_subchnl_info(void __user *arg)
-{
-       struct cdrom_subchnl schi;
-
-       /* Get attention stuff */
-       if (check_drive_status() != 0)
-               return -EIO;
-
-       sony_get_toc();
-       if (!sony_toc_read) {
-               return -EIO;
-       }
-       if (copy_from_user(&schi, arg, sizeof schi))
-               return -EFAULT;
-
-       switch (sony_audio_status) {
-       case CDROM_AUDIO_PLAY:
-               if (read_subcode() < 0) {
-                       return -EIO;
-               }
-               break;
-
-       case CDROM_AUDIO_PAUSED:
-       case CDROM_AUDIO_COMPLETED:
-               break;
-
-       case CDROM_AUDIO_NO_STATUS:
-               schi.cdsc_audiostatus = sony_audio_status;
-               if (copy_to_user(arg, &schi, sizeof schi))
-                       return -EFAULT;
-               return 0;
-               break;
-
-       case CDROM_AUDIO_INVALID:
-       case CDROM_AUDIO_ERROR:
-       default:
-               return -EIO;
-       }
-
-       schi.cdsc_audiostatus = sony_audio_status;
-       schi.cdsc_adr = last_sony_subcode->address;
-       schi.cdsc_ctrl = last_sony_subcode->control;
-       schi.cdsc_trk = bcd_to_int(last_sony_subcode->track_num);
-       schi.cdsc_ind = bcd_to_int(last_sony_subcode->index_num);
-       if (schi.cdsc_format == CDROM_MSF) {
-               schi.cdsc_absaddr.msf.minute = bcd_to_int(last_sony_subcode->abs_msf[0]);
-               schi.cdsc_absaddr.msf.second = bcd_to_int(last_sony_subcode->abs_msf[1]);
-               schi.cdsc_absaddr.msf.frame = bcd_to_int(last_sony_subcode->abs_msf[2]);
-
-               schi.cdsc_reladdr.msf.minute = bcd_to_int(last_sony_subcode->rel_msf[0]);
-               schi.cdsc_reladdr.msf.second = bcd_to_int(last_sony_subcode->rel_msf[1]);
-               schi.cdsc_reladdr.msf.frame = bcd_to_int(last_sony_subcode->rel_msf[2]);
-       } else if (schi.cdsc_format == CDROM_LBA) {
-               schi.cdsc_absaddr.lba = msf_to_log(last_sony_subcode->abs_msf);
-               schi.cdsc_reladdr.lba = msf_to_log(last_sony_subcode->rel_msf);
-       }
-       return copy_to_user(arg, &schi, sizeof schi) ? -EFAULT : 0;
-}
-
-
-/*
- * The big ugly ioctl handler.
- */
-static int
-cdu_ioctl(struct inode *inode,
-                 struct file *file,
-                 unsigned int cmd,
-                 unsigned long arg)
-{
-       Byte status[2];
-       Byte cmd_buff[10], params[10];
-       int  i;
-       int  dsc_status;
-       void __user *argp = (void __user *)arg;
-
-       if (check_drive_status() != 0)
-               return -EIO;
-
-       switch (cmd) {
-       case CDROMSTART:                        /* Spin up the drive */
-               if (spin_up_drive(status) < 0) {
-                       printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTART)\n",
-                                       status[0]);
-                       return -EIO;
-               }
-               return 0;
-               break;
-
-       case CDROMSTOP:                 /* Spin down the drive */
-               cmd_buff[0] = SONY535_HOLD;
-               do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-
-               /*
-                * Spin the drive down, ignoring the error if the disk was
-                * already not spinning.
-                */
-               sony_audio_status = CDROM_AUDIO_NO_STATUS;
-               cmd_buff[0] = SONY535_SPIN_DOWN;
-               dsc_status = do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-               if (((dsc_status < 0) && (dsc_status != BAD_STATUS)) ||
-                       ((status[0] & ~(SONY535_STATUS1_NOT_SPINNING)) != 0)) {
-                       printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTOP)\n",
-                                       status[0]);
-                       return -EIO;
-               }
-               return 0;
-               break;
-
-       case CDROMPAUSE:                        /* Pause the drive */
-               cmd_buff[0] = SONY535_HOLD;             /* CDU-31 driver uses AUDIO_STOP, not pause */
-               if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
-                       printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPAUSE)\n",
-                                       status[0]);
-                       return -EIO;
-               }
-               /* Get the current position and save it for resuming */
-               if (read_subcode() < 0) {
-                       return -EIO;
-               }
-               cur_pos_msf[0] = last_sony_subcode->abs_msf[0];
-               cur_pos_msf[1] = last_sony_subcode->abs_msf[1];
-               cur_pos_msf[2] = last_sony_subcode->abs_msf[2];
-               sony_audio_status = CDROM_AUDIO_PAUSED;
-               return 0;
-               break;
-
-       case CDROMRESUME:                       /* Start the drive after being paused */
-               set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
-               if (sony_audio_status != CDROM_AUDIO_PAUSED) {
-                       return -EINVAL;
-               }
-               spin_up_drive(status);
-
-               /* Start the drive at the saved position. */
-               cmd_buff[0] = SONY535_PLAY_AUDIO;
-               cmd_buff[1] = 0;                /* play back starting at this address */
-               cmd_buff[2] = cur_pos_msf[0];
-               cmd_buff[3] = cur_pos_msf[1];
-               cmd_buff[4] = cur_pos_msf[2];
-               cmd_buff[5] = SONY535_PLAY_AUDIO;
-               cmd_buff[6] = 2;                /* set ending address */
-               cmd_buff[7] = final_pos_msf[0];
-               cmd_buff[8] = final_pos_msf[1];
-               cmd_buff[9] = final_pos_msf[2];
-               if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
-                       (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
-                       printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMRESUME)\n",
-                                       status[0]);
-                       return -EIO;
-               }
-               sony_audio_status = CDROM_AUDIO_PLAY;
-               return 0;
-               break;
-
-       case CDROMPLAYMSF:                      /* Play starting at the given MSF address. */
-               if (copy_from_user(params, argp, 6))
-                       return -EFAULT;
-               spin_up_drive(status);
-               set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
-               /* The parameters are given in int, must be converted */
-               for (i = 0; i < 3; i++) {
-                       cmd_buff[2 + i] = int_to_bcd(params[i]);
-                       cmd_buff[7 + i] = int_to_bcd(params[i + 3]);
-               }
-               cmd_buff[0] = SONY535_PLAY_AUDIO;
-               cmd_buff[1] = 0;                /* play back starting at this address */
-               /* cmd_buff[2-4] are filled in for loop above */
-               cmd_buff[5] = SONY535_PLAY_AUDIO;
-               cmd_buff[6] = 2;                /* set ending address */
-               /* cmd_buff[7-9] are filled in for loop above */
-               if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
-                       (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
-                       printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYMSF)\n",
-                                       status[0]);
-                       return -EIO;
-               }
-               /* Save the final position for pauses and resumes */
-               final_pos_msf[0] = cmd_buff[7];
-               final_pos_msf[1] = cmd_buff[8];
-               final_pos_msf[2] = cmd_buff[9];
-               sony_audio_status = CDROM_AUDIO_PLAY;
-               return 0;
-               break;
-
-       case CDROMREADTOCHDR:           /* Read the table of contents header */
-               {
-                       struct cdrom_tochdr __user *hdr = argp;
-                       struct cdrom_tochdr loc_hdr;
-
-                       sony_get_toc();
-                       if (!sony_toc_read)
-                               return -EIO;
-                       loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num);
-                       loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num);
-                       if (copy_to_user(hdr, &loc_hdr, sizeof *hdr))
-                               return -EFAULT;
-               }
-               return 0;
-               break;
-
-       case CDROMREADTOCENTRY: /* Read a given table of contents entry */
-               {
-                       struct cdrom_tocentry __user *entry = argp;
-                       struct cdrom_tocentry loc_entry;
-                       int  track_idx;
-                       Byte *msf_val = NULL;
-
-                       sony_get_toc();
-                       if (!sony_toc_read) {
-                               return -EIO;
-                       }
-
-                       if (copy_from_user(&loc_entry, entry, sizeof loc_entry))
-                               return -EFAULT;
-
-                       /* Lead out is handled separately since it is special. */
-                       if (loc_entry.cdte_track == CDROM_LEADOUT) {
-                               loc_entry.cdte_adr = 0 /*sony_toc->address2 */ ;
-                               loc_entry.cdte_ctrl = sony_toc->control2;
-                               msf_val = sony_toc->lead_out_start_msf;
-                       } else {
-                               track_idx = find_track(int_to_bcd(loc_entry.cdte_track));
-                               if (track_idx < 0)
-                                       return -EINVAL;
-                               loc_entry.cdte_adr = 0 /*sony_toc->tracks[track_idx].address */ ;
-                               loc_entry.cdte_ctrl = sony_toc->tracks[track_idx].control;
-                               msf_val = sony_toc->tracks[track_idx].track_start_msf;
-                       }
-
-                       /* Logical buffer address or MSF format requested? */
-                       if (loc_entry.cdte_format == CDROM_LBA) {
-                               loc_entry.cdte_addr.lba = msf_to_log(msf_val);
-                       } else if (loc_entry.cdte_format == CDROM_MSF) {
-                               loc_entry.cdte_addr.msf.minute = bcd_to_int(*msf_val);
-                               loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val + 1));
-                               loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val + 2));
-                       }
-                       if (copy_to_user(entry, &loc_entry, sizeof *entry))
-                               return -EFAULT;
-               }
-               return 0;
-               break;
-
-       case CDROMPLAYTRKIND:           /* Play a track.  This currently ignores index. */
-               {
-                       struct cdrom_ti ti;
-                       int track_idx;
-
-                       sony_get_toc();
-                       if (!sony_toc_read)
-                               return -EIO;
-
-                       if (copy_from_user(&ti, argp, sizeof ti))
-                               return -EFAULT;
-                       if ((ti.cdti_trk0 < sony_toc->first_track_num)
-                               || (sony_toc->last_track_num < ti.cdti_trk0)
-                               || (ti.cdti_trk1 < ti.cdti_trk0)) {
-                               return -EINVAL;
-                       }
-                       track_idx = find_track(int_to_bcd(ti.cdti_trk0));
-                       if (track_idx < 0)
-                               return -EINVAL;
-                       params[1] = sony_toc->tracks[track_idx].track_start_msf[0];
-                       params[2] = sony_toc->tracks[track_idx].track_start_msf[1];
-                       params[3] = sony_toc->tracks[track_idx].track_start_msf[2];
-                       /*
-                        * If we want to stop after the last track, use the lead-out
-                        * MSF to do that.
-                        */
-                       if (bcd_to_int(sony_toc->last_track_num) <= ti.cdti_trk1) {
-                               log_to_msf(msf_to_log(sony_toc->lead_out_start_msf) - 1,
-                                                  &(params[4]));
-                       } else {
-                               track_idx = find_track(int_to_bcd(ti.cdti_trk1 + 1));
-                               if (track_idx < 0)
-                                       return -EINVAL;
-                               log_to_msf(msf_to_log(sony_toc->tracks[track_idx].track_start_msf) - 1,
-                                                  &(params[4]));
-                       }
-                       params[0] = 0x03;
-
-                       spin_up_drive(status);
-
-                       set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
-                       /* Start the drive at the saved position. */
-                       cmd_buff[0] = SONY535_PLAY_AUDIO;
-                       cmd_buff[1] = 0;        /* play back starting at this address */
-                       cmd_buff[2] = params[1];
-                       cmd_buff[3] = params[2];
-                       cmd_buff[4] = params[3];
-                       cmd_buff[5] = SONY535_PLAY_AUDIO;
-                       cmd_buff[6] = 2;        /* set ending address */
-                       cmd_buff[7] = params[4];
-                       cmd_buff[8] = params[5];
-                       cmd_buff[9] = params[6];
-                       if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
-                               (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
-                               printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYTRKIND)\n",
-                                               status[0]);
-                               printk("... Params: %x %x %x %x %x %x %x\n",
-                                               params[0], params[1], params[2],
-                                               params[3], params[4], params[5], params[6]);
-                               return -EIO;
-                       }
-                       /* Save the final position for pauses and resumes */
-                       final_pos_msf[0] = params[4];
-                       final_pos_msf[1] = params[5];
-                       final_pos_msf[2] = params[6];
-                       sony_audio_status = CDROM_AUDIO_PLAY;
-                       return 0;
-               }
-
-       case CDROMSUBCHNL:                      /* Get subchannel info */
-               return sony_get_subchnl_info(argp);
-
-       case CDROMVOLCTRL:                      /* Volume control.  What volume does this change, anyway? */
-               {
-                       struct cdrom_volctrl volctrl;
-
-                       if (copy_from_user(&volctrl, argp, sizeof volctrl))
-                               return -EFAULT;
-                       cmd_buff[0] = SONY535_SET_VOLUME;
-                       cmd_buff[1] = volctrl.channel0;
-                       cmd_buff[2] = volctrl.channel1;
-                       if (do_sony_cmd(cmd_buff, 3, status, NULL, 0, 0) != 0) {
-                               printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMVOLCTRL)\n",
-                                               status[0]);
-                               return -EIO;
-                       }
-               }
-               return 0;
-
-       case CDROMEJECT:                        /* Eject the drive */
-               cmd_buff[0] = SONY535_STOP;
-               do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-               cmd_buff[0] = SONY535_SPIN_DOWN;
-               do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-
-               sony_audio_status = CDROM_AUDIO_INVALID;
-               cmd_buff[0] = SONY535_EJECT_CADDY;
-               if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
-                       printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMEJECT)\n",
-                                       status[0]);
-                       return -EIO;
-               }
-               return 0;
-               break;
-
-       default:
-               return -EINVAL;
-       }
-}
-
-
-/*
- * Open the drive for operations.  Spin the drive up and read the table of
- * contents if these have not already been done.
- */
-static int
-cdu_open(struct inode *inode,
-                struct file *filp)
-{
-       Byte status[2], cmd_buff[2];
-
-       if (sony_inuse)
-               return -EBUSY;
-       if (check_drive_status() != 0)
-               return -EIO;
-       sony_inuse = 1;
-
-       if (spin_up_drive(status) != 0) {
-               printk(CDU535_MESSAGE_NAME " error 0x%.2x (cdu_open, spin up)\n",
-                               status[0]);
-               sony_inuse = 0;
-               return -EIO;
-       }
-       sony_get_toc();
-       if (!sony_toc_read) {
-               cmd_buff[0] = SONY535_SPIN_DOWN;
-               do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-               sony_inuse = 0;
-               return -EIO;
-       }
-       check_disk_change(inode->i_bdev);
-       sony_usage++;
-
-#ifdef LOCK_DOORS
-       /* disable the eject button while mounted */
-       cmd_buff[0] = SONY535_DISABLE_EJECT_BUTTON;
-       do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-#endif
-
-       return 0;
-}
-
-
-/*
- * Close the drive.  Spin it down if no task is using it.  The spin
- * down will fail if playing audio, so audio play is OK.
- */
-static int
-cdu_release(struct inode *inode,
-                       struct file *filp)
-{
-       Byte status[2], cmd_no;
-
-       sony_inuse = 0;
-
-       if (0 < sony_usage) {
-               sony_usage--;
-       }
-       if (sony_usage == 0) {
-               check_drive_status();
-
-               if (sony_audio_status != CDROM_AUDIO_PLAY) {
-                       cmd_no = SONY535_SPIN_DOWN;
-                       do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
-               }
-#ifdef LOCK_DOORS
-               /* enable the eject button after umount */
-               cmd_no = SONY535_ENABLE_EJECT_BUTTON;
-               do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
-#endif
-       }
-       return 0;
-}
-
-static struct block_device_operations cdu_fops =
-{
-       .owner          = THIS_MODULE,
-       .open           = cdu_open,
-       .release        = cdu_release,
-       .ioctl          = cdu_ioctl,
-       .media_changed  = cdu535_check_media_change,
-};
-
-static struct gendisk *cdu_disk;
-
-/*
- * Initialize the driver.
- */
-static int __init sony535_init(void)
-{
-       struct s535_sony_drive_config drive_config;
-       Byte cmd_buff[3];
-       Byte ret_buff[2];
-       Byte status[2];
-       unsigned long snap;
-       int  got_result = 0;
-       int  tmp_irq;
-       int  i;
-       int err;
-
-       /* Setting the base I/O address to 0 will disable it. */
-       if ((sony535_cd_base_io == 0xffff)||(sony535_cd_base_io == 0))
-               return 0;
-
-       /* Set up all the register locations */
-       result_reg = sony535_cd_base_io;
-       command_reg = sony535_cd_base_io;
-       data_reg = sony535_cd_base_io + 1;
-       read_status_reg = sony535_cd_base_io + 2;
-       select_unit_reg = sony535_cd_base_io + 3;
-
-#ifndef USE_IRQ
-       sony535_irq_used = 0;   /* polling only until this is ready... */
-#endif
-       /* we need to poll until things get initialized */
-       tmp_irq = sony535_irq_used;
-       sony535_irq_used = 0;
-
-#if DEBUG > 0
-       printk(KERN_INFO CDU535_MESSAGE_NAME ": probing base address %03X\n",
-                       sony535_cd_base_io);
-#endif
-       /* look for the CD-ROM, follows the procedure in the DOS driver */
-       inb(select_unit_reg);
-       /* wait for 40 18 Hz ticks (reverse-engineered from DOS driver) */
-       schedule_timeout_interruptible((HZ+17)*40/18);
-       inb(result_reg);
-
-       outb(0, read_status_reg);       /* does a reset? */
-       snap = jiffies;
-       while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
-               select_unit(0);
-               if (inb(result_reg) != 0xff) {
-                       got_result = 1;
-                       break;
-               }
-               sony_sleep();
-       }
-
-       if (!got_result || check_drive_status() == TIME_OUT)
-               goto Enodev;
-
-       /* CD-ROM drive responded --  get the drive configuration */
-       cmd_buff[0] = SONY535_INQUIRY;
-       if (do_sony_cmd(cmd_buff, 1, status, (Byte *)&drive_config, 28, 1) != 0)
-               goto Enodev;
-
-       /* was able to get the configuration,
-        * set drive mode as rest of init
-        */
-#if DEBUG > 0
-       /* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */
-       if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 )
-               printk(CDU535_MESSAGE_NAME
-                               "Inquiry command returned status = 0x%x\n", status[0]);
-#endif
-       /* now ready to use interrupts, if available */
-       sony535_irq_used = tmp_irq;
-
-       /* A negative sony535_irq_used will attempt an autoirq. */
-       if (sony535_irq_used < 0) {
-               unsigned long irq_mask, delay;
-
-               irq_mask = probe_irq_on();
-               enable_interrupts();
-               outb(0, read_status_reg);       /* does a reset? */
-               delay = jiffies + HZ/10;
-               while (time_before(jiffies, delay)) ;
-
-               sony535_irq_used = probe_irq_off(irq_mask);
-               disable_interrupts();
-       }
-       if (sony535_irq_used > 0) {
-           if (request_irq(sony535_irq_used, cdu535_interrupt,
-                                               IRQF_DISABLED, CDU535_HANDLE, NULL)) {
-                       printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME
-                                       " driver; polling instead.\n", sony535_irq_used);
-                       sony535_irq_used = 0;
-               }
-       }
-       cmd_buff[0] = SONY535_SET_DRIVE_MODE;
-       cmd_buff[1] = 0x0;      /* default audio */
-       if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) != 0)
-               goto Enodev_irq;
-
-       /* set the drive mode successful, we are set! */
-       sony_buffer_size = SONY535_BUFFER_SIZE;
-       sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE;
-
-       printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s",
-                  drive_config.vendor_id,
-                  drive_config.product_id,
-                  drive_config.product_rev_level);
-       printk("  base address %03X, ", sony535_cd_base_io);
-       if (tmp_irq > 0)
-               printk("IRQ%d, ", tmp_irq);
-       printk("using %d byte buffer\n", sony_buffer_size);
-
-       if (register_blkdev(MAJOR_NR, CDU535_HANDLE)) {
-               err = -EIO;
-               goto out1;
-       }
-       sonycd535_queue = blk_init_queue(do_cdu535_request, &sonycd535_lock);
-       if (!sonycd535_queue) {
-               err = -ENOMEM;
-               goto out1a;
-       }
-
-       blk_queue_hardsect_size(sonycd535_queue, CDU535_BLOCK_SIZE);
-       sony_toc = kmalloc(sizeof(struct s535_sony_toc), GFP_KERNEL);
-       err = -ENOMEM;
-       if (!sony_toc)
-               goto out2;
-       last_sony_subcode = kmalloc(sizeof(struct s535_sony_subcode), GFP_KERNEL);
-       if (!last_sony_subcode)
-               goto out3;
-       sony_buffer = kmalloc(sizeof(Byte *) * sony_buffer_sectors, GFP_KERNEL);
-       if (!sony_buffer)
-               goto out4;
-       for (i = 0; i < sony_buffer_sectors; i++) {
-               sony_buffer[i] = kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL);
-               if (!sony_buffer[i]) {
-                       while (--i>=0)
-                               kfree(sony_buffer[i]);
-                       goto out5;
-               }
-       }
-       initialized = 1;
-
-       cdu_disk = alloc_disk(1);
-       if (!cdu_disk)
-               goto out6;
-       cdu_disk->major = MAJOR_NR;
-       cdu_disk->first_minor = 0;
-       cdu_disk->fops = &cdu_fops;
-       sprintf(cdu_disk->disk_name, "cdu");
-
-       if (!request_region(sony535_cd_base_io, 4, CDU535_HANDLE)) {
-               printk(KERN_WARNING"sonycd535: Unable to request region 0x%x\n",
-                       sony535_cd_base_io);
-               goto out7;
-       }
-       cdu_disk->queue = sonycd535_queue;
-       add_disk(cdu_disk);
-       return 0;
-
-out7:
-       put_disk(cdu_disk);
-out6:
-       for (i = 0; i < sony_buffer_sectors; i++)
-               kfree(sony_buffer[i]);
-out5:
-       kfree(sony_buffer);
-out4:
-       kfree(last_sony_subcode);
-out3:
-       kfree(sony_toc);
-out2:
-       blk_cleanup_queue(sonycd535_queue);
-out1a:
-       unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
-out1:
-       if (sony535_irq_used)
-               free_irq(sony535_irq_used, NULL);
-       return err;
-Enodev_irq:
-       if (sony535_irq_used)
-               free_irq(sony535_irq_used, NULL);
-Enodev:
-       printk("Did not find a " CDU535_MESSAGE_NAME " drive\n");
-       return -EIO;
-}
-
-#ifndef MODULE
-
-/*
- * accept "kernel command line" parameters
- * (added by emoenke@gwdg.de)
- *
- * use: tell LILO:
- *                 sonycd535=0x320
- *
- * the address value has to be the existing CDROM port address.
- */
-static int __init
-sonycd535_setup(char *strings)
-{
-       int ints[3];
-       (void)get_options(strings, ARRAY_SIZE(ints), ints);
-       /* if IRQ change and default io base desired,
-        * then call with io base of 0
-        */
-       if (ints[0] > 0)
-               if (ints[1] != 0)
-                       sony535_cd_base_io = ints[1];
-       if (ints[0] > 1)
-               sony535_irq_used = ints[2];
-       if ((strings != NULL) && (*strings != '\0'))
-               printk(CDU535_MESSAGE_NAME
-                               ": Warning: Unknown interface type: %s\n", strings);
-                               
-       return 1;
-}
-
-__setup("sonycd535=", sonycd535_setup);
-
-#endif /* MODULE */
-
-static void __exit
-sony535_exit(void)
-{
-       int i;
-
-       release_region(sony535_cd_base_io, 4);
-       for (i = 0; i < sony_buffer_sectors; i++)
-               kfree(sony_buffer[i]);
-       kfree(sony_buffer);
-       kfree(last_sony_subcode);
-       kfree(sony_toc);
-       del_gendisk(cdu_disk);
-       put_disk(cdu_disk);
-       blk_cleanup_queue(sonycd535_queue);
-       if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
-               printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
-       else
-               printk(KERN_INFO CDU535_HANDLE " module released\n");
-}
-
-module_init(sony535_init);
-module_exit(sony535_exit);
-
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(CDU535_CDROM_MAJOR);
diff --git a/drivers/cdrom/sonycd535.h b/drivers/cdrom/sonycd535.h
deleted file mode 100644 (file)
index 5dea1ef..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-#ifndef SONYCD535_H
-#define SONYCD535_H
-
-/*
- * define all the commands recognized by the CDU-531/5
- */
-#define SONY535_REQUEST_DRIVE_STATUS_1         (0x80)
-#define SONY535_REQUEST_SENSE                  (0x82)
-#define SONY535_REQUEST_DRIVE_STATUS_2         (0x84)
-#define SONY535_REQUEST_ERROR_STATUS           (0x86)
-#define SONY535_REQUEST_AUDIO_STATUS           (0x88)
-#define SONY535_INQUIRY                                (0x8a)
-
-#define SONY535_SET_INACTIVITY_TIME            (0x90)
-
-#define SONY535_SEEK_AND_READ_N_BLOCKS_1       (0xa0)
-#define SONY535_SEEK_AND_READ_N_BLOCKS_2       (0xa4)
-#define SONY535_PLAY_AUDIO                     (0xa6)
-
-#define SONY535_REQUEST_DISC_CAPACITY          (0xb0)
-#define SONY535_REQUEST_TOC_DATA               (0xb2)
-#define SONY535_REQUEST_SUB_Q_DATA             (0xb4)
-#define SONY535_REQUEST_ISRC                   (0xb6)
-#define SONY535_REQUEST_UPC_EAN                        (0xb8)
-
-#define SONY535_SET_DRIVE_MODE                 (0xc0)
-#define SONY535_REQUEST_DRIVE_MODE             (0xc2)
-#define SONY535_SET_RETRY_COUNT                        (0xc4)
-
-#define SONY535_DIAGNOSTIC_1                   (0xc6)
-#define SONY535_DIAGNOSTIC_4                   (0xcc)
-#define SONY535_DIAGNOSTIC_5                   (0xce)
-
-#define SONY535_EJECT_CADDY                    (0xd0)
-#define SONY535_DISABLE_EJECT_BUTTON           (0xd2)
-#define SONY535_ENABLE_EJECT_BUTTON            (0xd4)
-
-#define SONY535_HOLD                           (0xe0)
-#define SONY535_AUDIO_PAUSE_ON_OFF             (0xe2)
-#define SONY535_SET_VOLUME                     (0xe8)
-
-#define SONY535_STOP                           (0xf0)
-#define SONY535_SPIN_UP                                (0xf2)
-#define SONY535_SPIN_DOWN                      (0xf4)
-
-#define SONY535_CLEAR_PARAMETERS               (0xf6)
-#define SONY535_CLEAR_ENDING_ADDRESS           (0xf8)
-
-/*
- * define some masks
- */
-#define SONY535_DATA_NOT_READY_BIT             (0x1)
-#define SONY535_RESULT_NOT_READY_BIT           (0x2)
-
-/*
- *  drive status 1
- */
-#define SONY535_STATUS1_COMMAND_ERROR          (0x1)
-#define SONY535_STATUS1_DATA_ERROR             (0x2)
-#define SONY535_STATUS1_SEEK_ERROR             (0x4)
-#define SONY535_STATUS1_DISC_TYPE_ERROR                (0x8)
-#define SONY535_STATUS1_NOT_SPINNING           (0x10)
-#define SONY535_STATUS1_EJECT_BUTTON_PRESSED   (0x20)
-#define SONY535_STATUS1_CADDY_NOT_INSERTED     (0x40)
-#define SONY535_STATUS1_BYTE_TWO_FOLLOWS       (0x80)
-
-/*
- * drive status 2
- */
-#define SONY535_CDD_LOADING_ERROR              (0x7)
-#define SONY535_CDD_NO_DISC                    (0x8)
-#define SONY535_CDD_UNLOADING_ERROR            (0x9)
-#define SONY535_CDD_CADDY_NOT_INSERTED         (0xd)
-#define SONY535_ATN_RESET_OCCURRED             (0x2)
-#define SONY535_ATN_DISC_CHANGED               (0x4)
-#define SONY535_ATN_RESET_AND_DISC_CHANGED     (0x6)
-#define SONY535_ATN_EJECT_IN_PROGRESS          (0xe)
-#define SONY535_ATN_BUSY                       (0xf)
-
-/*
- * define some parameters
- */
-#define SONY535_AUDIO_DRIVE_MODE               (0)
-#define SONY535_CDROM_DRIVE_MODE               (0xe0)
-
-#define SONY535_PLAY_OP_PLAYBACK               (0)
-#define SONY535_PLAY_OP_ENTER_HOLD             (1)
-#define SONY535_PLAY_OP_SET_AUDIO_ENDING_ADDR  (2)
-#define SONY535_PLAY_OP_SCAN_FORWARD           (3)
-#define SONY535_PLAY_OP_SCAN_BACKWARD          (4)
-
-/*
- *  convert from msf format to block number 
- */
-#define SONY_BLOCK_NUMBER(m,s,f) (((m)*60L+(s))*75L+(f))
-#define SONY_BLOCK_NUMBER_MSF(x) (((x)[0]*60L+(x)[1])*75L+(x)[2])
-
-/*
- *  error return values from the doSonyCmd() routines
- */
-#define TIME_OUT                       (-1)
-#define NO_CDROM                       (-2)
-#define BAD_STATUS                     (-3)
-#define CD_BUSY                                (-4)
-#define NOT_DATA_CD                    (-5)
-#define NO_ROOM                                (-6)
-
-#define LOG_START_OFFSET        150     /* Offset of first logical sector */
-
-#define SONY_JIFFIES_TIMEOUT   (5*HZ)  /* Maximum time
-                                          the drive will wait/try for an
-                                          operation */
-#define SONY_READY_RETRIES      (50000)  /* How many times to retry a
-                                                  spin waiting for a register
-                                                  to come ready */
-#define SONY535_FAST_POLLS     (10000)   /* how many times recheck 
-                                                  status waiting for a data
-                                                  to become ready */
-
-typedef unsigned char Byte;
-
-/*
- * This is the complete status returned from the drive configuration request
- * command.
- */
-struct s535_sony_drive_config
-{
-   char vendor_id[8];
-   char product_id[16];
-   char product_rev_level[4];
-};
-
-/* The following is returned from the request sub-q data command */
-struct s535_sony_subcode
-{
-   unsigned char address        :4;
-   unsigned char control        :4;
-   unsigned char track_num;
-   unsigned char index_num;
-   unsigned char rel_msf[3];
-   unsigned char abs_msf[3];
-};
-
-struct s535_sony_disc_capacity
-{
-   Byte mFirstTrack, sFirstTrack, fFirstTrack;
-   Byte mLeadOut, sLeadOut, fLeadOut;
-};
-
-/*
- * The following is returned from the request TOC (Table Of Contents) command.
- * (last_track_num-first_track_num+1) values are valid in tracks.
- */
-struct s535_sony_toc
-{
-   unsigned char reserved0      :4;
-   unsigned char control0       :4;
-   unsigned char point0;
-   unsigned char first_track_num;
-   unsigned char reserved0a;
-   unsigned char reserved0b;
-   unsigned char reserved1      :4;
-   unsigned char control1       :4;
-   unsigned char point1;
-   unsigned char last_track_num;
-   unsigned char dummy1;
-   unsigned char dummy2;
-   unsigned char reserved2      :4;
-   unsigned char control2       :4;
-   unsigned char point2;
-   unsigned char lead_out_start_msf[3];
-   struct
-   {
-      unsigned char reserved    :4;
-      unsigned char control     :4;
-      unsigned char track;
-      unsigned char track_start_msf[3];
-   } tracks[100];
-
-   unsigned int lead_out_start_lba;
-};
-
-#endif /* SONYCD535_H */