summaryrefslogtreecommitdiffstats
path: root/sys/i386/isa/matcd/matcd.c
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1995-09-28 13:15:49 +0000
committerjkh <jkh@FreeBSD.org>1995-09-28 13:15:49 +0000
commit698228783ee0e374da6c624d8f74a219b957632f (patch)
tree456cbf24f2fc15941a7b0980047f319dcab8496e /sys/i386/isa/matcd/matcd.c
parent978778a652020785842868727a71407b9618cf19 (diff)
downloadFreeBSD-src-698228783ee0e374da6c624d8f74a219b957632f.zip
FreeBSD-src-698228783ee0e374da6c624d8f74a219b957632f.tar.gz
o Support for CDIOCPREVENT and CDIOCALLOW ioctls that xcdplayer
were making and were no-brainers. However, the xcdplayer eject button didn't work because xcdplayer gave up and didn't bother to try the EJECT ioctl anyway when CDIOCALLOW was not available. This all works now. o A change so that xcdplayer gets TOC entry data for the lead-out area on the disc. Xcdplayer can now play the last track on a CD, which it would not do in earlier versions (but no one reported). Cdplayer gets the TOC data differently and it works in old and new versions. o Eliminated a race condition that caused the driver to sleep forever on very slow and heavily loaded systems on rare occasions when the system was doing lots of audio-related ioctls to the drive. o Fixed a problem where a locked drive could be unlocked by accessing one of the non-locking devs. Door locking now follows the documented rules. o Made all wait channel strings unique to matcd. Submitted by: Frank Durda IV <uhclem%nemesis@fw.ast.com>
Diffstat (limited to 'sys/i386/isa/matcd/matcd.c')
-rw-r--r--sys/i386/isa/matcd/matcd.c182
1 files changed, 132 insertions, 50 deletions
diff --git a/sys/i386/isa/matcd/matcd.c b/sys/i386/isa/matcd/matcd.c
index 665462e..e042f8f 100644
--- a/sys/i386/isa/matcd/matcd.c
+++ b/sys/i386/isa/matcd/matcd.c
@@ -269,10 +269,55 @@ Edit number code marking begins here - earlier edits were during development.
assuming both host adapter types is not significant.
4-Jul-95 Frank Durda IV bsdmail@nemesis.lonestar.org
+<22> Four external interface prototypes were altered by someone else.
+ I believe these changes are for making GCC and/or the linker shut-up
+ when building some other part of the system since matcd already
+ compiles -Wall with no warnings...
+ 8-Sep-95 Frank Durda IV bsdmail@nemesis.lonestar.org
+
+<23> This change implements the ioctls for preventing media removal
+ and allowing media removal.
+ Currently, these calls will work according to the following rules:
+ No "l" devs opened Any "l" dev open
+ CDALLOW accepted always rejected always
+ CDPREVENT accepted always accepted always
+
+ One refinement might be to allow CDALLOW/CDPREVENT to always
+ work if UID 0 issued the ioctl, but that will wait for later.
+
+ I also made a change to the information that the toc_entry code
+ returns so that xcdplayer won't malfunction. (It would not play
+ the last track on a non-mixed mode audio CD.) Unlike cdplayer,
+ xcdplayer asks for track information one track at a time, and
+ calls for information on the lead-out track by its official
+ number (0xaa), rather than referring to the "after last" (n+1) track
+ as cdplayer does. Anyway, this change should make both players
+ happy.
+ 16-Sep-95 Frank Durda IV bsdmail@nemesis.lonestar.org
+
+<24> In Edit 15 when the extra devs were created for selective locking,
+ the door locking was broken if a non-locking dev on the drive is
+ closed. The problem was caused by not tracking locked devs and
+ non-locking devs as being different partitions. The change is to
+ simply use the locking dev bit to flag a set of shadow partitions
+ when it comes to lock operations. All other operations treat the
+ locked and unlocked partitions as being identical.
+ 18-Sep-95 Frank Durda IV bsdmail@nemesis.lonestar.org
+
+<25> During work on Edit 23, I noted that on slow and very busy systems,
+ sometimes the driver would go to sleep forever. The problem appears
+ to have been a race condition caused by doing separate timeout/sleep
+ calls without using SPL first. The change here is to use tsleep
+ which provides the equivalent of timeout/sleep timeout/tsleep if the
+ last paremeter is tsleep is set to the time value that would have been
+ given to timeout.
+ I also fixed some duplicate location strings in the tsleep calls.
+ 24-Sep-95 Frank Durda IV bsdmail@nemesis.lonestar.org
+
---------------------------------------------------------------------------*/
/*Match this format: Version_dc(d)__dd-mmm-yy */
-static char MATCDVERSION[]="Version 1(21) 4-Jul-95";
+static char MATCDVERSION[]="Version 1(25) 18-Sep-95";
/* The following strings may not be changed*/
static char MATCDCOPYRIGHT[] = "Matsushita CD-ROM driver, Copr. 1994,1995 Frank Durda IV";
@@ -455,7 +500,7 @@ static struct kern_devconf kdc_matcd[TOTALDRIVES] = { { /*<12>*/
#define matcd_cdrive(dev) (((minor(dev)) & 0x18) >> 3)
#define matcd_controller(dev) (((minor(dev)) & 0x60) >> 5)
#ifdef LOCKDRIVE /*<15>*/
-#define matcd_lockable(dev) ((minor(dev)) & 0x80) /*<15>*/
+#define matcd_lockable(dev) (((minor(dev)) & 0x80) >> 5)/*<24>*/
#endif /*LOCKDRIVE*/ /*<15>*/
@@ -477,10 +522,14 @@ static struct kern_devconf kdc_matcd[TOTALDRIVES] = { { /*<12>*/
Entry points and other connections to/from kernel - see conf.c
---------------------------------------------------------------------------*/
- int matcdopen(dev_t dev, int flags, int fmt, struct proc *p);
- int matcdclose(dev_t dev, int flags, int fmt, struct proc *p);
+ int matcdopen(dev_t dev, int flags, /*<22>*/
+ int fmt, struct proc *p); /*<22>*/
+ int matcdclose(dev_t dev, int flags, /*<22>*/
+ int fmt, struct proc *p); /*<22>*/
void matcdstrategy(struct buf *bp);
- int matcdioctl(dev_t dev, int command, caddr_t addr, int flags, struct proc *p);
+ int matcdioctl(dev_t dev, int command, /*<22>*/
+ caddr_t addr, int flags, /*<22>*/
+ struct proc *p); /*<22>*/
int matcdsize(dev_t dev);
extern int hz;
extern int matcd_probe(struct isa_device *dev);
@@ -504,7 +553,6 @@ static void matcd_blockread(int state);
static void selectdrive(int port,int drive);
static void doreset(int port,int cdrive);
static int doprobe(int port,int cdrive);
-static void watchdog(int state, char * foo);
static void lockbus(int controller, int ldrive);
static void unlockbus(int controller, int ldrive);
static int matcd_volinfo(int ldrive);
@@ -544,6 +592,8 @@ static int media_chk(struct matcd_data *cd,int errnum,
int ldrive,int test); /*<14>*/
static int matcd_eject(int ldrive, int cdrive, int controller);/*<14>*/
static int matcd_doorclose(int ldrive, int cdrive, int controller);/*<16>*/
+static int matcd_dlock(int ldrive, int cdrive, /*<23>*/
+ int controller, int action); /*<23>*/
static int docmd(char * cmd, int ldrive, int cdrive, /*<14>*/
int controller, int port); /*<14>*/
@@ -558,9 +608,10 @@ static int docmd(char * cmd, int ldrive, int cdrive, /*<14>*/
<15> If LOCKDRIVE is enabled, additional minor number devices allow
<15> the drive to be locked while being accessed.
---------------------------------------------------------------------------*/
-int matcdopen(dev_t dev, int flags, int fmt, struct proc *p)
+int matcdopen(dev_t dev, int flags, int fmt, /*<22>*/
+ struct proc *p) /*<22>*/
{
- int cdrive,ldrive,partition,controller;
+ int cdrive,ldrive,partition,controller,lock; /*<24>*/
struct matcd_data *cd;
int i,z,port; /*<14>*/
unsigned char cmd[MAXCMDSIZ];
@@ -576,6 +627,7 @@ int matcdopen(dev_t dev, int flags, int fmt, struct proc *p)
cdrive=matcd_cdrive(dev);
partition=matcd_partition(dev);
controller=matcd_controller(dev);
+ lock=matcd_lockable(dev); /*<24>*/
cd= &matcd_data[ldrive];
port=cd->iobase; /*and port#*/
@@ -605,7 +657,7 @@ int matcdopen(dev_t dev, int flags, int fmt, struct proc *p)
zero_cmd(cmd);
cmd[0]=NOP; /*Test drive*/
matcd_slowcmd(port,ldrive,cdrive,cmd);
- i=waitforit(10*TICKRES,DTEN,port,"matcdopen");
+ i=waitforit(10*TICKRES,DTEN,port,"matopen");
z=get_stat(port,ldrive); /*Read status byte*/
#ifdef DEBUGOPEN
printf("matcd%d Result of NOP is %x %x\n",ldrive,i,z); /*<16>*/
@@ -711,7 +763,7 @@ int matcdopen(dev_t dev, int flags, int fmt, struct proc *p)
#endif /*DEBUGOPEN*/
#ifdef LOCKDRIVE /*<15>*/
- if (cd->openflags==0 && matcd_lockable(dev)) { /*<15>*/
+ if (cd->openflags==0 && lock) { /*<24>*/
zero_cmd(cmd);
cmd[0]=LOCK; /*Lock drive*/
cmd[1]=1;
@@ -719,7 +771,7 @@ int matcdopen(dev_t dev, int flags, int fmt, struct proc *p)
cd->flags |= MATCDLOCK; /*<15>Drive is now locked*/
}
#endif /*LOCKDRIVE*/
- cd->openflags |= (1<<partition);/*Mark partition open*/
+ cd->openflags |= (1<<(partition+lock));/*<24>Mark partition open*/
if (partition==RAW_PART ||
(partition < cd->dlabel.d_npartitions &&
@@ -729,7 +781,8 @@ int matcdopen(dev_t dev, int flags, int fmt, struct proc *p)
cd->partflags[partition] |= MATCDREADRAW;
}
#ifdef DEBUGOPEN
- printf("matcd%d: Open is complete\n",ldrive);
+ printf("matcd%d: Open is complete - openflags %x\n",
+ ldrive,cd->openflags);
#endif /*DEBUGOPEN*/
return(0);
}
@@ -751,9 +804,10 @@ int matcdopen(dev_t dev, int flags, int fmt, struct proc *p)
<15> the drive.
---------------------------------------------------------------------------*/
-int matcdclose(dev_t dev, int flags, int fmt, struct proc *p)
+int matcdclose(dev_t dev, int flags, int fmt, /*<22>*/
+ struct proc *p) /*<22>*/
{
- int ldrive,cdrive,port,partition,controller;
+ int ldrive,cdrive,port,partition,controller,lock; /*<24>*/
struct matcd_data *cd;
#ifdef LOCKDRIVE
unsigned char cmd[MAXCMDSIZ];
@@ -761,6 +815,7 @@ int matcdclose(dev_t dev, int flags, int fmt, struct proc *p)
ldrive=matcd_ldrive(dev);
cdrive=matcd_cdrive(dev);
+ lock=matcd_lockable(dev); /*<24>*/
cd=matcd_data+ldrive;
port=cd->iobase; /*and port#*/
@@ -773,22 +828,27 @@ int matcdclose(dev_t dev, int flags, int fmt, struct proc *p)
partition = matcd_partition(dev);
controller=matcd_controller(dev);
#ifdef DEBUGOPEN
- printf("matcd%d: Close partition=%d\n", ldrive, partition);
+ printf("matcd%d: Close partition=%d flags %x openflags %x partflags %x\n",
+ ldrive,partition,cd->flags,cd->openflags,
+ cd->partflags[partition]);
#endif /*DEBUGOPEN*/
if (!(cd->flags & MATCDINIT))
return(ENXIO);
cd->partflags[partition] &= ~(MATCDOPEN|MATCDREADRAW);
- cd->openflags &= ~(1<<partition);
+ cd->openflags &= ~(1<<(partition+lock));
+ if (cd->openflags==0) { /*<24>Really last close?*/
#ifdef LOCKDRIVE
- if (cd->openflags==0 && (cd->flags & MATCDLOCK)) { /*<15>*/
- zero_cmd(cmd);
- cmd[0]=LOCK; /*Unlock drive*/
- docmd(cmd,ldrive,cdrive,controller,port);/*<14>Issue cmd*/
- }
+ if (cd->flags & MATCDLOCK) { /*<24>Was drive locked?*/
+ zero_cmd(cmd); /*Yes, so unlock it*/
+ cmd[0]=LOCK; /*Unlock drive*/
+ docmd(cmd,ldrive,cdrive,controller,port);
+ }
#endif /*LOCKDRIVE*/
- cd->flags &= ~(MATCDWARN|MATCDLOCK); /*<15>Clear any warning flag*/
+ cd->flags &= ~(MATCDWARN|MATCDLOCK); /*<15>*/
+ /*<15>Clear warning flag*/
+ }
return(0);
}
@@ -960,7 +1020,8 @@ static void matcd_start(struct buf *dp)
things that don't fit into the block read scheme of things.
---------------------------------------------------------------------------*/
-int matcdioctl(dev_t dev, int command, caddr_t addr, int flags, struct proc *p)
+int matcdioctl(dev_t dev, int command, caddr_t addr, /*<22>*/
+ int flags, struct proc *p) /*<22>*/
{
struct matcd_data *cd;
int ldrive,cdrive,partition;
@@ -1024,6 +1085,14 @@ int matcdioctl(dev_t dev, int command, caddr_t addr, int flags, struct proc *p)
case CDIOCEJECT:
return(matcd_eject(ldrive, cdrive, controller));
+ case CDIOCALLOW: /*<23>*/
+ return(matcd_dlock(ldrive, cdrive, /*<23>*/
+ controller,0)); /*<23>*/
+
+ case CDIOCPREVENT: /*<23>*/
+ return(matcd_dlock(ldrive, cdrive, /*<23>*/
+ controller, MATCDLOCK)); /*<23>*/
+
#ifdef FULLDRIVER
case CDIOCPLAYTRACKS:
return(matcd_playtracks(ldrive, cdrive, controller,
@@ -1741,7 +1810,7 @@ static int matcd_volinfo(int ldrive)
zero_cmd(cmd);
cmd[0]=READDINFO; /*Read Disc Info*/
matcd_slowcmd(port,ldrive,cdrive,cmd);
- i=waitforit(10*TICKRES,DTEN,port,"volinfo");
+ i=waitforit(10*TICKRES,DTEN,port,"matvinf");
if (i) { /*THIS SHOULD NOT HAPPEN*/
z=get_stat(port,ldrive);/*Read status byte*/
printf("matcd%d: command failed, status %x\n",
@@ -1769,8 +1838,7 @@ static int matcd_volinfo(int ldrive)
#endif /*DEBUGOPEN*/
return(-1);
}
- timeout((timeout_func_t)watchdog, (caddr_t)0,hz);/*<16>*/
- tsleep((caddr_t)&nextcontroller, PRIBIO, "volinfo2", 0);/*<16>*/
+ tsleep((caddr_t)&nextcontroller, PRIBIO, "matvi2", hz);/*<25>*/
if ((--retry)==0) return(-1);
#ifdef DEBUGOPEN
printf("matcd%d: Retrying",ldrive);
@@ -2083,7 +2151,7 @@ int docmd(char * cmd, int ldrive, int cdrive, int controller, int port)
DIAGOUT(DIAGPORT,0xD0); /*Show where we are*/
#endif /*DIAGPORT*/
matcd_slowcmd(port,ldrive,cdrive,cmd);
- i=waitforit(80*TICKRES,DTEN,port,"cmd");
+ i=waitforit(80*TICKRES,DTEN,port,"matcmd"); /*<25>*/
z=get_stat(port,ldrive);/*Read status byte*/
if ((z & MATCD_ST_ERROR)==0) break;
i=chk_error(get_error(port,ldrive,cdrive));
@@ -2240,8 +2308,7 @@ int waitforit(int timelimit, int state, int port, char * where)
while (i<timelimit) {
j=inb(port+STATUS) & (STEN|DTEN); /*Read status*/
if (j!=(STEN|DTEN)) break;
- timeout((timeout_func_t)watchdog, (caddr_t)0,hz/100);
- tsleep((caddr_t)&nextcontroller, PRIBIO, where, 0);
+ tsleep((caddr_t)&nextcontroller, PRIBIO, where, hz/100);/*<25>*/
i++;
#ifdef DIAGPORT
DIAGOUT(DIAGPORT,0xE1+(diagloop++ * 0x100)); /*Show where we are*/
@@ -2259,20 +2326,6 @@ int waitforit(int timelimit, int state, int port, char * where)
/*---------------------------------------------------------------------------
- watchdog - Gives us a heartbeat for things we are waiting on
----------------------------------------------------------------------------*/
-
-static void watchdog(int state, char * foo)
-{
-#ifdef DIAGPORT
- DIAGOUT(DIAGPORT,0xF0); /*Show where we are*/
-#endif /*DIAGPORT*/
- wakeup((caddr_t)&nextcontroller);
- return;
-}
-
-
-/*---------------------------------------------------------------------------
lockbus - Wait for the bus on the requested driver interface
to go idle and acquire it.
Created in Edit 6
@@ -2289,7 +2342,7 @@ void lockbus(int controller, int ldrive)
DIAGOUT(DIAGPORT,0xF1); /*Show where we are*/
#endif /*DIAGPORT*/
tsleep((caddr_t)&matcd_data->status, PRIBIO,
- "matcdopen", 0);
+ "matlck", 0); /*<25>*/
}
if_state[controller] |= BUSBUSY; /*<18>It's ours NOW*/
#ifdef DIAGPORT
@@ -2394,13 +2447,40 @@ int matcd_doorclose(int ldrive, int cdrive, int controller)
cmd[0]=DOORCLOSE; /*Open Door*/
i=docmd(cmd,ldrive,cdrive,controller,port); /*Issue command*/
cd->flags &= ~(MATCDLABEL|MATCDLOCK); /*Mark vol info invalid*/
- timeout((timeout_func_t)watchdog, (caddr_t)0,hz);
- tsleep((caddr_t)&nextcontroller, PRIBIO, "doorclose", 0);
+ tsleep((caddr_t)&nextcontroller, PRIBIO, "matclos", hz);/*<25>*/
return(i); /*Return result we got*/
}
/*---------------------------------------------------------------------------
+<23> matcd_dlock - Honor/Reject drive tray requests
+---------------------------------------------------------------------------*/
+
+int matcd_dlock(int ldrive, int cdrive, int controller, int action)
+{
+ int i,port; /*<23>*/
+ struct matcd_data *cd; /*<23>*/
+ unsigned char cmd[MAXCMDSIZ]; /*<23>*/
+
+ cd=&matcd_data[ldrive]; /*<23>*/
+ port=cd->iobase; /*<23>Get I/O port base*/
+
+ zero_cmd(cmd); /*<23>Initialize command buffer*/
+ cmd[0]=LOCK; /*<23>Unlock drive*/
+
+ if (action) { /*<23>They want to lock the door?*/
+ cd->flags |= MATCDLOCK; /*<23>Remember we did this*/
+ cmd[1]=1; /*<23>Lock Door command*/
+ } else { /*<23>*/
+ cd->flags &= ~MATCDLOCK;/*<23>Remember we did this*/
+ /*<23>Unlock Door command*/
+ } /*<23>*/
+ i=docmd(cmd,ldrive,cdrive,controller,port); /*<23>Issue command*/
+ return(i); /*<23>Return result we got*/
+} /*<23>*/
+
+
+/*---------------------------------------------------------------------------
matcd_toc_header - Return Table of Contents header to caller
<13> New for Edit 13
---------------------------------------------------------------------------*/
@@ -2457,7 +2537,7 @@ static int matcd_toc_entries(int ldrive, int cdrive, int controller,
cmd[2]=trk+1;
lockbus(controller, ldrive); /*Request bus*/
matcd_slowcmd(port,ldrive,cdrive,cmd);
- i=waitforit(10*TICKRES,DTEN,port,"sense");
+ i=waitforit(10*TICKRES,DTEN,port,"mats1"); /*<25>*/
matcd_pread(port, 8, data); /*Read data returned*/
z=get_stat(port,ldrive); /*Read status byte*/
if ((z & MATCD_ST_ERROR)) { /*Something went wrong*/
@@ -2483,7 +2563,7 @@ static int matcd_toc_entries(int ldrive, int cdrive, int controller,
}
}
entries[trk].control=data[2]; /*Copy from last valid track*/
- entries[trk].track=0xaa; /*Lead-out*/
+ entries[trk].track=0xaa; /*<23>Lead-out*/
entries[trk].addr.msf.unused=0; /*Fill*/
entries[trk].addr.msf.minute=cd->volinfo.vol_msf[0];
entries[trk].addr.msf.second=cd->volinfo.vol_msf[1];
@@ -2496,7 +2576,9 @@ static int matcd_toc_entries(int ldrive, int cdrive, int controller,
*/
len=ioc_entry->data_len; /*<17>*/
- i=ioc_entry->starting_track - 1;/*<17>*/
+ i=ioc_entry->starting_track; /*<23>What did they want?*/
+ if (i==0xaa) i=trk-1; /*<23>Give them lead-out info*/
+ else i=ioc_entry->starting_track - 1; /*<23>start where they asked*/
from = &entries[i]; /*<17>*/
to = ioc_entry->data; /*<17>*/
@@ -2557,7 +2639,7 @@ static int matcd_read_subq(int ldrive, int cdrive, int controller,
subq.what.position.absaddr.msf.unused=0;
subq.what.position.reladdr.msf.unused=0;
- i=waitforit(10*TICKRES,DTEN,port,"sense");
+ i=waitforit(10*TICKRES,DTEN,port,"mats2"); /*<25>*/
matcd_pread(port, 11, data); /*Read data returned*/
z=get_stat(port,ldrive); /*Read status byte*/
if ((z & MATCD_ST_ERROR)) { /*Something went wrong*/
OpenPOWER on IntegriCloud