ia64/xen-unstable

changeset 358:88dba60f48b3

bitkeeper revision 1.166 (3e9c248dVGQSFqCQP51wgrGBpJNZoA)

initial support for ide cdrom drives
author smh22@boulderdash.cl.cam.ac.uk
date Tue Apr 15 15:26:05 2003 +0000 (2003-04-15)
parents c9a8a90c8a96
children de7100b69ca1
files .rootkeys xen/Rules.mk xen/drivers/Makefile xen/drivers/block/ll_rw_blk.c xen/drivers/cdrom/Makefile xen/drivers/cdrom/cdrom.c xen/drivers/ide/ide-cd.c xen/drivers/ide/ide-cd.h xen/include/xeno/cdrom.h xenolinux-2.4.21-pre4-sparse/arch/xeno/defconfig
line diff
     1.1 --- a/.rootkeys	Mon Apr 14 16:31:59 2003 +0000
     1.2 +++ b/.rootkeys	Tue Apr 15 15:26:05 2003 +0000
     1.3 @@ -82,10 +82,14 @@ 3ddb79beNQVrdGyoI4njXhgAjD6a4A xen/drive
     1.4  3ddb79beyWwLRP_BiM2t1JKgr_plEw xen/drivers/block/ll_rw_blk.c
     1.5  3e4a8cb7RhubVgsPwO7cK0pgAN8WCQ xen/drivers/block/xen_block.c
     1.6  3e5d129asHNyZOjBKTkqs-9AFzxemA xen/drivers/block/xen_segment.c
     1.7 +3e9c248afxxsnAzIt2na7Ej24yNFzg xen/drivers/cdrom/Makefile
     1.8 +3e9c248ajUkn2W3n4vgm72Hp2ftZ8A xen/drivers/cdrom/cdrom.c
     1.9  3e4a8cb7alzQCDKS7MlioPoHBKYkdQ xen/drivers/char/Makefile
    1.10  3e4a8cb7WmiYdC-ASGiCSG_CL8vsqg xen/drivers/char/xen_kbd.c
    1.11  3e4a8cb7nMChlro4wvOBo76n__iCFA xen/drivers/char/xen_serial.c
    1.12  3ddb79bdhcqD9ebrslr0O0oHqTiiXg xen/drivers/ide/Makefile
    1.13 +3e9c248aCM6Lex1Am8_NJIeesN4kKg xen/drivers/ide/ide-cd.c
    1.14 +3e9c248aFfSNR_hl-WQBbv-R9CTgzg xen/drivers/ide/ide-cd.h
    1.15  3ddb79bdErDn_WC3G-fWxKNR3viLnA xen/drivers/ide/ide-disk.c
    1.16  3ddb79bdIPNW36FrlId94jTXaW8HoA xen/drivers/ide/ide-dma.c
    1.17  3ddb79be5Ysvhn4se_Z-LQY_hI6UPw xen/drivers/ide/ide-features.c
    1.18 @@ -276,6 +280,7 @@ 3ddb79c1VvNRMM35bpdZMekirCXP-A xen/inclu
    1.19  3ddb79c116WbJV8bwGZXFFJy_GNNvw xen/include/xeno/byteorder/swab.h
    1.20  3ddb79c1pwmlw8VXW8aaSKAVGVmjDA xen/include/xeno/byteorder/swabb.h
    1.21  3ddb79c0c0cX_DZE209-Bb-Rx1v-Aw xen/include/xeno/cache.h
    1.22 +3e9c248aEG_nCngztiFmv5CfayNkcA xen/include/xeno/cdrom.h
    1.23  3ddb79c259jh8hE7vre_8NuE7nwNSA xen/include/xeno/config.h
    1.24  3ddb79c1V44RD26YqCUm-kqIupM37A xen/include/xeno/ctype.h
    1.25  3ddb79c05DdHQ0UxX_jKsXdR4QlMCA xen/include/xeno/delay.h
     2.1 --- a/xen/Rules.mk	Mon Apr 14 16:31:59 2003 +0000
     2.2 +++ b/xen/Rules.mk	Tue Apr 15 15:26:05 2003 +0000
     2.3 @@ -19,6 +19,7 @@ ALL_OBJS += $(BASEDIR)/drivers/char/driv
     2.4  ALL_OBJS += $(BASEDIR)/drivers/pci/driver.o
     2.5  ALL_OBJS += $(BASEDIR)/drivers/net/driver.o
     2.6  ALL_OBJS += $(BASEDIR)/drivers/block/driver.o
     2.7 +ALL_OBJS += $(BASEDIR)/drivers/cdrom/driver.o
     2.8  ALL_OBJS += $(BASEDIR)/drivers/ide/driver.o
     2.9  ALL_OBJS += $(BASEDIR)/drivers/scsi/driver.o
    2.10  ALL_OBJS += $(BASEDIR)/arch/$(ARCH)/arch.o
     3.1 --- a/xen/drivers/Makefile	Mon Apr 14 16:31:59 2003 +0000
     3.2 +++ b/xen/drivers/Makefile	Tue Apr 15 15:26:05 2003 +0000
     3.3 @@ -4,6 +4,7 @@ default:
     3.4  	$(MAKE) -C pci
     3.5  	$(MAKE) -C net
     3.6  	$(MAKE) -C block
     3.7 +	$(MAKE) -C cdrom
     3.8  	$(MAKE) -C ide
     3.9  	$(MAKE) -C scsi
    3.10  
    3.11 @@ -12,5 +13,6 @@ clean:
    3.12  	$(MAKE) -C pci clean
    3.13  	$(MAKE) -C net clean
    3.14  	$(MAKE) -C block clean
    3.15 +	$(MAKE) -C cdrom clean
    3.16  	$(MAKE) -C ide clean
    3.17  	$(MAKE) -C scsi clean
     4.1 --- a/xen/drivers/block/ll_rw_blk.c	Mon Apr 14 16:31:59 2003 +0000
     4.2 +++ b/xen/drivers/block/ll_rw_blk.c	Tue Apr 15 15:26:05 2003 +0000
     4.3 @@ -40,7 +40,14 @@
     4.4  #endif
     4.5  
     4.6  /* This will die as all synchronous stuff is coming to an end */
     4.7 +#if 0 
     4.8  #define complete(_r) panic("completion.h stuff may be needed...")
     4.9 +#else
    4.10 +// XXX SMH: we spin when waiting for completion so just toggle flag 
    4.11 +#define complete(_r) (*(int *)(_r) = 0)
    4.12 +#endif
    4.13 +
    4.14 +
    4.15  
    4.16  /*
    4.17   * MAC Floppy IWM hooks
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/xen/drivers/cdrom/Makefile	Tue Apr 15 15:26:05 2003 +0000
     5.3 @@ -0,0 +1,7 @@
     5.4 +
     5.5 +include $(BASEDIR)/Rules.mk
     5.6 +
     5.7 +default: $(OBJS)
     5.8 +	$(LD) -r -o driver.o $(OBJS)
     5.9 +clean:
    5.10 +	rm -f *.o *~ core
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xen/drivers/cdrom/cdrom.c	Tue Apr 15 15:26:05 2003 +0000
     6.3 @@ -0,0 +1,2665 @@
     6.4 +/* linux/drivers/cdrom/cdrom.c. 
     6.5 +   Copyright (c) 1996, 1997 David A. van Leeuwen.
     6.6 +   Copyright (c) 1997, 1998 Erik Andersen <andersee@debian.org>
     6.7 +   Copyright (c) 1998, 1999 Jens Axboe <axboe@image.dk>
     6.8 +
     6.9 +   May be copied or modified under the terms of the GNU General Public
    6.10 +   License.  See linux/COPYING for more information.
    6.11 +
    6.12 +   Uniform CD-ROM driver for Linux.
    6.13 +   See Documentation/cdrom/cdrom-standard.tex for usage information.
    6.14 +
    6.15 +   The routines in the file provide a uniform interface between the
    6.16 +   software that uses CD-ROMs and the various low-level drivers that
    6.17 +   actually talk to the hardware. Suggestions are welcome.
    6.18 +   Patches that work are more welcome though.  ;-)
    6.19 +
    6.20 + To Do List:
    6.21 + ----------------------------------
    6.22 +
    6.23 + -- Modify sysctl/proc interface. I plan on having one directory per
    6.24 + drive, with entries for outputing general drive information, and sysctl
    6.25 + based tunable parameters such as whether the tray should auto-close for
    6.26 + that drive. Suggestions (or patches) for this welcome!
    6.27 +
    6.28 +
    6.29 + Revision History
    6.30 + ----------------------------------
    6.31 + 1.00  Date Unknown -- David van Leeuwen <david@tm.tno.nl>
    6.32 + -- Initial version by David A. van Leeuwen. I don't have a detailed
    6.33 +  changelog for the 1.x series, David?
    6.34 +
    6.35 +2.00  Dec  2, 1997 -- Erik Andersen <andersee@debian.org>
    6.36 +  -- New maintainer! As David A. van Leeuwen has been too busy to activly
    6.37 +  maintain and improve this driver, I am now carrying on the torch. If
    6.38 +  you have a problem with this driver, please feel free to contact me.
    6.39 +
    6.40 +  -- Added (rudimentary) sysctl interface. I realize this is really weak
    6.41 +  right now, and is _very_ badly implemented. It will be improved...
    6.42 +
    6.43 +  -- Modified CDROM_DISC_STATUS so that it is now incorporated into
    6.44 +  the Uniform CD-ROM driver via the cdrom_count_tracks function.
    6.45 +  The cdrom_count_tracks function helps resolve some of the false
    6.46 +  assumptions of the CDROM_DISC_STATUS ioctl, and is also used to check
    6.47 +  for the correct media type when mounting or playing audio from a CD.
    6.48 +
    6.49 +  -- Remove the calls to verify_area and only use the copy_from_user and
    6.50 +  copy_to_user stuff, since these calls now provide their own memory
    6.51 +  checking with the 2.1.x kernels.
    6.52 +
    6.53 +  -- Major update to return codes so that errors from low-level drivers
    6.54 +  are passed on through (thanks to Gerd Knorr for pointing out this
    6.55 +  problem).
    6.56 +
    6.57 +  -- Made it so if a function isn't implemented in a low-level driver,
    6.58 +  ENOSYS is now returned instead of EINVAL.
    6.59 +
    6.60 +  -- Simplified some complex logic so that the source code is easier to read.
    6.61 +
    6.62 +  -- Other stuff I probably forgot to mention (lots of changes).
    6.63 +
    6.64 +2.01 to 2.11 Dec 1997-Jan 1998
    6.65 +  -- TO-DO!  Write changelogs for 2.01 to 2.12.
    6.66 +
    6.67 +2.12  Jan  24, 1998 -- Erik Andersen <andersee@debian.org>
    6.68 +  -- Fixed a bug in the IOCTL_IN and IOCTL_OUT macros.  It turns out that
    6.69 +  copy_*_user does not return EFAULT on error, but instead returns the number 
    6.70 +  of bytes not copied.  I was returning whatever non-zero stuff came back from 
    6.71 +  the copy_*_user functions directly, which would result in strange errors.
    6.72 +
    6.73 +2.13  July 17, 1998 -- Erik Andersen <andersee@debian.org>
    6.74 +  -- Fixed a bug in CDROM_SELECT_SPEED where you couldn't lower the speed
    6.75 +  of the drive.  Thanks to Tobias Ringstr|m <tori@prosolvia.se> for pointing
    6.76 +  this out and providing a simple fix.
    6.77 +  -- Fixed the procfs-unload-module bug with the fill_inode procfs callback.
    6.78 +  thanks to Andrea Arcangeli
    6.79 +  -- Fixed it so that the /proc entry now also shows up when cdrom is
    6.80 +  compiled into the kernel.  Before it only worked when loaded as a module.
    6.81 +
    6.82 +  2.14 August 17, 1998 -- Erik Andersen <andersee@debian.org>
    6.83 +  -- Fixed a bug in cdrom_media_changed and handling of reporting that
    6.84 +  the media had changed for devices that _don't_ implement media_changed.  
    6.85 +  Thanks to Grant R. Guenther <grant@torque.net> for spotting this bug.
    6.86 +  -- Made a few things more pedanticly correct.
    6.87 +
    6.88 +2.50 Oct 19, 1998 - Jens Axboe <axboe@image.dk>
    6.89 +  -- New maintainers! Erik was too busy to continue the work on the driver,
    6.90 +  so now Chris Zwilling <chris@cloudnet.com> and Jens Axboe <axboe@image.dk>
    6.91 +  will do their best to follow in his footsteps
    6.92 +  
    6.93 +  2.51 Dec 20, 1998 - Jens Axboe <axboe@image.dk>
    6.94 +  -- Check if drive is capable of doing what we ask before blindly changing
    6.95 +  cdi->options in various ioctl.
    6.96 +  -- Added version to proc entry.
    6.97 +  
    6.98 +  2.52 Jan 16, 1999 - Jens Axboe <axboe@image.dk>
    6.99 +  -- Fixed an error in open_for_data where we would sometimes not return
   6.100 +  the correct error value. Thanks Huba Gaspar <huba@softcell.hu>.
   6.101 +  -- Fixed module usage count - usage was based on /proc/sys/dev
   6.102 +  instead of /proc/sys/dev/cdrom. This could lead to an oops when other
   6.103 +  modules had entries in dev. Feb 02 - real bug was in sysctl.c where
   6.104 +  dev would be removed even though it was used. cdrom.c just illuminated
   6.105 +  that bug.
   6.106 +  
   6.107 +  2.53 Feb 22, 1999 - Jens Axboe <axboe@image.dk>
   6.108 +  -- Fixup of several ioctl calls, in particular CDROM_SET_OPTIONS has
   6.109 +  been "rewritten" because capabilities and options aren't in sync. They
   6.110 +  should be...
   6.111 +  -- Added CDROM_LOCKDOOR ioctl. Locks the door and keeps it that way.
   6.112 +  -- Added CDROM_RESET ioctl.
   6.113 +  -- Added CDROM_DEBUG ioctl. Enable debug messages on-the-fly.
   6.114 +  -- Added CDROM_GET_CAPABILITY ioctl. This relieves userspace programs
   6.115 +  from parsing /proc/sys/dev/cdrom/info.
   6.116 +  
   6.117 +  2.54 Mar 15, 1999 - Jens Axboe <axboe@image.dk>
   6.118 +  -- Check capability mask from low level driver when counting tracks as
   6.119 +  per suggestion from Corey J. Scotts <cstotts@blue.weeg.uiowa.edu>.
   6.120 +  
   6.121 +  2.55 Apr 25, 1999 - Jens Axboe <axboe@image.dk>
   6.122 +  -- autoclose was mistakenly checked against CDC_OPEN_TRAY instead of
   6.123 +  CDC_CLOSE_TRAY.
   6.124 +  -- proc info didn't mask against capabilities mask.
   6.125 +  
   6.126 +  3.00 Aug 5, 1999 - Jens Axboe <axboe@image.dk>
   6.127 +  -- Unified audio ioctl handling across CD-ROM drivers. A lot of the
   6.128 +  code was duplicated before. Drives that support the generic packet
   6.129 +  interface are now being fed packets from here instead.
   6.130 +  -- First attempt at adding support for MMC2 commands - for DVD and
   6.131 +  CD-R(W) drives. Only the DVD parts are in now - the interface used is
   6.132 +  the same as for the audio ioctls.
   6.133 +  -- ioctl cleanups. if a drive couldn't play audio, it didn't get
   6.134 +  a change to perform device specific ioctls as well.
   6.135 +  -- Defined CDROM_CAN(CDC_XXX) for checking the capabilities.
   6.136 +  -- Put in sysctl files for autoclose, autoeject, check_media, debug,
   6.137 +  and lock.
   6.138 +  -- /proc/sys/dev/cdrom/info has been updated to also contain info about
   6.139 +  CD-Rx and DVD capabilities.
   6.140 +  -- Now default to checking media type.
   6.141 +  -- CDROM_SEND_PACKET ioctl added. The infrastructure was in place for
   6.142 +  doing this anyway, with the generic_packet addition.
   6.143 +  
   6.144 +  3.01 Aug 6, 1999 - Jens Axboe <axboe@image.dk>
   6.145 +  -- Fix up the sysctl handling so that the option flags get set
   6.146 +  correctly.
   6.147 +  -- Fix up ioctl handling so the device specific ones actually get
   6.148 +  called :).
   6.149 +  
   6.150 +  3.02 Aug 8, 1999 - Jens Axboe <axboe@image.dk>
   6.151 +  -- Fixed volume control on SCSI drives (or others with longer audio
   6.152 +  page).
   6.153 +  -- Fixed a couple of DVD minors. Thanks to Andrew T. Veliath
   6.154 +  <andrewtv@usa.net> for telling me and for having defined the various
   6.155 +  DVD structures and ioctls in the first place! He designed the original
   6.156 +  DVD patches for ide-cd and while I rearranged and unified them, the
   6.157 +  interface is still the same.
   6.158 +  
   6.159 +  3.03 Sep 1, 1999 - Jens Axboe <axboe@image.dk>
   6.160 +  -- Moved the rest of the audio ioctls from the CD-ROM drivers here. Only
   6.161 +  CDROMREADTOCENTRY and CDROMREADTOCHDR are left.
   6.162 +  -- Moved the CDROMREADxxx ioctls in here.
   6.163 +  -- Defined the cdrom_get_last_written and cdrom_get_next_block as ioctls
   6.164 +  and exported functions.
   6.165 +  -- Erik Andersen <andersen@xmission.com> modified all SCMD_ commands
   6.166 +  to now read GPCMD_ for the new generic packet interface. All low level
   6.167 +  drivers are updated as well.
   6.168 +  -- Various other cleanups.
   6.169 +
   6.170 +  3.04 Sep 12, 1999 - Jens Axboe <axboe@image.dk>
   6.171 +  -- Fixed a couple of possible memory leaks (if an operation failed and
   6.172 +  we didn't free the buffer before returning the error).
   6.173 +  -- Integrated Uniform CD Changer handling from Richard Sharman
   6.174 +  <rsharman@pobox.com>.
   6.175 +  -- Defined CD_DVD and CD_CHANGER log levels.
   6.176 +  -- Fixed the CDROMREADxxx ioctls.
   6.177 +  -- CDROMPLAYTRKIND uses the GPCMD_PLAY_AUDIO_MSF command - too few
   6.178 +  drives supported it. We loose the index part, however.
   6.179 +  -- Small modifications to accomodate opens of /dev/hdc1, required
   6.180 +  for ide-cd to handle multisession discs.
   6.181 +  -- Export cdrom_mode_sense and cdrom_mode_select.
   6.182 +  -- init_cdrom_command() for setting up a cgc command.
   6.183 +  
   6.184 +  3.05 Oct 24, 1999 - Jens Axboe <axboe@image.dk>
   6.185 +  -- Changed the interface for CDROM_SEND_PACKET. Before it was virtually
   6.186 +  impossible to send the drive data in a sensible way.
   6.187 +  -- Lowered stack usage in mmc_ioctl(), dvd_read_disckey(), and
   6.188 +  dvd_read_manufact.
   6.189 +  -- Added setup of write mode for packet writing.
   6.190 +  -- Fixed CDDA ripping with cdda2wav - accept much larger requests of
   6.191 +  number of frames and split the reads in blocks of 8.
   6.192 +
   6.193 +  3.06 Dec 13, 1999 - Jens Axboe <axboe@image.dk>
   6.194 +  -- Added support for changing the region of DVD drives.
   6.195 +  -- Added sense data to generic command.
   6.196 +
   6.197 +  3.07 Feb 2, 2000 - Jens Axboe <axboe@suse.de>
   6.198 +  -- Do same "read header length" trick in cdrom_get_disc_info() as
   6.199 +  we do in cdrom_get_track_info() -- some drive don't obey specs and
   6.200 +  fail if they can't supply the full Mt Fuji size table.
   6.201 +  -- Deleted stuff related to setting up write modes. It has a different
   6.202 +  home now.
   6.203 +  -- Clear header length in mode_select unconditionally.
   6.204 +  -- Removed the register_disk() that was added, not needed here.
   6.205 +
   6.206 +  3.08 May 1, 2000 - Jens Axboe <axboe@suse.de>
   6.207 +  -- Fix direction flag in setup_send_key and setup_report_key. This
   6.208 +  gave some SCSI adapters problems.
   6.209 +  -- Always return -EROFS for write opens
   6.210 +  -- Convert to module_init/module_exit style init and remove some
   6.211 +  of the #ifdef MODULE stuff
   6.212 +  -- Fix several dvd errors - DVD_LU_SEND_ASF should pass agid,
   6.213 +  DVD_HOST_SEND_RPC_STATE did not set buffer size in cdb, and
   6.214 +  dvd_do_auth passed uninitialized data to drive because init_cdrom_command
   6.215 +  did not clear a 0 sized buffer.
   6.216 +  
   6.217 +  3.09 May 12, 2000 - Jens Axboe <axboe@suse.de>
   6.218 +  -- Fix Video-CD on SCSI drives that don't support READ_CD command. In
   6.219 +  that case switch block size and issue plain READ_10 again, then switch
   6.220 +  back.
   6.221 +
   6.222 +  3.10 Jun 10, 2000 - Jens Axboe <axboe@suse.de>
   6.223 +  -- Fix volume control on CD's - old SCSI-II drives now use their own
   6.224 +  code, as doing MODE6 stuff in here is really not my intention.
   6.225 +  -- Use READ_DISC_INFO for more reliable end-of-disc.
   6.226 +
   6.227 +  3.11 Jun 12, 2000 - Jens Axboe <axboe@suse.de>
   6.228 +  -- Fix bug in getting rpc phase 2 region info.
   6.229 +  -- Reinstate "correct" CDROMPLAYTRKIND
   6.230 +
   6.231 +   3.12 Oct 18, 2000 - Jens Axboe <axboe@suse.de>
   6.232 +  -- Use quiet bit on packet commands not known to work
   6.233 +
   6.234 +-------------------------------------------------------------------------*/
   6.235 +
   6.236 +#define REVISION "Revision: 3.12"
   6.237 +#define VERSION "Id: cdrom.c 3.12 2000/10/18"
   6.238 +
   6.239 +/* I use an error-log mask to give fine grain control over the type of
   6.240 +   messages dumped to the system logs.  The available masks include: */
   6.241 +#define CD_NOTHING      0x0
   6.242 +#define CD_WARNING	0x1
   6.243 +#define CD_REG_UNREG	0x2
   6.244 +#define CD_DO_IOCTL	0x4
   6.245 +#define CD_OPEN		0x8
   6.246 +#define CD_CLOSE	0x10
   6.247 +#define CD_COUNT_TRACKS 0x20
   6.248 +#define CD_CHANGER	0x40
   6.249 +#define CD_DVD		0x80
   6.250 +
   6.251 +/* Define this to remove _all_ the debugging messages */
   6.252 +/* #define ERRLOGMASK CD_NOTHING */
   6.253 +#define ERRLOGMASK (CD_WARNING)
   6.254 +/* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_COUNT_TRACKS|CD_CLOSE) */
   6.255 +/* #define ERRLOGMASK (CD_WARNING|CD_REG_UNREG|CD_DO_IOCTL|CD_OPEN|CD_CLOSE|CD_COUNT_TRACKS) */
   6.256 +
   6.257 +#include <xeno/config.h>
   6.258 +#include <xeno/module.h>
   6.259 +/* #include <xeno/fs.h> */
   6.260 +#include <xeno/major.h>
   6.261 +#include <xeno/types.h>
   6.262 +#include <xeno/errno.h>
   6.263 +#include <xeno/kernel.h>
   6.264 +#include <xeno/mm.h>
   6.265 +#include <xeno/slab.h> 
   6.266 +#include <xeno/cdrom.h>
   6.267 +/* #include <xeno/sysctl.h> */
   6.268 +/* #include <xeno/proc_fs.h> */
   6.269 +#include <xeno/init.h>
   6.270 +
   6.271 +/* #include <asm/fcntl.h> */
   6.272 +/* #include <asm/segment.h> */
   6.273 +#include <asm/uaccess.h>
   6.274 +
   6.275 +/* used to tell the module to turn on full debugging messages */
   6.276 +static int debug;
   6.277 +/* used to keep tray locked at all times */
   6.278 +static int keeplocked;
   6.279 +/* default compatibility mode */
   6.280 +static int autoclose=1;
   6.281 +static int autoeject;
   6.282 +static int lockdoor = 1;
   6.283 +/* will we ever get to use this... sigh. */
   6.284 +static int check_media_type;
   6.285 +MODULE_PARM(debug, "i");
   6.286 +MODULE_PARM(autoclose, "i");
   6.287 +MODULE_PARM(autoeject, "i");
   6.288 +MODULE_PARM(lockdoor, "i");
   6.289 +MODULE_PARM(check_media_type, "i");
   6.290 +
   6.291 +#if (ERRLOGMASK!=CD_NOTHING)
   6.292 +#define cdinfo(type, fmt, args...) \
   6.293 +        if ((ERRLOGMASK & type) || debug==1 ) \
   6.294 +            printk(KERN_INFO "cdrom: " fmt, ## args)
   6.295 +#else
   6.296 +#define cdinfo(type, fmt, args...) 
   6.297 +#endif
   6.298 +
   6.299 +/* These are used to simplify getting data in from and back to user land */
   6.300 +#define IOCTL_IN(arg, type, in)					\
   6.301 +	if (copy_from_user(&(in), (type *) (arg), sizeof (in)))	\
   6.302 +		return -EFAULT;
   6.303 +
   6.304 +#define IOCTL_OUT(arg, type, out) \
   6.305 +	if (copy_to_user((type *) (arg), &(out), sizeof (out)))	\
   6.306 +		return -EFAULT;
   6.307 +
   6.308 +/* The (cdo->capability & ~cdi->mask & CDC_XXX) construct was used in
   6.309 +   a lot of places. This macro makes the code more clear. */
   6.310 +#define CDROM_CAN(type) (cdi->ops->capability & ~cdi->mask & (type))
   6.311 +
   6.312 +/* used in the audio ioctls */
   6.313 +#define CHECKAUDIO if ((ret=check_for_audio_disc(cdi, cdo))) return ret
   6.314 +
   6.315 +/* Not-exported routines. */
   6.316 +static int open_for_data(struct cdrom_device_info * cdi);
   6.317 +static int check_for_audio_disc(struct cdrom_device_info * cdi,
   6.318 +			 struct cdrom_device_ops * cdo);
   6.319 +static void sanitize_format(union cdrom_addr *addr, 
   6.320 +		u_char * curr, u_char requested);
   6.321 +static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
   6.322 +		     unsigned long arg);
   6.323 +
   6.324 +int cdrom_get_last_written(kdev_t dev, long *last_written);
   6.325 +int cdrom_get_next_writable(kdev_t dev, long *next_writable);
   6.326 +
   6.327 +#ifdef CONFIG_SYSCTL
   6.328 +static void cdrom_sysctl_register(void);
   6.329 +#endif /* CONFIG_SYSCTL */ 
   6.330 +static struct cdrom_device_info *topCdromPtr;
   6.331 +#if 0
   6.332 +static devfs_handle_t devfs_handle;
   6.333 +static struct unique_numspace cdrom_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
   6.334 +#endif
   6.335 +
   6.336 +/* This macro makes sure we don't have to check on cdrom_device_ops
   6.337 + * existence in the run-time routines below. Change_capability is a
   6.338 + * hack to have the capability flags defined const, while we can still
   6.339 + * change it here without gcc complaining at every line.
   6.340 + */
   6.341 +#define ENSURE(call, bits) if (cdo->call == NULL) *change_capability &= ~(bits)
   6.342 +
   6.343 +int register_cdrom(struct cdrom_device_info *cdi)
   6.344 +{
   6.345 +	static char banner_printed;
   6.346 +	int major = MAJOR(cdi->dev);
   6.347 +        struct cdrom_device_ops *cdo = cdi->ops;
   6.348 +        int *change_capability = (int *)&cdo->capability; /* hack */
   6.349 +
   6.350 +	cdinfo(CD_OPEN, "entering register_cdrom\n"); 
   6.351 +
   6.352 +	if (major < 0 || major >= MAX_BLKDEV)
   6.353 +		return -1;
   6.354 +	if (cdo->open == NULL || cdo->release == NULL)
   6.355 +		return -2;
   6.356 +	if ( !banner_printed ) {
   6.357 +		printk(KERN_INFO "Uniform CD-ROM driver " REVISION "\n");
   6.358 +		banner_printed = 1;
   6.359 +#ifdef CONFIG_SYSCTL
   6.360 +		cdrom_sysctl_register();
   6.361 +#endif /* CONFIG_SYSCTL */ 
   6.362 +	}
   6.363 +	ENSURE(drive_status, CDC_DRIVE_STATUS );
   6.364 +	ENSURE(media_changed, CDC_MEDIA_CHANGED);
   6.365 +	ENSURE(tray_move, CDC_CLOSE_TRAY | CDC_OPEN_TRAY);
   6.366 +	ENSURE(lock_door, CDC_LOCK);
   6.367 +	ENSURE(select_speed, CDC_SELECT_SPEED);
   6.368 +	ENSURE(get_last_session, CDC_MULTI_SESSION);
   6.369 +	ENSURE(get_mcn, CDC_MCN);
   6.370 +	ENSURE(reset, CDC_RESET);
   6.371 +	ENSURE(audio_ioctl, CDC_PLAY_AUDIO);
   6.372 +	ENSURE(dev_ioctl, CDC_IOCTLS);
   6.373 +	ENSURE(generic_packet, CDC_GENERIC_PACKET);
   6.374 +	cdi->mc_flags = 0;
   6.375 +	cdo->n_minors = 0;
   6.376 +        cdi->options = CDO_USE_FFLAGS;
   6.377 +	
   6.378 +	if (autoclose==1 && CDROM_CAN(CDC_CLOSE_TRAY))
   6.379 +		cdi->options |= (int) CDO_AUTO_CLOSE;
   6.380 +	if (autoeject==1 && CDROM_CAN(CDC_OPEN_TRAY))
   6.381 +		cdi->options |= (int) CDO_AUTO_EJECT;
   6.382 +	if (lockdoor==1)
   6.383 +		cdi->options |= (int) CDO_LOCK;
   6.384 +	if (check_media_type==1)
   6.385 +		cdi->options |= (int) CDO_CHECK_TYPE;
   6.386 +#if 0
   6.387 +	if (!devfs_handle)
   6.388 +		devfs_handle = devfs_mk_dir (NULL, "cdroms", NULL);
   6.389 +	cdi->number = devfs_alloc_unique_number (&cdrom_numspace);
   6.390 +	if (cdi->de) {
   6.391 +		int pos;
   6.392 +		devfs_handle_t slave;
   6.393 +		char rname[64];
   6.394 +
   6.395 +		pos = devfs_generate_path (cdi->de, rname + 3,
   6.396 +					   sizeof rname - 3);
   6.397 +		if (pos >= 0) {
   6.398 +			char vname[16];
   6.399 +			sprintf (vname, "cdrom%d", cdi->number);
   6.400 +			strncpy (rname + pos, "../", 3);
   6.401 +			devfs_mk_symlink (devfs_handle, vname,
   6.402 +					  DEVFS_FL_DEFAULT,
   6.403 +					  rname + pos, &slave, NULL);
   6.404 +			devfs_auto_unregister (cdi->de, slave);
   6.405 +		}
   6.406 +	}
   6.407 +#endif
   6.408 +	cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
   6.409 +	cdi->next = topCdromPtr; 	
   6.410 +	topCdromPtr = cdi;
   6.411 +	return 0;
   6.412 +}
   6.413 +#undef ENSURE
   6.414 +
   6.415 +int unregister_cdrom(struct cdrom_device_info *unreg)
   6.416 +{
   6.417 +	struct cdrom_device_info *cdi, *prev;
   6.418 +	int major = MAJOR(unreg->dev);
   6.419 +
   6.420 +	cdinfo(CD_OPEN, "entering unregister_cdrom\n"); 
   6.421 +
   6.422 +	if (major < 0 || major >= MAX_BLKDEV)
   6.423 +		return -1;
   6.424 +
   6.425 +	prev = NULL;
   6.426 +	cdi = topCdromPtr;
   6.427 +	while (cdi != NULL && cdi->dev != unreg->dev) {
   6.428 +		prev = cdi;
   6.429 +		cdi = cdi->next;
   6.430 +	}
   6.431 +
   6.432 +	if (cdi == NULL)
   6.433 +		return -2;
   6.434 +	if (prev)
   6.435 +		prev->next = cdi->next;
   6.436 +	else
   6.437 +		topCdromPtr = cdi->next;
   6.438 +	cdi->ops->n_minors--;
   6.439 +#if 0
   6.440 +	devfs_unregister (cdi->de);
   6.441 +	devfs_dealloc_unique_number (&cdrom_numspace, cdi->number);
   6.442 +#endif
   6.443 +	cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
   6.444 +	return 0;
   6.445 +}
   6.446 +
   6.447 +struct cdrom_device_info *cdrom_find_device(kdev_t dev)
   6.448 +{
   6.449 +	struct cdrom_device_info *cdi;
   6.450 +
   6.451 +	cdi = topCdromPtr;
   6.452 +	while (cdi != NULL && cdi->dev != dev)
   6.453 +		cdi = cdi->next;
   6.454 +
   6.455 +	return cdi;
   6.456 +}
   6.457 +
   6.458 +/* We use the open-option O_NONBLOCK to indicate that the
   6.459 + * purpose of opening is only for subsequent ioctl() calls; no device
   6.460 + * integrity checks are performed.
   6.461 + *
   6.462 + * We hope that all cd-player programs will adopt this convention. It
   6.463 + * is in their own interest: device control becomes a lot easier
   6.464 + * this way.
   6.465 + */
   6.466 +int cdrom_open(struct inode *ip, struct file *fp)
   6.467 +{
   6.468 +	struct cdrom_device_info *cdi;
   6.469 +	kdev_t dev = ip->i_rdev;
   6.470 +	int ret;
   6.471 +
   6.472 +	cdinfo(CD_OPEN, "entering cdrom_open\n"); 
   6.473 +	if ((cdi = cdrom_find_device(dev)) == NULL)
   6.474 +		return -ENODEV;
   6.475 +
   6.476 +#if 0
   6.477 +	if ((fp->f_mode & FMODE_WRITE) && !CDROM_CAN(CDC_DVD_RAM))
   6.478 +		return -EROFS;
   6.479 +
   6.480 +	/* if this was a O_NONBLOCK open and we should honor the flags,
   6.481 +	 * do a quick open without drive/disc integrity checks. */
   6.482 +	if ((fp->f_flags & O_NONBLOCK) && (cdi->options & CDO_USE_FFLAGS))
   6.483 +		ret = cdi->ops->open(cdi, 1);
   6.484 +	else
   6.485 +		ret = open_for_data(cdi);
   6.486 +#else 
   6.487 +	ret = open_for_data(cdi);
   6.488 +#endif
   6.489 +
   6.490 +	if (!ret) cdi->use_count++;
   6.491 +
   6.492 +	cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n", cdi->name, cdi->use_count);
   6.493 +	/* Do this on open.  Don't wait for mount, because they might
   6.494 +	    not be mounting, but opening with O_NONBLOCK */
   6.495 +	check_disk_change(dev);
   6.496 +	return ret;
   6.497 +}
   6.498 +
   6.499 +static
   6.500 +int open_for_data(struct cdrom_device_info * cdi)
   6.501 +{
   6.502 +	int ret;
   6.503 +	struct cdrom_device_ops *cdo = cdi->ops;
   6.504 +	tracktype tracks;
   6.505 +	cdinfo(CD_OPEN, "entering open_for_data\n");
   6.506 +	/* Check if the driver can report drive status.  If it can, we
   6.507 +	   can do clever things.  If it can't, well, we at least tried! */
   6.508 +	if (cdo->drive_status != NULL) {
   6.509 +		ret = cdo->drive_status(cdi, CDSL_CURRENT);
   6.510 +		cdinfo(CD_OPEN, "drive_status=%d\n", ret); 
   6.511 +		if (ret == CDS_TRAY_OPEN) {
   6.512 +			cdinfo(CD_OPEN, "the tray is open...\n"); 
   6.513 +			/* can/may i close it? */
   6.514 +			if (CDROM_CAN(CDC_CLOSE_TRAY) &&
   6.515 +			    cdi->options & CDO_AUTO_CLOSE) {
   6.516 +				cdinfo(CD_OPEN, "trying to close the tray.\n"); 
   6.517 +				ret=cdo->tray_move(cdi,0);
   6.518 +				if (ret) {
   6.519 +					cdinfo(CD_OPEN, "bummer. tried to close the tray but failed.\n"); 
   6.520 +					/* Ignore the error from the low
   6.521 +					level driver.  We don't care why it
   6.522 +					couldn't close the tray.  We only care 
   6.523 +					that there is no disc in the drive, 
   6.524 +					since that is the _REAL_ problem here.*/
   6.525 +					ret=-ENOMEDIUM;
   6.526 +					goto clean_up_and_return;
   6.527 +				}
   6.528 +			} else {
   6.529 +				cdinfo(CD_OPEN, "bummer. this drive can't close the tray.\n"); 
   6.530 +				ret=-ENOMEDIUM;
   6.531 +				goto clean_up_and_return;
   6.532 +			}
   6.533 +			/* Ok, the door should be closed now.. Check again */
   6.534 +			ret = cdo->drive_status(cdi, CDSL_CURRENT);
   6.535 +			if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) {
   6.536 +				cdinfo(CD_OPEN, "bummer. the tray is still not closed.\n"); 
   6.537 +				cdinfo(CD_OPEN, "tray might not contain a medium.\n");
   6.538 +				ret=-ENOMEDIUM;
   6.539 +				goto clean_up_and_return;
   6.540 +			}
   6.541 +			cdinfo(CD_OPEN, "the tray is now closed.\n"); 
   6.542 +		}
   6.543 +		if (ret!=CDS_DISC_OK) {
   6.544 +			ret = -ENOMEDIUM;
   6.545 +			goto clean_up_and_return;
   6.546 +		}
   6.547 +	}
   6.548 +	cdrom_count_tracks(cdi, &tracks);
   6.549 +	if (tracks.error == CDS_NO_DISC) {
   6.550 +		cdinfo(CD_OPEN, "bummer. no disc.\n");
   6.551 +		ret=-ENOMEDIUM;
   6.552 +		goto clean_up_and_return;
   6.553 +	}
   6.554 +	/* CD-Players which don't use O_NONBLOCK, workman
   6.555 +	 * for example, need bit CDO_CHECK_TYPE cleared! */
   6.556 +	if (tracks.data==0) {
   6.557 +		if (cdi->options & CDO_CHECK_TYPE) {
   6.558 +		    /* give people a warning shot, now that CDO_CHECK_TYPE
   6.559 +		       is the default case! */
   6.560 +		    cdinfo(CD_OPEN, "bummer. wrong media type.\n"); 
   6.561 +#if 0
   6.562 +		    cdinfo(CD_WARNING, "pid %d must open device O_NONBLOCK!\n",
   6.563 +					(unsigned int)current->pid); 
   6.564 +#else
   6.565 +		    cdinfo(CD_WARNING, "xen must open device O_NONBLOCK!\n"); 
   6.566 +#endif
   6.567 +		    ret=-EMEDIUMTYPE;
   6.568 +		    goto clean_up_and_return;
   6.569 +		}
   6.570 +		else {
   6.571 +		    cdinfo(CD_OPEN, "wrong media type, but CDO_CHECK_TYPE not set.\n");
   6.572 +		}
   6.573 +	}
   6.574 +
   6.575 +	cdinfo(CD_OPEN, "all seems well, opening the device.\n"); 
   6.576 +
   6.577 +	/* all seems well, we can open the device */
   6.578 +	ret = cdo->open(cdi, 0); /* open for data */
   6.579 +	cdinfo(CD_OPEN, "opening the device gave me %d.\n", ret); 
   6.580 +	/* After all this careful checking, we shouldn't have problems
   6.581 +	   opening the device, but we don't want the device locked if 
   6.582 +	   this somehow fails... */
   6.583 +	if (ret) {
   6.584 +		cdinfo(CD_OPEN, "open device failed.\n"); 
   6.585 +		goto clean_up_and_return;
   6.586 +	}
   6.587 +	if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
   6.588 +			cdo->lock_door(cdi, 1);
   6.589 +			cdinfo(CD_OPEN, "door locked.\n");
   6.590 +	}
   6.591 +	cdinfo(CD_OPEN, "device opened successfully.\n"); 
   6.592 +	return ret;
   6.593 +
   6.594 +	/* Something failed.  Try to unlock the drive, because some drivers
   6.595 +	(notably ide-cd) lock the drive after every command.  This produced
   6.596 +	a nasty bug where after mount failed, the drive would remain locked!  
   6.597 +	This ensures that the drive gets unlocked after a mount fails.  This 
   6.598 +	is a goto to avoid bloating the driver with redundant code. */ 
   6.599 +clean_up_and_return:
   6.600 +	cdinfo(CD_WARNING, "open failed.\n"); 
   6.601 +	if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
   6.602 +			cdo->lock_door(cdi, 0);
   6.603 +			cdinfo(CD_OPEN, "door unlocked.\n");
   6.604 +	}
   6.605 +	return ret;
   6.606 +}
   6.607 +
   6.608 +/* This code is similar to that in open_for_data. The routine is called
   6.609 +   whenever an audio play operation is requested.
   6.610 +*/
   6.611 +int check_for_audio_disc(struct cdrom_device_info * cdi,
   6.612 +			 struct cdrom_device_ops * cdo)
   6.613 +{
   6.614 +        int ret;
   6.615 +	tracktype tracks;
   6.616 +	cdinfo(CD_OPEN, "entering check_for_audio_disc\n");
   6.617 +	if (!(cdi->options & CDO_CHECK_TYPE))
   6.618 +		return 0;
   6.619 +	if (cdo->drive_status != NULL) {
   6.620 +		ret = cdo->drive_status(cdi, CDSL_CURRENT);
   6.621 +		cdinfo(CD_OPEN, "drive_status=%d\n", ret); 
   6.622 +		if (ret == CDS_TRAY_OPEN) {
   6.623 +			cdinfo(CD_OPEN, "the tray is open...\n"); 
   6.624 +			/* can/may i close it? */
   6.625 +			if (CDROM_CAN(CDC_CLOSE_TRAY) &&
   6.626 +			    cdi->options & CDO_AUTO_CLOSE) {
   6.627 +				cdinfo(CD_OPEN, "trying to close the tray.\n"); 
   6.628 +				ret=cdo->tray_move(cdi,0);
   6.629 +				if (ret) {
   6.630 +					cdinfo(CD_OPEN, "bummer. tried to close tray but failed.\n"); 
   6.631 +					/* Ignore the error from the low
   6.632 +					level driver.  We don't care why it
   6.633 +					couldn't close the tray.  We only care 
   6.634 +					that there is no disc in the drive, 
   6.635 +					since that is the _REAL_ problem here.*/
   6.636 +					return -ENOMEDIUM;
   6.637 +				}
   6.638 +			} else {
   6.639 +				cdinfo(CD_OPEN, "bummer. this driver can't close the tray.\n"); 
   6.640 +				return -ENOMEDIUM;
   6.641 +			}
   6.642 +			/* Ok, the door should be closed now.. Check again */
   6.643 +			ret = cdo->drive_status(cdi, CDSL_CURRENT);
   6.644 +			if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) {
   6.645 +				cdinfo(CD_OPEN, "bummer. the tray is still not closed.\n"); 
   6.646 +				return -ENOMEDIUM;
   6.647 +			}	
   6.648 +			if (ret!=CDS_DISC_OK) {
   6.649 +				cdinfo(CD_OPEN, "bummer. disc isn't ready.\n"); 
   6.650 +				return -EIO;
   6.651 +			}	
   6.652 +			cdinfo(CD_OPEN, "the tray is now closed.\n"); 
   6.653 +		}	
   6.654 +	}
   6.655 +	cdrom_count_tracks(cdi, &tracks);
   6.656 +	if (tracks.error) 
   6.657 +		return(tracks.error);
   6.658 +
   6.659 +	if (tracks.audio==0)
   6.660 +		return -EMEDIUMTYPE;
   6.661 +
   6.662 +	return 0;
   6.663 +}
   6.664 +
   6.665 +
   6.666 +/* Admittedly, the logic below could be performed in a nicer way. */
   6.667 +int cdrom_release(struct inode *ip, struct file *fp)
   6.668 +{
   6.669 +	kdev_t dev = ip->i_rdev;
   6.670 +	struct cdrom_device_info *cdi = cdrom_find_device(dev);
   6.671 +	struct cdrom_device_ops *cdo = cdi->ops;
   6.672 +	int opened_for_data;
   6.673 +
   6.674 +	cdinfo(CD_CLOSE, "entering cdrom_release\n"); 
   6.675 +
   6.676 +	if (cdi->use_count > 0)
   6.677 +		cdi->use_count--;
   6.678 +	if (cdi->use_count == 0)
   6.679 +		cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);
   6.680 +	if (cdi->use_count == 0 &&
   6.681 +	    cdo->capability & CDC_LOCK && !keeplocked) {
   6.682 +		cdinfo(CD_CLOSE, "Unlocking door!\n");
   6.683 +		cdo->lock_door(cdi, 0);
   6.684 +	}
   6.685 +#if 0
   6.686 +	opened_for_data = !(cdi->options & CDO_USE_FFLAGS) ||
   6.687 +		!(fp && fp->f_flags & O_NONBLOCK);
   6.688 +#else 
   6.689 +	opened_for_data = 1; /* XXX SMH: guess */
   6.690 +#endif
   6.691 +	cdo->release(cdi);
   6.692 +	if (cdi->use_count == 0) {      /* last process that closes dev*/
   6.693 +		if (opened_for_data &&
   6.694 +		    cdi->options & CDO_AUTO_EJECT && CDROM_CAN(CDC_OPEN_TRAY))
   6.695 +			cdo->tray_move(cdi, 1);
   6.696 +	}
   6.697 +	return 0;
   6.698 +}
   6.699 +
   6.700 +static int cdrom_read_mech_status(struct cdrom_device_info *cdi, 
   6.701 +				  struct cdrom_changer_info *buf)
   6.702 +{
   6.703 +	struct cdrom_generic_command cgc;
   6.704 +	struct cdrom_device_ops *cdo = cdi->ops;
   6.705 +	int length;
   6.706 +
   6.707 +	/*
   6.708 +	 * Sanyo changer isn't spec compliant (doesn't use regular change
   6.709 +	 * LOAD_UNLOAD command, and it doesn't implement the mech status
   6.710 +	 * command below
   6.711 +	 */
   6.712 +	if (cdi->sanyo_slot) {
   6.713 +		buf->hdr.nslots = 3;
   6.714 +		buf->hdr.curslot = cdi->sanyo_slot == 3 ? 0 : cdi->sanyo_slot;
   6.715 +		for (length = 0; length < 3; length++) {
   6.716 +			buf->slots[length].disc_present = 1;
   6.717 +			buf->slots[length].change = 0;
   6.718 +		}
   6.719 +		return 0;
   6.720 +	}
   6.721 +
   6.722 +	length = sizeof(struct cdrom_mechstat_header) +
   6.723 +		 cdi->capacity * sizeof(struct cdrom_slot);
   6.724 +
   6.725 +	init_cdrom_command(&cgc, buf, length, CGC_DATA_READ);
   6.726 +	cgc.cmd[0] = GPCMD_MECHANISM_STATUS;
   6.727 +	cgc.cmd[8] = (length >> 8) & 0xff;
   6.728 +	cgc.cmd[9] = length & 0xff;
   6.729 +	return cdo->generic_packet(cdi, &cgc);
   6.730 +}
   6.731 +
   6.732 +static int cdrom_slot_status(struct cdrom_device_info *cdi, int slot)
   6.733 +{
   6.734 +	struct cdrom_changer_info info;
   6.735 +	int ret;
   6.736 +
   6.737 +	cdinfo(CD_CHANGER, "entering cdrom_slot_status()\n"); 
   6.738 +	if (cdi->sanyo_slot)
   6.739 +		return CDS_NO_INFO;
   6.740 +	
   6.741 +	if ((ret = cdrom_read_mech_status(cdi, &info)))
   6.742 +		return ret;
   6.743 +
   6.744 +	if (info.slots[slot].disc_present)
   6.745 +		return CDS_DISC_OK;
   6.746 +	else
   6.747 +		return CDS_NO_DISC;
   6.748 +
   6.749 +}
   6.750 +
   6.751 +/* Return the number of slots for an ATAPI/SCSI cdrom, 
   6.752 + * return 1 if not a changer. 
   6.753 + */
   6.754 +int cdrom_number_of_slots(struct cdrom_device_info *cdi) 
   6.755 +{
   6.756 +	int status;
   6.757 +	int nslots = 1;
   6.758 +	struct cdrom_changer_info info;
   6.759 +
   6.760 +	cdinfo(CD_CHANGER, "entering cdrom_number_of_slots()\n"); 
   6.761 +	/* cdrom_read_mech_status requires a valid value for capacity: */
   6.762 +	cdi->capacity = 0; 
   6.763 +
   6.764 +	if ((status = cdrom_read_mech_status(cdi, &info)) == 0)
   6.765 +		nslots = info.hdr.nslots;
   6.766 +
   6.767 +	return nslots;
   6.768 +}
   6.769 +
   6.770 +
   6.771 +/* If SLOT < 0, unload the current slot.  Otherwise, try to load SLOT. */
   6.772 +static int cdrom_load_unload(struct cdrom_device_info *cdi, int slot) 
   6.773 +{
   6.774 +	struct cdrom_generic_command cgc;
   6.775 +
   6.776 +	cdinfo(CD_CHANGER, "entering cdrom_load_unload()\n"); 
   6.777 +	if (cdi->sanyo_slot && slot < 0)
   6.778 +		return 0;
   6.779 +
   6.780 +	init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
   6.781 +	cgc.cmd[0] = GPCMD_LOAD_UNLOAD;
   6.782 +	cgc.cmd[4] = 2 + (slot >= 0);
   6.783 +	cgc.cmd[8] = slot;
   6.784 +
   6.785 +	/* The Sanyo 3 CD changer uses byte 7 of the 
   6.786 +	GPCMD_TEST_UNIT_READY to command to switch CDs instead of
   6.787 +	using the GPCMD_LOAD_UNLOAD opcode. */
   6.788 +	if (cdi->sanyo_slot && -1 < slot) {
   6.789 +		cgc.cmd[0] = GPCMD_TEST_UNIT_READY;
   6.790 +		cgc.cmd[7] = slot;
   6.791 +		cgc.cmd[4] = cgc.cmd[8] = 0;
   6.792 +		cdi->sanyo_slot = slot ? slot : 3;
   6.793 +	}
   6.794 +
   6.795 +	return cdi->ops->generic_packet(cdi, &cgc);
   6.796 +}
   6.797 +
   6.798 +int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
   6.799 +{
   6.800 +	struct cdrom_changer_info info;
   6.801 +	int curslot;
   6.802 +	int ret;
   6.803 +
   6.804 +	cdinfo(CD_CHANGER, "entering cdrom_select_disc()\n"); 
   6.805 +	if (!CDROM_CAN(CDC_SELECT_DISC))
   6.806 +		return -EDRIVE_CANT_DO_THIS;
   6.807 +
   6.808 +	(void) cdi->ops->media_changed(cdi, slot);
   6.809 +
   6.810 +	if (slot == CDSL_NONE) {
   6.811 +		/* set media changed bits, on both queues */
   6.812 +		cdi->mc_flags = 0x3;
   6.813 +		return cdrom_load_unload(cdi, -1);
   6.814 +	}
   6.815 +
   6.816 +	if ((ret = cdrom_read_mech_status(cdi, &info)))
   6.817 +		return ret;
   6.818 +
   6.819 +	curslot = info.hdr.curslot;
   6.820 +
   6.821 +	if (cdi->use_count > 1 || keeplocked) {
   6.822 +		if (slot == CDSL_CURRENT) {
   6.823 +	    		return curslot;
   6.824 +		} else {
   6.825 +			return -EBUSY;
   6.826 +		}
   6.827 +	}
   6.828 +
   6.829 +	/* Specifying CDSL_CURRENT will attempt to load the currnet slot,
   6.830 +	which is useful if it had been previously unloaded.
   6.831 +	Whether it can or not, it returns the current slot. 
   6.832 +	Similarly,  if slot happens to be the current one, we still
   6.833 +	try and load it. */
   6.834 +	if (slot == CDSL_CURRENT)
   6.835 +		slot = curslot;
   6.836 +
   6.837 +	/* set media changed bits on both queues */
   6.838 +	cdi->mc_flags = 0x3;
   6.839 +	if ((ret = cdrom_load_unload(cdi, slot)))
   6.840 +		return ret;
   6.841 +
   6.842 +	return slot;
   6.843 +}
   6.844 +
   6.845 +/* We want to make media_changed accessible to the user through an
   6.846 + * ioctl. The main problem now is that we must double-buffer the
   6.847 + * low-level implementation, to assure that the VFS and the user both
   6.848 + * see a medium change once.
   6.849 + */
   6.850 +
   6.851 +static
   6.852 +int media_changed(struct cdrom_device_info *cdi, int queue)
   6.853 +{
   6.854 +	unsigned int mask = (1 << (queue & 1));
   6.855 +	int ret = !!(cdi->mc_flags & mask);
   6.856 +
   6.857 +	if (!CDROM_CAN(CDC_MEDIA_CHANGED))
   6.858 +	    return ret;
   6.859 +	/* changed since last call? */
   6.860 +	if (cdi->ops->media_changed(cdi, CDSL_CURRENT)) {
   6.861 +		cdi->mc_flags = 0x3;    /* set bit on both queues */
   6.862 +		ret |= 1;
   6.863 +	}
   6.864 +	cdi->mc_flags &= ~mask;         /* clear bit */
   6.865 +	return ret;
   6.866 +}
   6.867 +
   6.868 +int cdrom_media_changed(kdev_t dev)
   6.869 +{
   6.870 +	struct cdrom_device_info *cdi = cdrom_find_device(dev);
   6.871 +	/* This talks to the VFS, which doesn't like errors - just 1 or 0.  
   6.872 +	 * Returning "0" is always safe (media hasn't been changed). Do that 
   6.873 +	 * if the low-level cdrom driver dosn't support media changed. */ 
   6.874 +	if (cdi == NULL || cdi->ops->media_changed == NULL)
   6.875 +		return 0;
   6.876 +	if (!CDROM_CAN(CDC_MEDIA_CHANGED))
   6.877 +		return 0;
   6.878 +	return media_changed(cdi, 0);
   6.879 +}
   6.880 +
   6.881 +/* badly broken, I know. Is due for a fixup anytime. */
   6.882 +void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype* tracks)
   6.883 +{
   6.884 +	struct cdrom_tochdr header;
   6.885 +	struct cdrom_tocentry entry;
   6.886 +	int ret, i;
   6.887 +	tracks->data=0;
   6.888 +	tracks->audio=0;
   6.889 +	tracks->cdi=0;
   6.890 +	tracks->xa=0;
   6.891 +	tracks->error=0;
   6.892 +	cdinfo(CD_COUNT_TRACKS, "entering cdrom_count_tracks\n"); 
   6.893 +        if (!CDROM_CAN(CDC_PLAY_AUDIO)) { 
   6.894 +                tracks->error=CDS_NO_INFO;
   6.895 +                return;
   6.896 +        }        
   6.897 +	/* Grab the TOC header so we can see how many tracks there are */
   6.898 +	if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header))) {
   6.899 +		if (ret == -ENOMEDIUM)
   6.900 +			tracks->error = CDS_NO_DISC;
   6.901 +		else
   6.902 +			tracks->error = CDS_NO_INFO;
   6.903 +		return;
   6.904 +	}	
   6.905 +	/* check what type of tracks are on this disc */
   6.906 +	entry.cdte_format = CDROM_MSF;
   6.907 +	for (i = header.cdth_trk0; i <= header.cdth_trk1; i++) {
   6.908 +		entry.cdte_track  = i;
   6.909 +		if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry)) {
   6.910 +			tracks->error=CDS_NO_INFO;
   6.911 +			return;
   6.912 +		}	
   6.913 +		if (entry.cdte_ctrl & CDROM_DATA_TRACK) {
   6.914 +		    if (entry.cdte_format == 0x10)
   6.915 +			tracks->cdi++;
   6.916 +		    else if (entry.cdte_format == 0x20) 
   6.917 +			tracks->xa++;
   6.918 +		    else
   6.919 +			tracks->data++;
   6.920 +		} else
   6.921 +		    tracks->audio++;
   6.922 +		cdinfo(CD_COUNT_TRACKS, "track %d: format=%d, ctrl=%d\n",
   6.923 +		       i, entry.cdte_format, entry.cdte_ctrl);
   6.924 +	}	
   6.925 +	cdinfo(CD_COUNT_TRACKS, "disc has %d tracks: %d=audio %d=data %d=Cd-I %d=XA\n", 
   6.926 +		header.cdth_trk1, tracks->audio, tracks->data, 
   6.927 +		tracks->cdi, tracks->xa);
   6.928 +}	
   6.929 +
   6.930 +/* Requests to the low-level drivers will /always/ be done in the
   6.931 +   following format convention:
   6.932 +
   6.933 +   CDROM_LBA: all data-related requests.
   6.934 +   CDROM_MSF: all audio-related requests.
   6.935 +
   6.936 +   However, a low-level implementation is allowed to refuse this
   6.937 +   request, and return information in its own favorite format.
   6.938 +
   6.939 +   It doesn't make sense /at all/ to ask for a play_audio in LBA
   6.940 +   format, or ask for multi-session info in MSF format. However, for
   6.941 +   backward compatibility these format requests will be satisfied, but
   6.942 +   the requests to the low-level drivers will be sanitized in the more
   6.943 +   meaningful format indicated above.
   6.944 + */
   6.945 +
   6.946 +static
   6.947 +void sanitize_format(union cdrom_addr *addr,
   6.948 +		     u_char * curr, u_char requested)
   6.949 +{
   6.950 +	if (*curr == requested)
   6.951 +		return;                 /* nothing to be done! */
   6.952 +	if (requested == CDROM_LBA) {
   6.953 +		addr->lba = (int) addr->msf.frame +
   6.954 +			75 * (addr->msf.second - 2 + 60 * addr->msf.minute);
   6.955 +	} else {                        /* CDROM_MSF */
   6.956 +		int lba = addr->lba;
   6.957 +		addr->msf.frame = lba % 75;
   6.958 +		lba /= 75;
   6.959 +		lba += 2;
   6.960 +		addr->msf.second = lba % 60;
   6.961 +		addr->msf.minute = lba / 60;
   6.962 +	}
   6.963 +	*curr = requested;
   6.964 +}
   6.965 +
   6.966 +void init_cdrom_command(struct cdrom_generic_command *cgc, void *buf, int len,
   6.967 +			int type)
   6.968 +{
   6.969 +	memset(cgc, 0, sizeof(struct cdrom_generic_command));
   6.970 +	if (buf)
   6.971 +		memset(buf, 0, len);
   6.972 +	cgc->buffer = (char *) buf;
   6.973 +	cgc->buflen = len;
   6.974 +	cgc->data_direction = type;
   6.975 +	cgc->timeout = 5*HZ;
   6.976 +}
   6.977 +
   6.978 +/* DVD handling */
   6.979 +
   6.980 +#define copy_key(dest,src)	memcpy((dest), (src), sizeof(dvd_key))
   6.981 +#define copy_chal(dest,src)	memcpy((dest), (src), sizeof(dvd_challenge))
   6.982 +
   6.983 +static void setup_report_key(struct cdrom_generic_command *cgc, unsigned agid, unsigned type)
   6.984 +{
   6.985 +	cgc->cmd[0] = GPCMD_REPORT_KEY;
   6.986 +	cgc->cmd[10] = type | (agid << 6);
   6.987 +	switch (type) {
   6.988 +		case 0: case 8: case 5: {
   6.989 +			cgc->buflen = 8;
   6.990 +			break;
   6.991 +		}
   6.992 +		case 1: {
   6.993 +			cgc->buflen = 16;
   6.994 +			break;
   6.995 +		}
   6.996 +		case 2: case 4: {
   6.997 +			cgc->buflen = 12;
   6.998 +			break;
   6.999 +		}
  6.1000 +	}
  6.1001 +	cgc->cmd[9] = cgc->buflen;
  6.1002 +	cgc->data_direction = CGC_DATA_READ;
  6.1003 +}
  6.1004 +
  6.1005 +static void setup_send_key(struct cdrom_generic_command *cgc, unsigned agid, unsigned type)
  6.1006 +{
  6.1007 +	cgc->cmd[0] = GPCMD_SEND_KEY;
  6.1008 +	cgc->cmd[10] = type | (agid << 6);
  6.1009 +	switch (type) {
  6.1010 +		case 1: {
  6.1011 +			cgc->buflen = 16;
  6.1012 +			break;
  6.1013 +		}
  6.1014 +		case 3: {
  6.1015 +			cgc->buflen = 12;
  6.1016 +			break;
  6.1017 +		}
  6.1018 +		case 6: {
  6.1019 +			cgc->buflen = 8;
  6.1020 +			break;
  6.1021 +		}
  6.1022 +	}
  6.1023 +	cgc->cmd[9] = cgc->buflen;
  6.1024 +	cgc->data_direction = CGC_DATA_WRITE;
  6.1025 +}
  6.1026 +
  6.1027 +static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
  6.1028 +{
  6.1029 +	int ret;
  6.1030 +	u_char buf[20];
  6.1031 +	struct cdrom_generic_command cgc;
  6.1032 +	struct cdrom_device_ops *cdo = cdi->ops;
  6.1033 +	rpc_state_t rpc_state;
  6.1034 +
  6.1035 +	memset(buf, 0, sizeof(buf));
  6.1036 +	init_cdrom_command(&cgc, buf, 0, CGC_DATA_READ);
  6.1037 +
  6.1038 +	switch (ai->type) {
  6.1039 +	/* LU data send */
  6.1040 +	case DVD_LU_SEND_AGID:
  6.1041 +		cdinfo(CD_DVD, "entering DVD_LU_SEND_AGID\n"); 
  6.1042 +		setup_report_key(&cgc, ai->lsa.agid, 0);
  6.1043 +
  6.1044 +		if ((ret = cdo->generic_packet(cdi, &cgc)))
  6.1045 +			return ret;
  6.1046 +
  6.1047 +		ai->lsa.agid = buf[7] >> 6;
  6.1048 +		/* Returning data, let host change state */
  6.1049 +		break;
  6.1050 +
  6.1051 +	case DVD_LU_SEND_KEY1:
  6.1052 +		cdinfo(CD_DVD, "entering DVD_LU_SEND_KEY1\n"); 
  6.1053 +		setup_report_key(&cgc, ai->lsk.agid, 2);
  6.1054 +
  6.1055 +		if ((ret = cdo->generic_packet(cdi, &cgc)))
  6.1056 +			return ret;
  6.1057 +
  6.1058 +		copy_key(ai->lsk.key, &buf[4]);
  6.1059 +		/* Returning data, let host change state */
  6.1060 +		break;
  6.1061 +
  6.1062 +	case DVD_LU_SEND_CHALLENGE:
  6.1063 +		cdinfo(CD_DVD, "entering DVD_LU_SEND_CHALLENGE\n"); 
  6.1064 +		setup_report_key(&cgc, ai->lsc.agid, 1);
  6.1065 +
  6.1066 +		if ((ret = cdo->generic_packet(cdi, &cgc)))
  6.1067 +			return ret;
  6.1068 +
  6.1069 +		copy_chal(ai->lsc.chal, &buf[4]);
  6.1070 +		/* Returning data, let host change state */
  6.1071 +		break;
  6.1072 +
  6.1073 +	/* Post-auth key */
  6.1074 +	case DVD_LU_SEND_TITLE_KEY:
  6.1075 +		cdinfo(CD_DVD, "entering DVD_LU_SEND_TITLE_KEY\n"); 
  6.1076 +		setup_report_key(&cgc, ai->lstk.agid, 4);
  6.1077 +		cgc.cmd[5] = ai->lstk.lba;
  6.1078 +		cgc.cmd[4] = ai->lstk.lba >> 8;
  6.1079 +		cgc.cmd[3] = ai->lstk.lba >> 16;
  6.1080 +		cgc.cmd[2] = ai->lstk.lba >> 24;
  6.1081 +
  6.1082 +		if ((ret = cdo->generic_packet(cdi, &cgc)))
  6.1083 +			return ret;
  6.1084 +
  6.1085 +		ai->lstk.cpm = (buf[4] >> 7) & 1;
  6.1086 +		ai->lstk.cp_sec = (buf[4] >> 6) & 1;
  6.1087 +		ai->lstk.cgms = (buf[4] >> 4) & 3;
  6.1088 +		copy_key(ai->lstk.title_key, &buf[5]);
  6.1089 +		/* Returning data, let host change state */
  6.1090 +		break;
  6.1091 +
  6.1092 +	case DVD_LU_SEND_ASF:
  6.1093 +		cdinfo(CD_DVD, "entering DVD_LU_SEND_ASF\n"); 
  6.1094 +		setup_report_key(&cgc, ai->lsasf.agid, 5);
  6.1095 +		
  6.1096 +		if ((ret = cdo->generic_packet(cdi, &cgc)))
  6.1097 +			return ret;
  6.1098 +
  6.1099 +		ai->lsasf.asf = buf[7] & 1;
  6.1100 +		break;
  6.1101 +
  6.1102 +	/* LU data receive (LU changes state) */
  6.1103 +	case DVD_HOST_SEND_CHALLENGE:
  6.1104 +		cdinfo(CD_DVD, "entering DVD_HOST_SEND_CHALLENGE\n"); 
  6.1105 +		setup_send_key(&cgc, ai->hsc.agid, 1);
  6.1106 +		buf[1] = 0xe;
  6.1107 +		copy_chal(&buf[4], ai->hsc.chal);
  6.1108 +
  6.1109 +		if ((ret = cdo->generic_packet(cdi, &cgc)))
  6.1110 +			return ret;
  6.1111 +
  6.1112 +		ai->type = DVD_LU_SEND_KEY1;
  6.1113 +		break;
  6.1114 +
  6.1115 +	case DVD_HOST_SEND_KEY2:
  6.1116 +		cdinfo(CD_DVD, "entering DVD_HOST_SEND_KEY2\n"); 
  6.1117 +		setup_send_key(&cgc, ai->hsk.agid, 3);
  6.1118 +		buf[1] = 0xa;
  6.1119 +		copy_key(&buf[4], ai->hsk.key);
  6.1120 +
  6.1121 +		if ((ret = cdo->generic_packet(cdi, &cgc))) {
  6.1122 +			ai->type = DVD_AUTH_FAILURE;
  6.1123 +			return ret;
  6.1124 +		}
  6.1125 +		ai->type = DVD_AUTH_ESTABLISHED;
  6.1126 +		break;
  6.1127 +
  6.1128 +	/* Misc */
  6.1129 +	case DVD_INVALIDATE_AGID:
  6.1130 +		cdinfo(CD_DVD, "entering DVD_INVALIDATE_AGID\n"); 
  6.1131 +		setup_report_key(&cgc, ai->lsa.agid, 0x3f);
  6.1132 +		if ((ret = cdo->generic_packet(cdi, &cgc)))
  6.1133 +			return ret;
  6.1134 +		break;
  6.1135 +
  6.1136 +	/* Get region settings */
  6.1137 +	case DVD_LU_SEND_RPC_STATE:
  6.1138 +		cdinfo(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n");
  6.1139 +		setup_report_key(&cgc, 0, 8);
  6.1140 +		memset(&rpc_state, 0, sizeof(rpc_state_t));
  6.1141 +		cgc.buffer = (char *) &rpc_state;
  6.1142 +
  6.1143 +		if ((ret = cdo->generic_packet(cdi, &cgc)))
  6.1144 +			return ret;
  6.1145 +
  6.1146 +		ai->lrpcs.type = rpc_state.type_code;
  6.1147 +		ai->lrpcs.vra = rpc_state.vra;
  6.1148 +		ai->lrpcs.ucca = rpc_state.ucca;
  6.1149 +		ai->lrpcs.region_mask = rpc_state.region_mask;
  6.1150 +		ai->lrpcs.rpc_scheme = rpc_state.rpc_scheme;
  6.1151 +		break;
  6.1152 +
  6.1153 +	/* Set region settings */
  6.1154 +	case DVD_HOST_SEND_RPC_STATE:
  6.1155 +		cdinfo(CD_DVD, "entering DVD_HOST_SEND_RPC_STATE\n");
  6.1156 +		setup_send_key(&cgc, 0, 6);
  6.1157 +		buf[1] = 6;
  6.1158 +		buf[4] = ai->hrpcs.pdrc;
  6.1159 +
  6.1160 +		if ((ret = cdo->generic_packet(cdi, &cgc)))
  6.1161 +			return ret;
  6.1162 +		break;
  6.1163 +
  6.1164 +	default:
  6.1165 +		cdinfo(CD_WARNING, "Invalid DVD key ioctl (%d)\n", ai->type);
  6.1166 +		return -ENOTTY;
  6.1167 +	}
  6.1168 +
  6.1169 +	return 0;
  6.1170 +}
  6.1171 +
  6.1172 +static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
  6.1173 +{
  6.1174 +	unsigned char buf[20], *base;
  6.1175 +	struct dvd_layer *layer;
  6.1176 +	struct cdrom_generic_command cgc;
  6.1177 +	struct cdrom_device_ops *cdo = cdi->ops;
  6.1178 +	int ret, layer_num = s->physical.layer_num;
  6.1179 +
  6.1180 +	if (layer_num >= DVD_LAYERS)
  6.1181 +		return -EINVAL;
  6.1182 +
  6.1183 +	init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
  6.1184 +	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
  6.1185 +	cgc.cmd[6] = layer_num;
  6.1186 +	cgc.cmd[7] = s->type;
  6.1187 +	cgc.cmd[9] = cgc.buflen & 0xff;
  6.1188 +
  6.1189 +	/*
  6.1190 +	 * refrain from reporting errors on non-existing layers (mainly)
  6.1191 +	 */
  6.1192 +	cgc.quiet = 1;
  6.1193 +
  6.1194 +	if ((ret = cdo->generic_packet(cdi, &cgc)))
  6.1195 +		return ret;
  6.1196 +
  6.1197 +	base = &buf[4];
  6.1198 +	layer = &s->physical.layer[layer_num];
  6.1199 +
  6.1200 +	/*
  6.1201 +	 * place the data... really ugly, but at least we won't have to
  6.1202 +	 * worry about endianess in userspace.
  6.1203 +	 */
  6.1204 +	memset(layer, 0, sizeof(*layer));
  6.1205 +	layer->book_version = base[0] & 0xf;
  6.1206 +	layer->book_type = base[0] >> 4;
  6.1207 +	layer->min_rate = base[1] & 0xf;
  6.1208 +	layer->disc_size = base[1] >> 4;
  6.1209 +	layer->layer_type = base[2] & 0xf;
  6.1210 +	layer->track_path = (base[2] >> 4) & 1;
  6.1211 +	layer->nlayers = (base[2] >> 5) & 3;
  6.1212 +	layer->track_density = base[3] & 0xf;
  6.1213 +	layer->linear_density = base[3] >> 4;
  6.1214 +	layer->start_sector = base[5] << 16 | base[6] << 8 | base[7];
  6.1215 +	layer->end_sector = base[9] << 16 | base[10] << 8 | base[11];
  6.1216 +	layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15];
  6.1217 +	layer->bca = base[16] >> 7;
  6.1218 +
  6.1219 +	return 0;
  6.1220 +}
  6.1221 +
  6.1222 +static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s)
  6.1223 +{
  6.1224 +	int ret;
  6.1225 +	u_char buf[8];
  6.1226 +	struct cdrom_generic_command cgc;
  6.1227 +	struct cdrom_device_ops *cdo = cdi->ops;
  6.1228 +
  6.1229 +	init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
  6.1230 +	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
  6.1231 +	cgc.cmd[6] = s->copyright.layer_num;
  6.1232 +	cgc.cmd[7] = s->type;
  6.1233 +	cgc.cmd[8] = cgc.buflen >> 8;
  6.1234 +	cgc.cmd[9] = cgc.buflen & 0xff;
  6.1235 +
  6.1236 +	if ((ret = cdo->generic_packet(cdi, &cgc)))
  6.1237 +		return ret;
  6.1238 +
  6.1239 +	s->copyright.cpst = buf[4];
  6.1240 +	s->copyright.rmi = buf[5];
  6.1241 +
  6.1242 +	return 0;
  6.1243 +}
  6.1244 +
  6.1245 +static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s)
  6.1246 +{
  6.1247 +	int ret, size;
  6.1248 +	u_char *buf;
  6.1249 +	struct cdrom_generic_command cgc;
  6.1250 +	struct cdrom_device_ops *cdo = cdi->ops;
  6.1251 +
  6.1252 +	size = sizeof(s->disckey.value) + 4;
  6.1253 +
  6.1254 +	if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL)
  6.1255 +		return -ENOMEM;
  6.1256 +
  6.1257 +	init_cdrom_command(&cgc, buf, size, CGC_DATA_READ);
  6.1258 +	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
  6.1259 +	cgc.cmd[7] = s->type;
  6.1260 +	cgc.cmd[8] = size >> 8;
  6.1261 +	cgc.cmd[9] = size & 0xff;
  6.1262 +	cgc.cmd[10] = s->disckey.agid << 6;
  6.1263 +
  6.1264 +	if (!(ret = cdo->generic_packet(cdi, &cgc)))
  6.1265 +		memcpy(s->disckey.value, &buf[4], sizeof(s->disckey.value));
  6.1266 +
  6.1267 +	kfree(buf);
  6.1268 +	return ret;
  6.1269 +}
  6.1270 +
  6.1271 +static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s)
  6.1272 +{
  6.1273 +	int ret;
  6.1274 +	u_char buf[4 + 188];
  6.1275 +	struct cdrom_generic_command cgc;
  6.1276 +	struct cdrom_device_ops *cdo = cdi->ops;
  6.1277 +
  6.1278 +	init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
  6.1279 +	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
  6.1280 +	cgc.cmd[7] = s->type;
  6.1281 +	cgc.cmd[9] = cgc.buflen = 0xff;
  6.1282 +
  6.1283 +	if ((ret = cdo->generic_packet(cdi, &cgc)))
  6.1284 +		return ret;
  6.1285 +
  6.1286 +	s->bca.len = buf[0] << 8 | buf[1];
  6.1287 +	if (s->bca.len < 12 || s->bca.len > 188) {
  6.1288 +		cdinfo(CD_WARNING, "Received invalid BCA length (%d)\n", s->bca.len);
  6.1289 +		return -EIO;
  6.1290 +	}
  6.1291 +	memcpy(s->bca.value, &buf[4], s->bca.len);
  6.1292 +
  6.1293 +	return 0;
  6.1294 +}
  6.1295 +
  6.1296 +static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s)
  6.1297 +{
  6.1298 +	int ret = 0, size;
  6.1299 +	u_char *buf;
  6.1300 +	struct cdrom_generic_command cgc;
  6.1301 +	struct cdrom_device_ops *cdo = cdi->ops;
  6.1302 +
  6.1303 +	size = sizeof(s->manufact.value) + 4;
  6.1304 +
  6.1305 +	if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL)
  6.1306 +		return -ENOMEM;
  6.1307 +
  6.1308 +	init_cdrom_command(&cgc, buf, size, CGC_DATA_READ);
  6.1309 +	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
  6.1310 +	cgc.cmd[7] = s->type;
  6.1311 +	cgc.cmd[8] = size >> 8;
  6.1312 +	cgc.cmd[9] = size & 0xff;
  6.1313 +
  6.1314 +	if ((ret = cdo->generic_packet(cdi, &cgc))) {
  6.1315 +		kfree(buf);
  6.1316 +		return ret;
  6.1317 +	}
  6.1318 +
  6.1319 +	s->manufact.len = buf[0] << 8 | buf[1];
  6.1320 +	if (s->manufact.len < 0 || s->manufact.len > 2048) {
  6.1321 +		cdinfo(CD_WARNING, "Received invalid manufacture info length"
  6.1322 +				   " (%d)\n", s->bca.len);
  6.1323 +		ret = -EIO;
  6.1324 +	} else {
  6.1325 +		memcpy(s->manufact.value, &buf[4], s->manufact.len);
  6.1326 +	}
  6.1327 +
  6.1328 +	kfree(buf);
  6.1329 +	return ret;
  6.1330 +}
  6.1331 +
  6.1332 +static int dvd_read_struct(struct cdrom_device_info *cdi, dvd_struct *s)
  6.1333 +{
  6.1334 +	switch (s->type) {
  6.1335 +	case DVD_STRUCT_PHYSICAL:
  6.1336 +		return dvd_read_physical(cdi, s);
  6.1337 +
  6.1338 +	case DVD_STRUCT_COPYRIGHT:
  6.1339 +		return dvd_read_copyright(cdi, s);
  6.1340 +
  6.1341 +	case DVD_STRUCT_DISCKEY:
  6.1342 +		return dvd_read_disckey(cdi, s);
  6.1343 +
  6.1344 +	case DVD_STRUCT_BCA:
  6.1345 +		return dvd_read_bca(cdi, s);
  6.1346 +
  6.1347 +	case DVD_STRUCT_MANUFACT:
  6.1348 +		return dvd_read_manufact(cdi, s);
  6.1349 +		
  6.1350 +	default:
  6.1351 +		cdinfo(CD_WARNING, ": Invalid DVD structure read requested (%d)\n",
  6.1352 +					s->type);
  6.1353 +		return -EINVAL;
  6.1354 +	}
  6.1355 +}
  6.1356 +
  6.1357 +int cdrom_mode_sense(struct cdrom_device_info *cdi,
  6.1358 +		     struct cdrom_generic_command *cgc,
  6.1359 +		     int page_code, int page_control)
  6.1360 +{
  6.1361 +	struct cdrom_device_ops *cdo = cdi->ops;
  6.1362 +
  6.1363 +	memset(cgc->cmd, 0, sizeof(cgc->cmd));
  6.1364 +
  6.1365 +	cgc->cmd[0] = GPCMD_MODE_SENSE_10;
  6.1366 +	cgc->cmd[2] = page_code | (page_control << 6);
  6.1367 +	cgc->cmd[7] = cgc->buflen >> 8;
  6.1368 +	cgc->cmd[8] = cgc->buflen & 0xff;
  6.1369 +	cgc->data_direction = CGC_DATA_READ;
  6.1370 +	return cdo->generic_packet(cdi, cgc);
  6.1371 +}
  6.1372 +
  6.1373 +int cdrom_mode_select(struct cdrom_device_info *cdi,
  6.1374 +		      struct cdrom_generic_command *cgc)
  6.1375 +{
  6.1376 +	struct cdrom_device_ops *cdo = cdi->ops;
  6.1377 +
  6.1378 +	memset(cgc->cmd, 0, sizeof(cgc->cmd));
  6.1379 +	memset(cgc->buffer, 0, 2);
  6.1380 +	cgc->cmd[0] = GPCMD_MODE_SELECT_10;
  6.1381 +	cgc->cmd[1] = 0x10;		/* PF */
  6.1382 +	cgc->cmd[7] = cgc->buflen >> 8;
  6.1383 +	cgc->cmd[8] = cgc->buflen & 0xff;
  6.1384 +	cgc->data_direction = CGC_DATA_WRITE;
  6.1385 +	return cdo->generic_packet(cdi, cgc);
  6.1386 +}
  6.1387 +
  6.1388 +static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
  6.1389 +				 struct cdrom_subchnl *subchnl, int mcn)
  6.1390 +{
  6.1391 +	struct cdrom_device_ops *cdo = cdi->ops;
  6.1392 +	struct cdrom_generic_command cgc;
  6.1393 +	char buffer[32];
  6.1394 +	int ret;
  6.1395 +
  6.1396 +	init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
  6.1397 +	cgc.cmd[0] = GPCMD_READ_SUBCHANNEL;
  6.1398 +	cgc.cmd[1] = 2;     /* MSF addressing */
  6.1399 +	cgc.cmd[2] = 0x40;  /* request subQ data */
  6.1400 +	cgc.cmd[3] = mcn ? 2 : 1;
  6.1401 +	cgc.cmd[8] = 16;
  6.1402 +
  6.1403 +	if ((ret = cdo->generic_packet(cdi, &cgc)))
  6.1404 +		return ret;
  6.1405 +
  6.1406 +	subchnl->cdsc_audiostatus = cgc.buffer[1];
  6.1407 +	subchnl->cdsc_format = CDROM_MSF;
  6.1408 +	subchnl->cdsc_ctrl = cgc.buffer[5] & 0xf;
  6.1409 +	subchnl->cdsc_trk = cgc.buffer[6];
  6.1410 +	subchnl->cdsc_ind = cgc.buffer[7];
  6.1411 +
  6.1412 +	subchnl->cdsc_reladdr.msf.minute = cgc.buffer[13];
  6.1413 +	subchnl->cdsc_reladdr.msf.second = cgc.buffer[14];
  6.1414 +	subchnl->cdsc_reladdr.msf.frame = cgc.buffer[15];
  6.1415 +	subchnl->cdsc_absaddr.msf.minute = cgc.buffer[9];
  6.1416 +	subchnl->cdsc_absaddr.msf.second = cgc.buffer[10];
  6.1417 +	subchnl->cdsc_absaddr.msf.frame = cgc.buffer[11];
  6.1418 +
  6.1419 +	return 0;
  6.1420 +}
  6.1421 +
  6.1422 +/*
  6.1423 + * Specific READ_10 interface
  6.1424 + */
  6.1425 +static int cdrom_read_cd(struct cdrom_device_info *cdi,
  6.1426 +			 struct cdrom_generic_command *cgc, int lba,
  6.1427 +			 int blocksize, int nblocks)
  6.1428 +{
  6.1429 +	struct cdrom_device_ops *cdo = cdi->ops;
  6.1430 +
  6.1431 +	memset(&cgc->cmd, 0, sizeof(cgc->cmd));
  6.1432 +	cgc->cmd[0] = GPCMD_READ_10;
  6.1433 +	cgc->cmd[2] = (lba >> 24) & 0xff;
  6.1434 +	cgc->cmd[3] = (lba >> 16) & 0xff;
  6.1435 +	cgc->cmd[4] = (lba >>  8) & 0xff;
  6.1436 +	cgc->cmd[5] = lba & 0xff;
  6.1437 +	cgc->cmd[6] = (nblocks >> 16) & 0xff;
  6.1438 +	cgc->cmd[7] = (nblocks >>  8) & 0xff;
  6.1439 +	cgc->cmd[8] = nblocks & 0xff;
  6.1440 +	cgc->buflen = blocksize * nblocks;
  6.1441 +	return cdo->generic_packet(cdi, cgc);
  6.1442 +}
  6.1443 +
  6.1444 +/* very generic interface for reading the various types of blocks */
  6.1445 +static int cdrom_read_block(struct cdrom_device_info *cdi,
  6.1446 +			    struct cdrom_generic_command *cgc,
  6.1447 +			    int lba, int nblocks, int format, int blksize)
  6.1448 +{
  6.1449 +	struct cdrom_device_ops *cdo = cdi->ops;
  6.1450 +
  6.1451 +	memset(&cgc->cmd, 0, sizeof(cgc->cmd));
  6.1452 +	cgc->cmd[0] = GPCMD_READ_CD;
  6.1453 +	/* expected sector size - cdda,mode1,etc. */
  6.1454 +	cgc->cmd[1] = format << 2;
  6.1455 +	/* starting address */
  6.1456 +	cgc->cmd[2] = (lba >> 24) & 0xff;
  6.1457 +	cgc->cmd[3] = (lba >> 16) & 0xff;
  6.1458 +	cgc->cmd[4] = (lba >>  8) & 0xff;
  6.1459 +	cgc->cmd[5] = lba & 0xff;
  6.1460 +	/* number of blocks */
  6.1461 +	cgc->cmd[6] = (nblocks >> 16) & 0xff;
  6.1462 +	cgc->cmd[7] = (nblocks >>  8) & 0xff;
  6.1463 +	cgc->cmd[8] = nblocks & 0xff;
  6.1464 +	cgc->buflen = blksize * nblocks;
  6.1465 +	
  6.1466 +	/* set the header info returned */
  6.1467 +	switch (blksize) {
  6.1468 +	case CD_FRAMESIZE_RAW0	: cgc->cmd[9] = 0x58; break;
  6.1469 +	case CD_FRAMESIZE_RAW1	: cgc->cmd[9] = 0x78; break;
  6.1470 +	case CD_FRAMESIZE_RAW	: cgc->cmd[9] = 0xf8; break;
  6.1471 +	default			: cgc->cmd[9] = 0x10;
  6.1472 +	}
  6.1473 +	
  6.1474 +	return cdo->generic_packet(cdi, cgc);
  6.1475 +}
  6.1476 +
  6.1477 +/* Just about every imaginable ioctl is supported in the Uniform layer
  6.1478 + * these days. ATAPI / SCSI specific code now mainly resides in
  6.1479 + * mmc_ioct().
  6.1480 + */
  6.1481 +int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
  6.1482 +		       unsigned long arg)
  6.1483 +{
  6.1484 +	kdev_t dev = ip->i_rdev;
  6.1485 +	struct cdrom_device_info *cdi = cdrom_find_device(dev);
  6.1486 +	struct cdrom_device_ops *cdo = cdi->ops;
  6.1487 +	int ret;
  6.1488 +
  6.1489 +	/* the first few commands do not deal with audio drive_info, but
  6.1490 +	   only with routines in cdrom device operations. */
  6.1491 +	switch (cmd) {
  6.1492 +	case CDROMMULTISESSION: {
  6.1493 +		struct cdrom_multisession ms_info;
  6.1494 +		u_char requested_format;
  6.1495 +		cdinfo(CD_DO_IOCTL, "entering CDROMMULTISESSION\n"); 
  6.1496 +                if (!(cdo->capability & CDC_MULTI_SESSION))
  6.1497 +                        return -ENOSYS;
  6.1498 +		IOCTL_IN(arg, struct cdrom_multisession, ms_info);
  6.1499 +		requested_format = ms_info.addr_format;
  6.1500 +		if (!((requested_format == CDROM_MSF) ||
  6.1501 +			(requested_format == CDROM_LBA)))
  6.1502 +				return -EINVAL;
  6.1503 +		ms_info.addr_format = CDROM_LBA;
  6.1504 +		if ((ret=cdo->get_last_session(cdi, &ms_info)))
  6.1505 +			return ret;
  6.1506 +		sanitize_format(&ms_info.addr, &ms_info.addr_format,
  6.1507 +				requested_format);
  6.1508 +		IOCTL_OUT(arg, struct cdrom_multisession, ms_info);
  6.1509 +		cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION successful\n"); 
  6.1510 +		return 0;
  6.1511 +		}
  6.1512 +
  6.1513 +	case CDROMEJECT: {
  6.1514 +		cdinfo(CD_DO_IOCTL, "entering CDROMEJECT\n"); 
  6.1515 +		if (!CDROM_CAN(CDC_OPEN_TRAY))
  6.1516 +			return -ENOSYS;
  6.1517 +		if (cdi->use_count != 1 || keeplocked)
  6.1518 +			return -EBUSY;
  6.1519 +		if (CDROM_CAN(CDC_LOCK))
  6.1520 +			if ((ret=cdo->lock_door(cdi, 0)))
  6.1521 +				return ret;
  6.1522 +
  6.1523 +		return cdo->tray_move(cdi, 1);
  6.1524 +		}
  6.1525 +
  6.1526 +	case CDROMCLOSETRAY: {
  6.1527 +		cdinfo(CD_DO_IOCTL, "entering CDROMCLOSETRAY\n"); 
  6.1528 +		if (!CDROM_CAN(CDC_CLOSE_TRAY))
  6.1529 +			return -ENOSYS;
  6.1530 +		return cdo->tray_move(cdi, 0);
  6.1531 +		}
  6.1532 +
  6.1533 +	case CDROMEJECT_SW: {
  6.1534 +		cdinfo(CD_DO_IOCTL, "entering CDROMEJECT_SW\n"); 
  6.1535 +		if (!CDROM_CAN(CDC_OPEN_TRAY))
  6.1536 +			return -ENOSYS;
  6.1537 +		if (keeplocked)
  6.1538 +			return -EBUSY;
  6.1539 +		cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT);
  6.1540 +		if (arg)
  6.1541 +			cdi->options |= CDO_AUTO_CLOSE | CDO_AUTO_EJECT;
  6.1542 +		return 0;
  6.1543 +		}
  6.1544 +
  6.1545 +	case CDROM_MEDIA_CHANGED: {
  6.1546 +		struct cdrom_changer_info info;
  6.1547 +
  6.1548 +		cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n"); 
  6.1549 +		if (!CDROM_CAN(CDC_MEDIA_CHANGED))
  6.1550 +			return -ENOSYS;
  6.1551 +
  6.1552 +		/* cannot select disc or select current disc */
  6.1553 +		if (!CDROM_CAN(CDC_SELECT_DISC) || arg == CDSL_CURRENT)
  6.1554 +			return media_changed(cdi, 1);
  6.1555 +
  6.1556 +		if ((unsigned int)arg >= cdi->capacity)
  6.1557 +			return -EINVAL;
  6.1558 +
  6.1559 +		if ((ret = cdrom_read_mech_status(cdi, &info)))
  6.1560 +			return ret;
  6.1561 +
  6.1562 +		return info.slots[arg].change;
  6.1563 +		}
  6.1564 +
  6.1565 +	case CDROM_SET_OPTIONS: {
  6.1566 +		cdinfo(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n"); 
  6.1567 +		/* options need to be in sync with capability. too late for
  6.1568 +		   that, so we have to check each one separately... */
  6.1569 +		switch (arg) {
  6.1570 +		case CDO_USE_FFLAGS:
  6.1571 +		case CDO_CHECK_TYPE:
  6.1572 +			break;
  6.1573 +		case CDO_LOCK:
  6.1574 +			if (!CDROM_CAN(CDC_LOCK))
  6.1575 +				return -ENOSYS;
  6.1576 +			break;
  6.1577 +		case 0:
  6.1578 +			return cdi->options;
  6.1579 +		/* default is basically CDO_[AUTO_CLOSE|AUTO_EJECT] */
  6.1580 +		default:
  6.1581 +			if (!CDROM_CAN(arg))
  6.1582 +				return -ENOSYS;
  6.1583 +		}
  6.1584 +		cdi->options |= (int) arg;
  6.1585 +		return cdi->options;
  6.1586 +		}
  6.1587 +
  6.1588 +	case CDROM_CLEAR_OPTIONS: {
  6.1589 +		cdinfo(CD_DO_IOCTL, "entering CDROM_CLEAR_OPTIONS\n"); 
  6.1590 +		cdi->options &= ~(int) arg;
  6.1591 +		return cdi->options;
  6.1592 +		}
  6.1593 +
  6.1594 +	case CDROM_SELECT_SPEED: {
  6.1595 +		cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_SPEED\n"); 
  6.1596 +		if (!CDROM_CAN(CDC_SELECT_SPEED))
  6.1597 +			return -ENOSYS;
  6.1598 +		return cdo->select_speed(cdi, arg);
  6.1599 +		}
  6.1600 +
  6.1601 +	case CDROM_SELECT_DISC: {
  6.1602 +		cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_DISC\n"); 
  6.1603 +		if (!CDROM_CAN(CDC_SELECT_DISC))
  6.1604 +			return -ENOSYS;
  6.1605 +
  6.1606 +                if ((arg != CDSL_CURRENT) && (arg != CDSL_NONE))
  6.1607 +			if ((int)arg >= cdi->capacity)
  6.1608 +				return -EINVAL;
  6.1609 +
  6.1610 +		/* cdo->select_disc is a hook to allow a driver-specific
  6.1611 +		 * way of seleting disc.  However, since there is no
  6.1612 +		 * equiv hook for cdrom_slot_status this may not 
  6.1613 +		 * actually be useful...
  6.1614 +		 */
  6.1615 +		if (cdo->select_disc != NULL)
  6.1616 +			return cdo->select_disc(cdi, arg);
  6.1617 +
  6.1618 +		/* no driver specific select_disc(), call our own */
  6.1619 +		cdinfo(CD_CHANGER, "Using generic cdrom_select_disc()\n"); 
  6.1620 +		return cdrom_select_disc(cdi, arg);
  6.1621 +		}
  6.1622 +
  6.1623 +	case CDROMRESET: {
  6.1624 +		if (!capable(CAP_SYS_ADMIN))
  6.1625 +			return -EACCES;
  6.1626 +		cdinfo(CD_DO_IOCTL, "entering CDROM_RESET\n");
  6.1627 +		if (!CDROM_CAN(CDC_RESET))
  6.1628 +			return -ENOSYS;
  6.1629 +		return cdo->reset(cdi);
  6.1630 +		}
  6.1631 +
  6.1632 +	case CDROM_LOCKDOOR: {
  6.1633 +		cdinfo(CD_DO_IOCTL, "%socking door.\n", arg ? "L" : "Unl");
  6.1634 +		if (!CDROM_CAN(CDC_LOCK))
  6.1635 +			return -EDRIVE_CANT_DO_THIS;
  6.1636 +		keeplocked = arg ? 1 : 0;
  6.1637 +		/* don't unlock the door on multiple opens,but allow root
  6.1638 +		 * to do so */
  6.1639 +		if ((cdi->use_count != 1) && !arg && !capable(CAP_SYS_ADMIN))
  6.1640 +			return -EBUSY;
  6.1641 +		return cdo->lock_door(cdi, arg);
  6.1642 +		}
  6.1643 +
  6.1644 +	case CDROM_DEBUG: {
  6.1645 +		if (!capable(CAP_SYS_ADMIN))
  6.1646 +			return -EACCES;
  6.1647 +		cdinfo(CD_DO_IOCTL, "%sabling debug.\n", arg ? "En" : "Dis");
  6.1648 +		debug = arg ? 1 : 0;
  6.1649 +		return debug;
  6.1650 +		}
  6.1651 +
  6.1652 +	case CDROM_GET_CAPABILITY: {
  6.1653 +		cdinfo(CD_DO_IOCTL, "entering CDROM_GET_CAPABILITY\n");
  6.1654 +		return (cdo->capability & ~cdi->mask);
  6.1655 +		}
  6.1656 +
  6.1657 +/* The following function is implemented, although very few audio
  6.1658 + * discs give Universal Product Code information, which should just be
  6.1659 + * the Medium Catalog Number on the box.  Note, that the way the code
  6.1660 + * is written on the CD is /not/ uniform across all discs!
  6.1661 + */
  6.1662 +	case CDROM_GET_MCN: {
  6.1663 +		struct cdrom_mcn mcn;
  6.1664 +		cdinfo(CD_DO_IOCTL, "entering CDROM_GET_MCN\n"); 
  6.1665 +		if (!(cdo->capability & CDC_MCN))
  6.1666 +			return -ENOSYS;
  6.1667 +		if ((ret=cdo->get_mcn(cdi, &mcn)))
  6.1668 +			return ret;
  6.1669 +		IOCTL_OUT(arg, struct cdrom_mcn, mcn);
  6.1670 +		cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN successful\n"); 
  6.1671 +		return 0;
  6.1672 +		}
  6.1673 +
  6.1674 +	case CDROM_DRIVE_STATUS: {
  6.1675 +		cdinfo(CD_DO_IOCTL, "entering CDROM_DRIVE_STATUS\n"); 
  6.1676 +		if (!(cdo->capability & CDC_DRIVE_STATUS))
  6.1677 +			return -ENOSYS;
  6.1678 +		if (!CDROM_CAN(CDC_SELECT_DISC))
  6.1679 +			return cdo->drive_status(cdi, CDSL_CURRENT);
  6.1680 +                if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE)) 
  6.1681 +			return cdo->drive_status(cdi, CDSL_CURRENT);
  6.1682 +		if (((int)arg >= cdi->capacity))
  6.1683 +			return -EINVAL;
  6.1684 +		return cdrom_slot_status(cdi, arg);
  6.1685 +		}
  6.1686 +
  6.1687 +	/* Ok, this is where problems start.  The current interface for the
  6.1688 +	   CDROM_DISC_STATUS ioctl is flawed.  It makes the false assumption
  6.1689 +	   that CDs are all CDS_DATA_1 or all CDS_AUDIO, etc.  Unfortunatly,
  6.1690 +	   while this is often the case, it is also very common for CDs to
  6.1691 +	   have some tracks with data, and some tracks with audio.  Just 
  6.1692 +	   because I feel like it, I declare the following to be the best
  6.1693 +	   way to cope.  If the CD has ANY data tracks on it, it will be
  6.1694 +	   returned as a data CD.  If it has any XA tracks, I will return
  6.1695 +	   it as that.  Now I could simplify this interface by combining these 
  6.1696 +	   returns with the above, but this more clearly demonstrates
  6.1697 +	   the problem with the current interface.  Too bad this wasn't 
  6.1698 +	   designed to use bitmasks...         -Erik 
  6.1699 +
  6.1700 +	   Well, now we have the option CDS_MIXED: a mixed-type CD. 
  6.1701 +	   User level programmers might feel the ioctl is not very useful.
  6.1702 +	   					---david
  6.1703 +	*/
  6.1704 +	case CDROM_DISC_STATUS: {
  6.1705 +		tracktype tracks;
  6.1706 +		cdinfo(CD_DO_IOCTL, "entering CDROM_DISC_STATUS\n"); 
  6.1707 +		cdrom_count_tracks(cdi, &tracks);
  6.1708 +		if (tracks.error) 
  6.1709 +			return(tracks.error);
  6.1710 +
  6.1711 +		/* Policy mode on */
  6.1712 +		if (tracks.audio > 0) {
  6.1713 +			if (tracks.data==0 && tracks.cdi==0 && tracks.xa==0) 
  6.1714 +				return CDS_AUDIO;
  6.1715 +			else
  6.1716 +				return CDS_MIXED;
  6.1717 +		}
  6.1718 +		if (tracks.cdi > 0) return CDS_XA_2_2;
  6.1719 +		if (tracks.xa > 0) return CDS_XA_2_1;
  6.1720 +		if (tracks.data > 0) return CDS_DATA_1;
  6.1721 +		/* Policy mode off */
  6.1722 +
  6.1723 +		cdinfo(CD_WARNING,"This disc doesn't have any tracks I recognize!\n");
  6.1724 +		return CDS_NO_INFO;
  6.1725 +		}
  6.1726 +
  6.1727 +	case CDROM_CHANGER_NSLOTS: {
  6.1728 +		cdinfo(CD_DO_IOCTL, "entering CDROM_CHANGER_NSLOTS\n"); 
  6.1729 +		return cdi->capacity;
  6.1730 +		}
  6.1731 +	}
  6.1732 +
  6.1733 +	/* use the ioctls that are implemented through the generic_packet()
  6.1734 +	   interface. this may look at bit funny, but if -ENOTTY is
  6.1735 +	   returned that particular ioctl is not implemented and we
  6.1736 +	   let it go through the device specific ones. */
  6.1737 +	if (CDROM_CAN(CDC_GENERIC_PACKET)) {
  6.1738 +		ret = mmc_ioctl(cdi, cmd, arg);
  6.1739 +		if (ret != -ENOTTY) {
  6.1740 +			return ret;
  6.1741 +		}
  6.1742 +	}
  6.1743 +
  6.1744 +	/* note: most of the cdinfo() calls are commented out here,
  6.1745 +	   because they fill up the sys log when CD players poll
  6.1746 +	   the drive. */
  6.1747 +	switch (cmd) {
  6.1748 +	case CDROMSUBCHNL: {
  6.1749 +		struct cdrom_subchnl q;
  6.1750 +		u_char requested, back;
  6.1751 +		if (!CDROM_CAN(CDC_PLAY_AUDIO))
  6.1752 +			return -ENOSYS;
  6.1753 +		/* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/ 
  6.1754 +		IOCTL_IN(arg, struct cdrom_subchnl, q);
  6.1755 +		requested = q.cdsc_format;
  6.1756 +		if (!((requested == CDROM_MSF) ||
  6.1757 +		      (requested == CDROM_LBA)))
  6.1758 +			return -EINVAL;
  6.1759 +		q.cdsc_format = CDROM_MSF;
  6.1760 +		if ((ret=cdo->audio_ioctl(cdi, cmd, &q)))
  6.1761 +			return ret;
  6.1762 +		back = q.cdsc_format; /* local copy */
  6.1763 +		sanitize_format(&q.cdsc_absaddr, &back, requested);
  6.1764 +		sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
  6.1765 +		IOCTL_OUT(arg, struct cdrom_subchnl, q);
  6.1766 +		/* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ 
  6.1767 +		return 0;
  6.1768 +		}
  6.1769 +	case CDROMREADTOCHDR: {
  6.1770 +		struct cdrom_tochdr header;
  6.1771 +		if (!CDROM_CAN(CDC_PLAY_AUDIO))
  6.1772 +			return -ENOSYS;
  6.1773 +		/* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */ 
  6.1774 +		IOCTL_IN(arg, struct cdrom_tochdr, header);
  6.1775 +		if ((ret=cdo->audio_ioctl(cdi, cmd, &header)))
  6.1776 +			return ret;
  6.1777 +		IOCTL_OUT(arg, struct cdrom_tochdr, header);
  6.1778 +		/* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */ 
  6.1779 +		return 0;
  6.1780 +		}
  6.1781 +	case CDROMREADTOCENTRY: {
  6.1782 +		struct cdrom_tocentry entry;
  6.1783 +		u_char requested_format;
  6.1784 +		if (!CDROM_CAN(CDC_PLAY_AUDIO))
  6.1785 +			return -ENOSYS;
  6.1786 +		/* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */ 
  6.1787 +		IOCTL_IN(arg, struct cdrom_tocentry, entry);
  6.1788 +		requested_format = entry.cdte_format;
  6.1789 +		if (!((requested_format == CDROM_MSF) || 
  6.1790 +			(requested_format == CDROM_LBA)))
  6.1791 +				return -EINVAL;
  6.1792 +		/* make interface to low-level uniform */
  6.1793 +		entry.cdte_format = CDROM_MSF;
  6.1794 +		if ((ret=cdo->audio_ioctl(cdi, cmd, &entry)))
  6.1795 +			return ret;
  6.1796 +		sanitize_format(&entry.cdte_addr,
  6.1797 +		&entry.cdte_format, requested_format);
  6.1798 +		IOCTL_OUT(arg, struct cdrom_tocentry, entry);
  6.1799 +		/* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */ 
  6.1800 +		return 0;
  6.1801 +		}
  6.1802 +	case CDROMPLAYMSF: {
  6.1803 +		struct cdrom_msf msf;
  6.1804 +		if (!CDROM_CAN(CDC_PLAY_AUDIO))
  6.1805 +			return -ENOSYS;
  6.1806 +		cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); 
  6.1807 +		IOCTL_IN(arg, struct cdrom_msf, msf);
  6.1808 +		return cdo->audio_ioctl(cdi, cmd, &msf);
  6.1809 +		}
  6.1810 +	case CDROMPLAYTRKIND: {
  6.1811 +		struct cdrom_ti ti;
  6.1812 +		if (!CDROM_CAN(CDC_PLAY_AUDIO))
  6.1813 +			return -ENOSYS;
  6.1814 +		cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n"); 
  6.1815 +		IOCTL_IN(arg, struct cdrom_ti, ti);
  6.1816 +		CHECKAUDIO;
  6.1817 +		return cdo->audio_ioctl(cdi, cmd, &ti);
  6.1818 +		}
  6.1819 +	case CDROMVOLCTRL: {
  6.1820 +		struct cdrom_volctrl volume;
  6.1821 +		if (!CDROM_CAN(CDC_PLAY_AUDIO))
  6.1822 +			return -ENOSYS;
  6.1823 +		cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRL\n"); 
  6.1824 +		IOCTL_IN(arg, struct cdrom_volctrl, volume);
  6.1825 +		return cdo->audio_ioctl(cdi, cmd, &volume);
  6.1826 +		}
  6.1827 +	case CDROMVOLREAD: {
  6.1828 +		struct cdrom_volctrl volume;
  6.1829 +		if (!CDROM_CAN(CDC_PLAY_AUDIO))
  6.1830 +			return -ENOSYS;
  6.1831 +		cdinfo(CD_DO_IOCTL, "entering CDROMVOLREAD\n"); 
  6.1832 +		if ((ret=cdo->audio_ioctl(cdi, cmd, &volume)))
  6.1833 +			return ret;
  6.1834 +		IOCTL_OUT(arg, struct cdrom_volctrl, volume);
  6.1835 +		return 0;
  6.1836 +		}
  6.1837 +	case CDROMSTART:
  6.1838 +	case CDROMSTOP:
  6.1839 +	case CDROMPAUSE:
  6.1840 +	case CDROMRESUME: {
  6.1841 +		if (!CDROM_CAN(CDC_PLAY_AUDIO))
  6.1842 +			return -ENOSYS;
  6.1843 +		cdinfo(CD_DO_IOCTL, "doing audio ioctl (start/stop/pause/resume)\n"); 
  6.1844 +		CHECKAUDIO;
  6.1845 +		return cdo->audio_ioctl(cdi, cmd, NULL);
  6.1846 +		}
  6.1847 +	} /* switch */
  6.1848 +
  6.1849 +	/* do the device specific ioctls */
  6.1850 +	if (CDROM_CAN(CDC_IOCTLS))
  6.1851 +		return cdo->dev_ioctl(cdi, cmd, arg);
  6.1852 +	
  6.1853 +	return -ENOSYS;
  6.1854 +}
  6.1855 +
  6.1856 +static inline
  6.1857 +int msf_to_lba(char m, char s, char f)
  6.1858 +{
  6.1859 +	return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
  6.1860 +}
  6.1861 +
  6.1862 +/*
  6.1863 + * Required when we need to use READ_10 to issue other than 2048 block
  6.1864 + * reads
  6.1865 + */
  6.1866 +static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size)
  6.1867 +{
  6.1868 +	struct cdrom_device_ops *cdo = cdi->ops;
  6.1869 +	struct cdrom_generic_command cgc;
  6.1870 +	struct modesel_head mh;
  6.1871 +
  6.1872 +	memset(&mh, 0, sizeof(mh));
  6.1873 +	mh.block_desc_length = 0x08;
  6.1874 +	mh.block_length_med = (size >> 8) & 0xff;
  6.1875 +	mh.block_length_lo = size & 0xff;
  6.1876 +
  6.1877 +	memset(&cgc, 0, sizeof(cgc));
  6.1878 +	cgc.cmd[0] = 0x15;
  6.1879 +	cgc.cmd[1] = 1 << 4;
  6.1880 +	cgc.cmd[4] = 12;
  6.1881 +	cgc.buflen = sizeof(mh);
  6.1882 +	cgc.buffer = (char *) &mh;
  6.1883 +	cgc.data_direction = CGC_DATA_WRITE;
  6.1884 +	mh.block_desc_length = 0x08;
  6.1885 +	mh.block_length_med = (size >> 8) & 0xff;
  6.1886 +	mh.block_length_lo = size & 0xff;
  6.1887 +
  6.1888 +	return cdo->generic_packet(cdi, &cgc);
  6.1889 +}
  6.1890 +
  6.1891 +static int cdrom_do_cmd(struct cdrom_device_info *cdi,
  6.1892 +			struct cdrom_generic_command *cgc)
  6.1893 +{
  6.1894 +	struct request_sense *usense, sense;
  6.1895 +	unsigned char *ubuf;
  6.1896 +	int ret;
  6.1897 +
  6.1898 +	if (cgc->data_direction == CGC_DATA_UNKNOWN)
  6.1899 +		return -EINVAL;
  6.1900 +
  6.1901 +	if (cgc->buflen < 0 || cgc->buflen >= 131072)
  6.1902 +		return -EINVAL;
  6.1903 +
  6.1904 +	if ((ubuf = cgc->buffer)) {
  6.1905 +		cgc->buffer = kmalloc(cgc->buflen, GFP_KERNEL);
  6.1906 +		if (cgc->buffer == NULL)
  6.1907 +			return -ENOMEM;
  6.1908 +	}
  6.1909 +
  6.1910 +	usense = cgc->sense;
  6.1911 +	cgc->sense = &sense;
  6.1912 +	if (usense && !access_ok(VERIFY_WRITE, usense, sizeof(*usense)))
  6.1913 +		return -EFAULT;
  6.1914 +
  6.1915 +	if (cgc->data_direction == CGC_DATA_READ) {
  6.1916 +		if (!access_ok(VERIFY_READ, ubuf, cgc->buflen))
  6.1917 +			return -EFAULT;
  6.1918 +	} else if (cgc->data_direction == CGC_DATA_WRITE) {
  6.1919 +		if (copy_from_user(cgc->buffer, ubuf, cgc->buflen)) {
  6.1920 +			kfree(cgc->buffer);
  6.1921 +			return -EFAULT;
  6.1922 +		}
  6.1923 +	}
  6.1924 +
  6.1925 +	ret = cdi->ops->generic_packet(cdi, cgc);
  6.1926 +	__copy_to_user(usense, cgc->sense, sizeof(*usense));
  6.1927 +	if (!ret && cgc->data_direction == CGC_DATA_READ)
  6.1928 +		__copy_to_user(ubuf, cgc->buffer, cgc->buflen);
  6.1929 +	kfree(cgc->buffer);
  6.1930 +	return ret;
  6.1931 +}
  6.1932 +
  6.1933 +static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
  6.1934 +		     unsigned long arg)
  6.1935 +{		
  6.1936 +	struct cdrom_device_ops *cdo = cdi->ops;
  6.1937 +	struct cdrom_generic_command cgc;
  6.1938 +	kdev_t dev = cdi->dev;
  6.1939 +	char buffer[32];
  6.1940 +	int ret = 0;
  6.1941 +
  6.1942 +	memset(&cgc, 0, sizeof(cgc));
  6.1943 +
  6.1944 +	/* build a unified command and queue it through
  6.1945 +	   cdo->generic_packet() */
  6.1946 +	switch (cmd) {
  6.1947 +	case CDROMREADRAW:
  6.1948 +	case CDROMREADMODE1:
  6.1949 +	case CDROMREADMODE2: {
  6.1950 +		struct cdrom_msf msf;
  6.1951 +		int blocksize = 0, format = 0, lba;
  6.1952 +		
  6.1953 +		switch (cmd) {
  6.1954 +		case CDROMREADRAW:
  6.1955 +			blocksize = CD_FRAMESIZE_RAW;
  6.1956 +			break;
  6.1957 +		case CDROMREADMODE1:
  6.1958 +			blocksize = CD_FRAMESIZE;
  6.1959 +			format = 2;
  6.1960 +			break;
  6.1961 +		case CDROMREADMODE2:
  6.1962 +			blocksize = CD_FRAMESIZE_RAW0;
  6.1963 +			break;
  6.1964 +		}
  6.1965 +		IOCTL_IN(arg, struct cdrom_msf, msf);
  6.1966 +		lba = msf_to_lba(msf.cdmsf_min0,msf.cdmsf_sec0,msf.cdmsf_frame0);
  6.1967 +		/* FIXME: we need upper bound checking, too!! */
  6.1968 +		if (lba < 0)
  6.1969 +			return -EINVAL;
  6.1970 +		cgc.buffer = (char *) kmalloc(blocksize, GFP_KERNEL);
  6.1971 +		if (cgc.buffer == NULL)
  6.1972 +			return -ENOMEM;
  6.1973 +		cgc.data_direction = CGC_DATA_READ;
  6.1974 +		ret = cdrom_read_block(cdi, &cgc, lba, 1, format, blocksize);
  6.1975 +		if (ret) {
  6.1976 +			/*
  6.1977 +			 * SCSI-II devices are not required to support
  6.1978 +			 * READ_CD, so let's try switching block size
  6.1979 +			 */
  6.1980 +			/* FIXME: switch back again... */
  6.1981 +			if ((ret = cdrom_switch_blocksize(cdi, blocksize))) {
  6.1982 +				kfree(cgc.buffer);
  6.1983 +				return ret;
  6.1984 +			}
  6.1985 +			cgc.sense = NULL;
  6.1986 +			ret = cdrom_read_cd(cdi, &cgc, lba, blocksize, 1);
  6.1987 +			ret |= cdrom_switch_blocksize(cdi, blocksize);
  6.1988 +		}
  6.1989 +		if (!ret && copy_to_user((char *)arg, cgc.buffer, blocksize))
  6.1990 +			ret = -EFAULT;
  6.1991 +		kfree(cgc.buffer);
  6.1992 +		return ret;
  6.1993 +		}
  6.1994 +	case CDROMREADAUDIO: {
  6.1995 +		struct cdrom_read_audio ra;
  6.1996 +		int lba, nr;
  6.1997 +
  6.1998 +		IOCTL_IN(arg, struct cdrom_read_audio, ra);
  6.1999 +
  6.2000 +		if (ra.addr_format == CDROM_MSF)
  6.2001 +			lba = msf_to_lba(ra.addr.msf.minute,
  6.2002 +					 ra.addr.msf.second,
  6.2003 +					 ra.addr.msf.frame);
  6.2004 +		else if (ra.addr_format == CDROM_LBA)
  6.2005 +			lba = ra.addr.lba;
  6.2006 +		else
  6.2007 +			return -EINVAL;
  6.2008 +
  6.2009 +		/* FIXME: we need upper bound checking, too!! */
  6.2010 +		if (lba < 0 || ra.nframes <= 0)
  6.2011 +			return -EINVAL;
  6.2012 +
  6.2013 +		/*
  6.2014 +		 * start with will ra.nframes size, back down if alloc fails
  6.2015 +		 */
  6.2016 +		nr = ra.nframes;
  6.2017 +		do {
  6.2018 +			cgc.buffer = kmalloc(CD_FRAMESIZE_RAW * nr, GFP_KERNEL);
  6.2019 +			if (cgc.buffer)
  6.2020 +				break;
  6.2021 +
  6.2022 +			nr >>= 1;
  6.2023 +		} while (nr);
  6.2024 +
  6.2025 +		if (!nr)
  6.2026 +			return -ENOMEM;
  6.2027 +
  6.2028 +		if (!access_ok(VERIFY_WRITE, ra.buf, ra.nframes*CD_FRAMESIZE_RAW)) {
  6.2029 +			kfree(cgc.buffer);
  6.2030 +			return -EFAULT;
  6.2031 +		}
  6.2032 +		cgc.data_direction = CGC_DATA_READ;
  6.2033 +		while (ra.nframes > 0) {
  6.2034 +			if (nr > ra.nframes)
  6.2035 +				nr = ra.nframes;
  6.2036 +
  6.2037 +			ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW);
  6.2038 +			if (ret)
  6.2039 +				break;
  6.2040 +			__copy_to_user(ra.buf, cgc.buffer, CD_FRAMESIZE_RAW*nr);
  6.2041 +			ra.buf += CD_FRAMESIZE_RAW * nr;
  6.2042 +			ra.nframes -= nr;
  6.2043 +			lba += nr;
  6.2044 +		}
  6.2045 +		kfree(cgc.buffer);
  6.2046 +		return ret;
  6.2047 +		}
  6.2048 +	case CDROMSUBCHNL: {
  6.2049 +		struct cdrom_subchnl q;
  6.2050 +		u_char requested, back;
  6.2051 +		IOCTL_IN(arg, struct cdrom_subchnl, q);
  6.2052 +		requested = q.cdsc_format;
  6.2053 +		if (!((requested == CDROM_MSF) ||
  6.2054 +		      (requested == CDROM_LBA)))
  6.2055 +			return -EINVAL;
  6.2056 +		q.cdsc_format = CDROM_MSF;
  6.2057 +		if ((ret = cdrom_read_subchannel(cdi, &q, 0)))
  6.2058 +			return ret;
  6.2059 +		back = q.cdsc_format; /* local copy */
  6.2060 +		sanitize_format(&q.cdsc_absaddr, &back, requested);
  6.2061 +		sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
  6.2062 +		IOCTL_OUT(arg, struct cdrom_subchnl, q);
  6.2063 +		/* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ 
  6.2064 +		return 0;
  6.2065 +		}
  6.2066 +	case CDROMPLAYMSF: {
  6.2067 +		struct cdrom_msf msf;
  6.2068 +		cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n");
  6.2069 +		IOCTL_IN(arg, struct cdrom_msf, msf);
  6.2070 +		cgc.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
  6.2071 +		cgc.cmd[3] = msf.cdmsf_min0;
  6.2072 +		cgc.cmd[4] = msf.cdmsf_sec0;
  6.2073 +		cgc.cmd[5] = msf.cdmsf_frame0;
  6.2074 +		cgc.cmd[6] = msf.cdmsf_min1;
  6.2075 +		cgc.cmd[7] = msf.cdmsf_sec1;
  6.2076 +		cgc.cmd[8] = msf.cdmsf_frame1;
  6.2077 +		cgc.data_direction = CGC_DATA_NONE;
  6.2078 +		return cdo->generic_packet(cdi, &cgc);
  6.2079 +		}
  6.2080 +	case CDROMPLAYBLK: {
  6.2081 +		struct cdrom_blk blk;
  6.2082 +		cdinfo(CD_DO_IOCTL, "entering CDROMPLAYBLK\n");
  6.2083 +		IOCTL_IN(arg, struct cdrom_blk, blk);
  6.2084 +		cgc.cmd[0] = GPCMD_PLAY_AUDIO_10;
  6.2085 +		cgc.cmd[2] = (blk.from >> 24) & 0xff;
  6.2086 +		cgc.cmd[3] = (blk.from >> 16) & 0xff;
  6.2087 +		cgc.cmd[4] = (blk.from >>  8) & 0xff;
  6.2088 +		cgc.cmd[5] = blk.from & 0xff;
  6.2089 +		cgc.cmd[7] = (blk.len >> 8) & 0xff;
  6.2090 +		cgc.cmd[8] = blk.len & 0xff;
  6.2091 +		cgc.data_direction = CGC_DATA_NONE;
  6.2092 +		return cdo->generic_packet(cdi, &cgc);
  6.2093 +		}
  6.2094 +	case CDROMVOLCTRL:
  6.2095 +	case CDROMVOLREAD: {
  6.2096 +		struct cdrom_volctrl volctrl;
  6.2097 +		char mask[32];
  6.2098 +		unsigned short offset;
  6.2099 +		cdinfo(CD_DO_IOCTL, "entering CDROMVOLUME\n");
  6.2100 +
  6.2101 +		IOCTL_IN(arg, struct cdrom_volctrl, volctrl);
  6.2102 +
  6.2103 +		cgc.buffer = buffer;
  6.2104 +		cgc.buflen = 24;
  6.2105 +		if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_AUDIO_CTL_PAGE, 0)))
  6.2106 +		    return ret;
  6.2107 +		
  6.2108 +		/* some drives have longer pages, adjust and reread. */
  6.2109 +		if (buffer[1] > cgc.buflen) {
  6.2110 +			cgc.buflen = buffer[1] + 2;
  6.2111 +			if ((ret = cdrom_mode_sense(cdi, &cgc, 
  6.2112 +					GPMODE_AUDIO_CTL_PAGE, 0))) 
  6.2113 +			    return ret;
  6.2114 +		}
  6.2115 +		
  6.2116 +		/* get the offset from the length of the page. length
  6.2117 +		   is measure from byte 2 an on, thus the 14. */
  6.2118 +		offset = buffer[1] - 14;
  6.2119 +
  6.2120 +		/* now we have the current volume settings. if it was only
  6.2121 +		   a CDROMVOLREAD, return these values */
  6.2122 +		if (cmd == CDROMVOLREAD) {
  6.2123 +			volctrl.channel0 = buffer[offset+9];
  6.2124 +			volctrl.channel1 = buffer[offset+11];
  6.2125 +			volctrl.channel2 = buffer[offset+13];
  6.2126 +			volctrl.channel3 = buffer[offset+15];
  6.2127 +			IOCTL_OUT(arg, struct cdrom_volctrl, volctrl);
  6.2128 +			return 0;
  6.2129 +		}
  6.2130 +		
  6.2131 +		/* get the volume mask */
  6.2132 +		cgc.buffer = mask;
  6.2133 +		if ((ret = cdrom_mode_sense(cdi, &cgc, 
  6.2134 +				GPMODE_AUDIO_CTL_PAGE, 1)))
  6.2135 +			return ret;
  6.2136 +
  6.2137 +		buffer[offset+9] = volctrl.channel0 & mask[offset+9];
  6.2138 +		buffer[offset+11] = volctrl.channel1 & mask[offset+11];
  6.2139 +		buffer[offset+13] = volctrl.channel2 & mask[offset+13];
  6.2140 +		buffer[offset+15] = volctrl.channel3 & mask[offset+15];
  6.2141 +
  6.2142 +		/* set volume */
  6.2143 +		cgc.buffer = buffer;
  6.2144 +		return cdrom_mode_select(cdi, &cgc);
  6.2145 +		}
  6.2146 +
  6.2147 +	case CDROMSTART:
  6.2148 +	case CDROMSTOP: {
  6.2149 +		cdinfo(CD_DO_IOCTL, "entering CDROMSTART/CDROMSTOP\n"); 
  6.2150 +		cgc.cmd[0] = GPCMD_START_STOP_UNIT;
  6.2151 +		cgc.cmd[1] = 1;
  6.2152 +		cgc.cmd[4] = (cmd == CDROMSTART) ? 1 : 0;
  6.2153 +		cgc.data_direction = CGC_DATA_NONE;
  6.2154 +		return cdo->generic_packet(cdi, &cgc);
  6.2155 +		}
  6.2156 +
  6.2157 +	case CDROMPAUSE:
  6.2158 +	case CDROMRESUME: {
  6.2159 +		cdinfo(CD_DO_IOCTL, "entering CDROMPAUSE/CDROMRESUME\n"); 
  6.2160 +		cgc.cmd[0] = GPCMD_PAUSE_RESUME;
  6.2161 +		cgc.cmd[8] = (cmd == CDROMRESUME) ? 1 : 0;
  6.2162 +		cgc.data_direction = CGC_DATA_NONE;
  6.2163 +		return cdo->generic_packet(cdi, &cgc);
  6.2164 +		}
  6.2165 +
  6.2166 +	case DVD_READ_STRUCT: {
  6.2167 +		dvd_struct *s;
  6.2168 +		int size = sizeof(dvd_struct);
  6.2169 +		if (!CDROM_CAN(CDC_DVD))
  6.2170 +			return -ENOSYS;
  6.2171 +		if ((s = (dvd_struct *) kmalloc(size, GFP_KERNEL)) == NULL)
  6.2172 +			return -ENOMEM;
  6.2173 +		cdinfo(CD_DO_IOCTL, "entering DVD_READ_STRUCT\n"); 
  6.2174 +		if (copy_from_user(s, (dvd_struct *)arg, size)) {
  6.2175 +			kfree(s);
  6.2176 +			return -EFAULT;
  6.2177 +		}
  6.2178 +		if ((ret = dvd_read_struct(cdi, s))) {
  6.2179 +			kfree(s);
  6.2180 +			return ret;
  6.2181 +		}
  6.2182 +		if (copy_to_user((dvd_struct *)arg, s, size))
  6.2183 +			ret = -EFAULT;
  6.2184 +		kfree(s);
  6.2185 +		return ret;
  6.2186 +		}
  6.2187 +
  6.2188 +	case DVD_AUTH: {
  6.2189 +		dvd_authinfo ai;
  6.2190 +		if (!CDROM_CAN(CDC_DVD))
  6.2191 +			return -ENOSYS;
  6.2192 +		cdinfo(CD_DO_IOCTL, "entering DVD_AUTH\n"); 
  6.2193 +		IOCTL_IN(arg, dvd_authinfo, ai);
  6.2194 +		if ((ret = dvd_do_auth (cdi, &ai)))
  6.2195 +			return ret;
  6.2196 +		IOCTL_OUT(arg, dvd_authinfo, ai);
  6.2197 +		return 0;
  6.2198 +		}
  6.2199 +
  6.2200 +	case CDROM_SEND_PACKET: {
  6.2201 +		if (!CDROM_CAN(CDC_GENERIC_PACKET))
  6.2202 +			return -ENOSYS;
  6.2203 +		cdinfo(CD_DO_IOCTL, "entering CDROM_SEND_PACKET\n"); 
  6.2204 +		IOCTL_IN(arg, struct cdrom_generic_command, cgc);
  6.2205 +		return cdrom_do_cmd(cdi, &cgc);
  6.2206 +		}
  6.2207 +	case CDROM_NEXT_WRITABLE: {
  6.2208 +		long next = 0;
  6.2209 +		cdinfo(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLE\n"); 
  6.2210 +		if ((ret = cdrom_get_next_writable(dev, &next)))
  6.2211 +			return ret;
  6.2212 +		IOCTL_OUT(arg, long, next);
  6.2213 +		return 0;
  6.2214 +		}
  6.2215 +	case CDROM_LAST_WRITTEN: {
  6.2216 +		long last = 0;
  6.2217 +		cdinfo(CD_DO_IOCTL, "entering CDROM_LAST_WRITTEN\n"); 
  6.2218 +		if ((ret = cdrom_get_last_written(dev, &last)))
  6.2219 +			return ret;
  6.2220 +		IOCTL_OUT(arg, long, last);
  6.2221 +		return 0;
  6.2222 +		}
  6.2223 +	} /* switch */
  6.2224 +
  6.2225 +	return -ENOTTY;
  6.2226 +}
  6.2227 +
  6.2228 +int cdrom_get_track_info(kdev_t dev, __u16 track, __u8 type,
  6.2229 +			 track_information *ti)
  6.2230 +{
  6.2231 +        struct cdrom_device_info *cdi = cdrom_find_device(dev);
  6.2232 +	struct cdrom_device_ops *cdo = cdi->ops;
  6.2233 +	struct cdrom_generic_command cgc;
  6.2234 +	int ret;
  6.2235 +
  6.2236 +	init_cdrom_command(&cgc, ti, 8, CGC_DATA_READ);
  6.2237 +	cgc.cmd[0] = GPCMD_READ_TRACK_RZONE_INFO;
  6.2238 +	cgc.cmd[1] = type & 3;
  6.2239 +	cgc.cmd[4] = (track & 0xff00) >> 8;
  6.2240 +	cgc.cmd[5] = track & 0xff;
  6.2241 +	cgc.cmd[8] = 8;
  6.2242 +	cgc.quiet = 1;
  6.2243 +
  6.2244 +	if ((ret = cdo->generic_packet(cdi, &cgc)))
  6.2245 +		return ret;
  6.2246 +	
  6.2247 +	cgc.buflen = be16_to_cpu(ti->track_information_length) +
  6.2248 +		     sizeof(ti->track_information_length);
  6.2249 +
  6.2250 +	if (cgc.buflen > sizeof(track_information))
  6.2251 +		cgc.buflen = sizeof(track_information);
  6.2252 +
  6.2253 +	cgc.cmd[8] = cgc.buflen;
  6.2254 +	return cdo->generic_packet(cdi, &cgc);
  6.2255 +}
  6.2256 +
  6.2257 +/* requires CD R/RW */
  6.2258 +int cdrom_get_disc_info(kdev_t dev, disc_information *di)
  6.2259 +{
  6.2260 +	struct cdrom_device_info *cdi = cdrom_find_device(dev);
  6.2261 +	struct cdrom_device_ops *cdo = cdi->ops;
  6.2262 +	struct cdrom_generic_command cgc;
  6.2263 +	int ret;
  6.2264 +
  6.2265 +	/* set up command and get the disc info */
  6.2266 +	init_cdrom_command(&cgc, di, sizeof(*di), CGC_DATA_READ);
  6.2267 +	cgc.cmd[0] = GPCMD_READ_DISC_INFO;
  6.2268 +	cgc.cmd[8] = cgc.buflen = 2;
  6.2269 +	cgc.quiet = 1;
  6.2270 +
  6.2271 +	if ((ret = cdo->generic_packet(cdi, &cgc)))
  6.2272 +		return ret;
  6.2273 +
  6.2274 +	/* not all drives have the same disc_info length, so requeue
  6.2275 +	 * packet with the length the drive tells us it can supply
  6.2276 +	 */
  6.2277 +	cgc.buflen = be16_to_cpu(di->disc_information_length) +
  6.2278 +		     sizeof(di->disc_information_length);
  6.2279 +
  6.2280 +	if (cgc.buflen > sizeof(disc_information))
  6.2281 +		cgc.buflen = sizeof(disc_information);
  6.2282 +
  6.2283 +	cgc.cmd[8] = cgc.buflen;
  6.2284 +	return cdo->generic_packet(cdi, &cgc);
  6.2285 +}
  6.2286 +
  6.2287 +
  6.2288 +/* return the last written block on the CD-R media. this is for the udf
  6.2289 +   file system. */
  6.2290 +int cdrom_get_last_written(kdev_t dev, long *last_written)
  6.2291 +{	
  6.2292 +	struct cdrom_device_info *cdi = cdrom_find_device(dev);
  6.2293 +	struct cdrom_tocentry toc;
  6.2294 +	disc_information di;
  6.2295 +	track_information ti;
  6.2296 +	__u32 last_track;
  6.2297 +	int ret = -1;
  6.2298 +
  6.2299 +	if (!CDROM_CAN(CDC_GENERIC_PACKET))
  6.2300 +		goto use_toc;
  6.2301 +
  6.2302 +	if ((ret = cdrom_get_disc_info(dev, &di)))
  6.2303 +		goto use_toc;
  6.2304 +
  6.2305 +	last_track = (di.last_track_msb << 8) | di.last_track_lsb;
  6.2306 +	if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti)))
  6.2307 +		goto use_toc;
  6.2308 +
  6.2309 +	/* if this track is blank, try the previous. */
  6.2310 +	if (ti.blank) {
  6.2311 +		last_track--;
  6.2312 +		if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti)))
  6.2313 +			goto use_toc;
  6.2314 +	}
  6.2315 +
  6.2316 +	/* if last recorded field is valid, return it. */
  6.2317 +	if (ti.lra_v) {
  6.2318 +		*last_written = be32_to_cpu(ti.last_rec_address);
  6.2319 +	} else {
  6.2320 +		/* make it up instead */
  6.2321 +		*last_written = be32_to_cpu(ti.track_start) +
  6.2322 +				be32_to_cpu(ti.track_size);
  6.2323 +		if (ti.free_blocks)
  6.2324 +			*last_written -= (be32_to_cpu(ti.free_blocks) + 7);
  6.2325 +	}
  6.2326 +	return 0;
  6.2327 +
  6.2328 +	/* this is where we end up if the drive either can't do a
  6.2329 +	   GPCMD_READ_DISC_INFO or GPCMD_READ_TRACK_RZONE_INFO or if
  6.2330 +	   it fails. then we return the toc contents. */
  6.2331 +use_toc:
  6.2332 +	toc.cdte_format = CDROM_MSF;
  6.2333 +	toc.cdte_track = CDROM_LEADOUT;
  6.2334 +	if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &toc))
  6.2335 +		return ret;
  6.2336 +	sanitize_format(&toc.cdte_addr, &toc.cdte_format, CDROM_LBA);
  6.2337 +	*last_written = toc.cdte_addr.lba;
  6.2338 +	return 0;
  6.2339 +}
  6.2340 +
  6.2341 +/* return the next writable block. also for udf file system. */
  6.2342 +int cdrom_get_next_writable(kdev_t dev, long *next_writable)
  6.2343 +{
  6.2344 +	struct cdrom_device_info *cdi = cdrom_find_device(dev);
  6.2345 +	disc_information di;
  6.2346 +	track_information ti;
  6.2347 +	__u16 last_track;
  6.2348 +	int ret = -1;
  6.2349 +
  6.2350 +	if (!CDROM_CAN(CDC_GENERIC_PACKET))
  6.2351 +		goto use_last_written;
  6.2352 +
  6.2353 +	if ((ret = cdrom_get_disc_info(dev, &di)))
  6.2354 +		goto use_last_written;
  6.2355 +
  6.2356 +	last_track = (di.last_track_msb << 8) | di.last_track_lsb;
  6.2357 +	if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti)))
  6.2358 +		goto use_last_written;
  6.2359 +
  6.2360 +        /* if this track is blank, try the previous. */
  6.2361 +	if (ti.blank) {
  6.2362 +		last_track--;
  6.2363 +		if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti)))
  6.2364 +			goto use_last_written;
  6.2365 +	}
  6.2366 +
  6.2367 +	/* if next recordable address field is valid, use it. */
  6.2368 +	if (ti.nwa_v)
  6.2369 +		*next_writable = be32_to_cpu(ti.next_writable);
  6.2370 +	else
  6.2371 +		goto use_last_written;
  6.2372 +
  6.2373 +	return 0;
  6.2374 +
  6.2375 +use_last_written:
  6.2376 +	if ((ret = cdrom_get_last_written(dev, next_writable))) {
  6.2377 +		*next_writable = 0;
  6.2378 +		return ret;
  6.2379 +	} else {
  6.2380 +		*next_writable += 7;
  6.2381 +		return 0;
  6.2382 +	}
  6.2383 +}
  6.2384 +
  6.2385 +EXPORT_SYMBOL(cdrom_get_disc_info);
  6.2386 +EXPORT_SYMBOL(cdrom_get_track_info);
  6.2387 +EXPORT_SYMBOL(cdrom_get_next_writable);
  6.2388 +EXPORT_SYMBOL(cdrom_get_last_written);
  6.2389 +EXPORT_SYMBOL(cdrom_count_tracks);
  6.2390 +EXPORT_SYMBOL(register_cdrom);
  6.2391 +EXPORT_SYMBOL(unregister_cdrom);
  6.2392 +EXPORT_SYMBOL(cdrom_open);
  6.2393 +EXPORT_SYMBOL(cdrom_release);
  6.2394 +EXPORT_SYMBOL(cdrom_ioctl);
  6.2395 +EXPORT_SYMBOL(cdrom_media_changed);
  6.2396 +EXPORT_SYMBOL(cdrom_number_of_slots);
  6.2397 +EXPORT_SYMBOL(cdrom_select_disc);
  6.2398 +EXPORT_SYMBOL(cdrom_mode_select);
  6.2399 +EXPORT_SYMBOL(cdrom_mode_sense);
  6.2400 +EXPORT_SYMBOL(init_cdrom_command);
  6.2401 +EXPORT_SYMBOL(cdrom_find_device);
  6.2402 +
  6.2403 +#ifdef CONFIG_SYSCTL
  6.2404 +
  6.2405 +#define CDROM_STR_SIZE 1000
  6.2406 +
  6.2407 +struct cdrom_sysctl_settings {
  6.2408 +	char	info[CDROM_STR_SIZE];	/* general info */
  6.2409 +	int	autoclose;		/* close tray upon mount, etc */
  6.2410 +	int	autoeject;		/* eject on umount */
  6.2411 +	int	debug;			/* turn on debugging messages */
  6.2412 +	int	lock;			/* lock the door on device open */
  6.2413 +	int	check;			/* check media type */
  6.2414 +} cdrom_sysctl_settings;
  6.2415 +
  6.2416 +int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp,
  6.2417 +                           void *buffer, size_t *lenp)
  6.2418 +{
  6.2419 +        int pos;
  6.2420 +	struct cdrom_device_info *cdi;
  6.2421 +	char *info = cdrom_sysctl_settings.info;
  6.2422 +	
  6.2423 +	if (!*lenp || (filp->f_pos && !write)) {
  6.2424 +		*lenp = 0;
  6.2425 +		return 0;
  6.2426 +	}
  6.2427 +
  6.2428 +	pos = sprintf(info, "CD-ROM information, " VERSION "\n");
  6.2429 +	
  6.2430 +	pos += sprintf(info+pos, "\ndrive name:\t");
  6.2431 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2432 +	    pos += sprintf(info+pos, "\t%s", cdi->name);
  6.2433 +
  6.2434 +	pos += sprintf(info+pos, "\ndrive speed:\t");
  6.2435 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2436 +	    pos += sprintf(info+pos, "\t%d", cdi->speed);
  6.2437 +
  6.2438 +	pos += sprintf(info+pos, "\ndrive # of slots:");
  6.2439 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2440 +	    pos += sprintf(info+pos, "\t%d", cdi->capacity);
  6.2441 +
  6.2442 +	pos += sprintf(info+pos, "\nCan close tray:\t");
  6.2443 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2444 +	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CLOSE_TRAY) != 0);
  6.2445 +
  6.2446 +	pos += sprintf(info+pos, "\nCan open tray:\t");
  6.2447 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2448 +	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_OPEN_TRAY) != 0);
  6.2449 +
  6.2450 +	pos += sprintf(info+pos, "\nCan lock tray:\t");
  6.2451 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2452 +	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_LOCK) != 0);
  6.2453 +
  6.2454 +	pos += sprintf(info+pos, "\nCan change speed:");
  6.2455 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2456 +	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_SPEED) != 0);
  6.2457 +
  6.2458 +	pos += sprintf(info+pos, "\nCan select disk:");
  6.2459 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2460 +	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_DISC) != 0);
  6.2461 +
  6.2462 +	pos += sprintf(info+pos, "\nCan read multisession:");
  6.2463 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2464 +	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MULTI_SESSION) != 0);
  6.2465 +
  6.2466 +	pos += sprintf(info+pos, "\nCan read MCN:\t");
  6.2467 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2468 +	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MCN) != 0);
  6.2469 +
  6.2470 +	pos += sprintf(info+pos, "\nReports media changed:");
  6.2471 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2472 +	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MEDIA_CHANGED) != 0);
  6.2473 +
  6.2474 +	pos += sprintf(info+pos, "\nCan play audio:\t");
  6.2475 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2476 +	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_PLAY_AUDIO) != 0);
  6.2477 +
  6.2478 +	pos += sprintf(info+pos, "\nCan write CD-R:\t");
  6.2479 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2480 +	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_R) != 0);
  6.2481 +
  6.2482 +	pos += sprintf(info+pos, "\nCan write CD-RW:");
  6.2483 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2484 +	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_RW) != 0);
  6.2485 +
  6.2486 +	pos += sprintf(info+pos, "\nCan read DVD:\t");
  6.2487 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2488 +	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD) != 0);
  6.2489 +
  6.2490 +	pos += sprintf(info+pos, "\nCan write DVD-R:");
  6.2491 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2492 +	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_R) != 0);
  6.2493 +
  6.2494 +	pos += sprintf(info+pos, "\nCan write DVD-RAM:");
  6.2495 +	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
  6.2496 +	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0);
  6.2497 +
  6.2498 +	strcpy(info+pos,"\n\n");
  6.2499 +		
  6.2500 +        return proc_dostring(ctl, write, filp, buffer, lenp);
  6.2501 +}
  6.2502 +
  6.2503 +/* Unfortunately, per device settings are not implemented through
  6.2504 +   procfs/sysctl yet. When they are, this will naturally disappear. For now
  6.2505 +   just update all drives. Later this will become the template on which
  6.2506 +   new registered drives will be based. */
  6.2507 +void cdrom_update_settings(void)
  6.2508 +{
  6.2509 +	struct cdrom_device_info *cdi;
  6.2510 +
  6.2511 +	for (cdi = topCdromPtr; cdi != NULL; cdi = cdi->next) {
  6.2512 +		if (autoclose && CDROM_CAN(CDC_CLOSE_TRAY))
  6.2513 +			cdi->options |= CDO_AUTO_CLOSE;
  6.2514 +		else if (!autoclose)
  6.2515 +			cdi->options &= ~CDO_AUTO_CLOSE;
  6.2516 +		if (autoeject && CDROM_CAN(CDC_OPEN_TRAY))
  6.2517 +			cdi->options |= CDO_AUTO_EJECT;
  6.2518 +		else if (!autoeject)
  6.2519 +			cdi->options &= ~CDO_AUTO_EJECT;
  6.2520 +		if (lockdoor && CDROM_CAN(CDC_LOCK))
  6.2521 +			cdi->options |= CDO_LOCK;
  6.2522 +		else if (!lockdoor)
  6.2523 +			cdi->options &= ~CDO_LOCK;
  6.2524 +		if (check_media_type)
  6.2525 +			cdi->options |= CDO_CHECK_TYPE;
  6.2526 +		else
  6.2527 +			cdi->options &= ~CDO_CHECK_TYPE;
  6.2528 +	}
  6.2529 +}
  6.2530 +
  6.2531 +static int cdrom_sysctl_handler(ctl_table *ctl, int write, struct file * filp,
  6.2532 +				void *buffer, size_t *lenp)
  6.2533 +{
  6.2534 +	int *valp = ctl->data;
  6.2535 +	int val = *valp;
  6.2536 +	int ret;
  6.2537 +	
  6.2538 +	ret = proc_dointvec(ctl, write, filp, buffer, lenp);
  6.2539 +
  6.2540 +	if (write && *valp != val) {
  6.2541 +	
  6.2542 +		/* we only care for 1 or 0. */
  6.2543 +		if (*valp)
  6.2544 +			*valp = 1;
  6.2545 +		else
  6.2546 +			*valp = 0;
  6.2547 +
  6.2548 +		switch (ctl->ctl_name) {
  6.2549 +		case DEV_CDROM_AUTOCLOSE: {
  6.2550 +			if (valp == &cdrom_sysctl_settings.autoclose)
  6.2551 +				autoclose = cdrom_sysctl_settings.autoclose;
  6.2552 +			break;
  6.2553 +			}
  6.2554 +		case DEV_CDROM_AUTOEJECT: {
  6.2555 +			if (valp == &cdrom_sysctl_settings.autoeject)
  6.2556 +				autoeject = cdrom_sysctl_settings.autoeject;
  6.2557 +			break;
  6.2558 +			}
  6.2559 +		case DEV_CDROM_DEBUG: {
  6.2560 +			if (valp == &cdrom_sysctl_settings.debug)
  6.2561 +				debug = cdrom_sysctl_settings.debug;
  6.2562 +			break;
  6.2563 +			}
  6.2564 +		case DEV_CDROM_LOCK: {
  6.2565 +			if (valp == &cdrom_sysctl_settings.lock)
  6.2566 +				lockdoor = cdrom_sysctl_settings.lock;
  6.2567 +			break;
  6.2568 +			}
  6.2569 +		case DEV_CDROM_CHECK_MEDIA: {
  6.2570 +			if (valp == &cdrom_sysctl_settings.check)
  6.2571 +				check_media_type = cdrom_sysctl_settings.check;
  6.2572 +			break;
  6.2573 +			}
  6.2574 +		}
  6.2575 +		/* update the option flags according to the changes. we
  6.2576 +		   don't have per device options through sysctl yet,
  6.2577 +		   but we will have and then this will disappear. */
  6.2578 +		cdrom_update_settings();
  6.2579 +	}
  6.2580 +
  6.2581 +        return ret;
  6.2582 +}
  6.2583 +
  6.2584 +/* Place files in /proc/sys/dev/cdrom */
  6.2585 +ctl_table cdrom_table[] = {
  6.2586 +	{DEV_CDROM_INFO, "info", &cdrom_sysctl_settings.info, 
  6.2587 +		CDROM_STR_SIZE, 0444, NULL, &cdrom_sysctl_info},
  6.2588 +	{DEV_CDROM_AUTOCLOSE, "autoclose", &cdrom_sysctl_settings.autoclose,
  6.2589 +		sizeof(int), 0644, NULL, &cdrom_sysctl_handler },
  6.2590 +	{DEV_CDROM_AUTOEJECT, "autoeject", &cdrom_sysctl_settings.autoeject,
  6.2591 +		sizeof(int), 0644, NULL, &cdrom_sysctl_handler },
  6.2592 +	{DEV_CDROM_DEBUG, "debug", &cdrom_sysctl_settings.debug,
  6.2593 +		sizeof(int), 0644, NULL, &cdrom_sysctl_handler },
  6.2594 +	{DEV_CDROM_LOCK, "lock", &cdrom_sysctl_settings.lock,
  6.2595 +		sizeof(int), 0644, NULL, &cdrom_sysctl_handler },
  6.2596 +	{DEV_CDROM_CHECK_MEDIA, "check_media", &cdrom_sysctl_settings.check,
  6.2597 +		sizeof(int), 0644, NULL, &cdrom_sysctl_handler },
  6.2598 +	{0}
  6.2599 +	};
  6.2600 +
  6.2601 +ctl_table cdrom_cdrom_table[] = {
  6.2602 +	{DEV_CDROM, "cdrom", NULL, 0, 0555, cdrom_table},
  6.2603 +	{0}
  6.2604 +	};
  6.2605 +
  6.2606 +/* Make sure that /proc/sys/dev is there */
  6.2607 +ctl_table cdrom_root_table[] = {
  6.2608 +#ifdef CONFIG_PROC_FS
  6.2609 +	{CTL_DEV, "dev", NULL, 0, 0555, cdrom_cdrom_table},
  6.2610 +#endif /* CONFIG_PROC_FS */
  6.2611 +	{0}
  6.2612 +	};
  6.2613 +static struct ctl_table_header *cdrom_sysctl_header;
  6.2614 +
  6.2615 +static void cdrom_sysctl_register(void)
  6.2616 +{
  6.2617 +	static int initialized;
  6.2618 +
  6.2619 +	if (initialized == 1)
  6.2620 +		return;
  6.2621 +
  6.2622 +	cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1);
  6.2623 +	cdrom_root_table->child->de->owner = THIS_MODULE;
  6.2624 +
  6.2625 +	/* set the defaults */
  6.2626 +	cdrom_sysctl_settings.autoclose = autoclose;
  6.2627 +	cdrom_sysctl_settings.autoeject = autoeject;
  6.2628 +	cdrom_sysctl_settings.debug = debug;
  6.2629 +	cdrom_sysctl_settings.lock = lockdoor;
  6.2630 +	cdrom_sysctl_settings.check = check_media_type;
  6.2631 +
  6.2632 +	initialized = 1;
  6.2633 +}
  6.2634 +
  6.2635 +static void cdrom_sysctl_unregister(void)
  6.2636 +{
  6.2637 +	if (cdrom_sysctl_header)
  6.2638 +		unregister_sysctl_table(cdrom_sysctl_header);
  6.2639 +}
  6.2640 +
  6.2641 +#endif /* CONFIG_SYSCTL */
  6.2642 +
  6.2643 +static int __init cdrom_init(void)
  6.2644 +{
  6.2645 +#ifdef CONFIG_SYSCTL
  6.2646 +	cdrom_sysctl_register();
  6.2647 +#endif
  6.2648 +#if 0
  6.2649 +	if (!devfs_handle)
  6.2650 +		devfs_handle = devfs_mk_dir(NULL, "cdroms", NULL);
  6.2651 +#endif
  6.2652 +	return 0;
  6.2653 +}
  6.2654 +
  6.2655 +static void __exit cdrom_exit(void)
  6.2656 +{
  6.2657 +	printk(KERN_INFO "Uniform CD-ROM driver unloaded\n");
  6.2658 +#ifdef CONFIG_SYSCTL
  6.2659 +	cdrom_sysctl_unregister();
  6.2660 +#endif
  6.2661 +#if 0
  6.2662 +	devfs_unregister(devfs_handle);
  6.2663 +#endif
  6.2664 +}
  6.2665 +
  6.2666 +module_init(cdrom_init);
  6.2667 +module_exit(cdrom_exit);
  6.2668 +MODULE_LICENSE("GPL");
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xen/drivers/ide/ide-cd.c	Tue Apr 15 15:26:05 2003 +0000
     7.3 @@ -0,0 +1,3072 @@
     7.4 +/*
     7.5 + * linux/drivers/ide/ide-cd.c
     7.6 + *
     7.7 + * Copyright (C) 1994, 1995, 1996  scott snyder  <snyder@fnald0.fnal.gov>
     7.8 + * Copyright (C) 1996-1998  Erik Andersen <andersee@debian.org>
     7.9 + * Copyright (C) 1998-2000  Jens Axboe <axboe@suse.de>
    7.10 + *
    7.11 + * May be copied or modified under the terms of the GNU General Public
    7.12 + * License.  See linux/COPYING for more information.
    7.13 + *
    7.14 + * ATAPI CD-ROM driver.  To be used with ide.c.
    7.15 + * See Documentation/cdrom/ide-cd for usage information.
    7.16 + *
    7.17 + * Suggestions are welcome. Patches that work are more welcome though. ;-)
    7.18 + * For those wishing to work on this driver, please be sure you download
    7.19 + * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI 
    7.20 + * (SFF-8020i rev 2.6) standards. These documents can be obtained by 
    7.21 + * anonymous ftp from:
    7.22 + * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
    7.23 + * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf
    7.24 + *
    7.25 + * Drives that deviate from these standards will be accomodated as much
    7.26 + * as possible via compile time or command-line options.  Since I only have
    7.27 + * a few drives, you generally need to send me patches...
    7.28 + *
    7.29 + * ----------------------------------
    7.30 + * TO DO LIST:
    7.31 + * -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on
    7.32 + *   boot
    7.33 + *
    7.34 + * ----------------------------------
    7.35 + * 1.00  Oct 31, 1994 -- Initial version.
    7.36 + * 1.01  Nov  2, 1994 -- Fixed problem with starting request in
    7.37 + *                       cdrom_check_status.
    7.38 + * 1.03  Nov 25, 1994 -- leaving unmask_intr[] as a user-setting (as for disks)
    7.39 + * (from mlord)       -- minor changes to cdrom_setup()
    7.40 + *                    -- renamed ide_dev_s to ide_drive_t, enable irq on command
    7.41 + * 2.00  Nov 27, 1994 -- Generalize packet command interface;
    7.42 + *                       add audio ioctls.
    7.43 + * 2.01  Dec  3, 1994 -- Rework packet command interface to handle devices
    7.44 + *                       which send an interrupt when ready for a command.
    7.45 + * 2.02  Dec 11, 1994 -- Cache the TOC in the driver.
    7.46 + *                       Don't use SCMD_PLAYAUDIO_TI; it's not included
    7.47 + *                       in the current version of ATAPI.
    7.48 + *                       Try to use LBA instead of track or MSF addressing
    7.49 + *                       when possible.
    7.50 + *                       Don't wait for READY_STAT.
    7.51 + * 2.03  Jan 10, 1995 -- Rewrite block read routines to handle block sizes
    7.52 + *                       other than 2k and to move multiple sectors in a
    7.53 + *                       single transaction.
    7.54 + * 2.04  Apr 21, 1995 -- Add work-around for Creative Labs CD220E drives.
    7.55 + *                       Thanks to Nick Saw <cwsaw@pts7.pts.mot.com> for
    7.56 + *                       help in figuring this out.  Ditto for Acer and
    7.57 + *                       Aztech drives, which seem to have the same problem.
    7.58 + * 2.04b May 30, 1995 -- Fix to match changes in ide.c version 3.16 -ml
    7.59 + * 2.05  Jun  8, 1995 -- Don't attempt to retry after an illegal request
    7.60 + *                        or data protect error.
    7.61 + *                       Use HWIF and DEV_HWIF macros as in ide.c.
    7.62 + *                       Always try to do a request_sense after
    7.63 + *                        a failed command.
    7.64 + *                       Include an option to give textual descriptions
    7.65 + *                        of ATAPI errors.
    7.66 + *                       Fix a bug in handling the sector cache which
    7.67 + *                        showed up if the drive returned data in 512 byte
    7.68 + *                        blocks (like Pioneer drives).  Thanks to
    7.69 + *                        Richard Hirst <srh@gpt.co.uk> for diagnosing this.
    7.70 + *                       Properly supply the page number field in the
    7.71 + *                        MODE_SELECT command.
    7.72 + *                       PLAYAUDIO12 is broken on the Aztech; work around it.
    7.73 + * 2.05x Aug 11, 1995 -- lots of data structure renaming/restructuring in ide.c
    7.74 + *                       (my apologies to Scott, but now ide-cd.c is independent)
    7.75 + * 3.00  Aug 22, 1995 -- Implement CDROMMULTISESSION ioctl.
    7.76 + *                       Implement CDROMREADAUDIO ioctl (UNTESTED).
    7.77 + *                       Use input_ide_data() and output_ide_data().
    7.78 + *                       Add door locking.
    7.79 + *                       Fix usage count leak in cdrom_open, which happened
    7.80 + *                        when a read-write mount was attempted.
    7.81 + *                       Try to load the disk on open.
    7.82 + *                       Implement CDROMEJECT_SW ioctl (off by default).
    7.83 + *                       Read total cdrom capacity during open.
    7.84 + *                       Rearrange logic in cdrom_decode_status.  Issue
    7.85 + *                        request sense commands for failed packet commands
    7.86 + *                        from here instead of from cdrom_queue_packet_command.
    7.87 + *                        Fix a race condition in retrieving error information.
    7.88 + *                       Suppress printing normal unit attention errors and
    7.89 + *                        some drive not ready errors.
    7.90 + *                       Implement CDROMVOLREAD ioctl.
    7.91 + *                       Implement CDROMREADMODE1/2 ioctls.
    7.92 + *                       Fix race condition in setting up interrupt handlers
    7.93 + *                        when the `serialize' option is used.
    7.94 + * 3.01  Sep  2, 1995 -- Fix ordering of reenabling interrupts in
    7.95 + *                        cdrom_queue_request.
    7.96 + *                       Another try at using ide_[input,output]_data.
    7.97 + * 3.02  Sep 16, 1995 -- Stick total disk capacity in partition table as well.
    7.98 + *                       Make VERBOSE_IDE_CD_ERRORS dump failed command again.
    7.99 + *                       Dump out more information for ILLEGAL REQUEST errs.
   7.100 + *                       Fix handling of errors occurring before the
   7.101 + *                        packet command is transferred.
   7.102 + *                       Fix transfers with odd bytelengths.
   7.103 + * 3.03  Oct 27, 1995 -- Some Creative drives have an id of just `CD'.
   7.104 + *                       `DCI-2S10' drives are broken too.
   7.105 + * 3.04  Nov 20, 1995 -- So are Vertos drives.
   7.106 + * 3.05  Dec  1, 1995 -- Changes to go with overhaul of ide.c and ide-tape.c
   7.107 + * 3.06  Dec 16, 1995 -- Add support needed for partitions.
   7.108 + *                       More workarounds for Vertos bugs (based on patches
   7.109 + *                        from Holger Dietze <dietze@aix520.informatik.uni-leipzig.de>).
   7.110 + *                       Try to eliminate byteorder assumptions.
   7.111 + *                       Use atapi_cdrom_subchnl struct definition.
   7.112 + *                       Add STANDARD_ATAPI compilation option.
   7.113 + * 3.07  Jan 29, 1996 -- More twiddling for broken drives: Sony 55D,
   7.114 + *                        Vertos 300.
   7.115 + *                       Add NO_DOOR_LOCKING configuration option.
   7.116 + *                       Handle drive_cmd requests w/NULL args (for hdparm -t).
   7.117 + *                       Work around sporadic Sony55e audio play problem.
   7.118 + * 3.07a Feb 11, 1996 -- check drive->id for NULL before dereferencing, to fix
   7.119 + *                        problem with "hde=cdrom" with no drive present.  -ml
   7.120 + * 3.08  Mar  6, 1996 -- More Vertos workarounds.
   7.121 + * 3.09  Apr  5, 1996 -- Add CDROMCLOSETRAY ioctl.
   7.122 + *                       Switch to using MSF addressing for audio commands.
   7.123 + *                       Reformat to match kernel tabbing style.
   7.124 + *                       Add CDROM_GET_UPC ioctl.
   7.125 + * 3.10  Apr 10, 1996 -- Fix compilation error with STANDARD_ATAPI.
   7.126 + * 3.11  Apr 29, 1996 -- Patch from Heiko Eissfeldt <heiko@colossus.escape.de>
   7.127 + *                       to remove redundant verify_area calls.
   7.128 + * 3.12  May  7, 1996 -- Rudimentary changer support.  Based on patches
   7.129 + *                        from Gerhard Zuber <zuber@berlin.snafu.de>.
   7.130 + *                       Let open succeed even if there's no loaded disc.
   7.131 + * 3.13  May 19, 1996 -- Fixes for changer code.
   7.132 + * 3.14  May 29, 1996 -- Add work-around for Vertos 600.
   7.133 + *                        (From Hennus Bergman <hennus@sky.ow.nl>.)
   7.134 + * 3.15  July 2, 1996 -- Added support for Sanyo 3 CD changers
   7.135 + *                        from Ben Galliart <bgallia@luc.edu> with 
   7.136 + *                        special help from Jeff Lightfoot 
   7.137 + *                        <jeffml@pobox.com>
   7.138 + * 3.15a July 9, 1996 -- Improved Sanyo 3 CD changer identification
   7.139 + * 3.16  Jul 28, 1996 -- Fix from Gadi to reduce kernel stack usage for ioctl.
   7.140 + * 3.17  Sep 17, 1996 -- Tweak audio reads for some drives.
   7.141 + *                       Start changing CDROMLOADFROMSLOT to CDROM_SELECT_DISC.
   7.142 + * 3.18  Oct 31, 1996 -- Added module and DMA support.
   7.143 + *                       
   7.144 + *                       
   7.145 + * 4.00  Nov 5, 1996   -- New ide-cd maintainer,
   7.146 + *                                 Erik B. Andersen <andersee@debian.org>
   7.147 + *                     -- Newer Creative drives don't always set the error
   7.148 + *                          register correctly.  Make sure we see media changes
   7.149 + *                          regardless.
   7.150 + *                     -- Integrate with generic cdrom driver.
   7.151 + *                     -- CDROMGETSPINDOWN and CDROMSETSPINDOWN ioctls, based on
   7.152 + *                          a patch from Ciro Cattuto <>.
   7.153 + *                     -- Call set_device_ro.
   7.154 + *                     -- Implement CDROMMECHANISMSTATUS and CDROMSLOTTABLE
   7.155 + *                          ioctls, based on patch by Erik Andersen
   7.156 + *                     -- Add some probes of drive capability during setup.
   7.157 + *
   7.158 + * 4.01  Nov 11, 1996  -- Split into ide-cd.c and ide-cd.h
   7.159 + *                     -- Removed CDROMMECHANISMSTATUS and CDROMSLOTTABLE 
   7.160 + *                          ioctls in favor of a generalized approach 
   7.161 + *                          using the generic cdrom driver.
   7.162 + *                     -- Fully integrated with the 2.1.X kernel.
   7.163 + *                     -- Other stuff that I forgot (lots of changes)
   7.164 + *
   7.165 + * 4.02  Dec 01, 1996  -- Applied patch from Gadi Oxman <gadio@netvision.net.il>
   7.166 + *                          to fix the drive door locking problems.
   7.167 + *
   7.168 + * 4.03  Dec 04, 1996  -- Added DSC overlap support.
   7.169 + * 4.04  Dec 29, 1996  -- Added CDROMREADRAW ioclt based on patch 
   7.170 + *                          by Ales Makarov (xmakarov@sun.felk.cvut.cz)
   7.171 + *
   7.172 + * 4.05  Nov 20, 1997  -- Modified to print more drive info on init
   7.173 + *                        Minor other changes
   7.174 + *                        Fix errors on CDROMSTOP (If you have a "Dolphin",
   7.175 + *                          you must define IHAVEADOLPHIN)
   7.176 + *                        Added identifier so new Sanyo CD-changer works
   7.177 + *                        Better detection if door locking isn't supported
   7.178 + *
   7.179 + * 4.06  Dec 17, 1997  -- fixed endless "tray open" messages  -ml
   7.180 + * 4.07  Dec 17, 1997  -- fallback to set pc->stat on "tray open"
   7.181 + * 4.08  Dec 18, 1997  -- spew less noise when tray is empty
   7.182 + *                     -- fix speed display for ACER 24X, 18X
   7.183 + * 4.09  Jan 04, 1998  -- fix handling of the last block so we return
   7.184 + *                         an end of file instead of an I/O error (Gadi)
   7.185 + * 4.10  Jan 24, 1998  -- fixed a bug so now changers can change to a new
   7.186 + *                         slot when there is no disc in the current slot.
   7.187 + *                     -- Fixed a memory leak where info->changer_info was
   7.188 + *                         malloc'ed but never free'd when closing the device.
   7.189 + *                     -- Cleaned up the global namespace a bit by making more
   7.190 + *                         functions static that should already have been.
   7.191 + * 4.11  Mar 12, 1998  -- Added support for the CDROM_SELECT_SPEED ioctl
   7.192 + *                         based on a patch for 2.0.33 by Jelle Foks 
   7.193 + *                         <jelle@scintilla.utwente.nl>, a patch for 2.0.33
   7.194 + *                         by Toni Giorgino <toni@pcape2.pi.infn.it>, the SCSI
   7.195 + *                         version, and my own efforts.  -erik
   7.196 + *                     -- Fixed a stupid bug which egcs was kind enough to
   7.197 + *                         inform me of where "Illegal mode for this track"
   7.198 + *                         was never returned due to a comparison on data
   7.199 + *                         types of limited range.
   7.200 + * 4.12  Mar 29, 1998  -- Fixed bug in CDROM_SELECT_SPEED so write speed is 
   7.201 + *                         now set ionly for CD-R and CD-RW drives.  I had 
   7.202 + *                         removed this support because it produced errors.
   7.203 + *                         It produced errors _only_ for non-writers. duh.
   7.204 + * 4.13  May 05, 1998  -- Suppress useless "in progress of becoming ready"
   7.205 + *                         messages, since this is not an error.
   7.206 + *                     -- Change error messages to be const
   7.207 + *                     -- Remove a "\t" which looks ugly in the syslogs
   7.208 + * 4.14  July 17, 1998 -- Change to pointing to .ps version of ATAPI spec
   7.209 + *                         since the .pdf version doesn't seem to work...
   7.210 + *                     -- Updated the TODO list to something more current.
   7.211 + *
   7.212 + * 4.15  Aug 25, 1998  -- Updated ide-cd.h to respect mechine endianess, 
   7.213 + *                         patch thanks to "Eddie C. Dost" <ecd@skynet.be>
   7.214 + *
   7.215 + * 4.50  Oct 19, 1998  -- New maintainers!
   7.216 + *                         Jens Axboe <axboe@image.dk>
   7.217 + *                         Chris Zwilling <chris@cloudnet.com>
   7.218 + *
   7.219 + * 4.51  Dec 23, 1998  -- Jens Axboe <axboe@image.dk>
   7.220 + *                      - ide_cdrom_reset enabled since the ide subsystem
   7.221 + *                         handles resets fine now. <axboe@image.dk>
   7.222 + *                      - Transfer size fix for Samsung CD-ROMs, thanks to
   7.223 + *                        "Ville Hallik" <ville.hallik@mail.ee>.
   7.224 + *                      - other minor stuff.
   7.225 + *
   7.226 + * 4.52  Jan 19, 1999  -- Jens Axboe <axboe@image.dk>
   7.227 + *                      - Detect DVD-ROM/RAM drives
   7.228 + *
   7.229 + * 4.53  Feb 22, 1999   - Include other model Samsung and one Goldstar
   7.230 + *                         drive in transfer size limit.
   7.231 + *                      - Fix the I/O error when doing eject without a medium
   7.232 + *                         loaded on some drives.
   7.233 + *                      - CDROMREADMODE2 is now implemented through
   7.234 + *                         CDROMREADRAW, since many drives don't support
   7.235 + *                         MODE2 (even though ATAPI 2.6 says they must).
   7.236 + *                      - Added ignore parameter to ide-cd (as a module), eg
   7.237 + *                         	insmod ide-cd ignore='hda hdb'
   7.238 + *                         Useful when using ide-cd in conjunction with
   7.239 + *                         ide-scsi. TODO: non-modular way of doing the
   7.240 + *                         same.
   7.241 + *
   7.242 + * 4.54  Aug 5, 1999	- Support for MMC2 class commands through the generic
   7.243 + *			  packet interface to cdrom.c.
   7.244 + *			- Unified audio ioctl support, most of it.
   7.245 + *			- cleaned up various deprecated verify_area().
   7.246 + *			- Added ide_cdrom_packet() as the interface for
   7.247 + *			  the Uniform generic_packet().
   7.248 + *			- bunch of other stuff, will fill in logs later.
   7.249 + *			- report 1 slot for non-changers, like the other
   7.250 + *			  cd-rom drivers. don't report select disc for
   7.251 + *			  non-changers as well.
   7.252 + *			- mask out audio playing, if the device can't do it.
   7.253 + *
   7.254 + * 4.55  Sep 1, 1999	- Eliminated the rest of the audio ioctls, except
   7.255 + *			  for CDROMREADTOC[ENTRY|HEADER]. Some of the drivers
   7.256 + *			  use this independently of the actual audio handling.
   7.257 + *			  They will disappear later when I get the time to
   7.258 + *			  do it cleanly.
   7.259 + *			- Minimize the TOC reading - only do it when we
   7.260 + *			  know a media change has occurred.
   7.261 + *			- Moved all the CDROMREADx ioctls to the Uniform layer.
   7.262 + *			- Heiko Eissfeldt <heiko@colossus.escape.de> supplied
   7.263 + *			  some fixes for CDI.
   7.264 + *			- CD-ROM leaving door locked fix from Andries
   7.265 + *			  Brouwer <Andries.Brouwer@cwi.nl>
   7.266 + *			- Erik Andersen <andersen@xmission.com> unified
   7.267 + *			  commands across the various drivers and how
   7.268 + *			  sense errors are handled.
   7.269 + *
   7.270 + * 4.56  Sep 12, 1999	- Removed changer support - it is now in the
   7.271 + *			  Uniform layer.
   7.272 + *			- Added partition based multisession handling.
   7.273 + *			- Mode sense and mode select moved to the
   7.274 + *			  Uniform layer.
   7.275 + *			- Fixed a problem with WPI CDS-32X drive - it
   7.276 + *			  failed the capabilities 
   7.277 + *
   7.278 + * 4.57  Apr 7, 2000	- Fixed sense reporting.
   7.279 + *			- Fixed possible oops in ide_cdrom_get_last_session()
   7.280 + *			- Fix locking mania and make ide_cdrom_reset relock
   7.281 + *			- Stop spewing errors to log when magicdev polls with
   7.282 + *			  TEST_UNIT_READY on some drives.
   7.283 + *			- Various fixes from Tobias Ringstrom:
   7.284 + *			  tray if it was locked prior to the reset.
   7.285 + *			  - cdrom_read_capacity returns one frame too little.
   7.286 + *			  - Fix real capacity reporting.
   7.287 + *
   7.288 + * 4.58  May 1, 2000	- Clean up ACER50 stuff.
   7.289 + *			- Fix small problem with ide_cdrom_capacity
   7.290 + *
   7.291 + * 4.59  Aug 11, 2000	- Fix changer problem in cdrom_read_toc, we weren't
   7.292 + *			  correctly sensing a disc change.
   7.293 + *			- Rearranged some code
   7.294 + *			- Use extended sense on drives that support it for
   7.295 + *			  correctly reporting tray status -- from
   7.296 + *			  Michael D Johnson <johnsom@orst.edu>
   7.297 + *
   7.298 + *************************************************************************/
   7.299 + 
   7.300 +#define IDECD_VERSION "4.59"
   7.301 +
   7.302 +#include <xeno/config.h>
   7.303 +#include <xeno/module.h>
   7.304 +#include <xeno/types.h>
   7.305 +#include <xeno/kernel.h>
   7.306 +#include <xeno/delay.h>
   7.307 +#include <xeno/timer.h>
   7.308 +#include <xeno/slab.h>
   7.309 +#include <xeno/interrupt.h>
   7.310 +#include <xeno/errno.h>
   7.311 +#include <xeno/cdrom.h>
   7.312 +#include <xeno/ide.h>
   7.313 +// #include <xeno/completion.h>
   7.314 +
   7.315 +#include <asm/irq.h>
   7.316 +#include <asm/io.h>
   7.317 +#include <asm/byteorder.h>
   7.318 +#include <asm/uaccess.h>
   7.319 +#include <asm/unaligned.h>
   7.320 +
   7.321 +#include "ide-cd.h"
   7.322 +
   7.323 +/****************************************************************************
   7.324 + * Generic packet command support and error handling routines.
   7.325 + */
   7.326 +
   7.327 +/* Mark that we've seen a media change, and invalidate our internal
   7.328 +   buffers. */
   7.329 +static void cdrom_saw_media_change (ide_drive_t *drive)
   7.330 +{
   7.331 +	struct cdrom_info *info = drive->driver_data;
   7.332 +	
   7.333 +	CDROM_STATE_FLAGS (drive)->media_changed = 1;
   7.334 +	CDROM_STATE_FLAGS (drive)->toc_valid = 0;
   7.335 +	info->nsectors_buffered = 0;
   7.336 +}
   7.337 +
   7.338 +static int cdrom_log_sense(ide_drive_t *drive, struct packet_command *pc,
   7.339 +			   struct request_sense *sense)
   7.340 +{
   7.341 +	int log = 0;
   7.342 +
   7.343 +	if (sense == NULL || pc == NULL || pc->quiet)
   7.344 +		return 0;
   7.345 +
   7.346 +	switch (sense->sense_key) {
   7.347 +		case NO_SENSE: case RECOVERED_ERROR:
   7.348 +			break;
   7.349 +		case NOT_READY:
   7.350 +			/*
   7.351 +			 * don't care about tray state messages for
   7.352 +			 * e.g. capacity commands or in-progress or
   7.353 +			 * becoming ready
   7.354 +			 */
   7.355 +			if (sense->asc == 0x3a || sense->asc == 0x04)
   7.356 +				break;
   7.357 +			log = 1;
   7.358 +			break;
   7.359 +		case UNIT_ATTENTION:
   7.360 +			/*
   7.361 +			 * Make good and sure we've seen this potential media
   7.362 +			 * change. Some drives (i.e. Creative) fail to present
   7.363 +			 * the correct sense key in the error register.
   7.364 +			 */
   7.365 +			cdrom_saw_media_change(drive);
   7.366 +			break;
   7.367 +		default:
   7.368 +			log = 1;
   7.369 +			break;
   7.370 +	}
   7.371 +	return log;
   7.372 +}
   7.373 +
   7.374 +static
   7.375 +void cdrom_analyze_sense_data(ide_drive_t *drive,
   7.376 +			      struct packet_command *failed_command,
   7.377 +			      struct request_sense *sense)
   7.378 +{
   7.379 +
   7.380 +	if (!cdrom_log_sense(drive, failed_command, sense))
   7.381 +		return;
   7.382 +
   7.383 +	/*
   7.384 +	 * If a read toc is executed for a CD-R or CD-RW medium where
   7.385 +	 * the first toc has not been recorded yet, it will fail with
   7.386 +	 * 05/24/00 (which is a confusing error)
   7.387 +	 */
   7.388 +	if (failed_command && failed_command->c[0] == GPCMD_READ_TOC_PMA_ATIP)
   7.389 +		if (sense->sense_key == 0x05 && sense->asc == 0x24)
   7.390 +			return;
   7.391 +
   7.392 +#if VERBOSE_IDE_CD_ERRORS
   7.393 +	{
   7.394 +		int i;
   7.395 +		const char *s;
   7.396 +		char buf[80];
   7.397 +
   7.398 +		printk ("ATAPI device %s:\n", drive->name);
   7.399 +		if (sense->error_code==0x70)
   7.400 +			printk("  Error: ");
   7.401 +		else if (sense->error_code==0x71)
   7.402 +			printk("  Deferred Error: ");
   7.403 +		else if (sense->error_code == 0x7f)
   7.404 +			printk("  Vendor-specific Error: ");
   7.405 +		else
   7.406 +			printk("  Unknown Error Type: ");
   7.407 +
   7.408 +		if (sense->sense_key < ARY_LEN(sense_key_texts))
   7.409 +			s = sense_key_texts[sense->sense_key];
   7.410 +		else
   7.411 +			s = "bad sense key!";
   7.412 +
   7.413 +		printk("%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
   7.414 +
   7.415 +		if (sense->asc == 0x40) {
   7.416 +			sprintf(buf, "Diagnostic failure on component 0x%02x",
   7.417 +				 sense->ascq);
   7.418 +			s = buf;
   7.419 +		} else {
   7.420 +			int lo = 0, mid, hi = ARY_LEN(sense_data_texts);
   7.421 +			unsigned long key = (sense->sense_key << 16);
   7.422 +			key |= (sense->asc << 8);
   7.423 +			if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
   7.424 +				key |= sense->ascq;
   7.425 +			s = NULL;
   7.426 +
   7.427 +			while (hi > lo) {
   7.428 +				mid = (lo + hi) / 2;
   7.429 +				if (sense_data_texts[mid].asc_ascq == key ||
   7.430 +				    sense_data_texts[mid].asc_ascq == (0xff0000|key)) {
   7.431 +					s = sense_data_texts[mid].text;
   7.432 +					break;
   7.433 +				}
   7.434 +				else if (sense_data_texts[mid].asc_ascq > key)
   7.435 +					hi = mid;
   7.436 +				else
   7.437 +					lo = mid+1;
   7.438 +			}
   7.439 +		}
   7.440 +
   7.441 +		if (s == NULL) {
   7.442 +			if (sense->asc > 0x80)
   7.443 +				s = "(vendor-specific error)";
   7.444 +			else
   7.445 +				s = "(reserved error code)";
   7.446 +		}
   7.447 +
   7.448 +		printk("  %s -- (asc=0x%02x, ascq=0x%02x)\n",
   7.449 +			s, sense->asc, sense->ascq);
   7.450 +
   7.451 +		if (failed_command != NULL) {
   7.452 +
   7.453 +			int lo=0, mid, hi= ARY_LEN (packet_command_texts);
   7.454 +			s = NULL;
   7.455 +
   7.456 +			while (hi > lo) {
   7.457 +				mid = (lo + hi) / 2;
   7.458 +				if (packet_command_texts[mid].packet_command ==
   7.459 +				    failed_command->c[0]) {
   7.460 +					s = packet_command_texts[mid].text;
   7.461 +					break;
   7.462 +				}
   7.463 +				if (packet_command_texts[mid].packet_command >
   7.464 +				    failed_command->c[0])
   7.465 +					hi = mid;
   7.466 +				else
   7.467 +					lo = mid+1;
   7.468 +			}
   7.469 +
   7.470 +			printk ("  The failed \"%s\" packet command was: \n  \"", s);
   7.471 +			for (i=0; i<sizeof (failed_command->c); i++)
   7.472 +				printk ("%02x ", failed_command->c[i]);
   7.473 +			printk ("\"\n");
   7.474 +		}
   7.475 +
   7.476 +		/* The SKSV bit specifies validity of the sense_key_specific
   7.477 +		 * in the next two commands. It is bit 7 of the first byte.
   7.478 +		 * In the case of NOT_READY, if SKSV is set the drive can
   7.479 +		 * give us nice ETA readings.
   7.480 +		 */
   7.481 +		if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) {
   7.482 +			int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100;
   7.483 +			printk("  Command is %02d%% complete\n", progress / 0xffff);
   7.484 +
   7.485 +		}
   7.486 +
   7.487 +		if (sense->sense_key == ILLEGAL_REQUEST &&
   7.488 +		    (sense->sks[0] & 0x80) != 0) {
   7.489 +			printk("  Error in %s byte %d",
   7.490 +				(sense->sks[0] & 0x40) != 0 ?
   7.491 +				"command packet" : "command data",
   7.492 +				(sense->sks[1] << 8) + sense->sks[2]);
   7.493 +
   7.494 +			if ((sense->sks[0] & 0x40) != 0)
   7.495 +				printk (" bit %d", sense->sks[0] & 0x07);
   7.496 +
   7.497 +			printk ("\n");
   7.498 +		}
   7.499 +	}
   7.500 +
   7.501 +#else /* not VERBOSE_IDE_CD_ERRORS */
   7.502 +
   7.503 +	/* Suppress printing unit attention and `in progress of becoming ready'
   7.504 +	   errors when we're not being verbose. */
   7.505 +
   7.506 +	if (sense->sense_key == UNIT_ATTENTION ||
   7.507 +	    (sense->sense_key == NOT_READY && (sense->asc == 4 ||
   7.508 +						sense->asc == 0x3a)))
   7.509 +		return;
   7.510 +
   7.511 +	printk("%s: error code: 0x%02x  sense_key: 0x%02x  asc: 0x%02x  ascq: 0x%02x\n",
   7.512 +		drive->name,
   7.513 +		sense->error_code, sense->sense_key,
   7.514 +		sense->asc, sense->ascq);
   7.515 +#endif /* not VERBOSE_IDE_CD_ERRORS */
   7.516 +}
   7.517 +
   7.518 +static void cdrom_queue_request_sense(ide_drive_t *drive, 
   7.519 +				      struct completion *wait,
   7.520 +				      struct request_sense *sense,
   7.521 +				      struct packet_command *failed_command)
   7.522 +{
   7.523 +	struct cdrom_info *info		= drive->driver_data;
   7.524 +	struct packet_command *pc	= &info->request_sense_pc;
   7.525 +	struct request *rq;
   7.526 +
   7.527 +	if (sense == NULL)
   7.528 +		sense = &info->sense_data;
   7.529 +
   7.530 +	memset(pc, 0, sizeof(struct packet_command));
   7.531 +	pc->c[0] = GPCMD_REQUEST_SENSE;
   7.532 +	pc->c[4] = pc->buflen = 18;
   7.533 +	pc->buffer = (char *) sense;
   7.534 +	pc->sense = (struct request_sense *) failed_command;
   7.535 +
   7.536 +	/* stuff the sense request in front of our current request */
   7.537 +	rq = &info->request_sense_request;
   7.538 +	ide_init_drive_cmd(rq);
   7.539 +	rq->cmd = REQUEST_SENSE_COMMAND;
   7.540 +	rq->buffer = (char *) pc;
   7.541 +	rq->waiting = wait;
   7.542 +	(void) ide_do_drive_cmd(drive, rq, ide_preempt);
   7.543 +}
   7.544 +
   7.545 +
   7.546 +static void cdrom_end_request (int uptodate, ide_drive_t *drive)
   7.547 +{
   7.548 +	struct request *rq = HWGROUP(drive)->rq;
   7.549 +
   7.550 +	if (rq->cmd == REQUEST_SENSE_COMMAND && uptodate) {
   7.551 +		struct packet_command *pc = (struct packet_command *) rq->buffer;
   7.552 +		cdrom_analyze_sense_data(drive,
   7.553 +			(struct packet_command *) pc->sense,
   7.554 +			(struct request_sense *) (pc->buffer - pc->c[4]));
   7.555 +	}
   7.556 +	if (rq->cmd == READ || rq->cmd == WRITE)
   7.557 +		if (!rq->current_nr_sectors)
   7.558 +			uptodate = 1;
   7.559 +
   7.560 +	ide_end_request (uptodate, HWGROUP(drive));
   7.561 +}
   7.562 +
   7.563 +
   7.564 +/* Returns 0 if the request should be continued.
   7.565 +   Returns 1 if the request was ended. */
   7.566 +static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
   7.567 +				int good_stat, int *stat_ret)
   7.568 +{
   7.569 +	struct request *rq = HWGROUP(drive)->rq;
   7.570 +	int stat, err, sense_key;
   7.571 +	struct packet_command *pc;
   7.572 +	
   7.573 +	/* Check for errors. */
   7.574 +	stat = GET_STAT();
   7.575 +	*stat_ret = stat;
   7.576 +
   7.577 +	if (OK_STAT (stat, good_stat, BAD_R_STAT))
   7.578 +		return 0;
   7.579 +
   7.580 +	/* Get the IDE error register. */
   7.581 +	err = GET_ERR();
   7.582 +	sense_key = err >> 4;
   7.583 +
   7.584 +	if (rq == NULL) {
   7.585 +		printk("%s: missing rq in cdrom_decode_status\n", drive->name);
   7.586 +		*startstop = ide_stopped;
   7.587 +		return 1;
   7.588 +	}
   7.589 +
   7.590 +	if (rq->cmd == REQUEST_SENSE_COMMAND) {
   7.591 +		/* We got an error trying to get sense info
   7.592 +		   from the drive (probably while trying
   7.593 +		   to recover from a former error).  Just give up. */
   7.594 +
   7.595 +		pc = (struct packet_command *) rq->buffer;
   7.596 +		pc->stat = 1;
   7.597 +		cdrom_end_request (1, drive);
   7.598 +		*startstop = ide_error (drive, "request sense failure", stat);
   7.599 +		return 1;
   7.600 +
   7.601 +	} else if (rq->cmd == PACKET_COMMAND) {
   7.602 +		/* All other functions, except for READ. */
   7.603 +		struct completion *wait = NULL;
   7.604 +		pc = (struct packet_command *) rq->buffer;
   7.605 +
   7.606 +		/* Check for tray open. */
   7.607 +		if (sense_key == NOT_READY) {
   7.608 +			cdrom_saw_media_change (drive);
   7.609 +		} else if (sense_key == UNIT_ATTENTION) {
   7.610 +			/* Check for media change. */
   7.611 +			cdrom_saw_media_change (drive);
   7.612 +			/*printk("%s: media changed\n",drive->name);*/
   7.613 +			return 0;
   7.614 +		} else if (!pc->quiet) {
   7.615 +			/* Otherwise, print an error. */
   7.616 +			ide_dump_status(drive, "packet command error", stat);
   7.617 +		}
   7.618 +		
   7.619 +		/* Set the error flag and complete the request.
   7.620 +		   Then, if we have a CHECK CONDITION status,
   7.621 +		   queue a request sense command.  We must be careful,
   7.622 +		   though: we don't want the thread in
   7.623 +		   cdrom_queue_packet_command to wake up until
   7.624 +		   the request sense has completed.  We do this
   7.625 +		   by transferring the semaphore from the packet
   7.626 +		   command request to the request sense request. */
   7.627 +
   7.628 +		if ((stat & ERR_STAT) != 0) {
   7.629 +			wait = rq->waiting;
   7.630 +			rq->waiting = NULL;
   7.631 +		}
   7.632 +
   7.633 +		pc->stat = 1;
   7.634 +		cdrom_end_request (1, drive);
   7.635 +
   7.636 +		if ((stat & ERR_STAT) != 0)
   7.637 +			cdrom_queue_request_sense(drive, wait, pc->sense, pc);
   7.638 +	} else {
   7.639 +		/* Handle errors from READ and WRITE requests. */
   7.640 +
   7.641 +		if (sense_key == NOT_READY) {
   7.642 +			/* Tray open. */
   7.643 +			cdrom_saw_media_change (drive);
   7.644 +
   7.645 +			/* Fail the request. */
   7.646 +			printk ("%s: tray open\n", drive->name);
   7.647 +			cdrom_end_request (0, drive);
   7.648 +		} else if (sense_key == UNIT_ATTENTION) {
   7.649 +			/* Media change. */
   7.650 +			cdrom_saw_media_change (drive);
   7.651 +
   7.652 +			/* Arrange to retry the request.
   7.653 +			   But be sure to give up if we've retried
   7.654 +			   too many times. */
   7.655 +			if (++rq->errors > ERROR_MAX)
   7.656 +				cdrom_end_request (0, drive);
   7.657 +		} else if (sense_key == ILLEGAL_REQUEST ||
   7.658 +			   sense_key == DATA_PROTECT) {
   7.659 +			/* No point in retrying after an illegal
   7.660 +			   request or data protect error.*/
   7.661 +			ide_dump_status (drive, "command error", stat);
   7.662 +			cdrom_end_request (0, drive);
   7.663 +		} else if ((err & ~ABRT_ERR) != 0) {
   7.664 +			/* Go to the default handler
   7.665 +			   for other errors. */
   7.666 +			*startstop = ide_error (drive, "cdrom_decode_status", stat);
   7.667 +			return 1;
   7.668 +		} else if ((++rq->errors > ERROR_MAX)) {
   7.669 +			/* We've racked up too many retries.  Abort. */
   7.670 +			cdrom_end_request (0, drive);
   7.671 +		}
   7.672 +
   7.673 +		/* If we got a CHECK_CONDITION status,
   7.674 +		   queue a request sense command. */
   7.675 +		if ((stat & ERR_STAT) != 0)
   7.676 +			cdrom_queue_request_sense(drive, NULL, NULL, NULL);
   7.677 +	}
   7.678 +
   7.679 +	/* Retry, or handle the next request. */
   7.680 +	*startstop = ide_stopped;
   7.681 +	return 1;
   7.682 +}
   7.683 +
   7.684 +static int cdrom_timer_expiry(ide_drive_t *drive)
   7.685 +{
   7.686 +	struct request *rq = HWGROUP(drive)->rq;
   7.687 +	struct packet_command *pc = (struct packet_command *) rq->buffer;
   7.688 +	unsigned long wait = 0;
   7.689 +
   7.690 +	/*
   7.691 +	 * Some commands are *slow* and normally take a long time to
   7.692 +	 * complete. Usually we can use the ATAPI "disconnect" to bypass
   7.693 +	 * this, but not all commands/drives support that. Let
   7.694 +	 * ide_timer_expiry keep polling us for these.
   7.695 +	 */
   7.696 +	switch (pc->c[0]) {
   7.697 +		case GPCMD_BLANK:
   7.698 +		case GPCMD_FORMAT_UNIT:
   7.699 +		case GPCMD_RESERVE_RZONE_TRACK:
   7.700 +			wait = WAIT_CMD;
   7.701 +			break;
   7.702 +		default:
   7.703 +			wait = 0;
   7.704 +			break;
   7.705 +	}
   7.706 +	return wait;
   7.707 +}
   7.708 +
   7.709 +/* Set up the device registers for transferring a packet command on DEV,
   7.710 +   expecting to later transfer XFERLEN bytes.  HANDLER is the routine
   7.711 +   which actually transfers the command to the drive.  If this is a
   7.712 +   drq_interrupt device, this routine will arrange for HANDLER to be
   7.713 +   called when the interrupt from the drive arrives.  Otherwise, HANDLER
   7.714 +   will be called immediately after the drive is prepared for the transfer. */
   7.715 +
   7.716 +static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
   7.717 +						  int xferlen,
   7.718 +						  ide_handler_t *handler)
   7.719 +{
   7.720 +	ide_startstop_t startstop;
   7.721 +	struct cdrom_info *info = drive->driver_data;
   7.722 +
   7.723 +	/* Wait for the controller to be idle. */
   7.724 +	if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
   7.725 +		return startstop;
   7.726 +
   7.727 +	if (info->dma) {
   7.728 +		if (info->cmd == READ) {
   7.729 +			info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive);
   7.730 +		} else if (info->cmd == WRITE) {
   7.731 +			info->dma = !HWIF(drive)->dmaproc(ide_dma_write, drive);
   7.732 +		} else {
   7.733 +			printk("ide-cd: DMA set, but not allowed\n");
   7.734 +		}
   7.735 +	}
   7.736 +
   7.737 +	/* Set up the controller registers. */
   7.738 +	OUT_BYTE (info->dma, IDE_FEATURE_REG);
   7.739 +	OUT_BYTE (0, IDE_NSECTOR_REG);
   7.740 +	OUT_BYTE (0, IDE_SECTOR_REG);
   7.741 +
   7.742 +	OUT_BYTE (xferlen & 0xff, IDE_LCYL_REG);
   7.743 +	OUT_BYTE (xferlen >> 8  , IDE_HCYL_REG);
   7.744 +	if (IDE_CONTROL_REG)
   7.745 +		OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
   7.746 + 
   7.747 +	if (info->dma)
   7.748 +		(void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
   7.749 +
   7.750 +	if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
   7.751 +		ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry);
   7.752 +		OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
   7.753 +		return ide_started;
   7.754 +	} else {
   7.755 +		OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
   7.756 +		return (*handler) (drive);
   7.757 +	}
   7.758 +}
   7.759 +
   7.760 +/* Send a packet command to DRIVE described by CMD_BUF and CMD_LEN.
   7.761 +   The device registers must have already been prepared
   7.762 +   by cdrom_start_packet_command.
   7.763 +   HANDLER is the interrupt handler to call when the command completes
   7.764 +   or there's data ready. */
   7.765 +/*
   7.766 + * changed 5 parameters to 3 for dvd-ram
   7.767 + * struct packet_command *pc; now packet_command_t *pc;
   7.768 + */
   7.769 +static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
   7.770 +					  struct packet_command *pc,
   7.771 +					  ide_handler_t *handler)
   7.772 +{
   7.773 +	unsigned char *cmd_buf	= pc->c;
   7.774 +	int cmd_len		= sizeof(pc->c);
   7.775 +	unsigned int timeout	= pc->timeout;
   7.776 +	ide_startstop_t startstop;
   7.777 +
   7.778 +	if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
   7.779 +		/* Here we should have been called after receiving an interrupt
   7.780 +		   from the device.  DRQ should how be set. */
   7.781 +		int stat_dum;
   7.782 +
   7.783 +		/* Check for errors. */
   7.784 +		if (cdrom_decode_status (&startstop, drive, DRQ_STAT, &stat_dum))
   7.785 +			return startstop;
   7.786 +	} else {
   7.787 +		/* Otherwise, we must wait for DRQ to get set. */
   7.788 +		if (ide_wait_stat (&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY))
   7.789 +			return startstop;
   7.790 +	}
   7.791 +
   7.792 +	/* Arm the interrupt handler. */
   7.793 +	ide_set_handler (drive, handler, timeout, cdrom_timer_expiry);
   7.794 +
   7.795 +	/* Send the command to the device. */
   7.796 +	atapi_output_bytes (drive, cmd_buf, cmd_len);
   7.797 +	return ide_started;
   7.798 +}
   7.799 +
   7.800 +/****************************************************************************
   7.801 + * Block read functions.
   7.802 + */
   7.803 +
   7.804 +/*
   7.805 + * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector
   7.806 + * buffer.  Once the first sector is added, any subsequent sectors are
   7.807 + * assumed to be continuous (until the buffer is cleared).  For the first
   7.808 + * sector added, SECTOR is its sector number.  (SECTOR is then ignored until
   7.809 + * the buffer is cleared.)
   7.810 + */
   7.811 +static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
   7.812 +                                  int sectors_to_transfer)
   7.813 +{
   7.814 +	struct cdrom_info *info = drive->driver_data;
   7.815 +
   7.816 +	/* Number of sectors to read into the buffer. */
   7.817 +	int sectors_to_buffer = MIN (sectors_to_transfer,
   7.818 +				     (SECTOR_BUFFER_SIZE >> SECTOR_BITS) -
   7.819 +				       info->nsectors_buffered);
   7.820 +
   7.821 +	char *dest;
   7.822 +
   7.823 +	/* If we couldn't get a buffer, don't try to buffer anything... */
   7.824 +	if (info->buffer == NULL)
   7.825 +		sectors_to_buffer = 0;
   7.826 +
   7.827 +	/* If this is the first sector in the buffer, remember its number. */
   7.828 +	if (info->nsectors_buffered == 0)
   7.829 +		info->sector_buffered = sector;
   7.830 +
   7.831 +	/* Read the data into the buffer. */
   7.832 +	dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE;
   7.833 +	while (sectors_to_buffer > 0) {
   7.834 +		atapi_input_bytes (drive, dest, SECTOR_SIZE);
   7.835 +		--sectors_to_buffer;
   7.836 +		--sectors_to_transfer;
   7.837 +		++info->nsectors_buffered;
   7.838 +		dest += SECTOR_SIZE;
   7.839 +	}
   7.840 +
   7.841 +	/* Throw away any remaining data. */
   7.842 +	while (sectors_to_transfer > 0) {
   7.843 +		char dum[SECTOR_SIZE];
   7.844 +		atapi_input_bytes (drive, dum, sizeof (dum));
   7.845 +		--sectors_to_transfer;
   7.846 +	}
   7.847 +}
   7.848 +
   7.849 +/*
   7.850 + * Check the contents of the interrupt reason register from the cdrom
   7.851 + * and attempt to recover if there are problems.  Returns  0 if everything's
   7.852 + * ok; nonzero if the request has been terminated.
   7.853 + */
   7.854 +static inline
   7.855 +int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
   7.856 +{
   7.857 +	ireason &= 3;
   7.858 +	if (ireason == 2) return 0;
   7.859 +
   7.860 +	if (ireason == 0) {
   7.861 +		/* Whoops... The drive is expecting to receive data from us! */
   7.862 +		printk ("%s: cdrom_read_intr: "
   7.863 +			"Drive wants to transfer data the wrong way!\n",
   7.864 +			drive->name);
   7.865 +
   7.866 +		/* Throw some data at the drive so it doesn't hang
   7.867 +		   and quit this request. */
   7.868 +		while (len > 0) {
   7.869 +			int dum = 0;
   7.870 +			atapi_output_bytes (drive, &dum, sizeof (dum));
   7.871 +			len -= sizeof (dum);
   7.872 +		}
   7.873 +	} else  if (ireason == 1) {
   7.874 +		/* Some drives (ASUS) seem to tell us that status
   7.875 +		 * info is available. just get it and ignore.
   7.876 +		 */
   7.877 +		GET_STAT();
   7.878 +		return 0;
   7.879 +	} else {
   7.880 +		/* Drive wants a command packet, or invalid ireason... */
   7.881 +		printk ("%s: cdrom_read_intr: bad interrupt reason %d\n",
   7.882 +			drive->name, ireason);
   7.883 +	}
   7.884 +
   7.885 +	cdrom_end_request (0, drive);
   7.886 +	return -1;
   7.887 +}
   7.888 +
   7.889 +/*
   7.890 + * Interrupt routine.  Called when a read request has completed.
   7.891 + */
   7.892 +static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
   7.893 +{
   7.894 +	int stat;
   7.895 +	int ireason, len, sectors_to_transfer, nskip;
   7.896 +	struct cdrom_info *info = drive->driver_data;
   7.897 +	int i, dma = info->dma, dma_error = 0;
   7.898 +	ide_startstop_t startstop;
   7.899 +
   7.900 +	struct request *rq = HWGROUP(drive)->rq;
   7.901 +
   7.902 +	/* Check for errors. */
   7.903 +	if (dma) {
   7.904 +		info->dma = 0;
   7.905 +		if ((dma_error = HWIF(drive)->dmaproc(ide_dma_end, drive)))
   7.906 +			HWIF(drive)->dmaproc(ide_dma_off, drive);
   7.907 +	}
   7.908 +
   7.909 +	if (cdrom_decode_status (&startstop, drive, 0, &stat))
   7.910 +		return startstop;
   7.911 + 
   7.912 +	if (dma) {
   7.913 +		if (!dma_error) {
   7.914 +			for (i = rq->nr_sectors; i > 0;) {
   7.915 +				i -= rq->current_nr_sectors;
   7.916 +				ide_end_request(1, HWGROUP(drive));
   7.917 +			}
   7.918 +			return ide_stopped;
   7.919 +		} else
   7.920 +			return ide_error (drive, "dma error", stat);
   7.921 +	}
   7.922 +
   7.923 +	/* Read the interrupt reason and the transfer length. */
   7.924 +	ireason = IN_BYTE (IDE_NSECTOR_REG);
   7.925 +	len = IN_BYTE (IDE_LCYL_REG) + 256 * IN_BYTE (IDE_HCYL_REG);
   7.926 +
   7.927 +	/* If DRQ is clear, the command has completed. */
   7.928 +	if ((stat & DRQ_STAT) == 0) {
   7.929 +		/* If we're not done filling the current buffer, complain.
   7.930 +		   Otherwise, complete the command normally. */
   7.931 +		if (rq->current_nr_sectors > 0) {
   7.932 +			printk ("%s: cdrom_read_intr: data underrun (%ld blocks)\n",
   7.933 +				drive->name, rq->current_nr_sectors);
   7.934 +			cdrom_end_request (0, drive);
   7.935 +		} else
   7.936 +			cdrom_end_request (1, drive);
   7.937 +		return ide_stopped;
   7.938 +	}
   7.939 +
   7.940 +	/* Check that the drive is expecting to do the same thing we are. */
   7.941 +	if (cdrom_read_check_ireason (drive, len, ireason))
   7.942 +		return ide_stopped;
   7.943 +
   7.944 +	/* Assume that the drive will always provide data in multiples
   7.945 +	   of at least SECTOR_SIZE, as it gets hairy to keep track
   7.946 +	   of the transfers otherwise. */
   7.947 +	if ((len % SECTOR_SIZE) != 0) {
   7.948 +		printk ("%s: cdrom_read_intr: Bad transfer size %d\n",
   7.949 +			drive->name, len);
   7.950 +		if (CDROM_CONFIG_FLAGS (drive)->limit_nframes)
   7.951 +			printk ("  This drive is not supported by this version of the driver\n");
   7.952 +		else {
   7.953 +			printk ("  Trying to limit transfer sizes\n");
   7.954 +			CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
   7.955 +		}
   7.956 +		cdrom_end_request (0, drive);
   7.957 +		return ide_stopped;
   7.958 +	}
   7.959 +
   7.960 +	/* The number of sectors we need to read from the drive. */
   7.961 +	sectors_to_transfer = len / SECTOR_SIZE;
   7.962 +
   7.963 +	/* First, figure out if we need to bit-bucket
   7.964 +	   any of the leading sectors. */
   7.965 +	nskip = MIN ((int)(rq->current_nr_sectors - (rq->bh->b_size >> SECTOR_BITS)),
   7.966 +		     sectors_to_transfer);
   7.967 +
   7.968 +	while (nskip > 0) {
   7.969 +		/* We need to throw away a sector. */
   7.970 +		char dum[SECTOR_SIZE];
   7.971 +		atapi_input_bytes (drive, dum, sizeof (dum));
   7.972 +
   7.973 +		--rq->current_nr_sectors;
   7.974 +		--nskip;
   7.975 +		--sectors_to_transfer;
   7.976 +	}
   7.977 +
   7.978 +	/* Now loop while we still have data to read from the drive. */
   7.979 +	while (sectors_to_transfer > 0) {
   7.980 +		int this_transfer;
   7.981 +
   7.982 +		/* If we've filled the present buffer but there's another
   7.983 +		   chained buffer after it, move on. */
   7.984 +		if (rq->current_nr_sectors == 0 && rq->nr_sectors)
   7.985 +			cdrom_end_request (1, drive);
   7.986 +
   7.987 +		/* If the buffers are full, cache the rest of the data in our
   7.988 +		   internal buffer. */
   7.989 +		if (rq->current_nr_sectors == 0) {
   7.990 +			cdrom_buffer_sectors(drive, rq->sector, sectors_to_transfer);
   7.991 +			sectors_to_transfer = 0;
   7.992 +		} else {
   7.993 +			/* Transfer data to the buffers.
   7.994 +			   Figure out how many sectors we can transfer
   7.995 +			   to the current buffer. */
   7.996 +			this_transfer = MIN (sectors_to_transfer,
   7.997 +					     rq->current_nr_sectors);
   7.998 +
   7.999 +			/* Read this_transfer sectors
  7.1000 +			   into the current buffer. */
  7.1001 +			while (this_transfer > 0) {
  7.1002 +				atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE);
  7.1003 +				rq->buffer += SECTOR_SIZE;
  7.1004 +				--rq->nr_sectors;
  7.1005 +				--rq->current_nr_sectors;
  7.1006 +				++rq->sector;
  7.1007 +				--this_transfer;
  7.1008 +				--sectors_to_transfer;
  7.1009 +			}
  7.1010 +		}
  7.1011 +	}
  7.1012 +
  7.1013 +	/* Done moving data!
  7.1014 +	   Wait for another interrupt. */
  7.1015 +	ide_set_handler(drive, &cdrom_read_intr, WAIT_CMD, NULL);
  7.1016 +	return ide_started;
  7.1017 +}
  7.1018 +
  7.1019 +/*
  7.1020 + * Try to satisfy some of the current read request from our cached data.
  7.1021 + * Returns nonzero if the request has been completed, zero otherwise.
  7.1022 + */
  7.1023 +static int cdrom_read_from_buffer (ide_drive_t *drive)
  7.1024 +{
  7.1025 +	struct cdrom_info *info = drive->driver_data;
  7.1026 +	struct request *rq = HWGROUP(drive)->rq;
  7.1027 +
  7.1028 +	/* Can't do anything if there's no buffer. */
  7.1029 +	if (info->buffer == NULL) return 0;
  7.1030 +
  7.1031 +	/* Loop while this request needs data and the next block is present
  7.1032 +	   in our cache. */
  7.1033 +	while (rq->nr_sectors > 0 &&
  7.1034 +	       rq->sector >= info->sector_buffered &&
  7.1035 +	       rq->sector < info->sector_buffered + info->nsectors_buffered) {
  7.1036 +		if (rq->current_nr_sectors == 0)
  7.1037 +			cdrom_end_request (1, drive);
  7.1038 +
  7.1039 +		memcpy (rq->buffer,
  7.1040 +			info->buffer +
  7.1041 +			(rq->sector - info->sector_buffered) * SECTOR_SIZE,
  7.1042 +			SECTOR_SIZE);
  7.1043 +		rq->buffer += SECTOR_SIZE;
  7.1044 +		--rq->current_nr_sectors;
  7.1045 +		--rq->nr_sectors;
  7.1046 +		++rq->sector;
  7.1047 +	}
  7.1048 +
  7.1049 +	/* If we've satisfied the current request,
  7.1050 +	   terminate it successfully. */
  7.1051 +	if (rq->nr_sectors == 0) {
  7.1052 +		cdrom_end_request (1, drive);
  7.1053 +		return -1;
  7.1054 +	}
  7.1055 +
  7.1056 +	/* Move on to the next buffer if needed. */
  7.1057 +	if (rq->current_nr_sectors == 0)
  7.1058 +		cdrom_end_request (1, drive);
  7.1059 +
  7.1060 +	/* If this condition does not hold, then the kluge i use to
  7.1061 +	   represent the number of sectors to skip at the start of a transfer
  7.1062 +	   will fail.  I think that this will never happen, but let's be
  7.1063 +	   paranoid and check. */
  7.1064 +	if (rq->current_nr_sectors < (rq->bh->b_size >> SECTOR_BITS) &&
  7.1065 +	    (rq->sector % SECTORS_PER_FRAME) != 0) {
  7.1066 +		printk ("%s: cdrom_read_from_buffer: buffer botch (%ld)\n",
  7.1067 +			drive->name, rq->sector);
  7.1068 +		cdrom_end_request (0, drive);
  7.1069 +		return -1;
  7.1070 +	}
  7.1071 +
  7.1072 +	return 0;
  7.1073 +}
  7.1074 +
  7.1075 +/*
  7.1076 + * Routine to send a read packet command to the drive.
  7.1077 + * This is usually called directly from cdrom_start_read.
  7.1078 + * However, for drq_interrupt devices, it is called from an interrupt
  7.1079 + * when the drive is ready to accept the command.
  7.1080 + */
  7.1081 +static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive)
  7.1082 +{
  7.1083 +	struct packet_command pc;
  7.1084 +	struct request *rq = HWGROUP(drive)->rq;
  7.1085 +	int nsect, sector, nframes, frame, nskip;
  7.1086 +
  7.1087 +	/* Number of sectors to transfer. */
  7.1088 +	nsect = rq->nr_sectors;
  7.1089 +
  7.1090 +	/* Starting sector. */
  7.1091 +	sector = rq->sector;
  7.1092 +
  7.1093 +	/* If the requested sector doesn't start on a cdrom block boundary,
  7.1094 +	   we must adjust the start of the transfer so that it does,
  7.1095 +	   and remember to skip the first few sectors.
  7.1096 +	   If the CURRENT_NR_SECTORS field is larger than the size
  7.1097 +	   of the buffer, it will mean that we're to skip a number
  7.1098 +	   of sectors equal to the amount by which CURRENT_NR_SECTORS
  7.1099 +	   is larger than the buffer size. */
  7.1100 +	nskip = (sector % SECTORS_PER_FRAME);
  7.1101 +	if (nskip > 0) {
  7.1102 +		/* Sanity check... */
  7.1103 +		if (rq->current_nr_sectors != (rq->bh->b_size >> SECTOR_BITS) &&
  7.1104 +			(rq->sector % CD_FRAMESIZE != 0)) {
  7.1105 +			printk ("%s: cdrom_start_read_continuation: buffer botch (%lu)\n",
  7.1106 +				drive->name, rq->current_nr_sectors);
  7.1107 +			cdrom_end_request (0, drive);
  7.1108 +			return ide_stopped;
  7.1109 +		}
  7.1110 +		sector -= nskip;
  7.1111 +		nsect += nskip;
  7.1112 +		rq->current_nr_sectors += nskip;
  7.1113 +	}
  7.1114 +
  7.1115 +	/* Convert from sectors to cdrom blocks, rounding up the transfer
  7.1116 +	   length if needed. */
  7.1117 +	nframes = (nsect + SECTORS_PER_FRAME-1) / SECTORS_PER_FRAME;
  7.1118 +	frame = sector / SECTORS_PER_FRAME;
  7.1119 +
  7.1120 +	/* Largest number of frames was can transfer at once is 64k-1. For
  7.1121 +	   some drives we need to limit this even more. */
  7.1122 +	nframes = MIN (nframes, (CDROM_CONFIG_FLAGS (drive)->limit_nframes) ?
  7.1123 +		(65534 / CD_FRAMESIZE) : 65535);
  7.1124 +
  7.1125 +	/* Set up the command */
  7.1126 +	memset (&pc.c, 0, sizeof (pc.c));
  7.1127 +	pc.c[0] = GPCMD_READ_10;
  7.1128 +	pc.c[7] = (nframes >> 8);
  7.1129 +	pc.c[8] = (nframes & 0xff);
  7.1130 +	put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]);
  7.1131 +	pc.timeout = WAIT_CMD;
  7.1132 +
  7.1133 +	/* Send the command to the drive and return. */
  7.1134 +	return cdrom_transfer_packet_command(drive, &pc, &cdrom_read_intr);
  7.1135 +}
  7.1136 +
  7.1137 +
  7.1138 +#define IDECD_SEEK_THRESHOLD	(1000)			/* 1000 blocks */
  7.1139 +#define IDECD_SEEK_TIMER	(5 * WAIT_MIN_SLEEP)	/* 100 ms */
  7.1140 +#define IDECD_SEEK_TIMEOUT     WAIT_CMD			/* 10 sec */
  7.1141 +
  7.1142 +static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
  7.1143 +{
  7.1144 +	struct cdrom_info *info = drive->driver_data;
  7.1145 +	int stat;
  7.1146 +	static int retry = 10;
  7.1147 +	ide_startstop_t startstop;
  7.1148 +
  7.1149 +	if (cdrom_decode_status (&startstop, drive, 0, &stat))
  7.1150 +		return startstop;
  7.1151 +	CDROM_CONFIG_FLAGS(drive)->seeking = 1;
  7.1152 +
  7.1153 +	if (retry && jiffies - info->start_seek > IDECD_SEEK_TIMER) {
  7.1154 +		if (--retry == 0) {
  7.1155 +			/*
  7.1156 +			 * this condition is far too common, to bother
  7.1157 +			 * users about it
  7.1158 +			 */
  7.1159 +#if 0
  7.1160 +			printk("%s: disabled DSC seek overlap\n", drive->name);
  7.1161 +#endif
  7.1162 +			drive->dsc_overlap = 0;
  7.1163 +		}
  7.1164 +	}
  7.1165 +	return ide_stopped;
  7.1166 +}
  7.1167 +
  7.1168 +static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
  7.1169 +{
  7.1170 +	struct packet_command pc;
  7.1171 +	struct request *rq = HWGROUP(drive)->rq;
  7.1172 +	int sector, frame, nskip;
  7.1173 +
  7.1174 +	sector = rq->sector;
  7.1175 +	nskip = (sector % SECTORS_PER_FRAME);
  7.1176 +	if (nskip > 0)
  7.1177 +		sector -= nskip;
  7.1178 +	frame = sector / SECTORS_PER_FRAME;
  7.1179 +
  7.1180 +	memset (&pc.c, 0, sizeof (pc.c));
  7.1181 +	pc.c[0] = GPCMD_SEEK;
  7.1182 +	put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]);
  7.1183 +
  7.1184 +	pc.timeout = WAIT_CMD;
  7.1185 +	return cdrom_transfer_packet_command(drive, &pc, &cdrom_seek_intr);
  7.1186 +}
  7.1187 +
  7.1188 +static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block)
  7.1189 +{
  7.1190 +	struct cdrom_info *info = drive->driver_data;
  7.1191 +
  7.1192 +	info->dma = 0;
  7.1193 +	info->cmd = 0;
  7.1194 +	info->start_seek = jiffies;
  7.1195 +	return cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation);
  7.1196 +}
  7.1197 +
  7.1198 +static inline int cdrom_merge_requests(struct request *rq, struct request *nxt)
  7.1199 +{
  7.1200 +	int ret = 1;
  7.1201 +
  7.1202 +	/*
  7.1203 +	 * partitions not really working, but better check anyway...
  7.1204 +	 */
  7.1205 +	if (rq->cmd == nxt->cmd && rq->rq_dev == nxt->rq_dev) {
  7.1206 +		rq->nr_sectors += nxt->nr_sectors;
  7.1207 +		rq->hard_nr_sectors += nxt->nr_sectors;
  7.1208 +		rq->bhtail->b_reqnext = nxt->bh;
  7.1209 +		rq->bhtail = nxt->bhtail;
  7.1210 +		list_del(&nxt->queue);
  7.1211 +		blkdev_release_request(nxt);
  7.1212 +		ret = 0;
  7.1213 +	}
  7.1214 +
  7.1215 +	return ret;
  7.1216 +}
  7.1217 +
  7.1218 +/*
  7.1219 + * the current request will always be the first one on the list
  7.1220 + */
  7.1221 +static void cdrom_attempt_remerge(ide_drive_t *drive, struct request *rq)
  7.1222 +{
  7.1223 +	struct list_head *entry;
  7.1224 +	struct request *nxt;
  7.1225 +	unsigned long flags;
  7.1226 +
  7.1227 +	spin_lock_irqsave(&io_request_lock, flags);
  7.1228 +
  7.1229 +	while (1) {
  7.1230 +		entry = rq->queue.next;
  7.1231 +		if (entry == &drive->queue.queue_head)
  7.1232 +			break;
  7.1233 +
  7.1234 +		nxt = blkdev_entry_to_request(entry);
  7.1235 +		if (rq->sector + rq->nr_sectors != nxt->sector)
  7.1236 +			break;
  7.1237 +		else if (rq->nr_sectors + nxt->nr_sectors > SECTORS_MAX)
  7.1238 +			break;
  7.1239 +
  7.1240 +		if (cdrom_merge_requests(rq, nxt))
  7.1241 +			break;
  7.1242 +	}
  7.1243 +
  7.1244 +	spin_unlock_irqrestore(&io_request_lock, flags);
  7.1245 +}
  7.1246 +
  7.1247 +/* Fix up a possibly partially-processed request so that we can
  7.1248 +   start it over entirely, or even put it back on the request queue. */
  7.1249 +static void restore_request (struct request *rq)
  7.1250 +{
  7.1251 +	if (rq->buffer != rq->bh->b_data) {
  7.1252 +		int n = (rq->buffer - rq->bh->b_data) / SECTOR_SIZE;
  7.1253 +		rq->buffer = rq->bh->b_data;
  7.1254 +		rq->nr_sectors += n;
  7.1255 +		rq->sector -= n;
  7.1256 +	}
  7.1257 +	rq->current_nr_sectors = rq->bh->b_size >> SECTOR_BITS;
  7.1258 +	rq->hard_nr_sectors = rq->nr_sectors;
  7.1259 +	rq->hard_sector = rq->sector;
  7.1260 +}
  7.1261 +
  7.1262 +/*
  7.1263 + * Start a read request from the CD-ROM.
  7.1264 + */
  7.1265 +static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block)
  7.1266 +{
  7.1267 +	struct cdrom_info *info = drive->driver_data;
  7.1268 +	struct request *rq = HWGROUP(drive)->rq;
  7.1269 +	int minor = MINOR (rq->rq_dev);
  7.1270 +
  7.1271 +	/* If the request is relative to a partition, fix it up to refer to the
  7.1272 +	   absolute address.  */
  7.1273 +	if (minor & PARTN_MASK) {
  7.1274 +		rq->sector = block;
  7.1275 +		minor &= ~PARTN_MASK;
  7.1276 +		rq->rq_dev = MKDEV(MAJOR(rq->rq_dev), minor);
  7.1277 +	}
  7.1278 +
  7.1279 +	/* We may be retrying this request after an error.  Fix up
  7.1280 +	   any weirdness which might be present in the request packet. */
  7.1281 +	restore_request(rq);
  7.1282 +
  7.1283 +	/* Satisfy whatever we can of this request from our cached sector. */
  7.1284 +	if (cdrom_read_from_buffer(drive))
  7.1285 +		return ide_stopped;
  7.1286 +
  7.1287 +	cdrom_attempt_remerge(drive, rq);
  7.1288 +
  7.1289 +	/* Clear the local sector buffer. */
  7.1290 +	info->nsectors_buffered = 0;
  7.1291 +
  7.1292 +	/* use dma, if possible. */
  7.1293 +	if (drive->using_dma && (rq->sector % SECTORS_PER_FRAME == 0) &&
  7.1294 +				(rq->nr_sectors % SECTORS_PER_FRAME == 0))
  7.1295 +		info->dma = 1;
  7.1296 +	else
  7.1297 +		info->dma = 0;
  7.1298 +
  7.1299 +	info->cmd = READ;
  7.1300 +	/* Start sending the read request to the drive. */
  7.1301 +	return cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation);
  7.1302 +}
  7.1303 +
  7.1304 +/****************************************************************************
  7.1305 + * Execute all other packet commands.
  7.1306 + */
  7.1307 +
  7.1308 +/* Forward declarations. */
  7.1309 +static int cdrom_lockdoor(ide_drive_t *drive, int lockflag,
  7.1310 +			  struct request_sense *sense);
  7.1311 +
  7.1312 +/* Interrupt routine for packet command completion. */
  7.1313 +static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
  7.1314 +{
  7.1315 +	int ireason, len, stat, thislen;
  7.1316 +	struct request *rq = HWGROUP(drive)->rq;
  7.1317 +	struct packet_command *pc = (struct packet_command *)rq->buffer;
  7.1318 +	ide_startstop_t startstop;
  7.1319 +
  7.1320 +	/* Check for errors. */
  7.1321 +	if (cdrom_decode_status (&startstop, drive, 0, &stat))
  7.1322 +		return startstop;
  7.1323 +
  7.1324 +	/* Read the interrupt reason and the transfer length. */
  7.1325 +	ireason = IN_BYTE (IDE_NSECTOR_REG);
  7.1326 +	len = IN_BYTE (IDE_LCYL_REG) + 256 * IN_BYTE (IDE_HCYL_REG);
  7.1327 +
  7.1328 +	/* If DRQ is clear, the command has completed.
  7.1329 +	   Complain if we still have data left to transfer. */
  7.1330 +	if ((stat & DRQ_STAT) == 0) {
  7.1331 +		/* Some of the trailing request sense fields are optional, and
  7.1332 +		   some drives don't send them.  Sigh. */
  7.1333 +		if (pc->c[0] == GPCMD_REQUEST_SENSE &&
  7.1334 +		    pc->buflen > 0 &&
  7.1335 +		    pc->buflen <= 5) {
  7.1336 +			while (pc->buflen > 0) {
  7.1337 +				*pc->buffer++ = 0;
  7.1338 +				--pc->buflen;
  7.1339 +			}
  7.1340 +		}
  7.1341 +
  7.1342 +		if (pc->buflen == 0)
  7.1343 +			cdrom_end_request (1, drive);
  7.1344 +		else {
  7.1345 +			/* Comment this out, because this always happens 
  7.1346 +			   right after a reset occurs, and it is annoying to 
  7.1347 +			   always print expected stuff.  */
  7.1348 +			/*
  7.1349 +			printk ("%s: cdrom_pc_intr: data underrun %d\n",
  7.1350 +				drive->name, pc->buflen);
  7.1351 +			*/
  7.1352 +			pc->stat = 1;
  7.1353 +			cdrom_end_request (1, drive);
  7.1354 +		}
  7.1355 +		return ide_stopped;
  7.1356 +	}
  7.1357 +
  7.1358 +	/* Figure out how much data to transfer. */
  7.1359 +	thislen = pc->buflen;
  7.1360 +	if (thislen > len) thislen = len;
  7.1361 +
  7.1362 +	/* The drive wants to be written to. */
  7.1363 +	if ((ireason & 3) == 0) {
  7.1364 +		/* Transfer the data. */
  7.1365 +		atapi_output_bytes (drive, pc->buffer, thislen);
  7.1366 +
  7.1367 +		/* If we haven't moved enough data to satisfy the drive,
  7.1368 +		   add some padding. */
  7.1369 +		while (len > thislen) {
  7.1370 +			int dum = 0;
  7.1371 +			atapi_output_bytes (drive, &dum, sizeof (dum));
  7.1372 +			len -= sizeof (dum);
  7.1373 +		}
  7.1374 +
  7.1375 +		/* Keep count of how much data we've moved. */
  7.1376 +		pc->buffer += thislen;
  7.1377 +		pc->buflen -= thislen;
  7.1378 +	}
  7.1379 +
  7.1380 +	/* Same drill for reading. */
  7.1381 +	else if ((ireason & 3) == 2) {
  7.1382 +
  7.1383 +		/* Transfer the data. */
  7.1384 +		atapi_input_bytes (drive, pc->buffer, thislen);
  7.1385 +
  7.1386 +		/* If we haven't moved enough data to satisfy the drive,
  7.1387 +		   add some padding. */
  7.1388 +		while (len > thislen) {
  7.1389 +			int dum = 0;
  7.1390 +			atapi_input_bytes (drive, &dum, sizeof (dum));
  7.1391 +			len -= sizeof (dum);
  7.1392 +		}
  7.1393 +
  7.1394 +		/* Keep count of how much data we've moved. */
  7.1395 +		pc->buffer += thislen;
  7.1396 +		pc->buflen -= thislen;
  7.1397 +	} else {
  7.1398 +		printk ("%s: cdrom_pc_intr: The drive "
  7.1399 +			"appears confused (ireason = 0x%2x)\n",
  7.1400 +			drive->name, ireason);
  7.1401 +		pc->stat = 1;
  7.1402 +	}
  7.1403 +
  7.1404 +	/* Now we wait for another interrupt. */
  7.1405 +	ide_set_handler (drive, &cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry);
  7.1406 +	return ide_started;
  7.1407 +}
  7.1408 +
  7.1409 +
  7.1410 +static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive)
  7.1411 +{
  7.1412 +	struct request *rq = HWGROUP(drive)->rq;
  7.1413 +	struct packet_command *pc = (struct packet_command *)rq->buffer;
  7.1414 +
  7.1415 +	if (!pc->timeout)
  7.1416 +		pc->timeout = WAIT_CMD;
  7.1417 +
  7.1418 +	/* Send the command to the drive and return. */
  7.1419 +	return cdrom_transfer_packet_command(drive, pc, &cdrom_pc_intr);
  7.1420 +}
  7.1421 +
  7.1422 +
  7.1423 +static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
  7.1424 +{
  7.1425 +	int len;
  7.1426 +	struct request *rq = HWGROUP(drive)->rq;
  7.1427 +	struct packet_command *pc = (struct packet_command *)rq->buffer;
  7.1428 +	struct cdrom_info *info = drive->driver_data;
  7.1429 +
  7.1430 +	info->dma = 0;
  7.1431 +	info->cmd = 0;
  7.1432 +	pc->stat = 0;
  7.1433 +	len = pc->buflen;
  7.1434 +
  7.1435 +	/* Start sending the command to the drive. */
  7.1436 +	return cdrom_start_packet_command (drive, len, cdrom_do_pc_continuation);
  7.1437 +}
  7.1438 +
  7.1439 +
  7.1440 +/* Sleep for TIME jiffies.
  7.1441 +   Not to be called from an interrupt handler. */
  7.1442 +static
  7.1443 +void cdrom_sleep (int time)
  7.1444 +{
  7.1445 +	int sleep = time;
  7.1446 +
  7.1447 +	do {
  7.1448 +		set_current_state(TASK_INTERRUPTIBLE);
  7.1449 +		sleep = schedule_timeout(sleep);
  7.1450 +	} while (sleep);
  7.1451 +}
  7.1452 +
  7.1453 +static
  7.1454 +int cdrom_queue_packet_command(ide_drive_t *drive, struct packet_command *pc)
  7.1455 +{
  7.1456 +	struct request_sense sense;
  7.1457 +	struct request req;
  7.1458 +	int retries = 10;
  7.1459 +
  7.1460 +	if (pc->sense == NULL)
  7.1461 +		pc->sense = &sense;
  7.1462 +
  7.1463 +	/* Start of retry loop. */
  7.1464 +	do {
  7.1465 +		ide_init_drive_cmd (&req);
  7.1466 +		req.cmd = PACKET_COMMAND;
  7.1467 +		req.buffer = (char *)pc;
  7.1468 +		if (ide_do_drive_cmd (drive, &req, ide_wait)) {
  7.1469 +			printk("%s: do_drive_cmd returned stat=%02x,err=%02x\n",
  7.1470 +				drive->name, req.buffer[0], req.buffer[1]);
  7.1471 +			/* FIXME: we should probably abort/retry or something */
  7.1472 +		}
  7.1473 +		if (pc->stat != 0) {
  7.1474 +			/* The request failed.  Retry if it was due to a unit
  7.1475 +			   attention status
  7.1476 +			   (usually means media was changed). */
  7.1477 +			struct request_sense *reqbuf = pc->sense;
  7.1478 +
  7.1479 +			if (reqbuf->sense_key == UNIT_ATTENTION)
  7.1480 +				cdrom_saw_media_change (drive);
  7.1481 +			else if (reqbuf->sense_key == NOT_READY &&
  7.1482 +				 reqbuf->asc == 4 && reqbuf->ascq != 4) {
  7.1483 +				/* The drive is in the process of loading
  7.1484 +				   a disk.  Retry, but wait a little to give
  7.1485 +				   the drive time to complete the load. */
  7.1486 +				cdrom_sleep(2 * HZ);
  7.1487 +			} else {
  7.1488 +				/* Otherwise, don't retry. */
  7.1489 +				retries = 0;
  7.1490 +			}
  7.1491 +			--retries;
  7.1492 +		}
  7.1493 +
  7.1494 +		/* End of retry loop. */
  7.1495 +	} while (pc->stat != 0 && retries >= 0);
  7.1496 +
  7.1497 +	/* Return an error if the command failed. */
  7.1498 +	return pc->stat ? -EIO : 0;
  7.1499 +}
  7.1500 +
  7.1501 +/*
  7.1502 + * Write handling
  7.1503 + */
  7.1504 +static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason)
  7.1505 +{
  7.1506 +	/* Two notes about IDE interrupt reason here - 0 means that
  7.1507 +	 * the drive wants to receive data from us, 2 means that
  7.1508 +	 * the drive is expecting data from us.
  7.1509 +	 */
  7.1510 +	ireason &= 3;
  7.1511 +
  7.1512 +	if (ireason == 2) {
  7.1513 +		/* Whoops... The drive wants to send data. */
  7.1514 +		printk("%s: cdrom_write_intr: wrong transfer direction!\n",
  7.1515 +			drive->name);
  7.1516 +
  7.1517 +		/* Throw some data at the drive so it doesn't hang
  7.1518 +		   and quit this request. */
  7.1519 +		while (len > 0) {
  7.1520 +			int dum = 0;
  7.1521 +			atapi_output_bytes(drive, &dum, sizeof(dum));
  7.1522 +			len -= sizeof(dum);
  7.1523 +		}
  7.1524 +	} else {
  7.1525 +		/* Drive wants a command packet, or invalid ireason... */
  7.1526 +		printk("%s: cdrom_write_intr: bad interrupt reason %d\n",
  7.1527 +			drive->name, ireason);
  7.1528 +	}
  7.1529 +
  7.1530 +	cdrom_end_request(0, drive);
  7.1531 +	return 1;
  7.1532 +}
  7.1533 +
  7.1534 +static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
  7.1535 +{
  7.1536 +	int stat, ireason, len, sectors_to_transfer, uptodate;
  7.1537 +	struct cdrom_info *info = drive->driver_data;
  7.1538 +	int i, dma_error = 0, dma = info->dma;
  7.1539 +	ide_startstop_t startstop;
  7.1540 +
  7.1541 +	struct request *rq = HWGROUP(drive)->rq;
  7.1542 +
  7.1543 +	/* Check for errors. */
  7.1544 +	if (dma) {
  7.1545 +		info->dma = 0;
  7.1546 +		if ((dma_error = HWIF(drive)->dmaproc(ide_dma_end, drive))) {
  7.1547 +			printk("ide-cd: write dma error\n");
  7.1548 +			HWIF(drive)->dmaproc(ide_dma_off, drive);
  7.1549 +		}
  7.1550 +	}
  7.1551 +
  7.1552 +	if (cdrom_decode_status(&startstop, drive, 0, &stat)) {
  7.1553 +		printk("ide-cd: write_intr decode_status bad\n");
  7.1554 +		return startstop;
  7.1555 +	}
  7.1556 + 
  7.1557 +	/*
  7.1558 +	 * using dma, transfer is complete now
  7.1559 +	 */
  7.1560 +	if (dma) {
  7.1561 +		if (dma_error)
  7.1562 +			return ide_error(drive, "dma error", stat);
  7.1563 +
  7.1564 +		rq = HWGROUP(drive)->rq;
  7.1565 +		for (i = rq->nr_sectors; i > 0;) {
  7.1566 +			i -= rq->current_nr_sectors;
  7.1567 +			ide_end_request(1, HWGROUP(drive));
  7.1568 +		}
  7.1569 +		return ide_stopped;
  7.1570 +	}
  7.1571 +
  7.1572 +	/* Read the interrupt reason and the transfer length. */
  7.1573 +	ireason = IN_BYTE(IDE_NSECTOR_REG);
  7.1574 +	len = IN_BYTE(IDE_LCYL_REG) + 256 * IN_BYTE(IDE_HCYL_REG);
  7.1575 +
  7.1576 +	/* If DRQ is clear, the command has completed. */
  7.1577 +	if ((stat & DRQ_STAT) == 0) {
  7.1578 +		/* If we're not done writing, complain.
  7.1579 +		 * Otherwise, complete the command normally.
  7.1580 +		 */
  7.1581 +		uptodate = 1;
  7.1582 +		if (rq->current_nr_sectors > 0) {
  7.1583 +			printk("%s: write_intr: data underrun (%ld blocks)\n",
  7.1584 +			drive->name, rq->current_nr_sectors);
  7.1585 +			uptodate = 0;
  7.1586 +		}
  7.1587 +		cdrom_end_request(uptodate, drive);
  7.1588 +		return ide_stopped;
  7.1589 +	}
  7.1590 +
  7.1591 +	/* Check that the drive is expecting to do the same thing we are. */
  7.1592 +	if (ireason & 3)
  7.1593 +		if (cdrom_write_check_ireason(drive, len, ireason))
  7.1594 +			return ide_stopped;
  7.1595 +
  7.1596 +	sectors_to_transfer = len / SECTOR_SIZE;
  7.1597 +
  7.1598 +	/*
  7.1599 +	 * now loop and write out the data
  7.1600 +	 */
  7.1601 +	while (sectors_to_transfer > 0) {
  7.1602 +		int this_transfer;
  7.1603 +
  7.1604 +		if (!rq->current_nr_sectors) {
  7.1605 +			printk("ide-cd: write_intr: oops\n");
  7.1606 +			break;
  7.1607 +		}
  7.1608 +
  7.1609 +		/*
  7.1610 +		 * Figure out how many sectors we can transfer
  7.1611 +		 */
  7.1612 +		this_transfer = MIN(sectors_to_transfer,rq->current_nr_sectors);
  7.1613 +
  7.1614 +		while (this_transfer > 0) {
  7.1615 +			atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE);
  7.1616 +			rq->buffer += SECTOR_SIZE;
  7.1617 +			--rq->nr_sectors;
  7.1618 +			--rq->current_nr_sectors;
  7.1619 +			++rq->sector;
  7.1620 +			--this_transfer;
  7.1621 +			--sectors_to_transfer;
  7.1622 +		}
  7.1623 +
  7.1624 +		/*
  7.1625 +		 * current buffer complete, move on
  7.1626 +		 */
  7.1627 +		if (rq->current_nr_sectors == 0 && rq->nr_sectors)
  7.1628 +			cdrom_end_request (1, drive);
  7.1629 +	}
  7.1630 +
  7.1631 +	/* re-arm handler */
  7.1632 +	ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL);
  7.1633 +	return ide_started;
  7.1634 +}
  7.1635 +
  7.1636 +static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive)
  7.1637 +{
  7.1638 +	struct packet_command pc;	/* packet_command_t pc; */
  7.1639 +	struct request *rq = HWGROUP(drive)->rq;
  7.1640 +	unsigned nframes, frame;
  7.1641 +
  7.1642 +	nframes = rq->nr_sectors >> 2;
  7.1643 +	frame = rq->sector >> 2;
  7.1644 +
  7.1645 +	memset(&pc.c, 0, sizeof(pc.c));
  7.1646 +	/*
  7.1647 +	 * we might as well use WRITE_12, but none of the device I have
  7.1648 +	 * support the streaming feature anyway, so who cares.
  7.1649 +	 */
  7.1650 +	pc.c[0] = GPCMD_WRITE_10;
  7.1651 +#if 0	/* the immediate bit */
  7.1652 +	pc.c[1] = 1 << 3;
  7.1653 +#endif
  7.1654 +	pc.c[7] = (nframes >> 8) & 0xff;
  7.1655 +	pc.c[8] = nframes & 0xff;
  7.1656 +	put_unaligned(cpu_to_be32(frame), (unsigned int *)&pc.c[2]);
  7.1657 +	pc.timeout = 2 * WAIT_CMD;
  7.1658 +
  7.1659 +	return cdrom_transfer_packet_command(drive, &pc, cdrom_write_intr);
  7.1660 +}
  7.1661 +
  7.1662 +static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)
  7.1663 +{
  7.1664 +	struct cdrom_info *info = drive->driver_data;
  7.1665 +
  7.1666 +	/*
  7.1667 +	 * writes *must* be 2kB frame aligned
  7.1668 +	 */
  7.1669 +	if ((rq->nr_sectors & 3) || (rq->sector & 3)) {
  7.1670 +		cdrom_end_request(0, drive);
  7.1671 +		return ide_stopped;
  7.1672 +	}
  7.1673 +
  7.1674 +	/*
  7.1675 +	 * for dvd-ram and such media, it's a really big deal to get
  7.1676 +	 * big writes all the time. so scour the queue and attempt to
  7.1677 +	 * remerge requests, often the plugging will not have had time
  7.1678 +	 * to do this properly
  7.1679 +	 */
  7.1680 +	cdrom_attempt_remerge(drive, rq);
  7.1681 +
  7.1682 +	info->nsectors_buffered = 0;
  7.1683 +
  7.1684 +        /* use dma, if possible. we don't need to check more, since we
  7.1685 +	 * know that the transfer is always (at least!) 2KB aligned */
  7.1686 +	info->dma = drive->using_dma ? 1 : 0;
  7.1687 +	info->cmd = WRITE;
  7.1688 +
  7.1689 +	/* Start sending the read request to the drive. */
  7.1690 +	return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont);
  7.1691 +}
  7.1692 +
  7.1693 +/****************************************************************************
  7.1694 + * cdrom driver request routine.
  7.1695 + */
  7.1696 +static ide_startstop_t
  7.1697 +ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block)
  7.1698 +{
  7.1699 +	ide_startstop_t action;
  7.1700 +	struct cdrom_info *info = drive->driver_data;
  7.1701 +
  7.1702 +	switch (rq->cmd) {
  7.1703 +		case WRITE:
  7.1704 +		case READ: {
  7.1705 +			if (CDROM_CONFIG_FLAGS(drive)->seeking) {
  7.1706 +				unsigned long elpased = jiffies - info->start_seek;
  7.1707 +				int stat = GET_STAT();
  7.1708 +
  7.1709 +				if ((stat & SEEK_STAT) != SEEK_STAT) {
  7.1710 +					if (elpased < IDECD_SEEK_TIMEOUT) {
  7.1711 +						ide_stall_queue(drive, IDECD_SEEK_TIMER);
  7.1712 +						return ide_stopped;
  7.1713 +					}
  7.1714 +					printk ("%s: DSC timeout\n", drive->name);
  7.1715 +				}
  7.1716 +				CDROM_CONFIG_FLAGS(drive)->seeking = 0;
  7.1717 +			}
  7.1718 +			if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap)
  7.1719 +				action = cdrom_start_seek (drive, block);
  7.1720 +			else {
  7.1721 +				if (rq->cmd == READ)
  7.1722 +					action = cdrom_start_read(drive, block);
  7.1723 +				else
  7.1724 +					action = cdrom_start_write(drive, rq);
  7.1725 +			}
  7.1726 +			info->last_block = block;
  7.1727 +			return action;
  7.1728 +		}
  7.1729 +
  7.1730 +		case PACKET_COMMAND:
  7.1731 +		case REQUEST_SENSE_COMMAND: {
  7.1732 +			return cdrom_do_packet_command(drive);
  7.1733 +		}
  7.1734 +
  7.1735 +		case RESET_DRIVE_COMMAND: {
  7.1736 +			cdrom_end_request(1, drive);
  7.1737 +			return ide_do_reset(drive);
  7.1738 +		}
  7.1739 +
  7.1740 +		default: {
  7.1741 +			printk("ide-cd: bad cmd %d\n", rq->cmd);
  7.1742 +			cdrom_end_request(0, drive);
  7.1743 +			return ide_stopped;
  7.1744 +		}
  7.1745 +	}
  7.1746 +}
  7.1747 +
  7.1748 +
  7.1749 +
  7.1750 +/****************************************************************************
  7.1751 + * Ioctl handling.
  7.1752 + *
  7.1753 + * Routines which queue packet commands take as a final argument a pointer
  7.1754 + * to a request_sense struct.  If execution of the command results
  7.1755 + * in an error with a CHECK CONDITION status, this structure will be filled
  7.1756 + * with the results of the subsequent request sense command.  The pointer
  7.1757 + * can also be NULL, in which case no sense information is returned.
  7.1758 + */
  7.1759 +
  7.1760 +#if ! STANDARD_ATAPI
  7.1761 +static inline
  7.1762 +int bin2bcd (int x)
  7.1763 +{
  7.1764 +	return (x%10) | ((x/10) << 4);
  7.1765 +}
  7.1766 +
  7.1767 +
  7.1768 +static inline
  7.1769 +int bcd2bin (int x)
  7.1770 +{
  7.1771 +	return (x >> 4) * 10 + (x & 0x0f);
  7.1772 +}
  7.1773 +
  7.1774 +static
  7.1775 +void msf_from_bcd (struct atapi_msf *msf)
  7.1776 +{
  7.1777 +	msf->minute = bcd2bin (msf->minute);
  7.1778 +	msf->second = bcd2bin (msf->second);
  7.1779 +	msf->frame  = bcd2bin (msf->frame);
  7.1780 +}
  7.1781 +
  7.1782 +#endif /* not STANDARD_ATAPI */
  7.1783 +
  7.1784 +
  7.1785 +static inline
  7.1786 +void lba_to_msf (int lba, byte *m, byte *s, byte *f)
  7.1787 +{
  7.1788 +	lba += CD_MSF_OFFSET;
  7.1789 +	lba &= 0xffffff;  /* negative lbas use only 24 bits */
  7.1790 +	*m = lba / (CD_SECS * CD_FRAMES);
  7.1791 +	lba %= (CD_SECS * CD_FRAMES);
  7.1792 +	*s = lba / CD_FRAMES;
  7.1793 +	*f = lba % CD_FRAMES;
  7.1794 +}
  7.1795 +
  7.1796 +
  7.1797 +static inline
  7.1798 +int msf_to_lba (byte m, byte s, byte f)
  7.1799 +{
  7.1800 +	return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
  7.1801 +}
  7.1802 +
  7.1803 +static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
  7.1804 +{
  7.1805 +	struct packet_command pc;
  7.1806 +	struct cdrom_info *info = drive->driver_data;
  7.1807 +	struct cdrom_device_info *cdi = &info->devinfo;
  7.1808 +
  7.1809 +	memset(&pc, 0, sizeof(pc));
  7.1810 +	pc.sense = sense;
  7.1811 +
  7.1812 +	pc.c[0] = GPCMD_TEST_UNIT_READY;
  7.1813 +
  7.1814 +#if ! STANDARD_ATAPI
  7.1815 +        /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to 
  7.1816 +           switch CDs instead of supporting the LOAD_UNLOAD opcode   */
  7.1817 +
  7.1818 +        pc.c[7] = cdi->sanyo_slot % 3;
  7.1819 +#endif /* not STANDARD_ATAPI */
  7.1820 +
  7.1821 +	return cdrom_queue_packet_command(drive, &pc);
  7.1822 +}
  7.1823 +
  7.1824 +
  7.1825 +/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
  7.1826 +static int
  7.1827 +cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
  7.1828 +{
  7.1829 +	struct request_sense my_sense;
  7.1830 +	struct packet_command pc;
  7.1831 +	int stat;
  7.1832 +
  7.1833 +	if (sense == NULL)
  7.1834 +		sense = &my_sense;
  7.1835 +
  7.1836 +	/* If the drive cannot lock the door, just pretend. */
  7.1837 +	if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) {
  7.1838 +		stat = 0;
  7.1839 +	} else {
  7.1840 +		memset(&pc, 0, sizeof(pc));
  7.1841 +		pc.sense = sense;
  7.1842 +		pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
  7.1843 +		pc.c[4] = lockflag ? 1 : 0;
  7.1844 +		stat = cdrom_queue_packet_command (drive, &pc);
  7.1845 +	}
  7.1846 +
  7.1847 +	/* If we got an illegal field error, the drive
  7.1848 +	   probably cannot lock the door. */
  7.1849 +	if (stat != 0 &&
  7.1850 +	    sense->sense_key == ILLEGAL_REQUEST &&
  7.1851 +	    (sense->asc == 0x24 || sense->asc == 0x20)) {
  7.1852 +		printk ("%s: door locking not supported\n",
  7.1853 +			drive->name);
  7.1854 +		CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
  7.1855 +		stat = 0;
  7.1856 +	}
  7.1857 +	
  7.1858 +	/* no medium, that's alright. */
  7.1859 +	if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)
  7.1860 +		stat = 0;
  7.1861 +
  7.1862 +	if (stat == 0)
  7.1863 +		CDROM_STATE_FLAGS (drive)->door_locked = lockflag;
  7.1864 +
  7.1865 +	return stat;
  7.1866 +}
  7.1867 +
  7.1868 +
  7.1869 +/* Eject the disk if EJECTFLAG is 0.
  7.1870 +   If EJECTFLAG is 1, try to reload the disk. */
  7.1871 +static int cdrom_eject(ide_drive_t *drive, int ejectflag,
  7.1872 +		       struct request_sense *sense)
  7.1873 +{
  7.1874 +	struct packet_command pc;
  7.1875 +
  7.1876 +	if (CDROM_CONFIG_FLAGS(drive)->no_eject && !ejectflag)
  7.1877 +		return -EDRIVE_CANT_DO_THIS;
  7.1878 +	
  7.1879 +	/* reload fails on some drives, if the tray is locked */
  7.1880 +	if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag)
  7.1881 +		return 0;
  7.1882 +
  7.1883 +	memset(&pc, 0, sizeof (pc));
  7.1884 +	pc.sense = sense;
  7.1885 +
  7.1886 +	pc.c[0] = GPCMD_START_STOP_UNIT;
  7.1887 +	pc.c[4] = 0x02 + (ejectflag != 0);
  7.1888 +	return cdrom_queue_packet_command (drive, &pc);
  7.1889 +}
  7.1890 +
  7.1891 +static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
  7.1892 +			       struct request_sense *sense)
  7.1893 +{
  7.1894 +	struct {
  7.1895 +		__u32 lba;
  7.1896 +		__u32 blocklen;
  7.1897 +	} capbuf;
  7.1898 +
  7.1899 +	int stat;
  7.1900 +	struct packet_command pc;
  7.1901 +
  7.1902 +	memset(&pc, 0, sizeof(pc));
  7.1903 +	pc.sense = sense;
  7.1904 +
  7.1905 +	pc.c[0] = GPCMD_READ_CDVD_CAPACITY;
  7.1906 +	pc.buffer = (char *)&capbuf;
  7.1907 +	pc.buflen = sizeof(capbuf);
  7.1908 +
  7.1909 +	stat = cdrom_queue_packet_command(drive, &pc);
  7.1910 +	if (stat == 0)
  7.1911 +		*capacity = 1 + be32_to_cpu(capbuf.lba);
  7.1912 +
  7.1913 +	return stat;
  7.1914 +}
  7.1915 +
  7.1916 +static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
  7.1917 +				int format, char *buf, int buflen,
  7.1918 +				struct request_sense *sense)
  7.1919 +{
  7.1920 +	struct packet_command pc;
  7.1921 +
  7.1922 +	memset(&pc, 0, sizeof(pc));
  7.1923 +	pc.sense = sense;
  7.1924 +
  7.1925 +	pc.buffer =  buf;
  7.1926 +	pc.buflen = buflen;
  7.1927 +	pc.quiet = 1;
  7.1928 +	pc.c[0] = GPCMD_READ_TOC_PMA_ATIP;
  7.1929 +	pc.c[6] = trackno;
  7.1930 +	pc.c[7] = (buflen >> 8);
  7.1931 +	pc.c[8] = (buflen & 0xff);
  7.1932 +	pc.c[9] = (format << 6);
  7.1933 +
  7.1934 +	if (msf_flag)
  7.1935 +		pc.c[1] = 2;
  7.1936 +
  7.1937 +	return cdrom_queue_packet_command (drive, &pc);
  7.1938 +}
  7.1939 +
  7.1940 +
  7.1941 +/* Try to read the entire TOC for the disk into our internal buffer. */
  7.1942 +static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
  7.1943 +{
  7.1944 +	int minor, stat, ntracks, i;
  7.1945 +	kdev_t dev;
  7.1946 +	struct cdrom_info *info = drive->driver_data;
  7.1947 +	struct atapi_toc *toc = info->toc;
  7.1948 +	struct {
  7.1949 +		struct atapi_toc_header hdr;
  7.1950 +		struct atapi_toc_entry  ent;
  7.1951 +	} ms_tmp;
  7.1952 +
  7.1953 +	if (toc == NULL) {
  7.1954 +		/* Try to allocate space. */
  7.1955 +		toc = (struct atapi_toc *) kmalloc (sizeof (struct atapi_toc),
  7.1956 +						    GFP_KERNEL);
  7.1957 +		info->toc = toc;
  7.1958 +		if (toc == NULL) {
  7.1959 +			printk ("%s: No cdrom TOC buffer!\n", drive->name);
  7.1960 +			return -ENOMEM;
  7.1961 +		}
  7.1962 +	}
  7.1963 +
  7.1964 +	/* Check to see if the existing data is still valid.
  7.1965 +	   If it is, just return. */
  7.1966 +	(void) cdrom_check_status(drive, sense);
  7.1967 +
  7.1968 +	if (CDROM_STATE_FLAGS(drive)->toc_valid)
  7.1969 +		return 0;
  7.1970 +
  7.1971 +	/* First read just the header, so we know how long the TOC is. */
  7.1972 +	stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
  7.1973 +				    sizeof(struct atapi_toc_header), sense);
  7.1974 +	if (stat) return stat;
  7.1975 +
  7.1976 +#if ! STANDARD_ATAPI
  7.1977 +	if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) {
  7.1978 +		toc->hdr.first_track = bcd2bin (toc->hdr.first_track);
  7.1979 +		toc->hdr.last_track  = bcd2bin (toc->hdr.last_track);
  7.1980 +	}
  7.1981 +#endif  /* not STANDARD_ATAPI */
  7.1982 +
  7.1983 +	ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
  7.1984 +	if (ntracks <= 0)
  7.1985 +		return -EIO;
  7.1986 +	if (ntracks > MAX_TRACKS)
  7.1987 +		ntracks = MAX_TRACKS;
  7.1988 +
  7.1989 +	/* Now read the whole schmeer. */
  7.1990 +	stat = cdrom_read_tocentry(drive, toc->hdr.first_track, 1, 0,
  7.1991 +				  (char *)&toc->hdr,
  7.1992 +				   sizeof(struct atapi_toc_header) +
  7.1993 +				   (ntracks + 1) *
  7.1994 +				   sizeof(struct atapi_toc_entry), sense);
  7.1995 +
  7.1996 +	if (stat && toc->hdr.first_track > 1) {
  7.1997 +		/* Cds with CDI tracks only don't have any TOC entries,
  7.1998 +		   despite of this the returned values are
  7.1999 +		   first_track == last_track = number of CDI tracks + 1,
  7.2000 +		   so that this case is indistinguishable from the same
  7.2001 +		   layout plus an additional audio track.
  7.2002 +		   If we get an error for the regular case, we assume
  7.2003 +		   a CDI without additional audio tracks. In this case
  7.2004 +		   the readable TOC is empty (CDI tracks are not included)
  7.2005 +		   and only holds the Leadout entry. Heiko Ei▀feldt */
  7.2006 +		ntracks = 0;
  7.2007 +		stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0,
  7.2008 +					   (char *)&toc->hdr,
  7.2009 +					   sizeof(struct atapi_toc_header) +
  7.2010 +					   (ntracks + 1) *
  7.2011 +					   sizeof(struct atapi_toc_entry),
  7.2012 +					   sense);
  7.2013 +		if (stat) {
  7.2014 +			return stat;
  7.2015 +		}
  7.2016 +#if ! STANDARD_ATAPI
  7.2017 +		if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) {
  7.2018 +			toc->hdr.first_track = bin2bcd(CDROM_LEADOUT);
  7.2019 +			toc->hdr.last_track = bin2bcd(CDROM_LEADOUT);
  7.2020 +		} else
  7.2021 +#endif  /* not STANDARD_ATAPI */
  7.2022 +		{
  7.2023 +			toc->hdr.first_track = CDROM_LEADOUT;
  7.2024 +			toc->hdr.last_track = CDROM_LEADOUT;
  7.2025 +		}
  7.2026 +	}
  7.2027 +
  7.2028 +	if (stat)
  7.2029 +		return stat;
  7.2030 +
  7.2031 +	toc->hdr.toc_length = ntohs (toc->hdr.toc_length);
  7.2032 +
  7.2033 +#if ! STANDARD_ATAPI
  7.2034 +	if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) {
  7.2035 +		toc->hdr.first_track = bcd2bin (toc->hdr.first_track);
  7.2036 +		toc->hdr.last_track  = bcd2bin (toc->hdr.last_track);
  7.2037 +	}
  7.2038 +#endif  /* not STANDARD_ATAPI */
  7.2039 +
  7.2040 +	for (i=0; i<=ntracks; i++) {
  7.2041 +#if ! STANDARD_ATAPI
  7.2042 +		if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd) {
  7.2043 +			if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd)
  7.2044 +				toc->ent[i].track = bcd2bin (toc->ent[i].track);
  7.2045 +			msf_from_bcd (&toc->ent[i].addr.msf);
  7.2046 +		}
  7.2047 +#endif  /* not STANDARD_ATAPI */
  7.2048 +		toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute,
  7.2049 +						   toc->ent[i].addr.msf.second,
  7.2050 +						   toc->ent[i].addr.msf.frame);
  7.2051 +	}
  7.2052 +
  7.2053 +	/* Read the multisession information. */
  7.2054 +	if (toc->hdr.first_track != CDROM_LEADOUT) {
  7.2055 +		/* Read the multisession information. */
  7.2056 +		stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
  7.2057 +					   sizeof(ms_tmp), sense);
  7.2058 +		if (stat) return stat;
  7.2059 +	} else {
  7.2060 +		ms_tmp.ent.addr.msf.minute = 0;
  7.2061 +		ms_tmp.ent.addr.msf.second = 2;
  7.2062 +		ms_tmp.ent.addr.msf.frame  = 0;
  7.2063 +		ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT;
  7.2064 +	}
  7.2065 +
  7.2066 +#if ! STANDARD_ATAPI
  7.2067 +	if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd)
  7.2068 +		msf_from_bcd (&ms_tmp.ent.addr.msf);
  7.2069 +#endif  /* not STANDARD_ATAPI */
  7.2070 +
  7.2071 +	toc->last_session_lba = msf_to_lba (ms_tmp.ent.addr.msf.minute,
  7.2072 +					    ms_tmp.ent.addr.msf.second,
  7.2073 +					    ms_tmp.ent.addr.msf.frame);
  7.2074 +
  7.2075 +	toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
  7.2076 +
  7.2077 +	/* Now try to get the total cdrom capacity. */
  7.2078 +	minor = (drive->select.b.unit) << PARTN_BITS;
  7.2079 +	dev = MKDEV(HWIF(drive)->major, minor);
  7.2080 +	stat = cdrom_get_last_written(dev, &toc->capacity);
  7.2081 +	if (stat)
  7.2082 +		stat = cdrom_read_capacity(drive, &toc->capacity, sense);
  7.2083 +	if (stat)
  7.2084 +		toc->capacity = 0x1fffff;
  7.2085 +
  7.2086 +	HWIF(drive)->gd->sizes[drive->select.b.unit << PARTN_BITS] = (toc->capacity * SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9);
  7.2087 +	drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
  7.2088 +
  7.2089 +	/* Remember that we've read this stuff. */
  7.2090 +	CDROM_STATE_FLAGS (drive)->toc_valid = 1;
  7.2091 +
  7.2092 +	return 0;
  7.2093 +}
  7.2094 +
  7.2095 +
  7.2096 +static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
  7.2097 +				 int buflen, struct request_sense *sense)
  7.2098 +{
  7.2099 +	struct packet_command pc;
  7.2100 +
  7.2101 +	memset(&pc, 0, sizeof(pc));
  7.2102 +	pc.sense = sense;
  7.2103 +
  7.2104 +	pc.buffer = buf;
  7.2105 +	pc.buflen = buflen;
  7.2106 +	pc.c[0] = GPCMD_READ_SUBCHANNEL;
  7.2107 +	pc.c[1] = 2;     /* MSF addressing */
  7.2108 +	pc.c[2] = 0x40;  /* request subQ data */
  7.2109 +	pc.c[3] = format;
  7.2110 +	pc.c[7] = (buflen >> 8);
  7.2111 +	pc.c[8] = (buflen & 0xff);
  7.2112 +	return cdrom_queue_packet_command(drive, &pc);
  7.2113 +}
  7.2114 +
  7.2115 +/* ATAPI cdrom drives are free to select the speed you request or any slower
  7.2116 +   rate :-( Requesting too fast a speed will _not_ produce an error. */
  7.2117 +static int cdrom_select_speed(ide_drive_t *drive, int speed,
  7.2118 +			      struct request_sense *sense)
  7.2119 +{
  7.2120 +	struct packet_command pc;
  7.2121 +	memset(&pc, 0, sizeof(pc));
  7.2122 +	pc.sense = sense;
  7.2123 +
  7.2124 +	if (speed == 0)
  7.2125 +		speed = 0xffff; /* set to max */
  7.2126 +	else
  7.2127 +		speed *= 177;   /* Nx to kbytes/s */
  7.2128 +
  7.2129 +	pc.c[0] = GPCMD_SET_SPEED;
  7.2130 +	/* Read Drive speed in kbytes/second MSB */
  7.2131 +	pc.c[2] = (speed >> 8) & 0xff;	
  7.2132 +	/* Read Drive speed in kbytes/second LSB */
  7.2133 +	pc.c[3] = speed & 0xff;
  7.2134 +	if (CDROM_CONFIG_FLAGS(drive)->cd_r ||
  7.2135 +	    CDROM_CONFIG_FLAGS(drive)->cd_rw ||
  7.2136 +	    CDROM_CONFIG_FLAGS(drive)->dvd_r) {
  7.2137 +		/* Write Drive speed in kbytes/second MSB */
  7.2138 +		pc.c[4] = (speed >> 8) & 0xff;
  7.2139 +		/* Write Drive speed in kbytes/second LSB */
  7.2140 +		pc.c[5] = speed & 0xff;
  7.2141 +       }
  7.2142 +
  7.2143 +	return cdrom_queue_packet_command(drive, &pc);
  7.2144 +}
  7.2145 +
  7.2146 +static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end)
  7.2147 +{
  7.2148 +	struct request_sense sense;
  7.2149 +	struct packet_command pc;
  7.2150 +
  7.2151 +	memset(&pc, 0, sizeof (pc));
  7.2152 +	pc.sense = &sense;
  7.2153 +
  7.2154 +	pc.c[0] = GPCMD_PLAY_AUDIO_MSF;
  7.2155 +	lba_to_msf(lba_start, &pc.c[3], &pc.c[4], &pc.c[5]);
  7.2156 +	lba_to_msf(lba_end-1, &pc.c[6], &pc.c[7], &pc.c[8]);
  7.2157 +
  7.2158 +	return cdrom_queue_packet_command(drive, &pc);
  7.2159 +}
  7.2160 +
  7.2161 +static int cdrom_get_toc_entry(ide_drive_t *drive, int track,
  7.2162 +				struct atapi_toc_entry **ent)
  7.2163 +{
  7.2164 +	struct cdrom_info *info = drive->driver_data;
  7.2165 +	struct atapi_toc *toc = info->toc;
  7.2166 +	int ntracks;
  7.2167 +
  7.2168 +	/*
  7.2169 +	 * don't serve cached data, if the toc isn't valid
  7.2170 +	 */
  7.2171 +	if (!CDROM_STATE_FLAGS(drive)->toc_valid)
  7.2172 +		return -EINVAL;
  7.2173 +
  7.2174 +	/* Check validity of requested track number. */
  7.2175 +	ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
  7.2176 +	if (toc->hdr.first_track == CDROM_LEADOUT) ntracks = 0;
  7.2177 +	if (track == CDROM_LEADOUT)
  7.2178 +		*ent = &toc->ent[ntracks];
  7.2179 +	else if (track < toc->hdr.first_track ||
  7.2180 +		 track > toc->hdr.last_track)
  7.2181 +		return -EINVAL;
  7.2182 +	else
  7.2183 +		*ent = &toc->ent[track - toc->hdr.first_track];
  7.2184 +
  7.2185 +	return 0;
  7.2186 +}
  7.2187 +
  7.2188 +/* the generic packet interface to cdrom.c */
  7.2189 +static int ide_cdrom_packet(struct cdrom_device_info *cdi,
  7.2190 +			    struct cdrom_generic_command *cgc)
  7.2191 +{
  7.2192 +	struct packet_command pc;
  7.2193 +	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
  7.2194 +
  7.2195 +	if (cgc->timeout <= 0)
  7.2196 +		cgc->timeout = WAIT_CMD;
  7.2197 +
  7.2198 +	/* here we queue the commands from the uniform CD-ROM
  7.2199 +	   layer. the packet must be complete, as we do not
  7.2200 +	   touch it at all. */
  7.2201 +	memset(&pc, 0, sizeof(pc));
  7.2202 +	memcpy(pc.c, cgc->cmd, CDROM_PACKET_SIZE);
  7.2203 +	pc.buffer = cgc->buffer;
  7.2204 +	pc.buflen = cgc->buflen;
  7.2205 +	pc.quiet = cgc->quiet;
  7.2206 +	pc.timeout = cgc->timeout;
  7.2207 +	pc.sense = cgc->sense;
  7.2208 +	return cgc->stat = cdrom_queue_packet_command(drive, &pc);
  7.2209 +}
  7.2210 +
  7.2211 +static
  7.2212 +int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi,
  7.2213 +			 unsigned int cmd, unsigned long arg)
  7.2214 +{
  7.2215 +	struct cdrom_generic_command cgc;
  7.2216 +	char buffer[16];
  7.2217 +	int stat;
  7.2218 +
  7.2219 +	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
  7.2220 +
  7.2221 +	/* These will be moved into the Uniform layer shortly... */
  7.2222 +	switch (cmd) {
  7.2223 + 	case CDROMSETSPINDOWN: {
  7.2224 + 		char spindown;
  7.2225 + 
  7.2226 + 		if (copy_from_user(&spindown, (void *) arg, sizeof(char)))
  7.2227 +			return -EFAULT;
  7.2228 + 
  7.2229 +                if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0)))
  7.2230 +			return stat;
  7.2231 +
  7.2232 + 		buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f);
  7.2233 +
  7.2234 + 		return cdrom_mode_select(cdi, &cgc);
  7.2235 + 	} 
  7.2236 + 
  7.2237 + 	case CDROMGETSPINDOWN: {
  7.2238 + 		char spindown;
  7.2239 + 
  7.2240 +                if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0)))
  7.2241 +			return stat;
  7.2242 + 
  7.2243 + 		spindown = buffer[11] & 0x0f;
  7.2244 + 
  7.2245 +		if (copy_to_user((void *) arg, &spindown, sizeof (char)))
  7.2246 +			return -EFAULT;
  7.2247 + 
  7.2248 + 		return 0;
  7.2249 + 	}
  7.2250 +  
  7.2251 +	default:
  7.2252 +		return -EINVAL;
  7.2253 +	}
  7.2254 +
  7.2255 +}
  7.2256 +
  7.2257 +static
  7.2258 +int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
  7.2259 +			   unsigned int cmd, void *arg)
  7.2260 +			   
  7.2261 +{
  7.2262 +	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
  7.2263 +	struct cdrom_info *info = drive->driver_data;
  7.2264 +	int stat;
  7.2265 +
  7.2266 +	switch (cmd) {
  7.2267 +	/*
  7.2268 +	 * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since
  7.2269 +	 * atapi doesn't support it
  7.2270 +	 */
  7.2271 +	case CDROMPLAYTRKIND: {
  7.2272 +		unsigned long lba_start, lba_end;
  7.2273 +		struct cdrom_ti *ti = (struct cdrom_ti *)arg;
  7.2274 +		struct atapi_toc_entry *first_toc, *last_toc;
  7.2275 +
  7.2276 +		stat = cdrom_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
  7.2277 +		if (stat)
  7.2278 +			return stat;
  7.2279 +
  7.2280 +		stat = cdrom_get_toc_entry(drive, ti->cdti_trk1, &last_toc);
  7.2281 +		if (stat)
  7.2282 +			return stat;
  7.2283 +
  7.2284 +		if (ti->cdti_trk1 != CDROM_LEADOUT)
  7.2285 +			++last_toc;
  7.2286 +		lba_start = first_toc->addr.lba;
  7.2287 +		lba_end   = last_toc->addr.lba;
  7.2288 +
  7.2289 +		if (lba_end <= lba_start)
  7.2290 +			return -EINVAL;
  7.2291 +
  7.2292 +		return cdrom_play_audio(drive, lba_start, lba_end);
  7.2293 +	}
  7.2294 +
  7.2295 +	case CDROMREADTOCHDR: {
  7.2296 +		struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
  7.2297 +		struct atapi_toc *toc;
  7.2298 +
  7.2299 +		/* Make sure our saved TOC is valid. */
  7.2300 +		stat = cdrom_read_toc(drive, NULL);
  7.2301 +		if (stat) return stat;
  7.2302 +
  7.2303 +		toc = info->toc;
  7.2304 +		tochdr->cdth_trk0 = toc->hdr.first_track;
  7.2305 +		tochdr->cdth_trk1 = toc->hdr.last_track;
  7.2306 +
  7.2307 +		return 0;
  7.2308 +	}
  7.2309 +
  7.2310 +	case CDROMREADTOCENTRY: {
  7.2311 +		struct cdrom_tocentry *tocentry = (struct cdrom_tocentry*) arg;
  7.2312 +		struct atapi_toc_entry *toce;
  7.2313 +
  7.2314 +		stat = cdrom_get_toc_entry (drive, tocentry->cdte_track, &toce);
  7.2315 +		if (stat) return stat;
  7.2316 +
  7.2317 +		tocentry->cdte_ctrl = toce->control;
  7.2318 +		tocentry->cdte_adr  = toce->adr;
  7.2319 +		if (tocentry->cdte_format == CDROM_MSF) {
  7.2320 +			lba_to_msf (toce->addr.lba,
  7.2321 +				   &tocentry->cdte_addr.msf.minute,
  7.2322 +				   &tocentry->cdte_addr.msf.second,
  7.2323 +				   &tocentry->cdte_addr.msf.frame);
  7.2324 +		} else
  7.2325 +			tocentry->cdte_addr.lba = toce->addr.lba;
  7.2326 +
  7.2327 +		return 0;
  7.2328 +	}
  7.2329 +
  7.2330 +	default:
  7.2331 +		return -EINVAL;
  7.2332 +	}
  7.2333 +}
  7.2334 +
  7.2335 +static
  7.2336 +int ide_cdrom_reset (struct cdrom_device_info *cdi)
  7.2337 +{
  7.2338 +	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
  7.2339 +	struct request_sense sense;
  7.2340 +	struct request req;
  7.2341 +	int ret;
  7.2342 +
  7.2343 +	ide_init_drive_cmd (&req);
  7.2344 +	req.cmd = RESET_DRIVE_COMMAND;
  7.2345 +	ret = ide_do_drive_cmd(drive, &req, ide_wait);
  7.2346 +
  7.2347 +	/*
  7.2348 +	 * A reset will unlock the door. If it was previously locked,
  7.2349 +	 * lock it again.
  7.2350 +	 */
  7.2351 +	if (CDROM_STATE_FLAGS(drive)->door_locked)
  7.2352 +		(void) cdrom_lockdoor(drive, 1, &sense);
  7.2353 +
  7.2354 +	return ret;
  7.2355 +}
  7.2356 +
  7.2357 +
  7.2358 +static
  7.2359 +int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
  7.2360 +{
  7.2361 +	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
  7.2362 +	struct request_sense sense;
  7.2363 +
  7.2364 +	if (position) {
  7.2365 +		int stat = cdrom_lockdoor(drive, 0, &sense);
  7.2366 +		if (stat) return stat;
  7.2367 +	}
  7.2368 +
  7.2369 +	return cdrom_eject(drive, !position, &sense);
  7.2370 +}
  7.2371 +
  7.2372 +static
  7.2373 +int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
  7.2374 +{
  7.2375 +	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
  7.2376 +	return cdrom_lockdoor(drive, lock, NULL);
  7.2377 +}
  7.2378 +
  7.2379 +static
  7.2380 +int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
  7.2381 +{
  7.2382 +	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
  7.2383 +	struct request_sense sense;
  7.2384 +	int stat;
  7.2385 +
  7.2386 +	if ((stat = cdrom_select_speed (drive, speed, &sense)) < 0)
  7.2387 +		return stat;
  7.2388 +
  7.2389 +        cdi->speed = CDROM_STATE_FLAGS (drive)->current_speed;
  7.2390 +        return 0;
  7.2391 +}
  7.2392 +
  7.2393 +static
  7.2394 +int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
  7.2395 +{
  7.2396 +	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
  7.2397 +
  7.2398 +	if (slot_nr == CDSL_CURRENT) {
  7.2399 +		struct request_sense sense;
  7.2400 +		int stat = cdrom_check_status(drive, &sense);
  7.2401 +		if (stat == 0 || sense.sense_key == UNIT_ATTENTION)
  7.2402 +			return CDS_DISC_OK;
  7.2403 +
  7.2404 +		if (sense.sense_key == NOT_READY && sense.asc == 0x04 &&
  7.2405 +		    sense.ascq == 0x04)
  7.2406 +			return CDS_DISC_OK;
  7.2407 +
  7.2408 +
  7.2409 +		/*
  7.2410 +		 * If not using Mt Fuji extended media tray reports,
  7.2411 +		 * just return TRAY_OPEN since ATAPI doesn't provide
  7.2412 +		 * any other way to detect this...
  7.2413 +		 */
  7.2414 +		if (sense.sense_key == NOT_READY) {
  7.2415 +			if (sense.asc == 0x3a && sense.ascq == 1)
  7.2416 +				return CDS_NO_DISC;
  7.2417 +			else
  7.2418 +				return CDS_TRAY_OPEN;
  7.2419 +		}
  7.2420 +
  7.2421 +		return CDS_DRIVE_NOT_READY;
  7.2422 +	}
  7.2423 +	return -EINVAL;
  7.2424 +}
  7.2425 +
  7.2426 +static
  7.2427 +int ide_cdrom_get_last_session (struct cdrom_device_info *cdi,
  7.2428 +				struct cdrom_multisession *ms_info)
  7.2429 +{
  7.2430 +	struct atapi_toc *toc;
  7.2431 +	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
  7.2432 +	struct cdrom_info *info = drive->driver_data;
  7.2433 +	struct request_sense sense;
  7.2434 +	int ret;
  7.2435 +
  7.2436 +	if (!CDROM_STATE_FLAGS(drive)->toc_valid || info->toc == NULL)
  7.2437 +		if ((ret = cdrom_read_toc(drive, &sense)))
  7.2438 +			return ret;
  7.2439 +
  7.2440 +	toc = info->toc;
  7.2441 +	ms_info->addr.lba = toc->last_session_lba;
  7.2442 +	ms_info->xa_flag = toc->xa_flag;
  7.2443 +
  7.2444 +	return 0;
  7.2445 +}
  7.2446 +
  7.2447 +static
  7.2448 +int ide_cdrom_get_mcn (struct cdrom_device_info *cdi,
  7.2449 +		       struct cdrom_mcn *mcn_info)
  7.2450 +{
  7.2451 +	int stat;
  7.2452 +	char mcnbuf[24];
  7.2453 +	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
  7.2454 +
  7.2455 +/* get MCN */
  7.2456 +	if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf), NULL)))
  7.2457 +		return stat;
  7.2458 +
  7.2459 +	memcpy (mcn_info->medium_catalog_number, mcnbuf+9,
  7.2460 +		sizeof (mcn_info->medium_catalog_number)-1);
  7.2461 +	mcn_info->medium_catalog_number[sizeof (mcn_info->medium_catalog_number)-1]
  7.2462 +		= '\0';
  7.2463 +
  7.2464 +	return 0;
  7.2465 +}
  7.2466 +
  7.2467 +
  7.2468 +
  7.2469 +/****************************************************************************
  7.2470 + * Other driver requests (open, close, check media change).
  7.2471 + */
  7.2472 +
  7.2473 +static
  7.2474 +int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi,
  7.2475 +				       int slot_nr)
  7.2476 +{
  7.2477 +	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
  7.2478 +	int retval;
  7.2479 +	
  7.2480 +	if (slot_nr == CDSL_CURRENT) {
  7.2481 +		(void) cdrom_check_status(drive, NULL);
  7.2482 +		retval = CDROM_STATE_FLAGS (drive)->media_changed;
  7.2483 +		CDROM_STATE_FLAGS (drive)->media_changed = 0;
  7.2484 +		return retval;
  7.2485 +	} else {
  7.2486 +		return -EINVAL;
  7.2487 +	}
  7.2488 +}
  7.2489 +
  7.2490 +
  7.2491 +static
  7.2492 +int ide_cdrom_open_real (struct cdrom_device_info *cdi, int purpose)
  7.2493 +{
  7.2494 +	return 0;
  7.2495 +}
  7.2496 +
  7.2497 +
  7.2498 +/*
  7.2499 + * Close down the device.  Invalidate all cached blocks.
  7.2500 + */
  7.2501 +
  7.2502 +static
  7.2503 +void ide_cdrom_release_real (struct cdrom_device_info *cdi)
  7.2504 +{
  7.2505 +}
  7.2506 +
  7.2507 +
  7.2508 +
  7.2509 +/****************************************************************************
  7.2510 + * Device initialization.
  7.2511 + */
  7.2512 +static struct cdrom_device_ops ide_cdrom_dops = {
  7.2513 +	open:			ide_cdrom_open_real,
  7.2514 +	release:		ide_cdrom_release_real,
  7.2515 +	drive_status:		ide_cdrom_drive_status,
  7.2516 +	media_changed:		ide_cdrom_check_media_change_real,
  7.2517 +	tray_move:		ide_cdrom_tray_move,
  7.2518 +	lock_door:		ide_cdrom_lock_door,
  7.2519 +	select_speed:		ide_cdrom_select_speed,
  7.2520 +	get_last_session:	ide_cdrom_get_last_session,
  7.2521 +	get_mcn:		ide_cdrom_get_mcn,
  7.2522 +	reset:			ide_cdrom_reset,
  7.2523 +	audio_ioctl:		ide_cdrom_audio_ioctl,
  7.2524 +	dev_ioctl:		ide_cdrom_dev_ioctl,
  7.2525 +	capability:		CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
  7.2526 +				CDC_SELECT_SPEED | CDC_SELECT_DISC |
  7.2527 +				CDC_MULTI_SESSION | CDC_MCN |
  7.2528 +				CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET |
  7.2529 +				CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_CD_R |
  7.2530 +				CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM |
  7.2531 +				CDC_GENERIC_PACKET,
  7.2532 +	generic_packet:		ide_cdrom_packet,
  7.2533 +};
  7.2534 +
  7.2535 +static int ide_cdrom_register (ide_drive_t *drive, int nslots)
  7.2536 +{
  7.2537 +	struct cdrom_info *info = drive->driver_data;
  7.2538 +	struct cdrom_device_info *devinfo = &info->devinfo;
  7.2539 +	int minor = (drive->select.b.unit) << PARTN_BITS;
  7.2540 +
  7.2541 +	devinfo->dev = MKDEV (HWIF(drive)->major, minor);
  7.2542 +	devinfo->ops = &ide_cdrom_dops;
  7.2543 +	devinfo->mask = 0;
  7.2544 +	*(int *)&devinfo->speed = CDROM_STATE_FLAGS (drive)->current_speed;
  7.2545 +	*(int *)&devinfo->capacity = nslots;
  7.2546 +	devinfo->handle = (void *) drive;
  7.2547 +	strcpy(devinfo->name, drive->name);
  7.2548 +	
  7.2549 +	/* set capability mask to match the probe. */
  7.2550 +	if (!CDROM_CONFIG_FLAGS (drive)->cd_r)
  7.2551 +		devinfo->mask |= CDC_CD_R;
  7.2552 +	if (!CDROM_CONFIG_FLAGS (drive)->cd_rw)
  7.2553 +		devinfo->mask |= CDC_CD_RW;
  7.2554 +	if (!CDROM_CONFIG_FLAGS (drive)->dvd)
  7.2555 +		devinfo->mask |= CDC_DVD;
  7.2556 +	if (!CDROM_CONFIG_FLAGS (drive)->dvd_r)
  7.2557 +		devinfo->mask |= CDC_DVD_R;
  7.2558 +	if (!CDROM_CONFIG_FLAGS (drive)->dvd_ram)
  7.2559 +		devinfo->mask |= CDC_DVD_RAM;
  7.2560 +	if (!CDROM_CONFIG_FLAGS (drive)->is_changer)
  7.2561 +		devinfo->mask |= CDC_SELECT_DISC;
  7.2562 +	if (!CDROM_CONFIG_FLAGS (drive)->audio_play)
  7.2563 +		devinfo->mask |= CDC_PLAY_AUDIO;
  7.2564 +	if (!CDROM_CONFIG_FLAGS (drive)->close_tray)
  7.2565 +		devinfo->mask |= CDC_CLOSE_TRAY;
  7.2566 +
  7.2567 +#if 0
  7.2568 +	devinfo->de = devfs_register(drive->de, "cd", DEVFS_FL_DEFAULT,
  7.2569 +				     HWIF(drive)->major, minor,
  7.2570 +				     S_IFBLK | S_IRUGO | S_IWUGO,
  7.2571 +				     ide_fops, NULL);
  7.2572 +#endif
  7.2573 +
  7.2574 +	return register_cdrom(devinfo);
  7.2575 +}
  7.2576 +
  7.2577 +static
  7.2578 +int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_page *cap)
  7.2579 +{
  7.2580 +	struct cdrom_info *info = drive->driver_data;
  7.2581 +	struct cdrom_device_info *cdi = &info->devinfo;
  7.2582 +	struct cdrom_generic_command cgc;
  7.2583 +	int stat, attempts = 3, size = sizeof(*cap);
  7.2584 +
  7.2585 +	/*
  7.2586 +	 * ACER50 (and others?) require the full spec length mode sense
  7.2587 +	 * page capabilities size, but older drives break.
  7.2588 +	 */
  7.2589 +	if (drive->id) {
  7.2590 +		if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") ||
  7.2591 +		    !strcmp(drive->id->model, "WPI CDS-32X")))
  7.2592 +			size -= sizeof(cap->pad);
  7.2593 +	}
  7.2594 +
  7.2595 +	/* we have to cheat a little here. the packet will eventually
  7.2596 +	 * be queued with ide_cdrom_packet(), which extracts the
  7.2597 +	 * drive from cdi->handle. Since this device hasn't been
  7.2598 +	 * registered with the Uniform layer yet, it can't do this.
  7.2599 +	 * Same goes for cdi->ops.
  7.2600 +	 */
  7.2601 +	cdi->handle = (ide_drive_t *) drive;
  7.2602 +	cdi->ops = &ide_cdrom_dops;
  7.2603 +	init_cdrom_command(&cgc, cap, size, CGC_DATA_UNKNOWN);
  7.2604 +	do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
  7.2605 +		stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
  7.2606 +		if (!stat)
  7.2607 +			break;
  7.2608 +	} while (--attempts);
  7.2609 +	return stat;
  7.2610 +}
  7.2611 +
  7.2612 +static
  7.2613 +int ide_cdrom_probe_capabilities (ide_drive_t *drive)
  7.2614 +{
  7.2615 +	struct cdrom_info *info = drive->driver_data;
  7.2616 +	struct cdrom_device_info *cdi = &info->devinfo;
  7.2617 +	struct atapi_capabilities_page cap;
  7.2618 +	int nslots = 1;
  7.2619 +
  7.2620 +	if (CDROM_CONFIG_FLAGS (drive)->nec260) {
  7.2621 +		CDROM_CONFIG_FLAGS (drive)->no_eject = 0;                       
  7.2622 +		CDROM_CONFIG_FLAGS (drive)->audio_play = 1;       
  7.2623 +		return nslots;
  7.2624 +	}
  7.2625 +
  7.2626 +	if (ide_cdrom_get_capabilities(drive, &cap))
  7.2627 +		return 0;
  7.2628 +
  7.2629 +	if (cap.lock == 0)
  7.2630 +		CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
  7.2631 +	if (cap.eject)
  7.2632 +		CDROM_CONFIG_FLAGS (drive)->no_eject = 0;
  7.2633 +	if (cap.cd_r_write)
  7.2634 +		CDROM_CONFIG_FLAGS (drive)->cd_r = 1;
  7.2635 +	if (cap.cd_rw_write)
  7.2636 +		CDROM_CONFIG_FLAGS (drive)->cd_rw = 1;
  7.2637 +	if (cap.test_write)
  7.2638 +		CDROM_CONFIG_FLAGS (drive)->test_write = 1;
  7.2639 +	if (cap.dvd_ram_read || cap.dvd_r_read || cap.dvd_rom)
  7.2640 +		CDROM_CONFIG_FLAGS (drive)->dvd = 1;
  7.2641 +	if (cap.dvd_ram_write)
  7.2642 +		CDROM_CONFIG_FLAGS (drive)->dvd_ram = 1;
  7.2643 +	if (cap.dvd_r_write)
  7.2644 +		CDROM_CONFIG_FLAGS (drive)->dvd_r = 1;
  7.2645 +	if (cap.audio_play)
  7.2646 +		CDROM_CONFIG_FLAGS (drive)->audio_play = 1;
  7.2647 +	if (cap.mechtype == mechtype_caddy || cap.mechtype == mechtype_popup)
  7.2648 +		CDROM_CONFIG_FLAGS (drive)->close_tray = 0;
  7.2649 +
  7.2650 +#if ! STANDARD_ATAPI
  7.2651 +	if (cdi->sanyo_slot > 0) {
  7.2652 +		CDROM_CONFIG_FLAGS (drive)->is_changer = 1;
  7.2653 +		nslots = 3;
  7.2654 +	}
  7.2655 +
  7.2656 +	else
  7.2657 +#endif /* not STANDARD_ATAPI */
  7.2658 +	if (cap.mechtype == mechtype_individual_changer ||
  7.2659 +	    cap.mechtype == mechtype_cartridge_changer) {
  7.2660 +		if ((nslots = cdrom_number_of_slots(cdi)) > 1) {
  7.2661 +			CDROM_CONFIG_FLAGS (drive)->is_changer = 1;
  7.2662 +			CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 1;
  7.2663 +		}
  7.2664 +	}
  7.2665 +
  7.2666 +	/* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
  7.2667 +	if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) {
  7.2668 +		CDROM_STATE_FLAGS (drive)->current_speed  = 
  7.2669 +			(((unsigned int)cap.curspeed) + (176/2)) / 176;
  7.2670 +		CDROM_CONFIG_FLAGS (drive)->max_speed = 
  7.2671 +			(((unsigned int)cap.maxspeed) + (176/2)) / 176;
  7.2672 +	} else {
  7.2673 +		CDROM_STATE_FLAGS (drive)->current_speed  = 
  7.2674 +			(ntohs(cap.curspeed) + (176/2)) / 176;
  7.2675 +		CDROM_CONFIG_FLAGS (drive)->max_speed = 
  7.2676 +			(ntohs(cap.maxspeed) + (176/2)) / 176;
  7.2677 +	}
  7.2678 +
  7.2679 +	/* don't print speed if the drive reported 0.
  7.2680 +	 */
  7.2681 +	printk("%s: ATAPI", drive->name);
  7.2682 +	if (CDROM_CONFIG_FLAGS(drive)->max_speed)
  7.2683 +		printk(" %dX", CDROM_CONFIG_FLAGS(drive)->max_speed);
  7.2684 +	printk(" %s", CDROM_CONFIG_FLAGS(drive)->dvd ? "DVD-ROM" : "CD-ROM");
  7.2685 +
  7.2686 +	if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_ram)
  7.2687 +        	printk (" DVD%s%s", 
  7.2688 +        	(CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-R" : "", 
  7.2689 +        	(CDROM_CONFIG_FLAGS (drive)->dvd_ram)? "-RAM" : "");
  7.2690 +
  7.2691 +        if (CDROM_CONFIG_FLAGS (drive)->cd_r|CDROM_CONFIG_FLAGS (drive)->cd_rw) 
  7.2692 +        	printk (" CD%s%s", 
  7.2693 +        	(CDROM_CONFIG_FLAGS (drive)->cd_r)? "-R" : "", 
  7.2694 +        	(CDROM_CONFIG_FLAGS (drive)->cd_rw)? "/RW" : "");
  7.2695 +
  7.2696 +        if (CDROM_CONFIG_FLAGS (drive)->is_changer) 
  7.2697 +        	printk (" changer w/%d slots", nslots);
  7.2698 +        else 	
  7.2699 +        	printk (" drive");
  7.2700 +
  7.2701 +	printk (", %dkB Cache", be16_to_cpu(cap.buffer_size));
  7.2702 +
  7.2703 +#ifdef CONFIG_BLK_DEV_IDEDMA
  7.2704 +	if (drive->using_dma)
  7.2705 +		(void) HWIF(drive)->dmaproc(ide_dma_verbose, drive);
  7.2706 +#endif /* CONFIG_BLK_DEV_IDEDMA */
  7.2707 +	printk("\n");
  7.2708 +
  7.2709 +	return nslots;
  7.2710 +}
  7.2711 +
  7.2712 +static void ide_cdrom_add_settings(ide_drive_t *drive)
  7.2713 +{
  7.2714 +#if 0 
  7.2715 +	int major = HWIF(drive)->major;
  7.2716 +	int minor = drive->select.b.unit << PARTN_BITS;
  7.2717 +
  7.2718 +	ide_add_setting(drive,	"breada_readahead",	SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL);
  7.2719 +	ide_add_setting(drive,	"file_readahead",	SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor],	NULL);
  7.2720 +	ide_add_setting(drive,	"max_kb_per_request",	SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL);
  7.2721 +#endif
  7.2722 +	ide_add_setting(drive,	"dsc_overlap",		SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1,	1, &drive->dsc_overlap, NULL);
  7.2723 +}
  7.2724 +
  7.2725 +static
  7.2726 +int ide_cdrom_setup (ide_drive_t *drive)
  7.2727 +{
  7.2728 +	struct cdrom_info *info = drive->driver_data;
  7.2729 +	struct cdrom_device_info *cdi = &info->devinfo;
  7.2730 +	int minor = drive->select.b.unit << PARTN_BITS;
  7.2731 +	int nslots;
  7.2732 +
  7.2733 +	/*
  7.2734 +	 * default to read-only always and fix latter at the bottom
  7.2735 +	 */
  7.2736 +	set_device_ro(MKDEV(HWIF(drive)->major, minor), 1);
  7.2737 +#if 0
  7.2738 +	set_blocksize(MKDEV(HWIF(drive)->major, minor), CD_FRAMESIZE);
  7.2739 +#endif
  7.2740 +
  7.2741 +	drive->special.all	= 0;
  7.2742 +	drive->ready_stat	= 0;
  7.2743 +
  7.2744 +	CDROM_STATE_FLAGS (drive)->media_changed = 1;
  7.2745 +	CDROM_STATE_FLAGS (drive)->toc_valid     = 0;
  7.2746 +	CDROM_STATE_FLAGS (drive)->door_locked   = 0;
  7.2747 +
  7.2748 +#if NO_DOOR_LOCKING
  7.2749 +	CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
  7.2750 +#else
  7.2751 +	CDROM_CONFIG_FLAGS (drive)->no_doorlock = 0;
  7.2752 +#endif
  7.2753 +
  7.2754 +	if (drive->id != NULL)
  7.2755 +		CDROM_CONFIG_FLAGS (drive)->drq_interrupt =
  7.2756 +			((drive->id->config & 0x0060) == 0x20);
  7.2757 +	else
  7.2758 +		CDROM_CONFIG_FLAGS (drive)->drq_interrupt = 0;
  7.2759 +
  7.2760 +	CDROM_CONFIG_FLAGS (drive)->is_changer = 0;
  7.2761 +	CDROM_CONFIG_FLAGS (drive)->cd_r = 0;
  7.2762 +	CDROM_CONFIG_FLAGS (drive)->cd_rw = 0;
  7.2763 +	CDROM_CONFIG_FLAGS (drive)->test_write = 0;
  7.2764 +	CDROM_CONFIG_FLAGS (drive)->dvd = 0;
  7.2765 +	CDROM_CONFIG_FLAGS (drive)->dvd_r = 0;
  7.2766 +	CDROM_CONFIG_FLAGS (drive)->dvd_ram = 0;
  7.2767 +	CDROM_CONFIG_FLAGS (drive)->no_eject = 1;
  7.2768 +	CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 0;
  7.2769 +	CDROM_CONFIG_FLAGS (drive)->audio_play = 0;
  7.2770 +	CDROM_CONFIG_FLAGS (drive)->close_tray = 1;
  7.2771 +	
  7.2772 +	/* limit transfer size per interrupt. */
  7.2773 +	CDROM_CONFIG_FLAGS (drive)->limit_nframes = 0;
  7.2774 +	if (drive->id != NULL) {
  7.2775 +		/* a testament to the nice quality of Samsung drives... */
  7.2776 +		if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430"))
  7.2777 +			CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
  7.2778 +		else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432"))
  7.2779 +			CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
  7.2780 +		/* the 3231 model does not support the SET_CD_SPEED command */
  7.2781 +		else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-3231"))
  7.2782 +			cdi->mask |= CDC_SELECT_SPEED;
  7.2783 +	}
  7.2784 +
  7.2785 +#if ! STANDARD_ATAPI
  7.2786 +	/* by default Sanyo 3 CD changer support is turned off and
  7.2787 +           ATAPI Rev 2.2+ standard support for CD changers is used */
  7.2788 +	cdi->sanyo_slot = 0;
  7.2789 +
  7.2790 +	CDROM_CONFIG_FLAGS (drive)->nec260 = 0;
  7.2791 +	CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 0;
  7.2792 +	CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd = 0;
  7.2793 +	CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 0;
  7.2794 +	CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 0;
  7.2795 +
  7.2796 +	if (drive->id != NULL) {
  7.2797 +		if (strcmp (drive->id->model, "V003S0DS") == 0 &&
  7.2798 +		    drive->id->fw_rev[4] == '1' &&
  7.2799 +		    drive->id->fw_rev[6] <= '2') {
  7.2800 +			/* Vertos 300.
  7.2801 +			   Some versions of this drive like to talk BCD. */
  7.2802 +			CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 1;
  7.2803 +			CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd = 1;
  7.2804 +			CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1;
  7.2805 +			CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1;
  7.2806 +		}
  7.2807 +
  7.2808 +		else if (strcmp (drive->id->model, "V006E0DS") == 0 &&
  7.2809 +		    drive->id->fw_rev[4] == '1' &&
  7.2810 +		    drive->id->fw_rev[6] <= '2') {
  7.2811 +			/* Vertos 600 ESD. */
  7.2812 +			CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 1;
  7.2813 +		}
  7.2814 +
  7.2815 +		else if (strcmp (drive->id->model,
  7.2816 +				 "NEC CD-ROM DRIVE:260") == 0 &&
  7.2817 +			 strncmp (drive->id->fw_rev, "1.01", 4) == 0) { /* FIXME */
  7.2818 +			/* Old NEC260 (not R).
  7.2819 +			   This drive was released before the 1.2 version
  7.2820 +			   of the spec. */
  7.2821 +			CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd = 1;
  7.2822 +			CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1;
  7.2823 +			CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1;
  7.2824 +			CDROM_CONFIG_FLAGS (drive)->nec260         = 1;
  7.2825 +		}
  7.2826 +
  7.2827 +		else if (strcmp (drive->id->model, "WEARNES CDD-120") == 0 &&
  7.2828 +			 strncmp (drive->id->fw_rev, "A1.1", 4) == 0) { /* FIXME */
  7.2829 +			/* Wearnes */
  7.2830 +			CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1;
  7.2831 +			CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1;
  7.2832 +		}
  7.2833 +
  7.2834 +                /* Sanyo 3 CD changer uses a non-standard command
  7.2835 +                    for CD changing */
  7.2836 +                 else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) ||
  7.2837 +                         (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) ||
  7.2838 +                         (strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) {
  7.2839 +                        /* uses CD in slot 0 when value is set to 3 */
  7.2840 +                        cdi->sanyo_slot = 3;
  7.2841 +                }
  7.2842 +
  7.2843 +
  7.2844 +	}
  7.2845 +#endif /* not STANDARD_ATAPI */
  7.2846 +
  7.2847 +	info->toc		= NULL;
  7.2848 +	info->buffer		= NULL;
  7.2849 +	info->sector_buffered	= 0;
  7.2850 +	info->nsectors_buffered	= 0;
  7.2851 +	info->changer_info      = NULL;
  7.2852 +	info->last_block	= 0;
  7.2853 +	info->start_seek	= 0;
  7.2854 +
  7.2855 +	nslots = ide_cdrom_probe_capabilities (drive);
  7.2856 +
  7.2857 +	if (CDROM_CONFIG_FLAGS(drive)->dvd_ram)
  7.2858 +		set_device_ro(MKDEV(HWIF(drive)->major, minor), 0);
  7.2859 +
  7.2860 +	if (ide_cdrom_register (drive, nslots)) {
  7.2861 +		printk ("%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
  7.2862 +		info->devinfo.handle = NULL;
  7.2863 +		return 1;
  7.2864 +	}
  7.2865 +	ide_cdrom_add_settings(drive);
  7.2866 +	return 0;
  7.2867 +}
  7.2868 +
  7.2869 +/* Forwarding functions to generic routines. */
  7.2870 +static
  7.2871 +int ide_cdrom_ioctl (ide_drive_t *drive,
  7.2872 +		     struct inode *inode, struct file *file,
  7.2873 +		     unsigned int cmd, unsigned long arg)
  7.2874 +{
  7.2875 +	return cdrom_ioctl (inode, file, cmd, arg);
  7.2876 +}
  7.2877 +
  7.2878 +static
  7.2879 +int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive)
  7.2880 +{
  7.2881 +	struct cdrom_info *info = drive->driver_data;
  7.2882 +	int rc = -ENOMEM;
  7.2883 +
  7.2884 +	MOD_INC_USE_COUNT;
  7.2885 +	if (info->buffer == NULL)
  7.2886 +		info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL);
  7.2887 +        if ((info->buffer == NULL) || (rc = cdrom_open(ip, fp))) {
  7.2888 +		drive->usage--;
  7.2889 +		MOD_DEC_USE_COUNT;
  7.2890 +	}
  7.2891 +	return rc;
  7.2892 +}
  7.2893 +
  7.2894 +static
  7.2895 +void ide_cdrom_release (struct inode *inode, struct file *file,
  7.2896 +			ide_drive_t *drive)
  7.2897 +{
  7.2898 +	cdrom_release (inode, file);
  7.2899 +	MOD_DEC_USE_COUNT;
  7.2900 +}
  7.2901 +
  7.2902 +static
  7.2903 +int ide_cdrom_check_media_change (ide_drive_t *drive)
  7.2904 +{
  7.2905 +	return cdrom_media_changed(MKDEV (HWIF (drive)->major,
  7.2906 +			(drive->select.b.unit) << PARTN_BITS));
  7.2907 +}
  7.2908 +
  7.2909 +static
  7.2910 +void ide_cdrom_revalidate (ide_drive_t *drive)
  7.2911 +{
  7.2912 +	struct cdrom_info *info = drive->driver_data;
  7.2913 +	struct atapi_toc *toc;
  7.2914 +	int minor = drive->select.b.unit << PARTN_BITS;
  7.2915 +	struct request_sense sense;
  7.2916 +
  7.2917 +	cdrom_read_toc(drive, &sense);
  7.2918 +
  7.2919 +	if (!CDROM_STATE_FLAGS(drive)->toc_valid)
  7.2920 +		return;
  7.2921 +
  7.2922 +	toc = info->toc;
  7.2923 +
  7.2924 +	/* for general /dev/cdrom like mounting, one big disc */
  7.2925 +	drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
  7.2926 +	HWIF(drive)->gd->sizes[minor] = toc->capacity * BLOCKS_PER_FRAME;
  7.2927 +
  7.2928 +	/*
  7.2929 +	 * reset block size, ide_revalidate_disk incorrectly sets it to
  7.2930 +	 * 1024 even for CDROM's
  7.2931 +	 */
  7.2932 +	blk_size[HWIF(drive)->major] = HWIF(drive)->gd->sizes;
  7.2933 +#if 0
  7.2934 +	set_blocksize(MKDEV(HWIF(drive)->major, minor), CD_FRAMESIZE);
  7.2935 +#endif
  7.2936 +}
  7.2937 +
  7.2938 +static
  7.2939 +unsigned long ide_cdrom_capacity (ide_drive_t *drive)
  7.2940 +{
  7.2941 +	unsigned long capacity;
  7.2942 +
  7.2943 +	if (cdrom_read_capacity(drive, &capacity, NULL))
  7.2944 +		return 0;
  7.2945 +
  7.2946 +	return capacity * SECTORS_PER_FRAME;
  7.2947 +}
  7.2948 +
  7.2949 +static
  7.2950 +int ide_cdrom_cleanup(ide_drive_t *drive)
  7.2951 +{
  7.2952 +	struct cdrom_info *info = drive->driver_data;
  7.2953 +	struct cdrom_device_info *devinfo = &info->devinfo;
  7.2954 +
  7.2955 +	if (ide_unregister_subdriver (drive))
  7.2956 +		return 1;
  7.2957 +	if (info->buffer != NULL)
  7.2958 +		kfree(info->buffer);
  7.2959 +	if (info->toc != NULL)
  7.2960 +		kfree(info->toc);
  7.2961 +	if (info->changer_info != NULL)
  7.2962 +		kfree(info->changer_info);
  7.2963 +	if (devinfo->handle == drive && unregister_cdrom (devinfo))
  7.2964 +		printk ("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name);
  7.2965 +	kfree(info);
  7.2966 +	drive->driver_data = NULL;
  7.2967 +	return 0;
  7.2968 +}
  7.2969 +
  7.2970 +static
  7.2971 +int ide_cdrom_reinit (ide_drive_t *drive)
  7.2972 +{
  7.2973 +	return 0;
  7.2974 +}
  7.2975 +
  7.2976 +static ide_driver_t ide_cdrom_driver = {
  7.2977 +	name:			"ide-cdrom",
  7.2978 +	version:		IDECD_VERSION,
  7.2979 +	media:			ide_cdrom,
  7.2980 +	busy:			0,
  7.2981 +	supports_dma:		1,
  7.2982 +	supports_dsc_overlap:	1,
  7.2983 +	cleanup:		ide_cdrom_cleanup,
  7.2984 +	do_request:		ide_do_rw_cdrom,
  7.2985 +	end_request:		NULL,
  7.2986 +	ioctl:			ide_cdrom_ioctl,
  7.2987 +	open:			ide_cdrom_open,
  7.2988 +	release:		ide_cdrom_release,
  7.2989 +	media_change:		ide_cdrom_check_media_change,
  7.2990 +	revalidate:		ide_cdrom_revalidate,
  7.2991 +	pre_reset:		NULL,
  7.2992 +	capacity:		ide_cdrom_capacity,
  7.2993 +	special:		NULL,
  7.2994 +#if 0
  7.2995 +	proc:			NULL,
  7.2996 +	driver_reinit:		ide_cdrom_reinit,
  7.2997 +#endif
  7.2998 +};
  7.2999 +
  7.3000 +int ide_cdrom_init(void);
  7.3001 +static ide_module_t ide_cdrom_module = {
  7.3002 +	IDE_DRIVER_MODULE,
  7.3003 +	ide_cdrom_init,
  7.3004 +	&ide_cdrom_driver,
  7.3005 +	NULL
  7.3006 +};
  7.3007 +
  7.3008 +/* options */
  7.3009 +char *ignore = NULL;
  7.3010 +
  7.3011 +MODULE_PARM(ignore, "s");
  7.3012 +MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
  7.3013 +
  7.3014 +static void __exit ide_cdrom_exit(void)
  7.3015 +{
  7.3016 +	ide_drive_t *drive;
  7.3017 +	int failed = 0;
  7.3018 +
  7.3019 +	while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, &ide_cdrom_driver, failed)) != NULL)
  7.3020 +		if (ide_cdrom_cleanup (drive)) {
  7.3021 +			printk ("%s: cleanup_module() called while still busy\n", drive->name);
  7.3022 +			failed++;
  7.3023 +		}
  7.3024 +	ide_unregister_module (&ide_cdrom_module);
  7.3025 +}
  7.3026 + 
  7.3027 +int ide_cdrom_init(void)
  7.3028 +{
  7.3029 +	ide_drive_t *drive;
  7.3030 +	struct cdrom_info *info;
  7.3031 +	int failed = 0;
  7.3032 +
  7.3033 +	MOD_INC_USE_COUNT;
  7.3034 +	while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, NULL, failed++)) != NULL) {
  7.3035 +		/* skip drives that we were told to ignore */
  7.3036 +		if (ignore != NULL) {
  7.3037 +			if (strstr(ignore, drive->name)) {
  7.3038 +				printk("ide-cd: ignoring drive %s\n", drive->name);
  7.3039 +				continue;
  7.3040 +			}
  7.3041 +		}
  7.3042 +		if (drive->scsi) {
  7.3043 +			printk("ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name);
  7.3044 +			continue;
  7.3045 +		}
  7.3046 +		info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL);
  7.3047 +		if (info == NULL) {
  7.3048 +			printk ("%s: Can't allocate a cdrom structure\n", drive->name);
  7.3049 +			continue;
  7.3050 +		}
  7.3051 +		if (ide_register_subdriver (drive, &ide_cdrom_driver, IDE_SUBDRIVER_VERSION)) {
  7.3052 +			printk ("%s: Failed to register the driver with ide.c\n", drive->name);
  7.3053 +			kfree (info);
  7.3054 +			continue;
  7.3055 +		}
  7.3056 +		memset (info, 0, sizeof (struct cdrom_info));
  7.3057 +		drive->driver_data = info;
  7.3058 +		DRIVER(drive)->busy++;
  7.3059 +		if (ide_cdrom_setup (drive)) {
  7.3060 +			DRIVER(drive)->busy--;
  7.3061 +			if (ide_cdrom_cleanup (drive))
  7.3062 +				printk ("%s: ide_cdrom_cleanup failed in ide_cdrom_init\n", drive->name);
  7.3063 +			continue;
  7.3064 +		}
  7.3065 +		DRIVER(drive)->busy--;
  7.3066 +		failed--;
  7.3067 +	}
  7.3068 +	ide_register_module(&ide_cdrom_module);
  7.3069 +	MOD_DEC_USE_COUNT;
  7.3070 +	return 0;
  7.3071 +}
  7.3072 +
  7.3073 +module_init(ide_cdrom_init);
  7.3074 +module_exit(ide_cdrom_exit);
  7.3075 +MODULE_LICENSE("GPL");
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/xen/drivers/ide/ide-cd.h	Tue Apr 15 15:26:05 2003 +0000
     8.3 @@ -0,0 +1,746 @@
     8.4 +/*
     8.5 + *  linux/drivers/ide/ide_cd.h
     8.6 + *
     8.7 + *  Copyright (C) 1996-98  Erik Andersen
     8.8 + *  Copyright (C) 1998-2000 Jens Axboe
     8.9 + */
    8.10 +#ifndef _IDE_CD_H
    8.11 +#define _IDE_CD_H
    8.12 +
    8.13 +#include <xeno/cdrom.h>
    8.14 +#include <asm/byteorder.h>
    8.15 +
    8.16 +/* Turn this on to have the driver print out the meanings of the
    8.17 +   ATAPI error codes.  This will use up additional kernel-space
    8.18 +   memory, though. */
    8.19 +
    8.20 +#ifndef VERBOSE_IDE_CD_ERRORS
    8.21 +#define VERBOSE_IDE_CD_ERRORS 1
    8.22 +#endif
    8.23 +
    8.24 +
    8.25 +/* Turning this on will remove code to work around various nonstandard
    8.26 +   ATAPI implementations.  If you know your drive follows the standard,
    8.27 +   this will give you a slightly smaller kernel. */
    8.28 +
    8.29 +#ifndef STANDARD_ATAPI
    8.30 +#define STANDARD_ATAPI 0
    8.31 +#endif
    8.32 +
    8.33 +
    8.34 +/* Turning this on will disable the door-locking functionality.
    8.35 +   This is apparently needed for supermount. */
    8.36 +
    8.37 +#ifndef NO_DOOR_LOCKING
    8.38 +#define NO_DOOR_LOCKING 0
    8.39 +#endif
    8.40 +
    8.41 +/************************************************************************/
    8.42 +
    8.43 +#define SECTOR_BITS 		9
    8.44 +// XXX SMH: already defined in ide.h
    8.45 +#ifdef SECTOR_SIZE
    8.46 +#undef SECTOR_SIZE 
    8.47 +#endif
    8.48 +#define SECTOR_SIZE		(1 << SECTOR_BITS)
    8.49 +#define SECTORS_PER_FRAME	(CD_FRAMESIZE >> SECTOR_BITS)
    8.50 +#define SECTOR_BUFFER_SIZE	(CD_FRAMESIZE * 32)
    8.51 +#define SECTORS_BUFFER		(SECTOR_BUFFER_SIZE >> SECTOR_BITS)
    8.52 +#define SECTORS_MAX		(131072 >> SECTOR_BITS)
    8.53 +
    8.54 +#define BLOCKS_PER_FRAME	(CD_FRAMESIZE / BLOCK_SIZE)
    8.55 +
    8.56 +#define MIN(a,b) ((a) < (b) ? (a) : (b))
    8.57 +
    8.58 +/* special command codes for strategy routine. */
    8.59 +#define PACKET_COMMAND        4315
    8.60 +#define REQUEST_SENSE_COMMAND 4316
    8.61 +#define RESET_DRIVE_COMMAND   4317
    8.62 +
    8.63 +
    8.64 +/* Configuration flags.  These describe the capabilities of the drive.
    8.65 +   They generally do not change after initialization, unless we learn
    8.66 +   more about the drive from stuff failing. */
    8.67 +struct ide_cd_config_flags {
    8.68 +	__u8 drq_interrupt	: 1; /* Device sends an interrupt when ready
    8.69 +					for a packet command. */
    8.70 +	__u8 no_doorlock	: 1; /* Drive cannot lock the door. */
    8.71 +	__u8 no_eject		: 1; /* Drive cannot eject the disc. */
    8.72 +	__u8 nec260		: 1; /* Drive is a pre-1.2 NEC 260 drive. */
    8.73 +	__u8 playmsf_as_bcd	: 1; /* PLAYMSF command takes BCD args. */
    8.74 +	__u8 tocaddr_as_bcd	: 1; /* TOC addresses are in BCD. */
    8.75 +	__u8 toctracks_as_bcd	: 1; /* TOC track numbers are in BCD. */
    8.76 +	__u8 subchan_as_bcd	: 1; /* Subchannel info is in BCD. */
    8.77 +	__u8 is_changer		: 1; /* Drive is a changer. */
    8.78 +	__u8 cd_r		: 1; /* Drive can write to CD-R media . */
    8.79 +	__u8 cd_rw		: 1; /* Drive can write to CD-R/W media . */
    8.80 +	__u8 dvd		: 1; /* Drive is a DVD-ROM */
    8.81 +	__u8 dvd_r		: 1; /* Drive can write DVD-R */
    8.82 +	__u8 dvd_ram		: 1; /* Drive can write DVD-RAM */
    8.83 +	__u8 test_write		: 1; /* Drive can fake writes */
    8.84 +	__u8 supp_disc_present	: 1; /* Changer can report exact contents
    8.85 +					of slots. */
    8.86 +	__u8 limit_nframes	: 1; /* Drive does not provide data in
    8.87 +					multiples of SECTOR_SIZE when more
    8.88 +					than one interrupt is needed. */
    8.89 +	__u8 seeking		: 1; /* Seeking in progress */
    8.90 +	__u8 audio_play		: 1; /* can do audio related commands */
    8.91 +	__u8 close_tray		: 1; /* can close the tray */
    8.92 +	__u8 writing		: 1; /* pseudo write in progress */
    8.93 +	__u8 reserved		: 3;
    8.94 +	byte max_speed;		     /* Max speed of the drive */
    8.95 +};
    8.96 +#define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags))
    8.97 +
    8.98 + 
    8.99 +/* State flags.  These give information about the current state of the
   8.100 +   drive, and will change during normal operation. */
   8.101 +struct ide_cd_state_flags {
   8.102 +	__u8 media_changed : 1; /* Driver has noticed a media change. */
   8.103 +	__u8 toc_valid     : 1; /* Saved TOC information is current. */
   8.104 +	__u8 door_locked   : 1; /* We think that the drive door is locked. */
   8.105 +	__u8 writing       : 1; /* the drive is currently writing */
   8.106 +	__u8 reserved      : 4;
   8.107 +	byte current_speed;	/* Current speed of the drive */
   8.108 +};
   8.109 +
   8.110 +#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags))
   8.111 +
   8.112 +struct packet_command {
   8.113 +	char *buffer;
   8.114 +	int buflen;
   8.115 +	int stat;
   8.116 +	int quiet;
   8.117 +	int timeout;
   8.118 +	struct request_sense *sense;
   8.119 +	unsigned char c[12];
   8.120 +};
   8.121 +
   8.122 +/* Structure of a MSF cdrom address. */
   8.123 +struct atapi_msf {
   8.124 +	byte reserved;
   8.125 +	byte minute;
   8.126 +	byte second;
   8.127 +	byte frame;
   8.128 +};
   8.129 +
   8.130 +/* Space to hold the disk TOC. */
   8.131 +#define MAX_TRACKS 99
   8.132 +struct atapi_toc_header {
   8.133 +	unsigned short toc_length;
   8.134 +	byte first_track;
   8.135 +	byte last_track;
   8.136 +};
   8.137 +
   8.138 +struct atapi_toc_entry {
   8.139 +	byte reserved1;
   8.140 +#if defined(__BIG_ENDIAN_BITFIELD)
   8.141 +	__u8 adr     : 4;
   8.142 +	__u8 control : 4;
   8.143 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   8.144 +	__u8 control : 4;
   8.145 +	__u8 adr     : 4;
   8.146 +#else
   8.147 +#error "Please fix <asm/byteorder.h>"
   8.148 +#endif
   8.149 +	byte track;
   8.150 +	byte reserved2;
   8.151 +	union {
   8.152 +		unsigned lba;
   8.153 +		struct atapi_msf msf;
   8.154 +	} addr;
   8.155 +};
   8.156 +
   8.157 +struct atapi_toc {
   8.158 +	int    last_session_lba;
   8.159 +	int    xa_flag;
   8.160 +	unsigned long capacity;
   8.161 +	struct atapi_toc_header hdr;
   8.162 +	struct atapi_toc_entry  ent[MAX_TRACKS+1];
   8.163 +	  /* One extra for the leadout. */
   8.164 +};
   8.165 +
   8.166 +
   8.167 +/* This structure is annoyingly close to, but not identical with,
   8.168 +   the cdrom_subchnl structure from cdrom.h. */
   8.169 +struct atapi_cdrom_subchnl {
   8.170 + 	u_char  acdsc_reserved;
   8.171 + 	u_char  acdsc_audiostatus;
   8.172 + 	u_short acdsc_length;
   8.173 +	u_char  acdsc_format;
   8.174 +
   8.175 +#if defined(__BIG_ENDIAN_BITFIELD)
   8.176 +	u_char  acdsc_ctrl:     4;
   8.177 +	u_char  acdsc_adr:      4;
   8.178 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   8.179 +	u_char  acdsc_adr:	4;
   8.180 +	u_char  acdsc_ctrl:	4;
   8.181 +#else
   8.182 +#error "Please fix <asm/byteorder.h>"
   8.183 +#endif
   8.184 +	u_char  acdsc_trk;
   8.185 +	u_char  acdsc_ind;
   8.186 +	union {
   8.187 +		struct atapi_msf msf;
   8.188 +		int	lba;
   8.189 +	} acdsc_absaddr;
   8.190 +	union {
   8.191 +		struct atapi_msf msf;
   8.192 +		int	lba;
   8.193 +	} acdsc_reladdr;
   8.194 +};
   8.195 +
   8.196 +
   8.197 +
   8.198 +/* This should probably go into cdrom.h along with the other
   8.199 + * generic stuff now in the Mt. Fuji spec.
   8.200 + */
   8.201 +struct atapi_capabilities_page {
   8.202 +	struct mode_page_header header;
   8.203 +#if defined(__BIG_ENDIAN_BITFIELD)
   8.204 +	__u8 parameters_saveable : 1;
   8.205 +	__u8 reserved1           : 1;
   8.206 +	__u8 page_code           : 6;
   8.207 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   8.208 +	__u8 page_code           : 6;
   8.209 +	__u8 reserved1           : 1;
   8.210 +	__u8 parameters_saveable : 1;
   8.211 +#else
   8.212 +#error "Please fix <asm/byteorder.h>"
   8.213 +#endif
   8.214 +
   8.215 +	byte     page_length;
   8.216 +
   8.217 +#if defined(__BIG_ENDIAN_BITFIELD)
   8.218 +	__u8 reserved2           : 2;
   8.219 +	/* Drive supports reading of DVD-RAM discs */
   8.220 +	__u8 dvd_ram_read        : 1;
   8.221 +	/* Drive supports reading of DVD-R discs */
   8.222 +	__u8 dvd_r_read          : 1;
   8.223 +	/* Drive supports reading of DVD-ROM discs */
   8.224 +	__u8 dvd_rom             : 1;
   8.225 +	/* Drive supports reading CD-R discs with addressing method 2 */
   8.226 +	__u8 method2             : 1; /* reserved in 1.2 */
   8.227 +	/* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
   8.228 +	__u8 cd_rw_read		 : 1; /* reserved in 1.2 */
   8.229 +	/* Drive supports read from CD-R discs (orange book, part II) */
   8.230 +	__u8 cd_r_read           : 1; /* reserved in 1.2 */
   8.231 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   8.232 +	/* Drive supports read from CD-R discs (orange book, part II) */
   8.233 +	__u8 cd_r_read           : 1; /* reserved in 1.2 */
   8.234 +	/* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
   8.235 +	__u8 cd_rw_read          : 1; /* reserved in 1.2 */
   8.236 +	/* Drive supports reading CD-R discs with addressing method 2 */
   8.237 +	__u8 method2             : 1;
   8.238 +	/* Drive supports reading of DVD-ROM discs */
   8.239 +	__u8 dvd_rom             : 1;
   8.240 +	/* Drive supports reading of DVD-R discs */
   8.241 +	__u8 dvd_r_read          : 1;
   8.242 +	/* Drive supports reading of DVD-RAM discs */
   8.243 +	__u8 dvd_ram_read        : 1;
   8.244 +	__u8 reserved2		 : 2;
   8.245 +#else
   8.246 +#error "Please fix <asm/byteorder.h>"
   8.247 +#endif
   8.248 +
   8.249 +#if defined(__BIG_ENDIAN_BITFIELD)
   8.250 +	__u8 reserved3           : 2;
   8.251 +	/* Drive can write DVD-RAM discs */
   8.252 +	__u8 dvd_ram_write       : 1;
   8.253 +	/* Drive can write DVD-R discs */
   8.254 +	__u8 dvd_r_write         : 1;
   8.255 +	__u8 reserved3a          : 1;
   8.256 +	/* Drive can fake writes */
   8.257 +	__u8 test_write          : 1;
   8.258 +	/* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
   8.259 +	__u8 cd_rw_write	 : 1; /* reserved in 1.2 */
   8.260 +	/* Drive supports write to CD-R discs (orange book, part II) */
   8.261 +	__u8 cd_r_write          : 1; /* reserved in 1.2 */
   8.262 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   8.263 +	/* Drive can write to CD-R discs (orange book, part II) */
   8.264 +	__u8 cd_r_write          : 1; /* reserved in 1.2 */
   8.265 +	/* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
   8.266 +	__u8 cd_rw_write	 : 1; /* reserved in 1.2 */
   8.267 +	/* Drive can fake writes */
   8.268 +	__u8 test_write          : 1;
   8.269 +	__u8 reserved3a          : 1;
   8.270 +	/* Drive can write DVD-R discs */
   8.271 +	__u8 dvd_r_write         : 1;
   8.272 +	/* Drive can write DVD-RAM discs */
   8.273 +	__u8 dvd_ram_write       : 1;
   8.274 +	__u8 reserved3           : 2;
   8.275 +#else
   8.276 +#error "Please fix <asm/byteorder.h>"
   8.277 +#endif
   8.278 +
   8.279 +#if defined(__BIG_ENDIAN_BITFIELD)
   8.280 +	__u8 reserved4           : 1;
   8.281 +	/* Drive can read multisession discs. */
   8.282 +	__u8 multisession        : 1;
   8.283 +	/* Drive can read mode 2, form 2 data. */
   8.284 +	__u8 mode2_form2         : 1;
   8.285 +	/* Drive can read mode 2, form 1 (XA) data. */
   8.286 +	__u8 mode2_form1         : 1;
   8.287 +	/* Drive supports digital output on port 2. */
   8.288 +	__u8 digport2            : 1;
   8.289 +	/* Drive supports digital output on port 1. */
   8.290 +	__u8 digport1            : 1;
   8.291 +	/* Drive can deliver a composite audio/video data stream. */
   8.292 +	__u8 composite           : 1;
   8.293 +	/* Drive supports audio play operations. */
   8.294 +	__u8 audio_play          : 1;
   8.295 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   8.296 +	/* Drive supports audio play operations. */
   8.297 +	__u8 audio_play          : 1;
   8.298 +	/* Drive can deliver a composite audio/video data stream. */
   8.299 +	__u8 composite           : 1;
   8.300 +	/* Drive supports digital output on port 1. */
   8.301 +	__u8 digport1            : 1;
   8.302 +	/* Drive supports digital output on port 2. */
   8.303 +	__u8 digport2            : 1;
   8.304 +	/* Drive can read mode 2, form 1 (XA) data. */
   8.305 +	__u8 mode2_form1         : 1;
   8.306 +	/* Drive can read mode 2, form 2 data. */
   8.307 +	__u8 mode2_form2         : 1;
   8.308 +	/* Drive can read multisession discs. */
   8.309 +	__u8 multisession        : 1;
   8.310 +	__u8 reserved4           : 1;
   8.311 +#else
   8.312 +#error "Please fix <asm/byteorder.h>"
   8.313 +#endif
   8.314 +
   8.315 +#if defined(__BIG_ENDIAN_BITFIELD)
   8.316 +	__u8 reserved5           : 1;
   8.317 +	/* Drive can return Media Catalog Number (UPC) info. */
   8.318 +	__u8 upc                 : 1;
   8.319 +	/* Drive can return International Standard Recording Code info. */
   8.320 +	__u8 isrc                : 1;
   8.321 +	/* Drive supports C2 error pointers. */
   8.322 +	__u8 c2_pointers         : 1;
   8.323 +	/* R-W data will be returned deinterleaved and error corrected. */
   8.324 +	__u8 rw_corr             : 1;
   8.325 +	/* Subchannel reads can return combined R-W information. */
   8.326 +	__u8 rw_supported        : 1;
   8.327 +	/* Drive can continue a read cdda operation from a loss of streaming.*/
   8.328 +	__u8 cdda_accurate       : 1;
   8.329 +	/* Drive can read Red Book audio data. */
   8.330 +	__u8 cdda                : 1;
   8.331 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   8.332 +	/* Drive can read Red Book audio data. */
   8.333 +	__u8 cdda                : 1;
   8.334 +	/* Drive can continue a read cdda operation from a loss of streaming.*/
   8.335 +	__u8 cdda_accurate       : 1;
   8.336 +	/* Subchannel reads can return combined R-W information. */
   8.337 +	__u8 rw_supported        : 1;
   8.338 +	/* R-W data will be returned deinterleaved and error corrected. */
   8.339 +	__u8 rw_corr             : 1;
   8.340 +	/* Drive supports C2 error pointers. */
   8.341 +	__u8 c2_pointers         : 1;
   8.342 +	/* Drive can return International Standard Recording Code info. */
   8.343 +	__u8 isrc                : 1;
   8.344 +	/* Drive can return Media Catalog Number (UPC) info. */
   8.345 +	__u8 upc                 : 1;
   8.346 +	__u8 reserved5           : 1;
   8.347 +#else
   8.348 +#error "Please fix <asm/byteorder.h>"
   8.349 +#endif
   8.350 +
   8.351 +#if defined(__BIG_ENDIAN_BITFIELD)
   8.352 +	/* Drive mechanism types. */
   8.353 +	mechtype_t mechtype	 : 3;
   8.354 +	__u8 reserved6           : 1;
   8.355 +	/* Drive can eject a disc or changer cartridge. */
   8.356 +	__u8 eject               : 1;
   8.357 +	/* State of prevent/allow jumper. */
   8.358 +	__u8 prevent_jumper      : 1;
   8.359 +	/* Present state of door lock. */
   8.360 +	__u8 lock_state          : 1;
   8.361 +	/* Drive can lock the door. */
   8.362 +	__u8 lock                : 1;
   8.363 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   8.364 +
   8.365 +	/* Drive can lock the door. */
   8.366 +	__u8 lock                : 1;
   8.367 +	/* Present state of door lock. */
   8.368 +	__u8 lock_state          : 1;
   8.369 +	/* State of prevent/allow jumper. */
   8.370 +	__u8 prevent_jumper      : 1;
   8.371 +	/* Drive can eject a disc or changer cartridge. */
   8.372 +	__u8 eject               : 1;
   8.373 +	__u8 reserved6           : 1;
   8.374 +	/* Drive mechanism types. */
   8.375 +	mechtype_t mechtype	 : 3;
   8.376 +#else
   8.377 +#error "Please fix <asm/byteorder.h>"
   8.378 +#endif
   8.379 +
   8.380 +#if defined(__BIG_ENDIAN_BITFIELD)
   8.381 +	__u8 reserved7           : 4;
   8.382 +	/* Drive supports software slot selection. */
   8.383 +	__u8 sss                 : 1;  /* reserved in 1.2 */
   8.384 +	/* Changer can report exact contents of slots. */
   8.385 +	__u8 disc_present        : 1;  /* reserved in 1.2 */
   8.386 +	/* Audio for each channel can be muted independently. */
   8.387 +	__u8 separate_mute       : 1;
   8.388 +	/* Audio level for each channel can be controlled independently. */
   8.389 +	__u8 separate_volume     : 1;
   8.390 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   8.391 +
   8.392 +	/* Audio level for each channel can be controlled independently. */
   8.393 +	__u8 separate_volume     : 1;
   8.394 +	/* Audio for each channel can be muted independently. */
   8.395 +	__u8 separate_mute       : 1;
   8.396 +	/* Changer can report exact contents of slots. */
   8.397 +	__u8 disc_present        : 1;  /* reserved in 1.2 */
   8.398 +	/* Drive supports software slot selection. */
   8.399 +	__u8 sss                 : 1;  /* reserved in 1.2 */
   8.400 +	__u8 reserved7           : 4;
   8.401 +#else
   8.402 +#error "Please fix <asm/byteorder.h>"
   8.403 +#endif
   8.404 +
   8.405 +	/* Note: the following four fields are returned in big-endian form. */
   8.406 +	/* Maximum speed (in kB/s). */
   8.407 +	unsigned short maxspeed;
   8.408 +	/* Number of discrete volume levels. */
   8.409 +	unsigned short n_vol_levels;
   8.410 +	/* Size of cache in drive, in kB. */
   8.411 +	unsigned short buffer_size;
   8.412 +	/* Current speed (in kB/s). */
   8.413 +	unsigned short curspeed;
   8.414 +	char pad[4];
   8.415 +};
   8.416 +
   8.417 +
   8.418 +struct atapi_mechstat_header {
   8.419 +#if defined(__BIG_ENDIAN_BITFIELD)
   8.420 +	__u8 fault         : 1;
   8.421 +	__u8 changer_state : 2;
   8.422 +	__u8 curslot       : 5;
   8.423 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   8.424 +	__u8 curslot       : 5;
   8.425 +	__u8 changer_state : 2;
   8.426 +	__u8 fault         : 1;
   8.427 +#else
   8.428 +#error "Please fix <asm/byteorder.h>"
   8.429 +#endif
   8.430 +
   8.431 +#if defined(__BIG_ENDIAN_BITFIELD)
   8.432 +	__u8 mech_state    : 3;
   8.433 +	__u8 door_open     : 1;
   8.434 +	__u8 reserved1     : 4;
   8.435 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   8.436 +	__u8 reserved1     : 4;
   8.437 +	__u8 door_open     : 1;
   8.438 +	__u8 mech_state    : 3;
   8.439 +#else
   8.440 +#error "Please fix <asm/byteorder.h>"
   8.441 +#endif
   8.442 +
   8.443 +	byte     curlba[3];
   8.444 +	byte     nslots;
   8.445 +	__u8 short slot_tablelen;
   8.446 +};
   8.447 +
   8.448 +
   8.449 +struct atapi_slot {
   8.450 +#if defined(__BIG_ENDIAN_BITFIELD)
   8.451 +	__u8 disc_present : 1;
   8.452 +	__u8 reserved1    : 6;
   8.453 +	__u8 change       : 1;
   8.454 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   8.455 +	__u8 change       : 1;
   8.456 +	__u8 reserved1    : 6;
   8.457 +	__u8 disc_present : 1;
   8.458 +#else
   8.459 +#error "Please fix <asm/byteorder.h>"
   8.460 +#endif
   8.461 +
   8.462 +	byte reserved2[3];
   8.463 +};
   8.464 +
   8.465 +struct atapi_changer_info {
   8.466 +	struct atapi_mechstat_header hdr;
   8.467 +	struct atapi_slot slots[0];
   8.468 +};
   8.469 +
   8.470 +/* Extra per-device info for cdrom drives. */
   8.471 +struct cdrom_info {
   8.472 +
   8.473 +	/* Buffer for table of contents.  NULL if we haven't allocated
   8.474 +	   a TOC buffer for this device yet. */
   8.475 +
   8.476 +	struct atapi_toc *toc;
   8.477 +
   8.478 +	unsigned long	sector_buffered;
   8.479 +	unsigned long	nsectors_buffered;
   8.480 +	unsigned char	*buffer;
   8.481 +
   8.482 +	/* The result of the last successful request sense command
   8.483 +	   on this device. */
   8.484 +	struct request_sense sense_data;
   8.485 +
   8.486 +	struct request request_sense_request;
   8.487 +	struct packet_command request_sense_pc;
   8.488 +	int dma;
   8.489 +	int cmd;
   8.490 +	unsigned long last_block;
   8.491 +	unsigned long start_seek;
   8.492 +	/* Buffer to hold mechanism status and changer slot table. */
   8.493 +	struct atapi_changer_info *changer_info;
   8.494 +
   8.495 +	struct ide_cd_config_flags	config_flags;
   8.496 +	struct ide_cd_state_flags	state_flags;
   8.497 +
   8.498 +        /* Per-device info needed by cdrom.c generic driver. */
   8.499 +        struct cdrom_device_info devinfo;
   8.500 +};
   8.501 +
   8.502 +/****************************************************************************
   8.503 + * Descriptions of ATAPI error codes.
   8.504 + */
   8.505 +
   8.506 +#define ARY_LEN(a) ((sizeof(a) / sizeof(a[0])))
   8.507 +
   8.508 +/* This stuff should be in cdrom.h, since it is now generic... */
   8.509 +
   8.510 +/* ATAPI sense keys (from table 140 of ATAPI 2.6) */
   8.511 +#define NO_SENSE                0x00
   8.512 +#define RECOVERED_ERROR         0x01
   8.513 +#define NOT_READY               0x02
   8.514 +#define MEDIUM_ERROR            0x03
   8.515 +#define HARDWARE_ERROR          0x04
   8.516 +#define ILLEGAL_REQUEST         0x05
   8.517 +#define UNIT_ATTENTION          0x06
   8.518 +#define DATA_PROTECT            0x07
   8.519 +#define ABORTED_COMMAND         0x0b
   8.520 +#define MISCOMPARE              0x0e
   8.521 +
   8.522 + 
   8.523 +
   8.524 +/* This stuff should be in cdrom.h, since it is now generic... */
   8.525 +#if VERBOSE_IDE_CD_ERRORS
   8.526 +
   8.527 + /* The generic packet command opcodes for CD/DVD Logical Units,
   8.528 + * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ 
   8.529 +const struct {
   8.530 +	unsigned short packet_command;
   8.531 +	const char * const text;
   8.532 +} packet_command_texts[] = {
   8.533 +	{ GPCMD_TEST_UNIT_READY, "Test Unit Ready" },
   8.534 +	{ GPCMD_REQUEST_SENSE, "Request Sense" },
   8.535 +	{ GPCMD_FORMAT_UNIT, "Format Unit" },
   8.536 +	{ GPCMD_INQUIRY, "Inquiry" },
   8.537 +	{ GPCMD_START_STOP_UNIT, "Start/Stop Unit" },
   8.538 +	{ GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" },
   8.539 +	{ GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" },
   8.540 +	{ GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" },
   8.541 +	{ GPCMD_READ_10, "Read 10" },
   8.542 +	{ GPCMD_WRITE_10, "Write 10" },
   8.543 +	{ GPCMD_SEEK, "Seek" },
   8.544 +	{ GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" },
   8.545 +	{ GPCMD_VERIFY_10, "Verify 10" },
   8.546 +	{ GPCMD_FLUSH_CACHE, "Flush Cache" },
   8.547 +	{ GPCMD_READ_SUBCHANNEL, "Read Subchannel" },
   8.548 +	{ GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" },
   8.549 +	{ GPCMD_READ_HEADER, "Read Header" },
   8.550 +	{ GPCMD_PLAY_AUDIO_10, "Play Audio 10" },
   8.551 +	{ GPCMD_GET_CONFIGURATION, "Get Configuration" },
   8.552 +	{ GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" },
   8.553 +	{ GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" },
   8.554 +	{ GPCMD_GET_EVENT_STATUS_NOTIFICATION, "Get Event Status Notification" },
   8.555 +	{ GPCMD_PAUSE_RESUME, "Pause/Resume" },
   8.556 +	{ GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" },
   8.557 +	{ GPCMD_READ_DISC_INFO, "Read Disc Info" },
   8.558 +	{ GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" },
   8.559 +	{ GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" },
   8.560 +	{ GPCMD_SEND_OPC, "Send OPC" },
   8.561 +	{ GPCMD_MODE_SELECT_10, "Mode Select 10" },
   8.562 +	{ GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" },
   8.563 +	{ GPCMD_MODE_SENSE_10, "Mode Sense 10" },
   8.564 +	{ GPCMD_CLOSE_TRACK, "Close Track" },
   8.565 +	{ GPCMD_BLANK, "Blank" },
   8.566 +	{ GPCMD_SEND_EVENT, "Send Event" },
   8.567 +	{ GPCMD_SEND_KEY, "Send Key" },
   8.568 +	{ GPCMD_REPORT_KEY, "Report Key" },
   8.569 +	{ GPCMD_LOAD_UNLOAD, "Load/Unload" },
   8.570 +	{ GPCMD_SET_READ_AHEAD, "Set Read-ahead" },
   8.571 +	{ GPCMD_READ_12, "Read 12" },
   8.572 +	{ GPCMD_GET_PERFORMANCE, "Get Performance" },
   8.573 +	{ GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" },
   8.574 +	{ GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" },
   8.575 +	{ GPCMD_SET_STREAMING, "Set Streaming" },
   8.576 +	{ GPCMD_READ_CD_MSF, "Read CD MSF" },
   8.577 +	{ GPCMD_SCAN, "Scan" },
   8.578 +	{ GPCMD_SET_SPEED, "Set Speed" },
   8.579 +	{ GPCMD_PLAY_CD, "Play CD" },
   8.580 +	{ GPCMD_MECHANISM_STATUS, "Mechanism Status" },
   8.581 +	{ GPCMD_READ_CD, "Read CD" },
   8.582 +};
   8.583 +
   8.584 +
   8.585 +
   8.586 +/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
   8.587 +const char * const sense_key_texts[16] = {
   8.588 +	"No sense data",
   8.589 +	"Recovered error",
   8.590 +	"Not ready",
   8.591 +	"Medium error",
   8.592 +	"Hardware error",
   8.593 +	"Illegal request",
   8.594 +	"Unit attention",
   8.595 +	"Data protect",
   8.596 +	"(reserved)",
   8.597 +	"(reserved)",
   8.598 +	"(reserved)",
   8.599 +	"Aborted command",
   8.600 +	"(reserved)",
   8.601 +	"(reserved)",
   8.602 +	"Miscompare",
   8.603 +	"(reserved)",
   8.604 +};
   8.605 +
   8.606 +/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
   8.607 +const struct {
   8.608 +	unsigned long asc_ascq;
   8.609 +	const char * const text;
   8.610 +} sense_data_texts[] = {
   8.611 +	{ 0x000000, "No additional sense information" },
   8.612 +	{ 0x000011, "Play operation in progress" },
   8.613 +	{ 0x000012, "Play operation paused" },
   8.614 +	{ 0x000013, "Play operation successfully completed" },
   8.615 +	{ 0x000014, "Play operation stopped due to error" },
   8.616 +	{ 0x000015, "No current audio status to return" },
   8.617 +	{ 0x010c0a, "Write error - padding blocks added" },
   8.618 +	{ 0x011700, "Recovered data with no error correction applied" },
   8.619 +	{ 0x011701, "Recovered data with retries" },
   8.620 +	{ 0x011702, "Recovered data with positive head offset" },
   8.621 +	{ 0x011703, "Recovered data with negative head offset" },
   8.622 +	{ 0x011704, "Recovered data with retries and/or CIRC applied" },
   8.623 +	{ 0x011705, "Recovered data using previous sector ID" },
   8.624 +	{ 0x011800, "Recovered data with error correction applied" },
   8.625 +	{ 0x011801, "Recovered data with error correction and retries applied"},
   8.626 +	{ 0x011802, "Recovered data - the data was auto-reallocated" },
   8.627 +	{ 0x011803, "Recovered data with CIRC" },
   8.628 +	{ 0x011804, "Recovered data with L-EC" },
   8.629 +	{ 0x015d00, 
   8.630 +	    "Failure prediction threshold exceeded - Predicted logical unit failure" },
   8.631 +	{ 0x015d01, 
   8.632 +	    "Failure prediction threshold exceeded - Predicted media failure" },
   8.633 +	{ 0x015dff, "Failure prediction threshold exceeded - False" },
   8.634 +	{ 0x017301, "Power calibration area almost full" },
   8.635 +	{ 0x020400, "Logical unit not ready - cause not reportable" },
   8.636 +	/* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */
   8.637 +	{ 0x020401,
   8.638 +	  "Logical unit not ready - in progress [sic] of becoming ready" },
   8.639 +	{ 0x020402, "Logical unit not ready - initializing command required" },
   8.640 +	{ 0x020403, "Logical unit not ready - manual intervention required" },
   8.641 +	{ 0x020404, "Logical unit not ready - format in progress" },
   8.642 +	{ 0x020407, "Logical unit not ready - operation in progress" },
   8.643 +	{ 0x020408, "Logical unit not ready - long write in progress" },
   8.644 +	{ 0x020600, "No reference position found (media may be upside down)" },
   8.645 +	{ 0x023000, "Incompatible medium installed" },
   8.646 +	{ 0x023a00, "Medium not present" },
   8.647 +	{ 0x025300, "Media load or eject failed" },
   8.648 +	{ 0x025700, "Unable to recover table of contents" },
   8.649 +	{ 0x030300, "Peripheral device write fault" },
   8.650 +	{ 0x030301, "No write current" },
   8.651 +	{ 0x030302, "Excessive write errors" },
   8.652 +	{ 0x030c00, "Write error" },
   8.653 +	{ 0x030c01, "Write error - Recovered with auto reallocation" },
   8.654 +	{ 0x030c02, "Write error - auto reallocation failed" },
   8.655 +	{ 0x030c03, "Write error - recommend reassignment" },
   8.656 +	{ 0x030c04, "Compression check miscompare error" },
   8.657 +	{ 0x030c05, "Data expansion occurred during compress" },
   8.658 +	{ 0x030c06, "Block not compressible" },
   8.659 +	{ 0x030c07, "Write error - recovery needed" },
   8.660 +	{ 0x030c08, "Write error - recovery failed" },
   8.661 +	{ 0x030c09, "Write error - loss of streaming" },
   8.662 +	{ 0x031100, "Unrecovered read error" },
   8.663 +	{ 0x031106, "CIRC unrecovered error" },
   8.664 +	{ 0x033101, "Format command failed" },
   8.665 +	{ 0x033200, "No defect spare location available" },
   8.666 +	{ 0x033201, "Defect list update failure" },
   8.667 +	{ 0x035100, "Erase failure" },
   8.668 +	{ 0x037200, "Session fixation error" },
   8.669 +	{ 0x037201, "Session fixation error writin lead-in" },
   8.670 +	{ 0x037202, "Session fixation error writin lead-out" },
   8.671 +	{ 0x037300, "CD control error" },
   8.672 +	{ 0x037302, "Power calibration area is full" },
   8.673 +	{ 0x037303, "Power calibration area error" },
   8.674 +	{ 0x037304, "Program memory area / RMA update failure" },
   8.675 +	{ 0x037305, "Program memory area / RMA is full" },
   8.676 +	{ 0x037306, "Program memory area / RMA is (almost) full" },
   8.677 +
   8.678 +	{ 0x040200, "No seek complete" },
   8.679 +	{ 0x040300, "Write fault" },
   8.680 +	{ 0x040900, "Track following error" },
   8.681 +	{ 0x040901, "Tracking servo failure" },
   8.682 +	{ 0x040902, "Focus servo failure" },
   8.683 +	{ 0x040903, "Spindle servo failure" },
   8.684 +	{ 0x041500, "Random positioning error" },
   8.685 +	{ 0x041501, "Mechanical positioning or changer error" },
   8.686 +	{ 0x041502, "Positioning error detected by read of medium" },
   8.687 +	{ 0x043c00, "Mechanical positioning or changer error" },
   8.688 +	{ 0x044000, "Diagnostic failure on component (ASCQ)" },
   8.689 +	{ 0x044400, "Internal CD/DVD logical unit failure" },
   8.690 +	{ 0x04b600, "Media load mechanism failed" },
   8.691 +	{ 0x051a00, "Parameter list length error" },
   8.692 +	{ 0x052000, "Invalid command operation code" },
   8.693 +	{ 0x052100, "Logical block address out of range" },
   8.694 +	{ 0x052102, "Invalid address for write" },
   8.695 +	{ 0x052400, "Invalid field in command packet" },
   8.696 +	{ 0x052600, "Invalid field in parameter list" },
   8.697 +	{ 0x052601, "Parameter not supported" },
   8.698 +	{ 0x052602, "Parameter value invalid" },
   8.699 +	{ 0x052700, "Write protected media" },
   8.700 +	{ 0x052c00, "Command sequence error" },
   8.701 +	{ 0x052c03, "Current program area is not empty" },
   8.702 +	{ 0x052c04, "Current program area is empty" },
   8.703 +	{ 0x053001, "Cannot read medium - unknown format" },
   8.704 +	{ 0x053002, "Cannot read medium - incompatible format" },
   8.705 +	{ 0x053900, "Saving parameters not supported" },
   8.706 +	{ 0x054e00, "Overlapped commands attempted" },
   8.707 +	{ 0x055302, "Medium removal prevented" },
   8.708 +	{ 0x055500, "System resource failure" },
   8.709 +	{ 0x056300, "End of user area encountered on this track" },
   8.710 +	{ 0x056400, "Illegal mode for this track or incompatible medium" },
   8.711 +	{ 0x056f00, "Copy protection key exchange failure - Authentication failure" },
   8.712 +	{ 0x056f01, "Copy protection key exchange failure - Key not present" },
   8.713 +	{ 0x056f02, "Copy protection key exchange failure - Key not established" },
   8.714 +	{ 0x056f03, "Read of scrambled sector without authentication" },
   8.715 +	{ 0x056f04, "Media region code is mismatched to logical unit" },
   8.716 +	{ 0x056f05,  "Drive region must be permanent / region reset count error" },
   8.717 +	{ 0x057203, "Session fixation error - incomplete track in session" },
   8.718 +	{ 0x057204, "Empty or partially written reserved track" },
   8.719 +	{ 0x057205, "No more RZONE reservations are allowed" },
   8.720 +	{ 0x05bf00, "Loss of streaming" },
   8.721 +	{ 0x062800, "Not ready to ready transition, medium may have changed" },
   8.722 +	{ 0x062900, "Power on, reset or hardware reset occurred" },
   8.723 +	{ 0x062a00, "Parameters changed" },
   8.724 +	{ 0x062a01, "Mode parameters changed" },
   8.725 +	{ 0x062e00, "Insufficient time for operation" },
   8.726 +	{ 0x063f00, "Logical unit operating conditions have changed" },
   8.727 +	{ 0x063f01, "Microcode has been changed" },
   8.728 +	{ 0x065a00, "Operator request or state change input (unspecified)" },
   8.729 +	{ 0x065a01, "Operator medium removal request" },
   8.730 +	{ 0x0bb900, "Play operation aborted" },
   8.731 +
   8.732 +	/* Here we use 0xff for the key (not a valid key) to signify
   8.733 +	 * that these can have _any_ key value associated with them... */
   8.734 +	{ 0xff0401, "Logical unit is in process of becoming ready" },
   8.735 +	{ 0xff0400, "Logical unit not ready, cause not reportable" },
   8.736 +	{ 0xff0402, "Logical unit not ready, initializing command required" },
   8.737 +	{ 0xff0403, "Logical unit not ready, manual intervention required" },
   8.738 +	{ 0xff0500, "Logical unit does not respond to selection" },
   8.739 +	{ 0xff0800, "Logical unit communication failure" },
   8.740 +	{ 0xff0802, "Logical unit communication parity error" },
   8.741 +	{ 0xff0801, "Logical unit communication time-out" },
   8.742 +	{ 0xff2500, "Logical unit not supported" },
   8.743 +	{ 0xff4c00, "Logical unit failed self-configuration" },
   8.744 +	{ 0xff3e00, "Logical unit has not self-configured yet" },
   8.745 +};
   8.746 +#endif
   8.747 +
   8.748 +
   8.749 +#endif /* _IDE_CD_H */
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xen/include/xeno/cdrom.h	Tue Apr 15 15:26:05 2003 +0000
     9.3 @@ -0,0 +1,1067 @@
     9.4 +/*
     9.5 + * -- <linux/cdrom.h>
     9.6 + * General header file for linux CD-ROM drivers 
     9.7 + * Copyright (C) 1992         David Giller, rafetmad@oxy.edu
     9.8 + *               1994, 1995   Eberhard Moenkeberg, emoenke@gwdg.de
     9.9 + *               1996         David van Leeuwen, david@tm.tno.nl
    9.10 + *               1997, 1998   Erik Andersen, andersee@debian.org
    9.11 + *               1998-2000    Jens Axboe, axboe@suse.de
    9.12 + */
    9.13 + 
    9.14 +#ifndef	_LINUX_CDROM_H
    9.15 +#define	_LINUX_CDROM_H
    9.16 +
    9.17 +#include <asm/byteorder.h>
    9.18 +
    9.19 +/*******************************************************
    9.20 + * As of Linux 2.1.x, all Linux CD-ROM application programs will use this 
    9.21 + * (and only this) include file.  It is my hope to provide Linux with
    9.22 + * a uniform interface between software accessing CD-ROMs and the various 
    9.23 + * device drivers that actually talk to the drives.  There may still be
    9.24 + * 23 different kinds of strange CD-ROM drives, but at least there will 
    9.25 + * now be one, and only one, Linux CD-ROM interface.
    9.26 + *
    9.27 + * Additionally, as of Linux 2.1.x, all Linux application programs 
    9.28 + * should use the O_NONBLOCK option when opening a CD-ROM device 
    9.29 + * for subsequent ioctl commands.  This allows for neat system errors 
    9.30 + * like "No medium found" or "Wrong medium type" upon attempting to 
    9.31 + * mount or play an empty slot, mount an audio disc, or play a data disc.
    9.32 + * Generally, changing an application program to support O_NONBLOCK
    9.33 + * is as easy as the following:
    9.34 + *       -    drive = open("/dev/cdrom", O_RDONLY);
    9.35 + *       +    drive = open("/dev/cdrom", O_RDONLY | O_NONBLOCK);
    9.36 + * It is worth the small change.
    9.37 + *
    9.38 + *  Patches for many common CD programs (provided by David A. van Leeuwen)
    9.39 + *  can be found at:  ftp://ftp.gwdg.de/pub/linux/cdrom/drivers/cm206/
    9.40 + * 
    9.41 + *******************************************************/
    9.42 +
    9.43 +/* When a driver supports a certain function, but the cdrom drive we are 
    9.44 + * using doesn't, we will return the error EDRIVE_CANT_DO_THIS.  We will 
    9.45 + * borrow the "Operation not supported" error from the network folks to 
    9.46 + * accomplish this.  Maybe someday we will get a more targeted error code, 
    9.47 + * but this will do for now... */
    9.48 +#define EDRIVE_CANT_DO_THIS  EOPNOTSUPP
    9.49 +
    9.50 +/*******************************************************
    9.51 + * The CD-ROM IOCTL commands  -- these should be supported by 
    9.52 + * all the various cdrom drivers.  For the CD-ROM ioctls, we 
    9.53 + * will commandeer byte 0x53, or 'S'.
    9.54 + *******************************************************/
    9.55 +#define CDROMPAUSE		0x5301 /* Pause Audio Operation */ 
    9.56 +#define CDROMRESUME		0x5302 /* Resume paused Audio Operation */
    9.57 +#define CDROMPLAYMSF		0x5303 /* Play Audio MSF (struct cdrom_msf) */
    9.58 +#define CDROMPLAYTRKIND		0x5304 /* Play Audio Track/index 
    9.59 +                                           (struct cdrom_ti) */
    9.60 +#define CDROMREADTOCHDR		0x5305 /* Read TOC header 
    9.61 +                                           (struct cdrom_tochdr) */
    9.62 +#define CDROMREADTOCENTRY	0x5306 /* Read TOC entry 
    9.63 +                                           (struct cdrom_tocentry) */
    9.64 +#define CDROMSTOP		0x5307 /* Stop the cdrom drive */
    9.65 +#define CDROMSTART		0x5308 /* Start the cdrom drive */
    9.66 +#define CDROMEJECT		0x5309 /* Ejects the cdrom media */
    9.67 +#define CDROMVOLCTRL		0x530a /* Control output volume 
    9.68 +                                           (struct cdrom_volctrl) */
    9.69 +#define CDROMSUBCHNL		0x530b /* Read subchannel data 
    9.70 +                                           (struct cdrom_subchnl) */
    9.71 +#define CDROMREADMODE2		0x530c /* Read CDROM mode 2 data (2336 Bytes) 
    9.72 +                                           (struct cdrom_read) */
    9.73 +#define CDROMREADMODE1		0x530d /* Read CDROM mode 1 data (2048 Bytes)
    9.74 +                                           (struct cdrom_read) */
    9.75 +#define CDROMREADAUDIO		0x530e /* (struct cdrom_read_audio) */
    9.76 +#define CDROMEJECT_SW		0x530f /* enable(1)/disable(0) auto-ejecting */
    9.77 +#define CDROMMULTISESSION	0x5310 /* Obtain the start-of-last-session 
    9.78 +                                           address of multi session disks 
    9.79 +                                           (struct cdrom_multisession) */
    9.80 +#define CDROM_GET_MCN		0x5311 /* Obtain the "Universal Product Code" 
    9.81 +                                           if available (struct cdrom_mcn) */
    9.82 +#define CDROM_GET_UPC		CDROM_GET_MCN  /* This one is depricated, 
    9.83 +                                          but here anyway for compatability */
    9.84 +#define CDROMRESET		0x5312 /* hard-reset the drive */
    9.85 +#define CDROMVOLREAD		0x5313 /* Get the drive's volume setting 
    9.86 +                                          (struct cdrom_volctrl) */
    9.87 +#define CDROMREADRAW		0x5314	/* read data in raw mode (2352 Bytes)
    9.88 +                                           (struct cdrom_read) */
    9.89 +/* 
    9.90 + * These ioctls are used only used in aztcd.c and optcd.c
    9.91 + */
    9.92 +#define CDROMREADCOOKED		0x5315	/* read data in cooked mode */
    9.93 +#define CDROMSEEK		0x5316  /* seek msf address */
    9.94 +  
    9.95 +/*
    9.96 + * This ioctl is only used by the scsi-cd driver.  
    9.97 +   It is for playing audio in logical block addressing mode.
    9.98 + */
    9.99 +#define CDROMPLAYBLK		0x5317	/* (struct cdrom_blk) */
   9.100 +
   9.101 +/* 
   9.102 + * These ioctls are only used in optcd.c
   9.103 + */
   9.104 +#define CDROMREADALL		0x5318	/* read all 2646 bytes */
   9.105 +
   9.106 +/* 
   9.107 + * These ioctls are (now) only in ide-cd.c for controlling 
   9.108 + * drive spindown time.  They should be implemented in the
   9.109 + * Uniform driver, via generic packet commands, GPCMD_MODE_SELECT_10,
   9.110 + * GPCMD_MODE_SENSE_10 and the GPMODE_POWER_PAGE...
   9.111 + *  -Erik
   9.112 + */
   9.113 +#define CDROMGETSPINDOWN        0x531d
   9.114 +#define CDROMSETSPINDOWN        0x531e
   9.115 +
   9.116 +/* 
   9.117 + * These ioctls are implemented through the uniform CD-ROM driver
   9.118 + * They _will_ be adopted by all CD-ROM drivers, when all the CD-ROM
   9.119 + * drivers are eventually ported to the uniform CD-ROM driver interface.
   9.120 + */
   9.121 +#define CDROMCLOSETRAY		0x5319	/* pendant of CDROMEJECT */
   9.122 +#define CDROM_SET_OPTIONS	0x5320  /* Set behavior options */
   9.123 +#define CDROM_CLEAR_OPTIONS	0x5321  /* Clear behavior options */
   9.124 +#define CDROM_SELECT_SPEED	0x5322  /* Set the CD-ROM speed */
   9.125 +#define CDROM_SELECT_DISC	0x5323  /* Select disc (for juke-boxes) */
   9.126 +#define CDROM_MEDIA_CHANGED	0x5325  /* Check is media changed  */
   9.127 +#define CDROM_DRIVE_STATUS	0x5326  /* Get tray position, etc. */
   9.128 +#define CDROM_DISC_STATUS	0x5327  /* Get disc type, etc. */
   9.129 +#define CDROM_CHANGER_NSLOTS    0x5328  /* Get number of slots */
   9.130 +#define CDROM_LOCKDOOR		0x5329  /* lock or unlock door */
   9.131 +#define CDROM_DEBUG		0x5330	/* Turn debug messages on/off */
   9.132 +#define CDROM_GET_CAPABILITY	0x5331	/* get capabilities */
   9.133 +
   9.134 +/* Note that scsi/scsi_ioctl.h also uses 0x5382 - 0x5386.
   9.135 + * Future CDROM ioctls should be kept below 0x537F
   9.136 + */
   9.137 +
   9.138 +/* This ioctl is only used by sbpcd at the moment */
   9.139 +#define CDROMAUDIOBUFSIZ        0x5382	/* set the audio buffer size */
   9.140 +					/* conflict with SCSI_IOCTL_GET_IDLUN */
   9.141 +
   9.142 +/* DVD-ROM Specific ioctls */
   9.143 +#define DVD_READ_STRUCT		0x5390  /* Read structure */
   9.144 +#define DVD_WRITE_STRUCT	0x5391  /* Write structure */
   9.145 +#define DVD_AUTH		0x5392  /* Authentication */
   9.146 +
   9.147 +#define CDROM_SEND_PACKET	0x5393	/* send a packet to the drive */
   9.148 +#define CDROM_NEXT_WRITABLE	0x5394	/* get next writable block */
   9.149 +#define CDROM_LAST_WRITTEN	0x5395	/* get last block written on disc */
   9.150 +
   9.151 +/*******************************************************
   9.152 + * CDROM IOCTL structures
   9.153 + *******************************************************/
   9.154 +
   9.155 +/* Address in MSF format */
   9.156 +struct cdrom_msf0		
   9.157 +{
   9.158 +	__u8	minute;
   9.159 +	__u8	second;
   9.160 +	__u8	frame;
   9.161 +};
   9.162 +
   9.163 +/* Address in either MSF or logical format */
   9.164 +union cdrom_addr		
   9.165 +{
   9.166 +	struct cdrom_msf0	msf;
   9.167 +	int			lba;
   9.168 +};
   9.169 +
   9.170 +/* This struct is used by the CDROMPLAYMSF ioctl */ 
   9.171 +struct cdrom_msf 
   9.172 +{
   9.173 +	__u8	cdmsf_min0;	/* start minute */
   9.174 +	__u8	cdmsf_sec0;	/* start second */
   9.175 +	__u8	cdmsf_frame0;	/* start frame */
   9.176 +	__u8	cdmsf_min1;	/* end minute */
   9.177 +	__u8	cdmsf_sec1;	/* end second */
   9.178 +	__u8	cdmsf_frame1;	/* end frame */
   9.179 +};
   9.180 +
   9.181 +/* This struct is used by the CDROMPLAYTRKIND ioctl */
   9.182 +struct cdrom_ti 
   9.183 +{
   9.184 +	__u8	cdti_trk0;	/* start track */
   9.185 +	__u8	cdti_ind0;	/* start index */
   9.186 +	__u8	cdti_trk1;	/* end track */
   9.187 +	__u8	cdti_ind1;	/* end index */
   9.188 +};
   9.189 +
   9.190 +/* This struct is used by the CDROMREADTOCHDR ioctl */
   9.191 +struct cdrom_tochdr 	
   9.192 +{
   9.193 +	__u8	cdth_trk0;	/* start track */
   9.194 +	__u8	cdth_trk1;	/* end track */
   9.195 +};
   9.196 +
   9.197 +/* This struct is used by the CDROMVOLCTRL and CDROMVOLREAD ioctls */
   9.198 +struct cdrom_volctrl
   9.199 +{
   9.200 +	__u8	channel0;
   9.201 +	__u8	channel1;
   9.202 +	__u8	channel2;
   9.203 +	__u8	channel3;
   9.204 +};
   9.205 +
   9.206 +/* This struct is used by the CDROMSUBCHNL ioctl */
   9.207 +struct cdrom_subchnl 
   9.208 +{
   9.209 +	__u8	cdsc_format;
   9.210 +	__u8	cdsc_audiostatus;
   9.211 +	__u8	cdsc_adr:	4;
   9.212 +	__u8	cdsc_ctrl:	4;
   9.213 +	__u8	cdsc_trk;
   9.214 +	__u8	cdsc_ind;
   9.215 +	union cdrom_addr cdsc_absaddr;
   9.216 +	union cdrom_addr cdsc_reladdr;
   9.217 +};
   9.218 +
   9.219 +
   9.220 +/* This struct is used by the CDROMREADTOCENTRY ioctl */
   9.221 +struct cdrom_tocentry 
   9.222 +{
   9.223 +	__u8	cdte_track;
   9.224 +	__u8	cdte_adr	:4;
   9.225 +	__u8	cdte_ctrl	:4;
   9.226 +	__u8	cdte_format;
   9.227 +	union cdrom_addr cdte_addr;
   9.228 +	__u8	cdte_datamode;
   9.229 +};
   9.230 +
   9.231 +/* This struct is used by the CDROMREADMODE1, and CDROMREADMODE2 ioctls */
   9.232 +struct cdrom_read      
   9.233 +{
   9.234 +	int	cdread_lba;
   9.235 +	char 	*cdread_bufaddr;
   9.236 +	int	cdread_buflen;
   9.237 +};
   9.238 +
   9.239 +/* This struct is used by the CDROMREADAUDIO ioctl */
   9.240 +struct cdrom_read_audio
   9.241 +{
   9.242 +	union cdrom_addr addr; /* frame address */
   9.243 +	__u8 addr_format;    /* CDROM_LBA or CDROM_MSF */
   9.244 +	int nframes;           /* number of 2352-byte-frames to read at once */
   9.245 +	__u8 *buf;           /* frame buffer (size: nframes*2352 bytes) */
   9.246 +};
   9.247 +
   9.248 +/* This struct is used with the CDROMMULTISESSION ioctl */
   9.249 +struct cdrom_multisession
   9.250 +{
   9.251 +	union cdrom_addr addr; /* frame address: start-of-last-session 
   9.252 +	                           (not the new "frame 16"!).  Only valid
   9.253 +	                           if the "xa_flag" is true. */
   9.254 +	__u8 xa_flag;        /* 1: "is XA disk" */
   9.255 +	__u8 addr_format;    /* CDROM_LBA or CDROM_MSF */
   9.256 +};
   9.257 +
   9.258 +/* This struct is used with the CDROM_GET_MCN ioctl.  
   9.259 + * Very few audio discs actually have Universal Product Code information, 
   9.260 + * which should just be the Medium Catalog Number on the box.  Also note 
   9.261 + * that the way the codeis written on CD is _not_ uniform across all discs!
   9.262 + */  
   9.263 +struct cdrom_mcn 
   9.264 +{
   9.265 +  __u8 medium_catalog_number[14]; /* 13 ASCII digits, null-terminated */
   9.266 +};
   9.267 +
   9.268 +/* This is used by the CDROMPLAYBLK ioctl */
   9.269 +struct cdrom_blk 
   9.270 +{
   9.271 +	unsigned from;
   9.272 +	unsigned short len;
   9.273 +};
   9.274 +
   9.275 +#define CDROM_PACKET_SIZE	12
   9.276 +
   9.277 +#define CGC_DATA_UNKNOWN	0
   9.278 +#define CGC_DATA_WRITE		1
   9.279 +#define CGC_DATA_READ		2
   9.280 +#define CGC_DATA_NONE		3
   9.281 +
   9.282 +/* for CDROM_PACKET_COMMAND ioctl */
   9.283 +struct cdrom_generic_command
   9.284 +{
   9.285 +	unsigned char 		cmd[CDROM_PACKET_SIZE];
   9.286 +	unsigned char 		*buffer;
   9.287 +	unsigned int 		buflen;
   9.288 +	int			stat;
   9.289 +	struct request_sense	*sense;
   9.290 +	unsigned char		data_direction;
   9.291 +	int			quiet;
   9.292 +	int			timeout;
   9.293 +	void			*reserved[1];
   9.294 +};
   9.295 +
   9.296 +
   9.297 +/*
   9.298 + * A CD-ROM physical sector size is 2048, 2052, 2056, 2324, 2332, 2336, 
   9.299 + * 2340, or 2352 bytes long.  
   9.300 +
   9.301 +*         Sector types of the standard CD-ROM data formats:
   9.302 + *
   9.303 + * format   sector type               user data size (bytes)
   9.304 + * -----------------------------------------------------------------------------
   9.305 + *   1     (Red Book)    CD-DA          2352    (CD_FRAMESIZE_RAW)
   9.306 + *   2     (Yellow Book) Mode1 Form1    2048    (CD_FRAMESIZE)
   9.307 + *   3     (Yellow Book) Mode1 Form2    2336    (CD_FRAMESIZE_RAW0)
   9.308 + *   4     (Green Book)  Mode2 Form1    2048    (CD_FRAMESIZE)
   9.309 + *   5     (Green Book)  Mode2 Form2    2328    (2324+4 spare bytes)
   9.310 + *
   9.311 + *
   9.312 + *       The layout of the standard CD-ROM data formats:
   9.313 + * -----------------------------------------------------------------------------
   9.314 + * - audio (red):                  | audio_sample_bytes |
   9.315 + *                                 |        2352        |
   9.316 + *
   9.317 + * - data (yellow, mode1):         | sync - head - data - EDC - zero - ECC |
   9.318 + *                                 |  12  -   4  - 2048 -  4  -   8  - 276 |
   9.319 + *
   9.320 + * - data (yellow, mode2):         | sync - head - data |
   9.321 + *                                 |  12  -   4  - 2336 |
   9.322 + *
   9.323 + * - XA data (green, mode2 form1): | sync - head - sub - data - EDC - ECC |
   9.324 + *                                 |  12  -   4  -  8  - 2048 -  4  - 276 |
   9.325 + *
   9.326 + * - XA data (green, mode2 form2): | sync - head - sub - data - Spare |
   9.327 + *                                 |  12  -   4  -  8  - 2324 -  4    |
   9.328 + *
   9.329 + */
   9.330 +
   9.331 +/* Some generally useful CD-ROM information -- mostly based on the above */
   9.332 +#define CD_MINS              74 /* max. minutes per CD, not really a limit */
   9.333 +#define CD_SECS              60 /* seconds per minute */
   9.334 +#define CD_FRAMES            75 /* frames per second */
   9.335 +#define CD_SYNC_SIZE         12 /* 12 sync bytes per raw data frame */
   9.336 +#define CD_MSF_OFFSET       150 /* MSF numbering offset of first frame */
   9.337 +#define CD_CHUNK_SIZE        24 /* lowest-level "data bytes piece" */
   9.338 +#define CD_NUM_OF_CHUNKS     98 /* chunks per frame */
   9.339 +#define CD_FRAMESIZE_SUB     96 /* subchannel data "frame" size */
   9.340 +#define CD_HEAD_SIZE          4 /* header (address) bytes per raw data frame */
   9.341 +#define CD_SUBHEAD_SIZE       8 /* subheader bytes per raw XA data frame */
   9.342 +#define CD_EDC_SIZE           4 /* bytes EDC per most raw data frame types */
   9.343 +#define CD_ZERO_SIZE          8 /* bytes zero per yellow book mode 1 frame */
   9.344 +#define CD_ECC_SIZE         276 /* bytes ECC per most raw data frame types */
   9.345 +#define CD_FRAMESIZE       2048 /* bytes per frame, "cooked" mode */
   9.346 +#define CD_FRAMESIZE_RAW   2352 /* bytes per frame, "raw" mode */
   9.347 +#define CD_FRAMESIZE_RAWER 2646 /* The maximum possible returned bytes */ 
   9.348 +/* most drives don't deliver everything: */
   9.349 +#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/
   9.350 +#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/
   9.351 +
   9.352 +#define CD_XA_HEAD        (CD_HEAD_SIZE+CD_SUBHEAD_SIZE) /* "before data" part of raw XA frame */
   9.353 +#define CD_XA_TAIL        (CD_EDC_SIZE+CD_ECC_SIZE) /* "after data" part of raw XA frame */
   9.354 +#define CD_XA_SYNC_HEAD   (CD_SYNC_SIZE+CD_XA_HEAD) /* sync bytes + header of XA frame */
   9.355 +
   9.356 +/* CD-ROM address types (cdrom_tocentry.cdte_format) */
   9.357 +#define	CDROM_LBA 0x01 /* "logical block": first frame is #0 */
   9.358 +#define	CDROM_MSF 0x02 /* "minute-second-frame": binary, not bcd here! */
   9.359 +
   9.360 +/* bit to tell whether track is data or audio (cdrom_tocentry.cdte_ctrl) */
   9.361 +#define	CDROM_DATA_TRACK	0x04
   9.362 +
   9.363 +/* The leadout track is always 0xAA, regardless of # of tracks on disc */
   9.364 +#define	CDROM_LEADOUT		0xAA
   9.365 +
   9.366 +/* audio states (from SCSI-2, but seen with other drives, too) */
   9.367 +#define	CDROM_AUDIO_INVALID	0x00	/* audio status not supported */
   9.368 +#define	CDROM_AUDIO_PLAY	0x11	/* audio play operation in progress */
   9.369 +#define	CDROM_AUDIO_PAUSED	0x12	/* audio play operation paused */
   9.370 +#define	CDROM_AUDIO_COMPLETED	0x13	/* audio play successfully completed */
   9.371 +#define	CDROM_AUDIO_ERROR	0x14	/* audio play stopped due to error */
   9.372 +#define	CDROM_AUDIO_NO_STATUS	0x15	/* no current audio status to return */
   9.373 +
   9.374 +/* capability flags used with the uniform CD-ROM driver */ 
   9.375 +#define CDC_CLOSE_TRAY		0x1     /* caddy systems _can't_ close */
   9.376 +#define CDC_OPEN_TRAY		0x2     /* but _can_ eject.  */
   9.377 +#define CDC_LOCK		0x4     /* disable manual eject */
   9.378 +#define CDC_SELECT_SPEED 	0x8     /* programmable speed */
   9.379 +#define CDC_SELECT_DISC		0x10    /* select disc from juke-box */
   9.380 +#define CDC_MULTI_SESSION 	0x20    /* read sessions>1 */
   9.381 +#define CDC_MCN			0x40    /* Medium Catalog Number */
   9.382 +#define CDC_MEDIA_CHANGED 	0x80    /* media changed */
   9.383 +#define CDC_PLAY_AUDIO		0x100   /* audio functions */
   9.384 +#define CDC_RESET               0x200   /* hard reset device */
   9.385 +#define CDC_IOCTLS              0x400   /* driver has non-standard ioctls */
   9.386 +#define CDC_DRIVE_STATUS        0x800   /* driver implements drive status */
   9.387 +#define CDC_GENERIC_PACKET	0x1000	/* driver implements generic packets */
   9.388 +#define CDC_CD_R		0x2000	/* drive is a CD-R */
   9.389 +#define CDC_CD_RW		0x4000	/* drive is a CD-RW */
   9.390 +#define CDC_DVD			0x8000	/* drive is a DVD */
   9.391 +#define CDC_DVD_R		0x10000	/* drive can write DVD-R */
   9.392 +#define CDC_DVD_RAM		0x20000	/* drive can write DVD-RAM */
   9.393 +
   9.394 +/* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */
   9.395 +#define CDS_NO_INFO		0	/* if not implemented */
   9.396 +#define CDS_NO_DISC		1
   9.397 +#define CDS_TRAY_OPEN		2
   9.398 +#define CDS_DRIVE_NOT_READY	3
   9.399 +#define CDS_DISC_OK		4
   9.400 +
   9.401 +/* return values for the CDROM_DISC_STATUS ioctl */
   9.402 +/* can also return CDS_NO_[INFO|DISC], from above */
   9.403 +#define CDS_AUDIO		100
   9.404 +#define CDS_DATA_1		101
   9.405 +#define CDS_DATA_2		102
   9.406 +#define CDS_XA_2_1		103
   9.407 +#define CDS_XA_2_2		104
   9.408 +#define CDS_MIXED		105
   9.409 +
   9.410 +/* User-configurable behavior options for the uniform CD-ROM driver */
   9.411 +#define CDO_AUTO_CLOSE		0x1     /* close tray on first open() */
   9.412 +#define CDO_AUTO_EJECT		0x2     /* open tray on last release() */
   9.413 +#define CDO_USE_FFLAGS		0x4     /* use O_NONBLOCK information on open */
   9.414 +#define CDO_LOCK		0x8     /* lock tray on open files */
   9.415 +#define CDO_CHECK_TYPE		0x10    /* check type on open for data */
   9.416 +
   9.417 +/* Special codes used when specifying changer slots. */
   9.418 +#define CDSL_NONE       	((int) (~0U>>1)-1)
   9.419 +#define CDSL_CURRENT    	((int) (~0U>>1))
   9.420 +
   9.421 +/* For partition based multisession access. IDE can handle 64 partitions
   9.422 + * per drive - SCSI CD-ROM's use minors to differentiate between the
   9.423 + * various drives, so we can't do multisessions the same way there.
   9.424 + * Use the -o session=x option to mount on them.
   9.425 + */
   9.426 +#define CD_PART_MAX		64
   9.427 +#define CD_PART_MASK		(CD_PART_MAX - 1)
   9.428 +
   9.429 +/*********************************************************************
   9.430 + * Generic Packet commands, MMC commands, and such
   9.431 + *********************************************************************/
   9.432 +
   9.433 + /* The generic packet command opcodes for CD/DVD Logical Units,
   9.434 + * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
   9.435 +#define GPCMD_BLANK			    0xa1
   9.436 +#define GPCMD_CLOSE_TRACK		    0x5b
   9.437 +#define GPCMD_FLUSH_CACHE		    0x35
   9.438 +#define GPCMD_FORMAT_UNIT		    0x04
   9.439 +#define GPCMD_GET_CONFIGURATION		    0x46
   9.440 +#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
   9.441 +#define GPCMD_GET_PERFORMANCE		    0xac
   9.442 +#define GPCMD_INQUIRY			    0x12
   9.443 +#define GPCMD_LOAD_UNLOAD		    0xa6
   9.444 +#define GPCMD_MECHANISM_STATUS		    0xbd
   9.445 +#define GPCMD_MODE_SELECT_10		    0x55
   9.446 +#define GPCMD_MODE_SENSE_10		    0x5a
   9.447 +#define GPCMD_PAUSE_RESUME		    0x4b
   9.448 +#define GPCMD_PLAY_AUDIO_10		    0x45
   9.449 +#define GPCMD_PLAY_AUDIO_MSF		    0x47
   9.450 +#define GPCMD_PLAY_AUDIO_TI		    0x48
   9.451 +#define GPCMD_PLAY_CD			    0xbc
   9.452 +#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL  0x1e
   9.453 +#define GPCMD_READ_10			    0x28
   9.454 +#define GPCMD_READ_12			    0xa8
   9.455 +#define GPCMD_READ_CDVD_CAPACITY	    0x25
   9.456 +#define GPCMD_READ_CD			    0xbe
   9.457 +#define GPCMD_READ_CD_MSF		    0xb9
   9.458 +#define GPCMD_READ_DISC_INFO		    0x51
   9.459 +#define GPCMD_READ_DVD_STRUCTURE	    0xad
   9.460 +#define GPCMD_READ_FORMAT_CAPACITIES	    0x23
   9.461 +#define GPCMD_READ_HEADER		    0x44
   9.462 +#define GPCMD_READ_TRACK_RZONE_INFO	    0x52
   9.463 +#define GPCMD_READ_SUBCHANNEL		    0x42
   9.464 +#define GPCMD_READ_TOC_PMA_ATIP		    0x43
   9.465 +#define GPCMD_REPAIR_RZONE_TRACK	    0x58
   9.466 +#define GPCMD_REPORT_KEY		    0xa4
   9.467 +#define GPCMD_REQUEST_SENSE		    0x03
   9.468 +#define GPCMD_RESERVE_RZONE_TRACK	    0x53
   9.469 +#define GPCMD_SCAN			    0xba
   9.470 +#define GPCMD_SEEK			    0x2b
   9.471 +#define GPCMD_SEND_DVD_STRUCTURE	    0xad
   9.472 +#define GPCMD_SEND_EVENT		    0xa2
   9.473 +#define GPCMD_SEND_KEY			    0xa3
   9.474 +#define GPCMD_SEND_OPC			    0x54
   9.475 +#define GPCMD_SET_READ_AHEAD		    0xa7
   9.476 +#define GPCMD_SET_STREAMING		    0xb6
   9.477 +#define GPCMD_START_STOP_UNIT		    0x1b
   9.478 +#define GPCMD_STOP_PLAY_SCAN		    0x4e
   9.479 +#define GPCMD_TEST_UNIT_READY		    0x00
   9.480 +#define GPCMD_VERIFY_10			    0x2f
   9.481 +#define GPCMD_WRITE_10			    0x2a
   9.482 +#define GPCMD_WRITE_AND_VERIFY_10	    0x2e
   9.483 +/* This is listed as optional in ATAPI 2.6, but is (curiously) 
   9.484 + * missing from Mt. Fuji, Table 57.  It _is_ mentioned in Mt. Fuji
   9.485 + * Table 377 as an MMC command for SCSi devices though...  Most ATAPI
   9.486 + * drives support it. */
   9.487 +#define GPCMD_SET_SPEED			    0xbb
   9.488 +/* This seems to be a SCSI specific CD-ROM opcode 
   9.489 + * to play data at track/index */
   9.490 +#define GPCMD_PLAYAUDIO_TI		    0x48
   9.491 +/*
   9.492 + * From MS Media Status Notification Support Specification. For
   9.493 + * older drives only.
   9.494 + */
   9.495 +#define GPCMD_GET_MEDIA_STATUS		    0xda
   9.496 +
   9.497 +/* Mode page codes for mode sense/set */
   9.498 +#define GPMODE_R_W_ERROR_PAGE		0x01
   9.499 +#define GPMODE_WRITE_PARMS_PAGE		0x05
   9.500 +#define GPMODE_AUDIO_CTL_PAGE		0x0e
   9.501 +#define GPMODE_POWER_PAGE		0x1a
   9.502 +#define GPMODE_FAULT_FAIL_PAGE		0x1c
   9.503 +#define GPMODE_TO_PROTECT_PAGE		0x1d
   9.504 +#define GPMODE_CAPABILITIES_PAGE	0x2a
   9.505 +#define GPMODE_ALL_PAGES		0x3f
   9.506 +/* Not in Mt. Fuji, but in ATAPI 2.6 -- depricated now in favor
   9.507 + * of MODE_SENSE_POWER_PAGE */
   9.508 +#define GPMODE_CDROM_PAGE		0x0d
   9.509 +
   9.510 +
   9.511 +
   9.512 +/* DVD struct types */
   9.513 +#define DVD_STRUCT_PHYSICAL	0x00
   9.514 +#define DVD_STRUCT_COPYRIGHT	0x01
   9.515 +#define DVD_STRUCT_DISCKEY	0x02
   9.516 +#define DVD_STRUCT_BCA		0x03
   9.517 +#define DVD_STRUCT_MANUFACT	0x04
   9.518 +
   9.519 +struct dvd_layer {
   9.520 +	__u8 book_version	: 4;
   9.521 +	__u8 book_type		: 4;
   9.522 +	__u8 min_rate		: 4;
   9.523 +	__u8 disc_size		: 4;
   9.524 +	__u8 layer_type		: 4;
   9.525 +	__u8 track_path		: 1;
   9.526 +	__u8 nlayers		: 2;
   9.527 +	__u8 track_density	: 4;
   9.528 +	__u8 linear_density	: 4;
   9.529 +	__u8 bca		: 1;
   9.530 +	__u32 start_sector;
   9.531 +	__u32 end_sector;
   9.532 +	__u32 end_sector_l0;
   9.533 +};
   9.534 +
   9.535 +#define DVD_LAYERS	4
   9.536 +
   9.537 +struct dvd_physical {
   9.538 +	__u8 type;
   9.539 +	__u8 layer_num;
   9.540 +	struct dvd_layer layer[DVD_LAYERS];
   9.541 +};
   9.542 +
   9.543 +struct dvd_copyright {
   9.544 +	__u8 type;
   9.545 +
   9.546 +	__u8 layer_num;
   9.547 +	__u8 cpst;
   9.548 +	__u8 rmi;
   9.549 +};
   9.550 +
   9.551 +struct dvd_disckey {
   9.552 +	__u8 type;
   9.553 +
   9.554 +	unsigned agid		: 2;
   9.555 +	__u8 value[2048];
   9.556 +};
   9.557 +
   9.558 +struct dvd_bca {
   9.559 +	__u8 type;
   9.560 +
   9.561 +	int len;
   9.562 +	__u8 value[188];
   9.563 +};
   9.564 +
   9.565 +struct dvd_manufact {
   9.566 +	__u8 type;
   9.567 +
   9.568 +	__u8 layer_num;
   9.569 +	int len;
   9.570 +	__u8 value[2048];
   9.571 +};
   9.572 +
   9.573 +typedef union {
   9.574 +	__u8 type;
   9.575 +
   9.576 +	struct dvd_physical	physical;
   9.577 +	struct dvd_copyright	copyright;
   9.578 +	struct dvd_disckey	disckey;
   9.579 +	struct dvd_bca		bca;
   9.580 +	struct dvd_manufact	manufact;
   9.581 +} dvd_struct;
   9.582 +
   9.583 +/*
   9.584 + * DVD authentication ioctl
   9.585 + */
   9.586 +
   9.587 +/* Authentication states */
   9.588 +#define DVD_LU_SEND_AGID	0
   9.589 +#define DVD_HOST_SEND_CHALLENGE	1
   9.590 +#define DVD_LU_SEND_KEY1	2
   9.591 +#define DVD_LU_SEND_CHALLENGE	3
   9.592 +#define DVD_HOST_SEND_KEY2	4
   9.593 +
   9.594 +/* Termination states */
   9.595 +#define DVD_AUTH_ESTABLISHED	5
   9.596 +#define DVD_AUTH_FAILURE	6
   9.597 +
   9.598 +/* Other functions */
   9.599 +#define DVD_LU_SEND_TITLE_KEY	7
   9.600 +#define DVD_LU_SEND_ASF		8
   9.601 +#define DVD_INVALIDATE_AGID	9
   9.602 +#define DVD_LU_SEND_RPC_STATE	10
   9.603 +#define DVD_HOST_SEND_RPC_STATE	11
   9.604 +
   9.605 +/* State data */
   9.606 +typedef __u8 dvd_key[5];		/* 40-bit value, MSB is first elem. */
   9.607 +typedef __u8 dvd_challenge[10];	/* 80-bit value, MSB is first elem. */
   9.608 +
   9.609 +struct dvd_lu_send_agid {
   9.610 +	__u8 type;
   9.611 +	unsigned agid		: 2;
   9.612 +};
   9.613 +
   9.614 +struct dvd_host_send_challenge {
   9.615 +	__u8 type;
   9.616 +	unsigned agid		: 2;
   9.617 +
   9.618 +	dvd_challenge chal;
   9.619 +};
   9.620 +
   9.621 +struct dvd_send_key {
   9.622 +	__u8 type;
   9.623 +	unsigned agid		: 2;
   9.624 +
   9.625 +	dvd_key key;
   9.626 +};
   9.627 +
   9.628 +struct dvd_lu_send_challenge {
   9.629 +	__u8 type;
   9.630 +	unsigned agid		: 2;
   9.631 +
   9.632 +	dvd_challenge chal;
   9.633 +};
   9.634 +
   9.635 +#define DVD_CPM_NO_COPYRIGHT	0
   9.636 +#define DVD_CPM_COPYRIGHTED	1
   9.637 +
   9.638 +#define DVD_CP_SEC_NONE		0
   9.639 +#define DVD_CP_SEC_EXIST	1
   9.640 +
   9.641 +#define DVD_CGMS_UNRESTRICTED	0
   9.642 +#define DVD_CGMS_SINGLE		2
   9.643 +#define DVD_CGMS_RESTRICTED	3
   9.644 +
   9.645 +struct dvd_lu_send_title_key {
   9.646 +	__u8 type;
   9.647 +	unsigned agid		: 2;
   9.648 +
   9.649 +	dvd_key title_key;
   9.650 +	int lba;
   9.651 +	unsigned cpm		: 1;
   9.652 +	unsigned cp_sec		: 1;
   9.653 +	unsigned cgms		: 2;
   9.654 +};
   9.655 +
   9.656 +struct dvd_lu_send_asf {
   9.657 +	__u8 type;
   9.658 +	unsigned agid		: 2;
   9.659 +
   9.660 +	unsigned asf		: 1;
   9.661 +};
   9.662 +
   9.663 +struct dvd_host_send_rpcstate {
   9.664 +	__u8 type;
   9.665 +	__u8 pdrc;
   9.666 +};
   9.667 +
   9.668 +struct dvd_lu_send_rpcstate {
   9.669 +	__u8 type		: 2;
   9.670 +	__u8 vra		: 3;
   9.671 +	__u8 ucca		: 3;
   9.672 +	__u8 region_mask;
   9.673 +	__u8 rpc_scheme;
   9.674 +};
   9.675 +
   9.676 +typedef union {
   9.677 +	__u8 type;
   9.678 +
   9.679 +	struct dvd_lu_send_agid		lsa;
   9.680 +	struct dvd_host_send_challenge	hsc;
   9.681 +	struct dvd_send_key		lsk;
   9.682 +	struct dvd_lu_send_challenge	lsc;
   9.683 +	struct dvd_send_key		hsk;
   9.684 +	struct dvd_lu_send_title_key	lstk;
   9.685 +	struct dvd_lu_send_asf		lsasf;
   9.686 +	struct dvd_host_send_rpcstate	hrpcs;
   9.687 +	struct dvd_lu_send_rpcstate	lrpcs;
   9.688 +} dvd_authinfo;
   9.689 +
   9.690 +struct request_sense {
   9.691 +#if defined(__BIG_ENDIAN_BITFIELD)
   9.692 +	__u8 valid		: 1;
   9.693 +	__u8 error_code		: 7;
   9.694 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   9.695 +	__u8 error_code		: 7;
   9.696 +	__u8 valid		: 1;
   9.697 +#endif
   9.698 +	__u8 segment_number;
   9.699 +#if defined(__BIG_ENDIAN_BITFIELD)
   9.700 +	__u8 reserved1		: 2;
   9.701 +	__u8 ili		: 1;
   9.702 +	__u8 reserved2		: 1;
   9.703 +	__u8 sense_key		: 4;
   9.704 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   9.705 +	__u8 sense_key		: 4;
   9.706 +	__u8 reserved2		: 1;
   9.707 +	__u8 ili		: 1;
   9.708 +	__u8 reserved1		: 2;
   9.709 +#endif
   9.710 +	__u8 information[4];
   9.711 +	__u8 add_sense_len;
   9.712 +	__u8 command_info[4];
   9.713 +	__u8 asc;
   9.714 +	__u8 ascq;
   9.715 +	__u8 fruc;
   9.716 +	__u8 sks[3];
   9.717 +	__u8 asb[46];
   9.718 +};
   9.719 +
   9.720 +#ifdef __KERNEL__
   9.721 +#if 0
   9.722 +#include <linux/devfs_fs_kernel.h>
   9.723 +#else
   9.724 +#include <xeno/kdev_t.h>
   9.725 +#endif
   9.726 +
   9.727 +struct cdrom_write_settings {
   9.728 +	unsigned char fpacket;		/* fixed/variable packets */
   9.729 +	unsigned long packet_size;	/* write out this number of packets */
   9.730 +	unsigned long nwa;		/* next writeable address */
   9.731 +	unsigned char writeable;	/* cdrom is writeable */
   9.732 +};
   9.733 +
   9.734 +/* Uniform cdrom data structures for cdrom.c */
   9.735 +struct cdrom_device_info {
   9.736 +	struct cdrom_device_ops  *ops;  /* link to device_ops */
   9.737 +	struct cdrom_device_info *next; /* next device_info for this major */
   9.738 +	void *handle;		        /* driver-dependent data */
   9.739 +#if 0
   9.740 +	devfs_handle_t de;		/* real driver should create this  */
   9.741 +#endif
   9.742 +	int number;			/* generic driver updates this  */
   9.743 +/* specifications */
   9.744 +        kdev_t dev;	                /* device number */
   9.745 +	int mask;                       /* mask of capability: disables them */
   9.746 +	int speed;			/* maximum speed for reading data */
   9.747 +	int capacity;			/* number of discs in jukebox */
   9.748 +/* device-related storage */
   9.749 +	int options		: 30;	/* options flags */
   9.750 +	unsigned mc_flags	: 2;	/* media change buffer flags */
   9.751 +    	int use_count;                  /* number of times device opened */
   9.752 +    	char name[20];                  /* name of the device type */
   9.753 +/* per-device flags */
   9.754 +        __u8 sanyo_slot		: 2;	/* Sanyo 3 CD changer support */
   9.755 +        __u8 reserved		: 6;	/* not used yet */
   9.756 +	struct cdrom_write_settings write;
   9.757 +};
   9.758 +
   9.759 +struct cdrom_device_ops {
   9.760 +/* routines */
   9.761 +	int (*open) (struct cdrom_device_info *, int);
   9.762 +	void (*release) (struct cdrom_device_info *);
   9.763 +	int (*drive_status) (struct cdrom_device_info *, int);
   9.764 +	int (*media_changed) (struct cdrom_device_info *, int);
   9.765 +	int (*tray_move) (struct cdrom_device_info *, int);
   9.766 +	int (*lock_door) (struct cdrom_device_info *, int);
   9.767 +	int (*select_speed) (struct cdrom_device_info *, int);
   9.768 +	int (*select_disc) (struct cdrom_device_info *, int);
   9.769 +	int (*get_last_session) (struct cdrom_device_info *,
   9.770 +				 struct cdrom_multisession *);
   9.771 +	int (*get_mcn) (struct cdrom_device_info *,
   9.772 +			struct cdrom_mcn *);
   9.773 +	/* hard reset device */
   9.774 +	int (*reset) (struct cdrom_device_info *);
   9.775 +	/* play stuff */
   9.776 +	int (*audio_ioctl) (struct cdrom_device_info *,unsigned int, void *);
   9.777 +	/* dev-specific */
   9.778 + 	int (*dev_ioctl) (struct cdrom_device_info *,
   9.779 +			  unsigned int, unsigned long);
   9.780 +/* driver specifications */
   9.781 +	const int capability;   /* capability flags */
   9.782 +	int n_minors;           /* number of active minor devices */
   9.783 +	/* handle uniform packets for scsi type devices (scsi,atapi) */
   9.784 +	int (*generic_packet) (struct cdrom_device_info *,
   9.785 +			       struct cdrom_generic_command *);
   9.786 +};
   9.787 +
   9.788 +/* the general block_device operations structure: */
   9.789 +#include <xeno/blkdev.h> /* XXX SMH: pull in wafer thin file and inode defns */
   9.790 +extern int cdrom_open(struct inode *, struct file *);
   9.791 +extern int cdrom_release(struct inode *, struct file *);
   9.792 +extern int cdrom_ioctl(struct inode *, struct file *, unsigned, unsigned long);
   9.793 +extern int cdrom_media_changed(kdev_t);
   9.794 +
   9.795 +extern int register_cdrom(struct cdrom_device_info *cdi);
   9.796 +extern int unregister_cdrom(struct cdrom_device_info *cdi);
   9.797 +
   9.798 +#if 0
   9.799 +static inline void devfs_plain_cdrom(struct cdrom_device_info *cdi,
   9.800 +				struct block_device_operations *ops)
   9.801 +{
   9.802 +	char vname[23];
   9.803 +
   9.804 +	sprintf (vname, "cdroms/cdrom%d", cdi->number);
   9.805 +	cdi->de = devfs_register (NULL, vname, DEVFS_FL_DEFAULT,
   9.806 +				    MAJOR (cdi->dev), MINOR (cdi->dev),
   9.807 +				    S_IFBLK | S_IRUGO | S_IWUGO,
   9.808 +				    ops, NULL);
   9.809 +}
   9.810 +#endif
   9.811 +
   9.812 +typedef struct {
   9.813 +    int data;
   9.814 +    int audio;
   9.815 +    int cdi;
   9.816 +    int xa;
   9.817 +    long error;
   9.818 +} tracktype;
   9.819 +
   9.820 +extern void cdrom_count_tracks(struct cdrom_device_info *cdi,tracktype* tracks);
   9.821 +extern int cdrom_get_next_writable(kdev_t dev, long *next_writable);
   9.822 +extern int cdrom_get_last_written(kdev_t dev, long *last_written);
   9.823 +extern int cdrom_number_of_slots(struct cdrom_device_info *cdi);
   9.824 +extern int cdrom_select_disc(struct cdrom_device_info *cdi, int slot);
   9.825 +extern int cdrom_mode_select(struct cdrom_device_info *cdi,
   9.826 +			     struct cdrom_generic_command *cgc);
   9.827 +extern int cdrom_mode_sense(struct cdrom_device_info *cdi,
   9.828 +			    struct cdrom_generic_command *cgc,
   9.829 +			    int page_code, int page_control);
   9.830 +extern void init_cdrom_command(struct cdrom_generic_command *cgc,
   9.831 +			       void *buffer, int len, int type);
   9.832 +extern struct cdrom_device_info *cdrom_find_device(kdev_t dev);
   9.833 +
   9.834 +typedef struct {
   9.835 +	__u16 disc_information_length;
   9.836 +#if defined(__BIG_ENDIAN_BITFIELD)
   9.837 +	__u8 reserved1			: 3;
   9.838 +        __u8 erasable			: 1;
   9.839 +        __u8 border_status		: 2;
   9.840 +        __u8 disc_status		: 2;
   9.841 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   9.842 +        __u8 disc_status		: 2;
   9.843 +        __u8 border_status		: 2;
   9.844 +        __u8 erasable			: 1;
   9.845 +	__u8 reserved1			: 3;
   9.846 +#else
   9.847 +#error "Please fix <asm/byteorder.h>"
   9.848 +#endif
   9.849 +	__u8 n_first_track;
   9.850 +	__u8 n_sessions_lsb;
   9.851 +	__u8 first_track_lsb;
   9.852 +	__u8 last_track_lsb;
   9.853 +#if defined(__BIG_ENDIAN_BITFIELD)
   9.854 +	__u8 did_v			: 1;
   9.855 +        __u8 dbc_v			: 1;
   9.856 +        __u8 uru			: 1;
   9.857 +        __u8 reserved2			: 5;
   9.858 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   9.859 +        __u8 reserved2			: 5;
   9.860 +        __u8 uru			: 1;
   9.861 +        __u8 dbc_v			: 1;
   9.862 +	__u8 did_v			: 1;
   9.863 +#endif
   9.864 +	__u8 disc_type;
   9.865 +	__u8 n_sessions_msb;
   9.866 +	__u8 first_track_msb;
   9.867 +	__u8 last_track_msb;
   9.868 +	__u32 disc_id;
   9.869 +	__u32 lead_in;
   9.870 +	__u32 lead_out;
   9.871 +	__u8 disc_bar_code[8];
   9.872 +	__u8 reserved3;
   9.873 +	__u8 n_opc;
   9.874 +} disc_information;
   9.875 +
   9.876 +typedef struct {
   9.877 +	__u16 track_information_length;
   9.878 +	__u8 track_lsb;
   9.879 +	__u8 session_lsb;
   9.880 +	__u8 reserved1;
   9.881 +#if defined(__BIG_ENDIAN_BITFIELD)
   9.882 +	__u8 reserved2			: 2;
   9.883 +        __u8 damage			: 1;
   9.884 +        __u8 copy			: 1;
   9.885 +        __u8 track_mode			: 4;
   9.886 +	__u8 rt				: 1;
   9.887 +	__u8 blank			: 1;
   9.888 +	__u8 packet			: 1;
   9.889 +	__u8 fp				: 1;
   9.890 +	__u8 data_mode			: 4;
   9.891 +	__u8 reserved3			: 6;
   9.892 +	__u8 lra_v			: 1;
   9.893 +	__u8 nwa_v			: 1;
   9.894 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   9.895 +        __u8 track_mode			: 4;
   9.896 +        __u8 copy			: 1;
   9.897 +        __u8 damage			: 1;
   9.898 +	__u8 reserved2			: 2;
   9.899 +	__u8 data_mode			: 4;
   9.900 +	__u8 fp				: 1;
   9.901 +	__u8 packet			: 1;
   9.902 +	__u8 blank			: 1;
   9.903 +	__u8 rt				: 1;
   9.904 +	__u8 nwa_v			: 1;
   9.905 +	__u8 lra_v			: 1;
   9.906 +	__u8 reserved3			: 6;
   9.907 +#endif
   9.908 +	__u32 track_start;
   9.909 +	__u32 next_writable;
   9.910 +	__u32 free_blocks;
   9.911 +	__u32 fixed_packet_size;
   9.912 +	__u32 track_size;
   9.913 +	__u32 last_rec_address;
   9.914 +} track_information;
   9.915 +
   9.916 +extern int cdrom_get_disc_info(kdev_t dev, disc_information *di);
   9.917 +extern int cdrom_get_track_info(kdev_t dev, __u16 track, __u8 type,
   9.918 +				track_information *ti);
   9.919 +
   9.920 +/* The SCSI spec says there could be 256 slots. */
   9.921 +#define CDROM_MAX_SLOTS	256
   9.922 +
   9.923 +struct cdrom_mechstat_header {
   9.924 +#if defined(__BIG_ENDIAN_BITFIELD)
   9.925 +	__u8 fault         : 1;
   9.926 +	__u8 changer_state : 2;
   9.927 +	__u8 curslot       : 5;
   9.928 +	__u8 mech_state    : 3;
   9.929 +	__u8 door_open     : 1;
   9.930 +	__u8 reserved1     : 4;
   9.931 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   9.932 +	__u8 curslot       : 5;
   9.933 +	__u8 changer_state : 2;
   9.934 +	__u8 fault         : 1;
   9.935 +	__u8 reserved1     : 4;
   9.936 +	__u8 door_open     : 1;
   9.937 +	__u8 mech_state    : 3;
   9.938 +#endif
   9.939 +	__u8     curlba[3];
   9.940 +	__u8     nslots;
   9.941 +	__u16 slot_tablelen;
   9.942 +};
   9.943 +
   9.944 +struct cdrom_slot {
   9.945 +#if defined(__BIG_ENDIAN_BITFIELD)
   9.946 +	__u8 disc_present : 1;
   9.947 +	__u8 reserved1    : 6;
   9.948 +	__u8 change       : 1;
   9.949 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   9.950 +	__u8 change       : 1;
   9.951 +	__u8 reserved1    : 6;
   9.952 +	__u8 disc_present : 1;
   9.953 +#endif
   9.954 +	__u8 reserved2[3];
   9.955 +};
   9.956 +
   9.957 +struct cdrom_changer_info {
   9.958 +	struct cdrom_mechstat_header hdr;
   9.959 +	struct cdrom_slot slots[CDROM_MAX_SLOTS];
   9.960 +};
   9.961 +
   9.962 +typedef enum {
   9.963 +	mechtype_caddy = 0,
   9.964 +	mechtype_tray  = 1,
   9.965 +	mechtype_popup = 2,
   9.966 +	mechtype_individual_changer = 4,
   9.967 +	mechtype_cartridge_changer  = 5
   9.968 +} mechtype_t;
   9.969 +
   9.970 +struct mode_page_header {
   9.971 +	__u16 mode_data_length;
   9.972 +	__u8 medium_type;
   9.973 +	__u8 reserved1;
   9.974 +	__u8 reserved2;
   9.975 +	__u8 reserved3;
   9.976 +	__u16 desc_length;
   9.977 +};
   9.978 +
   9.979 +typedef struct {
   9.980 +#if defined(__BIG_ENDIAN_BITFIELD)
   9.981 +	__u8 ps			: 1;
   9.982 +	__u8 reserved1		: 1;
   9.983 +	__u8 page_code		: 6;
   9.984 +        __u8 page_length;
   9.985 +	__u8 reserved2		: 1;
   9.986 +	__u8 bufe		: 1;
   9.987 +	__u8 ls_v		: 1;
   9.988 +	__u8 test_write		: 1;
   9.989 +        __u8 write_type		: 4;
   9.990 +	__u8 multi_session	: 2; /* or border, DVD */
   9.991 +	__u8 fp			: 1;
   9.992 +	__u8 copy		: 1;
   9.993 +	__u8 track_mode		: 4;
   9.994 +	__u8 reserved3		: 4;
   9.995 +	__u8 data_block_type	: 4;
   9.996 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
   9.997 +	__u8 page_code		: 6;
   9.998 +	__u8 reserved1		: 1;
   9.999 +	__u8 ps			: 1;
  9.1000 +        __u8 page_length;
  9.1001 +        __u8 write_type		: 4;
  9.1002 +	__u8 test_write		: 1;
  9.1003 +	__u8 ls_v		: 1;
  9.1004 +	__u8 bufe		: 1;
  9.1005 +	__u8 reserved2		: 1;
  9.1006 +	__u8 track_mode		: 4;
  9.1007 +	__u8 copy		: 1;
  9.1008 +	__u8 fp			: 1;
  9.1009 +	__u8 multi_session	: 2; /* or border, DVD */
  9.1010 +	__u8 data_block_type	: 4;
  9.1011 +	__u8 reserved3		: 4;
  9.1012 +#endif
  9.1013 +	__u8 link_size;
  9.1014 +	__u8 reserved4;
  9.1015 +#if defined(__BIG_ENDIAN_BITFIELD)
  9.1016 +	__u8 reserved5		: 2;
  9.1017 +	__u8 app_code		: 6;
  9.1018 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
  9.1019 +	__u8 app_code		: 6;
  9.1020 +	__u8 reserved5		: 2;
  9.1021 +#endif
  9.1022 +	__u8 session_format;
  9.1023 +	__u8 reserved6;
  9.1024 +	__u32 packet_size;
  9.1025 +	__u16 audio_pause;
  9.1026 +	__u8 mcn[16];
  9.1027 +	__u8 isrc[16];
  9.1028 +	__u8 subhdr0;
  9.1029 +	__u8 subhdr1;
  9.1030 +	__u8 subhdr2;
  9.1031 +	__u8 subhdr3;
  9.1032 +} __attribute__((packed)) write_param_page;
  9.1033 +
  9.1034 +struct modesel_head
  9.1035 +{
  9.1036 +	__u8	reserved1;
  9.1037 +	__u8	medium;
  9.1038 +	__u8	reserved2;
  9.1039 +	__u8	block_desc_length;
  9.1040 +	__u8	density;
  9.1041 +	__u8	number_of_blocks_hi;
  9.1042 +	__u8	number_of_blocks_med;
  9.1043 +	__u8	number_of_blocks_lo;
  9.1044 +	__u8	reserved3;
  9.1045 +	__u8	block_length_hi;
  9.1046 +	__u8	block_length_med;
  9.1047 +	__u8	block_length_lo;
  9.1048 +};
  9.1049 +
  9.1050 +typedef struct {
  9.1051 +	__u16 report_key_length;
  9.1052 +	__u8 reserved1;
  9.1053 +	__u8 reserved2;
  9.1054 +#if defined(__BIG_ENDIAN_BITFIELD)
  9.1055 +	__u8 type_code			: 2;
  9.1056 +	__u8 vra			: 3;
  9.1057 +	__u8 ucca			: 3;
  9.1058 +#elif defined(__LITTLE_ENDIAN_BITFIELD)
  9.1059 +	__u8 ucca			: 3;
  9.1060 +	__u8 vra			: 3;
  9.1061 +	__u8 type_code			: 2;
  9.1062 +#endif
  9.1063 +	__u8 region_mask;
  9.1064 +	__u8 rpc_scheme;
  9.1065 +	__u8 reserved3;
  9.1066 +} rpc_state_t;
  9.1067 +
  9.1068 +#endif  /* End of kernel only stuff */ 
  9.1069 +
  9.1070 +#endif  /* _LINUX_CDROM_H */
    10.1 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/defconfig	Mon Apr 14 16:31:59 2003 +0000
    10.2 +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/defconfig	Tue Apr 15 15:26:05 2003 +0000
    10.3 @@ -287,7 +287,7 @@ CONFIG_JBD=y
    10.4  # CONFIG_CRAMFS is not set
    10.5  # CONFIG_TMPFS is not set
    10.6  # CONFIG_RAMFS is not set
    10.7 -# CONFIG_ISO9660_FS is not set
    10.8 +CONFIG_ISO9660_FS=y
    10.9  # CONFIG_MINIX_FS is not set
   10.10  # CONFIG_VXFS_FS is not set
   10.11  # CONFIG_NTFS_FS is not set