The dynamically allocated struct's where not getting properly initialized
[unix-history] / sys / scsi / sd.c
index af8ae79..c587e77 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Written by Julian Elischer (julian@tfs.com)
+ * Written by Julian Elischer (julian@dialix.oz.au)
  * for TRW Financial Systems for use under the MACH(2.5) operating system.
  *
  * TRW Financial Systems, in accordance with their agreement with Carnegie
  * for TRW Financial Systems for use under the MACH(2.5) operating system.
  *
  * TRW Financial Systems, in accordance with their agreement with Carnegie
  * on the understanding that TFS is not responsible for the correct
  * functioning of this software in any circumstances.
  *
  * on the understanding that TFS is not responsible for the correct
  * functioning of this software in any circumstances.
  *
- * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
- * --------------------         -----   ----------------------
- * CURRENT PATCH LEVEL:         2       00149
- * --------------------         -----   ----------------------
+ * Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992
  *
  *
- * 16 Feb 93   Julian Elischer         ADDED for SCSI system
- * 20 Apr 93   Julian Elischer         Fixed error reporting
- *
- */
-
-static char rev[] = "$Revision: 1.3 $";
-
-/*
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
+ *     $Id: sd.c,v 1.8 1993/09/10 18:03:21 ats Exp $
  */
 
 #define SPLSD splbio
  */
 
 #define SPLSD splbio
@@ -79,7 +68,9 @@ struct buf sd_buf_queue[NSD];
 int    sd_done();
 int    sdstrategy();
 
 int    sd_done();
 int    sdstrategy();
 
+#ifdef SDDEBUG
 int    sd_debug = 0;
 int    sd_debug = 0;
+#endif /*SDDEBUG*/
 
 struct scsi_xfer       *sd_free_xfer[NSD];
 int                    sd_xfer_block_wait[NSD];
 
 struct scsi_xfer       *sd_free_xfer[NSD];
 int                    sd_xfer_block_wait[NSD];
@@ -114,7 +105,7 @@ struct      sd_data
 #define SDOPEN 0x01
        int             openparts;              /* one bit for each open partition */
        unsigned int    sd_start_of_unix;       /* unix vs dos partitions */
 #define SDOPEN 0x01
        int             openparts;              /* one bit for each open partition */
        unsigned int    sd_start_of_unix;       /* unix vs dos partitions */
-}sd_data[NSD];
+}*sd_data[NSD];
 
 
 static int     next_sd_unit = 0;
 
 
 static int     next_sd_unit = 0;
@@ -134,17 +125,31 @@ struct    scsi_switch *scsi_switch;
        struct  scsi_xfer       *sd_scsi_xfer;
 
        unit = next_sd_unit++;
        struct  scsi_xfer       *sd_scsi_xfer;
 
        unit = next_sd_unit++;
-       sd = sd_data + unit;
-       dp  = &(sd->params);
+#ifdef SDDEBUG
        if(scsi_debug & PRINTROUTINES) printf("sdattach: "); 
        if(scsi_debug & PRINTROUTINES) printf("sdattach: "); 
+#endif /*SDDEBUG*/
        /*******************************************************\
        * Check we have the resources for another drive         *
        \*******************************************************/
        if( unit >= NSD)
        {
        /*******************************************************\
        * Check we have the resources for another drive         *
        \*******************************************************/
        if( unit >= NSD)
        {
-               printf("Too many scsi disks..(%d > %d) reconfigure kernel",(unit + 1),NSD);
+               printf("Too many scsi disks..(%d > %d) reconfigure kernel\n",(unit + 1),NSD);
+               return(0);
+       }
+       if(sd_data[unit])
+       {
+               printf("sd%d: unit already has storage allocated!\n",unit);
                return(0);
        }
                return(0);
        }
+       sd = sd_data[unit] = malloc(sizeof(struct sd_data),M_DEVBUF,M_NOWAIT);
+       if(!sd)
+       {
+               printf("malloc failed in sd.c\n");
+               return(0);
+       }
+       bzero(sd,sizeof(struct sd_data));
+
+       dp  = &(sd->params);
        /*******************************************************\
        * Store information needed to contact our base driver   *
        \*******************************************************/
        /*******************************************************\
        * Store information needed to contact our base driver   *
        \*******************************************************/
@@ -182,21 +187,14 @@ struct    scsi_switch *scsi_switch;
        * request must specify this.                            *
        \*******************************************************/
        sd_get_parms(unit,  SCSI_NOSLEEP |  SCSI_NOMASK);
        * request must specify this.                            *
        \*******************************************************/
        sd_get_parms(unit,  SCSI_NOSLEEP |  SCSI_NOMASK);
-       printf("        sd%d: %dMB, cyls %d, heads %d, secs %d, bytes/sec %d\n",
+       printf("sd%d: %dMB (%d total sec), %d cyl, %d head, %d sec, bytes/sec %d\n",
                unit,
                unit,
-               (         dp->cyls 
-                       * dp->heads 
-                       * dp->sectors
-                       * dp->secsiz
-               )
-               / (1024 * 1024),
+               dp->disksize / ((1024L * 1024L) / dp->secsiz),
+               dp->disksize,
                dp->cyls,
                dp->heads,
                dp->sectors,
                dp->secsiz);
                dp->cyls,
                dp->heads,
                dp->sectors,
                dp->secsiz);
-       /*******************************************************\
-       * Set up the bufs for this device                       *
-       \*******************************************************/
        sd->flags |= SDINIT;
        return;
 
        sd->flags |= SDINIT;
        return;
 
@@ -217,10 +215,12 @@ sdopen(dev)
 
        unit = UNIT(dev);
        part = PARTITION(dev);
 
        unit = UNIT(dev);
        part = PARTITION(dev);
-       sd = sd_data + unit;
+       sd = sd_data[unit];
+#ifdef SDDEBUG
        if(scsi_debug & (PRINTROUTINES | TRACEOPENS))
                printf("sdopen: dev=0x%x (unit %d (of %d),partition %d)\n"
                                ,   dev,      unit,   NSD,         part);
        if(scsi_debug & (PRINTROUTINES | TRACEOPENS))
                printf("sdopen: dev=0x%x (unit %d (of %d),partition %d)\n"
                                ,   dev,      unit,   NSD,         part);
+#endif /*SDDEBUG*/
        /*******************************************************\
        * Check the unit is legal                               *
        \*******************************************************/
        /*******************************************************\
        * Check the unit is legal                               *
        \*******************************************************/
@@ -246,51 +246,64 @@ sdopen(dev)
           && ( sd->openparts))
                return(ENXIO);
        /*******************************************************\
           && ( sd->openparts))
                return(ENXIO);
        /*******************************************************\
-       * Check that it is still responding and ok.             *
-       * "unit attention errors should occur here if the drive *
-       * has been restarted or the pack changed                *
+       * "unit attention" errors should occur here if the      *
+       * drive has been restarted or the pack changed.         *
+       * just ingnore the result, it's a decoy instruction     *
+       * The error code will act on the error though           *
+       * and invalidate any media information we had.          *
        \*******************************************************/
        \*******************************************************/
+       sd_test_unit_ready(unit,0);
 
 
-       if(scsi_debug & TRACEOPENS)
-               printf("device is ");
-       if (sd_test_unit_ready(unit,0))
-       {
-               if(scsi_debug & TRACEOPENS) printf("not reponding\n");
-               return(ENXIO);
-       }
-       if(scsi_debug & TRACEOPENS)
-               printf("ok\n");
        /*******************************************************\
        * In case it is a funny one, tell it to start           *
        * not needed for  most hard drives (ignore failure)     *
        \*******************************************************/
        sd_start_unit(unit,SCSI_ERR_OK|SCSI_SILENT);
        /*******************************************************\
        * In case it is a funny one, tell it to start           *
        * not needed for  most hard drives (ignore failure)     *
        \*******************************************************/
        sd_start_unit(unit,SCSI_ERR_OK|SCSI_SILENT);
+
+       /*******************************************************\
+       * Check that it is still responding and ok.             *
+       \*******************************************************/
+       if (sd_test_unit_ready(unit,0))
+       {
+#ifdef SDDEBUG
+               if(scsi_debug & TRACEOPENS) printf("device not reponding\n");
+#endif /*SDDEBUG*/
+               return(ENXIO);
+       }
+#ifdef SDDEBUG
        if(scsi_debug & TRACEOPENS)
        if(scsi_debug & TRACEOPENS)
-               printf("started ");
+               printf("device ok\n");
+#endif /*SDDEBUG*/
+
        /*******************************************************\
        * Load the physical device parameters                   *
        \*******************************************************/
        sd_get_parms(unit, 0);  /* sets SDVALID */
        /*******************************************************\
        * Load the physical device parameters                   *
        \*******************************************************/
        sd_get_parms(unit, 0);  /* sets SDVALID */
-       if (sd->params.secsiz != SECSIZE)
+       if (sd->params.secsiz != SECSIZE)       /* XXX One day...*/
        {
                printf("sd%d: Can't deal with %d bytes logical blocks\n"
                        ,unit, sd->params.secsiz);
                Debugger();
                return(ENXIO);
        }
        {
                printf("sd%d: Can't deal with %d bytes logical blocks\n"
                        ,unit, sd->params.secsiz);
                Debugger();
                return(ENXIO);
        }
+#ifdef SDDEBUG
        if(scsi_debug & TRACEOPENS)
                printf("Params loaded ");
        if(scsi_debug & TRACEOPENS)
                printf("Params loaded ");
+#endif /*SDDEBUG*/
        /*******************************************************\
        * Load the partition info if not already loaded         *
        /*******************************************************\
        * Load the partition info if not already loaded         *
+       * Lock the pack in                                      *
        \*******************************************************/
        \*******************************************************/
-       sd_prevent(unit,PR_PREVENT,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */
+       sd_prevent(unit,PR_PREVENT,SCSI_ERR_OK|SCSI_SILENT);
        if((errcode = sdgetdisklabel(unit)) && (part != RAW_PART))
        {
        if((errcode = sdgetdisklabel(unit)) && (part != RAW_PART))
        {
-               sd_prevent(unit,PR_ALLOW,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */
+               sd_prevent(unit,PR_ALLOW,SCSI_ERR_OK|SCSI_SILENT);
                return(errcode);
        }
                return(errcode);
        }
+#ifdef SDDEBUG
        if(scsi_debug & TRACEOPENS)
                printf("Disklabel loaded ");
        if(scsi_debug & TRACEOPENS)
                printf("Disklabel loaded ");
+#endif /*SDDEBUG*/
        /*******************************************************\
        * Check the partition is legal                          *
        \*******************************************************/
        /*******************************************************\
        * Check the partition is legal                          *
        \*******************************************************/
@@ -298,8 +311,10 @@ sdopen(dev)
                sd_prevent(unit,PR_ALLOW,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */
                return(ENXIO);
        }
                sd_prevent(unit,PR_ALLOW,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */
                return(ENXIO);
        }
+#ifdef SDDEBUG
        if(scsi_debug & TRACEOPENS)
                printf("ok");
        if(scsi_debug & TRACEOPENS)
                printf("ok");
+#endif /*SDDEBUG*/
        /*******************************************************\
        *  Check that the partition exists                      *
        \*******************************************************/
        /*******************************************************\
        *  Check that the partition exists                      *
        \*******************************************************/
@@ -311,8 +326,10 @@ sdopen(dev)
        }
        sd->partflags[part] |= SDOPEN;
        sd->openparts |= (1 << part);
        }
        sd->partflags[part] |= SDOPEN;
        sd->openparts |= (1 << part);
+#ifdef SDDEBUG
        if(scsi_debug & TRACEOPENS)
                printf("open %d %d\n",sdstrats,sdqueues);
        if(scsi_debug & TRACEOPENS)
                printf("open %d %d\n",sdstrats,sdqueues);
+#endif /*SDDEBUG*/
        return(0);
 }
 
        return(0);
 }
 
@@ -392,7 +409,7 @@ int flags;
 void   sdminphys(bp)
 struct buf     *bp;
 {
 void   sdminphys(bp)
 struct buf     *bp;
 {
-       (*(sd_data[UNIT(bp->b_dev)].sc_sw->scsi_minphys))(bp);
+       (*(sd_data[UNIT(bp->b_dev)]->sc_sw->scsi_minphys))(bp);
 }
 
 /*******************************************************\
 }
 
 /*******************************************************\
@@ -412,10 +429,12 @@ struct    buf     *bp;
 
        sdstrats++;
        unit = UNIT((bp->b_dev));
 
        sdstrats++;
        unit = UNIT((bp->b_dev));
-       sd = sd_data + unit;
+       sd = sd_data[unit];
+#ifdef SDDEBUG
        if(scsi_debug & PRINTROUTINES) printf("\nsdstrategy ");
        if(scsi_debug & SHOWREQUESTS) printf("sd%d: %d bytes @ blk%d\n",
                                        unit,bp->b_bcount,bp->b_blkno);
        if(scsi_debug & PRINTROUTINES) printf("\nsdstrategy ");
        if(scsi_debug & SHOWREQUESTS) printf("sd%d: %d bytes @ blk%d\n",
                                        unit,bp->b_bcount,bp->b_blkno);
+#endif /*SDDEBUG*/
        sdminphys(bp);
        /*******************************************************\
        * If the device has been made invalid, error out        *
        sdminphys(bp);
        /*******************************************************\
        * If the device has been made invalid, error out        *
@@ -492,7 +511,7 @@ done:
 /***************************************************************\
 * sdstart looks to see if there is a buf waiting for the device        *
 * and that the device is not already busy. If both are true,   *
 /***************************************************************\
 * sdstart 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 deques the buf and creates a scsi command to perform the  *
+* It dequeues the buf and creates a scsi command to perform the        *
 * transfer in the buf. The transfer request will call sd_done  *
 * on completion, which will in turn call this routine again    *
 * so that the next queued transfer is performed.               *
 * transfer in the buf. The transfer request will call sd_done  *
 * on completion, which will in turn call this routine again    *
 * so that the next queued transfer is performed.               *
@@ -514,37 +533,41 @@ int       unit;
        struct  scsi_xfer       *xs;
        struct  scsi_rw_big     cmd;
        int                     blkno, nblk;
        struct  scsi_xfer       *xs;
        struct  scsi_rw_big     cmd;
        int                     blkno, nblk;
-       struct sd_data *sd = sd_data + unit;
+       struct sd_data *sd = sd_data[unit];
        struct partition *p ;
 
        struct partition *p ;
 
+#ifdef SDDEBUG
        if(scsi_debug & PRINTROUTINES) printf("sdstart%d ",unit);
        if(scsi_debug & PRINTROUTINES) printf("sdstart%d ",unit);
+#endif /*SDDEBUG*/
        /*******************************************************\
        /*******************************************************\
-       * See if there is a buf to do and we are not already    *
-       * doing one                                             *
+       * Check if the device is already running full capacity  *
        \*******************************************************/
        if(!sd_free_xfer[unit])
        {
                return;    /* none for us, unit already underway */
        }
 
        \*******************************************************/
        if(!sd_free_xfer[unit])
        {
                return;    /* none for us, unit already underway */
        }
 
-       if(sd_xfer_block_wait[unit])    /* there is one, but a special waits */
+       /*******************************************************\
+       * there is excess capacity, but a special waits         *
+       * It'll need the adapter as soon as we clear out of the *
+       * way and let it run (user level wait).                 *
+       \*******************************************************/
+       if(sd_xfer_block_wait[unit])  
        {
        {
-               return; /* give the special that's waiting a chance to run */
+               return;
        }
 
        }
 
-
+       /*******************************************************\
+       * See if there is a buf with work for us to do..        *
+       \*******************************************************/
        dp = &sd_buf_queue[unit];
        dp = &sd_buf_queue[unit];
-       if ((bp = dp->b_actf) != NULL)  /* yes, an assign */
+       if ((bp = dp->b_actf) == NULL)  /* yes, an assign */
        {
        {
-               dp->b_actf = bp->av_forw;
-       }
-       else
-       { 
                return;
        }
 
                return;
        }
 
-       xs=sd_get_xs(unit,0);   /* ok we can grab it */
-       xs->flags = INUSE;    /* Now ours */
+       dp->b_actf = bp->av_forw;
+
        /*******************************************************\
        *  If the device has become invalid, abort all the      *
        * reads and writes until all files have been closed and *
        /*******************************************************\
        *  If the device has become invalid, abort all the      *
        * reads and writes until all files have been closed and *
@@ -552,15 +575,12 @@ int       unit;
        \*******************************************************/
        if(!(sd->flags & SDVALID))
        {
        \*******************************************************/
        if(!(sd->flags & SDVALID))
        {
-               xs->error = XS_DRIVER_STUFFUP;
-               sd_done(unit,xs);  /* clean up (calls sdstart) */
-               return ;
+               goto bad;
        }
        /*******************************************************\
        }
        /*******************************************************\
-       * We have a buf, now we should move the data into       *
-       * a scsi_xfer definition and try start it               *
-       \*******************************************************/
-       /*******************************************************\
+       * We have a buf, now we know we are going to go through *
+       * With this thing..                                     *
+       *                                                       *
        *  First, translate the block to absolute               *
        \*******************************************************/
        p = sd->disklabel.d_partitions + PARTITION(bp->b_dev);
        *  First, translate the block to absolute               *
        \*******************************************************/
        p = sd->disklabel.d_partitions + PARTITION(bp->b_dev);
@@ -580,111 +600,30 @@ int      unit;
        cmd.length2     =       (nblk & 0xff00) >> 8;
        cmd.length1     =       (nblk & 0xff);
        /*******************************************************\
        cmd.length2     =       (nblk & 0xff00) >> 8;
        cmd.length1     =       (nblk & 0xff);
        /*******************************************************\
-       * Fill out the scsi_xfer structure                      *
+       * Call the routine that chats with the adapter          *
        *       Note: we cannot sleep as we may be an interrupt *
        \*******************************************************/
        *       Note: we cannot sleep as we may be an interrupt *
        \*******************************************************/
-       xs->flags       |=      SCSI_NOSLEEP;
-       xs->adapter     =       sd->ctlr;
-       xs->targ        =       sd->targ;
-       xs->lu          =       sd->lu;
-       xs->retries     =       SD_RETRIES;
-       xs->timeout     =       10000;/* 10000 millisecs for a disk !*/
-       xs->cmd         =       (struct scsi_generic *)&cmd;
-       xs->cmdlen      =       sizeof(cmd);
-       xs->resid       =       bp->b_bcount;
-       xs->when_done   =       sd_done;
-       xs->done_arg    =       unit;
-       xs->done_arg2   =       (int)xs;
-       xs->error       =       XS_NOERROR;
-       xs->bp          =       bp;
-       xs->data        =       (u_char *)bp->b_un.b_addr;
-       xs->datalen     =       bp->b_bcount;
-       /*******************************************************\
-       * Pass all this info to the scsi driver.                *
-       \*******************************************************/
-
-
-
-       if ( (*(sd->sc_sw->scsi_cmd))(xs) != SUCCESSFULLY_QUEUED)
+       if (sd_scsi_cmd(unit,
+                       &cmd,
+                       sizeof(cmd),
+                       (u_char *)bp->b_un.b_addr,
+                       bp->b_bcount,
+                       10000,
+                       bp,
+                       SCSI_NOSLEEP| ((bp->b_flags & B_READ)?
+                               SCSI_DATA_IN : SCSI_DATA_OUT))
+               != SUCCESSFULLY_QUEUED)
        {
        {
+bad:
                printf("sd%d: oops not queued",unit);
                printf("sd%d: oops not queued",unit);
-               xs->error = XS_DRIVER_STUFFUP;
-               sd_done(unit,xs);  /* clean up (calls sdstart) */
+               bp->b_error = EIO;
+               bp->b_flags |= B_ERROR;
+               biodone(bp);
+               return ;
        }
        sdqueues++;
 }
 
        }
        sdqueues++;
 }
 
-/*******************************************************\
-* This routine is called by the scsi interrupt when    *
-* the transfer is complete.
-\*******************************************************/
-int    sd_done(unit,xs)
-int    unit;
-struct scsi_xfer       *xs;
-{
-       struct  buf             *bp;
-       int     retval;
-       int     retries = 0;
-
-       if(scsi_debug & PRINTROUTINES) printf("sd_done%d ",unit);
-       if (! (xs->flags & INUSE))
-               panic("scsi_xfer not in use!");
-       if(bp = xs->bp)
-       {
-               switch(xs->error)
-               {
-               case    XS_NOERROR:
-                       bp->b_error = 0;
-                       bp->b_resid = 0;
-                       break;
-
-               case    XS_SENSE:
-                       retval = (sd_interpret_sense(unit,xs));
-                       if(retval)
-                       {
-                               bp->b_flags |= B_ERROR;
-                               bp->b_error = retval;
-                       }
-                       break;
-
-               case    XS_TIMEOUT:
-                       printf("sd%d timeout\n",unit);
-
-               case    XS_BUSY:        /* should retry */ /* how? */
-                       /************************************************/
-                       /* SHOULD put buf back at head of queue         */
-                       /* and decrement retry count in (*xs)           */
-                       /* HOWEVER, this should work as a kludge        */
-                       /************************************************/
-                       if(xs->retries--)
-                       {
-                               xs->error = XS_NOERROR;
-                               xs->flags &= ~ITSDONE;
-                               if ( (*(sd_data[unit].sc_sw->scsi_cmd))(xs)
-                                       == SUCCESSFULLY_QUEUED)
-                               {       /* don't wake the job, ok? */
-                                       return;
-                               }
-                               xs->flags |= ITSDONE;
-                       } /* fall through */
-
-               case    XS_DRIVER_STUFFUP:
-                       bp->b_flags |= B_ERROR;
-                       bp->b_error = EIO;
-                       break;
-               default:
-                       printf("sd%d: unknown error category from scsi driver\n"
-                               ,unit);
-               }       
-               biodone(bp);
-               sd_free_xs(unit,xs,0);
-               sdstart(unit);  /* If there's anything waiting.. do it */
-       }
-       else /* special has finished */
-       {
-               wakeup(xs);
-       }
-}
 /*******************************************************\
 * Perform special action on behalf of the user         *
 * Knows about the internals of this device             *
 /*******************************************************\
 * Perform special action on behalf of the user         *
 * Knows about the internals of this device             *
@@ -703,13 +642,15 @@ sdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
        \*******************************************************/
        unit = UNIT(dev);
        part = PARTITION(dev);
        \*******************************************************/
        unit = UNIT(dev);
        part = PARTITION(dev);
-       sd = &sd_data[unit];
+       sd = sd_data[unit];
+#ifdef SDDEBUG
        if(scsi_debug & PRINTROUTINES) printf("sdioctl%d ",unit);
        if(scsi_debug & PRINTROUTINES) printf("sdioctl%d ",unit);
+#endif /*SDDEBUG*/
 
        /*******************************************************\
        * If the device is not valid.. abandon ship             *
        \*******************************************************/
 
        /*******************************************************\
        * If the device is not valid.. abandon ship             *
        \*******************************************************/
