mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-04 12:28:58 +00:00
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.
This commit is contained in:
parent
1df5695c0a
commit
f03cb6c766
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=427
179
sys/scsi/cd.c
179
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user