date and time created 92/11/15 16:46:58 by ralph
authorRalph Campbell <ralph@ucbvax.Berkeley.EDU>
Mon, 16 Nov 1992 08:46:58 +0000 (00:46 -0800)
committerRalph Campbell <ralph@ucbvax.Berkeley.EDU>
Mon, 16 Nov 1992 08:46:58 +0000 (00:46 -0800)
SCCS-vsn: sys/pmax/stand/rz.c 7.1

usr/src/sys/pmax/stand/rz.c [new file with mode: 0644]

diff --git a/usr/src/sys/pmax/stand/rz.c b/usr/src/sys/pmax/stand/rz.c
new file mode 100644 (file)
index 0000000..b8da33a
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 1992 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson of Lawrence Berkeley Laboratory and Ralph Campbell.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)rz.c        7.1 (Berkeley) %G%
+ */
+
+/*
+ * SCSI CCS (Command Command Set) disk driver.
+ * NOTE: The name was changed from "sd" to "rz" for DEC naming compatibility.
+ * I guess I can't avoid confusion someplace.
+ */
+#include <pmax/stand/samachdep.h>
+#if NRZ > 0
+
+#include <stand/stand.h>
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include <pmax/dev/device.h>
+#include <pmax/dev/scsi.h>
+
+void   rzstart(), rzdone();
+
+struct driver rzdriver = {
+       "rz", (int (*)())0, rzstart, rzdone,
+};
+
+struct rz_softc {
+       struct  scsi_device sc_sd;      /* physical unit info */
+       u_short sc_part;                /* disk partition number */
+       u_short sc_type;                /* drive type from INQUIRY cmd */
+       u_int   sc_blks;                /* number of blocks on device */
+       int     sc_blksize;             /* device block size in bytes */
+       int     sc_bshift;              /* convert device blocks to DEV_BSIZE */
+       struct  disklabel sc_label;     /* disk label for this disk */
+       struct  ScsiCmd sc_cmd;         /* command for controller */
+       ScsiGroup1Cmd sc_rwcmd;         /* group 1 SCSI commands */
+       struct  scsi_fmt_sense sc_sense;        /* sense data from last cmd */
+       int     sc_error;               /* error code */
+       int     sc_resid;               /* amount of data not transfered */
+};
+
+volatile int   done;
+
+int
+rzstrategy(devdata, rw, bn, reqcnt, addr, cnt)
+       void *devdata;
+       int rw;
+       daddr_t bn;
+       u_int reqcnt;
+       char *addr;
+       u_int *cnt;     /* out: number of bytes transfered */
+{
+       register struct rz_softc *sc = (struct rz_softc *)devdata;
+       register int part = sc->sc_part;
+       register struct partition *pp = &sc->sc_label.d_partitions[part];
+       register int s;
+       long cylin;
+
+       sc->sc_error = 0;
+       s = howmany(reqcnt, DEV_BSIZE);
+       if ((unsigned)bn + s > pp->p_size) {
+               s = pp->p_size - bn;
+               /* if exactly at end of disk, return an EOF */
+               if (s == 0) {
+                       *cnt = 0;
+                       return (0);
+               }
+               /* if none of it fits, error */
+               if (s < 0) {
+                       *cnt = 0;
+                       return (EINVAL);
+               }
+               /* otherwise, truncate */
+               reqcnt = dbtob(s);
+       }
+       /*
+        * Non-aligned or partial-block transfers not handled.
+        */
+       s = sc->sc_blksize - 1;
+       if ((dbtob(bn) & s) || (reqcnt & s)) {
+               *cnt = 0;
+               return (EINVAL);
+       }
+       cylin = (bn + pp->p_offset) >> sc->sc_bshift;
+
+       sc->sc_cmd.buf = addr;
+       sc->sc_cmd.buflen = reqcnt;
+       sc->sc_cmd.cmd = (u_char *)&sc->sc_rwcmd;
+       sc->sc_cmd.cmdlen = sizeof(sc->sc_rwcmd);
+
+       if (rw & F_READ) {
+               sc->sc_cmd.flags = 0;
+               sc->sc_rwcmd.command = SCSI_READ_EXT;
+       } else {
+               sc->sc_cmd.flags = SCSICMD_DATA_TO_DEVICE;
+               sc->sc_rwcmd.command = SCSI_WRITE_EXT;
+       }
+       sc->sc_rwcmd.highAddr = cylin >> 24;
+       sc->sc_rwcmd.midHighAddr = cylin >> 16;
+       sc->sc_rwcmd.midLowAddr = cylin >> 8;
+       sc->sc_rwcmd.lowAddr = cylin;
+       s = howmany(reqcnt, sc->sc_blksize);
+       sc->sc_rwcmd.highBlockCount = s >> 8;
+       sc->sc_rwcmd.lowBlockCount = s;
+
+       rzstart(sc);
+
+       *cnt = reqcnt - sc->sc_resid;
+       return (sc->sc_error);
+}
+
+void
+rzstart(sc)
+       register struct rz_softc *sc;
+{
+       ScsiGroup0Cmd reqcmd;
+
+       /* tell controller to start this command */
+       done = 0;
+       (*sc->sc_sd.sd_cdriver->d_start)(&sc->sc_cmd);
+       while (!done)
+               ;
+
+       /* check for errors that need to be processed */
+       if (!(sc->sc_sense.status & SCSI_STATUS_CHECKCOND))
+               return;
+
+       /* start a REQUEST_SENSE command */
+       scsiGroup0Cmd(SCSI_REQUEST_SENSE, sc->sc_sd.sd_slave, 0,
+               sizeof(sc->sc_sense.sense), &reqcmd);
+       sc->sc_cmd.cmdlen = sizeof(ScsiGroup0Cmd);
+       sc->sc_cmd.cmd = (u_char *)&reqcmd;
+       sc->sc_cmd.buf = (char *)sc->sc_sense.sense;
+       sc->sc_cmd.buflen = sizeof(sc->sc_sense.sense);
+       sc->sc_cmd.flags = 0;
+
+       /* tell controller to start this command */
+       done = 0;
+       (*sc->sc_sd.sd_cdriver->d_start)(&sc->sc_cmd);
+       while (!done)
+               ;
+
+       if (sc->sc_error || (sc->sc_sense.status & SCSI_STATUS_CHECKCOND)) {
+               printf("rz%d: error reading sense data: error %d scsi status 0x%x\n",
+                       sc->sc_sd.sd_unit, sc->sc_error, sc->sc_sense.status);
+               /*
+                * We got an error during the REQUEST_SENSE,
+                * fill in no sense for data.
+                */
+               sc->sc_sense.sense[0] = 0x70;
+               sc->sc_sense.sense[2] = SCSI_CLASS7_NO_SENSE;
+       } else {
+               printf("rz%d: ", sc->sc_sd.sd_unit);
+               scsiPrintSense((ScsiClass7Sense *)sc->sc_sense.sense,
+                       sizeof(sc->sc_sense.sense) - sc->sc_resid);
+       }
+       if (sc->sc_error == 0)
+               sc->sc_error = EIO;
+}
+
+/*
+ * This is called by the controller driver when the command is done.
+ */
+void
+rzdone(data, error, resid, status)
+       void *data;
+       int error;              /* error number from errno.h */
+       int resid;              /* amount not transfered */
+       int status;             /* SCSI status byte */
+{
+       register struct rz_softc *sc = (struct rz_softc *)data;
+
+       sc->sc_error = error;
+       sc->sc_resid = resid;
+       sc->sc_sense.status = status;
+       done = 1;
+}
+
+int
+rzopen(f, ctlr, unit, part)
+       struct open_file *f;
+       int ctlr, unit, part;
+{
+       register struct rz_softc *sc;
+       register struct disklabel *lp;
+       register struct scsi_device *sd;
+       register int i;
+       char *msg;
+       ScsiGroup0Cmd inqcmd;
+       ScsiInquiryData inqbuf;
+       u_char capbuf[8];
+       char buf[DEV_BSIZE];
+       int cnt;
+       struct driver *scsi_driver;
+
+       if (unit >= NRZ || part >= MAXPARTITIONS)
+               return (ENXIO);
+#ifdef DS3100
+       if (ctlr >= NSII)
+               return (ENXIO);
+       else {
+               extern struct driver siidriver;
+
+               scsi_driver = &siidriver;
+       }
+#endif
+#ifdef DS5000
+       {
+       struct pmax_ctlr *cp, *tc_ctlr __P((int, int));
+
+       cp = tc_ctlr(ctlr, TC_SCSI);
+       if (!cp)
+               return (ENXIO);
+       ctlr = cp->pmax_unit;   /* convert from slot # to controller unit */
+       scsi_driver = cp->pmax_driver;
+       }
+#endif
+
+       sc = alloc(sizeof(struct rz_softc));
+       bzero(sc, sizeof(struct rz_softc));
+       f->f_devdata = (void *)sc;
+
+       sc->sc_sd.sd_driver = &rzdriver;
+       sc->sc_sd.sd_cdriver = scsi_driver;
+       sc->sc_sd.sd_unit = unit;
+       sc->sc_sd.sd_ctlr = ctlr;
+       sc->sc_sd.sd_drive = unit;
+       sc->sc_sd.sd_slave = 0;
+       sc->sc_sd.sd_flags = 0;
+       sc->sc_sd.sd_alive = 1;
+       sc->sc_part = part;
+
+       /* init fields that don't change */
+       sc->sc_cmd.sd = sd = &sc->sc_sd;
+       sc->sc_cmd.unit = (int)sc;
+
+       /*
+        * Try to find out what type of device this is.
+        */
+       scsiGroup0Cmd(SCSI_INQUIRY, sd->sd_slave, 0, sizeof(inqbuf), &inqcmd);
+       sc->sc_cmd.cmdlen = sizeof(ScsiGroup0Cmd);
+       sc->sc_cmd.cmd = (u_char *)&inqcmd;
+       sc->sc_cmd.buflen = sizeof(inqbuf);
+       sc->sc_cmd.buf = (char *)&inqbuf;
+       sc->sc_cmd.flags = 0;
+
+       /* tell controller to start this command */
+       rzstart(sc);
+
+       if (sc->sc_error || (i = sizeof(inqbuf) - sc->sc_resid) < 5)
+               goto bad;
+       switch (inqbuf.type) {
+       case SCSI_DISK_TYPE:            /* disk */
+       case SCSI_WORM_TYPE:            /* WORM */
+       case SCSI_ROM_TYPE:             /* CD-ROM */
+       case SCSI_OPTICAL_MEM_TYPE:     /* Magneto-optical */
+               break;
+
+       default:                        /* not a disk */
+               goto bad;
+       }
+       sc->sc_type = inqbuf.type;
+
+       /* find out how big a disk this is */
+       scsiGroup1Cmd(SCSI_READ_CAPACITY, sd->sd_slave, 0, 0, &sc->sc_rwcmd);
+       sc->sc_cmd.cmdlen = sizeof(ScsiGroup1Cmd);
+       sc->sc_cmd.cmd = (u_char *)&sc->sc_rwcmd;
+       sc->sc_cmd.buflen = sizeof(capbuf);
+       sc->sc_cmd.buf = (char *)capbuf;
+       sc->sc_cmd.flags = 0;
+
+       rzstart(sc);
+
+       if (sc->sc_error || sc->sc_resid != 0)
+               goto bad;
+       sc->sc_blks = ((capbuf[0] << 24) | (capbuf[1] << 16) |
+               (capbuf[2] << 8) | capbuf[3]) + 1;
+       sc->sc_blksize = (capbuf[4] << 24) | (capbuf[5] << 16) |
+               (capbuf[6] << 8) | capbuf[7];
+
+#if 0
+       printf("rz%d at %s%d drive %d slave %d", sd->sd_unit,
+               sd->sd_cdriver->d_name, sd->sd_ctlr, sd->sd_drive,
+               sd->sd_slave);
+       if (inqbuf.version > 1 || i < 36)
+               printf(" type 0x%x, qual 0x%x, ver %d",
+                       inqbuf.type, inqbuf.qualifier, inqbuf.version);
+       else {
+               char vid[9], pid[17], revl[5];
+
+               bcopy((caddr_t)inqbuf.vendorID, (caddr_t)vid, 8);
+               bcopy((caddr_t)inqbuf.productID, (caddr_t)pid, 16);
+               bcopy((caddr_t)inqbuf.revLevel, (caddr_t)revl, 4);
+               for (i = 8; --i > 0; )
+                       if (vid[i] != ' ')
+                               break;
+               vid[i+1] = 0;
+               for (i = 16; --i > 0; )
+                       if (pid[i] != ' ')
+                               break;
+               pid[i+1] = 0;
+               for (i = 4; --i > 0; )
+                       if (revl[i] != ' ')
+                               break;
+               revl[i+1] = 0;
+               printf(" %s %s rev %s", vid, pid, revl);
+       }
+       printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
+#endif
+
+       if (sc->sc_blksize != DEV_BSIZE) {
+               if (sc->sc_blksize < DEV_BSIZE) {
+                       printf("rz%d: need %d byte blocks - drive ignored\n",
+                               unit, DEV_BSIZE);
+                       goto bad;
+               }
+               for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1)
+                       ++sc->sc_bshift;
+               sc->sc_blks <<= sc->sc_bshift;
+       }
+
+       /* try to read disk label and partition table information */
+       lp = &sc->sc_label;
+       lp->d_secsize = DEV_BSIZE;
+       lp->d_secpercyl = 1 << sc->sc_bshift;
+       lp->d_npartitions = MAXPARTITIONS;
+       lp->d_partitions[part].p_offset = 0;
+       lp->d_partitions[part].p_size = sc->sc_blks;
+       i = rzstrategy(sc, F_READ, (daddr_t)LABELSECTOR, DEV_BSIZE, buf, &cnt);
+       if (i || cnt != DEV_BSIZE) {
+               printf("rz%d: error reading disk label\n", unit);
+               goto bad;
+       } else {
+               msg = getdisklabel(buf, lp);
+               if (msg) {
+                       printf("rz%d: %s\n", unit, msg);
+                       goto bad;
+               }
+       }
+
+       if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0) {
+       bad:
+               free(sc, sizeof(struct rz_softc));
+               return (ENXIO);
+       }
+       return (0);
+}
+
+rzclose(f)
+       struct open_file *f;
+{
+       free(f->f_devdata, sizeof(struct rz_softc));
+       f->f_devdata = (void *)0;
+       return (0);
+}
+#endif