-       if (!(sd_data[unit].flags & SDVALID))
+       if (!(sd->flags & SDVALID))
                return(EIO);
        switch(cmd)
        {
                return(EIO);
        switch(cmd)
        {
@@ -793,7 +734,7 @@ unsigned char       unit;
        /*unsigned int n, m;*/
        char *errstring;
        struct dos_partition *dos_partition_p;
        /*unsigned int n, m;*/
        char *errstring;
        struct dos_partition *dos_partition_p;
-       struct sd_data *sd = sd_data + unit;
+       struct sd_data *sd = sd_data[unit];
 
        /*******************************************************\
        * If the inflo is already loaded, use it                *
 
        /*******************************************************\
        * If the inflo is already loaded, use it                *
@@ -804,6 +745,7 @@ unsigned char       unit;
        /*******************************************************\
        * make partition 3 the whole disk in case of failure    *
        *   then get pdinfo                                     *
        /*******************************************************\
        * make partition 3 the whole disk in case of failure    *
        *   then get pdinfo                                     *
+       * for historical reasons, make part a same as raw part  *
        \*******************************************************/
        sd->disklabel.d_partitions[0].p_offset = 0;
        sd->disklabel.d_partitions[0].p_size = sd->params.disksize;
        \*******************************************************/
        sd->disklabel.d_partitions[0].p_offset = 0;
        sd->disklabel.d_partitions[0].p_size = sd->params.disksize;
@@ -819,11 +761,11 @@ unsigned char     unit;
        {
                sd->disklabel.d_secpercyl = 100;
                                        /* as long as it's not 0 */
        {
                sd->disklabel.d_secpercyl = 100;
                                        /* as long as it's not 0 */
-                                       /* readdisklabel divides by it */
+                                       /* readdisklabel divides by it (?)*/
        }
 
        /*******************************************************\
        }
 
        /*******************************************************\
-       * all the generic bisklabel extraction routine          *
+       * Call the generic disklabel extraction routine         *
        \*******************************************************/
        if(errstring = readdisklabel(makedev(0 ,(unit<<UNITSHIFT )+3)
                                        , sdstrategy
        \*******************************************************/
        if(errstring = readdisklabel(makedev(0 ,(unit<<UNITSHIFT )+3)
                                        , sdstrategy
@@ -835,9 +777,6 @@ unsigned char       unit;
                printf("sd%d: %s\n",unit, errstring);
                return(ENXIO);
        }
                printf("sd%d: %s\n",unit, errstring);
                return(ENXIO);
        }
-       /*******************************************************\
-       * leave partition 2 "open" for raw I/O                  *
-       \*******************************************************/
 
        sd->flags |= SDHAVELABEL; /* WE HAVE IT ALL NOW */
        return(ESUCCESS);
 
        sd->flags |= SDHAVELABEL; /* WE HAVE IT ALL NOW */
        return(ESUCCESS);
@@ -869,9 +808,10 @@ sd_size(unit, flags)
                        &rdcap,
                        sizeof(rdcap),  
                        2000,
                        &rdcap,
                        sizeof(rdcap),  
                        2000,
-                       flags) != 0)
+                       NULL,
+                       flags | SCSI_DATA_IN) != 0)
        {
        {
-               printf("could not get size of unit %d\n", unit);
+               printf("sd%d: could not get size\n", unit);
                return(0);
        } else {
                size = rdcap.addr_0 + 1 ;
                return(0);
        } else {
                size = rdcap.addr_0 + 1 ;
@@ -899,26 +839,31 @@ int       unit,flags;
                        0,
                        0,
                        100000,
                        0,
                        0,
                        100000,
+                       NULL,
                        flags));
 }
 
 /*******************************************************\
 * Prevent or allow the user to remove the tape         *
                        flags));
 }
 
 /*******************************************************\
 * Prevent or allow the user to remove the tape         *
+* Don't change this status if any partitions are open  *
 \*******************************************************/
 sd_prevent(unit,type,flags)
 int    unit,type,flags;
 {
        struct  scsi_prevent    scsi_cmd;
 
 \*******************************************************/
 sd_prevent(unit,type,flags)
 int    unit,type,flags;
 {
        struct  scsi_prevent    scsi_cmd;
 
+       if(sd_data[unit]->openparts) return;
+
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = PREVENT_ALLOW;
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = PREVENT_ALLOW;
-       scsi_cmd.prevent=type;
+       scsi_cmd.how=type;
        return (sd_scsi_cmd(unit,
                        &scsi_cmd,
                        sizeof(scsi_cmd),
                        0,
                        0,
                        5000,
        return (sd_scsi_cmd(unit,
                        &scsi_cmd,
                        sizeof(scsi_cmd),
                        0,
                        0,
                        5000,
+                       NULL,
                        flags) );
 }
 /*******************************************************\
                        flags) );
 }
 /*******************************************************\
@@ -931,7 +876,7 @@ int unit,flags;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = START_STOP;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = START_STOP;
-       scsi_cmd.start = 1;
+       scsi_cmd.how = SSS_START;
 
        return (sd_scsi_cmd(unit,
                        &scsi_cmd,
 
        return (sd_scsi_cmd(unit,
                        &scsi_cmd,
@@ -939,6 +884,7 @@ int unit,flags;
                        0,
                        0,
                        2000,
                        0,
                        0,
                        2000,
+                       NULL,
                        flags));
 }
 
                        flags));
 }
 
@@ -968,7 +914,8 @@ sd_reassign_blocks(unit,block)
                        &rbdata,
                        sizeof(rbdata),
                        5000,
                        &rbdata,
                        sizeof(rbdata),
                        5000,
-                       0));
+                       NULL,
+                       SCSI_DATA_OUT));
 }
 
 #define b2tol(a)       (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
 }
 
 #define b2tol(a)       (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
@@ -981,7 +928,7 @@ sd_reassign_blocks(unit,block)
 
 int    sd_get_parms(unit, flags)
 {
 
 int    sd_get_parms(unit, flags)
 {
-       struct sd_data *sd = sd_data + unit;
+       struct sd_data *sd = sd_data[unit];
        struct disk_parms *disk_parms = &sd->params;
        struct  scsi_mode_sense         scsi_cmd;
        struct  scsi_mode_sense_data
        struct disk_parms *disk_parms = &sd->params;
        struct  scsi_mode_sense         scsi_cmd;
        struct  scsi_mode_sense_data
@@ -999,11 +946,12 @@ int       sd_get_parms(unit, flags)
        /*******************************************************\
        * First do a mode sense page 3                          *
        \*******************************************************/
        /*******************************************************\
        * First do a mode sense page 3                          *
        \*******************************************************/
+#ifdef SDDEBUG
        if (sd_debug)
        {
                bzero(&scsi_cmd, sizeof(scsi_cmd));
                scsi_cmd.op_code = MODE_SENSE;
        if (sd_debug)
        {
                bzero(&scsi_cmd, sizeof(scsi_cmd));
                scsi_cmd.op_code = MODE_SENSE;
-               scsi_cmd.page_code = 3;
+               scsi_cmd.page = 3;
                scsi_cmd.length = 0x24;
                /*******************************************************\
                * do the command, but we don't need the results         *
                scsi_cmd.length = 0x24;
                /*******************************************************\
                * do the command, but we don't need the results         *
@@ -1015,11 +963,13 @@ int      sd_get_parms(unit, flags)
                                &scsi_sense,
                                sizeof(scsi_sense),
                                2000,
                                &scsi_sense,
                                sizeof(scsi_sense),
                                2000,
-                               flags) != 0)
+                               NULL,
+                               flags | SCSI_DATA_IN) != 0)
                {
                {
-                       printf("could not mode sense (3) for unit %d\n", unit);
-                       return(ENXIO);
+                       printf("sd%d: could not mode sense (3)\n", unit);
                } 
                } 
+               else
+               {
                printf("unit %d: %d trk/zone, %d alt_sec/zone, %d alt_trk/zone, %d alt_trk/lun\n",
                        unit,
                        b2tol(scsi_sense.pages.disk_format.trk_z),
                printf("unit %d: %d trk/zone, %d alt_sec/zone, %d alt_trk/zone, %d alt_trk/lun\n",
                        unit,
                        b2tol(scsi_sense.pages.disk_format.trk_z),
@@ -1032,7 +982,9 @@ int        sd_get_parms(unit, flags)
                        b2tol(scsi_sense.pages.disk_format.interleave),
                        sd_size(unit, flags),
                        _3btol(scsi_sense.blk_desc.blklen));
                        b2tol(scsi_sense.pages.disk_format.interleave),
                        sd_size(unit, flags),
                        _3btol(scsi_sense.blk_desc.blklen));
+               }
        }
        }
+#endif /*SDDEBUG*/
 
 
        /*******************************************************\
 
 
        /*******************************************************\
@@ -1040,7 +992,7 @@ int        sd_get_parms(unit, flags)
        \*******************************************************/
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = MODE_SENSE;
        \*******************************************************/
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = MODE_SENSE;
-       scsi_cmd.page_code = 4;
+       scsi_cmd.page = 4;
        scsi_cmd.length = 0x20;
        /*******************************************************\
        * If the command worked, use the results to fill out    *
        scsi_cmd.length = 0x20;
        /*******************************************************\
        * If the command worked, use the results to fill out    *
@@ -1052,20 +1004,27 @@ int     sd_get_parms(unit, flags)
                        &scsi_sense,
                        sizeof(scsi_sense),
                        2000,
                        &scsi_sense,
                        sizeof(scsi_sense),
                        2000,
-                       flags) != 0)
+                       NULL,
+                       flags | SCSI_DATA_IN) != 0)
        {
        {
-               printf("could not mode sense (4) for unit %d\n", unit);
-               printf(" using ficticious geometry\n");
-               /* use adaptec standard ficticious geometry */
+               printf("sd%d could not mode sense (4).", unit);
+               printf(" Using ficticious geometry\n");
+               /*
+                * use adaptec standard ficticious geometry
+                * this depends on which controller (e.g. 1542C is
+                * different. but we have to put SOMETHING here..)
+                */
                sectors = sd_size(unit, flags);
                disk_parms->heads = 64;
                disk_parms->sectors = 32;
                disk_parms->cyls = sectors/(64 * 32);
                disk_parms->secsiz = SECSIZE;
                sectors = sd_size(unit, flags);
                disk_parms->heads = 64;
                disk_parms->sectors = 32;
                disk_parms->cyls = sectors/(64 * 32);
                disk_parms->secsiz = SECSIZE;
+               disk_parms->disksize = sectors;
        } 
        else
        {
 
        } 
        else
        {
 
+#ifdef SDDEBUG
                if (sd_debug)
                {
                printf("         %d cyls, %d heads, %d precomp, %d red_write, %d land_zone\n",
                if (sd_debug)
                {
                printf("         %d cyls, %d heads, %d precomp, %d red_write, %d land_zone\n",
@@ -1075,20 +1034,22 @@ int     sd_get_parms(unit, flags)
                        b2tol(scsi_sense.pages.rigid_geometry.st_cyl_rwc),
                        b2tol(scsi_sense.pages.rigid_geometry.land_zone));
                }
                        b2tol(scsi_sense.pages.rigid_geometry.st_cyl_rwc),
                        b2tol(scsi_sense.pages.rigid_geometry.land_zone));
                }
+#endif /*SDDEBUG*/
 
                /*******************************************************\
                * KLUDGE!!(for zone recorded disks)                     *
                * give a number of sectors so that sec * trks * cyls    *
                * is <= disk_size                                       *
 
                /*******************************************************\
                * KLUDGE!!(for zone recorded disks)                     *
                * give a number of sectors so that sec * trks * cyls    *
                * is <= disk_size                                       *
+               * can lead to wasted space! THINK ABOUT THIS !          *
                \*******************************************************/
                disk_parms->heads = scsi_sense.pages.rigid_geometry.nheads;
                disk_parms->cyls = _3btol(&scsi_sense.pages.rigid_geometry.ncyl_2);
                disk_parms->secsiz = _3btol(&scsi_sense.blk_desc.blklen);
 
                sectors = sd_size(unit, flags);
                \*******************************************************/
                disk_parms->heads = scsi_sense.pages.rigid_geometry.nheads;
                disk_parms->cyls = _3btol(&scsi_sense.pages.rigid_geometry.ncyl_2);
                disk_parms->secsiz = _3btol(&scsi_sense.blk_desc.blklen);
 
                sectors = sd_size(unit, flags);
-               sectors /= disk_parms->cyls;
-               sectors /= disk_parms->heads;
-               disk_parms->sectors = sectors; /* dubious on SCSI*/
+               disk_parms->disksize = sectors;
+               sectors /= (disk_parms->heads * disk_parms->cyls);
+               disk_parms->sectors = sectors; /* dubious on SCSI*//*XXX*/
        }
 
        sd->flags |= SDVALID;
        }
 
        sd->flags |= SDVALID;
@@ -1098,22 +1059,110 @@ int    sd_get_parms(unit, flags)
 /*******************************************************\
 * close the device.. only called if we are the LAST    *
 * occurence of an open device                          *
 /*******************************************************\
 * close the device.. only called if we are the LAST    *
 * occurence of an open device                          *
+* convenient now but usually a pain                    *
 \*******************************************************/
 sdclose(dev)
 dev_t dev;
 {
        unsigned char unit, part;
        unsigned int old_priority;
 \*******************************************************/
 sdclose(dev)
 dev_t dev;
 {
        unsigned char unit, part;
        unsigned int old_priority;
+       struct sd_data *sd;
 
        unit = UNIT(dev);
        part = PARTITION(dev);
 
        unit = UNIT(dev);
        part = PARTITION(dev);
-       sd_data[unit].partflags[part] &= ~SDOPEN;
-       sd_data[unit].openparts &= ~(1 << part);
-       if(sd_data[unit].openparts == 0) /* if all partitions closed */
+       sd = sd_data[unit];
+       sd->partflags[part] &= ~SDOPEN;
+       sd->openparts &= ~(1 << part);
+       sd_prevent(unit,PR_ALLOW,SCSI_SILENT|SCSI_ERR_OK);
+       return(0);
+}
+
+/*******************************************************\
+* This routine is called by the scsi interrupt when    *
+* the transfer is complete.
+\*******************************************************/
+int    sd_done(unit,xs)
+int    unit;
+struct scsi_xfer       *xs;
+{
+       struct  buf             *bp;
+       int     retval;
+       int     retries = 0;
+
+#ifdef SDDEBUG
+       if(scsi_debug & PRINTROUTINES) printf("sd_done%d ",unit);
+#endif /*SDDEBUG*/
+#ifdef PARANOID
+       if (! (xs->flags & INUSE))
+               panic("scsi_xfer not in use!");
+#endif
+       if((bp = xs->bp) == NULL)
        {
        {
-               sd_prevent(unit,PR_ALLOW,SCSI_SILENT|SCSI_ERR_OK);
+               /***********************************************\
+               * if it's a normal user level request, then ask *
+               * The user level code to handle error checking  *
+               * rather than doing it here at interrupt time   *
+               \***********************************************/
+               wakeup(xs);
+               return;
        }
        }
-       return(0);
+
+       /***********************************************\
+       * 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 right now, despite cost                *
+       \***********************************************/
+       switch(xs->error)
+       {
+       case    XS_NOERROR:
+               bp->b_error = 0;
+               bp->b_resid = 0;
+               break;
+
+       case    XS_SENSE:
+               retval = (sd_interpret_sense(unit,xs));
+               if(retval)
+               {
+                       bp->b_flags |= B_ERROR;
+                       bp->b_error = retval;
+               }
+               break;
+
+       case    XS_BUSY:        
+               /*should somehow arange for a 1 sec delay here (how?)*/
+       case    XS_TIMEOUT:
+               /***********************************************\
+               * If we can, resubmit it to the adapter.        *
+               \***********************************************/
+               if(xs->retries--)
+               {
+                       xs->error = XS_NOERROR;
+                       xs->flags &= ~ITSDONE;
+                       if ( (*(sd_data[unit]->sc_sw->scsi_cmd))(xs)
+                               == SUCCESSFULLY_QUEUED)
+                       {       /* don't wake the job, ok? */
+                               return;
+                       }
+                       xs->flags |= ITSDONE;
+               } /* fall through */
+
+       case    XS_DRIVER_STUFFUP:
+               bp->b_flags |= B_ERROR;
+               bp->b_error = EIO;
+               break;
+       default:
+               printf("sd%d: unknown error category from scsi driver\n"
+                       ,unit);
+       }       
+       /*******************************\
+       * tell the owner we're done     *
+       * then free our resources       *
+       * and see if there's more work  *
+       \*******************************/
+       biodone(bp);
+       sd_free_xs(unit,xs,0);
+       sdstart(unit);  /* If there's anything waiting.. do it */
 }
 
 /*******************************************************\
 }
 
 /*******************************************************\
@@ -1121,11 +1170,12 @@ dev_t dev;
 * Call it through the switch table, and tell it which  *
 * sub-unit we want, and what target and lu we wish to  *
 * talk to. Also tell it where to find the command      *
 * Call it through the switch table, and tell it which  *
 * sub-unit we want, and what target and lu we wish to  *
 * talk to. Also tell it where to find the command      *
-* how long int is.                                     *
+* and how long it is.                                  *
 * Also tell it where to read/write the data, and how   *
 * Also tell it where to read/write the data, and how   *
-* long the data is supposed to be                      *
+* long the data is supposed to be. If we have  a buf   *
+* to associate with the transfer, we need that too.    *
 \*******************************************************/
 \*******************************************************/
-int    sd_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,flags)
+int    sd_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,bp,flags)
 
 int    unit,flags;
 struct scsi_generic *scsi_cmd;
 
 int    unit,flags;
 struct scsi_generic *scsi_cmd;
@@ -1133,112 +1183,136 @@ int   cmdlen;
 int    timeout;
 u_char *data_addr;
 int    datalen;
 int    timeout;
 u_char *data_addr;
 int    datalen;
+struct buf *bp;
 {
        struct  scsi_xfer *xs;
        int     retval;
        int     s;
 {
        struct  scsi_xfer *xs;
        int     retval;
        int     s;
-       struct sd_data *sd = sd_data + unit;
+       struct sd_data *sd = sd_data[unit];
 
 
+#ifdef SDDEBUG
        if(scsi_debug & PRINTROUTINES) printf("\nsd_scsi_cmd%d ",unit);
        if(scsi_debug & PRINTROUTINES) printf("\nsd_scsi_cmd%d ",unit);
-       if(sd->sc_sw)   /* If we have a scsi driver */
+#endif /*SDDEBUG*/
+
+#ifdef PARANOID
+       if(!(sd->sc_sw))        /* If we have a scsi driver */
+       {/* How we got here is anyone's guess */
+               printf("sd%d: not set up\n",unit);
+               return(EINVAL);
+       }
+#endif
+       xs = sd_get_xs(unit,flags); /* should wait unless booting */
+#ifdef PARANOID
+       if(!xs)
        {
        {
-               xs = sd_get_xs(unit,flags); /* should wait unless booting */
-               if(!xs)
-               {
-                       printf("sd_scsi_cmd%d: controller busy"
-                                       " (this should never happen)\n",unit); 
-                               return(EBUSY);
-               }
-               xs->flags |= INUSE;
-               /*******************************************************\
-               * Fill out the scsi_xfer structure                      *
-               \*******************************************************/
-               xs->flags       |=      flags;
-               xs->adapter     =       sd->ctlr;
-               xs->targ        =       sd->targ;
-               xs->lu          =       sd->lu;
-               xs->retries     =       SD_RETRIES;
-               xs->timeout     =       timeout;
-               xs->cmd         =       scsi_cmd;
-               xs->cmdlen      =       cmdlen;
-               xs->data        =       data_addr;
-               xs->datalen     =       datalen;
-               xs->resid       =       datalen;
-               xs->when_done   =       (flags & SCSI_NOMASK)
-                                       ?(int (*)())0
-                                       :sd_done;
-               xs->done_arg    =       unit;
-               xs->done_arg2   =       (int)xs;
-retry:         xs->error       =       XS_NOERROR;
-               xs->bp          =       0;
-               retval = (*(sd->sc_sw->scsi_cmd))(xs);
-               switch(retval)
-               {
-               case    SUCCESSFULLY_QUEUED:
-                       s = splbio();
-                       while(!(xs->flags & ITSDONE))
-                               sleep(xs,PRIBIO+1);
-                       splx(s);
+               printf("sd_scsi_cmd%d: controller busy"
+                               " (this should never happen)\n",unit); 
+                       return(EBUSY);
+       }
+#endif
+       /*******************************************************\
+       * Fill out the scsi_xfer structure                      *
+       \*******************************************************/
+       xs->flags       =       INUSE | flags;
+       xs->adapter     =       sd->ctlr;
+       xs->targ        =       sd->targ;
+       xs->lu          =       sd->lu;
+       xs->retries     =       SD_RETRIES;
+       xs->timeout     =       timeout;
+       xs->cmd         =       scsi_cmd;
+       xs->cmdlen      =       cmdlen;
+       xs->data        =       data_addr;
+       xs->datalen     =       datalen;
+       xs->resid       =       datalen;
+       xs->when_done   =       sd_done;
+       xs->done_arg    =       unit;
+       xs->done_arg2   =       (int)xs;
+       xs->bp          =       bp;
+retry: xs->error       =       XS_NOERROR;
 
 
-               case    HAD_ERROR:
-                       /*printf("err = %d ",xs->error);*/
-                       switch(xs->error)
-                       {
-                       case    XS_NOERROR:
-                               retval = ESUCCESS;
-                               break;
-                       case    XS_SENSE:
-                               retval = (sd_interpret_sense(unit,xs));
-                               break;
-                       case    XS_DRIVER_STUFFUP:
-                               retval = EIO;
-                               break;
-                       case    XS_TIMEOUT:
-                               if(xs->retries-- )
-                               {
-                                       xs->flags &= ~ITSDONE;
-                                       goto retry;
-                               }
-                               retval = EIO;
-                               break;
-                       case    XS_BUSY:
-                               if(xs->retries-- )
-                               {
-                                       xs->flags &= ~ITSDONE;
-                                       goto retry;
-                               }
-                               retval = EIO;
-                               break;
-                       default:
-                               retval = EIO;
-                               printf("sd%d: unknown error category from scsi driver\n"
-                                       ,unit);
-                       }       
-                       break;
-               case    COMPLETE:
+       /*******************************************************\
+       * Do the transfer. If we are polling we will return:    *
+       * COMPLETE,     Was poll, and sd_done has been called   *
+       * HAD_ERROR,    Was poll and an error was encountered   *
+       * TRY_AGAIN_LATER, Adapter short resources, try again   *
+       *                                                       *
+       * if under full steam (interrupts) it will return:      *
+       * SUCCESSFULLY_QUEUED, will do a wakeup when complete   *
+       * HAD_ERROR,    had an erro before it could queue       *
+       * 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 proccessing    *
+       * and the buffer code both expect us to return straight *
+       * to them, so as soon as the command is queued, return  *
+       \*******************************************************/
+       retval = (*(sd->sc_sw->scsi_cmd))(xs);
+       if(bp) return retval; /* will sleep (or not) elsewhere */
+
+       /*******************************************************\
+       * Only here for non I/O cmds. It's cheaper to process   *
+       * the error status here than at interrupt time so       *
+       * sd_done will have done nothing except wake us up.     *
+       \*******************************************************/
+       switch(retval)
+       {
+       case    SUCCESSFULLY_QUEUED:
+               s = splbio();
+               while(!(xs->flags & ITSDONE))
+                       sleep(xs,PRIBIO+1);
+               splx(s);
+               /* fall through to check success of completed command */
+
+       case    HAD_ERROR:
+               switch(xs->error)
+               {
+               case    XS_NOERROR: /* nearly always hit this one */
                        retval = ESUCCESS;
                        break;
                        retval = ESUCCESS;
                        break;
-               case    TRY_AGAIN_LATER:
+
+               case    XS_SENSE:
+                       retval = (sd_interpret_sense(unit,xs));
+                       break;
+               case    XS_BUSY:
+                       /* should sleep 1 sec here */
+               case    XS_TIMEOUT:
                        if(xs->retries-- )
                        {
                                xs->flags &= ~ITSDONE;
                                goto retry;
                        }
                        if(xs->retries-- )
                        {
                                xs->flags &= ~ITSDONE;
                                goto retry;
                        }
+               case    XS_DRIVER_STUFFUP:
                        retval = EIO;
                        break;
                default:
                        retval = EIO;
                        retval = EIO;
                        break;
                default:
                        retval = EIO;
+                       printf("sd%d: unknown error category from scsi driver\n"
+                               ,unit);
+               }       
+               break;
+       case    COMPLETE:       /* Polling command completed ok */
+               retval = ESUCCESS;
+               break;
+
+       case    TRY_AGAIN_LATER:        /* adapter resource shortage */
+               /* should sleep 1 sec here */
+               if(xs->retries-- )
+               {
+                       xs->flags &= ~ITSDONE;
+                       goto retry;
                }
                }
-               sd_free_xs(unit,xs,flags);
-               sdstart(unit);          /* check if anything is waiting fr the xs */
-       }
-       else
-       {
-               printf("sd%d: not set up\n",unit);
-               return(EINVAL);
+       default:
+               retval = EIO;
        }
        }
+       /*******************************************************\
+       * we have finished with the xfer stuct, free it and     *
+       * check if anyone else needs to be started up.          *
+       \*******************************************************/
+       sd_free_xs(unit,xs,flags);
+       sdstart(unit); /* check queue */
        return(retval);
 }
        return(retval);
 }
+
 /***************************************************************\
 * Look at the returned sense and act on the error and detirmine        *
 * The unix error number to pass back... (0 = report no error)  *
 /***************************************************************\
 * Look at the returned sense and act on the error and detirmine        *
 * The unix error number to pass back... (0 = report no error)  *
@@ -1251,6 +1325,7 @@ struct    scsi_xfer *xs;
        struct  scsi_sense_data *sense;
        int     key;
        int     silent;
        struct  scsi_sense_data *sense;
        int     key;
        int     silent;
+       long int        info;
 
        /***************************************************************\
        * If the flags say errs are ok, then always return ok.          *
 
        /***************************************************************\
        * If the flags say errs are ok, then always return ok.          *
@@ -1259,11 +1334,15 @@ struct  scsi_xfer *xs;
        silent = (xs->flags & SCSI_SILENT);
 
        sense = &(xs->sense);
        silent = (xs->flags & SCSI_SILENT);
 
        sense = &(xs->sense);
-       switch(sense->error_class)
+       info = ((sense->ext.extended.info[0] <<24)|
+               (sense->ext.extended.info[1] <<16)|
+               (sense->ext.extended.info[2] <<8)|
+               (sense->ext.extended.info[3] ));
+       switch(sense->error_code & SSD_ERRCODE)
        {
        {
-       case 7:
+       case 0x70:
                {
                {
-               key=sense->ext.extended.sense_key;
+               key=sense->ext.extended.flags & SSD_KEY;
                switch(key)
                {
                case    0x0:
                switch(key)
                {
                case    0x0:
@@ -1272,13 +1351,9 @@ struct   scsi_xfer *xs;
                        if(!silent)
                        {
                                printf("sd%d: soft error(corrected) ", unit); 
                        if(!silent)
                        {
                                printf("sd%d: soft error(corrected) ", unit); 
-                               if(sense->valid)
+                               if(sense->error_code & SSD_ERRCODE_VALID)
                                {
                                {
-                                       printf("block no. %d (decimal)",
-                                       (sense->ext.extended.info[0] <<24)|
-                                       (sense->ext.extended.info[1] <<16)|
-                                       (sense->ext.extended.info[2] <<8)|
-                                       (sense->ext.extended.info[3] ));
+                                       printf("block no. %d (decimal)",info);
                                }
                                printf("\n");
                        }
                                }
                                printf("\n");
                        }
@@ -1291,13 +1366,9 @@ struct   scsi_xfer *xs;
                        if(!silent)
                        {
                                printf("sd%d: medium error ", unit); 
                        if(!silent)
                        {
                                printf("sd%d: medium error ", unit); 
-                               if(sense->valid)
+                               if(sense->error_code & SSD_ERRCODE_VALID)
                                {
                                {
-                                       printf("block no. %d (decimal)",
-                                       (sense->ext.extended.info[0] <<24)|
-                                       (sense->ext.extended.info[1] <<16)|
-                                       (sense->ext.extended.info[2] <<8)|
-                                       (sense->ext.extended.info[3] ));
+                                       printf("block no. %d (decimal)",info);
                                }
                                printf("\n");
                        }
                                }
                                printf("\n");
                        }
@@ -1317,8 +1388,8 @@ struct    scsi_xfer *xs;
                        * sure that we don't have any residual state    *
                        \***********************************************/
                        if(!silent)printf("sd%d: Unit attention.\n ", unit); 
                        * sure that we don't have any residual state    *
                        \***********************************************/
                        if(!silent)printf("sd%d: Unit attention.\n ", unit); 
-                       sd_data[unit].flags &= ~(SDVALID | SDHAVELABEL);
-                       if (sd_data[unit].openparts)
+                       sd_data[unit]->flags &= ~(SDVALID | SDHAVELABEL);
+                       if (sd_data[unit]->openparts)
                        {
                                return(EIO);
                        }
                        {
                                return(EIO);
                        }
@@ -1328,13 +1399,9 @@ struct   scsi_xfer *xs;
                        {
                                printf("sd%d: attempted protection violation ",
                                                unit); 
                        {
                                printf("sd%d: attempted protection violation ",
                                                unit); 
-                               if(sense->valid)
+                               if(sense->error_code & SSD_ERRCODE_VALID)
                                {
                                {
-                                       printf("block no. %d (decimal)\n",
-                                       (sense->ext.extended.info[0] <<24)|
-                                       (sense->ext.extended.info[1] <<16)|
-                                       (sense->ext.extended.info[2] <<8)|
-                                       (sense->ext.extended.info[3] ));
+                                       printf("block no. %d (decimal)\n",info);
                                }
                                printf("\n");
                        }
                                }
                                printf("\n");
                        }
@@ -1342,15 +1409,11 @@ struct  scsi_xfer *xs;
                case    0x8:
                        if(!silent)
                        {
                case    0x8:
                        if(!silent)
                        {
-                               printf("sd%d: block wrong state (worm)\n ",
+                               printf("sd%d: block wrong state (format?)\n ",
                                unit); 
                                unit); 
-                               if(sense->valid)
+                               if(sense->error_code & SSD_ERRCODE_VALID)
                                {
                                {
-                                       printf("block no. %d (decimal)\n",
-                                       (sense->ext.extended.info[0] <<24)|
-                                       (sense->ext.extended.info[1] <<16)|
-                                       (sense->ext.extended.info[2] <<8)|
-                                       (sense->ext.extended.info[3] ));
+                                       printf("block no. %d (decimal)\n",info);
                                }
                                printf("\n");
                        }
                                }
                                printf("\n");
                        }
@@ -1372,13 +1435,9 @@ struct   scsi_xfer *xs;
                        {
                                printf("sd%d: search returned\n ",
                                        unit); 
                        {
                                printf("sd%d: search returned\n ",
                                        unit); 
-                               if(sense->valid)
+                               if(sense->error_code & SSD_ERRCODE_VALID)
                                {
                                {
-                                       printf("block no. %d (decimal)\n",
-                                       (sense->ext.extended.info[0] <<24)|
-                                       (sense->ext.extended.info[1] <<16)|
-                                       (sense->ext.extended.info[2] <<8)|
-                                       (sense->ext.extended.info[3] ));
+                                       printf("block no. %d (decimal)\n",info);
                                }
                                printf("\n");
                        }
                                }
                                printf("\n");
                        }
@@ -1392,13 +1451,9 @@ struct   scsi_xfer *xs;
                        {
                                printf("sd%d: verify miscompare\n ",
                                unit); 
                        {
                                printf("sd%d: verify miscompare\n ",
                                unit); 
-                               if(sense->valid)
+                               if(sense->error_code & SSD_ERRCODE_VALID)
                                {
                                {
-                                       printf("block no. %d (decimal)\n",
-                                       (sense->ext.extended.info[0] <<24)|
-                                       (sense->ext.extended.info[1] <<16)|
-                                       (sense->ext.extended.info[2] <<8)|
-                                       (sense->ext.extended.info[3] ));
+                                       printf("block no. %d (decimal)\n",info);
                                }
                                printf("\n");
                        }
                                }
                                printf("\n");
                        }
@@ -1410,19 +1465,12 @@ struct  scsi_xfer *xs;
                }
                break;
        }
                }
                break;
        }
