diff options
author | dufault <dufault@FreeBSD.org> | 1995-04-14 15:10:44 +0000 |
---|---|---|
committer | dufault <dufault@FreeBSD.org> | 1995-04-14 15:10:44 +0000 |
commit | a644aba5017dfc9956e335d54cbdc4f68b763576 (patch) | |
tree | 3a69b37cbf049735d0cbf7b77ca3da8ae11c9866 /sys | |
parent | 3ce68508565a04b191a7642e35ddbfeaef1c0c67 (diff) | |
download | FreeBSD-src-a644aba5017dfc9956e335d54cbdc4f68b763576.zip FreeBSD-src-a644aba5017dfc9956e335d54cbdc4f68b763576.tar.gz |
Added "scsi target" device that can act as a target for scsi transfers
from an initiator
Added Julian's support for residuals.
Added Julian's fixes to the tape driver
Made compile cleanly with -Wall
Reduce boot up output
Diffstat (limited to 'sys')
-rw-r--r-- | sys/scsi/cd.c | 34 | ||||
-rw-r--r-- | sys/scsi/ch.c | 25 | ||||
-rw-r--r-- | sys/scsi/pt.c | 52 | ||||
-rw-r--r-- | sys/scsi/scsi_all.h | 7 | ||||
-rw-r--r-- | sys/scsi/scsi_base.c | 406 | ||||
-rw-r--r-- | sys/scsi/scsi_driver.c | 21 | ||||
-rw-r--r-- | sys/scsi/scsi_driver.h | 16 | ||||
-rw-r--r-- | sys/scsi/scsi_ioctl.c | 9 | ||||
-rw-r--r-- | sys/scsi/scsiconf.c | 283 | ||||
-rw-r--r-- | sys/scsi/scsiconf.h | 37 | ||||
-rw-r--r-- | sys/scsi/sctarg.c | 271 | ||||
-rw-r--r-- | sys/scsi/sd.c | 42 | ||||
-rw-r--r-- | sys/scsi/st.c | 231 |
13 files changed, 1052 insertions, 382 deletions
diff --git a/sys/scsi/cd.c b/sys/scsi/cd.c index f8713ed..137482a 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.36 1995/03/15 14:22:03 dufault Exp $ + * $Id: cd.c,v 1.37 1995/03/21 11:21:00 dufault Exp $ */ #define SPLCD splbio @@ -183,6 +183,12 @@ cdattach(struct scsi_link *sc_link) * Use the subdriver to request information regarding * the drive. We cannot use interrupts yet, so the * request must specify this. + * + * XXX dufault@hda.com: + * Need to handle this better in the case of no record. Rather than + * a state driven sense handler I think we should make it so that + * the command can get the sense back so that it can selectively log + * errors. */ cd_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK); if (dp->disksize) { @@ -190,8 +196,9 @@ cdattach(struct scsi_link *sc_link) cd->params.disksize, cd->params.blksize); } else { - printf("drive empty"); + printf("can't get the size\n"); } + cd->flags |= CDINIT; cd_registerdev(unit); @@ -220,7 +227,7 @@ struct scsi_link *sc_link) return (ENXIO); SC_DEBUG(sc_link, SDEV_DB1, - ("cd_open: dev=0x%x (unit %d,partition %d)\n", + ("cd_open: dev=0x%lx (unit %ld,partition %ld)\n", dev, unit, part)); /* * Check that it is still responding and ok. @@ -278,7 +285,7 @@ struct scsi_link *sc_link) * Check that the partition CAN exist */ if (part >= cd->disklabel.d_npartitions) { - SC_DEBUG(sc_link, SDEV_DB3, ("partition %d > %d\n", part + SC_DEBUG(sc_link, SDEV_DB3, ("partition %ld > %d\n", part ,cd->disklabel.d_npartitions)); errcode = ENXIO; goto bad; @@ -288,7 +295,7 @@ struct scsi_link *sc_link) */ if (cd->disklabel.d_partitions[part].p_fstype == FS_UNUSED) { SC_DEBUG(sc_link, SDEV_DB3, - ("part %d type UNUSED\n", part)); + ("part %ld type UNUSED\n", part)); errcode = ENXIO; goto bad; } @@ -326,7 +333,7 @@ cd_close(dev_t dev, int flag, int fmt, struct proc *p, part = PARTITION(dev); cd = sc_link->sd; - SC_DEBUG(sc_link, SDEV_DB2, ("cd%ld: closing part %d\n", unit, part)); + SC_DEBUG(sc_link, SDEV_DB2, ("cd%d: closing part %d\n", unit, part)); cd->partflags[part] &= ~CDOPEN; cd->openparts &= ~(1 << part); @@ -449,7 +456,7 @@ cdstart(unit) 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)); + SC_DEBUG(sc_link, SDEV_DB2, ("cdstart%ld ", unit)); /* * See if there is a buf to do and we are not already * doing one @@ -961,7 +968,6 @@ cd_size(unit, flags) 20000, /* might be a disk-changer */ NULL, SCSI_DATA_IN | flags) != 0) { - printf("cd%d: could not get size\n", unit); return (0); } else { size = rdcap.addr_0 + 1; @@ -977,7 +983,7 @@ cd_size(unit, flags) blksize = 2048; /* some drives lie ! */ if (size < 100) size = 400000; /* ditto */ - SC_DEBUG(sc_link, SDEV_DB3, ("cd%ld: %d %d byte blocks\n" + SC_DEBUG(sc_link, SDEV_DB3, ("cd%d: %ld %ld byte blocks\n" ,unit, size, blksize)); cd->params.disksize = size; cd->params.blksize = blksize; @@ -1183,15 +1189,7 @@ errval cd_reset(unit) u_int32 unit; { - return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit), - 0, - 0, - 0, - 0, - CDRETRIES, - 2000, - NULL, - SCSI_RESET)); + return scsi_reset_target(SCSI_LINK(&cd_switch, unit)); } /* diff --git a/sys/scsi/ch.c b/sys/scsi/ch.c index a4cd115e..ae71850 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.16 1995/03/15 14:22:04 dufault Exp $ + * $Id: ch.c,v 1.17 1995/03/28 07:57:22 bde Exp $ */ #include <sys/types.h> @@ -128,8 +128,7 @@ ch_registerdev(int unit) errval chattach(struct scsi_link *sc_link) { - u_int32 unit, i; - unsigned char *tbl; + u_int32 unit; struct scsi_data *ch = sc_link->sd; @@ -170,7 +169,7 @@ struct scsi_link *sc_link) * Only allow one at a time */ if (cd->flags & CH_OPEN) { - printf("ch%d: already open\n", unit); + printf("ch%ld: already open\n", unit); return EBUSY; } /* @@ -182,15 +181,15 @@ struct scsi_link *sc_link) /* * Check that it is still responding and ok. */ - if (errcode = (scsi_test_unit_ready(sc_link, 0))) { - printf("ch%d: not ready\n", unit); + if ( (errcode = (scsi_test_unit_ready(sc_link, 0))) ) { + printf("ch%ld: not ready\n", unit); sc_link->flags &= ~SDEV_OPEN; return errcode; } /* * Make sure data is loaded */ - if (errcode = (ch_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK))) { + if ( (errcode = (ch_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK))) ) { printf("ch%d: scsi changer :- offline\n", unit); sc_link->flags &= ~SDEV_OPEN; return (errcode); @@ -221,12 +220,8 @@ ch_ioctl(dev_t dev, int cmd, caddr_t arg, int mode, struct proc *p, struct scsi_link *sc_link) { /* struct ch_cmd_buf *args; */ - union scsi_cmd *scsi_cmd; - register i, j; - u_int32 opri; - errval errcode = 0; unsigned char unit; - u_int32 number, flags; + u_int32 flags; errval ret; struct scsi_data *cd; @@ -438,7 +433,7 @@ ch_mode_sense(unit, flags) /* * Read in the pages */ - if (errcode = scsi_scsi_cmd(sc_link, + if ( (errcode = scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd, sizeof(struct scsi_mode_sense), (u_char *) & scsi_sense, @@ -446,9 +441,9 @@ ch_mode_sense(unit, flags) CHRETRIES, 5000, NULL, - flags | SCSI_DATA_IN) != 0) { + flags | SCSI_DATA_IN) != 0) ) { if (!(flags & SCSI_SILENT)) - printf("ch%d: could not mode sense\n", unit); + printf("ch%ld: could not mode sense\n", unit); return (errcode); } sc_link->flags |= SDEV_MEDIA_LOADED; diff --git a/sys/scsi/pt.c b/sys/scsi/pt.c index e606b8e..7b8fbf4 100644 --- a/sys/scsi/pt.c +++ b/sys/scsi/pt.c @@ -37,7 +37,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id:$ + * $Id: pt.c,v 1.1 1995/03/04 20:50:46 dufault Exp $ */ /* @@ -49,6 +49,7 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/buf.h> +#include <sys/proc.h> #include <scsi/scsi_all.h> #include <scsi/scsiconf.h> @@ -58,12 +59,13 @@ struct scsi_data { void ptstart(u_int32 unit); void pt_strategy(struct buf *bp, struct scsi_link *sc_link); +int pt_sense(struct scsi_xfer *scsi_xfer); SCSI_DEVICE_ENTRIES(pt) struct scsi_device pt_switch = { - NULL, + pt_sense, ptstart, /* we have a queue, and this is how we service it */ NULL, NULL, @@ -155,13 +157,12 @@ ptstart(unit) sizeof(cmd), (u_char *) bp->b_un.b_addr, bp->b_bcount, - 0, /* can't retry a read on a tape really */ - 100000, + 0, + 10000, bp, flags | SCSI_NOSLEEP) == SUCCESSFULLY_QUEUED) { } else { -badnews: - printf("pt%d: oops not queued\n", unit); + printf("pt%ld: oops not queued\n", unit); bp->b_flags |= B_ERROR; bp->b_error = EIO; biodone(bp); @@ -212,3 +213,42 @@ pt_strategy(struct buf *bp, struct scsi_link *sc_link) splx(opri); return; } + +/* + * sense handler: Called to determine what to do when the + * device returns a CHECK CONDITION. + * + * For the processor type devices we try to handle the "info" field. + */ + +int pt_sense(struct scsi_xfer *xs) +{ + struct scsi_sense_data *sense = &(xs->sense); + struct buf *bp; + + long resid; + + if ((sense->error_code & SSD_ERRCODE_VALID) == 0 || + (sense->ext.extended.flags & SSD_ILI) == 0) { + return SCSIRET_CONTINUE; /* let the default handler handle it */ + } + + resid = ntohl(*((int32 *) sense->ext.extended.info)); + + bp = xs->bp; + + if (resid < 0) { + /* It synthesized data in order to fill our request. + * Move resid back to cover this. + */ + xs->resid = -resid; + xs->flags |= SCSI_RESID_VALID; + return 0; + } + else { + /* It wanted to send more data. We can't really do anything + * about this. + */ + return SCSIRET_CONTINUE; + } +} diff --git a/sys/scsi/scsi_all.h b/sys/scsi/scsi_all.h index 77538bf..7d806c7 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.10 1995/03/01 22:24:41 dufault Exp $ + * $Id: scsi_all.h,v 1.11 1995/03/04 12:36:55 bde Exp $ */ /* @@ -207,8 +207,9 @@ struct scsi_changedef #define T_COMM 9 #define T_ASC0 10 #define T_ASC1 11 -#define T_UNKNOWN 12 -#define T_NTYPES 13 +#define T_TARGET 12 +#define T_UNKNOWN 13 +#define T_NTYPES 14 #define T_NODEVICE 0x1F diff --git a/sys/scsi/scsi_base.c b/sys/scsi/scsi_base.c index d4a5482..d3dba21 100644 --- a/sys/scsi/scsi_base.c +++ b/sys/scsi/scsi_base.c @@ -17,6 +17,7 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> +#include <sys/kernel.h> #include <sys/buf.h> #include <sys/uio.h> #include <sys/malloc.h> @@ -61,8 +62,9 @@ get_xs(sc_link, flags) sc_link->flags |= SDEV_WAITING; tsleep((caddr_t)sc_link, PRIBIO, "scsiget", 0); } + sc_link->active++; sc_link->opennings--; - if (xs = next_free_xs) { + if ( (xs = next_free_xs) ) { next_free_xs = xs->next; splx(s); } else { @@ -97,6 +99,7 @@ free_xs(xs, sc_link, flags) SC_DEBUG(sc_link, SDEV_DB3, ("free_xs\n")); /* if was 0 and someone waits, wake them up */ + sc_link->active--; if ((!sc_link->opennings++) && (sc_link->flags & SDEV_WAITING)) { sc_link->flags &= ~SDEV_WAITING; wakeup((caddr_t)sc_link); /* remember, it wakes them ALL up */ @@ -156,6 +159,42 @@ scsi_read_capacity(sc_link, blk_size, flags) return (size); } +errval +scsi_reset_target(sc_link) + struct scsi_link *sc_link; +{ + return (scsi_scsi_cmd(sc_link, + 0, + 0, + 0, + 0, + 1, + 2000, + NULL, + SCSI_RESET)); +} + +errval +scsi_target_mode(sc_link, on_off) + struct scsi_link *sc_link; + int on_off; +{ + struct scsi_generic scsi_cmd; + bzero(&scsi_cmd, sizeof(scsi_cmd)); + scsi_cmd.opcode = SCSI_OP_TARGET; + scsi_cmd.bytes[0] = (on_off) ? 1 : 0; + + return (scsi_scsi_cmd(sc_link, + &scsi_cmd, + sizeof(scsi_cmd), + 0, + 0, + 1, + 2000, + NULL, + SCSI_ESCAPE)); +} + /* * Get scsi driver to send a "are you ready?" command */ @@ -354,8 +393,11 @@ scsi_done(xs) free_xs(xs, sc_link, SCSI_NOSLEEP); /*XXX */ return; /* it did it all, finish up */ } - /* BUG: This isn't used anywhere. Do you have plans for it, + /* XXX: This isn't used anywhere. Do you have plans for it, * Julian? (dufault@hda.com). + * This allows a private 'done' handler to + * resubmit the command if it wants to retry, + * In this case the xs must NOT be freed. (julian) */ if (retval == -2) { return; /* it did it all, finish up */ @@ -373,15 +415,16 @@ scsi_done(xs) } /* * Go and handle errors now. - * If it returns -1 then we should RETRY + * If it returns SCSIRET_DO_RETRY then we should RETRY */ - if ((retval = sc_err1(xs)) == -1) { + if ((retval = sc_err1(xs)) == SCSIRET_DO_RETRY) { if ((*(sc_link->adapter->scsi_cmd)) (xs) == SUCCESSFULLY_QUEUED) { /* don't wake the job, ok? */ return; } xs->flags |= ITSDONE; } + free_xs(xs, sc_link, SCSI_NOSLEEP); /* does a start if needed */ biodone(bp); } @@ -414,20 +457,23 @@ scsi_scsi_cmd(sc_link, scsi_cmd, cmdlen, data_addr, datalen, * Reject zero length commands and assert all defined commands * are the correct length. */ - if (cmdlen == 0) - return EFAULT; - else + if ((flags & (SCSI_RESET | SCSI_ESCAPE)) == 0) { - static u_int8 sizes[] = {6, 10, 10, 0, 0, 12, 0, 0 }; - u_int8 size = sizes[((scsi_cmd->opcode) >> 5)]; - if (size && (size != cmdlen)) - return EIO; + if (cmdlen == 0) + return EFAULT; + else + { + static u_int8 sizes[] = {6, 10, 10, 0, 0, 12, 0, 0 }; + u_int8 size = sizes[((scsi_cmd->opcode) >> 5)]; + if (size && (size != cmdlen)) + return EIO; + } } if (bp && !(flags & SCSI_USER)) flags |= SCSI_NOSLEEP; SC_DEBUG(sc_link, SDEV_DB2, ("scsi_cmd\n")); - xs = get_xs(sc_link, flags); /* should wait unless booting */ + xs = get_xs(sc_link, flags); if (!xs) return (ENOMEM); /* * Fill out the scsi_xfer structure. We don't know whose context @@ -442,7 +488,7 @@ scsi_scsi_cmd(sc_link, scsi_cmd, cmdlen, data_addr, datalen, xs->cmdlen = cmdlen; xs->data = data_addr; xs->datalen = datalen; - xs->resid = datalen; + xs->resid = 0; xs->bp = bp; /*XXX*/ /*use constant not magic number */ if (datalen && ((caddr_t) data_addr < (caddr_t) KERNBASE)) { @@ -503,8 +549,9 @@ retry: switch (retval) { case SUCCESSFULLY_QUEUED: - if (bp) - return retval; /* will sleep (or not) elsewhere */ + if (bp) { + return 0; /* will sleep (or not) elsewhere */ + } s = splbio(); while (!(xs->flags & ITSDONE)) { tsleep((caddr_t)xs, PRIBIO + 1, "scsicmd", 0); @@ -514,7 +561,7 @@ retry: case COMPLETE: /* Polling command completed ok */ /*XXX*/ case HAD_ERROR: /* Polling command completed with error */ SC_DEBUG(sc_link, SDEV_DB3, ("back in cmd()\n")); - if ((retval = sc_err1(xs)) == -1) + if ((retval = sc_err1(xs)) == SCSIRET_DO_RETRY) goto retry; break; @@ -562,85 +609,168 @@ bad: return (retval); } -static errval -sc_err1(xs) - struct scsi_xfer *xs; +static errval +sc_done(struct scsi_xfer *xs, int code) { - struct buf *bp = xs->bp; - errval retval; - - SC_DEBUG(xs->sc_link, SDEV_DB3, ("sc_err1,err = 0x%x \n", xs->error)); /* * If it has a buf, we might be working with * a request from the buffer cache or some other * piece of code that requires us to process - * errors at inetrrupt time. We have probably + * errors at interrupt time. We have probably * been called by scsi_done() */ - switch ((int)xs->error) { - case XS_NOERROR: /* nearly always hit this one */ - retval = ESUCCESS; - if (bp) { - bp->b_error = 0; - bp->b_resid = 0; - } - break; + struct buf *bp; - case XS_SENSE: - retval = scsi_interpret_sense(xs); - if (retval == SCSIRET_DO_RETRY) { - if (xs->retries--) { - xs->error = XS_NOERROR; - xs->flags &= ~ITSDONE; - goto retry; - } - retval = EIO; /* Too many retries */ + if (code == SCSIRET_DO_RETRY) { + if (xs->retries--) { + xs->error = XS_NOERROR; + xs->flags &= ~ITSDONE; + return SCSIRET_DO_RETRY; } + code = EIO; /* Too many retries */ + } + /* + * an EOF condition results in a VALID resid.. + */ + if(xs->flags & SCSI_EOF) { + xs->resid = xs->datalen; + xs->flags |= SCSI_RESID_VALID; + } + + bp = xs->bp; + if (code != ESUCCESS) { if (bp) { bp->b_error = 0; - if (retval) { - bp->b_flags |= B_ERROR; - bp->b_error = retval; - bp->b_resid = bp->b_bcount; - } + bp->b_flags |= B_ERROR; + bp->b_error = code; + bp->b_resid = bp->b_bcount; SC_DEBUG(xs->sc_link, SDEV_DB3, - ("scsi_interpret_sense (bp) returned %d\n", retval)); + ("scsi_interpret_sense (bp) returned %d\n", code)); } else { SC_DEBUG(xs->sc_link, SDEV_DB3, - ("scsi_interpret_sense (no bp) returned %d\n", retval)); + ("scsi_interpret_sense (no bp) returned %d\n", code)); } - break; + } + else { + if (bp) { + + bp->b_error = 0; + + /* XXX: We really shouldn't need this SCSI_RESID_VALID flag. + * If we initialize it to 0 and only touch it if we have + * a value then we can leave out the test. + */ + + if (xs->flags & SCSI_RESID_VALID) { + bp->b_resid = xs->resid; + bp->b_flags |= B_ERROR; + } else { + bp->b_resid = 0; + } + } + } + + return code; +} + +/* + * submit a scsi command, given the command.. used for retries + * and callable from timeout() + */ +#ifdef NOTYET +errval scsi_submit(xs) + struct scsi_xfer *xs; +{ + struct scsi_link *sc_link = xs->sc_link; + int retval; + + retval = (*(sc_link->adapter->scsi_cmd)) (xs); + + return retval; +} + +/* + * Retry a scsi command, given the command, and a delay. + */ +errval scsi_retry(xs,delay) + struct scsi_xfer *xs; + int delay; +{ + if(delay) + { + timeout(((void())*)scsi_submit,xs,hz*delay); + return(0); + } + else + { + return(scsi_submit(xs)); + } +} +#endif + +/* + * handle checking for errors.. + * called at interrupt time from scsi_done() and + * at user time from scsi_scsi_cmd(), depending on whether + * there was a bp (basically, if there is a bp, there may be no + * associated process at the time. (it could be an async operation)) + * lower level routines shouldn't know about xs->bp.. we are the lowest. + */ +static errval +sc_err1(xs) + struct scsi_xfer *xs; +{ + SC_DEBUG(xs->sc_link, SDEV_DB3, ("sc_err1,err = 0x%lx \n", xs->error)); + + switch ((int)xs->error) { + case XS_SENSE: + return sc_done(xs, scsi_interpret_sense(xs)); + + case XS_NOERROR: + return sc_done(xs, ESUCCESS); case XS_BUSY: - /*should somehow arange for a 1 sec delay here (how?) */ - /* XXX tsleep(&localvar, priority, "foo", hz); - that's how! */ + /* should somehow arange for a 1 sec delay here (how?)[jre] + * tsleep(&localvar, priority, "foo", hz); + * that's how! [unknown] + * no, we could be at interrupt context.. use + * timeout(scsi_resubmit,xs,hz); [jre] (not implimenteed yet) + */ case XS_TIMEOUT: - /* - * If we can, resubmit it to the adapter. - */ - if (xs->retries--) { - xs->error = XS_NOERROR; - xs->flags &= ~ITSDONE; - goto retry; - } + return sc_done(xs, SCSIRET_DO_RETRY); + /* fall through */ case XS_DRIVER_STUFFUP: - if (bp) { - bp->b_flags |= B_ERROR; - bp->b_error = EIO; - } - retval = EIO; - break; + return sc_done(xs, EIO); + default: - retval = EIO; sc_print_addr(xs->sc_link); printf("unknown error category from scsi driver\n"); + return sc_done(xs, EIO); } - return retval; -retry: - return (-1); +} + +int +scsi_sense_qualifiers(xs, asc, ascq) + struct scsi_xfer *xs; + int *asc; + int *ascq; +{ + struct scsi_sense_data_new *sense; + struct scsi_sense_extended *ext; + + sense = (struct scsi_sense_data_new *)&(xs->sense); + + ext = &(sense->ext.extended); + + if (ext->extra_len < 5) + return 0; + + *asc = (ext->extra_len >= 5) ? ext->add_sense_code : 0; + *ascq = (ext->extra_len >= 6) ? ext->add_sense_code_qual : 0; + + return 1; } /* @@ -655,7 +785,6 @@ void scsi_sense_print(xs) struct scsi_sense_extended *ext; u_int32 key; u_int32 info; - errval errcode; int asc, ascq; /* This sense key text now matches what is in the SCSI spec @@ -675,7 +804,7 @@ void scsi_sense_print(xs) "MISCOMPARE", "RESERVED" }; - sc_print_addr(xs->sc_link); + sc_print_start(xs->sc_link); sense = (struct scsi_sense_data_new *)&(xs->sense); ext = &(sense->ext.extended); @@ -706,8 +835,14 @@ void scsi_sense_print(xs) info); break; default: - if (info) - printf(" info:%lx", info); + if (info) { + if (sense->ext.extended.flags & SSD_ILI) { + printf(" ILI (length mismatch): %ld", info); + } + else { + printf(" info:%lx", info); + } + } } } else if (info) @@ -734,11 +869,11 @@ void scsi_sense_print(xs) if (strlen(desc) > 40) sc_print_addr(xs->sc_link);; - printf("%s", desc); + printf(" %s", desc); } if (ext->extra_len >= 7 && ext->fru) { - printf(" fru:%x", ext->fru); + printf(" field replaceable unit: %x", ext->fru); } if (ext->extra_len >= 10 && @@ -764,6 +899,7 @@ void scsi_sense_print(xs) } printf("\n"); + sc_print_finish(); } /* @@ -781,10 +917,11 @@ scsi_interpret_sense(xs) u_int32 key; u_int32 silent; errval errcode; + int error_code; /* * If the flags say errs are ok, then always return ok. - * BUG: What if it is a deferred error? + * XXX: What if it is a deferred error? */ if (xs->flags & SCSI_ERR_OK) return (ESUCCESS); @@ -823,20 +960,34 @@ scsi_interpret_sense(xs) * request a retry or continue with default sense handling. */ if (sc_link->device->err_handler) { - SC_DEBUG(sc_link, SDEV_DB2, ("calling private err_handler()\n")); + SC_DEBUG(sc_link, SDEV_DB2, + ("calling private err_handler()\n")); errcode = (*sc_link->device->err_handler) (xs); - if (errcode >= 0) + SC_DEBUG(sc_link, SDEV_DB2, + ("private err_handler() returned %d\n",errcode)); + if (errcode >= 0) { + SC_DEBUG(sc_link, SDEV_DB2, + ("SCSI_EOF = %d\n",(xs->flags & SCSI_EOF)?1:0)); + SC_DEBUG(sc_link, SDEV_DB2, + ("SCSI_RESID_VALID = %d\n", + (xs->flags & SCSI_RESID_VALID)?1:0)); + + if(xs->flags & SCSI_EOF) { + xs->resid = xs->datalen; + xs->flags |= SCSI_RESID_VALID; + } return errcode; /* valid errno value */ + } switch(errcode) { - case SCSIRET_DO_RETRY: /* Requested a retry */ + case SCSIRET_DO_RETRY: /* Requested a retry */ return errcode; - case SCSIRET_CONTINUE: /* Continue with default sense processing */ + case SCSIRET_CONTINUE: /* Continue with default sense processing */ break; - default: + default: sc_print_addr(xs->sc_link); printf("unknown return code %d from sense handler.\n", errcode); @@ -844,15 +995,17 @@ scsi_interpret_sense(xs) return errcode; } } + /* otherwise use the default */ silent = (xs->flags & SCSI_SILENT); key = sense->ext.extended.flags & SSD_KEY; + error_code = sense->error_code & SSD_ERRCODE; if (!silent) { scsi_sense_print(xs); } - switch (sense->error_code & SSD_ERRCODE) { + switch (error_code) { case 0x71: /* deferred error */ /* Print even if silent (not silent was already done) */ @@ -860,7 +1013,7 @@ scsi_interpret_sense(xs) scsi_sense_print(xs); } - /* BUG: + /* XXX: * This error doesn't relate to the command associated * with this request sense. A deferred error is an error * for a command that has already returned GOOD status (see 7.2.14.2). @@ -890,9 +1043,11 @@ scsi_interpret_sense(xs) switch ((int)key) { case 0x0: /* NO SENSE */ case 0x1: /* RECOVERED ERROR */ - if (xs->resid == xs->datalen) - xs->resid = 0; /* not short read */ case 0xc: /* EQUAL */ + if(xs->flags & SCSI_EOF) { + xs->resid = xs->datalen; + xs->flags |= SCSI_RESID_VALID; + } return (ESUCCESS); case 0x2: /* NOT READY */ sc_link->flags &= ~SDEV_MEDIA_LOADED; @@ -911,6 +1066,7 @@ scsi_interpret_sense(xs) case 0xd: /* VOLUME OVERFLOW */ return (ENOSPC); case 0x8: /* BLANK CHECK */ + xs->flags |= SCSI_EOF; /* force EOF on tape read */ return (ESUCCESS); default: return (EIO); @@ -1014,16 +1170,38 @@ sc_print_start(sc_link) struct scsi_link *sc_link; { sc_print_addr(sc_link); - sc_printing = 1; + sc_printing++; } void sc_print_finish() { - sc_printing = 0; + sc_printing--; +} + +static void +id_put(int id, char *after) +{ + switch(id) + { + case SCCONF_UNSPEC: + break; + + case SCCONF_ANY: + printf("?"); + break; + + default: + printf("%d", id); + break; + } + + printf("%s", after); } /* - * Print out the scsi_link structure's address info. + * sc_print_addr: Print out the scsi_link structure's address info. + * This should handle any circumstance, even the transitory ones + * during system configuration. */ void @@ -1033,12 +1211,26 @@ sc_print_addr(sc_link) if (sc_printing) printf("\n"); - if (strcmp(sc_link->device->name, "probe") != 0) - printf("%s%d", sc_link->device->name, sc_link->dev_unit); + if (sc_link->device == 0) { + printf("nodevice"); + } + else if (strcmp(sc_link->device->name, "probe") != 0) { + printf("%s", sc_link->device->name); + id_put(sc_link->dev_unit, ""); + } - printf("(%s%d:%d:%d): ", sc_link->adapter->name, sc_link->adapter_unit, - sc_link->target, sc_link->lun); + if (sc_link->adapter == 0) { + printf("(noadapter:"); + } + else { + printf("(%s", sc_link->adapter->name); + id_put(sc_link->adapter_unit, ":"); + } + + id_put(sc_link->target, ":"); + id_put(sc_link->lun, "): "); } + #ifdef SCSIDEBUG /* * Given a scsi_xfer, dump the request, in all it's glory @@ -1047,18 +1239,18 @@ void show_scsi_xs(xs) struct scsi_xfer *xs; { - printf("xs(0x%x): ", xs); - printf("flg(0x%x)", xs->flags); - printf("sc_link(0x%x)", xs->sc_link); + printf("xs(%p): ", xs); + printf("flg(0x%lx)", xs->flags); + printf("sc_link(%p)", xs->sc_link); printf("retr(0x%x)", xs->retries); - printf("timo(0x%x)", xs->timeout); - printf("cmd(0x%x)", xs->cmd); - printf("len(0x%x)", xs->cmdlen); - printf("data(0x%x)", xs->data); - printf("len(0x%x)", xs->datalen); - printf("res(0x%x)", xs->resid); - printf("err(0x%x)", xs->error); - printf("bp(0x%x)", xs->bp); + printf("timo(0x%lx)", xs->timeout); + printf("cmd(%p)", xs->cmd); + printf("len(0x%lx)", xs->cmdlen); + printf("data(%p)", xs->data); + printf("len(0x%lx)", xs->datalen); + printf("res(0x%lx)", xs->resid); + printf("err(0x%lx)", xs->error); + printf("bp(%p)", xs->bp); show_scsi_cmd(xs); } @@ -1077,7 +1269,7 @@ show_scsi_cmd(struct scsi_xfer *xs) printf(","); printf("%x", b[i++]); } - printf("-[%d bytes]\n", xs->datalen); + printf("-[%ld bytes]\n", xs->datalen); if (xs->datalen) show_mem(xs->data, min(64, xs->datalen)); } else { @@ -1090,11 +1282,11 @@ show_mem(address, num) unsigned char *address; u_int32 num; { - u_int32 x, y; + u_int32 y; printf("------------------------------"); for (y = 0; y < num; y += 1) { if (!(y % 16)) - printf("\n%03d: ", y); + printf("\n%03ld: ", y); printf("%02x ", *address++); } printf("\n------------------------------\n"); diff --git a/sys/scsi/scsi_driver.c b/sys/scsi/scsi_driver.c index 7f78661..e44c081 100644 --- a/sys/scsi/scsi_driver.c +++ b/sys/scsi/scsi_driver.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: scsi_driver.c,v 1.6 1995/03/16 18:15:48 bde Exp $ + * $Id: scsi_driver.c,v 1.7 1995/03/21 11:21:02 dufault Exp $ * */ #include <sys/types.h> @@ -125,18 +125,19 @@ struct scsi_device *device) errcode = (device->dev_open) ? (*device->dev_open)(dev, flags, fmt, p, sc_link) : 0; - if (sc_link->flags & SDEV_ONCE_ONLY) { + if (errcode == 0 && (sc_link->flags & SDEV_ONCE_ONLY)) { /* * Only allow one at a time */ if (sc_link->flags & SDEV_OPEN) { - return EBUSY; + errcode = EBUSY; + } + else { + sc_link->flags |= SDEV_OPEN; } - - sc_link->flags |= SDEV_OPEN; } - SC_DEBUG(sc_link, SDEV_DB1, ("%sopen: dev=0x%x (unit %d) result %d\n", + SC_DEBUG(sc_link, SDEV_DB1, ("%sopen: dev=0x%lx (unit %ld) result %d\n", device->name, dev, unit, errcode)); return errcode; @@ -192,12 +193,14 @@ scsi_strategy(struct buf *bp, struct scsi_device *device) struct scsi_link *sc_link = SCSI_LINK(device, unit); 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)); + SC_DEBUG(sc_link, SDEV_DB1, ("%ld bytes @ blk%ld\n", + bp->b_bcount, bp->b_blkno)); + + bp->b_resid = 0; + bp->b_error = 0; if (bp->b_bcount == 0) { - bp->b_resid = 0; biodone(bp); } else if (device->dev_strategy) diff --git a/sys/scsi/scsi_driver.h b/sys/scsi/scsi_driver.h index 867b2f1..9d325ef 100644 --- a/sys/scsi/scsi_driver.h +++ b/sys/scsi/scsi_driver.h @@ -35,12 +35,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: scsi_driver.h,v 1.1 1995/03/01 22:24:42 dufault Exp $ + * $Id: scsi_driver.h,v 1.2 1995/03/04 20:50:52 dufault Exp $ * */ #ifndef _SCSI__DRIVER_H_ #define _SCSI__DRIVER_H_ +#ifdef KERNEL + #include <sys/conf.h> struct kern_devconf; @@ -59,4 +61,16 @@ int scsi_ioctl __P((dev_t, u_int32, caddr_t, int, struct proc *, void scsi_strategy __P((struct buf *, struct scsi_device *)); void scsi_minphys __P((struct buf *, struct scsi_device *)); +int suopen __P((dev_t, int, int, struct proc *)); +int suclose __P((dev_t, int, int, struct proc *)); +void sustrategy __P((struct buf *)); +int suioctl __P((dev_t, int, caddr_t, int, struct proc *)); +int sudump __P((dev_t)); +int supsize __P((dev_t)); +int suread __P((dev_t, struct uio *, int)); +int suwrite __P((dev_t, struct uio *, int)); +int suselect __P((dev_t, int, struct proc *)); + +#endif /* KERNEL */ + #endif /* _SCSI__DRIVER_H_ */ diff --git a/sys/scsi/scsi_ioctl.c b/sys/scsi/scsi_ioctl.c index 90dc134..c34fe59 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.11 1995/03/01 22:24:42 dufault Exp $ + * $Id: scsi_ioctl.c,v 1.12 1995/03/04 20:50:55 dufault Exp $ * * */ @@ -97,7 +97,10 @@ struct scsi_xfer *xs; switch((int)xs->error) { case XS_NOERROR: SC_DEBUG(xs->sc_link,SDEV_DB3,("no error\n")); - screq->datalen_used = xs->datalen - xs->resid; /* probably rubbish */ + if (xs->flags & SCSI_RESID_VALID) + screq->datalen_used = xs->datalen - xs->resid; + else + screq->datalen_used = xs->datalen; screq->retsts = SCCMD_OK; break; @@ -283,7 +286,7 @@ struct proc *p, struct scsi_link *sc_link) if (len) { struct uio auio; struct iovec aiov; - long cnt, error = 0; + long cnt; aiov.iov_base = d_addr; aiov.iov_len = len; diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c index 4aac5c6..2e92c5c 100644 --- a/sys/scsi/scsiconf.c +++ b/sys/scsi/scsiconf.c @@ -16,7 +16,7 @@ * * New configuration setup: dufault@hda.com * - * $Id: scsiconf.c,v 1.25 1995/03/19 14:29:06 davidg Exp $ + * $Id: scsiconf.c,v 1.26 1995/03/21 11:21:04 dufault Exp $ */ #include <sys/types.h> @@ -37,6 +37,7 @@ #include "ch.h" #include "su.h" +#include "sctarg.h" #include <scsi/scsi_all.h> #include <scsi/scsiconf.h> @@ -312,7 +313,6 @@ static struct scsidevs knowndevs[] = */ struct scsidevs *scsi_probedev(); struct scsidevs *scsi_selectdev(); -errval scsi_probe_bus(int bus, int targ, int lun); /* XXX dufault@hda.com * This scsi_device doesn't have the scsi_data_size. @@ -364,11 +364,14 @@ static int next_free_type = T_NTYPES; * more than once - the list links are part of the structure. That is * prevented. * - * Unusual devices should always be registered as type "-1". Then + * Custom 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. + * + * This is usually called only by the "device_init" function generated + * automatically in the SCSI_DEVICE_ENTRIES macro. */ void @@ -438,7 +441,7 @@ scsi_init(void) /* First call all type initialization functions. */ - ukinit(); + ukinit(); /* We always have the unknown device. */ for (i = 0; scsi_tinit[i]; i++) (*scsi_tinit[i])(); @@ -472,12 +475,6 @@ scsi_init(void) } } -/* Feel free to take this out when everyone is sure this config - * code works well. For now it lets us tell new configurations from - * old ones. - */ -#define CONFIG_NOISE - /* scsi_bus_conf: Figure out which bus this is. If it is wired in config * use that. Otherwise use the next free one. */ @@ -501,9 +498,9 @@ scsi_bus_conf(sc_link_proto) (sc_link_proto->adapter_unit == scsi_cinit[i].unit) ) { bus = scsi_cinit[i].bus; -#ifdef CONFIG_NOISE - printf("Choosing drivers for scbus configured at %d\n", bus); -#endif + if (bootverbose) + printf("Choosing drivers for scbus configured at %d\n", + bus); break; } } @@ -535,10 +532,9 @@ scsi_assign_unit(struct scsi_link *sc_link) sc_link->scsibus == scsi_dinit[i].cunit) { sc_link->dev_unit = scsi_dinit[i].unit; found = 1; -#ifdef CONFIG_NOISE - printf("%s is configured at %d\n", - sc_link->device->name, sc_link->dev_unit); -#endif + if (bootverbose) + printf("%s is configured at %d\n", + sc_link->device->name, sc_link->dev_unit); break; } } @@ -549,6 +545,47 @@ scsi_assign_unit(struct scsi_link *sc_link) return sc_link->dev_unit; } + +#if NSCTARG > 0 +/* The SCSI target configuration is simpler. If an entry is present + * we just return the bus, target and lun for that unit. + */ +static void +scsi_sctarg_lookup(char *name, int unit, int *target, int *lun, int *bus) +{ + int i; + + *bus = SCCONF_UNSPEC; + *target = SCCONF_UNSPEC; + *lun = SCCONF_UNSPEC; + + for (i = 0; scsi_dinit[i].name; i++) { + if ((strcmp(name, scsi_dinit[i].name) == 0) && + unit == scsi_dinit[i].unit) + { + *bus = scsi_dinit[i].cunit; + *target = scsi_dinit[i].target; + *lun = scsi_dinit[i].lun; + } + } +} +#endif /* NSCTARG > 0 */ + +void scsi_configure_start(void) +{ + scsi_init(); +} + +void scsi_configure_finish(void) +{ + + static errval scsi_attach_sctarg __P((void)); +#if NSCTARG > 0 + scsi_attach_sctarg(); +#endif + +} + /* * The routine called by the adapter boards to get all their * devices configured in. @@ -560,8 +597,6 @@ scsi_attachdevs(sc_link_proto) int scsibus; struct scsibus_data *scbus; - scsi_init(); - if ( (scsibus = scsi_bus_conf(sc_link_proto)) == -1) { return; } @@ -621,7 +656,6 @@ 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; @@ -667,6 +701,120 @@ scsi_free_unit(struct scsi_link *sc_link) extend_release(sc_link->device->links, sc_link->dev_unit); } +#if NSCTARG > 0 + +/* XXX: It is a bug that the sc_link has this information + * about the adapter in it. The sc_link should refer to + * a structure that is host adpater specific. That will also + * pull all knowledge of an sc_link out of the adapter drivers. + */ + +errval +scsi_set_bus(int bus, struct scsi_link *sc_link) +{ + struct scsi_link *ad_link; + struct scsibus_data *scsibus_data; + + if (bus < 0 || bus > scbusses->nelem) { + return ENXIO; + } + + scsibus_data = (struct scsibus_data *)extend_get(scbusses, bus); + + if(!scsibus_data) { + return ENXIO; + } + + ad_link = scsibus_data->adapter_link; + + sc_link->adapter_unit = ad_link->adapter_unit; + sc_link->adapter_targ = ad_link->adapter_targ; + sc_link->adapter = ad_link->adapter; + sc_link->device = ad_link->device; + sc_link->flags = ad_link->flags; + + return 0; +} + +/* + * Allocate and attach as many SCSI target devices as configured. + * There are two ways that you can configure the target device: + * 1. In the configuration file. That is handled here. + * 2. Via the minor number. That takes precedence over the config file. + */ +static errval + scsi_attach_sctarg() +{ + struct scsi_link *sc_link = NULL; + int dev_unit; + struct scsi_device *sctarg = scsi_device_lookup(T_TARGET); + + if (sctarg == 0) { + return ENXIO; + } + + for (dev_unit = 0; dev_unit < NSCTARG; dev_unit++) { + + int target, lun, bus; + + /* If we don't have a link block allocate one. + */ + if (!sc_link) { + sc_link = malloc(sizeof(*sc_link), M_TEMP, M_NOWAIT); + } + + scsi_sctarg_lookup(sctarg->name, dev_unit, &target, &lun, &bus); + + if (IS_SPECIFIED(bus)) { + struct scsibus_data *scsibus_data; + + if (bus < 0 || bus > scbusses->nelem) { + printf("%s%d: configured on illegal bus %d.\n", + sctarg->name, dev_unit, bus); + continue; + } + + scsibus_data = (struct scsibus_data *)extend_get(scbusses, bus); + + if(!scsibus_data) { + printf("%s%d: no bus %d.\n", sctarg->name, dev_unit, bus); + continue; + } + + *sc_link = *scsibus_data->adapter_link; /* struct copy */ + sc_link->target = target; + sc_link->lun = lun; + } + else { + /* This will be configured in the open routine. + */ + sc_link->scsibus = SCCONF_UNSPEC; + sc_link->target = SCCONF_UNSPEC; + sc_link->lun = SCCONF_UNSPEC; + } + + sc_link->quirks = 0; + sc_link->device = sctarg; + sc_link->dev_unit = dev_unit; + + if (scsi_alloc_unit(sc_link)) { + + if (scsi_device_attach(sc_link) == 0) { + sc_link = NULL; /* it's been used */ + } + else + scsi_free_unit(sc_link); + } + } + + if (sc_link) { + free(sc_link, M_TEMP); + } + + return 0; +} +#endif /* NSCTARG > 0 */ + /* * Probe the requested scsi bus. It must be already set up. * targ and lun optionally narrow the search if not -1 @@ -674,7 +822,7 @@ scsi_free_unit(struct scsi_link *sc_link) errval scsi_probe_bus(int bus, int targ, int lun) { - struct scsibus_data *scsi ; + struct scsibus_data *scsibus_data ; int maxtarg,mintarg,maxlun,minlun; struct scsi_link *sc_link_proto; u_int8 scsi_addr ; @@ -686,9 +834,9 @@ scsi_probe_bus(int bus, int targ, int lun) if ((bus < 0 ) || ( bus >= scbusses->nelem)) { return ENXIO; } - scsi = (struct scsibus_data *)extend_get(scbusses, bus); - if(!scsi) return ENXIO; - sc_link_proto = scsi->adapter_link; + scsibus_data = (struct scsibus_data *)extend_get(scbusses, bus); + if(!scsibus_data) return ENXIO; + sc_link_proto = scsibus_data->adapter_link; scsi_addr = sc_link_proto->adapter_targ; if(targ == -1){ maxtarg = 7; @@ -716,7 +864,7 @@ scsi_probe_bus(int bus, int targ, int lun) * The spot appears to already have something * linked in, skip past it. Must be doing a 'reprobe' */ - if(scsi->sc_link[targ][lun]) + if(scsibus_data->sc_link[targ][lun]) {/* don't do this one, but check other luns */ maybe_more = 1; continue; @@ -751,7 +899,7 @@ scsi_probe_bus(int bus, int targ, int lun) if (scsi_alloc_unit(sc_link)) { if (scsi_device_attach(sc_link) == 0) { - scsi->sc_link[targ][lun] = sc_link; + scsibus_data->sc_link[targ][lun] = sc_link; sc_link = NULL; /* it's been used */ } else @@ -779,16 +927,33 @@ scsi_link_get(bus, targ, lun) int targ; int lun; { - struct scsibus_data *scsi = + struct scsibus_data *scsibus_data = (struct scsibus_data *)extend_get(scbusses, bus); - return (scsi) ? scsi->sc_link[targ][lun] : 0; + return (scsibus_data) ? scsibus_data->sc_link[targ][lun] : 0; } -static void rm_spaces(char *text, int n) +/* make_readable: Make the inquiry data readable. Anything less than a ' ' + * is made a '?' and trailing spaces are removed. + */ +static void +make_readable(to, from, n) + char *to; + char *from; + size_t n; { - while (n && text[n - 1] == ' ') - n--; - text[n] = 0; /* Zap */ + int i; + + for (i = 0; from[i] && i < n - 1; i++) { + if (from[i] < ' ') + to[i]='?'; + else + to[i] = from[i]; + } + + while (i && to[i - 1] == ' ') + i--; + + to[i] = 0; } /* @@ -802,20 +967,17 @@ scsi_probedev(sc_link, maybe_more, type_p) struct scsi_link *sc_link; int *type_p; { - u_int8 unit = sc_link->adapter_unit; u_int8 target = sc_link->target; u_int8 lu = sc_link->lun; - struct scsi_adapter *scsi_adapter = sc_link->adapter; struct scsidevs *bestmatch = (struct scsidevs *) 0; char *dtype = (char *) 0, *desc; char *qtype; struct scsi_inquiry_data *inqbuf; u_int32 len, qualifier, type; boolean remov; - char manu[32]; - char model[32]; - char version[32]; - int z; + char manu[8 + 1]; + char model[16 + 1]; + char version[4 + 1]; inqbuf = &sc_link->inqbuf; @@ -864,7 +1026,7 @@ scsi_probedev(sc_link, maybe_more, type_p) /* * Any device qualifier that has the top bit set (qualifier&4 != 0) - * is vendor specific and won't match in this switch. + * is vendor specific and will match in the default of this switch. */ switch ((int)qualifier) { @@ -873,28 +1035,25 @@ scsi_probedev(sc_link, maybe_more, type_p) break; case SID_QUAL_LU_OFFLINE: - qtype = ", Unit not Connected!"; + qtype = "Supported device currently not connected"; break; - case SID_QUAL_RSVD: - qtype = ", Reserved Peripheral Qualifier!"; + case SID_QUAL_RSVD: /* Peripheral qualifier reserved in SCSI-2 spec */ *maybe_more = 1; return (struct scsidevs *) 0; - break; - case SID_QUAL_BAD_LU: + case SID_QUAL_BAD_LU: /* Target can not support a device on this unit */ /* * Check for a non-existent unit. If the device is returning * this much, then we must set the flag that has * the searchers keep looking on other luns. */ - qtype = ", The Target can't support this Unit!"; *maybe_more = 1; return (struct scsidevs *) 0; default: - dtype = "vendor specific"; - qtype = ""; + dtype = ""; + qtype = "Vendor specific peripheral qualifier"; *maybe_more = 1; break; } @@ -918,40 +1077,34 @@ scsi_probedev(sc_link, maybe_more, type_p) len = sizeof(struct scsi_inquiry_data) - 1; desc = inqbuf->vendor; desc[len - (desc - (char *) inqbuf)] = 0; - strncpy(manu, inqbuf->vendor, 8); - strncpy(model, inqbuf->product, 16); - strncpy(version, inqbuf->revision, 4); - for(z = 0; z < 4; z++) { - if (version[z]<' ') version[z]='?'; - } - } else + make_readable(manu, inqbuf->vendor, sizeof(manu)); + make_readable(model, inqbuf->product, sizeof(model)); + make_readable(version, inqbuf->revision, sizeof(version)); + } else { /* * If not advanced enough, use default values */ - { desc = "early protocol device"; - strncpy(manu, "unknown", 8); - strncpy(model, "unknown", 16); - strncpy(version, "????", 4); + make_readable(manu, "unknown", sizeof(manu)); + make_readable(model, "unknown", sizeof(model)); + make_readable(version, "????", sizeof(version)); } - rm_spaces(manu, 8); - rm_spaces(model, 16); - rm_spaces(version, 4); - - sc_print_addr(sc_link); + sc_print_start(sc_link); - printf("\"%s %s %s\" is a ", manu, model, version ); + printf("\"%s %s %s\" ", manu, model, version ); printf("type %ld %sSCSI %d" ,type ,remov ? "removable " : "fixed " ,inqbuf->version & SID_ANSII ); if (qtype[0]) { - printf(" qualifier %ld(%s)" ,qualifier ,qtype); + sc_print_addr(sc_link); + printf(" qualifier %ld: %s" ,qualifier ,qtype); } printf("\n"); + sc_print_finish(); /* * Try make as good a match as possible with diff --git a/sys/scsi/scsiconf.h b/sys/scsi/scsiconf.h index 66c4fc2..0bacad6 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.20 1995/03/16 18:15:50 bde Exp $ + * $Id: scsiconf.h,v 1.21 1995/03/21 11:21:05 dufault Exp $ */ #ifndef SCSI_SCSICONF_H #define SCSI_SCSICONF_H 1 @@ -31,9 +31,11 @@ typedef unsigned char u_int8; #include <scsi/scsi_all.h> #include <scsi/scsi_driver.h> +#include <machine/cpu.h> /* XXX For bootverbose (funny place) */ + /* Minor number fields: * - * OLD STYLE SCSI devices: + * NON-FIXED SCSI devices: * * ???? ???? ???? ???N MMMMMMMM mmmmmmmm * @@ -42,7 +44,7 @@ typedef unsigned char u_int8; * M: Major device number. * m: old style minor device number. * - * NEW (FIXED) SCSI devices: + * FIXED SCSI devices: * * ???? SBBB LLLI IIIN MMMMMMMM mmmmmmmm * @@ -62,7 +64,7 @@ typedef unsigned char u_int8; #define SCSI_BUS(DEV) (((DEV) & 0x07000000) >> 24) #define SCSI_LUN(DEV) (((DEV) & 0x00E00000) >> 21) #define SCSI_ID(DEV) (((DEV) & 0x001E0000) >> 17) -#define SCSI_NEW(DEV) (((DEV) & 0x00010000) >> 16) +#define SCSI_FIXED(DEV) (((DEV) & 0x00010000) >> 16) #define SCSI_MKDEV(B, L, I) ( \ @@ -243,8 +245,8 @@ void NAME##strategy(struct buf *bp) \ /* A unit, type, etc can be SCCONF_ANY to indicate it is a '?' * in the config. */ -#define SCCONF_UNSPEC -1 -#define SCCONF_ANY -2 +#define SCCONF_UNSPEC 255 +#define SCCONF_ANY 254 struct isa_driver; struct scsi_ctlr_config @@ -340,20 +342,25 @@ struct scsi_link /* 44+*/struct scsi_inquiry_data inqbuf; /* Inquiry data */ }; -/* XXX dufault@hda.com: SDEV_BOUNCE is set down in the adapter drivers +/* XXX-HA: 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 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. + * XXX-HA And I added the "supports residuals properly" flag that ALSO goes + * in an adapter structure. I figure I'll fix both at once. */ + #define SDEV_MEDIA_LOADED 0x0001 /* device figures are still valid */ #define SDEV_WAITING 0x0002 /* a process is waiting for this */ #define SDEV_OPEN 0x0004 /* at least 1 open session */ -#define SDEV_BOUNCE 0x0008 /* unit requires DMA bounce buffer */ +#define SDEV_BOUNCE 0x0008 /* XXX-HA: unit needs DMA bounce buffer */ #define SDEV_DBX 0x00F0 /* debugging flags (scsi_debug.h) */ #define SDEV_ONCE_ONLY 0x0100 /* unit can only be opened once */ #define SDEV_BOOTVERBOSE 0x0200 /* be noisy during boot */ +#define SDEV_RESIDS_WORK 0x0400 /* XXX-HA: Residuals work */ +#define SDEV_TARGET_OPS 0x0800 /* XXX-HA: Supports target ops */ /* * One of these is allocated and filled in for each scsi bus. @@ -406,7 +413,9 @@ struct scsi_xfer #define SCSI_NOMASK 0x02 /* dont allow interrupts.. booting */ #define SCSI_NOSTART 0x04 /* left over from ancient history */ #define SCSI_USER 0x08 /* Is a user cmd, call scsi_user_done */ +#define SCSI_ITSDONE 0x10 /* the transfer is as done as it gets */ #define ITSDONE 0x10 /* the transfer is as done as it gets */ +#define SCSI_INUSE 0x20 /* The scsi_xfer block is in use */ #define INUSE 0x20 /* The scsi_xfer block is in use */ #define SCSI_SILENT 0x40 /* Don't report errors to console */ #define SCSI_ERR_OK 0x80 /* An error on this operation is OK. */ @@ -416,6 +425,8 @@ struct scsi_xfer #define SCSI_DATA_OUT 0x800 /* expect data to flow OUT of memory */ #define SCSI_TARGET 0x1000 /* This defines a TARGET mode op. */ #define SCSI_ESCAPE 0x2000 /* Escape operation */ +#define SCSI_EOF 0x4000 /* The operation should return EOF */ +#define SCSI_RESID_VALID 0x8000 /* The resid field contains valid data */ /* * Escape op codes. This provides an extensible setup for operations @@ -447,10 +458,13 @@ void free_xs(struct scsi_xfer *xs, struct scsi_link *sc_link,u_int32 flags); u_int32 scsi_read_capacity __P(( struct scsi_link *sc_link, u_int32 *blk_size, u_int32 flags)); errval scsi_test_unit_ready( struct scsi_link *sc_link, u_int32 flags); +errval scsi_reset_target __P((struct scsi_link *)); +errval scsi_target_mode __P((struct scsi_link *, int)); errval scsi_change_def( struct scsi_link *sc_link, u_int32 flags); errval scsi_inquire( struct scsi_link *sc_link, struct scsi_inquiry_data *inqbuf, u_int32 flags); errval scsi_prevent( struct scsi_link *sc_link, u_int32 type,u_int32 flags); +errval scsi_probe_bus __P((int, int, int)); errval scsi_probe_busses __P(( int, int, int)); errval scsi_start_unit( struct scsi_link *sc_link, u_int32 flags); errval scsi_stop_unit(struct scsi_link *sc_link, u_int32 eject, u_int32 flags); @@ -469,9 +483,11 @@ dev_t scsi_dev_lookup __P((int (*opener)(dev_t dev, int flags, int fmt, struct proc *p))); int scsi_opened_ok __P((dev_t dev, int flag, int type, struct scsi_link *sc_link)); +errval scsi_set_bus __P((int, struct scsi_link *)); char *scsi_sense_desc __P((int, int)); void scsi_sense_print __P((struct scsi_xfer *)); +int scsi_sense_qualifiers __P((struct scsi_xfer *, int *, int *)); void show_scsi_xs __P((struct scsi_xfer *)); void show_scsi_cmd __P((struct scsi_xfer *)); void show_mem __P((unsigned char * , u_int32)); @@ -494,7 +510,10 @@ void scsi_device_register __P((struct scsi_device *sd)); extern struct kern_devconf kdc_scbus0; /* XXX should go away */ -#endif +void scsi_configure_start __P((void)); +void scsi_configure_finish __P((void)); + +#endif /* KERNEL */ #define SCSI_EXTERNALLEN (sizeof(struct scsi_link)) diff --git a/sys/scsi/sctarg.c b/sys/scsi/sctarg.c new file mode 100644 index 0000000..9824f9b --- /dev/null +++ b/sys/scsi/sctarg.c @@ -0,0 +1,271 @@ +/* + * sctarg: Processor Type driver. + * + * 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: sctarg.c,v 1.1 1995/03/04 20:50:46 dufault Exp $ + */ + +/* + * XXX dufault@hda.com: We need the "kern devconf" stuff, but I'm not + * going to add it until it is done in a simple way that provides + * base behavior in scsi_driver.c + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/proc.h> +#include <scsi/scsi_all.h> +#include <scsi/scsiconf.h> + +#define OPEN 0x01 + +struct scsi_data { + struct buf *buf_queue; /* the queue of pending IO operations */ + int flags; /* Already open */ +}; + +errval sctarg_open(dev_t dev, int flags, int fmt, struct proc *p, +struct scsi_link *sc_link); +void sctargstart(u_int32 unit); +errval sctarg_close(dev_t dev, int flag, int fmt, struct proc *p, + struct scsi_link *sc_link); +void sctarg_strategy(struct buf *bp, struct scsi_link *sc_link); + +SCSI_DEVICE_ENTRIES(sctarg) + +struct scsi_device sctarg_switch = +{ + NULL, + sctargstart, /* we have a queue, and this is how we service it */ + NULL, + NULL, + "sctarg", + 0, + {0, 0}, + SDEV_ONCE_ONLY, + 0, + "Processor Target", + sctargopen, + sizeof(struct scsi_data), + T_TARGET, + 0, + 0, + sctarg_open, + 0, + 0, + sctarg_strategy, +}; + +errval sctarg_open(dev_t dev, int flags, int fmt, struct proc *p, +struct scsi_link *sc_link) +{ + int ret = 0; + + /* Does this host adapter support target mode operation? + */ + if ((sc_link->flags & SDEV_TARGET_OPS) == 0) + return ENODEV; /* Operation not supported */ + + if (SCSI_FIXED(dev)) { + sc_link->scsibus = SCSI_BUS(dev); + scsi_set_bus(sc_link->scsibus, sc_link); + + sc_link->target = SCSI_ID(dev); + sc_link->lun = SCSI_LUN(dev); + } + + if (sc_link->scsibus == SCCONF_UNSPEC || + sc_link->target == SCCONF_UNSPEC || + sc_link->lun == SCCONF_UNSPEC) + return ENXIO; + + /* XXX: You can have more than one target device on a single + * host adapter. We need a reference count. + */ + if ((sc_link->sd->flags & OPEN) == 0) /* Enable target mode */ + { + ret = scsi_target_mode(sc_link, 1); + sc_link->sd->flags |= OPEN; + } + + return ret; +} + +errval sctarg_close(dev_t dev, int flags, int fmt, struct proc *p, +struct scsi_link *sc_link) +{ + int ret = 0; + + /* XXX: You can have more than one target device on a single + * host adapter. We need a reference count. + */ + ret = scsi_target_mode(sc_link, 0); + + sc_link->sd->flags &= ~OPEN; + + return ret; +} + +/* + * sctargstart looks to see if there is a buf waiting for the device + * and that the device is not already busy. If both are true, + * It dequeues the buf and creates a scsi command to perform the + * transfer required. The transfer request will call scsi_done + * on completion, which will in turn call this routine again + * so that the next queued transfer is performed. + * The bufs are queued by the strategy routine (sctargstrategy) + * + * This routine is also called after other non-queued requests + * have been made of the scsi driver, to ensure that the queue + * continues to be drained. + * sctargstart() is called at splbio + */ +void +sctargstart(unit) + u_int32 unit; +{ + struct scsi_link *sc_link = SCSI_LINK(&sctarg_switch, unit); + struct scsi_data *sctarg = sc_link->sd; + register struct buf *bp = 0; + struct + { +#define PROCESSOR_SEND 0x0A +#define PROCESSOR_RECEIVE 0x08 + u_char op_code; + u_char byte2; + u_char len[3]; + u_char control; + } cmd; + + u_int32 flags; + + SC_DEBUG(sc_link, SDEV_DB2, ("sctargstart ")); + /* + * See if there is a buf to do and we are not already + * doing one + */ + while (sc_link->opennings != 0) { + + /* if a special awaits, let it proceed first */ + if (sc_link->flags & SDEV_WAITING) { + sc_link->flags &= ~SDEV_WAITING; + wakeup((caddr_t)sc_link); + return; + } + if ((bp = sctarg->buf_queue) == NULL) { + return; /* no work to bother with */ + } + sctarg->buf_queue = bp->b_actf; + + /* + * Fill out the scsi command + */ + bzero(&cmd, sizeof(cmd)); + flags = SCSI_TARGET; + if ((bp->b_flags & B_READ) == B_WRITE) { + cmd.op_code = PROCESSOR_SEND; + flags |= SCSI_DATA_OUT; + } else { + cmd.op_code = PROCESSOR_RECEIVE; + flags |= SCSI_DATA_IN; + } + + scsi_uto3b(bp->b_bcount, cmd.len); + /* + * go ask the adapter to do all this for us + */ + if (scsi_scsi_cmd(sc_link, + (struct scsi_generic *) &cmd, + sizeof(cmd), + (u_char *) bp->b_un.b_addr, + bp->b_bcount, + 0, + 100000, + bp, + flags | SCSI_NOSLEEP) == SUCCESSFULLY_QUEUED) { + } else { + printf("sctarg%ld: oops not queued\n", unit); + bp->b_flags |= B_ERROR; + bp->b_error = EIO; + biodone(bp); + } + } /* go back and see if we can cram more work in.. */ +} + +void +sctarg_strategy(struct buf *bp, struct scsi_link *sc_link) +{ + struct buf **dp; + unsigned char unit; + u_int32 opri; + struct scsi_data *sctarg; + + unit = STUNIT((bp->b_dev)); + sctarg = sc_link->sd; + + opri = splbio(); + + /* + * Use a bounce buffer if necessary + */ +#ifdef BOUNCE_BUFFERS + if (sc_link->flags & SDEV_BOUNCE) + vm_bounce_alloc(bp); +#endif + + /* + * Place it at the end of the queue of activities for this device. + */ + dp = &(sctarg->buf_queue); + while (*dp) { + dp = &((*dp)->b_actf); + } + *dp = bp; + bp->b_actf = NULL; + + /* + * Tell the device to get going on the transfer if it's + * not doing anything, otherwise just wait for completion + * (All a bit silly if we're only allowing 1 open but..) + */ + sctargstart(unit); + + splx(opri); + return; +} diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c index cc49a9f..03dd4db 100644 --- a/sys/scsi/sd.c +++ b/sys/scsi/sd.c @@ -50,10 +50,6 @@ u_int32 sdstrats, sdqueues; #define SD_RETRIES 4 #define MAXTRANSFER 8 /* 1 page at a time */ -#define SDUNITSHIFT 3 -#define SDUNIT(DEV) SH3_UNIT(DEV) -#define SDSETUNIT(DEV, U) SH3SETUNIT((DEV), (U)) - #define PARTITION(dev) dkpart(dev) #define SDUNIT(dev) dkunit(dev) @@ -187,19 +183,20 @@ sdattach(struct scsi_link *sc_link) * (could happen on removable media - MOD) * -- this avoids the division below from falling over */ - if(dp->secsiz == 0) dp->secsiz = 512; - printf("%luMB (%lu S), %u C %u H %u S/T %u B/S", + if(dp->secsiz == 0) dp->secsiz = SECSIZE; + printf("%ldMB (%ld %d byte sectors)", dp->disksize / ((1024L * 1024L) / dp->secsiz), dp->disksize, - dp->cyls, - dp->heads, - dp->sectors, dp->secsiz); +#ifndef SCSI_REPORT_GEOMETRY if ( (sc_link->flags & SDEV_BOOTVERBOSE) ) +#endif { printf("\n"); sc_print_addr(sc_link); + printf("with %d cyls, %d heads, and an average %d sectors/track", + dp->cyls, dp->heads, dp->sectors); } sd->flags |= SDINIT; @@ -237,7 +234,7 @@ sd_open(dev, mode, fmt, p, sc_link) } SC_DEBUG(sc_link, SDEV_DB1, - ("sd_open: dev=0x%x (unit %d, partition %d)\n", + ("sd_open: dev=0x%lx (unit %ld, partition %d)\n", dev, unit, PARTITION(dev))); /* @@ -318,7 +315,7 @@ sd_open(dev, mode, fmt, p, sc_link) goto bad; SC_DEBUG(sc_link, SDEV_DB3, ("Slice tables initialized ")); - SC_DEBUG(sc_link, SDEV_DB3, ("open %d %d\n", sdstrats, sdqueues)); + SC_DEBUG(sc_link, SDEV_DB3, ("open %ld %ld\n", sdstrats, sdqueues)); return 0; @@ -376,12 +373,7 @@ sd_strategy(struct buf *bp, struct scsi_link *sc_link) bp->b_error = EIO; goto bad; } - /* - * If it's a null transfer, return immediatly - */ - if (bp->b_bcount == 0) { - goto done; - } + /* * Odd number of bytes */ @@ -503,7 +495,7 @@ sdstart(u_int32 unit) * With this thing.. */ blkno = bp->b_pblkno; - if (bp->b_bcount & 511) + if (bp->b_bcount & (SECSIZE - 1)) { goto bad; } @@ -733,7 +725,7 @@ sd_get_parms(unit, flags) } else { SC_DEBUG(sc_link, SDEV_DB3, - ("%d cyls, %d heads, %d precomp, %d red_write, %d land_zone\n", + ("%ld 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, b2tol(scsi_sense.pages.rigid_geometry.st_cyl_wp), @@ -822,6 +814,11 @@ int sd_sense_handler(struct scsi_xfer *xs) if ((sense->error_code & SSD_ERRCODE) == 0x71) return SCSIRET_CONTINUE; + if (((sense->error_code & SSD_ERRCODE) == 0x70) && + ((sense->ext.extended.flags & SSD_KEY) == 0x05)) + /* No point in retrying Illegal Requests */ + return SCSIRET_CONTINUE; + inqbuf = &(xs->sc_link->inqbuf); /* It is dangerous to retry on removable drives without @@ -861,7 +858,6 @@ sddump(dev_t dev) static int sddoingadump = 0; struct scsi_xfer *xs = &sx; errval retval; - int c; addr = (char *) 0; /* starting address */ @@ -938,11 +934,11 @@ sddump(dev_t dev) xs->timeout = 10000; /* 10000 millisecs for a disk ! */ xs->cmd = (struct scsi_generic *) &cmd; xs->cmdlen = sizeof(cmd); - xs->resid = blkcnt * 512; + xs->resid = 0; xs->error = XS_NOERROR; xs->bp = 0; xs->data = (u_char *) CADDR1; /* XXX use pmap_enter() */ - xs->datalen = blkcnt * 512; + xs->datalen = blkcnt * SECSIZE; /* * Pass all this info to the scsi driver. @@ -963,7 +959,7 @@ sddump(dev_t dev) /* update block count */ num -= blkcnt; blknum += blkcnt; - (int) addr += 512 * blkcnt; + (int) addr += SECSIZE * blkcnt; /* operator aborting dump? */ if (cncheckc()) diff --git a/sys/scsi/st.c b/sys/scsi/st.c index c391b0a..81c8e04 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.30 1995/03/15 14:22:11 dufault Exp $ + * $Id: st.c,v 1.31 1995/03/21 11:21:08 dufault Exp $ */ /* @@ -343,10 +343,10 @@ stattach(struct scsi_link *sc_link) NULL, 0, 0)) { printf("drive offline"); } else { - printf("density code 0x%x, ", st->media_density); + printf("density code 0x%lx, ", 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); + printf("%ld-byte", st->media_blksiz); } else { printf("variable"); } @@ -390,7 +390,7 @@ st_identify_drive(unit) */ 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); + printf("st%ld: couldn't get device type, using default\n", unit); return; } if ((inqbuf->version & SID_ANSII) == 0) { @@ -431,7 +431,7 @@ st_identify_drive(unit) strcmp("????????????????", finger->model) == 0) && (strcmp(version, finger->version) == 0 || strcmp("????", finger->version) == 0)) { - printf("st%d: %s is a known rogue\n", unit, finger->name); + printf("st%ld: %s is a known rogue\n", unit, finger->name); st->rogues = finger; st->drive_quirks = finger->quirks; st->quirks = finger->quirks; /*start value */ @@ -550,7 +550,7 @@ struct scsi_link *sc_link) * Check that the device is ready to use (media loaded?) * This time take notice of the return result */ - if (errno = (scsi_test_unit_ready(sc_link, 0))) { + if ( (errno = scsi_test_unit_ready(sc_link, 0)) ) { uprintf("st%d: not ready\n", unit); st_unmount(unit, NOEJECT); return (errno); @@ -653,7 +653,7 @@ st_mount_tape(dev, flags) * If the media is new, then make sure we give it a chance to * to do a 'load' instruction. ( We assume it is new) */ - if (errno = st_load(unit, LD_LOAD, 0)) { + if ( (errno = st_load(unit, LD_LOAD, 0)) ) { return (errno); } /* @@ -669,14 +669,14 @@ st_mount_tape(dev, flags) * asked to look at the media. This quirk does this. */ if (st->quirks & ST_Q_SNS_HLP) { - if (errno = st_touch_tape(unit)) + if ( (errno = st_touch_tape(unit)) ) return errno; } /* * Load the physical device parameters * loads: blkmin, blkmax */ - if (errno = st_rd_blk_lim(unit, 0)) { + if ( (errno = st_rd_blk_lim(unit, 0)) ) { return errno; } /* @@ -685,7 +685,7 @@ st_mount_tape(dev, flags) * As we have a tape in, it should be reflected here. * If not you may need the "quirk" above. */ - if (errno = st_mode_sense(unit, 0, NULL, 0, 0)) { + if ( (errno = st_mode_sense(unit, 0, NULL, 0, 0)) ) { return errno; } /* @@ -710,12 +710,12 @@ st_mount_tape(dev, flags) st->flags |= ST_FIXEDBLOCKS; } } else { - if (errno = st_decide_mode(unit, FALSE)) { + if ( (errno = st_decide_mode(unit, FALSE)) ) { return errno; } } - if (errno = st_mode_select(unit, 0, NULL, 0)) { - printf("st%d: Cannot set selected mode", unit); + if ( (errno = st_mode_select(unit, 0, NULL, 0)) ) { + printf("st%ld: Cannot set selected mode", unit); return errno; } scsi_prevent(sc_link, PR_PREVENT, 0); /* who cares if it fails? */ @@ -776,7 +776,7 @@ st_decide_mode(unit, first_read) */ switch ((int)(st->quirks & (ST_Q_FORCE_FIXED_MODE | ST_Q_FORCE_VAR_MODE))) { case (ST_Q_FORCE_FIXED_MODE | ST_Q_FORCE_VAR_MODE): - printf("st%d: bad quirks\n", unit); + printf("st%ld: bad quirks\n", unit); return (EINVAL); case ST_Q_FORCE_FIXED_MODE: /*specified fixed, but not what size */ st->flags |= ST_FIXEDBLOCKS; @@ -786,7 +786,7 @@ st_decide_mode(unit, first_read) st->blksiz = st->media_blksiz; else st->blksiz = DEF_FIXED_BSIZE; - SC_DEBUG(sc_link, SDEV_DB3, ("Quirks force fixed mode(%d)\n", + SC_DEBUG(sc_link, SDEV_DB3, ("Quirks force fixed mode(%ld)\n", st->blksiz)); goto done; case ST_Q_FORCE_VAR_MODE: @@ -803,7 +803,7 @@ st_decide_mode(unit, first_read) st->flags |= ST_FIXEDBLOCKS; st->blksiz = st->blkmin; SC_DEBUG(sc_link, SDEV_DB3, - ("blkmin == blkmax of %d\n", st->blkmin)); + ("blkmin == blkmax of %ld\n", st->blkmin)); goto done; } /* @@ -851,7 +851,7 @@ st_decide_mode(unit, first_read) } st->blksiz = st->media_blksiz; SC_DEBUG(sc_link, SDEV_DB3, - ("Used media_blksiz of %d\n", st->media_blksiz)); + ("Used media_blksiz of %ld\n", st->media_blksiz)); goto done; } /* @@ -897,7 +897,7 @@ void st_strategy(struct buf *bp, struct scsi_link *sc_link) { struct buf **dp; - unsigned char unit; + unsigned char unit; /* XXX Everywhere else unit is "u_int32". Please int? */ u_int32 opri; struct scsi_data *st; @@ -915,7 +915,7 @@ st_strategy(struct buf *bp, struct scsi_link *sc_link) */ if (st->flags & ST_FIXEDBLOCKS) { if (bp->b_bcount % st->blksiz) { - printf("st%d: bad request, must be multiple of %d\n", + printf("st%d: bad request, must be multiple of %ld\n", unit, st->blksiz); bp->b_error = EIO; goto bad; @@ -925,7 +925,7 @@ st_strategy(struct buf *bp, struct scsi_link *sc_link) * as are out-of-range requests on variable drives. */ else if (bp->b_bcount < st->blkmin || bp->b_bcount > st->blkmax) { - printf("st%d: bad request, must be between %d and %d\n", + printf("st%d: bad request, must be between %ld and %ld\n", unit, st->blkmin, st->blkmax); bp->b_error = EIO; goto bad; @@ -1102,7 +1102,7 @@ ststart(unit) stqueues++; } else { badnews: - printf("st%d: oops not queued\n", unit); + printf("st%ld: oops not queued\n", unit); bp->b_flags |= B_ERROR; bp->b_error = EIO; biodone(bp); @@ -1166,7 +1166,7 @@ struct proc *p, struct scsi_link *sc_link) case MTIOCTOP: { - SC_DEBUG(sc_link, SDEV_DB1, ("[ioctl: op=0x%x count=0x%x]\n", + SC_DEBUG(sc_link, SDEV_DB1, ("[ioctl: op=0x%x count=0x%lx]\n", mt->mt_op, mt->mt_count)); /* compat: in U*x it is a short */ @@ -1259,7 +1259,7 @@ try_new_value: * Check that the mode being asked for is aggreeable to the * drive. If not, put it back the way it was. */ - if (errcode = st_mode_select(unit, 0, NULL, 0)) { /* put it back as it was */ + if ( (errcode = st_mode_select(unit, 0, NULL, 0)) ) { /* put back as it was */ printf("st%d: Cannot set selected mode", unit); st->density = hold_density; st->blksiz = hold_blksiz; @@ -1364,7 +1364,7 @@ st_rd_blk_lim(unit, flags) /* * do the command, update the global values */ - if (errno = scsi_scsi_cmd(sc_link, + if ( (errno = scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd, sizeof(scsi_cmd), (u_char *) & scsi_blkl, @@ -1372,14 +1372,14 @@ st_rd_blk_lim(unit, flags) ST_RETRIES, 5000, NULL, - flags | SCSI_DATA_IN)) { + flags | SCSI_DATA_IN)) ) { return errno; } st->blkmin = b2tol(scsi_blkl.min_length); st->blkmax = scsi_3btou(&scsi_blkl.max_length_2); SC_DEBUG(sc_link, SDEV_DB3, - ("(%d <= blksiz <= %d)\n", st->blkmin, st->blkmax)); + ("(%ld <= blksiz <= %ld)\n", st->blkmin, st->blkmax)); return 0; } @@ -1446,7 +1446,7 @@ st_mode_sense(unit, flags, page, pagelen, pagecode) * or if we need it as a template for the mode select * store it away. */ - if (errno = scsi_scsi_cmd(sc_link, + if ( (errno = scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd, sizeof(scsi_cmd), (u_char *) &dat, @@ -1454,7 +1454,7 @@ st_mode_sense(unit, flags, page, pagelen, pagecode) ST_RETRIES, 5000, NULL, - flags | SCSI_DATA_IN)) { + flags | SCSI_DATA_IN)) ) { return errno; } st->numblks = scsi_3btou(dat.blk_desc.nblocks); @@ -1464,7 +1464,7 @@ st_mode_sense(unit, flags, page, pagelen, pagecode) st->flags |= ST_READONLY; } SC_DEBUG(sc_link, SDEV_DB3, - ("density code 0x%x, %d-byte blocks, write-%s, ", + ("density code 0x%lx, %ld-byte blocks, write-%s, ", st->media_density, st->media_blksiz, st->flags & ST_READONLY ? "protected" : "enabled")); SC_DEBUG(sc_link, SDEV_DB3, ("%sbuffered\n", @@ -1559,14 +1559,14 @@ u_int32 unit,mode; bzero(&page, sizeof(page)); pagesize = sizeof(page.pages.configuration) + PAGE_HEADERLEN; - if ( retval = st_mode_sense(unit, 0, - &page, pagesize, ST_PAGE_CONFIGURATION)) + if ( (retval = st_mode_sense(unit, 0, + &page, pagesize, ST_PAGE_CONFIGURATION)) ) { printf("sense returned an error of %d\n",retval); return retval; } if ( noisy_st) - printf("drive reports value of %d, setting %d\n", + printf("drive reports value of %d, setting %ld\n", page.pages.configuration.data_compress_alg,mode); page.pg_code &= ST_P_CODE; @@ -1581,10 +1581,10 @@ u_int32 unit,mode; page.pages.configuration.data_compress_alg = 1; break; default: - printf("st%d: bad value for compression mode\n",unit); + printf("st%ld: bad value for compression mode\n",unit); return EINVAL; } - if ( retval = st_mode_select(unit, 0, &page, pagesize)) + if ( (retval = st_mode_select(unit, 0, &page, pagesize)) ) { printf("select returned an error of %d\n",retval); return retval; @@ -1859,12 +1859,6 @@ st_erase(unit, immed, flags) flags)); } -#ifdef NETBSD -#define SIGNAL_SHORT_READ -#else -#define SIGNAL_SHORT_READ bp->b_flags |= B_ERROR; -#endif - /* * Look at the returned sense and act on the error and detirmine * The unix error number to pass back... (0 = report no error) @@ -1877,7 +1871,6 @@ st_interpret_sense(xs) struct scsi_link *sc_link = xs->sc_link; struct scsi_sense_data *sense = &(xs->sense); boolean silent = xs->flags & SCSI_SILENT; - struct buf *bp = xs->bp; u_int32 unit = sc_link->dev_unit; struct scsi_data *st = SCSI_DATA(&st_switch, unit); u_int32 key; @@ -1889,97 +1882,92 @@ st_interpret_sense(xs) if (sense->error_code & SSD_ERRCODE_VALID) { info = ntohl(*((int32 *) sense->ext.extended.info)); } else { - info = xs->datalen; /* bad choice if fixed blocks */ + if (st->flags & ST_FIXEDBLOCKS) { + info = xs->datalen / st->blksiz; + } else { + info = xs->datalen; + } } if ((sense->error_code & SSD_ERRCODE) != 0x70) { - return SCSIRET_CONTINUE; /* let the generic code handle it */ + return SCSIRET_CONTINUE;/* let the generic code handle it */ } - if (st->flags & ST_FIXEDBLOCKS) { - xs->resid = info * st->blksiz; - if (sense->ext.extended.flags & SSD_EOM) { - st->flags |= ST_EIO_PENDING; - if (bp) { - bp->b_resid = xs->resid; - SIGNAL_SHORT_READ + if(sense->ext.extended.flags & (SSD_EOM|SSD_FILEMARK|SSD_ILI)) { + if (st->flags & ST_FIXEDBLOCKS) { + xs->resid = info * st->blksiz; + xs->flags |= SCSI_RESID_VALID; + if (sense->ext.extended.flags & SSD_EOM) { + st->flags |= ST_EIO_PENDING; } - } - if (sense->ext.extended.flags & SSD_FILEMARK) { - st->flags |= ST_AT_FILEMARK; - if (bp) { - bp->b_resid = xs->resid; - SIGNAL_SHORT_READ + if (sense->ext.extended.flags & SSD_FILEMARK) { + st->flags |= ST_AT_FILEMARK; } - } - if (sense->ext.extended.flags & SSD_ILI) { - st->flags |= ST_EIO_PENDING; - if (bp) { - bp->b_resid = xs->resid; - SIGNAL_SHORT_READ + if (sense->ext.extended.flags & SSD_ILI) { + st->flags |= ST_EIO_PENDING; + if (sense->error_code & SSD_ERRCODE_VALID && + !silent) + printf("st%ld: block wrong size" + ", %ld blocks residual\n", unit + ,info); + /*XXX*/ /* is this how it works ? */ + /* check def of ILI for fixed blk tapes */ + + /* + * This quirk code helps the drive read + * the first tape block, regardless of + * format. That is required for these + * drives to return proper MODE SENSE + * information. + */ + if ((st->quirks & ST_Q_SNS_HLP) && + !(sc_link->flags & SDEV_MEDIA_LOADED)) { + st->blksiz -= 512; + } } - if (sense->error_code & SSD_ERRCODE_VALID && - !silent) - printf("st%d: block wrong size" - ", %d blocks residual\n", unit - ,info); - /* - * This quirk code helps the drive read - * the first tape block, regardless of - * format. That is required for these - * drives to return proper MODE SENSE - * information. + * If no data was tranfered, do it immediatly */ - if ((st->quirks & ST_Q_SNS_HLP) && - !(sc_link->flags & SDEV_MEDIA_LOADED)) { - st->blksiz -= 512; - } - } - /* - * If no data was tranfered, do it immediatly - */ - if (xs->resid >= xs->datalen) { - if (st->flags & ST_EIO_PENDING) { - return EIO; - } - if (st->flags & ST_AT_FILEMARK) { - if (bp) { - bp->b_resid = xs->resid; - SIGNAL_SHORT_READ + if (xs->resid >= xs->datalen) { + xs->flags &= ~SCSI_RESID_VALID; + if (st->flags & ST_AT_FILEMARK) { + xs->flags |= SCSI_EOF; + st->flags &= ~ST_AT_FILEMARK; + return 0; + } + if (st->flags & ST_EIO_PENDING) { + st->flags &= ~ST_EIO_PENDING; + return EIO; } - return 0; } - } - } else { /* must be variable mode */ - xs->resid = xs->datalen; /* to be sure */ - if (sense->ext.extended.flags & SSD_EOM) { - return (EIO); - } - if (sense->ext.extended.flags & SSD_FILEMARK) { - if (bp) - bp->b_resid = bp->b_bcount; return 0; - } - if (sense->ext.extended.flags & SSD_ILI) { - if (info < 0) { - /* - * the record was bigger than the read - */ - if (!silent) - printf("st%d: %d-byte record " - "too big\n", unit, - xs->datalen - info); + } else { /* must be variable mode */ + xs->resid = xs->datalen; /* to be sure */ + if (sense->ext.extended.flags & SSD_EOM) { return (EIO); } - xs->resid = info; - if (bp) { - bp->b_resid = info; - SIGNAL_SHORT_READ + if (sense->ext.extended.flags & SSD_FILEMARK) { + xs->flags |= SCSI_EOF; + } + if (sense->ext.extended.flags & SSD_ILI) { + if (info < 0) { + /* + * the record was bigger than the read + */ + if (!silent) + printf("st%ld: %ld-byte record " + "too big\n", unit, + xs->datalen - info); + return (EIO); + } + xs->resid = info; + xs->flags |= SCSI_RESID_VALID; } } + return 0; } key = sense->ext.extended.flags & SSD_KEY; if (key == 0x8) { + xs->flags |= SCSI_EOF; /* some drives need this */ /* * This quirk code helps the drive read the * first tape block, regardless of format. That @@ -1987,19 +1975,16 @@ st_interpret_sense(xs) * MODE SENSE information. */ if ((st->quirks & ST_Q_SNS_HLP) && - !(sc_link->flags & SDEV_MEDIA_LOADED)) { /* still starting */ + !(sc_link->flags & SDEV_MEDIA_LOADED)) { + /* still starting */ st->blksiz -= 512; } else if (!(st->flags & (ST_2FM_AT_EOD | ST_BLANK_READ))) { st->flags |= ST_BLANK_READ; - xs->resid = xs->datalen; - if (bp) { - bp->b_resid = xs->resid; - /*return an EOF */ - } + xs->flags |= SCSI_EOF; return (ESUCCESS); } } - return SCSIRET_CONTINUE; /* let the default/generic handler handle it */ + return SCSIRET_CONTINUE; /* Use the the generic handler */ } /* @@ -2031,7 +2016,7 @@ st_touch_tape(unit) if (!buf) return (ENOMEM); - if (errno = st_mode_sense(unit, 0, NULL, 0, 0)) { + if (( errno = st_mode_sense(unit, 0, NULL, 0, 0)) ) { goto bad; } st->blksiz = 1024; @@ -2045,11 +2030,11 @@ st_touch_tape(unit) default: readsiz = 1; st->flags &= ~ST_FIXEDBLOCKS; - } if (errno = st_mode_select(unit, 0, NULL, 0)) { + } if ( (errno = st_mode_select(unit, 0, NULL, 0)) ) { goto bad; } st_read(unit, buf, readsiz, SCSI_SILENT); - if (errno = st_rewind(unit, FALSE, 0)) { + if ( (errno = st_rewind(unit, FALSE, 0)) ) { bad: free(buf, M_TEMP); return (errno); } |