summaryrefslogtreecommitdiffstats
path: root/sys/scsi
diff options
context:
space:
mode:
authorrgrimes <rgrimes@FreeBSD.org>1993-09-09 07:18:52 +0000
committerrgrimes <rgrimes@FreeBSD.org>1993-09-09 07:18:52 +0000
commit9c6b6f08465215d466da01bb745faf3eef0cd483 (patch)
tree82970d64025c619e9a4ba15bc7b58d6dd07ee5a8 /sys/scsi
parente0b6b31115a3e81dc72795d3943af0cad5fd441a (diff)
downloadFreeBSD-src-9c6b6f08465215d466da01bb745faf3eef0cd483.zip
FreeBSD-src-9c6b6f08465215d466da01bb745faf3eef0cd483.tar.gz
The scsi cd.c driver is now fully dynamic. You can change the lines
in your config file from: device cd0 device cd1 ... device cdn to either device cd0 or psuedo-device cd0 The driver now dynamically allocates all per unit dependent structs, so it will never run out of units (okay, so now we need 32 bit device major/minor numbers!). It will allocate unit numbers as it needs them.
Diffstat (limited to 'sys/scsi')
-rw-r--r--sys/scsi/cd.c179
1 files changed, 116 insertions, 63 deletions
diff --git a/sys/scsi/cd.c b/sys/scsi/cd.c
index 030a192..6d6a3d4 100644
--- a/sys/scsi/cd.c
+++ b/sys/scsi/cd.c
@@ -14,7 +14,7 @@
*
* Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
*
- * $Id: cd.c,v 1.6 1993/08/28 03:08:49 rgrimes Exp $
+ * $Id: cd.c,v 1.7 1993/09/08 21:04:32 rgrimes Exp $
*/
#define SPLCD splbio
@@ -68,10 +68,6 @@ int cd_done();
int cdstrategy();
int cd_debug = 0;
-struct buf cd_buf_queue[NCD];
-struct scsi_xfer cd_scsi_xfer[NCD][CDOUTSTANDING]; /* XXX */
-struct scsi_xfer *cd_free_xfer[NCD];
-int cd_xfer_block_wait[NCD];
struct cd_data
{
@@ -94,12 +90,21 @@ struct cd_data
int partflags[MAXPARTITIONS]; /* per partition flags */
#define CDOPEN 0x01
int openparts; /* one bit for each open partition */
-}*cd_data[NCD];
+ int xfer_block_wait;
+ struct scsi_xfer *free_xfer;
+ struct scsi_xfer scsi_xfer[CDOUTSTANDING]; /* XXX */
+ struct buf buf_queue;
+};
#define CD_STOP 0
#define CD_START 1
#define CD_EJECT -2
+struct cd_driver
+{
+ int size;
+ struct cd_data **cd_data;
+}*cd_driver;
static int next_cd_unit = 0;
/***********************************************************************\
@@ -109,34 +114,77 @@ static int next_cd_unit = 0;
int cdattach(ctlr,targ,lu,scsi_switch)
struct scsi_switch *scsi_switch;
{
- int unit,i;
- unsigned char *tbl;
- struct cd_data *cd;
- struct cd_parms *dp;
+ int unit,i;
+ unsigned char *tbl;
+ struct cd_data *cd, **cdrealloc;
+ struct cd_parms *dp;
#ifdef CDDEBUG
if(scsi_debug & PRINTROUTINES) printf("cdattach: ");
#endif /*CDDEBUG*/
/*******************************************************\
- * Check we have the resources for another drive *
+ * Check if we have resources allocated yet, if not *
+ * allocate and initialize them *
+ \*******************************************************/
+ if (next_cd_unit == 0)
+ {
+ cd_driver =
+ malloc(sizeof(struct cd_driver),M_DEVBUF,M_NOWAIT);
+ if(!cd_driver)
+ {
+ printf("cd%d: malloc failed for cd_driver\n",unit);
+ return(0);
+ }
+ bzero(cd_driver,sizeof(cd_driver));
+ cd_driver->size = 0;
+ }
+ /*******************************************************\
+ * allocate the resources for another drive *
+ * if we have already allocate a cd_data pointer we must *
+ * copy the old pointers into a new region that is *
+ * larger and release the old region, aka realloc *
\*******************************************************/
unit = next_cd_unit++;
- if( unit >= NCD)
+ /* XXX
+ * This if will always be true for now, but future code may
+ * preallocate more units to reduce overhead. This would be
+ * done by changing the malloc to be (next_cd_unit * x) and
+ * the cd_driver->size++ to be +x
+ */
+ if(unit >= cd_driver->size)
{
- printf("Too many scsi CDs..(%d > %d) reconfigure kernel\n",
- (unit + 1),NCD);
- return(0);
+ cdrealloc =
+ malloc(sizeof(cd_driver->cd_data) * next_cd_unit,
+ M_DEVBUF,M_NOWAIT);
+ if(!cdrealloc)
+ {
+ printf("cd%d: malloc failed for cdrealloc\n",unit);
+ return(0);
+ }
+ /* Make sure we have something to copy before we copy it */
+ if(cd_driver->size)
+ {
+ bcopy(cd_driver->cd_data,cdrealloc,
+ sizeof(cd_driver->cd_data) * cd_driver->size);
+ free(cd_driver->cd_data,M_DEVBUF);
+ }
+ cd_driver->cd_data = cdrealloc;
+ cd_driver->cd_data[unit] = NULL;
+ cd_driver->size++;
}
- cd = cd_data[unit];
- if(cd_data[unit])
+ if(cd_driver->cd_data[unit])
{
printf("cd%d: Already has storage!\n",unit);
return(0);
}
- cd = cd_data[unit] = malloc(sizeof(struct cd_data),M_DEVBUF,M_NOWAIT);
+ /*******************************************************\
+ * allocate the per drive data area *
+ \*******************************************************/
+ cd = cd_driver->cd_data[unit] =
+ malloc(sizeof(struct cd_data),M_DEVBUF,M_NOWAIT);
if(!cd)
{
- printf("cd%d: malloc failed in cd.c\n",unit);
+ printf("cd%d: malloc failed for cd_data\n",unit);
return(0);
}
dp = &(cd->params);
@@ -152,8 +200,8 @@ struct scsi_switch *scsi_switch;
i = cd->cmdscount;
while(i-- )
{
- cd_scsi_xfer[unit][i].next = cd_free_xfer[unit];
- cd_free_xfer[unit] = &cd_scsi_xfer[unit][i];
+ cd->scsi_xfer[i].next = cd->free_xfer;
+ cd->free_xfer = &cd->scsi_xfer[i];
}
/*******************************************************\
* Use the subdriver to request information regarding *
@@ -171,11 +219,8 @@ struct scsi_switch *scsi_switch;
}
cd->flags |= CDINIT;
return;
-
}
-
-
/*******************************************************\
* open the device. Make sure the partition info *
* is a up-to-date as can be. *
@@ -193,16 +238,16 @@ cdopen(dev)
#ifdef CDDEBUG
if(scsi_debug & (PRINTROUTINES | TRACEOPENS))
printf("cdopen: dev=0x%x (unit %d (of %d),partition %d)\n"
- , dev, unit, NCD, part);
+ ,dev,unit,cd_driver->size,part);
#endif /*CDDEBUG*/
/*******************************************************\
* Check the unit is legal *
\*******************************************************/
- if ( unit >= NCD )
+ if ( unit >= cd_driver->size )
{
return(ENXIO);
}
- cd = cd_data[unit];
+ cd = cd_driver->cd_data[unit];
/*******************************************************\
* Make sure the device has been initialised *
\*******************************************************/
@@ -309,26 +354,28 @@ int flags;
int unit;
{
struct scsi_xfer *xs;
+ struct cd_data *cd;
int s;
+ cd = cd_driver->cd_data[unit];
if(flags & (SCSI_NOSLEEP | SCSI_NOMASK))
{
- if (xs = cd_free_xfer[unit])
+ if (xs = cd->free_xfer)
{
- cd_free_xfer[unit] = xs->next;
+ cd->free_xfer = xs->next;
xs->flags = 0;
}
}
else
{
s = SPLCD();
- while (!(xs = cd_free_xfer[unit]))
+ while (!(xs = cd->free_xfer))
{
- cd_xfer_block_wait[unit]++; /* someone waiting! */
- sleep((caddr_t)&cd_free_xfer[unit], PRIBIO+1);
- cd_xfer_block_wait[unit]--;
+ cd->xfer_block_wait++; /* someone waiting! */
+ sleep((caddr_t)&cd->free_xfer, PRIBIO+1);
+ cd->xfer_block_wait--;
}
- cd_free_xfer[unit] = xs->next;
+ cd->free_xfer = xs->next;
splx(s);
xs->flags = 0;
}
@@ -343,25 +390,27 @@ struct scsi_xfer *xs;
int unit;
int flags;
{
+ struct cd_data *cd;
int s;
+ cd = cd_driver->cd_data[unit];
if(flags & SCSI_NOMASK)
{
- if (cd_xfer_block_wait[unit])
+ if (cd->xfer_block_wait)
{
printf("cd%d: doing a wakeup from NOMASK mode\n", unit);
- wakeup((caddr_t)&cd_free_xfer[unit]);
+ wakeup((caddr_t)&cd->free_xfer);
}
- xs->next = cd_free_xfer[unit];
- cd_free_xfer[unit] = xs;
+ xs->next = cd->free_xfer;
+ cd->free_xfer = xs;
}
else
{
s = SPLCD();
- if (cd_xfer_block_wait[unit])
- wakeup((caddr_t)&cd_free_xfer[unit]);
- xs->next = cd_free_xfer[unit];
- cd_free_xfer[unit] = xs;
+ if (cd->xfer_block_wait)
+ wakeup((caddr_t)&cd->free_xfer);
+ xs->next = cd->free_xfer;
+ cd->free_xfer = xs;
splx(s);
}
}
@@ -376,7 +425,7 @@ int flags;
void cdminphys(bp)
struct buf *bp;
{
- (*(cd_data[UNIT(bp->b_dev)]->sc_sw->scsi_minphys))(bp);
+ (*(cd_driver->cd_data[UNIT(bp->b_dev)]->sc_sw->scsi_minphys))(bp);
}
/*******************************************************\
@@ -396,7 +445,7 @@ struct buf *bp;
cdstrats++;
unit = UNIT((bp->b_dev));
- cd = cd_data[unit];
+ cd = cd_driver->cd_data[unit];
#ifdef CDDEBUG
if(scsi_debug & PRINTROUTINES) printf("\ncdstrategy ");
if(scsi_debug & SHOWREQUESTS) printf("cd%d: %d bytes @ blk%d\n",
@@ -446,7 +495,7 @@ struct buf *bp;
}
opri = SPLCD();
- dp = &cd_buf_queue[unit];
+ dp = &cd->buf_queue;
/*******************************************************\
* Place it in the queue of disk activities for this disk*
@@ -497,28 +546,29 @@ int unit;
struct scsi_xfer *xs;
struct scsi_rw_big cmd;
int blkno, nblk;
- struct cd_data *cd = cd_data[unit];
+ struct cd_data *cd;
struct partition *p ;
#ifdef CDDEBUG
if(scsi_debug & PRINTROUTINES) printf("cdstart%d ",unit);
#endif /*CDDEBUG*/
+ cd = cd_driver->cd_data[unit];
/*******************************************************\
* See if there is a buf to do and we are not already *
* doing one *
\*******************************************************/
- if(!cd_free_xfer[unit])
+ if(!cd->free_xfer)
{
return; /* none for us, unit already underway */
}
- if(cd_xfer_block_wait[unit]) /* there is one, but a special waits */
+ if(cd->xfer_block_wait) /* there is one, but a special waits */
{
return; /* give the special that's waiting a chance to run */
}
- dp = &cd_buf_queue[unit];
+ dp = &cd->buf_queue;
if ((bp = dp->b_actf) != NULL) /* yes, an assign */
{
dp->b_actf = bp->av_forw;
@@ -607,10 +657,12 @@ struct scsi_xfer *xs;
{
struct buf *bp;
int retval;
+ struct cd_data *cd;
#ifdef CDDEBUG
if(scsi_debug & PRINTROUTINES) printf("cd_done%d ",unit);
#endif /*CDDEBUG*/
+ cd = cd_driver->cd_data[unit];
if (! (xs->flags & INUSE)) /* paranoia always pays off */
panic("scsi_xfer not in use!");
if(bp = xs->bp)
@@ -643,7 +695,7 @@ struct scsi_xfer *xs;
{
xs->error = XS_NOERROR;
xs->flags &= ~ITSDONE;
- if ( (*(cd_data[unit]->sc_sw->scsi_cmd))(xs)
+ if ((*(cd->sc_sw->scsi_cmd))(xs)
== SUCCESSFULLY_QUEUED)
{ /* shhh! don't wake the job, ok? */
/* don't tell cdstart either, */
@@ -686,7 +738,7 @@ cdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
\*******************************************************/
unit = UNIT(dev);
part = PARTITION(dev);
- cd = cd_data[unit];
+ cd = cd_driver->cd_data[unit];
#ifdef CDDEBUG
if(scsi_debug & PRINTROUTINES) printf("cdioctl%d ",unit);
#endif /*CDDEBUG*/
@@ -694,7 +746,7 @@ cdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
/*******************************************************\
* If the device is not valid.. abandon ship *
\*******************************************************/
- if (!(cd_data[unit]->flags & CDVALID))
+ if (!(cd_driver->cd_data[unit]->flags & CDVALID))
return(EIO);
switch(cmd)
{
@@ -998,8 +1050,9 @@ unsigned char unit;
/*unsigned int n, m;*/
char *errstring;
struct dos_partition *dos_partition_p;
- struct cd_data *cd = cd_data[unit];
+ struct cd_data *cd;
+ cd = cd_driver->cd_data[unit];
/*******************************************************\
* If the info is already loaded, use it *
\*******************************************************/
@@ -1083,8 +1136,8 @@ cd_size(unit, flags)
#ifdef CDDEBUG
if(cd_debug)printf("cd%d: %d %d byte blocks\n",unit,size,blksize);
#endif /*CDDEBUG*/
- cd_data[unit]->params.disksize = size;
- cd_data[unit]->params.blksize = blksize;
+ cd_driver->cd_data[unit]->params.disksize = size;
+ cd_driver->cd_data[unit]->params.blksize = blksize;
return(size);
}
@@ -1301,7 +1354,7 @@ cd_start_unit(unit,part,type)
{
struct scsi_start_stop scsi_cmd;
- if(type==CD_EJECT && (cd_data[unit]->openparts&~(1<<part)) == 0 ) {
+ if(type==CD_EJECT && (cd_driver->cd_data[unit]->openparts&~(1<<part)) == 0 ) {
cd_prevent_unit(unit,CD_EJECT,0);
}
@@ -1329,7 +1382,7 @@ int unit,type,flags;
{
struct scsi_prevent scsi_cmd;
- if(type==CD_EJECT || type==PR_PREVENT || cd_data[unit]->openparts == 0 ) {
+ if(type==CD_EJECT || type==PR_PREVENT || cd_driver->cd_data[unit]->openparts == 0 ) {
bzero(&scsi_cmd, sizeof(scsi_cmd));
scsi_cmd.op_code = PREVENT_ALLOW;
scsi_cmd.how = (type==CD_EJECT)?PR_ALLOW:type;
@@ -1422,7 +1475,7 @@ struct cd_toc_entry *data;
int cd_get_parms(unit, flags)
{
- struct cd_data *cd = cd_data[unit];
+ struct cd_data *cd = cd_driver->cd_data[unit];
/*******************************************************\
* First check if we have it all loaded *
@@ -1459,8 +1512,8 @@ dev_t dev;
if(scsi_debug & TRACEOPENS)
printf("cd%d: closing part %d\n",unit,part);
#endif
- cd_data[unit]->partflags[part] &= ~CDOPEN;
- cd_data[unit]->openparts &= ~(1 << part);
+ cd_driver->cd_data[unit]->partflags[part] &= ~CDOPEN;
+ cd_driver->cd_data[unit]->openparts &= ~(1 << part);
cd_prevent_unit(unit,PR_ALLOW,SCSI_SILENT);
return(0);
}
@@ -1486,7 +1539,7 @@ int datalen;
struct scsi_xfer *xs;
int retval;
int s;
- struct cd_data *cd = cd_data[unit];
+ struct cd_data *cd = cd_driver->cd_data[unit];
#ifdef CDDEBUG
if(scsi_debug & PRINTROUTINES) printf("\ncd_scsi_cmd%d ",unit);
@@ -1660,8 +1713,8 @@ struct scsi_xfer *xs;
return(EINVAL);
case 0x6:
if(!silent)printf("cd%d: Unit attention\n", unit);
- if (cd_data[unit]->openparts)
- cd_data[unit]->flags &= ~(CDVALID | CDHAVELABEL);
+ if (cd_driver->cd_data[unit]->openparts)
+ cd_driver->cd_data[unit]->flags &= ~(CDVALID | CDHAVELABEL);
{
return(EIO);
}
OpenPOWER on IntegriCloud