-       case 0:
-       case 1:
-       case 2:
-       case 3:
-       case 4:
-       case 5:
-       case 6:
+       default:
                {
                {
-                       if(!silent)printf("sd%d: error class %d code %d\n",
+                       if(!silent)printf("sd%d: code %d\n",
                                unit,
                                unit,
-                               sense->error_class,
-                               sense->error_code);
-               if(sense->valid)
+                               sense->error_code & SSD_ERRCODE);
+               if(sense->error_code & SSD_ERRCODE_VALID)
                        if(!silent)printf("block no. %d (decimal)\n",
                        (sense->ext.unextended.blockhi <<16)
                        + (sense->ext.unextended.blockmed <<8)
                        if(!silent)printf("block no. %d (decimal)\n",
                        (sense->ext.unextended.blockhi <<16)
                        + (sense->ext.unextended.blockmed <<8)
@@ -1444,7 +1492,8 @@ sdsize(dev_t dev)
        if (unit >= NSD)
                return(-1);
 
        if (unit >= NSD)
                return(-1);
 
-       sd = &sd_data[unit];
+       sd = sd_data[unit];
+       if(!sd) return(-1);
        if((sd->flags & SDINIT) == 0) return(-1);
        if (sd == 0 || (sd->flags & SDHAVELABEL) == 0)
                val = sdopen (MAKESDDEV(major(dev), unit, RAW_PART), FREAD, S_IFBLK, 0);
        if((sd->flags & SDINIT) == 0) return(-1);
        if (sd == 0 || (sd->flags & SDHAVELABEL) == 0)
                val = sdopen (MAKESDDEV(major(dev), unit, RAW_PART), FREAD, S_IFBLK, 0);
@@ -1453,14 +1502,146 @@ sdsize(dev_t dev)
 
        return((int)sd->disklabel.d_partitions[part].p_size);
 }
 
        return((int)sd->disklabel.d_partitions[part].p_size);
 }
-
-sddump()
+/*#define SCSIDUMP*/
+#ifdef SCSIDUMP
+#include <vm/vm.h>
+/***********************************************************************\
+* dump all of physical memory into the partition specified, starting   *
+* at offset 'dumplo' into the partition.                               *
+\***********************************************************************/
+static struct  scsi_xfer sx;
+#define        MAXTRANSFER 8 /* 1 page at a time */
+int
+sddump(dev_t dev)                      /* dump core after a system crash */
 {
 {
-    printf("sddump()        -- not implemented\n");
-    return(-1);
-}
+       register struct sd_data *sd;    /* disk unit to do the IO */
+       long    num;                    /* number of sectors to write */
+       int     unit, part, sdc;
+       long    blkoff, blknum, blkcnt;
+       long    nblocks;
+       char    *addr;
+       struct  scsi_rw_big     cmd;
+       extern  int Maxmem;
+       static  sddoingadump = 0 ;
+       extern  caddr_t CADDR1; /* map the page we are about to write, here*/
+       struct scsi_xfer *xs = &sx;
+       int     retval;
+
+       addr = (char *) 0;              /* starting address */
+
+       /* toss any characters present prior to dump */
+       while (sgetc(1))
+               ;
+
+       /* size of memory to dump */
+       num = Maxmem;
+       unit = UNIT(dev);               /* eventually support floppies? */
+       part = PARTITION(dev);          /* file system */
+       /* check for acceptable drive number */
+       if (unit >= NSD) return(ENXIO);         /* 31 Jul 92*/
+
+       sd = sd_data[unit];
+       if(!sd) return (ENXIO);
+       /* was it ever initialized etc. ? */
+       if (!(sd->flags & SDINIT))              return (ENXIO);
+       if (sd->flags & SDVALID != SDVALID)     return (ENXIO) ;
+       if (sd->flags & SDWRITEPROT)            return (ENXIO);
 
 
+       /* Convert to disk sectors */
+       num = (u_long) num * NBPG / sd->disklabel.d_secsize;
 
 
+       /* check if controller active */
+       if (sddoingadump) return(EFAULT);
 
 
+       nblocks = sd->disklabel.d_partitions[part].p_size;
+       blkoff = sd->disklabel.d_partitions[part].p_offset;
 
 
+       /* check transfer bounds against partition size */
+       if ((dumplo < 0) || ((dumplo + num) > nblocks))
+               return(EINVAL);
+
+       sddoingadump = 1  ;
+
+       blknum = dumplo + blkoff;
+       while (num > 0)
+       {
+               if (blkcnt > MAXTRANSFER) blkcnt = MAXTRANSFER;
+               pmap_enter(     kernel_pmap,
+                               CADDR1,
+                               trunc_page(addr),
+                               VM_PROT_READ,
+                               TRUE);
+#ifndef        NOT_TRUSTED
+               /*******************************************************\
+               *  Fill out the scsi command                            *
+               \*******************************************************/
+               bzero(&cmd, sizeof(cmd));
+               cmd.op_code     =       WRITE_BIG;
+               cmd.addr_3      =       (blknum & 0xff000000) >> 24;
+               cmd.addr_2      =       (blknum & 0xff0000) >> 16;
+               cmd.addr_1      =       (blknum & 0xff00) >> 8;
+               cmd.addr_0      =       blknum & 0xff;
+               cmd.length2     =       (blkcnt & 0xff00) >> 8;
+               cmd.length1     =       (blkcnt & 0xff);
+               /*******************************************************\
+               * Fill out the scsi_xfer structure                      *
+               *       Note: we cannot sleep as we may be an interrupt *
+               \*******************************************************/
+               bzero(xs, sizeof(sx));
+               xs->flags       |=      SCSI_NOMASK|SCSI_NOSLEEP|INUSE;
+               xs->adapter     =       sd->ctlr;
+               xs->targ        =       sd->targ;
+               xs->lu          =       sd->lu;
+               xs->retries     =       SD_RETRIES;
+               xs->timeout     =       10000;/* 10000 millisecs for a disk !*/
+               xs->cmd         =       (struct scsi_generic *)&cmd;
+               xs->cmdlen      =       sizeof(cmd);
+               xs->resid       =       blkcnt * 512;
+               xs->when_done   =       0;
+               xs->done_arg    =       unit;
+               xs->done_arg2   =       (int)xs;
+               xs->error       =       XS_NOERROR;
+               xs->bp          =       0;
+               xs->data        =       (u_char *)CADDR1;
+               xs->datalen     =       blkcnt * 512;
+
+               /*******************************************************\
+               * Pass all this info to the scsi driver.                *
+               \*******************************************************/
+               retval = (*(sd->sc_sw->scsi_cmd))(xs);
+               switch(retval)
+               {
+               case    SUCCESSFULLY_QUEUED:
+               case    HAD_ERROR:
+                       return(ENXIO); /* we said not to sleep! */
+               case    COMPLETE:
+                       break;
+               default:
+                       return(ENXIO); /* we said not to sleep! */
+               }
+#else  NOT_TRUSTED
+               /* lets just talk about this first...*/
+               printf ("sd%d: dump addr 0x%x, blk %d\n",unit,addr,blknum);
+#endif NOT_TRUSTED
+               
+               if ((unsigned)addr % (1024*1024) == 0) printf("%d ", num/2048) ;
+               /* update block count */
+               num -= MAXTRANSFER;
+               blknum += MAXTRANSFER ;
+               (int) addr += 512 * MAXTRANSFER;
+
+               /* operator aborting dump? */
+               if (sgetc(1))
+                       return(EINTR);
+       }
+       return(0);
+}
+#else  SCSIDUMP
+sddump()
+{
+       printf("\nsddump()        -- not implemented\n");
+       DELAY(20000000);        /* 20 seconds */
+       return(-1);
+}
+#endif SCSIDUMP