summaryrefslogtreecommitdiffstats
path: root/sys/scsi
diff options
context:
space:
mode:
authordufault <dufault@FreeBSD.org>1995-03-01 22:24:47 +0000
committerdufault <dufault@FreeBSD.org>1995-03-01 22:24:47 +0000
commitc022092526531e80e9b53415fd187a53dff3bade (patch)
tree8158f942cd0116a4705af957aa3471bb2b19d72f /sys/scsi
parentbeac11b74f9d02eab450b4902b573368f816e565 (diff)
downloadFreeBSD-src-c022092526531e80e9b53415fd187a53dff3bade.zip
FreeBSD-src-c022092526531e80e9b53415fd187a53dff3bade.tar.gz
Reviewed by: gibbs@freefall.cdrom.com julian@freefall.cdrom.com
1. Support for fixed device configuration 2. Hoisted common code to scsi_driver 3. SCSI busses dynamically allocated at boot 4. Reorg'd for LKMs
Diffstat (limited to 'sys/scsi')
-rw-r--r--sys/scsi/README9
-rw-r--r--sys/scsi/cd.c288
-rw-r--r--sys/scsi/ch.c239
-rw-r--r--sys/scsi/scsi_all.h10
-rw-r--r--sys/scsi/scsi_driver.c177
-rw-r--r--sys/scsi/scsi_driver.h57
-rw-r--r--sys/scsi/scsi_ioctl.c6
-rw-r--r--sys/scsi/scsiconf.c729
-rw-r--r--sys/scsi/scsiconf.h153
-rw-r--r--sys/scsi/sd.c293
-rw-r--r--sys/scsi/st.c308
-rw-r--r--sys/scsi/uk.c200
12 files changed, 1291 insertions, 1178 deletions
diff --git a/sys/scsi/README b/sys/scsi/README
index b110930..b9a626a 100644
--- a/sys/scsi/README
+++ b/sys/scsi/README
@@ -1,3 +1,6 @@
+WARNING: This file was not fully updated by dufault@hda.com when
+changing the configuration. See the end for new notes.
+
This release consists of the following files
(relative to the base of the source tree )
@@ -193,4 +196,8 @@ The use of this new structure has allowed the compaction of a
lot of duplicated code into a single copy (now in scsi_base.c)
and makes more simple the USER level scsi implimentation.
-
+------Tue Feb 28 07:43:17 EST 1995-----
+dufault@hda.com: Redid configuration to support wired devices.
+All driver entries now get bounced directly into the routines in
+"scsi_driver" via a set of functions generated by the SCSI_ENTRIES macro
+in scsi_conf.h. This lets us put the common code in a single place.
diff --git a/sys/scsi/cd.c b/sys/scsi/cd.c
index a95f99f..d052203 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.32 1994/12/24 09:48:32 bde Exp $
+ * $Id: cd.c,v 1.33 1995/01/08 13:38:28 dufault Exp $
*/
#define SPLCD splbio
@@ -42,11 +42,11 @@
#include <sys/dkstat.h>
/* static function prototypes */
-static errval cd_get_parms(int, int);
-static errval cd_get_mode(u_int32, struct cd_mode_data *, u_int32);
-static errval cd_set_mode(u_int32 unit, struct cd_mode_data *);
-static errval cd_read_toc(u_int32, u_int32, u_int32, struct cd_toc_entry *,
- u_int32);
+static errval cd_get_parms __P((int, int));
+static errval cd_get_mode __P((u_int32, struct cd_mode_data *, u_int32));
+static errval cd_set_mode __P((u_int32 unit, struct cd_mode_data *));
+static errval cd_read_toc __P((u_int32, u_int32, u_int32, struct cd_toc_entry *,
+ u_int32));
static errval cd_pause __P((u_int32, u_int32));
static errval cd_reset __P((u_int32));
@@ -66,24 +66,11 @@ int32 cdstrats, cdqueues;
#define PARTITION(z) (minor(z) & 0x07)
#define RAW_PART 2
-errval cdstrategy();
+void cdstart(u_int32 unit);
-void cdstart();
-struct scsi_device cd_switch =
-{
- NULL, /* use default error handler */
- cdstart, /* we have a queue, which is started by this */
- NULL, /* we do not have an async handler */
- NULL, /* use default 'done' routine */
- "cd", /* we are to be refered to by this name */
- 0, /* no device specific flags */
- { 0, 0 } /* spares not used */
-};
-
-struct cd_data {
+struct scsi_data {
u_int32 flags;
#define CDINIT 0x04 /* device has been init'd */
- struct scsi_link *sc_link; /* address of scsi low level switch */
u_int32 ad_info; /* info about the adapter */
u_int32 cmdscount; /* cmds allowed outstanding by board */
struct cd_parms {
@@ -99,37 +86,55 @@ struct cd_data {
int dkunit;
};
-#define CD_STOP 0
-#define CD_START 1
-#define CD_EJECT -2
+static int cdunit(dev_t dev) { return CDUNIT(dev); }
+static dev_t cdsetunit(dev_t dev, int unit) { return CDSETUNIT(dev, unit); }
-struct cd_driver {
- u_int32 size;
- struct cd_data **cd_data;
-} cd_driver;
+errval cd_open(dev_t dev, int flags, struct scsi_link *sc_link);
+errval cd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag,
+ struct scsi_link *sc_link);
+errval cd_close(dev_t dev, struct scsi_link *sc_link);
+void cd_strategy(struct buf *bp, struct scsi_link *sc_link);
-static u_int32 next_cd_unit = 0;
+SCSI_DEVICE_ENTRIES(cd)
-static int
-cd_goaway(struct kern_devconf *kdc, int force) /* XXX should do a lot more */
+struct scsi_device cd_switch =
{
- dev_detach(kdc);
- FREE(kdc, M_TEMP);
- return 0;
-}
+ NULL, /* use default error handler */
+ cdstart, /* we have a queue, which is started by this */
+ NULL, /* we do not have an async handler */
+ NULL, /* use default 'done' routine */
+ "cd", /* we are to be refered to by this name */
+ 0, /* no device specific flags */
+ {0, 0},
+ 0, /* Link flags */
+ cdattach,
+ cdopen,
+ sizeof(struct scsi_data),
+ T_READONLY,
+ cdunit,
+ cdsetunit,
+ cd_open,
+ cd_ioctl,
+ cd_close,
+ cd_strategy,
+};
+
+#define CD_STOP 0
+#define CD_START 1
+#define CD_EJECT -2
static int
cd_externalize(struct proc *p, struct kern_devconf *kdc, void *userp,
size_t len)
{
- return scsi_externalize(cd_driver.cd_data[kdc->kdc_unit]->sc_link,
+ return scsi_externalize(SCSI_LINK(&cd_switch, kdc->kdc_unit),
userp, &len);
}
static struct kern_devconf kdc_cd_template = {
0, 0, 0, /* filled in by dev_attach */
"cd", 0, MDDC_SCSI,
- cd_externalize, 0, cd_goaway, SCSI_EXTERNALLEN,
+ cd_externalize, 0, scsi_goaway, SCSI_EXTERNALLEN,
&kdc_scbus0, /* parent - XXX should be host adapter*/
0, /* parentdata */
DC_UNKNOWN, /* not supported */
@@ -150,85 +155,29 @@ cd_registerdev(int unit)
if(dk_ndrive < DK_NDRIVE) {
sprintf(dk_names[dk_ndrive], "cd%d", unit);
dk_wpms[dk_ndrive] = (150*1024/2);
- cd_driver.cd_data[unit]->dkunit = dk_ndrive++;
+ SCSI_DATA(&cd_switch, unit)->dkunit = dk_ndrive++;
} else {
- cd_driver.cd_data[unit]->dkunit = -1;
+ SCSI_DATA(&cd_switch, unit)->dkunit = -1;
}
}
-errval cdopen();
/*
* The routine called by the low level scsi routine when it discovers
* A device suitable for this driver
*/
int
-cdattach(sc_link)
- struct scsi_link *sc_link;
+cdattach(struct scsi_link *sc_link)
{
u_int32 unit;
- struct cd_data *cd, **cdrealloc;
struct cd_parms *dp;
+ struct scsi_data *cd = sc_link->sd;
- SC_DEBUG(sc_link, SDEV_DB2, ("cdattach "));
-
- /*
- * 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
- */
- /* 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
- */
- unit = next_cd_unit++;
- if (unit >= cd_driver.size) {
- cdrealloc =
- malloc(sizeof(cd_driver.cd_data) * next_cd_unit,
- M_DEVBUF, M_NOWAIT);
- if (!cdrealloc) {
- printf("cd%ld: malloc failed for cdrealloc\n", unit);
- return (0);
- }
- /* Make sure we have something to copy before we copy it */
- bzero(cdrealloc, sizeof(cd_driver.cd_data) * next_cd_unit);
- 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++;
- }
- if (cd_driver.cd_data[unit]) {
- printf("cd%ld: Already has storage!\n", unit);
- return (0);
- }
- /*
- * 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%ld: malloc failed for cd_data\n", unit);
- return (0);
- }
- bzero(cd, sizeof(struct cd_data));
+ unit = sc_link->dev_unit;
dp = &(cd->params);
- /*
- * Store information needed to contact our base driver
- */
- cd->sc_link = sc_link;
- sc_link->device = &cd_switch;
- sc_link->dev_unit = unit;
- sc_link->dev = CDSETUNIT(scsi_dev_lookup(cdopen), unit);
- if (cd->sc_link->adapter->adapter_info) {
- cd->ad_info = ((*(cd->sc_link->adapter->adapter_info)) (sc_link->adapter_unit));
+ if (sc_link->adapter->adapter_info) {
+ cd->ad_info = ((*(sc_link->adapter->adapter_info)) (sc_link->adapter_unit));
cd->cmdscount = cd->ad_info & AD_INF_MAX_CMDS;
if (cd->cmdscount > CDOUTSTANDING)
cd->cmdscount = CDOUTSTANDING;
@@ -244,50 +193,41 @@ cdattach(sc_link)
*/
cd_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK);
if (dp->disksize) {
- printf("cd%ld: cd present.[%ld x %ld byte records]\n",
- unit,
+ printf("cd present.[%ld x %ld byte records]\n",
cd->params.disksize,
cd->params.blksize);
} else {
- printf("cd%ld: drive empty\n", unit);
+ printf("drive empty\n");
}
cd->flags |= CDINIT;
cd_registerdev(unit);
- return (1);
+
+ return 0;
}
/*
* open the device. Make sure the partition info is a up-to-date as can be.
*/
errval
-cdopen(dev)
- dev_t dev;
+cd_open(dev_t dev, int flags, struct scsi_link *sc_link)
{
errval errcode = 0;
u_int32 unit, part;
- struct cd_data *cd;
- struct scsi_link *sc_link;
+ struct scsi_data *cd;
unit = CDUNIT(dev);
part = PARTITION(dev);
- /*
- * Check the unit is legal
- */
- if (unit >= cd_driver.size) {
- return (ENXIO);
- }
- cd = cd_driver.cd_data[unit];
+ cd = sc_link->sd;
/*
* Make sure the device has been initialised
*/
if ((cd == NULL) || (!(cd->flags & CDINIT)))
return (ENXIO);
- sc_link = cd->sc_link;
SC_DEBUG(sc_link, SDEV_DB1,
- ("cdopen: dev=0x%x (unit %d (of %d),partition %d)\n",
- dev, unit, cd_driver.size, part));
+ ("cdopen: dev=0x%x (unit %d,partition %d)\n",
+ dev, unit, part));
/*
* If it's been invalidated, and not everybody has closed it then
* forbid re-entry. (may have changed media)
@@ -376,17 +316,15 @@ cdopen(dev)
* occurence of an open device
*/
errval
-cdclose(dev)
- dev_t dev;
+cd_close(dev_t dev, struct scsi_link *sc_link)
{
u_int8 unit, part;
- struct cd_data *cd;
- struct scsi_link *sc_link;
+ struct scsi_data *cd;
unit = CDUNIT(dev);
part = PARTITION(dev);
- cd = cd_driver.cd_data[unit];
- sc_link = cd->sc_link;
+ cd = sc_link->sd;
+
SC_DEBUG(sc_link, SDEV_DB2, ("cd%ld: closing part %d\n", unit, part));
cd->partflags[part] &= ~CDOPEN;
cd->openparts &= ~(1 << part);
@@ -396,50 +334,31 @@ cdclose(dev)
*/
if (!(cd->openparts)) {
scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
- cd->sc_link->flags &= ~SDEV_OPEN;
+ sc_link->flags &= ~SDEV_OPEN;
}
return (0);
}
-/*
- * trim the size of the transfer if needed,
- * called by physio
- * basically the smaller of our max and the scsi driver's
- * minphys (note we have no max ourselves)
- *
- * Trim buffer length if buffer-size is bigger than page size
- */
-void
-cdminphys(bp)
- struct buf *bp;
-{
- (*(cd_driver.cd_data[CDUNIT(bp->b_dev)]->sc_link->adapter->scsi_minphys)) (bp);
-}
/*
* Actually translate the requested transfer into one the physical driver can
* understand. The transfer is described by a buf and will include only one
* physical transfer.
*/
-errval
-cdstrategy(bp)
- struct buf *bp;
+void
+cd_strategy(struct buf *bp, struct scsi_link *sc_link)
{
struct buf *dp;
u_int32 opri;
u_int32 unit = CDUNIT((bp->b_dev));
- struct cd_data *cd = cd_driver.cd_data[unit];
+ struct scsi_data *cd = sc_link->sd;
cdstrats++;
- SC_DEBUG(cd->sc_link, SDEV_DB2, ("\ncdstrategy "));
- SC_DEBUG(cd->sc_link, SDEV_DB1, ("cd%ld: %d bytes @ blk%d\n",
- unit, bp->b_bcount, bp->b_blkno));
- cdminphys(bp);
/*
* If the device has been made invalid, error out
* maybe the media changed
*/
- if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED)) {
+ if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
bp->b_error = EIO;
goto bad;
}
@@ -478,7 +397,7 @@ cdstrategy(bp)
* Use a bounce buffer if necessary
*/
#ifdef BOUNCE_BUFFERS
- if (cd->sc_link->flags & SDEV_BOUNCE)
+ if (sc_link->flags & SDEV_BOUNCE)
vm_bounce_alloc(bp);
#endif
@@ -494,7 +413,7 @@ cdstrategy(bp)
cdstart(unit);
splx(opri);
- return 0; /* XXX ??? is this the right return? */
+ return;
bad:
bp->b_flags |= B_ERROR;
done:
@@ -504,7 +423,7 @@ cdstrategy(bp)
*/
bp->b_resid = bp->b_bcount;
biodone(bp);
- return (0);
+ return;
}
/*
@@ -532,8 +451,8 @@ cdstart(unit)
struct scsi_rw_big cmd;
u_int32 blkno, nblk;
struct partition *p;
- struct cd_data *cd = cd_driver.cd_data[unit];
- struct scsi_link *sc_link = cd->sc_link;
+ struct scsi_link *sc_link = SCSI_LINK(&cd_switch, unit);
+ struct scsi_data *cd = sc_link->sd;
SC_DEBUG(sc_link, SDEV_DB2, ("cdstart%d ", unit));
/*
@@ -620,24 +539,24 @@ cdstart(unit)
* Knows about the internals of this device
*/
errval
-cdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
+cd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct scsi_link *sc_link)
{
errval error = 0;
u_int8 unit, part;
- register struct cd_data *cd;
+ register struct scsi_data *cd;
/*
* Find the device that the user is talking about
*/
unit = CDUNIT(dev);
part = PARTITION(dev);
- cd = cd_driver.cd_data[unit];
- SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdioctl 0x%x ", cmd));
+ cd = sc_link->sd;
+ SC_DEBUG(sc_link, SDEV_DB2, ("cdioctl 0x%x ", cmd));
/*
* If the device is not valid.. abandon ship
*/
- if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED))
+ if (!(sc_link->flags & SDEV_MEDIA_LOADED))
return (EIO);
switch (cmd) {
@@ -925,32 +844,32 @@ cdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
error = cd_pause(unit, 0);
break;
case CDIOCSTART:
- error = scsi_start_unit(cd->sc_link, 0);
+ error = scsi_start_unit(sc_link, 0);
break;
case CDIOCSTOP:
- error = scsi_stop_unit(cd->sc_link, 0, 0);
+ error = scsi_stop_unit(sc_link, 0, 0);
break;
case CDIOCEJECT:
- error = scsi_stop_unit(cd->sc_link, 1, 0);
+ error = scsi_stop_unit(sc_link, 1, 0);
break;
case CDIOCALLOW:
- error = scsi_prevent(cd->sc_link, PR_ALLOW, 0);
+ error = scsi_prevent(sc_link, PR_ALLOW, 0);
break;
case CDIOCPREVENT:
- error = scsi_prevent(cd->sc_link, PR_PREVENT, 0);
+ error = scsi_prevent(sc_link, PR_PREVENT, 0);
break;
case CDIOCSETDEBUG:
- cd->sc_link->flags |= (SDEV_DB1 | SDEV_DB2);
+ sc_link->flags |= (SDEV_DB1 | SDEV_DB2);
break;
case CDIOCCLRDEBUG:
- cd->sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
+ sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
break;
case CDIOCRESET:
return (cd_reset(unit));
break;
default:
if(part == RAW_PART || SCSI_SUPER(dev))
- error = scsi_do_ioctl(dev, cd->sc_link,cmd,addr,flag);
+ error = scsi_do_ioctl(dev, cmd, addr, flag, sc_link);
else
error = ENOTTY;
break;
@@ -970,9 +889,9 @@ cd_getdisklabel(unit)
u_int8 unit;
{
/*unsigned int n, m; */
- struct cd_data *cd;
+ struct scsi_data *cd;
- cd = cd_driver.cd_data[unit];
+ cd = SCSI_DATA(&cd_switch, unit);
bzero(&cd->disklabel, sizeof(struct disklabel));
/*
@@ -1023,7 +942,8 @@ cd_size(unit, flags)
struct scsi_read_cd_capacity scsi_cmd;
u_int32 size;
u_int32 blksize;
- struct cd_data *cd = cd_driver.cd_data[unit];
+ struct scsi_link *sc_link = SCSI_LINK(&cd_switch, unit);
+ struct scsi_data *cd = sc_link->sd;
/*
* make up a scsi command and ask the scsi driver to do
@@ -1036,7 +956,7 @@ cd_size(unit, flags)
* If the command works, interpret the result as a 4 byte
* number of blocks and a blocksize
*/
- if (scsi_scsi_cmd(cd->sc_link,
+ if (scsi_scsi_cmd(sc_link,
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
(u_char *) & rdcap,
@@ -1061,7 +981,7 @@ cd_size(unit, flags)
blksize = 2048; /* some drives lie ! */
if (size < 100)
size = 400000; /* ditto */
- SC_DEBUG(cd->sc_link, SDEV_DB3, ("cd%ld: %d %d byte blocks\n"
+ SC_DEBUG(sc_link, SDEV_DB3, ("cd%ld: %d %d byte blocks\n"
,unit, size, blksize));
cd->params.disksize = size;
cd->params.blksize = blksize;
@@ -1085,7 +1005,7 @@ cd_get_mode(unit, data, page)
scsi_cmd.op_code = MODE_SENSE;
scsi_cmd.page = page;
scsi_cmd.length = sizeof(*data) & 0xff;
- retval = scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+ retval = scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
(u_char *) data,
@@ -1112,7 +1032,7 @@ cd_set_mode(unit, data)
scsi_cmd.byte2 |= SMS_PF;
scsi_cmd.length = sizeof(*data) & 0xff;
data->header.data_length = 0;
- return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+ return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
(u_char *) data,
@@ -1140,7 +1060,7 @@ cd_play(unit, blk, len)
scsi_cmd.blk_addr[3] = blk & 0xff;
scsi_cmd.xfer_len[0] = (len >> 8) & 0xff;
scsi_cmd.xfer_len[1] = len & 0xff;
- return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+ return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
0,
@@ -1170,7 +1090,7 @@ cd_play_big(unit, blk, len)
scsi_cmd.xfer_len[1] = (len >> 16) & 0xff;
scsi_cmd.xfer_len[2] = (len >> 8) & 0xff;
scsi_cmd.xfer_len[3] = len & 0xff;
- return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+ return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
0,
@@ -1196,7 +1116,7 @@ cd_play_tracks(unit, strack, sindex, etrack, eindex)
scsi_cmd.start_index = sindex;
scsi_cmd.end_track = etrack;
scsi_cmd.end_index = eindex;
- return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+ return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
0,
@@ -1225,7 +1145,7 @@ cd_play_msf(unit, startm, starts, startf, endm, ends, endf)
scsi_cmd.end_s = ends;
scsi_cmd.end_f = endf;
- return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+ return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
0,
@@ -1249,7 +1169,7 @@ cd_pause(unit, go)
scsi_cmd.op_code = PAUSE;
scsi_cmd.resume = go;
- return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+ return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
0,
@@ -1267,7 +1187,7 @@ errval
cd_reset(unit)
u_int32 unit;
{
- return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+ return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
0,
0,
0,
@@ -1300,7 +1220,7 @@ cd_read_subchannel(unit, mode, format, track, data, len)
scsi_cmd.track = track;
scsi_cmd.data_len[0] = (len) >> 8;
scsi_cmd.data_len[1] = (len) & 0xff;
- return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+ return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
(struct scsi_generic *) &scsi_cmd,
sizeof(struct scsi_read_subchannel),
(u_char *) data,
@@ -1335,7 +1255,7 @@ cd_read_toc(unit, mode, start, data, len)
scsi_cmd.from_track = start;
scsi_cmd.data_len[0] = (ntoc) >> 8;
scsi_cmd.data_len[1] = (ntoc) & 0xff;
- return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+ return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
(struct scsi_generic *) &scsi_cmd,
sizeof(struct scsi_read_toc),
(u_char *) data,
@@ -1357,19 +1277,19 @@ cd_get_parms(unit, flags)
int unit;
int flags;
{
- struct cd_data *cd = cd_driver.cd_data[unit];
+ struct scsi_link *sc_link = SCSI_LINK(&cd_switch, unit);
/*
* First check if we have it all loaded
*/
- if (cd->sc_link->flags & SDEV_MEDIA_LOADED)
+ if (sc_link->flags & SDEV_MEDIA_LOADED)
return (0);
/*
* give a number of sectors so that sec * trks * cyls
* is <= disk_size
*/
if (cd_size(unit, flags)) {
- cd->sc_link->flags |= SDEV_MEDIA_LOADED;
+ sc_link->flags |= SDEV_MEDIA_LOADED;
return (0);
} else {
return (ENXIO);
diff --git a/sys/scsi/ch.c b/sys/scsi/ch.c
index 2c93393..1c19f5e 100644
--- a/sys/scsi/ch.c
+++ b/sys/scsi/ch.c
@@ -2,7 +2,7 @@
* Written by grefen@?????
* Based on scsi drivers by Julian Elischer (julian@tfs.com)
*
- * $Id: ch.c,v 1.12 1995/01/08 13:38:29 dufault Exp $
+ * $Id: ch.c,v 1.13 1995/01/19 21:02:54 ats Exp $
*/
#include <sys/types.h>
@@ -26,37 +26,14 @@
static errval ch_mode_sense(u_int32, u_int32);
-struct scsi_xfer ch_scsi_xfer[NCH];
-u_int32 ch_xfer_block_wait[NCH];
-
-#define PAGESIZ 4096
-#define STQSIZE 4
#define CHRETRIES 2
#define MODE(z) ( (minor(z) & 0x0F) )
#define ESUCCESS 0
-errval chopen();
-errval chattach();
-
-/*
- * This driver is so simple it uses all the default services
- */
-struct scsi_device ch_switch =
-{
- NULL,
- NULL,
- NULL,
- NULL,
- "ch",
- 0,
- 0, 0
-};
-
-struct ch_data {
+struct scsi_data {
u_int32 flags;
- struct scsi_link *sc_link; /* all the inter level info */
u_int16 chmo; /* Offset of first CHM */
u_int16 chms; /* No. of CHM */
u_int16 slots; /* No. of Storage Elements */
@@ -70,32 +47,55 @@ struct ch_data {
u_int16 lsterr; /* details of lasterror */
u_char stor; /* posible Storage locations */
u_int32 initialized;
-} ch_data[NCH];
+};
-#define CH_OPEN 0x01
-#define CH_KNOWN 0x02
+static int chunit(dev_t dev) { return CHUNIT(dev); }
+static dev_t chsetunit(dev_t dev, int unit) { return CHSETUNIT(dev, unit); }
-static u_int32 next_ch_unit = 0;
+errval ch_open(dev_t dev, int flags, struct scsi_link *sc_link);
+errval ch_ioctl(dev_t dev, int cmd, caddr_t addr, int flag,
+ struct scsi_link *sc_link);
+errval ch_close(dev_t dev, struct scsi_link *sc_link);
-static int
-ch_goaway(struct kern_devconf *kdc, int force) /* XXX should do a lot more */
+SCSI_DEVICE_ENTRIES(ch)
+
+struct scsi_device ch_switch =
{
- dev_detach(kdc);
- FREE(kdc, M_TEMP);
- return 0;
-}
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "ch",
+ 0,
+ {0, 0},
+ 0, /* Link flags */
+ chattach,
+ chopen,
+ sizeof(struct scsi_data),
+ T_CHANGER,
+ chunit,
+ chsetunit,
+ ch_open,
+ ch_ioctl,
+ ch_close,
+ 0,
+};
+
+#define CH_OPEN 0x01
+#define CH_KNOWN 0x02
static int
ch_externalize(struct proc *p, struct kern_devconf *kdc, void *userp,
size_t len)
{
- return scsi_externalize(ch_data[kdc->kdc_unit].sc_link, userp, &len);
+ return scsi_externalize(SCSI_LINK(&ch_switch, kdc->kdc_unit),
+ userp, &len);
}
static struct kern_devconf kdc_ch_template = {
0, 0, 0, /* filled in by dev_attach */
"ch", 0, MDDC_SCSI,
- ch_externalize, 0, ch_goaway, SCSI_EXTERNALLEN,
+ ch_externalize, 0, scsi_goaway, SCSI_EXTERNALLEN,
&kdc_scbus0, /* parent */
0, /* parentdata */
DC_UNKNOWN, /* not supported */
@@ -119,28 +119,14 @@ ch_registerdev(int unit)
* a device suitable for this driver.
*/
errval
-chattach(sc_link)
- struct scsi_link *sc_link;
+chattach(struct scsi_link *sc_link)
{
u_int32 unit, i, stat;
unsigned char *tbl;
- SC_DEBUG(sc_link, SDEV_DB2, ("chattach: "));
- /*
- * Check we have the resources for another drive
- */
- unit = next_ch_unit++;
- if (unit >= NCH) {
- printf("Too many scsi changers..(%d > %d) reconfigure kernel\n", (unit + 1), NCH);
- return (0);
- }
- /*
- * Store information needed to contact our base driver
- */
- ch_data[unit].sc_link = sc_link;
- sc_link->device = &ch_switch;
- sc_link->dev_unit = unit;
- sc_link->dev = CHSETUNIT(scsi_dev_lookup(chopen), unit);
+ struct scsi_data *ch = sc_link->sd;
+
+ unit = sc_link->dev_unit;
/*
* Use the subdriver to request information regarding
@@ -148,59 +134,46 @@ chattach(sc_link)
* request must specify this.
*/
if ((ch_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK /*| SCSI_SILENT */ ))) {
- printf("ch%d: scsi changer :- offline\n", unit);
+ printf("scsi changer :- offline\n");
stat = CH_OPEN;
} else {
- printf("ch%d: scsi changer, %d slot(s) %d drive(s) %d arm(s) %d i/e-slot(s)\n",
- unit, ch_data[unit].slots, ch_data[unit].drives, ch_data[unit].chms, ch_data[unit].imexs);
+ printf("scsi changer, %d slot(s) %d drive(s) %d arm(s) %d i/e-slot(s)\n",
+ ch->slots, ch->drives, ch->chms, ch->imexs);
stat = CH_KNOWN;
}
- ch_data[unit].initialized = 1;
+ ch->initialized = 1;
ch_registerdev(unit);
- return 1;
- /* XXX ??? is this the right return val? */
+ return 0;
}
/*
* open the device.
*/
errval
-chopen(dev)
- dev_t dev;
+ch_open(dev_t dev, int flags, struct scsi_link *sc_link)
{
errval errcode = 0;
u_int32 unit, mode;
- struct scsi_link *sc_link;
+ struct scsi_data *cd;
unit = CHUNIT(dev);
mode = MODE(dev);
- /*
- * Check the unit is legal
- */
- if (unit >= NCH) {
- printf("ch%d: ch %d > %d\n", unit, unit, NCH);
- errcode = ENXIO;
- return (errcode);
- }
+ cd = sc_link->sd;
/*
* Only allow one at a time
*/
- if (ch_data[unit].flags & CH_OPEN) {
+ if (cd->flags & CH_OPEN) {
printf("ch%d: already open\n", unit);
return EBUSY;
}
/*
* Make sure the device has been initialised
*/
- if (!ch_data[unit].initialized)
+ if (!cd->initialized)
return (ENXIO);
- sc_link = ch_data[unit].sc_link;
-
- SC_DEBUG(sc_link, SDEV_DB1, ("chopen: dev=0x%x (unit %d (of %d))\n"
- ,dev, unit, NCH));
/*
* Catch any unit attention errors.
*/
@@ -223,7 +196,7 @@ chopen(dev)
sc_link->flags &= ~SDEV_OPEN;
return (errcode);
}
- ch_data[unit].flags = CH_OPEN;
+ cd->flags = CH_OPEN;
return 0;
}
@@ -232,18 +205,9 @@ chopen(dev)
* occurence of an open device
*/
errval
-chclose(dev)
- dev_t dev;
+ch_close(dev_t dev, struct scsi_link *sc_link)
{
- unsigned char unit, mode;
- struct scsi_link *sc_link;
-
- unit = CHUNIT(dev);
- mode = MODE(dev);
- sc_link = ch_data[unit].sc_link;
-
- SC_DEBUG(sc_link, SDEV_DB1, ("Closing device"));
- ch_data[unit].flags = 0;
+ sc_link->sd->flags = 0;
sc_link->flags &= ~SDEV_OPEN;
return (0);
}
@@ -253,11 +217,8 @@ chclose(dev)
* Knows about the internals of this device
*/
errval
-chioctl(dev, cmd, arg, mode)
- dev_t dev;
- u_int32 cmd;
- caddr_t arg;
- int mode;
+ch_ioctl(dev_t dev, int cmd, caddr_t arg, int mode,
+struct scsi_link *sc_link)
{
/* struct ch_cmd_buf *args; */
union scsi_cmd *scsi_cmd;
@@ -267,14 +228,14 @@ chioctl(dev, cmd, arg, mode)
unsigned char unit;
u_int32 number, flags;
errval ret;
- struct scsi_link *sc_link;
+ struct scsi_data *cd;
/*
* Find the device that the user is talking about
*/
flags = 0; /* give error messages, act on errors etc. */
unit = CHUNIT(dev);
- sc_link = ch_data[unit].sc_link;
+ cd = sc_link->sd;
switch ((int)cmd) {
case CHIOOP:{
@@ -284,15 +245,15 @@ chioctl(dev, cmd, arg, mode)
switch ((short) (ch->ch_op)) {
case CHGETPARAM:
- ch->u.getparam.chmo = ch_data[unit].chmo;
- ch->u.getparam.chms = ch_data[unit].chms;
- ch->u.getparam.sloto = ch_data[unit].sloto;
- ch->u.getparam.slots = ch_data[unit].slots;
- ch->u.getparam.imexo = ch_data[unit].imexo;
- ch->u.getparam.imexs = ch_data[unit].imexs;
- ch->u.getparam.driveo = ch_data[unit].driveo;
- ch->u.getparam.drives = ch_data[unit].drives;
- ch->u.getparam.rot = ch_data[unit].rot;
+ ch->u.getparam.chmo = cd->chmo;
+ ch->u.getparam.chms = cd->chms;
+ ch->u.getparam.sloto = cd->sloto;
+ ch->u.getparam.slots = cd->slots;
+ ch->u.getparam.imexo = cd->imexo;
+ ch->u.getparam.imexs = cd->imexs;
+ ch->u.getparam.driveo = cd->driveo;
+ ch->u.getparam.drives = cd->drives;
+ ch->u.getparam.rot = cd->rot;
ch->result = 0;
return 0;
break;
@@ -313,7 +274,7 @@ chioctl(dev, cmd, arg, mode)
}
}
default:
- return scsi_do_ioctl(dev, sc_link, cmd, arg, mode);
+ return scsi_do_ioctl(dev, cmd, arg, mode, sc_link);
}
return (ret ? ESUCCESS : EIO);
}
@@ -328,6 +289,10 @@ ch_getelem(unit, stat, type, from, data, flags)
struct scsi_read_element_status scsi_cmd;
char elbuf[32];
errval ret;
+ struct scsi_link *sc_link;
+
+ if ((sc_link = SCSI_LINK(&ch_switch, unit)) == 0)
+ return ENXIO;
bzero(&scsi_cmd, sizeof(scsi_cmd));
scsi_cmd.op_code = READ_ELEMENT_STATUS;
@@ -337,7 +302,7 @@ ch_getelem(unit, stat, type, from, data, flags)
scsi_cmd.number_of_elements[1] = 1;
scsi_cmd.allocation_length[2] = 32;
- if ((ret = scsi_scsi_cmd(ch_data[unit].sc_link,
+ if ((ret = scsi_scsi_cmd(sc_link,
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
(u_char *) elbuf,
@@ -346,7 +311,7 @@ ch_getelem(unit, stat, type, from, data, flags)
100000,
NULL,
SCSI_DATA_IN | flags) != ESUCCESS)) {
- *stat = ch_data[unit].lsterr;
+ *stat = sc_link->sd->lsterr;
bcopy(elbuf + 16, data, 16);
return ret;
}
@@ -361,6 +326,10 @@ ch_move(unit, stat, chm, from, to, flags)
{
struct scsi_move_medium scsi_cmd;
errval ret;
+ struct scsi_link *sc_link;
+
+ if ((sc_link = SCSI_LINK(&ch_switch, unit)) == 0)
+ return ENXIO;
bzero(&scsi_cmd, sizeof(scsi_cmd));
scsi_cmd.op_code = MOVE_MEDIUM;
@@ -371,7 +340,7 @@ ch_move(unit, stat, chm, from, to, flags)
scsi_cmd.destination_address[0] = (to >> 8) & 0xff;
scsi_cmd.destination_address[1] = to & 0xff;
scsi_cmd.invert = (chm & CH_INVERT) ? 1 : 0;
- if ((ret = scsi_scsi_cmd(ch_data[unit].sc_link,
+ if ((ret = scsi_scsi_cmd(sc_link,
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
NULL,
@@ -380,7 +349,7 @@ ch_move(unit, stat, chm, from, to, flags)
100000,
NULL,
flags) != ESUCCESS)) {
- *stat = ch_data[unit].lsterr;
+ *stat = sc_link->sd->lsterr;
return ret;
}
return ret;
@@ -393,6 +362,10 @@ ch_position(unit, stat, chm, to, flags)
{
struct scsi_position_to_element scsi_cmd;
errval ret;
+ struct scsi_link *sc_link;
+
+ if ((sc_link = SCSI_LINK(&ch_switch, unit)) == 0)
+ return ENXIO;
bzero(&scsi_cmd, sizeof(scsi_cmd));
scsi_cmd.op_code = POSITION_TO_ELEMENT;
@@ -401,7 +374,7 @@ ch_position(unit, stat, chm, to, flags)
scsi_cmd.source_address[0] = (to >> 8) & 0xff;
scsi_cmd.source_address[1] = to & 0xff;
scsi_cmd.invert = (chm & CH_INVERT) ? 1 : 0;
- if ((ret = scsi_scsi_cmd(ch_data[unit].sc_link,
+ if ((ret = scsi_scsi_cmd(sc_link,
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
NULL,
@@ -410,7 +383,7 @@ ch_position(unit, stat, chm, to, flags)
100000,
NULL,
flags) != ESUCCESS)) {
- *stat = ch_data[unit].lsterr;
+ *stat = sc_link->sd->lsterr;
return ret;
}
return ret;
@@ -438,7 +411,13 @@ ch_mode_sense(unit, flags)
u_char *b;
int32 i, l;
errval errcode;
- struct scsi_link *sc_link = ch_data[unit].sc_link;
+ struct scsi_data *cd;
+ struct scsi_link *sc_link;
+
+ if ((sc_link = SCSI_LINK(&ch_switch, unit)) == 0)
+ return ENXIO;
+
+ cd = sc_link->sd;
/*
* First check if we have it all loaded
@@ -494,22 +473,22 @@ ch_mode_sense(unit, flags)
u_char *bb = b;
switch ((int)pc) {
case 0x1d:
- ch_data[unit].chmo = p2copy(bb);
- ch_data[unit].chms = p2copy(bb);
- ch_data[unit].sloto = p2copy(bb);
- ch_data[unit].slots = p2copy(bb);
- ch_data[unit].imexo = p2copy(bb);
- ch_data[unit].imexs = p2copy(bb);
- ch_data[unit].driveo = p2copy(bb);
- ch_data[unit].drives = p2copy(bb);
+ cd->chmo = p2copy(bb);
+ cd->chms = p2copy(bb);
+ cd->sloto = p2copy(bb);
+ cd->slots = p2copy(bb);
+ cd->imexo = p2copy(bb);
+ cd->imexs = p2copy(bb);
+ cd->driveo = p2copy(bb);
+ cd->drives = p2copy(bb);
break;
case 0x1e:
- ch_data[unit].rot = (*b) & 1;
+ cd->rot = (*b) & 1;
break;
case 0x1f:
- ch_data[unit].stor = *b & 0xf;
+ cd->stor = *b & 0xf;
bb += 2;
- ch_data[unit].stor = p4copy(bb);
+ cd->stor = p4copy(bb);
break;
default:
break;
@@ -519,10 +498,10 @@ ch_mode_sense(unit, flags)
}
SC_DEBUG(sc_link, SDEV_DB2,
(" cht(%d-%d)slot(%d-%d)imex(%d-%d)cts(%d-%d) %s rotate\n",
- ch_data[unit].chmo, ch_data[unit].chms,
- ch_data[unit].sloto, ch_data[unit].slots,
- ch_data[unit].imexo, ch_data[unit].imexs,
- ch_data[unit].driveo, ch_data[unit].drives,
- ch_data[unit].rot ? "can" : "can't"));
+ cd->chmo, cd->chms,
+ cd->sloto, cd->slots,
+ cd->imexo, cd->imexs,
+ cd->driveo, cd->drives,
+ cd->rot ? "can" : "can't"));
return (0);
}
diff --git a/sys/scsi/scsi_all.h b/sys/scsi/scsi_all.h
index d24b1d0..af8dce2 100644
--- a/sys/scsi/scsi_all.h
+++ b/sys/scsi/scsi_all.h
@@ -14,7 +14,7 @@
*
* Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
*
- * $Id: scsi_all.h,v 1.8 1995/01/08 13:38:30 dufault Exp $
+ * $Id: scsi_all.h,v 1.9 1995/02/22 01:44:21 gibbs Exp $
*/
/*
@@ -203,10 +203,14 @@ struct scsi_changedef
#define T_READONLY 5
#define T_SCANNER 6
#define T_OPTICAL 7
-#define T_NODEVICE 0x1F
-
#define T_CHANGER 8
#define T_COMM 9
+#define T_ASC0 10
+#define T_ASC1 11
+#define T_UNKNOWN 12
+#define T_NTYPES 13
+
+#define T_NODEVICE 0x1F
#define T_REMOV 1
#define T_FIXED 0
diff --git a/sys/scsi/scsi_driver.c b/sys/scsi/scsi_driver.c
new file mode 100644
index 0000000..8155c70
--- /dev/null
+++ b/sys/scsi/scsi_driver.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 1995, HD Associates, Inc.
+ * PO Box 276
+ * Pepperell, MA 01463
+ * 508 433 5266
+ * dufault@hda.com
+ *
+ * This code is contributed to the University of California at Berkeley:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: scsi_ioctl.c,v 1.10 1995/01/19 12:41:36 dufault Exp $
+ *
+ */
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <scsi/scsi_driver.h>
+
+#define GETUNIT(DEVICE, DEV) \
+ ((DEVICE)->getunit) ? (*(DEVICE)->getunit)((DEV)) : minor((DEV))
+
+int
+scsi_goaway(struct kern_devconf *kdc, int force) /* XXX should do a lot more */
+{
+ dev_detach(kdc);
+ FREE(kdc, M_TEMP);
+ return 0;
+}
+
+int scsi_device_attach(struct scsi_link *sc_link)
+{
+ errval errcode;
+ dev_t dev;
+ struct scsi_device *device = sc_link->device;
+
+ SC_DEBUG(sc_link, SDEV_DB2,
+ ("%s%dattach: ", device->name, sc_link->dev_unit));
+
+ dev = scsi_dev_lookup(device->open);
+
+ sc_link->dev = (device->setunit ?
+ (*device->setunit)(dev, sc_link->dev_unit) :
+ makedev(major(dev), sc_link->dev_unit) );
+
+ errcode = (*(device->attach))(sc_link);
+
+ if (errcode == 0)
+ sc_link->flags |= device->link_flags;
+
+ return errcode;
+}
+
+errval
+scsi_open(dev_t dev, int flags, struct scsi_device *device)
+{
+ errval errcode;
+ u_int32 unit;
+ struct scsi_link *sc_link;
+
+ unit = GETUNIT(device, dev);
+ sc_link = SCSI_LINK(device, unit);
+
+ /*
+ * Check the unit is legal
+ */
+ if (sc_link == 0 || sc_link->sd == 0)
+ return ENXIO;
+
+ errcode = (device->dev_open) ?
+ (*device->dev_open)(dev, flags, sc_link) : 0;
+
+ if (sc_link->flags & SDEV_ONCE_ONLY) {
+ /*
+ * Only allow one at a time
+ */
+ if (sc_link->flags & SDEV_OPEN) {
+ return EBUSY;
+ }
+
+ sc_link->flags |= SDEV_OPEN;
+ }
+
+ SC_DEBUG(sc_link, SDEV_DB1, ("%sopen: dev=0x%x (unit %d of %d) result %d\n",
+ device->name, dev, unit, device->size, errcode));
+
+ return errcode;
+}
+
+/*
+ * close the device.. only called if we are the LAST
+ * occurence of an open device
+ */
+errval
+scsi_close(dev_t dev, struct scsi_device *device)
+{
+ errval errcode;
+ struct scsi_link *scsi_link = SCSI_LINK(device, GETUNIT(device, dev));
+
+ SC_DEBUG(scsi_link, SDEV_DB1, ("%sclose: Closing device\n", device->name));
+
+ errcode = (device->dev_close) ?
+ (*device->dev_close)(dev, scsi_link) : 0;
+
+ if (scsi_link->flags & SDEV_ONCE_ONLY)
+ scsi_link->flags &= ~SDEV_OPEN;
+
+ return errcode;
+}
+
+errval
+scsi_ioctl(dev_t dev, u_int32 cmd, caddr_t arg, int mode,
+struct scsi_device *device)
+{
+ errval errcode;
+ struct scsi_link *scsi_link = SCSI_LINK(device, GETUNIT(device, dev));
+
+ errcode = (device->dev_ioctl) ?
+ (*device->dev_ioctl)(dev, cmd, arg, mode, scsi_link)
+ : scsi_do_ioctl(dev, cmd, arg, mode, scsi_link);
+
+ return errcode;
+}
+
+void
+scsi_minphys(struct buf *bp, struct scsi_device *device)
+{
+ struct scsi_link *sc_link = SCSI_LINK(device, GETUNIT(device, bp->b_dev));
+ (*sc_link->adapter->scsi_minphys)(bp);
+}
+
+void
+scsi_strategy(struct buf *bp, struct scsi_device *device)
+{
+ struct scsi_link *sc_link = SCSI_LINK(device, GETUNIT(device, bp->b_dev));
+
+ SC_DEBUG(sc_link, SDEV_DB2, ("\n%sstrategy ", device->name));
+ SC_DEBUG(sc_link, SDEV_DB1, ("%s%ld: %d bytes @ blk%d\n",
+ device->name, unit, bp->b_bcount, bp->b_blkno));
+
+ if (device->dev_strategy)
+ {
+ (*sc_link->adapter->scsi_minphys)(bp);
+ (*device->dev_strategy)(bp, sc_link);
+ }
+}
diff --git a/sys/scsi/scsi_driver.h b/sys/scsi/scsi_driver.h
new file mode 100644
index 0000000..dff132e
--- /dev/null
+++ b/sys/scsi/scsi_driver.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 1995, HD Associates, Inc.
+ * PO Box 276
+ * Pepperell, MA 01463
+ * 508 433 5266
+ * dufault@hda.com
+ *
+ * This code is contributed to the University of California at Berkeley:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: scsi_ioctl.c,v 1.10 1995/01/19 12:41:36 dufault Exp $
+ *
+ */
+#ifndef _SCSI__DRIVER_H_
+#define _SCSI__DRIVER_H_
+
+struct kern_devconf;
+struct scsi_link;
+struct scsi_device;
+struct buf;
+
+int scsi_goaway __P((struct kern_devconf *, int));
+int scsi_device_attach __P((struct scsi_link *));
+errval scsi_open __P((dev_t, int, struct scsi_device *));
+errval scsi_close __P((dev_t, struct scsi_device *));
+errval scsi_ioctl __P((dev_t, u_int32, caddr_t, int, struct scsi_device *));
+void scsi_strategy __P((struct buf *, struct scsi_device *));
+void scsi_minphys __P((struct buf *, struct scsi_device *));
+
+#endif /* _SCSI__DRIVER_H_ */
diff --git a/sys/scsi/scsi_ioctl.c b/sys/scsi/scsi_ioctl.c
index db26691..bca35ca 100644
--- a/sys/scsi/scsi_ioctl.c
+++ b/sys/scsi/scsi_ioctl.c
@@ -38,7 +38,7 @@
* SUCH DAMAGE.
*End copyright
*
- * $Id: scsi_ioctl.c,v 1.9 1995/01/08 13:38:32 dufault Exp $
+ * $Id: scsi_ioctl.c,v 1.10 1995/01/19 12:41:36 dufault Exp $
*
*
*/
@@ -242,8 +242,8 @@ void scsiminphys(struct buf *bp)
* If user-level type command, we must still be running
* in the context of the calling process
*/
-errval scsi_do_ioctl(dev_t dev,
-struct scsi_link *sc_link, int cmd, caddr_t addr, int f)
+errval scsi_do_ioctl(dev_t dev, int cmd, caddr_t addr, int f,
+struct scsi_link *sc_link)
{
errval ret = 0;
diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c
index 52152b3..c65a774 100644
--- a/sys/scsi/scsiconf.c
+++ b/sys/scsi/scsiconf.c
@@ -14,7 +14,9 @@
*
* Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
*
- * $Id: scsiconf.c,v 1.18 1995/01/08 13:38:33 dufault Exp $
+ * New configuration setup: dufault@hda.com
+ *
+ * $Id: scsiconf.c,v 1.19 1995/02/14 06:18:06 phk Exp $
*/
#include <sys/types.h>
@@ -27,68 +29,92 @@
#include <sys/conf.h>
#include <machine/clock.h>
-#include "st.h"
+#include "scbus.h"
+
#include "sd.h"
-#include "ch.h"
+#include "st.h"
#include "cd.h"
-#include "uk.h"
-#include "su.h"
-
-#include "scbus.h"
-/* If we have any at all, we want at least 8 */
-#if NSCBUS > 0
-#if NSCBUS < 8
-#undef NSCBUS
-#endif /* NSCBUS < 8 */
-#endif /* NSCBUS > 0 */
+#include "ch.h"
-#ifndef NSCBUS
-#define NSCBUS 8
-#endif /* NSCBUS */
+#include "su.h"
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
-#ifdef TFS
-#include "bll.h"
-#include "cals.h"
-#include "kil.h"
-#include "scan.h"
-#else /* TFS */
-#define NBLL 0
-#define NCALS 0
-#define NKIL 0
-#define NSCAN 0
-#endif /* TFS */
+/* Extensible arrays: Use a realloc like implementation to permit
+ * the arrays to be extend. These are set up to be moved out
+ * of this file if needed elsewhere.
+ */
+struct extend_array
+{
+ int nelem;
+ void **ps;
+};
-#if NSD > 0
-extern sdattach();
-#endif /* NSD */
-#if NST > 0
-extern stattach();
-#endif /* NST */
-#if NCH > 0
-extern chattach();
-#endif /* NCH */
-#if NCD > 0
-extern cdattach();
-#endif /* NCD */
-#if NBLL > 0
-extern bllattach();
-#endif /* NBLL */
-#if NCALS > 0
-extern calsattach();
-#endif /* NCALS */
-#if NKIL > 0
-extern kil_attach();
-#endif /* NKIL */
-#if NUK > 0
-extern ukattach();
-#endif /* NUK */
-
-errval scsi_probe_bus(int, int, int);
+static void *extend_alloc(size_t s)
+{
+ void *p = malloc(s, M_DEVBUF, M_NOWAIT);
+ if (!p)
+ panic("extend_alloc: malloc failed.");
+ return p;
+}
+
+static void extend_free(void *p) { free(p, M_DEVBUF); }
+
+#define EXTEND_CHUNK 8
+
+struct extend_array *extend_new(void)
+{
+ struct extend_array *p = extend_alloc(sizeof(*p));
+ p->nelem = 0;
+ p->ps = 0;
+
+ return p;
+}
+
+void *extend_set(struct extend_array *ea, int index, void *value)
+{
+ if (index >= ea->nelem) {
+ void **space;
+ space = extend_alloc(sizeof(void *) * (index + EXTEND_CHUNK));
+ bzero(space, sizeof(void *) * (index + EXTEND_CHUNK));
+
+ /* Make sure we have something to copy before we copy it */
+ if (ea->nelem) {
+ bcopy(ea->ps, space, sizeof(void *) * ea->nelem);
+ extend_free(ea->ps);
+ }
+
+ ea->ps = space;
+ ea->nelem = index + EXTEND_CHUNK;
+ }
+ if (ea->ps[index]) {
+ printf("extend_set: entry %d already has storage.\n", index);
+ return 0;
+ }
+ else
+ ea->ps[index] = value;
+
+ return value;
+}
+
+void *extend_get(struct extend_array *ea, int index)
+{
+ if (index >= ea->nelem || index < 0)
+ return 0;
+ return ea->ps[index];
+}
+
+void extend_release(struct extend_array *ea, int index)
+{
+ void *p = extend_get(ea, index);
+ if (p) {
+ ea->ps[index] = 0;
+ }
+}
/*
+ * This extend_array holds an array of "scsibus_data" pointers.
* One of these is allocated and filled in for each scsi bus.
* it holds pointers to allow the scsi bus to get to the driver
* That is running each LUN on the bus
@@ -96,33 +122,8 @@ errval scsi_probe_bus(int, int, int);
* supplied by the adapter driver, this is used to initialise
* the others, before they have the rest of the fields filled in
*/
-struct scsibus_data *scbus_data[NSCBUS];
-
-/*
- * The structure of pre-configured devices that might be turned
- * off and therefore may not show up
- */
-struct predefined {
- u_char scsibus;
- u_char dev;
- u_char lu;
- errval(*attach_rtn) ();
- char *devname;
- char flags;
-} pd[] =
-{
-#ifdef EXAMPLE_PREDEFINE
-#if NSD > 0
- {
- 0, 0, 0, sdattach, "sd", 0
- }, /* define a disk at scsibus=0 dev=0 lu=0 */
-#endif /* NSD */
-#endif /* EXAMPLE_PREDEFINE */
- {
- 0, 9, 9
- } /*illegal dummy end entry */
-};
+struct extend_array *scbusses;
/*
* The structure of known drivers for autoconfiguration
@@ -133,7 +134,6 @@ struct scsidevs {
char *manufacturer;
char *model;
char *version;
- errval(*attach_rtn) ();
char *devname;
char flags; /* 1 show my comparisons during boot(debug) */
#ifdef NEW_SCSICONF
@@ -146,13 +146,11 @@ struct scsidevs {
#define SC_ONE_LU 0x00
#define SC_MORE_LUS 0x02
-#if NUK > 0
static struct scsidevs unknowndev =
{
- -1, 0, "*", "*", "*",
- ukattach, "uk", SC_MORE_LUS
+ T_UNKNOWN, 0, "*", "*", "*",
+ "uk", SC_MORE_LUS
};
-#endif /*NUK*/
#ifdef NEW_SCSICONF
static st_modes mode_tandberg3600 =
@@ -205,75 +203,57 @@ static struct scsidevs knowndevs[] =
#if NSD > 0
{
T_DIRECT, T_FIXED, "MAXTOR", "XT-4170S", "B5A",
- sdattach, "mx1", SC_ONE_LU
+ "mx1", SC_ONE_LU
},
{
T_DIRECT, T_FIXED, "*", "*", "*",
- sdattach, "sd", SC_ONE_LU
+ "sd", SC_ONE_LU
},
#endif /* NSD */
#if NST > 0
{
T_SEQUENTIAL, T_REMOV, "TANDBERG", " TDC 3600", "*",
- stattach, "st", SC_ONE_LU, ST_Q_NEEDS_PAGE_0, mode_tandberg3600
+ "st", SC_ONE_LU, ST_Q_NEEDS_PAGE_0, mode_tandberg3600
},
{
T_SEQUENTIAL, T_REMOV, "ARCHIVE", "VIPER 2525*", "-005",
- stattach, "st", SC_ONE_LU, 0, mode_archive2525
+ "st", SC_ONE_LU, 0, mode_archive2525
},
{
T_SEQUENTIAL, T_REMOV, "ARCHIVE", "VIPER 150", "*",
- stattach, "st", SC_ONE_LU, ST_Q_NEEDS_PAGE_0, mode_archive150
+ "st", SC_ONE_LU, ST_Q_NEEDS_PAGE_0, mode_archive150
},
{
T_SEQUENTIAL, T_REMOV, "WANGTEK", "5525ES*", "*",
- stattach, "st", SC_ONE_LU, 0, mode_wangtek5525
+ "st", SC_ONE_LU, 0, mode_wangtek5525
},
{
T_SEQUENTIAL, T_REMOV, "WangDAT", "Model 1300", "*",
- stattach, "st", SC_ONE_LU, 0, mode_wangdat1300
+ "st", SC_ONE_LU, 0, mode_wangdat1300
},
{
T_SEQUENTIAL, T_REMOV, "*", "*", "*",
- stattach, "st", SC_ONE_LU, 0, mode_unktape
+ "st", SC_ONE_LU, 0, mode_unktape
},
#endif /* NST */
-#if NCALS > 0
- {
- T_PROCESSOR, T_FIXED, "*", "*", "*",
- calsattach, "cals", SC_MORE_LUS
- },
-#endif /* NCALS */
#if NCH > 0
{
T_CHANGER, T_REMOV, "*", "*", "*",
- chattach, "ch", SC_ONE_LU
+ "ch", SC_ONE_LU
},
#endif /* NCH */
#if NCD > 0
#ifndef UKTEST /* make cdroms unrecognised to test the uk driver */
{
T_READONLY, T_REMOV, "SONY", "CD-ROM CDU-8012", "3.1a",
- cdattach, "cd", SC_ONE_LU
+ "cd", SC_ONE_LU
},
{
T_READONLY, T_REMOV, "PIONEER", "CD-ROM DRM-600", "*",
- cdattach, "cd", SC_MORE_LUS
+ "cd", SC_MORE_LUS
},
#endif
#endif /* NCD */
-#if NBLL > 0
- {
- T_PROCESSOR, T_FIXED, "AEG", "READER", "V1.0",
- bllattach, "bll", SC_MORE_LUS
- },
-#endif /* NBLL */
-#if NKIL > 0
- {
- T_SCANNER, T_FIXED, "KODAK", "IL Scanner 900", "*",
- kil_attach, "kil", SC_ONE_LU
- },
-#endif /* NKIL */
{
0
}
@@ -283,56 +263,37 @@ static struct scsidevs knowndevs[] =
#if NSD > 0
{
T_DIRECT, T_FIXED, "standard", "any"
- ,"any", sdattach, "sd", SC_ONE_LU
+ ,"any", "sd", SC_ONE_LU
},
{
T_DIRECT, T_FIXED, "MAXTOR ", "XT-4170S "
- ,"B5A ", sdattach, "mx1", SC_ONE_LU
+ ,"B5A ", "mx1", SC_ONE_LU
},
#endif /* NSD */
#if NST > 0
{
T_SEQUENTIAL, T_REMOV, "standard", "any"
- ,"any", stattach, "st", SC_ONE_LU
+ ,"any", "st", SC_ONE_LU
},
#endif /* NST */
-#if NCALS > 0
- {
- T_PROCESSOR, T_FIXED, "standard", "any"
- ,"any", calsattach, "cals", SC_MORE_LUS
- },
-#endif /* NCALS */
#if NCH > 0
{
T_CHANGER, T_REMOV, "standard", "any"
- ,"any", chattach, "ch", SC_ONE_LU
+ ,"any", "ch", SC_ONE_LU
},
#endif /* NCH */
#if NCD > 0
#ifndef UKTEST /* make cdroms unrecognised to test the uk driver */
{
T_READONLY, T_REMOV, "SONY ", "CD-ROM CDU-8012 "
- ,"3.1a", cdattach, "cd", SC_ONE_LU
+ ,"3.1a", "cd", SC_ONE_LU
},
{
T_READONLY, T_REMOV, "PIONEER ", "CD-ROM DRM-600 "
- ,"any", cdattach, "cd", SC_MORE_LUS
+ ,"any", "cd", SC_MORE_LUS
},
#endif
#endif /* NCD */
-#if NBLL > 0
- {
- T_PROCESSOR, T_FIXED, "AEG ", "READER "
- ,"V1.0", bllattach, "bll", SC_MORE_LUS
- },
-#endif /* NBLL */
-#if NKIL > 0
- {
- T_SCANNER, T_FIXED, "KODAK ", "IL Scanner 900 "
- ,"any", kil_attach, "kil", SC_ONE_LU
- },
-#endif /* NKIL */
-
{
0
}
@@ -342,34 +303,35 @@ static struct scsidevs knowndevs[] =
/*
* Declarations
*/
-struct predefined *scsi_get_predef();
struct scsidevs *scsi_probedev();
-struct scsidevs *selectdev();
+struct scsidevs *scsi_selectdev();
+errval scsi_probe_bus(int bus, int targ, int lun);
-struct scsi_device probe_switch =
+/* XXX dufault@hda.com
+ * This scsi_device doesn't have the scsi_data_size.
+ * This is used during probe and used to be "probe_switch".
+ */
+struct scsi_device inval_switch =
{
NULL,
NULL,
NULL,
NULL,
- "probe",
+ "??",
0,
- { 0, 0 }
+ {0, 0},
+ NULL,
+ 0
};
/*
- * controls debug level within the scsi subsystem -
- * see scsiconf.h for values
- */
-int32 scsibus = 0x0; /* This is the Nth scsibus we've seen */
-
-/*
* XXX
* This is BOGUS.
* We do this because it was easier than adding the requisite information
* to the scsi_link structure and modifying everything to use that.
* Someday, we will do just that, and users will be able to nail down their
* preferred SCSI ids.
+ *
*/
struct kern_devconf kdc_scbus0 = {
0, 0, 0, /* filled in by dev_attach */
@@ -381,6 +343,207 @@ struct kern_devconf kdc_scbus0 = {
"SCSI subsystem"
};
+static int free_bus; /* First bus not wired down */
+
+extern void ukinit();
+
+static struct scsi_device *device_list;
+static int next_free_type = T_NTYPES;
+
+/* Register new functions at the head of the list. That allows
+ * you to replace a standard driver with a new one.
+ *
+ * You can't register the exact device (the same in memory structure)
+ * more than once - the list links are part of the structure. That is
+ * prevented.
+ *
+ * Unusual devices should always be registered as type "-1". Then
+ * the next available type number will be allocated for it.
+ *
+ * Be careful not to register a type as 0 unless you really mean to
+ * replace the disk driver.
+ */
+
+void
+scsi_device_register(struct scsi_device *sd)
+{
+ /* Not only is it pointless to add the same device more than once
+ * but it will also screw up the list.
+ */
+ struct scsi_device *is_there;
+ for (is_there = device_list; is_there; is_there = is_there->next)
+ if (is_there == sd)
+ return;
+
+ if (sd->type == -1)
+ sd->type = next_free_type++;
+
+ sd->next = device_list;
+ device_list = sd;
+
+ if (sd->links == 0)
+ sd->links = extend_new();
+}
+
+static struct scsi_device *
+scsi_device_lookup(int type)
+{
+ extern struct scsi_device uk_switch;
+ struct scsi_device *sd;
+
+ for (sd = device_list; sd; sd = sd->next)
+ if (sd->type == type)
+ return sd;
+
+ return &uk_switch;
+}
+
+static struct scsi_device *
+scsi_device_lookup_by_name(char *name)
+{
+ extern struct scsi_device uk_switch;
+ struct scsi_device *sd;
+
+ for (sd = device_list; sd; sd = sd->next)
+ if (strcmp(sd->name, name) == 0)
+ return sd;
+
+ return &uk_switch;
+}
+
+/* Macro that lets us know something is specified.
+ */
+#define IS_SPECIFIED(ARG) (ARG != SCCONF_UNSPEC && ARG != SCCONF_ANY)
+
+/* scsi_init: Do all the one time processing. This initializes the
+ * type drivers and initializes the configuration.
+ */
+static void
+scsi_init(void)
+{
+ static int done = 0;
+ if(!done) {
+ int i;
+
+ done = 1;
+
+ scbusses = extend_new();
+
+ dev_attach(&kdc_scbus0);
+
+ /* First call all type initialization functions.
+ */
+ ukinit();
+
+ for (i = 0; scsi_tinit[i]; i++)
+ (*scsi_tinit[i])();
+
+ /* Lowest free bus for auto-configure is one
+ * more than the first one not
+ * specified in config:
+ */
+ for (i = 0; scsi_cinit[i].driver; i++)
+ if (IS_SPECIFIED(scsi_cinit[i].unit) &&
+ free_bus <= scsi_cinit[i].unit)
+ free_bus = scsi_cinit[i].unit + 1;
+
+ /* Lowest free unit for each type for auto-configure is one
+ * more than the first one not specified in the config file:
+ */
+ for (i = 0; scsi_dinit[i].name; i++) {
+ struct scsi_device_config *sdc = scsi_dinit + i;
+ struct scsi_device *sd =
+ scsi_device_lookup_by_name(sdc->name);
+
+ /* This is a little tricky: We don't want "sd 4" to match as
+ * a wired down device, but we do want "sd 4 target 5" or
+ * even "sd 4 scbus 1" to match.
+ */
+ if (IS_SPECIFIED(sdc->unit) &&
+ (IS_SPECIFIED(sdc->target) || IS_SPECIFIED(sdc->cunit)) &&
+ sd->free_unit <= sdc->unit)
+ sd->free_unit = sdc->unit + 1;
+ }
+ }
+}
+
+/* Feel free to take this out when everyone is sure this config
+ * code works well:
+ */
+#define CONFIGD() printf(" config'd at ")
+
+/* scsi_bus_conf: Figure out which bus this is. If it is wired in config
+ * use that. Otherwise use the next free one.
+ */
+static int
+scsi_bus_conf(sc_link_proto)
+ struct scsi_link *sc_link_proto;
+{
+ int i;
+ int bus;
+
+ /* Which bus is this? Try to find a match in the "scsi_cinit"
+ * table. If it isn't wired down auto-configure it at the
+ * next available bus.
+ */
+
+ printf("scbus");
+ bus = SCCONF_UNSPEC;
+ for (i = 0; scsi_cinit[i].driver; i++) {
+ if (IS_SPECIFIED(scsi_cinit[i].unit))
+ {
+ if (!strcmp(sc_link_proto->adapter->name, scsi_cinit[i].driver) &&
+ (sc_link_proto->adapter_unit == scsi_cinit[i].unit) )
+ {
+ CONFIGD();
+ bus = scsi_cinit[i].bus;
+ break;
+ }
+ }
+ }
+
+ if (bus == SCCONF_UNSPEC)
+ bus = free_bus++;
+
+ printf("%d: ", bus);
+
+ return bus;
+}
+
+/* scsi_assign_unit: Look through the structure generated by config.
+ * See if there is a fixed assignment for this unit. If there isn't,
+ * assign the next free unit.
+ */
+static int
+scsi_assign_unit(struct scsi_link *sc_link)
+{
+ int i;
+ int found;
+ printf("%s", sc_link->device->name);
+ found = 0;
+ for (i = 0; scsi_dinit[i].name; i++) {
+ if ((strcmp(sc_link->device->name, scsi_dinit[i].name) == 0) &&
+ sc_link->target == scsi_dinit[i].target &&
+ (
+ (sc_link->lun == scsi_dinit[i].lun) ||
+ (sc_link->lun == 0 && scsi_dinit[i].lun == SCCONF_UNSPEC)
+ ) &&
+ sc_link->scsibus == scsi_dinit[i].cunit) {
+ CONFIGD();
+ sc_link->dev_unit = scsi_dinit[i].unit;
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ sc_link->dev_unit = sc_link->device->free_unit++;
+
+ printf("%d: ", sc_link->dev_unit);
+
+ return sc_link->dev_unit;
+}
+
/*
* The routine called by the adapter boards to get all their
* devices configured in.
@@ -389,22 +552,21 @@ void
scsi_attachdevs(sc_link_proto)
struct scsi_link *sc_link_proto;
{
- static int timesthru = 0;
- if(!timesthru++) {
- dev_attach(&kdc_scbus0);
- }
+ int scsibus;
+ struct scsibus_data *scbus;
+
+ scsi_init();
- if(scsibus >= NSCBUS) {
- printf("too many scsi busses, reconfigure the kernel\n");
+ if ( (scsibus = scsi_bus_conf(sc_link_proto)) == -1) {
return;
}
sc_link_proto->scsibus = scsibus;
- scbus_data[scsibus] = malloc(sizeof(struct scsibus_data), M_TEMP, M_NOWAIT);
- if(!scbus_data[scsibus]) {
+ scbus = malloc(sizeof(struct scsibus_data), M_TEMP, M_NOWAIT);
+ if(scbus == 0 || extend_set(scbusses, scsibus, scbus) == 0) {
panic("scsi_attachdevs: malloc\n");
}
- bzero(scbus_data[scsibus], sizeof(struct scsibus_data));
- scbus_data[scsibus]->adapter_link = sc_link_proto;
+ bzero(scbus, sizeof(struct scsibus_data));
+ scbus->adapter_link = sc_link_proto;
#if defined(SCSI_DELAY) && SCSI_DELAY > 2
printf("%s%d waiting for scsi devices to settle\n",
sc_link_proto->adapter->name, sc_link_proto->adapter_unit);
@@ -413,8 +575,7 @@ scsi_attachdevs(sc_link_proto)
#define SCSI_DELAY 2
#endif /* SCSI_DELAY */
DELAY(1000000 * SCSI_DELAY);
- scsibus++;
- scsi_probe_bus(scsibus - 1,-1,-1);
+ scsi_probe_bus(scsibus,-1,-1);
}
/*
@@ -426,7 +587,7 @@ errval
scsi_probe_busses(int bus, int targ, int lun)
{
if (bus == -1) {
- for(bus = 0; bus < scsibus; bus++) {
+ for(bus = 0; bus < scbusses->nelem; bus++) {
scsi_probe_bus(bus, targ, lun);
}
return 0;
@@ -435,6 +596,65 @@ scsi_probe_busses(int bus, int targ, int lun)
}
}
+/* scsi_alloc_unit: Register a scsi_data pointer for a given
+ * unit in a given scsi_device structure.
+ *
+ * XXX dufault@hda.com: I still don't like the way this reallocs stuff -
+ * but at least now it is collected in one place instead of existing
+ * in multiple type drivers. I'd like it better if we had it do a
+ * second pass after it knew the sizes of everything and set up everything
+ * at once.
+ */
+static int
+scsi_alloc_unit(struct scsi_link *sc_link)
+{
+ u_int32 unit;
+ struct scsi_link **strealloc;
+ struct scsi_data *sd;
+ struct scsi_device *dsw;
+
+ unit = sc_link->dev_unit;
+ dsw = sc_link->device;
+
+ /*
+ * allocate the per unit data area
+ */
+ if (dsw->sizeof_scsi_data)
+ {
+ sd = malloc(dsw->sizeof_scsi_data, M_DEVBUF, M_NOWAIT);
+ if (!sd) {
+ printf("%s%ld: malloc failed for scsi_data\n",
+ sc_link->device->name, unit);
+ return 0;
+ }
+ bzero(sd, dsw->sizeof_scsi_data);
+ }
+ else
+ sd = 0;
+
+ sc_link->sd = sd;
+
+ if (extend_set(dsw->links, unit, (void *)sc_link) == 0) {
+ printf("%s%ld: Can't store link pointer.\n",
+ sc_link->device->name, unit);
+ free(sd, M_DEVBUF);
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+scsi_free_unit(struct scsi_link *sc_link)
+{
+ if (sc_link->sd)
+ {
+ free(sc_link->sd, M_DEVBUF);
+ sc_link->sd = 0;
+ }
+ extend_release(sc_link->device->links, sc_link->dev_unit);
+}
+
/*
* Probe the requested scsi bus. It must be already set up.
* targ and lun optionally narrow the search if not -1
@@ -447,14 +667,13 @@ scsi_probe_bus(int bus, int targ, int lun)
struct scsi_link *sc_link_proto;
u_int8 scsi_addr ;
struct scsidevs *bestmatch = NULL;
- struct predefined *predef = NULL;
struct scsi_link *sc_link = NULL;
boolean maybe_more;
- if ((bus < 0 ) || ( bus >= scsibus)) {
+ if ((bus < 0 ) || ( bus >= scbusses->nelem)) {
return ENXIO;
}
- scsi = scbus_data[bus];
+ scsi = (struct scsibus_data *)extend_get(scbusses, bus);
if(!scsi) return ENXIO;
sc_link_proto = scsi->adapter_link;
scsi_addr = sc_link_proto->adapter_targ;
@@ -474,7 +693,6 @@ scsi_probe_bus(int bus, int targ, int lun)
maxlun = minlun = lun;
}
-
for ( targ = mintarg;targ <= maxtarg; targ++) {
maybe_more = 0; /* by default only check 1 lun */
if (targ == scsi_addr) {
@@ -496,14 +714,13 @@ scsi_probe_bus(int bus, int targ, int lun)
*/
if (!sc_link) {
sc_link = malloc(sizeof(*sc_link), M_TEMP, M_NOWAIT);
- *sc_link = *sc_link_proto; /* struct copy */
- sc_link->opennings = 1;
- sc_link->device = &probe_switch;
}
+ *sc_link = *sc_link_proto; /* struct copy */
+ sc_link->opennings = 1;
+ sc_link->device = &inval_switch;
sc_link->target = targ;
sc_link->lun = lun;
sc_link->quirks = 0;
- predef = scsi_get_predef(sc_link, &maybe_more);
bestmatch = scsi_probedev(sc_link, &maybe_more);
#ifdef NEW_SCSICONF
if (bestmatch) {
@@ -514,36 +731,24 @@ scsi_probe_bus(int bus, int targ, int lun)
sc_link->devmodes = NULL;
}
#endif
- if ((bestmatch) && (predef)) { /* both exist */
- if (bestmatch->attach_rtn
- != predef->attach_rtn) {
- printf("Clash in found/expected devices\n");
-#if NUK > 0
- if(bestmatch == &unknowndev) {
- printf("will link in PREDEFINED\n");
- (*(predef->attach_rtn)) (sc_link);
- } else
-#endif /*NUK*/
- {
- printf("will link in FOUND\n");
- (*(bestmatch->attach_rtn)) (sc_link);
+ if (bestmatch) { /* FOUND */
+ sc_link->device = scsi_device_lookup(bestmatch->type);
+
+ (void)scsi_assign_unit(sc_link);
+
+ if (scsi_alloc_unit(sc_link)) {
+
+ if (scsi_device_attach(sc_link) == 0) {
+ scsi->sc_link[targ][lun] = sc_link;
+ sc_link = NULL; /* it's been used */
}
- } else {
- (*(bestmatch->attach_rtn)) (sc_link);
+ else
+ scsi_free_unit(sc_link);
}
}
- if ((bestmatch) && (!predef)) { /* just FOUND */
- (*(bestmatch->attach_rtn)) (sc_link);
- }
- if ((!bestmatch) && (predef)) { /* just predef */
- (*(predef->attach_rtn)) (sc_link);
- }
- if ((bestmatch) || (predef)) { /* one exists */
- scsi->sc_link[targ][lun] = sc_link;
- sc_link = NULL; /* it's been used */
- }
+
if (!(maybe_more)) { /* nothing suggests we'll find more */
- break; /* nothing here, skip to next targ */
+ break; /* nothing here, skip to next targ */
}
/* otherwise something says we should look further */
}
@@ -562,47 +767,10 @@ scsi_link_get(bus, targ, lun)
int targ;
int lun;
{
- struct scsibus_data *scsi = scbus_data[bus];
+ struct scsibus_data *scsi =
+ (struct scsibus_data *)extend_get(scbusses, bus);
return (scsi) ? scsi->sc_link[targ][lun] : 0;
}
-
-/*
- * given a target and lu, check if there is a predefined device for
- * that address
- */
-struct predefined *
-scsi_get_predef(sc_link, maybe_more)
- struct scsi_link *sc_link;
- boolean *maybe_more;
-{
- u_int8 unit = sc_link->scsibus;
- u_int8 target = sc_link->target;
- u_int8 lu = sc_link->lun;
- struct scsi_adapter *scsi_adapter = sc_link->adapter;
- u_int32 upto, numents;
-
- numents = (sizeof(pd) / sizeof(struct predefined)) - 1;
-
- for (upto = 0; upto < numents; upto++) {
- if (pd[upto].scsibus != unit)
- continue;
- if (pd[upto].dev != target)
- continue;
- if (pd[upto].lu != lu)
- continue;
-
- printf("%s%d targ %d lun %d: <%s> - PRECONFIGURED -\n"
- ,scsi_adapter->name
- ,unit
- ,target
- ,lu
- ,pd[upto].devname);
- *maybe_more = pd[upto].flags & SC_MORE_LUS;
- return (&(pd[upto]));
- }
- return ((struct predefined *) 0);
-}
-
/*
* given a target and lu, ask the device what
* it is, and find the correct driver table
@@ -709,45 +877,13 @@ scsi_probedev(sc_link, maybe_more)
*maybe_more = 1;
break;
}
+
if (dtype == 0) {
- switch ((int)type) {
- case T_DIRECT:
- dtype = "direct";
- break;
- case T_SEQUENTIAL:
- dtype = "sequential";
- break;
- case T_PRINTER:
- dtype = "printer";
- break;
- case T_PROCESSOR:
- dtype = "processor";
- break;
- case T_READONLY:
- dtype = "readonly";
- break;
- case T_WORM:
- dtype = "worm";
- break;
- case T_SCANNER:
- dtype = "scanner";
- break;
- case T_OPTICAL:
- dtype = "optical";
- break;
- case T_CHANGER:
- dtype = "changer";
- break;
- case T_COMM:
- dtype = "communication";
- break;
- case T_NODEVICE:
+ if (type == T_NODEVICE) {
*maybe_more = 1;
return (struct scsidevs *) 0;
- default:
- dtype = "unknown";
- break;
}
+ dtype = scsi_type_long_name(type);
}
/*
* Then if it's advanced enough, more detailed
@@ -813,12 +949,12 @@ scsi_probedev(sc_link, maybe_more)
* Try make as good a match as possible with
* available sub drivers
*/
- bestmatch = (selectdev(
+ bestmatch = (scsi_selectdev(
qualifier, type, remov ? T_REMOV : T_FIXED, manu, model, version));
if ((bestmatch) && (bestmatch->flags & SC_MORE_LUS)) {
*maybe_more = 1;
}
- return (bestmatch);
+ return bestmatch;
}
/* Try to find the major number for a device during attach.
@@ -871,7 +1007,7 @@ match(pattern, name)
* available sub drivers
*/
struct scsidevs *
-selectdev(qualifier, type, remov, manu, model, rev)
+scsi_selectdev(qualifier, type, remov, manu, model, rev)
u_int32 qualifier, type;
boolean remov;
char *manu, *model, *rev;
@@ -966,11 +1102,10 @@ selectdev(qualifier, type, remov, manu, model, rev)
}
#endif /* NEW_SCSICONF */
if (bestmatch == (struct scsidevs *) 0) {
-#if NUK > 0
+ /* XXX At this point we should default to a base type driver.
+ */
+ printf("No explicit driver match. Attaching as unknown.\n");
bestmatch = &unknowndev;
-#else
- printf("No explicit device driver match.\n");
-#endif
}
return (bestmatch);
}
@@ -985,3 +1120,43 @@ scsi_externalize(struct scsi_link *sl, void *userp, size_t *lenp)
return copyout(sl, userp, sizeof *sl);
}
+
+/* XXX dufault@hda.com:
+ * having this table of names conflicts with our decision
+ * that all type information be contained in a type driver.
+ */
+static struct {char *name; char *long_name; } types[] = {
+ { "sd", "direct" },
+ { "st", "sequential" },
+ { "prn", "printer" },
+ { "proc", "processor" },
+ { "worm", "worm" },
+ { "cd", "readonly" },
+ { "scan", "scanner" },
+ { "opmem", "optical" },
+ { "ch", "changer" },
+ { "comm", "communication" },
+ { "asc0", "ASC-0" },
+ { "asc1", "ASC-1" },
+ { "uk", "unknown" },
+ { "inval", "invalid" },
+};
+
+char *
+scsi_type_name(int type)
+{
+ if (type >= 0 && type < (sizeof(types) / sizeof(types[0])))
+ return types[type].name;
+
+ return "inval";
+}
+
+char *
+scsi_type_long_name(int type)
+{
+ if (type >= 0 && type < (sizeof(types) / sizeof(types[0])))
+ return types[type].long_name;
+
+ return "invalid";
+}
+
diff --git a/sys/scsi/scsiconf.h b/sys/scsi/scsiconf.h
index 5519d42..50faf12 100644
--- a/sys/scsi/scsiconf.h
+++ b/sys/scsi/scsiconf.h
@@ -14,7 +14,7 @@
*
* Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
*
- * $Id: scsiconf.h,v 1.16 1995/01/31 11:41:45 dufault Exp $
+ * $Id: scsiconf.h,v 1.17 1995/02/14 06:17:23 phk Exp $
*/
#ifndef SCSI_SCSICONF_H
#define SCSI_SCSICONF_H 1
@@ -29,6 +29,7 @@ typedef unsigned char u_int8;
#include <scsi/scsi_debug.h>
#include <scsi/scsi_all.h>
+#include <scsi/scsi_driver.h>
/* Minor number fields:
*
@@ -140,22 +141,131 @@ struct scsi_adapter
#define AD_INF_MAX_CMDS 0x000000FF
/* 24 bits of other adapter characteristics go here */
+/* Don't poke around inside of "scsi_data". Each low level
+ * driver has its own definition for it.
+ */
+struct scsi_data;
+
+struct scsi_link; /* scsi_link refers to scsi_device and vice-versa */
+struct scsi_xfer;
/*
* These entry points are called by the low-end drivers to get services from
* whatever high-end drivers they are attached to. Each device type has one
* of these statically allocated.
+ *
+ * XXX dufault@hda.com: Each adapter driver has a scsi_device structure
+ * that I don't think should be there.
+ * This structure should be rearranged and cleaned up once the
+ * instance down in the adapter drivers is removed.
*/
+
struct scsi_device
{
-/* 4*/ errval (*err_handler)(); /* returns -1 to say err processing complete */
-/* 8*/ void (*start)();
+/* 4*/ errval (*err_handler)(struct scsi_xfer *xs); /* return -1 to say
+ * err processing complete */
+/* 8*/ void (*start)(u_int32 unit);
/* 12*/ int32 (*async)();
/* 16*/ int32 (*done)(); /* returns -1 to say done processing complete */
/* 20*/ char *name; /* name of device type */
/* 24*/ u_int32 flags; /* device type dependent flags */
/* 32*/ int32 spare[2];
+
+/* 36*/ int32 link_flags; /* Flags OR'd into sc_link at attach time */
+/* 40*/ errval (*attach)(struct scsi_link *sc_link);
+/* 44*/ int (*open)(dev_t dev, int flags);
+/* 48*/ int sizeof_scsi_data;
+/* 52*/ int type; /* Type of device this supports */
+/* 56*/ int (*getunit)(dev_t dev);
+/* 60*/ dev_t (*setunit)(dev_t dev, int unit);
+
+/* 64*/ errval (*dev_open)(dev_t dev, int flags, struct scsi_link *sc_link);
+/* 68*/ errval (*dev_ioctl)(dev_t dev, int cmd, caddr_t arg, int mode,
+ struct scsi_link *sc_link);
+/* 72*/ errval (*dev_close)(dev_t dev, struct scsi_link *sc_link);
+/* 76*/ void (*dev_strategy)(struct buf *bp, struct scsi_link *sc_link);
+
+ /* Not initialized after this */
+
+#define SCSI_LINK(DEV, UNIT) ( \
+ (struct scsi_link *)(extend_get((DEV)->links, (UNIT))) \
+ )
+
+#define SCSI_DATA(DEV, UNIT) ( \
+ (SCSI_LINK((DEV), (UNIT)) ? \
+ (SCSI_LINK((DEV), (UNIT))->sd) : \
+ (struct scsi_data *)0) \
+ )
+
+/* 80*/ struct extend_array *links;
+
+/* 84*/ int free_unit;
+/* 88*/ struct scsi_device *next; /* Next in list in the registry. */
};
+/* SCSI_DEVICE_ENTRIES: A macro to generate all the entry points from the
+ * name.
+ */
+#define SCSI_DEVICE_ENTRIES(NAME) \
+errval NAME##attach(struct scsi_link *sc_link); \
+extern struct scsi_device NAME##_switch; \
+void NAME##init(void) \
+{ \
+ scsi_device_register(&NAME##_switch); \
+} \
+errval NAME##open(dev_t dev, int flags) \
+{ \
+ return scsi_open(dev, flags, &NAME##_switch); \
+} \
+errval NAME##ioctl(dev_t dev, int cmd, caddr_t addr, int flag) \
+{ \
+ return scsi_ioctl(dev, cmd, addr, flag, &NAME##_switch); \
+} \
+errval NAME##close(dev_t dev) \
+{ \
+ return scsi_close(dev, &NAME##_switch); \
+} \
+void NAME##minphys(struct buf *bp) \
+{ \
+ scsi_minphys(bp, &NAME##_switch); \
+} \
+void NAME##strategy(struct buf *bp) \
+{ \
+ scsi_strategy(bp, &NAME##_switch); \
+}
+
+#ifdef KERNEL
+/* Configuration tables for config.
+ */
+/* A unit, type, etc can be SCCONF_ANY to indicate it is a '?'
+ * in the config.
+ */
+#define SCCONF_UNSPEC -1
+#define SCCONF_ANY -2
+
+struct isa_driver;
+struct scsi_ctlr_config
+{
+ int bus;
+ char *driver;
+ int unit;
+};
+
+struct scsi_device_config
+{
+ char *name; /* SCSI device name (sd, st, etc) */
+ int unit; /* desired device unit */
+ int cunit; /* Controller unit */
+ int target; /* SCSI ID (target) */
+ int lun; /* SCSI lun */
+ int flags; /* Flags from config */
+};
+
+extern void (*scsi_tinit[])(void);
+extern struct scsi_ctlr_config scsi_cinit[];
+extern struct scsi_device_config scsi_dinit[];
+
+#endif
+
#ifdef NEW_SCSICONF
/*
* Define various devices that we know mis-behave in some way,
@@ -222,13 +332,24 @@ struct scsi_link
/* 28*/ void * fordriver; /* for private use by the driver */
/* 32*/ void * devmodes; /* device specific mode tables */
/* 36*/ dev_t dev; /* Device major number (character) */
-/* 40+*/struct scsi_inquiry_data inqbuf; /* Inquiry data */
+/* 40*/ struct scsi_data *sd; /* Device data structure */
+/* 44+*/struct scsi_inquiry_data inqbuf; /* Inquiry data */
};
-#define SDEV_MEDIA_LOADED 0x01 /* device figures are still valid */
-#define SDEV_WAITING 0x02 /* a process is waiting for this */
-#define SDEV_OPEN 0x04 /* at least 1 open session */
-#define SDEV_BOUNCE 0x08 /* unit requires DMA bounce buffer */
-#define SDEV_DBX 0xF0 /* debuging flags (scsi_debug.h) */
+#define SDEV_MEDIA_LOADED 0x00000001 /* device figures are still valid */
+#define SDEV_WAITING 0x00000002 /* a process is waiting for this */
+#define SDEV_OPEN 0x00000004 /* at least 1 open session */
+
+/* XXX dufault@hda.com: SDEV_BOUNCE is set down in the adapter drivers
+ * in an sc_link structure to indicate that this host adapter requires
+ * ISA DMA bounce buffers. I think eventually the link structure should
+ * be associated only with the type drive and not the adapter driver,
+ * and the bounce flag should be in something associated with the
+ * adapter driver.
+ */
+#define SDEV_BOUNCE 0x00000008 /* unit requires DMA bounce buffer */
+
+#define SDEV_DBX 0x000000F0 /* debuging flags (scsi_debug.h) */
+#define SDEV_ONCE_ONLY 0x00010000 /* unit can only be opened once */
/*
* One of these is allocated and filled in for each scsi bus.
@@ -313,6 +434,8 @@ struct scsi_xfer
#define XS_LENGTH 0x09 /* Illegal length (over/under run) */
#ifdef KERNEL
+char * scsi_type_long_name(int type);
+char * scsi_type_name(int type);
void scsi_attachdevs __P((struct scsi_link *sc_link_proto));
struct scsi_xfer *get_xs( struct scsi_link *sc_link, u_int32 flags);
void free_xs(struct scsi_xfer *xs, struct scsi_link *sc_link,u_int32 flags);
@@ -330,11 +453,11 @@ errval scsi_scsi_cmd( struct scsi_link *sc_link, struct scsi_generic *scsi_cmd,
u_int32 datalen, u_int32 retries,
u_int32 timeout, struct buf *bp,
u_int32 flags);
-errval scsi_do_ioctl __P((dev_t dev, struct scsi_link *sc_link, int cmd, caddr_t addr, int f));
+errval scsi_do_ioctl __P((dev_t dev,
+ int cmd, caddr_t addr, int f, struct scsi_link *sc_link));
struct scsi_link *scsi_link_get __P((int bus, int targ, int lun));
-
-dev_t scsi_dev_lookup __P((int (*opener)(dev_t dev)));
+dev_t scsi_dev_lookup __P((int (*opener)(dev_t dev, int flags)));
int scsi_opened_ok __P((dev_t dev, int flag, int type, struct scsi_link *sc_link));
@@ -349,8 +472,10 @@ int32 scsi_3btoi __P((u_char *bytes));
extern void sc_print_addr(struct scsi_link *);
-extern int scsi_externalize(struct scsi_link *, void *, size_t *);
-extern int scsi_internalize(struct scsi_link *, void **, size_t *);
+extern int scsi_externalize(struct scsi_link *, void *, size_t *);
+
+void scsi_device_register(struct scsi_device *sd);
+
extern struct kern_devconf kdc_scbus0; /* XXX should go away */
#endif
diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c
index 584b3f2..0a37774 100644
--- a/sys/scsi/sd.c
+++ b/sys/scsi/sd.c
@@ -14,7 +14,7 @@
*
* Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992
*
- * $Id: sd.c,v 1.49 1995/01/08 13:38:34 dufault Exp $
+ * $Id: sd.c,v 1.50 1995/01/31 11:41:46 dufault Exp $
*/
#define SPLSD splbio
@@ -43,46 +43,27 @@
u_int32 sdstrats, sdqueues;
-#define PAGESIZ 4096
#define SECSIZE 512
-#define PDLOCATION 29
-#define BOOTRECORDSIGNATURE (0x55aa & 0x00ff)
#define SDOUTSTANDING 2
-#define SDQSIZE 4
#define SD_RETRIES 4
#define MAXTRANSFER 8 /* 1 page at a time */
-
#define MAKESDDEV(maj, unit, part) (makedev(maj,((unit<<SDUNITSHIFT)+part)))
#define PARTITION(z) (minor(z) & 0x07)
-#define WHOLE_DISK(unit) ( (unit << SDUNITSHIFT) + RAWPART )
-
errval sdgetdisklabel __P((unsigned char unit));
errval sd_get_parms __P((int unit, int flags));
-void sdstrategy __P((struct buf *));
-void sdstart __P((u_int32));
+void sdstrategy __P((struct buf *bp));
-int sd_sense_handler __P((struct scsi_xfer *));
-
-struct scsi_device sd_switch =
-{
- sd_sense_handler,
- sdstart, /* have a queue, served by this */
- NULL, /* have no async handler */
- NULL, /* Use default 'done' routine */
- "sd",
- 0,
- { 0, 0 }
-};
+int sd_sense_handler __P((struct scsi_xfer *));
+void sdstart __P((u_int32));
-struct sd_data {
+struct scsi_data {
u_int32 flags;
#define SDINIT 0x04 /* device has been init'd */
#define SDHAVELABEL 0x10 /* have read the label */
#define SDDOSPART 0x20 /* Have read the DOS partition table */
#define SDWRITEPROT 0x40 /* Device in readonly mode (S/W) */
- struct scsi_link *sc_link; /* contains our targ, lun etc. */
u_int32 ad_info; /* info about the adapter */
u_int32 cmdscount; /* cmds allowed outstanding by board */
boolean wlabel; /* label is writable */
@@ -108,35 +89,53 @@ struct sd_data {
int dkunit; /* disk stats unit number */
};
-struct sd_driver {
- u_int32 size;
- struct sd_data **sd_data;
-} sd_driver;
+static int sdunit(dev_t dev) { return SDUNIT(dev); }
+static dev_t sdsetunit(dev_t dev, int unit) { return SDSETUNIT(dev, unit); }
-static u_int32 next_sd_unit = 0;
+errval sd_open(dev_t dev, int flags, struct scsi_link *sc_link);
+errval sd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag,
+ struct scsi_link *sc_link);
+errval sd_close(dev_t dev, struct scsi_link *sc_link);
+void sd_strategy(struct buf *bp, struct scsi_link *sc_link);
-static struct scsi_xfer sx;
+SCSI_DEVICE_ENTRIES(sd)
-static int
-sd_goaway(struct kern_devconf *kdc, int force) /* XXX should do a lot more */
+struct scsi_device sd_switch =
{
- dev_detach(kdc);
- FREE(kdc, M_TEMP);
- return 0;
-}
+ sd_sense_handler,
+ sdstart, /* have a queue, served by this */
+ NULL, /* have no async handler */
+ NULL, /* Use default 'done' routine */
+ "sd",
+ 0,
+ {0, 0},
+ 0, /* Link flags */
+ sdattach,
+ sdopen,
+ sizeof(struct scsi_data),
+ T_DIRECT,
+ sdunit,
+ sdsetunit,
+ sd_open,
+ sd_ioctl,
+ sd_close,
+ sd_strategy,
+};
+
+static struct scsi_xfer sx;
static int
sd_externalize(struct proc *p, struct kern_devconf *kdc, void *userp,
size_t len)
{
- return scsi_externalize(sd_driver.sd_data[kdc->kdc_unit]->sc_link,
+ return scsi_externalize(SCSI_LINK(&sd_switch, kdc->kdc_unit),
userp, &len);
}
static struct kern_devconf kdc_sd_template = {
0, 0, 0, /* filled in by dev_attach */
"sd", 0, MDDC_SCSI,
- sd_externalize, 0, sd_goaway, SCSI_EXTERNALLEN,
+ sd_externalize, 0, scsi_goaway, SCSI_EXTERNALLEN,
&kdc_scbus0, /* XXX parent */
0, /* parentdata */
DC_UNKNOWN, /* not supported */
@@ -156,87 +155,31 @@ sd_registerdev(int unit)
if(dk_ndrive < DK_NDRIVE) {
sprintf(dk_names[dk_ndrive], "sd%d", unit);
dk_wpms[dk_ndrive] = (8*1024*1024/2);
- sd_driver.sd_data[unit]->dkunit = dk_ndrive++;
+ SCSI_DATA(&sd_switch, unit)->dkunit = dk_ndrive++;
} else {
- sd_driver.sd_data[unit]->dkunit = -1;
+ SCSI_DATA(&sd_switch, unit)->dkunit = -1;
}
}
-errval sdopen();
-
/*
* The routine called by the low level scsi routine when it discovers
* a device suitable for this driver.
*/
errval
-sdattach(sc_link)
- struct scsi_link *sc_link;
+sdattach(struct scsi_link *sc_link)
{
u_int32 unit;
- struct sd_data *sd, **sdrealloc;
struct disk_parms *dp;
- SC_DEBUG(sc_link, SDEV_DB2, ("sdattach: "));
+ struct scsi_data *sd = sc_link->sd;
- /*
- * allocate the resources for another drive
- * if we have already allocate a sd_data pointer we must
- * copy the old pointers into a new region that is
- * larger and release the old region, aka realloc
- */
- /* 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_sd_unit * x) and
- * the sd_driver.size++ to be +x
- */
- unit = next_sd_unit++;
- if (unit >= sd_driver.size) {
- sdrealloc =
- malloc(sizeof(sd_driver.sd_data) * next_sd_unit,
- M_DEVBUF, M_NOWAIT);
- if (!sdrealloc) {
- printf("sd%ld: malloc failed for sdrealloc\n", unit);
- return (0);
- }
- /* Make sure we have something to copy before we copy it */
- bzero(sdrealloc, sizeof(sd_driver.sd_data) * next_sd_unit);
- if (sd_driver.size) {
- bcopy(sd_driver.sd_data, sdrealloc,
- sizeof(sd_driver.sd_data) * sd_driver.size);
- free(sd_driver.sd_data, M_DEVBUF);
- }
- sd_driver.sd_data = sdrealloc;
- sd_driver.sd_data[unit] = NULL;
- sd_driver.size++;
- }
- if (sd_driver.sd_data[unit]) {
- printf("sd%ld: Already has storage!\n", unit);
- return (0);
- }
- /*
- * alloate the per drive data area
- */
- sd = sd_driver.sd_data[unit] =
- malloc(sizeof(struct sd_data), M_DEVBUF, M_NOWAIT);
- if (!sd) {
- printf("sd%ld: malloc failed for sd_data\n", unit);
- return (0);
- }
- bzero(sd, sizeof(struct sd_data));
+ unit = sc_link->dev_unit;
dp = &(sd->params);
- /*
- * Store information needed to contact our base driver
- */
- sd->sc_link = sc_link;
- sc_link->device = &sd_switch;
- sc_link->dev_unit = unit;
- sc_link->dev = SDSETUNIT(scsi_dev_lookup(sdopen), unit);
- if (sd->sc_link->adapter->adapter_info) {
- sd->ad_info = ((*(sd->sc_link->adapter->adapter_info)) (sc_link->adapter_unit));
+ if (sc_link->adapter->adapter_info) {
+ sd->ad_info = ((*(sc_link->adapter->adapter_info)) (sc_link->adapter_unit));
sd->cmdscount = sd->ad_info & AD_INF_MAX_CMDS;
if (sd->cmdscount > SDOUTSTANDING) {
sd->cmdscount = SDOUTSTANDING;
@@ -258,8 +201,7 @@ sdattach(sc_link)
* -- this avoids the division below from falling over
*/
if(dp->secsiz == 0) dp->secsiz = 512;
- printf("sd%ld: %ldMB (%ld total sec), %d cyl, %d head, %d sec, bytes/sec %d\n",
- unit,
+ printf("%ldMB (%ld total sec), %d cyl, %d head, %d sec, bytes/sec %d\n",
dp->disksize / ((1024L * 1024L) / dp->secsiz),
dp->disksize,
dp->cyls,
@@ -268,30 +210,24 @@ sdattach(sc_link)
dp->secsiz);
sd->flags |= SDINIT;
sd_registerdev(unit);
- return (1);
+
+ return 0;
}
/*
* open the device. Make sure the partition info is a up-to-date as can be.
*/
errval
-sdopen(dev)
- int dev; /* XXX should be dev_t, but avoid promotion problems for now */
+sd_open(dev_t dev, int flags, struct scsi_link *sc_link)
{
errval errcode = 0;
u_int32 unit, part;
- struct sd_data *sd;
- struct scsi_link *sc_link;
+ struct scsi_data *sd;
unit = SDUNIT(dev);
part = PARTITION(dev);
- /*
- * Check the unit is legal
- */
- if (unit >= sd_driver.size) {
- return (ENXIO);
- }
- sd = sd_driver.sd_data[unit];
+ sd = sc_link->sd;
+
/*
* Make sure the disk has been initialised
* At some point in the future, get the scsi driver
@@ -300,11 +236,10 @@ sdopen(dev)
if ((!sd) || (!(sd->flags & SDINIT))) {
return (ENXIO);
}
- sc_link = sd->sc_link;
SC_DEBUG(sc_link, SDEV_DB1,
- ("sdopen: dev=0x%x (unit %d (of %d),partition %d)\n",
- dev, unit, sd_driver.size, part));
+ ("sdopen: dev=0x%x (unit %d, partition %d)\n",
+ dev, unit, part));
/*
* "unit attention" errors should occur here if the
@@ -323,7 +258,7 @@ sdopen(dev)
sd->flags &= ~SDHAVELABEL;
/*
- * If somebody still has it open, then forbid re-entry.
+ * If somebody still has it open, then forbid re-entry.
*/
if (sd->openparts) {
errcode = ENXIO;
@@ -405,62 +340,42 @@ bad:
* device. Convenient now but usually a pain.
*/
errval
-sdclose(dev)
- dev_t dev;
+sd_close(dev_t dev, struct scsi_link *sc_link)
{
unsigned char unit, part;
- struct sd_data *sd;
+ struct scsi_data *sd;
unit = SDUNIT(dev);
part = PARTITION(dev);
- sd = sd_driver.sd_data[unit];
+ sd = sc_link->sd;
sd->partflags[part] &= ~SDOPEN;
sd->openparts &= ~(1 << part);
- scsi_prevent(sd->sc_link, PR_ALLOW, SCSI_SILENT | SCSI_ERR_OK);
+ scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT | SCSI_ERR_OK);
if (!(sd->openparts))
- sd->sc_link->flags &= ~SDEV_OPEN;
+ sc_link->flags &= ~SDEV_OPEN;
return 0;
}
/*
- * trim the size of the transfer if needed, called by physio
- * basically the smaller of our max and the scsi driver's
- * minphys (note we have no max)
- *
- * Trim buffer length if buffer-size is bigger than page size
- */
-void
-sdminphys(bp)
- struct buf *bp;
-{
- (*(sd_driver.sd_data[SDUNIT(bp->b_dev)]->sc_link->adapter->scsi_minphys)) (bp);
-}
-
-/*
* Actually translate the requested transfer into one the physical driver
* can understand. The transfer is described by a buf and will include
* only one physical transfer.
*/
void
-sdstrategy(bp)
- struct buf *bp;
+sd_strategy(struct buf *bp, struct scsi_link *sc_link)
{
struct buf *dp;
u_int32 opri;
- struct sd_data *sd;
+ struct scsi_data *sd;
u_int32 unit;
sdstrats++;
unit = SDUNIT((bp->b_dev));
- sd = sd_driver.sd_data[unit];
- SC_DEBUG(sd->sc_link, SDEV_DB2, ("sdstrategy "));
- SC_DEBUG(sd->sc_link, SDEV_DB1,
- (" %d bytes @ blk%d\n", bp->b_bcount, bp->b_blkno));
- sdminphys(bp);
+ sd = sc_link->sd;
/*
* If the device has been made invalid, error out
*/
- if (!(sd->sc_link->flags & SDEV_MEDIA_LOADED)) {
+ if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
sd->flags &= ~SDHAVELABEL;
bp->b_error = EIO;
goto bad;
@@ -512,7 +427,7 @@ sdstrategy(bp)
* Use a bounce buffer if necessary
*/
#ifdef BOUNCE_BUFFERS
- if (sd->sc_link->flags & SDEV_BOUNCE)
+ if (sc_link->flags & SDEV_BOUNCE)
vm_bounce_alloc(bp);
#endif
@@ -566,11 +481,10 @@ done:
* sdstart() is called at SPLSD from sdstrategy and scsi_done
*/
void
-sdstart(unit)
- u_int32 unit;
+sdstart(u_int32 unit)
{
- register struct sd_data *sd = sd_driver.sd_data[unit];
- register struct scsi_link *sc_link = sd->sc_link;
+ register struct scsi_link *sc_link = SCSI_LINK(&sd_switch, unit);
+ register struct scsi_data *sd = sc_link->sd;
struct buf *bp = 0;
struct buf *dp;
struct scsi_rw_big cmd;
@@ -671,25 +585,26 @@ bad:
* Knows about the internals of this device
*/
errval
-sdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
+sd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag,
+struct scsi_link *sc_link)
{
/* struct sd_cmd_buf *args; */
errval error = 0;
unsigned char unit, part;
- register struct sd_data *sd;
+ register struct scsi_data *sd;
/*
* Find the device that the user is talking about
*/
unit = SDUNIT(dev);
part = PARTITION(dev);
- sd = sd_driver.sd_data[unit];
- SC_DEBUG(sd->sc_link, SDEV_DB1, ("sdioctl (0x%x)", cmd));
+ sd = sc_link->sd;
+ SC_DEBUG(sc_link, SDEV_DB1, ("sdioctl (0x%x)", cmd));
/*
* If the device is not valid.. abandon ship
*/
- if (!(sd->sc_link->flags & SDEV_MEDIA_LOADED))
+ if (!(sc_link->flags & SDEV_MEDIA_LOADED))
return (EIO);
switch (cmd) {
@@ -778,7 +693,7 @@ sdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
default:
if (part == RAWPART || SCSI_SUPER(dev) )
- error = scsi_do_ioctl(dev, sd->sc_link, cmd, addr, flag);
+ error = scsi_do_ioctl(dev, cmd, addr, flag, sc_link);
else
error = ENOTTY;
break;
@@ -793,7 +708,7 @@ errval
sdgetdisklabel(unsigned char unit)
{
char *errstring;
- struct sd_data *sd = sd_driver.sd_data[unit];
+ struct scsi_data *sd = SCSI_DATA(&sd_switch, unit);
dev_t dev;
dev = makedev(0, (unit << SDUNITSHIFT) + RAWPART);
@@ -859,7 +774,7 @@ sd_size(unit, flags)
struct scsi_read_cap_data rdcap;
struct scsi_read_capacity scsi_cmd;
u_int32 size;
- struct sd_data *sd = sd_driver.sd_data[unit];
+ struct scsi_link *sc_link = SCSI_LINK(&sd_switch, unit);
/*
* make up a scsi command and ask the scsi driver to do
@@ -872,7 +787,7 @@ sd_size(unit, flags)
* If the command works, interpret the result as a 4 byte
* number of blocks
*/
- if (scsi_scsi_cmd(sd->sc_link,
+ if (scsi_scsi_cmd(sc_link,
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
(u_char *) & rdcap,
@@ -901,7 +816,7 @@ sd_reassign_blocks(unit, block)
{
struct scsi_reassign_blocks scsi_cmd;
struct scsi_reassign_blocks_data rbdata;
- struct sd_data *sd = sd_driver.sd_data[unit];
+ struct scsi_link *sc_link = SCSI_LINK(&sd_switch, unit);
bzero(&scsi_cmd, sizeof(scsi_cmd));
bzero(&rbdata, sizeof(rbdata));
@@ -914,7 +829,7 @@ sd_reassign_blocks(unit, block)
rbdata.defect_descriptor[0].dlbaddr_1 = ((block >> 8) & 0xff);
rbdata.defect_descriptor[0].dlbaddr_0 = ((block) & 0xff);
- return (scsi_scsi_cmd(sd->sc_link,
+ return (scsi_scsi_cmd(sc_link,
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
(u_char *) & rbdata,
@@ -935,7 +850,8 @@ errval
sd_get_parms(unit, flags)
int unit, flags;
{
- struct sd_data *sd = sd_driver.sd_data[unit];
+ struct scsi_link *sc_link = SCSI_LINK(&sd_switch, unit);
+ struct scsi_data *sd = sc_link->sd;
struct disk_parms *disk_parms = &sd->params;
struct scsi_mode_sense scsi_cmd;
struct scsi_mode_sense_data {
@@ -948,7 +864,7 @@ sd_get_parms(unit, flags)
/*
* First check if we have it all loaded
*/
- if (sd->sc_link->flags & SDEV_MEDIA_LOADED)
+ if (sc_link->flags & SDEV_MEDIA_LOADED)
return 0;
/*
@@ -962,7 +878,7 @@ sd_get_parms(unit, flags)
* If the command worked, use the results to fill out
* the parameter structure
*/
- if (scsi_scsi_cmd(sd->sc_link,
+ if (scsi_scsi_cmd(sc_link,
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
(u_char *) & scsi_sense,
@@ -987,7 +903,7 @@ sd_get_parms(unit, flags)
disk_parms->disksize = sectors;
} else {
- SC_DEBUG(sd->sc_link, SDEV_DB3,
+ SC_DEBUG(sc_link, SDEV_DB3,
("%d cyls, %d heads, %d precomp, %d red_write, %d land_zone\n",
scsi_3btou(&scsi_sense.pages.rigid_geometry.ncyl_2),
scsi_sense.pages.rigid_geometry.nheads,
@@ -1022,7 +938,7 @@ sd_get_parms(unit, flags)
disk_parms->secsiz = SECSIZE;
disk_parms->sectors = sectors; /* dubious on SCSI *//*XXX */
}
- sd->sc_link->flags |= SDEV_MEDIA_LOADED;
+ sc_link->flags |= SDEV_MEDIA_LOADED;
return 0;
}
@@ -1030,18 +946,18 @@ int
sdsize(dev_t dev)
{
u_int32 unit = SDUNIT(dev), part = PARTITION(dev), val;
- struct sd_data *sd;
+ struct scsi_data *sd;
- if (unit >= sd_driver.size)
+ if ( (sd = SCSI_DATA(&sd_switch, unit)) == 0)
return -1;
- sd = sd_driver.sd_data[unit];
- if (!sd)
- return -1;
if ((sd->flags & SDINIT) == 0)
return -1;
if (sd == 0 || (sd->flags & SDHAVELABEL) == 0) {
- val = sdopen(MAKESDDEV(major(dev), unit, RAWPART), FREAD, S_IFBLK, 0);
+ /* XXX: By rights sdopen should be called like:
+ * sdopen(MAKESDDEV(major(dev), unit, RAWPART), FREAD, S_IFBLK, 0);
+ */
+ val = sdopen(MAKESDDEV(major(dev), unit, RAWPART), FREAD);
if (val != 0)
return -1;
}
@@ -1087,10 +1003,7 @@ int sd_sense_handler(struct scsi_xfer *xs)
if (inqbuf->dev_qual2 & SID_REMOVABLE)
return SCSIRET_CONTINUE;
- /* I have to retry HARDWARE ERROR for ASC 44 and ASCQ 0
- * so that the CDC-WREN IV will work during TCAL. In general,
- * I think we should just retry disk errors. Does anyone
- * have a good reason not to?
+ /* Retry all disk errors.
*/
scsi_sense_print(xs);
if (xs->retries)
@@ -1108,7 +1021,8 @@ int sd_sense_handler(struct scsi_xfer *xs)
errval
sddump(dev_t dev)
{ /* dump core after a system crash */
- register struct sd_data *sd; /* disk unit to do the IO */
+ register struct scsi_data *sd; /* disk unit to do the IO */
+ struct scsi_link *sc_link;
int32 num; /* number of sectors to write */
u_int32 unit, part;
int32 blkoff, blknum, blkcnt = MAXTRANSFER;
@@ -1133,17 +1047,18 @@ sddump(dev_t dev)
num = Maxmem;
unit = SDUNIT(dev); /* eventually support floppies? */
part = PARTITION(dev); /* file system */
- /* check for acceptable drive number */
- if (unit >= sd_driver.size)
- return (ENXIO);
- sd = sd_driver.sd_data[unit];
- if (!sd)
- return (ENXIO);
+ sc_link = SCSI_LINK(&sd_switch, unit);
+
+ if (!sc_link)
+ return ENXIO;
+
+ sd = sc_link->sd;
+
/* was it ever initialized etc. ? */
if (!(sd->flags & SDINIT))
return (ENXIO);
- if (sd->sc_link->flags & SDEV_MEDIA_LOADED != SDEV_MEDIA_LOADED)
+ if (sc_link->flags & SDEV_MEDIA_LOADED != SDEV_MEDIA_LOADED)
return (ENXIO);
if (sd->flags & SDWRITEPROT)
return (ENXIO);
@@ -1188,7 +1103,7 @@ sddump(dev_t dev)
*/
bzero(xs, sizeof(sx));
xs->flags |= SCSI_NOMASK | SCSI_NOSLEEP | INUSE | SCSI_DATA_OUT;
- xs->sc_link = sd->sc_link;
+ xs->sc_link = sc_link;
xs->retries = SD_RETRIES;
xs->timeout = 10000; /* 10000 millisecs for a disk ! */
xs->cmd = (struct scsi_generic *) &cmd;
@@ -1202,7 +1117,7 @@ sddump(dev_t dev)
/*
* Pass all this info to the scsi driver.
*/
- retval = (*(sd->sc_link->adapter->scsi_cmd)) (xs);
+ retval = (*(sc_link->adapter->scsi_cmd)) (xs);
switch (retval) {
case SUCCESSFULLY_QUEUED:
case HAD_ERROR:
diff --git a/sys/scsi/st.c b/sys/scsi/st.c
index cf4f80f..5bb9cbc 100644
--- a/sys/scsi/st.c
+++ b/sys/scsi/st.c
@@ -12,7 +12,7 @@
* on the understanding that TFS is not responsible for the correct
* functioning of this software in any circumstances.
*
- * $Id: st.c,v 1.26 1995/01/31 11:41:47 dufault Exp $
+ * $Id: st.c,v 1.27 1995/02/25 19:11:11 jkh Exp $
*/
/*
@@ -50,7 +50,6 @@ u_int32 ststrats, stqueues;
/* Defines for device specific stuff */
#define PAGE_0_SENSE_DATA_SIZE 12
-#define PAGESIZ 4096
#define DEF_FIXED_BSIZE 512
#define ST_RETRIES 4 /* only on non IO commands */
@@ -154,7 +153,7 @@ static struct rogues gallery[] = /* ends with an all-null entry */
errval st_space __P((u_int32 unit, int32 number, u_int32 what, u_int32 flags));
errval st_rewind __P((u_int32 unit, boolean immed, u_int32 flags));
errval st_erase __P((u_int32 unit, boolean immed, u_int32 flags)); /* AKL */
-errval st_mode_sense __P((u_int32 unit, u_int32 flags));
+static errval st_mode_sense __P((u_int32 unit, u_int32 flags));
errval st_decide_mode __P((u_int32 unit, boolean first_read));
errval st_rd_blk_lim __P((u_int32 unit, u_int32 flags));
errval st_touch_tape __P((u_int32 unit));
@@ -162,10 +161,8 @@ errval st_write_filemarks __P((u_int32 unit, int32 number, u_int32 flags));
errval st_load __P((u_int32 unit, u_int32 type, u_int32 flags));
errval st_mode_select __P((u_int32 unit, u_int32 flags));
void ststrategy();
-void stminphys();
int32 st_chkeod();
-errval stattach();
-void ststart();
+void ststart(u_int32 unit);
void st_unmount();
errval st_mount_tape();
void st_loadquirks();
@@ -178,26 +175,13 @@ errval st_interpret_sense();
#define NOEJECT 0
#define EJECT 1
-struct scsi_device st_switch =
-{
- st_interpret_sense, /* check errors with us first */
- ststart, /* we have a queue, and this is how we service it */
- NULL,
- NULL, /* use the default 'done' routine */
- "st",
- 0,
- { 0, 0 }
-};
-
-struct st_data {
+struct scsi_data {
/*--------------------present operating parameters, flags etc.----------------*/
u_int32 flags; /* see below */
u_int32 blksiz; /* blksiz we are using */
u_int32 density; /* present density */
u_int32 quirks; /* quirks for the open mode */
u_int32 last_dsty; /* last density openned */
-/*--------------------device/scsi parameters----------------------------------*/
- struct scsi_link *sc_link; /* our link to the adpter etc. */
/*--------------------parameters reported by the device ----------------------*/
u_int32 blkmin; /* min blk size */
u_int32 blkmax; /* max blk size */
@@ -231,6 +215,39 @@ struct st_data {
u_int32 xfer_block_wait; /* is a process waiting? */
};
+static int stunit(dev_t dev) { return STUNIT(dev); }
+static dev_t stsetunit(dev_t dev, int unit) { return STSETUNIT(dev, unit); }
+
+errval st_open(dev_t dev, int flags, struct scsi_link *sc_link);
+errval st_ioctl(dev_t dev, int cmd, caddr_t addr, int flag,
+ struct scsi_link *sc_link);
+errval st_close(dev_t dev, struct scsi_link *sc_link);
+void st_strategy(struct buf *bp, struct scsi_link *sc_link);
+
+SCSI_DEVICE_ENTRIES(st)
+
+struct scsi_device st_switch =
+{
+ st_interpret_sense, /* check errors with us first */
+ ststart, /* we have a queue, and this is how we service it */
+ NULL,
+ NULL, /* use the default 'done' routine */
+ "st",
+ 0,
+ {0, 0},
+ 0, /* Link flags */
+ stattach,
+ stopen,
+ sizeof(struct scsi_data),
+ T_SEQUENTIAL,
+ stunit,
+ stsetunit,
+ st_open,
+ st_ioctl,
+ st_close,
+ st_strategy,
+};
+
#define ST_INITIALIZED 0x01
#define ST_INFO_VALID 0x02
#define ST_OPEN 0x04
@@ -255,33 +272,18 @@ struct st_data {
ST_FIXEDBLOCKS | ST_READONLY | \
ST_FM_WRITTEN | ST_2FM_AT_EOD | ST_PER_ACTION)
-struct st_driver {
- u_int32 size;
- struct st_data **st_data;
-} st_driver;
-
-static u_int32 next_st_unit = 0;
-
-static int
-st_goaway(struct kern_devconf *kdc, int force) /* XXX should do a lot more */
-{
- dev_detach(kdc);
- FREE(kdc, M_TEMP);
- return 0;
-}
-
static int
st_externalize(struct proc *p, struct kern_devconf *kdc, void *userp,
size_t len)
{
- return scsi_externalize(st_driver.st_data[kdc->kdc_unit]->sc_link,
+ return scsi_externalize(SCSI_LINK(&st_switch, kdc->kdc_unit),
userp, &len);
}
static struct kern_devconf kdc_st_template = {
0, 0, 0, /* filled in by dev_attach */
"st", 0, MDDC_SCSI,
- st_externalize, 0, st_goaway, SCSI_EXTERNALLEN,
+ st_externalize, 0, scsi_goaway, SCSI_EXTERNALLEN,
&kdc_scbus0, /* XXX parent */
0, /* parentdata */
DC_UNKNOWN, /* not supported */
@@ -300,82 +302,26 @@ st_registerdev(int unit)
dev_attach(kdc);
}
-errval stopen();
/*
* The routine called by the low level scsi routine when it discovers
- * A device suitable for this driver
+ * a device suitable for this driver
*/
errval
-stattach(sc_link)
- struct scsi_link *sc_link;
+stattach(struct scsi_link *sc_link)
{
u_int32 unit;
- struct st_data *st, **strealloc;
- SC_DEBUG(sc_link, SDEV_DB2, ("stattach: "));
+ struct scsi_data *st = sc_link->sd;
- /*
- * allocate the resources for another drive
- * if we have already allocate a st_data pointer we must
- * copy the old pointers into a new region that is
- * larger and release the old region, aka realloc
- */
- /* 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_st_unit * x) and
- * the st_driver.size++ to be +x
- */
- unit = next_st_unit++;
- if (unit >= st_driver.size) {
- strealloc =
- malloc(sizeof(st_driver.st_data) * next_st_unit,
- M_DEVBUF, M_NOWAIT);
- if (!strealloc) {
- printf("st%ld: malloc failed for strealloc\n", unit);
- return (0);
- }
- /* Make sure we have something to copy before we copy it */
- bzero(strealloc, sizeof(st_driver.st_data) * next_st_unit);
- if (st_driver.size) {
- bcopy(st_driver.st_data, strealloc,
- sizeof(st_driver.st_data) * st_driver.size);
- free(st_driver.st_data, M_DEVBUF);
- }
- st_driver.st_data = strealloc;
- st_driver.st_data[unit] = NULL;
- st_driver.size++;
- }
- if (st_driver.st_data[unit]) {
- printf("st%ld: Already has storage!\n", unit);
- return (0);
- }
- /*
- * allocate the per drive data area
- */
- st = st_driver.st_data[unit] =
- malloc(sizeof(struct st_data), M_DEVBUF, M_NOWAIT);
- if (!st) {
- printf("st%ld: malloc failed for st_data\n", unit);
- return 0;
- }
- bzero(st, sizeof(struct st_data));
-
- /*
- * Store information needed to contact our base driver
- */
- st->sc_link = sc_link;
- sc_link->device = &st_switch;
- sc_link->dev_unit = unit;
- sc_link->dev = STSETUNIT(scsi_dev_lookup(stopen), unit);
+ unit = sc_link->dev_unit;
/*
* Check if the drive is a known criminal and take
* Any steps needed to bring it into line
*/
#ifdef NEW_SCSICONF
- st_loadquirks(st);
+ st_loadquirks(sc_link);
#else
st_identify_drive(unit);
#endif
@@ -385,9 +331,9 @@ stattach(sc_link)
* request must specify this.
*/
if (st_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT)) {
- printf("st%d: drive offline\n", unit);
+ printf("drive offline\n");
} else {
- printf("st%d: density code 0x%x, ", unit, st->media_density);
+ printf("density code 0x%x, ", st->media_density);
if (!scsi_test_unit_ready(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT)) {
if (st->media_blksiz) {
printf("%d-byte", st->media_blksiz);
@@ -406,6 +352,7 @@ stattach(sc_link)
st->buf_queue = 0;
st->flags |= ST_INITIALIZED;
st_registerdev(unit);
+
return 0;
}
@@ -418,19 +365,20 @@ void
st_identify_drive(unit)
u_int32 unit;
{
- struct st_data *st = st_driver.st_data[unit];
+ struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
+ struct scsi_data *st = sc_link->sd;
struct rogues *finger;
char manu[32];
char model[32];
char model2[32];
char version[32];
u_int32 model_len;
- struct scsi_inquiry_data *inqbuf = &st->sc_link->inqbuf;
+ struct scsi_inquiry_data *inqbuf = &sc_link->inqbuf;
/*
* Get the device type information
*/
- if (scsi_inquire(st->sc_link, inqbuf,
+ if (scsi_inquire(sc_link, inqbuf,
SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT) != 0) {
printf("st%d: couldn't get device type, using default\n", unit);
return;
@@ -477,7 +425,7 @@ st_identify_drive(unit)
st->rogues = finger;
st->drive_quirks = finger->quirks;
st->quirks = finger->quirks; /*start value */
- st_loadquirks(st);
+ st_loadquirks(sc_link);
break;
} else {
finger++; /* go to next suspect */
@@ -492,19 +440,20 @@ st_identify_drive(unit)
* operations.
*/
void
-st_loadquirks(st)
- struct st_data *st;
+st_loadquirks(sc_link)
+ struct scsi_link *sc_link;
{
+ struct scsi_data *st = sc_link->sd;
int i;
#ifdef NEW_SCSICONF
struct st_mode *mode;
struct st_mode *mode2;
- mode = (struct st_mode*) st->sc_link->devmodes;
+ mode = (struct st_mode*) sc_link->devmodes;
if (!mode)
return;
- st->quirks = st->drive_quirks = st->sc_link->quirks;
+ st->quirks = st->drive_quirks = sc_link->quirks;
#else
struct modes *mode;
@@ -546,34 +495,23 @@ st_loadquirks(st)
* open the device.
*/
errval
-stopen(dev, flags)
- dev_t dev;
- u_int32 flags;
+st_open(dev_t dev, int flags, struct scsi_link *sc_link)
{
u_int32 unit, mode, dsty;
errval errno = 0;
- struct st_data *st;
- struct scsi_link *sc_link;
+ struct scsi_data *st;
+
unit = STUNIT(dev);
mode = MODE(dev);
dsty = DSTY(dev);
- /*
- * Check the unit is legal
- */
- if (unit >= st_driver.size) {
- return (ENXIO);
- }
- st = st_driver.st_data[unit];
+ st = sc_link->sd;
/*
* Make sure the device has been initialised
*/
if ((st == NULL) || (!(st->flags & ST_INITIALIZED)))
return (ENXIO);
- sc_link = st->sc_link;
- SC_DEBUG(sc_link, SDEV_DB1, ("open: dev=0x%x (unit %d (of %d))\n"
- ,dev, unit, st_driver.size));
/*
* Only allow one at a time
*/
@@ -642,19 +580,15 @@ stopen(dev, flags)
* occurence of an open device
*/
errval
-stclose(dev)
- dev_t dev;
+st_close(dev_t dev, struct scsi_link *sc_link)
{
unsigned char unit, mode;
- struct st_data *st;
- struct scsi_link *sc_link;
+ struct scsi_data *st;
unit = STUNIT(dev);
mode = MODE(dev);
- st = st_driver.st_data[unit];
- sc_link = st->sc_link;
+ st = sc_link->sd;
- SC_DEBUG(sc_link, SDEV_DB1, ("closing\n"));
if ((st->flags & (ST_WRITTEN | ST_FM_WRITTEN)) == ST_WRITTEN)
st_write_filemarks(unit, 1, 0);
switch (mode & 0x3) {
@@ -687,15 +621,15 @@ st_mount_tape(dev, flags)
u_int32 flags;
{
u_int32 unit, mode, dsty;
- struct st_data *st;
+ struct scsi_data *st;
struct scsi_link *sc_link;
errval errno = 0;
unit = STUNIT(dev);
mode = MODE(dev);
dsty = DSTY(dev);
- st = st_driver.st_data[unit];
- sc_link = st->sc_link;
+ sc_link = SCSI_LINK(&st_switch, unit);
+ st = sc_link->sd;
if (st->flags & ST_MOUNTED)
return 0;
@@ -789,8 +723,8 @@ st_mount_tape(dev, flags)
void
st_unmount(int unit, boolean eject)
{
- struct st_data *st = st_driver.st_data[unit];
- struct scsi_link *sc_link = st->sc_link;
+ struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
+ struct scsi_data *st = sc_link->sd;
int32 nmarks;
if (!(st->flags & ST_MOUNTED))
@@ -816,10 +750,8 @@ st_decide_mode(unit, first_read)
u_int32 unit;
boolean first_read;
{
- struct st_data *st = st_driver.st_data[unit];
-#ifdef SCSIDEBUG
- struct scsi_link *sc_link = st->sc_link;
-#endif
+ struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
+ struct scsi_data *st = sc_link->sd;
SC_DEBUG(sc_link, SDEV_DB2, ("starting block mode decision\n"));
@@ -944,38 +876,22 @@ done:
}
/*
- * trim the size of the transfer if needed,
- * called by physio
- * basically the smaller of our min and the scsi driver's
- * minphys
- */
-void
-stminphys(bp)
- struct buf *bp;
-{
- (*(st_driver.st_data[STUNIT(bp->b_dev)]->sc_link->adapter->scsi_minphys)) (bp);
-}
-
-/*
* Actually translate the requested transfer into
* one the physical driver can understand
* The transfer is described by a buf and will include
* only one physical transfer.
*/
void
-ststrategy(bp)
- struct buf *bp;
+st_strategy(struct buf *bp, struct scsi_link *sc_link)
{
struct buf **dp;
unsigned char unit;
u_int32 opri;
- struct st_data *st;
+ struct scsi_data *st;
ststrats++;
unit = STUNIT((bp->b_dev));
- st = st_driver.st_data[unit];
- SC_DEBUG(st->sc_link, SDEV_DB1,
- (" strategy: %d bytes @ blk%d\n", bp->b_bcount, bp->b_blkno));
+ st = sc_link->sd;
/*
* If it's a null transfer, return immediatly
*/
@@ -1002,14 +918,13 @@ ststrategy(bp)
bp->b_error = EIO;
goto bad;
}
- stminphys(bp);
opri = splbio();
/*
* Use a bounce buffer if necessary
*/
#ifdef BOUNCE_BUFFERS
- if (st->sc_link->flags & SDEV_BOUNCE)
+ if (sc_link->flags & SDEV_BOUNCE)
vm_bounce_alloc(bp);
#endif
@@ -1062,8 +977,8 @@ void
ststart(unit)
u_int32 unit;
{
- struct st_data *st = st_driver.st_data[unit];
- struct scsi_link *sc_link = st->sc_link;
+ struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
+ struct scsi_data *st = sc_link->sd;
register struct buf *bp = 0;
struct scsi_rw_tape cmd;
u_int32 flags;
@@ -1188,16 +1103,13 @@ badnews:
* knows about the internals of this device
*/
errval
-stioctl(dev, cmd, arg, flag)
- dev_t dev;
- int cmd;
- caddr_t arg;
- int flag;
+st_ioctl(dev_t dev, int cmd, caddr_t arg, int flag,
+struct scsi_link *sc_link)
{
errval errcode = 0;
unsigned char unit;
u_int32 number, flags, dsty;
- struct st_data *st;
+ struct scsi_data *st;
u_int32 hold_blksiz;
u_int32 hold_density;
int32 nmarks;
@@ -1209,7 +1121,7 @@ stioctl(dev, cmd, arg, flag)
flags = 0; /* give error messages, act on errors etc. */
unit = STUNIT(dev);
dsty = DSTY(dev);
- st = st_driver.st_data[unit];
+ st = sc_link->sd;
hold_blksiz = st->blksiz;
hold_density = st->density;
@@ -1219,7 +1131,7 @@ stioctl(dev, cmd, arg, flag)
{
struct mtget *g = (struct mtget *) arg;
- SC_DEBUG(st->sc_link, SDEV_DB1, ("[ioctl: get status]\n"));
+ SC_DEBUG(sc_link, SDEV_DB1, ("[ioctl: get status]\n"));
bzero(g, sizeof(struct mtget));
g->mt_type = 0x7; /* Ultrix compat *//*? */
g->mt_density = st->density;
@@ -1237,7 +1149,7 @@ stioctl(dev, cmd, arg, flag)
case MTIOCTOP:
{
- SC_DEBUG(st->sc_link, SDEV_DB1, ("[ioctl: op=0x%x count=0x%x]\n",
+ SC_DEBUG(sc_link, SDEV_DB1, ("[ioctl: op=0x%x count=0x%x]\n",
mt->mt_op, mt->mt_count));
/* compat: in U*x it is a short */
@@ -1315,7 +1227,7 @@ stioctl(dev, cmd, arg, flag)
break;
default:
if(IS_CTLMODE(dev))
- errcode = scsi_do_ioctl(dev, st->sc_link,cmd,arg,flag);
+ errcode = scsi_do_ioctl(dev, cmd, arg, flag, sc_link);
else
errcode = ENOTTY;
break;
@@ -1369,8 +1281,9 @@ st_read(unit, buf, size, flags)
u_int32 unit, size, flags;
char *buf;
{
+ struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
+ struct scsi_data *st = sc_link->sd;
struct scsi_rw_tape scsi_cmd;
- struct st_data *st = st_driver.st_data[unit];
/*
* If it's a null transfer, return immediatly
@@ -1387,7 +1300,7 @@ st_read(unit, buf, size, flags)
} else {
scsi_uto3b(size, scsi_cmd.len);
}
- return (scsi_scsi_cmd(st->sc_link,
+ return (scsi_scsi_cmd(sc_link,
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
(u_char *) buf,
@@ -1410,11 +1323,11 @@ errval
st_rd_blk_lim(unit, flags)
u_int32 unit, flags;
{
+ struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
+ struct scsi_data *st = sc_link->sd;
struct scsi_blk_limits scsi_cmd;
struct scsi_blk_limits_data scsi_blkl;
- struct st_data *st = st_driver.st_data[unit];
errval errno;
- struct scsi_link *sc_link = st->sc_link;
/*
* First check if we have it all loaded
@@ -1460,7 +1373,7 @@ st_rd_blk_lim(unit, flags)
* open
* ioctl (to reset original blksize)
*/
-errval
+static errval
st_mode_sense(unit, flags)
u_int32 unit, flags;
{
@@ -1485,8 +1398,8 @@ st_mode_sense(unit, flags)
* back when you issue a mode select
*/
} scsi_sense_page_0;
- struct st_data *st = st_driver.st_data[unit];
- struct scsi_link *sc_link = st->sc_link;
+ struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
+ struct scsi_data *st = sc_link->sd;
/*
* Define what sort of structure we're working with
@@ -1566,7 +1479,8 @@ st_mode_select(unit, flags)
struct blk_desc blk_desc;
unsigned char sense_data[PAGE_0_SENSE_DATA_SIZE];
} dat_page_0;
- struct st_data *st = st_driver.st_data[unit];
+ struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
+ struct scsi_data *st = sc_link->sd;
/*
* Define what sort of structure we're working with
@@ -1600,7 +1514,7 @@ st_mode_select(unit, flags)
/*
* do the command
*/
- return (scsi_scsi_cmd(st->sc_link,
+ return (scsi_scsi_cmd(sc_link,
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
(u_char *) dat_ptr,
@@ -1621,7 +1535,8 @@ st_space(unit, number, what, flags)
{
errval error;
struct scsi_space scsi_cmd;
- struct st_data *st = st_driver.st_data[unit];
+ struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
+ struct scsi_data *st = sc_link->sd;
switch ((int)what) {
case SP_BLKS:
@@ -1674,7 +1589,7 @@ st_space(unit, number, what, flags)
scsi_cmd.op_code = SPACE;
scsi_cmd.byte2 = what & SS_CODE;
scsi_uto3b(number, scsi_cmd.number);
- return (scsi_scsi_cmd(st->sc_link,
+ return (scsi_scsi_cmd(sc_link,
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
0,
@@ -1694,7 +1609,8 @@ st_write_filemarks(unit, number, flags)
int32 number;
{
struct scsi_write_filemarks scsi_cmd;
- struct st_data *st = st_driver.st_data[unit];
+ struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
+ struct scsi_data *st = sc_link->sd;
/*
* It's hard to write a negative number of file marks.
@@ -1720,7 +1636,7 @@ st_write_filemarks(unit, number, flags)
bzero(&scsi_cmd, sizeof(scsi_cmd));
scsi_cmd.op_code = WRITE_FILEMARKS;
scsi_uto3b(number, scsi_cmd.number);
- return scsi_scsi_cmd(st->sc_link,
+ return scsi_scsi_cmd(sc_link,
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
0,
@@ -1747,7 +1663,7 @@ st_chkeod(unit, position, nmarks, flags)
u_int32 flags;
{
errval error;
- struct st_data *st = st_driver.st_data[unit];
+ struct scsi_data *st = SCSI_DATA(&st_switch, unit);
switch ((int)(st->flags & (ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD))) {
default:
@@ -1774,8 +1690,8 @@ st_load(unit, type, flags)
u_int32 unit, type, flags;
{
struct scsi_load scsi_cmd;
- struct st_data *st = st_driver.st_data[unit];
- struct scsi_link *sc_link = st->sc_link;
+ struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
+ struct scsi_data *st = sc_link->sd;
bzero(&scsi_cmd, sizeof(scsi_cmd));
if (type != LD_LOAD) {
@@ -1791,7 +1707,7 @@ st_load(unit, type, flags)
return (0);
scsi_cmd.op_code = LOAD_UNLOAD;
scsi_cmd.how |= type;
- return (scsi_scsi_cmd(st->sc_link,
+ return (scsi_scsi_cmd(sc_link,
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
0,
@@ -1811,7 +1727,8 @@ st_rewind(unit, immed, flags)
boolean immed;
{
struct scsi_rewind scsi_cmd;
- struct st_data *st = st_driver.st_data[unit];
+ struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
+ struct scsi_data *st = sc_link->sd;
errval error;
int32 nmarks;
@@ -1822,7 +1739,7 @@ st_rewind(unit, immed, flags)
bzero(&scsi_cmd, sizeof(scsi_cmd));
scsi_cmd.op_code = REWIND;
scsi_cmd.byte2 = immed ? SR_IMMED : 0;
- return (scsi_scsi_cmd(st->sc_link,
+ return (scsi_scsi_cmd(sc_link,
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
0,
@@ -1842,7 +1759,8 @@ st_erase(unit, immed, flags)
boolean immed;
{
struct scsi_erase scsi_cmd;
- struct st_data *st = st_driver.st_data[unit];
+ struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
+ struct scsi_data *st = sc_link->sd;
errval error;
int32 nmarks;
@@ -1863,7 +1781,7 @@ st_erase(unit, immed, flags)
scsi_cmd.op_code = ERASE;
scsi_cmd.byte2 = SE_LONG; /* LONG_ERASE - AKL */
scsi_cmd.byte2 += immed ? SE_IMMED : 0; /* immed bit is here the 2nd! */
- return (scsi_scsi_cmd(st->sc_link,
+ return (scsi_scsi_cmd(sc_link,
(struct scsi_generic *) &scsi_cmd,
sizeof(scsi_cmd),
0,
@@ -1894,7 +1812,7 @@ st_interpret_sense(xs)
boolean silent = xs->flags & SCSI_SILENT;
struct buf *bp = xs->bp;
u_int32 unit = sc_link->dev_unit;
- struct st_data *st = st_driver.st_data[unit];
+ struct scsi_data *st = SCSI_DATA(&st_switch, unit);
u_int32 key;
int32 info;
@@ -2037,7 +1955,7 @@ errval
st_touch_tape(unit)
u_int32 unit;
{
- struct st_data *st = st_driver.st_data[unit];
+ struct scsi_data *st = SCSI_DATA(&st_switch, unit);
char *buf;
u_int32 readsiz;
errval errno;
diff --git a/sys/scsi/uk.c b/sys/scsi/uk.c
index 7544d1e..0f21110 100644
--- a/sys/scsi/uk.c
+++ b/sys/scsi/uk.c
@@ -1,21 +1,16 @@
/*
- * Dummy driver for a device we can't identify.
+ * Driver for a device we can't identify.
* by Julian Elischer (julian@tfs.com)
*
- * $Id: uk.c,v 1.5 1994/12/16 06:03:28 phk Exp $
+ * $Id: uk.c,v 1.6 1995/01/08 13:38:38 dufault Exp $
*/
#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/errno.h>
-#include <sys/ioctl.h>
-#include <sys/malloc.h>
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
-/*
- * This driver is so simple it uses all the default services
- */
+SCSI_DEVICE_ENTRIES(uk)
+
struct scsi_device uk_switch =
{
NULL,
@@ -24,187 +19,28 @@ struct scsi_device uk_switch =
NULL,
"uk",
0,
- 0, 0
-};
-
-struct uk_data {
- u_int32 flags;
-#define UK_KNOWN 0x02
- struct scsi_link *sc_link; /* all the inter level info */
+ {0, 0},
+ SDEV_ONCE_ONLY, /* Only one open allowed */
+ ukattach,
+ ukopen,
+ 0,
+ T_UNKNOWN,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
};
-struct uk_driver {
- u_int32 size;
- struct uk_data **uk_data;
-} uk_driver;
-
-static u_int32 next_uk_unit = 0;
-
-errval ukopen();
/*
* The routine called by the low level scsi routine when it discovers
* a device suitable for this driver.
*/
errval
-ukattach(sc_link)
- struct scsi_link *sc_link;
-{
- u_int32 unit, i, stat;
- struct uk_data *uk, **ukrealloc;
- unsigned char *tbl;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("ukattach: "));
-
- /*
- * allocate the resources for another drive
- * if we have already allocate a uk_data pointer we must
- * copy the old pointers into a new region that is
- * larger and release the old region, aka realloc
- */
- /* 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_uk_unit * x) and
- * the uk_driver.size++ to be +x
- */
- unit = next_uk_unit++;
- if (unit >= uk_driver.size) {
- ukrealloc =
- malloc(sizeof(uk_driver.uk_data) * next_uk_unit,
- M_DEVBUF, M_NOWAIT);
- if (!ukrealloc) {
- printf("uk%ld: malloc failed for ukrealloc\n", unit);
- return (0);
- }
- /* Make sure we have something to copy before we copy it */
- bzero(ukrealloc, sizeof(uk_driver.uk_data) * next_uk_unit);
- if (uk_driver.size) {
- bcopy(uk_driver.uk_data, ukrealloc,
- sizeof(uk_driver.uk_data) * uk_driver.size);
- free(uk_driver.uk_data, M_DEVBUF);
- }
- uk_driver.uk_data = ukrealloc;
- uk_driver.uk_data[unit] = NULL;
- uk_driver.size++;
- }
- if (uk_driver.uk_data[unit]) {
- printf("uk%ld: Already has storage!\n", unit);
- return (0);
- }
- /*
- * alloate the per drive data area
- */
- uk = uk_driver.uk_data[unit] =
- malloc(sizeof(struct uk_data), M_DEVBUF, M_NOWAIT);
- if (!uk) {
- printf("uk%ld: malloc failed for uk_data\n", unit);
- return (0);
- }
- bzero(uk, sizeof(struct uk_data));
-
- /*
- * Store information needed to contact our base driver
- */
- uk->sc_link = sc_link;
- sc_link->device = &uk_switch;
- sc_link->dev_unit = unit;
- sc_link->dev = UKSETUNIT(scsi_dev_lookup(ukopen), unit);
-
- printf("uk%d: unknown device\n", unit);
- uk->flags = UK_KNOWN;
-
- return 1; /* XXX ??? */
-}
-
-/*
- * open the device.
- */
-errval
-ukopen(dev)
- dev_t dev;
+ukattach(struct scsi_link *sc_link)
{
- errval errcode = 0;
- u_int32 unit, mode;
- struct uk_data *uk;
- struct scsi_link *sc_link;
- unit = UKUNIT(dev);
-
- /*
- * Check the unit is legal
- */
- if (unit >= uk_driver.size) {
- printf("uk%d: uk %d > %d\n", unit, unit, uk_driver.size);
- return ENXIO;
- }
- uk = uk_driver.uk_data[unit];
+ printf("unknown device\n");
- /*
- * Make sure the device has been initialised
- */
- if((!uk) || (!(uk->flags & UK_KNOWN))) {
- printf("uk%d: not set up\n", unit);
- return ENXIO;
- }
-
- /*
- * Only allow one at a time
- */
- sc_link = uk->sc_link;
- if (sc_link->flags & SDEV_OPEN) {
- printf("uk%d: already open\n", unit);
- return ENXIO;
- }
- sc_link->flags |= SDEV_OPEN;
- SC_DEBUG(sc_link, SDEV_DB1, ("ukopen: dev=0x%x (unit %d (of %d))\n",
- dev, unit, uk_driver.size));
- /*
- * Catch any unit attention errors.
- */
return 0;
}
-
-/*
- * close the device.. only called if we are the LAST
- * occurence of an open device
- */
-errval
-ukclose(dev)
- dev_t dev;
-{
- u_int32 unit = minor(dev);
- unsigned mode; /* XXX !!! XXX FIXME!!! 0??? */
- struct uk_data *uk;
- struct scsi_link *sc_link;
-
- uk = uk_driver.uk_data[unit];
- sc_link = uk->sc_link;
-
- SC_DEBUG(sc_link, SDEV_DB1, ("Closing device"));
- sc_link->flags &= ~SDEV_OPEN;
- return (0);
-}
-
-/*
- * Perform special action on behalf of the user
- * Only does generic scsi ioctls.
- */
-errval
-ukioctl(dev, cmd, arg, mode)
- dev_t dev;
- u_int32 cmd;
- caddr_t arg;
- int mode;
-{
- unsigned char unit;
- struct uk_data *uk;
- struct scsi_link *sc_link;
-
- /*
- * Find the device that the user is talking about
- */
- unit = UKUNIT(dev);
- uk = uk_driver.uk_data[unit];
- sc_link = uk->sc_link;
- return(scsi_do_ioctl(dev,sc_link,cmd,arg,mode));
-}
-
OpenPOWER on IntegriCloud