From: downsj Date: Mon, 14 Apr 1997 04:09:03 +0000 (+0000) Subject: Merge in various pieces of current NetBSD scsi code, including but not limited X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=cb3ad6e35079dc4fa3654fb673602e2463382b94;p=openbsd Merge in various pieces of current NetBSD scsi code, including but not limited to: * New changer driver. * Better optical support. * Different `done' semantics. * New quirks for SCSI QIC tape driver, SCSI floppy drives. * Better support for SCSI-I devices. Everybody needs to test this. --- diff --git a/sys/scsi/cd.c b/sys/scsi/cd.c index 0bb33ae9974..963b0c6c7be 100644 --- a/sys/scsi/cd.c +++ b/sys/scsi/cd.c @@ -1,8 +1,8 @@ -/* $OpenBSD: cd.c,v 1.22 1997/03/29 23:54:20 briggs Exp $ */ -/* $NetBSD: cd.c,v 1.92 1996/05/05 19:52:50 christos Exp $ */ +/* $OpenBSD: cd.c,v 1.23 1997/04/14 04:09:03 downsj Exp $ */ +/* $NetBSD: cd.c,v 1.100 1997/04/02 02:29:30 mycroft Exp $ */ /* - * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1994, 1995, 1997 Charles M. Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -111,7 +111,7 @@ void cdunlock __P((struct cd_softc *)); void cdstart __P((void *)); void cdminphys __P((struct buf *)); void cdgetdisklabel __P((dev_t, struct cd_softc *)); -int cddone __P((struct scsi_xfer *, int)); +void cddone __P((struct scsi_xfer *)); u_long cd_size __P((struct cd_softc *, int)); int cd_get_mode __P((struct cd_softc *, struct cd_mode_data *, int)); int cd_set_mode __P((struct cd_softc *, struct cd_mode_data *)); @@ -642,17 +642,14 @@ cdstart(v) } } -int -cddone(xs, complete) +void +cddone(xs) struct scsi_xfer *xs; - int complete; { struct cd_softc *cd = xs->sc_link->device_softc; - if (complete && (xs->bp != NULL)) - disk_unbusy(&cd->sc_dk, (xs->bp->b_bcount - xs->bp->b_resid)); - - return (0); + if (xs->bp != NULL) + disk_unbusy(&cd->sc_dk, xs->bp->b_bcount - xs->bp->b_resid); } void @@ -1305,7 +1302,7 @@ cd_read_subchannel(cd, mode, format, track, data, len) _lto2b(len, scsi_cmd.data_len); return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd, sizeof(struct scsi_read_subchannel), (u_char *)data, len, - CDRETRIES, 5000, NULL, SCSI_DATA_IN); + CDRETRIES, 5000, NULL, SCSI_DATA_IN||SCSI_SILENT); } /* diff --git a/sys/scsi/ch.c b/sys/scsi/ch.c index b4f6be9e15d..c7fdea0549e 100644 --- a/sys/scsi/ch.c +++ b/sys/scsi/ch.c @@ -1,8 +1,8 @@ -/* $OpenBSD: ch.c,v 1.6 1996/08/12 10:21:41 deraadt Exp $ */ -/* $NetBSD: ch.c,v 1.21 1996/04/19 00:02:29 christos Exp $ */ +/* $OpenBSD: ch.c,v 1.7 1997/04/14 04:09:05 downsj Exp $ */ +/* $NetBSD: ch.c,v 1.26 1997/02/21 22:06:52 thorpej Exp $ */ /* - * Copyright (c) 1996 Jason R. Thorpe + * Copyright (c) 1996, 1997 Jason R. Thorpe * All rights reserved. * * Partially based on an autochanger driver written by Stefan Grefen @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -81,6 +82,12 @@ struct ch_softc { u_int8_t sc_exchangemask[4]; int flags; /* misc. info */ + + /* + * Quirks; see below. + */ + int sc_settledelay; /* delay for settle */ + }; /* sc_flags */ @@ -114,6 +121,21 @@ int ch_position __P((struct ch_softc *, struct changer_position *)); int ch_usergetelemstatus __P((struct ch_softc *, int, u_int8_t *)); int ch_getelemstatus __P((struct ch_softc *, int, int, caddr_t, size_t)); int ch_get_params __P((struct ch_softc *, int)); +void ch_get_quirks __P((struct ch_softc *, struct scsi_inquiry_data *)); + +/* + * SCSI changer quirks. + */ +struct chquirk { + struct scsi_inquiry_pattern cq_match; /* device id pattern */ + int cq_settledelay; /* settle delay, in seconds */ +}; + +struct chquirk chquirks[] = { + {{T_CHANGER, T_REMOV, + "SPECTRA", "9000", "0200"}, + 75}, +}; int chmatch(parent, match, aux) @@ -147,6 +169,21 @@ chattach(parent, self, aux) printf("\n"); + /* + * Find out our device's quirks. + */ + ch_get_quirks(sc, sa->sa_inqbuf); + + /* + * Some changers require a long time to settle out, to do + * tape inventory, for instance. + */ + if (sc->sc_settledelay) { + printf("%s: waiting %d seconds for changer to settle...\n", + sc->sc_dev.dv_xname, sc->sc_settledelay); + delay(1000000 * sc->sc_settledelay); + } + /* * Get information about the device. Note we can't use * interrupts yet. @@ -154,18 +191,14 @@ chattach(parent, self, aux) if (ch_get_params(sc, SCSI_AUTOCONF)) printf("%s: offline\n", sc->sc_dev.dv_xname); else { - printf("%s: %d slot%s, %d drive%s, %d picker%s", +#define PLURAL(c) (c) == 1 ? "" : "s" + printf("%s: %d slot%s, %d drive%s, %d picker%s, %d portal%s\n", sc->sc_dev.dv_xname, - sc->sc_counts[CHET_ST], (sc->sc_counts[CHET_ST] > 1) ? - "s" : "", - sc->sc_counts[CHET_DT], (sc->sc_counts[CHET_DT] > 1) ? - "s" : "", - sc->sc_counts[CHET_MT], (sc->sc_counts[CHET_MT] > 1) ? - "s" : ""); - if (sc->sc_counts[CHET_IE]) - printf(", %d portal%s", sc->sc_counts[CHET_IE], - (sc->sc_counts[CHET_IE] > 1) ? "s" : ""); - printf("\n"); + sc->sc_counts[CHET_ST], PLURAL(sc->sc_counts[CHET_ST]), + sc->sc_counts[CHET_DT], PLURAL(sc->sc_counts[CHET_DT]), + sc->sc_counts[CHET_MT], PLURAL(sc->sc_counts[CHET_MT]), + sc->sc_counts[CHET_IE], PLURAL(sc->sc_counts[CHET_IE])); +#undef PLURAL #ifdef CHANGER_DEBUG printf("%s: move mask: 0x%x 0x%x 0x%x 0x%x\n", sc->sc_dev.dv_xname, @@ -250,6 +283,21 @@ chioctl(dev, cmd, data, flags, p) struct ch_softc *sc = ch_cd.cd_devs[CHUNIT(dev)]; int error = 0; + /* + * If this command can change the device's state, we must + * have the device open for writing. + */ + switch (cmd) { + case CHIOGPICKER: + case CHIOGPARAMS: + case CHIOGSTATUS: + break; + + default: + if ((flags & FWRITE) == 0) + return (EBADF); + } + switch (cmd) { case CHIOMOVE: error = ch_move(sc, (struct changer_move *)data); @@ -637,3 +685,22 @@ ch_get_params(sc, scsiflags) sc->sc_link->flags |= SDEV_MEDIA_LOADED; return (0); } + +void +ch_get_quirks(sc, inqbuf) + struct ch_softc *sc; + struct scsi_inquiry_data *inqbuf; +{ + struct chquirk *match; + int priority; + + sc->sc_settledelay = 0; + + match = (struct chquirk *)scsi_inqmatch(inqbuf, + (caddr_t)chquirks, + sizeof(chquirks) / sizeof(chquirks[0]), + sizeof(chquirks[0]), &priority); + if (priority != 0) { + sc->sc_settledelay = match->cq_settledelay; + } +} diff --git a/sys/scsi/scsi_all.h b/sys/scsi/scsi_all.h index c9492a5bb48..746d6dbf086 100644 --- a/sys/scsi/scsi_all.h +++ b/sys/scsi/scsi_all.h @@ -1,5 +1,5 @@ -/* $OpenBSD: scsi_all.h,v 1.4 1996/07/02 20:18:49 deraadt Exp $ */ -/* $NetBSD: scsi_all.h,v 1.7 1996/03/19 03:06:10 mycroft Exp $ */ +/* $OpenBSD: scsi_all.h,v 1.5 1997/04/14 04:09:06 downsj Exp $ */ +/* $NetBSD: scsi_all.h,v 1.10 1996/09/12 01:57:17 thorpej Exp $ */ /* * SCSI general interface description @@ -35,8 +35,14 @@ #define SCSI_CTL_LINK 0x01 #define SCSI_CTL_FLAG 0x02 #define SCSI_CTL_VENDOR 0xC0 -#define SCSI_CMD_LUN 0xA0 /* these two should not be needed */ -#define SCSI_CMD_LUN_SHIFT 5 /* LUN in the cmd is no longer SCSI */ + + +/* + * Some old SCSI devices need the LUN to be set in the top 3 bits of the + * second byte of the CDB. + */ +#define SCSI_CMD_LUN_MASK 0xe0 +#define SCSI_CMD_LUN_SHIFT 5 struct scsi_generic { @@ -176,8 +182,6 @@ struct scsi_changedef { #define CHANGE_DEFINITION 0x40 #define MODE_SENSE_BIG 0x54 #define MODE_SELECT_BIG 0x55 -#define MOVE_MEDIUM 0xa5 -#define READ_ELEMENT_STATUS 0xb8 /* * Sort of an extra one, for SCSI_RESET. diff --git a/sys/scsi/scsi_base.c b/sys/scsi/scsi_base.c index ac52d489caa..42e47dbcb85 100644 --- a/sys/scsi/scsi_base.c +++ b/sys/scsi/scsi_base.c @@ -1,8 +1,8 @@ -/* $OpenBSD: scsi_base.c,v 1.10 1996/06/16 03:07:19 downsj Exp $ */ -/* $NetBSD: scsi_base.c,v 1.36 1996/05/03 19:48:20 christos Exp $ */ +/* $OpenBSD: scsi_base.c,v 1.11 1997/04/14 04:09:07 downsj Exp $ */ +/* $NetBSD: scsi_base.c,v 1.43 1997/04/02 02:29:36 mycroft Exp $ */ /* - * Copyright (c) 1994, 1995 Charles Hannum. All rights reserved. + * Copyright (c) 1994, 1995, 1997 Charles M. Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -14,7 +14,7 @@ * 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 Charles Hannum. + * This product includes software developed by Charles M. Hannum. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * @@ -49,8 +49,6 @@ #include #include -void scsi_error __P((struct scsi_xfer *, int)); - LIST_HEAD(xs_free_list, scsi_xfer) xs_free_list; static __inline struct scsi_xfer *scsi_make_xs __P((struct scsi_link *, @@ -181,6 +179,14 @@ scsi_make_xs(sc_link, scsi_cmd, cmdlen, data_addr, datalen, xs->timeout = timeout; xs->bp = bp; + /* + * Set the LUN in the CDB if we have an older device. We also + * set it for more modern SCSI-II devices "just in case". + */ + if ((sc_link->scsi_version & SID_ANSII) <= 2) + xs->cmd->bytes[0] |= + ((sc_link->lun << SCSI_CMD_LUN_SHIFT) & SCSI_CMD_LUN_MASK); + return xs; } @@ -318,6 +324,7 @@ scsi_done(xs) struct scsi_xfer *xs; { struct scsi_link *sc_link = xs->sc_link; + struct buf *bp; int error; SC_DEBUG(sc_link, SDEV_DB2, ("scsi_done\n")); @@ -341,23 +348,7 @@ scsi_done(xs) return; } - /* - * If the device has it's own done routine, call it first. - * If it returns a legit error value, return that, otherwise - * it wants us to continue with normal processing. - * - * Make sure the upper-level driver knows that this might not - * actually be the last time they hear from us. We need to get - * status back. - */ - if (sc_link->device->done) { - SC_DEBUG(sc_link, SDEV_DB2, ("calling private done()\n")); - error = (*sc_link->device->done)(xs, 0); - if (error == EJUSTRETURN) - goto done; - SC_DEBUG(sc_link, SDEV_DB3, ("continuing with generic done()\n")); - } - if (xs->bp == NULL) { + if (!((xs->flags & (SCSI_NOSLEEP | SCSI_POLL)) == SCSI_NOSLEEP)) { /* * if it's a normal upper level request, then ask * the upper level code to handle error checking @@ -366,12 +357,14 @@ scsi_done(xs) wakeup(xs); return; } + /* * Go and handle errors now. * If it returns ERESTART then we should RETRY */ retry: - if (sc_err1(xs, 1) == ERESTART) { + error = sc_err1(xs, 1); + if (error == ERESTART) { switch ((*(sc_link->adapter->scsi_cmd)) (xs)) { case SUCCESSFULLY_QUEUED: return; @@ -382,7 +375,18 @@ retry: goto retry; } } -done: + + bp = xs->bp; + if (bp) { + if (error) { + bp->b_error = error; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + } else { + bp->b_error = 0; + bp->b_resid = xs->resid; + } + } if (sc_link->device->done) { /* * Tell the device the operation is actually complete. @@ -390,9 +394,11 @@ done: * notification of the upper-level driver only; they * won't be returning any meaningful information to us. */ - (void)(*sc_link->device->done)(xs, 1); + (*sc_link->device->done)(xs); } scsi_free_xs(xs, SCSI_NOSLEEP); + if (bp) + biodone(bp); } int @@ -417,14 +423,19 @@ retry: * TRY_AGAIN_LATER, (as for polling) * After the wakeup, we must still check if it succeeded * - * If we have a bp however, all the error processing - * and the buffer code both expect us to return straight - * to them, so as soon as the command is queued, return + * If we have a SCSI_NOSLEEP (typically because we have a buf) + * we just return. All the error proccessing and the buffer + * code both expect us to return straight to them, so as soon + * as the command is queued, return. */ switch ((*(xs->sc_link->adapter->scsi_cmd)) (xs)) { case SUCCESSFULLY_QUEUED: - if (xs->bp) + if ((xs->flags & (SCSI_NOSLEEP | SCSI_POLL)) == SCSI_NOSLEEP) return EJUSTRETURN; +#ifdef DIAGNOSTIC + if (xs->flags & SCSI_NOSLEEP) + panic("scsi_execute_xs: NOSLEEP and POLL"); +#endif s = splbio(); while ((xs->flags & ITSDONE) == 0) tsleep(xs, PRIBIO + 1, "scsi_scsi_cmd", 0); @@ -561,30 +572,9 @@ sc_err1(xs, async) break; } - scsi_error(xs, error); return error; } -void -scsi_error(xs, error) - struct scsi_xfer *xs; - int error; -{ - struct buf *bp = xs->bp; - - if (bp) { - if (error) { - bp->b_error = error; - bp->b_flags |= B_ERROR; - bp->b_resid = bp->b_bcount; - } else { - bp->b_error = 0; - bp->b_resid = xs->resid; - } - biodone(bp); - } -} - /* * Look at the returned sense and act on the error, determining * the unix error number to pass back. (0 = report no error) diff --git a/sys/scsi/scsi_debug.h b/sys/scsi/scsi_debug.h index b190adedd81..b46012c8c8c 100644 --- a/sys/scsi/scsi_debug.h +++ b/sys/scsi/scsi_debug.h @@ -1,5 +1,5 @@ -/* $OpenBSD: scsi_debug.h,v 1.4 1996/11/28 13:20:36 niklas Exp $ */ -/* $NetBSD: scsi_debug.h,v 1.5 1994/12/28 19:43:00 mycroft Exp $ */ +/* $OpenBSD: scsi_debug.h,v 1.5 1997/04/14 04:09:08 downsj Exp $ */ +/* $NetBSD: scsi_debug.h,v 1.7 1996/10/12 23:23:16 christos Exp $ */ /* * Written by Julian Elischer (julian@tfs.com) diff --git a/sys/scsi/scsi_disk.h b/sys/scsi/scsi_disk.h index 614e40f83b3..002812619c7 100644 --- a/sys/scsi/scsi_disk.h +++ b/sys/scsi/scsi_disk.h @@ -1,5 +1,5 @@ -/* $OpenBSD: scsi_disk.h,v 1.5 1996/10/31 01:09:23 niklas Exp $ */ -/* $NetBSD: scsi_disk.h,v 1.9 1996/03/19 03:07:02 mycroft Exp $ */ +/* $OpenBSD: scsi_disk.h,v 1.6 1997/04/14 04:09:09 downsj Exp $ */ +/* $NetBSD: scsi_disk.h,v 1.10 1996/07/05 16:19:05 christos Exp $ */ /* * SCSI interface description @@ -176,41 +176,34 @@ union disk_pages { u_int8_t reserved3; } rigid_geometry; struct page_flex_geometry { - u_char pg_code; /* page code (should be 5) */ - u_char pg_length; /* page length (should be 0x1e) */ - u_char xfr_rate1; - u_char xfr_rate0; - u_char nheads; /* number of heads */ - u_char ph_sec_t; /* physical sectors per track */ - u_char bytes_s_1; /* bytes per sector (MSB) */ - u_char bytes_s_0; /* bytes per sector (LSB) */ - u_char ncyl_1; /* number of cylinders (MSB) */ - u_char ncyl_0; /* number of cylinders (LSB) */ - u_char st_cyl_wp_1; /* starting cyl., write precomp (MSB) */ - u_char st_cyl_wp_0; /* starting cyl., write precomp (LSB) */ - u_char st_cyl_rwc_1; /* starting cyl., red. write cur (MSB) */ - u_char st_cyl_rwc_0; /* starting cyl., red. write cur (LSB) */ - u_char driv_step_1; /* drive step rate (MSB) */ - u_char driv_step_0; /* drive step rate (LSB) */ - u_char driv_step_w; /* drive step pulse width */ - u_char head_settle_1; /* head settle delay (MSB) */ - u_char head_settle_0; /* head settle delay (LSB) */ - u_char motor_on; /* motor on delay */ - u_char motor_off; /* motor off delay */ - u_char flags; /* various flags */ -#define MO 0x20 /* motor on (pin 16)? */ -#define SSN 0x40 /* start at sector 1 */ -#define TRDY 0x20 /* RDY (pin 34) valid */ - u_char step_p_cyl; /* step pulses per cylinder */ - u_char write_pre; /* write precompensation */ - u_char head_load; /* head load delay */ - u_char head_unload; /* head unload delay */ - u_char pin_34_2; /* pin 34 (6) and pin 2 (7/11) definition */ - u_char pin_4_1; /* pin 4 (8/9) and pin 1 (13) definition */ - u_char reserved1; - u_char reserved2; - u_char reserved3; - u_char reserved4; + u_int8_t pg_code; /* page code (should be 5) */ + u_int8_t pg_length; /* page length (should be 0x1e) */ + u_int8_t xfr_rate[2]; + u_int8_t nheads; /* number of heads */ + u_int8_t ph_sec_tr; /* physical sectors per track */ + u_int8_t bytes_s[2]; /* bytes per sector */ + u_int8_t ncyl[2]; /* number of cylinders */ + u_int8_t st_cyl_wp[2]; /* start cyl., write precomp */ + u_int8_t st_cyl_rwc[2]; /* start cyl., red. write cur */ + u_int8_t driv_step[2]; /* drive step rate */ + u_int8_t driv_step_w; /* drive step pulse width */ + u_int8_t head_settle[2];/* head settle delay */ + u_int8_t motor_on; /* motor on delay */ + u_int8_t motor_off; /* motor off delay */ + u_int8_t flags; /* various flags */ +#define MOTOR_ON 0x20 /* motor on (pin 16)? */ +#define START_AT_SECTOR_1 0x40 /* start at sector 1 */ +#define READY_VALID 0x20 /* RDY (pin 34) valid */ + u_int8_t step_p_cyl; /* step pulses per cylinder */ + u_int8_t write_pre; /* write precompensation */ + u_int8_t head_load; /* head load delay */ + u_int8_t head_unload; /* head unload delay */ + u_int8_t pin_34_2; /* pin 34 (6) pin 2 (7/11) definition */ + u_int8_t pin_4_1; /* pin 4 (8/9) pin 1 (13) definition */ + u_int8_t reserved1; + u_int8_t reserved2; + u_int8_t reserved3; + u_int8_t reserved4; } flex_geometry; }; diff --git a/sys/scsi/scsi_ioctl.c b/sys/scsi/scsi_ioctl.c index c9c5625dd44..f1fc067dff8 100644 --- a/sys/scsi/scsi_ioctl.c +++ b/sys/scsi/scsi_ioctl.c @@ -1,5 +1,5 @@ -/* $OpenBSD: scsi_ioctl.c,v 1.6 1996/08/13 00:06:24 niklas Exp $ */ -/* $NetBSD: scsi_ioctl.c,v 1.20 1996/02/14 21:47:22 christos Exp $ */ +/* $OpenBSD: scsi_ioctl.c,v 1.7 1997/04/14 04:09:11 downsj Exp $ */ +/* $NetBSD: scsi_ioctl.c,v 1.23 1996/10/12 23:23:17 christos Exp $ */ /* * Copyright (c) 1994 Charles Hannum. All rights reserved. @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -289,6 +290,16 @@ scsi_do_ioctl(sc_link, dev, cmd, addr, flag, p) SC_DEBUG(sc_link, SDEV_DB2, ("scsi_do_ioctl(0x%lx)\n", cmd)); + /* Check for the safe-ness of this request. */ + switch (cmd) { + case SCIOCIDENTIFY: + break; + + default: + if ((flag & FWRITE) == 0) + return EBADF; + } + switch(cmd) { case SCIOCCOMMAND: { scsireq_t *screq = (scsireq_t *)addr; diff --git a/sys/scsi/scsi_tape.h b/sys/scsi/scsi_tape.h index 3ac4bc1eb3b..6b613873fd6 100644 --- a/sys/scsi/scsi_tape.h +++ b/sys/scsi/scsi_tape.h @@ -1,5 +1,5 @@ -/* $OpenBSD: scsi_tape.h,v 1.5 1996/10/31 01:09:24 niklas Exp $ */ -/* $NetBSD: scsi_tape.h,v 1.8 1996/03/19 03:07:36 mycroft Exp $ */ +/* $OpenBSD: scsi_tape.h,v 1.6 1997/04/14 04:09:13 downsj Exp $ */ +/* $NetBSD: scsi_tape.h,v 1.9 1996/05/24 02:04:47 thorpej Exp $ */ /* * Copyright (c) 1994 Charles Hannum. All rights reserved. @@ -210,6 +210,7 @@ struct block_desc_cipher { 0x15 1 45434 RLL CS ECMA TC17 4 0x16 48 10000 MFM C X3.193-1990 1 0x17 48 42500 MFM C X3B5/91-174 1 + 0x45 73 67733 RLL C QIC3095 where Code means: NRZI Non Return to Zero, change on ones @@ -245,5 +246,6 @@ struct block_desc_cipher { #define QIC_1320 0x12 #define DDS 0x13 #define DAT_1 0x13 +#define QIC_3095 0x45 #endif /* _SCSI_TAPE_H_ */ diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c index 2f4859caef3..822ffafc3a7 100644 --- a/sys/scsi/scsiconf.c +++ b/sys/scsi/scsiconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scsiconf.c,v 1.27 1997/04/02 08:01:56 deraadt Exp $ */ +/* $OpenBSD: scsiconf.c,v 1.28 1997/04/14 04:09:14 downsj Exp $ */ /* $NetBSD: scsiconf.c,v 1.57 1996/05/02 01:09:01 neil Exp $ */ /* @@ -332,6 +332,8 @@ struct scsi_quirk_inquiry_pattern scsi_quirk_patterns[] = { "NEC ", "CD-ROM DRIVE:210", "1.0"}, SDEV_NOLUNS}, {{T_CDROM, T_REMOV, "NEC ", "CD-ROM DRIVE:841", ""}, SDEV_NOLUNS}, + {{T_CDROM, T_REMOV, + "PIONEER ", "CD-ROM DR-124X ", "1.01"}, SDEV_NOLUNS}, {{T_CDROM, T_REMOV, "SONY ", "CD-ROM CDU-541 ", ""}, SDEV_NOLUNS}, {{T_CDROM, T_REMOV, @@ -361,7 +363,11 @@ struct scsi_quirk_inquiry_pattern scsi_quirk_patterns[] = { {{T_DIRECT, T_FIXED, "DEC ", "RZ55 (C) DEC", ""}, SDEV_AUTOSAVE}, {{T_DIRECT, T_FIXED, - "EMULEX ", "MD21/S2 ESDI", "A00"}, SDEV_FORCELUNS}, + "EMULEX ", "MD21/S2 ESDI", "A00"}, SDEV_FORCELUNS|SDEV_AUTOSAVE}, + {{T_DIRECT, T_FIXED, + "IBMRAID ", "0662S", ""}, SDEV_AUTOSAVE}, + {{T_DIRECT, T_FIXED, + "IBM ", "0663H", ""}, SDEV_AUTOSAVE}, {{T_DIRECT, T_FIXED, "MAXTOR ", "XT-3280 ", ""}, SDEV_NOLUNS}, {{T_DIRECT, T_FIXED, @@ -392,6 +398,8 @@ struct scsi_quirk_inquiry_pattern scsi_quirk_patterns[] = { "QUANTUM ", "PD210S SUN0207", ""}, SDEV_NOLUNS}, {{T_DIRECT, T_FIXED, "RODIME ", "RO3000S ", ""}, SDEV_NOLUNS}, + {{T_DIRECT, T_FIXED, + "SEAGATE ", "ST125N ", ""}, SDEV_NOLUNS}, {{T_DIRECT, T_FIXED, "SEAGATE ", "ST157N ", ""}, SDEV_NOLUNS}, {{T_DIRECT, T_FIXED, @@ -406,6 +414,9 @@ struct scsi_quirk_inquiry_pattern scsi_quirk_patterns[] = { "IOMEGA", "ZIP 100", ""}, SDEV_NOMODESENSE}, {{T_DIRECT, T_FIXED, "IBM", "0661467", "G"}, SDEV_NOMODESENSE}, + /* Letting the motor run kills floppy drives and disks quit fast. */ + {{T_DIRECT, T_REMOV, + "TEAC", "FC-1", ""}, SDEV_NOSTARTUNIT}, /* XXX: QIC-36 tape behind Emulex adapter. Very broken. */ {{T_SEQUENTIAL, T_REMOV, @@ -631,6 +642,7 @@ scsi_probedev(scsi, target, lun) if ((inqbuf.version & SID_ANSII) == 0 && (sc_link->quirks & SDEV_FORCELUNS) == 0) sc_link->quirks |= SDEV_NOLUNS; + sc_link->scsi_version = inqbuf.version; if ((sc_link->quirks & SDEV_NOLUNS) == 0) scsi->moreluns |= (1 << target); diff --git a/sys/scsi/scsiconf.h b/sys/scsi/scsiconf.h index bf3c60337a3..d0a460715d3 100644 --- a/sys/scsi/scsiconf.h +++ b/sys/scsi/scsiconf.h @@ -1,5 +1,5 @@ -/* $OpenBSD: scsiconf.h,v 1.11 1997/01/18 16:18:32 briggs Exp $ */ -/* $NetBSD: scsiconf.h,v 1.29 1996/03/19 03:07:50 mycroft Exp $ */ +/* $OpenBSD: scsiconf.h,v 1.12 1997/04/14 04:09:15 downsj Exp $ */ +/* $NetBSD: scsiconf.h,v 1.35 1997/04/02 02:29:38 mycroft Exp $ */ /* * Copyright (c) 1993, 1994, 1995 Charles Hannum. All rights reserved. @@ -125,7 +125,7 @@ struct scsi_device { * we're simply notifying the upper-level driver that the command * is complete and expect no status back. */ - int (*done) __P((struct scsi_xfer *, int)); + void (*done) __P((struct scsi_xfer *)); }; /* @@ -135,6 +135,7 @@ struct scsi_device { * as well. */ struct scsi_link { + u_int8_t scsi_version; /* SCSI-I, SCSI-II, etc. */ u_int8_t scsibus; /* the Nth scsibus */ u_int8_t target; /* targ of this dev */ u_int8_t lun; /* lun of this dev */ @@ -155,6 +156,7 @@ struct scsi_link { #define SDEV_NOLUNS 0x04 /* does not grok LUNs */ #define SDEV_FORCELUNS 0x08 /* prehistoric drive/ctlr groks LUNs */ #define SDEV_NOMODESENSE 0x10 /* removable media/optical drives */ +#define SDEV_NOSTARTUNIT 0x20 /* do not issue start unit requests in sd.c */ u_int8_t inquiry_flags; /* copy of flags from probe INQUIRY */ struct scsi_device *device; /* device entry points etc. */ void *device_softc; /* needed for call to foo_start */ diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c index 8a5331d0921..fa818ef3baf 100644 --- a/sys/scsi/sd.c +++ b/sys/scsi/sd.c @@ -1,8 +1,8 @@ -/* $OpenBSD: sd.c,v 1.22 1997/01/04 08:50:21 deraadt Exp $ */ -/* $NetBSD: sd.c,v 1.100.4.1 1996/06/04 23:14:08 thorpej Exp $ */ +/* $OpenBSD: sd.c,v 1.23 1997/04/14 04:09:16 downsj Exp $ */ +/* $NetBSD: sd.c,v 1.111 1997/04/02 02:29:41 mycroft Exp $ */ /* - * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1994, 1995, 1997 Charles M. Hannum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -98,6 +98,13 @@ struct sd_softc { u_long disksize; /* total number sectors */ } params; struct buf buf_queue; + u_int8_t type; +}; + +struct scsi_mode_sense_data { + struct scsi_mode_header header; + struct scsi_blk_desc blk_desc; + union disk_pages pages; }; int sdmatch __P((struct device *, void *, void *)); @@ -107,9 +114,12 @@ void sdunlock __P((struct sd_softc *)); void sdminphys __P((struct buf *)); void sdgetdisklabel __P((dev_t, struct sd_softc *)); void sdstart __P((void *)); -int sddone __P((struct scsi_xfer *, int)); +void sddone __P((struct scsi_xfer *)); int sd_reassign_blocks __P((struct sd_softc *, u_long)); +int sd_get_optparms __P((struct sd_softc *, int, struct disk_parms *)); int sd_get_parms __P((struct sd_softc *, int)); +static int sd_mode_sense __P((struct sd_softc *, struct scsi_mode_sense_data *, + int, int)); struct cfattach sd_ca = { sizeof(struct sd_softc), sdmatch, sdattach @@ -162,6 +172,7 @@ sdattach(parent, self, aux) struct device *parent, *self; void *aux; { + int error; struct sd_softc *sd = (void *)self; struct disk_parms *dp = &sd->params; struct scsibus_attach_args *sa = aux; @@ -173,6 +184,7 @@ sdattach(parent, self, aux) * Store information needed to contact our base driver */ sd->sc_link = sc_link; + sd->type = (sa->sa_inqbuf->device & SID_TYPE); sc_link->device = &sd_switch; sc_link->device_softc = sd; if (sc_link->openings > SDOUTSTANDING) @@ -200,9 +212,15 @@ sdattach(parent, self, aux) */ printf("\n"); printf("%s: ", sd->sc_dev.dv_xname); - if (scsi_start(sd->sc_link, SSS_START, - SCSI_AUTOCONF | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE | SCSI_SILENT) || - sd_get_parms(sd, SCSI_AUTOCONF) != 0) + + if ((sd->sc_link->quirks & SDEV_NOSTARTUNIT) == 0) { + error = scsi_start(sd->sc_link, SSS_START, + SCSI_AUTOCONF | SCSI_IGNORE_ILLEGAL_REQUEST | + SCSI_IGNORE_MEDIA_CHANGE | SCSI_SILENT); + } else + error = 0; + + if (error || sd_get_parms(sd, SCSI_AUTOCONF) != 0) printf("drive offline\n"); else printf("%ldMB, %d cyl, %d head, %d sec, %d bytes/sec\n", @@ -295,11 +313,14 @@ sdopen(dev, flag, fmt, p) goto bad3; /* Start the pack spinning if necessary. */ - error = scsi_start(sc_link, SSS_START, - SCSI_IGNORE_ILLEGAL_REQUEST | - SCSI_IGNORE_MEDIA_CHANGE | SCSI_SILENT); - if (error) - goto bad3; + if ((sc_link->quirks & SDEV_NOSTARTUNIT) == 0) { + error = scsi_start(sc_link, SSS_START, + SCSI_IGNORE_ILLEGAL_REQUEST | + SCSI_IGNORE_MEDIA_CHANGE | + SCSI_SILENT); + if (error) + goto bad3; + } sc_link->flags |= SDEV_OPEN; @@ -600,7 +621,7 @@ sdstart(v) */ error = scsi_scsi_cmd(sc_link, cmdp, cmdlen, (u_char *)bp->b_data, bp->b_bcount, - SDRETRIES, 10000, bp, SCSI_NOSLEEP | + SDRETRIES, 60000, bp, SCSI_NOSLEEP | ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT)); if (error) { disk_unbusy(&sd->sc_dk, 0); @@ -610,17 +631,14 @@ sdstart(v) } } -int -sddone(xs, complete) +void +sddone(xs) struct scsi_xfer *xs; - int complete; { struct sd_softc *sd = xs->sc_link->device_softc; - if (complete && (xs->bp != NULL)) + if (xs->bp != NULL) disk_unbusy(&sd->sc_dk, (xs->bp->b_bcount - xs->bp->b_resid)); - - return (0); } void @@ -792,7 +810,10 @@ sdgetdisklabel(dev, sd) /* as long as it's not 0 - readdisklabel divides by it (?) */ } - strncpy(lp->d_typename, "SCSI disk", 16); + if (sd->type == T_OPTICAL) + strncpy(lp->d_typename, "SCSI optical", 16); + else + strncpy(lp->d_typename, "SCSI disk", 16); lp->d_type = DTYPE_SCSI; strncpy(lp->d_packname, "fictitious", 16); lp->d_secperunit = sd->params.disksize; @@ -844,16 +865,41 @@ sd_reassign_blocks(sd, blkno) 5000, NULL, SCSI_DATA_OUT); } -/* - * Get the scsi driver to send a full inquiry to the * device and use the - * results to fill out the disk parameter structure. - */ + +static int +sd_mode_sense(sd, scsi_sense, page, flags) + struct sd_softc *sd; + struct scsi_mode_sense_data *scsi_sense; + int page, flags; +{ + struct scsi_mode_sense scsi_cmd; + + /* + * Make sure the sense buffer is clean before we do + * the mode sense, so that checks for bogus values of + * 0 will work in case the mode sense fails. + */ + bzero(scsi_sense, sizeof(*scsi_sense)); + + bzero(&scsi_cmd, sizeof(scsi_cmd)); + scsi_cmd.opcode = MODE_SENSE; + scsi_cmd.page = page; + scsi_cmd.length = 0x20; + /* + * If the command worked, use the results to fill out + * the parameter structure + */ + return scsi_scsi_cmd(sd->sc_link, (struct scsi_generic *)&scsi_cmd, + sizeof(scsi_cmd), (u_char *)scsi_sense, sizeof(*scsi_sense), + SDRETRIES, 6000, NULL, flags | SCSI_DATA_IN | SCSI_SILENT); +} + int -sd_get_parms(sd, flags) +sd_get_optparms(sd, flags, dp) struct sd_softc *sd; int flags; + struct disk_parms *dp; { - struct disk_parms *dp = &sd->params; struct scsi_mode_sense scsi_cmd; struct scsi_mode_sense_data { struct scsi_mode_header header; @@ -861,26 +907,67 @@ sd_get_parms(sd, flags) union disk_pages pages; } scsi_sense; u_long sectors; + int error; - if ((sd->sc_link->quirks & SDEV_NOMODESENSE) != 0) - goto fake_it; - - /* - * do a "mode sense page 4" + dp->blksize = 512; + if ((sectors = scsi_size(sd->sc_link, flags)) == 0) + return 1; + + /* XXX + * It is better to get the following params from the + * mode sense page 6 only (optical device parameter page). + * However, there are stupid optical devices which does NOT + * support the page 6. Ghaa.... */ - bzero(&scsi_sense, sizeof(scsi_sense)); bzero(&scsi_cmd, sizeof(scsi_cmd)); scsi_cmd.opcode = MODE_SENSE; - scsi_cmd.page = 4; - scsi_cmd.length = 0x20; + scsi_cmd.page = 0x3f; /* all pages */ + scsi_cmd.length = sizeof(struct scsi_mode_header) + + sizeof(struct scsi_blk_desc); + + if ((error = scsi_scsi_cmd(sd->sc_link, + (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd), + (u_char *)&scsi_sense, sizeof(scsi_sense), SDRETRIES, + 6000, NULL, flags | SCSI_DATA_IN)) != 0) + return error; + + dp->blksize = _3btol(scsi_sense.blk_desc.blklen); + if (dp->blksize == 0) + dp->blksize = 512; /* - * If the command worked, use the results to fill out - * the parameter structure + * Create a pseudo-geometry. */ - if (scsi_scsi_cmd(sd->sc_link, (struct scsi_generic *)&scsi_cmd, - sizeof(scsi_cmd), (u_char *)&scsi_sense, sizeof(scsi_sense), - SDRETRIES, 6000, NULL, flags | SCSI_DATA_IN) == 0) { + dp->heads = 64; + dp->sectors = 32; + dp->cyls = sectors / (dp->heads * dp->sectors); + dp->disksize = sectors; + + return 0; +} + +/* + * Get the scsi driver to send a full inquiry to the * device and use the + * results to fill out the disk parameter structure. + */ +int +sd_get_parms(sd, flags) + struct sd_softc *sd; + int flags; +{ + struct disk_parms *dp = &sd->params; + struct scsi_mode_sense_data scsi_sense; + u_long sectors; + int page; + int error; + + if (sd->type == T_OPTICAL) { + if ((error = sd_get_optparms(sd, flags, dp)) != 0) + sd->sc_link->flags &= ~SDEV_MEDIA_LOADED; + return error; + } + + if ((error = sd_mode_sense(sd, &scsi_sense, page = 4, flags)) == 0) { SC_DEBUG(sd->sc_link, SDEV_DB3, ("%d cyls, %d heads, %d precomp, %d red_write, %d land_zone\n", _3btol(scsi_sense.pages.rigid_geometry.ncyl), @@ -899,11 +986,8 @@ sd_get_parms(sd, flags) dp->cyls = _3btol(scsi_sense.pages.rigid_geometry.ncyl); dp->blksize = _3btol(scsi_sense.blk_desc.blklen); - if (dp->heads == 0 || dp->cyls == 0) { - printf("%s: mode sense (4) returned nonsense", - sd->sc_dev.dv_xname); + if (dp->heads == 0 || dp->cyls == 0) goto fake_it; - } if (dp->blksize == 0) dp->blksize = 512; @@ -912,48 +996,40 @@ sd_get_parms(sd, flags) dp->disksize = sectors; sectors /= (dp->heads * dp->cyls); dp->sectors = sectors; /* XXX dubious on SCSI */ + return 0; - } else { - /* - * do a "mode sense page 5" - */ - scsi_cmd.opcode = MODE_SENSE; - scsi_cmd.page = 5; - scsi_cmd.length = 0x20; - if (scsi_scsi_cmd(sd->sc_link, (struct scsi_generic *)&scsi_cmd, - sizeof(scsi_cmd), (u_char *)&scsi_sense, sizeof(scsi_sense), - SDRETRIES, 6000, NULL, - flags | SCSI_DATA_IN | SCSI_SILENT) == 0) { - dp->heads = scsi_sense.pages.flex_geometry.nheads; - dp->cyls = - scsi_sense.pages.flex_geometry.ncyl_1 * 256 + - scsi_sense.pages.flex_geometry.ncyl_0; - dp->blksize = _3btol(scsi_sense.blk_desc.blklen); - dp->sectors = scsi_sense.pages.flex_geometry.ph_sec_t; - dp->disksize = dp->heads * dp->cyls * dp->sectors; - if (dp->heads == 0 || dp->cyls == 0 - || dp->sectors == 0) { - printf("%s: mode sense (5) returned nonsense", - sd->sc_dev.dv_xname); - goto fake_it; - } + } - if (dp->blksize == 0) - dp->blksize = 512; + if ((error = sd_mode_sense(sd, &scsi_sense, page = 5, flags)) == 0) { + dp->heads = scsi_sense.pages.flex_geometry.nheads; + dp->cyls = _2btol(scsi_sense.pages.flex_geometry.ncyl); + dp->blksize = _3btol(scsi_sense.blk_desc.blklen); + dp->sectors = scsi_sense.pages.flex_geometry.ph_sec_tr; + dp->disksize = dp->heads * dp->cyls * dp->sectors; + if (dp->disksize == 0) + goto fake_it; + + if (dp->blksize == 0) + dp->blksize = 512; - return 0; - } else - printf("%s: could not mode sense (4/5)", sd->sc_dev.dv_xname); + return 0; } fake_it: + if ((sd->sc_link->quirks & SDEV_NOMODESENSE) == 0) { + if (error == 0) + printf("%s: mode sense (%d) returned nonsense", + sd->sc_dev.dv_xname, page); + else + printf("%s: could not mode sense (4/5)", + sd->sc_dev.dv_xname); + printf("; using fictitious geometry\n"); + } /* * use adaptec standard fictitious geometry * this depends on which controller (e.g. 1542C is * different. but we have to put SOMETHING here..) */ - if ((sd->sc_link->quirks & SDEV_NOMODESENSE) == 0) - printf("; using fictitious geometry\n"); sectors = scsi_size(sd->sc_link, flags); dp->heads = 64; dp->sectors = 32; diff --git a/sys/scsi/st.c b/sys/scsi/st.c index c11c3fa46e9..f10c83d3f75 100644 --- a/sys/scsi/st.c +++ b/sys/scsi/st.c @@ -1,5 +1,5 @@ -/* $OpenBSD: st.c,v 1.14 1997/02/24 20:17:35 jkatz Exp $ */ -/* $NetBSD: st.c,v 1.66 1996/05/05 19:53:01 christos Exp $ */ +/* $OpenBSD: st.c,v 1.15 1997/04/14 04:09:17 downsj Exp $ */ +/* $NetBSD: st.c,v 1.71 1997/02/21 23:03:49 thorpej Exp $ */ /* * Copyright (c) 1994 Charles Hannum. All rights reserved. @@ -81,8 +81,11 @@ #define STUNIT(z) ((minor(z) >> 4) ) #define CTLMODE 3 -#define SCSI_2_MAX_DENSITY_CODE 0x17 /* maximum density code specified - * in SCSI II spec. */ +/* + * Maximum density code known. + */ +#define SCSI_2_MAX_DENSITY_CODE 0x45 + /* * Define various devices that we know mis-behave in some way, * and note how they are bad, so we can correct for them @@ -99,6 +102,7 @@ struct quirkdata { #define ST_Q_SENSE_HELP 0x0002 /* must do READ for good MODE SENSE */ #define ST_Q_IGNORE_LOADS 0x0004 #define ST_Q_BLKSIZE 0x0008 /* variable-block media_blksize > 0 */ +#define ST_Q_UNIMODAL 0x0010 /* unimode drive rejects mode select */ u_int page_0_size; #define MAX_PAGE_0_SIZE 64 struct modes modes[4]; @@ -202,6 +206,13 @@ struct st_quirk_inquiry_pattern st_quirk_patterns[] = { {0, 0, 0}, /* minor 8-11 */ {0, 0, 0} /* minor 12-15 */ }}}, + {{T_SEQUENTIAL, T_REMOV, + "HP ", "T4000s ", ""}, {ST_Q_UNIMODAL, 0, { + {0, 0, QIC_3095}, /* minor 0-3 */ + {0, 0, QIC_3095}, /* minor 4-7 */ + {0, 0, QIC_3095}, /* minor 8-11 */ + {0, 0, QIC_3095}, /* minor 12-15 */ + }}}, #if 0 {{T_SEQUENTIAL, T_REMOV, "EXABYTE ", "EXB-8200 ", ""}, {0, 12, { @@ -1402,6 +1413,18 @@ st_mode_select(st, flags) scsi_select_len = 12 + st->page_0_size; + /* + * This quirk deals with drives that have only one valid mode + * and think this gives them license to reject all mode selects, + * even if the selected mode is the one that is supported. + */ + if (st->quirks & ST_Q_UNIMODAL) { + SC_DEBUG(sc_link, SDEV_DB3, + ("not setting density 0x%x blksize 0x%x\n", + st->density, st->blksize)); + return 0; + } + /* * Set up for a mode select */