This adds two new callbacks into the Uniform cdrom driver: pre-ioctl,
and post-ioctl. I added support for these into all the low-level cdrom
drivers. This also make a nice clean solution for certain proprietary
cdrom drivers that need to manage their drive's spin-up. Anyway, try
this out and see if you can make your favorate cdrom driver Oops.
I am trying to squash _all_ cdrom bugs in the kernel. cdu31a is next in
the queue (even though I don't have one). If you have experienced a bug
in any of the cdrom drivers run under the Uniform cdrom driver , please
report them to me. I am maintaining a list and working on them as I have
time.
patch follows.
-Erik
-- Erik B. Andersen Web: http://www.inconnect.com/~andersen/ email: andersee@debian.org --This message was written using 73% post-consumer electrons--
diff --unified --new-file --recursive linux-2.1.105.virgin/Documentation/cdrom/cdrom-standard.tex linux/Documentation/cdrom/cdrom-standard.tex --- linux-2.1.105.virgin/Documentation/cdrom/cdrom-standard.tex Fri May 1 14:59:50 1998 +++ linux/Documentation/cdrom/cdrom-standard.tex Wed Jun 10 23:46:51 1998 @@ -1,5 +1,5 @@ \documentclass{article} -\def\version{$Id: cdrom-standard.tex,v 1.9 1997/12/28 15:42:49 david Exp $} +\def\version{$Id: cdrom-standard.tex,v 1.91 1998/06/10 23:33:11 erik Exp $} \newcommand{\newsection}[1]{\newpage\section{#1}} \evensidemargin=0pt @@ -246,6 +246,8 @@ void *{});\cr &int& (* dev_ioctl)(struct\ cdrom_device_info *, unsigned\ int, unsigned\ long);\cr + &int& (* pre_ioctl)(struct\ cdrom_device_info *);\cr + &int& (* post_ioctl)(struct\ cdrom_device_info *);\cr \noalign{\medskip} &const\ int& capability;& capability flags \cr &int& n_minors;& number of active minor devices \cr @@ -547,6 +549,20 @@ CDROMREADAUDIO, CDROMREADRAW, CDROMREADCOOKED, CDROMSEEK, CDROMPLAY\-BLK and CDROM\-READALL}. +\subsection{$Int\ pre_ioctl(struct\ cdrom_device_info * cdi)$} + +This is a callback function into the low-level device driver that is +made before every ioctl call. This should be used to increment the +module use count, spin up the cdrom drive (if necessary), and do any +house-keeping needed to make sure the drive is in a safe, sane state. + +\subsection{$Int\ reset(struct\ cdrom_device_info * cdi)$} + +This is a callback function into the low-level device driver that is +made after every ioctl call. This should be used to decrement the module +use count, and do any house-keeping needed to make sure the drive is in +a safe, sane state. + \subsection{\cdrom\ capabilities} Instead of just implementing some $ioctl$ calls, the interface in @@ -568,6 +584,8 @@ CDC_RESET& hard reset device\cr CDC_IOCTLS& driver has non-standard ioctls\cr CDC_DRIVE_STATUS& driver implements drive status\cr +CDC_PRE_IOCTL& driver utilizes a pre-ioctl callback\cr +CDC_POST_IOCTL& driver utilizes a post-ioctl callback\cr } $$ The capability flag is declared $const$, to prevent drivers from @@ -609,10 +627,13 @@ $$ The initial value of this register is $CDO_AUTO_CLOSE \mathrel| -CDO_USE_FFLAGS \mathrel| CDO_LOCK$, reflecting my own view on user -interface and software standards. Before you protest, there are two -new $ioctl$s implemented in \cdromc, that allow you to control the -behavior by software. These are: +CDO_USE_FFLAGS \mathrel| CDO_LOCK$ \mathrel| $CDO_CHECK_TYPE$, +reflecting my own view on user interface and software standards. Those +that wish to not check the media type, can use the optional command-line +argument "dont_check_media_type=1", which will enable the old non-media +type checking behavior. Additionally, you can change the default cdrom +options at any time by using the two new $ioctl$s implemented in +\cdromc. These are: $$ \halign{$#$\ \hfil&$/*$ \rm# $*/$\hfil\cr CDROM_SET_OPTIONS& set options specified in $(int)\ arg$\cr @@ -933,7 +954,7 @@ CDS_DATA_1& data disc, mode 1 (2048 user bytes/frame)\cr CDS_DATA_2& data disc, mode 2 (2336 user bytes/frame)\cr CDS_XA_2_1& mixed data (XA), mode 2, form 1 (2048 user bytes)\cr - CDS_XA_2_2& mixed data (XA), mode 2, form 1 (2324 user bytes)\cr + CDS_XA_2_2& mixed data (XA), mode 2, form 1 (2324 user bytes)\cr CDS_MIXED& mixed audio/data disc\cr } $$ diff --unified --new-file --recursive linux-2.1.105.virgin/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c --- linux-2.1.105.virgin/drivers/block/ide-cd.c Sat May 16 08:59:34 1998 +++ linux/drivers/block/ide-cd.c Thu Jun 11 00:29:53 1998 @@ -13,22 +13,30 @@ * Suggestions are welcome. Patches that work are more welcome though. ;-) * For those wishing to work on this driver, please be sure you download * and comply with the latest ATAPI standard. This document can be - * obtained by anonymous ftp from fission.dt.wdc.com in directory: - * /pub/standards/SFF_atapi/spec/SFF8020-r2.6/PDF/8020r26.pdf + * obtained by anonymous ftp from: + * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps * * Drives that deviate from the ATAPI standard will be accomodated as much - * as possible via compile options. Since I only have a few drives, you you - * generally need to send me patches... + * as possible via compile time or command-line options. Since I only have + * a few drives, you generally need to send me patches... * * ---------------------------------- * TO DO LIST: - * -Avoid printing error messages for expected errors from the drive. - * (If you are using a cd changer, you may get errors in the kernel - * logs that are completly expected. Don't complain to me about this, - * unless you have a patch to fix it. I am working on it...) + * -Implement Microsoft Media Status Notification per the spec at + * http://www.microsoft.com/hwdev/respec/storspec.htm + * This will allow us to get automagically noticied when the media changes + * from ATAPI drives (something the stock ATAPI spec is lacking). Looks + * very cool. I discovered its existance the other day at work... * -Fix ide_cdrom_reset so that it works (it does nothing right now) * -Query the drive to find what features are available before trying to * use them (like trying to close the tray in drives that can't). + * -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on + * boot. + * -Handle older drives that can't report their speed. (i.e. check if they + * support a version of ATAPI where they can report their speed before + * checking their speed and believing what they return). + * -It seems we do not honor it when Uniform gets a request to change the + * cdi->options. We should _always_ check the options before doing stuff. * * * ---------------------------------- @@ -205,10 +213,14 @@ * messages, since this is not an error. * -- Change error messages to be const * -- Remove a "\t" which looks ugly in the syslogs + * 4.14 June 11, 1998 -- Add support for pre and post ioctl from the Uniform + * cdrom driver. + * -- Change to pointing to .ps version of ATAPI spec, + * since the .pdf version doesn't seem to work... * *************************************************************************/ -#define IDECD_VERSION "4.13" +#define IDECD_VERSION "4.14" #include <linux/module.h> #include <linux/types.h> @@ -1157,7 +1169,7 @@ if (pc->buflen == 0) cdrom_end_request (1, drive); else { - /* Comment this out, because this always happins + /* Comment this out, because this always happens right after a reset occurs, and it is annoying to always print expected stuff. */ /* @@ -2455,6 +2467,23 @@ static +int ide_cdrom_pre_ioctl (struct cdrom_device_info *cdi) +{ + /* Increment module use count */ + MOD_INC_USE_COUNT; + return 0; +} + +static +int ide_cdrom_post_ioctl (struct cdrom_device_info *cdi) +{ + /* Decrement module use count */ + MOD_DEC_USE_COUNT; + return 0; +} + + +static int ide_cdrom_reset (struct cdrom_device_info *cdi) { @@ -2780,10 +2809,12 @@ ide_cdrom_reset, /* reset */ ide_cdrom_audio_ioctl, /* audio_ioctl */ ide_cdrom_dev_ioctl, /* dev_ioctl */ + ide_cdrom_pre_ioctl, /* called before each ioctl call */ + ide_cdrom_post_ioctl, /* called after each ioctl call */ CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED - | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN - | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET - | CDC_IOCTLS | CDC_DRIVE_STATUS, /* capability */ + | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | + CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS | + CDC_PRE_IOCTL | CDC_POST_IOCTL, /* capability */ 0 /* n_minors */ }; diff --unified --new-file --recursive linux-2.1.105.virgin/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c --- linux-2.1.105.virgin/drivers/cdrom/cdrom.c Mon Apr 6 22:21:49 1998 +++ linux/drivers/cdrom/cdrom.c Thu Jun 11 00:16:07 1998 @@ -16,6 +16,10 @@ To Do List: ---------------------------------- + -- Get rid of the stupid CD_RETURN macro I just added (which bloats + the driver for no good reason) and just set the return code in a variable, + break out from the switch, and then return the exit code. + -- 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 @@ -69,12 +73,24 @@ -- 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 return 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 June 8, 1998 -- Erik Andersen <andersee@debian.org> + -- Added in pre and post ioctl callbacks into the low-level drivers. + This will allow low-level drivers to increment modules use counts, as + well as do intelligent things such as spin-up the drive. This avoids + nasty race conditions where the user could (theoretically) remove the + low-level device driver modules from underneath us during an ioctl + call. + -- Made media type checking the default (again). I added in an option + so that people can set "dont_check_media_type= 1" on the kernel + command line, and any old applications that cannot cope with media + type checking will automagically work again (at least as far as + backwards behavior can be considered to be working ;-). -------------------------------------------------------------------------*/ -#define REVISION "Revision: 2.12" -#define VERSION "Id: cdrom.c 2.12 1998/01/24 22:15:45 erik Exp" +#define REVISION "Revision: 2.13" +#define VERSION "Id: cdrom.c 2.13 1998/06/08 19:28:02 erik Exp" /* 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: */ @@ -89,10 +105,8 @@ /* 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> @@ -104,11 +118,19 @@ #include <linux/malloc.h> #include <linux/cdrom.h> #include <linux/sysctl.h> +#include <linux/init.h> #include <asm/fcntl.h> #include <asm/segment.h> #include <asm/uaccess.h> + +#ifdef MODULE +static int dont_check_media_type = 0; +MODULE_PARM(dont_check_media_type, "i"); +#endif + + #if (ERRLOGMASK!=CD_NOTHING) #define cdinfo(type, fmt, args...) \ if (ERRLOGMASK & type) printk(KERN_INFO "cdrom: " fmt, ## args) @@ -195,8 +217,15 @@ ENSURE(reset, CDC_RESET); ENSURE(audio_ioctl, CDC_PLAY_AUDIO); ENSURE(dev_ioctl, CDC_IOCTLS); - cdi->options = CDO_AUTO_CLOSE | CDO_USE_FFLAGS | CDO_LOCK; - /* default compatibility mode */ + ENSURE(pre_ioctl, CDC_PRE_IOCTL); + ENSURE(post_ioctl, CDC_POST_IOCTL); + cdi->options = CDO_AUTO_CLOSE | CDO_USE_FFLAGS | CDO_CHECK_TYPE | CDO_LOCK; + if (dont_check_media_type==0) + cdi->options |= (int) CDO_CHECK_TYPE; + else { + printk(KERN_INFO "Not checking media type -- as you request.\n"); + printk(KERN_INFO " CDROM apps that cannot cope with media type checking should be fixed.\n"); + } cdi->mc_flags = 0; cdo->n_minors = 0; @@ -211,6 +240,7 @@ cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name); cdi->next = topCdromPtr; topCdromPtr = cdi; + MOD_INC_USE_COUNT; return 0; } #undef ENSURE @@ -238,6 +268,7 @@ topCdromPtr = cdi->next; cdi->ops->n_minors--; cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name); + MOD_DEC_USE_COUNT; return 0; } @@ -337,11 +368,16 @@ } /* CD-Players which don't use O_NONBLOCK, workman * for example, need bit CDO_CHECK_TYPE cleared! */ - if (cdi->options & CDO_CHECK_TYPE && tracks.data==0) { + if (cdi->options & CDO_CHECK_TYPE) { + if (tracks.data==0) { cdinfo(CD_OPEN, "bummer. wrong media type.\n"); ret=-EMEDIUMTYPE; goto clean_up_and_return; + } } + else + cdinfo(CD_OPEN, "not checking media type-- per drive options\n"); + cdinfo(CD_OPEN, "all seems well, opening the device.\n"); @@ -388,8 +424,10 @@ int ret; tracktype tracks; cdinfo(CD_OPEN, "entering check_for_audio_disc\n"); - if (!(cdi->options & CDO_CHECK_TYPE)) + if (!(cdi->options & CDO_CHECK_TYPE)) { + cdinfo(CD_OPEN, "not checking -- per drive options\n"); return 0; + } if (cdo->drive_status != NULL) { ret = cdo->drive_status(cdi, CDSL_CURRENT); cdinfo(CD_OPEN, "drive_status=%d\n", ret); @@ -586,6 +624,13 @@ *curr = requested; } +// Add the do/while so that we can use this like a function call. +#define CD_RETURN(code) \ + do { if (!(cdo->capability & CDC_POST_IOCTL)) \ + cdo->post_ioctl(cdi);\ + return(code); } while (0) + + /* Some of the cdrom ioctls are not implemented here, because these * appear to be either too device-specific, or it is not clear to me * what use they are. These are (number of drivers that support them @@ -611,6 +656,13 @@ return -ENODEV; cdo = cdi->ops; + // After this point, all returns should be using the + // CD_RETURN macro, which handles the post_ioctl call + // and then returns. + if (!(cdo->capability & CDC_PRE_IOCTL)) { + cdo->pre_ioctl(cdi); + } + /* the first few commands do not deal with audio drive_info, but only with routines in cdrom device operations. */ switch (cmd) { @@ -621,91 +673,91 @@ struct cdrom_multisession ms_info; u_char requested_format; cdinfo(CD_DO_IOCTL, "entering CDROMMULTISESSION\n"); - if (!(cdo->capability & CDC_MULTI_SESSION)) - return -ENOSYS; + if (!(cdo->capability & CDC_MULTI_SESSION)) + CD_RETURN(-ENOSYS); IOCTL_IN(arg, struct cdrom_multisession, ms_info); requested_format = ms_info.addr_format; if (!((requested_format == CDROM_MSF) || (requested_format == CDROM_LBA))) - return -EINVAL; + CD_RETURN(-EINVAL); ms_info.addr_format = CDROM_LBA; if ((ret=cdo->get_last_session(cdi, &ms_info))) - return ret; + CD_RETURN( ret); sanitize_format(&ms_info.addr, &ms_info.addr_format, requested_format); IOCTL_OUT(arg, struct cdrom_multisession, ms_info); cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION sucessful\n"); - return 0; + CD_RETURN( 0); } case CDROMEJECT: { int ret; cdinfo(CD_DO_IOCTL, "entering CDROMEJECT\n"); if (!(cdo->capability & ~cdi->mask & CDC_OPEN_TRAY)) - return -ENOSYS; + CD_RETURN( -ENOSYS); if (cdi->use_count != 1) - return -EBUSY; + CD_RETURN( -EBUSY); if (cdo->capability & ~cdi->mask & CDC_LOCK) { if ((ret=cdo->lock_door(cdi, 0))) - return ret; + CD_RETURN( ret); } - return cdo->tray_move(cdi, 1); + CD_RETURN( cdo->tray_move(cdi, 1)); } case CDROMCLOSETRAY: cdinfo(CD_DO_IOCTL, "entering CDROMCLOSETRAY\n"); if (!(cdo->capability & ~cdi->mask & CDC_OPEN_TRAY)) - return -ENOSYS; - return cdo->tray_move(cdi, 0); + CD_RETURN( -ENOSYS); + CD_RETURN( cdo->tray_move(cdi, 0)); case CDROMEJECT_SW: cdinfo(CD_DO_IOCTL, "entering CDROMEJECT_SW\n"); cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT); if (arg) cdi->options |= CDO_AUTO_CLOSE | CDO_AUTO_EJECT; - return 0; + CD_RETURN( 0); case CDROM_MEDIA_CHANGED: { cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n"); if (!(cdo->capability & ~cdi->mask & CDC_MEDIA_CHANGED)) - return -ENOSYS; + CD_RETURN( -ENOSYS); if (!(cdo->capability & ~cdi->mask & CDC_SELECT_DISC) || arg == CDSL_CURRENT) /* cannot select disc or select current disc */ - return media_changed(cdi, 1); + CD_RETURN( media_changed(cdi, 1)); if ((unsigned int)arg >= cdi->capacity) - return -EINVAL; - return cdo->media_changed (cdi, arg); + CD_RETURN( -EINVAL); + CD_RETURN( cdo->media_changed (cdi, arg)); } case CDROM_SET_OPTIONS: cdinfo(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n"); cdi->options |= (int) arg; - return cdi->options; + CD_RETURN( cdi->options); case CDROM_CLEAR_OPTIONS: cdinfo(CD_DO_IOCTL, "entering CDROM_CLEAR_OPTIONS\n"); cdi->options &= ~(int) arg; - return cdi->options; + CD_RETURN( cdi->options); case CDROM_SELECT_SPEED: { cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_SPEED\n"); if (!(cdo->capability & ~cdi->mask & CDC_SELECT_SPEED)) - return -ENOSYS; + CD_RETURN( -ENOSYS); if ((int)arg > cdi->speed ) - return -EINVAL; - return cdo->select_speed(cdi, arg); + CD_RETURN( -EINVAL); + CD_RETURN( cdo->select_speed(cdi, arg)); } case CDROM_SELECT_DISC: { cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_DISC\n"); if (!(cdo->capability & ~cdi->mask & CDC_SELECT_DISC)) - return -ENOSYS; + CD_RETURN( -ENOSYS); if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE)) - return cdo->select_disc(cdi, arg); + CD_RETURN( cdo->select_disc(cdi, arg)); if ((int)arg >= cdi->capacity) - return -EDRIVE_CANT_DO_THIS; - return cdo->select_disc(cdi, arg); + CD_RETURN( -EDRIVE_CANT_DO_THIS); + CD_RETURN( cdo->select_disc(cdi, arg)); } /* The following function is implemented, although very few audio @@ -718,23 +770,23 @@ struct cdrom_mcn mcn; cdinfo(CD_DO_IOCTL, "entering CDROM_GET_MCN\n"); if (!(cdo->capability & CDC_MCN)) - return -ENOSYS; + CD_RETURN( -ENOSYS); if ((ret=cdo->get_mcn(cdi, &mcn))) - return ret; + CD_RETURN( ret); IOCTL_OUT(arg, struct cdrom_mcn, mcn); cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN sucessful\n"); - return 0; + CD_RETURN( 0); } case CDROM_DRIVE_STATUS: { cdinfo(CD_DO_IOCTL, "entering CDROM_DRIVE_STATUS\n"); if (!(cdo->capability & CDC_DRIVE_STATUS)) - return -ENOSYS; + CD_RETURN( -ENOSYS); if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE)) - return cdo->drive_status(cdi, arg); + CD_RETURN( cdo->drive_status(cdi, arg)); if (((int)arg > cdi->capacity)) - return -EINVAL; - return cdo->drive_status(cdi, arg); + CD_RETURN( -EINVAL); + CD_RETURN( cdo->drive_status(cdi, arg)); } /* Ok, this is where problems start. The current interface for the @@ -759,26 +811,26 @@ cdinfo(CD_DO_IOCTL, "entering CDROM_DISC_STATUS\n"); cdrom_count_tracks(cdi, &tracks); if (tracks.error) - return(tracks.error); + CD_RETURN( tracks.error); /* Policy mode on */ if (tracks.audio > 0) { if (tracks.data==0 && tracks.cdi==0 && tracks.xa==0) - return CDS_AUDIO; - else return CDS_MIXED; + CD_RETURN( CDS_AUDIO); + else CD_RETURN( CDS_MIXED); } - if (tracks.cdi > 0) return CDS_XA_2_2; - if (tracks.xa > 0) return CDS_XA_2_1; - if (tracks.data > 0) return CDS_DATA_1; + if (tracks.cdi > 0) CD_RETURN( CDS_XA_2_2); + if (tracks.xa > 0) CD_RETURN( CDS_XA_2_1); + if (tracks.data > 0) CD_RETURN( CDS_DATA_1); /* Policy mode off */ cdinfo(CD_WARNING,"This disc doesn't have any tracks I recognise!\n"); - return CDS_NO_INFO; + CD_RETURN( CDS_NO_INFO); } case CDROM_CHANGER_NSLOTS: cdinfo(CD_DO_IOCTL, "entering CDROM_CHANGER_NSLOTS\n"); - return cdi->capacity; + CD_RETURN( cdi->capacity); /* The following is not implemented, because there are too many * different data types. We could support /1/ raw mode, that is large @@ -793,9 +845,9 @@ cdinfo(CD_DO_IOCTL, "entering CDROMREADMODE1\n"); IOCTL_IN(arg, struct cdrom_msf, msf); if (ret=cdo->read_audio(dev, cmd, &msf, &buf, cdi)) - return ret; + CD_RETURN( ret); IOCTL_OUT(arg, __typeof__(buf), buf); - return 0; + CD_RETURN( 0); } #endif } /* switch */ @@ -803,10 +855,10 @@ /* Now all the audio-ioctls follow, they are all routed through the same call audio_ioctl(). */ -#define CHECKAUDIO if ((ret=check_for_audio_disc(cdi, cdo))) return ret +#define CHECKAUDIO if ((ret=check_for_audio_disc(cdi, cdo))) CD_RETURN( ret) if (!(cdo->capability & CDC_PLAY_AUDIO)) - return -ENOSYS; + CD_RETURN( -ENOSYS); else { switch (cmd) { case CDROMSUBCHNL: { @@ -820,16 +872,16 @@ requested = q.cdsc_format; if (!((requested == CDROM_MSF) || (requested == CDROM_LBA))) - return -EINVAL; + CD_RETURN( -EINVAL); q.cdsc_format = CDROM_MSF; if ((ret=cdo->audio_ioctl(cdi, cmd, &q))) - return ret; + CD_RETURN( ret); back = q.cdsc_format; /* local copy */ sanitize_format(&q.cdsc_absaddr, &back, requested); sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); IOCTL_OUT(arg, struct cdrom_subchnl, q); /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL sucessful\n"); */ - return 0; + CD_RETURN( 0); } case CDROMREADTOCHDR: { int ret; @@ -839,10 +891,10 @@ /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */ IOCTL_IN(arg, struct cdrom_tochdr, header); if ((ret=cdo->audio_ioctl(cdi, cmd, &header))) - return ret; + CD_RETURN( ret); IOCTL_OUT(arg, struct cdrom_tochdr, header); /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR sucessful\n"); */ - return 0; + CD_RETURN( 0); } case CDROMREADTOCENTRY: { int ret; @@ -855,16 +907,16 @@ requested_format = entry.cdte_format; if (!((requested_format == CDROM_MSF) || (requested_format == CDROM_LBA))) - return -EINVAL; + CD_RETURN( -EINVAL); /* make interface to low-level uniform */ entry.cdte_format = CDROM_MSF; if ((ret=cdo->audio_ioctl(cdi, cmd, &entry))) - return ret; + CD_RETURN( ret); sanitize_format(&entry.cdte_addr, &entry.cdte_format, requested_format); IOCTL_OUT(arg, struct cdrom_tocentry, entry); /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY sucessful\n"); */ - return 0; + CD_RETURN( 0); } case CDROMPLAYMSF: { int ret; @@ -872,7 +924,7 @@ cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); IOCTL_IN(arg, struct cdrom_msf, msf); CHECKAUDIO; - return cdo->audio_ioctl(cdi, cmd, &msf); + CD_RETURN( cdo->audio_ioctl(cdi, cmd, &msf)); } case CDROMPLAYTRKIND: { int ret; @@ -880,22 +932,22 @@ cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n"); IOCTL_IN(arg, struct cdrom_ti, ti); CHECKAUDIO; - return cdo->audio_ioctl(cdi, cmd, &ti); + CD_RETURN( cdo->audio_ioctl(cdi, cmd, &ti)); } case CDROMVOLCTRL: { struct cdrom_volctrl volume; cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRL\n"); IOCTL_IN(arg, struct cdrom_volctrl, volume); - return cdo->audio_ioctl(cdi, cmd, &volume); + CD_RETURN( cdo->audio_ioctl(cdi, cmd, &volume)); } case CDROMVOLREAD: { int ret; struct cdrom_volctrl volume; cdinfo(CD_DO_IOCTL, "entering CDROMVOLREAD\n"); if ((ret=cdo->audio_ioctl(cdi, cmd, &volume))) - return ret; + CD_RETURN( ret); IOCTL_OUT(arg, struct cdrom_volctrl, volume); - return 0; + CD_RETURN( 0); } case CDROMSTART: case CDROMSTOP: @@ -904,16 +956,16 @@ int ret; cdinfo(CD_DO_IOCTL, "doing audio ioctl (start/stop/pause/resume)\n"); CHECKAUDIO; - return cdo->audio_ioctl(cdi, cmd, NULL); + CD_RETURN( cdo->audio_ioctl(cdi, cmd, NULL)); } } /* switch */ } /* device specific ioctls? */ if (!(cdo->capability & CDC_IOCTLS)) - return -ENOSYS; + CD_RETURN( -ENOSYS); else - return cdo->dev_ioctl(cdi, cmd, arg); + CD_RETURN( cdo->dev_ioctl(cdi, cmd, arg)); } EXPORT_SYMBOL(register_cdrom); @@ -1038,6 +1090,13 @@ unregister_sysctl_table(cdrom_sysctl_header); } #endif /* endif CONFIG_SYSCTL */ + + +__initfunc(void cdrom_setup(char *str, int *ints)) +{ + if ( ints[0] != 0 ) + dont_check_media_type = 1; +} int init_module(void) { diff --unified --new-file --recursive linux-2.1.105.virgin/drivers/cdrom/cdu31a.c linux/drivers/cdrom/cdu31a.c --- linux-2.1.105.virgin/drivers/cdrom/cdu31a.c Sat Feb 28 09:19:51 1998 +++ linux/drivers/cdrom/cdu31a.c Mon Jun 8 22:33:57 1998 @@ -228,6 +228,15 @@ /* Define the following if you have data corruption problems. */ #undef SONY_POLL_EACH_BYTE +/* The base I/O address of the Sony Interface. This is a variable (not a + #define) so it can be easily changed via some future ioctl() */ +static unsigned int cdu31a_port = 0; +MODULE_PARM(cdu31a_port, "i"); +/* What IRQ is the drive using? 0 if none. */ +static int cdu31a_irq = 0; +MODULE_PARM(cdu31a_irq, "i"); + + /* ** Edit the following data to change interrupts, DMA channels, etc. ** Default is polled and no DMA. DMA is not recommended for double-speed @@ -257,7 +266,6 @@ static int handle_sony_cd_attention(void); static int read_subcode(void); static void sony_get_toc(void); -/*static int scd_open(struct inode *inode, struct file *filp);*/ static int scd_open(struct cdrom_device_info *, int); static void do_sony_cd_cmd(unsigned char cmd, unsigned char *params, @@ -266,6 +274,7 @@ unsigned int *result_size); static void size_to_buf(unsigned int size, unsigned char *buf); +static int scd_spinup(void); /* Parameters for the read-ahead. */ static unsigned int sony_next_block; /* Next 512 byte block offset */ @@ -273,11 +282,6 @@ in the current read command. */ -/* The base I/O address of the Sony Interface. This is a variable (not a - #define) so it can be easily changed via some future ioctl() */ -static unsigned int cdu31a_port = 0; -MODULE_PARM(cdu31a_port, "i"); - /* * The following are I/O addresses of the various registers for the drive. The * comment for the base address also applies here. @@ -351,10 +355,6 @@ static unsigned volatile char cur_pos_msf[3] = { 0, 0, 0 }; static unsigned volatile char final_pos_msf[3] = { 0, 0, 0 }; -/* What IRQ is the drive using? 0 if none. */ -static int cdu31a_irq = 0; -MODULE_PARM(cdu31a_irq, "i"); - /* The interrupt handler will wake this queue up when it gets an interrupts. */ static struct wait_queue *cdu31a_irq_wait = NULL; @@ -401,6 +401,35 @@ /* * Uniform cdrom interface function + * This is called before any ioctl is called. + */ +static int scd_pre_ioctl(struct cdrom_device_info * cdi) +{ + /* Increment module use count and spin up drive here. + */ + if (scd_spinup() != 0) { + MOD_DEC_USE_COUNT; + return -EIO; + } + MOD_INC_USE_COUNT; + return 0; +} + +/* + * Uniform cdrom interface function + * This is called after every ioctl exits. + */ +static int scd_post_ioctl(struct cdrom_device_info * cdi) +{ + /* Decrement module use count here. + */ + MOD_DEC_USE_COUNT; + return 0; +} + + +/* + * Uniform cdrom interface function * report back, if disc has changed from time of last request. */ static int @@ -1680,7 +1709,6 @@ #endif } -static int scd_spinup(void); /* * The OS calls this to perform a read or write operation to the drive. @@ -3272,9 +3300,12 @@ scd_reset, /* hard reset */ scd_audio_ioctl, /* audio ioctl */ scd_dev_ioctl, /* device-specific ioctl */ - CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_MULTI_SESSION | - CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | - CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS, /* capability */ + scd_pre_ioctl, /* called before each ioctl call */ + scd_post_ioctl, /* called after each ioctl call */ + CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK | CDC_SELECT_SPEED | + CDC_MULTI_SESSION | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | + CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS | + CDC_PRE_IOCTL | CDC_POST_IOCTL, /* capability */ 1, /* number of minor devices */ }; diff --unified --new-file --recursive linux-2.1.105.virgin/drivers/cdrom/cm206.c linux/drivers/cdrom/cm206.c --- linux-2.1.105.virgin/drivers/cdrom/cm206.c Sat Jun 6 22:05:02 1998 +++ linux/drivers/cdrom/cm206.c Mon Jun 8 21:02:29 1998 @@ -1189,6 +1189,18 @@ return 0; } +int cm206_pre_ioctl(struct cdrom_device_info * cdi) +{ + MOD_INC_USE_COUNT; + return 0; +} + +int cm206_post_ioctl(struct cdrom_device_info * cdi) +{ + MOD_DEC_USE_COUNT; + return 0; +} + int cm206_reset(struct cdrom_device_info * cdi) { stop_read(); @@ -1236,9 +1248,11 @@ cm206_reset, /* hard reset */ cm206_audio_ioctl, /* audio ioctl */ cm206_ioctl, /* device-specific ioctl */ + cm206_pre_ioctl, /* called before each ioctl call */ + cm206_post_ioctl, /* called after each ioctl call */ CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED | - CDC_IOCTLS | CDC_DRIVE_STATUS, + CDC_IOCTLS | CDC_PRE_IOCTL | CDC_POST_IOCTL | CDC_DRIVE_STATUS, /* capability */ 1, /* number of minor devices */ }; diff --unified --new-file --recursive linux-2.1.105.virgin/drivers/cdrom/mcd.c linux/drivers/cdrom/mcd.c --- linux-2.1.105.virgin/drivers/cdrom/mcd.c Sat Feb 28 09:19:51 1998 +++ linux/drivers/cdrom/mcd.c Mon Jun 8 22:35:32 1998 @@ -191,6 +191,8 @@ int mcd_audio_ioctl(struct cdrom_device_info * cdi, unsigned int cmd, void * arg); int mcd_drive_status(struct cdrom_device_info * cdi, int slot_nr); +static int mcd_pre_ioctl(struct cdrom_device_info * cdi); +static int mcd_post_ioctl(struct cdrom_device_info * cdi); static struct cdrom_device_ops mcd_dops = { mcd_open, /* open */ @@ -207,8 +209,10 @@ NULL, /* hard reset */ mcd_audio_ioctl, /* audio ioctl */ NULL, /* device-specific ioctl */ + mcd_pre_ioctl, /* called before each ioctl call */ + mcd_post_ioctl, /* called after each ioctl call */ CDC_OPEN_TRAY | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO - | CDC_DRIVE_STATUS, /* capability */ + | CDC_PRE_IOCTL | CDC_POST_IOCTL | CDC_DRIVE_STATUS, /* capability */ 0, /* number of minor devices */ }; @@ -238,6 +242,21 @@ if (ints[0] > 2) mitsumi_bug_93_wait = ints[3]; #endif /* WORK_AROUND_MITSUMI_BUG_93 */ +} + + +static +int mcd_pre_ioctl(struct cdrom_device_info * cdi) +{ + MOD_INC_USE_COUNT; + return 0; +} + +static +int mcd_post_ioctl(struct cdrom_device_info * cdi) +{ + MOD_DEC_USE_COUNT; + return 0; } diff --unified --new-file --recursive linux-2.1.105.virgin/drivers/cdrom/mcdx.c linux/drivers/cdrom/mcdx.c --- linux-2.1.105.virgin/drivers/cdrom/mcdx.c Sat Feb 28 09:19:51 1998 +++ linux/drivers/cdrom/mcdx.c Mon Jun 8 22:36:24 1998 @@ -228,6 +228,8 @@ static int mcdx_lockdoor(struct cdrom_device_info * cdi, int lock); static int mcdx_audio_ioctl(struct cdrom_device_info * cdi, unsigned int cmd, void * arg); +static int mcdx_pre_ioctl(struct cdrom_device_info * cdi); +static int mcdx_post_ioctl(struct cdrom_device_info * cdi); /* misc internal support functions */ static void log2msf(unsigned int, struct cdrom_msf0*); @@ -285,8 +287,10 @@ NULL, /* hard reset */ mcdx_audio_ioctl, /* audio ioctl */ NULL, /* device-specific ioctl */ + mcdx_pre_ioctl, /* called before each ioctl call */ + mcdx_post_ioctl, /* called after each ioctl call */ CDC_OPEN_TRAY | CDC_LOCK | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO - | CDC_DRIVE_STATUS, /* capability */ + | CDC_PRE_IOCTL | CDC_POST_IOCTL | CDC_DRIVE_STATUS, /* capability */ 0, /* number of minor devices */ }; @@ -751,6 +755,21 @@ MOD_DEC_USE_COUNT; } + +static int +mcdx_pre_ioctl(struct cdrom_device_info * cdi) +{ + MOD_INC_USE_COUNT; + return 0; +} + +static int +mcdx_post_ioctl(struct cdrom_device_info * cdi) +{ + MOD_DEC_USE_COUNT; + return 0; +} + static int mcdx_media_changed(struct cdrom_device_info * cdi, int disc_nr) /* Return: 1 if media changed since last call to this function diff --unified --new-file --recursive linux-2.1.105.virgin/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c --- linux-2.1.105.virgin/drivers/cdrom/sbpcd.c Sat Jun 6 22:05:02 1998 +++ linux/drivers/cdrom/sbpcd.c Mon Jun 8 22:18:21 1998 @@ -2054,6 +2054,19 @@ return (0); } +static int sbpcd_pre_ioctl(struct cdrom_device_info *cdi) +{ + if (!st_spinning) cc_SpinUp(); + MOD_INC_USE_COUNT; + return 0; +} + +static int sbpcd_post_ioctl(struct cdrom_device_info *cdi) +{ + MOD_DEC_USE_COUNT; + return 0; +} + static int sbpcd_reset(struct cdrom_device_info *cdi) { int i = MINOR(cdi->dev); @@ -5410,8 +5423,11 @@ sbpcd_reset, /* hard reset */ sbpcd_audio_ioctl, /* audio ioctl */ sbpcd_dev_ioctl, /* device-specific ioctl */ + sbpcd_pre_ioctl, /* called before each ioctl call */ + sbpcd_post_ioctl, /* called after each ioctl call */ CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_MULTI_SESSION | - CDC_MEDIA_CHANGED | CDC_MCN | CDC_PLAY_AUDIO | CDC_IOCTLS, /* capability */ + CDC_MEDIA_CHANGED | CDC_MCN | CDC_PLAY_AUDIO | CDC_IOCTLS | + CDC_PRE_IOCTL | CDC_POST_IOCTL, /* capability */ 1, /* number of minor devices */ }; diff --unified --new-file --recursive linux-2.1.105.virgin/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- linux-2.1.105.virgin/drivers/scsi/sr.c Sat May 16 09:00:18 1998 +++ linux/drivers/scsi/sr.c Mon Jun 8 22:24:22 1998 @@ -98,9 +98,12 @@ sr_reset, /* hard reset */ sr_audio_ioctl, /* audio ioctl */ sr_dev_ioctl, /* device-specific ioctl */ - CDC_CLOSE_TRAY | CDC_OPEN_TRAY| CDC_LOCK | CDC_SELECT_SPEED | + sr_pre_ioctl, /* called before each ioctl call */ + sr_post_ioctl, /* called after each ioctl call */ + CDC_CLOSE_TRAY | CDC_OPEN_TRAY| CDC_LOCK | CDC_SELECT_SPEED | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | - CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS, + CDC_RESET | CDC_IOCTLS | CDC_PRE_IOCTL | CDC_POST_IOCTL | + CDC_DRIVE_STATUS, 0 }; @@ -378,6 +381,18 @@ SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors); requeue_sr_request(SCpnt); } +} + +int sr_pre_ioctl(struct cdrom_device_info *cdi) +{ + MOD_INC_USE_COUNT; + return 0; +} + +int sr_post_ioctl(struct cdrom_device_info *cdi) +{ + MOD_DEC_USE_COUNT; + return 0; } static int sr_open(struct cdrom_device_info *cdi, int purpose) diff --unified --new-file --recursive linux-2.1.105.virgin/drivers/scsi/sr.h linux/drivers/scsi/sr.h --- linux-2.1.105.virgin/drivers/scsi/sr.h Mon Nov 3 10:49:42 1997 +++ linux/drivers/scsi/sr.h Mon Jun 8 22:21:47 1998 @@ -52,6 +52,8 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed); int sr_audio_ioctl(struct cdrom_device_info*, unsigned int, void*); int sr_dev_ioctl(struct cdrom_device_info*, unsigned int, unsigned long); +int sr_pre_ioctl(struct cdrom_device_info *cdi); +int sr_post_ioctl(struct cdrom_device_info *cdi); int sr_read_sector(int minor, int lba, int blksize, unsigned char *dest); int sr_is_xa(int minor); diff --unified --new-file --recursive linux-2.1.105.virgin/include/linux/cdrom.h linux/include/linux/cdrom.h --- linux-2.1.105.virgin/include/linux/cdrom.h Mon Jan 5 01:06:26 1998 +++ linux/include/linux/cdrom.h Thu Jun 11 00:04:03 1998 @@ -225,7 +225,7 @@ /* This struct is used with the CDROM_GET_MCN ioctl. * Very few audio discs actually have Universal Product Code information, * which should just be the Medium Catalog Number on the box. Also note - * that the way the codeis written on CD is _not_ uniform across all discs! + * that the way the code is written on CD is _not_ uniform across all discs! */ struct cdrom_mcn { @@ -309,7 +309,7 @@ /* The leadout track is always 0xAA, regardless of # of tracks on disc */ #define CDROM_LEADOUT 0xAA -/* audio states (from SCSI-2, but seen with other drives, too) */ +/* audio states (from SCSI-2, but used with Uniform interface and others) */ #define CDROM_AUDIO_INVALID 0x00 /* audio status not supported */ #define CDROM_AUDIO_PLAY 0x11 /* audio play operation in progress */ #define CDROM_AUDIO_PAUSED 0x12 /* audio play operation paused */ @@ -317,14 +317,6 @@ #define CDROM_AUDIO_ERROR 0x14 /* audio play stopped due to error */ #define CDROM_AUDIO_NO_STATUS 0x15 /* no current audio status to return */ -/* CD-ROM-specific SCSI command opcodes */ -#define SCMD_READ_TOC 0x43 /* read table of contents */ -#define SCMD_PLAYAUDIO_MSF 0x47 /* play data at time offset */ -#define SCMD_PLAYAUDIO_TI 0x48 /* play data at track/index */ -#define SCMD_PAUSE_RESUME 0x4B /* pause/resume audio */ -#define SCMD_READ_SUBCHANNEL 0x42 /* read SC info on playing disc */ -#define SCMD_PLAYAUDIO10 0x45 /* play data at logical block */ - /* capability flags used with the uniform CD-ROM driver */ #define CDC_CLOSE_TRAY 0x1 /* caddy systems _can't_ close */ #define CDC_OPEN_TRAY 0x2 /* but _can_ eject. */ @@ -338,6 +330,8 @@ #define CDC_RESET 0x200 /* hard reset device */ #define CDC_IOCTLS 0x400 /* driver has non-standard ioctls */ #define CDC_DRIVE_STATUS 0x800 /* driver implements drive status */ +#define CDC_PRE_IOCTL 0x1000 /* pre-ioctl callback */ +#define CDC_POST_IOCTL 0x2000 /* post-ioctl callback */ /* drive status possibilities used with the uniform CD-ROM driver */ #define CDS_NO_INFO 0 /* if not implemented */ @@ -365,7 +359,18 @@ #define CDSL_NONE ((int) (~0U>>1)-1) #define CDSL_CURRENT ((int) (~0U>>1)) + +/* From here on are kernel-only things that user space apps will not need */ #ifdef __KERNEL__ + + /* CD-ROM-specific SCSI command opcodes -- used by ide-cd and scsi */ +#define SCMD_READ_TOC 0x43 /* read table of contents */ +#define SCMD_PLAYAUDIO_MSF 0x47 /* play data at time offset */ +#define SCMD_PLAYAUDIO_TI 0x48 /* play data at track/index */ +#define SCMD_PAUSE_RESUME 0x4B /* pause/resume audio */ +#define SCMD_READ_SUBCHANNEL 0x42 /* read SC info on playing disc */ +#define SCMD_PLAYAUDIO10 0x45 /* play data at logical block */ + /* Uniform cdrom data structures for cdrom.c */ struct cdrom_device_info { struct cdrom_device_ops *ops; /* link to device_ops */ @@ -405,6 +410,10 @@ /* dev-specific */ int (*dev_ioctl) (struct cdrom_device_info *, unsigned int, unsigned long); + /* pre-ioctl callback */ + int (*pre_ioctl) (struct cdrom_device_info *); + /* post-ioctl callback */ + int (*post_ioctl) (struct cdrom_device_info *); /* driver specifications */ const int capability; /* capability flags */ int n_minors; /* number of active minor devices */ diff --unified --new-file --recursive linux-2.1.105.virgin/init/main.c linux/init/main.c --- linux-2.1.105.virgin/init/main.c Sun Jun 7 15:34:17 1998 +++ linux/init/main.c Tue Jun 9 22:30:35 1998 @@ -157,6 +157,7 @@ extern void sound_setup(char *str, int *ints); extern void reboot_setup(char *str, int *ints); extern void video_setup(char *str, int *ints); +extern void cdrom_setup(char *str, int *ints); #ifdef CONFIG_CDU31A extern void cdu31a_setup(char *str, int *ints); #endif CONFIG_CDU31A @@ -667,6 +668,9 @@ #ifdef CONFIG_ISP16_CDI { "isp16=", isp16_setup }, #endif CONFIG_ISP16_CDI +#ifdef ( CONFIG_CDU31A | CONFIG_MCD | CONFIG_MCDX | CONFIG_SBPCD | CONFIG_CM206 | CONFIG_BLK_DEV_SR | CONFIG_BLK_DEV_IDECD ) + { "cdrom=", cdrom_setup }, +#endif #ifdef CONFIG_SOUND { "sound=", sound_setup }, #endif
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu