diff options
Diffstat (limited to 'sys/scsi')
-rw-r--r-- | sys/scsi/README | 9 | ||||
-rw-r--r-- | sys/scsi/cd.c | 288 | ||||
-rw-r--r-- | sys/scsi/ch.c | 239 | ||||
-rw-r--r-- | sys/scsi/scsi_all.h | 10 | ||||
-rw-r--r-- | sys/scsi/scsi_driver.c | 177 | ||||
-rw-r--r-- | sys/scsi/scsi_driver.h | 57 | ||||
-rw-r--r-- | sys/scsi/scsi_ioctl.c | 6 | ||||
-rw-r--r-- | sys/scsi/scsiconf.c | 729 | ||||
-rw-r--r-- | sys/scsi/scsiconf.h | 153 | ||||
-rw-r--r-- | sys/scsi/sd.c | 293 | ||||
-rw-r--r-- | sys/scsi/st.c | 308 | ||||
-rw-r--r-- | sys/scsi/uk.c | 200 |
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)); -} - |