📄 cdrom.c
字号:
/* linux/drivers/cdrom/cdrom.c. Copyright (c) 1996, 1997 David A. van Leeuwen. Copyright (c) 1997, 1998 Erik Andersen <andersee@debian.org> Copyright (c) 1998, 1999 Jens Axboe <axboe@image.dk> May be copied or modified under the terms of the GNU General Public License. See linux/COPYING for more information. Uniform CD-ROM driver for Linux. See Documentation/cdrom/cdrom-standard.tex for usage information. The routines in the file provide a uniform interface between the software that uses CD-ROMs and the various low-level drivers that actually talk to the hardware. Suggestions are welcome. Patches that work are more welcome though. ;-) To Do List: ---------------------------------- -- Modify sysctl/proc interface. I plan on having one directory per drive, with entries for outputing general drive information, and sysctl based tunable parameters such as whether the tray should auto-close for that drive. Suggestions (or patches) for this welcome! Revision History ---------------------------------- 1.00 Date Unknown -- David van Leeuwen <david@tm.tno.nl> -- Initial version by David A. van Leeuwen. I don't have a detailed changelog for the 1.x series, David?2.00 Dec 2, 1997 -- Erik Andersen <andersee@debian.org> -- New maintainer! As David A. van Leeuwen has been too busy to activly maintain and improve this driver, I am now carrying on the torch. If you have a problem with this driver, please feel free to contact me. -- Added (rudimentary) sysctl interface. I realize this is really weak right now, and is _very_ badly implemented. It will be improved... -- Modified CDROM_DISC_STATUS so that it is now incorporated into the Uniform CD-ROM driver via the cdrom_count_tracks function. The cdrom_count_tracks function helps resolve some of the false assumptions of the CDROM_DISC_STATUS ioctl, and is also used to check for the correct media type when mounting or playing audio from a CD. -- Remove the calls to verify_area and only use the copy_from_user and copy_to_user stuff, since these calls now provide their own memory checking with the 2.1.x kernels. -- Major update to return codes so that errors from low-level drivers are passed on through (thanks to Gerd Knorr for pointing out this problem). -- Made it so if a function isn't implemented in a low-level driver, ENOSYS is now returned instead of EINVAL. -- Simplified some complex logic so that the source code is easier to read. -- Other stuff I probably forgot to mention (lots of changes).2.01 to 2.11 Dec 1997-Jan 1998 -- TO-DO! Write changelogs for 2.01 to 2.12.2.12 Jan 24, 1998 -- Erik Andersen <andersee@debian.org> -- Fixed a bug in the IOCTL_IN and IOCTL_OUT macros. It turns out that copy_*_user does not return EFAULT on error, but instead returns the number of bytes not copied. I was returning whatever non-zero stuff came back from the copy_*_user functions directly, which would result in strange errors.2.13 July 17, 1998 -- Erik Andersen <andersee@debian.org> -- Fixed a bug in CDROM_SELECT_SPEED where you couldn't lower the speed of the drive. Thanks to Tobias Ringstr|m <tori@prosolvia.se> for pointing this out and providing a simple fix. -- Fixed the procfs-unload-module bug with the fill_inode procfs callback. thanks to Andrea Arcangeli -- Fixed it so that the /proc entry now also shows up when cdrom is compiled into the kernel. Before it only worked when loaded as a module. 2.14 August 17, 1998 -- Erik Andersen <andersee@debian.org> -- Fixed a bug in cdrom_media_changed and handling of reporting that the media had changed for devices that _don't_ implement media_changed. Thanks to Grant R. Guenther <grant@torque.net> for spotting this bug. -- Made a few things more pedanticly correct.2.50 Oct 19, 1998 - Jens Axboe <axboe@image.dk> -- New maintainers! Erik was too busy to continue the work on the driver, so now Chris Zwilling <chris@cloudnet.com> and Jens Axboe <axboe@image.dk> will do their best to follow in his footsteps 2.51 Dec 20, 1998 - Jens Axboe <axboe@image.dk> -- Check if drive is capable of doing what we ask before blindly changing cdi->options in various ioctl. -- Added version to proc entry. 2.52 Jan 16, 1999 - Jens Axboe <axboe@image.dk> -- Fixed an error in open_for_data where we would sometimes not return the correct error value. Thanks Huba Gaspar <huba@softcell.hu>. -- Fixed module usage count - usage was based on /proc/sys/dev instead of /proc/sys/dev/cdrom. This could lead to an oops when other modules had entries in dev. Feb 02 - real bug was in sysctl.c where dev would be removed even though it was used. cdrom.c just illuminated that bug. 2.53 Feb 22, 1999 - Jens Axboe <axboe@image.dk> -- Fixup of several ioctl calls, in particular CDROM_SET_OPTIONS has been "rewritten" because capabilities and options aren't in sync. They should be... -- Added CDROM_LOCKDOOR ioctl. Locks the door and keeps it that way. -- Added CDROM_RESET ioctl. -- Added CDROM_DEBUG ioctl. Enable debug messages on-the-fly. -- Added CDROM_GET_CAPABILITY ioctl. This relieves userspace programs from parsing /proc/sys/dev/cdrom/info. 2.54 Mar 15, 1999 - Jens Axboe <axboe@image.dk> -- Check capability mask from low level driver when counting tracks as per suggestion from Corey J. Scotts <cstotts@blue.weeg.uiowa.edu>. 2.55 Apr 25, 1999 - Jens Axboe <axboe@image.dk> -- autoclose was mistakenly checked against CDC_OPEN_TRAY instead of CDC_CLOSE_TRAY. -- proc info didn't mask against capabilities mask. 3.00 Aug 5, 1999 - Jens Axboe <axboe@image.dk> -- Unified audio ioctl handling across CD-ROM drivers. A lot of the code was duplicated before. Drives that support the generic packet interface are now being fed packets from here instead. -- First attempt at adding support for MMC2 commands - for DVD and CD-R(W) drives. Only the DVD parts are in now - the interface used is the same as for the audio ioctls. -- ioctl cleanups. if a drive couldn't play audio, it didn't get a change to perform device specific ioctls as well. -- Defined CDROM_CAN(CDC_XXX) for checking the capabilities. -- Put in sysctl files for autoclose, autoeject, check_media, debug, and lock. -- /proc/sys/dev/cdrom/info has been updated to also contain info about CD-Rx and DVD capabilities. -- Now default to checking media type. -- CDROM_SEND_PACKET ioctl added. The infrastructure was in place for doing this anyway, with the generic_packet addition. 3.01 Aug 6, 1999 - Jens Axboe <axboe@image.dk> -- Fix up the sysctl handling so that the option flags get set correctly. -- Fix up ioctl handling so the device specific ones actually get called :). 3.02 Aug 8, 1999 - Jens Axboe <axboe@image.dk> -- Fixed volume control on SCSI drives (or others with longer audio page). -- Fixed a couple of DVD minors. Thanks to Andrew T. Veliath <andrewtv@usa.net> for telling me and for having defined the various DVD structures and ioctls in the first place! He designed the original DVD patches for ide-cd and while I rearranged and unified them, the interface is still the same. 3.03 Sep 1, 1999 - Jens Axboe <axboe@image.dk> -- Moved the rest of the audio ioctls from the CD-ROM drivers here. Only CDROMREADTOCENTRY and CDROMREADTOCHDR are left. -- Moved the CDROMREADxxx ioctls in here. -- Defined the cdrom_get_last_written and cdrom_get_next_block as ioctls and exported functions. -- Erik Andersen <andersen@xmission.com> modified all SCMD_ commands to now read GPCMD_ for the new generic packet interface. All low level drivers are updated as well. -- Various other cleanups. 3.04 Sep 12, 1999 - Jens Axboe <axboe@image.dk> -- Fixed a couple of possible memory leaks (if an operation failed and we didn't free the buffer before returning the error). -- Integrated Uniform CD Changer handling from Richard Sharman <rsharman@pobox.com>. -- Defined CD_DVD and CD_CHANGER log levels. -- Fixed the CDROMREADxxx ioctls. -- CDROMPLAYTRKIND uses the GPCMD_PLAY_AUDIO_MSF command - too few drives supported it. We loose the index part, however. -- Small modifications to accomodate opens of /dev/hdc1, required for ide-cd to handle multisession discs. -- Export cdrom_mode_sense and cdrom_mode_select. -- init_cdrom_command() for setting up a cgc command. 3.05 Oct 24, 1999 - Jens Axboe <axboe@image.dk> -- Changed the interface for CDROM_SEND_PACKET. Before it was virtually impossible to send the drive data in a sensible way. -- Lowered stack usage in mmc_ioctl(), dvd_read_disckey(), and dvd_read_manufact. -- Added setup of write mode for packet writing. -- Fixed CDDA ripping with cdda2wav - accept much larger requests of number of frames and split the reads in blocks of 8. 3.06 Dec 13, 1999 - Jens Axboe <axboe@image.dk> -- Added support for changing the region of DVD drives. -- Added sense data to generic command. 3.07 Feb 2, 2000 - Jens Axboe <axboe@suse.de> -- Do same "read header length" trick in cdrom_get_disc_info() as we do in cdrom_get_track_info() -- some drive don't obey specs and fail if they can't supply the full Mt Fuji size table. -- Deleted stuff related to setting up write modes. It has a different home now. -- Clear header length in mode_select unconditionally. -- Removed the register_disk() that was added, not needed here. 3.08 May 1, 2000 - Jens Axboe <axboe@suse.de> -- Fix direction flag in setup_send_key and setup_report_key. This gave some SCSI adapters problems. -- Always return -EROFS for write opens -- Convert to module_init/module_exit style init and remove some of the #ifdef MODULE stuff -- Fix several dvd errors - DVD_LU_SEND_ASF should pass agid, DVD_HOST_SEND_RPC_STATE did not set buffer size in cdb, and dvd_do_auth passed uninitialized data to drive because init_cdrom_command did not clear a 0 sized buffer. 3.09 May 12, 2000 - Jens Axboe <axboe@suse.de> -- Fix Video-CD on SCSI drives that don't support READ_CD command. In that case switch block size and issue plain READ_10 again, then switch back. 3.10 Jun 10, 2000 - Jens Axboe <axboe@suse.de> -- Fix volume control on CD's - old SCSI-II drives now use their own code, as doing MODE6 stuff in here is really not my intention. -- Use READ_DISC_INFO for more reliable end-of-disc. 3.11 Jun 12, 2000 - Jens Axboe <axboe@suse.de> -- Fix bug in getting rpc phase 2 region info. -- Reinstate "correct" CDROMPLAYTRKIND 3.12 Oct 18, 2000 - Jens Axboe <axboe@suse.de> -- Use quiet bit on packet commands not known to work-------------------------------------------------------------------------*/#define REVISION "Revision: 3.12"#define VERSION "Id: cdrom.c 3.12 2000/10/18"/* I use an error-log mask to give fine grain control over the type of messages dumped to the system logs. The available masks include: */#define CD_NOTHING 0x0#define CD_WARNING 0x1#define CD_REG_UNREG 0x2#define CD_DO_IOCTL 0x4#define CD_OPEN 0x8#define CD_CLOSE 0x10#define CD_COUNT_TRACKS 0x20#define CD_CHANGER 0x40#define CD_DVD 0x80/* Define this to remove _all_ the debugging messages *//* #define ERRLOGMASK CD_NOTHING */#define ERRLOGMASK (CD_WARNING)/* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_COUNT_TRACKS|CD_CLOSE) *//* #define ERRLOGMASK (CD_WARNING|CD_REG_UNREG|CD_DO_IOCTL|CD_OPEN|CD_CLOSE|CD_COUNT_TRACKS) */#include <linux/config.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/major.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/malloc.h> #include <linux/cdrom.h>#include <linux/sysctl.h>#include <linux/proc_fs.h>#include <linux/init.h>#include <asm/fcntl.h>#include <asm/segment.h>#include <asm/uaccess.h>/* used to tell the module to turn on full debugging messages */static int debug;/* used to keep tray locked at all times */static int keeplocked;/* default compatibility mode */static int autoclose=1;static int autoeject;static int lockdoor = 1;/* will we ever get to use this... sigh. */static int check_media_type;MODULE_PARM(debug, "i");MODULE_PARM(autoclose, "i");MODULE_PARM(autoeject, "i");MODULE_PARM(lockdoor, "i");MODULE_PARM(check_media_type, "i");#if (ERRLOGMASK!=CD_NOTHING)#define cdinfo(type, fmt, args...) \ if ((ERRLOGMASK & type) || debug==1 ) \ printk(KERN_INFO "cdrom: " fmt, ## args)#else#define cdinfo(type, fmt, args...) #endif/* These are used to simplify getting data in from and back to user land */#define IOCTL_IN(arg, type, in) \ if (copy_from_user(&in, (type *) arg, sizeof in)) \ return -EFAULT;#define IOCTL_OUT(arg, type, out) \ if (copy_to_user((type *) arg, &out, sizeof out)) \ return -EFAULT;/* The (cdo->capability & ~cdi->mask & CDC_XXX) construct was used in a lot of places. This macro makes the code more clear. */#define CDROM_CAN(type) (cdi->ops->capability & ~cdi->mask & (type))/* used in the audio ioctls */#define CHECKAUDIO if ((ret=check_for_audio_disc(cdi, cdo))) return ret/* Not-exported routines. */static int cdrom_open(struct inode *ip, struct file *fp);static int cdrom_release(struct inode *ip, struct file *fp);static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);static int cdrom_media_changed(kdev_t dev);static int open_for_data(struct cdrom_device_info * cdi);static int check_for_audio_disc(struct cdrom_device_info * cdi, struct cdrom_device_ops * cdo);static void sanitize_format(union cdrom_addr *addr, u_char * curr, u_char requested);static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, unsigned long arg);int cdrom_get_last_written(kdev_t dev, long *last_written);int cdrom_get_next_writable(kdev_t dev, long *next_writable);#ifdef CONFIG_SYSCTLstatic void cdrom_sysctl_register(void);#endif /* CONFIG_SYSCTL */ static struct cdrom_device_info *topCdromPtr;static devfs_handle_t devfs_handle;struct block_device_operations cdrom_fops ={ open: cdrom_open, release: cdrom_release, ioctl: cdrom_ioctl, check_media_change: cdrom_media_changed,};/* This macro makes sure we don't have to check on cdrom_device_ops * existence in the run-time routines below. Change_capability is a * hack to have the capability flags defined const, while we can still * change it here without gcc complaining at every line. */#define ENSURE(call, bits) if (cdo->call == NULL) *change_capability &= ~(bits)int register_cdrom(struct cdrom_device_info *cdi){ static char banner_printed; int major = MAJOR(cdi->dev); struct cdrom_device_ops *cdo = cdi->ops; int *change_capability = (int *)&cdo->capability; /* hack */ char vname[16]; static unsigned int cdrom_counter; cdinfo(CD_OPEN, "entering register_cdrom\n"); if (major < 0 || major >= MAX_BLKDEV) return -1; if (cdo->open == NULL || cdo->release == NULL) return -2; if ( !banner_printed ) { printk(KERN_INFO "Uniform CD-ROM driver " REVISION "\n"); banner_printed = 1;#ifdef CONFIG_SYSCTL cdrom_sysctl_register();#endif /* CONFIG_SYSCTL */ } ENSURE(drive_status, CDC_DRIVE_STATUS ); ENSURE(media_changed, CDC_MEDIA_CHANGED); ENSURE(tray_move, CDC_CLOSE_TRAY | CDC_OPEN_TRAY); ENSURE(lock_door, CDC_LOCK); ENSURE(select_speed, CDC_SELECT_SPEED); ENSURE(get_last_session, CDC_MULTI_SESSION); ENSURE(get_mcn, CDC_MCN); ENSURE(reset, CDC_RESET); ENSURE(audio_ioctl, CDC_PLAY_AUDIO); ENSURE(dev_ioctl, CDC_IOCTLS); ENSURE(generic_packet, CDC_GENERIC_PACKET); cdi->mc_flags = 0; cdo->n_minors = 0; cdi->options = CDO_USE_FFLAGS; if (autoclose==1 && CDROM_CAN(CDC_CLOSE_TRAY)) cdi->options |= (int) CDO_AUTO_CLOSE; if (autoeject==1 && CDROM_CAN(CDC_OPEN_TRAY)) cdi->options |= (int) CDO_AUTO_EJECT; if (lockdoor==1) cdi->options |= (int) CDO_LOCK; if (check_media_type==1) cdi->options |= (int) CDO_CHECK_TYPE; if (!devfs_handle) devfs_handle = devfs_mk_dir (NULL, "cdroms", NULL); sprintf (vname, "cdrom%u", cdrom_counter++); if (cdi->de) { int pos; devfs_handle_t slave; char rname[64]; pos = devfs_generate_path (cdi->de, rname + 3, sizeof rname - 3); if (pos >= 0) { strncpy (rname + pos, "../", 3); devfs_mk_symlink (devfs_handle, vname, DEVFS_FL_DEFAULT, rname + pos, &slave, NULL); devfs_auto_unregister (cdi->de, slave); } } else { cdi->de = devfs_register (devfs_handle, vname, DEVFS_FL_DEFAULT, MAJOR (cdi->dev), MINOR (cdi->dev), S_IFBLK | S_IRUGO | S_IWUGO, &cdrom_fops, NULL); } cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name); cdi->next = topCdromPtr; topCdromPtr = cdi; return 0;}#undef ENSUREint unregister_cdrom(struct cdrom_device_info *unreg){ struct cdrom_device_info *cdi, *prev; int major = MAJOR(unreg->dev);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -