⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cdrom.c

📁 powerpc内核 mpc8241芯片 linux系统下cdrom驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 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   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! -- Change the CDROMREADMODE1, CDROMREADMODE2, CDROMREADAUDIO, and  CDROMREADRAW ioctls so they go through the Uniform CD-ROM driver.  -- Sync options and capability flags.  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>.-------------------------------------------------------------------------*/#define REVISION "Revision: 2.54"#define VERSION "Id: cdrom.c 2.54 1999/03/15"/* 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 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 <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 = 0;/* used to keep tray locked at all times */static int keeplocked = 0;/* default compatibility mode */static int autoclose=1;static int autoeject=0;static int lockdoor = 1;static int check_media_type = 0;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)	\	copy_from_user_ret(&in, (type *) arg, sizeof in, -EFAULT)#define IOCTL_OUT(arg, type, out) \	copy_to_user_ret((type *) arg, &out, sizeof out, -EFAULT)#define FM_WRITE	0x2                 /* file mode write bit *//* 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);#ifdef CONFIG_SYSCTLstatic void cdrom_sysctl_register(void);#endif /* CONFIG_SYSCTL */ static struct cdrom_device_info *topCdromPtr = NULL;struct file_operations cdrom_fops ={	NULL,                           /* lseek */	block_read,                     /* read - general block-dev read */	block_write,                    /* write - general block-dev write */	NULL,                           /* readdir */	NULL,                           /* poll */	cdrom_ioctl,                    /* ioctl */	NULL,                           /* mmap */	cdrom_open,                     /* open */	NULL,				/* flush */	cdrom_release,                  /* release */	NULL,                           /* fsync */	NULL,                           /* fasync */	cdrom_media_changed,            /* media_change */	NULL                            /* revalidate */};/* 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 = 0;	int major = MAJOR (cdi->dev);        struct cdrom_device_ops *cdo = cdi->ops;        int *change_capability = (int *)&cdo->capability; /* hack */	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 CDROM 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(select_disc, CDC_SELECT_DISC);	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);	cdi->mc_flags = 0;	cdo->n_minors = 0;        cdi->options = CDO_USE_FFLAGS;		if (autoclose==1 && cdo->capability & ~cdi->mask & CDC_OPEN_TRAY)		cdi->options |= (int) CDO_AUTO_CLOSE;	if (autoeject==1 && cdo->capability & ~cdi->mask & 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;	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);	cdinfo(CD_OPEN, "entering unregister_cdrom\n"); 	if (major < 0 || major >= MAX_BLKDEV)		return -1;	prev = NULL;	cdi = topCdromPtr;	while (cdi != NULL && cdi->dev != unreg->dev) {		prev = cdi;		cdi = cdi->next;	}	if (cdi == NULL)		return -2;	if (prev)		prev->next = cdi->next;	else		topCdromPtr = cdi->next;	cdi->ops->n_minors--;	cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);	return 0;}staticstruct cdrom_device_info *cdrom_find_device (kdev_t dev){	struct cdrom_device_info *cdi;	cdi = topCdromPtr;	while (cdi != NULL && cdi->dev != dev)		cdi = cdi->next;	return cdi;}/* We use the open-option O_NONBLOCK to indicate that the * purpose of opening is only for subsequent ioctl() calls; no device * integrity checks are performed. * * We hope that all cd-player programs will adopt this convention. It * is in their own interest: device control becomes a lot easier * this way. */staticint cdrom_open(struct inode *ip, struct file *fp){	kdev_t dev = ip->i_rdev;	struct cdrom_device_info *cdi = cdrom_find_device(dev);	int purpose = !!(fp->f_flags & O_NONBLOCK);	int ret=0;	cdinfo(CD_OPEN, "entering cdrom_open\n"); 	if (cdi == NULL)		return -ENODEV;	if (fp->f_mode & FM_WRITE)		return -EROFS;	purpose = purpose || !(cdi->options & CDO_USE_FFLAGS);	if (purpose)		ret = cdi->ops->open(cdi, purpose);	else		ret = open_for_data(cdi);	if (!ret) cdi->use_count++;	cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n", cdi->name, cdi->use_count);	/* Do this on open.  Don't wait for mount, because they might	    not be mounting, but opening with O_NONBLOCK */	check_disk_change(dev);	return ret;}staticint open_for_data(struct cdrom_device_info * cdi){	int ret;	struct cdrom_device_ops *cdo = cdi->ops;	tracktype tracks;	cdinfo(CD_OPEN, "entering open_for_data\n");	/* Check if the driver can report drive status.  If it can, we	   can do clever things.  If it can't, well, we at least tried! */	if (cdo->drive_status != NULL) {		ret = cdo->drive_status(cdi, CDSL_CURRENT);		cdinfo(CD_OPEN, "drive_status=%d\n", ret); 		if (ret == CDS_TRAY_OPEN) {			cdinfo(CD_OPEN, "the tray is open...\n"); 			/* can/may i close it? */			if (cdo->capability & ~cdi->mask & CDC_CLOSE_TRAY &&			    cdi->options & CDO_AUTO_CLOSE) {				cdinfo(CD_OPEN, "trying to close the tray.\n"); 				ret=cdo->tray_move(cdi,0);				if (ret) {					cdinfo(CD_OPEN, "bummer. tried to close the tray but failed.\n"); 					/* Ignore the error from the low					level driver.  We don't care why it					couldn't close the tray.  We only care 					that there is no disc in the drive, 					since that is the _REAL_ problem here.*/					ret=-ENOMEDIUM;					goto clean_up_and_return;				}			} else {				cdinfo(CD_OPEN, "bummer. this drive can't close the tray.\n"); 				ret=-ENOMEDIUM;				goto clean_up_and_return;			}			/* Ok, the door should be closed now.. Check again */			ret = cdo->drive_status(cdi, CDSL_CURRENT);			if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) {				cdinfo(CD_OPEN, "bummer. the tray is still not closed.\n"); 				cdinfo(CD_OPEN, "tray might not contain a medium.\n");				ret=-ENOMEDIUM;				goto clean_up_and_return;			}			cdinfo(CD_OPEN, "the tray is now closed.\n"); 		}		if (ret!=CDS_DISC_OK) {			ret = -ENOMEDIUM;			goto clean_up_and_return;		}	}	cdrom_count_tracks(cdi, &tracks);	if (tracks.error == CDS_NO_DISC) {		cdinfo(CD_OPEN, "bummer. no disc.\n");		ret=-ENOMEDIUM;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -