New version of scsi code from Julian
authorRod Grimes <rgrimes@FreeBSD.org>
Thu, 18 Nov 1993 05:03:27 +0000 (05:03 +0000)
committerRod Grimes <rgrimes@FreeBSD.org>
Thu, 18 Nov 1993 05:03:27 +0000 (05:03 +0000)
33 files changed:
sys/conf/files
sys/i386/conf/LINT
sys/i386/i386/conf.c
sys/i386/include/param.h
sys/i386/isa/aha1542.c
sys/i386/isa/aha1742.c
sys/i386/isa/bt742a.c
sys/i386/isa/ultra14f.c
sys/i386/isa/wd.c
sys/i386/isa/wx.c
sys/kern/kern__physio.c
sys/kern/kern_subr.c
sys/scsi/README
sys/scsi/cd.c
sys/scsi/ch.c
sys/scsi/scsi_all.h
sys/scsi/scsi_base.c [new file with mode: 0644]
sys/scsi/scsi_cd.h
sys/scsi/scsi_changer.h
sys/scsi/scsi_debug.h [new file with mode: 0644]
sys/scsi/scsi_disk.h
sys/scsi/scsi_ioctl.c [new file with mode: 0644]
sys/scsi/scsi_tape.h
sys/scsi/scsiconf.c
sys/scsi/scsiconf.h
sys/scsi/sd.c
sys/scsi/st.c
sys/scsi/su.c [new file with mode: 0644]
sys/scsi/uk.c [new file with mode: 0644]
sys/sys/buf.h
sys/sys/chio.h
sys/sys/mtio.h
sys/sys/scsiio.h [new file with mode: 0644]

index 5709296..948431a 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: files,v 1.9 1993/11/07 22:54:36 wollman Exp $
+# $Id: files,v 1.10 1993/11/18 00:06:16 wollman Exp $
 #
 ddb/db_access.c                optional ddb
 ddb/db_aout.c          optional ddb
 #
 ddb/db_access.c                optional ddb
 ddb/db_aout.c          optional ddb
@@ -199,9 +199,12 @@ pcfs/pcfs_vnops.c  optional pcfs
 scsi/cd.c              optional cd
 scsi/ch.c              optional ch
 scsi/scsiconf.c                optional scbus
 scsi/cd.c              optional cd
 scsi/ch.c              optional ch
 scsi/scsiconf.c                optional scbus
+scsi/scsi_base.c       optional scbus
+scsi/scsi_ioctl.c      optional scbus
 scsi/sd.c              optional sd
 scsi/sd.c              optional sd
-scsi/sg.c              optional sg
 scsi/st.c              optional st
 scsi/st.c              optional st
+scsi/su.c              optional su
+scsi/uk.c              optional uk
 ufs/mfs_vfsops.c       optional mfs
 ufs/mfs_vnops.c                optional mfs
 ufs/ufs_alloc.c                standard
 ufs/mfs_vfsops.c       optional mfs
 ufs/mfs_vnops.c                optional mfs
 ufs/ufs_alloc.c                standard
index a48a73b..ef33ef5 100644 (file)
@@ -4,7 +4,7 @@
 #
 #      This kernel is NOT MEANT to be runnable!
 #
 #
 #      This kernel is NOT MEANT to be runnable!
 #
-#      $Id: LINT,v 1.28 1993/11/07 22:54:51 wollman Exp $
+#      $Id: LINT,v 1.29 1993/11/17 23:24:12 wollman Exp $
 #
 
 machine                "i386"
 #
 
 machine                "i386"
@@ -87,6 +87,7 @@ options               "SHMMAXPGS=64"          # 256Kb of sharable memory
 #pseudo-device tb                      #tablet line discipline.
 pseudo-device  tpip
 #pseudo-device tun
 #pseudo-device tb                      #tablet line discipline.
 pseudo-device  tpip
 #pseudo-device tun
+device         uk0                     #unknown scsi devices
 pseudo-device  vnodepager
 
 #
 pseudo-device  vnodepager
 
 #
index 755a0dd..ae333fd 100644 (file)
@@ -1,4 +1,4 @@
-/*-
+/*
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
  *
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
  *
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)conf.c        5.8 (Berkeley) 5/12/91
  * SUCH DAMAGE.
  *
  *     from: @(#)conf.c        5.8 (Berkeley) 5/12/91
- *     $Id: conf.c,v 1.13 1993/10/26 22:25:20 nate Exp $
+ *     $Id: conf.c,v 1.14 1993/11/03 18:07:32 nate Exp $
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -126,20 +126,6 @@ int        chopen(),chclose(),chioctl();
 #define        chioctl         enxio
 #endif
 
 #define        chioctl         enxio
 #endif
 
-#include "sg.h"
-#if NSG > 0
-int    sgopen(),sgclose(),sgioctl(),sgstrategy();
-#define        sgdump          enxio
-#define        sgsize          NULL
-#else
-#define        sgopen          enxio
-#define        sgclose         enxio
-#define        sgstrategy      enxio
-#define        sgioctl         enxio
-#define        sgdump          enxio
-#define        sgsize          NULL
-#endif
-
 #include "wt.h"
 #if NWT > 0
 int    wtopen(),wtclose(),wtstrategy(),wtioctl();
 #include "wt.h"
 #if NWT > 0
 int    wtopen(),wtclose(),wtstrategy(),wtioctl();
@@ -377,6 +363,26 @@ extern     struct tty sio_tty[];
 #define        sio_tty         NULL
 #endif
 
 #define        sio_tty         NULL
 #endif
 
+#include "su.h"
+#if NSU > 0
+int    suopen(),suclose(),suioctl();
+#define        susize          NULL
+#else
+#define        suopen          enxio
+#define        suclose         enxio
+#define        suioctl         enxio
+#define        susize          NULL
+#endif
+
+#include "uk.h"
+#if NUK > 0
+int    ukopen(),ukclose(),ukioctl();
+#else
+#define        ukopen          enxio
+#define        ukclose         enxio
+#define        ukioctl         enxio
+#endif
+
 struct cdevsw  cdevsw[] =
 {
        { cnopen,       cnclose,        cnread,         cnwrite,        /*0*/
 struct cdevsw  cdevsw[] =
 {
        { cnopen,       cnclose,        cnread,         cnwrite,        /*0*/
@@ -433,9 +439,9 @@ struct cdevsw       cdevsw[] =
        { chopen,       chclose,        enxio,          enxio,          /*17*/
          chioctl,      enxio,          enxio,          NULL,   /* ch */
          enxio,        enxio,          enxio },
        { chopen,       chclose,        enxio,          enxio,          /*17*/
          chioctl,      enxio,          enxio,          NULL,   /* ch */
          enxio,        enxio,          enxio },
-       { sgopen,       sgclose,        enodev,         enodev,         /*18*/
-         sgioctl,      enodev,         nullop,         NULL,   /* scsi 'generic' */
-         seltrue,      enodev,         sgstrategy },
+       { suopen,       suclose,        enodev,         enodev,         /*18*/
+         suioctl,      enodev,         nullop,         NULL,   /* scsi 'generic' */
+         seltrue,      enodev,         enodev },
        { twopen,       twclose,        twread,         twwrite,        /*19*/
          enodev,       nullop,         nullop,         NULL,   /* tw */
          twselect,     enodev,         enodev },
        { twopen,       twclose,        twread,         twwrite,        /*19*/
          enodev,       nullop,         nullop,         NULL,   /* tw */
          twselect,     enodev,         enodev },
@@ -472,6 +478,9 @@ struct cdevsw       cdevsw[] =
        { sndopen,      sndclose,       sndread,        sndwrite,       /*30*/
          sndioctl,     enodev,         enodev,         NULL,   /* sound driver */
          sndselect,    enodev,         NULL },
        { sndopen,      sndclose,       sndread,        sndwrite,       /*30*/
          sndioctl,     enodev,         enodev,         NULL,   /* sound driver */
          sndselect,    enodev,         NULL },
+       { ukopen,       ukclose,        enxio,          enxio,          /*31*/
+         ukioctl,      enxio,          enxio,          NULL,   /* unknown */
+         enxio,        enxio,          enxio },                /* scsi */
 /*
  * If you need a cdev major number, please contact the FreeBSD team
  * by sending mail to `freebsd-hackers@freefall.cdrom.com'.
 /*
  * If you need a cdev major number, please contact the FreeBSD team
  * by sending mail to `freebsd-hackers@freefall.cdrom.com'.
index c9e77b2..8f46b47 100644 (file)
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)param.h       5.8 (Berkeley) 6/28/91
  * SUCH DAMAGE.
  *
  *     from: @(#)param.h       5.8 (Berkeley) 6/28/91
- *     $Id: param.h,v 1.8 1993/11/07 17:42:58 wollman Exp $
+ *     $Id: param.h,v 1.9 1993/11/13 02:25:14 davidg Exp $
  */
 
 #ifndef _MACHINE_PARAM_H_
  */
 
 #ifndef _MACHINE_PARAM_H_
 #define i386_btop(x)           ((unsigned)(x) >> PGSHIFT)
 #define i386_ptob(x)           ((unsigned)(x) << PGSHIFT)
 
 #define i386_btop(x)           ((unsigned)(x) >> PGSHIFT)
 #define i386_ptob(x)           ((unsigned)(x) << PGSHIFT)
 
-/*
- * phystokv stolen from SCSI device drivers and fixed to use KERNBASE
- */
-#define PHYSTOKV(x)    (x | KERNBASE)
 #endif /* _MACHINE_PARAM_H_ */
 #endif /* _MACHINE_PARAM_H_ */
index c242624..b731ed6 100644 (file)
  * 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.
  *
- *     $Id: aha1542.c,v 1.13 1993/10/28 02:38:36 rgrimes Exp $
+ *      $Id: aha1542.c,v 2.8 93/10/24 12:55:08 julian Exp Locker: julian $
  */
 
 /*
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  */
 
  */
 
 /*
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  */
 
-/*
- * a FEW lines in this driver come from a MACH adaptec-disk driver
- * so the copyright below is included:
- *
- * Copyright 1990 by Open Software Foundation,
- * Grenoble, FRANCE
- *
- *             All Rights Reserved
- * 
- *   Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appears in all copies and
- * that both the copyright notice and this permission notice appear in
- * supporting documentation, and that the name of OSF or Open Software
- * Foundation not be used in advertising or publicity pertaining to
- * distribution of the software without specific, written prior
- * permission.
- * 
- *   OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
- * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
- * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-
 #include <sys/types.h>
 #include <sys/types.h>
+#ifdef KERNEL                  /* don't laugh.. look for main() */
 #include <aha.h>
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/errno.h>
 #include <sys/ioctl.h>
 #include <aha.h>
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/errno.h>
 #include <sys/ioctl.h>
+#include <sys/malloc.h>
 #include <sys/buf.h>
 #include <sys/proc.h>
 #include <sys/user.h>
 #include <sys/buf.h>
 #include <sys/proc.h>
 #include <sys/user.h>
-
-#ifdef  MACH    /* EITHER CMU OR OSF */
-#include <i386/ipl.h>
-#include <i386at/scsi.h>
-#include <i386at/scsiconf.h>
-
-#ifdef  OSF     /* OSF ONLY */
-#include <sys/table.h>
-#include <i386/handler.h>
-#include <i386/dispatcher.h>
-#include <i386/AT386/atbus.h>
-
-#else   OSF     /* CMU ONLY */
-#include <i386at/atbus.h>
-#include <i386/pio.h>
-#endif  OSF
-#endif  MACH    /* end of MACH specific */
-
-#ifdef  __386BSD__      /* 386BSD specific */
-#define isa_dev isa_device
-#define dev_unit id_unit
-#define dev_addr id_iobase
-
 #include <i386/isa/isa_device.h>
 #include <i386/isa/isa_device.h>
+#endif /* KERNEL */
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
-#endif  __386BSD__
 
 
-
-#ifdef __386BSD__
+#ifdef KERNEL
 #include "ddb.h"
 #if    NDDB > 0
 #include "ddb.h"
 #if    NDDB > 0
-int    Debugger();
-#else  NDDB
+int     Debugger();
+#else  /* NDDB */
 #define Debugger() panic("should call debugger here (adaptec.c)")
 #define Debugger() panic("should call debugger here (adaptec.c)")
-#endif NDDB
-#endif __386BSD__
-extern int     hz;
-extern int delaycount;  /* from clock setup code */
+#endif /* NDDB */
+extern int hz;
+#else /*KERNEL */
+#define NAHA 1
+#endif /*KERNEL */
 
 /************************** board definitions *******************************/
 
 /************************** board definitions *******************************/
+
 /*
  * I/O Port Interface
  */
 
 /*
  * I/O Port Interface
  */
 
-#define        AHA_BASE                aha_base[unit]
+#define        AHA_BASE                aha->aha_base
 #define        AHA_CTRL_STAT_PORT      (AHA_BASE + 0x0)        /* control & status */
 #define        AHA_CMD_DATA_PORT       (AHA_BASE + 0x1)        /* cmds and datas */
 #define        AHA_INTR_PORT           (AHA_BASE + 0x2)        /* Intr. stat */
 #define        AHA_CTRL_STAT_PORT      (AHA_BASE + 0x0)        /* control & status */
 #define        AHA_CMD_DATA_PORT       (AHA_BASE + 0x1)        /* cmds and datas */
 #define        AHA_INTR_PORT           (AHA_BASE + 0x2)        /* Intr. stat */
@@ -155,7 +107,7 @@ extern int delaycount;  /* from clock setup code */
 #define AHA_MBX_ENABLE         0x29    /* enable mail box interface */
 
 struct aha_cmd_buf {
 #define AHA_MBX_ENABLE         0x29    /* enable mail box interface */
 
 struct aha_cmd_buf {
-        u_char byte[16];       
+       u_char  byte[16];
 };
 
 /*
 };
 
 /*
@@ -178,8 +130,8 @@ struct aha_mbx {
        struct aha_mbx_out {
                unsigned char cmd;
                unsigned char ccb_addr[3];
        struct aha_mbx_out {
                unsigned char cmd;
                unsigned char ccb_addr[3];
-       } mbo [AHA_MBX_SIZE];
-       struct aha_mbx_in{
+       } mbo[AHA_MBX_SIZE];
+       struct aha_mbx_in {
                unsigned char stat;
                unsigned char ccb_addr[3];
        } mbi[AHA_MBX_SIZE];
                unsigned char stat;
                unsigned char ccb_addr[3];
        } mbi[AHA_MBX_SIZE];
@@ -193,60 +145,59 @@ struct aha_mbx {
 #define AHA_MBO_START  0x1     /* MBO activate entry */
 #define AHA_MBO_ABORT  0x2     /* MBO abort entry */
 
 #define AHA_MBO_START  0x1     /* MBO activate entry */
 #define AHA_MBO_ABORT  0x2     /* MBO abort entry */
 
+/*
+ * mbi.stat values
+ */
+
 #define AHA_MBI_FREE   0x0     /* MBI entry is free */
 #define AHA_MBI_OK     0x1     /* completed without error */
 #define AHA_MBI_ABORT  0x2     /* aborted ccb */
 #define AHA_MBI_UNKNOWN        0x3     /* Tried to abort invalid CCB */
 #define AHA_MBI_ERROR  0x4     /* Completed with error */
 
 #define AHA_MBI_FREE   0x0     /* MBI entry is free */
 #define AHA_MBI_OK     0x1     /* completed without error */
 #define AHA_MBI_ABORT  0x2     /* aborted ccb */
 #define AHA_MBI_UNKNOWN        0x3     /* Tried to abort invalid CCB */
 #define AHA_MBI_ERROR  0x4     /* Completed with error */
 
-extern struct aha_mbx aha_mbx[];
-
 /* FOR OLD VERSIONS OF THE !%$@ this may have to be 16 (yuk) */
 #define        AHA_NSEG        17      /* Number of scatter gather segments <= 16 */
                                /* allow 64 K i/o (min) */
 
 struct aha_ccb {
 /* FOR OLD VERSIONS OF THE !%$@ this may have to be 16 (yuk) */
 #define        AHA_NSEG        17      /* Number of scatter gather segments <= 16 */
                                /* allow 64 K i/o (min) */
 
 struct aha_ccb {
-       unsigned char   opcode;
-       unsigned char   lun:3;
-       unsigned char   data_in:1;              /* must be 0 */
-       unsigned char   data_out:1;             /* must be 0 */
-       unsigned char   target:3;
-       unsigned char   scsi_cmd_length;
-       unsigned char   req_sense_length;
-       unsigned char   data_length[3];
-       unsigned char   data_addr[3];
-       unsigned char   link_addr[3];
-       unsigned char   link_id;
-       unsigned char   host_stat;
-       unsigned char   target_stat;
-       unsigned char   reserved[2];
-       struct  scsi_generic    scsi_cmd;
-       struct  scsi_sense_data scsi_sense;
-       struct  aha_scat_gath {
+       unsigned char opcode;
+       unsigned char lun:3;
+       unsigned char data_in:1;        /* must be 0 */
+       unsigned char data_out:1;       /* must be 0 */
+       unsigned char target:3;
+       unsigned char scsi_cmd_length;
+       unsigned char req_sense_length;
+       unsigned char data_length[3];
+       unsigned char data_addr[3];
+       unsigned char link_addr[3];
+       unsigned char link_id;
+       unsigned char host_stat;
+       unsigned char target_stat;
+       unsigned char reserved[2];
+       struct scsi_generic scsi_cmd;
+       struct scsi_sense_data scsi_sense;
+       struct aha_scat_gath {
                unsigned char seg_len[3];
                unsigned char seg_addr[3];
        } scat_gath[AHA_NSEG];
                unsigned char seg_len[3];
                unsigned char seg_addr[3];
        } scat_gath[AHA_NSEG];
-       struct  aha_ccb *next;
-       struct  scsi_xfer       *xfer;          /* the scsi_xfer for this cmd */
-       struct  aha_mbx_out     *mbx;           /* pointer to mail box */
-       int     flags;
+       struct aha_ccb *next;
+       struct scsi_xfer *xfer; /* the scsi_xfer for this cmd */
+       struct aha_mbx_out *mbx;        /* pointer to mail box */
+       int     flags;
 #define CCB_FREE        0
 #define CCB_ACTIVE      1
 #define CCB_ABORTED     2
 #define CCB_FREE        0
 #define CCB_ACTIVE      1
 #define CCB_ABORTED     2
-
 };
 
 };
 
-
 /*
  * opcode fields
  */
 
 #define AHA_INITIATOR_CCB      0x00    /* SCSI Initiator CCB */
 #define AHA_TARGET_CCB         0x01    /* SCSI Target CCB */
 /*
  * opcode fields
  */
 
 #define AHA_INITIATOR_CCB      0x00    /* SCSI Initiator CCB */
 #define AHA_TARGET_CCB         0x01    /* SCSI Target CCB */
-#define AHA_INIT_SCAT_GATH_CCB 0x02    /* SCSI Initiator with scattter gather*/
+#define AHA_INIT_SCAT_GATH_CCB 0x02    /* SCSI Initiator with scatter gather */
 #define AHA_RESET_CCB          0x81    /* SCSI Bus reset */
 
 #define AHA_RESET_CCB          0x81    /* SCSI Bus reset */
 
-
 /*
  * aha_ccb.host_stat values
  */
 /*
  * aha_ccb.host_stat values
  */
@@ -266,34 +217,28 @@ struct aha_ccb {
 #define AHA_INV_CCB    0x1a    /* Invalid CCB or segment list */
 #define AHA_ABORTED      42
 
 #define AHA_INV_CCB    0x1a    /* Invalid CCB or segment list */
 #define AHA_ABORTED      42
 
-
-
-
-struct aha_setup
-{
-       u_char  sync_neg:1;
-       u_char  parity:1;
-       u_char  :6;
-       u_char  speed;
-       u_char  bus_on;
-       u_char  bus_off;
-       u_char  num_mbx;
-       u_char  mbx[3];
-       struct
-       {
-               u_char  offset:4;
-               u_char  period:3;
-               u_char  valid:1;
-       }sync[8];
-       u_char  disc_sts;
+struct aha_setup {
+       u_char  sync_neg:1;
+       u_char  parity:1;
+               u_char:6;
+       u_char  speed;
+       u_char  bus_on;
+       u_char  bus_off;
+       u_char  num_mbx;
+       u_char  mbx[3];
+       struct {
+               u_char  offset:4;
+               u_char  period:3;
+               u_char  valid:1;
+       } sync[8];
+       u_char  disc_sts;
 };
 
 };
 
-struct aha_config
-{
-       u_char  chan;
-       u_char  intr;
-       u_char  scsi_dev:3;
-       u_char  :5;
+struct aha_config {
+       u_char  chan;
+       u_char  intr;
+       u_char  scsi_dev:3;
+               u_char:5;
 };
 
 struct aha_inquire
 };
 
 struct aha_inquire
@@ -331,58 +276,82 @@ struct    aha_extbios
 #define CHAN6  0x40
 #define CHAN7  0x80
 
 #define CHAN6  0x40
 #define CHAN7  0x80
 
-
 /*********************************** end of board definitions***************/
 
 /*********************************** end of board definitions***************/
 
-
-#ifdef MACH
-#define PHYSTOKV(x)    phystokv(x)
-#define KVTOPHYS(x)    kvtophys(x)
-#else  MACH
-#ifdef __386BSD__
+#define PHYSTOKV(x)    (((long int)(x)) ^ aha->kv_phys_xor)
 #define KVTOPHYS(x)    vtophys(x)
 #define KVTOPHYS(x)    vtophys(x)
-#else  __386BSD__
-#endif __386BSD__
-#endif MACH
 #define        AHA_DMA_PAGES   AHA_NSEG
 
 #define PAGESIZ        4096
 #define INVALIDATE_CACHE {asm volatile( ".byte 0x0F ;.byte 0x08" ); }
 
 #define        AHA_DMA_PAGES   AHA_NSEG
 
 #define PAGESIZ        4096
 #define INVALIDATE_CACHE {asm volatile( ".byte 0x0F ;.byte 0x08" ); }
 
-
-u_char                 aha_scratch_buf[256];
-#ifdef MACH
-caddr_t                        aha_base[NAHA];         /* base port for each board */
-#else
-short                  aha_base[NAHA];         /* base port for each board */
-#endif
-struct aha_mbx         aha_mbx[NAHA];
-struct aha_ccb         *aha_ccb_free[NAHA];
-struct aha_ccb         aha_ccb[NAHA][AHA_MBX_SIZE];
-struct scsi_xfer       aha_scsi_xfer[NAHA];
-struct isa_dev         *ahainfo[NAHA];
-struct aha_ccb         *aha_get_ccb();
-int                    aha_int[NAHA];
-int                    aha_dma[NAHA];
-int                    aha_scsi_dev[NAHA];
-int                    aha_initialized[NAHA];
-#ifdef OSF
-int                    aha_attached[NAHA];
-#endif OSF
+u_char  aha_scratch_buf[256];
 #ifdef AHADEBUG
 #ifdef AHADEBUG
-int                    aha_debug = 1;
-#endif /*AHADEBUG*/
+int     aha_debug = 1;
+#endif /*AHADEBUG */
 
 
-int ahaprobe(), ahaattach(), ahaintr();
-#ifdef MACH
-struct isa_driver      ahadriver = { ahaprobe, 0, ahaattach, "aha", 0, 0, 0};
-int                    (*ahaintrs[])() = {ahaintr, 0};
-#endif
-#ifdef __386BSD__
-struct isa_driver      ahadriver = { ahaprobe, ahaattach, "aha",};
-#endif __386BSD__
-static int             ahaunit = 0;
+struct aha_data {
+       short   aha_base;       /* base port for each board */
+       /*
+        * xor this with a physaddr to get a kv addr and visa versa
+        * for items in THIS STRUCT only. 
+        * Used to get the CCD's physical and kv addresses from each
+        * other.
+        */
+       long int kv_phys_xor;
+       struct aha_mbx aha_mbx; /* all the mailboxes */
+       struct aha_ccb *aha_ccb_free;   /* the next free ccb */
+       struct aha_ccb aha_ccb[AHA_MBX_SIZE];   /* all the CCBs      */
+       int     aha_int;        /* our irq level        */
+       int     aha_dma;        /* out DMA req channel  */
+       int     aha_scsi_dev;   /* ourscsi bus address  */
+       struct scsi_link sc_link;       /* prototype for subdevs */
+} *ahadata[NAHA];
+
+struct aha_ccb *aha_get_ccb();
+int     ahaprobe();
+void   aha_done();
+int     ahaattach();
+int     ahaintr();
+int32   aha_scsi_cmd();
+void   aha_timeout();
+void    ahaminphys();
+u_int32 aha_adapter_info();
+
+#ifdef KERNEL
+struct scsi_adapter aha_switch =
+{
+    aha_scsi_cmd,
+    ahaminphys,
+    0,
+    0,
+    aha_adapter_info,
+    "aha",
+    0, 0
+};
+
+/* the below structure is so we have a default dev struct for out link struct */
+struct scsi_device aha_dev =
+{
+    NULL,                      /* Use default error handler */
+    NULL,                      /* have a queue, served by this */
+    NULL,                      /* have no async handler */
+    NULL,                      /* Use default 'done' routine */
+    "aha",
+    0,
+    0, 0
+};
 
 
+struct isa_driver ahadriver =
+{
+    ahaprobe,
+    ahaattach,
+    "aha"
+};
+
+#endif /* KERNEL */
+
+static int ahaunit = 0;
 
 #define aha_abortmbx(mbx) \
        (mbx)->cmd = AHA_MBO_ABORT; \
 
 #define aha_abortmbx(mbx) \
        (mbx)->cmd = AHA_MBO_ABORT; \
@@ -391,330 +360,307 @@ static int              ahaunit = 0;
        (mbx)->cmd = AHA_MBO_START; \
        outb(AHA_CMD_DATA_PORT, AHA_START_SCSI);
 
        (mbx)->cmd = AHA_MBO_START; \
        outb(AHA_CMD_DATA_PORT, AHA_START_SCSI);
 
+#define AHA_RESET_TIMEOUT      1000    /* time to wait for reset (mSec) */
+#ifndef        KERNEL
+main()
+{
+       printf("size of aha_data is %d\n", sizeof(struct aha_data));
+       printf("size of aha_ccb is %d\n", sizeof(struct aha_ccb));
+       printf("size of aha_mbx is %d\n", sizeof(struct aha_mbx));
+}
 
 
+#else /*KERNEL */
 
 
-int    aha_scsi_cmd();
-int    aha_timeout();
-void   ahaminphys();
-long int       aha_adapter_info();
-
-struct scsi_switch     aha_switch =
-{
-       aha_scsi_cmd,
-       ahaminphys,
-       0,
-       0,
-       aha_adapter_info,
-       "aha",
-       0,0
-};     
-#define AHA_CMD_TIMEOUT_FUDGE  200     /* multiplied to get Secs       */
-#define AHA_RESET_TIMEOUT      1000000 /* time to wait for reset       */
-#define AHA_SCSI_TIMEOUT_FUDGE 20      /* divided by for mSecs         */
-
-
-/***********************************************************************\
-* aha_cmd(unit,icnt, ocnt,wait, retval, opcode, args)                  *
-* Activate Adapter command                                             *
-*      icnt:   number of args (outbound bytes written after opcode)    *
-*      ocnt:   number of expected returned bytes                       *
-*      wait:   number of seconds to wait for response                  *
-*      retval: buffer where to place returned bytes                    *
-*      opcode: opcode AHA_NOP, AHA_MBX_INIT, AHA_START_SCSI ...        *
-*      args:   parameters                                              *
-*                                                                      *
-* Performs an adapter command through the ports. Not to be confused    *
-*      with a scsi command, which is read in via the dma               *
-* One of the adapter commands tells it to read in a scsi command       *
-\***********************************************************************/
-
-
-aha_cmd(unit,icnt, ocnt, wait,retval, opcode, args)
-
-u_char *retval;
-unsigned opcode;
-u_char args;
+/*
+ * aha_cmd(unit,icnt, ocnt,wait, retval, opcode, args)
+ * Activate Adapter command
+ *    icnt:   number of args (outbound bytes written after opcode)
+ *    ocnt:   number of expected returned bytes
+ *    wait:   number of seconds to wait for response
+ *    retval: buffer where to place returned bytes
+ *    opcode: opcode AHA_NOP, AHA_MBX_INIT, AHA_START_SCSI ...
+ *    args:   parameters
+ *
+ * Performs an adapter command through the ports. Not to be confused
+ * with a scsi command, which is read in via the dma.  One of the adapter
+ * commands tells it to read in a scsi command but that one is done
+ * separately.  This is only called during set-up.
+ */
+int
+aha_cmd(unit, icnt, ocnt, wait, retval, opcode, args)
+       u_char *retval;
+       unsigned opcode;
+       u_char  args;
 {
 {
+       struct aha_data *aha = ahadata[unit];
        unsigned *ic = &opcode;
        unsigned *ic = &opcode;
-       u_char oc;
+       u_char  oc;
        register i;
        register i;
-       int     sts;
-
-       /*******************************************************\
-       * multiply the wait argument by a big constant          *
-       * zero defaults to 1                                    *
-       \*******************************************************/
-       if(!wait) 
-               wait = AHA_CMD_TIMEOUT_FUDGE * delaycount; 
+       int     sts;
+
+       /*
+        * multiply the wait argument by a big constant
+        * zero defaults to 1 sec..
+        * all wait loops are in 50uSec cycles
+        */
+       if (wait)
+               wait *= 20000;
        else
        else
-               wait *= AHA_CMD_TIMEOUT_FUDGE * delaycount; 
-       /*******************************************************\
-       * Wait for the adapter to go idle, unless it's one of   *
-       * the commands which don't need this                    *
-       \*******************************************************/
-       if (opcode != AHA_MBX_INIT && opcode != AHA_START_SCSI)
-       {
-               i = AHA_CMD_TIMEOUT_FUDGE * delaycount; /* 1 sec?*/
-               while (--i)
-               {
+               wait = 20000;
+       /*
+        * Wait for the adapter to go idle, unless it's one of
+        * the commands which don't need this
+        */
+       if (opcode != AHA_MBX_INIT && opcode != AHA_START_SCSI) {
+               i = 20000;      /*do this for upto about a second */
+               while (--i) {
                        sts = inb(AHA_CTRL_STAT_PORT);
                        sts = inb(AHA_CTRL_STAT_PORT);
-                       if (sts & AHA_IDLE)
-                       {
+                       if (sts & AHA_IDLE) {
                                break;
                        }
                                break;
                        }
+                       DELAY(50);
                }
                }
-               if (!i)
-               {
+               if (!i) {
                        printf("aha%d: aha_cmd, host not idle(0x%x)\n",
                        printf("aha%d: aha_cmd, host not idle(0x%x)\n",
-                               unit,sts);
-                       return(ENXIO);
+                           unit, sts);
+                       return (ENXIO);
                }
        }
                }
        }
-       /*******************************************************\
-       * Now that it is idle, if we expect output, preflush the*
-       * queue feeding to us.                                  *
-       \*******************************************************/
-       if (ocnt)
-       {
-               while((inb(AHA_CTRL_STAT_PORT)) & AHA_DF)
+       /*
+        * Now that it is idle, if we expect output, preflush the
+        * queue feeding to us.
+        */
+       if (ocnt) {
+               while ((inb(AHA_CTRL_STAT_PORT)) & AHA_DF)
                        inb(AHA_CMD_DATA_PORT);
        }
                        inb(AHA_CMD_DATA_PORT);
        }
-                       
-       /*******************************************************\
-       * Output the command and the number of arguments given  *
-       * for each byte, first check the port is empty.         *
-       \*******************************************************/
-       icnt++;         /* include the command */
-       while (icnt--)
-       {
+       /*
+        * Output the command and the number of arguments given
+        * for each byte, first check the port is empty.
+        */
+       icnt++;
+       /* include the command */
+       while (icnt--) {
                sts = inb(AHA_CTRL_STAT_PORT);
                sts = inb(AHA_CTRL_STAT_PORT);
-               for (i=0; i< wait; i++)
-               {
+               for (i = wait; i; i--) {
                        sts = inb(AHA_CTRL_STAT_PORT);
                        if (!(sts & AHA_CDF))
                                break;
                        sts = inb(AHA_CTRL_STAT_PORT);
                        if (!(sts & AHA_CDF))
                                break;
+                       DELAY(50);
                }
                }
-               if (i >=  wait)
-               {
-                       printf("aha%d: aha_cmd, cmd/data port full\n",unit);
-                       outb(AHA_CTRL_STAT_PORT, AHA_SRST); 
-                       return(ENXIO);
+               if (i == 0) {
+                       printf("aha%d: aha_cmd, cmd/data port full\n", unit);
+                       outb(AHA_CTRL_STAT_PORT, AHA_SRST);
+                       return (ENXIO);
                }
                }
-               outb(AHA_CMD_DATA_PORT, (u_char)(*ic++));
+               outb(AHA_CMD_DATA_PORT, (u_char) (*ic++));
        }
        }
-       /*******************************************************\
-       * If we expect input, loop that many times, each time,  *
-       * looking for the data register to have valid data      *
-       \*******************************************************/
-       while (ocnt--)
-       {
+       /*
+        * If we expect input, loop that many times, each time,
+        * looking for the data register to have valid data
+        */
+       while (ocnt--) {
                sts = inb(AHA_CTRL_STAT_PORT);
                sts = inb(AHA_CTRL_STAT_PORT);
-               for (i=0; i< wait; i++)
-               {
+               for (i = wait; i; i--) {
                        sts = inb(AHA_CTRL_STAT_PORT);
                        sts = inb(AHA_CTRL_STAT_PORT);
-                       if (sts  & AHA_DF)
+                       if (sts & AHA_DF)
                                break;
                                break;
+                       DELAY(50);
                }
                }
-               if (i >=  wait)
-               {
+               if (i == 0) {
                        printf("aha%d: aha_cmd, cmd/data port empty %d\n",
                        printf("aha%d: aha_cmd, cmd/data port empty %d\n",
-                               unit,ocnt);
-                       return(ENXIO);
+                           unit, ocnt);
+                       return (ENXIO);
                }
                oc = inb(AHA_CMD_DATA_PORT);
                if (retval)
                        *retval++ = oc;
        }
                }
                oc = inb(AHA_CMD_DATA_PORT);
                if (retval)
                        *retval++ = oc;
        }
-       /*******************************************************\
-       * Wait for the board to report a finised instruction    *
-       \*******************************************************/
-       i=AHA_CMD_TIMEOUT_FUDGE * delaycount;   /* 1 sec? */
-       while (--i)
-       {
+       /*
+        * Wait for the board to report a finised instruction
+        */
+       i = 20000;
+       while (--i) {
                sts = inb(AHA_INTR_PORT);
                sts = inb(AHA_INTR_PORT);
-               if (sts & AHA_HACC)
-               {
+               if (sts & AHA_HACC) {
                        break;
                }
                        break;
                }
+               DELAY(50);
        }
        }
-       if (!i)
-       {
-               printf("aha%d: aha_cmd, host not finished(0x%x)\n",unit,sts);
-               return(ENXIO);
+       if (i == 0) {
+               printf("aha%d: aha_cmd, host not finished(0x%x)\n", unit, sts);
+               return (ENXIO);
        }
        outb(AHA_CTRL_STAT_PORT, AHA_IRST);
        }
        outb(AHA_CTRL_STAT_PORT, AHA_IRST);
-       return(0);
+       return 0;
 }
 
 }
 
-/*******************************************************\
-* Check if the device can be found at the port given   *
-* and if so, set it up ready for further work          *
-* as an argument, takes the isa_dev structure from     *
-* autoconf.c                                           *
-\*******************************************************/
+/*
+ * Check if the device can be found at the port given
+ * and if so, set it up ready for further work
+ * as an argument, takes the isa_device structure from
+ * autoconf.c
+ */
+int
 ahaprobe(dev)
 ahaprobe(dev)
-struct isa_dev *dev;
+       struct isa_device *dev;
 {
 {
-       int     unit = ahaunit;
-#if defined(OSF)
-       static ihandler_t aha_handler[NAHA];
-       static ihandler_id_t *aha_handler_id[NAHA];
-       register ihandler_t *chp = &aha_handler[unit];;
-#endif /* defined(OSF) */
-
-       /***********************************************\
-       * find unit and check we have that many defined *
-       \***********************************************/
-       dev->dev_unit = unit;
-       aha_base[unit] = dev->dev_addr;
-       if(unit >= NAHA) 
-       {
-               printf("aha%d: unit number too high\n",unit);
-               return(0);
+       int     unit = ahaunit;
+       struct aha_data *aha;
+
+       /*
+        * find unit and check we have that many defined
+        */
+       if (unit >= NAHA) {
+               printf("aha%d: unit number too high\n", unit);
+               return 0;
        }
        }
-       /***********************************************\
-       * Try initialise a unit at this location        *
-       * sets up dma and bus speed, loads aha_int[unit]*
-       \***********************************************/
-       if (aha_init(unit) != 0)
-       {
-               return(0);
+       dev->id_unit = unit;
+
+       /*
+        * a quick safety check so we can be sleazy later
+        */
+       if (sizeof(struct aha_data) > PAGESIZ) {
+               printf("aha struct > pagesize\n");
+               return 0;
        }
        }
+       /*
+        * Allocate a storage area for us
+        */
+       if (ahadata[unit]) {
+               printf("aha%d: memory already allocated\n", unit);
+               return 0;
+       }
+       aha = malloc(sizeof(struct aha_data), M_TEMP, M_NOWAIT);
+       if (!aha) {
+               printf("aha%d: cannot malloc!\n", unit);
+               return 0;
+       }
+       ahadata[unit] = aha;
+       aha->aha_base = dev->id_iobase;
+       /*
+        * Try initialise a unit at this location
+        * sets up dma and bus speed, loads aha->aha_int
+        */
+       if (aha_init(unit) != 0) {
+               ahadata[unit] = NULL;
+               free(aha, M_TEMP);
+               return 0;
+       }
+       /*
+        * Calculate the xor product of the aha struct's
+        * physical and virtual address. This allows us
+        * to change addresses within the structure
+        * from physical to virtual easily, as long as
+        * the structure is less than 1 page in size.
+        * This is used to recognise CCBs which are in 
+        * this struct and which are refered to by the
+        * hardware using physical addresses.
+        * (assumes malloc returns a chunk that doesn't
+        * span pages)
+        * eventually use the hash table in aha1742.c
+        */
+       aha->kv_phys_xor = (long int) aha ^ (KVTOPHYS(aha));
 
 
-       /***********************************************\
-       * If it's there, put in it's interrupt vectors  *
-       \***********************************************/
-#if !defined(OSF)
-#if    defined MACH
-       iunit[aha_int[unit]] =unit;
-       ivect[aha_int[unit]] = ahaintr;
-       intpri[aha_int[unit]] = dev->dev_spl;
-       form_pic_mask();
-       /*take_dev_irq(dev);*/
-#else
-#ifdef __386BSD__
-       dev->id_irq = (1 << aha_int[unit]);
-       dev->id_drq = aha_dma[unit];
-#endif __386BSD__
-#endif
-#else /* !defined(OSF) */
-       dev->dev_pic = aha_dma[unit];
-       chp->ih_level = dev->dev_pic;
-       chp->ih_handler = dev->dev_intr[0];
-       chp->ih_resolver = i386_resolver;
-       chp->ih_rdev = dev;
-       chp->ih_stats.intr_type = INTR_DEVICE;
-       chp->ih_stats.intr_cnt = 0;
-       chp->ih_hparam[0].intparam = unit;
-       if ((aha_handler_id[unit] = handler_add(chp)) != NULL)
-               handler_enable(aha_handler_id[unit]);
-       else
-               panic("Unable to add aha interrupt handler");
-#endif /* !defined(OSF) */
-#ifndef        __386BSD__
-       printf("port=%x spl=%d\n", dev->dev_addr, dev->dev_spl);
-#endif __386BSD__
-       ahaunit ++;
-       return(1);
+       /*
+        * If it's there, put in it's interrupt vectors
+        */
+       dev->id_irq = (1 << aha->aha_int);
+       dev->id_drq = aha->aha_dma;
+       ahaunit++;
+       return 0x4;
 }
 
 }
 
-/***********************************************\
-* Attach all the sub-devices we can find       *
-\***********************************************/
+/*
+ * Attach all the sub-devices we can find
+ */
+int
 ahaattach(dev)
 ahaattach(dev)
-struct isa_dev *dev;
+       struct isa_device *dev;
 {
 {
-       int     unit = dev->dev_unit;
-
-       /***********************************************\
-       * ask the adapter what subunits are present     *
-       \***********************************************/
-       scsi_attachdevs( unit, aha_scsi_dev[unit], &aha_switch);
-#if defined(OSF)
-       aha_attached[unit]=1;
-#endif /* defined(OSF) */
-       return;
+       int     unit = dev->id_unit;
+       struct aha_data *aha = ahadata[unit];
+
+       /*
+        * fill in the prototype scsi_link.
+        */
+       aha->sc_link.adapter_unit = unit;
+       aha->sc_link.adapter_targ = aha->aha_scsi_dev;
+       aha->sc_link.adapter = &aha_switch;
+       aha->sc_link.device = &aha_dev;
+
+       /*
+        * ask the adapter what subunits are present
+        */
+       scsi_attachdevs(&(aha->sc_link));
+
+       return 1;
 }
 
 }
 
-/***********************************************\
-* Return some information to the caller about  *
-* the adapter and it's capabilities            *
-\***********************************************/
-long int aha_adapter_info(unit)
-int    unit;
+/*
+ * Return some information to the caller about the adapter and its
+ * capabilities.
+ */
+u_int32 
+aha_adapter_info(unit)
+       int     unit;
 {
 {
-       return(2);      /* 2 outstanding requests at a time per device */
+       return (2);             /* 2 outstanding requests at a time per device */
 }
 
 }
 
-/***********************************************\
-* Catch an interrupt from the adaptor          *
-\***********************************************/
+/*
+ * Catch an interrupt from the adaptor
+ */
+int
 ahaintr(unit)
 {
        struct aha_ccb *ccb;
        unsigned char stat;
        register i;
 ahaintr(unit)
 {
        struct aha_ccb *ccb;
        unsigned char stat;
        register i;
+       struct aha_data *aha = ahadata[unit];
 
 #ifdef AHADEBUG
 
 #ifdef AHADEBUG
-       if(scsi_debug & PRINTROUTINES)
-               printf("ahaintr ");
-#endif /*AHADEBUG*/
-       /***********************************************\
-       * First acknowlege the interrupt, Then if it's  *
-       * not telling about a completed operation       *
-       * just return.                                  *
-       \***********************************************/
+       printf("ahaintr ");
+#endif /*AHADEBUG */
+       /*
+        * First acknowlege the interrupt, Then if it's not telling about
+        * a completed operation just return. 
+        */
        stat = inb(AHA_INTR_PORT);
        outb(AHA_CTRL_STAT_PORT, AHA_IRST);
        stat = inb(AHA_INTR_PORT);
        outb(AHA_CTRL_STAT_PORT, AHA_IRST);
+       if (!(stat & AHA_MBIF))
+               return 1;
 #ifdef AHADEBUG
 #ifdef AHADEBUG
-       if(scsi_debug & TRACEINTERRUPTS)
-               printf("int ");
-#endif /*AHADEBUG*/
-       if (! (stat & AHA_MBIF))
-               return(1);
-#ifdef AHADEBUG
-       if(scsi_debug & TRACEINTERRUPTS)
-               printf("b ");
-#endif /*AHADEBUG*/
-#if defined(OSF)
-       if (!aha_attached[unit])
-       {
-               return(1);
-       }
-#endif /* defined(OSF) */
-       /***********************************************\
-       * If it IS then process the competed operation  *
-       \***********************************************/
-       for (i = 0; i < AHA_MBX_SIZE; i++)
-       {
-               if (aha_mbx[unit].mbi[i].stat != AHA_MBI_FREE) 
-               {
-                       ccb = (struct aha_ccb *)PHYSTOKV(
-                               (_3btol(aha_mbx[unit].mbi[i].ccb_addr)));
-
-                       if((stat =  aha_mbx[unit].mbi[i].stat) != AHA_MBI_OK)
-                       {
-                               switch(stat)
-                               {
-                               case    AHA_MBI_ABORT:
+       printf("mbxin ");
+#endif /*AHADEBUG */
+       /*
+        * If it IS then process the competed operation
+        */
+       for (i = 0; i < AHA_MBX_SIZE; i++) {
+               if (aha->aha_mbx.mbi[i].stat != AHA_MBI_FREE) {
+                       ccb = (struct aha_ccb *) PHYSTOKV(
+                           (_3btol(aha->aha_mbx.mbi[i].ccb_addr)));
+
+                       if ((stat = aha->aha_mbx.mbi[i].stat) != AHA_MBI_OK) {
+                               switch (stat) {
+                               case AHA_MBI_ABORT:
 #ifdef AHADEBUG
 #ifdef AHADEBUG
-                                       if(aha_debug)
-                                           printf("abort");
-#endif /*AHADEBUG*/
+                                       if (aha_debug)
+                                               printf("abort");
+#endif /*AHADEBUG */
                                        ccb->host_stat = AHA_ABORTED;
                                        break;
 
                                        ccb->host_stat = AHA_ABORTED;
                                        break;
 
-                               case    AHA_MBI_UNKNOWN:
-                                       ccb = (struct aha_ccb *)0;
+                               case AHA_MBI_UNKNOWN:
+                                       ccb = (struct aha_ccb *) 0;
 #ifdef AHADEBUG
 #ifdef AHADEBUG
-                                       if(aha_debug)
-                                            printf("unknown ccb for abort ");
-#endif /*AHADEBUG*/
+                                       if (aha_debug)
+                                               printf("unknown ccb for abort ");
+#endif /*AHADEBUG */
                                        /* may have missed it */
                                        /* no such ccb known for abort */
 
                                        /* may have missed it */
                                        /* no such ccb known for abort */
 
-                               case    AHA_MBI_ERROR:
+                               case AHA_MBI_ERROR:
                                        break;
 
                                default:
                                        break;
 
                                default:
@@ -722,214 +668,191 @@ ahaintr(unit)
 
                                }
 #ifdef AHADEBUG
 
                                }
 #ifdef AHADEBUG
-                               if( aha_debug && ccb )
-                               {
-                                       u_char  *cp;
-                                       cp = (u_char *)(&(ccb->scsi_cmd));
-                                       printf("op=%x %x %x %x %x %x\n", 
-                                               cp[0], cp[1], cp[2],
-                                               cp[3], cp[4], cp[5]);
+                                if (aha_debug && ccb) {
+                                       u_char *cp;
+                                       cp = (u_char *) (&(ccb->scsi_cmd));
+                                       printf("op=%x %x %x %x %x %x\n",
+                                           cp[0], cp[1], cp[2],
+                                           cp[3], cp[4], cp[5]);
                                        printf("stat %x for mbi[%d]\n"
                                        printf("stat %x for mbi[%d]\n"
-                                               , aha_mbx[unit].mbi[i].stat, i);
+                                           ,aha->aha_mbx.mbi[i].stat, i);
                                        printf("addr = 0x%x\n", ccb);
                                }
                                        printf("addr = 0x%x\n", ccb);
                                }
-#endif /*AHADEBUG*/
+#endif /*AHADEBUG */
                        }
                        }
-                       if(ccb)
-                       {
-                               untimeout(aha_timeout,ccb);
-                               aha_done(unit,ccb);
+                       if (ccb) {
+                               untimeout(aha_timeout, ccb);
+                               aha_done(unit, ccb);
                        }
                        }
-                       aha_mbx[unit].mbi[i].stat = AHA_MBI_FREE;
+                       aha->aha_mbx.mbi[i].stat = AHA_MBI_FREE;
                }
        }
                }
        }
-       return(1);
+       return 1;
 }
 
 }
 
-/***********************************************\
-* A ccb (and hence a mbx-out is put onto the   *
-* free list.                                   *
-\***********************************************/
-aha_free_ccb(unit,ccb, flags)
-struct aha_ccb *ccb;
+/*
+ * A ccb (and hence a mbx-out is put onto the 
+ * free list.
+ */
+void
+aha_free_ccb(unit, ccb, flags)
+       struct aha_ccb *ccb;
 {
 {
+       struct aha_data *aha = ahadata[unit];
        unsigned int opri;
        unsigned int opri;
-       
-#ifdef AHADEBUG
-       if(scsi_debug & PRINTROUTINES)
-               printf("ccb%d(0x%x)> ",unit,flags);
-#endif /*AHADEBUG*/
-       if (!(flags & SCSI_NOMASK)) 
-               opri = splbio();
-
-       ccb->next = aha_ccb_free[unit];
-       aha_ccb_free[unit] = ccb;
+
+       if (!(flags & SCSI_NOMASK))
+               opri = splbio();
+
+       ccb->next = aha->aha_ccb_free;
+       aha->aha_ccb_free = ccb;
        ccb->flags = CCB_FREE;
        ccb->flags = CCB_FREE;
-       /***********************************************\
-       * If there were none, wake abybody waiting for  *
-       * one to come free, starting with queued entries*
-       \***********************************************/
+       /*
+        * If there were none, wake anybody waiting for
+        * one to come free, starting with queued entries
+        */
        if (!ccb->next) {
        if (!ccb->next) {
-               wakeup(&aha_ccb_free[unit]);
+               wakeup(&aha->aha_ccb_free);
        }
        }
-       if (!(flags & SCSI_NOMASK)) 
+       if (!(flags & SCSI_NOMASK))
                splx(opri);
 }
 
                splx(opri);
 }
 
-/***********************************************\
-* Get a free ccb (and hence mbox-out entry)    *
-\***********************************************/
+/*
+ * Get a free ccb (and hence mbox-out entry)
+ */
 struct aha_ccb *
 struct aha_ccb *
-aha_get_ccb(unit,flags)
+aha_get_ccb(unit, flags)
 {
 {
+       struct aha_data *aha = ahadata[unit];
        unsigned opri;
        struct aha_ccb *rc;
 
        unsigned opri;
        struct aha_ccb *rc;
 
-#ifdef AHADEBUG
-       if(scsi_debug & PRINTROUTINES)
-               printf("<ccb%d(0x%x) ",unit,flags);
-#endif /*AHADEBUG*/
-       if (!(flags & SCSI_NOMASK)) 
-               opri = splbio();
-       /***********************************************\
-       * If we can and have to, sleep waiting for one  *
-       * to come free                                  *
-       \***********************************************/
-       while ((!(rc = aha_ccb_free[unit])) && (!(flags & SCSI_NOSLEEP)))
-       {
-               sleep(&aha_ccb_free[unit], PRIBIO);
+       if (!(flags & SCSI_NOMASK))
+               opri = splbio();
+       /*
+        * If we can and have to, sleep waiting for one
+        * to come free
+        */
+       while ((!(rc = aha->aha_ccb_free)) && (!(flags & SCSI_NOSLEEP))) {
+               sleep(&aha->aha_ccb_free, PRIBIO);
        }
        }
-       if (rc) 
-       {
-               aha_ccb_free[unit] = aha_ccb_free[unit]->next;
+       if (rc) {
+               aha->aha_ccb_free = aha->aha_ccb_free->next;
                rc->flags = CCB_ACTIVE;
        }
                rc->flags = CCB_ACTIVE;
        }
-       if (!(flags & SCSI_NOMASK)) 
+       if (!(flags & SCSI_NOMASK))
                splx(opri);
                splx(opri);
-       return(rc);
+       return (rc);
 }
 }
-               
-
-/***********************************************\
-* We have a ccb which has been processed by the        *
-* adaptor, now we look to see how the operation        *
-* went. Wake up the owner if waiting           *
-\***********************************************/
-aha_done(unit,ccb)
-struct aha_ccb *ccb;
+
+/*
+ * We have a ccb which has been processed by the
+ * adaptor, now we look to see how the operation
+ * went. Wake up the owner if waiting
+ */
+void
+aha_done(unit, ccb)
+       int     unit;
+       struct  aha_ccb *ccb;
 {
 {
-       struct  scsi_sense_data *s1,*s2;
-       struct  scsi_xfer *xs = ccb->xfer;
+       struct aha_data *aha = ahadata[unit];
+       struct scsi_sense_data *s1, *s2;
+       struct scsi_xfer *xs = ccb->xfer;
 
 
-#ifdef AHADEBUG
-       if(scsi_debug & PRINTROUTINES )
-               printf("aha_done ");
-#endif /*AHADEBUG*/
-       /***********************************************\
-       * Otherwise, put the results of the operation   *
-       * into the xfer and call whoever started it     *
-       \***********************************************/
-       if(!(xs->flags & INUSE))
-       {
-               printf("aha%d: exiting but not in use!\n",unit);
+       SC_DEBUG(xs->sc_link, SDEV_DB2, ("aha_done\n"));
+       /*
+        * Otherwise, put the results of the operation
+        * into the xfer and call whoever started it
+        */
+       if (!(xs->flags & INUSE)) {
+               printf("aha%d: exiting but not in use!\n", unit);
                Debugger();
        }
                Debugger();
        }
-       if (    (       ccb->host_stat != AHA_OK 
-                       || ccb->target_stat != SCSI_OK)
-             && (!(xs->flags & SCSI_ERR_OK)))
-       {
-               s1 = (struct scsi_sense_data *)(((char *)(&ccb->scsi_cmd)) 
-                               + ccb->scsi_cmd_length);
+       if (((ccb->host_stat != AHA_OK) || (ccb->target_stat != SCSI_OK))
+           && ((xs->flags & SCSI_ERR_OK) == 0)) {
+               /*
+                * We have an error, that we cannot ignore.
+                */
+               s1 = (struct scsi_sense_data *) (((char *) (&ccb->scsi_cmd))
+                   + ccb->scsi_cmd_length);
                s2 = &(xs->sense);
 
                s2 = &(xs->sense);
 
-               if(ccb->host_stat)
-               {
-                       switch(ccb->host_stat)
-                       {
-                       case    AHA_ABORTED:
-                       case    AHA_SEL_TIMEOUT:        /* No response */
+               if (ccb->host_stat) {
+                       SC_DEBUG(xs->sc_link, SDEV_DB3, ("host err 0x%x\n",
+                               ccb->host_stat));
+                       switch (ccb->host_stat) {
+                       case AHA_ABORTED:
+                       case AHA_SEL_TIMEOUT:   /* No response */
                                xs->error = XS_TIMEOUT;
                                break;
                        default:        /* Other scsi protocol messes */
                                xs->error = XS_DRIVER_STUFFUP;
                                xs->error = XS_TIMEOUT;
                                break;
                        default:        /* Other scsi protocol messes */
                                xs->error = XS_DRIVER_STUFFUP;
-#ifdef AHADEBUG
-                               if (aha_debug > 1)
-                               {
-                                       printf("host_stat%x\n",
-                                               ccb->host_stat);
-                               }
-#endif /*AHADEBUG*/
+                               printf("aha%d:host_stat%x\n",
+                                   unit, ccb->host_stat);
                        }
                        }
-
-               }
-               else
-               {
-                       switch(ccb->target_stat)
-                       {
+               } else {
+                       SC_DEBUG(xs->sc_link, SDEV_DB3, ("target err 0x%x\n",
+                               ccb->target_stat));
+                       switch (ccb->target_stat) {
                        case 0x02:
                        case 0x02:
-                               /* structure copy!!!!!*/
-                               *s2=*s1;
+                               /* structure copy!!!!! */
+                               *s2 = *s1;
                                xs->error = XS_SENSE;
                                break;
                        case 0x08:
                                xs->error = XS_BUSY;
                                break;
                        default:
                                xs->error = XS_SENSE;
                                break;
                        case 0x08:
                                xs->error = XS_BUSY;
                                break;
                        default:
-#ifdef AHADEBUG
-                               if (aha_debug > 1)
-                               {
-                                       printf("target_stat%x\n",
-                                               ccb->target_stat);
-                               }
-#endif /*AHADEBUG*/
+                               printf("aha%d:target_stat%x\n",
+                                   unit, ccb->target_stat);
                                xs->error = XS_DRIVER_STUFFUP;
                        }
                }
                                xs->error = XS_DRIVER_STUFFUP;
                        }
                }
-       }
-       else            /* All went correctly  OR errors expected */
-       {
+       } else {
+               /* All went correctly  OR errors expected */
                xs->resid = 0;
        }
        xs->flags |= ITSDONE;
                xs->resid = 0;
        }
        xs->flags |= ITSDONE;
-       aha_free_ccb(unit,ccb, xs->flags);
-       if(xs->when_done)
-               (*(xs->when_done))(xs->done_arg,xs->done_arg2);
+       aha_free_ccb(unit, ccb, xs->flags);
+       scsi_done(xs);
 }
 
 }
 
-
-/***********************************************\
-* Start the board, ready for normal operation  *
-\***********************************************/
+/*
+ * Start the board, ready for normal operation
+ */
+int
 aha_init(unit)
 aha_init(unit)
-int    unit;
+       int     unit;
 {
 {
+       struct aha_data *aha = ahadata[unit];
        unsigned char ad[3];
        unsigned char ad[3];
-       volatile int i,sts;
+       volatile int i, sts;
        struct  aha_config conf;
        struct  aha_inquire inquire;
        struct  aha_extbios extbios;
 
        struct  aha_config conf;
        struct  aha_inquire inquire;
        struct  aha_extbios extbios;
 
-       /***********************************************\
-       * reset board, If it doesn't respond, assume    *
-       * that it's not there.. good for the probe      *
-       \***********************************************/
+       /*
+        * reset board, If it doesn't respond, assume 
+        * that it's not there.. good for the probe
+        */
 
 
-       outb(AHA_CTRL_STAT_PORT, AHA_HRST|AHA_SRST);
+       outb(AHA_CTRL_STAT_PORT, AHA_HRST | AHA_SRST);
 
 
-       for (i=0; i < AHA_RESET_TIMEOUT; i++)
-       {
-               sts = inb(AHA_CTRL_STAT_PORT) ;
-               if ( sts == (AHA_IDLE | AHA_INIT))
+       for (i = AHA_RESET_TIMEOUT; i; i--) {
+               sts = inb(AHA_CTRL_STAT_PORT);
+               if (sts == (AHA_IDLE | AHA_INIT))
                        break;
                        break;
+               DELAY(1000);    /* calibrated in msec */
        }
        }
-       if (i >= AHA_RESET_TIMEOUT)
-       {
+       if (i == 0) {
 #ifdef AHADEBUG
                if (aha_debug)
                        printf("aha_init: No answer from adaptec board\n");
 #ifdef AHADEBUG
                if (aha_debug)
                        printf("aha_init: No answer from adaptec board\n");
-#endif /*AHADEBUG*/
-               return(ENXIO);
+#endif /*AHADEBUG */
+               return (ENXIO);
        }
        }
+
        /*
         * Assume we have a board at this stage, do an adapter inquire
         * to find out what type of controller it is
        /*
         * Assume we have a board at this stage, do an adapter inquire
         * to find out what type of controller it is
@@ -967,514 +890,399 @@ int     unit;
                aha_cmd(unit, 2, 0, 0, 0, AHA_MBX_ENABLE,
                        0, extbios.mailboxlock);
        }
                aha_cmd(unit, 2, 0, 0, 0, AHA_MBX_ENABLE,
                        0, extbios.mailboxlock);
        }
-       /***********************************************\
-       * Setup dma channel from jumpers and save int   *
-       * level                                         *
-       \***********************************************/
-#ifdef __386BSD__
-       printf("aha%d: reading board settings, ",unit);
-#define        PRNT(x) printf(x)
-#else  __386BSD__
-       printf("aha%d:",unit);
+
+       /*
+        * setup dma channel from jumpers and save int
+        * level
+        */
+       printf("aha%d: reading board settings, ", unit);
 #define        PRNT(x) printf(x)
 #define        PRNT(x) printf(x)
-#endif __386BSD__
-       DELAY(10000);   /* for Bustek 545 */
-       aha_cmd(unit,0, sizeof(conf), 0 ,&conf, AHA_CONF_GET);
-       switch(conf.chan)
-       {
-       case    CHAN0:
+       DELAY(1000);            /* for Bustek 545 */
+       aha_cmd(unit, 0, sizeof(conf), 0, &conf, AHA_CONF_GET);
+       switch (conf.chan) {
+       case CHAN0:
                outb(0x0b, 0x0c);
                outb(0x0a, 0x00);
                outb(0x0b, 0x0c);
                outb(0x0a, 0x00);
-               aha_dma[unit] = 0;
+               aha->aha_dma = 0;
                PRNT("dma=0 ");
                break;
                PRNT("dma=0 ");
                break;
-       case    CHAN5:
+       case CHAN5:
                outb(0xd6, 0xc1);
                outb(0xd4, 0x01);
                outb(0xd6, 0xc1);
                outb(0xd4, 0x01);
-               aha_dma[unit] = 5;
+               aha->aha_dma = 5;
                PRNT("dma=5 ");
                break;
                PRNT("dma=5 ");
                break;
-       case    CHAN6:
+       case CHAN6:
                outb(0xd6, 0xc2);
                outb(0xd4, 0x02);
                outb(0xd6, 0xc2);
                outb(0xd4, 0x02);
-               aha_dma[unit] = 6;
+               aha->aha_dma = 6;
                PRNT("dma=6 ");
                break;
                PRNT("dma=6 ");
                break;
-       case    CHAN7:
+       case CHAN7:
                outb(0xd6, 0xc3);
                outb(0xd4, 0x03);
                outb(0xd6, 0xc3);
                outb(0xd4, 0x03);
-               aha_dma[unit] = 7;
+               aha->aha_dma = 7;
                PRNT("dma=7 ");
                break;
        default:
                printf("illegal dma jumper setting\n");
                PRNT("dma=7 ");
                break;
        default:
                printf("illegal dma jumper setting\n");
-               return(EIO);
+               return (EIO);
        }
        }
-       switch(conf.intr)
-       {
-       case    INT9:
-               aha_int[unit] = 9;
+       switch (conf.intr) {
+       case INT9:
+               aha->aha_int = 9;
                PRNT("int=9 ");
                break;
                PRNT("int=9 ");
                break;
-       case    INT10:
-               aha_int[unit] = 10;
+       case INT10:
+               aha->aha_int = 10;
                PRNT("int=10 ");
                break;
                PRNT("int=10 ");
                break;
-       case    INT11:
-               aha_int[unit] = 11;
+       case INT11:
+               aha->aha_int = 11;
                PRNT("int=11 ");
                break;
                PRNT("int=11 ");
                break;
-       case    INT12:
-               aha_int[unit] = 12;
+       case INT12:
+               aha->aha_int = 12;
                PRNT("int=12 ");
                break;
                PRNT("int=12 ");
                break;
-       case    INT14:
-               aha_int[unit] = 14;
+       case INT14:
+               aha->aha_int = 14;
                PRNT("int=14 ");
                break;
                PRNT("int=14 ");
                break;
-       case    INT15:
-               aha_int[unit] = 15;
+       case INT15:
+               aha->aha_int = 15;
                PRNT("int=15 ");
                break;
        default:
                printf("illegal int jumper setting\n");
                PRNT("int=15 ");
                break;
        default:
                printf("illegal int jumper setting\n");
-               return(EIO);
+               return (EIO);
        }
        }
-       /* who are we on the scsi bus */
-       aha_scsi_dev[unit] = conf.scsi_dev;
 
 
+       /* who are we on the scsi bus? */
+       aha->aha_scsi_dev = conf.scsi_dev;
 
 
-       /***********************************************\
-       * Initialize memory transfer speed              *
-       \***********************************************/
-/*
- * XXX This code seems to BREAK more boards than it makes
- * work right, we are just going to NOP this here...
- */ 
-#if 0
-       if(!(aha_set_bus_speed(unit)))
-       {
-               return(EIO);
+       /*
+        * Change the bus on/off times to not clash with other dma users.
+        */
+       aha_cmd(unit, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7);
+       aha_cmd(unit, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4);
+
+#ifdef TUNE_1542
+       /*
+        * Initialize memory transfer speed
+        * Not compiled in by default because it breaks some machines 
+        */
+       if (!(aha_set_bus_speed(unit))) {
+               return (EIO);
        }
 #else
        printf ("\n");
        }
 #else
        printf ("\n");
-#endif
-       
+#endif /*TUNE_1542*/
+       /*
+        * Initialize mail box 
+        */
+       lto3b(KVTOPHYS(&aha->aha_mbx), ad);
 
 
-       /***********************************************\
-       * Initialize mail box                           *
-       \***********************************************/
-
-       lto3b(KVTOPHYS(&aha_mbx[unit]), ad);
-
-       aha_cmd(unit,4, 0, 0, 0, AHA_MBX_INIT,
-                       AHA_MBX_SIZE,
-                       ad[0],
-                       ad[1],
-                       ad[2]);
-
-
-       /***********************************************\
-       * link the ccb's with the mbox-out entries and  *
-       * into a free-list                              *
-       \***********************************************/
-       for (i=0; i < AHA_MBX_SIZE; i++) {
-               aha_ccb[unit][i].next = aha_ccb_free[unit];
-               aha_ccb_free[unit] = &aha_ccb[unit][i];
-               aha_ccb_free[unit]->flags = CCB_FREE;
-               aha_ccb_free[unit]->mbx = &aha_mbx[unit].mbo[i];
-               lto3b(KVTOPHYS(aha_ccb_free[unit]), aha_mbx[unit].mbo[i].ccb_addr);
-       }
+       aha_cmd(unit, 4, 0, 0, 0, AHA_MBX_INIT,
+           AHA_MBX_SIZE,
+           ad[0],
+           ad[1],
+           ad[2]);
 
 
-       /***********************************************\
-       * Note that we are going and return (to probe)  *
-       \***********************************************/
-       aha_initialized[unit]++;
-       return(0);
+       /*
+        * link the ccb's with the mbox-out entries and
+        * into a free-list
+        * this is a kludge but it works
+        */
+       for (i = 0; i < AHA_MBX_SIZE; i++) {
+               aha->aha_ccb[i].next = aha->aha_ccb_free;
+               aha->aha_ccb_free = &aha->aha_ccb[i];
+               aha->aha_ccb_free->flags = CCB_FREE;
+               aha->aha_ccb_free->mbx = &aha->aha_mbx.mbo[i];
+               lto3b(KVTOPHYS(aha->aha_ccb_free), aha->aha_mbx.mbo[i].ccb_addr);
+       }
+       /*
+        * Note that we are going and return (to probe)
+        */
+       return 0;
 }
 
 }
 
-
-
-
-
-void ahaminphys(bp)
-struct buf *bp;
+void 
+ahaminphys(bp)
+       struct buf *bp;
 {
 {
-#ifdef MACH
-#if !defined(OSF)
-       bp->b_flags |= B_NPAGES;                /* can support scat/gather */
-#endif /* !defined(OSF) */
-#endif MACH
-/*     aha seems to explode with 17 segs (64k may require 17 segs) */
-/*     on old boards so use a max of 16 segs if you have problems here*/
-       if(bp->b_bcount > ((AHA_NSEG - 1) * PAGESIZ))
-       {
+/*      aha seems to explode with 17 segs (64k may require 17 segs) */
+/*      on old boards so use a max of 16 segs if you have problems here */
+       if (bp->b_bcount > ((AHA_NSEG - 1) * PAGESIZ)) {
                bp->b_bcount = ((AHA_NSEG - 1) * PAGESIZ);
        }
 }
                bp->b_bcount = ((AHA_NSEG - 1) * PAGESIZ);
        }
 }
-       
-/***********************************************\
-* start a scsi operation given the command and *
-* the data address. Also needs the unit, target        *
-* and lu                                       *
-\***********************************************/
-int    aha_scsi_cmd(xs)
-struct scsi_xfer *xs;
+
+/*
+ * start a scsi operation given the command and
+ * the data address. Also needs the unit, target
+ * and lu
+ */
+int32 
+aha_scsi_cmd(xs)
+       struct scsi_xfer *xs;
 {
 {
-       struct  scsi_sense_data *s1,*s2;
+       struct scsi_link *sc_link = xs->sc_link;
+       int     unit = sc_link->adapter_unit;
+       struct aha_data *aha = ahadata[unit];
+       struct scsi_sense_data *s1, *s2;
        struct aha_ccb *ccb;
        struct aha_scat_gath *sg;
        struct aha_ccb *ccb;
        struct aha_scat_gath *sg;
-       int     seg;    /* scatter gather seg being worked on */
-       int i   = 0;
-       int rc  =  0;
-       int     thiskv;
-       int     thisphys,nextphys;
-       int     unit =xs->adapter;
-       int     bytes_this_seg,bytes_this_page,datalen,flags;
-       struct  iovec   *iovp;
-       int     s;
-
-#ifdef AHADEBUG
-       if(scsi_debug & PRINTROUTINES)
-               printf("aha_scsi_cmd ");
-#endif /*AHADEBUG*/
-       /***********************************************\
-       * get a ccb (mbox-out) to use. If the transfer  *
-       * is from a buf (possibly from interrupt time)  *
-       * then we can't allow it to sleep               *
-       \***********************************************/
+       int     seg;            /* scatter gather seg being worked on */
+       int     i = 0;
+       int     rc = 0;
+       int     thiskv;
+       int     thisphys, nextphys;
+       int     bytes_this_seg, bytes_this_page, datalen, flags;
+       struct iovec *iovp;
+       int     s;
+
+       SC_DEBUG(xs->sc_link, SDEV_DB2, ("aha_scsi_cmd\n"));
+       /*
+        * get a ccb (mbox-out) to use. If the transfer
+        * is from a buf (possibly from interrupt time)
+        * then we can't allow it to sleep
+        */
        flags = xs->flags;
        flags = xs->flags;
-       if(!(flags & INUSE))
-       {
-               printf("aha%d: not in use!\n",unit);
-               Debugger();
-               xs->flags |= INUSE;
-       }
-       if(flags & ITSDONE)
-       {
-               printf("aha%d: Already done! check device retry code\n",unit);
-               Debugger();
-               xs->flags &= ~ITSDONE;
-       }
-       if(xs->bp) flags |= (SCSI_NOSLEEP); /* just to be sure */
-       if (!(ccb = aha_get_ccb(unit,flags)))
-       {
+       if (!(ccb = aha_get_ccb(unit, flags))) {
                xs->error = XS_DRIVER_STUFFUP;
                xs->error = XS_DRIVER_STUFFUP;
-               return(TRY_AGAIN_LATER);
+               return (TRY_AGAIN_LATER);
        }
        }
-
        if (ccb->mbx->cmd != AHA_MBO_FREE)
        if (ccb->mbx->cmd != AHA_MBO_FREE)
-               printf("aha%d: MBO not free\n",unit);
+               printf("aha%d: MBO not free\n", unit);
 
 
-       /***********************************************\
-       * Put all the arguments for the xfer in the ccb *
-       \***********************************************/
-       ccb->xfer               =       xs;
-       if(flags & SCSI_RESET)
-       {
-               ccb->opcode     =       AHA_RESET_CCB;
-       }
-       else
-       {
+       /*
+        * Put all the arguments for the xfer in the ccb
+        */
+       ccb->xfer = xs;
+       if (flags & SCSI_RESET) {
+               ccb->opcode = AHA_RESET_CCB;
+       } else {
                /* can't use S/G if zero length */
                /* can't use S/G if zero length */
-               ccb->opcode     =       (xs->datalen?
-                                               AHA_INIT_SCAT_GATH_CCB
-                                               :AHA_INITIATOR_CCB);
+               ccb->opcode = (xs->datalen ?
+                   AHA_INIT_SCAT_GATH_CCB
+                   AHA_INITIATOR_CCB);
        }
        }
-       ccb->target             =       xs->targ;;
-       ccb->data_out           =       0;
-       ccb->data_in            =       0;
-       ccb->lun                =       xs->lu;
-       ccb->scsi_cmd_length    =       xs->cmdlen;
-       ccb->req_sense_length   =       sizeof(ccb->scsi_sense);
-
-       if((xs->datalen) && (!(flags & SCSI_RESET)))
-       { /* can use S/G only if not zero length */
-               lto3b(KVTOPHYS(ccb->scat_gath), ccb->data_addr );
-               sg              =       ccb->scat_gath ;
-               seg             =       0;
-               if(flags & SCSI_DATA_UIO)
-               {
-                       iovp = ((struct uio *)xs->data)->uio_iov;
-                       datalen = ((struct uio *)xs->data)->uio_iovcnt;
-                       while ((datalen) && (seg < AHA_NSEG))
-                       {
-                               lto3b(iovp->iov_base,&(sg->seg_addr));
-                               lto3b(iovp->iov_len,&(sg->seg_len));
-#ifdef AHADEBUG
-                               if(scsi_debug & SHOWSCATGATH)
-                                       printf("(0x%x@0x%x)"
-                                                       ,iovp->iov_len
-                                                       ,iovp->iov_base);
-#endif /*AHADEBUG*/
+       ccb->target = sc_link->target;
+       ccb->data_out = 0;
+       ccb->data_in = 0;
+       ccb->lun = sc_link->lun;
+       ccb->scsi_cmd_length = xs->cmdlen;
+       ccb->req_sense_length = sizeof(ccb->scsi_sense);
+
+       if ((xs->datalen) && (!(flags & SCSI_RESET))) {
+               /* can use S/G only if not zero length */
+               lto3b(KVTOPHYS(ccb->scat_gath), ccb->data_addr);
+               sg = ccb->scat_gath;
+               seg = 0;
+#ifdef TFS_ONLY
+               if (flags & SCSI_DATA_UIO) {
+                       iovp = ((struct uio *) xs->data)->uio_iov;
+                       datalen = ((struct uio *) xs->data)->uio_iovcnt;
+                       while ((datalen) && (seg < AHA_NSEG)) {
+                               lto3b(iovp->iov_base, sg->seg_addr);
+                               lto3b(iovp->iov_len, sg->seg_len);
+                               SC_DEBUGN(xs->sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)"
+                                       ,iovp->iov_len
+                                       ,iovp->iov_base));
                                sg++;
                                iovp++;
                                seg++;
                                datalen--;
                        }
                                sg++;
                                iovp++;
                                seg++;
                                datalen--;
                        }
-               }
-               else
+               } else
+#endif /*TFS_ONLY */
                {
                {
-                       /***********************************************\
-                       * Set up the scatter gather block               *
-                       \***********************************************/
-               
-#ifdef AHADEBUG
-                       if(scsi_debug & SHOWSCATGATH)
-                               printf("%d @0x%x:- ",xs->datalen,xs->data);
-#endif /*AHADEBUG*/
-                       datalen         =       xs->datalen;
-                       thiskv          =       (int)xs->data;
-                       thisphys        =       KVTOPHYS(thiskv);
-               
-                       while ((datalen) && (seg < AHA_NSEG))
-                       {
-                               bytes_this_seg  = 0;
-       
+                       /*
+                        * Set up the scatter gather block
+                        */
+
+                       SC_DEBUG(xs->sc_link, SDEV_DB4,
+                           ("%d @0x%x:- ", xs->datalen, xs->data));
+                       datalen = xs->datalen;
+                       thiskv = (int) xs->data;
+                       thisphys = KVTOPHYS(thiskv);
+
+                       while ((datalen) && (seg < AHA_NSEG)) {
+                               bytes_this_seg = 0;
+
                                /* put in the base address */
                                /* put in the base address */
-                               lto3b(thisphys,&(sg->seg_addr));
-               
-#ifdef AHADEBUG
-                               if(scsi_debug & SHOWSCATGATH)
-                                       printf("0x%x",thisphys);
-#endif /*AHADEBUG*/
-       
+                               lto3b(thisphys, sg->seg_addr);
+
+                               SC_DEBUGN(xs->sc_link, SDEV_DB4,
+                                   ("0x%x", thisphys));
+
                                /* do it at least once */
                                /* do it at least once */
-                               nextphys = thisphys;    
-                               while ((datalen) && (thisphys == nextphys))
-                               /***************************************\
-                               * This page is contiguous (physically)  *
-                               * with the the last, just extend the    *
-                               * length                                *
-                               \***************************************/
-                               {
+                               nextphys = thisphys;
+                               while ((datalen) && (thisphys == nextphys)) {
+                                       /*
+                                        * This page is contiguous (physically)
+                                        * with the the last, just extend the
+                                        * length
+                                        */
+                                       /* check it fits on the ISA bus */
+                                       if (thisphys > 0xFFFFFF)
+                                       {
+                                               printf("aha%d: DMA beyond"
+                                                       " end Of ISA\n", unit);
+                                               xs->error = XS_DRIVER_STUFFUP;
+                                               aha_free_ccb(unit, ccb, flags);
+                                               return (HAD_ERROR);
+                                       }
                                        /** how far to the end of the page ***/
                                        nextphys = (thisphys & (~(PAGESIZ - 1)))
                                        /** how far to the end of the page ***/
                                        nextphys = (thisphys & (~(PAGESIZ - 1)))
-                                                               + PAGESIZ;
-                                       bytes_this_page = nextphys - thisphys;
+                                           + PAGESIZ;
+                                       bytes_this_page = nextphys - thisphys;
                                        /**** or the data ****/
                                        /**** or the data ****/
-                                       bytes_this_page = min(bytes_this_page
-                                                               ,datalen);
-                                       bytes_this_seg  += bytes_this_page;
-                                       datalen         -= bytes_this_page;
-               
+                                       bytes_this_page = min(bytes_this_page
+                                           ,datalen);
+                                       bytes_this_seg += bytes_this_page;
+                                       datalen -= bytes_this_page;
+
                                        /**** get more ready for the next page ****/
                                        /**** get more ready for the next page ****/
-                                       thiskv  = (thiskv & (~(PAGESIZ - 1)))
-                                                               + PAGESIZ;
-                                       if(datalen)
+                                       thiskv = (thiskv & (~(PAGESIZ - 1)))
+                                           + PAGESIZ;
+                                       if (datalen)
                                                thisphys = KVTOPHYS(thiskv);
                                }
                                                thisphys = KVTOPHYS(thiskv);
                                }
-                               /***************************************\
-                               * next page isn't contiguous, finish the seg*
-                               \***************************************/
-#ifdef AHADEBUG
-                               if(scsi_debug & SHOWSCATGATH)
-                                       printf("(0x%x)",bytes_this_seg);
-#endif /*AHADEBUG*/
-                               lto3b(bytes_this_seg,&(sg->seg_len));   
+                               /*
+                                * next page isn't contiguous, finish the seg
+                                */
+                               SC_DEBUGN(xs->sc_link, SDEV_DB4,
+                                   ("(0x%x)", bytes_this_seg));
+                               lto3b(bytes_this_seg, sg->seg_len);
                                sg++;
                                seg++;
                        }
                }
                                sg++;
                                seg++;
                        }
                }
-               lto3b(seg * sizeof(struct aha_scat_gath),ccb->data_length);
-#ifdef AHADEBUG
-               if(scsi_debug & SHOWSCATGATH)
-                       printf("\n");
-#endif /*AHADEBUG*/
-               if (datalen)
-               { /* there's still data, must have run out of segs! */
+               lto3b(seg * sizeof(struct aha_scat_gath), ccb->data_length);
+               SC_DEBUGN(xs->sc_link, SDEV_DB4, ("\n"));
+
+               if (datalen) {  /* there's still data, must have run out of segs! */
                        printf("aha%d: aha_scsi_cmd, more than %d DMA segs\n",
                        printf("aha%d: aha_scsi_cmd, more than %d DMA segs\n",
-                               unit,AHA_NSEG);
+                           unit, AHA_NSEG);
                        xs->error = XS_DRIVER_STUFFUP;
                        xs->error = XS_DRIVER_STUFFUP;
-                       aha_free_ccb(unit,ccb,flags);
-                       return(HAD_ERROR);
+                       aha_free_ccb(unit, ccb, flags);
+                       return (HAD_ERROR);
                }
                }
-
+       } else {                /* No data xfer, use non S/G values */
+               lto3b(0, ccb->data_addr);
+               lto3b(0, ccb->data_length);
        }
        }
-       else
-       {       /* No data xfer, use non S/G values */
-               lto3b(0, ccb->data_addr );
-               lto3b(0,ccb->data_length);
-       }
-       lto3b(0, ccb->link_addr );
-       /***********************************************\
-       * Put the scsi command in the ccb and start it  *
-       \***********************************************/
-       if(!(flags & SCSI_RESET))
+       lto3b(0, ccb->link_addr);
+       /*
+        * Put the scsi command in the ccb and start it
+        */
+       if (!(flags & SCSI_RESET))
                bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmd_length);
                bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmd_length);
-#ifdef AHADEBUG
-       if(scsi_debug & SHOWCOMMANDS)
-       {
-               u_char  *b = (u_char *)&ccb->scsi_cmd;
-               if(!(flags & SCSI_RESET))
-               {
-                       int i = 0;
-                       printf("aha%d:%d:%d-"
-                               ,unit
-                               ,ccb->target
-                               ,ccb->lun );
-                               while(i < ccb->scsi_cmd_length )
-                               {
-                                       if(i) printf(",");
-                                        printf("%x",b[i++]);
-                               }
-               }
-               else
-               {
-                       printf("aha%d:%d:%d-RESET- " 
-                               ,unit 
-                               ,ccb->target
-                               ,ccb->lun
-                       );
-               }
-       }
-#endif /*AHADEBUG*/
-       if (!(flags & SCSI_NOMASK))
-       {
-               s= splbio(); /* stop instant timeouts */
-               timeout(aha_timeout,ccb,(xs->timeout * hz) / 1000);
+       if (!(flags & SCSI_NOMASK)) {
+               s = splbio();   /* stop instant timeouts */
+               timeout(aha_timeout, ccb, (xs->timeout * hz) / 1000);
                aha_startmbx(ccb->mbx);
                aha_startmbx(ccb->mbx);
-               /***********************************************\
-               * Usually return SUCCESSFULLY QUEUED            *
-               \***********************************************/
+               /*
+                * Usually return SUCCESSFULLY QUEUED
+                */
                splx(s);
                splx(s);
-#ifdef AHADEBUG
-               if(scsi_debug & TRACEINTERRUPTS)
-                       printf("sent ");
-#endif /*AHADEBUG*/
-               return(SUCCESSFULLY_QUEUED);
+               SC_DEBUG(xs->sc_link, SDEV_DB3, ("sent\n"));
+               return (SUCCESSFULLY_QUEUED);
        }
        aha_startmbx(ccb->mbx);
        }
        aha_startmbx(ccb->mbx);
-#ifdef AHADEBUG
-       if(scsi_debug & TRACEINTERRUPTS)
-               printf("cmd_sent, waiting ");
-#endif /*AHADEBUG*/
-       /***********************************************\
-       * If we can't use interrupts, poll on completion*
-       \***********************************************/
-       {
-               int done = 0;
-               int count = delaycount * xs->timeout / AHA_SCSI_TIMEOUT_FUDGE;
-               while((!done) && count)
-               {
-                       i=0;
-                       while ( (!done) && i<AHA_MBX_SIZE)
-                       {
-                               if ((aha_mbx[unit].mbi[i].stat != AHA_MBI_FREE )
-                                  && (PHYSTOKV(_3btol(aha_mbx[unit].mbi[i].ccb_addr)
-                                       == (int)ccb)))
-                               {
-                                       aha_mbx[unit].mbi[i].stat = AHA_MBI_FREE;
-                                       aha_done(unit,ccb);
-                                       done++;
-                               }
-                               i++;
-                       }
-                       count--;
-               }
-               if (!count)
-               {
-                       if (!(xs->flags & SCSI_SILENT))
-                               printf("aha%d: cmd fail\n",unit);
-                       aha_abortmbx(ccb->mbx);
-                       count = delaycount * 2000 / AHA_SCSI_TIMEOUT_FUDGE;
-                       while((!done) && count)
-                       {
-                               i=0;
-                               while ( (!done) && i<AHA_MBX_SIZE)
-                               {
-                                       if ((aha_mbx[unit].mbi[i].stat != AHA_MBI_FREE )
-                                       && (PHYSTOKV(_3btol(aha_mbx[unit].mbi[i].ccb_addr)
-                                               == (int)ccb)))
-                                       {
-                                               aha_mbx[unit].mbi[i].stat = AHA_MBI_FREE;
-                                               aha_done(unit,ccb);
-                                               done++;
-                                       }
-                                       i++;
-                               }
-                               count--;
-                       }
-                       if(!count)
-                       {
-                               printf("aha%d: abort failed in wait\n",unit);
-                               ccb->mbx->cmd = AHA_MBO_FREE;
-                       }
-                       aha_free_ccb(unit,ccb,flags);
-                       ahaintr(unit);
-                       xs->error = XS_DRIVER_STUFFUP;
-                       return(HAD_ERROR);
-               }
-               ahaintr(unit);
-               if(xs->error) return(HAD_ERROR);
-               return(COMPLETE);
+       SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd sent, waiting\n"));
 
 
-       } 
+       /*
+        * If we can't use interrupts, poll on completion
+        */
+       return (aha_poll(unit, xs, ccb));       /* only during boot */
 }
 }
-/***************************************************************\
-* try each speed in turn, when we find one that works, use     *
-* the NEXT one for a safety margin, unless that doesn't exist  *
-* or doesn't work. returns the nSEC value of the time used     *
-* or 0 if it could get a working speed ( or the NEXT speed     *
-* failed)                                                      *
-\***************************************************************/
-
-int    aha_set_bus_speed(unit)
-int    unit;
-{
-       int     speed;
-       int     retval,retval2;
 
 
-#ifdef EISA
-       speed = 0; /* start at the fastest */
-#else  EISA
-       speed = 1; /* 100 ns can crash some ISA busses (!?!) */
-#endif EISA
-       while (1)
-       {
-               retval = aha_bus_speed_check(unit,speed);
-               if(retval == HAD_ERROR) 
-               {
-                       printf("no working bus speed!!!\n");
-                       return(0);
+/*
+ * Poll a particular unit, looking for a particular xs
+ */
+int 
+aha_poll(unit, xs, ccb)
+       int     unit;
+       struct scsi_xfer *xs;
+       struct aha_ccb *ccb;
+{
+       struct aha_data *aha = ahadata[unit];
+       int     done = 0;
+       int     count = xs->timeout;
+       u_char  stat;
+
+       /*timeouts are in msec, so we loop in 1000uSec cycles */
+       while (count) {
+               /*
+                * If we had interrupts enabled, would we
+                * have got an interrupt?
+                */
+               stat = inb(AHA_INTR_PORT);
+               if (stat & AHA_ANY_INTR) {
+                       ahaintr(unit);
                }
                }
-               if(retval == 0)
-               {
-                       speed++;
+               if (xs->flags & ITSDONE) {
+                       break;
                }
                }
-               else    /* Go one slower to be safe */
-               {       /* unless eisa at 100 ns.. trust it */
-                       if(speed != 0)
-                       {
-                               speed++;
-                       }
-                       printf("%d nSEC ok, using ",retval);
-                       retval2 = aha_bus_speed_check(unit,speed);
-                       if(retval2 == HAD_ERROR) /* retval is slowest already */
-                       {
-                               printf("marginal ");
-                               retval2 = retval;
-                       }
-                       if(retval2)
-                       {
-                               printf("%d nSEC\n",retval2);
-                               return(retval2);
+               DELAY(1000);    /* only happens in boot so ok */
+               count--;
+       }
+       if (count == 0) {
+               /*
+                * We timed out, so call the timeout handler
+                * manually, accout  for the fact that the
+                * clock is not running yet by taking out the 
+                * clock queue entry it makes
+                */
+               aha_timeout(ccb);
+
+               /*
+                * because we are polling,
+                * take out the timeout entry aha_timeout made
+                */
+               untimeout(aha_timeout, ccb);
+               count = 2000;
+               while (count) {
+                       /*
+                        * Once again, wait for the int bit
+                        */
+                       stat = inb(AHA_INTR_PORT);
+                       if (stat & AHA_ANY_INTR) {
+                               ahaintr(unit);
                        }
                        }
-                       else
-                       {
-                               printf(".. slower failed, abort\n",retval);
-                               return(0);
+                       if (xs->flags & ITSDONE) {
+                               break;
                        }
                        }
-
+                       DELAY(1000);    /* only happens in boot so ok */
+                       count--;
+               }
+               if (count == 0) {
+                       /*
+                        * We timed out again.. this is bad
+                        * Notice that this time there is no
+                        * clock queue entry to remove
+                        */
+                       aha_timeout(ccb);
                }
        }
                }
        }
+       if (xs->error)
+               return (HAD_ERROR);
+       return (COMPLETE);
+
 }
 
 }
 
-/***************************************************************\
-* Set the DMA speed to the Nth speed and try an xfer. If it    *
-* fails return 0, if it succeeds return the nSec value selected        *
-* If there is no such speed return HAD_ERROR.                  *
-\***************************************************************/
+#ifdef TUNE_1542
+/*
+ * Try all the speeds from slowest to fastest.. if it finds a
+ * speed that fails, back off one notch from the last working
+ * speed (unless there is no other notch).
+ * Returns the nSEC value of the time used
+ * or 0 if it could get a working speed (or the NEXT speed 
+ * failed)
+ */
 static struct bus_speed
 {
        char    arg;
 static struct bus_speed
 {
        char    arg;
@@ -1490,93 +1298,146 @@ static struct bus_speed
        {0xee,400},
        {0xff,450}
 };
        {0xee,400},
        {0xff,450}
 };
-static char aha_test_string[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz!@";
 
 
-int aha_bus_speed_check(unit,speed)
-int    unit,speed;
+int    
+aha_set_bus_speed(unit)
+       int     unit;
 {
 {
-       int     numspeeds = sizeof(aha_bus_speeds)/sizeof(struct bus_speed);
-       u_char  ad[3];
+       int     speed;
+       int     lastworking;
+       int     retval,retval2;
+       struct  aha_data *aha = ahadata[unit];
 
 
-       /*******************************************************\
-       * Check we have such an entry                           *
-       \*******************************************************/
-       if(speed >= numspeeds) return(HAD_ERROR);       /* illegal speed */
-       
-       /*******************************************************\
-       * Set the dma-speed                                     *
-       \*******************************************************/
-       aha_cmd(unit,1, 0, 0, 0, AHA_SPEED_SET,aha_bus_speeds[speed].arg);
-
-       /*******************************************************\
-       * put the test data into the buffer and calculate       *
-       * it's address. Read it onto the board                  *
-       \*******************************************************/
-       strcpy(aha_scratch_buf,aha_test_string);
-       lto3b(KVTOPHYS(aha_scratch_buf),ad);
-
-       aha_cmd(unit,3, 0, 0, 0, AHA_WRITE_FIFO, ad[0], ad[1], ad[2]);
-
-       /*******************************************************\
-       * clear the buffer then copy the contents back from the *
-       * board.                                                *
-       \*******************************************************/
-       bzero(aha_scratch_buf,54);      /* 54 bytes transfered by test */
-
-       aha_cmd(unit,3, 0, 0, 0, AHA_READ_FIFO, ad[0], ad[1], ad[2]);
-
-       /*******************************************************\
-       * Compare the original data and the final data and      *
-       * return the correct value depending upon the result    *
-       \*******************************************************/
-       if(strcmp(aha_test_string,aha_scratch_buf))
-       {       /* copy failed.. assume too fast */
-               return(0);
-       }
-       else
-       {       /* copy succeded assume speed ok */
-               return(aha_bus_speeds[speed].nsecs);
+       lastworking = -1;
+       speed = 7;
+       while (1) {
+               retval = aha_bus_speed_check(unit,speed);
+               if(retval != 0) {
+                       lastworking = speed;
+               }
+               if((retval == 0) || (speed == 0)) {
+                       if(lastworking == -1) {
+                               printf("No working bus speed for aha154X\n");
+                               return 0;
+                       }
+                       printf("%d nSEC ok, using "
+                               ,aha_bus_speeds[lastworking].nsecs);
+                       if(lastworking == 7) { /* is slowest already */
+                               printf("marginal ");
+                       } else {
+                               lastworking++;
+                       }
+                       retval2 = aha_bus_speed_check(unit,lastworking);
+                       if(retval2 == 0) {
+                               printf("test retry failed.. aborting.\n");
+                               return 0;
+                       }
+                       printf("%d nSEC\n",retval2);
+                       return retval2 ;
+
+               }
+               speed--;
        }
 }
 
        }
 }
 
+/*
+ * Set the DMA speed to the Nth speed and try an xfer. If it
+ * fails return 0, if it succeeds return the nSec value selected
+ * If there is no such speed return HAD_ERROR.
+ */
+static char aha_test_string[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz!@";
 
 
-
-aha_timeout(struct aha_ccb *ccb)
+int 
+aha_bus_speed_check(unit, speed)
+       int     unit, speed;
 {
 {
-       int     unit;
-       int     s       = splbio();
+       int     numspeeds = sizeof(aha_bus_speeds) / sizeof(struct bus_speed);
+       int     loopcount;
+       u_char  ad[3];
+       struct aha_data *aha = ahadata[unit];
+
+       /*
+        * Check we have such an entry
+        */
+       if (speed >= numspeeds)
+               return (HAD_ERROR);     /* illegal speed */
 
 
-       unit = ccb->xfer->adapter;
-       printf("aha%d: device %d timed out ",unit ,ccb->xfer->targ);
+       /*
+        * Set the dma-speed
+        */
+       aha_cmd(unit, 1, 0, 0, 0, AHA_SPEED_SET, aha_bus_speeds[speed].arg);
 
 
-       /***************************************\
-       * If The ccb's mbx is not free, then    *
-       * the board has gone south              *
-       \***************************************/
-       if(ccb->mbx->cmd != AHA_MBO_FREE)
+       /*
+        * put the test data into the buffer and calculate
+        * it's address. Read it onto the board
+        */
+       lto3b(KVTOPHYS(aha_scratch_buf), ad);
+       for(loopcount = 2000;loopcount;loopcount--)
        {
        {
-               printf("aha%d: not taking commands!\n",unit);
+               strcpy(aha_scratch_buf, aha_test_string);
+
+               aha_cmd(unit, 3, 0, 0, 0, AHA_WRITE_FIFO, ad[0], ad[1], ad[2]);
+
+               /*
+               * clear the buffer then copy the contents back from the
+               * board.
+               */
+               bzero(aha_scratch_buf, 54);     /* 54 bytes transfered by test */
+       
+               aha_cmd(unit, 3, 0, 0, 0, AHA_READ_FIFO, ad[0], ad[1], ad[2]);
+       
+               /*
+               * Compare the original data and the final data and
+               * return the correct value depending upon the result
+               */
+               if (strcmp(aha_test_string, aha_scratch_buf))   
+                       return 0; /* failed test */
+       }
+                       /* copy succeded assume speed ok */
+
+       return (aha_bus_speeds[speed].nsecs);
+       
+}
+#endif /*TUNE_1542*/
+
+void
+aha_timeout(struct aha_ccb * ccb)
+{
+       int     unit;
+       int     s = splbio();
+       struct aha_data *aha;
+
+       unit = ccb->xfer->sc_link->adapter_unit;
+       aha = ahadata[unit];
+       sc_print_addr(ccb->xfer->sc_link);
+       printf("timed out ");
+
+       /*
+        * If The ccb's mbx is not free, then
+        * the board has gone south
+        */
+       if (ccb->mbx->cmd != AHA_MBO_FREE) {
+               printf("\nadapter not taking commands.. frozen?!\n");
                Debugger();
        }
                Debugger();
        }
-       /***************************************\
-       * If it has been through before, then   *
-       * a previous abort has failed, don't    *
-       * try abort again                       *
-       \***************************************/
-       if(ccb->flags == CCB_ABORTED) /* abort timed out */
-       {
+       /*
+        * If it has been through before, then
+        * a previous abort has failed, don't
+        * try abort again
+        */
+       if (ccb->flags == CCB_ABORTED) {
+               /* abort timed out */
                printf(" AGAIN\n");
                printf(" AGAIN\n");
-               ccb->xfer->retries = 0; /* I MEAN IT ! */
+               ccb->xfer->retries = 0;         /* I MEAN IT ! */
                ccb->host_stat = AHA_ABORTED;
                ccb->host_stat = AHA_ABORTED;
-               aha_done(unit,ccb);
-       }
-       else    /* abort the operation that has timed out */
-       {
+               aha_done(unit, ccb);
+       } else {
+               /* abort the operation that has timed out */
                printf("\n");
                aha_abortmbx(ccb->mbx);
                printf("\n");
                aha_abortmbx(ccb->mbx);
-                               /* 2 secs for the abort */
-               timeout(aha_timeout,ccb,2 * hz);
+               /* 4 secs for the abort */
+               timeout(aha_timeout, ccb, 4 * hz);
                ccb->flags = CCB_ABORTED;
                ccb->flags = CCB_ABORTED;
-       }
-       splx(s);
+       } splx(s);
 }
 }
+#endif /* KERNEL */
index 1e3e154..dda5042 100644 (file)
  *
  * commenced: Sun Sep 27 18:14:01 PDT 1992
  *
  *
  * commenced: Sun Sep 27 18:14:01 PDT 1992
  *
- *     $Id: aha1742.c,v 1.9 1993/08/28 03:07:40 rgrimes Exp $
+ *      $Id: aha1742.c,v 2.4 93/10/24 12:47:00 julian Exp Locker: julian $
  */
 
 #include <sys/types.h>
  */
 
 #include <sys/types.h>
-#include <ahb.h>
 
 
+#ifdef KERNEL                  /* don't laugh, it compiles as a program too.. look */
+#include <ahb.h>
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/errno.h>
 #include <sys/ioctl.h>
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/errno.h>
 #include <sys/ioctl.h>
+#include <sys/malloc.h>
 #include <sys/buf.h>
 #include <sys/proc.h>
 #include <sys/user.h>
 #include <sys/buf.h>
 #include <sys/proc.h>
 #include <sys/user.h>
-
-#ifdef  MACH    /* EITHER CMU OR OSF */
-#include <i386/ipl.h>
-#include <i386at/scsi.h>
-#include <i386at/scsiconf.h>
-
-#ifdef  OSF     /* OSF ONLY */
-#include <sys/table.h>
-#include <i386/handler.h>
-#include <i386/dispatcher.h>
-#include <i386/AT386/atbus.h>
-
-#else   OSF     /* CMU ONLY */
-#include <i386at/atbus.h>
-#include <i386/pio.h>
-#endif  OSF
-#endif  MACH    /* end of MACH specific */
-
-#ifdef  __386BSD__      /* 386BSD specific */
-#define isa_dev isa_device
-#define dev_unit id_unit
-#define dev_addr id_iobase
-
 #include <i386/include/pio.h>
 #include <i386/isa/isa_device.h>
 #include <i386/include/pio.h>
 #include <i386/isa/isa_device.h>
+#endif /*KERNEL */
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
-#endif  __386BSD__
 
 
-/*\f*/
+/*\f */
 
 
-#ifdef  __386BSD__
+#ifdef KERNEL
+# ifdef NetBSD
+#  ifdef DDB
+int     Debugger();
+#  else        /* DDB */
+#define Debugger() panic("should call debugger here (adaptec.c)")
+#  endif /* DDB */
+# else
 #include "ddb.h"
 #if     NDDB > 0
 int     Debugger();
 #include "ddb.h"
 #if     NDDB > 0
 int     Debugger();
-#else   NDDB
+#else  /* NDDB */
 #define Debugger() panic("should call debugger here (adaptec.c)")
 #define Debugger() panic("should call debugger here (adaptec.c)")
-#endif  NDDB
-#endif  __386BSD__
-
-#ifdef  MACH
-int     Debugger();
-#endif  MACH
+#endif /* NDDB */
+#endif /* netbsd */
+#else /* KERNEL */
+#define NAHB 1
+#endif /* kernel */
+
+#ifndef NetBSD
+typedef void (*timeout_t) __P((caddr_t));
+#endif
 
 typedef unsigned long int physaddr;
 
 typedef unsigned long int physaddr;
-extern int     hz;
-
-#ifdef        MACH
-extern physaddr kvtophys();
-#define PHYSTOKV(x)   phystokv(x)
-#define KVTOPHYS(x)   kvtophys(x)
-#endif MACH
+extern int hz;
 
 
-#ifdef        __386BSD__
 #define KVTOPHYS(x)   vtophys(x)
 #define KVTOPHYS(x)   vtophys(x)
-#endif        __386BSD__
-
-extern int delaycount;  /* from clock setup code */
-#define        NUM_CONCURRENT  16      /* number of concurrent ops per board */
-#define        AHB_NSEG        33      /* number of dma segments supported     */
-#define FUDGE(X)       (X>>1)  /* our loops are slower than spinwait() */
-/*\f*/
-/***********************************************************************\
-* AHA1740 standard EISA Host ID regs  (Offset from slot base)          *
-\***********************************************************************/
-#define HID0           0xC80 /* 0,1: msb of ID2, 3-7: ID1      */
-#define HID1           0xC81 /* 0-4: ID3, 4-7: LSB ID2         */
-#define HID2           0xC82 /* product, 0=174[20] 1 = 1744    */
-#define HID3           0xC83 /* firmware revision              */
+
+#define AHB_ECB_MAX    32      /* store up to 32ECBs at any one time     */
+                               /* in aha1742 H/W ( Not MAX ? )         */
+#define        ECB_HASH_SIZE   32      /* when we have a physical addr. for      */
+                               /* a ecb and need to find the ecb in    */
+                               /* space, look it up in the hash table  */
+#define        ECB_HASH_SHIFT  9       /* only hash on multiples of 512  */
+#define ECB_HASH(x)    ((((long int)(x))>>ECB_HASH_SHIFT) % ECB_HASH_SIZE)
+
+#define        AHB_NSEG        33      /* number of dma segments supported       */
+
+/*
+ * AHA1740 standard EISA Host ID regs  (Offset from slot base)
+ */
+#define HID0           0xC80   /* 0,1: msb of ID2, 3-7: ID1      */
+#define HID1           0xC81   /* 0-4: ID3, 4-7: LSB ID2         */
+#define HID2           0xC82   /* product, 0=174[20] 1 = 1744    */
+#define HID3           0xC83   /* firmware revision              */
 
 #define CHAR1(B1,B2) (((B1>>2) & 0x1F) | '@')
 #define CHAR2(B1,B2) (((B1<<3) & 0x18) | ((B2>>5) & 0x7)|'@')
 
 #define CHAR1(B1,B2) (((B1>>2) & 0x1F) | '@')
 #define CHAR2(B1,B2) (((B1<<3) & 0x18) | ((B2>>5) & 0x7)|'@')
@@ -104,9 +90,9 @@ extern int delaycount;  /* from clock setup code */
 /* AHA1740 EISA board control registers (Offset from slot base) */
 #define        EBCTRL          0xC84
 #define  CDEN          0x01
 /* AHA1740 EISA board control registers (Offset from slot base) */
 #define        EBCTRL          0xC84
 #define  CDEN          0x01
-/***********************************************************************\
-* AHA1740 EISA board mode registers (Offset from slot base)            *
-\***********************************************************************/
+/*
+ * AHA1740 EISA board mode registers (Offset from slot base)
+ */
 #define PORTADDR       0xCC0
 #define         PORTADDR_ENHANCED      0x80
 #define BIOSADDR       0xCC1
 #define PORTADDR       0xCC0
 #define         PORTADDR_ENHANCED      0x80
 #define BIOSADDR       0xCC1
@@ -123,18 +109,18 @@ extern int delaycount;  /* from clock setup code */
 #define        INT12   0x03
 #define        INT14   0x05
 #define        INT15   0x06
 #define        INT12   0x03
 #define        INT14   0x05
 #define        INT15   0x06
-#define INTHIGH 0x08    /* int high=ACTIVE (else edge) */
+#define INTHIGH 0x08           /* int high=ACTIVE (else edge) */
 #define        INTEN   0x10
 /**** bit definitions for SCSIDEF ****/
 #define        INTEN   0x10
 /**** bit definitions for SCSIDEF ****/
-#define        HSCSIID 0x0F    /* our SCSI ID */
-#define        RSTPWR  0x10    /* reset scsi bus on power up or reset */
+#define        HSCSIID 0x0F            /* our SCSI ID */
+#define        RSTPWR  0x10            /* reset scsi bus on power up or reset */
 /**** bit definitions for BUSDEF ****/
 /**** bit definitions for BUSDEF ****/
-#define        B0uS    0x00    /* give up bus immediatly */
-#define        B4uS    0x01    /* delay 4uSec. */
+#define        B0uS    0x00            /* give up bus immediatly */
+#define        B4uS    0x01            /* delay 4uSec. */
 #define        B8uS    0x02
 #define        B8uS    0x02
-/***********************************************************************\
-* AHA1740 ENHANCED mode mailbox control regs (Offset from slot base)   *
-\***********************************************************************/
+/*
+ * AHA1740 ENHANCED mode mailbox control regs (Offset from slot base)
+ */
 #define MBOXOUT0       0xCD0
 #define MBOXOUT1       0xCD1
 #define MBOXOUT2       0xCD2
 #define MBOXOUT0       0xCD0
 #define MBOXOUT1       0xCD1
 #define MBOXOUT2       0xCD2
@@ -152,9 +138,9 @@ extern int delaycount;  /* from clock setup code */
 
 #define G2STAT2                0xCDC
 
 
 #define G2STAT2                0xCDC
 
-/*******************************************************\
-* Bit definitions for the 5 control/status registers   *
-\*******************************************************/
+/*
+ * Bit definitions for the 5 control/status registers
+ */
 #define        ATTN_TARGET             0x0F
 #define        ATTN_OPCODE             0xF0
 #define  OP_IMMED              0x10
 #define        ATTN_TARGET             0x0F
 #define        ATTN_OPCODE             0xF0
 #define  OP_IMMED              0x10
@@ -181,138 +167,130 @@ extern int delaycount;  /* from clock setup code */
 #define        G2STAT_MBOX_EMPTY       0x04
 
 #define        G2STAT2_HOST_READY      0x01
 #define        G2STAT_MBOX_EMPTY       0x04
 
 #define        G2STAT2_HOST_READY      0x01
-/*\f*/
 
 
-struct ahb_dma_seg
-{
-       physaddr        addr;
-       long            len;
+struct ahb_dma_seg {
+       physaddr addr;
+       long    len;
 };
 
 };
 
-struct ahb_ecb_status
-{
-       u_short status;
-#       define ST_DON  0x0001
-#       define ST_DU   0x0002
-#       define ST_QF   0x0008
-#       define ST_SC   0x0010
-#       define ST_DO   0x0020
-#       define ST_CH   0x0040
-#       define ST_INT  0x0080
-#       define ST_ASA  0x0100
-#       define ST_SNS  0x0200
-#       define ST_INI  0x0800
-#       define ST_ME   0x1000
-#       define ST_ECA  0x4000
-       u_char  ha_status;
-#       define HS_OK                   0x00
-#       define HS_CMD_ABORTED_HOST     0x04
-#       define HS_CMD_ABORTED_ADAPTER  0x05
-#       define HS_TIMED_OUT            0x11
-#       define HS_HARDWARE_ERR         0x20
-#       define HS_SCSI_RESET_ADAPTER   0x22
-#       define HS_SCSI_RESET_INCOMING  0x23
-       u_char  targ_status;
-#       define TS_OK                   0x00
-#       define TS_CHECK_CONDITION      0x02
-#       define TS_BUSY                 0x08
-       u_long  resid_count;
-       u_long  resid_addr;
-       u_short addit_status;
-       u_char  sense_len;
-       u_char  unused[9];
-       u_char  cdb[6];
+struct ahb_ecb_status {
+       u_short status;
+#define        ST_DON  0x0001
+#define        ST_DU   0x0002
+#define        ST_QF   0x0008
+#define        ST_SC   0x0010
+#define        ST_DO   0x0020
+#define        ST_CH   0x0040
+#define        ST_INT  0x0080
+#define        ST_ASA  0x0100
+#define        ST_SNS  0x0200
+#define        ST_INI  0x0800
+#define        ST_ME   0x1000
+#define        ST_ECA  0x4000
+       u_char  ha_status;
+#define        HS_OK                   0x00
+#define        HS_CMD_ABORTED_HOST     0x04
+#define        HS_CMD_ABORTED_ADAPTER  0x05
+#define        HS_TIMED_OUT            0x11
+#define        HS_HARDWARE_ERR         0x20
+#define        HS_SCSI_RESET_ADAPTER   0x22
+#define        HS_SCSI_RESET_INCOMING  0x23
+       u_char  targ_status;
+#define        TS_OK                   0x00
+#define        TS_CHECK_CONDITION      0x02
+#define        TS_BUSY                 0x08
+       u_long  resid_count;
+       u_long  resid_addr;
+       u_short addit_status;
+       u_char  sense_len;
+       u_char  unused[9];
+       u_char  cdb[6];
 };
 
 };
 
-/*\f*/
 
 
-struct ecb
-{
-       u_char  opcode;
-#       define ECB_SCSI_OP     0x01
-       u_char  :4;
-       u_char  options:3;
-       u_char  :1;
-       short opt1;
-#       define ECB_CNE 0x0001
-#       define ECB_DI  0x0080
-#       define ECB_SES 0x0400
-#       define ECB_S_G 0x1000
-#       define ECB_DSB 0x4000
-#       define ECB_ARS 0x8000
-       short opt2;
-#       define ECB_LUN 0x0007
-#       define ECB_TAG 0x0008
-#       define ECB_TT  0x0030
-#       define ECB_ND  0x0040
-#       define ECB_DAT 0x0100
-#       define ECB_DIR 0x0200
-#       define ECB_ST  0x0400
-#       define ECB_CHK 0x0800
-#       define ECB_REC 0x4000
-#       define ECB_NRB 0x8000
-       u_short         unused1;
-       physaddr        data;
-       u_long          datalen;
-       physaddr        status;
-       physaddr        chain;
-       short           unused2;
-       short           unused3;
-       physaddr        sense;
-       u_char          senselen;
-       u_char          cdblen;
-       short           cksum;
-       u_char          cdb[12];
+struct ecb {
+       u_char  opcode;
+#define        ECB_SCSI_OP     0x01
+               u_char:4;
+       u_char  options:3;
+               u_char:1;
+       short   opt1;
+#define        ECB_CNE 0x0001
+#define        ECB_DI  0x0080
+#define        ECB_SES 0x0400
+#define        ECB_S_G 0x1000
+#define        ECB_DSB 0x4000
+#define        ECB_ARS 0x8000
+       short   opt2;
+#define        ECB_LUN 0x0007
+#define        ECB_TAG 0x0008
+#define        ECB_TT  0x0030
+#define        ECB_ND  0x0040
+#define        ECB_DAT 0x0100
+#define        ECB_DIR 0x0200
+#define        ECB_ST  0x0400
+#define        ECB_CHK 0x0800
+#define        ECB_REC 0x4000
+#define        ECB_NRB 0x8000
+       u_short unused1;
+       physaddr data;
+       u_long  datalen;
+       physaddr status;
+       physaddr chain;
+       short   unused2;
+       short   unused3;
+       physaddr sense;
+       u_char  senselen;
+       u_char  cdblen;
+       short   cksum;
+       u_char  cdb[12];
        /*-----------------end of hardware supported fields----------------*/
        /*-----------------end of hardware supported fields----------------*/
-       struct  ecb     *next;  /* in free list */
-       struct  scsi_xfer *xs; /* the scsi_xfer for this cmd */
-       int             flags;
+       struct ecb *next;       /* in free list */
+       struct scsi_xfer *xs;   /* the scsi_xfer for this cmd */
+       int     flags;
 #define ECB_FREE       0
 #define ECB_ACTIVE     1
 #define ECB_ABORTED    2
 #define ECB_IMMED      4
 #define ECB_IMMED_FAIL 8
 #define ECB_FREE       0
 #define ECB_ACTIVE     1
 #define ECB_ABORTED    2
 #define ECB_IMMED      4
 #define ECB_IMMED_FAIL 8
-       struct  ahb_dma_seg     ahb_dma[AHB_NSEG];
-       struct  ahb_ecb_status  ecb_status;
-       struct  scsi_sense_data ecb_sense;
+       struct ahb_dma_seg ahb_dma[AHB_NSEG];
+       struct ahb_ecb_status ecb_status;
+       struct scsi_sense_data ecb_sense;
+       struct ecb *nexthash;
+       physaddr hashkey;       /* physaddr of this struct */
 };
 
 };
 
-/*\f*/
-
-struct ahb_data
-{
-       int     flags;
+struct ahb_data {
+       int     flags;
 #define        AHB_INIT        0x01;
 #define        AHB_INIT        0x01;
-       int     baseport;
-       struct  ecb ecbs[NUM_CONCURRENT];
-       struct  ecb *free_ecb;
-       int     our_id;                 /* our scsi id */
-       int     vect;
-       struct  ecb *immed_ecb;         /* an outstanding immediete command */
-} ahb_data[NAHB];
-
-int    ahbprobe();
-int    ahb_attach();
-int    ahbintr();
-int    ahb_scsi_cmd();
-int    ahb_timeout();
+       int     baseport;
+       struct ecb *ecbhash[ECB_HASH_SIZE];
+       struct ecb *free_ecb;
+       int     our_id;         /* our scsi id */
+       int     vect;
+       struct ecb *immed_ecb;  /* an outstanding immediete command */
+       struct scsi_link sc_link;
+       int     numecbs;
+}      *ahbdata[NAHB];
+
+int     ahbprobe();
+int    ahbprobe1 __P((struct isa_device *dev));
+int     ahb_attach();
+int    ahb_init __P((int unit));
+int     ahbintr();
+int32   ahb_scsi_cmd();
+void    ahb_timeout();
+void   ahb_done();
 struct ecb *cheat;
 struct ecb *cheat;
-void   ahbminphys();
-long int ahb_adapter_info();
-
-#ifdef  MACH
-struct  isa_driver      ahbdriver = { ahbprobe, 0, ahb_attach, "ahb", 0, 0, 0};
-int (*ahbintrs[])() = {ahbintr, 0};
-#endif  MACH
-
-#ifdef  __386BSD__
-struct  isa_driver      ahbdriver = { ahbprobe, ahb_attach, "ahb"};
-#endif  __386BSD__
+void   ahb_free_ecb();
+void    ahbminphys();
+struct ecb *ahb_ecb_phys_kv();
+u_int32 ahb_adapter_info();
 
 #define        MAX_SLOTS       8
 
 #define        MAX_SLOTS       8
-static ahb_slot = 0;   /* slot last board was found in */
-static ahb_unit = 0;
-int    ahb_debug = 0;
+static  ahb_slot = 0;          /* slot last board was found in */
+static  ahb_unit = 0;
+int     ahb_debug = 0;
 #define AHB_SHOWECBS 0x01
 #define AHB_SHOWINTS 0x02
 #define AHB_SHOWCMDS 0x04
 #define AHB_SHOWECBS 0x01
 #define AHB_SHOWINTS 0x02
 #define AHB_SHOWCMDS 0x04
@@ -321,7 +299,15 @@ int        ahb_debug = 0;
 #define SUCCESS 0
 #define PAGESIZ 4096
 
 #define SUCCESS 0
 #define PAGESIZ 4096
 
-struct scsi_switch     ahb_switch = 
+#ifdef KERNEL
+struct isa_driver ahbdriver =
+{
+       ahbprobe,
+       ahb_attach,
+       "ahb"
+};
+
+struct scsi_adapter ahb_switch =
 {
        ahb_scsi_cmd,
        ahbminphys,
 {
        ahb_scsi_cmd,
        ahbminphys,
@@ -329,400 +315,395 @@ struct  scsi_switch     ahb_switch =
        0,
        ahb_adapter_info,
        "ahb",
        0,
        ahb_adapter_info,
        "ahb",
-       0,0
+       { 0, 0 }
+};
+
+/* the below structure is so we have a default dev struct for our link struct */
+struct scsi_device ahb_dev =
+{
+    NULL,                      /* Use default error handler */
+    NULL,                      /* have a queue, served by this */
+    NULL,                      /* have no async handler */
+    NULL,                      /* Use default 'done' routine */
+    "ahb",
+    0,
+    { 0, 0 }
 };
 
 };
 
-/*\f*/
-/***********************************************************************\
-* Function to send a command out through a mailbox                     *
-\***********************************************************************/
-ahb_send_mbox( int             unit
-               ,int            opcode
-               ,int            target
-               ,struct ecb     *ecb)
+#endif /*KERNEL */
+
+#ifndef        KERNEL
+main()
+{
+       printf("ahb_data size is %d\n", sizeof(struct ahb_data));
+       printf("ecb size is %d\n", sizeof(struct ecb));
+}
+
+#else /*KERNEL */
+
+/*
+ * Function to send a command out through a mailbox
+ */
+void
+ahb_send_mbox(int unit, int opcode, int target, struct ecb *ecb)
 {
 {
-       int     port = ahb_data[unit].baseport;
-       int     spincount = FUDGE(delaycount) * 1; /* 1ms should be enough */
-       int     s = splbio();
-       int     stport = port + G2STAT;
-
-       while(      ((inb(stport) & (G2STAT_BUSY | G2STAT_MBOX_EMPTY))
-                                       != (G2STAT_MBOX_EMPTY))
-               && (spincount--));
-       if(spincount == -1)
-       {
-               printf("ahb%d: board not responding\n",unit);
+       int     port = ahbdata[unit]->baseport;
+       int     wait = 100;     /* 1ms should be enough */
+       int     stport = port + G2STAT;
+       int     s = splbio();
+
+       while (--wait) {
+               if ((inb(stport) & (G2STAT_BUSY | G2STAT_MBOX_EMPTY))
+                   == (G2STAT_MBOX_EMPTY))
+                       break;
+               DELAY(10);
+       }
+       if (wait == 0) {
+               printf("ahb%d: board not responding\n", unit);
                Debugger();
        }
                Debugger();
        }
-
-       outl(port + MBOXOUT0,KVTOPHYS(ecb));    /* don't know this will work */
-       outb(port + ATTN, opcode|target);
+       outl(port + MBOXOUT0, KVTOPHYS(ecb));   /* don't know this will work */
+       outb(port + ATTN, opcode | target);
 
        splx(s);
 }
 
 
        splx(s);
 }
 
-/***********************************************************************\
-* Function to poll for command completion when in poll mode            *
-\***********************************************************************/
-ahb_poll(int unit ,int wait) /* in msec  */
-{
-       int     port = ahb_data[unit].baseport;
-       int     spincount = FUDGE(delaycount) * wait; /* in msec */
-       int     stport = port + G2STAT;
-int    start = spincount;
-
-retry:
-       while( (spincount--) && (!(inb(stport) &  G2STAT_INT_PEND)));
-       if(spincount == -1)
-       {
-               printf("ahb%d: board not responding\n",unit);
-               return(EIO);
+/*
+ * Function to poll for command completion when in poll mode
+ */
+int
+ahb_poll(int unit, int wait)
+{                              /* in msec  */
+       struct ahb_data *ahb = ahbdata[unit];
+       int     port = ahb->baseport;
+       int     stport = port + G2STAT;
+
+      retry:
+       while (--wait) {
+               if (inb(stport) & G2STAT_INT_PEND)
+                       break;
+               DELAY(1000);
+       } if (wait == 0) {
+               printf("ahb%d: board not responding\n", unit);
+               return (EIO);
        }
        }
-if ((int)cheat != PHYSTOKV(inl(port + MBOXIN0)))
-{
-       printf("discarding %x ",inl(port + MBOXIN0));
-       outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
-       spinwait(50);
-       goto retry;
-}/* don't know this will work */
+       if (cheat != ahb_ecb_phys_kv(ahb, inl(port + MBOXIN0))) {
+               printf("discarding %x ", inl(port + MBOXIN0));
+               outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
+               DELAY(50000);
+               goto retry;
+       }
+       /* don't know this will work */
        ahbintr(unit);
        ahbintr(unit);
-       return(0);
+       return (0);
 }
 }
-/***********************************************************************\
-* Function to  send an immediate type command to the adapter           *
-\***********************************************************************/
-ahb_send_immed(        int             unit
-               ,int            target
-               ,u_long         cmd)
+
+/*
+ * Function to  send an immediate type command to the adapter
+ */
+void
+ahb_send_immed(int unit, int target, u_long cmd)
 {
 {
-       int     port = ahb_data[unit].baseport;
-       int     spincount = FUDGE(delaycount) * 1; /* 1ms should be enough */
-       int     s = splbio();
-       int     stport = port + G2STAT;
-
-       while(      ((inb(stport) & (G2STAT_BUSY | G2STAT_MBOX_EMPTY))
-                                       != (G2STAT_MBOX_EMPTY))
-               && (spincount--));
-       if(spincount == -1)
-       {
-               printf("ahb%d: board not responding\n",unit);
+       int     port = ahbdata[unit]->baseport;
+       int     s = splbio();
+       int     stport = port + G2STAT;
+       int     wait = 100;     /* 1 ms enough? */
+
+       while (--wait) {
+               if ((inb(stport) & (G2STAT_BUSY | G2STAT_MBOX_EMPTY))
+                   == (G2STAT_MBOX_EMPTY))
+                       break;
+               DELAY(10);
+       } if (wait == 0) {
+               printf("ahb%d: board not responding\n", unit);
                Debugger();
        }
                Debugger();
        }
-
-       outl(port + MBOXOUT0,cmd);      /* don't know this will work */
+       outl(port + MBOXOUT0, cmd);     /* don't know this will work */
        outb(port + G2CNTRL, G2CNTRL_SET_HOST_READY);
        outb(port + ATTN, OP_IMMED | target);
        splx(s);
 }
 
        outb(port + G2CNTRL, G2CNTRL_SET_HOST_READY);
        outb(port + ATTN, OP_IMMED | target);
        splx(s);
 }
 
-/*\f*/
-
-/*******************************************************\
-* Check  the slots looking for a board we recognise    *
-* If we find one, note it's address (slot) and call    *
-* the actual probe routine to check it out.            *
-\*******************************************************/
+/*
+ * Check the slots looking for a board we recognise
+ * If we find one, note it's address (slot) and call
+ * the actual probe routine to check it out.
+ */
+int
 ahbprobe(dev)
 ahbprobe(dev)
-struct isa_dev *dev;
+       struct isa_device *dev;
 {
 {
-       int     port;
-       u_char  byte1,byte2,byte3;
+       int     port;
+       u_char  byte1, byte2, byte3;
+
        ahb_slot++;
        ahb_slot++;
-       while (ahb_slot<8)
-       {
+       while (ahb_slot < 8) {
                port = 0x1000 * ahb_slot;
                byte1 = inb(port + HID0);
                byte2 = inb(port + HID1);
                byte3 = inb(port + HID2);
                port = 0x1000 * ahb_slot;
                byte1 = inb(port + HID0);
                byte2 = inb(port + HID1);
                byte3 = inb(port + HID2);
-               if(byte1 == 0xff)
-               {
+               if (byte1 == 0xff) {
                        ahb_slot++;
                        continue;
                }
                        ahb_slot++;
                        continue;
                }
-               if ((CHAR1(byte1,byte2) == 'A')
-                && (CHAR2(byte1,byte2) == 'D')
-                && (CHAR3(byte1,byte2) == 'P')
-                && ((byte3 == 0 ) || (byte3 == 1)))
-               {
-                       dev->dev_addr = port;
-                       return(ahbprobe1(dev));
+               if ((CHAR1(byte1, byte2) == 'A')
+                   && (CHAR2(byte1, byte2) == 'D')
+                   && (CHAR3(byte1, byte2) == 'P')
+                   && ((byte3 == 0) || (byte3 == 1))) {
+                       dev->id_iobase = port;
+                       return ahbprobe1(dev);
                }
                ahb_slot++;
        }
                }
                ahb_slot++;
        }
-       return(0);
+       return 0;
 }
 }
-/*******************************************************\
-* Check if the device can be found at the port given    *
-* and if so, set it up ready for further work           *
-* as an argument, takes the isa_dev structure from      *
-* autoconf.c                                            *
-\*******************************************************/
+
+/*
+ * Check if the device can be found at the port given
+ * and if so, set it up ready for further work
+ * as an argument, takes the isa_device structure from
+ * autoconf.c.
+ */
+int
 ahbprobe1(dev)
 ahbprobe1(dev)
-struct isa_dev *dev;
+       struct isa_device *dev;
 {
 {
-       /***********************************************\
-       * find unit and check we have that many defined *
-       \***********************************************/
-       int     unit = ahb_unit;
-#if defined(OSF)
-       static ihandler_t ahb_handler[NAHB];
-       static ihandler_id_t *ahb_handler_id[NAHB];
-       register ihandler_t *chp = &ahb_handler[unit];;
-#endif /* defined(OSF) */
-
-       dev->dev_unit = unit;
-       ahb_data[unit].baseport = dev->dev_addr;
-       if(unit >= NAHB) 
-       {
-               printf("ahb: unit number (%d) too high\n",unit);
-               return(0);
+       /*
+        * find unit and check we have that many defined
+        */
+       int     unit = ahb_unit;
+       struct  ahb_data *ahb;
+
+       if (unit >= NAHB) {
+               printf("ahb: unit number (%d) too high\n", unit);
+               return 0;
        }
        }
-       /***********************************************\
-       * Try initialise a unit at this location        *
-       * sets up dma and bus speed, loads ahb_data[unit].vect*
-       \***********************************************/
-       if (ahb_init(unit) != 0)
-       {
-               return(0);
+       dev->id_unit = unit;
+
+       /*
+        * Allocate a storage area for us
+        */
+       if (ahbdata[unit]) {
+               printf("ahb%d: memory already allocated\n", unit);
+               return 0;
        }
        }
-
-       /***********************************************\
-       * If it's there, put in it's interrupt vectors  *
-       \***********************************************/
-#ifdef MACH
-       dev->dev_pic = ahb_data[unit].vect;
-#if defined(OSF)                               /* OSF */
-       chp->ih_level = dev->dev_pic;
-       chp->ih_handler = dev->dev_intr[0];
-       chp->ih_resolver = i386_resolver;
-       chp->ih_rdev = dev;
-       chp->ih_stats.intr_type = INTR_DEVICE;
-       chp->ih_stats.intr_cnt = 0;
-       chp->ih_hparam[0].intparam = unit;
-       if ((ahb_handler_id[unit] = handler_add(chp)) != NULL)
-               handler_enable(ahb_handler_id[unit]);
-       else
-               panic("Unable to add ahb interrupt handler");
-#else                                          /* CMU */
-       take_dev_irq(dev);
-#endif /* !defined(OSF) */
-       printf("port=%x spl=%d\n", dev->dev_addr, dev->dev_spl);
-#endif MACH
-#ifdef  __386BSD__                             /* 386BSD */
-        dev->id_irq = (1 << ahb_data[unit].vect);
-        dev->id_drq = -1; /* use EISA dma */
-#endif  __386BSD__
+       ahb = malloc(sizeof(struct ahb_data), M_TEMP, M_NOWAIT);
+       if (!ahb) {
+               printf("ahb%d: cannot malloc!\n", unit);
+               return 0;
+       }
+       bzero(ahb, sizeof(struct ahb_data));
+       ahbdata[unit] = ahb;
+       ahb->baseport = dev->id_iobase;
+       /*
+        * Try initialise a unit at this location
+        * sets up dma and bus speed, loads ahb->vect
+        */
+       if (ahb_init(unit) != 0) {
+               ahbdata[unit] = NULL;
+               free(ahb, M_TEMP);
+               return (0);
+       }
+       /*
+        * If it's there, put in it's interrupt vectors
+        */
+       dev->id_irq = (1 << ahb->vect);
+       dev->id_drq = -1;       /* use EISA dma */
 
        ahb_unit++;
 
        ahb_unit++;
-       return(1);
+       return 0x1000;
 }
 
 }
 
-/***********************************************\
-* Attach all the sub-devices we can find       *
-\***********************************************/
+/*
+ * Attach all the sub-devices we can find
+ */
+int
 ahb_attach(dev)
 ahb_attach(dev)
-struct isa_dev *dev;
+       struct isa_device *dev;
 {
 {
-       int     unit = dev->dev_unit;
-
-       /***********************************************\
-       * ask the adapter what subunits are present     *
-       \***********************************************/
-       scsi_attachdevs( unit, ahb_data[unit].our_id, &ahb_switch);
-#if defined(OSF)
-       ahb_attached[unit]=1;
-#endif /* defined(OSF) */
-       return;
+#ifdef NetBSD
+       int     unit = dev->id_masunit;
+#else
+       int     unit = dev->id_unit;
+#endif
+       struct ahb_data *ahb = ahbdata[unit];
+
+       /*
+        * fill in the prototype scsi_link.
+        */
+       ahb->sc_link.adapter_unit = unit;
+       ahb->sc_link.adapter_targ = ahb->our_id;
+       ahb->sc_link.adapter = &ahb_switch;
+       ahb->sc_link.device = &ahb_dev;
+
+       /*
+        * ask the adapter what subunits are present
+        */
+       scsi_attachdevs(&(ahb->sc_link));
+
+       return 1;
 }
 
 }
 
-/***********************************************\
-* Return some information to the caller about   *
-* the adapter and it's capabilities             *
-\***********************************************/
-long int ahb_adapter_info(unit)
-int    unit;
+/*
+ * Return some information to the caller about
+ * the adapter and it's capabilities
+ */
+u_int32 
+ahb_adapter_info(unit)
+       int     unit;
 {
 {
-       return(2);      /* 2 outstanding requests at a time per device */
+       return (2);             /* 2 outstanding requests at a time per device */
 }
 
 }
 
-/***********************************************\
-* Catch an interrupt from the adaptor          *
-\***********************************************/
+/*
+ * Catch an interrupt from the adaptor
+ */
+int
 ahbintr(unit)
 ahbintr(unit)
+       int     unit;
 {
 {
-       struct ecb      *ecb;
-       unsigned char   stat;
-       register        i;
-       u_char          ahbstat;
-       int             target;
-       long int        mboxval;
+       struct ecb *ecb;
+       unsigned char stat;
+       u_char  ahbstat;
+       int     target;
+       long int mboxval;
+       struct ahb_data *ahb = ahbdata[unit];
 
 
-       int     port = ahb_data[unit].baseport;
+       int     port = ahb->baseport;
 
 #ifdef AHBDEBUG
 
 #ifdef AHBDEBUG
-       if(scsi_debug & PRINTROUTINES)
-               printf("ahbintr ");
-#endif /*AHBDEBUG*/
-
-#if defined(OSF)
-       if (!ahb_attached[unit])
-       {
-               return(1);
-       }
-#endif /* defined(OSF) */
-       while(inb(port + G2STAT) & G2STAT_INT_PEND)
-       {
-               /***********************************************\
-               * First get all the information and then        *
-               * acknowlege the interrupt                      *
-               \***********************************************/
+       printf("ahbintr ");
+#endif /*AHBDEBUG */
+
+       while (inb(port + G2STAT) & G2STAT_INT_PEND) {
+               /*
+                * First get all the information and then 
+                * acknowlege the interrupt
+                */
                ahbstat = inb(port + G2INTST);
                target = ahbstat & G2INTST_TARGET;
                stat = ahbstat & G2INTST_INT_STAT;
                ahbstat = inb(port + G2INTST);
                target = ahbstat & G2INTST_TARGET;
                stat = ahbstat & G2INTST_INT_STAT;
-               mboxval = inl(port + MBOXIN0);/* don't know this will work */
+               mboxval = inl(port + MBOXIN0);  /* don't know this will work */
                outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
 #ifdef AHBDEBUG
                outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
 #ifdef AHBDEBUG
-               if(scsi_debug & TRACEINTERRUPTS)
-                       printf("status = 0x%x ",stat);
-#endif /*AHBDEBUG*/
-               /***********************************************\
-               * Process the completed operation               *
-               \***********************************************/
-       
-               if(stat == AHB_ECB_OK) /* common case is fast */
-               {
-                       ecb = (struct ecb *)PHYSTOKV(mboxval); 
-               }
-               else
-               {
-                       switch(stat)
-                       {
-                       case    AHB_IMMED_OK:
-                               ecb = ahb_data[unit].immed_ecb;
-                               ahb_data[unit].immed_ecb = 0;
+               printf("status = 0x%x ", stat);
+#endif /*AHBDEBUG */
+               /*
+                * Process the completed operation
+                */
+
+               if (stat == AHB_ECB_OK) {       /* common case is fast */
+                       ecb = ahb_ecb_phys_kv(ahb, mboxval);
+               } else {
+                       switch (stat) {
+                       case AHB_IMMED_OK:
+                               ecb = ahb->immed_ecb;
+                               ahb->immed_ecb = 0;
                                break;
                                break;
-                       case    AHB_IMMED_ERR:
-                               ecb = ahb_data[unit].immed_ecb;
+                       case AHB_IMMED_ERR:
+                               ecb = ahb->immed_ecb;
                                ecb->flags |= ECB_IMMED_FAIL;
                                ecb->flags |= ECB_IMMED_FAIL;
-                               ahb_data[unit].immed_ecb = 0;
+                               ahb->immed_ecb = 0;
                                break;
                                break;
-                       case    AHB_ASN:        /* for target mode */
+                       case AHB_ASN:   /* for target mode */
                                printf("ahb%d: Unexpected ASN interrupt(%x)\n",
                                printf("ahb%d: Unexpected ASN interrupt(%x)\n",
-                                       unit, mboxval);
+                                   unit, mboxval);
                                ecb = 0;
                                break;
                                ecb = 0;
                                break;
-                       case    AHB_HW_ERR:
+                       case AHB_HW_ERR:
                                printf("ahb%d: Hardware error interrupt(%x)\n",
                                printf("ahb%d: Hardware error interrupt(%x)\n",
-                                       unit, mboxval);
+                                   unit, mboxval);
                                ecb = 0;
                                break;
                                ecb = 0;
                                break;
-                       case    AHB_ECB_RECOVERED:
-                               ecb = (struct ecb *)PHYSTOKV(mboxval); 
+                       case AHB_ECB_RECOVERED:
+                               ecb = ahb_ecb_phys_kv(ahb, mboxval);
                                break;
                                break;
-                       case    AHB_ECB_ERR:
-                               ecb = (struct ecb *)PHYSTOKV(mboxval); 
+                       case AHB_ECB_ERR:
+                               ecb = ahb_ecb_phys_kv(ahb, mboxval);
                                break;
                        default:
                                break;
                        default:
-                               printf(" Unknown return from ahb%d(%x)\n",unit,ahbstat);
-                               ecb=0;
+                               printf(" Unknown return from ahb%d(%x)\n", unit, ahbstat);
+                               ecb = 0;
                        }
                        }
-               }
-               if(ecb)
-               {
+               } if (ecb) {
 #ifdef AHBDEBUG
 #ifdef AHBDEBUG
-                       if(ahb_debug & AHB_SHOWCMDS )
-                       {
-                               ahb_show_scsi_cmd(ecb->xs);
+                       if (ahb_debug & AHB_SHOWCMDS) {
+                               show_scsi_cmd(ecb->xs);
                        }
                        }
-                       if((ahb_debug & AHB_SHOWECBS) && ecb)
-                               printf("<int ecb(%x)>",ecb);
-#endif /*AHBDEBUG*/
-                       untimeout(ahb_timeout,ecb);
-                       ahb_done(unit,ecb,((stat == AHB_ECB_OK)?SUCCESS:FAIL));
+                       if ((ahb_debug & AHB_SHOWECBS) && ecb)
+                               printf("<int ecb(%x)>", ecb);
+#endif /*AHBDEBUG */
+                       untimeout((timeout_t)ahb_timeout, (caddr_t)ecb);
+                       ahb_done(unit, ecb, ((stat == AHB_ECB_OK) ? SUCCESS : FAIL));
                }
        }
                }
        }
-       return(1);
+       return 1;
 }
 
 }
 
-/***********************************************\
-* We have a ecb which has been processed by the        *
-* adaptor, now we look to see how the operation        *
-* went.                                                *
-\***********************************************/
-ahb_done(unit,ecb,state)
-int    unit,state;
-struct ecb *ecb;
+/*
+ * We have a ecb which has been processed by the
+ * adaptor, now we look to see how the operation
+ * went.
+ */
+void
+ahb_done(unit, ecb, state)
+       int    unit, state;
+       struct ecb *ecb;
 {
 {
-       struct  ahb_ecb_status  *stat = &ecb->ecb_status;
-       struct  scsi_sense_data *s1,*s2;
-       struct  scsi_xfer *xs = ecb->xs;
-
-#ifdef AHBDEBUG
-       if(scsi_debug & (PRINTROUTINES | TRACEINTERRUPTS))
-               printf("ahb_done ");
-#endif /*AHBDEBUG*/
-       /***********************************************\
-       * Otherwise, put the results of the operation   *
-       * into the xfer and call whoever started it     *
-       \***********************************************/
-       if(ecb->flags & ECB_IMMED)
-       {
-               if(ecb->flags & ECB_IMMED_FAIL)
-               {
+       struct ahb_ecb_status *stat = &ecb->ecb_status;
+       struct scsi_sense_data *s1, *s2;
+       struct scsi_xfer *xs = ecb->xs;
+
+       SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahb_done\n"));
+       /*
+        * Otherwise, put the results of the operation
+        * into the xfer and call whoever started it
+        */
+       if (ecb->flags & ECB_IMMED) {
+               if (ecb->flags & ECB_IMMED_FAIL) {
                        xs->error = XS_DRIVER_STUFFUP;
                }
                goto done;
        }
                        xs->error = XS_DRIVER_STUFFUP;
                }
                goto done;
        }
-       if ( (state == SUCCESS) || (xs->flags & SCSI_ERR_OK))
-       {               /* All went correctly  OR errors expected */
+       if ((state == SUCCESS) || (xs->flags & SCSI_ERR_OK)) {  /* All went correctly  OR errors expected */
                xs->resid = 0;
                xs->error = 0;
                xs->resid = 0;
                xs->error = 0;
-       }
-       else
-       {
+       } else {
 
                s1 = &(ecb->ecb_sense);
                s2 = &(xs->sense);
 
 
                s1 = &(ecb->ecb_sense);
                s2 = &(xs->sense);
 
-               if(stat->ha_status)
-               {
-                       switch(stat->ha_status)
-                       {
-                       case    HS_SCSI_RESET_ADAPTER:
+               if (stat->ha_status) {
+                       switch (stat->ha_status) {
+                       case HS_SCSI_RESET_ADAPTER:
                                break;
                                break;
-                       case    HS_SCSI_RESET_INCOMING:
+                       case HS_SCSI_RESET_INCOMING:
                                break;
                                break;
-                       case    HS_CMD_ABORTED_HOST:    /* No response */
-                       case    HS_CMD_ABORTED_ADAPTER: /* No response */
+                       case HS_CMD_ABORTED_HOST:       /* No response */
+                       case HS_CMD_ABORTED_ADAPTER:    /* No response */
                                break;
                                break;
-                       case    HS_TIMED_OUT:           /* No response */
+                       case HS_TIMED_OUT:      /* No response */
 #ifdef AHBDEBUG
 #ifdef AHBDEBUG
-                               if (ahb_debug & AHB_SHOWMISC)
-                               {
+                               if (ahb_debug & AHB_SHOWMISC) {
                                        printf("timeout reported back\n");
                                }
                                        printf("timeout reported back\n");
                                }
-#endif /*AHBDEBUG*/
+#endif /*AHBDEBUG */
                                xs->error = XS_TIMEOUT;
                                break;
                        default:        /* Other scsi protocol messes */
                                xs->error = XS_DRIVER_STUFFUP;
 #ifdef AHBDEBUG
                                xs->error = XS_TIMEOUT;
                                break;
                        default:        /* Other scsi protocol messes */
                                xs->error = XS_DRIVER_STUFFUP;
 #ifdef AHBDEBUG
-                               if (ahb_debug & AHB_SHOWMISC)
-                               {
+                               if (ahb_debug & AHB_SHOWMISC) {
                                        printf("unexpected ha_status: %x\n",
                                        printf("unexpected ha_status: %x\n",
-                                               stat->ha_status);
+                                           stat->ha_status);
                                }
                                }
-#endif /*AHBDEBUG*/
+#endif /*AHBDEBUG */ 
                        }
                        }
-
-               }
-               else
-               {
-                       switch(stat->targ_status)
-                       {
+               } else {
+                       switch (stat->targ_status) {
                        case TS_CHECK_CONDITION:
                        case TS_CHECK_CONDITION:
-                               /* structure copy!!!!!*/
-                               *s2=*s1;
+                               /* structure copy!!!!! */
+                               *s2 = *s1;
                                xs->error = XS_SENSE;
                                break;
                        case TS_BUSY:
                                xs->error = XS_SENSE;
                                break;
                        case TS_BUSY:
@@ -730,352 +711,339 @@ struct ecb *ecb;
                                break;
                        default:
 #ifdef AHBDEBUG
                                break;
                        default:
 #ifdef AHBDEBUG
-                               if (ahb_debug & AHB_SHOWMISC)
-                               {
+                               if (ahb_debug & AHB_SHOWMISC) {
                                        printf("unexpected targ_status: %x\n",
                                        printf("unexpected targ_status: %x\n",
-                                               stat->targ_status);
+                                           stat->targ_status);
                                }
                                }
-#endif /*AHBDEBUG*/
+#endif /*AHBDEBUG */
                                xs->error = XS_DRIVER_STUFFUP;
                        }
                }
        }
 done:  xs->flags |= ITSDONE;
                                xs->error = XS_DRIVER_STUFFUP;
                        }
                }
        }
 done:  xs->flags |= ITSDONE;
-       ahb_free_ecb(unit,ecb, xs->flags);
-       if(xs->when_done)
-               (*(xs->when_done))(xs->done_arg,xs->done_arg2);
+       ahb_free_ecb(unit, ecb, xs->flags);
+       scsi_done(xs);
 }
 
 }
 
-/***********************************************\
-* A ecb (and hence a mbx-out is put onto the   *
-* free list.                                   *
-\***********************************************/
-ahb_free_ecb(unit,ecb, flags)
-struct ecb *ecb;
+/*
+ * A ecb (and hence a mbx-out is put onto the 
+ * free list.
+ */
+void
+ahb_free_ecb(unit, ecb, flags)
+       int     unit, flags;
+       struct  ecb *ecb;
 {
        unsigned int opri;
 {
        unsigned int opri;
-       
-#ifdef AHBDEBUG
-       if(scsi_debug & PRINTROUTINES)
-               printf("ecb%d(0x%x)> ",unit,flags);
-#endif /*AHBDEBUG*/
-       if (!(flags & SCSI_NOMASK)) 
-               opri = splbio();
-
-       ecb->next = ahb_data[unit].free_ecb;
-       ahb_data[unit].free_ecb = ecb;
+       struct ahb_data *ahb = ahbdata[unit];
+
+       if (!(flags & SCSI_NOMASK))
+               opri = splbio();
+
+       ecb->next = ahb->free_ecb;
+       ahb->free_ecb = ecb;
        ecb->flags = ECB_FREE;
        ecb->flags = ECB_FREE;
-       /***********************************************\
-       * If there were none, wake abybody waiting for  *
-       * one to come free, starting with queued entries*
-       \***********************************************/
+       /*
+        * If there were none, wake abybody waiting for
+        * one to come free, starting with queued entries
+        */
        if (!ecb->next) {
        if (!ecb->next) {
-               wakeup(&ahb_data[unit].free_ecb);
+               wakeup((caddr_t)&ahb->free_ecb);
        }
        }
-       if (!(flags & SCSI_NOMASK)) 
+       if (!(flags & SCSI_NOMASK))
                splx(opri);
 }
 
                splx(opri);
 }
 
-/***********************************************\
-* Get a free ecb (and hence mbox-out entry)    *
-\***********************************************/
+/*
+ * Get a free ecb 
+ * If there are none, see if we can allocate a
+ * new one. If so, put it in the hash table too
+ * otherwise either return an error or sleep
+ */
 struct ecb *
 struct ecb *
-ahb_get_ecb(unit,flags)
+ahb_get_ecb(unit, flags)
+       int     unit, flags;
 {
 {
+       struct ahb_data *ahb = ahbdata[unit];
        unsigned opri;
        unsigned opri;
-       struct ecb *rc;
+       struct ecb *ecbp;
+       int     hashnum;
 
 
-#ifdef AHBDEBUG
-       if(scsi_debug & PRINTROUTINES)
-               printf("<ecb%d(0x%x) ",unit,flags);
-#endif /*AHBDEBUG*/
-       if (!(flags & SCSI_NOMASK)) 
-               opri = splbio();
-       /***********************************************\
-       * If we can and have to, sleep waiting for one  *
-       * to come free                                  *
-       \***********************************************/
-       while ((!(rc = ahb_data[unit].free_ecb)) && (!(flags & SCSI_NOSLEEP)))
-       {
-               sleep(&ahb_data[unit].free_ecb, PRIBIO);
-       }
-       if (rc) 
-       {
-               ahb_data[unit].free_ecb = rc->next;
-               rc->flags = ECB_ACTIVE;
+       if (!(flags & SCSI_NOMASK))
+               opri = splbio();
+       /*
+        * If we can and have to, sleep waiting for one to come free
+        * but only if we can't allocate a new one.
+        */
+       while (!(ecbp = ahb->free_ecb)) {
+               if (ahb->numecbs < AHB_ECB_MAX) {
+                       ecbp = (struct ecb *) malloc(sizeof(struct ecb),
+                               M_TEMP,
+                               M_NOWAIT);
+                       if (ecbp) {
+                               bzero(ecbp, sizeof(struct ecb));
+                               ahb->numecbs++;
+                               ecbp->flags = ECB_ACTIVE;
+                               /*
+                                * put in the phystokv hash table
+                                * Never gets taken out.
+                                */
+                               ecbp->hashkey = KVTOPHYS(ecbp);
+                               hashnum = ECB_HASH(ecbp->hashkey);
+                               ecbp->nexthash = ahb->ecbhash[hashnum];
+                               ahb->ecbhash[hashnum] = ecbp;
+                       } else {
+                               printf("ahb%d: Can't malloc ECB\n", unit);
+                       } goto gottit;
+               } else {
+                       if (!(flags & SCSI_NOSLEEP)) {
+                               tsleep((caddr_t)&ahb->free_ecb, PRIBIO,
+                                   "ahbecb", 0);
+                       }
+               }
+       } if (ecbp) {
+               /* Get ECB from from free list */
+               ahb->free_ecb = ecbp->next;
+               ecbp->flags = ECB_ACTIVE;
        }
        }
-       if (!(flags & SCSI_NOMASK)) 
+gottit:        if (!(flags & SCSI_NOMASK))
                splx(opri);
                splx(opri);
-       return(rc);
+
+       return (ecbp);
 }
 }
-               
 
 
+/*
+ * given a physical address, find the ecb that
+ * it corresponds to:
+ */
+struct ecb *
+ahb_ecb_phys_kv(ahb, ecb_phys)
+       struct ahb_data *ahb;
+       physaddr ecb_phys;
+{
+       int     hashnum = ECB_HASH(ecb_phys);
+       struct ecb *ecbp = ahb->ecbhash[hashnum];
 
 
-/***********************************************\
-* Start the board, ready for normal operation  *
-\***********************************************/
+       while (ecbp) {
+               if (ecbp->hashkey == ecb_phys)
+                       break;
+               ecbp = ecbp->nexthash;
+       }
+       return ecbp;
+}
+
+/*
+ * Start the board, ready for normal operation
+ */
+int
 ahb_init(unit)
 ahb_init(unit)
-int    unit;
+       int     unit;
 {
 {
-       int     port = ahb_data[unit].baseport;
-       int     intdef;
-       int     spincount = FUDGE(delaycount) * 1000; /* 1 sec enough? */
-       int     i;
-       int     stport = port + G2STAT;
+       struct ahb_data *ahb = ahbdata[unit];
+       int     port = ahb->baseport;
+       int     intdef;
+       int     wait = 1000;    /* 1 sec enough? */
+       int     i;
+       int     stport = port + G2STAT;
 #define        NO_NO 1
 #ifdef NO_NO
 #define        NO_NO 1
 #ifdef NO_NO
-       /***********************************************\
-       * reset board, If it doesn't respond, assume    *
-       * that it's not there.. good for the probe      *
-       \***********************************************/
-       outb(port + EBCTRL,CDEN);       /* enable full card */
-       outb(port + PORTADDR,PORTADDR_ENHANCED);
-
-       outb(port + G2CNTRL,G2CNTRL_HARD_RESET);
-       spinwait(1);
-       outb(port + G2CNTRL,0);
-       spinwait(10);
-       while(      ((inb(stport) & G2STAT_BUSY ))
-               && (spincount--));
-       if(spincount == -1)
-       {
+       /*
+        * reset board, If it doesn't respond, assume 
+        * that it's not there.. good for the probe
+        */
+       outb(port + EBCTRL, CDEN);      /* enable full card */
+       outb(port + PORTADDR, PORTADDR_ENHANCED);
+
+       outb(port + G2CNTRL, G2CNTRL_HARD_RESET);
+       DELAY(1000);
+       outb(port + G2CNTRL, 0);
+       DELAY(10000);
+       while (--wait) {
+               if ((inb(stport) & G2STAT_BUSY) == 0)
+                       break;
+               DELAY(1000);
+       } if (wait == 0) {
 #ifdef AHBDEBUG
                if (ahb_debug & AHB_SHOWMISC)
 #ifdef AHBDEBUG
                if (ahb_debug & AHB_SHOWMISC)
-                       printf("ahb_init: No answer from bt742a board\n");
-#endif /*AHBDEBUG*/
-               return(ENXIO);
+                       printf("ahb_init: No answer from aha1742 board\n");
+#endif /*AHBDEBUG */
+               return (ENXIO);
        }
        i = inb(port + MBOXIN0) & 0xff;
        }
        i = inb(port + MBOXIN0) & 0xff;
-       if(i)
-       {
-               printf("self test failed, val = 0x%x\n",i);
-               return(EIO);
+       if (i) {
+               printf("self test failed, val = 0x%x\n", i);
+               return (EIO);
        }
 #endif
        }
 #endif
-       while( inb(stport) &  G2STAT_INT_PEND)
-       {
+       while (inb(stport) & G2STAT_INT_PEND) {
                printf(".");
                outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
                printf(".");
                outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
-               spinwait(10);
+               DELAY(10000);
        }
        }
-       outb(port + EBCTRL,CDEN);       /* enable full card */
-       outb(port + PORTADDR,PORTADDR_ENHANCED);
-       /***********************************************\
-       * Assume we have a board at this stage          *
-       * setup dma channel from jumpers and save int   *
-       * level                                         *
-       \***********************************************/
-#ifdef __386BSD__
-       printf("ahb%d: reading board settings, ",unit);
-#else  __386BSD__
-       printf("ahb%d:",unit);
-#endif __386BSD__
+       outb(port + EBCTRL, CDEN);      /* enable full card */
+       outb(port + PORTADDR, PORTADDR_ENHANCED);
+       /*
+        * Assume we have a board at this stage
+        * setup dma channel from jumpers and save int
+        * level
+        */
+       printf("ahb%d: reading board settings, ", unit);
 
        intdef = inb(port + INTDEF);
 
        intdef = inb(port + INTDEF);
-       switch(intdef & 0x07)
-       {
-       case    INT9:
-               ahb_data[unit].vect = 9;
+       switch (intdef & 0x07) {
+       case INT9:
+               ahb->vect = 9;
                break;
                break;
-       case    INT10:
-               ahb_data[unit].vect = 10;
+       case INT10:
+               ahb->vect = 10;
                break;
                break;
-       case    INT11:
-               ahb_data[unit].vect = 11;
+       case INT11:
+               ahb->vect = 11;
                break;
                break;
-       case    INT12:
-               ahb_data[unit].vect = 12;
+       case INT12:
+               ahb->vect = 12;
                break;
                break;
-       case    INT14:
-               ahb_data[unit].vect = 14;
+       case INT14:
+               ahb->vect = 14;
                break;
                break;
-       case    INT15:
-               ahb_data[unit].vect = 15;
+       case INT15:
+               ahb->vect = 15;
                break;
        default:
                printf("illegal int setting\n");
                break;
        default:
                printf("illegal int setting\n");
-               return(EIO);
-       }
-#ifdef __386BSD__
-       printf("int=%d\n",ahb_data[unit].vect);
-#else  __386BSD__
-       printf("int=%d ",ahb_data[unit].vect);
-#endif __386BSD__
-
-       outb(port + INTDEF ,(intdef | INTEN)); /* make sure we can interrupt */
-       /* who are we on the scsi bus */
-       ahb_data[unit].our_id = (inb(port + SCSIDEF) & HSCSIID);
-
-       /***********************************************\
-       * link up all our ECBs into a free list         *
-       \***********************************************/
-       for (i=0; i < NUM_CONCURRENT; i++)
-       {
-               ahb_data[unit].ecbs[i].next = ahb_data[unit].free_ecb;
-               ahb_data[unit].free_ecb = &ahb_data[unit].ecbs[i];
-               ahb_data[unit].free_ecb->flags = ECB_FREE;
+               return (EIO);
        }
        }
+       printf("int=%d\n", ahb->vect);
 
 
-       /***********************************************\
-       * Note that we are going and return (to probe)  *
-       \***********************************************/
-       ahb_data[unit].flags |= AHB_INIT;
-       return( 0 );
-}
+       outb(port + INTDEF, (intdef | INTEN));  /* make sure we can interrupt */
 
 
+       /* who are we on the scsi bus? */
+       ahb->our_id = (inb(port + SCSIDEF) & HSCSIID);
+
+       /*
+        * Note that we are going and return (to probe)
+        */
+       ahb->flags |= AHB_INIT;
+       return (0);
+}
 
 #ifndef        min
 #define min(x,y) (x < y ? x : y)
 
 #ifndef        min
 #define min(x,y) (x < y ? x : y)
-#endif min
-
+#endif /* min */ 
 
 
-void ahbminphys(bp)
-struct buf *bp;
+void
+ahbminphys(bp)
+       struct buf *bp;
 {
 {
-#ifdef MACH
-#if    !defined(OSF)
-       bp->b_flags |= B_NPAGES;                /* can support scat/gather */
-#endif /* defined(OSF) */
-#endif MACH
-       if(bp->b_bcount > ((AHB_NSEG-1) * PAGESIZ))
-       {
-               bp->b_bcount = ((AHB_NSEG-1) * PAGESIZ);
+       if (bp->b_bcount > ((AHB_NSEG - 1) * PAGESIZ)) {
+               bp->b_bcount = ((AHB_NSEG - 1) * PAGESIZ);
        }
 }
        }
 }
-       
-/***********************************************\
-* start a scsi operation given the command and *
-* the data address. Also needs the unit, target        *
-* and lu                                       *
-\***********************************************/
-int    ahb_scsi_cmd(xs)
-struct scsi_xfer *xs;
+
+/*
+ * start a scsi operation given the command and
+ * the data address. Also needs the unit, target
+ * and lu
+ */
+int32 
+ahb_scsi_cmd(xs)
+       struct scsi_xfer *xs;
 {
 {
-       struct  scsi_sense_data *s1,*s2;
        struct ecb *ecb;
        struct ahb_dma_seg *sg;
        struct ecb *ecb;
        struct ahb_dma_seg *sg;
-       int     seg;    /* scatter gather seg being worked on */
-       int i   = 0;
-       int rc  =  0;
-       int     thiskv;
-       physaddr        thisphys,nextphys;
-       int     unit =xs->adapter;
-       int     bytes_this_seg,bytes_this_page,datalen,flags;
-       struct  iovec   *iovp;
-       int     s;
-#ifdef AHBDEBUG
-       if(scsi_debug & PRINTROUTINES)
-               printf("ahb_scsi_cmd ");
-#endif /*AHBDEBUG*/
-       /***********************************************\
-       * get a ecb (mbox-out) to use. If the transfer  *
-       * is from a buf (possibly from interrupt time)  *
-       * then we can't allow it to sleep               *
-       \***********************************************/
+       int     seg;            /* scatter gather seg being worked on */
+       int     thiskv;
+       physaddr thisphys, nextphys;
+       int     unit = xs->sc_link->adapter_unit;
+       int     bytes_this_seg, bytes_this_page, datalen, flags;
+       struct ahb_data *ahb = ahbdata[unit];
+       int     s;
+
+       SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahb_scsi_cmd\n"));
+       /*
+        * get a ecb (mbox-out) to use. If the transfer
+        * is from a buf (possibly from interrupt time)
+        * then we can't allow it to sleep
+        */
        flags = xs->flags;
        flags = xs->flags;
-       if(xs->bp) flags |= (SCSI_NOSLEEP); /* just to be sure */
-       if(flags & ITSDONE)
-       {
-               printf("ahb%d: Already done?",unit);
+       if (xs->bp)
+               flags |= (SCSI_NOSLEEP);        /* just to be sure */
+       if (flags & ITSDONE) {
+               printf("ahb%d: Already done?", unit);
                xs->flags &= ~ITSDONE;
        }
                xs->flags &= ~ITSDONE;
        }
-       if(!(flags & INUSE))
-       {
-               printf("ahb%d: Not in use?",unit);
+       if (!(flags & INUSE)) {
+               printf("ahb%d: Not in use?", unit);
                xs->flags |= INUSE;
        }
                xs->flags |= INUSE;
        }
-       if (!(ecb = ahb_get_ecb(unit,flags)))
-       {
+       if (!(ecb = ahb_get_ecb(unit, flags))) {
                xs->error = XS_DRIVER_STUFFUP;
                xs->error = XS_DRIVER_STUFFUP;
-               return(TRY_AGAIN_LATER);
+               return (TRY_AGAIN_LATER);
        }
        }
-
-cheat = ecb;
-#ifdef AHBDEBUG
-       if(ahb_debug & AHB_SHOWECBS)
-                               printf("<start ecb(%x)>",ecb);
-       if(scsi_debug & SHOWCOMMANDS)
-       {
-               ahb_show_scsi_cmd(xs);
-       }
-#endif /*AHBDEBUG*/
+       cheat = ecb;
+       SC_DEBUG(xs->sc_link, SDEV_DB3, ("start ecb(%x)\n", ecb));
        ecb->xs = xs;
        ecb->xs = xs;
-       /***********************************************\
-       * If it's a reset, we need to do an 'immediate' *
-       * command, and store it's ccb for later         *
-       * if there is already an immediate waiting,     *
-       * then WE must wait                             *
-       \***********************************************/
-       if(flags & SCSI_RESET)
-       {
+       /*
+        * If it's a reset, we need to do an 'immediate'
+        * command, and store it's ecb for later
+        * if there is already an immediate waiting, 
+        * then WE must wait
+        */
+       if (flags & SCSI_RESET) {
                ecb->flags |= ECB_IMMED;
                ecb->flags |= ECB_IMMED;
-               if(ahb_data[unit].immed_ecb)
-               {
-                       return(TRY_AGAIN_LATER);
+               if (ahb->immed_ecb) {
+                       return (TRY_AGAIN_LATER);
                }
                }
-               ahb_data[unit].immed_ecb = ecb;
-               if (!(flags & SCSI_NOMASK))
-               {
+               ahb->immed_ecb = ecb;
+               if (!(flags & SCSI_NOMASK)) {
                        s = splbio();
                        s = splbio();
-                       ahb_send_immed(unit,xs->targ,AHB_TARG_RESET);
-                       timeout(ahb_timeout,ecb,(xs->timeout * hz)/1000);
+                       ahb_send_immed(unit, xs->sc_link->target, AHB_TARG_RESET);
+                       timeout((timeout_t)ahb_timeout, (caddr_t)ecb, (xs->timeout * hz) / 1000);
                        splx(s);
                        splx(s);
-                       return(SUCCESSFULLY_QUEUED);
-               }
-               else
-               {
-                       ahb_send_immed(unit,xs->targ,AHB_TARG_RESET);
-                       /***********************************************\
-                       * If we can't use interrupts, poll on completion*
-                       \***********************************************/
-#ifdef AHBDEBUG
-                       if(scsi_debug & TRACEINTERRUPTS)
-                               printf("wait ");
-#endif /*AHBDEBUG*/
-                       if( ahb_poll(unit,xs->timeout))
-                       {
-                               ahb_free_ecb(unit,ecb,flags);
+                       return (SUCCESSFULLY_QUEUED);
+               } else {
+                       ahb_send_immed(unit, xs->sc_link->target, AHB_TARG_RESET);
+                       /*
+                        * If we can't use interrupts, poll on completion
+                        */
+                       SC_DEBUG(xs->sc_link, SDEV_DB3, ("wait\n"));
+                       if (ahb_poll(unit, xs->timeout)) {
+                               ahb_free_ecb(unit, ecb, flags);
                                xs->error = XS_TIMEOUT;
                                xs->error = XS_TIMEOUT;
-                               return(HAD_ERROR);
+                               return (HAD_ERROR);
                        }
                        }
-                       return(COMPLETE);
+                       return (COMPLETE);
                }
                }
-       }       
-       /***********************************************\
-       * Put all the arguments for the xfer in the ecb *
-       \***********************************************/
+       }
+       /*
+        * Put all the arguments for the xfer in the ecb
+        */
        ecb->opcode = ECB_SCSI_OP;
        ecb->opcode = ECB_SCSI_OP;
-       ecb->opt1 = ECB_SES|ECB_DSB|ECB_ARS;
-       if(xs->datalen)
-       {
+       ecb->opt1 = ECB_SES | ECB_DSB | ECB_ARS;
+       if (xs->datalen) {
                ecb->opt1 |= ECB_S_G;
        }
                ecb->opt1 |= ECB_S_G;
        }
-       ecb->opt2               =       xs->lu | ECB_NRB;
-       ecb->cdblen             =       xs->cmdlen;
-       ecb->sense              =       KVTOPHYS(&(ecb->ecb_sense));
-       ecb->senselen           =       sizeof(ecb->ecb_sense);
-       ecb->status             =       KVTOPHYS(&(ecb->ecb_status));
-
-       if(xs->datalen)
-       { /* should use S/G only if not zero length */
-               ecb->data       =       KVTOPHYS(ecb->ahb_dma);
-               sg              =       ecb->ahb_dma ;
-               seg             =       0;
-               if(flags & SCSI_DATA_UIO)
-               {
-                       iovp = ((struct uio *)xs->data)->uio_iov;
-                       datalen = ((struct uio *)xs->data)->uio_iovcnt;
+       ecb->opt2 = xs->sc_link->lun | ECB_NRB;
+       ecb->cdblen = xs->cmdlen;
+       ecb->sense = KVTOPHYS(&(ecb->ecb_sense));
+       ecb->senselen = sizeof(ecb->ecb_sense);
+       ecb->status = KVTOPHYS(&(ecb->ecb_status));
+
+       if (xs->datalen) {      /* should use S/G only if not zero length */
+               ecb->data = KVTOPHYS(ecb->ahb_dma);
+               sg = ecb->ahb_dma;
+               seg = 0;
+#ifdef TFS
+               if (flags & SCSI_DATA_UIO) {
+                       iovp = ((struct uio *) xs->data)->uio_iov;
+                       datalen = ((struct uio *) xs->data)->uio_iovcnt;
                        xs->datalen = 0;
                        xs->datalen = 0;
-                       while ((datalen) && (seg < AHB_NSEG))
-                       {
-                               sg->addr = (physaddr)iovp->iov_base;
-                               xs->datalen += sg->len = iovp->iov_len; 
-#ifdef AHBDEBUG
-                               if(scsi_debug & SHOWSCATGATH)
-                                       printf("(0x%x@0x%x)"
-                                                       ,iovp->iov_len
-                                                       ,iovp->iov_base);
-#endif /*AHBDEBUG*/
+                       while ((datalen) && (seg < AHB_NSEG)) {
+                               sg->addr = (physaddr) iovp->iov_base;
+                               xs->datalen += sg->len = iovp->iov_len;
+                               SC_DEBUGN(xs->sc_link, SDEV_DB4,
+                                   ("(0x%x@0x%x)", iovp->iov_len
+                                       ,iovp->iov_base));
                                sg++;
                                iovp++;
                                seg++;
                                sg++;
                                iovp++;
                                seg++;
@@ -1083,240 +1051,198 @@ cheat = ecb;
                        }
                }
                else
                        }
                }
                else
+#endif /*TFS */
                {
                {
-                       /***********************************************\
-                       * Set up the scatter gather block               *
-                       \***********************************************/
-               
-#ifdef AHBDEBUG
-                       if(scsi_debug & SHOWSCATGATH)
-                               printf("%d @0x%x:- ",xs->datalen,xs->data);
-#endif /*AHBDEBUG*/
-                       datalen         =       xs->datalen;
-                       thiskv          =       (int)xs->data;
-                       thisphys        =       KVTOPHYS(thiskv);
-               
-                       while ((datalen) && (seg < AHB_NSEG))
-                       {
-                               bytes_this_seg  = 0;
-       
+                       /*
+                        * Set up the scatter gather block
+                        */
+
+                       SC_DEBUG(xs->sc_link, SDEV_DB4,
+                           ("%d @0x%x:- ", xs->datalen, xs->data));
+                       datalen = xs->datalen;
+                       thiskv = (int) xs->data;
+                       thisphys = KVTOPHYS(thiskv);
+
+                       while ((datalen) && (seg < AHB_NSEG)) {
+                               bytes_this_seg = 0;
+
                                /* put in the base address */
                                sg->addr = thisphys;
                                /* put in the base address */
                                sg->addr = thisphys;
-               
-#ifdef AHBDEBUG
-                               if(scsi_debug & SHOWSCATGATH)
-                                       printf("0x%x",thisphys);
-#endif /*AHBDEBUG*/
-       
+
+                               SC_DEBUGN(xs->sc_link, SDEV_DB4, ("0x%x", thisphys));
+
                                /* do it at least once */
                                /* do it at least once */
-                               nextphys = thisphys;    
-                               while ((datalen) && (thisphys == nextphys))
-                               /*********************************************\
-                               * This page is contiguous (physically) with   *
-                               * the the last, just extend the length        *
-                               \*********************************************/
-                               {
+                               nextphys = thisphys;
+                               while ((datalen) && (thisphys == nextphys)) {
+                                       /*
+                                        * This page is contiguous (physically) with   
+                                        * the the last, just extend the length             
+                                        */
                                        /* how far to the end of the page */
                                        /* how far to the end of the page */
-                                       nextphys= (thisphys & (~(PAGESIZ - 1)))
-                                                               + PAGESIZ;
-                                       bytes_this_page = nextphys - thisphys;
+                                       nextphys = (thisphys & (~(PAGESIZ - 1)))
+                                           + PAGESIZ;
+                                       bytes_this_page = nextphys - thisphys;
                                        /**** or the data ****/
                                        /**** or the data ****/
-                                       bytes_this_page = min(bytes_this_page
-                                                               ,datalen);
-                                       bytes_this_seg  += bytes_this_page;
-                                       datalen         -= bytes_this_page;
-               
+                                       bytes_this_page = min(bytes_this_page
+                                           ,datalen);
+                                       bytes_this_seg += bytes_this_page;
+                                       datalen -= bytes_this_page;
+
                                        /* get more ready for the next page */
                                        /* get more ready for the next page */
-                                       thiskv  = (thiskv & (~(PAGESIZ - 1)))
-                                                               + PAGESIZ;
-                                       if(datalen)
+                                       thiskv = (thiskv & (~(PAGESIZ - 1)))
+                                           + PAGESIZ;
+                                       if (datalen)
                                                thisphys = KVTOPHYS(thiskv);
                                }
                                                thisphys = KVTOPHYS(thiskv);
                                }
-                               /********************************************\
-                               * next page isn't contiguous, finish the seg *
-                               \********************************************/
-#ifdef AHBDEBUG
-                               if(scsi_debug & SHOWSCATGATH)
-                                       printf("(0x%x)",bytes_this_seg);
-#endif /*AHBDEBUG*/
-                               sg->len = bytes_this_seg;       
+                               /*
+                                * next page isn't contiguous, finish the seg 
+                                */
+                               SC_DEBUGN(xs->sc_link, SDEV_DB4,
+                                   ("(0x%x)", bytes_this_seg));
+                               sg->len = bytes_this_seg;
                                sg++;
                                seg++;
                        }
                } /*end of iov/kv decision */
                ecb->datalen = seg * sizeof(struct ahb_dma_seg);
                                sg++;
                                seg++;
                        }
                } /*end of iov/kv decision */
                ecb->datalen = seg * sizeof(struct ahb_dma_seg);
-#ifdef AHBDEBUG
-               if(scsi_debug & SHOWSCATGATH)
-                       printf("\n");
-#endif /*AHBDEBUG*/
-               if (datalen)
-               { /* there's still data, must have run out of segs! */
+               SC_DEBUGN(xs->sc_link, SDEV_DB4, ("\n"));
+               if (datalen) {  /* there's still data, must have run out of segs! */
                        printf("ahb_scsi_cmd%d: more than %d DMA segs\n",
                        printf("ahb_scsi_cmd%d: more than %d DMA segs\n",
-                               unit,AHB_NSEG);
+                           unit, AHB_NSEG);
                        xs->error = XS_DRIVER_STUFFUP;
                        xs->error = XS_DRIVER_STUFFUP;
-                       ahb_free_ecb(unit,ecb,flags);
-                       return(HAD_ERROR);
+                       ahb_free_ecb(unit, ecb, flags);
+                       return (HAD_ERROR);
                }
                }
-
-       }
-       else
-       {       /* No data xfer, use non S/G values */
-               ecb->data = (physaddr)0;
+       } else {                /* No data xfer, use non S/G values */
+               ecb->data = (physaddr) 0;
                ecb->datalen = 0;
                ecb->datalen = 0;
-       }
-       ecb->chain = (physaddr)0;
-       /***********************************************\
-       * Put the scsi command in the ecb and start it  *
-       \***********************************************/
+       } ecb->chain = (physaddr) 0;
+       /*
+        * Put the scsi command in the ecb and start it
+        */
        bcopy(xs->cmd, ecb->cdb, xs->cmdlen);
        bcopy(xs->cmd, ecb->cdb, xs->cmdlen);
-       /***********************************************\
-       * Usually return SUCCESSFULLY QUEUED            *
-       \***********************************************/
-       if (!(flags & SCSI_NOMASK))
-       {
+       /*
+        * Usually return SUCCESSFULLY QUEUED
+        */
+       if (!(flags & SCSI_NOMASK)) {
                s = splbio();
                s = splbio();
-               ahb_send_mbox(unit,OP_START_ECB,xs->targ,ecb);
-               timeout(ahb_timeout,ecb,(xs->timeout * hz)/1000);
+               ahb_send_mbox(unit, OP_START_ECB, xs->sc_link->target, ecb);
+               timeout((timeout_t)ahb_timeout, (caddr_t)ecb, (xs->timeout * hz) / 1000);
                splx(s);
                splx(s);
-#ifdef AHBDEBUG
-               if(scsi_debug & TRACEINTERRUPTS)
-                       printf("cmd_sent ");
-#endif /*AHBDEBUG*/
-               return(SUCCESSFULLY_QUEUED);
+               SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_sent\n"));
+               return (SUCCESSFULLY_QUEUED);
        }
        }
-       /***********************************************\
-       * If we can't use interrupts, poll on completion*
-       \***********************************************/
-       ahb_send_mbox(unit,OP_START_ECB,xs->targ,ecb);
-#ifdef AHBDEBUG
-       if(scsi_debug & TRACEINTERRUPTS)
-               printf("cmd_wait ");
-#endif /*AHBDEBUG*/
-       do
-       {
-               if(ahb_poll(unit,xs->timeout))
-               {
-                       if (!(xs->flags & SCSI_SILENT)) printf("cmd fail\n");
-                       ahb_send_mbox(unit,OP_ABORT_ECB,xs->targ,ecb);
-                       if(ahb_poll(unit,2000))
-                       {
+       /*
+        * If we can't use interrupts, poll on completion
+        */
+       ahb_send_mbox(unit, OP_START_ECB, xs->sc_link->target, ecb);
+       SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_wait\n"));
+       do {
+               if (ahb_poll(unit, xs->timeout)) {
+                       if (!(xs->flags & SCSI_SILENT))
+                               printf("cmd fail\n");
+                       ahb_send_mbox(unit, OP_ABORT_ECB, xs->sc_link->target, ecb);
+                       if (ahb_poll(unit, 2000)) {
                                printf("abort failed in wait\n");
                                printf("abort failed in wait\n");
-                               ahb_free_ecb(unit,ecb,flags);
+                               ahb_free_ecb(unit, ecb, flags);
                        }
                        xs->error = XS_DRIVER_STUFFUP;
                        }
                        xs->error = XS_DRIVER_STUFFUP;
-                       return(HAD_ERROR);
+                       return (HAD_ERROR);
                }
                }
-       } while (!(xs->flags & ITSDONE));/* something (?) else finished */
-       if(xs->error)
-       {
-               return(HAD_ERROR);
+       } while (!(xs->flags & ITSDONE));       /* something (?) else finished */
+       if (xs->error) {
+               return (HAD_ERROR);
        }
        }
-       return(COMPLETE);
+       return (COMPLETE);
 }
 
 }
 
-
-ahb_timeout(struct ecb *ecb)
+void
+ahb_timeout(struct ecb * ecb)
 {
 {
-       int     unit;
-       int     s       = splbio();
+       int     unit;
+       struct ahb_data *ahb;
+       int     s = splbio();
+
+       unit = ecb->xs->sc_link->adapter_unit;
+       ahb = ahbdata[unit];
+       printf("ahb%d:%d:%d (%s%d) timed out ", unit
+           ,ecb->xs->sc_link->target
+           ,ecb->xs->sc_link->lun
+           ,ecb->xs->sc_link->device->name
+           ,ecb->xs->sc_link->dev_unit);
 
 
-       unit = ecb->xs->adapter;
-       printf("ahb%d:%d device timed out\n",unit
-                       ,ecb->xs->targ);
 #ifdef AHBDEBUG
 #ifdef AHBDEBUG
-       if(ahb_debug & AHB_SHOWECBS)
+       if (ahb_debug & AHB_SHOWECBS)
                ahb_print_active_ecb(unit);
                ahb_print_active_ecb(unit);
-#endif /*AHBDEBUG*/
-
-       /***************************************\
-       * If it's immediate, don't try abort it *
-       \***************************************/
-       if(ecb->flags & ECB_IMMED)
-       {
-               ecb->xs->retries = 0; /* I MEAN IT ! */
+#endif /*AHBDEBUG */
+
+       /*
+        * If it's immediate, don't try abort it 
+        */
+       if (ecb->flags & ECB_IMMED) {
+               ecb->xs->retries = 0;   /* I MEAN IT ! */
                ecb->flags |= ECB_IMMED_FAIL;
                ecb->flags |= ECB_IMMED_FAIL;
-                              ahb_done(unit,ecb,FAIL);
+               ahb_done(unit, ecb, FAIL);
                splx(s);
                return;
        }
                splx(s);
                return;
        }
-       /***************************************\
-       * If it has been through before, then   *
-       * a previous abort has failed, don't    *
-       * try abort again                       *
-       \***************************************/
-       if(ecb->flags == ECB_ABORTED) /* abort timed out */
-       {
+       /*
+        * If it has been through before, then
+        * a previous abort has failed, don't
+        * try abort again
+        */
+       if (ecb->flags == ECB_ABORTED) {
+               /*
+                * abort timed out
+                */
                printf("AGAIN");
                printf("AGAIN");
-               ecb->xs->retries = 0; /* I MEAN IT ! */
+               ecb->xs->retries = 0;   /* I MEAN IT ! */
                ecb->ecb_status.ha_status = HS_CMD_ABORTED_HOST;
                ecb->ecb_status.ha_status = HS_CMD_ABORTED_HOST;
-               ahb_done(unit,ecb,FAIL);
-       }
-       else    /* abort the operation that has timed out */
-       {
+               ahb_done(unit, ecb, FAIL);
+       } else {                /* abort the operation that has timed out */
                printf("\n");
                printf("\n");
-               ahb_send_mbox(unit,OP_ABORT_ECB,ecb->xs->targ,ecb);
-                       /* 2 secs for the abort */
-               timeout(ahb_timeout,ecb,2 * hz);
+               ahb_send_mbox(unit, OP_ABORT_ECB, ecb->xs->sc_link->target, ecb);
+               /* 2 secs for the abort */
+               timeout((timeout_t)ahb_timeout, (caddr_t)ecb, 2 * hz);
                ecb->flags = ECB_ABORTED;
        }
        splx(s);
 }
 
 #ifdef AHBDEBUG
                ecb->flags = ECB_ABORTED;
        }
        splx(s);
 }
 
 #ifdef AHBDEBUG
-ahb_show_scsi_cmd(struct scsi_xfer *xs)
-{
-       u_char  *b = (u_char *)xs->cmd;
-       int i = 0;
-       if(!(xs->flags & SCSI_RESET))
-       {
-               printf("ahb%d:%d:%d-"
-                       ,xs->adapter
-                       ,xs->targ
-                       ,xs->lu);
-               while(i < xs->cmdlen )
-               {
-                       if(i) printf(",");
-                       printf("%x",b[i++]);
-               }
-               printf("-\n");
-       }
-       else
-       {
-               printf("ahb%d:%d:%d-RESET-\n" 
-                       ,xs->adapter 
-                       ,xs->targ
-                       ,xs->lu
-               );
-       }
-}
+void
 ahb_print_ecb(ecb)
 ahb_print_ecb(ecb)
-struct ecb *ecb;
+       struct ecb *ecb;
 {
        printf("ecb:%x op:%x cmdlen:%d senlen:%d\n"
 {
        printf("ecb:%x op:%x cmdlen:%d senlen:%d\n"
-               ,ecb
-               ,ecb->opcode
-               ,ecb->cdblen
-               ,ecb->senselen);
+           ,ecb
+           ,ecb->opcode
+           ,ecb->cdblen
+           ,ecb->senselen);
        printf("        datlen:%d hstat:%x tstat:%x flags:%x\n"
        printf("        datlen:%d hstat:%x tstat:%x flags:%x\n"
-               ,ecb->datalen
-               ,ecb->ecb_status.ha_status
-               ,ecb->ecb_status.targ_status
-               ,ecb->flags);
-       ahb_show_scsi_cmd(ecb->xs);
+           ,ecb->datalen
+           ,ecb->ecb_status.ha_status
+           ,ecb->ecb_status.targ_status
+           ,ecb->flags);
+       show_scsi_cmd(ecb->xs);
 }
 
 }
 
+void
 ahb_print_active_ecb(int unit)
 {
 ahb_print_active_ecb(int unit)
 {
-       struct  ecb *ecb = ahb_data[unit].ecbs;
-       int     i = NUM_CONCURRENT;
+       struct ahb_data *ahb = ahbdata[unit];
+       struct ecb *ecb;
+       int     i = 0;
 
 
-       while(i--)
-       {
-               if(ecb->flags != ECB_FREE)
-               {
-                       ahb_print_ecb(ecb);
-               }
-               ecb++;
+       while (i < ECB_HASH_SIZE) {
+               ecb = ahb->ecbhash[i];
+               while (ecb) {
+                       if (ecb->flags != ECB_FREE) {
+                               ahb_print_ecb(ecb);
+                       }
+                       ecb = ecb->nexthash;
+               } i++;
        }
 }
        }
 }
-#endif /*AHBDEBUG */
+#endif /*AHBDEBUG */
+#endif /*KERNEL */
index ebf6504..fa46753 100644 (file)
@@ -12,7 +12,7 @@
  * 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.
  *
- *     $Id: bt742a.c,v 1.8 1993/10/12 07:15:35 rgrimes Exp $
+ *      $Id: bt742a.c,v 2.3 93/10/16 02:00:33 julian Exp Locker: julian $
  */
 
 /*
  */
 
 /*
  */
 
 #include <sys/types.h>
  */
 
 #include <sys/types.h>
-#include <bt.h>
 
 
+#ifdef KERNEL          /* don't laugh.. it compiles to a program too.. look */
+#include <bt.h>
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/errno.h>
 #include <sys/ioctl.h>
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/errno.h>
 #include <sys/ioctl.h>
+#include <sys/malloc.h>
 #include <sys/buf.h>
 #include <sys/proc.h>
 #include <sys/user.h>
 #include <sys/buf.h>
 #include <sys/proc.h>
 #include <sys/user.h>
-
-#ifdef MACH    /* EITHER CMU OR OSF */
-#include <i386/ipl.h>
-#include <i386at/scsi.h>
-#include <i386at/scsiconf.h>
-
-#ifdef OSF     /* OSF ONLY */
-#include <sys/table.h>
-#include <i386/handler.h>
-#include <i386/dispatcher.h>
-#include <i386/AT386/atbus.h>
-
-#else  OSF     /* CMU ONLY */
-#include <i386at/atbus.h>
-#include <i386/pio.h>
-#endif OSF
-#endif MACH    /* end of MACH specific */
-
-#ifdef __386BSD__      /* 386BSD specific */
-#define isa_dev isa_device
-#define dev_unit id_unit
-#define dev_addr id_iobase
+#endif /* KERNEL */
 
 #include <i386/isa/isa_device.h>
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
 
 #include <i386/isa/isa_device.h>
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
-#endif __386BSD__
 
 
-
-#ifdef __386BSD__
+#ifdef KERNEL
 #include "ddb.h"
 #if    NDDB > 0
 #include "ddb.h"
 #if    NDDB > 0
-int    Debugger();
-#else  NDDB
+int     Debugger();
+#else  /* NDDB */
 #define        Debugger() panic("should call debugger here (bt742a.c)")
 #define        Debugger() panic("should call debugger here (bt742a.c)")
-#endif NDDB
-#endif __386BSD__
-
-#ifdef MACH
-int    Debugger();
-#endif MACH
+#endif /* NDDB */
+#else /*KERNEL */
+#define        NBT 1
+#endif /*KERNEL */
 
 extern int hz;
 
 extern int hz;
-extern int delaycount; /* from clock setup code */
 typedef unsigned long int physaddr;
 
 /*
  * I/O Port Interface
  */
 
 typedef unsigned long int physaddr;
 
 /*
  * I/O Port Interface
  */
 
-#define        BT_BASE         bt_base[unit]
-#define        BT_CTRL_STAT_PORT       (BT_BASE + 0x0) /* control & status */
-#define        BT_CMD_DATA_PORT        (BT_BASE + 0x1) /* cmds and datas */
-#define        BT_INTR_PORT            (BT_BASE + 0x2) /* Intr. stat */
+#define        BT_BASE                 bt->bt_base
+#define        BT_CTRL_STAT_PORT       (BT_BASE + 0x0)         /* control & status */
+#define        BT_CMD_DATA_PORT        (BT_BASE + 0x1)         /* cmds and datas */
+#define        BT_INTR_PORT            (BT_BASE + 0x2)         /* Intr. stat */
 
 /*
  * BT_CTRL_STAT bits (write)
 
 /*
  * BT_CTRL_STAT bits (write)
@@ -132,12 +108,12 @@ typedef unsigned long int physaddr;
 #define BT_INQUIRE_EXTENDED    0x8D    /* Adapter Setup Inquiry */
 
 /* Follows command appeared at FirmWare 3.31 */
 #define BT_INQUIRE_EXTENDED    0x8D    /* Adapter Setup Inquiry */
 
 /* Follows command appeared at FirmWare 3.31 */
-#define BT_ROUND_ROBIN 0x8f            /* Enable/Disable(default) round robin */
+#define        BT_ROUND_ROBIN  0x8f    /* Enable/Disable(default) round robin */
 #define   BT_DISABLE           0x00    /* Parameter value for Disable */
 #define   BT_ENABLE            0x01    /* Parameter value for Enable */
 
 struct bt_cmd_buf {
 #define   BT_DISABLE           0x00    /* Parameter value for Disable */
 #define   BT_ENABLE            0x01    /* Parameter value for Enable */
 
 struct bt_cmd_buf {
-        u_char byte[16];       
+       u_char  byte[16];
 };
 
 /*
 };
 
 /*
@@ -151,41 +127,45 @@ struct bt_cmd_buf {
 #define BT_MBIF                0x01    /* MBX in full */
 
 /*
 #define BT_MBIF                0x01    /* MBX in full */
 
 /*
- * Mail box defs 
+ * Mail box defs  etc.
+ * these could be bigger but we need the bt_data to fit on a single page..
  */
 
  */
 
-#define BT_MBX_SIZE              255   /* mail box size  (MAX 255 MBxs) */
-#define BT_CCB_SIZE              32    /* store up to 32CCBs at any one time */ 
-                                       /* in bt742a H/W ( Not MAX ? )        */
+#define BT_MBX_SIZE    16      /* mail box size  (MAX 255 MBxs) */
+                               /* don't need that many really */
+#define BT_CCB_MAX     32      /* store up to 32CCBs at any one time */
+                               /* in bt742a H/W ( Not MAX ? ) */
+#define        CCB_HASH_SIZE   32      /* when we have a physical addr. for */
+                               /* a ccb and need to find the ccb in */
+                               /* space, look it up in the hash table */
+#define        CCB_HASH_SHIFT  9       /* only hash on multiples of 512 */
+#define CCB_HASH(x)    ((((long int)(x))>>CCB_HASH_SHIFT) % CCB_HASH_SIZE)
 
 #define bt_nextmbx( wmb, mbx, mbio ) \
 
 #define bt_nextmbx( wmb, mbx, mbio ) \
-       if ( (wmb) == &((mbx)->mbio[BT_MBX_SIZE - 1 ]) ) \
+       if ( (wmb) == &((mbx)->mbio[BT_MBX_SIZE - 1 ]) ) \
                (wmb) = &((mbx)->mbio[0]); \
                (wmb) = &((mbx)->mbio[0]); \
-       } else { \
-               (wmb)++; \
-       }
-
+       else \
+               (wmb)++;
 
 typedef struct bt_mbx_out {
 
 typedef struct bt_mbx_out {
-       physaddr        ccb_addr;
-       unsigned char   dummy[3];
-       unsigned char   cmd;
+       physaddr ccb_addr;
+       unsigned char dummy[3];
+       unsigned char cmd;
 } BT_MBO;
 
 } BT_MBO;
 
-typedef struct bt_mbx_in{
-       physaddr        ccb_addr;
-       unsigned char   btstat;
-       unsigned char   sdstat;
-       unsigned char   dummy;
-       unsigned char   stat;
+typedef struct bt_mbx_in {
+       physaddr ccb_addr;
+       unsigned char btstat;
+       unsigned char sdstat;
+       unsigned char dummy;
+       unsigned char stat;
 } BT_MBI;
 
 } BT_MBI;
 
-struct bt_mbx
-{
-       BT_MBO mbo[BT_MBX_SIZE];
-       BT_MBI mbi[BT_MBX_SIZE];
-       BT_MBO *tmbo;                   /* Target Mail Box out */
-       BT_MBI *tmbi;                   /* Target Mail Box in  */
+struct bt_mbx {
+       BT_MBO  mbo[BT_MBX_SIZE];
+       BT_MBI  mbi[BT_MBX_SIZE];
+       BT_MBO *tmbo;           /* Target Mail Box out */
+       BT_MBI *tmbi;           /* Target Mail Box in */
 };
 
 /*
 };
 
 /*
@@ -196,64 +176,72 @@ struct bt_mbx
 #define BT_MBO_START   0x1     /* MBO activate entry */
 #define BT_MBO_ABORT   0x2     /* MBO abort entry */
 
 #define BT_MBO_START   0x1     /* MBO activate entry */
 #define BT_MBO_ABORT   0x2     /* MBO abort entry */
 
+/*
+ * mbi.stat values
+ */
+
 #define BT_MBI_FREE    0x0     /* MBI entry is free */
 #define BT_MBI_OK      0x1     /* completed without error */
 #define BT_MBI_ABORT   0x2     /* aborted ccb */
 #define BT_MBI_UNKNOWN 0x3     /* Tried to abort invalid CCB */
 #define BT_MBI_ERROR   0x4     /* Completed with error */
 
 #define BT_MBI_FREE    0x0     /* MBI entry is free */
 #define BT_MBI_OK      0x1     /* completed without error */
 #define BT_MBI_ABORT   0x2     /* aborted ccb */
 #define BT_MBI_UNKNOWN 0x3     /* Tried to abort invalid CCB */
 #define BT_MBI_ERROR   0x4     /* Completed with error */
 
-extern struct bt_mbx bt_mbx[];
-
 #if    defined(BIG_DMA)
 #if    defined(BIG_DMA)
-/* #define     BT_NSEG 8192*/  /* Number of scatter gather segments - to much vm */
-#define        BT_NSEG 512
+WARNING...THIS WON'T WORK(won't fit on 1 page)
+/* #define      BT_NSEG 2048    /* Number of scatter gather segments - to much vm */
+#define        BT_NSEG 128
 #else
 #define        BT_NSEG 33
 #else
 #define        BT_NSEG 33
-#endif /* BIG_DMA */
-struct bt_scat_gath
-       {
-               unsigned long   seg_len;
-               physaddr        seg_addr;
-       };
+#endif /* BIG_DMA */
+
+struct bt_scat_gath {
+       unsigned long seg_len;
+       physaddr seg_addr;
+};
 
 struct bt_ccb {
 
 struct bt_ccb {
-       unsigned char           opcode;
-       unsigned char           :3,data_in:1,data_out:1,:3;
-       unsigned char           scsi_cmd_length;
-       unsigned char           req_sense_length;
+       unsigned char opcode;
+       unsigned char:3, data_in:1, data_out:1,:3;
+       unsigned char scsi_cmd_length;
+       unsigned char req_sense_length;
        /*------------------------------------longword boundary */
        /*------------------------------------longword boundary */
-       unsigned long           data_length;
+       unsigned long data_length;
        /*------------------------------------longword boundary */
        /*------------------------------------longword boundary */
-       physaddr                data_addr;
+       physaddr data_addr;
        /*------------------------------------longword boundary */
        /*------------------------------------longword boundary */
-       unsigned char           dummy[2];
-       unsigned char           host_stat;
-       unsigned char           target_stat;
+       unsigned char dummy[2];
+       unsigned char host_stat;
+       unsigned char target_stat;
        /*------------------------------------longword boundary */
        /*------------------------------------longword boundary */
-       unsigned char           target;
-       unsigned char           lun;
-       unsigned char           scsi_cmd[12];   /* 12 bytes (bytes only)*/
-       unsigned char           dummy2[1];
-       unsigned char           link_id;
+       unsigned char target;
+       unsigned char lun;
+       unsigned char scsi_cmd[12];     /* 12 bytes (bytes only) */
+       unsigned char dummy2[1];
+       unsigned char link_id;
        /*------------------------------------4 longword boundary */
        /*------------------------------------4 longword boundary */
-       physaddr                link_addr;
+       physaddr link_addr;
        /*------------------------------------longword boundary */
        /*------------------------------------longword boundary */
-       physaddr                sense_ptr;
+       physaddr sense_ptr;
+/*-----end of HW fields-------------------------------longword boundary */
+       struct scsi_sense_data scsi_sense;
        /*------------------------------------longword boundary */
        /*------------------------------------longword boundary */
-       struct  scsi_sense_data scsi_sense;
+       struct bt_scat_gath scat_gath[BT_NSEG];
        /*------------------------------------longword boundary */
        /*------------------------------------longword boundary */
-       struct  bt_scat_gath    scat_gath[BT_NSEG];
+       struct bt_ccb *next;
        /*------------------------------------longword boundary */
        /*------------------------------------longword boundary */
-       struct  bt_ccb          *next;
+       struct scsi_xfer *xfer; /* the scsi_xfer for this cmd */
        /*------------------------------------longword boundary */
        /*------------------------------------longword boundary */
-       struct  scsi_xfer       *xfer;          /* the scsi_xfer for this cmd */
+       struct bt_mbx_out *mbx; /* pointer to mail box */
        /*------------------------------------longword boundary */
        /*------------------------------------longword boundary */
-       struct  bt_mbx_out      *mbx;           /* pointer to mail box */
-       /*------------------------------------longword boundary */
-       int             flags;
+       int     flags;
 #define        CCB_FREE        0
 #define CCB_ACTIVE     1
 #define        CCB_ABORTED     2
 #define        CCB_FREE        0
 #define CCB_ACTIVE     1
 #define        CCB_ABORTED     2
+       /*------------------------------------longword boundary */
+       struct bt_ccb *nexthash;        /* if two hash the same */
+       /*------------------------------------longword boundary */
+       physaddr hashkey;       /*physaddr of this ccb */
+       /*------------------------------------longword boundary */
 };
 
 /*
 };
 
 /*
@@ -262,10 +250,9 @@ struct bt_ccb {
 
 #define BT_INITIATOR_CCB       0x00    /* SCSI Initiator CCB */
 #define BT_TARGET_CCB          0x01    /* SCSI Target CCB */
 
 #define BT_INITIATOR_CCB       0x00    /* SCSI Initiator CCB */
 #define BT_TARGET_CCB          0x01    /* SCSI Target CCB */
-#define BT_INIT_SCAT_GATH_CCB  0x02    /* SCSI Initiator with scattter gather*/
+#define BT_INIT_SCAT_GATH_CCB  0x02    /* SCSI Initiator with scattter gather */
 #define BT_RESET_CCB           0x81    /* SCSI Bus reset */
 
 #define BT_RESET_CCB           0x81    /* SCSI Bus reset */
 
-
 /*
  * bt_ccb.host_stat values
  */
 /*
  * bt_ccb.host_stat values
  */
@@ -285,37 +272,35 @@ struct bt_ccb {
 #define BT_INV_CCB     0x1a    /* Invalid CCB or segment list */
 #define BT_ABORTED     42      /* pseudo value from driver */
 
 #define BT_INV_CCB     0x1a    /* Invalid CCB or segment list */
 #define BT_ABORTED     42      /* pseudo value from driver */
 
-struct bt_boardID
-{
-       u_char  board_type;
-       u_char  custom_feture;
-       char    firm_revision;
-       u_char  firm_version;
+struct bt_boardID {
+       u_char  board_type;
+       u_char  custom_feture;
+       char    firm_revision;
+       u_char  firm_version;
 };
 
 };
 
-struct bt_setup
-{
-       u_char  sync_neg:1;
-       u_char  parity:1;
+struct bt_setup {
+       u_char  sync_neg:1;
+       u_char  parity:1;
        u_char  :6;
        u_char  :6;
-       u_char  speed;
-       u_char  bus_on;
-       u_char  bus_off;
-       u_char  num_mbx;
-       u_char  mbx[3];
+       u_char  speed;
+       u_char  bus_on;
+       u_char  bus_off;
+       u_char  num_mbx;
+       u_char  mbx[3];         /*XXX */
+       /* doesn't make sense with 32bit addresses */
        struct {
        struct {
-               u_char  offset:4;
-               u_char  period:3;
-               u_char  valid:1;
-       }sync[8];
-       u_char  disc_sts;
+               u_char  offset:4;
+               u_char  period:3;
+               u_char  valid:1;
+       } sync[8];
+       u_char  disc_sts;
 };
 
 };
 
-struct bt_config
-{
-       u_char  chan;
-       u_char  intr;
-       u_char  scsi_dev:3;
+struct bt_config {
+       u_char  chan;
+       u_char  intr;
+       u_char  scsi_dev:3;
        u_char  :5;
 };
 
        u_char  :5;
 };
 
@@ -332,398 +317,385 @@ struct  bt_config
 #define CHAN6  0x40
 #define CHAN7  0x80
 
 #define CHAN6  0x40
 #define CHAN7  0x80
 
-
-
-
-#ifdef        MACH
-extern physaddr        kvtophys();
-#define PHYSTOKV(x)   phystokv(x)
-#define KVTOPHYS(x)   kvtophys(x)
-#endif MACH
-
-#ifdef        __386BSD__
-#define KVTOPHYS(x)   vtophys(x)
-#endif        __386BSD__
-
-
-
-#define PAGESIZ        4096
+#define KVTOPHYS(x)    vtophys(x)
+#define PAGESIZ                4096
 #define INVALIDATE_CACHE {asm volatile( ".byte 0x0F ;.byte 0x08" ); }
 
 #define INVALIDATE_CACHE {asm volatile( ".byte 0x0F ;.byte 0x08" ); }
 
+u_char  bt_scratch_buf[256];
 
 
-u_char                 bt_scratch_buf[256];
-#ifdef MACH
-caddr_t                        bt_base[NBT];           /* base port for each board */
-#else  MACH
-short                  bt_base[NBT];           /* base port for each board */
-#endif MACH
-struct bt_mbx          bt_mbx[NBT];
-struct bt_ccb          *bt_ccb_free[NBT];
-struct bt_ccb          bt_ccb[NBT][BT_CCB_SIZE];
-struct scsi_xfer       bt_scsi_xfer[NBT];
-struct isa_dev         *btinfo[NBT];
-struct bt_ccb          *bt_get_ccb();
-int                    bt_int[NBT];
-int                    bt_dma[NBT];
-int                    bt_scsi_dev[NBT];
-int                    bt_initialized[NBT];
-#if defined(OSF)
-int                    bt_attached[NBT];
-#endif /* defined(OSF) */
+struct bt_data {
+       short   bt_base;                /* base port for each board */
+       struct bt_mbx bt_mbx;           /* all our mailboxes */
+       struct bt_ccb *bt_ccb_free;     /* list of free CCBs */
+       struct bt_ccb *ccbhash[CCB_HASH_SIZE];  /* phys to kv hash */
+       int     bt_int;                 /* int. read off board */
+       int     bt_dma;                 /* DMA channel read of board */
+       int     bt_scsi_dev;            /* adapters scsi id */
+       int     numccbs;                /* how many we have malloc'd */
+       struct scsi_link sc_link;       /* prototype for devs */
+}      *btdata[NBT];
 
 /***********debug values *************/
 #define        BT_SHOWCCBS 0x01
 #define        BT_SHOWINTS 0x02
 #define        BT_SHOWCMDS 0x04
 #define        BT_SHOWMISC 0x08
 
 /***********debug values *************/
 #define        BT_SHOWCCBS 0x01
 #define        BT_SHOWINTS 0x02
 #define        BT_SHOWCMDS 0x04
 #define        BT_SHOWMISC 0x08
-int    bt_debug = 0;
-
+int     bt_debug = 0;
+
+#ifdef KERNEL
+int     btprobe();
+int     btattach();
+int     btintr();
+int32   bt_scsi_cmd();
+void   bt_timeout();
+void   bt_inquire_setup_information();
+void    bt_done();
+void    btminphys();
+u_int32 bt_adapter_info();
+struct bt_ccb *bt_get_ccb();
+struct bt_ccb *bt_ccb_phys_kv();
+
+static int btunit = 0;
+
+struct isa_driver btdriver =
+{
+    btprobe,
+    btattach,
+    "bt"
+};
 
 
-int btprobe(), btattach();
-int btintr();
+struct scsi_adapter bt_switch =
+{
+    bt_scsi_cmd,
+    btminphys,
+    0,
+    0,
+    bt_adapter_info,
+    "bt",
+    0, 0
+};
 
 
-#ifdef MACH
-struct isa_driver      btdriver = { btprobe, 0, btattach, "bt", 0, 0, 0};
-int (*btintrs[])() = {btintr, 0};
-#endif MACH
+/* the below structure is so we have a default dev struct for out link struct */
+struct scsi_device bt_dev =
+{
+    NULL,                      /* Use default error handler */
+    NULL,                      /* have a queue, served by this */
+    NULL,                      /* have no async handler */
+    NULL,                      /* Use default 'done' routine */
+    "bt",
+    0,
+    0, 0
+};
 
 
-#ifdef __386BSD__
-struct isa_driver      btdriver = { btprobe, btattach, "bt"};
-#endif __386BSD__
+#endif /*KERNEL */
 
 
-static int     btunit = 0;
+#define BT_RESET_TIMEOUT 1000
+#ifndef        KERNEL
+main()
+{
+       printf("bt_data is %d bytes\n", sizeof(struct bt_data));
+       printf("bt_ccb is %d bytes\n", sizeof(struct bt_ccb));
+       printf("bt_mbx is %d bytes\n", sizeof(struct bt_mbx));
+}
 
 
-int    bt_scsi_cmd();
-int    bt_timeout();
-void   btminphys();
-long int bt_adapter_info();
+#else /*KERNEL */
 
 
-struct scsi_switch     bt_switch =
-{
-       bt_scsi_cmd,
-       btminphys,
-       0,
-       0,
-       bt_adapter_info,
-       "bt",
-       0,0
-};     
-#define BT_CMD_TIMEOUT_FUDGE 200 /* multiplied to get Secs */
-#define BT_RESET_TIMEOUT 1000000
-#define BT_SCSI_TIMEOUT_FUDGE 20 /* divided by for mSecs */
-
-
-/***********************************************************************\
-* bt_cmd(unit,icnt, ocnt,wait, retval, opcode, args)                   *
-* Activate Adapter command                                             *
-*      icnt:   number of args (outbound bytes written after opcode)    *
-*      ocnt:   number of expected returned bytes                       *
-*      wait:   number of seconds to wait for response                  *
-*      retval: buffer where to place returned bytes                    *
-*      opcode: opcode BT_NOP, BT_MBX_INIT, BT_START_SCSI ...           *
-*      args:   parameters                                              *
-*                                                                      *
-* Performs an adapter command through the ports. Not to be confused    *
-*      with a scsi command, which is read in via the dma               *
-* One of the adapter commands tells it to read in a scsi command       *
-\***********************************************************************/
-bt_cmd(unit,icnt, ocnt, wait,retval, opcode, args)
-
-u_char *retval;
-unsigned opcode;
-u_char args;
+/*
+ * bt_cmd(unit,icnt, ocnt,wait, retval, opcode, args)
+ *
+ * Activate Adapter command
+ *    icnt:   number of args (outbound bytes written after opcode)
+ *    ocnt:   number of expected returned bytes
+ *    wait:   number of seconds to wait for response
+ *    retval: buffer where to place returned bytes
+ *    opcode: opcode BT_NOP, BT_MBX_INIT, BT_START_SCSI ...
+ *    args:   parameters
+ *
+ * Performs an adapter command through the ports.  Not to be confused with a
+ * scsi command, which is read in via the dma; one of the adapter commands
+ * tells it to read in a scsi command.
+ */
+int
+bt_cmd(unit, icnt, ocnt, wait, retval, opcode, args)
+       u_char          *retval;
+       unsigned        opcode;
+       u_char          args;
 {
 {
-       unsigned *ic = &opcode;
-       u_char oc;
-       register i;
-       int     sts;
-
-       /*******************************************************\
-       * multiply the wait argument by a big constant          *
-       * zero defaults to 1                                    *
-       \*******************************************************/
-       if(!wait) 
-               wait = BT_CMD_TIMEOUT_FUDGE * delaycount; 
+       struct          bt_data *bt = btdata[unit];
+       unsigned        *ic = &opcode;
+       u_char          oc;
+       register        i;
+       int             sts;
+
+       /*
+        * multiply the wait argument by a big constant
+        * zero defaults to 1
+        */
+       if (wait)
+               wait *= 100000;
        else
        else
-               wait *= BT_CMD_TIMEOUT_FUDGE * delaycount; 
-       /*******************************************************\
-       * Wait for the adapter to go idle, unless it's one of   *
-       * the commands which don't need this                    *
-       \*******************************************************/
-       if (opcode != BT_MBX_INIT && opcode != BT_START_SCSI)
-       {
-               i = BT_CMD_TIMEOUT_FUDGE * delaycount; /* 1 sec?*/
-               while (--i)
-               {
+               wait = 100000;
+       /*
+        * Wait for the adapter to go idle, unless it's one of
+        * the commands which don't need this
+        */
+       if (opcode != BT_MBX_INIT && opcode != BT_START_SCSI) {
+               i = 100000;     /* 1 sec? */
+               while (--i) {
                        sts = inb(BT_CTRL_STAT_PORT);
                        sts = inb(BT_CTRL_STAT_PORT);
-                       if (sts & BT_IDLE)
-                       {
+                       if (sts & BT_IDLE) {
                                break;
                        }
                                break;
                        }
+                       DELAY(10);
                }
                }
-               if (!i)
-               {
-                       printf("bt%d: bt_cmd, host not idle(0x%x)\n",unit,sts);
-                       return(ENXIO);
+               if (i == 0) {
+                       printf("bt%d: bt_cmd, host not idle(0x%x)\n", unit, sts);
+                       return (ENXIO);
                }
        }
                }
        }
-       /*******************************************************\
-       * Now that it is idle, if we expect output, preflush the*
-       * queue feeding to us.                                  *
-       \*******************************************************/
-       if (ocnt)
-       {
-               while((inb(BT_CTRL_STAT_PORT)) & BT_DF)
+       /*
+        * Now that it is idle, if we expect output, preflush the
+        * queue feeding to us.
+        */
+       if (ocnt) {
+               while ((inb(BT_CTRL_STAT_PORT)) & BT_DF)
                        inb(BT_CMD_DATA_PORT);
        }
                        inb(BT_CMD_DATA_PORT);
        }
-                       
-       /*******************************************************\
-       * Output the command and the number of arguments given  *
-       * for each byte, first check the port is empty.         *
-       \*******************************************************/
-       icnt++;         /* include the command */
-       while (icnt--)
-       {
+       /*
+        * Output the command and the number of arguments given
+        * for each byte, first check the port is empty.
+        */
+       icnt++;
+                               /* include the command */
+       while (icnt--) {
                sts = inb(BT_CTRL_STAT_PORT);
                sts = inb(BT_CTRL_STAT_PORT);
-               for (i=0; i< wait; i++)
-               {
+               for (i = wait; i; i--) {
                        sts = inb(BT_CTRL_STAT_PORT);
                        if (!(sts & BT_CDF))
                                break;
                        sts = inb(BT_CTRL_STAT_PORT);
                        if (!(sts & BT_CDF))
                                break;
+                       DELAY(10);
                }
                }
-               if (i >=  wait)
-               {
-                       printf("bt%d: bt_cmd, cmd/data port full\n",unit);
-                       outb(BT_CTRL_STAT_PORT, BT_SRST); 
-                       return(ENXIO);
+               if (i == 0) {
+                       printf("bt%d: bt_cmd, cmd/data port full\n", unit);
+                       outb(BT_CTRL_STAT_PORT, BT_SRST);
+                       return (ENXIO);
                }
                }
-               outb(BT_CMD_DATA_PORT, (u_char)(*ic++));
+               outb(BT_CMD_DATA_PORT, (u_char) (*ic++));
        }
        }
-       /*******************************************************\
-       * If we expect input, loop that many times, each time,  *
-       * looking for the data register to have valid data      *
-       \*******************************************************/
-       while (ocnt--)
-       {
+       /*
+        * If we expect input, loop that many times, each time,
+        * looking for the data register to have valid data
+        */
+       while (ocnt--) {
                sts = inb(BT_CTRL_STAT_PORT);
                sts = inb(BT_CTRL_STAT_PORT);
-               for (i=0; i< wait; i++)
-               {
+               for (i = wait; i; i--) {
                        sts = inb(BT_CTRL_STAT_PORT);
                        sts = inb(BT_CTRL_STAT_PORT);
-                       if (sts  & BT_DF)
+                       if (sts & BT_DF)
                                break;
                                break;
+                       DELAY(10);
                }
                }
-               if (i >=  wait)
-               {
+               if (i == 0) {
                        printf("bt%d: bt_cmd, cmd/data port empty %d\n",
                        printf("bt%d: bt_cmd, cmd/data port empty %d\n",
-                               unit,ocnt);
-                       return(ENXIO);
+                           unit, ocnt);
+                       return (ENXIO);
                }
                oc = inb(BT_CMD_DATA_PORT);
                if (retval)
                        *retval++ = oc;
        }
                }
                oc = inb(BT_CMD_DATA_PORT);
                if (retval)
                        *retval++ = oc;
        }
-       /*******************************************************\
-       * Wait for the board to report a finised instruction    *
-       \*******************************************************/
-       i=BT_CMD_TIMEOUT_FUDGE * delaycount;    /* 1 sec? */
-       while (--i)
-       {
+       /*
+        * Wait for the board to report a finised instruction
+        */
+       i = 100000;     /* 1 sec? */
+       while (--i) {
                sts = inb(BT_INTR_PORT);
                sts = inb(BT_INTR_PORT);
-               if (sts & BT_HACC)
-               {
+               if (sts & BT_HACC) {
                        break;
                }
                        break;
                }
+               DELAY(10);
        }
        }
-       if (!i)
-       {
-               printf("bt%d: bt_cmd, host not finished(0x%x)\n",unit,sts);
-               return(ENXIO);
+       if (i == 0) {
+               printf("bt%d: bt_cmd, host not finished(0x%x)\n", unit, sts);
+               return (ENXIO);
        }
        outb(BT_CTRL_STAT_PORT, BT_IRST);
        }
        outb(BT_CTRL_STAT_PORT, BT_IRST);
-       return(0);
+       return (0);
 }
 
 }
 
-/*******************************************************\
-* Check if the device can be found at the port given   *
-* and if so, set it up ready for further work          *
-* as an argument, takes the isa_dev structure from     *
-* autoconf.c                                           *
-\*******************************************************/
-
+/*
+ * Check if the device can be found at the port given
+ * and if so, set it up ready for further work
+ * as an argument, takes the isa_device structure from
+ * autoconf.c
+ */
+int
 btprobe(dev)
 btprobe(dev)
-struct isa_dev *dev;
+       struct isa_device *dev;
 {
 {
-       /***********************************************\
-       * find unit and check we have that many defined *
-       \***********************************************/
+       /*
+        * find unit and check we have that many defined
+        */
        int     unit = btunit;
        int     unit = btunit;
-#if defined(OSF)
-       static ihandler_t bt_handler[NBT];
-       static ihandler_id_t *bt_handler_id[NBT];
-       register ihandler_t *chp = &bt_handler[unit];;
-#endif /* defined(OSF) */
-
-       dev->dev_unit = unit;
-       bt_base[unit] = dev->dev_addr;
-       if(unit >= NBT) 
-       {
-               printf("bt%d: unit number too high\n",unit);
-               return(0);
+       struct bt_data *bt;
+
+       if (unit >= NBT) {
+               printf("bt%d: unit number too high\n", unit);
+               return 0;
        }
        }
-       /***********************************************\
-       * Try initialise a unit at this location        *
-       * sets up dma and bus speed, loads bt_int[unit]*
-       \***********************************************/
-       if (bt_init(unit) != 0)
-       {
-               return(0);
+       /*
+        * Allocate a storage area for us
+        */
+       if (btdata[unit]) {
+               printf("bt%d: memory already allocated\n", unit);
+               return 0;
        }
        }
-
-       /***********************************************\
-       * If it's there, put in it's interrupt vectors  *
-       \***********************************************/
-#ifdef MACH
-       dev->dev_pic = bt_int[unit];
-#if defined(OSF)                               /* OSF */
-       chp->ih_level = dev->dev_pic;
-       chp->ih_handler = dev->dev_intr[0];
-       chp->ih_resolver = i386_resolver;
-       chp->ih_rdev = dev;
-       chp->ih_stats.intr_type = INTR_DEVICE;
-       chp->ih_stats.intr_cnt = 0;
-       chp->ih_hparam[0].intparam = unit;
-       if ((bt_handler_id[unit] = handler_add(chp)) != NULL)
-               handler_enable(bt_handler_id[unit]);
-       else
-               panic("Unable to add bt interrupt handler");
-#else                                          /* CMU */
-       take_dev_irq(dev);
-#endif /* !defined(OSF) */
-       printf("port=%x spl=%d\n", dev->dev_addr, dev->dev_spl);
-#endif MACH
-#ifdef  __386BSD__                             /* 386BSD */
-        dev->id_irq = (1 << bt_int[unit]);
-        dev->id_drq = bt_dma[unit];
-#endif  __386BSD__
+       bt = malloc(sizeof(struct bt_data), M_TEMP, M_NOWAIT);
+       if (!bt) {
+               printf("bt%d: cannot malloc!\n", unit);
+               return 0;
+       }
+       bzero(bt, sizeof(struct bt_data));
+       btdata[unit] = bt;
+       bt->bt_base = dev->id_iobase;
+
+       /*
+        * Try initialise a unit at this location
+        * sets up dma and bus speed, loads bt->bt_int
+        */
+       if (bt_init(unit) != 0) {
+               btdata[unit] = NULL;
+               free(bt, M_TEMP);
+               return 0;
+       }
+       /*
+        * If it's there, put in it's interrupt vectors
+        */ dev->id_unit = unit;
+       dev->id_irq = (1 << bt->bt_int);
+       dev->id_drq = bt->bt_dma;
 
        btunit++;
 
        btunit++;
-       return(1);
+       return 1;
 }
 
 }
 
-/***********************************************\
-* Attach all the sub-devices we can find       *
-\***********************************************/
+/*
+ * Attach all the sub-devices we can find
+ */
+int
 btattach(dev)
 btattach(dev)
-struct isa_dev *dev;
+       struct isa_device *dev;
 {
 {
-       int     unit = dev->dev_unit;
-
-
-       /***********************************************\
-       * ask the adapter what subunits are present     *
-       \***********************************************/
-       scsi_attachdevs( unit, bt_scsi_dev[unit], &bt_switch);
-#if defined(OSF)
-       bt_attached[unit]=1;
-#endif /* defined(OSF) */
-       return;
+       int     unit = dev->id_unit;
+       struct  bt_data *bt = btdata[unit];
+
+       /*
+        * fill in the prototype scsi_link.
+        */
+       bt->sc_link.adapter_unit = unit;
+       bt->sc_link.adapter_targ = bt->bt_scsi_dev;
+       bt->sc_link.adapter = &bt_switch;
+       bt->sc_link.device = &bt_dev;
+
+       /*
+        * ask the adapter what subunits are present
+        */
+       scsi_attachdevs(&(bt->sc_link));
+       return 1;
 }
 
 }
 
-/***********************************************\
-* Return some information to the caller about   *
-* the adapter and it's capabilities             *
-\***********************************************/
-long int bt_adapter_info(unit)
-int    unit;
+/*
+ * Return some information to the caller about the adapter and its
+ * capabilities.
+ */
+u_int32 
+bt_adapter_info(unit)
+       int     unit;
 {
 {
-       return(2);      /* 2 outstanding requests at a time per device */
+       return (2);             /* 2 outstanding requests at a time per device */
 }
 
 }
 
-/***********************************************\
-* Catch an interrupt from the adaptor          *
-\***********************************************/
+/*
+ * Catch an interrupt from the adaptor
+ */
+int
 btintr(unit)
 btintr(unit)
+       int     unit;
 {
 {
-       BT_MBI        *wmbi;
+       struct bt_data *bt = btdata[unit];
+       BT_MBI *wmbi;
        struct bt_mbx *wmbx;
        struct bt_ccb *ccb;
        unsigned char stat;
        struct bt_mbx *wmbx;
        struct bt_ccb *ccb;
        unsigned char stat;
-       int           i,wait;
-       int           found = 0;
+       int     i, wait;
+       int     found = 0;
 
 #ifdef UTEST
 
 #ifdef UTEST
-       if(scsi_debug & PRINTROUTINES)
-               printf("btintr ");
+       printf("btintr ");
 #endif
 #endif
-       /***********************************************\
-       * First acknowlege the interrupt, Then if it's  *
-       * not telling about a completed operation       *
-       * just return.                                  *
-       \***********************************************/
+       /*
+        * First acknowlege the interrupt, Then if it's
+        * not telling about a completed operation
+        * just return. 
+        */
        stat = inb(BT_INTR_PORT);
 
        /* Mail Box out empty ? */
        stat = inb(BT_INTR_PORT);
 
        /* Mail Box out empty ? */
-       if ( stat & BT_MBOA ) {
-               printf("bt%d: Available Free mbo post\n",unit);
-               /* Disable MBO available interrupt */
-               outb(BT_CMD_DATA_PORT,BT_MBO_INTR_EN);
-               wait = BT_CMD_TIMEOUT_FUDGE * delaycount; 
-               for (i=0; i< wait; i++)
-               {
+       if (stat & BT_MBOA) {
+               printf("bt%d: Available Free mbo post\n", unit);
+               /* Disable MBO available interrupt */
+               outb(BT_CMD_DATA_PORT, BT_MBO_INTR_EN);
+               wait = 100000;  /* 1 sec enough? */
+               for (i = wait; i; i--) {
                        if (!(inb(BT_CTRL_STAT_PORT) & BT_CDF))
                                break;
                        if (!(inb(BT_CTRL_STAT_PORT) & BT_CDF))
                                break;
+                       DELAY(10);
                }
                }
-               if (i >=  wait)
-               {
-                       printf("bt%d: bt_intr, cmd/data port full\n",unit);
-                       outb(BT_CTRL_STAT_PORT, BT_SRST); 
+               if (i == 0) {
+                       printf("bt%d: bt_intr, cmd/data port full\n", unit);
+                       outb(BT_CTRL_STAT_PORT, BT_SRST);
                        return 1;
                }
                outb(BT_CMD_DATA_PORT, 0x00);   /* Disable */
                        return 1;
                }
                outb(BT_CMD_DATA_PORT, 0x00);   /* Disable */
-               wakeup(&bt_mbx[unit]);
+               wakeup(&bt->bt_mbx);
                outb(BT_CTRL_STAT_PORT, BT_IRST);
                return 1;
        }
                outb(BT_CTRL_STAT_PORT, BT_IRST);
                return 1;
        }
-       if (! (stat & BT_MBIF)) {
+       if (!(stat & BT_MBIF)) {
                outb(BT_CTRL_STAT_PORT, BT_IRST);
                return 1;
        }
                outb(BT_CTRL_STAT_PORT, BT_IRST);
                return 1;
        }
-#if defined(OSF)
-       if (!bt_attached[unit])
-       {
-               return(1);
-       }
-#endif /* defined(OSF) */
-       /***********************************************\
-       * If it IS then process the competed operation  *
-       \***********************************************/
-       wmbx = &bt_mbx[unit];
+       /*
+        * If it IS then process the competed operation
+        */
+       wmbx = &bt->bt_mbx;
        wmbi = wmbx->tmbi;
        wmbi = wmbx->tmbi;
-AGAIN:
-       while ( wmbi->stat != BT_MBI_FREE ) { 
+      AGAIN:
+       while (wmbi->stat != BT_MBI_FREE) {
+               ccb = bt_ccb_phys_kv(bt, (wmbi->ccb_addr));
+               if (!ccb) {
+                       wmbi->stat = BT_MBI_FREE;
+                       printf("bt: BAD CCB ADDR!\n");
+                       continue;
+               }
                found++;
                found++;
-               ccb = (struct bt_ccb *)PHYSTOKV((wmbi->ccb_addr));
-               if((stat =  wmbi->stat) != BT_MBI_OK)
-               {
-                       switch(stat)
-                       {
-                       case    BT_MBI_ABORT:
+               if ((stat = wmbi->stat) != BT_MBI_OK) {
+                       switch (stat) {
+                       case BT_MBI_ABORT:
 #ifdef UTEST
 #ifdef UTEST
-                               if(bt_debug & BT_SHOWMISC)
+                               if (bt_debug & BT_SHOWMISC)
                                        printf("abort ");
 #endif
                                ccb->host_stat = BT_ABORTED;
                                break;
 
                                        printf("abort ");
 #endif
                                ccb->host_stat = BT_ABORTED;
                                break;
 
-                       case    BT_MBI_UNKNOWN:
-                               ccb = (struct bt_ccb *)0;
+                       case BT_MBI_UNKNOWN:
+                               ccb = (struct bt_ccb *) 0;
 #ifdef UTEST
 #ifdef UTEST
-                               if(bt_debug & BT_SHOWMISC)
+                               if (bt_debug & BT_SHOWMISC)
                                        printf("unknown ccb for abort");
 #endif
                                break;
 
                                        printf("unknown ccb for abort");
 #endif
                                break;
 
-                       case    BT_MBI_ERROR:
+                       case BT_MBI_ERROR:
                                break;
 
                        default:
                                break;
 
                        default:
@@ -731,40 +703,36 @@ AGAIN:
 
                        }
 #ifdef UTEST
 
                        }
 #ifdef UTEST
-                       if((bt_debug & BT_SHOWCMDS ) && ccb)
-                       {
-                               u_char  *cp;
+                        if ((bt_debug & BT_SHOWCMDS) && ccb) {
+                               u_char *cp;
                                cp = ccb->scsi_cmd;
                                cp = ccb->scsi_cmd;
-                               printf("op=%x %x %x %x %x %x\n", 
-                                       cp[0], cp[1], cp[2],
-                                       cp[3], cp[4], cp[5]);
+                               printf("op=%x %x %x %x %x %x\n",
+                                   cp[0], cp[1], cp[2],
+                                   cp[3], cp[4], cp[5]);
                                printf("stat %x for mbi addr = 0x%08x\n"
                                printf("stat %x for mbi addr = 0x%08x\n"
-                                       , wmbi->stat, wmbi );
+                                   ,wmbi->stat, wmbi);
                                printf("addr = 0x%x\n", ccb);
                        }
                                printf("addr = 0x%x\n", ccb);
                        }
-#endif
+#endif 
                }
                wmbi->stat = BT_MBI_FREE;
                }
                wmbi->stat = BT_MBI_FREE;
-               if(ccb)
-               {
-                       untimeout(bt_timeout,ccb);
-                       bt_done(unit,ccb);
+               if (ccb) {
+                       untimeout(bt_timeout, ccb);
+                       bt_done(unit, ccb);
                }
                }
-
-               /* Set the IN mail Box pointer for next */
-               bt_nextmbx( wmbi, wmbx, mbi );
+               /* Set the IN mail Box pointer for next */ bt_nextmbx(wmbi, wmbx, mbi);
        }
        }
-       if ( !found ) {
-               for ( i = 0; i < BT_MBX_SIZE; i++) {
-                       if ( wmbi->stat != BT_MBI_FREE ) {
-                               found ++;
+       if (!found) {
+               for (i = 0; i < BT_MBX_SIZE; i++) {
+                       if (wmbi->stat != BT_MBI_FREE) {
+                               found++;
                                break;
                        }
                                break;
                        }
-                       bt_nextmbx( wmbi, wmbx, mbi );
+                       bt_nextmbx(wmbi, wmbx, mbi);
                }
                }
-               if ( !found ) {
+               if (!found) {
                        printf("bt%d: mbi at 0x%08x should be found, stat=%02x..resync\n",
                        printf("bt%d: mbi at 0x%08x should be found, stat=%02x..resync\n",
-                               unit, wmbi, stat ); 
+                           unit, wmbi, stat);
                } else {
                        found = 0;
                        goto AGAIN;
                } else {
                        found = 0;
                        goto AGAIN;
@@ -772,846 +740,772 @@ AGAIN:
        }
        wmbx->tmbi = wmbi;
        outb(BT_CTRL_STAT_PORT, BT_IRST);
        }
        wmbx->tmbi = wmbi;
        outb(BT_CTRL_STAT_PORT, BT_IRST);
-       return(1);
+       return 1;
 }
 
 }
 
-/***********************************************\
-* A ccb (and hence a mbx-out is put onto the   *
-* free list.                                   *
-\***********************************************/
-bt_free_ccb(unit,ccb, flags)
-struct bt_ccb *ccb;
+/*
+ * A ccb is put onto the free list.
+ */
+void
+bt_free_ccb(unit, ccb, flags)
+       struct bt_ccb *ccb;
 {
 {
+       struct bt_data *bt = btdata[unit];
        unsigned int opri;
 
        unsigned int opri;
 
-#ifdef UTEST   
-       if(scsi_debug & PRINTROUTINES)
-               printf("ccb%d(0x%x)> ",unit,flags);
-#endif
-       if (!(flags & SCSI_NOMASK)) 
-               opri = splbio();
+       if (!(flags & SCSI_NOMASK))
+               opri = splbio();
 
 
-       ccb->next = bt_ccb_free[unit];
-       bt_ccb_free[unit] = ccb;
+       ccb->next = bt->bt_ccb_free;
+       bt->bt_ccb_free = ccb;
        ccb->flags = CCB_FREE;
        ccb->flags = CCB_FREE;
-       /***********************************************\
-       * If there were none, wake abybody waiting for  *
-       * one to come free, starting with queued entries*
-       \***********************************************/
+       /*
+        * If there were none, wake anybody waiting for one to come free,
+        * starting with queued entries.
+        */
        if (!ccb->next) {
        if (!ccb->next) {
-               wakeup(&bt_ccb_free[unit]);
+               wakeup(&bt->bt_ccb_free);
        }
        }
-       if (!(flags & SCSI_NOMASK)) 
+
+       if (!(flags & SCSI_NOMASK))
                splx(opri);
 }
 
                splx(opri);
 }
 
-/***********************************************\
-* Get a free ccb                               *
-\***********************************************/
+/*
+ * Get a free ccb 
+ *
+ * If there are none, see if we can allocate a new one.  If so, put it in
+ * the hash table too otherwise either return an error or sleep.
+ */
 struct bt_ccb *
 struct bt_ccb *
-bt_get_ccb(unit,flags)
+bt_get_ccb(unit, flags)
 {
 {
-       unsigned      opri;
-       struct bt_ccb *rc;
+       struct bt_data *bt = btdata[unit];
+       unsigned opri;
+       struct bt_ccb *ccbp;
        struct bt_mbx *wmbx;    /* Mail Box pointer specified unit */
        struct bt_mbx *wmbx;    /* Mail Box pointer specified unit */
-       BT_MBO        *wmbo;    /* Out Mail Box pointer */
+       BT_MBO *wmbo;           /* Out Mail Box pointer */
+       int     hashnum;
 
 
-#ifdef UTEST
-       if(scsi_debug & PRINTROUTINES)
-               printf("<ccb%d(0x%x) ",unit,flags);
-#endif
-       if (!(flags & SCSI_NOMASK)) 
-               opri = splbio();
-       /***********************************************\
-       * If we can and have to, sleep waiting for one  *
-       * to come free                                  *
-       \***********************************************/
-       while ((!(rc = bt_ccb_free[unit])) && (!(flags & SCSI_NOSLEEP)))
-       {
-               sleep(&bt_ccb_free[unit], PRIBIO);
+       if (!(flags & SCSI_NOMASK))
+               opri = splbio();
+       /*
+        * If we can and have to, sleep waiting for one to come free
+        * but only if we can't allocate a new one.
+        */
+       while (!(ccbp = bt->bt_ccb_free)) {
+               if (bt->numccbs < BT_CCB_MAX) {
+                       if (ccbp = (struct bt_ccb *) malloc(sizeof(struct bt_ccb),
+                               M_TEMP,
+                               M_NOWAIT)) {
+                               bzero(ccbp, sizeof(struct bt_ccb));
+                               bt->numccbs++;
+                               ccbp->flags = CCB_ACTIVE;
+                               /*
+                                * put in the phystokv hash table
+                                * Never gets taken out.
+                                */
+                               ccbp->hashkey = KVTOPHYS(ccbp);
+                               hashnum = CCB_HASH(ccbp->hashkey);
+                               ccbp->nexthash = bt->ccbhash[hashnum];
+                               bt->ccbhash[hashnum] = ccbp;
+                       } else {
+                               printf("bt%d: Can't malloc CCB\n", unit);
+                       }
+                       goto gottit;
+               } else {
+                       if (!(flags & SCSI_NOSLEEP)) {
+                               sleep(&bt->bt_ccb_free, PRIBIO);
+                       }
+               }
        }
        }
-       if (rc) 
-       {
+       if (ccbp) {
                /* Get CCB from from free list */
                /* Get CCB from from free list */
-               bt_ccb_free[unit] = rc->next;
-               rc->flags = CCB_ACTIVE;
-#ifdef HE      
-               /* Get the Target OUT mail Box pointer */
-               wmbx = &bt_mbx[unit];
-               wmbo = wmbx->tmbo;
-               while ( wmbo->cmd != BT_MBO_FREE ) {
-                       /* Enable MBO available interrupt */
-                       outb(BT_CMD_DATA_PORT,BT_MBO_INTR_EN);
-                       printf("Wait free mbo.."); /* AMURAI */
-                       sleep( wmbx, PRIBIO);
-                       printf("Got free mbo\n");  /* AMURAI */
-               } 
-
-               /* Link CCB to the Mail Box */
-               rc->mbx        = wmbo;
-               wmbo->ccb_addr = KVTOPHYS(rc);
-
-               /* Set the OUT mail Box pointer for next */
-               bt_nextmbx( wmbo, wmbx, mbo );
-               wmbx->tmbo = wmbo;
-#endif
+               bt->bt_ccb_free = ccbp->next;
+               ccbp->flags = CCB_ACTIVE;
        }
        }
-       if (!(flags & SCSI_NOMASK)) 
+      gottit:
+       if (!(flags & SCSI_NOMASK))
                splx(opri);
                splx(opri);
-       
-       return(rc);
+
+       return (ccbp);
+}
+
+/*
+ * given a physical address, find the ccb that
+ * it corresponds to:
+ */
+struct bt_ccb *
+bt_ccb_phys_kv(bt, ccb_phys)
+       struct bt_data *bt;
+       physaddr ccb_phys;
+{
+       int     hashnum = CCB_HASH(ccb_phys);
+       struct bt_ccb *ccbp = bt->ccbhash[hashnum];
+
+       while (ccbp) {
+               if (ccbp->hashkey == ccb_phys)
+                       break;
+               ccbp = ccbp->nexthash;
+       }
+       return ccbp;
 }
 }
-/***********************************************\
-* Get a MBO and then Send it                   *
-\***********************************************/
-BT_MBO *bt_send_mbo( int unit,
-                    int flags,
-                    int cmd,
-                    struct bt_ccb *ccb )
+
+/*
+ * Get a MBO and then Send it  
+ */
+BT_MBO *
+bt_send_mbo(int unit, int flags, int cmd, struct bt_ccb *ccb)
 {
 {
-       unsigned      opri;
-       BT_MBO        *wmbo;    /* Mail Box Out pointer */
-       struct bt_mbx *wmbx;    /* Mail Box pointer specified unit */
-       int           i, wait;
+       struct  bt_data *bt = btdata[unit];
+       unsigned opri;
+       BT_MBO  *wmbo;          /* Mail Box Out pointer */
+       struct  bt_mbx *wmbx;   /* Mail Box pointer specified unit */
+       int     i, wait;
 
 
-       wmbx = &bt_mbx[unit];
+       wmbx = &bt->bt_mbx;
 
 
-       if (!(flags & SCSI_NOMASK)) 
-               opri = splbio();
+       if (!(flags & SCSI_NOMASK))
+               opri = splbio();
 
        /* Get the Target OUT mail Box pointer and move to Next */
        wmbo = wmbx->tmbo;
 
        /* Get the Target OUT mail Box pointer and move to Next */
        wmbo = wmbx->tmbo;
-       wmbx->tmbo = ( wmbo == &( wmbx->mbo[BT_MBX_SIZE - 1 ] ) ?
-                      &(wmbx->mbo[0]) : wmbo + 1 );
+       wmbx->tmbo = (wmbo == &(wmbx->mbo[BT_MBX_SIZE - 1]) ?
+           &(wmbx->mbo[0]) : wmbo + 1);
 
        /* 
 
        /* 
-         * Check the outmail box is free or not
+        * Check the outmail box is free or not.
         * Note: Under the normal operation, it shuld NOT happen to wait.
         * Note: Under the normal operation, it shuld NOT happen to wait.
-         */
-       while ( wmbo->cmd != BT_MBO_FREE ) {
-
-               wait = BT_CMD_TIMEOUT_FUDGE * delaycount; 
-               /* Enable MBO available interrupt */
-               outb(BT_CMD_DATA_PORT,BT_MBO_INTR_EN);
-               for (i=0; i< wait; i++)
-               {
+        */
+       while (wmbo->cmd != BT_MBO_FREE) {
+               wait = 100000;  /* 1 sec enough? */
+               /* Enable MBO available interrupt */
+               outb(BT_CMD_DATA_PORT, BT_MBO_INTR_EN);
+               for (i = wait; i; i--) {
                        if (!(inb(BT_CTRL_STAT_PORT) & BT_CDF))
                                break;
                        if (!(inb(BT_CTRL_STAT_PORT) & BT_CDF))
                                break;
+                       DELAY(10);
                }
                }
-               if (i >=  wait)
-               {
-                       printf("bt%d: bt_send_mbo, cmd/data port full\n",unit);
-                       outb(BT_CTRL_STAT_PORT, BT_SRST); 
-                       return( (BT_MBO *)0 );
+               if (i == 0) {
+                       printf("bt%d: bt_send_mbo, cmd/data port full\n", unit);
+                       outb(BT_CTRL_STAT_PORT, BT_SRST);
+                       return ((BT_MBO *) 0);
                }
                outb(BT_CMD_DATA_PORT, 0x01);   /* Enable */
                }
                outb(BT_CMD_DATA_PORT, 0x01);   /* Enable */
-               sleep( wmbx, PRIBIO);
+               sleep(wmbx, PRIBIO);    /*XXX *//*can't do this! */
+               /* May be servicing an int */
        }
        }
-
        /* Link CCB to the Mail Box */
        /* Link CCB to the Mail Box */
-       wmbo->ccb_addr  = KVTOPHYS(ccb);
-       ccb->mbx        = wmbo;
-       wmbo->cmd       = cmd;
+       wmbo->ccb_addr = KVTOPHYS(ccb);
+       ccb->mbx = wmbo;
+       wmbo->cmd = cmd;
 
 
-       /* Send it ! */
+       /* Send it! */
        outb(BT_CMD_DATA_PORT, BT_START_SCSI);
 
        outb(BT_CMD_DATA_PORT, BT_START_SCSI);
 
-       if (!(flags & SCSI_NOMASK)) 
+       if (!(flags & SCSI_NOMASK))
                splx(opri);
 
                splx(opri);
 
-       return(wmbo);
+       return (wmbo);
 }
 }
-/***********************************************\
-* We have a ccb which has been processed by the        *
-* adaptor, now we look to see how the operation        *
-* went. Wake up the owner if waiting           *
-\***********************************************/
-bt_done(unit,ccb)
-struct bt_ccb *ccb;
-{
-       struct  scsi_sense_data *s1,*s2;
-       struct  scsi_xfer *xs = ccb->xfer;
 
 
-#ifdef UTEST
-       if(scsi_debug & (PRINTROUTINES | TRACEINTERRUPTS))
-               printf("bt_done ");
-#endif
-       /***********************************************\
-       * Otherwise, put the results of the operation   *
-       * into the xfer and call whoever started it     *
-       \***********************************************/
-       if (    (       ccb->host_stat != BT_OK 
-                       || ccb->target_stat != SCSI_OK)
-             && (!(xs->flags & SCSI_ERR_OK)))
-       {
+/*
+ * We have a ccb which has been processed by the
+ * adaptor, now we look to see how the operation
+ * went. Wake up the owner if waiting
+ */
+void
+bt_done(unit, ccb)
+       int     unit;
+       struct  bt_ccb *ccb;
+{
+       struct bt_data *bt = btdata[unit];
+       struct scsi_sense_data *s1, *s2;
+       struct scsi_xfer *xs = ccb->xfer;
+
+       SC_DEBUG(xs->sc_link, SDEV_DB2, ("bt_done\n"));
+       /*
+        * Otherwise, put the results of the operation
+        * into the xfer and call whoever started it
+        */
+       if ((ccb->host_stat != BT_OK || ccb->target_stat != SCSI_OK)
+           && (!(xs->flags & SCSI_ERR_OK))) {
 
                s1 = &(ccb->scsi_sense);
                s2 = &(xs->sense);
 
 
                s1 = &(ccb->scsi_sense);
                s2 = &(xs->sense);
 
-               if(ccb->host_stat)
-               {
-                       switch(ccb->host_stat)
-                       {
-                       case    BT_ABORTED:     /* No response */
-                       case    BT_SEL_TIMEOUT: /* No response */
-#ifdef UTEST
-                               if (bt_debug & BT_SHOWMISC)
-                               {
-                                       printf("timeout reported back\n");
-                               }
-#endif
+               if (ccb->host_stat) {
+                       switch (ccb->host_stat) {
+                       case BT_ABORTED:        /* No response */
+                       case BT_SEL_TIMEOUT:    /* No response */
+                               SC_DEBUG(xs->sc_link, SDEV_DB3,
+                                   ("timeout reported back\n"));
                                xs->error = XS_TIMEOUT;
                                break;
                        default:        /* Other scsi protocol messes */
                                xs->error = XS_DRIVER_STUFFUP;
                                xs->error = XS_TIMEOUT;
                                break;
                        default:        /* Other scsi protocol messes */
                                xs->error = XS_DRIVER_STUFFUP;
-#ifdef UTEST
-                               if (bt_debug & BT_SHOWMISC)
-                               {
-                                       printf("unexpected host_stat: %x\n",
-                                               ccb->host_stat);
-                               }
-#endif
+                               SC_DEBUG(xs->sc_link, SDEV_DB3,
+                                   ("unexpected host_stat: %x\n",
+                                       ccb->host_stat));
                        }
                        }
-
-               }
-               else
-               {
-                       switch(ccb->target_stat)
-                       {
+               } else {
+                       switch (ccb->target_stat) {
                        case 0x02:
                        case 0x02:
-                               /* structure copy!!!!!*/
-                               *s2=*s1;
+                               *s2 = *s1;
                                xs->error = XS_SENSE;
                                break;
                        case 0x08:
                                xs->error = XS_BUSY;
                                break;
                        default:
                                xs->error = XS_SENSE;
                                break;
                        case 0x08:
                                xs->error = XS_BUSY;
                                break;
                        default:
-#ifdef UTEST
-                               if (bt_debug & BT_SHOWMISC)
-                               {
-                                       printf("unexpected target_stat: %x\n",
-                                               ccb->target_stat);
-                               }
-#endif
+                               SC_DEBUG(xs->sc_link, SDEV_DB3,
+                                   ("unexpected target_stat: %x\n",
+                                       ccb->target_stat));
                                xs->error = XS_DRIVER_STUFFUP;
                        }
                }
                                xs->error = XS_DRIVER_STUFFUP;
                        }
                }
-       }
-       else            /* All went correctly  OR errors expected */
-       {
+       } else {                /* All went correctly  OR errors expected */
                xs->resid = 0;
        }
        xs->flags |= ITSDONE;
                xs->resid = 0;
        }
        xs->flags |= ITSDONE;
-       bt_free_ccb(unit,ccb, xs->flags);
-       if(xs->when_done)
-               (*(xs->when_done))(xs->done_arg,xs->done_arg2);
+       bt_free_ccb(unit, ccb, xs->flags);
+       scsi_done(xs);
 }
 
 }
 
-/***********************************************\
-* Start the board, ready for normal operation  *
-\***********************************************/
+/*
+ * Start the board, ready for normal operation
+ */
+int
 bt_init(unit)
 bt_init(unit)
-int    unit;
+       int     unit;
 {
 {
+       struct bt_data *bt = btdata[unit];
        unsigned char ad[4];
        unsigned char ad[4];
-       volatile int i,sts;
-       struct  bt_config conf;
+       volatile int i, sts;
+       struct bt_config conf;
 
 
-       /***********************************************\
-       * reset board, If it doesn't respond, assume    *
-       * that it's not there.. good for the probe      *
-       \***********************************************/
+       /*
+        * reset board, If it doesn't respond, assume 
+        * that it's not there.. good for the probe
+        */
 
 
-       outb(BT_CTRL_STAT_PORT, BT_HRST|BT_SRST);
+       outb(BT_CTRL_STAT_PORT, BT_HRST | BT_SRST);
 
 
-       for (i=0; i < BT_RESET_TIMEOUT; i++)
-       {
-               sts = inb(BT_CTRL_STAT_PORT) ;
-               if ( sts == (BT_IDLE | BT_INIT))
+       for (i = BT_RESET_TIMEOUT; i; i--) {
+               sts = inb(BT_CTRL_STAT_PORT);
+               if (sts == (BT_IDLE | BT_INIT))
                        break;
                        break;
+               DELAY(1000);
        }
        }
-       if (i >= BT_RESET_TIMEOUT)
-       {
-#ifdef UTEST
-               if (bt_debug & BT_SHOWMISC)
-                       printf("bt_init: No answer from bt742a board\n");
+       if (i == 0) {
+#ifdef UTEST
+               printf("bt_init: No answer from bt742a board\n");
 #endif
 #endif
-               return(ENXIO);
+               return (ENXIO);
        }
        }
-
-       /***********************************************\
-       * Assume we have a board at this stage          *
-       * setup dma channel from jumpers and save int   *
-       * level                                         *
-       \***********************************************/
-#ifdef __386BSD__
-       printf("bt%d: reading board settings, ",unit);
-#else  __386BSD__
-       printf("bt%d:",unit);
-#endif __386BSD__
-
-       bt_cmd(unit,0, sizeof(conf), 0 ,&conf, BT_CONF_GET);
-       switch(conf.chan)
-       {
-       case    EISADMA:
-               bt_dma[unit] = -1;
+       /*
+        * Assume we have a board at this stage
+        * setup dma channel from jumpers and save int
+        * level
+        */
+       printf("bt%d: reading board settings, ", unit);
+
+       bt_cmd(unit, 0, sizeof(conf), 0, &conf, BT_CONF_GET);
+       switch (conf.chan) {
+       case EISADMA:
+               bt->bt_dma = -1;
                break;
                break;
-       case    CHAN0:
+       case CHAN0:
                outb(0x0b, 0x0c);
                outb(0x0a, 0x00);
                outb(0x0b, 0x0c);
                outb(0x0a, 0x00);
-               bt_dma[unit] = 0;
+               bt->bt_dma = 0;
                break;
                break;
-       case    CHAN5:
+       case CHAN5:
                outb(0xd6, 0xc1);
                outb(0xd4, 0x01);
                outb(0xd6, 0xc1);
                outb(0xd4, 0x01);
-               bt_dma[unit] = 5;
+               bt->bt_dma = 5;
                break;
                break;
-       case    CHAN6:
+       case CHAN6:
                outb(0xd6, 0xc2);
                outb(0xd4, 0x02);
                outb(0xd6, 0xc2);
                outb(0xd4, 0x02);
-               bt_dma[unit] = 6;
+               bt->bt_dma = 6;
                break;
                break;
-       case    CHAN7:
+       case CHAN7:
                outb(0xd6, 0xc3);
                outb(0xd4, 0x03);
                outb(0xd6, 0xc3);
                outb(0xd4, 0x03);
-               bt_dma[unit] = 7;
+               bt->bt_dma = 7;
                break;
        default:
                break;
        default:
-               printf("illegal dma setting %x\n",conf.chan);
-               return(EIO);
+               printf("illegal dma setting %x\n", conf.chan);
+               return (EIO);
        }
        }
-       if (bt_dma[unit] == -1)
+       if (bt->bt_dma == -1)
                printf("eisa dma, ");
        else
                printf("eisa dma, ");
        else
-               printf("dma=%d, ",bt_dma[unit]);
+               printf("dma=%d, ", bt->bt_dma);
 
 
-       switch(conf.intr)
-       {
-       case    INT9:
-               bt_int[unit] = 9;
+       switch (conf.intr) {
+       case INT9:
+               bt->bt_int = 9;
                break;
                break;
-       case    INT10:
-               bt_int[unit] = 10;
+       case INT10:
+               bt->bt_int = 10;
                break;
                break;
-       case    INT11:
-               bt_int[unit] = 11;
+       case INT11:
+               bt->bt_int = 11;
                break;
                break;
-       case    INT12:
-               bt_int[unit] = 12;
+       case INT12:
+               bt->bt_int = 12;
                break;
                break;
-       case    INT14:
-               bt_int[unit] = 14;
+       case INT14:
+               bt->bt_int = 14;
                break;
                break;
-       case    INT15:
-               bt_int[unit] = 15;
+       case INT15:
+               bt->bt_int = 15;
                break;
        default:
                printf("illegal int setting\n");
                break;
        default:
                printf("illegal int setting\n");
-               return(EIO);
+               return (EIO);
        }
        }
-#ifdef __386BSD__
-       printf("int=%d\n",bt_int[unit]);
-#else
-       printf("int=%d ",bt_int[unit]);
-#endif __386BSD__
+       printf("int=%d\n", bt->bt_int);
 
        /* who are we on the scsi bus */
 
        /* who are we on the scsi bus */
-       bt_scsi_dev[unit] = conf.scsi_dev;
-       /***********************************************\
-       * Initialize mail box                           *
-       \***********************************************/
-       *((physaddr *)ad) = KVTOPHYS(&bt_mbx[unit]);
-       bt_cmd(unit,5, 0, 0, 0, BT_MBX_INIT_EXTENDED
-               , BT_MBX_SIZE
-               , ad[0]
-               , ad[1]
-               , ad[2] 
-               , ad[3]);
-
-       /***********************************************\
-       * Set Pointer chain null for just in case       *
-       * Link the ccb's into a free-list W/O mbox      *
-       * Initilize Mail Box stat to Free               *
-       \***********************************************/
-       if ( bt_ccb_free[unit]  !=  (struct bt_ccb *)0 ) {
+       bt->bt_scsi_dev = conf.scsi_dev;
+       /*
+        * Initialize mail box 
+        */
+       *((physaddr *) ad) = KVTOPHYS(&bt->bt_mbx);
+       bt_cmd(unit, 5, 0, 0, 0, BT_MBX_INIT_EXTENDED
+           ,BT_MBX_SIZE
+           ,ad[0]
+           ,ad[1]
+           ,ad[2]
+           ,ad[3]);
+
+       /*
+        * Set Pointer chain null for just in case
+        * Link the ccb's into a free-list W/O mbox
+        * Initialize mail box status to free
+        */
+       if (bt->bt_ccb_free != (struct bt_ccb *) 0) {
                printf("bt%d: bt_ccb_free is NOT initialized but init here\n",
                printf("bt%d: bt_ccb_free is NOT initialized but init here\n",
-                       unit);
-               bt_ccb_free[unit]        =  (struct bt_ccb *)0;
-       }
-       for (i=0; i < BT_CCB_SIZE; i++) {
-               bt_ccb[unit][i].next     = bt_ccb_free[unit];
-               bt_ccb_free[unit]        = &bt_ccb[unit][i];
-               bt_ccb_free[unit]->flags = CCB_FREE;
+                   unit);
+               bt->bt_ccb_free = (struct bt_ccb *) 0;
        }
        }
-       for (i=0; i < BT_MBX_SIZE; i++) {
-               bt_mbx[unit].mbo[i].cmd  = BT_MBO_FREE;
-               bt_mbx[unit].mbi[i].stat = BT_MBI_FREE;
+       for (i = 0; i < BT_MBX_SIZE; i++) {
+               bt->bt_mbx.mbo[i].cmd = BT_MBO_FREE;
+               bt->bt_mbx.mbi[i].stat = BT_MBI_FREE;
        }
        }
-
-       /***********************************************\
-       * Set up Initial mail box for round-robin       *
-       \***********************************************/
-       bt_mbx[unit].tmbo = &bt_mbx[unit].mbo[0];
-       bt_mbx[unit].tmbi = &bt_mbx[unit].mbi[0];
-       bt_inquire_setup_information( unit );
-
-       /*  Enable round-robin scheme - appeared at FirmWare 3.31 */
-       bt_cmd(unit, 1, 0, 0, 0, BT_ROUND_ROBIN, BT_ENABLE );
-
-       /***********************************************\
-       * Note that we are going and return (to probe)  *
-       \***********************************************/
-       bt_initialized[unit]++;
-       return( 0 );
+       /*
+        * Set up initial mail box for round-robin operation.
+        */
+       bt->bt_mbx.tmbo = &bt->bt_mbx.mbo[0];
+       bt->bt_mbx.tmbi = &bt->bt_mbx.mbi[0];
+       bt_inquire_setup_information(unit);
+
+       /* Enable round-robin scheme - appeared at firmware rev. 3.31 */
+       bt_cmd(unit, 1, 0, 0, 0, BT_ROUND_ROBIN, BT_ENABLE);
+
+       /*
+        * Note that we are going and return (to probe)
+        */
+       return 0;
 }
 }
-bt_inquire_setup_information( unit )
-int    unit;
+
+void
+bt_inquire_setup_information(unit)
+       int     unit;
 {
 {
+       struct  bt_data *bt = btdata[unit];
        struct  bt_setup setup;
        struct  bt_boardID bID;
        int     i;
 
        struct  bt_setup setup;
        struct  bt_boardID bID;
        int     i;
 
-       /* Inquire Board ID to Bt742 for FirmWare Version */
-       bt_cmd(unit, 0, sizeof(bID), 0, &bID, BT_INQUIRE );
+       /* Inquire Board ID to Bt742 for firmware version */
+       bt_cmd(unit, 0, sizeof(bID), 0, &bID, BT_INQUIRE);
        printf("bt%d: version %c.%c, ",
        printf("bt%d: version %c.%c, ",
-               unit, bID.firm_revision, bID.firm_version );
+           unit, bID.firm_revision, bID.firm_version);
 
 
-       /*  Ask setup information to Bt742 */
-       bt_cmd(unit, 1, sizeof(setup), 0, &setup, BT_SETUP_GET, sizeof(setup) );
+       /* Obtain setup information from Bt742. */
+       bt_cmd(unit, 1, sizeof(setup), 0, &setup, BT_SETUP_GET, sizeof(setup));
 
 
-       if ( setup.sync_neg ) {
+       if (setup.sync_neg) {
                printf("sync, ");
        } else {
                printf("async, ");
        }
                printf("sync, ");
        } else {
                printf("async, ");
        }
-
-       if ( setup.parity ) {
+       if (setup.parity) {
                printf("parity, ");
        } else {
                printf("no parity, ");
        }
                printf("parity, ");
        } else {
                printf("no parity, ");
        }
+       printf("%d mbxs, %d ccbs\n", setup.num_mbx, bt->numccbs);
 
 
-       printf("%d mbxs, %d ccbs\n", setup.num_mbx,
-               sizeof(bt_ccb)/(sizeof(struct bt_ccb) * NBT) );
-
-       for ( i = 0; i < 8; i++ ) {
-               if( !setup.sync[i].offset &&
+       for (i = 0; i < 8; i++) {
+               if (!setup.sync[i].offset &&
                    !setup.sync[i].period &&
                    !setup.sync[i].period &&
-                   !setup.sync[i].valid        )
+                   !setup.sync[i].valid)
                        continue;
 
                printf("bt%d: dev%02d Offset=%d,Transfer period=%d, Synchronous? %s",
                        continue;
 
                printf("bt%d: dev%02d Offset=%d,Transfer period=%d, Synchronous? %s",
-                       unit, i,
-                       setup.sync[i].offset, setup.sync[i].period, 
-                       setup.sync[i].valid  ? "Yes" : "No" );
+                   unit, i,
+                   setup.sync[i].offset, setup.sync[i].period,
+                   setup.sync[i].valid ? "Yes" : "No");
        }
        }
-       
 }
 
 }
 
-
 #ifndef        min
 #define min(x,y) (x < y ? x : y)
 #ifndef        min
 #define min(x,y) (x < y ? x : y)
-#endif min
-
+#endif /* min */
 
 
-void btminphys(bp)
-struct buf *bp;
+void 
+btminphys(bp)
+       struct buf *bp;
 {
 {
-#ifdef MACH
-#if    !defined(OSF)
-       bp->b_flags |= B_NPAGES;                /* can support scat/gather */
-#endif /* defined(OSF) */
-#endif MACH
-       if(bp->b_bcount > ((BT_NSEG-1) * PAGESIZ))
-       {
-               bp->b_bcount = ((BT_NSEG-1) * PAGESIZ);
+       if (bp->b_bcount > ((BT_NSEG - 1) * PAGESIZ)) {
+               bp->b_bcount = ((BT_NSEG - 1) * PAGESIZ);
        }
 }
        }
 }
-       
-/***********************************************\
-* start a scsi operation given the command and *
-* the data address. Also needs the unit, target        *
-* and lu                                       *
-\***********************************************/
-int    bt_scsi_cmd(xs)
-struct scsi_xfer *xs;
+
+/*
+ * start a scsi operation given the command and the data address.  Also needs
+ * the unit, target and lu.
+ */
+int32 
+bt_scsi_cmd(xs)
+       struct scsi_xfer *xs;
 {
 {
-       struct  scsi_sense_data *s1,*s2;
-       struct bt_ccb *ccb;
-       struct bt_scat_gath *sg;
-       int     seg;    /* scatter gather seg being worked on */
-       int i   = 0;
-       int rc  =  0;
+       struct  scsi_sense_data *s1, *s2;
+       struct  bt_ccb *ccb;
+       struct  bt_scat_gath *sg;
+       int     seg;            /* scatter gather seg being worked on */
+       int     i = 0;
+       int     c = 0;
        int     thiskv;
        int     thiskv;
-       physaddr        thisphys,nextphys;
-       int     unit =xs->adapter;
-       int     bytes_this_seg,bytes_this_page,datalen,flags;
-       struct  iovec   *iovp;
+       physaddr thisphys, nextphys;
+       int     unit = xs->sc_link->adapter_unit;
+       int     bytes_this_seg, bytes_this_page, datalen, flags;
+       struct  iovec *iovp;
+       struct  bt_data *bt = btdata[unit];
        BT_MBO  *mbo;
 
        BT_MBO  *mbo;
 
-#ifdef UTEST
-       if(scsi_debug & PRINTROUTINES)
-               printf("bt_scsi_cmd ");
-#endif
-       /***********************************************\
-       * get a ccb (mbox-out) to use. If the transfer  *
-       * is from a buf (possibly from interrupt time)  *
-       * then we can't allow it to sleep               *
-       \***********************************************/
+       SC_DEBUG(xs->sc_link, SDEV_DB2, ("bt_scsi_cmd\n"));
+       /*
+        * get a ccb (mbox-out) to use. If the transfer
+        * is from a buf (possibly from interrupt time)
+        * then we can't allow it to sleep
+        */
        flags = xs->flags;
        flags = xs->flags;
-       if(xs->bp) flags |= (SCSI_NOSLEEP); /* just to be sure */
-       if(flags & ITSDONE)
-       {
-               printf("bt%d: Already done?\n",unit);
+       if (xs->bp)
+               flags |= (SCSI_NOSLEEP);        /* just to be sure */
+       if (flags & ITSDONE) {
+               printf("bt%d: Already done?\n", unit);
                xs->flags &= ~ITSDONE;
        }
                xs->flags &= ~ITSDONE;
        }
-       if(!(flags & INUSE))
-       {
-               printf("bt%d: Not in use?\n",unit);
+       if (!(flags & INUSE)) {
+               printf("bt%d: Not in use?\n", unit);
                xs->flags |= INUSE;
        }
                xs->flags |= INUSE;
        }
-       if (!(ccb = bt_get_ccb(unit,flags)))
-       {
+       if (!(ccb = bt_get_ccb(unit, flags))) {
                xs->error = XS_DRIVER_STUFFUP;
                xs->error = XS_DRIVER_STUFFUP;
-               return(TRY_AGAIN_LATER);
+               return (TRY_AGAIN_LATER);
        }
        }
-#ifdef UTEST
-       if(bt_debug & BT_SHOWCCBS)
-                               printf("<start ccb(%x)>",ccb);
-#endif
-       /***********************************************\
-       * Put all the arguments for the xfer in the ccb *
-       \***********************************************/
-       ccb->xfer               =       xs;
-       if(flags & SCSI_RESET)
-       {
-               ccb->opcode     =       BT_RESET_CCB;
-       }
-       else
-       {
+       SC_DEBUG(xs->sc_link, SDEV_DB3,
+           ("start ccb(%x)\n", ccb));
+       /*
+        * Put all the arguments for the xfer in the ccb
+        */
+       ccb->xfer = xs;
+       if (flags & SCSI_RESET) {
+               ccb->opcode = BT_RESET_CCB;
+       } else {
                /* can't use S/G if zero length */
                /* can't use S/G if zero length */
-               ccb->opcode     =       (xs->datalen?
-                                               BT_INIT_SCAT_GATH_CCB
-                                               :BT_INITIATOR_CCB);
+               ccb->opcode = (xs->datalen ?
+                   BT_INIT_SCAT_GATH_CCB
+                   BT_INITIATOR_CCB);
        }
        }
-       ccb->target             =       xs->targ;;
-       ccb->data_out           =       0;
-       ccb->data_in            =       0;
-       ccb->lun                =       xs->lu;
-       ccb->scsi_cmd_length    =       xs->cmdlen;
-       ccb->sense_ptr          =       KVTOPHYS(&(ccb->scsi_sense));
-       ccb->req_sense_length   =       sizeof(ccb->scsi_sense);
-
-       if((xs->datalen) && (!(flags & SCSI_RESET)))
-       { /* can use S/G only if not zero length */
+       ccb->target = xs->sc_link->target;
+       ccb->data_out = 0;
+       ccb->data_in = 0;
+       ccb->lun = xs->sc_link->lun;
+       ccb->scsi_cmd_length = xs->cmdlen;
+       ccb->sense_ptr = KVTOPHYS(&(ccb->scsi_sense));
+       ccb->req_sense_length = sizeof(ccb->scsi_sense);
+
+       if ((xs->datalen) && (!(flags & SCSI_RESET))) {         /* can use S/G only if not zero length */
                ccb->data_addr = KVTOPHYS(ccb->scat_gath);
                ccb->data_addr = KVTOPHYS(ccb->scat_gath);
-               sg              =       ccb->scat_gath ;
-               seg             =       0;
-               if(flags & SCSI_DATA_UIO)
-               {
-                       iovp = ((struct uio *)xs->data)->uio_iov;
-                       datalen = ((struct uio *)xs->data)->uio_iovcnt;
+               sg = ccb->scat_gath;
+               seg = 0;
+#ifdef TFS
+               if (flags & SCSI_DATA_UIO) {
+                       iovp = ((struct uio *) xs->data)->uio_iov;
+                       datalen = ((struct uio *) xs->data)->uio_iovcnt;
                        xs->datalen = 0;
                        xs->datalen = 0;
-                       while ((datalen) && (seg < BT_NSEG))
-                       {
-                               sg->seg_addr = (physaddr)iovp->iov_base;
-                               xs->datalen += sg->seg_len = iovp->iov_len;     
-#ifdef UTEST
-                               if(scsi_debug & SHOWSCATGATH)
-                                       printf("(0x%x@0x%x)"
-                                                       ,iovp->iov_len
-                                                       ,iovp->iov_base);
-#endif
+                       while ((datalen) && (seg < BT_NSEG)) {
+                               sg->seg_addr = (physaddr) iovp->iov_base;
+                               xs->datalen += sg->seg_len = iovp->iov_len;
+                               SC_DEBUGN(xs->sc_link, SDEV_DB4, ("(0x%x@0x%x)"
+                                       ,iovp->iov_len, iovp->iov_base));
                                sg++;
                                iovp++;
                                seg++;
                                datalen--;
                        }
                                sg++;
                                iovp++;
                                seg++;
                                datalen--;
                        }
-               }
-               else
+               } else
+#endif /* TFS */
                {
                {
-                       /***********************************************\
-                       * Set up the scatter gather block               *
-                       \***********************************************/
-               
-#ifdef UTEST
-                       if(scsi_debug & SHOWSCATGATH)
-                               printf("%d @0x%x:- ",xs->datalen,xs->data);
-#endif
-                       datalen         =       xs->datalen;
-                       thiskv          =       (int)xs->data;
-                       thisphys        =       KVTOPHYS(thiskv);
-               
-                       while ((datalen) && (seg < BT_NSEG))
-                       {
-                               bytes_this_seg  = 0;
-       
+                       /*
+                        * Set up the scatter gather block
+                        */
+
+                       SC_DEBUG(xs->sc_link, SDEV_DB4,
+                           ("%d @0x%x:- ", xs->datalen, xs->data));
+                       datalen = xs->datalen;
+                       thiskv = (int) xs->data;
+                       thisphys = KVTOPHYS(thiskv);
+
+                       while ((datalen) && (seg < BT_NSEG)) {
+                               bytes_this_seg = 0;
+
                                /* put in the base address */
                                sg->seg_addr = thisphys;
                                /* put in the base address */
                                sg->seg_addr = thisphys;
-               
-#ifdef UTEST
-                               if(scsi_debug & SHOWSCATGATH)
-                                       printf("0x%x",thisphys);
-#endif
-       
+
+                               SC_DEBUGN(xs->sc_link, SDEV_DB4,
+                                   ("0x%x", thisphys));
+
                                /* do it at least once */
                                /* do it at least once */
-                               nextphys = thisphys;    
+                               nextphys = thisphys;
                                while ((datalen) && (thisphys == nextphys))
                                while ((datalen) && (thisphys == nextphys))
-                               /*********************************************\
-                               * This page is contiguous (physically) with   *
-                               * the the last, just extend the length        *
-                               \*********************************************/
+                                       /*
+                                        * This page is contiguous (physically) with 
+                                        * the the last, just extend the length 
+                                        */
                                {
                                        /* how far to the end of the page */
                                {
                                        /* how far to the end of the page */
-                                       nextphys= (thisphys & (~(PAGESIZ - 1)))
-                                                               + PAGESIZ;
-                                       bytes_this_page = nextphys - thisphys;
+                                       nextphys = (thisphys & (~(PAGESIZ - 1)))
+                                           + PAGESIZ;
+                                       bytes_this_page = nextphys - thisphys;
                                        /**** or the data ****/
                                        /**** or the data ****/
-                                       bytes_this_page = min(bytes_this_page
-                                                               ,datalen);
-                                       bytes_this_seg  += bytes_this_page;
-                                       datalen         -= bytes_this_page;
-               
+                                       bytes_this_page = min(bytes_this_page
+                                           ,datalen);
+                                       bytes_this_seg += bytes_this_page;
+                                       datalen -= bytes_this_page;
+
                                        /* get more ready for the next page */
                                        /* get more ready for the next page */
-                                       thiskv  = (thiskv & (~(PAGESIZ - 1)))
-                                                               + PAGESIZ;
-                                       if(datalen)
+                                       thiskv = (thiskv & (~(PAGESIZ - 1)))
+                                           + PAGESIZ;
+                                       if (datalen)
                                                thisphys = KVTOPHYS(thiskv);
                                }
                                                thisphys = KVTOPHYS(thiskv);
                                }
-                               /********************************************\
-                               * next page isn't contiguous, finish the seg *
-                               \********************************************/
-#ifdef UTEST
-                               if(scsi_debug & SHOWSCATGATH)
-                                       printf("(0x%x)",bytes_this_seg);
-#endif
-                               sg->seg_len = bytes_this_seg;   
+                               /*
+                                * next page isn't contiguous, finish the seg
+                                */
+                               SC_DEBUGN(xs->sc_link, SDEV_DB4,
+                                   ("(0x%x)", bytes_this_seg));
+                               sg->seg_len = bytes_this_seg;
                                sg++;
                                seg++;
                        }
                                sg++;
                                seg++;
                        }
-               } /*end of iov/kv decision */
+               }
+               /* end of iov/kv decision */
                ccb->data_length = seg * sizeof(struct bt_scat_gath);
                ccb->data_length = seg * sizeof(struct bt_scat_gath);
-#ifdef UTEST
-               if(scsi_debug & SHOWSCATGATH)
-                       printf("\n");
-#endif
-               if (datalen)
-               { /* there's still data, must have run out of segs! */
+               SC_DEBUGN(xs->sc_link, SDEV_DB4, ("\n"));
+               if (datalen) {
+                       /*
+                        * there's still data, must have run out of segs!
+                        */
                        printf("bt%d: bt_scsi_cmd, more than %d DMA segs\n",
                        printf("bt%d: bt_scsi_cmd, more than %d DMA segs\n",
-                               unit,BT_NSEG);
+                           unit, BT_NSEG);
                        xs->error = XS_DRIVER_STUFFUP;
                        xs->error = XS_DRIVER_STUFFUP;
-                       bt_free_ccb(unit,ccb,flags);
-                       return(HAD_ERROR);
+                       bt_free_ccb(unit, ccb, flags);
+                       return (HAD_ERROR);
                }
                }
-
-       }
-       else
-       {       /* No data xfer, use non S/G values */
-               ccb->data_addr = (physaddr)0;
+       } else {                /* No data xfer, use non S/G values */
+               ccb->data_addr = (physaddr) 0;
                ccb->data_length = 0;
        }
        ccb->link_id = 0;
                ccb->data_length = 0;
        }
        ccb->link_id = 0;
-       ccb->link_addr = (physaddr)0;
-       /***********************************************\
-       * Put the scsi command in the ccb and start it  *
-       \***********************************************/
-       if(!(flags & SCSI_RESET))
-       {
+       ccb->link_addr = (physaddr) 0;
+       /*
+        * Put the scsi command in the ccb and start it
+        */
+       if (!(flags & SCSI_RESET)) {
                bcopy(xs->cmd, ccb->scsi_cmd, ccb->scsi_cmd_length);
        }
                bcopy(xs->cmd, ccb->scsi_cmd, ccb->scsi_cmd_length);
        }
-#ifdef UTEST
-       if(scsi_debug & SHOWCOMMANDS)
-       {
-               u_char  *b = ccb->scsi_cmd;
-               if(!(flags & SCSI_RESET))
-               {
-                       int i = 0;
-                       printf("bt%d:%d:%d-"
-                               ,unit
-                               ,ccb->target
-                               ,ccb->lun);
-                       while(i < ccb->scsi_cmd_length )
-                       {
-                               if(i) printf(",");
-                               printf("%x",b[i++]);
-                       }
-                       printf("-\n");
-               }
-               else
-               {
-                       printf("bt%d:%d:%d-RESET- " 
-                               ,unit 
-                               ,ccb->target
-                               ,ccb->lun
-                       );
-               }
-       }
-#endif
-       if ( bt_send_mbo( unit, flags, BT_MBO_START, ccb ) == (BT_MBO *)0 )
-       {
+       if (bt_send_mbo(unit, flags, BT_MBO_START, ccb) == (BT_MBO *) 0) {
                xs->error = XS_DRIVER_STUFFUP;
                xs->error = XS_DRIVER_STUFFUP;
-               bt_free_ccb(unit,ccb,flags);
-               return(TRY_AGAIN_LATER);
+               bt_free_ccb(unit, ccb, flags);
+               return (TRY_AGAIN_LATER);
        }
        }
-       /***********************************************\
-       * Usually return SUCCESSFULLY QUEUED            *
-       \***********************************************/
-#ifdef UTEST
-       if(scsi_debug & TRACEINTERRUPTS)
-               printf("cmd_sent ");
-#endif
-       if (!(flags & SCSI_NOMASK))
-       {
-               timeout(bt_timeout,ccb,(xs->timeout * hz) / 1000);
-               return(SUCCESSFULLY_QUEUED);
-       } else
-       /***********************************************\
-       * If we can't use interrupts, poll on completion*
-       \***********************************************/
-       {
-               int done = 0;
-               int count = delaycount * xs->timeout / BT_SCSI_TIMEOUT_FUDGE;
-               struct bt_mbx *wmbx = &bt_mbx[unit];
-               BT_MBI        *wmbi = wmbx->tmbi;
-               unsigned char stat;
-#ifdef UTEST
-               if(scsi_debug & TRACEINTERRUPTS)
-                       printf("wait ");
-#endif
-               while((!done) && count)
-               {
-                       stat = inb(BT_INTR_PORT) & (BT_ANY_INTR | BT_MBIF );
-                       if ( !( stat & BT_ANY_INTR )       ||
-                             ( wmbi->stat == BT_MBI_FREE )||
-                             (PHYSTOKV(wmbi->ccb_addr) 
-                                       != (int)ccb      ) ) {
-                               count--;
-                               continue;
-                       }
-                       wmbi->stat = BT_MBI_FREE;
-                       bt_done(unit,ccb);
-                       done ++;
-                       outb(BT_CTRL_STAT_PORT, BT_IRST);
-                       /* Set the IN mail Box pointer for next */
-                       bt_nextmbx( wmbi, wmbx, mbi );
-                       wmbx->tmbi = wmbi;
+       /*
+        * Usually return SUCCESSFULLY QUEUED
+        */
+       SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_sent\n"));
+       if (!(flags & SCSI_NOMASK)) {
+               timeout(bt_timeout, ccb, (xs->timeout * hz) / 1000);
+               return (SUCCESSFULLY_QUEUED);
+       }
+       /*
+        * If we can't use interrupts, poll on completion
+        */
+       return (bt_poll(unit, xs, ccb));
+}
+
+/*
+ * Poll a particular unit, looking for a particular xs
+ */
+int 
+bt_poll(unit, xs, ccb)
+       int     unit;
+       struct  scsi_xfer *xs;
+       struct  bt_ccb *ccb;
+{
+       struct  bt_data *bt = btdata[unit];
+       int     done = 0;
+       int     count = xs->timeout;
+       u_char  stat;
+
+       /* timeouts are in msec, so we loop in 1000 usec cycles */
+       while (count) {
+               /*
+                * If we had interrupts enabled, would we
+                * have got an interrupt?
+                */
+               stat = inb(BT_INTR_PORT);
+               if (stat & BT_ANY_INTR) {
+                       btintr(unit);
                }
                }
-               if (!count && !done)
-               {
-#ifdef UTEST
-                       if (!(xs->flags & SCSI_SILENT))
-                               printf("cmd fail\n");
-#endif
-                       bt_send_mbo( unit, flags, BT_MBO_ABORT, ccb );
-                       count = delaycount * 2000 / BT_SCSI_TIMEOUT_FUDGE;
-                       while((!done) && count)
-                       {
-                               if ( !( stat & BT_ANY_INTR )       ||
-                                     ( wmbi->stat == BT_MBI_FREE )||
-                                     ( PHYSTOKV(wmbi->ccb_addr )
-                                                != (int)ccb     ) ) {
-                                       count--;
-                                       continue;
-                               }
-                               wmbi->stat = BT_MBI_FREE;
-                               bt_done(unit,ccb);
-                               done ++;
-                               outb(BT_CTRL_STAT_PORT, BT_IRST);
-                               /* Set the IN mail Box pointer for next */
-                               bt_nextmbx( wmbi, wmbx, mbi );
-                               wmbx->tmbi = wmbi;
+               if (xs->flags & ITSDONE) {
+                       break;
+               }
+               DELAY(1000);    /* only happens in boot so ok */
+               count--;
+       }
+       if (count == 0) {
+               /*
+                * We timed out, so call the timeout handler manually,
+                * accounting for the fact that the clock is not running yet
+                * by taking out the clock queue entry it makes.
+                */
+               bt_timeout(ccb);
+
+               /*
+                * because we are polling, take out the timeout entry
+                * bt_timeout made
+                */
+               untimeout(bt_timeout, ccb);
+               count = 2000;
+               while (count) {
+                       /*
+                        * Once again, wait for the int bit
+                        */
+                       stat = inb(BT_INTR_PORT);
+                       if (stat & BT_ANY_INTR) {
+                               btintr(unit);
                        }
                        }
-                       if(!count && !done)
-                       {
-                               printf("bt%d: abort failed in wait\n", unit);
-                               ccb->mbx->cmd = BT_MBO_FREE;
+                       if (xs->flags & ITSDONE) {
+                               break;
                        }
                        }
-                       bt_free_ccb(unit,ccb,flags);
-                       xs->error = XS_DRIVER_STUFFUP;
-                       return(HAD_ERROR);
+                       DELAY(1000);    /* only happens in boot so ok */
+                       count--;
+               }
+               if (count == 0) {
+                       /*
+                        * We timed out again...  This is bad.  Notice that
+                        * this time there is no clock queue entry to remove.
+                        */
+                       bt_timeout(ccb);
                }
                }
-               if(xs->error) return(HAD_ERROR);
-               return(COMPLETE);
        }
        }
+       if (xs->error)
+               return (HAD_ERROR);
+       return (COMPLETE);
 }
 
 }
 
-
-bt_timeout(struct bt_ccb *ccb)
+void
+bt_timeout(struct bt_ccb * ccb)
 {
 {
-       int     unit;
-       int     s       = splbio();
+       int     unit;
+       struct bt_data *bt;
+       int     s = splbio();
+
+       unit = ccb->xfer->sc_link->adapter_unit;
+       bt = btdata[unit];
+       printf("bt%d:%d:%d (%s%d) timed out ", unit
+           ,ccb->xfer->sc_link->target
+           ,ccb->xfer->sc_link->lun
+           ,ccb->xfer->sc_link->device->name
+           ,ccb->xfer->sc_link->dev_unit);
 
 
-       unit = ccb->xfer->adapter;
-       printf("bt%d: %d device timed out\n",unit
-                       ,ccb->xfer->targ);
 #ifdef UTEST
 #ifdef UTEST
-       if(bt_debug & BT_SHOWCCBS)
-               bt_print_active_ccbs(unit);
+       bt_print_active_ccbs(unit);
 #endif
 
 #endif
 
-       /***************************************\
-       * If The ccb's mbx is not free, then    *
-       * the board has gone Far East ?         *
-       \***************************************/
-       if((struct bt_ccb *)PHYSTOKV(ccb->mbx->ccb_addr)==ccb &&
-           ccb->mbx->cmd != BT_MBO_FREE )
-       {
-               printf("bt%d: not taking commands!\n"
-                                       ,unit);
-               Debugger();
-       }
-       /***************************************\
-       * If it has been through before, then   *
-       * a previous abort has failed, don't    *
-       * try abort again                       *
-       \***************************************/
-       if(ccb->flags == CCB_ABORTED) /* abort timed out */
-       {
-               printf("bt%d: Abort Operation has timed out\n",unit);
-               ccb->xfer->retries = 0; /* I MEAN IT ! */
-               ccb->host_stat = BT_ABORTED;
-               bt_done(unit,ccb);
+       /*
+        * If the ccb's mbx is not free, then the board has gone Far East?
+        */
+       if (bt_ccb_phys_kv(bt, ccb->mbx->ccb_addr) == ccb &&
+           ccb->mbx->cmd != BT_MBO_FREE) {
+               printf("bt%d: not taking commands!\n", unit);
+               Debugger();
        }
        }
-       else    /* abort the operation that has timed out */
-       {
-               printf("bt%d: Try to abort\n",unit);
-                       bt_send_mbo( unit, ~SCSI_NOMASK,
-                            BT_MBO_ABORT, ccb );
-                       /* 2 secs for the abort */
-               timeout(bt_timeout,ccb,2 * hz);
+       /*
+        * If it has been through before, then
+        * a previous abort has failed, don't
+        * try abort again
+        */
+       if (ccb->flags == CCB_ABORTED) {
+               /*
+                * abort timed out
+                */
+               printf("bt%d: Abort Operation has timed out\n", unit);
+               ccb->xfer->retries = 0;         /* I MEAN IT ! */
+               ccb->host_stat = BT_ABORTED;
+               bt_done(unit, ccb);
+       } else {                /* abort the operation that has timed out */
+               printf("bt%d: Try to abort\n", unit);
+               bt_send_mbo(unit, ~SCSI_NOMASK,
+                   BT_MBO_ABORT, ccb);
+               /* 2 secs for the abort */
+               timeout(bt_timeout, ccb, 2 * hz);
                ccb->flags = CCB_ABORTED;
        }
        splx(s);
 }
 
 #ifdef UTEST
                ccb->flags = CCB_ABORTED;
        }
        splx(s);
 }
 
 #ifdef UTEST
+void
 bt_print_ccb(ccb)
 bt_print_ccb(ccb)
-struct bt_ccb *ccb;
+       struct bt_ccb *ccb;
 {
        printf("ccb:%x op:%x cmdlen:%d senlen:%d\n"
 {
        printf("ccb:%x op:%x cmdlen:%d senlen:%d\n"
-               ,ccb
-               ,ccb->opcode
-               ,ccb->scsi_cmd_length
-               ,ccb->req_sense_length);
+           ,ccb
+           ,ccb->opcode
+           ,ccb->scsi_cmd_length
+           ,ccb->req_sense_length);
        printf("        datlen:%d hstat:%x tstat:%x flags:%x\n"
        printf("        datlen:%d hstat:%x tstat:%x flags:%x\n"
-               ,ccb->data_length
-               ,ccb->host_stat
-               ,ccb->target_stat
-               ,ccb->flags);
+           ,ccb->data_length
+           ,ccb->host_stat
+           ,ccb->target_stat
+           ,ccb->flags);
 }
 
 }
 
+void
 bt_print_active_ccbs(int unit)
 {
 bt_print_active_ccbs(int unit)
 {
-       struct  bt_ccb *ccb;
-       ccb = &(bt_ccb[unit][0]);
-       int     i = BT_CCB_SIZE;
-
-       while(i--)
-       {
-               if(ccb->flags != CCB_FREE)
-                       bt_print_ccb(ccb);
-               ccb++;
+       struct bt_data *bt = btdata[unit];
+       struct bt_ccb *ccb;
+       int     i = 0;
+
+       while (i < CCB_HASH_SIZE) {
+               ccb = bt->ccbhash[i];
+               while (ccb) {
+                       if (ccb->flags != CCB_FREE)
+                               bt_print_ccb(ccb);
+                       ccb = ccb->nexthash;
+               }
+               i++;
        }
 }
        }
 }
-#endif /*UTEST*/
+#endif /*UTEST */
+#endif /*KERNEL */
index 0d9b08c..76dc115 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Ported for use with the UltraStor 14f by Gary Close (gclose@wvnvms.wvnet.edu)
 /*
  * Ported for use with the UltraStor 14f by Gary Close (gclose@wvnvms.wvnet.edu)
+ * Slight fixes to timeouts to run with the 34F
  * Thanks to Julian Elischer for advice and help with this port.
  *
  * Written by Julian Elischer (julian@tfs.com)
  * Thanks to Julian Elischer for advice and help with this port.
  *
  * Written by Julian Elischer (julian@tfs.com)
  * commenced: Sun Sep 27 18:14:01 PDT 1992
  * slight mod to make work with 34F as well: Wed Jun  2 18:05:48 WST 1993
  *
  * commenced: Sun Sep 27 18:14:01 PDT 1992
  * slight mod to make work with 34F as well: Wed Jun  2 18:05:48 WST 1993
  *
- *     $Id: ultra14f.c,v 1.10 1993/10/14 00:07:04 rgrimes Exp $
+ *      $Id: ultra14f.c,v 2.3 93/10/16 02:01:08 julian Exp Locker: julian $
  */
  */
+
 #include <sys/types.h>
 #include <sys/types.h>
+
+#ifdef KERNEL                  /* don't laugh.. this compiles to a program too.. look */
 #include <uha.h>
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/errno.h>
 #include <sys/ioctl.h>
 #include <uha.h>
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/errno.h>
 #include <sys/ioctl.h>
+#include <sys/malloc.h>
 #include <sys/buf.h>
 #include <sys/proc.h>
 #include <sys/user.h>
 
 #include <sys/buf.h>
 #include <sys/proc.h>
 #include <sys/user.h>
 
-#ifdef  MACH    /* EITHER CMU OR OSF */
-#include <i386/ipl.h>
-#include <i386at/scsi.h>
-#include <i386at/scsiconf.h>
-
-#ifdef  OSF     /* OSF ONLY */
-#include <sys/table.h>
-#include <i386/handler.h>
-#include <i386/dispatcher.h>
-#include <i386/AT386/atbus.h>
-
-#else   OSF     /* CMU ONLY */
-#include <i386at/atbus.h>
-#include <i386/pio.h>
-#endif  OSF
-#endif  MACH    /* end of MACH specific */
-
-#ifdef  __386BSD__      /* 386BSD specific */
-#define isa_dev isa_device
-#define dev_unit id_unit
-#define dev_addr id_iobase
-
 #include <i386/include/pio.h>
 #include <i386/isa/isa_device.h>
 #include <i386/include/pio.h>
 #include <i386/isa/isa_device.h>
+#endif /*KERNEL */
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
-#endif  __386BSD__
 
 
-/*\f*/
+/*\f */
 
 
-#ifdef  __386BSD__
+#ifdef KERNEL
 #include "ddb.h"
 #if     NDDB > 0
 int     Debugger();
 #include "ddb.h"
 #if     NDDB > 0
 int     Debugger();
-#else   NDDB
+#else  /* NDDB */
 #define Debugger() panic("should call debugger here")
 #define Debugger() panic("should call debugger here")
-#endif  NDDB
-#endif  __386BSD__
-
-#ifdef  MACH
-int     Debugger();
-#endif  MACH
+#endif /* NDDB */
+#else /*KERNEL */
+#define NUHA 1
+#endif /*KERNEL */
+
+typedef struct {
+       unsigned char addr[4];
+} physaddr;
+typedef struct {
+       unsigned char len[4];
+} physlen;
 
 
-typedef struct {unsigned char addr[4]; } physaddr;
-typedef struct {unsigned char len[4]; } physlen;
+#define KVTOPHYS(x)   vtophys(x)
 
 
+#define UHA_MSCP_MAX   32      /* store up to 32MSCPs at any one time
+                                * MAX = ?
+                                */
+#define        MSCP_HASH_SIZE  32      /* when we have a physical addr. for
+                                * a mscp and need to find the mscp in
+                                * space, look it up in the hash table
+                                */
+#define        MSCP_HASH_SHIFT 9       /* only hash on multiples of 512 */
+#define MSCP_HASH(x)   ((((long int)(x))>>MSCP_HASH_SHIFT) % MSCP_HASH_SIZE)
 
 
-#ifdef        MACH
-extern physaddr kvtophys();
-#define PHYSTOKV(x)   phystokv(x)
-#define KVTOPHYS(x)   kvtophys(x)
-#endif MACH
+extern int hz;
+#define UHA_NSEG        33     /* number of dma segments supported */
 
 
-#ifdef        __386BSD__
-#define KVTOPHYS(x)   vtophys(x)
-#endif        __386BSD__
-
-extern int      hz;
-extern int delaycount;  /* from clock setup code */
-#define NUM_CONCURRENT 16      /* number of concurrent ops per board */
-#define UHA_NSEG        33      /* number of dma segments supported     */
-#define FUDGE(X)        (X>>1)  /* our loops are slower than spinwait() */
-/*\f*/
 /************************** board definitions *******************************/
 /*
  * I/O Port Interface
 /************************** board definitions *******************************/
 /*
  * I/O Port Interface
-*/
- #define UHA_LMASK              (0x000)  /* local doorbell mask reg */
- #define UHA_LINT               (0x001)  /* local doorbell int/stat reg */
- #define UHA_SMASK              (0x002)  /* system doorbell mask reg */
- #define UHA_SINT               (0x003)  /* system doorbell int/stat reg */
- #define UHA_ID0                (0x004)  /* product id reg 0 */
- #define UHA_ID1                (0x005)  /* product id reg 1 */
- #define UHA_CONF1              (0x006)  /* config reg 1 */
- #define UHA_CONF2              (0x007)  /* config reg 2 */
- #define UHA_OGM0               (0x008)  /* outgoing mail ptr 0 least sig */
- #define UHA_OGM1               (0x009)  /* outgoing mail ptr 1 least mid */
- #define UHA_OGM2               (0x00a)  /* outgoing mail ptr 2 most mid  */
- #define UHA_OGM3               (0x00b)  /* outgoing mail ptr 3 most sig  */
- #define UHA_ICM0               (0x00c)  /* incoming mail ptr 0 */
- #define UHA_ICM1               (0x00d)  /* incoming mail ptr 1 */
- #define UHA_ICM2               (0x00e)  /* incoming mail ptr 2 */
- #define UHA_ICM3               (0x00f)  /* incoming mail ptr 3 */
-
- /*
-* UHA_LMASK bits (read only) 
-*/
-
-#define UHA_LDIE                0x80    /* local doorbell int enabled */
-#define UHA_SRSTE               0x40    /* soft reset enabled */
-#define UHA_ABORTEN             0x10    /* abort MSCP enabled */
-#define UHA_OGMINTEN            0x01    /* outgoing mail interrupt enabled */
+ */
+#define UHA_LMASK              (0x000) /* local doorbell mask reg */
+#define UHA_LINT               (0x001) /* local doorbell int/stat reg */
+#define UHA_SMASK              (0x002) /* system doorbell mask reg */
+#define UHA_SINT               (0x003) /* system doorbell int/stat reg */
+#define UHA_ID0                (0x004) /* product id reg 0 */
+#define UHA_ID1                (0x005) /* product id reg 1 */
+#define UHA_CONF1              (0x006) /* config reg 1 */
+#define UHA_CONF2              (0x007) /* config reg 2 */
+#define UHA_OGM0               (0x008) /* outgoing mail ptr 0 least sig */
+#define UHA_OGM1               (0x009) /* outgoing mail ptr 1 least mid */
+#define UHA_OGM2               (0x00a) /* outgoing mail ptr 2 most mid  */
+#define UHA_OGM3               (0x00b) /* outgoing mail ptr 3 most sig  */
+#define UHA_ICM0               (0x00c) /* incoming mail ptr 0 */
+#define UHA_ICM1               (0x00d) /* incoming mail ptr 1 */
+#define UHA_ICM2               (0x00e) /* incoming mail ptr 2 */
+#define UHA_ICM3               (0x00f) /* incoming mail ptr 3 */
 
 /*
 
 /*
-* UHA_LINT bits (read)
-*/
+ * UHA_LMASK bits (read only) 
+ */
 
 
-#define UHA_LDIP                0x80    /* local doorbell int pending */
+#define UHA_LDIE                0x80   /* local doorbell int enabled */
+#define UHA_SRSTE               0x40   /* soft reset enabled */
+#define UHA_ABORTEN             0x10   /* abort MSCP enabled */
+#define UHA_OGMINTEN            0x01   /* outgoing mail interrupt enabled */
 
 /*
 
 /*
-* UHA_LINT bits (write)
-*/
+ * UHA_LINT bits (read)
+ */
 
 
-#define UHA_ADRST               0x40    /* adapter soft reset */
-#define UHA_SBRST               0x20    /* scsi bus reset */
-#define UHA_ASRST               0x60    /* adapter and scsi reset */
-#define UHA_ABORT               0x10    /* abort MSCP */
-#define UHA_OGMINT              0x01    /* tell adapter to get mail */
+#define UHA_LDIP                0x80   /* local doorbell int pending */
 
 /*
 
 /*
-* UHA_SMASK bits (read)
-*/
+ * UHA_LINT bits (write)
+ */
 
 
-#define UHA_SINTEN              0x80    /* system doorbell interupt Enabled */
-#define UHA_ABORT_COMPLETE_EN   0x10    /* abort MSCP command complete int Enabled */
-#define UHA_ICM_ENABLED         0x01    /* ICM interrupt enabled */
+#define UHA_ADRST               0x40   /* adapter soft reset */
+#define UHA_SBRST               0x20   /* scsi bus reset */
+#define UHA_ASRST               0x60   /* adapter and scsi reset */
+#define UHA_ABORT               0x10   /* abort MSCP */
+#define UHA_OGMINT              0x01   /* tell adapter to get mail */
 
 /*
 
 /*
-* UHA_SMASK bits (write)
-*/
+ * UHA_SMASK bits (read)
+ */
 
 
-#define UHA_ENSINT              0x80    /* enable system doorbell interrupt */
-#define UHA_EN_ABORT_COMPLETE   0x10    /* enable abort MSCP complete int */
-#define UHA_ENICM               0x01    /* enable ICM interrupt */
+#define UHA_SINTEN              0x80   /* system doorbell interupt Enabled */
+#define UHA_ABORT_COMPLETE_EN   0x10   /* abort MSCP command complete int Enabled */
+#define UHA_ICM_ENABLED         0x01   /* ICM interrupt enabled */
 
 /*
 
 /*
-* UHA_SINT bits (read)
-*/
+ * UHA_SMASK bits (write)
+ */
 
 
-#define UHA_SINTP               0x80    /* system doorbell int pending */
-#define UHA_ABORT_SUCC          0x10    /* abort MSCP successful */
-#define UHA_ABORT_FAIL          0x18    /* abort MSCP failed */
+#define UHA_ENSINT              0x80   /* enable system doorbell interrupt */
+#define UHA_EN_ABORT_COMPLETE   0x10   /* enable abort MSCP complete int */
+#define UHA_ENICM               0x01   /* enable ICM interrupt */
 
 /*
 
 /*
-* UHA_SINT bits (write)
-*/
+ * UHA_SINT bits (read)
+ */
+
+#define UHA_SINTP               0x80   /* system doorbell int pending */
+#define UHA_ABORT_SUCC          0x10   /* abort MSCP successful */
+#define UHA_ABORT_FAIL          0x18   /* abort MSCP failed */
+
+/*
+ * UHA_SINT bits (write)
+ */
 
 
-#define UHA_ABORT_ACK           0x18    /* acknowledge status and clear */
-#define UHA_ICM_ACK             0x01    /* acknowledge ICM and clear */
+#define UHA_ABORT_ACK           0x18   /* acknowledge status and clear */
+#define UHA_ICM_ACK             0x01   /* acknowledge ICM and clear */
 
 /* 
 
 /* 
-* UHA_CONF1 bits (read only)
-*/
-
-#define UHA_DMA_CH5             0x00    /* DMA channel 5 */
-#define UHA_DMA_CH6             0x40    /* 6 */
-#define UHA_DMA_CH7             0x80    /* 7 */
-#define UHA_IRQ15               0x00    /* IRQ 15 */
-#define UHA_IRQ14               0x10    /* 14 */
-#define UHA_IRQ11               0x20    /* 11 */
-#define UHA_IRQ10               0x30    /* 10 */
-
-/***********************************
-* ha_status error codes
-\***********************************/
-
-#define UHA_NO_ERR             0x00            /* No error supposedly */
-#define UHA_SBUS_ABORT_ERR     0x84            /* scsi bus abort error */
-#define UHA_SBUS_TIMEOUT       0x91            /* scsi bus selection timeout */
-#define UHA_SBUS_OVER_UNDER    0x92            /* scsi bus over/underrun */
-#define UHA_BAD_SCSI_CMD       0x96            /* illegal scsi command */
-#define UHA_AUTO_SENSE_ERR     0x9b            /* auto request sense err */
-#define UHA_SBUS_RES_ERR       0xa3            /* scsi bus reset error */
-#define UHA_BAD_SG_LIST                0xff            /* invalid scatter gath list */
-
-/*\f*/
-
-struct  uha_dma_seg
-{
-       physaddr                        addr;
-       physlen                         len;
+ * UHA_CONF1 bits (read only)
+ */
+
+#define UHA_DMA_CH5             0x00   /* DMA channel 5 */
+#define UHA_DMA_CH6             0x40   /* 6 */
+#define UHA_DMA_CH7             0x80   /* 7 */
+#define UHA_IRQ15               0x00   /* IRQ 15 */
+#define UHA_IRQ14               0x10   /* 14 */
+#define UHA_IRQ11               0x20   /* 11 */
+#define UHA_IRQ10               0x30   /* 10 */
+
+/*
+ * ha_status error codes
+ */
+
+#define UHA_NO_ERR             0x00    /* No error supposedly */
+#define UHA_SBUS_ABORT_ERR     0x84    /* scsi bus abort error */
+#define UHA_SBUS_TIMEOUT       0x91    /* scsi bus selection timeout */
+#define UHA_SBUS_OVER_UNDER    0x92    /* scsi bus over/underrun */
+#define UHA_BAD_SCSI_CMD       0x96    /* illegal scsi command */
+#define UHA_AUTO_SENSE_ERR     0x9b    /* auto request sense err */
+#define UHA_SBUS_RES_ERR       0xa3    /* scsi bus reset error */
+#define UHA_BAD_SG_LIST                0xff    /* invalid scatter gath list */
+
+struct uha_dma_seg {
+       physaddr addr;
+       physlen len;
 };
 };
-/*\f*/
 
 
-struct  mscp
-{
-       unsigned char           opcode:3;
-       #define U14_HAC         0x01            /*host adapter command*/
-       #define U14_TSP         0x02            /*target scsi pass through command*/
-       #define U14_SDR         0x04            /*scsi device reset*/
-       unsigned char           xdir:2;         /*xfer direction*/
-       #define U14_SDET        0x00            /*determined by scsi command*/
-       #define U14_SDIN        0x01            /*scsi data in*/
-       #define U14_SDOUT       0x02            /*scsi data out*/
-       #define U14_NODATA      0x03            /*no data xfer*/
-       unsigned char           dcn:1;          /*disable disconnect for this command*/
-       unsigned char           ca:1;           /*Cache control*/
-       unsigned char           sgth:1;         /*scatter gather flag*/
-       unsigned char           target:3;
-       unsigned char           chan:2;         /*scsi channel (always 0 for 14f)*/
-       unsigned char           lun:3;
-       physaddr                data;
-       physlen                 datalen;
-       physaddr                link;
-       unsigned char           link_id;
-       unsigned char           sg_num;         /*number of scat gath segs */
-                                               /*in s-g list if sg flag is*/
-                                               /*set. starts at 1, 8bytes per*/
-       unsigned char           senselen;
-       unsigned char           cdblen;
-       unsigned char           cdb[12];
-       unsigned char           ha_status;
-       unsigned char           targ_status;
-       physaddr                sense;          /* if 0 no auto sense */
+struct mscp {
+       unsigned char opcode:3;
+#define U14_HAC                0x01    /* host adapter command */
+#define U14_TSP                0x02    /* target scsi pass through command */
+#define U14_SDR                0x04    /* scsi device reset */
+       unsigned char xdir:2;   /* xfer direction */
+#define U14_SDET       0x00    /* determined by scsi command */
+#define U14_SDIN       0x01    /* scsi data in */
+#define U14_SDOUT      0x02    /* scsi data out */
+#define U14_NODATA     0x03    /* no data xfer */
+       unsigned char dcn:1;    /* disable disconnect for this command */
+       unsigned char ca:1;     /* cache control */
+       unsigned char sgth:1;   /* scatter gather flag */
+       unsigned char target:3;
+       unsigned char chan:2;   /* scsi channel (always 0 for 14f) */
+       unsigned char lun:3;
+       physaddr data;
+       physlen datalen;
+       physaddr link;
+       unsigned char link_id;
+       unsigned char sg_num;   /*number of scat gath segs */
+       /*in s-g list if sg flag is */
+       /*set. starts at 1, 8bytes per */
+       unsigned char senselen;
+       unsigned char cdblen;
+       unsigned char cdb[12];
+       unsigned char ha_status;
+       unsigned char targ_status;
+       physaddr sense;         /* if 0 no auto sense */
        /*-----------------end of hardware supported fields----------------*/
        /*-----------------end of hardware supported fields----------------*/
-       struct  mscp     *next;  /* in free list */
-       struct  scsi_xfer *xs; /* the scsi_xfer for this cmd */
-       int             flags;
+       struct mscp *next;      /* in free list */
+       struct scsi_xfer *xs;   /* the scsi_xfer for this cmd */
+       int     flags;
 #define MSCP_FREE        0
 #define MSCP_ACTIVE      1
 #define MSCP_ABORTED     2
 #define MSCP_FREE        0
 #define MSCP_ACTIVE      1
 #define MSCP_ABORTED     2
-       struct  uha_dma_seg     uha_dma[UHA_NSEG];
-       struct  scsi_sense_data mscp_sense;
+       struct uha_dma_seg uha_dma[UHA_NSEG];
+       struct scsi_sense_data mscp_sense;
+       struct mscp *nexthash;
+       long int hashkey;
 };
 
 };
 
-/*\f*/
-
-struct  uha_data
-{
+struct uha_data {
        int     flags;
 #define UHA_INIT        0x01;
        int     baseport;
        int     flags;
 #define UHA_INIT        0x01;
        int     baseport;
-       struct  mscp mscps[NUM_CONCURRENT];
-       struct  mscp *free_mscp;
-       int     our_id;                 /* our scsi id */
+       struct mscp *mscphash[MSCP_HASH_SIZE];
+       struct mscp *free_mscp;
+       int     our_id;         /* our scsi id */
        int     vect;
        int     vect;
-       int     dma;
-} uha_data[NUHA];
+       int     dma;
+       int     nummscps;
+       struct scsi_link sc_link;
+} *uhadata[NUHA];
 
 int     uhaprobe();
 int     uha_attach();
 int     uhaintr();
 
 int     uhaprobe();
 int     uha_attach();
 int     uhaintr();
-int     uha_scsi_cmd();
-int     uha_timeout();
-int    uha_abort();
-struct  mscp *cheat;
+int32   uha_scsi_cmd();
+void    uha_timeout();
+void   uha_free_mscp();
+int     uha_abort();
 void    uhaminphys();
 void    uhaminphys();
-long int uha_adapter_info();
+void    uha_done();
+u_int32 uha_adapter_info();
+struct mscp *uha_mscp_phys_kv();
 
 
+struct mscp *cheat;
 unsigned long int scratch;
 unsigned long int scratch;
-
-#ifdef  MACH
-struct  isa_driver      uhadriver = { uhaprobe, 0, uha_attach, "uha", 0, 0, 0};
-int (*uhaintrs[])() = {uhaintr, 0};
-#endif  MACH
-
-#ifdef  __386BSD__
-struct  isa_driver      uhadriver = { uhaprobe, uha_attach, "uha"};
-#endif  __386BSD__
-
-static uha_unit = 0;
-#ifdef UHADEBUG
-int     uha_debug = 0;
-#endif /*UHADEBUG*/
+static  uha_unit = 0;
 #define UHA_SHOWMSCPS 0x01
 #define UHA_SHOWINTS 0x02
 #define UHA_SHOWCMDS 0x04
 #define UHA_SHOWMSCPS 0x01
 #define UHA_SHOWINTS 0x02
 #define UHA_SHOWCMDS 0x04
@@ -294,7 +262,15 @@ int     uha_debug = 0;
 #define SUCCESS 0
 #define PAGESIZ 4096
 
 #define SUCCESS 0
 #define PAGESIZ 4096
 
-struct  scsi_switch     uha_switch = 
+#ifdef KERNEL
+struct isa_driver uhadriver =
+{
+       uhaprobe,
+       uha_attach,
+       "uha"
+};
+
+struct scsi_adapter uha_switch =
 {
        uha_scsi_cmd,
        uhaminphys,
 {
        uha_scsi_cmd,
        uhaminphys,
@@ -302,401 +278,447 @@ struct  scsi_switch     uha_switch =
        0,
        uha_adapter_info,
        "uha",
        0,
        uha_adapter_info,
        "uha",
-       0,0
+       0, 0
 };
 
 };
 
-/*\f*/
-/***********************************************************************\
-* Function to send a command out through a mailbox                      *
-\***********************************************************************/
-uha_send_mbox(  int             unit
-               ,struct mscp     *mscp)
+/* the below structure is so we have a default dev struct for out link struct */
+struct scsi_device uha_dev =
 {
 {
-       int     port = uha_data[unit].baseport;
-       int     spincount = FUDGE(delaycount) * 1000; /* 1s should be enough */
+    NULL,                      /* Use default error handler */
+    NULL,                      /* have a queue, served by this */
+    NULL,                      /* have no async handler */
+    NULL,                      /* Use default 'done' routine */
+    "uha",
+    0,
+    0, 0
+};
+
+#endif /*KERNEL */
+
+#ifndef        KERNEL
+main()
+{
+       printf("uha_data is %d bytes\n", sizeof(struct uha_data));
+       printf("mscp is %d bytes\n", sizeof(struct mscp));
+}
+
+#else /*KERNEL*/
+/*
+ * Function to send a command out through a mailbox
+ */
+void
+uha_send_mbox(int unit, struct mscp *mscp)
+{
+       struct uha_data *uha = uhadata[unit];
+       int     port = uha->baseport;
+       int     spincount = 100000;     /* 1s should be enough */
        int     s = splbio();
        int     s = splbio();
-               
-       while(      ((inb(port + UHA_LINT) & (UHA_LDIP))
-                                       != (0))
-               && (spincount--));
-       if(spincount == -1)
-       {
-               printf("uha%d: uha_send_mbox, board not responding\n",unit);
+
+       while (--spincount) {
+               if ((inb(port + UHA_LINT) & UHA_LDIP) == 0)
+                       break;
+               DELAY(100);
+       }
+       if (spincount == 0) {
+               printf("uha%d: uha_send_mbox, board not responding\n", unit);
                Debugger();
        }
                Debugger();
        }
-
-       outl(port + UHA_OGM0,KVTOPHYS(mscp)); 
+       outl(port + UHA_OGM0, KVTOPHYS(mscp));
        outb(port + UHA_LINT, (UHA_OGMINT));
        splx(s);
 }
 
        outb(port + UHA_LINT, (UHA_OGMINT));
        splx(s);
 }
 
-/***********************************************************************\
-* Function to send abort to 14f                                         *
-\***********************************************************************/
-
-uha_abort(     int             unit
-               ,struct mscp    *mscp)
+/*
+ * Function to send abort to 14f
+ */
+int
+uha_abort(int unit, struct mscp *mscp)
 {
 {
-       int     port = uha_data[unit].baseport;
-       int     spincount = FUDGE(delaycount) * 1;
-       int     abortcount = FUDGE(delaycount) * 2000;
-       int     s = splbio();
-       
-       while(((inb(port + UHA_LINT) & (UHA_LDIP))
-                               != (0))
-               && (spincount--));
-       if(spincount == -1);
+       struct uha_data *uha = uhadata[unit];
+       int     port = uha->baseport;
+       int     spincount = 100;        /* 1 mSec */
+       int     abortcount = 200000;    /*2 secs */
+       int     s = splbio();
+
+       while (--spincount) {
+               if ((inb(port + UHA_LINT) & UHA_LDIP) == 0)
+                       break;
+               DELAY(10);
+       }
+       if (spincount == 0);
        {
        {
-               printf("uha%d: uha_abort, board not responding\n",unit);
+               printf("uha%d: uha_abort, board not responding\n", unit);
                Debugger();
        }
                Debugger();
        }
+       outl(port + UHA_OGM0, KVTOPHYS(mscp));
+       outb(port + UHA_LINT, UHA_ABORT);
 
 
-       outl(port + UHA_OGM0,KVTOPHYS(mscp));
-       outb(port + UHA_LINT,UHA_ABORT);
-
-       while((abortcount--) && (!(inb(port + UHA_SINT) & UHA_ABORT_FAIL)));
-       if(abortcount == -1)
-       {
-               printf("uha%d: uha_abort, board not responding\n",unit);
-               Debugger();
+       while (--abortcount) {
+               if (inb(port + UHA_SINT) & UHA_ABORT_FAIL)
+                       break;
+               DELAY(10);
        }
        }
-       if((inb(port + UHA_SINT) & 0x10) != 0)
-       {
-               outb(port + UHA_SINT,UHA_ABORT_ACK);
-               return(1);
+       if (abortcount == 0) {
+               printf("uha%d: uha_abort, board not responding\n", unit);
+               Debugger();
        }
        }
-       else
-       {
-               outb(port + UHA_SINT,UHA_ABORT_ACK);
-               return(0);
+       if ((inb(port + UHA_SINT) & 0x10) != 0) {
+               outb(port + UHA_SINT, UHA_ABORT_ACK);
+               return (1);
+       } else {
+               outb(port + UHA_SINT, UHA_ABORT_ACK);
+               return (0);
        }
 }
 
        }
 }
 
-/***********************************************************************\
-* Function to poll for command completion when in poll mode             *
-\***********************************************************************/
-uha_poll(int unit ,int wait) /* in msec  */
+/*
+ * Function to poll for command completion when in poll mode.
+ *
+ *     wait = timeout in msec
+ */
+int
+uha_poll(int unit, int wait)
 {
 {
-       int     port = uha_data[unit].baseport;
-       int     spincount = FUDGE(delaycount) * wait; /* in msec */
-       int     stport = port + UHA_SINT;
-       int     start = spincount;
-
-retry:
-       while( (spincount--) && (!(inb(stport) &  UHA_SINTP)));
-       if(spincount == -1)
-       {
-               printf("uha%d: uha_poll, board not responding\n",unit);
-               return(EIO);
+       struct  uha_data *uha = uhadata[unit];
+       int     port = uha->baseport;
+       int     stport = port + UHA_SINT;
+
+      retry:
+       while (--wait) {
+               if (inb(stport) & UHA_SINTP)
+                       break;
+               DELAY(1000);    /* 1 mSec per loop */
+       }
+       if (wait == 0) {
+               printf("uha%d: uha_poll, board not responding\n", unit);
+               return (EIO);
        }
        }
-if ((int)cheat != PHYSTOKV(inl(port + UHA_ICM0)))
-{
-       printf("uha%d: discarding %x\n",unit,inl(port + UHA_ICM0));
-       outb(port + UHA_SINT, UHA_ICM_ACK);
-       spinwait(50);
-       goto retry;
-}/* don't know this will work */
        uhaintr(unit);
        uhaintr(unit);
-       return(0);
+       return (0);
 }
 
 }
 
-/*******************************************************\
-* Check if the device can be found at the port given    *
-* and if so, set it up ready for further work           *
-* as an argument, takes the isa_dev structure from      *
-* autoconf.c                                            *
-\*******************************************************/
+/*
+ * Check if the device can be found at the port given and if so, set it up
+ * ready for further work as an argument, takes the isa_device structure
+ * from autoconf.c
+ */
+int
 uhaprobe(dev)
 uhaprobe(dev)
-struct isa_dev *dev;
+       struct isa_device *dev;
 {
 {
-       int     unit = uha_unit;
-       dev->dev_unit = unit;
-       uha_data[unit].baseport = dev->dev_addr;
-       if(unit >= NUHA)
-       {
-               printf("uha%d: unit number too high\n",unit);
-               return(0);
-       }
-       
-       /*try and initialize unit at this location*/
-       if (uha_init(unit) != 0)
-       {
-               return(0);
-       }
+       int     unit = uha_unit;
+       struct uha_data *uha;
 
 
-       /* if its there put in it's interrupt and DRQ vectors */
+       dev->id_unit = unit;
 
 
-       dev->id_irq = (1 << uha_data[unit].vect);
-       dev->id_drq = uha_data[unit].dma;
+       /*
+        * find unit and check we have that many defined
+        */
+       if (unit >= NUHA) {
+               printf("uha: unit number (%d) too high\n", unit);
+               return (0);
+       }
+       dev->id_unit = unit;
+
+       /*
+        * Allocate a storage area for us
+        */
+       if (uhadata[unit]) {
+               printf("uha%d: memory already allocated\n", unit);
+               return 0;
+       }
+       uha = malloc(sizeof(struct uha_data), M_TEMP, M_NOWAIT);
+       if (!uha) {
+               printf("uha%d: cannot malloc!\n", unit);
+               return 0;
+       }
+       bzero(uha, sizeof(struct uha_data));
+       uhadata[unit] = uha;
+       uha->baseport = dev->id_iobase;
+       /*
+        * Try initialise a unit at this location
+        * sets up dma and bus speed, loads uha->vect
+        */
+       if (uha_init(unit) != 0) {
+               uhadata[unit] = NULL;
+               free(uha, M_TEMP);
+               return (0);
+       }
+       /* if it's there put in its interrupt and DRQ vectors */
+       dev->id_irq = (1 << uha->vect);
+       dev->id_drq = uha->dma;
 
 
-       
-       uha_unit ++;
-return(1);
+       uha_unit++;
+       return (16);
 }
 
 }
 
-/***********************************************\
-* Attach all the sub-devices we can find        *
-\***********************************************/
+/*
+ * Attach all the sub-devices we can find
+ */
+int
 uha_attach(dev)
 uha_attach(dev)
-struct  isa_dev *dev;
+       struct isa_device *dev;
 {
 {
-       int     unit = dev->dev_unit;
-
-
-       /***********************************************\
-       * ask the adapter what subunits are present     *
-       \***********************************************/
-       scsi_attachdevs( unit, uha_data[unit].our_id, &uha_switch);
-
-#if defined(OSF)
-       uha_attached[unit]=1;
-#endif /* defined(OSF) */
-       return;
+       int     unit = dev->id_unit;
+       struct uha_data *uha = uhadata[unit];
+
+       /*
+        * fill in the prototype scsi_link.
+        */
+       uha->sc_link.adapter_unit = unit;
+       uha->sc_link.adapter_targ = uha->our_id;
+       uha->sc_link.adapter = &uha_switch;
+       uha->sc_link.device = &uha_dev;
+
+       /*
+        * ask the adapter what subunits are present
+        */
+       scsi_attachdevs(&(uha->sc_link));
+
+       return 1;
 }
 
 }
 
-/***********************************************\
-* Return some information to the caller about   *
-* the adapter and it's capabilities             *
-\***********************************************/
-long int uha_adapter_info(unit)
-int     unit;
+/*
+ * Return some information to the caller about
+ * the adapter and it's capabilities
+ */
+u_int32 
+uha_adapter_info(unit)
+       int     unit;
 {
 {
-       return(2);      /* 2 outstanding requests at a time per device */
+       return (2);             /* 2 outstanding requests at a time per device */
 }
 
 }
 
-/***********************************************\
-* Catch an interrupt from the adaptor           *
-\***********************************************/
+/*
+ * Catch an interrupt from the adaptor
+ */
+int
 uhaintr(unit)
 {
 uhaintr(unit)
 {
-       struct mscp      *mscp;
-       u_char          uhastat;
-       unsigned long int        mboxval;
-
-       int     port = uha_data[unit].baseport;
+       struct uha_data *uha = uhadata[unit];
+       struct mscp *mscp;
+       u_char  uhastat;
+       unsigned long int mboxval;
 
 
+       int     port = uha->baseport;
 
 #ifdef UHADEBUG
 
 #ifdef UHADEBUG
-       if(scsi_debug & PRINTROUTINES)
-               printf("uhaintr ");
-#endif /*UHADEBUG*/
-
-#if defined(OSF)
-       if (!uha_attached[unit])
-       {
-               return(1);
-       }
-#endif /* defined(OSF) */
-       while(inb(port + UHA_SINT) & UHA_SINTP)
-       {
-               /***********************************************\
-               * First get all the information and then        *
-               * acknowlege the interrupt                      *
-               \***********************************************/
+       printf("uhaintr ");
+#endif /*UHADEBUG */
+
+       while (inb(port + UHA_SINT) & UHA_SINTP) {
+               /*
+                * First get all the information and then
+                * acknowledge the interrupt
+                */
                uhastat = inb(port + UHA_SINT);
                mboxval = inl(port + UHA_ICM0);
                uhastat = inb(port + UHA_SINT);
                mboxval = inl(port + UHA_ICM0);
-               outb(port + UHA_SINT,UHA_ICM_ACK);
-
-#ifdef UHADEBUG
-               if(scsi_debug & TRACEINTERRUPTS)
-                       printf("status = 0x%x ",uhastat);
-#endif /*UHADEBUG*/
-               /***********************************************\
-               * Process the completed operation               *
-               \***********************************************/
-       
-                       mscp = (struct mscp *)(PHYSTOKV(mboxval)); 
+               outb(port + UHA_SINT, UHA_ICM_ACK);
 
 #ifdef UHADEBUG
 
 #ifdef UHADEBUG
-                       if(uha_debug & UHA_SHOWCMDS )
-                       {
-                               uha_show_scsi_cmd(mscp->xs);
-                       }
-                       if((uha_debug & UHA_SHOWMSCPS) && mscp)
-                               printf("<int mscp(%x)>",mscp);
-#endif /*UHADEBUG*/
-                       untimeout(uha_timeout,mscp);
+               printf("status = 0x%x ", uhastat);
+#endif /*UHADEBUG*/
+               /*
+                * Process the completed operation
+                */
+
+               mscp = uha_mscp_phys_kv(uha, mboxval);
+               if (!mscp) {
+                       printf("uha: BAD MSCP RETURNED\n");
+                       return (0);     /* whatever it was, it'll timeout */
+               }
+               untimeout(uha_timeout, mscp);
 
 
-                       uha_done(unit,mscp);
+               uha_done(unit, mscp);
        }
        }
-       return(1);
+       return (1);
 }
 
 }
 
-/***********************************************\
-* We have a mscp which has been processed by the *
-* adaptor, now we look to see how the operation *
-* went.                                         *
-\***********************************************/
-
-uha_done(unit,mscp)
-int     unit;
-struct mscp *mscp;
+/*
+ * We have a mscp which has been processed by the adaptor, now we look to see
+ * how the operation went.
+ */
+void
+uha_done(unit, mscp)
+       int     unit;
+       struct  mscp *mscp;
 {
 {
-       struct  scsi_sense_data *s1,*s2;
-       struct  scsi_xfer *xs = mscp->xs;
-
-#ifdef UHADEBUG
-       if(scsi_debug & (PRINTROUTINES | TRACEINTERRUPTS))
-               printf("uha_done ");
-#endif /*UHADEBUG*/
-       /***********************************************\
-       * Otherwise, put the results of the operation   *
-       * into the xfer and call whoever started it     *
-       \***********************************************/
-       if ( (mscp->ha_status == UHA_NO_ERR) || (xs->flags & SCSI_ERR_OK))
-       {               /* All went correctly  OR errors expected */
+       struct uha_data *uha = uhadata[unit];
+       struct scsi_sense_data *s1, *s2;
+       struct scsi_xfer *xs = mscp->xs;
+
+       SC_DEBUG(xs->sc_link, SDEV_DB2, ("uha_done\n"));
+       /*
+        * Otherwise, put the results of the operation
+        * into the xfer and call whoever started it
+        */
+       if ((mscp->ha_status == UHA_NO_ERR) || (xs->flags & SCSI_ERR_OK)) {     /* All went correctly  OR errors expected */
                xs->resid = 0;
                xs->error = 0;
                xs->resid = 0;
                xs->error = 0;
-       }
-       else
-       {
+       } else {
 
                s1 = &(mscp->mscp_sense);
                s2 = &(xs->sense);
 
 
                s1 = &(mscp->mscp_sense);
                s2 = &(xs->sense);
 
-               if(mscp->ha_status != UHA_NO_ERR)
-               {
-                       switch(mscp->ha_status)
-                       {
-                       case    UHA_SBUS_TIMEOUT:           /* No response */
-#ifdef UHADEBUG
-                               if (uha_debug & UHA_SHOWMISC)
-                               {
-                                       printf("timeout reported back\n");
-                               }
-#endif /*UHADEBUG*/
+               if (mscp->ha_status != UHA_NO_ERR) {
+                       switch (mscp->ha_status) {
+                       case UHA_SBUS_TIMEOUT:          /* No response */
+                               SC_DEBUG(xs->sc_link, SDEV_DB3,
+                                   ("timeout reported back\n"));
                                xs->error = XS_TIMEOUT;
                                break;
                                xs->error = XS_TIMEOUT;
                                break;
-                       case    UHA_SBUS_OVER_UNDER:
-#ifdef UHADEBUG
-                               if (uha_debug & UHA_SHOWMISC)
-                               {
-                                       printf("scsi bus xfer over/underrun\n");
-                               }
-#endif /*UHADEBUG*/
+                       case UHA_SBUS_OVER_UNDER:
+                               SC_DEBUG(xs->sc_link, SDEV_DB3,
+                                   ("scsi bus xfer over/underrun\n"));
                                xs->error = XS_DRIVER_STUFFUP;
                                break;
                                xs->error = XS_DRIVER_STUFFUP;
                                break;
-                       case    UHA_BAD_SG_LIST:
-#ifdef UHADEBUG
-                               if (uha_debug & UHA_SHOWMISC)
-                               {
-                                       printf("bad sg list reported back\n");
-                               }
-#endif /*UHADEBUG*/
+                       case UHA_BAD_SG_LIST:
+                               SC_DEBUG(xs->sc_link, SDEV_DB3,
+                                   ("bad sg list reported back\n"));
                                xs->error = XS_DRIVER_STUFFUP;
                                break;
                                xs->error = XS_DRIVER_STUFFUP;
                                break;
-                       default:        /* Other scsi protocol messes */
+                       default:        /* Other scsi protocol messes */
                                xs->error = XS_DRIVER_STUFFUP;
                                xs->error = XS_DRIVER_STUFFUP;
-#ifdef UHADEBUG
-                               if (uha_debug & UHA_SHOWMISC)
-                               {
-                                       printf("unexpected ha_status: %x\n",
-                                               mscp->ha_status);
-                               }
-#endif /*UHADEBUG*/
+                               SC_DEBUG(xs->sc_link, SDEV_DB3,
+                                   ("unexpected ha_status: %x\n",
+                                       mscp->ha_status));
                        }
                        }
-
-               }
-               else
-               {
+               } else {
 
                        if (mscp->targ_status != 0)
 
                        if (mscp->targ_status != 0)
-/**************************************************************************\
-* I have no information for any possible value of target status field     *
-* other than 0 means no error!! So I guess any error is unexpected in that *
-* event!!                                                                 *
-\**************************************************************************/
+/*
+ * I have no information for any possible value of target status field
+ * other than 0 means no error!! So I guess any error is unexpected in that
+ * event!!
+ */
 
 
-                       {       
-#ifdef UHADEBUG
-                               if (uha_debug & UHA_SHOWMISC)
-                               {
-                                       printf("unexpected targ_status: %x\n",
-                                               mscp->targ_status);
-                               }
-#endif /*UHADEBUG*/
+                       {
+                               SC_DEBUG(xs->sc_link, SDEV_DB3,
+                                   ("unexpected targ_status: %x\n",
+                                       mscp->targ_status));
                                xs->error = XS_DRIVER_STUFFUP;
                        }
                }
                                xs->error = XS_DRIVER_STUFFUP;
                        }
                }
-       }
-done:   xs->flags |= ITSDONE;
-       uha_free_mscp(unit,mscp, xs->flags);
-       if(xs->when_done)
-               (*(xs->when_done))(xs->done_arg,xs->done_arg2);
+      }
+    done:
+       xs->flags |= ITSDONE;
+       uha_free_mscp(unit, mscp, xs->flags);
+       scsi_done(xs);
 }
 
 }
 
-/***********************************************\
-* A mscp (and hence a mbx-out is put onto the    *
-* free list.                                    *
-\***********************************************/
-uha_free_mscp(unit,mscp, flags)
-struct mscp *mscp;
+/*
+ * A mscp (and hence a mbx-out) is put onto the free list.
+ */
+void
+uha_free_mscp(unit, mscp, flags)
+       struct mscp *mscp;
 {
 {
+       struct uha_data *uha = uhadata[unit];
        unsigned int opri;
        unsigned int opri;
-       
-#ifdef UHADEBUG
-       if(scsi_debug & PRINTROUTINES)
-               printf("mscp%d(0x%x)> ",unit,flags);
-#endif /*UHADEBUG*/
-       if (!(flags & SCSI_NOMASK)) 
+
+       if (!(flags & SCSI_NOMASK))
                opri = splbio();
 
                opri = splbio();
 
-       mscp->next = uha_data[unit].free_mscp;
-       uha_data[unit].free_mscp = mscp;
+       mscp->next = uha->free_mscp;
+       uha->free_mscp = mscp;
        mscp->flags = MSCP_FREE;
        mscp->flags = MSCP_FREE;
-       /***********************************************\
-       * If there were none, wake abybody waiting for  *
-       * one to come free, starting with queued entries*
-       \***********************************************/
+       /*
+        * If there were none, wake abybody waiting for
+        * one to come free, starting with queued entries
+        */
        if (!mscp->next) {
        if (!mscp->next) {
-               wakeup(&uha_data[unit].free_mscp);
+               wakeup(&uha->free_mscp);
        }
        }
-       if (!(flags & SCSI_NOMASK)) 
+       if (!(flags & SCSI_NOMASK))
                splx(opri);
 }
 
                splx(opri);
 }
 
-/***********************************************\
-* Get a free mscp (and hence mbox-out entry)     *
-\***********************************************/
+/*
+ * Get a free mscp
+ *
+ * If there are none, see if we can allocate a new one.  If so, put it in the
+ * hash table too otherwise either return an error or sleep.
+ */
 struct mscp *
 struct mscp *
-uha_get_mscp(unit,flags)
+uha_get_mscp(unit, flags)
+       int     unit, flags;
 {
 {
+       struct uha_data *uha = uhadata[unit];
        unsigned opri;
        unsigned opri;
-       struct mscp *rc;
+       struct mscp *mscpp;
+       int     hashnum;
 
 
-#ifdef UHADEBUG
-       if(scsi_debug & PRINTROUTINES)
-               printf("<mscp%d(0x%x) ",unit,flags);
-#endif /*UHADEBUG*/
-       if (!(flags & SCSI_NOMASK)) 
+       if (!(flags & SCSI_NOMASK))
                opri = splbio();
                opri = splbio();
-       /***********************************************\
-       * If we can and have to, sleep waiting for one  *
-       * to come free                                  *
-       \***********************************************/
-       while ((!(rc = uha_data[unit].free_mscp)) && (!(flags & SCSI_NOSLEEP)))
-       {
-               sleep(&uha_data[unit].free_mscp, PRIBIO);
+       /*
+        * If we can and have to, sleep waiting for one to come free
+        * but only if we can't allocate a new one
+        */
+       while (!(mscpp = uha->free_mscp)) {
+               if (uha->nummscps < UHA_MSCP_MAX) {
+                       if (mscpp = (struct mscp *)malloc(sizeof(struct mscp),
+                           M_TEMP,
+                           M_NOWAIT)) {
+                               bzero(mscpp, sizeof(struct mscp));
+                               uha->nummscps++;
+                               mscpp->flags = MSCP_ACTIVE;
+                               /*
+                                * put in the phystokv hash table
+                                * Never gets taken out.
+                                */
+                               mscpp->hashkey = KVTOPHYS(mscpp);
+                               hashnum = MSCP_HASH(mscpp->hashkey);
+                               mscpp->nexthash = uha->mscphash[hashnum];
+                               uha->mscphash[hashnum] = mscpp;
+                       } else {
+                               printf("uha%d: Can't malloc MSCP\n", unit);
+                       }
+                       goto gottit;
+               } else {
+                       if (!(flags & SCSI_NOSLEEP)) {
+                               sleep(&uha->free_mscp, PRIBIO);
+                       }
+               }
        }
        }
-       if (rc) 
-       {
-               uha_data[unit].free_mscp = rc->next;
-               rc->flags = MSCP_ACTIVE;
+       if (mscpp) {
+               /* Get MSCP from from free list */
+               uha->free_mscp = mscpp->next;
+               mscpp->flags = MSCP_ACTIVE;
        }
        }
-       if (!(flags & SCSI_NOMASK)) 
+      gottit:
+       if (!(flags & SCSI_NOMASK))
                splx(opri);
                splx(opri);
-       return(rc);
+
+       return (mscpp);
 }
 }
-               
 
 
+/*
+ * given a physical address, find the mscp that it corresponds to.
+ */
+struct mscp *
+uha_mscp_phys_kv(uha, mscp_phys)
+       struct  uha_data *uha;
+       long    int mscp_phys;
+{
+       int     hashnum = MSCP_HASH(mscp_phys);
+       struct mscp *mscpp = uha->mscphash[hashnum];
 
 
-/***********************************************\
-* Start the board, ready for normal operation   *
-\***********************************************/
+       while (mscpp) {
+               if (mscpp->hashkey == mscp_phys)
+                       break;
+               mscpp = mscpp->nexthash;
+       }
+       return mscpp;
+}
 
 
+/*
+ * Start the board, ready for normal operation
+ */
+int
 uha_init(unit)
 uha_init(unit)
-int    unit;
-{      
+       int     unit;
+{
+       struct uha_data *uha = uhadata[unit];
        unsigned char ad[4];
        volatile unsigned char model;
        volatile unsigned char submodel;
        unsigned char ad[4];
        volatile unsigned char model;
        volatile unsigned char submodel;
@@ -705,20 +727,17 @@ int       unit;
        unsigned char dma_ch;
        unsigned char irq_ch;
        unsigned char uha_id;
        unsigned char dma_ch;
        unsigned char irq_ch;
        unsigned char uha_id;
-       int     port = uha_data[unit].baseport;
-       int     i;
-       int     resetcount = FUDGE(delaycount) * 4000;
+       int     port = uha->baseport;
+       int     i;
+       int     resetcount = 4000;      /* 4 secs? */
 
        model = inb(port + UHA_ID0);
        submodel = inb(port + UHA_ID1);
 
        model = inb(port + UHA_ID0);
        submodel = inb(port + UHA_ID1);
-                if ((model != 0x56) & (submodel != 0x40)) {
-#ifdef UHADEBUG
-                       printf("uha%d: uha_init, board not responding\n",unit);
-#endif /*UHADEBUG*/
-                       return(ENXIO);
-               }
-
-       printf("uha%d: reading board settings, ",unit);
+       if ((model != 0x56) & (submodel != 0x40)) {
+               printf("uha%d: uha_init, board not responding\n", unit);
+               return (ENXIO);
+       }
+       printf("uha%d: reading board settings, ", unit);
 
        config_reg1 = inb(port + UHA_CONF1);
        config_reg2 = inb(port + UHA_CONF2);
 
        config_reg1 = inb(port + UHA_CONF1);
        config_reg2 = inb(port + UHA_CONF2);
@@ -726,307 +745,256 @@ int     unit;
        irq_ch = (config_reg1 & 0x30);
        uha_id = (config_reg2 & 0x07);
 
        irq_ch = (config_reg1 & 0x30);
        uha_id = (config_reg2 & 0x07);
 
-       switch(dma_ch)
-       {
-       case    UHA_DMA_CH5:
-               uha_data[unit].dma = 5;
+       switch (dma_ch) {
+       case UHA_DMA_CH5:
+               uha->dma = 5;
                printf("dma=5 ");
                break;
                printf("dma=5 ");
                break;
-       case    UHA_DMA_CH6:
-               uha_data[unit].dma = 6;
+       case UHA_DMA_CH6:
+               uha->dma = 6;
                printf("dma=6 ");
                break;
                printf("dma=6 ");
                break;
-       case    UHA_DMA_CH7:
-               uha_data[unit].dma = 7;
+       case UHA_DMA_CH7:
+               uha->dma = 7;
                printf("dma=7 ");
                break;
        default:
                printf("illegal dma jumper setting\n");
                printf("dma=7 ");
                break;
        default:
                printf("illegal dma jumper setting\n");
-               return(EIO);
+               return (EIO);
        }
        }
-       switch(irq_ch)
-       {
-       case    UHA_IRQ10:
-               uha_data[unit].vect = 10;
+       switch (irq_ch) {
+       case UHA_IRQ10:
+               uha->vect = 10;
                printf("int=10 ");
                break;
                printf("int=10 ");
                break;
-       case    UHA_IRQ11:
-               uha_data[unit].vect = 11;
+       case UHA_IRQ11:
+               uha->vect = 11;
                printf("int=11 ");
                break;
                printf("int=11 ");
                break;
-       case    UHA_IRQ14:
-               uha_data[unit].vect = 14;
+       case UHA_IRQ14:
+               uha->vect = 14;
                printf("int=14 ");
                break;
                printf("int=14 ");
                break;
-       case    UHA_IRQ15:
-               uha_data[unit].vect = 15;
+       case UHA_IRQ15:
+               uha->vect = 15;
                printf("int=15 ");
                break;
        default:
                printf("illegal int jumper setting\n");
                printf("int=15 ");
                break;
        default:
                printf("illegal int jumper setting\n");
-               return(EIO);
+               return (EIO);
        }
        }
+
        /* who are we on the scsi bus */
        /* who are we on the scsi bus */
-       printf("id=%x\n",uha_id);
-       uha_data[unit].our_id = uha_id;
-
-       
-       /***********************************************\
-       * link up all our MSCPs into a free list         *
-       \***********************************************/
-       for (i=0; i < NUM_CONCURRENT; i++)
-       {
-               uha_data[unit].mscps[i].next = uha_data[unit].free_mscp;
-               uha_data[unit].free_mscp = &uha_data[unit].mscps[i];
-               uha_data[unit].free_mscp->flags = MSCP_FREE;
+       printf("id=%x\n", uha_id);
+       uha->our_id = uha_id;
+
+       /*
+        * Note that we are going and return (to probe)
+        */
+       outb(port + UHA_LINT, UHA_ASRST);
+       while (--resetcount) {
+               if (inb(port + UHA_LINT));
+               break;
+               DELAY(1000);    /* 1 mSec per loop */
        }
        }
-
-       /***********************************************\
-       * Note that we are going and return (to probe)  *
-       \***********************************************/
-       outb(port + UHA_LINT, UHA_ASRST);       
-       while( (resetcount--) && (!(inb(port + UHA_LINT))));
-       if(resetcount == -1)
-       {
-               printf("uha%d: board timed out during reset\n",unit);
-               return(ENXIO);
+       if (resetcount == 0) {
+               printf("uha%d: board timed out during reset\n", unit);
+               return (ENXIO);
        }
        }
-
-       outb(port + UHA_SMASK, 0x81); /* make sure interrupts are enabled */
-       uha_data[unit].flags |= UHA_INIT;
-       return(0);
+       outb(port + UHA_SMASK, 0x81);   /* make sure interrupts are enabled */
+       uha->flags |= UHA_INIT;
+       return (0);
 }
 
 }
 
-
-
 #ifndef min
 #define min(x,y) (x < y ? x : y)
 #ifndef min
 #define min(x,y) (x < y ? x : y)
-#endif  min
+#endif /* min */
 
 
-
-void uhaminphys(bp)
-struct  buf *bp;
+void
+uhaminphys(bp)
+       struct buf *bp;
 {
 {
-#ifdef  MACH
-#if     !defined(OSF)
-       bp->b_flags |= B_NPAGES;                /* can support scat/gather */
-#endif  /* defined(OSF) */
-#endif  MACH
-       if(bp->b_bcount > ((UHA_NSEG-1) * PAGESIZ))
-       {
-               bp->b_bcount = ((UHA_NSEG-1) * PAGESIZ);
+       if (bp->b_bcount > ((UHA_NSEG - 1) * PAGESIZ)) {
+               bp->b_bcount = ((UHA_NSEG - 1) * PAGESIZ);
        }
 }
 
        }
 }
 
-/***********************************************\
-* start a scsi operation given the command and  *
-* the data address. Also needs the unit, target *
-* and lu                                        *
-\***********************************************/
-int     uha_scsi_cmd(xs)
-struct scsi_xfer *xs;
+/*
+ * start a scsi operation given the command and the data address.  Also
+ * needs the unit, target and lu.
+ */
+int32 
+uha_scsi_cmd(xs)
+       struct scsi_xfer *xs;
 {
 {
-       struct  scsi_sense_data *s1,*s2;
-       struct mscp *mscp;
-       struct uha_dma_seg *sg;
-       int     seg;    /* scatter gather seg being worked on */
-       int i   = 0;
-       int rc  =  0;
+       struct  scsi_sense_data *s1, *s2;
+       struct  mscp *mscp;
+       struct  uha_dma_seg *sg;
+       int     seg;            /* scatter gather seg being worked on */
+       int     i = 0;
+       int     rc = 0;
        int     thiskv;
        int     thiskv;
-       unsigned long int        thisphys,nextphys;
-       int     unit =xs->adapter;
-       int     bytes_this_seg,bytes_this_page,datalen,flags;
-       struct  iovec   *iovp;
+       unsigned long int thisphys, nextphys;
+       int     unit = xs->sc_link->adapter_unit;
+       int     bytes_this_seg, bytes_this_page, datalen, flags;
+       struct iovec *iovp;
+       struct uha_data *uha = uhadata[unit];
        int     s;
        unsigned int stat;
        int     s;
        unsigned int stat;
-       int     port = uha_data[unit].baseport;
+       int     port = uha->baseport;
        unsigned long int templen;
 
        unsigned long int templen;
 
-
-#ifdef UHADEBUG
-       if(scsi_debug & PRINTROUTINES)
-               printf("uha_scsi_cmd ");
-#endif /*UHADEBUG*/
-       /***********************************************\
-       * get a mscp (mbox-out) to use. If the transfer  *
-       * is from a buf (possibly from interrupt time)  *
-       * then we can't allow it to sleep               *
-       \***********************************************/
+       SC_DEBUG(xs->sc_link, SDEV_DB2, ("uha_scsi_cmd\n"));
+       /*
+        * get a mscp (mbox-out) to use. If the transfer
+        * is from a buf (possibly from interrupt time)
+        * then we can't allow it to sleep
+        */
        flags = xs->flags;
        flags = xs->flags;
-       if(xs->bp) flags |= (SCSI_NOSLEEP); /* just to be sure */
-       if(flags & ITSDONE)
-       {
-               printf("uha%d: Already done?",unit);
+       if (xs->bp)
+               flags |= (SCSI_NOSLEEP);        /* just to be sure */
+       if (flags & ITSDONE) {
+               printf("uha%d: Already done?", unit);
                xs->flags &= ~ITSDONE;
        }
                xs->flags &= ~ITSDONE;
        }
-       if(!(flags & INUSE))
-       {
-               printf("uha%d: Not in use?",unit);
+       if (!(flags & INUSE)) {
+               printf("uha%d: Not in use?", unit);
                xs->flags |= INUSE;
        }
                xs->flags |= INUSE;
        }
-       if (!(mscp = uha_get_mscp(unit,flags)))
-       {
+       if (!(mscp = uha_get_mscp(unit, flags))) {
                xs->error = XS_DRIVER_STUFFUP;
                xs->error = XS_DRIVER_STUFFUP;
-               return(TRY_AGAIN_LATER);
+               return (TRY_AGAIN_LATER);
        }
        }
-
-cheat = mscp;
-#ifdef UHADEBUG
-       if(uha_debug & UHA_SHOWMSCPS)
-                               printf("<start mscp(%x)>",mscp);
-       if(scsi_debug & SHOWCOMMANDS)
-       {
-               uha_show_scsi_cmd(xs);
-       }
-#endif /*UHADEBUG*/
+       cheat = mscp;
+       SC_DEBUG(xs->sc_link, SDEV_DB3, ("start mscp(%x)\n", mscp));
        mscp->xs = xs;
        mscp->xs = xs;
-       /***********************************************\
-       * Put all the arguments for the xfer in the mscp *
-       \***********************************************/
 
 
-       if (flags & SCSI_RESET)
-       {
+       /*
+        * Put all the arguments for the xfer in the mscp
+        */
+       if (flags & SCSI_RESET) {
                mscp->opcode = 0x04;
                mscp->ca = 0x01;
                mscp->opcode = 0x04;
                mscp->ca = 0x01;
-       }
-       else
-       {
+       } else {
                mscp->opcode = 0x02;
                mscp->ca = 0x01;
                mscp->opcode = 0x02;
                mscp->ca = 0x01;
-       }               
-
-       if (flags & SCSI_DATA_IN)
-       {
+       }
+       if (flags & SCSI_DATA_IN) {
                mscp->xdir = 0x01;
        }
                mscp->xdir = 0x01;
        }
-       if (flags & SCSI_DATA_OUT)
-       {
+       if (flags & SCSI_DATA_OUT) {
                mscp->xdir = 0x02;
        }
                mscp->xdir = 0x02;
        }
-
-       if (xs->lu != 0)
-       {
+#ifdef GOTTABEJOKING
+       if (xs->sc_link->lun != 0) {
                xs->error = XS_DRIVER_STUFFUP;
                xs->error = XS_DRIVER_STUFFUP;
-               uha_free_mscp(unit,mscp,flags);
-               return(HAD_ERROR);
+               uha_free_mscp(unit, mscp, flags);
+               return (HAD_ERROR);
        }
        }
-       
-       mscp->dcn       = 0x00;
-       mscp->chan      = 0x00;
-       mscp->target    = xs->targ;
-       mscp->lun       = xs->lu;
-       mscp->link.addr[0]      = 0x00;
-       mscp->link.addr[1]      = 0x00;
-       mscp->link.addr[2]      = 0x00;
-       mscp->link.addr[3]      = 0x00;
-       mscp->link_id   = 0x00;
-       mscp->cdblen             =       xs->cmdlen;
-       scratch                 =       KVTOPHYS(&(mscp->mscp_sense));
-       mscp->sense.addr[0]     =       (scratch & 0xff);
-       mscp->sense.addr[1]     =       ((scratch >> 8) & 0xff);
-       mscp->sense.addr[2]     =       ((scratch >> 16) & 0xff);
-       mscp->sense.addr[3]     =       ((scratch >> 24) & 0xff);
-       mscp->senselen          =       sizeof(mscp->mscp_sense);
-       mscp->ha_status         =       0x00;
-       mscp->targ_status       =       0x00;
-
-       if(xs->datalen)
-       { /* should use S/G only if not zero length */
-               scratch                 =       KVTOPHYS(mscp->uha_dma);
-               mscp->data.addr[0]      =       (scratch & 0xff);
-               mscp->data.addr[1]      =       ((scratch >> 8) & 0xff);
-               mscp->data.addr[2]      =       ((scratch >> 16) & 0xff);
-               mscp->data.addr[3]      =       ((scratch >> 24) & 0xff);
-               sg              =       mscp->uha_dma ;
-               seg             =       0;
-               mscp->sgth      =       0x01;
-
-               if(flags & SCSI_DATA_UIO)
-               {
-                       iovp = ((struct uio *)xs->data)->uio_iov;
-                       datalen = ((struct uio *)xs->data)->uio_iovcnt;
+#endif
+       mscp->dcn = 0x00;
+       mscp->chan = 0x00;
+       mscp->target = xs->sc_link->target;
+       mscp->lun = xs->sc_link->lun;
+       mscp->link.addr[0] = 0x00;
+       mscp->link.addr[1] = 0x00;
+       mscp->link.addr[2] = 0x00;
+       mscp->link.addr[3] = 0x00;
+       mscp->link_id = 0x00;
+       mscp->cdblen = xs->cmdlen;
+       scratch = KVTOPHYS(&(mscp->mscp_sense));
+       mscp->sense.addr[0] = (scratch & 0xff);
+       mscp->sense.addr[1] = ((scratch >> 8) & 0xff);
+       mscp->sense.addr[2] = ((scratch >> 16) & 0xff);
+       mscp->sense.addr[3] = ((scratch >> 24) & 0xff);
+       mscp->senselen = sizeof(mscp->mscp_sense);
+       mscp->ha_status = 0x00;
+       mscp->targ_status = 0x00;
+
+       if (xs->datalen) {      /* should use S/G only if not zero length */
+               scratch = KVTOPHYS(mscp->uha_dma);
+               mscp->data.addr[0] = (scratch & 0xff);
+               mscp->data.addr[1] = ((scratch >> 8) & 0xff);
+               mscp->data.addr[2] = ((scratch >> 16) & 0xff);
+               mscp->data.addr[3] = ((scratch >> 24) & 0xff);
+               sg = mscp->uha_dma;
+               seg = 0;
+               mscp->sgth = 0x01;
+
+#ifdef TFS
+               if (flags & SCSI_DATA_UIO) {
+                       iovp = ((struct uio *) xs->data)->uio_iov;
+                       datalen = ((struct uio *) xs->data)->uio_iovcnt;
                        xs->datalen = 0;
                        xs->datalen = 0;
-                       while ((datalen) && (seg < UHA_NSEG))
-                       {
-                               scratch  = (unsigned long)iovp->iov_base;
-                               sg->addr.addr[0] = (scratch & 0xff); 
+                       while ((datalen) && (seg < UHA_NSEG)) {
+                               scratch = (unsigned long) iovp->iov_base;
+                               sg->addr.addr[0] = (scratch & 0xff);
                                sg->addr.addr[1] = ((scratch >> 8) & 0xff);
                                sg->addr.addr[2] = ((scratch >> 16) & 0xff);
                                sg->addr.addr[3] = ((scratch >> 24) & 0xff);
                                sg->addr.addr[1] = ((scratch >> 8) & 0xff);
                                sg->addr.addr[2] = ((scratch >> 16) & 0xff);
                                sg->addr.addr[3] = ((scratch >> 24) & 0xff);
-                               xs->datalen += *(unsigned long *)sg->len.len = iovp->iov_len; 
-#ifdef UHADEBUG
-                               if(scsi_debug & SHOWSCATGATH)
-                                       printf("(0x%x@0x%x)"
-                                                       ,iovp->iov_len
-                                                       ,iovp->iov_base);
-#endif /*UHADEBUG*/
+                               xs->datalen += *(unsigned long *) sg->len.len = iovp->iov_len;
+                               SC_DEBUGN(xs->sc_link, SDEV_DB4, ("(0x%x@0x%x)",
+                                       iovp->iov_len,
+                                       iovp->iov_base));
                                sg++;
                                iovp++;
                                seg++;
                                datalen--;
                        }
                                sg++;
                                iovp++;
                                seg++;
                                datalen--;
                        }
-               }
-               else
+               } else
+#endif /*TFS */
                {
                {
-                       /***********************************************\
-                       * Set up the scatter gather block               *
-                       \***********************************************/
-               
-#ifdef UHADEBUG
-                       if(scsi_debug & SHOWSCATGATH)
-                               printf("%d @0x%x:- ",xs->datalen,xs->data);
-#endif /*UHADEBUG*/
-                       datalen         =       xs->datalen;
-                       thiskv          =       (int)xs->data;
-                       thisphys        =       KVTOPHYS(thiskv);
-                       templen         =       0;
-               
-                       while ((datalen) && (seg < UHA_NSEG))
-                       {
-                               bytes_this_seg  = 0;
-       
+                       /*
+                        * Set up the scatter gather block
+                        */
+
+                       SC_DEBUG(xs->sc_link, SDEV_DB4,
+                           ("%d @0x%x:- ", xs->datalen, xs->data));
+                       datalen = xs->datalen;
+                       thiskv = (int) xs->data;
+                       thisphys = KVTOPHYS(thiskv);
+                       templen = 0;
+
+                       while ((datalen) && (seg < UHA_NSEG)) {
+                               bytes_this_seg = 0;
+
                                /* put in the base address */
                                sg->addr.addr[0] = (thisphys & 0xff);
                                sg->addr.addr[1] = ((thisphys >> 8) & 0xff);
                                sg->addr.addr[2] = ((thisphys >> 16) & 0xff);
                                sg->addr.addr[3] = ((thisphys >> 24) & 0xff);
                                /* put in the base address */
                                sg->addr.addr[0] = (thisphys & 0xff);
                                sg->addr.addr[1] = ((thisphys >> 8) & 0xff);
                                sg->addr.addr[2] = ((thisphys >> 16) & 0xff);
                                sg->addr.addr[3] = ((thisphys >> 24) & 0xff);
-               
-#ifdef UHADEBUG
-                               if(scsi_debug & SHOWSCATGATH)
-                                       printf("0x%x",thisphys);
-#endif /*UHADEBUG*/
-       
+
+                               SC_DEBUGN(xs->sc_link, SDEV_DB4, ("0x%x", thisphys));
+
                                /* do it at least once */
                                /* do it at least once */
-                               nextphys = thisphys;    
+                               nextphys = thisphys;
                                while ((datalen) && (thisphys == nextphys))
                                while ((datalen) && (thisphys == nextphys))
-                               /*********************************************\
-                               * This page is contiguous (physically) with   *
-                               * the the last, just extend the length        *
-                               \*********************************************/
+                                       /*
+                                        * This page is contiguous (physically) with 
+                                        * the the last, just extend the length 
+                                        */
                                {
                                        /* how far to the end of the page */
                                        nextphys = (thisphys & (~(PAGESIZ - 1)))
                                {
                                        /* how far to the end of the page */
                                        nextphys = (thisphys & (~(PAGESIZ - 1)))
-                                                               + PAGESIZ;
+                                           + PAGESIZ;
                                        bytes_this_page = nextphys - thisphys;
                                        /**** or the data ****/
                                        bytes_this_page = min(bytes_this_page
                                        bytes_this_page = nextphys - thisphys;
                                        /**** or the data ****/
                                        bytes_this_page = min(bytes_this_page
-                                                               ,datalen);
-                                       bytes_this_seg  += bytes_this_page;
-                                       datalen         -= bytes_this_page;
-               
+                                           ,datalen);
+                                       bytes_this_seg += bytes_this_page;
+                                       datalen -= bytes_this_page;
+
                                        /* get more ready for the next page */
                                        /* get more ready for the next page */
-                                       thiskv  = (thiskv & (~(PAGESIZ - 1)))
-                                                               + PAGESIZ;
-                                       if(datalen)
+                                       thiskv = (thiskv & (~(PAGESIZ - 1)))
+                                           + PAGESIZ;
+                                       if (datalen)
                                                thisphys = KVTOPHYS(thiskv);
                                }
                                                thisphys = KVTOPHYS(thiskv);
                                }
-                               /********************************************\
-                               * next page isn't contiguous, finish the seg *
-                               \********************************************/
-#ifdef UHADEBUG
-                               if(scsi_debug & SHOWSCATGATH)
-                                       printf("(0x%x)",bytes_this_seg);
-#endif /*UHADEBUG*/
+                               /*
+                                * next page isn't contiguous, finish the seg
+                                */
+                               SC_DEBUGN(xs->sc_link, SDEV_DB4,
+                                   ("(0x%x)", bytes_this_seg));
                                sg->len.len[0] = (bytes_this_seg & 0xff);
                                sg->len.len[1] = ((bytes_this_seg >> 8) & 0xff);
                                sg->len.len[2] = ((bytes_this_seg >> 16) & 0xff);
                                sg->len.len[0] = (bytes_this_seg & 0xff);
                                sg->len.len[1] = ((bytes_this_seg >> 8) & 0xff);
                                sg->len.len[2] = ((bytes_this_seg >> 16) & 0xff);
@@ -1035,29 +1003,24 @@ cheat = mscp;
                                sg++;
                                seg++;
                        }
                                sg++;
                                seg++;
                        }
-               } /*end of iov/kv decision */
+               }
+
+               /* end of iov/kv decision */
                mscp->datalen.len[0] = (templen & 0xff);
                mscp->datalen.len[1] = ((templen >> 8) & 0xff);
                mscp->datalen.len[2] = ((templen >> 16) & 0xff);
                mscp->datalen.len[3] = ((templen >> 24) & 0xff);
                mscp->sg_num = seg;
 
                mscp->datalen.len[0] = (templen & 0xff);
                mscp->datalen.len[1] = ((templen >> 8) & 0xff);
                mscp->datalen.len[2] = ((templen >> 16) & 0xff);
                mscp->datalen.len[3] = ((templen >> 24) & 0xff);
                mscp->sg_num = seg;
 
-#ifdef UHADEBUG
-               if(scsi_debug & SHOWSCATGATH)
-                       printf("\n");
-#endif /*UHADEBUG*/
-               if (datalen)
-               { /* there's still data, must have run out of segs! */
+               SC_DEBUGN(xs->sc_link, SDEV_DB4, ("\n"));
+               if (datalen) {  /* there's still data, must have run out of segs! */
                        printf("uha%d: uha_scsi_cmd, more than %d DMA segs\n",
                        printf("uha%d: uha_scsi_cmd, more than %d DMA segs\n",
-                               unit,UHA_NSEG);
+                           unit, UHA_NSEG);
                        xs->error = XS_DRIVER_STUFFUP;
                        xs->error = XS_DRIVER_STUFFUP;
-                       uha_free_mscp(unit,mscp,flags);
-                       return(HAD_ERROR);
+                       uha_free_mscp(unit, mscp, flags);
+                       return (HAD_ERROR);
                }
                }
-
-       }
-       else
-       {       /* No data xfer, use non S/G values */
+       } else {                /* No data xfer, use non S/G values */
                mscp->data.addr[0] = 0x00;
                mscp->data.addr[1] = 0x00;
                mscp->data.addr[2] = 0x00;
                mscp->data.addr[0] = 0x00;
                mscp->data.addr[1] = 0x00;
                mscp->data.addr[2] = 0x00;
@@ -1068,142 +1031,119 @@ cheat = mscp;
                mscp->datalen.len[3] = 0x00;
                mscp->xdir = 0x03;
                mscp->sgth = 0x00;
                mscp->datalen.len[3] = 0x00;
                mscp->xdir = 0x03;
                mscp->sgth = 0x00;
-               mscp->sg_num = 0x00;    
+               mscp->sg_num = 0x00;
        }
 
        }
 
-       /***********************************************\
-       * Put the scsi command in the mscp and start it  *
-       \***********************************************/
-       bcopy(xs->cmd, mscp->cdb, xs->cmdlen); 
+       /*
+        * Put the scsi command in the mscp and start it
+        */
+       bcopy(xs->cmd, mscp->cdb, xs->cmdlen);
 
 
-       /***********************************************\
-       * Usually return SUCCESSFULLY QUEUED            *
-       \***********************************************/
-       if (!(flags & SCSI_NOMASK))
-       {
+       /*
+        * Usually return SUCCESSFULLY QUEUED
+        */
+       if (!(flags & SCSI_NOMASK)) {
                s = splbio();
                s = splbio();
-               uha_send_mbox(unit,mscp);
-               timeout(uha_timeout,mscp,(xs->timeout * hz) / 1000);
+               uha_send_mbox(unit, mscp);
+               timeout(uha_timeout, mscp, (xs->timeout * hz) / 1000);
                splx(s);
                splx(s);
-#ifdef UHADEBUG
-               if(scsi_debug & TRACEINTERRUPTS)
-                       printf("cmd_sent ");
-#endif /*UHADEBUG*/
-               return(SUCCESSFULLY_QUEUED);
+               SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_sent\n"));
+               return (SUCCESSFULLY_QUEUED);
        }
        }
-       /***********************************************\
-       * If we can't use interrupts, poll on completion*
-       \***********************************************/
-       uha_send_mbox(unit,mscp);
-#ifdef UHADEBUG
-       if(scsi_debug & TRACEINTERRUPTS)
-               printf("cmd_wait ");
-#endif /*UHADEBUG*/
-       do
-       {
-               if(uha_poll(unit,xs->timeout))
-               {
+
+       /*
+        * If we can't use interrupts, poll on completion
+        */
+       uha_send_mbox(unit, mscp);
+       SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_wait\n"));
+       do {
+               if (uha_poll(unit, xs->timeout)) {
                        if (!(xs->flags & SCSI_SILENT))
                        if (!(xs->flags & SCSI_SILENT))
-                               printf("uha%d: cmd fail\n",unit);
-                       if(!(uha_abort(unit,mscp)))
-                       {
-                               printf("uha%d: abort failed in wait\n",unit);
-                               uha_free_mscp(unit,mscp,flags);
+                               printf("uha%d: cmd fail\n", unit);
+                       if (!(uha_abort(unit, mscp))) {
+                               printf("uha%d: abort failed in wait\n", unit);
+                               uha_free_mscp(unit, mscp, flags);
                        }
                        xs->error = XS_DRIVER_STUFFUP;
                        }
                        xs->error = XS_DRIVER_STUFFUP;
-                       return(HAD_ERROR);
+                       return (HAD_ERROR);
                }
                }
-       } while (!(xs->flags & ITSDONE));/* something (?) else finished */
-       if(xs->error)
-       {
-               return(HAD_ERROR);
        }
        }
-       return(COMPLETE);
+       while (!(xs->flags & ITSDONE)); /* something (?) else finished */
+       if (xs->error) {
+               return (HAD_ERROR);
+       }
+       return (COMPLETE);
 }
 
 }
 
-
+void
 uha_timeout(struct mscp *mscp)
 {
        int     unit;
 uha_timeout(struct mscp *mscp)
 {
        int     unit;
-       int     s       = splbio();
-       int     port = uha_data[unit].baseport;
+       struct uha_data *uha;
+       int     s = splbio();
+       /*int   port = uha->baseport; */
+
+       unit = mscp->xs->sc_link->adapter_unit;
+       uha = uhadata[unit];
+       printf("uha%d:%d:%d (%s%d) timed out ", unit
+           ,mscp->xs->sc_link->target
+           ,mscp->xs->sc_link->lun
+           ,mscp->xs->sc_link->device->name
+           ,mscp->xs->sc_link->dev_unit);
 
 
-       unit = mscp->xs->adapter;
-       printf("uha%d:%d device timed out\n",unit
-                       ,mscp->xs->targ);
 #ifdef UHADEBUG
 #ifdef UHADEBUG
-       if(uha_debug & UHA_SHOWMSCPS)
-               uha_print_active_mscp(unit);
-#endif /*UHADEBUG*/
+       uha_print_active_mscp(unit);
+#endif /*UHADEBUG */
 
 
-       if((uha_abort(unit,mscp) !=1) || (mscp->flags = MSCP_ABORTED))
-       {
+       if ((uha_abort(unit, mscp) != 1) || (mscp->flags = MSCP_ABORTED)) {
                printf("AGAIN");
                printf("AGAIN");
-               mscp->xs->retries = 0; /* I MEAN IT ! */
-               uha_done(unit,mscp,FAIL);
-       }
-       else    /* abort the operation that has timed out */
-       {
+               mscp->xs->retries = 0;  /* I MEAN IT ! */
+               uha_done(unit, mscp, FAIL);
+       } else {                /* abort the operation that has timed out */
                printf("\n");
                printf("\n");
-               timeout(uha_timeout,mscp,2 * hz);
+               timeout(uha_timeout, mscp, 2 * hz);
                mscp->flags = MSCP_ABORTED;
        }
        splx(s);
 }
 
                mscp->flags = MSCP_ABORTED;
        }
        splx(s);
 }
 
-uha_show_scsi_cmd(struct scsi_xfer *xs)
-{
-       u_char  *b = (u_char *)xs->cmd;
-       int i = 0;
-       if(!(xs->flags & SCSI_RESET))
-       {
-               printf("uha%d:%d:%d-"
-                       ,xs->adapter
-                       ,xs->targ
-                       ,xs->lu);
-               while(i < xs->cmdlen )
-               {
-                       if(i) printf(",");
-                       printf("%x",b[i++]);
-               }
-               printf("-\n");
-       }
-       else
-       {
-               printf("uha%d:%d:%d-RESET-\n" 
-                       ,xs->adapter 
-                       ,xs->targ
-                       ,xs->lu
-               );
-       }
-}
+#ifdef UHADEBUG
+void
 uha_print_mscp(mscp)
 uha_print_mscp(mscp)
-struct  mscp *mscp;
+       struct mscp *mscp;
 {
        printf("mscp:%x op:%x cmdlen:%d senlen:%d\n"
 {
        printf("mscp:%x op:%x cmdlen:%d senlen:%d\n"
-               ,mscp
-               ,mscp->opcode
-               ,mscp->cdblen
-               ,mscp->senselen);
+           ,mscp
+           ,mscp->opcode
+           ,mscp->cdblen
+           ,mscp->senselen);
        printf("        sg:%d sgnum:%x datlen:%d hstat:%x tstat:%x flags:%x\n"
        printf("        sg:%d sgnum:%x datlen:%d hstat:%x tstat:%x flags:%x\n"
-               ,mscp->sgth
-               ,mscp->sg_num
-               ,mscp->datalen
-               ,mscp->ha_status
-               ,mscp->targ_status
-               ,mscp->flags);
-       uha_show_scsi_cmd(mscp->xs);
+           ,mscp->sgth
+           ,mscp->sg_num
+           ,mscp->datalen
+           ,mscp->ha_status
+           ,mscp->targ_status
+           ,mscp->flags);
+       show_scsi_cmd(mscp->xs);
 }
 
 }
 
+void
 uha_print_active_mscp(int unit)
 {
 uha_print_active_mscp(int unit)
 {
-       struct  mscp *mscp = uha_data[unit].mscps;
-       int i = NUHA;
+       struct uha_data *uha = uhadata[unit];
+       struct mscp *mscp;
+       int     i = 0;
 
 
-       while(i--)
-       {
-               if(mscp->flags != MSCP_FREE)
-                       uha_print_mscp(mscp);
-               mscp++;
+       while (i < MSCP_HASH_SIZE) {
+               mscp = uha->mscphash[i];
+               while (mscp) {
+                       if (mscp->flags != MSCP_FREE) {
+                               uha_print_mscp(mscp);
+                       }
+                       mscp = mscp->nexthash;
+               }
+       i++;
        }
 }
        }
 }
+#endif /*UHADEBUG */
+#endif /*KERNEL */
index beb4d7d..95c3db6 100644 (file)
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)wd.c  7.2 (Berkeley) 5/9/91
  * SUCH DAMAGE.
  *
  *     from: @(#)wd.c  7.2 (Berkeley) 5/9/91
- *     $Id: wd.c,v 1.11 1993/10/16 13:46:31 rgrimes Exp $
+ *     $Id: wd.c,v 1.12 1993/11/17 23:25:20 wollman Exp $
  */
 
 /* TODO:peel out buffer at low ipl, speed improvement */
  */
 
 /* TODO:peel out buffer at low ipl, speed improvement */
@@ -1137,7 +1137,7 @@ wdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
                        auio.uio_segflg = 0;
                        auio.uio_offset =
                                fop->df_startblk * du->dk_dd.d_secsize;
                        auio.uio_segflg = 0;
                        auio.uio_offset =
                                fop->df_startblk * du->dk_dd.d_secsize;
-                       error = physio(wdformat, &rwdbuf[unit], dev, B_WRITE,
+                       error = physio(wdformat, &rwdbuf[unit], 0, dev, B_WRITE,
                                minphys, &auio);
                        fop->df_count -= auio.uio_resid;
                        fop->df_reg[0] = du->dk_status;
                                minphys, &auio);
                        fop->df_count -= auio.uio_resid;
                        fop->df_reg[0] = du->dk_status;
index 9964aa1..4d8dbc3 100644 (file)
@@ -36,7 +36,7 @@ static int wdtest = 0;
  * SUCH DAMAGE.
  *
  *     from: @(#)wx.c  7.2 (Berkeley) 5/9/91
  * SUCH DAMAGE.
  *
  *     from: @(#)wx.c  7.2 (Berkeley) 5/9/91
- *     $Id: wx.c,v 1.2 1993/10/26 23:04:38 nate Exp $
+ *     $Id: wx.c,v 1.3 1993/11/03 18:04:15 nate Exp $
  */
 
 /* TODO:peel out buffer at low ipl, speed improvement */
  */
 
 /* TODO:peel out buffer at low ipl, speed improvement */
@@ -1123,7 +1123,7 @@ wdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
                        auio.uio_segflg = 0;
                        auio.uio_offset =
                                fop->df_startblk * du->dk_dd.d_secsize;
                        auio.uio_segflg = 0;
                        auio.uio_offset =
                                fop->df_startblk * du->dk_dd.d_secsize;
-                       error = physio(wdformat, &rwdbuf[unit], dev, B_WRITE,
+                       error = physio(wdformat, &rwdbuf[unit], 0, dev, B_WRITE,
                                minphys, &auio);
                        fop->df_count -= auio.uio_resid;
                        fop->df_reg[0] = du->dk_status;
                                minphys, &auio);
                        fop->df_count -= auio.uio_resid;
                        fop->df_reg[0] = du->dk_status;
index 0995b1b..1872764 100644 (file)
@@ -45,7 +45,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $Id$
+ *     $Id: kern__physio.c,v 1.2 1993/10/16 15:24:06 rgrimes Exp $
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -58,7 +58,7 @@
 #include "vm/vm.h"
 #include "specdev.h"
 
 #include "vm/vm.h"
 #include "specdev.h"
 
-static physio(int (*)(), int, int, int, caddr_t, int *, struct proc *);
+int physio(int (*)(), int, struct buf *, int, int, caddr_t, int *, struct proc *);
 
 /*
  * Driver interface to do "raw" I/O in the address space of a
 
 /*
  * Driver interface to do "raw" I/O in the address space of a
@@ -77,25 +77,29 @@ rawwrite(dev, uio)
        return (uioapply(physio, cdevsw[major(dev)].d_strategy, dev, uio));
 }
 
        return (uioapply(physio, cdevsw[major(dev)].d_strategy, dev, uio));
 }
 
-static physio(strat, dev, off, rw, base, len, p)
+int physio(strat, dev, bp, off, rw, base, len, p)
        int (*strat)(); 
        dev_t dev;
        int (*strat)(); 
        dev_t dev;
+       struct buf *bp;
        int rw, off;
        caddr_t base;
        int *len;
        struct proc *p;
 {
        int rw, off;
        caddr_t base;
        int *len;
        struct proc *p;
 {
-       register struct buf *bp;
        int amttodo = *len, error, amtdone;
        vm_prot_t ftype;
        static zero;
        caddr_t adr;
        int amttodo = *len, error, amtdone;
        vm_prot_t ftype;
        static zero;
        caddr_t adr;
+       int bp_alloc = (bp == 0);
 
        rw = rw == UIO_READ ? B_READ : 0;
 
        /* create and build a buffer header for a transfer */
 
        rw = rw == UIO_READ ? B_READ : 0;
 
        /* create and build a buffer header for a transfer */
-       bp = (struct buf *)malloc(sizeof(*bp), M_TEMP, M_NOWAIT);
-       bzero((char *)bp, sizeof(*bp));                 /* 09 Sep 92*/
+
+       if (bp_alloc) {
+               bp = (struct buf *)malloc(sizeof(*bp), M_TEMP, M_NOWAIT);
+               bzero((char *)bp, sizeof(*bp));                 /* 09 Sep 92*/
+       }
        bp->b_flags = B_BUSY | B_PHYS | rw;
        bp->b_proc = p;
        bp->b_dev = dev;
        bp->b_flags = B_BUSY | B_PHYS | rw;
        bp->b_proc = p;
        bp->b_dev = dev;
@@ -112,11 +116,13 @@ static physio(strat, dev, off, rw, base, len, p)
 
                /* first, check if accessible */
                if (rw == B_READ && !useracc(base, bp->b_bcount, B_WRITE)) {
 
                /* first, check if accessible */
                if (rw == B_READ && !useracc(base, bp->b_bcount, B_WRITE)) {
-                       free(bp, M_TEMP);
+                       if (bp_alloc)
+                               free(bp, M_TEMP);
                        return (EFAULT);
                }
                if (rw == B_WRITE && !useracc(base, bp->b_bcount, B_READ)) {
                        return (EFAULT);
                }
                if (rw == B_WRITE && !useracc(base, bp->b_bcount, B_READ)) {
-                       free(bp, M_TEMP);
+                       if (bp_alloc)
+                               free(bp, M_TEMP);
                        return (EFAULT);
                }
 
                        return (EFAULT);
                }
 
@@ -147,7 +153,8 @@ static physio(strat, dev, off, rw, base, len, p)
        } while (amttodo && (bp->b_flags & B_ERROR) == 0 && amtdone > 0);
 
        error = bp->b_error;
        } while (amttodo && (bp->b_flags & B_ERROR) == 0 && amtdone > 0);
 
        error = bp->b_error;
-       free(bp, M_TEMP);
+       if (bp_alloc)
+               free(bp, M_TEMP);
        *len = amttodo;
        return (error);
 }
        *len = amttodo;
        return (error);
 }
index aa48658..904f8a1 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)kern_subr.c   7.7 (Berkeley) 4/15/91
  * SUCH DAMAGE.
  *
  *     from: @(#)kern_subr.c   7.7 (Berkeley) 4/15/91
- *     $Id$
+ *     $Id: kern_subr.c,v 1.2 1993/10/16 15:24:30 rgrimes Exp $
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -117,7 +117,7 @@ uioapply(func, arg1, arg2, uio)
                        continue;
                }
                cnt1 = cnt;
                        continue;
                }
                cnt1 = cnt;
-               error = (*func)(arg1, arg2, uio->uio_offset, uio->uio_rw,
+               error = (*func)(arg1, arg2, NULL, uio->uio_offset, uio->uio_rw,
                        iov->iov_base, &cnt1, uio->uio_procp);
                cnt -= cnt1;
                iov->iov_base += cnt;
                        iov->iov_base, &cnt1, uio->uio_procp);
                cnt -= cnt1;
                iov->iov_base += cnt;
index fbd1e6e..b110930 100644 (file)
@@ -1,46 +1,55 @@
 This release consists of the following files 
 This release consists of the following files 
-(relative to the base of the kernel tree)
-
-
-MAKEDEV
-
-scsi
-scsi/README
-scsi/scsiconf.h
-scsi/scsiconf.c
-scsi/scsi_all.h
-
-scsi/scsi_disk.h
-scsi/sd.c
-
-sys/mtio.h (modified)
-scsi/scsi_tape.h
-scsi/st.c
-
-sys/sgio.h
-scsi/scsi_generic.h
-scsi/sg.c /* port not complete */
-
-sys/chio.h
-scsi/scsi_changer.h
-scsi/ch.c
-
-sys/cdio.h
-scsi/scsi_cd.h
-scsi/cd.c
-
-i386/conf/SCSITEST
-i386/isa/aha1542.c
-
-i386/conf/AHBTEST
-i386/isa/aha1742.c
-
-i386/conf/UHATEST
-i386/isa/ultra14f.c
-
-i386/conf/BTTEST
-i386/isa/bt742a.c
-
+(relative to the base of the source tree )
+
+share/man/man4/scsi.4 <-useful general info
+share/man/man4/uk.4
+share/man/man4/su.4
+share/man/man4/ch.4
+share/man/man4/cd.4
+share/man/man4/sd.4
+share/man/man4/st.4 <--READ THIS IF YOU USE TAPES!
+sbin/scsi/procargs.c
+sbin/scsi/scsi.c
+sbin/scsi/scsi.1
+sbin/scsi/Makefile
+sbin/st/Makefile
+sbin/st/st.1
+sbin/st/st.c
+sys/sys/chio.h
+sys/sys/cdio.h
+sys/sys/mtio.h
+sys/sys/scsiio.h
+sys/i386/conf/EXAMPLE
+sys/i386/isa/ultra14f.c <-runs 14f and 34f
+sys/i386/isa/ultra_all.c.beta <-beta version, runs 14f,24f and 34f
+sys/i386/isa/bt742a.c
+sys/i386/isa/aha1742.c
+sys/i386/isa/aha1542.c
+sys/scsi/syspatches
+sys/scsi/syspatches/conf.c
+sys/scsi/syspatches/user_scsi.diffs
+sys/scsi/syspatches/MAKEDEV.diff
+sys/scsi/syspatches/isa.c.patch
+sys/scsi/syspatches/README
+sys/scsi/uk.c
+sys/scsi/su.c
+sys/scsi/st.c
+sys/scsi/sd.c
+sys/scsi/ch.c
+sys/scsi/cd.c
+sys/scsi/scsi_ioctl.c
+sys/scsi/scsi_base.c
+sys/scsi/scsiconf.c
+sys/scsi/scsi_tape.h
+sys/scsi/scsi_disk.h
+sys/scsi/scsi_changer.h
+sys/scsi/scsi_cd.h
+sys/scsi/scsi_all.h
+sys/scsi/scsi_debug.h
+sys/scsi/scsiconf.h
+sys/scsi/README <--this file
+
+notice sys/scsi/sg.c and sys/sys/sgio.h have been removed
 
 
 ----------------------------------------------------------------
 
 
 ----------------------------------------------------------------
@@ -54,34 +63,22 @@ generic scsi tape
 cd-rom  (plays music under the xcplayer (?) program)
 AEG Character recognition devices *
 Calera Character recognition devices *
 cd-rom  (plays music under the xcplayer (?) program)
 AEG Character recognition devices *
 Calera Character recognition devices *
-Kodak IL900 scanner *
+Generic scsi-II scanners *
 Exabyte tape changer device.
 Exabyte tape changer device.
-GENERIC SCSI DEVICES (user generated scsi commands) (port not complete)
+GENERIC SCSI DEVICES (user generated scsi commands) 
 ----------------------------------------------------------------
 
 
 There are also working bottom end drivers for:
 ----------------------------------------------------------------
 adaptec 1542 (and 1742 in 1542 mode)
 ----------------------------------------------------------------
 
 
 There are also working bottom end drivers for:
 ----------------------------------------------------------------
 adaptec 1542 (and 1742 in 1542 mode)
-bustec 742a (apparently works for VESA version)
-adaptec 174x 
+bustec 742a (apparently works for VESA version (445S?))(and 747?)
+adaptec 174x  (note NOT 27xx)
 Ultrastore 14f (works for 34f (VESA version))                          
 Ultrastore 14f (works for 34f (VESA version))                          
+Ultrastore 24f RSN (Beta version included here)
 ----------------------------------------------------------------
 
 
 ----------------------------------------------------------------
 
 
-Work is proceeding on the following bottom end drivers:
-----------------------------------------------------------------
-Future Domain (1680)**                 hosler@tfs.com & me
-Future Domain (8  bit)****             rpr@oce.nl
-WD7000**                               terry@icarus.weber.edu
-seagate st01/st02****                  overby@aspen.cray.com ?
-----------------------------------------------------------------
-* drivers not made public (proprietary.. proof that the concept works though)
-** driver not yet released but working.
-*** just a dream so far.
-**** some amount more than just a dream so far.
-
-
 ################## Using the scsi system ##################
 ------------minor numbers---------------
 This scsi system does not allocate minor numbers to devices depending
 ################## Using the scsi system ##################
 ------------minor numbers---------------
 This scsi system does not allocate minor numbers to devices depending
@@ -98,19 +95,18 @@ That would not change their minor numbers.
 THE EXCEPTION  TO THIS IS IN THE GENERIC SCSI DRIVER. in which case
 the following mapping applies:
 
 THE EXCEPTION  TO THIS IS IN THE GENERIC SCSI DRIVER. in which case
 the following mapping applies:
 
-BB LLL TTT  B= scsi bus number, T = target number, L = LUN.
-(yes I know it's strange but it's SGI compatible)
+BB TTT LLL  B= scsi bus number, T = target number, L = LUN.
 
 It is possible to run two different TYPES of scsi adapters at the 
 same time and have st0 on one and st1 on another. (for example)
 
 There is a scheme supported in which scsi devices can be 'wired in' even
 if they are not present or powered on at probe time. (see scsiconf.c)
 
 It is possible to run two different TYPES of scsi adapters at the 
 same time and have st0 on one and st1 on another. (for example)
 
 There is a scheme supported in which scsi devices can be 'wired in' even
 if they are not present or powered on at probe time. (see scsiconf.c)
+In addition, the scsi(1) command allows the operator ask for a
+reprobe at any time.  Newly found devices will be configured in. Any
+device that does not map to a known device type is attached to the
+'unknown' (uk) driver.
 
 
---------------getting started------------
-It should be possible to use the /dev entries for as0 as if they were 
-/dev entries for sd0 and the old as bootblocks should
-continue to work if you are using an adaptec 1542b.
 
 --------------making devices------------
 A changed version of /dev/MAKEDEV is supplied that
 
 --------------making devices------------
 A changed version of /dev/MAKEDEV is supplied that
@@ -120,25 +116,7 @@ e.g.
 cd /dev
 sh MAKEDEV sd0 sd1 sd2 st0 st1 cd0
 
 cd /dev
 sh MAKEDEV sd0 sd1 sd2 st0 st1 cd0
 
-
-The tape devices are as follows:
-rst0   basic raw device, will rewind on close
-nrst0  will not rewind on close
-erst0  will rewind and EJECTon close
-nerst0  will not rewind and WILL eject (some devices may rewind anyhow)
-
-------------future enhancements--------------
-Some people have indicated that they would like to have the SCSI ID
-encoded into the minor number in some way, and
-this may be supported at some timein the future, using
-minor numbers greater than 128. (or maybe a different major number)
-
-
-I will also be writing (probably) a generic scsi-error
-handling routine that will be table driven, so that the routine can
-be removed from each individual driver. With enough care,
-two similar devices with different error codes (quite common) could run
-the same driver but use different error tables.
+see st(1) and st(4) for info on tape devices.
 
 --------------file layout-------------------
 Originally I had all scsi definitions in one file: scsi.h
 
 --------------file layout-------------------
 Originally I had all scsi definitions in one file: scsi.h
@@ -159,18 +137,22 @@ scsi-changer.h            commands medium changer devices  --- CHAPTER 16
 User accessable structures (e.g. ioctl definitions) have been
 placed in sys/cdio, sys/sgio and sys/chio (based after sys/mtio for
 the ioctls for mag tapes (including st).
 User accessable structures (e.g. ioctl definitions) have been
 placed in sys/cdio, sys/sgio and sys/chio (based after sys/mtio for
 the ioctls for mag tapes (including st).
+General scsi ioctls are found in sys/scsiio.h.
 
 -----------cd-rom-----------------
 The cd rom driver ha been tested by a number of people and
 
 -----------cd-rom-----------------
 The cd rom driver ha been tested by a number of people and
-grefen@wilbur.zdv.uni-mainz.de has completed the audio play
+grefen@convex.com has completed the audio play
 functions.
 (xcdplayer was available from the 'from_ref' directory on agate)
 
 At this time it is possible audio play is broken on cdroms and I will
 be unable to fix it until I get one to test.
 functions.
 (xcdplayer was available from the 'from_ref' directory on agate)
 
 At this time it is possible audio play is broken on cdroms and I will
 be unable to fix it until I get one to test.
+***IMPORTANT***
+Cdrom audio is only suported at all for cdroms that use SCSI2 audio
+definitions.
 
 -------------media changer---------------
 
 -------------media changer---------------
-Once again courtesy of grefen@wilbur.zdv.uni-mainz.de.
+Once again courtesy of grefen@convex.com (in germany)
 I have not tested this but he assures me it's ready for testing.
 If anyone has an exabyte tape changer or similar, 
 contact the author for information regarding the control interface
 I have not tested this but he assures me it's ready for testing.
 If anyone has an exabyte tape changer or similar, 
 contact the author for information regarding the control interface
@@ -178,20 +160,6 @@ and program.
 
 WARNING: This has not been tested for a LONG TIME!
 
 
 WARNING: This has not been tested for a LONG TIME!
 
------------booting from an AHA-174x---------
-For some reason I have not yet worked out,
-the BIOS-based bootblocks I have posted will not boot
-from the aha1742 in extended mode. (it can't be serious
-because the MACH version works) This is in fact not a 
-problem because the aha1742 driver will force the board into extended
-mode during probe, so it can be left in standard mode during the boot.
-During the next reboot, the bios will place it back in standard mode
-ready for the NEXT boot.
-
-[Update: This has apparently been fixed in the newest NetBSD/FreeBSD
-releases ]
-
-
 
 ---------recent changes-----------
 Removed all bitfields from machine independent sections to make
 
 ---------recent changes-----------
 Removed all bitfields from machine independent sections to make
@@ -206,4 +174,23 @@ have particular problems so they can be handled specially.
 
 many bug-fixes and cleanups.
 
 
 many bug-fixes and cleanups.
 
-$Id$
+---------even more recent changes:--------
+
+rewrote almost the entire thing..
+
+
+
+------Mon Oct 11 22:20:25 WST 1993------
+
+Code is now all KNF (or close to it).
+
+A new structure has been introduced..
+Called scsi_link, one of these exists for every bus/target/lun
+that has a driver attached to it.
+It has links to the adapter and to the driver, as well as status
+information of global interest. (e.g. if the device is in use).
+The use of this new structure has allowed the compaction of a
+lot of duplicated code into a single copy (now in scsi_base.c)
+and makes more simple the USER level scsi implimentation.
+
+
index f5de591..68b09ba 100644 (file)
@@ -14,7 +14,7 @@
  *
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  *
  *
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  *
- *     $Id: cd.c,v 1.10 1993/09/21 05:30:35 rgrimes Exp $
+ *      $Id: cd.c,v 2.3 93/10/11 11:49:49 julian Exp Locker: julian $
  */
 
 #define SPLCD splbio
  */
 
 #define SPLCD splbio
 #include <scsi/scsi_disk.h>    /* rw_big and start_stop come from there */
 #include <scsi/scsiconf.h>
 
 #include <scsi/scsi_disk.h>    /* rw_big and start_stop come from there */
 #include <scsi/scsiconf.h>
 
-long int cdstrats,cdqueues;
-
+int32   cdstrats, cdqueues;
 
 #include <ddb.h>
 #if    NDDB > 0
 
 #include <ddb.h>
 #if    NDDB > 0
-int    Debugger();
-#else  NDDB > 0
+int     Debugger();
+#else  /* NDDB > 0 */
 #define Debugger()
 #define Debugger()
-#endif NDDB > 0
-
+#endif /* NDDB > 0 */
 
 #define PAGESIZ        4096
 
 #define PAGESIZ        4096
-#define SECSIZE 2048   /* XXX */ /* default only */
+#define SECSIZE 2048   /* XXX */       /* default only */
 #define        CDOUTSTANDING   2
 #define        CDOUTSTANDING   2
-#define CDQSIZE                4
-#define        CD_RETRIES      4
+#define        CDRETRIES       1
 
 #define        UNITSHIFT       3
 #define PARTITION(z)   (minor(z) & 0x07)
 #define        RAW_PART        3
 #define UNIT(z)                (  (minor(z) >> UNITSHIFT) )
 
 
 #define        UNITSHIFT       3
 #define PARTITION(z)   (minor(z) & 0x07)
 #define        RAW_PART        3
 #define UNIT(z)                (  (minor(z) >> UNITSHIFT) )
 
+extern int hz;
+errval  cdstrategy();
 
 
-extern int hz;
-int    cd_done();
-int    cdstrategy();
-int    cd_debug = 0;
-
-
-struct cd_data
+void    cdstart();
+struct scsi_device cd_switch =
 {
 {
-       int     flags;
-#define        CDVALID         0x02            /* PARAMS LOADED        */
-#define        CDINIT          0x04            /* device has been init'd */
-#define        CDWAIT          0x08            /* device has someone waiting */
-#define CDHAVELABEL    0x10            /* have read the label */
-       struct  scsi_switch *sc_sw;     /* address of scsi low level switch */
-       int     ctlr;                   /* so they know which one we want */
-       int     targ;                   /* our scsi target ID */
-       int     lu;                     /* out scsi lu */
-       int     cmdscount;              /* cmds allowed outstanding by board*/
-       struct  cd_parms
-       {
-               int     blksize;
-               u_long  disksize;               /* total number sectors */
-       }params;
-       struct  disklabel       disklabel;
-       int     partflags[MAXPARTITIONS];       /* per partition flags */
+    NULL,                      /* use default error handler */
+    cdstart,                   /* we have a queue, which is started by this */
+    NULL,                      /* we do not have an async handler */
+    NULL,                      /* use default 'done' routine */
+    "cd",                      /* we are to be refered to by this name */
+    0,                         /* no device specific flags */
+    0, 0                       /* spares not used */
+};
+
+struct cd_data {
+       u_int32 flags;
+#define        CDINIT          0x04    /* device has been init'd */
+       struct scsi_link *sc_link;      /* address of scsi low level switch */
+       u_int32 cmdscount;      /* cmds allowed outstanding by board */
+       struct cd_parms {
+               u_int32 blksize;
+               u_long  disksize;       /* total number sectors */
+       } params;
+       struct disklabel disklabel;
+       u_int32 partflags[MAXPARTITIONS];       /* per partition flags */
 #define CDOPEN 0x01
 #define CDOPEN 0x01
-       int             openparts;              /* one bit for each open partition */
-       int             xfer_block_wait;
-       struct  scsi_xfer       *free_xfer;
-       struct  scsi_xfer       scsi_xfer[CDOUTSTANDING]; /* XXX */
-       struct  buf             buf_queue;
+       u_int32 openparts;      /* one bit for each open partition */
+       u_int32 xfer_block_wait;
+       struct buf buf_queue;
 };
 
 #define CD_STOP                0
 #define CD_START       1
 #define CD_EJECT       -2
 
 };
 
 #define CD_STOP                0
 #define CD_START       1
 #define CD_EJECT       -2
 
-struct cd_driver
-{
-       int     size;
-       struct  cd_data **cd_data;
-}*cd_driver;
-
-static int     next_cd_unit = 0;
-/***********************************************************************\
-* The routine called by the low level scsi routine when it discovers   *
-* A device suitable for this driver                                    *
-\***********************************************************************/
-int    cdattach(ctlr,targ,lu,scsi_switch)
-struct scsi_switch *scsi_switch;
+struct cd_driver {
+       u_int32 size;
+       struct cd_data **cd_data;
+} cd_driver;
+
+static u_int32 next_cd_unit = 0;
+
+/*
+ * The routine called by the low level scsi routine when it discovers
+ * A device suitable for this driver
+ */
+int 
+cdattach(sc_link)
+       struct scsi_link *sc_link;
 {
 {
-       int             unit,i;
-       unsigned char   *tbl;
-       struct cd_data  *cd, **cdrealloc;
-       struct cd_parms *dp;
-
-#ifdef CDDEBUG
-       if(scsi_debug & PRINTROUTINES) printf("cdattach: "); 
-#endif /*CDDEBUG*/
-       /*******************************************************\
-       * Check if we have resources allocated yet, if not      *
-       * allocate and initialize them                          *
-       \*******************************************************/
-       if (next_cd_unit == 0)
-       {
-               cd_driver =
-                       malloc(sizeof(struct cd_driver),M_DEVBUF,M_NOWAIT);
-               if(!cd_driver)
-               {
-                       printf("cd%d: malloc failed for cd_driver\n",unit);
-                       return(0);
-               }
-               bzero(cd_driver,sizeof(cd_driver));
-               cd_driver->size = 0;
-       }
-       /*******************************************************\
-       * allocate the resources for another drive              *
-       * if we have already allocate a cd_data pointer we must *
-       * copy the old pointers into a new region that is       *
-       * larger and release the old region, aka realloc        *
-       \*******************************************************/
+       u_int32 unit, i;
+       unsigned char *tbl;
+       struct cd_data *cd, **cdrealloc;
+       struct cd_parms *dp;
+
+       SC_DEBUG(sc_link, SDEV_DB2, ("cdattach "));
+
+       /*
+        * Fill out any more info in the
+        * Link structure that we can
+        */
        unit = next_cd_unit++;
        unit = next_cd_unit++;
+       sc_link->device = &cd_switch;
+       sc_link->dev_unit = unit;
+       /*
+        * allocate the resources for another drive
+        * if we have already allocate a cd_data pointer we must
+        * copy the old pointers into a new region that is
+        * larger and release the old region, aka realloc
+        */
        /* XXX
         * This if will always be true for now, but future code may
         * preallocate more units to reduce overhead.  This would be
         * done by changing the malloc to be (next_cd_unit * x) and
        /* XXX
         * This if will always be true for now, but future code may
         * preallocate more units to reduce overhead.  This would be
         * done by changing the malloc to be (next_cd_unit * x) and
-        * the cd_driver->size++ to be +x
+        * the cd_driver.size++ to be +x
         */
         */
-       if(unit >= cd_driver->size)
-       {
+       if (unit >= cd_driver.size) {
                cdrealloc =
                cdrealloc =
-                       malloc(sizeof(cd_driver->cd_data) * next_cd_unit,
-                               M_DEVBUF,M_NOWAIT);
-               if(!cdrealloc)
-               {
-                       printf("cd%d: malloc failed for cdrealloc\n",unit);
-                       return(0);
+                   malloc(sizeof(cd_driver.cd_data) * next_cd_unit,
+                   M_DEVBUF, M_NOWAIT);
+               if (!cdrealloc) {
+                       printf("cd%d: malloc failed for cdrealloc\n", unit);
+                       return (0);
                }
                /* Make sure we have something to copy before we copy it */
                }
                /* Make sure we have something to copy before we copy it */
-               bzero(cdrealloc,sizeof(cd_driver->cd_data) * next_cd_unit);
-               if(cd_driver->size)
-               {
-                       bcopy(cd_driver->cd_data,cdrealloc,
-                               sizeof(cd_driver->cd_data) * cd_driver->size);
-                       free(cd_driver->cd_data,M_DEVBUF);
+               bzero(cdrealloc, sizeof(cd_driver.cd_data) * next_cd_unit);
+               if (cd_driver.size) {
+                       bcopy(cd_driver.cd_data, cdrealloc,
+                           sizeof(cd_driver.cd_data) * cd_driver.size);
+                       free(cd_driver.cd_data, M_DEVBUF);
                }
                }
-               cd_driver->cd_data = cdrealloc;
-               cd_driver->cd_data[unit] = NULL;
-               cd_driver->size++;
-       }
-       if(cd_driver->cd_data[unit])
-       {
-               printf("cd%d: Already has storage!\n",unit);
-               return(0);
+               cd_driver.cd_data = cdrealloc;
+               cd_driver.cd_data[unit] = NULL;
+               cd_driver.size++;
        }
        }
-       /*******************************************************\
-       * allocate the per drive data area                      *
-       \*******************************************************/
-       cd = cd_driver->cd_data[unit] =
-               malloc(sizeof(struct cd_data),M_DEVBUF,M_NOWAIT);
-       if(!cd)
-       {
-               printf("cd%d: malloc failed for cd_data\n",unit);
-               return(0);
+       if (cd_driver.cd_data[unit]) {
+               printf("cd%d: Already has storage!\n", unit);
+               return (0);
        }
        }
-       bzero(cd,sizeof(struct cd_data));
-       dp  = &(cd->params);
-       /*******************************************************\
-       * Store information needed to contact our base driver   *
-       \*******************************************************/
-       cd->sc_sw       =       scsi_switch;
-       cd->ctlr        =       ctlr;
-       cd->targ        =       targ;
-       cd->lu          =       lu;
-       cd->cmdscount = CDOUTSTANDING; /* XXX (ask the board) */
-
-       i = cd->cmdscount;
-       while(i-- )
-       {
-               cd->scsi_xfer[i].next = cd->free_xfer;
-               cd->free_xfer = &cd->scsi_xfer[i];
+       /*
+        * allocate the per drive data area
+        */
+       cd = cd_driver.cd_data[unit] =
+           malloc(sizeof(struct cd_data), M_DEVBUF, M_NOWAIT);
+       if (!cd) {
+               printf("cd%d: malloc failed for cd_data\n", unit);
+               return (0);
        }
        }
-       /*******************************************************\
-       * Use the subdriver to request information regarding    *
-       * the drive. We cannot use interrupts yet, so the       *
-       * request must specify this.                            *
-       \*******************************************************/
-       cd_get_parms(unit,  SCSI_NOSLEEP |  SCSI_NOMASK);
-       if(dp->disksize)
-       {
+       bzero(cd, sizeof(struct cd_data));
+       dp = &(cd->params);
+       /*
+        * Store information needed to contact our base driver
+        */
+       cd->sc_link = sc_link;
+       /* only allow 1 outstanding command on tapes */
+       sc_link->opennings = cd->cmdscount = CDOUTSTANDING;
+
+       /*
+        * Use the subdriver to request information regarding
+        * the drive. We cannot use interrupts yet, so the
+        * request must specify this.
+        */
+       cd_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK);
+       if (dp->disksize) {
                printf("cd%d: cd present.[%d x %d byte records]\n",
                printf("cd%d: cd present.[%d x %d byte records]\n",
-                               unit,
-                               cd->params.disksize,
-                               cd->params.blksize);
-       }
-       else
-       {
+                   unit,
+                   cd->params.disksize,
+                   cd->params.blksize);
+       } else {
                printf("cd%d: drive empty\n", unit);
        }
        cd->flags |= CDINIT;
                printf("cd%d: drive empty\n", unit);
        }
        cd->flags |= CDINIT;
-       return;
+       return (1);
 }
 
 }
 
-/*******************************************************\
-*      open the device. Make sure the partition info   *
-* is a up-to-date as can be.                           *
-\*******************************************************/
+/*
+ * open the device. Make sure the partition info is a up-to-date as can be.
+ */
+errval 
 cdopen(dev)
 {
 cdopen(dev)
 {
-       int errcode = 0;
-       int unit, part;
+       errval  errcode = 0;
+       u_int32 unit, part;
        struct cd_parms cd_parms;
        struct cd_data *cd;
        struct cd_parms cd_parms;
        struct cd_data *cd;
+       struct scsi_link *sc_link;
+       u_int32 heldflags;
 
        unit = UNIT(dev);
        part = PARTITION(dev);
 
 
        unit = UNIT(dev);
        part = PARTITION(dev);
 
-#ifdef CDDEBUG
-       if(scsi_debug & (PRINTROUTINES | TRACEOPENS))
-               printf("cdopen: dev=0x%x (unit %d (of %d),partition %d)\n"
-                       ,dev,unit,cd_driver->size,part);
-#endif /*CDDEBUG*/
-       /*******************************************************\
-       * Check the unit is legal                               *
-       \*******************************************************/
-       if ( unit >= cd_driver->size )
-       {
-               return(ENXIO);
+       /*
+        * Check the unit is legal
+        */
+       if (unit >= cd_driver.size) {
+               return (ENXIO);
        }
        }
-       cd = cd_driver->cd_data[unit];
-       /*******************************************************\
-       * Make sure the device has been initialised             *
-       \*******************************************************/
+       cd = cd_driver.cd_data[unit];
+       /*
+        * Make sure the device has been initialised
+        */
        if ((cd == NULL) || (!(cd->flags & CDINIT)))
        if ((cd == NULL) || (!(cd->flags & CDINIT)))
-               return(ENXIO);
-
-       /*******************************************************\
-       * If it's been invalidated, and not everybody has       *
-       * closed it then forbid re-entry.                       *
-       *       (may have changed media)                        *
-       \*******************************************************/
-       if ((! (cd->flags & CDVALID))
-          && ( cd->openparts))
-               return(ENXIO);
-
-       /*******************************************************\
-       * Check that it is still responding and ok.             *
-       * if the media has been changed this will result in a   *
-       * "unit attention" error which the error code will      *
-       * disregard because the CDVALID flag is not yet set     *
-       \*******************************************************/
-       cd_test_ready(unit, SCSI_SILENT);
-
-       /*******************************************************\
-       * Next time actually take notice of error returns       *
-       \*******************************************************/
-       if (cd_test_ready(unit, SCSI_SILENT) != 0) {
-#ifdef CDDEBUG
-               if(scsi_debug & TRACEOPENS)
-                       printf("not ready\n");
-#endif /*CDDEBUG*/
-               return(ENXIO);
+               return (ENXIO);
+
+       sc_link = cd->sc_link;
+       SC_DEBUG(sc_link, SDEV_DB1,
+           ("cdopen: dev=0x%x (unit %d (of %d),partition %d)\n",
+               dev, unit, cd_driver.size, part));
+       /*
+        * If it's been invalidated, and not everybody has closed it then
+        * forbid re-entry.  (may have changed media)
+        */
+       if ((!(sc_link->flags & SDEV_MEDIA_LOADED))
+           && (cd->openparts))
+               return (ENXIO);
+
+       /*
+        * Check that it is still responding and ok.
+        * if the media has been changed this will result in a
+        * "unit attention" error which the error code will
+        * disregard because the SDEV_MEDIA_LOADED flag is not yet set
+        */
+       scsi_test_unit_ready(sc_link, SCSI_SILENT);
+
+       /*
+        * Next time actually take notice of error returns
+        */
+       sc_link->flags |= SDEV_OPEN;    /* unit attn errors are now errors */
+       if (scsi_test_unit_ready(sc_link, SCSI_SILENT) != 0) {
+               SC_DEBUG(sc_link, SDEV_DB3, ("not ready\n"));
+               errcode = ENXIO;
+               goto bad;
+       }
+       SC_DEBUG(sc_link, SDEV_DB3, ("Device present\n"));
+       /*
+        * In case it is a funny one, tell it to start
+        * not needed for some drives
+        */
+       scsi_start_unit(sc_link, CD_START);
+       scsi_prevent(sc_link, PR_PREVENT, SCSI_SILENT);
+       SC_DEBUG(sc_link, SDEV_DB3, ("started "));
+       /*
+        * Load the physical device parameters 
+        */
+       if (cd_get_parms(unit, 0)) {
+               errcode = ENXIO;
+               goto bad;
        }
        }
-#ifdef CDDEBUG
-       if(scsi_debug & TRACEOPENS)
-               printf("Device present\n");
-#endif /*CDDEBUG*/
-       /*******************************************************\
-       * In case it is a funny one, tell it to start           *
-       * not needed for some drives                            *
-       \*******************************************************/
-       cd_start_unit(unit,part,CD_START);
-        cd_prevent_unit(unit,PR_PREVENT,SCSI_SILENT);
-#ifdef CDDEBUG
-       if(scsi_debug & TRACEOPENS)
-               printf("started ");
-#endif /*CDDEBUG*/
-       /*******************************************************\
-       * Load the physical device parameters                   *
-       \*******************************************************/
-       cd_get_parms(unit, 0);
-#ifdef CDDEBUG
-       if(scsi_debug & TRACEOPENS)
-               printf("Params loaded ");
-#endif /*CDDEBUG*/
-       /*******************************************************\
-       * Load the partition info if not already loaded         *
-       \*******************************************************/
+       SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded "));
+       /*
+        * Make up some partition information
+        */
        cdgetdisklabel(unit);
        cdgetdisklabel(unit);
-#ifdef CDDEBUG
-       if(scsi_debug & TRACEOPENS)
-               printf("Disklabel fabricated ");
-#endif /*CDDEBUG*/
-       /*******************************************************\
-       * Check the partition is legal                          *
-       \*******************************************************/
-       if (( part >= cd->disklabel.d_npartitions ) 
-               && (part != RAW_PART))
-       {
-#ifdef CDDEBUG
-               if(scsi_debug & TRACEOPENS)
-                       printf("partition %d > %d\n",part
-                               ,cd->disklabel.d_npartitions);
-#endif /*CDDEBUG*/
-               cd_prevent_unit(unit,PR_ALLOW,SCSI_SILENT);
-               return(ENXIO);
+       SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel fabricated "));
+       /*
+        * Check the partition is legal
+        */
+       if ((part >= cd->disklabel.d_npartitions)
+           && (part != RAW_PART)) {
+               SC_DEBUG(sc_link, SDEV_DB3, ("partition %d > %d\n", part
+                       ,cd->disklabel.d_npartitions));
+               errcode = ENXIO;
+               goto bad;
        }
        }
-       /*******************************************************\
-       *  Check that the partition exists                      *
-       \*******************************************************/
-       if (( cd->disklabel.d_partitions[part].p_fstype != FS_UNUSED )
-               || (part == RAW_PART))
-       {
-               cd->partflags[part] |= CDOPEN;
-               cd->openparts |= (1 << part);
-#ifdef CDDEBUG
-               if(scsi_debug & TRACEOPENS)
-                       printf("open complete\n");
-#endif /*CDDEBUG*/
-               cd->flags |= CDVALID;
+       /*
+        *  Check that the partition exists
+        */
+       if ((cd->disklabel.d_partitions[part].p_fstype == FS_UNUSED)
+           && (part != RAW_PART)) {
+               SC_DEBUG(sc_link, SDEV_DB3, ("part %d type UNUSED\n", part));
+               errcode = ENXIO;
+               goto bad;
        }
        }
-       else
-       {
-#ifdef CDDEBUG
-               if(scsi_debug & TRACEOPENS)
-                       printf("part %d type UNUSED\n",part);
-#endif /*CDDEBUG*/
-               cd_prevent_unit(unit,PR_ALLOW,SCSI_SILENT);
-               return(ENXIO);
+       cd->partflags[part] |= CDOPEN;
+       cd->openparts |= (1 << part);
+       SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n"));
+       sc_link->flags |= SDEV_MEDIA_LOADED;
+       return (0);
+      bad:
+
+       /*
+        *  if we would have been the only open
+        * then leave things back as they were
+        */
+       if (!(cd->openparts)) {
+               sc_link->flags &= ~SDEV_OPEN;
+               scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
        }
        }
-       return(0);
+       return (errcode);
 }
 
 }
 
-/*******************************************************\
-* Get ownership of a scsi_xfer structure               *
-* If need be, sleep on it, until it comes free         *
-\*******************************************************/
-struct scsi_xfer *cd_get_xs(unit,flags)
-int    flags;
-int    unit;
+/*
+ * close the device.. only called if we are the LAST
+ * occurence of an open device
+ */
+errval 
+cdclose(dev)
+       dev_t   dev;
 {
 {
-       struct scsi_xfer *xs;
+       u_int8  unit, part;
+       u_int32 old_priority;
        struct cd_data *cd;
        struct cd_data *cd;
-       int     s;
-
-       cd = cd_driver->cd_data[unit];
-       if(flags & (SCSI_NOSLEEP |  SCSI_NOMASK))
-       {
-               if (xs = cd->free_xfer)
-               {
-                       cd->free_xfer = xs->next;
-                       xs->flags = 0;
-               }
-       }
-       else
-       {
-               s = SPLCD();
-               while (!(xs = cd->free_xfer))
-               {
-                       cd->xfer_block_wait++;  /* someone waiting! */
-                       sleep((caddr_t)&cd->free_xfer, PRIBIO+1);
-                       cd->xfer_block_wait--;
-               }
-               cd->free_xfer = xs->next;
-               splx(s);
-               xs->flags = 0;
-       }
-       return(xs);
-}
+       struct scsi_link *sc_link;
 
 
-/*******************************************************\
-* Free a scsi_xfer, wake processes waiting for it      *
-\*******************************************************/
-cd_free_xs(unit,xs,flags)
-struct scsi_xfer *xs;
-int    unit;
-int    flags;
-{
-       struct cd_data *cd;
-       int     s;
-       
-       cd = cd_driver->cd_data[unit];
-       if(flags & SCSI_NOMASK)
-       {
-               if (cd->xfer_block_wait)
-               {
-                       printf("cd%d: doing a wakeup from NOMASK mode\n", unit);
-                       wakeup((caddr_t)&cd->free_xfer);
-               }
-               xs->next = cd->free_xfer;
-               cd->free_xfer = xs;
-       }
-       else
-       {
-               s = SPLCD();
-               if (cd->xfer_block_wait)
-                       wakeup((caddr_t)&cd->free_xfer);
-               xs->next = cd->free_xfer;
-               cd->free_xfer = xs;
-               splx(s);
+       unit = UNIT(dev);
+       part = PARTITION(dev);
+       cd = cd_driver.cd_data[unit];
+       sc_link = cd->sc_link;
+       SC_DEBUG(sc_link, SDEV_DB2, ("cd%d: closing part %d\n", unit, part));
+       cd->partflags[part] &= ~CDOPEN;
+       cd->openparts &= ~(1 << part);
+
+       /*
+        * If we were the last open of the entire device, release it.
+        */
+       if (!(cd->openparts)) {
+               scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
+               cd->sc_link->flags &= ~SDEV_OPEN;
        }
        }
+       return (0);
 }
 
 }
 
-/*******************************************************\
-* trim the size of the transfer if needed,             *
-* called by physio                                     *
-* basically the smaller of our max and the scsi driver's*
-* minphys (note we have no max ourselves)              *
-\*******************************************************/
-/* Trim buffer length if buffer-size is bigger than page size */
-void   cdminphys(bp)
-struct buf     *bp;
+/*
+ * trim the size of the transfer if needed,
+ * called by physio
+ * basically the smaller of our max and the scsi driver's
+ * minphys (note we have no max ourselves)
+ *
+ * Trim buffer length if buffer-size is bigger than page size
+ */
+void 
+cdminphys(bp)
+       struct buf *bp;
 {
 {
-       (*(cd_driver->cd_data[UNIT(bp->b_dev)]->sc_sw->scsi_minphys))(bp);
+       (*(cd_driver.cd_data[UNIT(bp->b_dev)]->sc_link->adapter->scsi_minphys)) (bp);
 }
 
 }
 
-/*******************************************************\
-* Actually translate the requested transfer into       *
-* one the physical driver can understand               *
-* The transfer is described by a buf and will include  *
-* only one physical transfer.                          *
-\*******************************************************/
-
-int    cdstrategy(bp)
-struct buf     *bp;
+/*
+ * Actually translate the requested transfer into one the physical driver can
+ * understand.  The transfer is described by a buf and will include only one
+ * physical transfer.
+ */
+errval 
+cdstrategy(bp)
+       struct buf *bp;
 {
 {
-       struct  buf     *dp;
-       unsigned int opri;
-       struct cd_data *cd;
-       int     unit;
+       struct buf *dp;
+       u_int32 opri;
+       u_int32 unit = UNIT((bp->b_dev));
+       struct cd_data *cd = cd_driver.cd_data[unit];
 
        cdstrats++;
 
        cdstrats++;
-       unit = UNIT((bp->b_dev));
-       cd = cd_driver->cd_data[unit];
-#ifdef CDDEBUG
-       if(scsi_debug & PRINTROUTINES) printf("\ncdstrategy ");
-       if(scsi_debug & SHOWREQUESTS) printf("cd%d: %d bytes @ blk%d\n",
-                                       unit,bp->b_bcount,bp->b_blkno);
-#endif /*CDDEBUG*/
+       SC_DEBUG(cd->sc_link, SDEV_DB2, ("\ncdstrategy "));
+       SC_DEBUG(cd->sc_link, SDEV_DB1, ("cd%d: %d bytes @ blk%d\n",
+               unit, bp->b_bcount, bp->b_blkno));
        cdminphys(bp);
        cdminphys(bp);
-       /*******************************************************\
-       * If the device has been made invalid, error out        *
-       * maybe the media changed                               *
-       \*******************************************************/
-       if(!(cd->flags & CDVALID))
-       {
+       /*
+        * If the device has been made invalid, error out
+        * maybe the media changed
+        */
+       if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED)) {
                bp->b_error = EIO;
                goto bad;
        }
                bp->b_error = EIO;
                goto bad;
        }
-       /*******************************************************\
-       * can't ever write to a CD                              *
-       \*******************************************************/
+       /*
+        * can't ever write to a CD
+        */
        if ((bp->b_flags & B_READ) == 0) {
                bp->b_error = EROFS;
                goto bad;
        }
        if ((bp->b_flags & B_READ) == 0) {
                bp->b_error = EROFS;
                goto bad;
        }
-       /*******************************************************\
-       * If it's a null transfer, return immediatly            *
-       \*******************************************************/
+       /*
+        * If it's a null transfer, return immediatly
+        */
        if (bp->b_bcount == 0) {
                goto done;
        }
        if (bp->b_bcount == 0) {
                goto done;
        }
-
-       /*******************************************************\
-       * Decide which unit and partition we are talking about  *
-       \*******************************************************/
-       if(PARTITION(bp->b_dev) != RAW_PART)
-       {
-               if (!(cd->flags & CDHAVELABEL))
-               {
-                       bp->b_error = EIO;
-                       goto bad;
-               }
+       /*
+        * Decide which unit and partition we are talking about
+        */
+       if (PARTITION(bp->b_dev) != RAW_PART) {
                /*
                 * do bounds checking, adjust transfer. if error, process.
                 * if end of partition, just return
                 */
                /*
                 * do bounds checking, adjust transfer. if error, process.
                 * if end of partition, just return
                 */
-               if (bounds_check_with_label(bp,&cd->disklabel,1) <= 0)
+               if (bounds_check_with_label(bp, &cd->disklabel, 1) <= 0)
                        goto done;
                /* otherwise, process transfer request */
        }
                        goto done;
                /* otherwise, process transfer request */
        }
-
        opri = SPLCD();
        dp = &cd->buf_queue;
 
        opri = SPLCD();
        dp = &cd->buf_queue;
 
-       /*******************************************************\
-       * Place it in the queue of disk activities for this disk*
-       \*******************************************************/
+       /*
+        * Place it in the queue of disk activities for this disk
+        */
        disksort(dp, bp);
 
        disksort(dp, bp);
 
-       /*******************************************************\
-       * Tell the device to get going on the transfer if it's  *
-       * not doing anything, otherwise just wait for completion*
-       \*******************************************************/
+       /*
+        * Tell the device to get going on the transfer if it's
+        * not doing anything, otherwise just wait for completion
+        */
        cdstart(unit);
 
        splx(opri);
        return;
        cdstart(unit);
 
        splx(opri);
        return;
-bad:
+      bad:
        bp->b_flags |= B_ERROR;
        bp->b_flags |= B_ERROR;
-done:
+      done:
 
 
-       /*******************************************************\
-       * Correctly set the buf to indicate a completed xfer    *
-       \*******************************************************/
-       bp->b_resid = bp->b_bcount;
+       /*
+        * Correctly set the buf to indicate a completed xfer
+        */
+       bp->b_resid = bp->b_bcount;
        biodone(bp);
        biodone(bp);
-       return;
+       return (0);
 }
 
 }
 
-/***************************************************************\
-* cdstart 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  *
-* transfer in the buf. The transfer request will call cd_done  *
-* on completion, which will in turn call this routine again    *
-* so that the next queued transfer is performed.               *
-* The bufs are queued by the strategy routine (cdstrategy)     *
-*                                                              *
-* This routine is also called after other non-queued requests  *
-* have been made of the scsi driver, to ensure that the queue  *
-* continues to be drained.                                     *
-*                                                              *
-* must be called at the correct (highish) spl level            *
-\***************************************************************/
-/* cdstart() is called at SPLCD  from cdstrategy and cd_done*/
+/*
+ * cdstart 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
+ * transfer in the buf. The transfer request will call scsi_done
+ * on completion, which will in turn call this routine again
+ * so that the next queued transfer is performed.
+ * The bufs are queued by the strategy routine (cdstrategy)
+ *
+ * This routine is also called after other non-queued requests
+ * have been made of the scsi driver, to ensure that the queue
+ * continues to be drained.
+ *
+ * must be called at the correct (highish) spl level
+ * cdstart() is called at SPLCD  from cdstrategy and scsi_done
+ */
+void 
 cdstart(unit)
 cdstart(unit)
-int    unit;
+       u_int32 unit;
 {
 {
-       register struct buf     *bp = 0;
-       register struct buf     *dp;
-       struct  scsi_xfer       *xs;
-       struct  scsi_rw_big     cmd;
-       int                     blkno, nblk;
-       struct cd_data *cd;
-       struct partition *p ;
-
-#ifdef CDDEBUG
-       if(scsi_debug & PRINTROUTINES) printf("cdstart%d ",unit);
-#endif /*CDDEBUG*/
-       cd = cd_driver->cd_data[unit];
-       /*******************************************************\
-       * See if there is a buf to do and we are not already    *
-       * doing one                                             *
-       \*******************************************************/
-       if(!cd->free_xfer)
-       {
-               return;    /* none for us, unit already underway */
+       register struct buf *bp = 0;
+       register struct buf *dp;
+       struct scsi_rw_big cmd;
+       u_int32 blkno, nblk;
+       struct partition *p;
+       struct cd_data *cd = cd_driver.cd_data[unit];
+       struct scsi_link *sc_link = cd->sc_link;
+
+       SC_DEBUG(sc_link, SDEV_DB2, ("cdstart%d ", unit));
+       /*
+        * See if there is a buf to do and we are not already
+        * doing one
+        */
+       if (!sc_link->opennings) {
+               return;         /* no room for us, unit already underway */
        }
        }
-
-       if(cd->xfer_block_wait)    /* there is one, but a special waits */
-       {
-               return; /* give the special that's waiting a chance to run */
+       if (sc_link->flags & SDEV_WAITING) {    /* is room, but a special waits */
+               return;         /* give the special that's waiting a chance to run */
        }
        }
-
-
        dp = &cd->buf_queue;
        dp = &cd->buf_queue;
-       if ((bp = dp->b_actf) != NULL)  /* yes, an assign */
-       {
+       if ((bp = dp->b_actf) != NULL) {        /* yes, an assign */
                dp->b_actf = bp->av_forw;
                dp->b_actf = bp->av_forw;
-       }
-       else
-       { 
+       } else {
                return;
        }
                return;
        }
-
-       xs=cd_get_xs(unit,0);   /* ok we can grab it */
-       xs->flags = INUSE;    /* Now ours */
-       /***************************************************************\
-       * Should reject all queued entries if CDVALID is not true       *
-       \***************************************************************/
-       if(!(cd->flags & CDVALID))
-       {
-               goto bad; /* no I/O.. media changed or something */
+       /*
+        * Should reject all queued entries if SDEV_MEDIA_LOADED is not true.
+        */
+       if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
+               goto bad;       /* no I/O.. media changed or something */
        }
        }
-
-       /*******************************************************\
-       * We have a buf, now we should move the data into       *
-       * a scsi_xfer definition and try start it               *
-       *                                                       *
-       *  First, translate the block to absolute               *
-       * and put it in terms of the logical blocksize of the   *
-       * device..                                              *
-       * really a bit silly until we have real partitions, but.*
-       \*******************************************************/
-       blkno = bp->b_blkno / (cd->params.blksize/512);
-       if(PARTITION(bp->b_dev) != RAW_PART)
-       {
+       /*
+        * We have a buf, now we should make a command 
+        *
+        * First, translate the block to absolute and put it in terms of the
+        * logical blocksize of the device.  Really a bit silly until we have
+        * real partitions, but.
+        */
+       blkno = bp->b_blkno / (cd->params.blksize / 512);
+       if (PARTITION(bp->b_dev) != RAW_PART) {
                p = cd->disklabel.d_partitions + PARTITION(bp->b_dev);
                blkno += p->p_offset;
        }
        nblk = (bp->b_bcount + (cd->params.blksize - 1)) / (cd->params.blksize);
                p = cd->disklabel.d_partitions + PARTITION(bp->b_dev);
                blkno += p->p_offset;
        }
        nblk = (bp->b_bcount + (cd->params.blksize - 1)) / (cd->params.blksize);
-       /* what if something asks for 512 bytes not on a 2k boundary? *//*XXX*/
+       /* what if something asks for 512 bytes not on a 2k boundary? *//*XXX */
 
 
-       /*******************************************************\
-       *  Fill out the scsi command                            *
-       \*******************************************************/
+       /*
+        *  Fill out the scsi command
+        */
        bzero(&cmd, sizeof(cmd));
        bzero(&cmd, sizeof(cmd));
-       cmd.op_code     =       READ_BIG;
-       cmd.addr_3      =       (blkno & 0xff000000) >> 24;
-       cmd.addr_2      =       (blkno & 0xff0000) >> 16;
-       cmd.addr_1      =       (blkno & 0xff00) >> 8;
-       cmd.addr_0      =       blkno & 0xff;
-       cmd.length2     =       (nblk & 0xff00) >> 8;
-       cmd.length1     =       (nblk & 0xff);
-       /*******************************************************\
-       * Fill out the scsi_xfer structure                      *
-       *       Note: we cannot sleep as we may be an interrupt *
-       \*******************************************************/
-       xs->flags       |=      SCSI_NOSLEEP;
-       xs->adapter     =       cd->ctlr;
-       xs->targ        =       cd->targ;
-       xs->lu          =       cd->lu;
-       xs->retries     =       CD_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   =       cd_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 ( (*(cd->sc_sw->scsi_cmd))(xs) != SUCCESSFULLY_QUEUED)
-       {
-               printf("cd%d: oops not queued",unit);
-               goto bad;
-       }       
-       cdqueues++;
-       return;
-bad:   xs->error = XS_DRIVER_STUFFUP;
-       cd_done(unit,xs);
-}
-
-/*******************************************************\
-* This routine is called by the scsi interrupt when    *
-* the transfer is complete. (or failed)                        *
-\*******************************************************/
-int    cd_done(unit,xs)
-int    unit;
-struct scsi_xfer       *xs;
-{
-       struct  buf             *bp;
-       int     retval;
-       struct cd_data *cd = cd_driver->cd_data[unit];
-
-#ifdef CDDEBUG
-       if(scsi_debug & PRINTROUTINES) printf("cd_done%d ",unit);
-#endif /*CDDEBUG*/
-#ifdef PARANOIA
-       if (! (xs->flags & INUSE))      /* paranoia always pays off */
-               panic("scsi_xfer not in use!");
-#endif /*PARANOIA*/
-       if(!(bp = xs->bp))
-       {
-               wakeup(xs);
-               return 0;
-       }
-       switch(xs->error)
-       {
-       case    XS_NOERROR:
-               bp->b_error = 0;
-               bp->b_resid = 0;
-               break;
-
-       case    XS_SENSE:
-               retval = (cd_interpret_sense(unit,xs));
-               if(retval)
-               {
-                       bp->b_flags |= B_ERROR;
-                       bp->b_error = retval;
-               }
-               break;
-
-       case    XS_TIMEOUT:
-               printf("cd%d timeout\n",unit);
-
-       case    XS_BUSY:        
-               /***********************************\
-               * Just resubmit it straight back to *
-               * the SCSI driver to try it again   *
-               \***********************************/
-               if(xs->retries--)
-               {
-                       xs->error = XS_NOERROR;
-                       xs->flags &= ~ITSDONE;
-                       if ((*(cd->sc_sw->scsi_cmd))(xs)
-                               == SUCCESSFULLY_QUEUED)
-                       {       /* shhh! don't wake the job, ok? */
-                               /* don't tell cdstart either, */
-                               return 0;
-                       }
-                       /* xs->error is set by the scsi driver */
-               } /* Fall through */
-
-       case    XS_DRIVER_STUFFUP:
-               bp->b_flags |= B_ERROR;
+       cmd.op_code = READ_BIG;
+       cmd.addr_3 = (blkno & 0xff000000) >> 24;
+       cmd.addr_2 = (blkno & 0xff0000) >> 16;
+       cmd.addr_1 = (blkno & 0xff00) >> 8;
+       cmd.addr_0 = blkno & 0xff;
+       cmd.length2 = (nblk & 0xff00) >> 8;
+       cmd.length1 = (nblk & 0xff);
+
+       /*
+        * Call the routine that chats with the adapter.
+        * Note: we cannot sleep as we may be an interrupt
+        */
+       if (scsi_scsi_cmd(sc_link,
+               (struct scsi_generic *) &cmd,
+               sizeof(cmd),
+               (u_char *) bp->b_un.b_addr,
+               bp->b_bcount,
+               CDRETRIES,
+               30000,
+               bp,
+               SCSI_NOSLEEP | ((bp->b_flags & B_READ) ?
+                   SCSI_DATA_IN : SCSI_DATA_OUT))
+           != SUCCESSFULLY_QUEUED) {
+             bad:
+               printf("cd%d: oops not queued", unit);
                bp->b_error = EIO;
                bp->b_error = EIO;
-               break;
-       default:
-               printf("cd%d: unknown error category from scsi driver\n"
-                       ,unit);
-       }       
-       biodone(bp);
-       cd_free_xs(unit,xs,0);
-       cdstart(unit);  /* If there's anything waiting.. do it */
-       return 0;
+               bp->b_flags |= B_ERROR;
+               biodone(bp);
+               return;
+       }
+       cdqueues++;
 }
 
 }
 
-/*******************************************************\
-* 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
+ */
+errval 
 cdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
 {
 cdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
 {
-       int error = 0;
-       unsigned int opri;
-       unsigned char unit, part;
+       errval  error = 0;
+       u_int32 opri;
+       u_int8  unit, part;
        register struct cd_data *cd;
 
        register struct cd_data *cd;
 
-
-       /*******************************************************\
-       * Find the device that the user is talking about        *
-       \*******************************************************/
+       /*
+        * Find the device that the user is talking about
+        */
        unit = UNIT(dev);
        part = PARTITION(dev);
        unit = UNIT(dev);
        part = PARTITION(dev);
-       cd = cd_driver->cd_data[unit];
-#ifdef CDDEBUG
-       if(scsi_debug & PRINTROUTINES) printf("cdioctl%d ",unit);
-#endif /*CDDEBUG*/
-
-       /*******************************************************\
-       * If the device is not valid.. abandon ship             *
-       \*******************************************************/
-       if (!(cd_driver->cd_data[unit]->flags & CDVALID))
-               return(EIO);
-       switch(cmd)
-       {
+       cd = cd_driver.cd_data[unit];
+       SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdioctl 0x%x ", cmd));
+
+       /*
+        * If the device is not valid.. abandon ship
+        */
+       if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED))
+               return (EIO);
+       switch (cmd) {
 
        case DIOCSBAD:
 
        case DIOCSBAD:
-                        error = EINVAL;
+               error = EINVAL;
                break;
 
        case DIOCGDINFO:
                break;
 
        case DIOCGDINFO:
-               *(struct disklabel *)addr = cd->disklabel;
+               *(struct disklabel *) addr = cd->disklabel;
                break;
 
                break;
 
-        case DIOCGPART:
-                ((struct partinfo *)addr)->disklab = &cd->disklabel;
-                ((struct partinfo *)addr)->part =
-                    &cd->disklabel.d_partitions[PARTITION(dev)];
-                break;
-
-        case DIOCWDINFO:
-        case DIOCSDINFO:
-                if ((flag & FWRITE) == 0)
-                        error = EBADF;
-                else
-                        error = setdisklabel(&cd->disklabel,
-                                       (struct disklabel *)addr,
-                         /*(cd->flags & DKFL_BSDLABEL) ? cd->openparts : */0,
-                               0);
-                if (error == 0) {
-                       cd->flags |= CDHAVELABEL;
-               }
-                break;
+       case DIOCGPART:
+               ((struct partinfo *) addr)->disklab = &cd->disklabel;
+               ((struct partinfo *) addr)->part =
+                   &cd->disklabel.d_partitions[PARTITION(dev)];
+               break;
+
+               /*
+                * a bit silly, but someone might want to test something on a 
+                * section of cdrom.
+                */
+       case DIOCWDINFO:
+       case DIOCSDINFO:
+               if ((flag & FWRITE) == 0)
+                       error = EBADF;
+               else
+                       error = setdisklabel(&cd->disklabel,
+                           (struct disklabel *) addr,
+                           0,
+                           0);
+               if (error == 0)
+                       break;
 
 
-        case DIOCWLABEL:
-                error = EBADF;
-                break;
+       case DIOCWLABEL:
+               error = EBADF;
+               break;
 
        case CDIOCPLAYTRACKS:
                {
 
        case CDIOCPLAYTRACKS:
                {
-                       struct  ioc_play_track *args
-                                       = (struct  ioc_play_track *)addr;
-                       struct  cd_mode_data data;
-                       if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
+                       struct ioc_play_track *args
+                       = (struct ioc_play_track *) addr;
+                       struct cd_mode_data data;
+                       if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
                                break;
                        data.page.audio.flags &= ~CD_PA_SOTC;
                        data.page.audio.flags |= CD_PA_IMMED;
                                break;
                        data.page.audio.flags &= ~CD_PA_SOTC;
                        data.page.audio.flags |= CD_PA_IMMED;
-                       if(error = cd_set_mode(unit,&data))
+                       if (error = cd_set_mode(unit, &data))
                                break;
                                break;
-                       return(cd_play_tracks(unit
-                                               ,args->start_track
-                                               ,args->start_index
-                                               ,args->end_track
-                                               ,args->end_index
-                                               ));
+                       return (cd_play_tracks(unit
+                               ,args->start_track
+                               ,args->start_index
+                               ,args->end_track
+                               ,args->end_index
+                           ));
                }
                break;
        case CDIOCPLAYMSF:
                {
                }
                break;
        case CDIOCPLAYMSF:
                {
-                       struct  ioc_play_msf *args
-                                       = (struct  ioc_play_msf *)addr;
-                       struct  cd_mode_data data;
-                       if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
+                       struct ioc_play_msf *args
+                       = (struct ioc_play_msf *) addr;
+                       struct cd_mode_data data;
+                       if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
                                break;
                        data.page.audio.flags &= ~CD_PA_SOTC;
                        data.page.audio.flags |= CD_PA_IMMED;
                                break;
                        data.page.audio.flags &= ~CD_PA_SOTC;
                        data.page.audio.flags |= CD_PA_IMMED;
-                       if(error = cd_set_mode(unit,&data))
+                       if (error = cd_set_mode(unit, &data))
                                break;
                                break;
-                       return(cd_play_msf(unit
-                                               ,args->start_m
-                                               ,args->start_s
-                                               ,args->start_f
-                                               ,args->end_m
-                                               ,args->end_s
-                                               ,args->end_f
-                                               ));
+                       return (cd_play_msf(unit
+                               ,args->start_m
+                               ,args->start_s
+                               ,args->start_f
+                               ,args->end_m
+                               ,args->end_s
+                               ,args->end_f
+                           ));
                }
                break;
        case CDIOCPLAYBLOCKS:
                {
                }
                break;
        case CDIOCPLAYBLOCKS:
                {
-                       struct  ioc_play_blocks *args
-                                       = (struct  ioc_play_blocks *)addr;
-                       struct  cd_mode_data data;
-                       if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
+                       struct ioc_play_blocks *args
+                       = (struct ioc_play_blocks *) addr;
+                       struct cd_mode_data data;
+                       if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
                                break;
                        data.page.audio.flags &= ~CD_PA_SOTC;
                        data.page.audio.flags |= CD_PA_IMMED;
                                break;
                        data.page.audio.flags &= ~CD_PA_SOTC;
                        data.page.audio.flags |= CD_PA_IMMED;
-                       if(error = cd_set_mode(unit,&data))
+                       if (error = cd_set_mode(unit, &data))
                                break;
                                break;
-                       return(cd_play(unit,args->blk,args->len));
-
+                       return (cd_play(unit, args->blk, args->len));
 
                }
                break;
        case CDIOCREADSUBCHANNEL:
                {
                        struct ioc_read_subchannel *args
 
                }
                break;
        case CDIOCREADSUBCHANNEL:
                {
                        struct ioc_read_subchannel *args
-                                       = (struct ioc_read_subchannel *)addr;
+                       = (struct ioc_read_subchannel *) addr;
                        struct cd_sub_channel_info data;
                        struct cd_sub_channel_info data;
-                       int len=args->data_len;
-                       if(len>sizeof(data)||
-                          len<sizeof(struct cd_sub_channel_header)) {
-                               error=EINVAL;
+                       u_int32 len = args->data_len;
+                       if (len > sizeof(data) ||
+                           len < sizeof(struct cd_sub_channel_header)) {
+                               error = EINVAL;
                                break;
                        }
                                break;
                        }
-                       if(error = cd_read_subchannel(unit,args->address_format,
-                                       args->data_format,args->track,&data,len)) {
+                       if (error = cd_read_subchannel(unit, args->address_format,
+                               args->data_format, args->track, &data, len)) {
                                break;
                        }
                                break;
                        }
-                       len=MIN(len,((data.header.data_len[0]<<8)+data.header.data_len[1]+
-                                       sizeof(struct cd_sub_channel_header)));
-                       if(copyout(&data,args->data,len)!=0) {
-                               error=EFAULT;
+                       len = MIN(len, ((data.header.data_len[0] << 8) + data.header.data_len[1] +
+                               sizeof(struct cd_sub_channel_header)));
+                       if (copyout(&data, args->data, len) != 0) {
+                               error = EFAULT;
                        }
                }
                break;
        case CDIOREADTOCHEADER:
                {
                        struct ioc_toc_header th;
                        }
                }
                break;
        case CDIOREADTOCHEADER:
                {
                        struct ioc_toc_header th;
-                       if( error = cd_read_toc(unit,0,0,&th,sizeof(th)))
+                       if (error = cd_read_toc(unit, 0, 0, &th, sizeof(th)))
                                break;
                                break;
-                       th.len=(th.len&0xff)<<8+((th.len>>8)&0xff);
-                       bcopy(&th,addr,sizeof(th));
+                       th.len = (th.len & 0xff) << 8 + ((th.len >> 8) & 0xff);
+                       bcopy(&th, addr, sizeof(th));
                }
                break;
        case CDIOREADTOCENTRYS:
                {
                }
                break;
        case CDIOREADTOCENTRYS:
                {
-                       struct ioc_read_toc_entry *te=  
-                                       (struct ioc_read_toc_entry *)addr;
+                       struct ioc_read_toc_entry *te =
+                       (struct ioc_read_toc_entry *) addr;
                        struct cd_toc_entry data[65];
                        struct ioc_toc_header *th;
                        struct cd_toc_entry data[65];
                        struct ioc_toc_header *th;
-                       int len=te->data_len;
-                       th=(struct ioc_toc_header *)data;
-
-                        if(len>sizeof(data) || len<sizeof(struct cd_toc_entry)) {
-                                error=EINVAL;
-                                break;
-                        }
-                       if(error = cd_read_toc(unit,te->address_format,
-                                                   te->starting_track,
-                                                   data,
-                                                   len))
+                       u_int32 len = te->data_len;
+                       th = (struct ioc_toc_header *) data;
+
+                       if (len > sizeof(data) || len < sizeof(struct cd_toc_entry)) {
+                               error = EINVAL;
                                break;
                                break;
-                       len=MIN(len,((((th->len&0xff)<<8)+((th->len>>8)))+
-                                                               sizeof(*th)));
-                       if(copyout(th,te->data,len)!=0) {
-                               error=EFAULT;
                        }
                        }
-                       
+                       if (error = cd_read_toc(unit, te->address_format,
+                               te->starting_track,
+                               data,
+                               len))
+                               break;
+                       len = MIN(len, ((((th->len & 0xff) << 8) + ((th->len >> 8))) +
+                               sizeof(*th)));
+                       if (copyout(th, te->data, len) != 0) {
+                               error = EFAULT;
+                       }
                }
                break;
        case CDIOCSETPATCH:
                {
                }
                break;
        case CDIOCSETPATCH:
                {
-                       struct ioc_patch *arg = (struct ioc_patch *)addr;
-                       struct  cd_mode_data data;
-                       if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
+                       struct ioc_patch *arg = (struct ioc_patch *) addr;
+                       struct cd_mode_data data;
+                       if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
                                break;
                        data.page.audio.port[LEFT_PORT].channels = arg->patch[0];
                        data.page.audio.port[RIGHT_PORT].channels = arg->patch[1];
                        data.page.audio.port[2].channels = arg->patch[2];
                        data.page.audio.port[3].channels = arg->patch[3];
                                break;
                        data.page.audio.port[LEFT_PORT].channels = arg->patch[0];
                        data.page.audio.port[RIGHT_PORT].channels = arg->patch[1];
                        data.page.audio.port[2].channels = arg->patch[2];
                        data.page.audio.port[3].channels = arg->patch[3];
-                       if(error = cd_set_mode(unit,&data))
-                               break;
+                       if (error = cd_set_mode(unit, &data))
+                               break; /* eh? */
                }
                break;
        case CDIOCGETVOL:
                {
                }
                break;
        case CDIOCGETVOL:
                {
-                       struct ioc_vol *arg = (struct ioc_vol *)addr;
-                       struct  cd_mode_data data;
-                       if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
+                       struct ioc_vol *arg = (struct ioc_vol *) addr;
+                       struct cd_mode_data data;
+                       if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
                                break;
                        arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
                        arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
                                break;
                        arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
                        arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
@@ -941,148 +740,146 @@ cdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
                break;
        case CDIOCSETVOL:
                {
                break;
        case CDIOCSETVOL:
                {
-                       struct ioc_vol *arg = (struct ioc_vol *)addr;
-                       struct  cd_mode_data data;
-                       if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
+                       struct ioc_vol *arg = (struct ioc_vol *) addr;
+                       struct cd_mode_data data;
+                       if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
                                break;
                        data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
                        data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
                        data.page.audio.port[2].volume = arg->vol[2];
                        data.page.audio.port[3].volume = arg->vol[3];
                                break;
                        data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
                        data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
                        data.page.audio.port[2].volume = arg->vol[2];
                        data.page.audio.port[3].volume = arg->vol[3];
-                       if(error = cd_set_mode(unit,&data))
+                       if (error = cd_set_mode(unit, &data))
                                break;
                }
                break;
        case CDIOCSETMONO:
                {
                                break;
                }
                break;
        case CDIOCSETMONO:
                {
-                       struct ioc_vol *arg = (struct ioc_vol *)addr;
-                       struct  cd_mode_data data;
-                       if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
+                       struct ioc_vol *arg = (struct ioc_vol *) addr;
+                       struct cd_mode_data data;
+                       if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
                                break;
                                break;
-                       data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL|RIGHT_CHANNEL|4|8;
-                       data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL|RIGHT_CHANNEL;
+                       data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL | RIGHT_CHANNEL | 4 | 8;
+                       data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL | RIGHT_CHANNEL;
                        data.page.audio.port[2].channels = 0;
                        data.page.audio.port[3].channels = 0;
                        data.page.audio.port[2].channels = 0;
                        data.page.audio.port[3].channels = 0;
-                       if(error = cd_set_mode(unit,&data))
+                       if (error = cd_set_mode(unit, &data))
                                break;
                }
                break;
        case CDIOCSETSTERIO:
                {
                                break;
                }
                break;
        case CDIOCSETSTERIO:
                {
-                       struct ioc_vol *arg = (struct ioc_vol *)addr;
-                       struct  cd_mode_data data;
-                       if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
+                       struct ioc_vol *arg = (struct ioc_vol *) addr;
+                       struct cd_mode_data data;
+                       if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
                                break;
                        data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
                        data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
                        data.page.audio.port[2].channels = 0;
                        data.page.audio.port[3].channels = 0;
                                break;
                        data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
                        data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
                        data.page.audio.port[2].channels = 0;
                        data.page.audio.port[3].channels = 0;
-                       if(error = cd_set_mode(unit,&data))
+                       if (error = cd_set_mode(unit, &data))
                                break;
                }
                break;
        case CDIOCSETMUTE:
                {
                                break;
                }
                break;
        case CDIOCSETMUTE:
                {
-                       struct ioc_vol *arg = (struct ioc_vol *)addr;
-                       struct  cd_mode_data data;
-                       if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
+                       struct ioc_vol *arg = (struct ioc_vol *) addr;
+                       struct cd_mode_data data;
+                       if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
                                break;
                        data.page.audio.port[LEFT_PORT].channels = 0;
                        data.page.audio.port[RIGHT_PORT].channels = 0;
                        data.page.audio.port[2].channels = 0;
                        data.page.audio.port[3].channels = 0;
                                break;
                        data.page.audio.port[LEFT_PORT].channels = 0;
                        data.page.audio.port[RIGHT_PORT].channels = 0;
                        data.page.audio.port[2].channels = 0;
                        data.page.audio.port[3].channels = 0;
-                       if(error = cd_set_mode(unit,&data))
+                       if (error = cd_set_mode(unit, &data))
                                break;
                }
                break;
        case CDIOCSETLEFT:
                {
                                break;
                }
                break;
        case CDIOCSETLEFT:
                {
-                       struct ioc_vol *arg = (struct ioc_vol *)addr;
-                       struct  cd_mode_data data;
-                       if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
+                       struct ioc_vol *arg = (struct ioc_vol *) addr;
+                       struct cd_mode_data data;
+                       if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
                                break;
                        data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
                        data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL;
                        data.page.audio.port[2].channels = 0;
                        data.page.audio.port[3].channels = 0;
                                break;
                        data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
                        data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL;
                        data.page.audio.port[2].channels = 0;
                        data.page.audio.port[3].channels = 0;
-                       if(error = cd_set_mode(unit,&data))
+                       if (error = cd_set_mode(unit, &data))
                                break;
                }
                break;
        case CDIOCSETRIGHT:
                {
                                break;
                }
                break;
        case CDIOCSETRIGHT:
                {
-                       struct ioc_vol *arg = (struct ioc_vol *)addr;
-                       struct  cd_mode_data data;
-                       if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
+                       struct ioc_vol *arg = (struct ioc_vol *) addr;
+                       struct cd_mode_data data;
+                       if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
                                break;
                        data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
                        data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
                        data.page.audio.port[2].channels = 0;
                        data.page.audio.port[3].channels = 0;
                                break;
                        data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
                        data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
                        data.page.audio.port[2].channels = 0;
                        data.page.audio.port[3].channels = 0;
-                       if(error = cd_set_mode(unit,&data))
+                       if (error = cd_set_mode(unit, &data))
                                break;
                }
                break;
        case CDIOCRESUME:
                                break;
                }
                break;
        case CDIOCRESUME:
-               error = cd_pause(unit,1);
+               error = cd_pause(unit, 1);
                break;
        case CDIOCPAUSE:
                break;
        case CDIOCPAUSE:
-               error = cd_pause(unit,0);
+               error = cd_pause(unit, 0);
                break;
        case CDIOCSTART:
                break;
        case CDIOCSTART:
-               error = cd_start_unit(unit,part,CD_START);
+               error = scsi_start_unit(cd->sc_link, 0);
                break;
        case CDIOCSTOP:
                break;
        case CDIOCSTOP:
-               error = cd_start_unit(unit,part,CD_STOP);
+               error = scsi_start_unit(cd->sc_link, 0);
                break;
        case CDIOCEJECT:
                break;
        case CDIOCEJECT:
-               error = cd_start_unit(unit,part,CD_EJECT);
+               error = scsi_start_unit(cd->sc_link, 0);
                break;
        case CDIOCSETDEBUG:
                break;
        case CDIOCSETDEBUG:
-               scsi_debug = 0xfff; cd_debug = 0xfff;
+               cd->sc_link->flags |= (SDEV_DB1 | SDEV_DB2);
                break;
        case CDIOCCLRDEBUG:
                break;
        case CDIOCCLRDEBUG:
-               scsi_debug = 0; cd_debug = 0;
+               cd->sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
                break;
        case CDIOCRESET:
                break;
        case CDIOCRESET:
-               return(cd_reset(unit));
+               return (cd_reset(unit));
                break;
        default:
                break;
        default:
-               error = ENOTTY;
+               if(part == RAW_PART)
+                       error = scsi_do_ioctl(cd->sc_link,cmd,addr,flag);
+               else
+                       error = ENOTTY;
                break;
        }
        return (error);
 }
 
                break;
        }
        return (error);
 }
 
-
-/*******************************************************\
-* Load the label information on the named device       *
-*                                                      *
-* EVENTUALLY take information about different          *
-* data tracks from the TOC and put it in the disklabel *
-\*******************************************************/
-int cdgetdisklabel(unit)
-unsigned char  unit;
+/*
+ * Load the label information on the named device
+ * Actually fabricate a disklabel
+ * 
+ * EVENTUALLY take information about different
+ * data tracks from the TOC and put it in the disklabel
+ */
+errval 
+cdgetdisklabel(unit)
+       u_int8  unit;
 {
 {
-       /*unsigned int n, m;*/
-       char *errstring;
-       struct dos_partition *dos_partition_p;
+       /*unsigned int n, m; */
+       char   *errstring;
        struct cd_data *cd;
 
        struct cd_data *cd;
 
-       cd = cd_driver->cd_data[unit];
-       /*******************************************************\
-       * If the info is already loaded, use it                 *
-       \*******************************************************/
-       if(cd->flags & CDHAVELABEL) return;
-
-       bzero(&cd->disklabel,sizeof(struct disklabel));
-       /*******************************************************\
-       * make partition 3 the whole disk in case of failure    *
-       *   then get pdinfo                                     *
-       \*******************************************************/
-       strncpy(cd->disklabel.d_typename,"scsi cd_rom",16);
-       strncpy(cd->disklabel.d_packname,"ficticious",16);
-       cd->disklabel.d_secsize = cd->params.blksize; /* as long as it's not 0 */
+       cd = cd_driver.cd_data[unit];
+
+       bzero(&cd->disklabel, sizeof(struct disklabel));
+       /*
+        * make partition 0 the whole disk
+        */
+       strncpy(cd->disklabel.d_typename, "scsi cd_rom", 16);
+       strncpy(cd->disklabel.d_packname, "ficticious", 16);
+       cd->disklabel.d_secsize = cd->params.blksize;   /* as long as it's not 0 */
        cd->disklabel.d_nsectors = 100;
        cd->disklabel.d_ntracks = 1;
        cd->disklabel.d_ncylinders = (cd->params.disksize / 100) + 1;
        cd->disklabel.d_nsectors = 100;
        cd->disklabel.d_ntracks = 1;
        cd->disklabel.d_ncylinders = (cd->params.disksize / 100) + 1;
@@ -1092,129 +889,118 @@ unsigned char  unit;
        cd->disklabel.d_interleave = 1;
        cd->disklabel.d_flags = D_REMOVABLE;
 
        cd->disklabel.d_interleave = 1;
        cd->disklabel.d_flags = D_REMOVABLE;
 
+       /*
+        * remember that comparisons with the partition are done
+        * assuming the blocks are 512 bytes so fudge it.
+        */
        cd->disklabel.d_npartitions = 1;
        cd->disklabel.d_npartitions = 1;
-        cd->disklabel.d_partitions[0].p_offset = 0;
-        cd->disklabel.d_partitions[0].p_size 
-               = cd->params.disksize * (cd->params.blksize / 512);
-        cd->disklabel.d_partitions[0].p_fstype = 9;
+       cd->disklabel.d_partitions[0].p_offset = 0;
+       cd->disklabel.d_partitions[0].p_size
+           = cd->params.disksize * (cd->params.blksize / 512);
+       cd->disklabel.d_partitions[0].p_fstype = 9;
 
        cd->disklabel.d_magic = DISKMAGIC;
        cd->disklabel.d_magic2 = DISKMAGIC;
        cd->disklabel.d_checksum = dkcksum(&(cd->disklabel));
 
 
        cd->disklabel.d_magic = DISKMAGIC;
        cd->disklabel.d_magic2 = DISKMAGIC;
        cd->disklabel.d_checksum = dkcksum(&(cd->disklabel));
 
-       /*******************************************************\
-       * Signal to other users and routines that we now have a *
-       * disklabel that represents the media (maybe)           *
-       \*******************************************************/
-       cd->flags |= CDHAVELABEL;
-       return(ESUCCESS);
-}
-
-/*******************************************************\
-* Get scsi driver to send a "are you ready" command    *
-\*******************************************************/
-cd_test_ready(unit,flags)
-int    unit,flags;
-{
-       struct  scsi_test_unit_ready scsi_cmd;
-
-       bzero(&scsi_cmd, sizeof(scsi_cmd));
-       scsi_cmd.op_code = TEST_UNIT_READY;
-
-       return (cd_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       0,
-                       0,
-                       100000,
-                       NULL,
-                       flags));
+       /*
+        * Signal to other users and routines that we now have a
+        * disklabel that represents the media (maybe)
+        */
+       return (ESUCCESS);
 }
 
 }
 
-
-/*******************************************************\
-* Find out form the device what it's capacity is       *
-\*******************************************************/
+/*
+ * Find out from the device what it's capacity is
+ */
+u_int32 
 cd_size(unit, flags)
 {
 cd_size(unit, flags)
 {
-       struct  scsi_read_cd_cap_data   rdcap;
-       struct  scsi_read_cd_capacity   scsi_cmd;
-       int size;
-       int     blksize;
-
-       /*******************************************************\
-       * make up a scsi command and ask the scsi driver to do  *
-       * it for you.                                           *
-       \*******************************************************/
+       struct scsi_read_cd_cap_data rdcap;
+       struct scsi_read_cd_capacity scsi_cmd;
+       u_int32 size;
+       u_int32 blksize;
+       struct cd_data *cd = cd_driver.cd_data[unit];
+
+       /*
+        * make up a scsi command and ask the scsi driver to do
+        * it for you.
+        */
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = READ_CD_CAPACITY;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = READ_CD_CAPACITY;
 
-       /*******************************************************\
-       * If the command works, interpret the result as a 4 byte*
-       * number of blocks                                      *
-       \*******************************************************/
-       if (cd_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       &rdcap,
-                       sizeof(rdcap),  
-                       2000,
-                       NULL,
-                       flags) != 0)
-       {
+       /*
+        * If the command works, interpret the result as a 4 byte
+        * number of blocks and a blocksize
+        */
+       if (scsi_scsi_cmd(cd->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               (u_char *) & rdcap,
+               sizeof(rdcap),
+               CDRETRIES,
+               20000,          /* might be a disk-changer */
+               NULL,
+               SCSI_DATA_IN | flags) != 0) {
                printf("cd%d: could not get size\n", unit);
                printf("cd%d: could not get size\n", unit);
-               return(0);
+               return (0);
        } else {
        } else {
-               size = rdcap.addr_0 + 1 ;
+               size = rdcap.addr_0 + 1;
                size += rdcap.addr_1 << 8;
                size += rdcap.addr_2 << 16;
                size += rdcap.addr_3 << 24;
                size += rdcap.addr_1 << 8;
                size += rdcap.addr_2 << 16;
                size += rdcap.addr_3 << 24;
-               blksize  = rdcap.length_0 ;
+               blksize = rdcap.length_0;
                blksize += rdcap.length_1 << 8;
                blksize += rdcap.length_2 << 16;
                blksize += rdcap.length_3 << 24;
        }
                blksize += rdcap.length_1 << 8;
                blksize += rdcap.length_2 << 16;
                blksize += rdcap.length_3 << 24;
        }
-#ifdef CDDEBUG
-       if(cd_debug)printf("cd%d: %d %d byte blocks\n",unit,size,blksize);
-#endif /*CDDEBUG*/
-       cd_driver->cd_data[unit]->params.disksize = size;
-       cd_driver->cd_data[unit]->params.blksize = blksize;
-       return(size);
+       if (blksize < 512)
+               blksize = 2048; /* some drives lie ! */
+       if (size < 100)
+               size = 400000;  /* ditto */
+       SC_DEBUG(cd->sc_link, SDEV_DB3, ("cd%d: %d %d byte blocks\n"
+               ,unit, size, blksize));
+       cd->params.disksize = size;
+       cd->params.blksize = blksize;
+       return (size);
 }
 }
-       
-
-/*******************************************************\
-* Get the requested page into the buffer given         *
-\*******************************************************/
-cd_get_mode(unit,data,page)
-int    unit;
-struct cd_mode_data *data;
-int    page;
+
+/*
+ * Get the requested page into the buffer given
+ */
+errval 
+cd_get_mode(unit, data, page)
+       u_int32 unit;
+       struct cd_mode_data *data;
+       u_int32 page;
 {
        struct scsi_mode_sense scsi_cmd;
 {
        struct scsi_mode_sense scsi_cmd;
-       int     retval;
+       errval  retval;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
-       bzero(data,sizeof(*data));
+       bzero(data, sizeof(*data));
        scsi_cmd.op_code = MODE_SENSE;
        scsi_cmd.page = page;
        scsi_cmd.length = sizeof(*data) & 0xff;
        scsi_cmd.op_code = MODE_SENSE;
        scsi_cmd.page = page;
        scsi_cmd.length = sizeof(*data) & 0xff;
-       retval = cd_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       data,
-                       sizeof(*data),
-                       20000,  /* should be immed */
-                       NULL,
-                       0);
+       retval = scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+           (struct scsi_generic *) &scsi_cmd,
+           sizeof(scsi_cmd),
+           (u_char *) data,
+           sizeof(*data),
+           CDRETRIES,
+           20000,              /* should be immed */
+           NULL,
+           SCSI_DATA_IN);
        return (retval);
 }
        return (retval);
 }
-/*******************************************************\
-* Get the requested page into the buffer given         *
-\*******************************************************/
-cd_set_mode(unit,data)
-int    unit;
-struct cd_mode_data *data;
+
+/*
+ * Get the requested page into the buffer given
+ */
+errval 
+cd_set_mode(unit, data)
+       u_int32 unit;
+       struct cd_mode_data *data;
 {
        struct scsi_mode_select scsi_cmd;
 
 {
        struct scsi_mode_select scsi_cmd;
 
@@ -1223,25 +1009,26 @@ struct  cd_mode_data *data;
        scsi_cmd.byte2 |= SMS_PF;
        scsi_cmd.length = sizeof(*data) & 0xff;
        data->header.data_length = 0;
        scsi_cmd.byte2 |= SMS_PF;
        scsi_cmd.length = sizeof(*data) & 0xff;
        data->header.data_length = 0;
-       /*show_mem(data,sizeof(*data));*/
-       return (cd_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       data,
-                       sizeof(*data),
-                       20000,  /* should be immed */
-                       NULL,
-                       0)
-       ); 
+       return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               (u_char *) data,
+               sizeof(*data),
+               CDRETRIES,
+               20000,          /* should be immed */
+               NULL,
+               SCSI_DATA_OUT));
 }
 }
-/*******************************************************\
-* Get scsi driver to send a "start playing" command    *
-\*******************************************************/
-cd_play(unit,blk,len)
-int    unit,blk,len;
+
+/*
+ * Get scsi driver to send a "start playing" command
+ */
+errval 
+cd_play(unit, blk, len)
+       u_int32 unit, blk, len;
 {
        struct scsi_play scsi_cmd;
 {
        struct scsi_play scsi_cmd;
-       int     retval;
+       errval  retval;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = PLAY;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = PLAY;
@@ -1251,24 +1038,26 @@ int     unit,blk,len;
        scsi_cmd.blk_addr[3] = blk & 0xff;
        scsi_cmd.xfer_len[0] = (len >> 8) & 0xff;
        scsi_cmd.xfer_len[1] = len & 0xff;
        scsi_cmd.blk_addr[3] = blk & 0xff;
        scsi_cmd.xfer_len[0] = (len >> 8) & 0xff;
        scsi_cmd.xfer_len[1] = len & 0xff;
-       retval = cd_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       0,
-                       0,
-                       200000, /* should be immed */
-                       NULL,
-                       0);
-       return(retval);
+       return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               0,
+               0,
+               CDRETRIES,
+               200000,         /* should be immed */
+               NULL,
+               0));
 }
 }
-/*******************************************************\
-* Get scsi driver to send a "start playing" command    *
-\*******************************************************/
-cd_play_big(unit,blk,len)
-int    unit,blk,len;
+
+/*
+ * Get scsi driver to send a "start playing" command
+ */
+errval 
+cd_play_big(unit, blk, len)
+       u_int32 unit, blk, len;
 {
        struct scsi_play_big scsi_cmd;
 {
        struct scsi_play_big scsi_cmd;
-       int     retval;
+       errval  retval;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = PLAY_BIG;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = PLAY_BIG;
@@ -1280,24 +1069,26 @@ int     unit,blk,len;
        scsi_cmd.xfer_len[1] = (len >> 16) & 0xff;
        scsi_cmd.xfer_len[2] = (len >> 8) & 0xff;
        scsi_cmd.xfer_len[3] = len & 0xff;
        scsi_cmd.xfer_len[1] = (len >> 16) & 0xff;
        scsi_cmd.xfer_len[2] = (len >> 8) & 0xff;
        scsi_cmd.xfer_len[3] = len & 0xff;
-       retval = cd_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       0,
-                       0,
-                       20000,  /* should be immed */
-                       NULL,
-                       0);
-       return(retval);
+       return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               0,
+               0,
+               CDRETRIES,
+               20000,          /* should be immed */
+               NULL,
+               0));
 }
 }
-/*******************************************************\
-* Get scsi driver to send a "start playing" command    *
-\*******************************************************/
-cd_play_tracks(unit,strack,sindex,etrack,eindex)
-int    unit,strack,sindex,etrack,eindex;
+
+/*
+ * Get scsi driver to send a "start playing" command
+ */
+errval 
+cd_play_tracks(unit, strack, sindex, etrack, eindex)
+       u_int32 unit, strack, sindex, etrack, eindex;
 {
        struct scsi_play_track scsi_cmd;
 {
        struct scsi_play_track scsi_cmd;
-       int     retval;
+       errval  retval;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = PLAY_TRACK;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = PLAY_TRACK;
@@ -1305,47 +1096,52 @@ int     unit,strack,sindex,etrack,eindex;
        scsi_cmd.start_index = sindex;
        scsi_cmd.end_track = etrack;
        scsi_cmd.end_index = eindex;
        scsi_cmd.start_index = sindex;
        scsi_cmd.end_track = etrack;
        scsi_cmd.end_index = eindex;
-       retval = cd_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       0,
-                       0,
-                       20000,  /* should be immed */
-                       NULL,
-                       0);
-       return(retval);
+       return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               0,
+               0,
+               CDRETRIES,
+               20000,          /* should be immed */
+               NULL,
+               0));
 }
 }
-/*******************************************************\
-* Get scsi driver to send a "play msf" command         *
-\*******************************************************/
-cd_play_msf(unit,startm,starts,startf,endm,ends,endf)
-int    unit,startm,starts,startf,endm,ends,endf;
+
+/*
+ * Get scsi driver to send a "play msf" command
+ */
+errval 
+cd_play_msf(unit, startm, starts, startf, endm, ends, endf)
+       u_int32 unit, startm, starts, startf, endm, ends, endf;
 {
        struct scsi_play_msf scsi_cmd;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = PLAY_MSF;
 {
        struct scsi_play_msf scsi_cmd;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = PLAY_MSF;
-       scsi_cmd.start_m=startm;
-       scsi_cmd.start_s=starts;
-       scsi_cmd.start_f=startf;
-       scsi_cmd.end_m=endm;
-       scsi_cmd.end_s=ends;
-       scsi_cmd.end_f=endf;
-
-       return (cd_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       0,
-                       0,
-                       2000,
-                       NULL,
-                       0));
+       scsi_cmd.start_m = startm;
+       scsi_cmd.start_s = starts;
+       scsi_cmd.start_f = startf;
+       scsi_cmd.end_m = endm;
+       scsi_cmd.end_s = ends;
+       scsi_cmd.end_f = endf;
+
+       return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               0,
+               0,
+               CDRETRIES,
+               2000,
+               NULL,
+               0));
 }
 }
-/*******************************************************\
-* Get scsi driver to send a "start up" command         *
-\*******************************************************/
-cd_pause(unit,go)
-int    unit,go;
+
+/*
+ * Get scsi driver to send a "start up" command
+ */
+errval 
+cd_pause(unit, go)
+       u_int32 unit, go;
 {
        struct scsi_pause scsi_cmd;
 
 {
        struct scsi_pause scsi_cmd;
 
@@ -1353,534 +1149,132 @@ int   unit,go;
        scsi_cmd.op_code = PAUSE;
        scsi_cmd.resume = go;
 
        scsi_cmd.op_code = PAUSE;
        scsi_cmd.resume = go;
 
-       return (cd_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       0,
-                       0,
-                       2000,
-                       NULL,
-                       0));
-}
-/*******************************************************\
-* Get scsi driver to send a "RESET" command            *
-\*******************************************************/
-cd_reset(unit)
-int    unit;
-{
-       return(cd_scsi_cmd(unit,
-                       0,
-                       0,
-                       0,
-                       0,
-                       2000,
-                       NULL,
-                       SCSI_RESET));
+       return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               0,
+               0,
+               CDRETRIES,
+               2000,
+               NULL,
+               0));
 }
 }
-/*******************************************************\
-* Get scsi driver to send a "start up" command         *
-\*******************************************************/
-cd_start_unit(unit,part,type)
-{
-       struct scsi_start_stop scsi_cmd;
-       struct cd_data *cd = cd_driver->cd_data[unit];
 
 
-        if(type==CD_EJECT
-       /*&& (cd->openparts  == 0)*/)/* trouble is WE have it open *//*XXX*/
-       {
-               cd_prevent_unit(unit,PR_ALLOW,0);
-       }
-
-       bzero(&scsi_cmd, sizeof(scsi_cmd));
-       scsi_cmd.op_code = START_STOP;
-       scsi_cmd.how |= (type==CD_START)?SSS_START:0;
-       scsi_cmd.how |= (type==CD_EJECT)?SSS_LOEJ:0;
-
-       if (cd_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       0,
-                       0,
-                       2000,
-                       NULL,
-                       0) != 0) {
-               return(ENXIO);
-       } else 
-               return(0);
-}
-/*******************************************************\
-* Prevent or allow the user to remove the disk          *
-\*******************************************************/
-cd_prevent_unit(unit,type,flags)
-int     unit,type,flags;
+/*
+ * Get scsi driver to send a "RESET" command
+ */
+errval 
+cd_reset(unit)
+       u_int32 unit;
 {
 {
-        struct  scsi_prevent    scsi_cmd;
-       struct cd_data *cd = cd_driver->cd_data[unit];
-
-        if(type==PR_PREVENT
-       || ( type==PR_ALLOW && cd->openparts == 0 ))/*XXX*/
-       {
-                bzero(&scsi_cmd, sizeof(scsi_cmd));
-                scsi_cmd.op_code = PREVENT_ALLOW;
-                scsi_cmd.how = type;
-                if (cd_scsi_cmd(unit,
-                        &scsi_cmd,
-                        sizeof(struct   scsi_prevent),
-                        0,
-                        0,
-                        5000,
-                       NULL,
-                        0) != 0)
-                {
-                 if(!(flags & SCSI_SILENT))
-                         printf("cd%d: cannot prevent/allow\n", unit);
-                 return(0);
-                }
-        }
-        return(1);
+       return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+               0,
+               0,
+               0,
+               0,
+               CDRETRIES,
+               2000,
+               NULL,
+               SCSI_RESET));
 }
 
 }
 
-/******************************************************\
-* Read Subchannel                                     *
-\******************************************************/
-
-cd_read_subchannel(unit,mode,format,track,data,len)
-int unit,mode,format,len;
-struct cd_sub_channel_info *data;
+/*
+ * Read subchannel
+ */
+errval 
+cd_read_subchannel(unit, mode, format, track, data, len)
+       u_int32 unit, mode, format, len;
+       struct cd_sub_channel_info *data;
 {
        struct scsi_read_subchannel scsi_cmd;
 {
        struct scsi_read_subchannel scsi_cmd;
-       int error;
+       errval  error;
 
 
-       bzero(&scsi_cmd,sizeof(scsi_cmd));
+       bzero(&scsi_cmd, sizeof(scsi_cmd));
 
 
-       scsi_cmd.op_code=READ_SUBCHANNEL;
-        if(mode==CD_MSF_FORMAT)
+       scsi_cmd.op_code = READ_SUBCHANNEL;
+       if (mode == CD_MSF_FORMAT)
                scsi_cmd.byte2 |= CD_MSF;
                scsi_cmd.byte2 |= CD_MSF;
-       scsi_cmd.byte3=SRS_SUBQ;
-       scsi_cmd.subchan_format=format;
-       scsi_cmd.track=track;
-       scsi_cmd.data_len[0]=(len)>>8;
-       scsi_cmd.data_len[1]=(len)&0xff;
-       return cd_scsi_cmd(unit,
-               &scsi_cmd,
-               sizeof(struct   scsi_read_subchannel),
-               data,
+       scsi_cmd.byte3 = SRS_SUBQ;
+       scsi_cmd.subchan_format = format;
+       scsi_cmd.track = track;
+       scsi_cmd.data_len[0] = (len) >> 8;
+       scsi_cmd.data_len[1] = (len) & 0xff;
+       return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(struct scsi_read_subchannel),
+                       (u_char *) data,
                len,
                len,
+               CDRETRIES,
                5000,
                NULL,
                5000,
                NULL,
-               0);
+               SCSI_DATA_IN));
 }
 
 }
 
-/*******************************************************\
-* Read Table of contents                                *
-\*******************************************************/
-cd_read_toc(unit,mode,start,data,len)
-int unit,mode,start,len;
-struct cd_toc_entry *data;
+/*
+ * Read table of contents
+ */
+errval 
+cd_read_toc(unit, mode, start, data, len)
+       u_int32 unit, mode, start, len;
+       struct cd_toc_entry *data;
 {
        struct scsi_read_toc scsi_cmd;
 {
        struct scsi_read_toc scsi_cmd;
-       int error;
-       int ntoc;
-       
-       bzero(&scsi_cmd,sizeof(scsi_cmd));
+       errval  error;
+       u_int32 ntoc;
+
+       bzero(&scsi_cmd, sizeof(scsi_cmd));
        /*if(len!=sizeof(struct ioc_toc_header))
        /*if(len!=sizeof(struct ioc_toc_header))
-          ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
-         else*/
-          ntoc=len;
-
-       scsi_cmd.op_code=READ_TOC;
-        if(mode==CD_MSF_FORMAT)
-                scsi_cmd.byte2 |= CD_MSF;
-       scsi_cmd.from_track=start;
-       scsi_cmd.data_len[0]=(ntoc)>>8;
-       scsi_cmd.data_len[1]=(ntoc)&0xff;
-        return cd_scsi_cmd(unit,
-                &scsi_cmd,
-                sizeof(struct   scsi_read_toc),
-                data,
-                len,
-                5000,
+        * ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
+        * else */
+       ntoc = len;
+
+       scsi_cmd.op_code = READ_TOC;
+       if (mode == CD_MSF_FORMAT)
+               scsi_cmd.byte2 |= CD_MSF;
+       scsi_cmd.from_track = start;
+       scsi_cmd.data_len[0] = (ntoc) >> 8;
+       scsi_cmd.data_len[1] = (ntoc) & 0xff;
+       return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(struct scsi_read_toc),
+                       (u_char *) data,
+               len,
+               CDRETRIES,
+               5000,
                NULL,
                NULL,
-                0);
+               SCSI_DATA_IN));
 }
 
 }
 
-
 #define b2tol(a)       (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
 
 #define b2tol(a)       (((unsigned)(a##_1) << 8) + (unsigned)a##_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    cd_get_parms(unit, flags)
-{
-       struct cd_data *cd = cd_driver->cd_data[unit];
-
-       /*******************************************************\
-       * First check if we have it all loaded                  *
-       \*******************************************************/
-               if(cd->flags & CDVALID) return(0);
-       /*******************************************************\
-       * give a number of sectors so that sec * trks * cyls    *
-       * is <= disk_size                                       *
-       \*******************************************************/
-       if(cd_size(unit, flags))
-       {
-               cd->flags |= CDVALID;
-               return(0);
-       }
-       else
-       {
-               return(ENXIO);
-       }
-}
-
-/*******************************************************\
-* close the device.. only called if we are the LAST    *
-* occurence of an open device                          *
-\*******************************************************/
-cdclose(dev)
-dev_t dev;
-{
-       unsigned char unit, part;
-       unsigned int old_priority;
-
-       unit = UNIT(dev);
-       part = PARTITION(dev);
-#ifdef CDDEBUG
-       if(scsi_debug & TRACEOPENS)
-               printf("cd%d: closing part %d\n",unit,part);
-#endif
-       cd_driver->cd_data[unit]->partflags[part] &= ~CDOPEN;
-       cd_driver->cd_data[unit]->openparts &= ~(1 << part);
-               cd_prevent_unit(unit,PR_ALLOW,SCSI_SILENT);
-       return(0);
-}
-
-/*******************************************************\
-* ask the scsi driver to perform a command for us.     *
-* 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.                                     *
-* Also tell it where to read/write the data, and how   *
-* long the data is supposed to be                      *
-\*******************************************************/
-int    cd_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,bp,flags)
-
-int    unit,flags;
-struct scsi_generic *scsi_cmd;
-int    cmdlen;
-int    timeout;
-u_char *data_addr;
-int    datalen;
-struct buf     *bp;
+/*
+ * Get the scsi driver to send a full inquiry to the device and use the
+ * results to fill out the disk parameter structure.
+ */
+errval 
+cd_get_parms(unit, flags)
 {
 {
-       struct  scsi_xfer *xs;
-       int     retval;
-       int     s;
-       struct cd_data *cd = cd_driver->cd_data[unit];
-
-#ifdef CDDEBUG
-       if(scsi_debug & PRINTROUTINES) printf("\ncd_scsi_cmd%d ",unit);
-#endif /*CDDEBUG*/
-#ifdef PARANOID
-       if(!(cd->sc_sw))        /* If we have a scsi driver */
-       {
-               /* !? how'd we GET here? */
-               panic("attempt to run bad cd device");
-       }
-#endif /*PARANOID*/
-       xs = cd_get_xs(unit,flags); /* should wait unless booting */
-       if(!xs)
-       {
-               printf("cd%d: scsi_cmd controller busy"
-                               " (this should never happen)\n",unit); 
-                       return(EBUSY);
-       }
-       xs->flags |= INUSE;
-       /*******************************************************\
-       * Fill out the scsi_xfer structure                      *
-       \*******************************************************/
-       xs->flags       |=      flags;
-       xs->adapter     =       cd->ctlr;
-       xs->targ        =       cd->targ;
-       xs->lu          =       cd->lu;
-       xs->retries     =       CD_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
-                               :cd_done;
-       xs->done_arg    =       unit;
-       xs->done_arg2   =       (int)xs;
-       xs->bp          =       bp;
-retry: xs->error       =       XS_NOERROR;
-       /*******************************************************\
-       * Do the transfer. If we are polling we will return:    *
-       * COMPLETE,     Was poll, and cd_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 = (*(cd->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 the result */
-
-       case    HAD_ERROR:
-               switch(xs->error)
-               {
-               case    XS_NOERROR:     /* usually this one */
-                       retval = ESUCCESS;
-                       break;
-
-               case    XS_SENSE:
-                       retval = (cd_interpret_sense(unit,xs));
-                       break;
-               case    XS_BUSY:
-                       /* should sleep here 1 sec */
-                       /* fall through */
-               case    XS_TIMEOUT:
-                       if(xs->retries-- )
-                       {
-                               xs->flags &= ~ITSDONE;
-                               goto retry;
-                       }
-                       /* fall through */
-               case    XS_DRIVER_STUFFUP:
-                       retval = EIO;
-                       break;
-               default:
-                       retval = EIO;
-                       printf("cd%d: unknown error category from scsi driver\n"
-                               ,unit);
-               }       
-               break;
-       case    COMPLETE:
-               retval = ESUCCESS;
-               break;
+       struct cd_data *cd = cd_driver.cd_data[unit];
 
 
-       case    TRY_AGAIN_LATER:
-               if(xs->retries-- )
-               {
-                       if(tsleep( 0,PRIBIO + 2,"retry",hz * 2))
-                       {
-                               xs->flags &= ~ITSDONE;
-                               goto retry;
-                       }
-               }
-               /* fall through */
-       default:
-               retval = EIO;
-       }
-
-       /*******************************************************\
-       * we have finished doing the  command, free the struct  *
-       * and check if anyone else needs it                     *
-       \*******************************************************/
-       cd_free_xs(unit,xs,flags);
-       cdstart(unit);          /* check if anything is waiting for the xs */
-       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)  *
-\***************************************************************/
-
-int    cd_interpret_sense(unit,xs)
-int    unit;
-struct scsi_xfer *xs;
-{
-       struct  scsi_sense_data *sense;
-       int     key;
-       int     silent;
-       int     info;
-       struct cd_data *cd = cd_driver->cd_data[unit];
-
-       static char *error_mes[] = {            "soft error (corrected)",
-               "not ready",                    "medium error",
-               "non-media hardware failure",   "illegal request",
-               "unit attention",               "readonly device",
-               "no data found",                "vendor unique",
-               "copy aborted",                 "command aborted",
-               "search returned equal",        "volume overflow",
-               "verify miscompare",            "unknown error key"
-       };
-
-       /***************************************************************\
-       * If the flags say errs are ok, then always return ok.          *
-       \***************************************************************/
-       if (xs->flags & SCSI_ERR_OK) return(ESUCCESS);
-       silent = (xs->flags & SCSI_SILENT);
-
-       sense = &(xs->sense);
-#ifdef CDDEBUG
-       if(cd_debug)
-       {
-               int count = 0;
-               printf("code%x valid%x\n"
-                               ,sense->error_code & SSD_ERRCODE
-                               ,sense->error_code & SSD_ERRCODE_VALID ? 1 : 0);
-               printf("seg%x key%x ili%x eom%x fmark%x\n"
-                               ,sense->ext.extended.segment
-                               ,sense->ext.extended.flags & SSD_KEY
-                               ,sense->ext.extended.flags & SSD_ILI ? 1 : 0
-                               ,sense->ext.extended.flags & SSD_EOM ? 1 : 0
-                               ,sense->ext.extended.flags & SSD_FILEMARK ? 1 : 0);
-               printf("info: %x %x %x %x followed by %d extra bytes\n"
-                               ,sense->ext.extended.info[0]
-                               ,sense->ext.extended.info[1]
-                               ,sense->ext.extended.info[2]
-                               ,sense->ext.extended.info[3]
-                               ,sense->ext.extended.extra_len);
-               printf("extra: ");
-               while(count < sense->ext.extended.extra_len)
-               {
-                       printf ("%x ",sense->ext.extended.extra_bytes[count++]);
-               }
-               printf("\n");
-       }
-#endif /*CDDEBUG*/
-       switch(sense->error_code & SSD_ERRCODE)
-       {
-       /***************************************************************\
-       * If it's code 70, use the extended stuff and interpret the key *
-       \***************************************************************/
-       case 0x71:/* delayed error */
-               printf("cd%d: DELAYED ERROR, key = 0x%x\n",unit,key);
-       case 0x70:
-               if(sense->error_code & SSD_ERRCODE_VALID)
-               {
-                       info = ntohl(*((long *)sense->ext.extended.info));
-               }
-               else
-               {
-                       info = 0;
-               }
-       
-               key=sense->ext.extended.flags & SSD_KEY;
-       
-               if (!silent)
-               {
-                       printf("cd%d: %s", unit, error_mes[key - 1]);
-                       if(sense->error_code & SSD_ERRCODE_VALID)
-                       {
-                               switch (key)
-                               {
-                               case    0x2:            /* NOT READY */
-                               case    0x5:            /* ILLEGAL REQUEST */
-                               case    0x6:            /* UNIT ATTENTION */
-                               case    0x7:            /* DATA PROTECT */
-                                       break;
-                               case    0x8:            /* BLANK CHECK */
-                                       printf(", requested size: %d (decimal)",
-                                       info);
-                                       break;
-                               default:
-                                       printf(", info = %d (decimal)", info);
-                               }
-                       }
-                       printf("\n");
-               }
-       
-               switch (key)
-               {
-               case    0x0:                            /* NO SENSE */
-               case    0x1:                            /* RECOVERED ERROR */
-                       xs->resid = 0;
-               case    0xc:                            /* EQUAL */
-                       return(ESUCCESS);
-               case    0x2:                            /* NOT READY */
-                       cd->flags &= ~(CDVALID | CDHAVELABEL);
-                       return(ENODEV);
-               case    0x5:                            /* ILLEGAL REQUEST */
-                       return(EINVAL);
-               case    0x6:                            /* UNIT ATTENTION */
-                       cd->flags &= ~(CDVALID | CDHAVELABEL);
-                       if (cd->openparts)
-                       {
-                               return(EIO);
-                       }
-                       return(ESUCCESS);
-               case    0x7:                            /* DATA PROTECT */
-                       return(EACCES);
-               case    0xd:                            /* VOLUME OVERFLOW */
-                       return(ENOSPC);
-               case    0x8:                            /* BLANK CHECK */
-                       return(ESUCCESS);
-               default:
-                       return(EIO);
-               }
-       /*******************************\
-       * Not code 70, just report it   *
-       \*******************************/
-       default:
-               if(!silent)
-               {
-                       printf("cd%d: error code %d", unit,
-                               sense->error_code & SSD_ERRCODE);
-                       if(sense->error_code & SSD_ERRCODE_VALID)
-                       {
-                               printf(" at block no. %d (decimal)",
-                                       (sense->ext.unextended.blockhi <<16)
-                                       + (sense->ext.unextended.blockmed <<8)
-                                       + (sense->ext.unextended.blocklow ));
-                       }       
-                       printf("\n");
-               }
-               return(EIO);
+       /*
+        * First check if we have it all loaded
+        */
+       if (cd->sc_link->flags & SDEV_MEDIA_LOADED)
+               return (0);
+       /*
+        * give a number of sectors so that sec * trks * cyls
+        * is <= disk_size 
+        */
+       if (cd_size(unit, flags)) {
+               cd->sc_link->flags |= SDEV_MEDIA_LOADED;
+               return (0);
+       } else {
+               return (ENXIO);
        }
 }
 
        }
 }
 
-
-
-
 int
 cdsize(dev_t dev)
 {
        return (-1);
 }
 int
 cdsize(dev_t dev)
 {
        return (-1);
 }
-
-#if 0
-show_mem(address,num)
-unsigned char   *address;
-int     num;
-{
-       int x,y;
-       printf("------------------------------");
-       for (y = 0; y<num; y += 1)
-       {
-               if(!(y % 16))
-                       printf("\n%03d: ",y);
-               printf("%02x ",*address++);
-       }
-       printf("\n------------------------------\n");
-}
-#endif
index a76d522..c403fe5 100644 (file)
@@ -1,7 +1,8 @@
 /* 
 /* 
- * Written by Julian Elischer (julian@tfs.com)
+ * Written by grefen@?????
+ * Based on scsi drivers by Julian Elischer (julian@tfs.com)
  *
  *
- *     $Id$
+ *      $Id: ch.c,v 2.2 93/10/16 00:58:30 julian Exp Locker: julian $
  */
 
 #include       <sys/types.h>
  */
 
 #include       <sys/types.h>
 #include <sys/user.h>
 #include <sys/chio.h>
 
 #include <sys/user.h>
 #include <sys/chio.h>
 
-#if defined(OSF)
-#define SECSIZE        512
-#endif /* defined(OSF) */
-
 #include <scsi/scsi_all.h>
 #include <scsi/scsi_changer.h>
 #include <scsi/scsiconf.h>
 
 #include <scsi/scsi_all.h>
 #include <scsi/scsi_changer.h>
 #include <scsi/scsiconf.h>
 
-
-struct  scsi_xfer ch_scsi_xfer[NCH];
-int     ch_xfer_block_wait[NCH];
-
+struct scsi_xfer ch_scsi_xfer[NCH];
+u_int32 ch_xfer_block_wait[NCH];
 
 #define PAGESIZ        4096
 #define STQSIZE                4
 
 #define PAGESIZ        4096
 #define STQSIZE                4
-#define        CH_RETRIES      4
-
+#define        CHRETRIES       2
 
 #define MODE(z)                (  (minor(z) & 0x0F) )
 #define UNIT(z)                (  (minor(z) >> 4) )
 
 
 #define MODE(z)                (  (minor(z) & 0x0F) )
 #define UNIT(z)                (  (minor(z) >> 4) )
 
-#ifndef        MACH
 #define ESUCCESS 0
 #define ESUCCESS 0
-#endif MACH
 
 
-int    ch_info_valid[NCH];     /* the info about the device is valid */
-int    ch_initialized[NCH] ;
-int    ch_debug = 1;
+errval  chattach();
 
 
-int chattach();
-int ch_done();
-struct ch_data
+/*
+ * This driver is so simple it uses all the default services
+ */
+struct scsi_device ch_switch =
 {
 {
-       int     flags;
-       struct  scsi_switch *sc_sw;     /* address of scsi low level switch */
-       int     ctlr;                   /* so they know which one we want */
-       int     targ;                   /* our scsi target ID */
-       int     lu;                     /* out scsi lu */
-       short   chmo;                   /* Offset of first CHM */
-       short   chms;                   /* No. of CHM */
-       short   slots;                  /* No. of Storage Elements */
-       short   sloto;                  /* Offset of first SE */
-       short   imexs;                  /* No. of Import/Export Slots */
-       short   imexo;                  /* Offset of first IM/EX */
-       short   drives;                 /* No. of CTS */
-       short   driveo;                 /* Offset of first CTS */
-       short   rot;                    /* CHM can rotate */
-       u_long  op_matrix;              /* possible opertaions */
-       u_short lsterr;         /* details of lasterror */
-       u_char  stor;                   /* posible Storage locations */
-}ch_data[NCH];
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    "ch",
+    0,
+    0, 0
+};
+
+struct ch_data {
+       u_int32 flags;
+       struct scsi_link *sc_link;      /* all the inter level info */
+       u_int16 chmo;                   /* Offset of first CHM */
+       u_int16 chms;                   /* No. of CHM */
+       u_int16 slots;                  /* No. of Storage Elements */
+       u_int16 sloto;                  /* Offset of first SE */
+       u_int16 imexs;                  /* No. of Import/Export Slots */
+       u_int16 imexo;                  /* Offset of first IM/EX */
+       u_int16 drives;                 /* No. of CTS */
+       u_int16 driveo;                 /* Offset of first CTS */
+       u_int16 rot;                    /* CHM can rotate */
+       u_long  op_matrix;              /* possible opertaions */
+       u_int16 lsterr;                 /* details of lasterror */
+       u_char  stor;                   /* posible Storage locations */
+       u_int32 initialized;
+} ch_data[NCH];
 
 #define CH_OPEN                0x01
 #define CH_KNOWN       0x02
 
 
 #define CH_OPEN                0x01
 #define CH_KNOWN       0x02
 
-static int     next_ch_unit = 0;
-/***********************************************************************\
-* The routine called by the low level scsi routine when it discovers   *
-* A device suitable for this driver                                    *
-\***********************************************************************/
+static u_int32 next_ch_unit = 0;
 
 
-int    chattach(ctlr,targ,lu,scsi_switch)
-struct scsi_switch *scsi_switch;
+/*
+ * The routine called by the low level scsi routine when it discovers
+ * a device suitable for this driver.
+ */
+errval 
+chattach(sc_link)
+       struct scsi_link *sc_link;
 {
 {
-       int     unit,i,stat;
+       u_int32 unit, i, stat;
        unsigned char *tbl;
 
        unsigned char *tbl;
 
-       if(scsi_debug & PRINTROUTINES) printf("chattach: ");
-       /*******************************************************\
-       * Check we have the resources for another drive         *
-       \*******************************************************/
+       SC_DEBUG(sc_link, SDEV_DB2, ("chattach: "));
+       /*
+        * Check we have the resources for another drive
+        */
        unit = next_ch_unit++;
        unit = next_ch_unit++;
-       if( unit >= NCH)
-       {
-               printf("Too many scsi changers..(%d > %d) reconfigure kernel\n",(unit + 1),NCH);
-               return(0);
-       }
-       /*******************************************************\
-       * Store information needed to contact our base driver   *
-       \*******************************************************/
-       ch_data[unit].sc_sw     =       scsi_switch;
-       ch_data[unit].ctlr      =       ctlr;
-       ch_data[unit].targ      =       targ;
-       ch_data[unit].lu        =       lu;
-
-       /*******************************************************\
-       * Use the subdriver to request information regarding    *
-       * the drive. We cannot use interrupts yet, so the       *
-       * request must specify this.                            *
-       \*******************************************************/
-       if((ch_mode_sense(unit,  SCSI_NOSLEEP |  SCSI_NOMASK /*| SCSI_SILENT*/)))
-       {
-               printf("ch%d: scsi changer, %d slot(s) %d drive(s) %d arm(s) %d i/e-slot(s)\n",
-                       unit, ch_data[unit].slots, ch_data[unit].drives, ch_data[unit].chms, ch_data[unit].imexs);
-               stat=CH_KNOWN;
+       if (unit >= NCH) {
+               printf("Too many scsi changers..(%d > %d) reconfigure kernel\n", (unit + 1), NCH);
+               return (0);
        }
        }
-       else
-       {
+       /*
+        * Store information needed to contact our base driver
+        */
+       ch_data[unit].sc_link = sc_link;
+       sc_link->device = &ch_switch;
+       sc_link->dev_unit = unit;
+
+       /*
+        * Use the subdriver to request information regarding
+        * the drive. We cannot use interrupts yet, so the
+        * request must specify this.
+        */
+       if ((ch_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK /*| SCSI_SILENT */ ))) {
                printf("ch%d: scsi changer :- offline\n", unit);
                printf("ch%d: scsi changer :- offline\n", unit);
-               stat=CH_OPEN;
+               stat = CH_OPEN;
+       } else {
+               printf("ch%d: scsi changer, %d slot(s) %d drive(s) %d arm(s) %d i/e-slot(s)\n",
+                   unit, ch_data[unit].slots, ch_data[unit].drives, ch_data[unit].chms, ch_data[unit].imexs);
+               stat = CH_KNOWN;
        }
        }
-       ch_initialized[unit] = stat;
+       ch_data[unit].initialized = 1;
 
        return;
 
 }
 
 
        return;
 
 }
 
-
-
-/*******************************************************\
-*      open the device.                                *
-\*******************************************************/
+/*
+ *    open the device.
+ */
+errval 
 chopen(dev)
 {
 chopen(dev)
 {
-       int errcode = 0;
-       int unit,mode;
+       errval  errcode = 0;
+       u_int32 unit, mode;
+       struct scsi_link *sc_link;
 
        unit = UNIT(dev);
        mode = MODE(dev);
 
 
        unit = UNIT(dev);
        mode = MODE(dev);
 
-       /*******************************************************\
-       * Check the unit is legal                               *
-       \*******************************************************/
-       if ( unit >= NCH )
-       {
-               printf("ch%d: ch %d  > %d\n",unit,unit,NCH);
-               errcode = ENXIO;
-               return(errcode);
-       }
-       /*******************************************************\
-       * Only allow one at a time                              *
-       \*******************************************************/
-       if(ch_data[unit].flags & CH_OPEN)
-       {
-               printf("ch%d: already open\n",unit);
+       /*
+        * Check the unit is legal 
+        */
+       if (unit >= NCH) {
+               printf("ch%d: ch %d  > %d\n", unit, unit, NCH);
                errcode = ENXIO;
                errcode = ENXIO;
-               goto bad;
+               return (errcode);
        }
        }
-       
-       if(ch_debug||(scsi_debug & (PRINTROUTINES | TRACEOPENS)))
-               printf("chopen: dev=0x%x (unit %d (of %d))\n"
-                               ,   dev,      unit,   NCH);
-       /*******************************************************\
-       * Make sure the device has been initialised             *
-       \*******************************************************/
-
-       if (!ch_initialized[unit])
-               return(ENXIO);
-       if (ch_initialized[unit]!=CH_KNOWN) {
-               if((ch_mode_sense(unit,  SCSI_NOSLEEP |  SCSI_NOMASK /*| SCSI_SILENT*/)))
-               {
-                       ch_initialized[unit]=CH_KNOWN;
-               }
-         else
-               {
-                       printf("ch%d: scsi changer :- offline\n", unit);
-                       return(ENXIO);
-               }
+       /*
+        * Only allow one at a time
+        */
+       if (ch_data[unit].flags & CH_OPEN) {
+               printf("ch%d: already open\n", unit);
+               return ENXIO;
        }
        }
-       /*******************************************************\
-       * Check that it is still responding and ok.             *
-       \*******************************************************/
-
-       if(ch_debug || (scsi_debug & TRACEOPENS))
-               printf("device is ");
-       if (!(ch_req_sense(unit, 0)))
-       {
-               errcode = ENXIO;
-               if(ch_debug || (scsi_debug & TRACEOPENS))
-                       printf("not responding\n");
-               goto bad;
+       /*
+        * Make sure the device has been initialised
+        */
+       if (!ch_data[unit].initialized)
+               return (ENXIO);
+
+       sc_link = ch_data[unit].sc_link;
+
+       SC_DEBUG(sc_link, SDEV_DB1, ("chopen: dev=0x%x (unit %d (of %d))\n"
+               ,dev, unit, NCH));
+       /*
+        * Catch any unit attention errors.
+        */
+       scsi_test_unit_ready(sc_link, SCSI_SILENT);
+
+       sc_link->flags |= SDEV_OPEN;
+       /*
+        * Check that it is still responding and ok.
+        */
+       if (errcode = (scsi_test_unit_ready(sc_link, 0))) {
+               printf("ch%d: not ready\n", unit);
+               sc_link->flags &= ~SDEV_OPEN;
+               return errcode;
        }
        }
-       if(ch_debug || (scsi_debug & TRACEOPENS))
-               printf("ok\n");
-
-       if(!(ch_test_ready(unit,0)))
-       {
-               printf("ch%d: not ready\n",unit);
-               return(EIO);
+       /*
+        * Make sure data is loaded
+        */
+       if (errcode = (ch_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK))) {
+               printf("ch%d: scsi changer :- offline\n", unit);
+               sc_link->flags &= ~SDEV_OPEN;
+               return (errcode);
        }
        }
-
-       ch_info_valid[unit] = TRUE;
-
-       /*******************************************************\
-       * Load the physical device parameters                   *
-       \*******************************************************/
-
        ch_data[unit].flags = CH_OPEN;
        ch_data[unit].flags = CH_OPEN;
-       return(errcode);
-bad:
-       return(errcode);
+       return 0;
 }
 
 }
 
-/*******************************************************\
-* 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
+ */
+errval 
 chclose(dev)
 {
 chclose(dev)
 {
-       unsigned char unit,mode;
+       unsigned char unit, mode;
+       struct scsi_link *sc_link;
 
        unit = UNIT(dev);
        mode = MODE(dev);
 
        unit = UNIT(dev);
        mode = MODE(dev);
+       sc_link = ch_data[unit].sc_link;
 
 
-       if(scsi_debug & TRACEOPENS)
-               printf("Closing device");
+       SC_DEBUG(sc_link, SDEV_DB1, ("Closing device"));
        ch_data[unit].flags = 0;
        ch_data[unit].flags = 0;
-       return(0);
-}
-
-
-
-/***************************************************************\
-* chstart                                                       *
-* This routine is also called after other non-queued requests  *
-* have been made of the scsi driver, to ensure that the queue  *
-* continues to be drained.                                     *
-\***************************************************************/
-/* chstart() is called at splbio */
-chstart(unit)
-{
-       int                     drivecount;
-       register struct buf     *bp = 0;
-       register struct buf     *dp;
-       struct  scsi_xfer       *xs;
-       int                     blkno, nblk;
-
-
-       if(scsi_debug & PRINTROUTINES) printf("chstart%d ",unit);
-       /*******************************************************\
-       * See if there is a buf to do and we are not already    *
-       * doing one                                             *
-       \*******************************************************/
-       xs=&ch_scsi_xfer[unit];
-       if(xs->flags & INUSE)
-       {
-               return;    /* unit already underway */
-       }
-       if(ch_xfer_block_wait[unit]) /* a special awaits, let it proceed first */
-       {
-               wakeup(&ch_xfer_block_wait[unit]);
-               return;
-       }
-
-       return;
-
+       sc_link->flags &= ~SDEV_OPEN;
+       return (0);
 }
 
 }
 
-
-/*******************************************************\
-* This routine is called by the scsi interrupt when    *
-* the transfer is complete.
-\*******************************************************/
-int    ch_done(unit,xs)
-int    unit;
-struct scsi_xfer       *xs;
-{
-       struct  buf             *bp;
-       int     retval;
-
-       if(ch_debug||(scsi_debug & PRINTROUTINES)) printf("ch_done%d ",unit);
-       if (! (xs->flags & INUSE))
-               panic("scsi_xfer not in use!");
-       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
+ */
+errval 
 chioctl(dev, cmd, arg, mode)
 chioctl(dev, cmd, arg, mode)
-dev_t dev;
-int cmd;
-caddr_t arg;
+       dev_t   dev;
+       u_int32 cmd;
+       caddr_t arg;
 {
 {
-       /* struct ch_cmd_buf *args;*/
+       /* struct ch_cmd_buf *args; */
        union scsi_cmd *scsi_cmd;
        union scsi_cmd *scsi_cmd;
-       register i,j;
-       unsigned int opri;
-       int errcode = 0;
+       register i, j;
+       u_int32 opri;
+       errval  errcode = 0;
        unsigned char unit;
        unsigned char unit;
-       int number,flags,ret;
-
-       /*******************************************************\
-       * Find the device that the user is talking about        *
-       \*******************************************************/
-       flags = 0;      /* give error messages, act on errors etc. */
+       u_int32 number, flags;
+       errval  ret;
+       struct scsi_link *sc_link;
+
+       /*
+        * Find the device that the user is talking about
+        */
+       flags = 0;              /* give error messages, act on errors etc. */
        unit = UNIT(dev);
        unit = UNIT(dev);
-
-       switch(cmd)
-       {
-               case CHIOOP: {
-                       struct chop *ch=(struct chop *) arg;
-                       if (ch_debug)
-                               printf("[chtape_chop: %x]\n", ch->ch_op);
-
-                        switch ((short)(ch->ch_op)) {
-                               case CHGETPARAM:
-                                       ch->u.getparam.chmo=     ch_data[unit].chmo;
-                                       ch->u.getparam.chms=   ch_data[unit].chms;
-                                       ch->u.getparam.sloto=  ch_data[unit].sloto;
-                                       ch->u.getparam.slots=  ch_data[unit].slots;
-                                       ch->u.getparam.imexo=  ch_data[unit].imexo;
-                                       ch->u.getparam.imexs=  ch_data[unit].imexs;
-                                       ch->u.getparam.driveo= ch_data[unit].driveo;
-                                       ch->u.getparam.drives= ch_data[unit].drives;
-                                       ch->u.getparam.rot=    ch_data[unit].rot;
-                                       ch->result=0;
-                                       return 0;
-                                       break;
-                               case CHPOSITION: 
-                                return ch_position(unit,&ch->result,ch->u.position.chm,
-                                               ch->u.position.to,
-                                               flags);
-                               case CHMOVE: 
-                                return ch_move(unit,&ch->result, ch->u.position.chm,
-                                       ch->u.move.from, ch->u.move.to,
-                                                               flags);
-                               case CHGETELEM:
-                                return ch_getelem(unit,&ch->result, ch->u.get_elem_stat.type,
-                                       ch->u.get_elem_stat.from, &ch->u.get_elem_stat.elem_data,
-                                                                       flags);
-                               default:
-                                return EINVAL;
+       sc_link = ch_data[unit].sc_link;
+
+       switch (cmd) {
+       case CHIOOP:{
+                       struct chop *ch = (struct chop *) arg;
+                       SC_DEBUG(sc_link, SDEV_DB2,
+                           ("[chtape_chop: %x]\n", ch->ch_op));
+
+                       switch ((short) (ch->ch_op)) {
+                       case CHGETPARAM:
+                               ch->u.getparam.chmo = ch_data[unit].chmo;
+                               ch->u.getparam.chms = ch_data[unit].chms;
+                               ch->u.getparam.sloto = ch_data[unit].sloto;
+                               ch->u.getparam.slots = ch_data[unit].slots;
+                               ch->u.getparam.imexo = ch_data[unit].imexo;
+                               ch->u.getparam.imexs = ch_data[unit].imexs;
+                               ch->u.getparam.driveo = ch_data[unit].driveo;
+                               ch->u.getparam.drives = ch_data[unit].drives;
+                               ch->u.getparam.rot = ch_data[unit].rot;
+                               ch->result = 0;
+                               return 0;
+                               break;
+                       case CHPOSITION:
+                               return ch_position(unit, &ch->result, ch->u.position.chm,
+                                   ch->u.position.to,
+                                   flags);
+                       case CHMOVE:
+                               return ch_move(unit, &ch->result, ch->u.position.chm,
+                                   ch->u.move.from, ch->u.move.to,
+                                   flags);
+                       case CHGETELEM:
+                               return ch_getelem(unit, &ch->result, ch->u.get_elem_stat.type,
+                                   ch->u.get_elem_stat.from, &ch->u.get_elem_stat.elem_data,
+                                   flags);
+                       default:
+                               return EINVAL;
+                       }
                }
                }
-
-        }
        default:
        default:
-               return EINVAL;
+               return scsi_do_ioctl(sc_link, cmd, arg, mode);
        }
        }
-
-       return(ret?ESUCCESS:EIO);
+       return (ret ? ESUCCESS : EIO);
 }
 
 }
 
-ch_getelem(unit,stat,type,from,data,flags)
-int unit,from,flags;
-short *stat;
-char *data;
+errval 
+ch_getelem(unit, stat, type, from, data, flags)
+       u_int32 unit, from, flags;
+       short  *stat;
+       char   *data;
 {
        struct scsi_read_element_status scsi_cmd;
 {
        struct scsi_read_element_status scsi_cmd;
-       char elbuf[32];
-       int ret;
+       char    elbuf[32];
+       errval  ret;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = READ_ELEMENT_STATUS;
        scsi_cmd.byte2 = type;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = READ_ELEMENT_STATUS;
        scsi_cmd.byte2 = type;
-       scsi_cmd.starting_element_addr[0]=(from>>8)&0xff;
-       scsi_cmd.starting_element_addr[1]=from&0xff;
-       scsi_cmd.number_of_elements[1]=1;
-       scsi_cmd.allocation_length[2]=32;
-       
-       if ((ret=ch_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       elbuf,
-                       32,
-                       100000,
-                       flags) !=ESUCCESS)) {
-                       *stat=ch_data[unit].lsterr;
-                       bcopy(elbuf+16,data,16);
-                       return ret;
-                       }
-       bcopy(elbuf+16,data,16); /*Just a hack sh */
+       scsi_cmd.starting_element_addr[0] = (from >> 8) & 0xff;
+       scsi_cmd.starting_element_addr[1] = from & 0xff;
+       scsi_cmd.number_of_elements[1] = 1;
+       scsi_cmd.allocation_length[2] = 32;
+
+       if ((ret = scsi_scsi_cmd(ch_data[unit].sc_link,
+                   (struct scsi_generic *) &scsi_cmd,
+                   sizeof(scsi_cmd),
+                   (u_char *) elbuf,
+                   32,
+                   CHRETRIES,
+                   100000,
+                   NULL,
+                   SCSI_DATA_IN | flags) != ESUCCESS)) {
+               *stat = ch_data[unit].lsterr;
+               bcopy(elbuf + 16, data, 16);
+               return ret;
+       }
+       bcopy(elbuf + 16, data, 16);    /*Just a hack sh */
        return ret;
 }
 
        return ret;
 }
 
-ch_move(unit,stat,chm,from,to,flags)
-int unit,chm,from,to,flags;
-short *stat;
+errval 
+ch_move(unit, stat, chm, from, to, flags)
+       u_int32 unit, chm, from, to, flags;
+       short  *stat;
 {
        struct scsi_move_medium scsi_cmd;
 {
        struct scsi_move_medium scsi_cmd;
-       int ret;
+       errval  ret;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = MOVE_MEDIUM;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = MOVE_MEDIUM;
-       scsi_cmd.transport_element_address[0]=(chm>>8)&0xff;
-       scsi_cmd.transport_element_address[1]=chm&0xff;
-       scsi_cmd.source_address[0]=(from>>8)&0xff;
-       scsi_cmd.source_address[1]=from&0xff;
-       scsi_cmd.destination_address[0]=(to>>8)&0xff;
-       scsi_cmd.destination_address[1]=to&0xff;
-       scsi_cmd.invert=(chm&CH_INVERT)?1:0;
-       if ((ret=ch_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       NULL,
-                       0,
-                       100000,
-                       flags) !=ESUCCESS)) {
-                       *stat=ch_data[unit].lsterr;
-                       return ret;
-                       }
+       scsi_cmd.transport_element_address[0] = (chm >> 8) & 0xff;
+       scsi_cmd.transport_element_address[1] = chm & 0xff;
+       scsi_cmd.source_address[0] = (from >> 8) & 0xff;
+       scsi_cmd.source_address[1] = from & 0xff;
+       scsi_cmd.destination_address[0] = (to >> 8) & 0xff;
+       scsi_cmd.destination_address[1] = to & 0xff;
+       scsi_cmd.invert = (chm & CH_INVERT) ? 1 : 0;
+       if ((ret = scsi_scsi_cmd(ch_data[unit].sc_link,
+                   (struct scsi_generic *) &scsi_cmd,
+                   sizeof(scsi_cmd),
+                   NULL,
+                   0,
+                   CHRETRIES,
+                   100000,
+                   NULL,
+                   flags) != ESUCCESS)) {
+               *stat = ch_data[unit].lsterr;
+               return ret;
+       }
        return ret;
 }
 
        return ret;
 }
 
-ch_position(unit,stat,chm,to,flags)
-int unit,chm,to,flags;
-short *stat;
+errval 
+ch_position(unit, stat, chm, to, flags)
+       u_int32 unit, chm, to, flags;
+       short  *stat;
 {
        struct scsi_position_to_element scsi_cmd;
 {
        struct scsi_position_to_element scsi_cmd;
-       int ret;
+       errval  ret;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = POSITION_TO_ELEMENT;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = POSITION_TO_ELEMENT;
-       scsi_cmd.transport_element_address[0]=(chm>>8)&0xff;
-       scsi_cmd.transport_element_address[1]=chm&0xff;
-       scsi_cmd.source_address[0]=(to>>8)&0xff;
-       scsi_cmd.source_address[1]=to&0xff;
-       scsi_cmd.invert=(chm&CH_INVERT)?1:0;
-       if ((ret=ch_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       NULL,
-                       0,
-                       100000,
-                       flags) !=ESUCCESS)) {
-                       *stat=ch_data[unit].lsterr;
-                       return ret;
-                       }
-       return ret;
-}
-
-/*******************************************************\
-* Check with the device that it is ok, (via scsi driver)*
-\*******************************************************/
-ch_req_sense(unit, flags)
-int    flags;
-{
-       struct  scsi_sense_data sense;
-       struct scsi_sense scsi_cmd;
-
-       bzero(&scsi_cmd, sizeof(scsi_cmd));
-       scsi_cmd.op_code = REQUEST_SENSE;
-       scsi_cmd.length = sizeof(sense);
-
-       if (ch_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(struct   scsi_sense),
-                       &sense,
-                       sizeof(sense),
-                       100000,
-                       flags | SCSI_DATA_IN) != 0)
-       {
-               return(FALSE);
+       scsi_cmd.transport_element_address[0] = (chm >> 8) & 0xff;
+       scsi_cmd.transport_element_address[1] = chm & 0xff;
+       scsi_cmd.source_address[0] = (to >> 8) & 0xff;
+       scsi_cmd.source_address[1] = to & 0xff;
+       scsi_cmd.invert = (chm & CH_INVERT) ? 1 : 0;
+       if ((ret = scsi_scsi_cmd(ch_data[unit].sc_link,
+                   (struct scsi_generic *) &scsi_cmd,
+                   sizeof(scsi_cmd),
+                   NULL,
+                   0,
+                   CHRETRIES,
+                   100000,
+                   NULL,
+                   flags) != ESUCCESS)) {
+               *stat = ch_data[unit].lsterr;
+               return ret;
        }
        }
-       else 
-               return(TRUE);
-}
-
-/*******************************************************\
-* Get scsi driver to send a "are you ready" command    *
-\*******************************************************/
-ch_test_ready(unit,flags)
-int    unit,flags;
-{
-       struct scsi_test_unit_ready scsi_cmd;
-
-       bzero(&scsi_cmd, sizeof(scsi_cmd));
-       scsi_cmd.op_code = TEST_UNIT_READY;
-
-       if (ch_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(struct   scsi_test_unit_ready),
-                       0,
-                       0,
-                       100000,
-                       flags) != 0) {
-               return(FALSE);
-       } else 
-               return(TRUE);
+       return ret;
 }
 
 }
 
-
 #ifdef __STDC__
 #define b2tol(a)       (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
 #else
 #define b2tol(a)       (((unsigned)(a/**/_1) << 8) + (unsigned)a/**/_0 )
 #endif
 
 #ifdef __STDC__
 #define b2tol(a)       (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
 #else
 #define b2tol(a)       (((unsigned)(a/**/_1) << 8) + (unsigned)a/**/_0 )
 #endif
 
-/*******************************************************\
-* Get the scsi driver to send a full inquiry to the    *
-* device and use the results to fill out the global    *
-* parameter structure.                                 *
-\*******************************************************/
+/*
+ * Get the scsi driver to send a full inquiry to the
+ * device and use the results to fill out the global 
+ * parameter structure.
+ */
+errval 
 ch_mode_sense(unit, flags)
 ch_mode_sense(unit, flags)
-int    unit,flags;
+       u_int32 unit, flags;
 {
        struct scsi_mode_sense scsi_cmd;
 {
        struct scsi_mode_sense scsi_cmd;
-       u_char scsi_sense[128]; /* Can't use scsi_mode_sense_data because of */
-                               /* missing block descriptor                  */
+       u_char  scsi_sense[128];        /* Can't use scsi_mode_sense_data because of
+                                        * missing block descriptor
+                                        */
        u_char *b;
        u_char *b;
-       int i,l;
-
-       /*******************************************************\
-       * First check if we have it all loaded                  *
-       \*******************************************************/
-       if (ch_info_valid[unit]==CH_KNOWN) return(TRUE);
-       /*******************************************************\
-       * First do a mode sense                                 *
-       \*******************************************************/
-       ch_info_valid[unit] &= ~CH_KNOWN;
-       for(l=1;l>=0;l--) {
-               bzero(&scsi_cmd, sizeof(scsi_cmd));
-               scsi_cmd.op_code = MODE_SENSE;
-               scsi_cmd.byte2 = SMS_DBD;
-               scsi_cmd.page = 0x3f;   /* All Pages */
-               scsi_cmd.length = sizeof(scsi_sense);
-       /*******************************************************\
-       * do the command, but we don't need the results         *
-       * just print them for our interest's sake               *
-       \*******************************************************/
-               if (ch_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(struct   scsi_mode_sense),
-                       &scsi_sense,
-                       sizeof(scsi_sense),
-                       5000,
-                       flags | SCSI_DATA_IN) == 0) {
-                               ch_info_valid[unit] = CH_KNOWN;
-                               break;
-                       }
-       }
-       if (ch_info_valid[unit]!=CH_KNOWN)   {
-               if(!(flags & SCSI_SILENT))
+       int32   i, l;
+       errval  errcode;
+       struct scsi_link *sc_link = ch_data[unit].sc_link;
+
+       /*
+        * First check if we have it all loaded
+        */
+       if (sc_link->flags & SDEV_MEDIA_LOADED)
+               return 0;
+
+       /*
+        * First do a mode sense 
+        */
+       /* sc_link->flags &= ~SDEV_MEDIA_LOADED; *//*XXX */
+       bzero(&scsi_cmd, sizeof(scsi_cmd));
+       scsi_cmd.op_code = MODE_SENSE;
+       scsi_cmd.byte2 = SMS_DBD;
+       scsi_cmd.page = 0x3f;   /* All Pages */
+       scsi_cmd.length = sizeof(scsi_sense);
+
+       /*
+        * Read in the pages
+        */
+       if (errcode = scsi_scsi_cmd(sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(struct scsi_mode_sense),
+                       (u_char *) & scsi_sense,
+               sizeof  (scsi_sense),
+               CHRETRIES,
+               5000,
+               NULL,
+               flags | SCSI_DATA_IN) != 0) {
+               if (!(flags & SCSI_SILENT))
                        printf("ch%d: could not mode sense\n", unit);
                        printf("ch%d: could not mode sense\n", unit);
-               return(FALSE);
+               return (errcode);
        }
        }
-       l=scsi_sense[0]-3;
-       b=&scsi_sense[4];
-       /*****************************\
-       * To avoid alignment problems *
-       \*****************************/
-/*FIX THIS FOR MSB */
+       sc_link->flags |= SDEV_MEDIA_LOADED;
+       l = scsi_sense[0] - 3;
+       b = &scsi_sense[4];
+
+       /*
+        * To avoid alignment problems
+        */
+/* XXX - FIX THIS FOR MSB */
 #define p2copy(valp)    (valp[1]+ (valp[0]<<8));valp+=2
 #define p4copy(valp)    (valp[3]+ (valp[2]<<8) + (valp[1]<<16) + (valp[0]<<24));valp+=4
 #if 0
 #define p2copy(valp)    (valp[1]+ (valp[0]<<8));valp+=2
 #define p4copy(valp)    (valp[3]+ (valp[2]<<8) + (valp[1]<<16) + (valp[0]<<24));valp+=4
 #if 0
-       printf("\nmode_sense %d\n",l);
-       for(i=0;i<l+4;i++) {
-               printf("%x%c",scsi_sense[i],i%8==7?'\n':':');
-       }
-       printf("\n");
+       printf("\nmode_sense %d\n", l);
+       for (i = 0; i < l + 4; i++) {
+               printf("%x%c", scsi_sense[i], i % 8 == 7 ? '\n' : ':');
+       } printf("\n");
 #endif
 #endif
-       for(i=0;i<l;) {
-               int pc=(*b++)&0x3f;
-               int pl=*b++;
-               u_char *bb=b;
-               switch(pc) {
-                       case 0x1d:
-                               ch_data[unit].chmo  =p2copy(bb);
-                               ch_data[unit].chms  =p2copy(bb);
-                               ch_data[unit].sloto =p2copy(bb);
-                               ch_data[unit].slots =p2copy(bb);
-                               ch_data[unit].imexo =p2copy(bb);
-                               ch_data[unit].imexs =p2copy(bb);
-                               ch_data[unit].driveo =p2copy(bb);
-                               ch_data[unit].drives =p2copy(bb);
-                               break;
-                       case 0x1e:
-                               ch_data[unit].rot = (*b)&1;
-                               break;
-                       case 0x1f:
-                               ch_data[unit].stor = *b&0xf;
-                               bb+=2;
-                               ch_data[unit].stor =p4copy(bb);
-                               break;
-                       default:
-                               break;
-               }
-               b+=pl;
-               i+=pl+2;
-       }
-       if (ch_debug)
-       {
-               printf("unit %d: cht(%d-%d)slot(%d-%d)imex(%d-%d)cts(%d-%d) %s rotate\n",
-                               unit,
-                               ch_data[unit].chmo,
-                               ch_data[unit].chms,
-                               ch_data[unit].sloto,
-                               ch_data[unit].slots,
-                               ch_data[unit].imexo,
-                               ch_data[unit].imexs,
-                               ch_data[unit].driveo,
-                               ch_data[unit].drives,
-                               ch_data[unit].rot?"can":"can't");
-       }
-       return(TRUE);
-}
-
-/*******************************************************\
-* ask the scsi driver to perform a command for us.     *
-* 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.                                     *
-* Also tell it where to read/write the data, and how   *
-* long the data is supposed to be                      *
-\*******************************************************/
-int    ch_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,flags)
-
-int    unit,flags;
-struct scsi_generic *scsi_cmd;
-int    cmdlen;
-int    timeout;
-u_char *data_addr;
-int    datalen;
-{
-       struct  scsi_xfer *xs;
-       int     retval;
-       int     s;
-
-       if(ch_debug||(scsi_debug & PRINTROUTINES)) printf("\nch_scsi_cmd%d %x",
-                               unit,scsi_cmd->opcode);
-       if(ch_data[unit].sc_sw) /* If we have a scsi driver */
-       {
-
-               xs = &(ch_scsi_xfer[unit]);
-               if(!(flags & SCSI_NOMASK))
-                       s = splbio();
-               ch_xfer_block_wait[unit]++;     /* there is someone waiting */
-               while (xs->flags & INUSE)
-               {
-                       sleep(&ch_xfer_block_wait[unit],PRIBIO+1);
-               }
-               ch_xfer_block_wait[unit]--;
-               xs->flags = INUSE;
-               if(!(flags & SCSI_NOMASK))
-                       splx(s);
-
-               /*******************************************************\
-               * Fill out the scsi_xfer structure                      *
-               \*******************************************************/
-               xs->flags       |=      flags;
-               xs->adapter     =       ch_data[unit].ctlr;
-               xs->targ        =       ch_data[unit].targ;
-               xs->lu          =       ch_data[unit].lu;
-               xs->retries     =       CH_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
-                                       :ch_done;
-               xs->done_arg    =       unit;
-               xs->done_arg2   =       (int)xs;
-retry:         xs->error       =       XS_NOERROR;
-               xs->bp          =       0;
-               ch_data[unit].lsterr=0;
-               retval = (*(ch_data[unit].sc_sw->scsi_cmd))(xs);
-               switch(retval)
-               {
-               case    SUCCESSFULLY_QUEUED:
-                       while(!(xs->flags & ITSDONE))
-                               sleep(xs,PRIBIO+1);
-
-               case    HAD_ERROR:
-               case    COMPLETE:
-                       switch(xs->error)
-                       {
-                       case    XS_NOERROR:
-                               retval = ESUCCESS;
-                               break;
-                       case    XS_SENSE:
-                               retval = (ch_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("ch%d: unknown error category from scsi driver\n"
-                                       ,unit);
-                               break;
-                       }       
+       for (i = 0; i < l;) {
+               u_int32 pc = (*b++) & 0x3f;
+               u_int32 pl = *b++;
+               u_char *bb = b;
+               switch (pc) {
+               case 0x1d:
+                       ch_data[unit].chmo = p2copy(bb);
+                       ch_data[unit].chms = p2copy(bb);
+                       ch_data[unit].sloto = p2copy(bb);
+                       ch_data[unit].slots = p2copy(bb);
+                       ch_data[unit].imexo = p2copy(bb);
+                       ch_data[unit].imexs = p2copy(bb);
+                       ch_data[unit].driveo = p2copy(bb);
+                       ch_data[unit].drives = p2copy(bb);
                        break;
                        break;
-               case    TRY_AGAIN_LATER:
-                       if(xs->retries-- )
-                       {
-                               xs->flags &= ~ITSDONE;
-                               goto retry;
-                       }
-                       retval = EIO;
+               case 0x1e:
+                       ch_data[unit].rot = (*b) & 1;
+                       break;
+               case 0x1f:
+                       ch_data[unit].stor = *b & 0xf;
+                       bb += 2;
+                       ch_data[unit].stor = p4copy(bb);
                        break;
                default:
                        break;
                default:
-                       retval = EIO;
-               }
-               xs->flags = 0;  /* it's free! */
-               chstart(unit);
-       }
-       else
-       {
-               printf("ch%d: not set up\n",unit);
-               return(EINVAL);
-       }
-       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)  *
-\***************************************************************/
-
-int    ch_interpret_sense(unit,xs)
-int    unit;
-struct scsi_xfer       *xs;
-{
-       struct  scsi_sense_data *sense;
-       int     key;
-       int     silent = xs->flags & SCSI_SILENT;
-
-       /***************************************************************\
-       * If errors are ok, report a success                            *
-       \***************************************************************/
-       if(xs->flags & SCSI_ERR_OK) return(ESUCCESS);
-
-       /***************************************************************\
-       * Get the sense fields and work out what CLASS                  *
-       \***************************************************************/
-       sense = &(xs->sense);
-       switch(sense->error_code & SSD_ERRCODE)
-       {
-       /***************************************************************\
-       * If it's class 7, use the extended stuff and interpret the key *
-       \***************************************************************/
-       case 0x70:
-               {
-               key=sense->ext.extended.flags & SSD_KEY;
-               if(sense->ext.extended.flags & SSD_ILI)
-                       if(!silent)
-                       {
-                               printf("length error ");
-                       }
-                       if(sense->error_code & SSD_ERRCODE_VALID)
-                               xs->resid = ntohl(*((long *)sense->ext.extended.info));
-                               if(xs->bp)
-                               {
-                                       xs->bp->b_flags |= B_ERROR;
-                                       return(ESUCCESS);
-                               }
-               if(sense->ext.extended.flags & SSD_EOM)
-                       if(!silent) printf("end of medium ");
-               if(sense->ext.extended.flags & SSD_FILEMARK)
-                       if(!silent) printf("filemark ");
-               if(ch_debug)
-               {
-                       printf("code%x valid%x\n"
-                                       ,sense->error_code & SSD_ERRCODE
-                                       ,sense->error_code & SSD_ERRCODE_VALID);
-                       printf("seg%x key%x ili%x eom%x fmark%x\n"
-                                       ,sense->ext.extended.segment
-                                       ,sense->ext.extended.flags & SSD_KEY
-                                       ,sense->ext.extended.flags & SSD_ILI
-                                       ,sense->ext.extended.flags & SSD_EOM
-                                       ,sense->ext.extended.flags & SSD_FILEMARK);
-                       printf("info: %x %x %x %x followed by %d extra bytes\n"
-                                       ,sense->ext.extended.info[0]
-                                       ,sense->ext.extended.info[1]
-                                       ,sense->ext.extended.info[2]
-                                       ,sense->ext.extended.info[3]
-                                       ,sense->ext.extended.extra_len);
-                       printf("extra: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n"
-                                       ,sense->ext.extended.extra_bytes[0]
-                                       ,sense->ext.extended.extra_bytes[1]
-                                       ,sense->ext.extended.extra_bytes[2]
-                                       ,sense->ext.extended.extra_bytes[3]
-                                       ,sense->ext.extended.extra_bytes[4]
-                                       ,sense->ext.extended.extra_bytes[5]
-                                       ,sense->ext.extended.extra_bytes[6]
-                                       ,sense->ext.extended.extra_bytes[7]
-                                       ,sense->ext.extended.extra_bytes[8]
-                                       ,sense->ext.extended.extra_bytes[9]
-                                       ,sense->ext.extended.extra_bytes[10]
-                                       ,sense->ext.extended.extra_bytes[11]
-                                       ,sense->ext.extended.extra_bytes[12]
-                                       ,sense->ext.extended.extra_bytes[13]
-                                       ,sense->ext.extended.extra_bytes[14]
-                                       ,sense->ext.extended.extra_bytes[15]);
-                                   
-               }
-               switch(key)
-               {
-               case    0x0:
-                       return(ESUCCESS);
-               case    0x1:
-                       if(!silent)
-                       {
-                               printf("ch%d: soft error(corrected)", unit); 
-                               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("\n");
-                       }
-                       return(ESUCCESS);
-               case    0x2:
-                       if(!silent) printf("ch%d: not ready\n", unit); 
-                       ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)|
-                                               sense->ext.extended.info[13] ;
-                       return(ENODEV);
-               case    0x3:
-                       if(!silent)
-                       {
-                               printf("ch%d: medium error", unit); 
-                               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("\n");
-                       }
-                       return(EIO);
-               case    0x4:
-                       if(!silent) printf("ch%d: non-media hardware failure\n",
-                               unit); 
-                       ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)|
-                                               sense->ext.extended.info[13] ;
-                       return(EIO);
-               case    0x5:
-                       if(!silent) printf("ch%d: illegal request\n", unit); 
-                       ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)|
-                                               sense->ext.extended.info[13] ;
-                       return(EINVAL);
-               case    0x6:
-                       if(!silent) printf("ch%d: Unit attention\n", unit); 
-                       ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)|
-                                               sense->ext.extended.info[13] ;
-                       ch_info_valid[unit] = FALSE;
-                       if (ch_data[unit].flags & CH_OPEN) /* TEMP!!!! */
-                               return(EIO);
-                       else
-                               return(ESUCCESS);
-               case    0x7:
-                       if(!silent)
-                       {
-                               printf("ch%d: attempted protection violation"
-                                                               , unit); 
-                               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("\n");
-                       }
-                       return(EACCES);
-               case    0x8:
-                       if(!silent)
-                       {
-                               printf("ch%d: block wrong state (worm)"
-                                                       , unit); 
-                               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("\n");
-                       }
-                       return(EIO);
-               case    0x9:
-                       if(!silent) printf("ch%d: vendor unique\n", unit); 
-                       return(EIO);
-               case    0xa:
-                       if(!silent) printf("ch%d: copy aborted\n", unit); 
-                       return(EIO);
-               case    0xb:
-                       if(!silent) printf("ch%d: command aborted\n", unit); 
-                       ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)|
-                                               sense->ext.extended.info[13] ;
-                       return(EIO);
-               case    0xc:
-                       if(!silent)
-                       {
-                               printf("ch%d: search returned", unit); 
-                               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("\n");
-                       }
-                       return(ESUCCESS);
-               case    0xd:
-                       if(!silent) printf("ch%d: volume overflow\n", unit); 
-                       return(ENOSPC);
-               case    0xe:
-                       if(!silent)
-                       {
-                               printf("ch%d: verify miscompare", unit); 
-                               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("\n");
-                       }
-                       return(EIO);
-               case    0xf:
-                       if(!silent) printf("ch%d: unknown error key\n", unit); 
-                       return(EIO);
-               }
-               break;
-       }
-       /***************************************************************\
-       * If it's NOT class 7, just report it.                          *
-       \***************************************************************/
-       default:
-               {
-                       if(!silent)
-                       {
-                               printf("ch%d: error code %d",
-                                       unit,
-                                       sense->error_code & SSD_ERRCODE);
-                               if(sense->error_code & SSD_ERRCODE_VALID)
-                               {
-                                       printf(" block no. %d (decimal)",
-                                       (sense->ext.unextended.blockhi <<16),
-                                       + (sense->ext.unextended.blockmed <<8),
-                                       + (sense->ext.unextended.blocklow ));
-                               }
-                               printf("\n");
-                       }
+                       break;
                }
                }
-               return(EIO);
+               b += pl;
+               i += pl + 2;
        }
        }
+       SC_DEBUG(sc_link, SDEV_DB2,
+           (" cht(%d-%d)slot(%d-%d)imex(%d-%d)cts(%d-%d) %s rotate\n",
+               ch_data[unit].chmo, ch_data[unit].chms,
+               ch_data[unit].sloto, ch_data[unit].slots,
+               ch_data[unit].imexo, ch_data[unit].imexs,
+               ch_data[unit].driveo, ch_data[unit].drives,
+               ch_data[unit].rot ? "can" : "can't"));
+       return (0);
 }
 }
-
-
-
index 8de19b0..2e7bdcf 100644 (file)
  *
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  *
  *
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  *
- *     $Id: scsi_all.h,v 1.4 1993/08/21 20:01:51 rgrimes Exp $
+ *     $Id: scsi_all.h,v 2.0 93/10/06 21:10:28 julian Exp Locker: julian $
  */
 
  */
 
-#ifndef _SCSI_SCSI_ALL_H_
-#define _SCSI_SCSI_ALL_H_ 1
-
+#ifndef        _SCSI_SCSI_ALL_H
+#define _SCSI_SCSI_ALL_H 1
 /*
  * SCSI command format
  */
 /*
  * SCSI command format
  */
 /*
  * Define dome bits that are in ALL (or a lot of) scsi commands
  */
 /*
  * Define dome bits that are in ALL (or a lot of) scsi commands
  */
-#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_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 */
 
 
 #define        SCSI_CMD_LUN_SHIFT      5       /* LUN in the cmd is no longer SCSI */
 
 
@@ -103,7 +102,7 @@ struct scsi_mode_sense
 struct scsi_mode_sense_big
 {
        u_char  op_code;
 struct scsi_mode_sense_big
 {
        u_char  op_code;
-       u_char  byte2;  /* same bits as small version */
+       u_char  byte2;          /* same bits as small version */
        u_char  page;           /* same bits as small version */
        u_char  unused[4];
        u_char  length[2];
        u_char  page;           /* same bits as small version */
        u_char  unused[4];
        u_char  length[2];
@@ -124,7 +123,7 @@ struct scsi_mode_select
 struct scsi_mode_select_big
 {
        u_char  op_code;
 struct scsi_mode_select_big
 {
        u_char  op_code;
-       u_char  byte2;  /* same bits as small version */
+       u_char  byte2;          /* same bits as small version */
        u_char  unused[5];
        u_char  length[2];
        u_char  control;
        u_char  unused[5];
        u_char  length[2];
        u_char  control;
@@ -159,6 +158,19 @@ struct scsi_prevent
 #define        PR_PREVENT 0x01
 #define PR_ALLOW   0x00
 
 #define        PR_PREVENT 0x01
 #define PR_ALLOW   0x00
 
+struct scsi_changedef
+{
+       u_char  op_code;
+       u_char  byte2;
+       u_char  unused1;
+       u_char  how;
+       u_char  unused[4];
+       u_char  datalen;
+       u_char  control;
+};
+#define SC_SCSI_1 0x01
+#define SC_SCSI_2 0x03
+
 /*
  * Opcodes
  */
 /*
  * Opcodes
  */
@@ -173,6 +185,7 @@ struct scsi_prevent
 #define RELEASE                0x17
 #define PREVENT_ALLOW          0x1e
 #define POSITION_TO_ELEMENT    0x2b
 #define RELEASE                0x17
 #define PREVENT_ALLOW          0x1e
 #define POSITION_TO_ELEMENT    0x2b
+#define        CHANGE_DEFINITION       0x40
 #define        MODE_SENSE_BIG          0x54
 #define        MODE_SELECT_BIG         0x55
 #define MOVE_MEDIUM            0xa5
 #define        MODE_SENSE_BIG          0x54
 #define        MODE_SELECT_BIG         0x55
 #define MOVE_MEDIUM            0xa5
@@ -234,62 +247,62 @@ struct scsi_inquiry_data
 
 struct scsi_sense_data
 {
 
 struct scsi_sense_data
 {
-       u_char  error_code;     /* same bits as new version */
+/* 1*/ u_char  error_code;     /* same bits as new version */
        union
        {
                struct
                {
        union
        {
                struct
                {
-                       u_char  blockhi;
-                       u_char  blockmed;
-                       u_char  blocklow;
+/* 2*/                 u_char  blockhi;
+/* 3*/                 u_char  blockmed;
+/* 4*/                 u_char  blocklow;
                } unextended;
                struct
                {
                } unextended;
                struct
                {
-                       u_char  segment;
-                       u_char  flags;  /* same bits as new version */
-                       u_char  info[4];
-                       u_char  extra_len;
+/* 2*/                 u_char  segment;
+/* 3*/                 u_char  flags;  /* same bits as new version */
+/* 7*/                 u_char  info[4];
+/* 8*/                 u_char  extra_len;
                        /* allocate enough room to hold new stuff
                        /* allocate enough room to hold new stuff
-                       ( by increasing 16 to 26 below) */
-                       u_char  extra_bytes[26];
+                       ( by increasing 16 to 24 below) */
+/*32*/                 u_char  extra_bytes[24];
                } extended;
        }ext;
                } extended;
        }ext;
-};
+};     /* total of 32 bytes */
 struct scsi_sense_data_new
 {
 struct scsi_sense_data_new
 {
-       u_char  error_code;
+/* 1*/ u_char  error_code;
 #define        SSD_ERRCODE             0x7F
 #define        SSD_ERRCODE_VALID       0x80
        union
        {
 #define        SSD_ERRCODE             0x7F
 #define        SSD_ERRCODE_VALID       0x80
        union
        {
-               struct  /* this is depreciated, the standard says "DON'T"*/
+               struct  /* this is deprecated, the standard says "DON'T"*/
                {
                {
-                       u_char  blockhi;
-                       u_char  blockmed;
-                       u_char  blocklow;
+/* 2*/                 u_char  blockhi;
+/* 3*/                 u_char  blockmed;
+/* 4*/                 u_char  blocklow;
                } unextended;
                struct
                {
                } unextended;
                struct
                {
-                       u_char  segment;
-                       u_char  flags;
+/* 2*/                 u_char  segment;
+/* 3*/                 u_char  flags;
 #define        SSD_KEY         0x0F
 #define        SSD_ILI         0x20
 #define        SSD_EOM         0x40
 #define        SSD_FILEMARK    0x80
 #define        SSD_KEY         0x0F
 #define        SSD_ILI         0x20
 #define        SSD_EOM         0x40
 #define        SSD_FILEMARK    0x80
-                       u_char  info[4];
-                       u_char  extra_len;
-                       u_char  cmd_spec_info[4];
-                       u_char  add_sense_code;
-                       u_char  add_sense_code_qual;
-                       u_char  fru;
-                       u_char  sense_key_spec_1;
+/* 7*/                 u_char  info[4];
+/* 8*/                 u_char  extra_len;
+/*12*/                 u_char  cmd_spec_info[4];
+/*13*/                 u_char  add_sense_code;
+/*14*/                 u_char  add_sense_code_qual;
+/*15*/                 u_char  fru;
+/*16*/                 u_char  sense_key_spec_1;
 #define        SSD_SCS_VALID           0x80
 #define        SSD_SCS_VALID           0x80
-                       u_char  sense_key_spec_2;
-                       u_char  sense_key_spec_3;
-                       u_char  extra_bytes[16];
+/*17*/                 u_char  sense_key_spec_2;
+/*18*/                 u_char  sense_key_spec_3;
+/*32*/                 u_char  extra_bytes[14];
                } extended;
        }ext;
                } extended;
        }ext;
-};
+}; /* total of 32 bytes */
 
 struct blk_desc
 {
 
 struct blk_desc
 {
@@ -324,4 +337,4 @@ struct scsi_mode_header_big
 #define        SCSI_CHECK              0x02
 #define        SCSI_BUSY               0x08    
 #define SCSI_INTERM            0x10
 #define        SCSI_CHECK              0x02
 #define        SCSI_BUSY               0x08    
 #define SCSI_INTERM            0x10
-#endif /* _SCSI_SCSI_ALL_H_ */
+#endif /*_SCSI_SCSI_ALL_H*/
diff --git a/sys/scsi/scsi_base.c b/sys/scsi/scsi_base.c
new file mode 100644 (file)
index 0000000..a1361ec
--- /dev/null
@@ -0,0 +1,852 @@
+/*
+ * Written By Julian ELischer
+ * Copyright julian Elischer 1993.
+ * Permission is granted to use or redistribute this file in any way as long
+ * as this notice remains. Julian Elischer does not guarantee that this file 
+ * is totally correct for any given task and users of this file must 
+ * accept responsibility for any damage that occurs from the application of this
+ * file.
+ * 
+ * Written by Julian Elischer (julian@dialix.oz.au)
+ *      $Id: scsi_base.c,v 2.4 93/10/16 00:58:43 julian Exp Locker: julian $
+ */
+
+#define SPLSD splbio
+#define ESUCCESS 0
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+#include <sys/errno.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsi_disk.h>
+#include <scsi/scsiconf.h>
+
+#ifdef NetBSD
+#ifdef DDB
+int     Debugger();
+#else  /* DDB */
+#define Debugger()
+#endif /* DDB */
+#else /* NetBSD */
+#include <ddb.h>
+#if    NDDB > 0
+int     Debugger();
+#else  /* NDDB > 0 */
+#define Debugger()
+#endif /* NDDB > 0 */
+#endif
+
+void   sc_print_addr __P((struct scsi_link *sc_link));
+
+struct scsi_xfer *next_free_xs;
+
+/*
+ * Get a scsi transfer structure for the caller. Charge the structure
+ * to the device that is referenced by the sc_link structure. If the 
+ * sc_link structure has no 'credits' then the device already has the
+ * maximum number or outstanding operations under way. In this stage,
+ * wait on the structure so that when one is freed, we are awoken again
+ * If the SCSI_NOSLEEP flag is set, then do not wait, but rather, return
+ * a NULL pointer, signifying that no slots were available
+ * Note in the link structure, that we are waiting on it.
+ */
+
+struct scsi_xfer *
+get_xs(sc_link, flags)
+       struct  scsi_link *sc_link;     /* who to charge the xs to */
+       u_int32 flags;                  /* if this call can sleep */
+{
+       struct  scsi_xfer *xs;
+       u_int32 s;
+
+       SC_DEBUG(sc_link, SDEV_DB3, ("get_xs\n"));
+       s = splbio();
+       while (!sc_link->opennings) {
+               SC_DEBUG(sc_link, SDEV_DB3, ("sleeping\n"));
+               if (flags & SCSI_NOSLEEP) {
+                       splx(s);
+                       return 0;
+               }
+               sc_link->flags |= SDEV_WAITING;
+               sleep(sc_link, PRIBIO);
+       }
+       sc_link->opennings--;
+       if (xs = next_free_xs) {
+               next_free_xs = xs->next;
+               splx(s);
+       } else {
+               splx(s);
+               SC_DEBUG(sc_link, SDEV_DB3, ("making\n"));
+               xs = malloc(sizeof(*xs), M_TEMP,
+                   ((flags & SCSI_NOSLEEP) ? M_NOWAIT : M_WAITOK));
+               if (xs == NULL) {
+                       sc_print_addr(sc_link);
+                       printf("cannot allocate scsi xs\n");
+                       return (NULL);
+               }
+       }
+       SC_DEBUG(sc_link, SDEV_DB3, ("returning\n"));
+       xs->sc_link = sc_link;
+       return (xs);
+}
+
+/*
+ * Given a scsi_xfer struct, and a device (referenced through sc_link)
+ * return the struct to the free pool and credit the device with it
+ * If another process is waiting for an xs, do a wakeup, let it proceed
+ */
+void 
+free_xs(xs, sc_link, flags)
+       struct scsi_xfer *xs;
+       struct scsi_link *sc_link;      /* who to credit for returning it */
+       u_int32 flags;
+{
+       xs->next = next_free_xs;
+       next_free_xs = xs;
+
+       SC_DEBUG(sc_link, SDEV_DB3, ("free_xs\n"));
+       /* if was 0 and someone waits, wake them up */
+       if ((!sc_link->opennings++) && (sc_link->flags & SDEV_WAITING)) {
+               wakeup(sc_link);
+       } else {
+               if (sc_link->device->start) {
+                       SC_DEBUG(sc_link, SDEV_DB2, ("calling private start()\n"));
+                       (*(sc_link->device->start)) (sc_link->dev_unit);
+               }
+       }
+}
+
+/*
+ * Find out from the device what its capacity is.
+ */
+u_int32 
+scsi_size(sc_link, flags)
+       struct scsi_link *sc_link;
+       u_int32 flags;
+{
+       struct scsi_read_cap_data rdcap;
+       struct scsi_read_capacity scsi_cmd;
+       u_int32 size;
+
+       /*
+        * make up a scsi command and ask the scsi driver to do
+        * it for you.
+        */
+       bzero(&scsi_cmd, sizeof(scsi_cmd));
+       scsi_cmd.op_code = READ_CAPACITY;
+
+       /*
+        * If the command works, interpret the result as a 4 byte
+        * number of blocks
+        */
+       if (scsi_scsi_cmd(sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               (u_char *) & rdcap,
+               sizeof(rdcap),
+               2,
+               20000,
+               NULL,
+               flags | SCSI_DATA_IN) != 0) {
+
+               sc_print_addr(sc_link);
+               printf("could not get size\n");
+               return (0);
+       } else {
+               size = rdcap.addr_0 + 1;
+               size += rdcap.addr_1 << 8;
+               size += rdcap.addr_2 << 16;
+               size += rdcap.addr_3 << 24;
+       }
+       return (size);
+}
+
+/*
+ * Get scsi driver to send a "are you ready?" command
+ */
+errval 
+scsi_test_unit_ready(sc_link, flags)
+       struct scsi_link *sc_link;
+       u_int32 flags;
+{
+       struct scsi_test_unit_ready scsi_cmd;
+
+       bzero(&scsi_cmd, sizeof(scsi_cmd));
+       scsi_cmd.op_code = TEST_UNIT_READY;
+
+       return (scsi_scsi_cmd(sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               0,
+               0,
+               2,
+               100000,
+               NULL,
+               flags));
+}
+
+/*
+ * Do a scsi operation, asking a device to run as SCSI-II if it can.
+ */
+errval 
+scsi_change_def(sc_link, flags)
+       struct scsi_link *sc_link;
+       u_int32 flags;
+{
+       struct scsi_changedef scsi_cmd;
+
+       bzero(&scsi_cmd, sizeof(scsi_cmd));
+       scsi_cmd.op_code = CHANGE_DEFINITION;
+       scsi_cmd.how = SC_SCSI_2;
+
+       return (scsi_scsi_cmd(sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               0,
+               0,
+               2,
+               100000,
+               NULL,
+               flags));
+}
+
+/*
+ * Do a scsi operation asking a device what it is
+ * Use the scsi_cmd routine in the switch table.
+ */
+errval 
+scsi_inquire(sc_link, inqbuf, flags)
+       struct scsi_link *sc_link;
+       struct scsi_inquiry_data *inqbuf;
+       u_int32 flags;
+{
+       struct scsi_inquiry scsi_cmd;
+
+       bzero(&scsi_cmd, sizeof(scsi_cmd));
+       scsi_cmd.op_code = INQUIRY;
+       scsi_cmd.length = sizeof(struct scsi_inquiry_data);
+
+       return (scsi_scsi_cmd(sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               (u_char *) inqbuf,
+               sizeof(struct scsi_inquiry_data),
+               2,
+               100000,
+               NULL,
+               SCSI_DATA_IN | flags));
+}
+
+/*
+ * Prevent or allow the user to remove the media
+ */
+errval 
+scsi_prevent(sc_link, type, flags)
+       struct scsi_link *sc_link;
+       u_int32 type, flags;
+{
+       struct scsi_prevent scsi_cmd;
+
+       bzero(&scsi_cmd, sizeof(scsi_cmd));
+       scsi_cmd.op_code = PREVENT_ALLOW;
+       scsi_cmd.how = type;
+       return (scsi_scsi_cmd(sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               0,
+               0,
+               2,
+               5000,
+               NULL,
+               flags));
+}
+
+/*
+ * Get scsi driver to send a "start up" command
+ */
+errval 
+scsi_start_unit(sc_link, flags)
+       struct scsi_link *sc_link;
+       u_int32 flags;
+{
+       struct scsi_start_stop scsi_cmd;
+
+       bzero(&scsi_cmd, sizeof(scsi_cmd));
+       scsi_cmd.op_code = START_STOP;
+       scsi_cmd.how = SSS_START;
+
+       return (scsi_scsi_cmd(sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               0,
+               0,
+               2,
+               6000,
+               NULL,
+               flags));
+}
+
+/*
+ * This routine is called by the scsi interrupt when the transfer is complete.
+ */
+void 
+scsi_done(xs)
+       struct scsi_xfer *xs;
+{
+       struct scsi_link *sc_link = xs->sc_link;
+       struct buf *bp = xs->bp;
+       errval  retval;
+
+       SC_DEBUG(sc_link, SDEV_DB2, ("scsi_done\n"));
+#ifdef SCSIDEBUG
+       if (sc_link->flags & SDEV_DB1)
+       {
+               show_scsi_cmd(xs);
+       }
+#endif /*SCSIDEBUG */
+       /*
+        * If it's a user level request, bypass all usual completion processing,
+        * let the user work it out.. We take reponsibility for freeing the
+        * xs when the user returns. (and restarting the device's queue).
+        */
+       if (xs->flags & SCSI_USER) {
+               biodone(xs->bp);
+#ifdef NOTNOW
+               SC_DEBUG(sc_link, SDEV_DB3, ("calling user done()\n"));
+               scsi_user_done(xs); /* to take a copy of the sense etc. */
+               SC_DEBUG(sc_link, SDEV_DB3, ("returned from user done()\n "));
+#endif
+               free_xs(xs, sc_link, SCSI_NOSLEEP); /* restarts queue too */
+               SC_DEBUG(sc_link, SDEV_DB3, ("returning to adapter\n"));
+               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.
+        */
+
+       if (sc_link->device->done) {
+               SC_DEBUG(sc_link, SDEV_DB2, ("calling private done()\n"));
+               retval = (*sc_link->device->done) (xs);
+               if (retval == -1) {
+                       free_xs(xs, sc_link, SCSI_NOSLEEP);     /*XXX */
+                       return; /* it did it all, finish up */
+               }
+               if (retval == -2) {
+                       return; /* it did it all, finish up */
+               }
+               SC_DEBUG(sc_link, SDEV_DB3, ("continuing with generic done()\n"));
+       }
+       if ((bp = xs->bp) == NULL) {
+               /*
+                * if it's a normal upper level request, then ask
+                * the upper level code to handle error checking
+                * rather than doing it here at interrupt time
+                */
+               wakeup(xs);
+               return;
+       }
+       /*
+        * Go and handle errors now.
+        * If it returns -1 then we should RETRY
+        */
+       if ((retval = sc_err1(xs)) == -1) {
+               if ((*(sc_link->adapter->scsi_cmd)) (xs)
+                   == SUCCESSFULLY_QUEUED) {   /* don't wake the job, ok? */
+                       return;
+               }
+               xs->flags |= ITSDONE;
+       }
+       free_xs(xs, sc_link, SCSI_NOSLEEP); /* does a start if needed */
+       biodone(bp);
+}
+
+/*
+ * ask the scsi driver to perform a command for us.
+ * tell it where to read/write the data, and how
+ * long the data is supposed to be. If we have  a buf
+ * to associate with the transfer, we need that too.
+ */
+errval 
+scsi_scsi_cmd(sc_link, scsi_cmd, cmdlen, data_addr, datalen,
+    retries, timeout, bp, flags)
+       struct scsi_link *sc_link;
+       struct scsi_generic *scsi_cmd;
+       u_int32 cmdlen;
+       u_char *data_addr;
+       u_int32 datalen;
+       u_int32 retries;
+       u_int32 timeout;
+       struct buf *bp;
+       u_int32 flags;
+{
+       struct scsi_xfer *xs;
+       errval  retval;
+       u_int32 s;
+
+       if (bp) flags |= SCSI_NOSLEEP;
+       SC_DEBUG(sc_link, SDEV_DB2, ("scsi_cmd\n"));
+
+       xs = get_xs(sc_link, flags);    /* should wait unless booting */
+       if (!xs) return (ENOMEM);
+       /*
+        * Fill out the scsi_xfer structure.  We don't know whose context
+        * the cmd is in, so copy it.
+        */
+       bcopy(scsi_cmd, &(xs->cmdstore), cmdlen);
+       xs->flags = INUSE | flags;
+       xs->sc_link = sc_link;
+       xs->retries = retries;
+       xs->timeout = timeout;
+       xs->cmd = &xs->cmdstore;
+       xs->cmdlen = cmdlen;
+       xs->data = data_addr;
+       xs->datalen = datalen;
+       xs->resid = datalen;
+       xs->bp = bp;
+/*XXX*/ /*use constant not magic number */
+       if (datalen && ((caddr_t) data_addr < (caddr_t) 0xfe000000)) {
+               if (bp) {
+                       printf("Data buffered space not in kernel context\n");
+#ifdef SCSIDEBUG
+                       show_scsi_cmd(xs);
+#endif /* SCSIDEBUG */
+                       retval = EFAULT;
+                       goto bad;
+               }
+               xs->data = malloc(datalen, M_TEMP, M_WAITOK);
+               /* I think waiting is ok *//*XXX */
+               switch (flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
+               case 0:
+                       printf("No direction flags, assuming both\n");
+#ifdef SCSIDEBUG
+                       show_scsi_cmd(xs);
+#endif /* SCSIDEBUG */
+               case SCSI_DATA_IN | SCSI_DATA_OUT:      /* weird */
+               case SCSI_DATA_OUT:
+                       bcopy(data_addr, xs->data, datalen);
+                       break;
+               case SCSI_DATA_IN:
+                       bzero(xs->data, datalen);
+               }
+       }
+retry:
+       xs->error = XS_NOERROR;
+#ifdef PARANOID
+       if (datalen && ((caddr_t) xs->data < (caddr_t) 0xfe000000)) {
+               printf("It's still wrong!\n");
+       }
+#endif /*PARANOID*/
+#ifdef SCSIDEBUG
+       if (sc_link->flags & SDEV_DB3) show_scsi_xs(xs);
+#endif /* SCSIDEBUG */
+       /*
+        * Do the transfer. If we are polling we will return:
+        * COMPLETE,  Was poll, and scsi_done has been called
+        * TRY_AGAIN_LATER, Adapter short resources, try again
+        * 
+        * if under full steam (interrupts) it will return:
+        * SUCCESSFULLY_QUEUED, will do a wakeup when complete
+        * 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 = (*(sc_link->adapter->scsi_cmd)) (xs);
+
+       switch (retval) {
+       case SUCCESSFULLY_QUEUED:
+               if (bp)
+                       return retval;  /* will sleep (or not) elsewhere */
+               s = splbio();
+               while (!(xs->flags & ITSDONE))
+                       sleep(xs, PRIBIO + 1);
+               splx(s);
+               /* fall through to check success of completed command */
+       case COMPLETE:          /* Polling command completed ok */
+/*XXX*/        case HAD_ERROR:         /* Polling command completed with error */
+               SC_DEBUG(sc_link, SDEV_DB3, ("back in cmd()\n"));
+               if ((retval = sc_err1(xs)) == -1)
+                       goto retry;
+               break;
+
+       case TRY_AGAIN_LATER:   /* adapter resource shortage */
+               SC_DEBUG(sc_link, SDEV_DB3, ("will try again \n"));
+               /* should sleep 1 sec here */
+               if (xs->retries--) {
+                       xs->flags &= ~ITSDONE;
+                       goto retry;
+               }
+       default:
+               retval = EIO;
+       }
+       /*
+        * If we had to copy the data out of the user's context,
+        * then do the other half (copy it back or whatever)
+        * and free the memory buffer
+        */
+       if (datalen && (xs->data != data_addr)) {
+               switch (flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
+               case 0:
+               case SCSI_DATA_IN | SCSI_DATA_OUT:      /* weird */
+               case SCSI_DATA_IN:
+                       bcopy(xs->data, data_addr, datalen);
+                       break;
+               }
+               free(xs->data, M_TEMP);
+       }
+       /*
+        * we have finished with the xfer stuct, free it and
+        * check if anyone else needs to be started up.
+        */
+bad:
+       free_xs(xs, sc_link, flags);    /* includes the 'start' op */
+       if (bp && retval) {
+               bp->b_error = retval;
+               bp->b_flags |= B_ERROR;
+               biodone(bp);
+       }
+       return (retval);
+}
+
+errval 
+sc_err1(xs)
+       struct scsi_xfer *xs;
+{
+       struct buf *bp = xs->bp;
+       errval  retval;
+
+       SC_DEBUG(xs->sc_link, SDEV_DB3, ("sc_err1,err = 0x%x \n", xs->error));
+       /*
+        * If it has a buf, we might be working with
+        * a request from the buffer cache or some other
+        * piece of code that requires us to process
+        * errors at inetrrupt time. We have probably
+        * been called by scsi_done()
+        */
+       switch (xs->error) {
+       case XS_NOERROR:        /* nearly always hit this one */
+               retval = ESUCCESS;
+               if (bp) {
+                       bp->b_error = 0;
+                       bp->b_resid = 0;
+               }
+               break;
+
+       case XS_SENSE:
+               if (bp) {
+                       bp->b_error = 0;
+                       bp->b_resid = 0;
+                       if (retval = (scsi_interpret_sense(xs))) {
+                               bp->b_flags |= B_ERROR;
+                               bp->b_error = retval;
+                               bp->b_resid = bp->b_bcount;
+                       }
+                       SC_DEBUG(xs->sc_link, SDEV_DB3,
+                           ("scsi_interpret_sense (bp) returned %d\n", retval));
+               } else {
+                       retval = (scsi_interpret_sense(xs));
+                       SC_DEBUG(xs->sc_link, SDEV_DB3,
+                           ("scsi_interpret_sense (no bp) returned %d\n", 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;
+                       goto retry;
+               }
+               /* fall through */
+       case XS_DRIVER_STUFFUP:
+               if (bp) {
+                       bp->b_flags |= B_ERROR;
+                       bp->b_error = EIO;
+               }
+               retval = EIO;
+               break;
+       default:
+               retval = EIO;
+               sc_print_addr(xs->sc_link);
+               printf("unknown error category from scsi driver\n");
+       }
+       return retval;
+retry:
+       return (-1);
+}
+
+/*
+ * Look at the returned sense and act on the error, determining
+ * the unix error number to pass back.  (0 = report no error)
+ *
+ * THIS IS THE DEFAULT ERROR HANDLER
+ */
+errval 
+scsi_interpret_sense(xs)
+       struct scsi_xfer *xs;
+{
+       struct scsi_sense_data *sense;
+       struct scsi_link *sc_link = xs->sc_link;
+       u_int32 key;
+       u_int32 silent;
+       u_int32 info;
+       errval  errcode;
+
+       static char *error_mes[] =
+       {"soft error (corrected)",
+           "not ready", "medium error",
+           "non-media hardware failure", "illegal request",
+           "unit attention", "readonly device",
+           "no data found", "vendor unique",
+           "copy aborted", "command aborted",
+           "search returned equal", "volume overflow",
+           "verify miscompare", "unknown error key"
+       };
+
+       /*
+        * If the flags say errs are ok, then always return ok.
+        */
+       if (xs->flags & SCSI_ERR_OK)
+               return (ESUCCESS);
+
+       sense = &(xs->sense);
+#ifdef SCSIDEBUG
+       if (sc_link->flags & SDEV_DB1) {
+               u_int32 count = 0;
+               printf("code%x valid%x ",
+                   sense->error_code & SSD_ERRCODE,
+                   sense->error_code & SSD_ERRCODE_VALID ? 1 : 0);
+               printf("seg%x key%x ili%x eom%x fmark%x\n",
+                   sense->ext.extended.segment,
+                   sense->ext.extended.flags & SSD_KEY,
+                   sense->ext.extended.flags & SSD_ILI ? 1 : 0,
+                   sense->ext.extended.flags & SSD_EOM ? 1 : 0,
+                   sense->ext.extended.flags & SSD_FILEMARK ? 1 : 0);
+               printf("info: %x %x %x %x followed by %d extra bytes\n",
+                   sense->ext.extended.info[0],
+                   sense->ext.extended.info[1],
+                   sense->ext.extended.info[2],
+                   sense->ext.extended.info[3],
+                   sense->ext.extended.extra_len);
+               printf("extra: ");
+               while (count < sense->ext.extended.extra_len) {
+                       printf("%x ", sense->ext.extended.extra_bytes[count++]);
+               }
+               printf("\n");
+       }
+#endif /*SCSIDEBUG */
+       /*
+        * If the device has it's own error handler, call it first.
+        * If it returns a legit error value, return that, otherwise
+        * it wants us to continue with normal error processing.
+        */
+       if (sc_link->device->err_handler) {
+               SC_DEBUG(sc_link, SDEV_DB2, ("calling private err_handler()\n"));
+               errcode = (*sc_link->device->err_handler) (xs);
+               if (errcode != -1)
+                       return errcode;         /* errcode >= 0  better ? */
+       }
+       /* otherwise use the default */
+       silent = (xs->flags & SCSI_SILENT);
+       switch (sense->error_code & SSD_ERRCODE) {
+               /*
+                * If it's code 70, use the extended stuff and interpret the key
+                */
+       case 0x71:              /* delayed error */
+               sc_print_addr(sc_link);
+               key = sense->ext.extended.flags & SSD_KEY;
+               printf(" DELAYED ERROR, key = 0x%x\n", key);
+       case 0x70:
+               if (sense->error_code & SSD_ERRCODE_VALID) {
+                       info = ntohl(*((long *) sense->ext.extended.info));
+               } else {
+                       info = 0;
+               }
+               key = sense->ext.extended.flags & SSD_KEY;
+
+               if (key && !silent) {
+                       sc_print_addr(sc_link);
+                       printf("%s", error_mes[key - 1]);
+                       if (sense->error_code & SSD_ERRCODE_VALID) {
+                               switch (key) {
+                               case 0x2:       /* NOT READY */
+                               case 0x5:       /* ILLEGAL REQUEST */
+                               case 0x6:       /* UNIT ATTENTION */
+                               case 0x7:       /* DATA PROTECT */
+                                       break;
+                               case 0x8:       /* BLANK CHECK */
+                                       printf(", requested size: %d (decimal)",
+                                           info);
+                                       break;
+                               default:
+                                       printf(", info = %d (decimal)", info);
+                               }
+                       }
+                       printf("\n");
+               }
+               switch (key) {
+               case 0x0:       /* NO SENSE */
+               case 0x1:       /* RECOVERED ERROR */
+                       if (xs->resid == xs->datalen)
+                               xs->resid = 0;  /* not short read */
+               case 0xc:       /* EQUAL */
+                       return (ESUCCESS);
+               case 0x2:       /* NOT READY */
+                       sc_link->flags &= ~SDEV_MEDIA_LOADED;
+                       return (EBUSY);
+               case 0x5:       /* ILLEGAL REQUEST */
+                       return (EINVAL);
+               case 0x6:       /* UNIT ATTENTION */
+                       sc_link->flags &= ~SDEV_MEDIA_LOADED;
+                       if (sc_link->flags & SDEV_OPEN) {
+                               return (EIO);
+                       } else {
+                               return 0;
+                       }
+               case 0x7:       /* DATA PROTECT */
+                       return (EACCES);
+               case 0xd:       /* VOLUME OVERFLOW */
+                       return (ENOSPC);
+               case 0x8:       /* BLANK CHECK */
+                       return (ESUCCESS);
+               default:
+                       return (EIO);
+               }
+       /*
+        * Not code 70, just report it
+        */
+       default:
+               if (!silent) {
+                       sc_print_addr(sc_link);
+                       printf("error code %d",
+                           sense->error_code & SSD_ERRCODE);
+                       if (sense->error_code & SSD_ERRCODE_VALID) {
+                               printf(" at block no. %d (decimal)",
+                                   (sense->ext.unextended.blockhi << 16) +
+                                   (sense->ext.unextended.blockmed << 8) +
+                                   (sense->ext.unextended.blocklow));
+                       }
+                       printf("\n");
+               }
+               return (EIO);
+       }
+}
+
+/*
+ * Utility routines often used in SCSI stuff
+ */
+
+/*
+ * convert a physical address to 3 bytes, 
+ * MSB at the lowest address,
+ * LSB at the highest.
+ */
+void
+lto3b(val, bytes)
+       int     val;
+       u_char  *bytes;
+{
+       *bytes++ = (val & 0xff0000) >> 16;
+       *bytes++ = (val & 0xff00) >> 8;
+       *bytes = val & 0xff;
+}
+
+/*
+ * The reverse of lto3b
+ */
+int
+_3btol(bytes)
+       u_char *bytes;
+{
+       u_int32 rc;
+       rc = (*bytes++ << 16);
+       rc += (*bytes++ << 8);
+       rc += *bytes;
+       return ((int) rc);
+}
+
+/*
+ * Print out the scsi_link structure's address info.
+ */
+
+void
+sc_print_addr(sc_link)
+       struct  scsi_link *sc_link;
+{
+
+       printf("%s%d(%s%d:%d:%d): ", sc_link->device->name, sc_link->dev_unit,  
+               sc_link->adapter->name,  sc_link->adapter_unit, 
+               sc_link->target,         sc_link->lun);         
+}
+#ifdef SCSIDEBUG
+/*
+ * Given a scsi_xfer, dump the request, in all it's glory
+ */
+void
+show_scsi_xs(xs)
+       struct scsi_xfer *xs;
+{
+       printf("xs(0x%x): ", xs);
+       printf("flg(0x%x)", xs->flags);
+       printf("sc_link(0x%x)", xs->sc_link);
+       printf("retr(0x%x)", xs->retries);
+       printf("timo(0x%x)", xs->timeout);
+       printf("cmd(0x%x)", xs->cmd);
+       printf("len(0x%x)", xs->cmdlen);
+       printf("data(0x%x)", xs->data);
+       printf("len(0x%x)", xs->datalen);
+       printf("res(0x%x)", xs->resid);
+       printf("err(0x%x)", xs->error);
+       printf("bp(0x%x)", xs->bp);
+       show_scsi_cmd(xs);
+}
+
+void
+show_scsi_cmd(struct scsi_xfer *xs)
+{
+       u_char *b = (u_char *) xs->cmd;
+       int     i = 0;
+
+       sc_print_addr(xs->sc_link);
+       printf("command: ");
+
+       if (!(xs->flags & SCSI_RESET)) {
+               while (i < xs->cmdlen) {
+                       if (i)
+                               printf(",");
+                       printf("%x", b[i++]);
+               }
+               printf("-[%d bytes]\n", xs->datalen);
+               if (xs->datalen)
+                       show_mem(xs->data, min(64, xs->datalen));
+       } else {
+               printf("-RESET-\n");
+       }
+}
+
+void
+show_mem(address, num)
+       unsigned char *address;
+       u_int32 num;
+{
+       u_int32 x, y;
+       printf("------------------------------");
+       for (y = 0; y < num; y += 1) {
+               if (!(y % 16))
+                       printf("\n%03d: ", y);
+               printf("%02x ", *address++);
+       }
+       printf("\n------------------------------\n");
+}
+#endif /*SCSIDEBUG */
index e9e80de..0a4759b 100644 (file)
  *
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  *
  *
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  *
- *     $Id: scsi_cd.h,v 1.4 1993/08/21 20:01:52 rgrimes Exp $
+ *     $Id: scsi_cd.h,v 1.6 93/08/26 21:09:19 julian Exp Locker: julian $
  */
  */
-
-#ifndef _SCSI_SCSI_CD_H_
-#define _SCSI_SCSI_CD_H_ 1
+#ifndef        _SCSI_SCSI_CD_H
+#define _SCSI_SCSI_CD_H 1
 
 /*
  *     Define two bits always in the same place in byte 2 (flag byte)
 
 /*
  *     Define two bits always in the same place in byte 2 (flag byte)
@@ -142,6 +141,7 @@ struct scsi_read_toc
        u_char  data_len[2];
        u_char  control;
 };
        u_char  data_len[2];
        u_char  control;
 };
+;
 
 struct scsi_read_cd_capacity
 {
 
 struct scsi_read_cd_capacity
 {
@@ -225,5 +225,5 @@ struct cd_mode_data
        struct blk_desc blk_desc;
        union cd_pages page;
 };
        struct blk_desc blk_desc;
        union cd_pages page;
 };
+#endif /*_SCSI_SCSI_CD_H*/
 
 
-#endif /* _SCSI_SCSI_CD_H_ */
index dda22ee..85819c8 100644 (file)
  *
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  *
  *
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  *
- *     $Id: scsi_changer.h,v 1.4 1993/08/21 20:01:53 rgrimes Exp $
+ *     $Id: scsi_changer.h,v 1.5 93/08/26 21:09:22 julian Exp Locker: julian $
  */
  */
-
-#ifndef _SCSI_SCSI_CHANGER_H_
-#define _SCSI_SCSI_CHANGER_H_ 1
+#ifndef _SCSI_SCSI_CHANGER_H
+#define _SCSI_SCSI_CHANGER_H 1
 
 /*
  * SCSI command format
 
 /*
  * SCSI command format
@@ -95,5 +94,5 @@ struct element_status_page
        u_char rsvd;
        u_char byte_count_of_descriptor_data[3];
 };
        u_char rsvd;
        u_char byte_count_of_descriptor_data[3];
 };
+#endif /*_SCSI_SCSI_CHANGER_H*/
 
 
-#endif /* _SCSI_SCSI_CHANGER_H_ */
diff --git a/sys/scsi/scsi_debug.h b/sys/scsi/scsi_debug.h
new file mode 100644 (file)
index 0000000..480ff14
--- /dev/null
@@ -0,0 +1,53 @@
+/*#define SCSIDEBUG 1*/
+/*
+ * Written by Julian Elischer (julian@tfs.com)
+ *
+ *     $Id: scsi_debug.h,v 1.3 93/10/10 09:26:05 julian Exp Locker: julian $
+ */
+#ifndef        _SCSI_SCSI_DEBUG_H
+#define _SCSI_SCSI_DEBUG_H 1
+
+/*
+ * These are the new debug bits.  (Sat Oct  2 12:46:46 WST 1993)
+ * the following DEBUG bits are defined to exist in the flags word of
+ * the scsi_link structure.
+ */
+#define        SDEV_DB1                0x10    /* scsi commands, errors, data  */ 
+#define        SDEV_DB2                0x20    /* routine flow tracking */
+#define        SDEV_DB3                0x40    /* internal to routine flows    */
+#define        SDEV_DB4                0x80    /* level 4 debugging for this dev */
+
+/* target and LUN we want to debug */
+#define        DEBUGTARG 9 /*9 = dissable*/
+#define        DEBUGLUN  0
+#define        DEBUGLEVEL      (SDEV_DB1|SDEV_DB2)
+/*
+ * This is the usual debug macro for use with the above bits
+ */
+#ifdef SCSIDEBUG
+#define        SC_DEBUG(sc_link,Level,Printstuff) \
+       if((sc_link)->flags & (Level))          \
+       {                                       \
+               printf("%s%d(%s%d:%d:%d): ",    \
+                       sc_link->device->name,  \
+                       sc_link->dev_unit,      \
+                       sc_link->adapter->name, \
+                       sc_link->adapter_unit,  \
+                       sc_link->target,        \
+                       sc_link->lun);          \
+               printf Printstuff;              \
+       }
+#define        SC_DEBUGN(sc_link,Level,Printstuff) \
+       if((sc_link)->flags & (Level))          \
+       {                                       \
+               printf Printstuff;              \
+       }
+#else
+#define SC_DEBUG(A,B,C) /* not included */
+#define SC_DEBUGN(A,B,C) /* not included */
+#endif
+
+#endif /*_SCSI_SCSI_DEBUG_H*/
+/* END OF FILE */
+
index e9cb724..60d0bcc 100644 (file)
@@ -3,7 +3,7 @@
  */
 
 /*
  */
 
 /*
- * Some lines of this file comes from a file of the name "scsi.h"
+ * Some lines of this file come from a file of the name "scsi.h"
  * distributed by OSF as part of mach2.5,
  *  so the following disclaimer has been kept.
  *
  * distributed by OSF as part of mach2.5,
  *  so the following disclaimer has been kept.
  *
  *
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  *
  *
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  *
- *     $Id: scsi_disk.h,v 1.4 1993/08/21 20:01:54 rgrimes Exp $
+ *     $Id: scsi_disk.h,v 1.4 93/08/26 21:09:23 julian Exp Locker: julian $
  */
 
  */
 
-#ifndef _SCSI_SCSI_DISK_H_
-#define _SCSI_SCSI_DISK_H_ 1
-
 /*
  * SCSI command format
  */
 
 /*
  * SCSI command format
  */
 
+#ifndef        _SCSI_SCSI_DISK_H
+#define _SCSI_SCSI_DISK_H 1
 
 struct scsi_reassign_blocks
 {
 
 struct scsi_reassign_blocks
 {
@@ -214,4 +213,4 @@ union       disk_pages /* this is the structure copied from osf */
           u_char reserved3;
        } rigid_geometry;
 } ;
           u_char reserved3;
        } rigid_geometry;
 } ;
-#endif /* _SCSI_SCSI_DISK_H*/
+#endif /* _SCSI_SCSI_DISK_H*/
diff --git a/sys/scsi/scsi_ioctl.c b/sys/scsi/scsi_ioctl.c
new file mode 100644 (file)
index 0000000..c1b576d
--- /dev/null
@@ -0,0 +1,329 @@
+/* 
+ * Contributed by HD Associates (hd@world.std.com).
+ * Copyright (c) 1992, 1993 HD Associates
+ *
+ * Berkeley style copyright.  
+ *
+ *
+ */
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/buf.h>
+#define        b_screq b_driver1       /* a patch in buf.h */
+#define        b_sc_link b_driver2     /* a patch in buf.h */
+#include <sys/proc.h>
+
+#include "scbus.h"
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <sys/scsiio.h>
+
+
+/*
+ * We let the user interpret his own sense in the generic scsi world.
+ * This routine is called at interrupt time if the SCSI_USER bit was set
+ * in the flags passed to scsi_scsi_cmd(). No other completion processing
+ * takes place, even if we are running over another device driver.
+ * The lower level routines that call us here, will free the xs and restart
+ * the device's queue if such exists.
+ */
+#ifndef min
+#define min(A,B) ((A<B) ? A : B )
+#endif
+
+void scsi_user_done(xs)
+struct scsi_xfer *xs;
+{
+
+       struct  buf     *bp;
+       scsireq_t *screq;
+
+       bp = xs->bp;
+       if(!bp) {       /* ALL user requests must have a buf */
+               sc_print_addr(xs->sc_link);
+               printf("User command with no buf\n");
+               return ;
+       }
+       screq = bp->b_screq;
+       if (!screq) {   /* Is it one of ours? (the SCSI_USER bit says it is) */
+               sc_print_addr(xs->sc_link);
+               printf("User command with no request\n");
+               return ;
+       }
+
+       SC_DEBUG(xs->sc_link,SDEV_DB2,("user-done\n"));
+       screq->retsts = 0;
+       screq->status = xs->status;
+       switch(xs->error) {
+       case    XS_NOERROR:
+               SC_DEBUG(xs->sc_link,SDEV_DB3,("no error\n"));
+               screq->datalen_used = xs->datalen - xs->resid; /* probably rubbish */
+               screq->retsts = SCCMD_OK;
+               break;
+
+       case    XS_SENSE:
+               SC_DEBUG(xs->sc_link,SDEV_DB3,("have sense\n"));
+               screq->senselen_used = min(sizeof(xs->sense),SENSEBUFLEN);
+               bcopy(&xs->sense,screq->sense,screq->senselen);
+               screq->retsts = SCCMD_SENSE;
+               break;
+
+       case    XS_DRIVER_STUFFUP:
+               sc_print_addr(xs->sc_link);
+               printf("host adapter code inconsistency\n");
+               screq->retsts = SCCMD_UNKNOWN;
+               break;
+
+       case    XS_TIMEOUT:
+               SC_DEBUG(xs->sc_link,SDEV_DB3,("timeout\n"));
+               screq->retsts = SCCMD_TIMEOUT;
+               break;
+
+       case    XS_BUSY:
+               SC_DEBUG(xs->sc_link,SDEV_DB3,("busy\n"));
+               screq->retsts = SCCMD_BUSY;
+               break;
+
+       default:
+               sc_print_addr(xs->sc_link);
+               printf("unknown error category from host adapter code\n");
+               screq->retsts = SCCMD_UNKNOWN;
+               break;
+       }
+       biodone(bp);    /* we're waiting on it in scsi_strategy() */
+       return;         /* it'll free the xs and restart any queue */
+}
+
+
+/* Pseudo strategy function
+ * Called by scsi_do_ioctl() via physio/physstrat if there is to
+ * be data transfered, and directly if there is no data transfer.
+ * 
+ * Should I reorganize this so it returns to physio instead
+ * of sleeping in scsiio_scsi_cmd?  Is there any advantage, other
+ * than avoiding the probable duplicate wakeup in iodone? [PD]
+ *
+ * No, seems ok to me... [JRE]
+ * (I don't see any duplicate wakeups)
+ *
+ * Can't be used with block devices or raw_read/raw_write directly
+ * from the cdevsw/bdevsw tables because they couldn't have added
+ * the screq structure. [JRE]
+ */
+void scsistrategy(struct buf *bp)
+{
+       errval err;
+       struct  scsi_link *sc_link = bp->b_sc_link;
+       scsireq_t *screq;
+       u_int32 flags = 0;
+       int s;
+
+
+       if(!sc_link) {
+               printf("user_strat: No link pointer\n");
+               scsierr(bp,EINVAL);
+               return;
+       }
+       SC_DEBUG(sc_link,SDEV_DB2,("user_strategy\n"));
+       screq = bp->b_screq;
+       if(!screq) {
+               sc_print_addr(sc_link);
+               printf("No request block\n");
+               scsierr(bp,EINVAL);
+               return;
+       }
+
+       /* We're in trouble if physio tried to break up the
+        * transfer:
+        */
+       if (bp->b_bcount != screq->datalen) {
+               sc_print_addr(sc_link);
+               printf("physio split the request.. cannot proceed\n");
+               scsierr(bp, EIO);
+               return;
+       }
+
+       if (screq->timeout == 0) {
+               scsierr(bp, EINVAL);
+               return;
+       }
+
+       if (screq->cmdlen > sizeof(struct scsi_generic)) {
+               sc_print_addr(sc_link);
+               printf("cmdlen too big ");
+               scsierr(bp, EFAULT);
+               return;
+       }
+
+
+       if (screq->flags & SCCMD_READ)
+               flags |= SCSI_DATA_IN;
+
+       if (screq->flags & SCCMD_WRITE)
+               flags |= SCSI_DATA_OUT;
+
+       if (screq->flags & SCCMD_TARGET)
+               flags |= SCSI_TARGET;
+
+       if (screq->flags & SCCMD_ESCAPE)
+               flags |= SCSI_ESCAPE;
+       err = scsi_scsi_cmd(sc_link,
+                       (struct scsi_generic *)screq->cmd,
+                       screq->cmdlen,
+                       (u_char *)bp->b_un.b_addr,
+                       screq->datalen,
+                       0,      /* user must do the retries *//* ignored */
+                       screq->timeout,
+                       bp,
+                       flags | SCSI_USER);
+
+
+
+       /*because there is a bp, scsi_scsi_cmd will return immediatly*/
+       if (err)
+       {
+               scsierr(bp, err);
+               return;
+       }
+       SC_DEBUG(sc_link,SDEV_DB3,("about to  sleep\n"));
+       s = splbio();
+       while(!(bp->b_flags & B_DONE))
+       {
+               sleep(bp,PRIBIO);
+       }
+       splx(s);
+       SC_DEBUG(sc_link,SDEV_DB3,("back from sleep\n"));
+       return;
+}
+
+void scsiminphys(struct buf *bp)
+{
+       /*XXX*//* call the adapter's minphys */
+}
+
+
+/*
+ * Something (e.g. another driver) has called us
+ * with an sc_link for a target/lun/adapter, and a scsi
+ * specific ioctl to perform, better try.
+ * If user-level type command, we must still be running
+ * in the context of the calling process
+ */
+errval scsi_do_ioctl(struct scsi_link *sc_link, int cmd, caddr_t addr, int f)
+{
+       errval ret = 0;
+       int phys;
+
+       SC_DEBUG(sc_link,SDEV_DB2,("scsi_do_ioctl(0x%x)\n",cmd));
+       switch(cmd)
+       {
+#ifndef NetBSD
+               case SCIOCCOMMAND:
+               {
+                       /*
+                        * You won't believe this, but the arg copied in
+                        * from the user space, is on the kernel stack
+                        * for this process, so we can't write
+                        * to it at interrupt time..
+                        * we need to copy it in and out!
+                        * Make a static copy using malloc!
+                        */
+                       scsireq_t *screq2 = (scsireq_t *)addr;
+                       scsireq_t *screq = (scsireq_t *)addr;
+                       int rwflag = (screq->flags & SCCMD_READ) ? B_READ : B_WRITE;
+                       struct buf *bp;
+                       caddr_t d_addr;
+                       int     len;
+
+                       if((unsigned int)screq < (unsigned int)0xfe000000)
+                       {
+                               screq = malloc(sizeof(scsireq_t),M_TEMP,M_WAITOK);
+                               bcopy(screq2,screq,sizeof(scsireq_t));
+                       }
+                       bp = malloc(sizeof (struct buf),M_TEMP,M_WAITOK);
+                       bzero(bp,sizeof(struct buf));
+                       d_addr = screq->databuf;
+                       bp->b_bcount = len = screq->datalen;
+                       bp->b_screq = screq;
+                       bp->b_sc_link = sc_link;
+                       if (len) {
+                               /* have data, translate it. (physio)*/
+#ifdef __NetBSD__
+#error "dev, mincntfn & uio need defining"
+                               ret = physio(scsistrategy, bp, dev, rwflag,
+                                       mincntfn, uio);
+#else
+                               ret = physio(scsistrategy,0,bp,0,rwflag,
+                                               d_addr,&len,curproc);
+#endif
+                       } else {
+                               /* if no data, no need to translate it.. */
+                               bp->b_un.b_addr = 0;
+                               bp->b_dev = -1; /* irrelevant info */
+                               bp->b_flags = 0;
+
+                               scsistrategy(bp);
+                               ret =  bp->b_error;
+                       }
+                       free(bp,M_TEMP);
+                       if((unsigned int)screq2 < (unsigned int)0xfe000000)
+                       {
+                               bcopy(screq,screq2,sizeof(scsireq_t));
+                               free(screq,M_TEMP);
+                       }
+                       break;
+               }
+#endif /* !NetBSD */
+               case SCIOCDEBUG:
+               {
+                       int level = *((int *)addr);
+                       SC_DEBUG(sc_link,SDEV_DB3,("debug set to %d\n",level));
+                       sc_link->flags &= ~SDEV_DBX; /*clear debug bits */
+                       if(level & 1) sc_link->flags |= SDEV_DB1;
+                       if(level & 2) sc_link->flags |= SDEV_DB2;
+                       if(level & 4) sc_link->flags |= SDEV_DB3;
+                       if(level & 8) sc_link->flags |= SDEV_DB4;
+                       ret = 0;
+                       break;
+               }
+               case SCIOCREPROBE:
+               {
+                       extern int scsibus;
+                       struct scsi_addr *sca = (struct scsi_addr *) addr;
+
+                       ret = scsi_probe_busses(sca->scbus,sca->target,sca->lun);
+                       break;
+               }
+               case SCIOCRECONFIG:
+               case SCIOCDECONFIG:
+                       ret = EINVAL;
+                       break;
+               case SCIOCIDENTIFY:
+               {
+                       struct scsi_addr *sca = (struct scsi_addr *) addr;
+                       sca->scbus      = sc_link->scsibus;
+                       sca->target     = sc_link->target;
+                       sca->lun        = sc_link->lun;
+                       break;
+               }
+
+               default:
+                       ret = ENOTTY;
+               break;
+       }
+
+       return ret;
+}
+
+scsierr(bp,err)
+struct buf *bp;
+int    err;
+{
+               bp->b_flags |= B_ERROR;
+               bp->b_error = err;
+               biodone(bp);
+               return;
+}
+
index 103e116..ac417c2 100644 (file)
 /*
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  *
 /*
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  *
- *     $Id: scsi_tape.h,v 1.6 1993/09/05 15:42:20 rgrimes Exp $
+ *     $Id: scsi_tape.h,v 1.8 93/08/31 21:40:16 julian Exp Locker: julian $
  */
  */
+#ifndef        SCSI_SCSI_TAPE_H
+#define SCSI_SCSI_TAPE_H 1
 
 
 
 
-#ifndef _SCSI_SCSI_TAPE_H_
-#define _SCSI_SCSI_TAPE_H_ 1
-
 
 /*
  * SCSI command formats
 
 /*
  * SCSI command formats
@@ -200,7 +199,6 @@ struct      blk_desc_cipher
 #define QIC_525                0x11
 #define QIC_1320       0x12
 #define DDS            0x13
 #define QIC_525                0x11
 #define QIC_1320       0x12
 #define DDS            0x13
-#define DAT-1          0x13
-
+#define DAT_1          0x13
 
 
-#endif /* _SCSI_SCSI_TAPE_H_ */
+#endif /*SCSI_SCSI_TAPE_H*/
index 70765b0..708cc7c 100644 (file)
  *
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  *
  *
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  *
- *     $Id: scsiconf.c,v 1.5 1993/08/28 03:08:53 rgrimes Exp $
+ *      $Id: scsiconf.c,v 2.6 93/10/24 12:43:51 julian Exp Locker: julian $
  */
 
 #include <sys/types.h>
  */
 
 #include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <sys/malloc.h>
 #include "st.h"
 #include "sd.h"
 #include "ch.h"
 #include "cd.h"
 #include "st.h"
 #include "sd.h"
 #include "ch.h"
 #include "cd.h"
-#include "sg.h"
+#include "uk.h"
+#include "su.h"
+#ifndef        NSCBUS
+#define        NSCBUS  8
+#endif /* NSCBUS */
 
 
-#ifdef MACH
-#include <i386/machparam.h>
-#endif MACH
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
 
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
 
-#if !defined(OSF) && !defined(__386BSD__)
+#ifdef TFS
 #include "bll.h"
 #include "cals.h"
 #include "kil.h"
 #include "bll.h"
 #include "cals.h"
 #include "kil.h"
-#else
+#include "scan.h"
+#else /* TFS */
 #define        NBLL 0
 #define        NCALS 0
 #define        NKIL 0
 #define        NBLL 0
 #define        NCALS 0
 #define        NKIL 0
-#endif /* !defined(OSF) && !defined(__386BSD__) */
+#define        NSCAN 0
+#endif /* TFS */
 
 #if NSD > 0
 
 #if NSD > 0
-extern sdattach();
-#endif NSD
+extern  sdattach();
+#endif /* NSD */
 #if NST > 0
 #if NST > 0
-extern stattach();
-#endif NST
+extern  stattach();
+#endif /* NST */
 #if NCH > 0
 #if NCH > 0
-extern chattach();
-#endif NCH
+extern  chattach();
+#endif /* NCH */
 #if NCD > 0
 #if NCD > 0
-extern cdattach();
-#endif NCD
+extern  cdattach();
+#endif /* NCD */
 #if NBLL > 0
 #if NBLL > 0
-extern bllattach();
-#endif NBLL
+extern  bllattach();
+#endif /* NBLL */
 #if NCALS > 0
 #if NCALS > 0
-extern calsattach();
-#endif NCALS
+extern  calsattach();
+#endif /* NCALS */
 #if NKIL > 0
 #if NKIL > 0
-extern kil_attach();
-#endif NKIL
-
-/***************************************************************\
-* The structure of pre-configured devices that might be turned *
-* off and therefore may not show up                            *
-\***************************************************************/
-struct predefined
-{
-       u_char  scsibus;
-       u_char  dev;
-       u_char  lu;
-       int     (*attach_rtn)();
-       char    *devname;
-       char    flags;
-}
-pd[] = 
+extern  kil_attach();
+#endif /* NKIL */
+#if NUK > 0
+extern  ukattach();
+#endif /* NUK */
+
+/*
+ * One of these is allocated and filled in for each scsi bus.
+ * it holds pointers to allow the scsi bus to get to the driver
+ * That is running each LUN on the bus
+ * it also has a template entry which is the prototype struct
+ * supplied by the adapter driver, this is used to initialise
+ * the others, before they have the rest of the fields filled in
+ */
+struct scsibus_data      *scbus_data[NSCBUS];
+
+/*
+ * The structure of pre-configured devices that might be turned
+ * off and therefore may not show up
+ */
+struct predefined {
+       u_char  scsibus;
+       u_char  dev;
+       u_char  lu;
+               errval(*attach_rtn) ();
+       char   *devname;
+       char    flags;
+} pd[] =
+
 {
 #ifdef EXAMPLE_PREDEFINE
 #if NSD > 0
 {
 #ifdef EXAMPLE_PREDEFINE
 #if NSD > 0
-       {0,0,0,sdattach,"sd",0},/* define a disk at scsibus=0 dev=0 lu=0 */
-#endif NSD
-#endif EXAMPLE_PREDEFINE
-       {0,9,9}                 /*illegal dummy end entry */
+       {
+               0, 0, 0, sdattach, "sd", 0
+       },                      /* define a disk at scsibus=0 dev=0 lu=0 */
+#endif /* NSD */
+#endif /* EXAMPLE_PREDEFINE */
+       {
+               0, 9, 9
+       } /*illegal dummy end entry */
 };
 
 };
 
+/*
+ * The structure of known drivers for autoconfiguration
+ */
+struct scsidevs {
+       u_int32 type;
+       boolean removable;
+       char   *manufacturer;
+       char   *model;
+       char   *version;
+               errval(*attach_rtn) ();
+       char   *devname;
+       char    flags;          /* 1 show my comparisons during boot(debug) */
+};
 
 
-/***************************************************************\
-* The structure of known drivers for autoconfiguration         *
-\***************************************************************/
-static struct scsidevs 
-{
-       int type;
-       int removable;
-       char    *manufacturer;
-       char    *model;
-       char    *version;
-       int     (*attach_rtn)();
-       char    *devname;
-       char    flags;          /* 1 show my comparisons during boot(debug) */
-}
 #define SC_SHOWME      0x01
 #define        SC_ONE_LU       0x00
 #define        SC_MORE_LUS     0x02
 #define SC_SHOWME      0x01
 #define        SC_ONE_LU       0x00
 #define        SC_MORE_LUS     0x02
-knowndevs[] = {
+#if    NUK > 0
+
+static struct scsidevs unknowndev = {
+       -1, 0, "standard", "any"
+           ,"any", ukattach, "uk", SC_MORE_LUS
+};
+#endif         /*NUK*/
+static struct scsidevs knowndevs[] =
+{
 #if NSD > 0
 #if NSD > 0
-       { T_DIRECT,T_FIXED,"standard","any"
-                       ,"any",sdattach,"sd",SC_ONE_LU },
-       { T_DIRECT,T_FIXED,"MAXTOR  ","XT-4170S        "
-                       ,"B5A ",sdattach,"mx1",SC_ONE_LU },
-#endif NSD
+       {
+               T_DIRECT, T_FIXED, "standard", "any"
+                   ,"any", sdattach, "sd", SC_ONE_LU
+       },
+       {
+               T_DIRECT, T_FIXED, "MAXTOR  ", "XT-4170S        "
+                   ,"B5A ", sdattach, "mx1", SC_ONE_LU
+       },
+#endif /* NSD */
 #if NST > 0
 #if NST > 0
-       { T_SEQUENTIAL,T_REMOV,"standard","any"
-                       ,"any",stattach,"st",SC_ONE_LU },
-#endif NST
+       {
+               T_SEQUENTIAL, T_REMOV, "standard", "any"
+                   ,"any", stattach, "st", SC_ONE_LU
+       },
+#endif /* NST */
 #if NCALS > 0
 #if NCALS > 0
-       { T_PROCESSOR,T_FIXED,"standard","any"
-                       ,"any",calsattach,"cals",SC_MORE_LUS },
-#endif NCALS
+       {
+               T_PROCESSOR, T_FIXED, "standard", "any"
+                   ,"any", calsattach, "cals", SC_MORE_LUS
+       },
+#endif /* NCALS */
 #if NCH > 0
 #if NCH > 0
-       { T_CHANGER,T_REMOV,"standard","any"
-                       ,"any",chattach,"ch",SC_ONE_LU },
-#endif NCH
+       {
+               T_CHANGER, T_REMOV, "standard", "any"
+                   ,"any", chattach, "ch", SC_ONE_LU
+       },
+#endif /* NCH */
 #if NCD > 0
 #if NCD > 0
-       { T_READONLY,T_REMOV,"SONY    ","CD-ROM CDU-8012 "
-                       ,"3.1a",cdattach,"cd",SC_ONE_LU },
-       { T_READONLY,T_REMOV,"PIONEER ","CD-ROM DRM-600  "
-                       ,"any",cdattach,"cd",SC_MORE_LUS },
-#endif NCD
+#ifndef UKTEST /* make cdroms unrecognised to test the uk driver */
+       {
+               T_READONLY, T_REMOV, "SONY    ", "CD-ROM CDU-8012 "
+                   ,"3.1a", cdattach, "cd", SC_ONE_LU
+       },
+       {
+               T_READONLY, T_REMOV, "PIONEER ", "CD-ROM DRM-600  "
+                   ,"any", cdattach, "cd", SC_MORE_LUS
+       },
+#endif
+#endif /* NCD */
 #if NBLL > 0
 #if NBLL > 0
-       { T_PROCESSOR,T_FIXED,"AEG     ","READER          "
-                       ,"V1.0",bllattach,"bll",SC_MORE_LUS },
-#endif NBLL
+       {
+               T_PROCESSOR, T_FIXED, "AEG     ", "READER          "
+                   ,"V1.0", bllattach, "bll", SC_MORE_LUS
+       },
+#endif /* NBLL */
 #if NKIL > 0
 #if NKIL > 0
-       { T_SCANNER,T_FIXED,"KODAK   ","IL Scanner 900  "
-                       ,"any",kil_attach,"kil",SC_ONE_LU },
-#endif NKIL
+       {
+               T_SCANNER, T_FIXED, "KODAK   ", "IL Scanner 900  "
+                   ,"any", kil_attach, "kil", SC_ONE_LU
+       },
+#endif /* NKIL */
 
 
-{0}
+       {
+               0
+       }
 };
 };
-/***************************************************************\
-* Declarations                                                 *
-\***************************************************************/
-struct predefined      *scsi_get_predef();
-struct scsidevs        *scsi_probedev();
-struct scsidevs        *selectdev();
-
-/* controls debug level within the scsi subsystem */
-/* see scsiconf.h for values                     */
-int    scsi_debug      =       0x0;
-int    scsibus         =       0x0; /* This is the Nth scsibus */
-
-/***************************************************************\
-* The routine called by the adapter boards to get all their    *
-* devices configured in.                                       *
-\***************************************************************/
-scsi_attachdevs( unit, scsi_addr, scsi_switch)
-int    unit,scsi_addr;
-struct scsi_switch     *scsi_switch;
+
+/*
+ * Declarations
+ */
+struct predefined *scsi_get_predef();
+struct scsidevs *scsi_probedev();
+struct scsidevs *selectdev();
+errval scsi_probe_bus __P((int bus, int targ, int lun));
+
+struct scsi_device probe_switch =
 {
 {
-       int     targ,lun;
-       struct  scsidevs        *bestmatch = (struct scsidevs *)0;
-       struct  predefined *predef;
-       int maybe_more;
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    "probe",
+    0,
+    { 0, 0 }
+};
 
 
-#ifdef SCSI_DELAY
-#if    SCSI_DELAY > 2
+/*
+ * controls debug level within the scsi subsystem -
+ * see scsiconf.h for values
+ */
+int32 scsibus = 0x0;           /* This is the Nth scsibus we've seen */
+
+/*
+ * The routine called by the adapter boards to get all their
+ * devices configured in.
+ */
+void
+scsi_attachdevs(sc_link_proto)
+       struct scsi_link *sc_link_proto;
+{
+
+       if(scsibus >= NSCBUS) {
+               printf("too many scsi busses, reconfigure the kernel\n");
+               return;
+       }
+       sc_link_proto->scsibus = scsibus;
+       scbus_data[scsibus] = malloc(sizeof(struct scsibus_data), M_TEMP, M_NOWAIT);
+       if(!scbus_data[scsibus]) {
+               panic("scsi_attachdevs: malloc\n");
+       }
+       bzero(scbus_data[scsibus], sizeof(struct scsibus_data));
+       scbus_data[scsibus]->adapter_link = sc_link_proto;
+#if defined(SCSI_DELAY) && SCSI_DELAY > 2
        printf("%s%d waiting for scsi devices to settle\n",
        printf("%s%d waiting for scsi devices to settle\n",
-               scsi_switch->name, unit);
-#else  SCSI_DELAY > 2
-#define        SCSI_DELAY 2
-#endif SCSI_DELAY > 2
-#else
+           sc_link_proto->adapter->name, sc_link_proto->adapter_unit);
+#else  /* SCSI_DELAY > 2 */
+#undef SCSI_DELAY
 #define SCSI_DELAY 2
 #define SCSI_DELAY 2
-#endif SCSI_DELAY
-       spinwait(1000 * SCSI_DELAY);
-       targ = 0;
-       while(targ < 8)
-       {
-               maybe_more = 0; /* by default only check 1 lun */
-               if (targ == scsi_addr) 
-               {
-                       targ++;
+#endif /* SCSI_DELAY */
+       DELAY(1000000 * SCSI_DELAY);
+       scsibus++;
+       scsi_probe_bus(scsibus - 1,-1,-1);
+}
+
+/*
+ * Probe the requested scsi bus. It must be already set up.
+ * -1 requests all set up scsi busses.
+ * targ and lun optionally narrow the search if not -1
+ */
+errval
+scsi_probe_busses(int bus, int targ, int lun)
+{
+       if (bus == -1) {
+               for(bus = 0; bus < scsibus; bus++) {
+                       scsi_probe_bus(bus, targ, lun);
+               }
+               return 0;
+       } else {
+               return scsi_probe_bus(bus, targ, lun);
+       }
+}
+
+/*
+ * Probe the requested scsi bus. It must be already set up.
+ * targ and lun optionally narrow the search if not -1
+ */
+errval
+scsi_probe_bus(int bus, int targ, int lun)
+{
+       struct scsibus_data *scsi ;
+       int     maxtarg,mintarg,maxlun,minlun;
+       struct scsi_link *sc_link_proto;
+       u_int8  scsi_addr ;
+       struct scsidevs *bestmatch = NULL;
+       struct predefined *predef = NULL;
+       struct scsi_link *sc_link = NULL;
+       boolean maybe_more;
+
+       if ((bus < 0 ) || ( bus >= scsibus)) {
+               return ENXIO;
+       }
+       scsi = scbus_data[bus];
+       if(!scsi) return ENXIO;
+       sc_link_proto = scsi->adapter_link;
+       scsi_addr = sc_link_proto->adapter_targ;
+       if(targ == -1){
+               maxtarg = 7;
+               mintarg = 0;
+       } else {
+               if((targ < 0 ) || (targ > 7)) return EINVAL;
+               maxtarg = mintarg = targ;
+       }
+
+       if(lun == -1){
+               maxlun = 7;
+               minlun = 0;
+       } else {
+               if((lun < 0 ) || (lun > 7)) return EINVAL;
+               maxlun = minlun = lun;
+       }
+
+
+       for ( targ = mintarg;targ <= maxtarg; targ++) {
+               maybe_more = 0; /* by default only check 1 lun */
+               if (targ == scsi_addr) {
                        continue;
                }
                        continue;
                }
-               lun = 0;
-               while(lun < 8)
-               {
-                       predef = scsi_get_predef(scsibus
-                                               ,targ
-                                               ,lun
-                                               ,scsi_switch
-                                               ,&maybe_more);
-                       bestmatch = scsi_probedev(unit
-                                               ,targ
-                                               ,lun 
-                                               ,scsi_switch
-                                               ,&maybe_more);
-                       if((bestmatch) && (predef)) /* both exist */
-                       {
-                               if(bestmatch->attach_rtn 
-                                   != predef->attach_rtn)
-                               {
-                                   printf("Clash in found/expected devices\n");
-                                   printf("will link in FOUND\n");
+               for ( lun = minlun; lun <= maxlun ;lun++) {
+                       /*
+                        * The spot appears to already have something
+                        * linked in, skip past it. Must be doing a 'reprobe'
+                        */
+                       if(scsi->sc_link[targ][lun])
+                       {/* don't do this one, but check other luns */
+                               maybe_more = 1;
+                               continue;
+                       }
+                       /*
+                        * If we presently don't have a link block
+                        * then allocate one to use while probing
+                        */
+                       if (!sc_link) {
+                               sc_link = malloc(sizeof(*sc_link), M_TEMP, M_NOWAIT);
+                               *sc_link = *sc_link_proto;      /* struct copy */
+                               sc_link->opennings = 1;
+                               sc_link->device = &probe_switch;
+                       }
+                       sc_link->target = targ;
+                       sc_link->lun = lun;
+                       predef = scsi_get_predef(sc_link, &maybe_more);
+                       bestmatch = scsi_probedev(sc_link, &maybe_more);
+                       if ((bestmatch) && (predef)) {  /* both exist */
+                               if (bestmatch->attach_rtn
+                                   != predef->attach_rtn) {
+                                       printf("Clash in found/expected devices\n");
+#if NUK > 0
+                                       if(bestmatch == &unknowndev) {
+                                               printf("will link in PREDEFINED\n");
+                                               (*(predef->attach_rtn)) (sc_link);
+                                       } else 
+#endif /*NUK*/
+                                       {
+                                               printf("will link in FOUND\n");
+                                               (*(bestmatch->attach_rtn)) (sc_link);
+                                       }
+                               } else {
+                                       (*(bestmatch->attach_rtn)) (sc_link);
                                }
                                }
-                               (*(bestmatch->attach_rtn))(unit,
-                                               targ,
-                                               lun,
-                                               scsi_switch);
                        }
                        }
-                       if((bestmatch) && (!predef)) /* just FOUND */
-                       {
-                               (*(bestmatch->attach_rtn))(unit,
-                                               targ,
-                                               lun,
-                                               scsi_switch);
+                       if ((bestmatch) && (!predef)) {         /* just FOUND */
+                               (*(bestmatch->attach_rtn)) (sc_link);
                        }
                        }
-                       if((!bestmatch) && (predef)) /* just predef */
-                       {
-                               (*(predef->attach_rtn))(unit,
-                                               targ,
-                                               lun,
-                                               scsi_switch);
+                       if ((!bestmatch) && (predef)) {         /* just predef */
+                               (*(predef->attach_rtn)) (sc_link);
                        }
                        }
-                       if(!(maybe_more)) /* nothing suggests we'll find more */
-                       {
+                       if ((bestmatch) || (predef)) {  /* one exists */
+                               scsi->sc_link[targ][lun] = sc_link;
+                               sc_link = NULL;         /* it's been used */
+                       }
+                       if (!(maybe_more)) {    /* nothing suggests we'll find more */
                                break;  /* nothing here, skip to next targ */
                        }
                                break;  /* nothing here, skip to next targ */
                        }
-                       /* otherwise something says we should look further*/
-                       lun++;
+                       /* otherwise something says we should look further */
                }
                }
-               targ++;
        }
        }
-#if NSG > 0
-       /***************************************************************\
-       * If available hook up the generic scsi driver, letting it      *
-       * know which target is US. (i.e. illegal or at least special)   *
-       \***************************************************************/
-       sg_attach(unit,scsi_addr,scsi_switch);
-#endif
-       scsibus++;      /* next time we are on the NEXT scsi bus */
+       if (sc_link) {
+               free(sc_link, M_TEMP);
+       }
+       return 0;
 }
 
 }
 
-/***********************************************\
-* given a target and lu, check if there is a   *
-* predefined device for that address           *
-\***********************************************/
-struct predefined      *scsi_get_predef(unit,target,lu,scsi_switch,maybe_more)
-int    unit,target,lu,*maybe_more;
-struct scsi_switch *scsi_switch;
+/*
+ * given a target and lu, check if there is a predefined device for
+ * that address
+ */
+struct predefined *
+scsi_get_predef(sc_link, maybe_more)
+       struct scsi_link *sc_link;
+       boolean *maybe_more;
 {
 {
-       int upto,numents;
+       u_int8  unit = sc_link->scsibus;
+       u_int8  target = sc_link->target;
+       u_int8  lu = sc_link->lun;
+       struct scsi_adapter *scsi_adapter = sc_link->adapter;
+       u_int32 upto, numents;
 
 
-       numents = (sizeof(pd)/sizeof(struct predefined)) - 1;
-       
-       for(upto = 0;upto < numents;upto++)
-       {
-               if(pd[upto].scsibus != unit)
+       numents = (sizeof(pd) / sizeof(struct predefined)) - 1;
+
+       for (upto = 0; upto < numents; upto++) {
+               if (pd[upto].scsibus != unit)
                        continue;
                        continue;
-               if(pd[upto].dev != target)
+               if (pd[upto].dev != target)
                        continue;
                        continue;
-               if(pd[upto].lu != lu)
+               if (pd[upto].lu != lu)
                        continue;
                        continue;
-               
+
                printf("%s%d targ %d lun %d: <%s> - PRECONFIGURED -\n"
                printf("%s%d targ %d lun %d: <%s> - PRECONFIGURED -\n"
-                       ,scsi_switch->name
-                       ,unit
-                       ,target
-                       ,lu
-                       ,pd[upto].devname);
+                   ,scsi_adapter->name
+                   ,unit
+                   ,target
+                   ,lu
+                   ,pd[upto].devname);
                *maybe_more = pd[upto].flags & SC_MORE_LUS;
                *maybe_more = pd[upto].flags & SC_MORE_LUS;
-               return(&(pd[upto]));
+               return (&(pd[upto]));
        }
        }
-       return((struct predefined *)0);
+       return ((struct predefined *) 0);
 }
 
 }
 
-/***********************************************\
-* given a target and lu, ask the device what   *
-* it is, and find the correct driver table     *
-* entry.                                       *
-\***********************************************/
-struct scsidevs        *scsi_probedev(unit,target,lu,scsi_switch, maybe_more)
-
-struct scsi_switch *scsi_switch;
-int    unit,target,lu;
-int *maybe_more;
+/*
+ * given a target and lu, ask the device what
+ * it is, and find the correct driver table
+ * entry.
+ */
+struct scsidevs *
+scsi_probedev(sc_link, maybe_more)
+       boolean *maybe_more;
+       struct scsi_link *sc_link;
 {
 {
-       struct  scsidevs        *bestmatch = (struct scsidevs *)0;
-       char    *dtype=(char *)0,*desc;
-       char    *qtype;
-       static  struct scsi_inquiry_data        inqbuf; 
-       int     len,qualifier,type,remov;
-       char    manu[32];
-       char    model[32];
-       char    version[32];
-
-
-       bzero(&inqbuf,sizeof(inqbuf));
-       /***********************************************\
-       * Ask the device what it is                     *
-       \***********************************************/
-#ifdef DEBUG
-       if((target == 0) && (lu == 0))
-               scsi_debug = 0xfff;
+       u_int8  unit = sc_link->adapter_unit;
+       u_int8  target = sc_link->target;
+       u_int8  lu = sc_link->lun;
+       struct scsi_adapter *scsi_adapter = sc_link->adapter;
+       struct scsidevs *bestmatch = (struct scsidevs *) 0;
+       char   *dtype = (char *) 0, *desc;
+       char   *qtype;
+       static struct scsi_inquiry_data inqbuf;
+       u_int32 len, qualifier, type;
+       boolean remov;
+       char    manu[32];
+       char    model[32];
+       char    version[32];
+
+       bzero(&inqbuf, sizeof(inqbuf));
+       /*
+        * Ask the device what it is
+        */
+#ifdef SCSIDEBUG
+       if ((target == DEBUGTARG) && (lu == DEBUGLUN))
+               sc_link->flags |= (DEBUGLEVEL);
        else
        else
-               scsi_debug = 0;
-#endif DEBUG
-       if(scsi_ready(  unit,
-                       target,
-                       lu,
-                       scsi_switch,
-                       SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE)
-       {
-               return(struct scsidevs *)0;
-       }
-       if(scsi_inquire(unit,
-                       target,
-                       lu,
-                       scsi_switch,
-                       &inqbuf,
-                       SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE)
-       {
-               return(struct scsidevs *)0;
-       }
+               sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2 | SDEV_DB3 | SDEV_DB4);
+#endif /* SCSIDEBUG */
+       /* catch unit attn */
+       scsi_test_unit_ready(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
+#ifdef DOUBTFULL
+       switch (scsi_test_unit_ready(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT)) {
+       case 0:         /* said it WAS ready */
+       case EBUSY:             /* replied 'NOT READY' but WAS present, continue */
+       case ENXIO:
+               break;
+       case EIO:               /* device timed out */
+       case EINVAL:            /* Lun not supported */
+       default:
+               return (struct scsidevs *) 0;
 
 
-       /***********************************************\
-       * note what BASIC type of device it is          *
-       \***********************************************/
-       if(scsi_debug & SHOWINQUIRY)
-       {
-               desc=(char *)&inqbuf;
-               printf("inq: %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
-               desc[0], desc[1], desc[2], desc[3],
-               desc[4], desc[5], desc[6], desc[7],
-               desc[8], desc[9], desc[10], desc[11],
-               desc[12]);
+       }
+#endif /*DOUBTFULL*/
+#ifdef SCSI_2_DEF
+       /* some devices need to be told to go to SCSI2 */
+       /* However some just explode if you tell them this.. leave it out */
+       scsi_change_def(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
+#endif /*SCSI_2_DEF */
+
+       /* Now go ask the device all about itself */
+       if (scsi_inquire(sc_link, &inqbuf, SCSI_NOSLEEP | SCSI_NOMASK) != 0) {
+               return (struct scsidevs *) 0;
        }
 
        }
 
+       /*
+        * note what BASIC type of device it is
+        */
        type = inqbuf.device & SID_TYPE;
        qualifier = inqbuf.device & SID_QUAL;
        remov = inqbuf.dev_qual2 & SID_REMOVABLE;
 
        type = inqbuf.device & SID_TYPE;
        qualifier = inqbuf.device & SID_QUAL;
        remov = inqbuf.dev_qual2 & SID_REMOVABLE;
 
-
-       /* Any device qualifier that has
-        * the top bit set (qualifier&4 != 0) is vendor specific and
-        * won't match in this switch.
+       /*
+        * Any device qualifier that has the top bit set (qualifier&4 != 0)
+        * is vendor specific and won't match in this switch.
         */
 
         */
 
-       switch(qualifier)
-       {
+       switch (qualifier) {
        case SID_QUAL_LU_OK:
        case SID_QUAL_LU_OK:
-               qtype="";
+               qtype = "";
                break;
 
        case SID_QUAL_LU_OFFLINE:
                break;
 
        case SID_QUAL_LU_OFFLINE:
-               qtype=", Unit not Connected!";
+               qtype = ", Unit not Connected!";
                break;
 
        case SID_QUAL_RSVD:
                break;
 
        case SID_QUAL_RSVD:
-               qtype=", Reserved Peripheral Qualifier!";
+               qtype = ", Reserved Peripheral Qualifier!";
                *maybe_more = 1;
                *maybe_more = 1;
-               return (struct scsidevs *)0;
+               return (struct scsidevs *) 0;
                break;
 
        case SID_QUAL_BAD_LU:
                /*
                 * Check for a non-existent unit.  If the device is returning
                break;
 
        case SID_QUAL_BAD_LU:
                /*
                 * Check for a non-existent unit.  If the device is returning
-                * this much, then we must set the flag that has
-                * the searcher keep looking on other luns.
-                */
-               qtype=", The Target can't support this Unit!";
+                * this much, then we must set the flag that has
+                * the searchers keep looking on other luns.
+                */
+               qtype = ", The Target can't support this Unit!";
                *maybe_more = 1;
                *maybe_more = 1;
-               return (struct scsidevs *)0;
+               return (struct scsidevs *) 0;
 
        default:
 
        default:
-               dtype="vendor specific";
-               qtype="";
+               dtype = "vendor specific";
+               qtype = "";
                *maybe_more = 1;
                break;
        }
                *maybe_more = 1;
                break;
        }
-
-       if (dtype == 0)
-       {
-               switch(type)
-               {
+       if (dtype == 0) {
+               switch (type) {
                case T_DIRECT:
                case T_DIRECT:
-                       dtype="direct";
+                       dtype = "direct";
                        break;
                case T_SEQUENTIAL:
                        break;
                case T_SEQUENTIAL:
-                       dtype="sequential";
+                       dtype = "sequential";
                        break;
                case T_PRINTER:
                        break;
                case T_PRINTER:
-                       dtype="printer";
+                       dtype = "printer";
                        break;
                case T_PROCESSOR:
                        break;
                case T_PROCESSOR:
-                       dtype="processor";
+                       dtype = "processor";
                        break;
                case T_READONLY:
                        break;
                case T_READONLY:
-                       dtype="readonly";
+                       dtype = "readonly";
                        break;
                case T_WORM:
                        break;
                case T_WORM:
-                       dtype="worm";
+                       dtype = "worm";
                        break;
                case T_SCANNER:
                        break;
                case T_SCANNER:
-                       dtype="scanner";
+                       dtype = "scanner";
                        break;
                case T_OPTICAL:
                        break;
                case T_OPTICAL:
-                       dtype="optical";
+                       dtype = "optical";
                        break;
                case T_CHANGER:
                        break;
                case T_CHANGER:
-                       dtype="changer";
+                       dtype = "changer";
                        break;
                case T_COMM:
                        break;
                case T_COMM:
-                       dtype="communication";
+                       dtype = "communication";
                        break;
                case T_NODEVICE:
                        *maybe_more = 1;
                        break;
                case T_NODEVICE:
                        *maybe_more = 1;
-                       return (struct scsidevs *)0;
+                       return (struct scsidevs *) 0;
                default:
                default:
-                       dtype="unknown";
+                       dtype = "unknown";
                        break;
                }
                        break;
                }
-
-       }
-       /***********************************************\
-       * Then if it's advanced enough, more detailed   *
-       * information                                   *
-       \***********************************************/
-       if((inqbuf.version & SID_ANSII) > 0) 
-       {
-               if ((len = inqbuf.additional_length 
-                               + ( (char *)inqbuf.unused
-                                 - (char *)&inqbuf))
-                       > (sizeof(struct scsi_inquiry_data) - 1))
-                       len = sizeof(struct scsi_inquiry_data) - 1;
-               desc=inqbuf.vendor;
-               desc[len-(desc - (char *)&inqbuf)] = 0;
-               strncpy(manu,inqbuf.vendor,8);manu[8]=0;
-               strncpy(model,inqbuf.product,16);model[16]=0;
-               strncpy(version,inqbuf.revision,4);version[4]=0;
        }
        }
-       else
-       /***********************************************\
-       * If not advanced enough, use default values    *
-       \***********************************************/
+       /*
+        * Then if it's advanced enough, more detailed
+        * information
+        */
+       if ((inqbuf.version & SID_ANSII) > 0) {
+               if ((len = inqbuf.additional_length
+                       + ((char *) inqbuf.unused
+                           - (char *) &inqbuf))
+                   > (sizeof(struct scsi_inquiry_data) - 1))
+                               len = sizeof(struct scsi_inquiry_data) - 1;
+               desc = inqbuf.vendor;
+               desc[len - (desc - (char *) &inqbuf)] = 0;
+               strncpy(manu, inqbuf.vendor, 8);
+               manu[8] = 0;
+               strncpy(model, inqbuf.product, 16);
+               model[16] = 0;
+               strncpy(version, inqbuf.revision, 4);
+               version[4] = 0;
+       } else
+               /*
+                * If not advanced enough, use default values
+                */
        {
        {
-               desc="early protocol device";
-               strncpy(manu,"unknown",8);
-               strncpy(model,"unknown",16);
-               strncpy(version,"????",4);
+               desc = "early protocol device";
+               strncpy(manu, "unknown", 8);
+               strncpy(model, "unknown", 16);
+               strncpy(version, "????", 4);
        }
        printf("%s%d targ %d lun %d: type %d(%s) %s SCSI%d\n"
        }
        printf("%s%d targ %d lun %d: type %d(%s) %s SCSI%d\n"
-               ,scsi_switch->name
-               ,unit
-               ,target
-               ,lu
-               ,type
-               ,dtype
-               ,remov?"removable":"fixed"
-               ,inqbuf.version & SID_ANSII
-       );
+           ,scsi_adapter->name
+           ,unit
+           ,target
+           ,lu
+           ,type
+           ,dtype
+           ,remov ? "removable" : "fixed"
+           ,inqbuf.version & SID_ANSII
+           );
        printf("%s%d targ %d lun %d: <%s%s%s>\n"
        printf("%s%d targ %d lun %d: <%s%s%s>\n"
-               ,scsi_switch->name
-               ,unit
-               ,target
-               ,lu
-               ,manu
-               ,model
-               ,version
-       );
-       if(qtype[0])
-       {
+           ,scsi_adapter->name
+           ,unit
+           ,target
+           ,lu
+           ,manu
+           ,model
+           ,version
+           );
+       if (qtype[0]) {
                printf("%s%d targ %d lun %d: qualifier %d(%s)\n"
                printf("%s%d targ %d lun %d: qualifier %d(%s)\n"
-               ,scsi_switch->name
-               ,unit
-               ,target
-               ,lu
-               ,qualifier
-               ,qtype
-       );
+                   ,scsi_adapter->name
+                   ,unit
+                   ,target
+                   ,lu
+                   ,qualifier
+                   ,qtype
+                   );
        }
        }
-       /***********************************************\
-       * Try make as good a match as possible with     *
-       * available sub drivers                         *
-       \***********************************************/
-       bestmatch = (selectdev(unit,target,lu,&scsi_switch,
-               qualifier,type,remov?T_REMOV:T_FIXED,manu,model,version));
-       if((bestmatch) && (bestmatch->flags & SC_MORE_LUS))
-       {
+       /*
+        * Try make as good a match as possible with
+        * available sub drivers       
+        */
+       bestmatch = (selectdev(
+               qualifier, type, remov ? T_REMOV : T_FIXED, manu, model, version));
+       if ((bestmatch) && (bestmatch->flags & SC_MORE_LUS)) {
                *maybe_more = 1;
        }
                *maybe_more = 1;
        }
-       return(bestmatch);
+       return (bestmatch);
 }
 }
-
-/***********************************************\
-* Try make as good a match as possible with    *
-* available sub drivers                                *
-\***********************************************/
-struct scsidevs        
-*selectdev(unit,target,lu,dvr_switch,qualifier,type,remov,manu,model,rev)
-int    unit,target,lu;
-struct scsi_switch *dvr_switch;
-int    qualifier,type,remov;
-char   *manu,*model,*rev;
+/*
+ * Try make as good a match as possible with
+ * available sub drivers       
+ */
+struct scsidevs *
+selectdev(qualifier, type, remov, manu, model, rev)
+       u_int32 qualifier, type;
+       boolean remov;
+       char   *manu, *model, *rev;
 {
 {
-       int     numents = (sizeof(knowndevs)/sizeof(struct scsidevs)) - 1;
-       int     count = 0;
-       int                     bestmatches = 0;
-       struct  scsidevs        *bestmatch = (struct scsidevs *)0;
-       struct  scsidevs        *thisentry = knowndevs;
+       u_int32 numents = (sizeof(knowndevs) / sizeof(struct scsidevs)) - 1;
+       u_int32 count = 0;
+       u_int32 bestmatches = 0;
+       struct scsidevs *bestmatch = (struct scsidevs *) 0;
+       struct scsidevs *thisentry = knowndevs;
 
        type |= qualifier;      /* why? */
 
        thisentry--;
 
        type |= qualifier;      /* why? */
 
        thisentry--;
-       while( count++ < numents)
-       {
+       while (count++ < numents) {
                thisentry++;
                thisentry++;
-               if(type != thisentry->type)
-               {
+               if (type != thisentry->type) {
                        continue;
                }
                        continue;
                }
-               if(bestmatches < 1)
-               {
+               if (bestmatches < 1) {
                        bestmatches = 1;
                        bestmatch = thisentry;
                }
                        bestmatches = 1;
                        bestmatch = thisentry;
                }
-               if(remov != thisentry->removable)
-               {
+               if (remov != thisentry->removable) {
                        continue;
                }
                        continue;
                }
-               if(bestmatches < 2)
-               {
+               if (bestmatches < 2) {
                        bestmatches = 2;
                        bestmatch = thisentry;
                }
                        bestmatches = 2;
                        bestmatch = thisentry;
                }
-               if(thisentry->flags & SC_SHOWME)
-                       printf("\n%s-\n%s-",thisentry->manufacturer, manu);
-               if(strcmp(thisentry->manufacturer, manu))
-               {
+               if (thisentry->flags & SC_SHOWME)
+                       printf("\n%s-\n%s-", thisentry->manufacturer, manu);
+               if (strcmp(thisentry->manufacturer, manu)) {
                        continue;
                }
                        continue;
                }
-               if(bestmatches < 3)
-               {
+               if (bestmatches < 3) {
                        bestmatches = 3;
                        bestmatch = thisentry;
                }
                        bestmatches = 3;
                        bestmatch = thisentry;
                }
-               if(thisentry->flags & SC_SHOWME)
-                       printf("\n%s-\n%s-",thisentry->model, model);
-               if(strcmp(thisentry->model, model))
-               {
+               if (thisentry->flags & SC_SHOWME)
+                       printf("\n%s-\n%s-", thisentry->model, model);
+               if (strcmp(thisentry->model, model)) {
                        continue;
                }
                        continue;
                }
-               if(bestmatches < 4)
-               {
+               if (bestmatches < 4) {
                        bestmatches = 4;
                        bestmatch = thisentry;
                }
                        bestmatches = 4;
                        bestmatch = thisentry;
                }
-               if(thisentry->flags & SC_SHOWME)
-                       printf("\n%s-\n%s-",thisentry->version, rev);
-               if(strcmp(thisentry->version, rev))
-               {
+               if (thisentry->flags & SC_SHOWME)
+                       printf("\n%s-\n%s-", thisentry->version, rev);
+               if (strcmp(thisentry->version, rev)) {
                        continue;
                }
                        continue;
                }
-               if(bestmatches < 5)
-               {
+               if (bestmatches < 5) {
                        bestmatches = 5;
                        bestmatch = thisentry;
                        break;
                }
        }
                        bestmatches = 5;
                        bestmatch = thisentry;
                        break;
                }
        }
-
-       if (bestmatch == (struct scsidevs *)0)
-               printf("        No explicit device driver match for \"%s %s\".\n",
-               manu, model);
-
-       return(bestmatch);
-}
-
-static int recurse = 0;
-/***********************************************\
-* Do a scsi operation asking a device if it is *
-* ready. Use the scsi_cmd routine in the switch *
-* table.                                       *
-\***********************************************/
-scsi_ready(unit,target,lu,scsi_switch, flags)
-struct scsi_switch *scsi_switch;
-{
-       struct  scsi_test_unit_ready scsi_cmd;
-       struct  scsi_xfer scsi_xfer;
-       volatile int rval;
-       int     key;
-
-       bzero(&scsi_cmd, sizeof(scsi_cmd));
-       bzero(&scsi_xfer, sizeof(scsi_xfer));
-       scsi_cmd.op_code = TEST_UNIT_READY;
-
-       scsi_xfer.flags=flags | INUSE;
-       scsi_xfer.adapter=unit;
-       scsi_xfer.targ=target;
-       scsi_xfer.lu=lu;
-       scsi_xfer.cmd=(struct scsi_generic *)&scsi_cmd;
-       scsi_xfer.retries=8;
-       scsi_xfer.timeout=10000;
-       scsi_xfer.cmdlen=sizeof(scsi_cmd);
-       scsi_xfer.data=0;
-       scsi_xfer.datalen=0;
-       scsi_xfer.resid=0;
-       scsi_xfer.when_done=0;
-       scsi_xfer.done_arg=0;
-retry: scsi_xfer.error=0;
-       /*******************************************************\
-       * do not use interrupts                                 *
-       \*******************************************************/
-       rval = (*(scsi_switch->scsi_cmd))(&scsi_xfer);
-       if (rval != COMPLETE)
-       {
-               if(scsi_debug)
-               {
-                       printf("scsi error, rval = 0x%x\n",rval);
-                       printf("code from driver: 0x%x\n",scsi_xfer.error);
-               }
-               switch(scsi_xfer.error)
-               {
-               case    XS_SENSE:
-               /*******************************************************\
-               * Any sense value is illegal except UNIT ATTENTION      *
-               * In which case we need to check again to get the       *
-               * correct response.                                     *
-               *( especially exabytes)                                 *
-               \*******************************************************/
-                       if(((scsi_xfer.sense.error_code & SSD_ERRCODE) == 0x70 )
-                       ||((scsi_xfer.sense.error_code & SSD_ERRCODE) == 0x71 ))
-                       {
-                               key = scsi_xfer.sense.ext.extended.flags & SSD_KEY ;
-                               switch(key)
-                               { 
-                               case    2:      /* not ready BUT PRESENT! */
-                                               return(COMPLETE);
-                               case    6:
-                                       spinwait(1000);
-                                       if(scsi_xfer.retries--)
-                                       {
-                                               scsi_xfer.flags &= ~ITSDONE;
-                                               goto retry;
-                                       }
-                                       return(COMPLETE);
-                               default:
-                                       if(scsi_debug)
-                                               printf("%d:%d,key=%x.",
-                                               target,lu,key);
-                               }
-                       }
-                       return(HAD_ERROR);
-               case    XS_BUSY:
-                       spinwait(1000);
-                       if(scsi_xfer.retries--)
-                       {
-                               scsi_xfer.flags &= ~ITSDONE;
-                               goto retry;
-                       }
-                       return(COMPLETE);       /* it's busy so it's there */
-               case    XS_TIMEOUT:
-               default:
-                       return(HAD_ERROR);
-               }
-       }
-       return(COMPLETE);
-}
-/***********************************************\
-* Do a scsi operation asking a device what it is*
-* Use the scsi_cmd routine in the switch table.        *
-\***********************************************/
-scsi_inquire(unit,target,lu,scsi_switch,inqbuf, flags)
-struct scsi_switch *scsi_switch;
-u_char *inqbuf;
-{
-       struct  scsi_inquiry scsi_cmd;
-       struct  scsi_xfer scsi_xfer;
-       volatile int rval;
-
-       bzero(&scsi_cmd, sizeof(scsi_cmd));
-       bzero(&scsi_xfer, sizeof(scsi_xfer));
-       scsi_cmd.op_code = INQUIRY;
-       scsi_cmd.length = sizeof(struct scsi_inquiry_data);
-
-       scsi_xfer.flags=flags | SCSI_DATA_IN | INUSE;
-       scsi_xfer.adapter=unit;
-       scsi_xfer.targ=target;
-       scsi_xfer.lu=lu;
-       scsi_xfer.retries=8;
-       scsi_xfer.timeout=10000;
-       scsi_xfer.cmd=(struct scsi_generic *)&scsi_cmd;
-       scsi_xfer.cmdlen= sizeof(struct scsi_inquiry);
-       scsi_xfer.data=inqbuf;
-       scsi_xfer.datalen=sizeof(struct scsi_inquiry_data);
-       scsi_xfer.resid=sizeof(struct scsi_inquiry_data);
-       scsi_xfer.when_done=0;
-       scsi_xfer.done_arg=0;
-retry: scsi_xfer.error=0;
-       /*******************************************************\
-       * do not use interrupts                                 *
-       \*******************************************************/
-       if ((*(scsi_switch->scsi_cmd))(&scsi_xfer) != COMPLETE)
-       {
-               if(scsi_debug) printf("inquiry had error(0x%x) ",scsi_xfer.error);
-               switch(scsi_xfer.error)
-               {
-               case    XS_NOERROR:
-                       break;
-               case    XS_SENSE:
-               /*******************************************************\
-               * Any sense value is illegal except UNIT ATTENTION      *
-               * In which case we need to check again to get the       *
-               * correct response.                                     *
-               *( especially exabytes)                                 *
-               \*******************************************************/
-                       if(((scsi_xfer.sense.error_code & SSD_ERRCODE) == 0x70 )
-                        && ((scsi_xfer.sense.ext.extended.flags & SSD_KEY) == 6))
-                       { /* it's changed so it's there */
-                               spinwait(1000);
-                               {
-                                       if(scsi_xfer.retries--)
-                                       {
-                                               scsi_xfer.flags &= ~ITSDONE;
-                                               goto retry;
-                                       }
-                               }
-                               return( COMPLETE);
-                       }
-                       return(HAD_ERROR);
-               case    XS_BUSY:
-                       spinwait(1000);
-                       if(scsi_xfer.retries--)
-                       {
-                               scsi_xfer.flags &= ~ITSDONE;
-                               goto retry;
-                       }
-               case    XS_TIMEOUT:
-               default:
-                       return(HAD_ERROR);
-               }
+       if (bestmatch == (struct scsidevs *) 0) {
+#if NUK > 0
+               bestmatch = &unknowndev;
+#else
+               printf("No explicit device driver match.\n");
+#endif
        }
        }
-       return(COMPLETE);
-}
-
-
-
-
-/***********************************************\
-* Utility routines often used in SCSI stuff    *
-\***********************************************/
-
-/***********************************************\
-* convert a physical address to 3 bytes,       *
-* MSB at the lowest address,                   *
-* LSB at the highest.                          *
-\***********************************************/
-
-lto3b(val, bytes)
-u_char *bytes;
-{
-       *bytes++ = (val&0xff0000)>>16;
-       *bytes++ = (val&0xff00)>>8;
-       *bytes = val&0xff;
+       return (bestmatch);
 }
 }
-
-/***********************************************\
-* The reverse of lto3b                         *
-\***********************************************/
-_3btol(bytes)
-u_char *bytes;
-{
-       int rc;
-       rc = (*bytes++ << 16);
-       rc += (*bytes++ << 8);
-       rc += *bytes;
-       return(rc);
-}
-
index 5738de5..856fe89 100644 (file)
  *
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  *
  *
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  *
- *     $Id: scsiconf.h,v 1.5 1993/08/28 03:08:54 rgrimes Exp $
+ *     $Id: scsiconf.h,v 2.4 93/10/16 00:59:13 julian Exp Locker: julian $
  */
  */
+#ifndef        SCSI_SCSICONF_H
+#define SCSI_SCSICONF_H 1
+typedef        int                     boolean;
+typedef        int                     errval;
+typedef        long int                int32;
+typedef        short int               int16;
+typedef        char                    int8;
+typedef        unsigned long int       u_int32;
+typedef        unsigned short int      u_int16;
+typedef        unsigned char           u_int8;
 
 
-#ifndef _SCSI_SCSICONF_H_
-#define _SCSI_SCSICONF_H_ 1
+#include <scsi/scsi_debug.h>
 
 
-/***********************************************\
-* these calls are called by the high-end       *
-* drivers to get services from whatever low-end        *
-* drivers they are attached to                 *
-\***********************************************/
-struct scsi_switch
+/*
+ * The following documentation tries to describe the relationship between the
+ * various structures defined in this file:
+ *
+ * each adapter type has a scsi_adapter struct. This describes the adapter and
+ *    identifies routines that can be called to use the adapter.
+ * each device type has a scsi_device struct. This describes the device and
+ *    identifies routines that can be called to use the device.
+ * each existing device position (scsibus + target + lun)
+ *    can be described by a scsi_link struct.
+ *    Only scsi positions that actually have devices, have a scsi_link
+ *    structure assigned. so in effect each device has scsi_link struct.
+ *    The scsi_link structure contains information identifying both the
+ *    device driver and the adapter driver for that position on that scsi bus,
+ *    and can be said to 'link' the two.
+ * each individual scsi bus has an array that points to all the scsi_link
+ *    structs associated with that scsi bus. Slots with no device have
+ *    a NULL pointer.
+ * each individual device also knows the address of it's own scsi_link
+ *    structure.
+ *
+ *                             -------------
+ *
+ * The key to all this is the scsi_link structure which associates all the 
+ * other structures with each other in the correct configuration.  The
+ * scsi_link is the connecting information that allows each part of the 
+ * scsi system to find the associated other parts.
+ */
+
+
+/*
+ * These entrypoints are called by the high-end drivers to get services from
+ * whatever low-end drivers they are attached to each adapter type has one of
+ * these statically allocated.
+ */
+struct scsi_adapter
 {
 {
-       int             (*scsi_cmd)();
-       void            (*scsi_minphys)();
-       int             (*open_target_lu)();
-       int             (*close_target_lu)();
-       long    int     (*adapter_info)(); /* see definitions below */
-       char            *name; /* name of scsi bus controller */
-       u_long  spare[2];
+/* 04*/        int32           (*scsi_cmd)();
+/* 08*/        void            (*scsi_minphys)();
+/* 12*/        int32           (*open_target_lu)();
+/* 16*/        int32           (*close_target_lu)();
+/* 20*/        u_int32         (*adapter_info)(); /* see definitions below */
+/* 24*/        char            *name; /* name of scsi bus controller */
+/* 32*/        u_long  spare[2];
 };
 };
-#define        AD_INF_MAX_CMDS         0x000000FF /* maximum number of entries
-                                               queuable to a device by 
-                                               the adapter */
-/* 24 bits of other adapter characteristics go here */
 
 
-/***********************************************\
-* The scsi debug control bits                  *
-\***********************************************/
-extern int     scsi_debug;
-#define PRINTROUTINES  0x01
-#define        TRACEOPENS      0x02
-#define        TRACEINTERRUPTS 0x04
-#define        SHOWREQUESTS    0x08
-#define        SHOWSCATGATH    0x10
-#define        SHOWINQUIRY     0x20
-#define        SHOWCOMMANDS    0x40
-
-
-/********************************/
-/* return values for scsi_cmd() */
-/********************************/
+/*
+ * return values for scsi_cmd()
+ */
 #define SUCCESSFULLY_QUEUED    0
 #define TRY_AGAIN_LATER                1
 #define        COMPLETE                2
 #define SUCCESSFULLY_QUEUED    0
 #define TRY_AGAIN_LATER                1
 #define        COMPLETE                2
-#define        HAD_ERROR               3
+#define        HAD_ERROR               3 /* do not use this, use COMPLETE */
 #define        ESCAPE_NOT_SUPPORTED    4
 
 #define        ESCAPE_NOT_SUPPORTED    4
 
+/*
+ * Format of adapter_info() response data
+ * e.g. maximum number of entries queuable to a device by the adapter
+ */
+#define        AD_INF_MAX_CMDS         0x000000FF
+/* 24 bits of other adapter characteristics go here */
+
+/*
+ * These entry points are called by the low-end drivers to get services from
+ * whatever high-end drivers they are attached to.  Each device type has one
+ * of these statically allocated.
+ */
+struct scsi_device
+{
+/*  4*/        errval  (*err_handler)(); /* returns -1 to say err processing complete */
+/*  8*/        void    (*start)();
+/* 12*/        int32   (*async)();
+/* 16*/        int32   (*done)();      /* returns -1 to say done processing complete */
+/* 20*/        char    *name;          /* name of device type */
+/* 24*/        u_int32 flags;          /* device type dependent flags */
+/* 32*/        int32   spare[2];
+};
+
+/*
+ * This structure describes the connection between an adapter driver and
+ * a device driver, and is used by each to call services provided by
+ * the other, and to allow generic scsi glue code to call these services
+ * as well.
+ */
+struct scsi_link
+{
+/*  1*/        u_int8  target;                 /* targ of this dev */
+/*  2*/        u_int8  lun;                    /* lun of this dev */
+/*  3*/        u_int8  adapter_targ;           /* what are we on the scsi bus */
+/*  4*/        u_int8  adapter_unit;           /* e.g. the 0 in aha0 */
+/*  5*/        u_int8  scsibus;                /* the Nth scsibus      */
+/*  6*/        u_int8  dev_unit;               /* e.g. the 0 in sd0 */
+/*  7*/        u_int8  opennings;              /* available operations */
+/*  8*/        u_int8  active;                 /* operations in progress */
+/* 10*/        u_int16 flags;                  /* flags that all devices have */
+/* 12*/        u_int8  spareb[2];              /* unused               */
+/* 16*/        struct  scsi_adapter *adapter;  /* adapter entry points etc. */
+/* 20*/        struct  scsi_device *device;    /* device entry points etc. */
+/* 24*/        struct  scsi_xfer *active_xs;   /* operations under way */
+/* 28*/        void *  fordriver;              /* for private use by the driver */
+/* 32*/        u_int32 spare;
+};
+#define        SDEV_MEDIA_LOADED       0x01    /* device figures are still valid */
+#define        SDEV_WAITING            0x02    /* a process is waiting for this */
+#define        SDEV_OPEN               0x04    /* at least 1 open session */
+#define        SDEV_DBX                0xF0    /* debuging flags (scsi_debug.h) */     
+
+/*
+ * One of these is allocated and filled in for each scsi bus.
+ * it holds pointers to allow the scsi bus to get to the driver
+ * That is running each LUN on the bus
+ * it also has a template entry which is the prototype struct
+ * supplied by the adapter driver, this is used to initialise
+ * the others, before they have the rest of the fields filled in
+ */
+struct scsibus_data {
+       struct scsi_link *adapter_link;         /* prototype supplied by adapter */
+       struct scsi_link *sc_link[8][8];
+};
+
+/*
+ * Each scsi transaction is fully described by one of these structures
+ * It includes information about the source of the command and also the
+ * device and adapter for which the command is destined.
+ * (via the scsi_link structure)                                               *
+ */
 struct scsi_xfer
 {
 struct scsi_xfer
 {
-       struct  scsi_xfer *next;        /* when free */
-       int     flags;
-       u_char  adapter;
-       u_char  targ;
-       u_char  lu;
-       u_char  retries;        /* the number of times to retry */
-       long    int     timeout;        /* in miliseconds */
-       struct  scsi_generic *cmd;
-       int     cmdlen;
-       u_char  *data;          /* either the dma address OR a uio address */
-       int     datalen;        /* data len (blank if uio)    */
-       int     resid;
-       int     (*when_done)();
-       int     done_arg;
-       int     done_arg2;
-       int     error;
-       struct  buf *bp;
-       struct  scsi_sense_data sense;
-
-       /* Believe it or not, Some targets fall on the ground with
+/*04*/ struct  scsi_xfer *next;        /* when free */
+/*08*/ u_int32 flags;
+/*12*/ struct  scsi_link *sc_link;     /* all about our device and adapter */
+/*13*/ u_int8  retries;                /* the number of times to retry */
+/*16*/ u_int8  spare[3];
+/*20*/ int32   timeout;                /* in milliseconds */
+/*24*/ struct  scsi_generic *cmd;      /* The scsi command to execute */
+/*28*/ int32   cmdlen;                 /* how long it is */
+/*32*/ u_char  *data;                  /* dma address OR a uio address */
+/*36*/ int32   datalen;                /* data len (blank if uio)    */
+/*40*/ int32   resid;                  /* how much buffer was not touched */
+/*44*/ int32   error;                  /* an error value       */
+/*48*/ struct  buf *bp;                /* If we need to associate with a buf */
+/*80*/ struct  scsi_sense_data sense; /* 32 bytes*/
+       /*
+        * Believe it or not, Some targets fall on the ground with
         * anything but a certain sense length.
         */
         * anything but a certain sense length.
         */
-       int req_sense_length;   /* Explicit request sense length */
-
-       int status;             /* SCSI status */
+/*84*/ int32 req_sense_length;         /* Explicit request sense length */
+/*88*/ int32 status;                   /* SCSI status */
+/*100*/        struct  scsi_generic cmdstore;  /* stash the command in here */
 };
 };
-/********************************/
-/* Flag values                 */
-/********************************/
+
+/*
+ * Per-request Flag values
+ */
 #define        SCSI_NOSLEEP    0x01    /* Not a user... don't sleep            */
 #define        SCSI_NOMASK     0x02    /* dont allow interrupts.. booting      */
 #define        SCSI_NOSTART    0x04    /* left over from ancient history       */
 #define        SCSI_NOSLEEP    0x01    /* Not a user... don't sleep            */
 #define        SCSI_NOMASK     0x02    /* dont allow interrupts.. booting      */
 #define        SCSI_NOSTART    0x04    /* left over from ancient history       */
+#define        SCSI_USER       0x08    /* Is a user cmd, call scsi_user_done   */
 #define        ITSDONE         0x10    /* the transfer is as done as it gets   */
 #define        INUSE           0x20    /* The scsi_xfer block is in use        */
 #define        SCSI_SILENT     0x40    /* Don't report errors to console       */
 #define        ITSDONE         0x10    /* the transfer is as done as it gets   */
 #define        INUSE           0x20    /* The scsi_xfer block is in use        */
 #define        SCSI_SILENT     0x40    /* Don't report errors to console       */
@@ -107,18 +198,18 @@ struct scsi_xfer
 #define        SCSI_TARGET     0x1000  /* This defines a TARGET mode op.       */
 #define        SCSI_ESCAPE     0x2000  /* Escape operation                     */
 
 #define        SCSI_TARGET     0x1000  /* This defines a TARGET mode op.       */
 #define        SCSI_ESCAPE     0x2000  /* Escape operation                     */
 
-/*************************************************************************/
-/* Escape op codes.  This provides an extensible setup for operations    */
-/* that are not scsi commands.  They are intended for modal operations.  */
-/*************************************************************************/
+/*
+ * Escape op codes.  This provides an extensible setup for operations
+ * that are not scsi commands.  They are intended for modal operations.
+ */
 
 #define SCSI_OP_TARGET 0x0001
 #define        SCSI_OP_RESET   0x0002
 #define        SCSI_OP_BDINFO  0x0003
 
 
 #define SCSI_OP_TARGET 0x0001
 #define        SCSI_OP_RESET   0x0002
 #define        SCSI_OP_BDINFO  0x0003
 
-/********************************/
-/* Error values                        */
-/********************************/
+/*
+ * Error values an adapter driver may return
+ */
 #define XS_NOERROR     0x0     /* there is no error, (sense is invalid)  */
 #define XS_SENSE       0x1     /* Check the returned sense for the error */
 #define        XS_DRIVER_STUFFUP 0x2   /* Driver failed to perform operation     */
 #define XS_NOERROR     0x0     /* there is no error, (sense is invalid)  */
 #define XS_SENSE       0x1     /* Check the returned sense for the error */
 #define        XS_DRIVER_STUFFUP 0x2   /* Driver failed to perform operation     */
@@ -126,4 +217,30 @@ struct scsi_xfer
 #define XS_SWTIMEOUT   0x04    /* The Timeout reported was caught by SW  */
 #define XS_BUSY                0x08    /* The device busy, try again later?      */
 
 #define XS_SWTIMEOUT   0x04    /* The Timeout reported was caught by SW  */
 #define XS_BUSY                0x08    /* The device busy, try again later?      */
 
-#endif /* _SCSI_SCSICONF_H_ */
+void scsi_attachdevs __P((struct scsi_link *sc_link_proto));
+struct scsi_xfer *get_xs( struct scsi_link *sc_link, u_int32 flags);
+void free_xs(struct scsi_xfer *xs, struct scsi_link *sc_link,u_int32 flags);
+u_int32 scsi_size( struct scsi_link *sc_link,u_int32 flags);
+errval scsi_test_unit_ready( struct scsi_link *sc_link, u_int32 flags);
+errval scsi_change_def( struct scsi_link *sc_link, u_int32 flags);
+errval scsi_inquire( struct scsi_link *sc_link,
+                       struct scsi_inquiry_data *inqbuf, u_int32 flags);
+errval scsi_prevent( struct scsi_link *sc_link, u_int32 type,u_int32 flags);
+errval scsi_start_unit( struct scsi_link *sc_link, u_int32 flags);
+void scsi_done(struct scsi_xfer *xs);
+errval scsi_scsi_cmd( struct scsi_link *sc_link, struct scsi_generic *scsi_cmd,
+                       u_int32 cmdlen, u_char *data_addr,
+                       u_int32 datalen, u_int32 retries,
+                       u_int32 timeout, struct buf *bp,
+                       u_int32 flags);
+errval scsi_do_ioctl __P((struct scsi_link *sc_link, int cmd, caddr_t addr, int f));
+
+void show_scsi_xs(struct scsi_xfer *xs);
+void show_scsi_cmd(struct scsi_xfer *xs);
+void show_mem(unsigned char * , u_int32);
+
+void   lto3b __P((int val, u_char *bytes));
+int    _3btol __P((u_char *bytes));
+
+#endif /*SCSI_SCSICONF_H*/
+/* END OF FILE */
index 6717449..b3320aa 100644 (file)
@@ -14,7 +14,7 @@
  *
  * Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992
  *
  *
  * Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992
  *
- *     $Id: sd.c,v 1.10 1993/09/20 06:28:13 rgrimes Exp $
+ *      $Id: sd.c,v 2.7 93/10/24 12:44:40 julian Exp Locker: julian $
  */
 
 #define SPLSD splbio
  */
 
 #define SPLSD splbio
 #include <scsi/scsi_disk.h>
 #include <scsi/scsiconf.h>
 
 #include <scsi/scsi_disk.h>
 #include <scsi/scsiconf.h>
 
-long int sdstrats,sdqueues;
-
+u_int32 sdstrats, sdqueues;
 
 
+#ifdef NetBSD
+#ifdef DDB
+int     Debugger();
+#else  /* DDB */
+#define Debugger()
+#endif /* DDB */
+#else /* NetBSD */
 #include <ddb.h>
 #if    NDDB > 0
 #include <ddb.h>
 #if    NDDB > 0
-int    Debugger();
-#else  NDDB > 0
+int     Debugger();
+#else  /* NDDB > 0 */
 #define Debugger()
 #define Debugger()
-#endif NDDB > 0
-
+#endif /* NDDB > 0 */
+#endif
 
 #define PAGESIZ        4096
 #define SECSIZE 512
 
 #define PAGESIZ        4096
 #define SECSIZE 512
-#define PDLOCATION     29      
+#define PDLOCATION     29
 #define BOOTRECORDSIGNATURE                    (0x55aa & 0x00ff)
 #define        SDOUTSTANDING   2
 #define SDQSIZE                4
 #define BOOTRECORDSIGNATURE                    (0x55aa & 0x00ff)
 #define        SDOUTSTANDING   2
 #define SDQSIZE                4
@@ -64,838 +70,704 @@ int       Debugger();
 
 #define WHOLE_DISK(unit) ( (unit << UNITSHIFT) + RAW_PART )
 
 
 #define WHOLE_DISK(unit) ( (unit << UNITSHIFT) + RAW_PART )
 
-struct buf sd_buf_queue[NSD];
-int    sd_done();
-int    sdstrategy();
+errval sdgetdisklabel __P((unsigned char unit));
+errval sd_get_parms __P((int unit, int flags));
+errval  sdstrategy();
+void    sdstart();
 
 
-#ifdef SDDEBUG
-int    sd_debug = 0;
-#endif /*SDDEBUG*/
-
-struct scsi_xfer       *sd_free_xfer[NSD];
-int                    sd_xfer_block_wait[NSD];
-
-struct sd_data
+struct scsi_device sd_switch =
 {
 {
-       int     flags;
-#define        SDVALID         0x02            /* PARAMS LOADED        */
-#define        SDINIT          0x04            /* device has been init'd */
-#define        SDWAIT          0x08            /* device has someone waiting */
-#define SDHAVELABEL    0x10            /* have read the label */
-#define SDDOSPART      0x20            /* Have read the DOS partition table */
-#define SDWRITEPROT    0x40            /* Device in readonly mode (S/W)*/
-       struct  scsi_switch *sc_sw;     /* address of scsi low level switch */
-       int     ctlr;                   /* so they know which one we want */
-       int     targ;                   /* our scsi target ID */
-       int     lu;                     /* out scsi lu */
-       long int        ad_info;        /* info about the adapter */
-       int     cmdscount;              /* cmds allowed outstanding by board*/
-       int     wlabel;                 /* label is writable */
-       struct  disk_parms
-       {
-               u_char  heads;          /* Number of heads */
-               u_short cyls;           /* Number of cylinders */
-               u_char  sectors;/*dubious*/     /* Number of sectors/track */
-               u_short secsiz;         /* Number of bytes/sector */
-               u_long  disksize;               /* total number sectors */
-       }params;
-       struct  disklabel       disklabel;
-       struct  dos_partition dosparts[NDOSPART]; /* DOS view of disk */
-       int     partflags[MAXPARTITIONS];       /* per partition flags */
+    NULL,                      /* Use default error handler */
+    sdstart,                   /* have a queue, served by this */
+    NULL,                      /* have no async handler */
+    NULL,                      /* Use default 'done' routine */
+    "sd",
+    0,
+    { 0, 0 }
+};
+
+struct sd_data {
+       u_int32 flags;
+#define        SDINIT          0x04    /* device has been init'd */
+#define SDHAVELABEL    0x10    /* have read the label */
+#define SDDOSPART      0x20    /* Have read the DOS partition table */
+#define SDWRITEPROT    0x40    /* Device in readonly mode (S/W) */
+       struct scsi_link *sc_link;      /* contains our targ, lun etc. */
+       u_int32 ad_info;        /* info about the adapter */
+       u_int32 cmdscount;      /* cmds allowed outstanding by board */
+       boolean wlabel;         /* label is writable */
+       struct disk_parms {
+               u_char  heads;  /* Number of heads */
+               u_int16 cyls;   /* Number of cylinders */
+               u_char  sectors;        /*dubious *//* Number of sectors/track */
+               u_int16 secsiz; /* Number of bytes/sector */
+               u_int32 disksize;       /* total number sectors */
+       } params;
+       struct disklabel disklabel;
+#ifdef NetBSD
+       struct cpu_disklabel cpudisklabel;
+#else
+       struct dos_partition dosparts[NDOSPART];        /* DOS view of disk */
+#endif /* NetBSD */
+       u_int32 partflags[MAXPARTITIONS];       /* per partition flags */
 #define SDOPEN 0x01
 #define SDOPEN 0x01
-       int             openparts;              /* one bit for each open partition */
-       unsigned int    sd_start_of_unix;       /* unix vs dos partitions */
-}*sd_data[NSD];
+       u_int32 openparts;              /* one bit for each open partition */
+       u_int32 sd_start_of_unix;       /* unix vs dos partitions */
+       struct buf buf_queue;
+       u_int32 xfer_block_wait;
+}      *sd_data[NSD];
 
 
+static u_int32 next_sd_unit = 0;
 
 
-static int     next_sd_unit = 0;
-/***********************************************************************\
-* The routine called by the low level scsi routine when it discovers   *
-* A device suitable for this driver                                    *
-\***********************************************************************/
-
-int    sdattach(ctlr,targ,lu,scsi_switch)
-struct scsi_switch *scsi_switch;
+/*
+ * The routine called by the low level scsi routine when it discovers
+ * a device suitable for this driver.
+ */
+errval 
+sdattach(sc_link)
+       struct scsi_link *sc_link;
 {
 {
-       int     unit,i;
-       unsigned char *tbl;
+       u_int32 unit;
        struct sd_data *sd;
        struct disk_parms *dp;
        struct sd_data *sd;
        struct disk_parms *dp;
-       long int        ad_info;
-       struct  scsi_xfer       *sd_scsi_xfer;
 
        unit = next_sd_unit++;
 
        unit = next_sd_unit++;
-#ifdef SDDEBUG
-       if(scsi_debug & PRINTROUTINES) printf("sdattach: "); 
-#endif /*SDDEBUG*/
-       /*******************************************************\
-       * Check we have the resources for another drive         *
-       \*******************************************************/
-       if( unit >= NSD)
-       {
-               printf("Too many scsi disks..(%d > %d) reconfigure kernel\n",(unit + 1),NSD);
-               return(0);
+       SC_DEBUG(sc_link, SDEV_DB2, ("sdattach: "));
+       /*
+        * Check we have the resources for another drive
+        */
+       if (unit >= 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);
+       if (sd_data[unit]) {
+               printf("sd%d: unit already has storage allocated!\n", unit);
+               return 0;
        }
        }
-       sd = sd_data[unit] = malloc(sizeof(struct sd_data),M_DEVBUF,M_NOWAIT);
-       if(!sd)
-       {
+       sd = sd_data[unit] = malloc(sizeof(struct sd_data), M_DEVBUF, M_NOWAIT);
+       if (!sd) {
                printf("malloc failed in sd.c\n");
                printf("malloc failed in sd.c\n");
-               return(0);
+               return (0);
        }
        }
-       bzero(sd,sizeof(struct sd_data));
-
-       dp  = &(sd->params);
-       /*******************************************************\
-       * Store information needed to contact our base driver   *
-       \*******************************************************/
-       sd->sc_sw       =       scsi_switch;
-       sd->ctlr        =       ctlr;
-       sd->targ        =       targ;
-       sd->lu          =       lu;
-       if(sd->sc_sw->adapter_info)
-       {
-               sd->ad_info = ( (*(sd->sc_sw->adapter_info))(ctlr));
-               sd->cmdscount = sd->ad_info & AD_INF_MAX_CMDS;
-               if(sd->cmdscount > SDOUTSTANDING)
-               {
+       bzero(sd, sizeof(struct sd_data));
+
+       dp = &(sd->params);
+       /*
+        * Store information needed to contact our base driver
+        */
+       sd->sc_link = sc_link;
+       sc_link->device = &sd_switch;
+       sc_link->dev_unit = unit;
+
+       if (sd->sc_link->adapter->adapter_info) {
+               sd->ad_info = ((*(sd->sc_link->adapter->adapter_info)) (sc_link->adapter_unit));
+               sd->cmdscount = sd->ad_info & AD_INF_MAX_CMDS;
+               if (sd->cmdscount > SDOUTSTANDING) {
                        sd->cmdscount = SDOUTSTANDING;
                }
                        sd->cmdscount = SDOUTSTANDING;
                }
-       }
-       else
-       {
+       } else {
                sd->ad_info = 1;
                sd->ad_info = 1;
-               sd->cmdscount = 1;
-       }
-
-       i = sd->cmdscount;
-       sd_scsi_xfer = (struct scsi_xfer *)malloc(sizeof(struct scsi_xfer) * i
-                               ,M_TEMP, M_NOWAIT);
-       while(i-- )
-       {
-               sd_scsi_xfer->next = sd_free_xfer[unit];
-               sd_free_xfer[unit] = sd_scsi_xfer;
-               sd_scsi_xfer++;
-       }
-       /*******************************************************\
-       * Use the subdriver to request information regarding    *
-       * the drive. We cannot use interrupts yet, so the       *
-       * request must specify this.                            *
-       \*******************************************************/
-       sd_get_parms(unit,  SCSI_NOSLEEP |  SCSI_NOMASK);
+               sd->cmdscount = 1;
+       } 
+       sc_link->opennings = sd->cmdscount;
+       /*
+        * Use the subdriver to request information regarding
+        * the drive. We cannot use interrupts yet, so the
+        * request must specify this.
+        */
+       sd_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK);
        printf("sd%d: %dMB (%d total sec), %d cyl, %d head, %d sec, bytes/sec %d\n",
        printf("sd%d: %dMB (%d total sec), %d cyl, %d head, %d sec, bytes/sec %d\n",
-               unit,
-               dp->disksize / ((1024L * 1024L) / dp->secsiz),
-               dp->disksize,
-               dp->cyls,
-               dp->heads,
-               dp->sectors,
-               dp->secsiz);
+           unit,
+           dp->disksize / ((1024L * 1024L) / dp->secsiz),
+           dp->disksize,
+           dp->cyls,
+           dp->heads,
+           dp->sectors,
+           dp->secsiz);
        sd->flags |= SDINIT;
        sd->flags |= SDINIT;
-       return;
-
+       return 0;
 }
 
 }
 
-
-
-/*******************************************************\
-*      open the device. Make sure the partition info   *
-* is a up-to-date as can be.                           *
-\*******************************************************/
+/*
+ * open the device. Make sure the partition info is a up-to-date as can be.
+ */
+errval
 sdopen(dev)
 sdopen(dev)
+       int     dev;    /* XXX should be dev_t, but avoid promotion problems for now */
 {
 {
-       int errcode = 0;
-       int unit, part;
-       struct disk_parms disk_parms;
-       struct sd_data *sd ;
+       errval  errcode = 0;
+       u_int32 unit, part;
+       struct sd_data *sd;
+       struct scsi_link *sc_link;
 
        unit = UNIT(dev);
        part = PARTITION(dev);
        sd = sd_data[unit];
 
        unit = UNIT(dev);
        part = PARTITION(dev);
        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);
-#endif /*SDDEBUG*/
-       /*******************************************************\
-       * Check the unit is legal                               *
-       \*******************************************************/
-       if ( unit >= NSD )
-       {
-               return(ENXIO);
+       /*
+        * Check the unit is legal
+        */
+       if (unit >= NSD) {
+               return (ENXIO);
        }
        }
-       /*******************************************************\
-       * Make sure the disk has been initialised               *
-       * At some point in the future, get the scsi driver      *
-       * to look for a new device if we are not initted        *
-       \*******************************************************/
-       if (! (sd->flags & SDINIT))
-       {
-               return(ENXIO);
+       /*
+        * Make sure the disk has been initialised
+        * At some point in the future, get the scsi driver
+        * to look for a new device if we are not initted
+        */
+       if ((!sd) || (!(sd->flags & SDINIT))) {
+               return (ENXIO);
        }
        }
+       sc_link = sd->sc_link;
+
+       SC_DEBUG(sc_link, SDEV_DB1,
+           ("sdopen: dev=0x%x (unit %d (of %d),partition %d)\n"
+               ,dev, unit, NSD, part));
+
+       /*
+        * "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.
+        */
+       scsi_test_unit_ready(sc_link, 0);
+
+       /*
+        * If it's been invalidated, then forget the label
+        */
+       sc_link->flags |= SDEV_OPEN;    /* unit attn becomes an err now */
+       if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
+               sd->flags &= ~SDHAVELABEL;
 
 
-       /*******************************************************\
-       * If it's been invalidated, and not everybody has       *
-       * closed it then forbid re-entry.                       *
-       \*******************************************************/
-       if ((! (sd->flags & SDVALID))
-          && ( sd->openparts))
-               return(ENXIO);
-       /*******************************************************\
-       * "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);
-
-       /*******************************************************\
-       * 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);
+               /*
+                * If somebody still has      it open, then forbid re-entry.
+                */
+               if (sd->openparts) {
+                       errcode = ENXIO;
+                       goto bad;
+               }
+       }
+       /*
+        * In case it is a funny one, tell it to start
+        * not needed for  most hard drives (ignore failure)
+        */
+       scsi_start_unit(sc_link, SCSI_ERR_OK | SCSI_SILENT);
+
+       /*
+        * Check that it is still responding and ok.
+        */
+       if (scsi_test_unit_ready(sc_link, 0)) {
+               SC_DEBUG(sc_link, SDEV_DB3, ("device not reponding\n"));
+               errcode = ENXIO;
+               goto bad;
        }
        }
-#ifdef SDDEBUG
-       if(scsi_debug & TRACEOPENS)
-               printf("device ok\n");
-#endif /*SDDEBUG*/
-
-       /*******************************************************\
-       * Load the physical device parameters                   *
-       \*******************************************************/
-       sd_get_parms(unit, 0);  /* sets SDVALID */
-       if (sd->params.secsiz != SECSIZE)       /* XXX One day...*/
-       {
-               printf("sd%d: Can't deal with %d bytes logical blocks\n"
-                       ,unit, sd->params.secsiz);
+       SC_DEBUG(sc_link, SDEV_DB3, ("device ok\n"));
+
+       /*
+        * Load the physical device parameters 
+        */
+       sd_get_parms(unit, 0);  /* sets SDEV_MEDIA_LOADED */
+       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();
                Debugger();
-               return(ENXIO);
+               errcode = ENXIO;
+               goto bad;
        }
        }
-#ifdef SDDEBUG
-       if(scsi_debug & TRACEOPENS)
-               printf("Params loaded ");
-#endif /*SDDEBUG*/
-       /*******************************************************\
-       * Load the partition info if not already loaded         *
-       * Lock the pack in                                      *
-       \*******************************************************/
-       sd_prevent(unit,PR_PREVENT,SCSI_ERR_OK|SCSI_SILENT);
-       if((errcode = sdgetdisklabel(unit)) && (part != RAW_PART))
-       {
-               sd_prevent(unit,PR_ALLOW,SCSI_ERR_OK|SCSI_SILENT);
-               return(errcode);
+       SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded "));
+
+       /* Lock the pack in. */
+       scsi_prevent(sc_link, PR_PREVENT, SCSI_ERR_OK | SCSI_SILENT);
+
+       /*
+        * Load the partition info if not already loaded.
+        */
+       if ((errcode = sdgetdisklabel(unit)) && (part != RAW_PART)) {
+               goto bad;
        }
        }
-#ifdef SDDEBUG
-       if(scsi_debug & TRACEOPENS)
-               printf("Disklabel loaded ");
-#endif /*SDDEBUG*/
-       /*******************************************************\
-       * Check the partition is legal                          *
-       \*******************************************************/
-       if ( part >= MAXPARTITIONS ) {
-               sd_prevent(unit,PR_ALLOW,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */
-               return(ENXIO);
+       SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel loaded "));
+       /*
+        * Check the partition is legal
+        */
+       if (part >= MAXPARTITIONS) {
+               errcode = ENXIO;
+               goto bad;
        }
        }
-#ifdef SDDEBUG
-       if(scsi_debug & TRACEOPENS)
-               printf("ok");
-#endif /*SDDEBUG*/
-       /*******************************************************\
-       *  Check that the partition exists                      *
-       \*******************************************************/
-       if (( sd->disklabel.d_partitions[part].p_size == 0 )
-               && (part != RAW_PART))
-       {
-               sd_prevent(unit,PR_ALLOW,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */
-               return(ENXIO);
+       SC_DEBUG(sc_link, SDEV_DB3, ("partition ok"));
+
+       /*
+        *  Check that the partition exists
+        */
+       if ((sd->disklabel.d_partitions[part].p_size == 0)
+           && (part != RAW_PART)) {
+               errcode = ENXIO;
+               goto bad;
        }
        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);
-#endif /*SDDEBUG*/
-       return(0);
-}
+       SC_DEBUG(sc_link, SDEV_DB3, ("open %d %d\n", sdstrats, sdqueues));
+       return 0;
 
 
-/*******************************************************\
-* Get ownership of a scsi_xfer                         *
-* If need be, sleep on it, until it comes free         *
-\*******************************************************/
-struct scsi_xfer *sd_get_xs(unit,flags)
-int    flags;
-int    unit;
-{
-       struct scsi_xfer *xs;
-       int     s;
-
-       if(flags & (SCSI_NOSLEEP |  SCSI_NOMASK))
-       {
-               if (xs = sd_free_xfer[unit])
-               {
-                       sd_free_xfer[unit] = xs->next;
-                       xs->flags = 0;
-               }
-       }
-       else
-       {
-               s = SPLSD();
-               while (!(xs = sd_free_xfer[unit]))
-               {
-                       sd_xfer_block_wait[unit]++;  /* someone waiting! */
-                       sleep((caddr_t)&sd_free_xfer[unit], PRIBIO+1);
-                       sd_xfer_block_wait[unit]--;
-               }
-               sd_free_xfer[unit] = xs->next;
-               splx(s);
-               xs->flags = 0;
+bad:
+       if (!(sd->openparts)) {
+               scsi_prevent(sc_link, PR_ALLOW, SCSI_ERR_OK | SCSI_SILENT);
+               sc_link->flags &= ~SDEV_OPEN;
        }
        }
-       return(xs);
+       return errcode;
 }
 
 }
 
-/*******************************************************\
-* Free a scsi_xfer, wake processes waiting for it      *
-\*******************************************************/
-sd_free_xs(unit,xs,flags)
-struct scsi_xfer *xs;
-int    unit;
-int    flags;
+/*
+ * close the device.. only called if we are the LAST occurence of an open
+ * device.  Convenient now but usually a pain.
+ */
+errval 
+sdclose(dev)
+       dev_t   dev;
 {
 {
-       int     s;
-       
-       if(flags & SCSI_NOMASK)
-       {
-               if (sd_xfer_block_wait[unit])
-               {
-                       printf("doing a wakeup from NOMASK mode\n");
-                       wakeup((caddr_t)&sd_free_xfer[unit]);
-               }
-               xs->next = sd_free_xfer[unit];
-               sd_free_xfer[unit] = xs;
-       }
-       else
-       {
-               s = SPLSD();
-               if (sd_xfer_block_wait[unit])
-                       wakeup((caddr_t)&sd_free_xfer[unit]);
-               xs->next = sd_free_xfer[unit];
-               sd_free_xfer[unit] = xs;
-               splx(s);
-       }
+       unsigned char unit, part;
+       struct sd_data *sd;
+
+       unit = UNIT(dev);
+       part = PARTITION(dev);
+       sd = sd_data[unit];
+       sd->partflags[part] &= ~SDOPEN;
+       sd->openparts &= ~(1 << part);
+       scsi_prevent(sd->sc_link, PR_ALLOW, SCSI_SILENT | SCSI_ERR_OK);
+       if (!(sd->openparts))
+               sd->sc_link->flags &= ~SDEV_OPEN;
+       return 0;
 }
 
 }
 
-/*******************************************************\
-* trim the size of the transfer if needed,             *
-* called by physio                                     *
-* basically the smaller of our max and the scsi driver's*
-* minphys (note we have no max)                                *
-\*******************************************************/
-/* Trim buffer length if buffer-size is bigger than page size */
-void   sdminphys(bp)
-struct buf     *bp;
+/*
+ * trim the size of the transfer if needed, called by physio
+ * basically the smaller of our max and the scsi driver's
+ * minphys (note we have no max)
+ *
+ * Trim buffer length if buffer-size is bigger than page size
+ */
+void 
+sdminphys(bp)
+       struct buf *bp;
 {
 {
-       (*(sd_data[UNIT(bp->b_dev)]->sc_sw->scsi_minphys))(bp);
+       (*(sd_data[UNIT(bp->b_dev)]->sc_link->adapter->scsi_minphys)) (bp);
 }
 
 }
 
-/*******************************************************\
-* Actually translate the requested transfer into       *
-* one the physical driver can understand               *
-* The transfer is described by a buf and will include  *
-* only one physical transfer.                          *
-\*******************************************************/
-
-int    sdstrategy(bp)
-struct buf     *bp;
+/*
+ * Actually translate the requested transfer into one the physical driver
+ * can understand.  The transfer is described by a buf and will include
+ * only one physical transfer.
+ */
+errval 
+sdstrategy(bp)
+       struct buf *bp;
 {
 {
-       struct  buf     *dp;
-       unsigned int opri;
-       struct sd_data *sd ;
-       int     unit;
+       struct buf *dp;
+       u_int32 opri;
+       struct sd_data *sd;
+       u_int32 unit;
 
        sdstrats++;
        unit = UNIT((bp->b_dev));
        sd = sd_data[unit];
 
        sdstrats++;
        unit = UNIT((bp->b_dev));
        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);
-#endif /*SDDEBUG*/
+       SC_DEBUG(sd->sc_link, SDEV_DB2, ("sdstrategy "));
+       SC_DEBUG(sd->sc_link, SDEV_DB1,
+           (" %d bytes @ blk%d\n", bp->b_bcount, bp->b_blkno));
        sdminphys(bp);
        sdminphys(bp);
-       /*******************************************************\
-       * If the device has been made invalid, error out        *
-       \*******************************************************/
-       if(!(sd->flags & SDVALID))
-       {
+       /*
+        * If the device has been made invalid, error out
+        */
+       if (!(sd->sc_link->flags & SDEV_MEDIA_LOADED)) {
+               sd->flags &= ~SDHAVELABEL;
                bp->b_error = EIO;
                goto bad;
        }
                bp->b_error = EIO;
                goto bad;
        }
-       /*******************************************************\
-       * "soft" write protect check                            *
-       \*******************************************************/
+       /*
+        * "soft" write protect check
+        */
        if ((sd->flags & SDWRITEPROT) && (bp->b_flags & B_READ) == 0) {
                bp->b_error = EROFS;
                goto bad;
        }
        if ((sd->flags & SDWRITEPROT) && (bp->b_flags & B_READ) == 0) {
                bp->b_error = EROFS;
                goto bad;
        }
-       /*******************************************************\
-       * If it's a null transfer, return immediatly            *
-       \*******************************************************/
-       if (bp->b_bcount == 0)
-       {
+       /*
+        * If it's a null transfer, return immediatly
+        */
+       if (bp->b_bcount == 0) {
                goto done;
        }
                goto done;
        }
-
-       /*******************************************************\
-       * Decide which unit and partition we are talking about  *
-       * only raw is ok if no label                            *
-       \*******************************************************/
-       if(PARTITION(bp->b_dev) != RAW_PART)
-       {
-               if (!(sd->flags & SDHAVELABEL))
-               {
+       /*
+        * Decide which unit and partition we are talking about
+        * only raw is ok if no label
+        */
+       if (PARTITION(bp->b_dev) != RAW_PART) {
+               if (!(sd->flags & SDHAVELABEL)) {
                        bp->b_error = EIO;
                        goto bad;
                }
                        bp->b_error = EIO;
                        goto bad;
                }
-
                /*
                 * do bounds checking, adjust transfer. if error, process.
                 * if end of partition, just return
                 */
                /*
                 * do bounds checking, adjust transfer. if error, process.
                 * if end of partition, just return
                 */
-               if (bounds_check_with_label(bp,&sd->disklabel,sd->wlabel) <= 0)
+               if (bounds_check_with_label(bp, &sd->disklabel, sd->wlabel) <= 0)
                        goto done;
                /* otherwise, process transfer request */
        }
                        goto done;
                /* otherwise, process transfer request */
        }
-
        opri = SPLSD();
        opri = SPLSD();
-       dp = &sd_buf_queue[unit];
+       dp = &sd->buf_queue;
 
 
-       /*******************************************************\
-       * Place it in the queue of disk activities for this disk*
-       \*******************************************************/
+       /*
+        * Place it in the queue of disk activities for this disk
+        */
        disksort(dp, bp);
 
        disksort(dp, bp);
 
-       /*******************************************************\
-       * Tell the device to get going on the transfer if it's  *
-       * not doing anything, otherwise just wait for completion*
-       \*******************************************************/
+       /*
+        * Tell the device to get going on the transfer if it's
+        * not doing anything, otherwise just wait for completion
+        */
        sdstart(unit);
 
        splx(opri);
        sdstart(unit);
 
        splx(opri);
-       return;
+       return 0;
 bad:
        bp->b_flags |= B_ERROR;
 done:
 
 bad:
        bp->b_flags |= B_ERROR;
 done:
 
-       /*******************************************************\
-       * Correctly set the buf to indicate a completed xfer    *
-       \*******************************************************/
-       bp->b_resid = bp->b_bcount;
+       /*
+        * Correctly set the buf to indicate a completed xfer
+        */
+       bp->b_resid = bp->b_bcount;
        biodone(bp);
        biodone(bp);
-       return;
+       return 0;
 }
 
 }
 
-/***************************************************************\
-* 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 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.               *
-* The bufs are queued by the strategy routine (sdstrategy)     *
-*                                                              *
-* This routine is also called after other non-queued requests  *
-* have been made of the scsi driver, to ensure that the queue  *
-* continues to be drained.                                     *
-*                                                              *
-* must be called at the correct (highish) spl level            *
-\***************************************************************/
-/* sdstart() is called at SPLSD  from sdstrategy and sd_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,
+ * It dequeues the buf and creates a scsi command to perform the
+ * transfer in the buf. The transfer request will call scsi_done
+ * on completion, which will in turn call this routine again
+ * so that the next queued transfer is performed.
+ * The bufs are queued by the strategy routine (sdstrategy)
+ *
+ * This routine is also called after other non-queued requests
+ * have been made of the scsi driver, to ensure that the queue
+ * continues to be drained.
+ *
+ * must be called at the correct (highish) spl level
+ * sdstart() is called at SPLSD  from sdstrategy and scsi_done
+ */
+void 
 sdstart(unit)
 sdstart(unit)
-int    unit;
+       u_int32 unit;
 {
 {
-       int                     drivecount;
-       register struct buf     *bp = 0;
-       register struct buf     *dp;
-       struct  scsi_xfer       *xs;
-       struct  scsi_rw_big     cmd;
-       int                     blkno, nblk;
-       struct sd_data *sd = sd_data[unit];
-       struct partition *p ;
-
-#ifdef SDDEBUG
-       if(scsi_debug & PRINTROUTINES) printf("sdstart%d ",unit);
-#endif /*SDDEBUG*/
-       /*******************************************************\
-       * Check if the device is already running full capacity  *
-       \*******************************************************/
-       if(!sd_free_xfer[unit])
-       {
-               return;    /* none for us, unit already underway */
-       }
-
-       /*******************************************************\
-       * 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;
-       }
+       register struct sd_data *sd = sd_data[unit];
+       register struct scsi_link *sc_link = sd->sc_link;
+       struct buf *bp = 0;
+       struct buf *dp;
+       struct scsi_rw_big cmd;
+       u_int32 blkno, nblk;
+       struct partition *p;
+
+       SC_DEBUG(sc_link, SDEV_DB2, ("sdstart "));
+       /*
+        * Check if the device has room for another command
+        */
+       while (sc_link->opennings) {
 
 
-       /*******************************************************\
-       * See if there is a buf with work for us to do..        *
-       \*******************************************************/
-       dp = &sd_buf_queue[unit];
-       if ((bp = dp->b_actf) == NULL)  /* yes, an assign */
-       {
-               return;
-       }
+               /*
+                * 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 (sc_link->flags & SDEV_WAITING) {
+                       return;
+               }
+               /*
+                * See if there is a buf with work for us to do..
+                */
+               dp = &sd->buf_queue;
+               if ((bp = dp->b_actf) == NULL) {        /* yes, an assign */
+                       return;
+               }
+               dp->b_actf = bp->av_forw;
 
 
-       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
+                * re-openned
+                */
+               if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
+                       sd->flags &= ~SDHAVELABEL;
+                       goto bad;
+               }
+               /*
+                * 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);
+               blkno = bp->b_blkno + p->p_offset;
+               nblk = (bp->b_bcount + 511) >> 9;
 
 
-       /*******************************************************\
-       *  If the device has become invalid, abort all the      *
-       * reads and writes until all files have been closed and *
-       * re-openned                                            *
-       \*******************************************************/
-       if(!(sd->flags & SDVALID))
-       {
-               goto bad;
-       }
-       /*******************************************************\
-       * 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);
-       blkno = bp->b_blkno + p->p_offset;
-       nblk = (bp->b_bcount + 511) >> 9;
-
-       /*******************************************************\
-       *  Fill out the scsi command                            *
-       \*******************************************************/
-       bzero(&cmd, sizeof(cmd));
-       cmd.op_code             =       (bp->b_flags & B_READ) 
-                                               ? READ_BIG : WRITE_BIG;
-       cmd.addr_3      =       (blkno & 0xff000000) >> 24;
-       cmd.addr_2      =       (blkno & 0xff0000) >> 16;
-       cmd.addr_1      =       (blkno & 0xff00) >> 8;
-       cmd.addr_0      =       blkno & 0xff;
-       cmd.length2     =       (nblk & 0xff00) >> 8;
-       cmd.length1     =       (nblk & 0xff);
-       /*******************************************************\
-       * Call the routine that chats with the adapter          *
-       *       Note: we cannot sleep as we may be an interrupt *
-       \*******************************************************/
-       if (sd_scsi_cmd(unit,
-                       &cmd,
+               /*
+                *  Fill out the scsi command
+                */
+               bzero(&cmd, sizeof(cmd));
+               cmd.op_code = (bp->b_flags & B_READ)
+                   ? READ_BIG : WRITE_BIG;
+               cmd.addr_3 = (blkno & 0xff000000) >> 24;
+               cmd.addr_2 = (blkno & 0xff0000) >> 16;
+               cmd.addr_1 = (blkno & 0xff00) >> 8;
+               cmd.addr_0 = blkno & 0xff;
+               cmd.length2 = (nblk & 0xff00) >> 8;
+               cmd.length1 = (nblk & 0xff);
+               /*
+                * Call the routine that chats with the adapter.
+                * Note: we cannot sleep as we may be an interrupt
+                */
+               if (scsi_scsi_cmd(sc_link,
+                       (struct scsi_generic *) &cmd,
                        sizeof(cmd),
                        sizeof(cmd),
-                       (u_char *)bp->b_un.b_addr,
+                       (u_char *) bp->b_un.b_addr,
                        bp->b_bcount,
                        bp->b_bcount,
+                       SD_RETRIES,
                        10000,
                        bp,
                        10000,
                        bp,
-                       SCSI_NOSLEEP| ((bp->b_flags & B_READ)?
-                               SCSI_DATA_IN : SCSI_DATA_OUT))
-               != SUCCESSFULLY_QUEUED)
-       {
+                       SCSI_NOSLEEP | ((bp->b_flags & B_READ) ?
+                           SCSI_DATA_IN : SCSI_DATA_OUT))
+                   == SUCCESSFULLY_QUEUED) {
+                       sdqueues++;
+               } else {
 bad:
 bad:
-               printf("sd%d: oops not queued",unit);
-               bp->b_error = EIO;
-               bp->b_flags |= B_ERROR;
-               biodone(bp);
-               return ;
+                       printf("sd%d: oops not queued", unit);
+                       bp->b_error = EIO;
+                       bp->b_flags |= B_ERROR;
+                       biodone(bp);
+               }
        }
        }
-       sdqueues++;
 }
 
 }
 
-/*******************************************************\
-* 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
+ */
+errval 
 sdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
 {
 sdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
 {
-       /* struct sd_cmd_buf *args;*/
-       int error = 0;
-       unsigned int opri;
+       /* struct sd_cmd_buf *args; */
+       errval  error = 0;
        unsigned char unit, part;
        register struct sd_data *sd;
 
        unsigned char unit, part;
        register struct sd_data *sd;
 
-
-       /*******************************************************\
-       * Find the device that the user is talking about        *
-       \*******************************************************/
+       /*
+        * Find the device that the user is talking about
+        */
        unit = UNIT(dev);
        part = PARTITION(dev);
        sd = sd_data[unit];
        unit = UNIT(dev);
        part = PARTITION(dev);
        sd = sd_data[unit];
-#ifdef SDDEBUG
-       if(scsi_debug & PRINTROUTINES) printf("sdioctl%d ",unit);
-#endif /*SDDEBUG*/
-
-       /*******************************************************\
-       * If the device is not valid.. abandon ship             *
-       \*******************************************************/
-       if (!(sd->flags & SDVALID))
-               return(EIO);
-       switch(cmd)
-       {
+       SC_DEBUG(sd->sc_link, SDEV_DB1, ("sdioctl (0x%x)", cmd));
+
+       /*
+        * If the device is not valid.. abandon ship
+        */
+       if (!(sd->sc_link->flags & SDEV_MEDIA_LOADED))
+               return (EIO);
+       switch (cmd) {
 
        case DIOCSBAD:
 
        case DIOCSBAD:
-                        error = EINVAL;
+               error = EINVAL;
                break;
 
        case DIOCGDINFO:
                break;
 
        case DIOCGDINFO:
-               *(struct disklabel *)addr = sd->disklabel;
+               *(struct disklabel *) addr = sd->disklabel;
+               break;
+
+       case DIOCGPART:
+               ((struct partinfo *) addr)->disklab = &sd->disklabel;
+               ((struct partinfo *) addr)->part =
+                   &sd->disklabel.d_partitions[PARTITION(dev)];
                break;
 
                break;
 
-        case DIOCGPART:
-                ((struct partinfo *)addr)->disklab = &sd->disklabel;
-                ((struct partinfo *)addr)->part =
-                    &sd->disklabel.d_partitions[PARTITION(dev)];
-                break;
-
-        case DIOCSDINFO:
-                if ((flag & FWRITE) == 0)
-                        error = EBADF;
-                else
-                        error = setdisklabel(&sd->disklabel,
-                                       (struct disklabel *)addr,
-                         /*(sd->flags & DKFL_BSDLABEL) ? sd->openparts : */0,
-                               sd->dosparts);
-                if (error == 0) {
+       case DIOCSDINFO:
+               if ((flag & FWRITE) == 0)
+                       error = EBADF;
+               else
+                       error = setdisklabel(&sd->disklabel,
+                           (struct disklabel *)addr,
+                       /*(sd->flags & DKFL_BSDLABEL) ? sd->openparts : */ 0,
+#ifdef NetBSD
+                           &sd->cpudisklabel
+#else
+                           sd->dosparts
+#endif
+                           );
+               if (error == 0) {
                        sd->flags |= SDHAVELABEL;
                }
                        sd->flags |= SDHAVELABEL;
                }
-                break;
+               break;
 
 
-        case DIOCWLABEL:
+       case DIOCWLABEL:
                sd->flags &= ~SDWRITEPROT;
                sd->flags &= ~SDWRITEPROT;
-                if ((flag & FWRITE) == 0)
-                        error = EBADF;
-                else
-                        sd->wlabel = *(int *)addr;
-                break;
+               if ((flag & FWRITE) == 0)
+                       error = EBADF;
+               else
+                       sd->wlabel = *(boolean *) addr;
+               break;
 
 
-        case DIOCWDINFO:
+       case DIOCWDINFO:
                sd->flags &= ~SDWRITEPROT;
                sd->flags &= ~SDWRITEPROT;
-                if ((flag & FWRITE) == 0)
-                        error = EBADF;
-                else
-               {
-                       if ((error = setdisklabel(&sd->disklabel
-                                               , (struct disklabel *)addr
-                       , /*(sd->flags & SDHAVELABEL) ? sd->openparts :*/ 0
-                                               , sd->dosparts)) == 0)
-                       {
-                               int wlab;
-
-                               sd->flags |= SDHAVELABEL; /* ok write will succeed */
-
-                               /* simulate opening partition 0 so write succeeds */
-                               sd->openparts |= (1 << 0);            /* XXX */
-                               wlab = sd->wlabel;
-                               sd->wlabel = 1;
-                               error = writedisklabel(dev, sdstrategy,
-                                       &sd->disklabel, sd->dosparts);
-                               sd->wlabel = wlab;
-                       }
-               }
-                break;
-
+               if ((flag & FWRITE) == 0)
+                       error = EBADF;
+               else {
+                       error = setdisklabel(&sd->disklabel,
+                           (struct disklabel *)addr,
+                           /*(sd->flags & SDHAVELABEL) ? sd->openparts : */ 0,
+#ifdef NetBSD
+                           &sd->cpudisklabel
+#else
+                           sd->dosparts
+#endif
+                           );
+                       if (!error) {
+                               boolean wlab;
+
+                               /* ok - write will succeed */
+                               sd->flags |= SDHAVELABEL;
+
+                               /* simulate opening partition 0 so write succeeds */
+                               sd->openparts |= (1 << 0);      /* XXX */
+                               wlab = sd->wlabel;
+                               sd->wlabel = 1;
+                               error = writedisklabel(dev, sdstrategy,
+                                   &sd->disklabel,
+#ifdef NetBSD
+                                   &sd->cpudisklabel
+#else
+                                   sd->dosparts
+#endif
+                                   );
+                               sd->wlabel = wlab;
+                       }
+               } 
+               break;
 
        default:
 
        default:
-               error = ENOTTY;
+               if (part == RAW_PART)
+                       error = scsi_do_ioctl(sd->sc_link, cmd, addr, flag);
+               else
+                       error = ENOTTY;
                break;
        }
                break;
        }
-       return (error);
+       return error;
 }
 
 }
 
-
-/*******************************************************\
-* Load the label information on the named device       *
-\*******************************************************/
-int sdgetdisklabel(unit)
-unsigned char  unit;
+/*
+ * Load the label information on the named device
+ */
+errval 
+sdgetdisklabel(unsigned char unit)
 {
 {
-       /*unsigned int n, m;*/
-       char *errstring;
-       struct dos_partition *dos_partition_p;
+       char   *errstring;
        struct sd_data *sd = sd_data[unit];
 
        struct sd_data *sd = sd_data[unit];
 
-       /*******************************************************\
-       * If the inflo is already loaded, use it                *
-       \*******************************************************/
-       if(sd->flags & SDHAVELABEL) return(ESUCCESS);
-
-       bzero(&sd->disklabel,sizeof(struct disklabel));
-       /*******************************************************\
-       * make partition 3 the whole disk in case of failure    *
-       *   then get pdinfo                                     *
-       * for historical reasons, make part a same as raw part  *
-       \*******************************************************/
+       /*
+        * If the inflo is already loaded, use it
+        */
+       if (sd->flags & SDHAVELABEL)
+               return (ESUCCESS);
+
+       bzero(&sd->disklabel, sizeof(struct disklabel));
+       /*
+        * 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[RAW_PART].p_offset = 0;
        sd->disklabel.d_partitions[RAW_PART].p_size = sd->params.disksize;
        sd->disklabel.d_npartitions = MAXPARTITIONS;
        sd->disklabel.d_partitions[0].p_offset = 0;
        sd->disklabel.d_partitions[0].p_size = sd->params.disksize;
        sd->disklabel.d_partitions[RAW_PART].p_offset = 0;
        sd->disklabel.d_partitions[RAW_PART].p_size = sd->params.disksize;
        sd->disklabel.d_npartitions = MAXPARTITIONS;
-       sd->disklabel.d_secsize = 512; /* as long as it's not 0 */
+       sd->disklabel.d_secsize = SECSIZE;      /* as long as it's not 0 */
        sd->disklabel.d_ntracks = sd->params.heads;
        sd->disklabel.d_nsectors = sd->params.sectors;
        sd->disklabel.d_ncylinders = sd->params.cyls;
        sd->disklabel.d_secpercyl = sd->params.heads * sd->params.sectors;
        sd->disklabel.d_ntracks = sd->params.heads;
        sd->disklabel.d_nsectors = sd->params.sectors;
        sd->disklabel.d_ncylinders = sd->params.cyls;
        sd->disklabel.d_secpercyl = sd->params.heads * sd->params.sectors;
-       if (sd->disklabel.d_secpercyl == 0)
-       {
+       if (sd->disklabel.d_secpercyl == 0) {
                sd->disklabel.d_secpercyl = 100;
                sd->disklabel.d_secpercyl = 100;
-                                       /* as long as it's not 0 */
-                                       /* readdisklabel divides by it (?)*/
+               /* as long as it's not 0 - readdisklabel divides by it (?) */
        }
        }
-
-       /*******************************************************\
-       * Call the generic disklabel extraction routine         *
-       \*******************************************************/
-       if(errstring = readdisklabel(makedev(0 ,(unit<<UNITSHIFT )+3)
-                                       , sdstrategy
-                                       , &sd->disklabel
-                                       , sd->dosparts
-                                       , 0
-                                       , 0))
-       {
-               printf("sd%d: %s\n",unit, errstring);
-               return(ENXIO);
+       /*
+        * Call the generic disklabel extraction routine
+        */
+       if (errstring = readdisklabel(makedev(0, (unit << UNITSHIFT) + 3),
+           sdstrategy,
+           &sd->disklabel,
+#ifdef NetBSD
+           &sd->cpudisklabel
+#else
+           sd->dosparts,
+           0,
+           0
+#endif
+           )) {
+               printf("sd%d: %s\n", unit, errstring);
+               return ENXIO;
        }
        }
-
-       sd->flags |= SDHAVELABEL; /* WE HAVE IT ALL NOW */
-       return(ESUCCESS);
+       sd->flags |= SDHAVELABEL;       /* WE HAVE IT ALL NOW */
+       return ESUCCESS;
 }
 
 }
 
-/*******************************************************\
-* Find out from the device what it's capacity is       *
-\*******************************************************/
+/*
+ * Find out from the device what it's capacity is
+ */
+u_int32 
 sd_size(unit, flags)
 sd_size(unit, flags)
+       int     unit, flags;
 {
        struct scsi_read_cap_data rdcap;
        struct scsi_read_capacity scsi_cmd;
 {
        struct scsi_read_cap_data rdcap;
        struct scsi_read_capacity scsi_cmd;
-       int size;
+       u_int32 size;
 
 
-       /*******************************************************\
-       * make up a scsi command and ask the scsi driver to do  *
-       * it for you.                                           *
-       \*******************************************************/
+       /*
+        * make up a scsi command and ask the scsi driver to do
+        * it for you.
+        */
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = READ_CAPACITY;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = READ_CAPACITY;
 
-       /*******************************************************\
-       * If the command works, interpret the result as a 4 byte*
-       * number of blocks                                      *
-       \*******************************************************/
-       if (sd_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       &rdcap,
-                       sizeof(rdcap),  
-                       6000,
-                       NULL,
-                       flags | SCSI_DATA_IN) != 0)
-       {
+       /*
+        * If the command works, interpret the result as a 4 byte
+        * number of blocks
+        */
+       if (scsi_scsi_cmd(sd_data[unit]->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               (u_char *) & rdcap,
+               sizeof(rdcap),
+               SD_RETRIES,
+               2000,
+               NULL,
+               flags | SCSI_DATA_IN) != 0) {
                printf("sd%d: could not get size\n", unit);
                printf("sd%d: could not get size\n", unit);
-               return(0);
+               return (0);
        } else {
        } else {
-               size = rdcap.addr_0 + 1 ;
+               size = rdcap.addr_0 + 1;
                size += rdcap.addr_1 << 8;
                size += rdcap.addr_2 << 16;
                size += rdcap.addr_3 << 24;
        }
                size += rdcap.addr_1 << 8;
                size += rdcap.addr_2 << 16;
                size += rdcap.addr_3 << 24;
        }
-       return(size);
-}
-       
-/*******************************************************\
-* Get scsi driver to send a "are you ready?" command   *
-\*******************************************************/
-sd_test_unit_ready(unit,flags)
-int    unit,flags;
-{
-       struct  scsi_test_unit_ready scsi_cmd;
-
-       bzero(&scsi_cmd, sizeof(scsi_cmd));
-       scsi_cmd.op_code = TEST_UNIT_READY;
-
-       return (sd_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       0,
-                       0,
-                       100000,
-                       NULL,
-                       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;
-
-       if(sd_data[unit]->openparts) return;
-
-       bzero(&scsi_cmd, sizeof(scsi_cmd));
-       scsi_cmd.op_code = PREVENT_ALLOW;
-       scsi_cmd.how=type;
-       return (sd_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       0,
-                       0,
-                       5000,
-                       NULL,
-                       flags) );
-}
-/*******************************************************\
-* Get scsi driver to send a "start up" command         *
-\*******************************************************/
-sd_start_unit(unit,flags)
-int    unit,flags;
-{
-       struct scsi_start_stop scsi_cmd;
-
-       bzero(&scsi_cmd, sizeof(scsi_cmd));
-       scsi_cmd.op_code = START_STOP;
-       scsi_cmd.how = SSS_START;
-
-       return (sd_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       0,
-                       0,
-                       6000,
-                       NULL,
-                       flags));
+       return (size);
 }
 
 }
 
-/*******************************************************\
-* Tell the device to map out a defective block         *
-\*******************************************************/
-sd_reassign_blocks(unit,block)
+/*
+ * Tell the device to map out a defective block
+ */
+errval 
+sd_reassign_blocks(unit, block)
+       int     unit, block;
 {
 {
-       struct  scsi_reassign_blocks            scsi_cmd;
-       struct  scsi_reassign_blocks_data       rbdata;
-
+       struct scsi_reassign_blocks scsi_cmd;
+       struct scsi_reassign_blocks_data rbdata;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        bzero(&rbdata, sizeof(rbdata));
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        bzero(&rbdata, sizeof(rbdata));
@@ -905,108 +777,67 @@ sd_reassign_blocks(unit,block)
        rbdata.length_lsb = sizeof(rbdata.defect_descriptor[0]);
        rbdata.defect_descriptor[0].dlbaddr_3 = ((block >> 24) & 0xff);
        rbdata.defect_descriptor[0].dlbaddr_2 = ((block >> 16) & 0xff);
        rbdata.length_lsb = sizeof(rbdata.defect_descriptor[0]);
        rbdata.defect_descriptor[0].dlbaddr_3 = ((block >> 24) & 0xff);
        rbdata.defect_descriptor[0].dlbaddr_2 = ((block >> 16) & 0xff);
-       rbdata.defect_descriptor[0].dlbaddr_1 = ((block >>  8) & 0xff);
-       rbdata.defect_descriptor[0].dlbaddr_0 = ((block      ) & 0xff);
-
-       return(sd_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       &rbdata,
-                       sizeof(rbdata),
-                       5000,
-                       NULL,
-                       SCSI_DATA_OUT));
+       rbdata.defect_descriptor[0].dlbaddr_1 = ((block >> 8) & 0xff);
+       rbdata.defect_descriptor[0].dlbaddr_0 = ((block) & 0xff);
+
+       return (scsi_scsi_cmd(sd_data[unit]->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               (u_char *) & rbdata,
+               sizeof(rbdata),
+               SD_RETRIES,
+               5000,
+               NULL,
+               SCSI_DATA_OUT));
 }
 }
-
 #define b2tol(a)       (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
 
 #define b2tol(a)       (((unsigned)(a##_1) << 8) + (unsigned)a##_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(unit, flags)
+/*
+ * Get the scsi driver to send a full inquiry to the
+ * device and use the results to fill out the disk 
+ * parameter structure.
+ */
+errval 
+sd_get_parms(unit, flags)
+       int     unit, flags;
 {
        struct sd_data *sd = sd_data[unit];
        struct disk_parms *disk_parms = &sd->params;
 {
        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  scsi_mode_header        header;
-               struct  blk_desc                blk_desc;
-               union   disk_pages              pages;
-       }scsi_sense;
-       int sectors;
-
-       /*******************************************************\
-       * First check if we have it all loaded                  *
-       \*******************************************************/
-               if(sd->flags & SDVALID) return(0);
-       /*******************************************************\
-       * First do a mode sense page 3                          *
-       \*******************************************************/
-#ifdef SDDEBUG
-       if (sd_debug)
-       {
-               bzero(&scsi_cmd, sizeof(scsi_cmd));
-               scsi_cmd.op_code = MODE_SENSE;
-               scsi_cmd.page = 3;
-               scsi_cmd.length = 0x24;
-               /*******************************************************\
-               * do the command, but we don't need the results         *
-               * just print them for our interest's sake               *
-               \*******************************************************/
-               if (sd_scsi_cmd(unit,
-                               &scsi_cmd,
-                               sizeof(scsi_cmd),
-                               &scsi_sense,
-                               sizeof(scsi_sense),
-                               2000,
-                               NULL,
-                               flags | SCSI_DATA_IN) != 0)
-               {
-                       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),
-                       b2tol(scsi_sense.pages.disk_format.alt_sec),
-                       b2tol(scsi_sense.pages.disk_format.alt_trk_z),
-                       b2tol(scsi_sense.pages.disk_format.alt_trk_v));
-               printf("         %d sec/trk, %d bytes/sec, %d interleave, %d %d bytes/log_blk\n",
-                       b2tol(scsi_sense.pages.disk_format.ph_sec_t),
-                       b2tol(scsi_sense.pages.disk_format.bytes_s),
-                       b2tol(scsi_sense.pages.disk_format.interleave),
-                       sd_size(unit, flags),
-                       _3btol(scsi_sense.blk_desc.blklen));
-               }
-       }
-#endif /*SDDEBUG*/
-
-
-       /*******************************************************\
-       * do a "mode sense page 4"                              *
-       \*******************************************************/
+       struct scsi_mode_sense scsi_cmd;
+       struct scsi_mode_sense_data {
+               struct scsi_mode_header header;
+               struct blk_desc blk_desc;
+               union disk_pages pages;
+       } scsi_sense;
+       u_int32 sectors;
+
+       /*
+        * First check if we have it all loaded
+        */
+       if (sd->flags & SDEV_MEDIA_LOADED)
+               return 0;
+
+       /*
+        * do a "mode sense page 4"
+        */
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = MODE_SENSE;
        scsi_cmd.page = 4;
        scsi_cmd.length = 0x20;
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = MODE_SENSE;
        scsi_cmd.page = 4;
        scsi_cmd.length = 0x20;
-       /*******************************************************\
-       * If the command worked, use the results to fill out    *
-       * the parameter structure                               *
-       \*******************************************************/
-       if (sd_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       &scsi_sense,
-                       sizeof(scsi_sense),
-                       2000,
-                       NULL,
-                       flags | SCSI_DATA_IN) != 0)
-       {
+       /*
+        * If the command worked, use the results to fill out
+        * the parameter structure
+        */
+       if (scsi_scsi_cmd(sd->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               (u_char *) & scsi_sense,
+               sizeof(scsi_sense),
+               SD_RETRIES,
+               2000,
+               NULL,
+               flags | SCSI_DATA_IN) != 0) {
+
                printf("sd%d could not mode sense (4).", unit);
                printf(" Using ficticious geometry\n");
                /*
                printf("sd%d could not mode sense (4).", unit);
                printf(" Using ficticious geometry\n");
                /*
@@ -1017,631 +848,212 @@ int    sd_get_parms(unit, flags)
                sectors = sd_size(unit, flags);
                disk_parms->heads = 64;
                disk_parms->sectors = 32;
                sectors = sd_size(unit, flags);
                disk_parms->heads = 64;
                disk_parms->sectors = 32;
-               disk_parms->cyls = sectors/(64 * 32);
+               disk_parms->cyls = sectors / (64 * 32);
                disk_parms->secsiz = SECSIZE;
                disk_parms->disksize = sectors;
                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",
+               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_2),
                        scsi_sense.pages.rigid_geometry.nheads,
                        b2tol(scsi_sense.pages.rigid_geometry.st_cyl_wp),
                        b2tol(scsi_sense.pages.rigid_geometry.st_cyl_rwc),
                        _3btol(&scsi_sense.pages.rigid_geometry.ncyl_2),
                        scsi_sense.pages.rigid_geometry.nheads,
                        b2tol(scsi_sense.pages.rigid_geometry.st_cyl_wp),
                        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                                       *
-               * can lead to wasted space! THINK ABOUT THIS !          *
-               \*******************************************************/
+                       b2tol(scsi_sense.pages.rigid_geometry.land_zone)));
+
+               /*
+                * 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->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);
+               disk_parms->secsiz = _3btol(scsi_sense.blk_desc.blklen);
 
                sectors = sd_size(unit, flags);
                disk_parms->disksize = sectors;
                sectors /= (disk_parms->heads * disk_parms->cyls);
 
                sectors = sd_size(unit, flags);
                disk_parms->disksize = sectors;
                sectors /= (disk_parms->heads * disk_parms->cyls);
-               disk_parms->sectors = sectors; /* dubious on SCSI*//*XXX*/
+               disk_parms->sectors = sectors;  /* dubious on SCSI *//*XXX */
        }
        }
-
-       sd->flags |= SDVALID;
-       return(0);
+       sd->sc_link->flags |= SDEV_MEDIA_LOADED;
+       return 0;
 }
 
 }
 
-/*******************************************************\
-* 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;
+int
+sdsize(dev_t dev)
 {
 {
-       unsigned char unit, part;
-       unsigned int old_priority;
+       u_int32 unit = UNIT(dev), part = PARTITION(dev), val;
        struct sd_data *sd;
 
        struct sd_data *sd;
 
-       unit = UNIT(dev);
-       part = PARTITION(dev);
-       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)
-       {
-               /***********************************************\
-               * 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;
-       }
-
-       /***********************************************\
-       * 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 */
-}
-
-/*******************************************************\
-* ask the scsi driver to perform a command for us.     *
-* 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      *
-* and how long it is.                                  *
-* Also tell it where to read/write the data, and how   *
-* 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,bp,flags)
-
-int    unit,flags;
-struct scsi_generic *scsi_cmd;
-int    cmdlen;
-int    timeout;
-u_char *data_addr;
-int    datalen;
-struct buf *bp;
-{
-       struct  scsi_xfer *xs;
-       int     retval;
-       int     s;
-       struct sd_data *sd = sd_data[unit];
-
-#ifdef SDDEBUG
-       if(scsi_debug & PRINTROUTINES) printf("\nsd_scsi_cmd%d ",unit);
-#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)
-       {
-               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;
-
-       /*******************************************************\
-       * 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;
-
-               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;
-                       }
-               case    XS_DRIVER_STUFFUP:
-                       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;
+       if (unit >= NSD)
+               return -1;
 
 
-       case    TRY_AGAIN_LATER:        /* adapter resource shortage */
-               /* should sleep 1 sec here */
-               if(xs->retries-- )
-               {
-                       xs->flags &= ~ITSDONE;
-                       goto retry;
-               }
-       default:
-               retval = EIO;
+       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 (val != 0)
+                       return -1;
        }
        }
-       /*******************************************************\
-       * 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);
-}
-
-/***************************************************************\
-* Look at the returned sense and act on the error and detirmine        *
-* The unix error number to pass back... (0 = report no error)  *
-\***************************************************************/
+       if (sd->flags & SDWRITEPROT)
+               return -1;
 
 
-int    sd_interpret_sense(unit,xs)
-int    unit;
-struct scsi_xfer *xs;
-{
-       struct  scsi_sense_data *sense;
-       int     key;
-       int     silent;
-       long int        info;
-
-       /***************************************************************\
-       * If the flags say errs are ok, then always return ok.          *
-       \***************************************************************/
-       if (xs->flags & SCSI_ERR_OK) return(ESUCCESS);
-       silent = (xs->flags & SCSI_SILENT);
-
-       sense = &(xs->sense);
-       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 0x70:
-               {
-               key=sense->ext.extended.flags & SSD_KEY;
-               switch(key)
-               {
-               case    0x0:
-                       return(ESUCCESS);
-               case    0x1:
-                       if(!silent)
-                       {
-                               printf("sd%d: soft error(corrected) ", unit); 
-                               if(sense->error_code & SSD_ERRCODE_VALID)
-                               {
-                                       printf("block no. %d (decimal)",info);
-                               }
-                               printf("\n");
-                       }
-                       return(ESUCCESS);
-               case    0x2:
-                       if(!silent)printf("sd%d: not ready\n ",
-                               unit); 
-                       return(ENODEV);
-               case    0x3:
-                       if(!silent)
-                       {
-                               printf("sd%d: medium error ", unit); 
-                               if(sense->error_code & SSD_ERRCODE_VALID)
-                               {
-                                       printf("block no. %d (decimal)",info);
-                               }
-                               printf("\n");
-                       }
-                       return(EIO);
-               case    0x4:
-                       if(!silent)printf("sd%d: non-media hardware failure\n ",
-                               unit); 
-                       return(EIO);
-               case    0x5:
-                       if(!silent)printf("sd%d: illegal request\n ",
-                               unit); 
-                       return(EINVAL);
-               case    0x6:
-                       /***********************************************\
-                       * If we are not open, then this is not an error *
-                       * as we don't have state yet. Either way, make  *
-                       * 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)
-                       {
-                               return(EIO);
-                       }
-                       return(ESUCCESS); /* not an error if nothing's open */
-               case    0x7:
-                       if(!silent)
-                       {
-                               printf("sd%d: attempted protection violation ",
-                                               unit); 
-                               if(sense->error_code & SSD_ERRCODE_VALID)
-                               {
-                                       printf("block no. %d (decimal)\n",info);
-                               }
-                               printf("\n");
-                       }
-                       return(EACCES);
-               case    0x8:
-                       if(!silent)
-                       {
-                               printf("sd%d: block wrong state (format?)\n ",
-                               unit); 
-                               if(sense->error_code & SSD_ERRCODE_VALID)
-                               {
-                                       printf("block no. %d (decimal)\n",info);
-                               }
-                               printf("\n");
-                       }
-                       return(EIO);
-               case    0x9:
-                       if(!silent)printf("sd%d: vendor unique\n",
-                               unit); 
-                       return(EIO);
-               case    0xa:
-                       if(!silent)printf("sd%d: copy aborted\n ",
-                               unit); 
-                       return(EIO);
-               case    0xb:
-                       if(!silent)printf("sd%d: command aborted\n ",
-                               unit); 
-                       return(EIO);
-               case    0xc:
-                       if(!silent)
-                       {
-                               printf("sd%d: search returned\n ",
-                                       unit); 
-                               if(sense->error_code & SSD_ERRCODE_VALID)
-                               {
-                                       printf("block no. %d (decimal)\n",info);
-                               }
-                               printf("\n");
-                       }
-                       return(ESUCCESS);
-               case    0xd:
-                       if(!silent)printf("sd%d: volume overflow\n ",
-                               unit); 
-                       return(ENOSPC);
-               case    0xe:
-                       if(!silent)
-                       {
-                               printf("sd%d: verify miscompare\n ",
-                               unit); 
-                               if(sense->error_code & SSD_ERRCODE_VALID)
-                               {
-                                       printf("block no. %d (decimal)\n",info);
-                               }
-                               printf("\n");
-                       }
-                       return(EIO);
-               case    0xf:
-                       if(!silent)printf("sd%d: unknown error key\n ",
-                               unit); 
-                       return(EIO);
-               }
-               break;
-       }
-       default:
-               {
-                       if(!silent)printf("sd%d: code %d\n",
-                               unit,
-                               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)
-                       + (sense->ext.unextended.blocklow ));
-               }
-               return(EIO);
-       }
+       return (int)sd->disklabel.d_partitions[part].p_size;
 }
 
 
 }
 
 
+#define SCSIDUMP 1
+#undef SCSIDUMP
+#define NOT_TRUSTED 1
 
 
-
-int
-sdsize(dev_t dev)
-{
-       int unit = UNIT(dev), part = PARTITION(dev), val;
-       struct sd_data *sd;
-
-       if (unit >= NSD)
-               return(-1);
-
-       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 ( val != 0 || sd->flags & SDWRITEPROT)
-               return (-1);
-
-       return((int)sd->disklabel.d_partitions[part].p_size);
-}
-/*#define SCSIDUMP*/
 #ifdef SCSIDUMP
 #include <vm/vm.h>
 #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 */
-{
+
+static struct scsi_xfer sx;
+#define        MAXTRANSFER 8           /* 1 page at a time */
+
+/*
+ * dump all of physical memory into the partition specified, starting
+ * at offset 'dumplo' into the partition.
+ */
+errval
+sddump(dev_t dev)
+{                              /* dump core after a system crash */
        register struct sd_data *sd;    /* disk unit to do the IO */
        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;
+       int32   num;            /* number of sectors to write */
+       u_int32 unit, part;
+       int32   blkoff, blknum, blkcnt = MAXTRANSFER;
+       int32   nblocks;
        char    *addr;
        char    *addr;
-       struct  scsi_rw_big     cmd;
+       struct  scsi_rw_big cmd;
        extern  int Maxmem;
        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;
+       static  int sddoingadump = 0;
+#define MAPTO CADDR1
+       extern  caddr_t MAPTO;  /* map the page we are about to write, here */
+       struct  scsi_xfer *xs = &sx;
+       errval  retval;
+       int     c;
 
 
-       addr = (char *) 0;              /* starting address */
+       addr = (char *) 0;      /* starting address */
 
        /* toss any characters present prior to dump */
 
        /* toss any characters present prior to dump */
-       while (sgetc(1))
-               ;
+       while ((c = sgetc(1)) && (c != 0x100)); /*syscons and pccons differ */
 
        /* size of memory to dump */
        num = Maxmem;
 
        /* size of memory to dump */
        num = Maxmem;
-       unit = UNIT(dev);               /* eventually support floppies? */
-       part = PARTITION(dev);          /* file system */
+       unit = UNIT(dev);       /* eventually support floppies? */
+       part = PARTITION(dev);  /* file system */
        /* check for acceptable drive number */
        /* check for acceptable drive number */
-       if (unit >= NSD) return(ENXIO);         /* 31 Jul 92*/
+       if (unit >= NSD)
+               return (ENXIO); /* 31 Jul 92 */
 
        sd = sd_data[unit];
 
        sd = sd_data[unit];
-       if(!sd) return (ENXIO);
+       if (!sd)
+               return (ENXIO);
        /* was it ever initialized etc. ? */
        /* was it ever initialized etc. ? */
-       if (!(sd->flags & SDINIT))              return (ENXIO);
-       if (sd->flags & SDVALID != SDVALID)     return (ENXIO) ;
-       if (sd->flags & SDWRITEPROT)            return (ENXIO);
+       if (!(sd->flags & SDINIT))
+               return (ENXIO);
+       if (sd->sc_link->flags & SDEV_MEDIA_LOADED != SDEV_MEDIA_LOADED)
+               return (ENXIO);
+       if (sd->flags & SDWRITEPROT)
+               return (ENXIO);
 
        /* Convert to disk sectors */
 
        /* Convert to disk sectors */
-       num = (u_long) num * NBPG / sd->disklabel.d_secsize;
+       num = (u_int32) num * NBPG / sd->disklabel.d_secsize;
 
        /* check if controller active */
 
        /* check if controller active */
-       if (sddoingadump) return(EFAULT);
+       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))
 
        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);
+               return (EINVAL);
 
 
-       sddoingadump = 1  ;
+       sddoingadump = 1;
 
        blknum = dumplo + blkoff;
 
        blknum = dumplo + blkoff;
-       while (num > 0)
-       {
-               if (blkcnt > MAXTRANSFER) blkcnt = MAXTRANSFER;
-               pmap_enter(     kernel_pmap,
-                               CADDR1,
-                               trunc_page(addr),
-                               VM_PROT_READ,
-                               TRUE);
+       /* blkcnt = initialise_me; */
+       while (num > 0) {
+               pmap_enter(kernel_pmap,
+                   MAPTO,
+                   trunc_page(addr),
+                   VM_PROT_READ,
+                   TRUE);
 #ifndef        NOT_TRUSTED
 #ifndef        NOT_TRUSTED
-               /*******************************************************\
-               *  Fill out the scsi command                            *
-               \*******************************************************/
+               /*
+                *  Fill out the scsi command
+                */
                bzero(&cmd, sizeof(cmd));
                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 *
-               \*******************************************************/
+               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
+                * don't use scsi_scsi_cmd() as it may want 
+                * to wait for an xs.
+                */
                bzero(xs, sizeof(sx));
                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:
+               xs->flags |= SCSI_NOMASK | SCSI_NOSLEEP | INUSE;
+               xs->sc_link = sd->sc_link;
+               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->error = XS_NOERROR;
+               xs->bp = 0;
+               xs->data = (u_char *) MAPTO;
+               xs->datalen = blkcnt * 512;
+
+               /*
+                * Pass all this info to the scsi driver.
+                */
+               retval = (*(sd->sc_link->adapter->scsi_cmd)) (xs);
+               switch (retval) {
+               case SUCCESSFULLY_QUEUED:
+               case HAD_ERROR:
+                       return (ENXIO);         /* we said not to sleep! */
+               case COMPLETE:
                        break;
                default:
                        break;
                default:
-                       return(ENXIO); /* we said not to sleep! */
+                       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) ;
+#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 */
                /* update block count */
-               num -= MAXTRANSFER;
-               blknum += MAXTRANSFER ;
-               (int) addr += 512 * MAXTRANSFER;
+               num -= blkcnt;
+               blknum += blkcnt;
+               (int) addr += 512 * blkcnt;
 
                /* operator aborting dump? */
 
                /* operator aborting dump? */
-               if (sgetc(1))
-                       return(EINTR);
+               if ((c = sgetc(1)) && (c != 0x100))
+                       return (EINTR);
        }
        }
-       return(0);
+       return (0);
 }
 }
-#else  SCSIDUMP
+#else  /* SCSIDUMP */
+errval
 sddump()
 {
        printf("\nsddump()        -- not implemented\n");
 sddump()
 {
        printf("\nsddump()        -- not implemented\n");
-       DELAY(20000000);        /* 20 seconds */
-       return(-1);
+       DELAY(60000000);        /* 60 seconds */
+       return -1;
 }
 }
-#endif SCSIDUMP
-
+#endif /* SCSIDUMP */
index e367389..08c8d46 100644 (file)
  * 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:         1       00098
+ * --------------------         -----   ----------------------
+ *
+ * 16 Feb 93    Julian Elischer         ADDED for SCSI system
+ * 1.15 is the last version to support MACH and OSF/1
+ */
+/* $Revision: 2.6 $ */
+
+/*
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  * major changes by Julian Elischer (julian@jules.dialix.oz.au) May 1993
  *
  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
  * major changes by Julian Elischer (julian@jules.dialix.oz.au) May 1993
  *
- *     $Id: st.c,v 1.11 1993/10/16 17:21:10 rgrimes Exp $
+ *      $Id: st.c,v 2.6 93/10/21 03:24:38 julian Exp Locker: julian $
  */
 
  */
 
-
 /*
  * To do:
  * work out some better way of guessing what a good timeout is going
 /*
  * To do:
  * work out some better way of guessing what a good timeout is going
 #include <sys/user.h>
 #include <sys/mtio.h>
 
 #include <sys/user.h>
 #include <sys/mtio.h>
 
-
 #include <scsi/scsi_all.h>
 #include <scsi/scsi_tape.h>
 #include <scsi/scsiconf.h>
 
 #include <scsi/scsi_all.h>
 #include <scsi/scsi_tape.h>
 #include <scsi/scsiconf.h>
 
-
-long int ststrats,stqueues;
+u_int32 ststrats, stqueues;
 
 /* Defines for device specific stuff */
 #define                PAGE_0_SENSE_DATA_SIZE  12
 #define PAGESIZ        4096
 #define DEF_FIXED_BSIZE  512
 
 /* Defines for device specific stuff */
 #define                PAGE_0_SENSE_DATA_SIZE  12
 #define PAGESIZ        4096
 #define DEF_FIXED_BSIZE  512
-#define STQSIZE                4
-#define        ST_RETRIES      4
-
+#define        ST_RETRIES      4       /* only on non IO commands */
 
 #define MODE(z)                (  (minor(z)       & 0x03) )
 #define DSTY(z)         ( ((minor(z) >> 2) & 0x03) )
 #define UNIT(z)                (  (minor(z) >> 4) )
 
 #define MODE(z)                (  (minor(z)       & 0x03) )
 #define DSTY(z)         ( ((minor(z) >> 2) & 0x03) )
 #define UNIT(z)                (  (minor(z) >> 4) )
-
-#define DSTY3  3
-#define DSTY2  2
-#define DSTY1  1
+#define CTLMODE        3
 
 #define SCSI_2_MAX_DENSITY_CODE        0x17    /* maximum density code specified
 
 #define SCSI_2_MAX_DENSITY_CODE        0x17    /* maximum density code specified
-                                          in SCSI II spec. */
-/***************************************************************\
-* Define various devices that we know mis-behave in some way,  *
-* and note how they are bad, so we can correct for them                *
-\***************************************************************/
-struct modes
-{
-       int     quirks;         /* same definitions as in rogues */
-       char    density;
-       char    spare[3];
+                                        * in SCSI II spec. */
+/*
+ * Define various devices that we know mis-behave in some way,
+ * and note how they are bad, so we can correct for them
+ */
+struct modes {
+       u_int32 blksiz;
+       u_int32 quirks;         /* same definitions as in rogues */
+       char    density;
+       char    spare[3];
 };
 };
-struct rogues
-{
-       char    *name;
-        char    *manu;
-        char    *model;
-        char    *version;
-       int     quirks;         /* valid for all modes */
-       struct  modes   modes[4];       
+
+struct rogues {
+       char   *name;
+       char   *manu;
+       char   *model;
+       char   *version;
+       u_int32 quirks;         /* valid for all modes */
+       struct modes modes[4];
 };
 
 /* define behaviour codes (quirks) */
 #define        ST_Q_NEEDS_PAGE_0       0x00001
 #define        ST_Q_FORCE_FIXED_MODE   0x00002
 #define        ST_Q_FORCE_VAR_MODE     0x00004
 };
 
 /* define behaviour codes (quirks) */
 #define        ST_Q_NEEDS_PAGE_0       0x00001
 #define        ST_Q_FORCE_FIXED_MODE   0x00002
 #define        ST_Q_FORCE_VAR_MODE     0x00004
-#define        ST_Q_SNS_HLP            0x00008 /* must do READ for good MODE SENSE */
+#define        ST_Q_SNS_HLP            0x00008         /* must do READ for good MODE SENSE */
 #define        ST_Q_IGNORE_LOADS       0x00010
 #define        ST_Q_IGNORE_LOADS       0x00010
-#define        ST_Q_BLKSIZ             0x00020 /* variable-block media_blksiz > 0 */
+#define        ST_Q_BLKSIZ             0x00020         /* variable-block media_blksiz > 0 */
 
 
-static struct rogues gallery[] = /* ends with an all null entry */
+static struct rogues gallery[] =       /* ends with an all-null entry */
 {
 {
-       { "Such an old device ", "pre-scsi", " unknown model  ","????",
-               0,
-               { {ST_Q_FORCE_FIXED_MODE,0},            /* minor  0,1,2,3 */
-                 {ST_Q_FORCE_FIXED_MODE,QIC_24},       /* minor  4,5,6,7 */
-                 {ST_Q_FORCE_VAR_MODE,HALFINCH_1600},  /* minor  8,9,10,11*/
-                 {ST_Q_FORCE_VAR_MODE,HALFINCH_6250}   /* minor  12,13,14,15*/
-               }
-       },
-       { "Tandberg tdc3600", "TANDBERG", " TDC 3600","????",
-               ST_Q_NEEDS_PAGE_0,
-               { {0,0},                                /* minor  0,1,2,3*/
-                 {ST_Q_FORCE_VAR_MODE,QIC_525},        /* minor  4,5,6,7*/
-                 {0,QIC_150},                          /* minor  8,9,10,11*/
-                 {0,QIC_120}                           /* minor  12,13,14,15*/
-               }
-       },
-       { "Rev 5 of the Archive 2525", "ARCHIVE ", "VIPER 2525 25462","-005",
-               0,
-               { {ST_Q_SNS_HLP,0},                     /* minor  0,1,2,3*/
-                 {ST_Q_SNS_HLP,QIC_525},               /* minor  4,5,6,7*/
-                 {0,QIC_150},                          /* minor  8,9,10,11*/
-                 {0,QIC_120}                           /* minor  12,13,14,15*/
-               }
-       },
-       { "Archive  Viper 150", "ARCHIVE ", "VIPER 150","????",
-               ST_Q_NEEDS_PAGE_0,
-               { {0,0},                                /* minor  0,1,2,3*/
-                 {0,QIC_150},                          /* minor  4,5,6,7*/
-                 {0,QIC_120},                          /* minor  8,9,10,11*/
-                 {0,QIC_24}                            /* minor  12,13,14,15*/
-               }
-       },
-       { "Wangtek 5525ES", "WANGTEK ", "5525ES SCSI REV7", "????",
-               0,
-               { {0,0},                                /* minor  0,1,2,3*/
-                 {ST_Q_BLKSIZ,QIC_525},                /* minor  4,5,6,7*/
-                 {0,QIC_150},                          /* minor  8,9,10,11*/
-                 {0,QIC_120}                           /* minor  12,13,14,15*/
-               }
-       },
-       {(char *)0}
+    {"Such an old device ", "pre-scsi", " unknown model  ", "????",
+       0,
+       {
+           {512, ST_Q_FORCE_FIXED_MODE, 0},    /* minor  0,1,2,3 */
+           {512, ST_Q_FORCE_FIXED_MODE, QIC_24},       /* minor  4,5,6,7 */
+           {0, ST_Q_FORCE_VAR_MODE, HALFINCH_1600},    /* minor  8,9,10,11 */
+           {0, ST_Q_FORCE_VAR_MODE, HALFINCH_6250}     /* minor  12,13,14,15 */
+       }
+    },
+    {"Tandberg tdc3600", "TANDBERG", " TDC 3600", "????",
+       ST_Q_NEEDS_PAGE_0,
+       {
+           {0, 0, 0},          /* minor  0,1,2,3 */
+           {0, ST_Q_FORCE_VAR_MODE, QIC_525},  /* minor  4,5,6,7 */
+           {0, 0, QIC_150},    /* minor  8,9,10,11 */
+           {0, 0, QIC_120}     /* minor  12,13,14,15 */
+       }
+    },
+    {"Rev 5 of the Archive 2525", "ARCHIVE ", "VIPER 2525 25462", "-005",
+       0,
+       {
+           {0, ST_Q_SNS_HLP, 0},       /* minor  0,1,2,3 */
+           {0, ST_Q_SNS_HLP, QIC_525},         /* minor  4,5,6,7 */
+           {0, 0, QIC_150},    /* minor  8,9,10,11 */
+           {0, 0, QIC_120}     /* minor  12,13,14,15 */
+       }
+    },
+    {"Archive  Viper 150", "ARCHIVE ", "VIPER 150", "????",
+       ST_Q_NEEDS_PAGE_0,
+       {
+           {0, 0, 0},          /* minor  0,1,2,3 */
+           {0, 0, QIC_150},    /* minor  4,5,6,7 */
+           {0, 0, QIC_120},    /* minor  8,9,10,11 */
+           {0, 0, QIC_24}      /* minor  12,13,14,15 */
+       }
+    },
+    {"Wangtek 5525ES", "WANGTEK ", "5525ES SCSI REV7", "????",
+       0,
+       {
+           {0, 0, 0},          /* minor  0,1,2,3 */
+           {0, ST_Q_BLKSIZ, QIC_525},  /* minor  4,5,6,7 */
+           {0, 0, QIC_150},    /* minor  8,9,10,11 */
+           {0, 0, QIC_120}     /* minor  12,13,14,15 */
+       }
+    },
+    {"WangDAT model 1300", "WangDAT ", "Model 1300", "????",
+       0,
+       {
+           {0, 0, 0},                                  /* minor  0,1,2,3 */
+           {512, ST_Q_FORCE_FIXED_MODE, 0x13},         /* minor  4,5,6,7 */
+           {1024, ST_Q_FORCE_FIXED_MODE, 0x13},        /* minor  8,9,10,11 */
+           {0, ST_Q_FORCE_VAR_MODE, 0x13}              /* minor  12,13,14,15 */
+       }
+    },
+    {(char *) 0}
 };
 
 };
 
-
-int    ststrategy();
-void   stminphys();
+errval st_space __P((u_int32 unit, int32 number, u_int32 what, u_int32 flags));
+errval st_rewind __P((u_int32 unit, boolean immed, u_int32 flags));
+errval st_mode_sense __P((u_int32 unit, u_int32 flags));
+errval st_decide_mode __P((u_int32 unit, boolean first_read));
+errval st_rd_blk_lim __P((u_int32 unit, u_int32 flags));
+errval st_touch_tape __P((u_int32 unit));
+errval st_write_filemarks __P((u_int32 unit, int32 number, u_int32 flags));
+errval st_load __P((u_int32 unit, u_int32 type, u_int32 flags));
+errval st_mode_select __P((u_int32 unit, u_int32 flags));
+void    ststrategy();
+void    stminphys();
+int32   st_chkeod();
+errval  stattach();
+void    ststart();
+void   st_unmount();
+errval st_mount_tape();
+void   st_loadquirks();
+void   st_identify_drive();
+errval  st_interpret_sense();
 
 #define ESUCCESS 0
 
 #define ESUCCESS 0
+#define NOEJECT 0
+#define EJECT 1
 
 
-#ifdef STDEBUG
-int    st_debug = 1;
-#endif /*STDEBUG*/
-
-int stattach();
-int st_done();
-
-struct st_data
+struct scsi_device st_switch =
 {
 {
+    st_interpret_sense,                /* check errors with us first */
+    ststart,                   /* we have a queue, and this is how we service it */
+    NULL,
+    NULL,                      /* use the default 'done' routine */
+    "st",
+    0,
+    { 0, 0 }
+};
+
+struct st_data {
 /*--------------------present operating parameters, flags etc.----------------*/
 /*--------------------present operating parameters, flags etc.----------------*/
-       int     flags;                  /* see below                          */
-       int     blksiz;                 /* blksiz we are using                */
-       int     density;                /* present density                    */
-       int     quirks;                 /* quirks for the open mode           */
-       int     last_dsty;              /* last density used                  */
+       u_int32 flags;          /* see below                          */
+       u_int32 blksiz;         /* blksiz we are using                */
+       u_int32 density;        /* present density                    */
+       u_int32 quirks;         /* quirks for the open mode           */
+       u_int32 last_dsty;      /* last density openned               */
 /*--------------------device/scsi parameters----------------------------------*/
 /*--------------------device/scsi parameters----------------------------------*/
-       struct  scsi_switch *sc_sw;     /* address of scsi low level switch   */
-       int     ctlr;                   /* so they know which one we want     */
-       int     targ;                   /* our scsi target ID                 */
-       int     lu;                     /* our scsi lu                        */
+       struct scsi_link *sc_link;      /* our link to the adpter etc.        */
 /*--------------------parameters reported by the device ----------------------*/
 /*--------------------parameters reported by the device ----------------------*/
-       int     blkmin;                 /* min blk size                       */
-       int     blkmax;                 /* max blk size                       */
+       u_int32 blkmin;         /* min blk size                       */
+       u_int32 blkmax;         /* max blk size                       */
+       struct rogues *rogues;  /* if we have a rogue entry           */
 /*--------------------parameters reported by the device for this media--------*/
 /*--------------------parameters reported by the device for this media--------*/
-       int     numblks;                /* nominal blocks capacity            */
-       int     media_blksiz;           /* 0 if not ST_FIXEDBLOCKS            */
-       int     media_density;          /* this is what it said when asked    */
+       u_int32 numblks;        /* nominal blocks capacity            */
+       u_int32 media_blksiz;   /* 0 if not ST_FIXEDBLOCKS            */
+       u_int32 media_density;  /* this is what it said when asked    */
 /*--------------------quirks for the whole drive------------------------------*/
 /*--------------------quirks for the whole drive------------------------------*/
-       int     drive_quirks;           /* quirks of this drive               */
+       u_int32 drive_quirks;   /* quirks of this drive               */
 /*--------------------How we should set up when openning each minor device----*/
 /*--------------------How we should set up when openning each minor device----*/
-       struct  modes   modes[4];       /* plus more for each mode            */
+       struct modes modes[4];  /* plus more for each mode            */
+       u_int8  modeflags[4];   /* flags for the modes                */
+#define DENSITY_SET_BY_USER    0x01
+#define DENSITY_SET_BY_QUIRK   0x02
+#define BLKSIZE_SET_BY_USER    0x04
+#define BLKSIZE_SET_BY_QUIRK   0x08
 /*--------------------storage for sense data returned by the drive------------*/
 /*--------------------storage for sense data returned by the drive------------*/
-        unsigned char   sense_data[12]; /* additional sense data needed       */
-                                        /* for mode sense/select.            */
-       struct  buf *buf_queue;         /* the queue of pending IO operations */
-       struct  scsi_xfer scsi_xfer;    /* The scsi xfer struct for this drive*/
-       int     xfer_block_wait;        /* whether there is a process waiting */
-}*st_data[NST];
+       unsigned char sense_data[12];   /*
+                                        * additional sense data needed
+                                        * for mode sense/select.
+                                        */
+       struct buf *buf_queue;          /* the queue of pending IO operations */
+       struct scsi_xfer scsi_xfer;     /* scsi xfer struct for this drive */
+       u_int32 xfer_block_wait;        /* is a process waiting? */
+}      *st_data[NST];
+
 #define ST_INITIALIZED 0x01
 #define        ST_INFO_VALID   0x02
 #define ST_OPEN                0x04
 #define ST_INITIALIZED 0x01
 #define        ST_INFO_VALID   0x02
 #define ST_OPEN                0x04
-#define        ST_BLOCK_SET    0x08            /* block size, mode set by ioctl      */
-#define        ST_WRITTEN      0x10            /* data have been written, EOD needed */
+#define        ST_BLOCK_SET    0x08    /* block size, mode set by ioctl      */
+#define        ST_WRITTEN      0x10    /* data have been written, EOD needed */
 #define        ST_FIXEDBLOCKS  0x20
 #define        ST_AT_FILEMARK  0x40
 #define        ST_FIXEDBLOCKS  0x20
 #define        ST_AT_FILEMARK  0x40
-#define        ST_EIO_PENDING  0x80            /* we couldn't report it then (had data)*/
-#define        ST_AT_BOM       0x100           /* ops history suggests Beg of Medium */
-#define        ST_READONLY     0x200           /* st_mode_sense says write protected */
-#define        ST_FM_WRITTEN   0x400           /* EOF file mark written  -- */
-                                       /* used with ~ST_WRITTEN to indicate  */
-                                       /* that multiple file marks have been */
-                                       /* written                            */
-#define        ST_BLANK_READ   0x800           /* BLANK CHECK encountered already */
-#define        ST_2FM_AT_EOD   0x1000          /* write 2 file marks at EOD */
+#define        ST_EIO_PENDING  0x80    /* we couldn't report it then (had data) */
+#define        ST_NEW_MOUNT    0x100   /* still need to decide mode              */
+#define        ST_READONLY     0x200   /* st_mode_sense says write protected */
+#define        ST_FM_WRITTEN   0x400   /*
+                                * EOF file mark written  -- used with
+                                * ~ST_WRITTEN to indicate that multiple file
+                                * marks have been written
+                                */
+#define        ST_BLANK_READ   0x800   /* BLANK CHECK encountered already */
+#define        ST_2FM_AT_EOD   0x1000  /* write 2 file marks at EOD */
+#define        ST_MOUNTED      0x2000  /* Device is presently mounted */
 
 #define        ST_PER_ACTION   (ST_AT_FILEMARK | ST_EIO_PENDING | ST_BLANK_READ)
 
 #define        ST_PER_ACTION   (ST_AT_FILEMARK | ST_EIO_PENDING | ST_BLANK_READ)
-#define        ST_PER_OPEN     ST_OPEN
-#define        ST_PER_MEDIA    (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \
-                       ST_FIXEDBLOCKS | ST_AT_BOM | ST_READONLY | \
+#define        ST_PER_MOUNT    (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \
+                       ST_FIXEDBLOCKS | ST_READONLY | \
                        ST_FM_WRITTEN | ST_2FM_AT_EOD | ST_PER_ACTION)
 
                        ST_FM_WRITTEN | ST_2FM_AT_EOD | ST_PER_ACTION)
 
-static int     next_st_unit = 0;
-/***********************************************************************\
-* The routine called by the low level scsi routine when it discovers   *
-* A device suitable for this driver                                    *
-\***********************************************************************/
+static u_int32 next_st_unit = 0;
 
 
-int    stattach(ctlr,targ,lu,scsi_switch)
-struct scsi_switch *scsi_switch;
+/*
+ * The routine called by the low level scsi routine when it discovers
+ * A device suitable for this driver
+ */
+
+errval 
+stattach(sc_link)
+       struct scsi_link *sc_link;
 {
 {
-       int     unit,i;
+       u_int32 unit;
        struct st_data *st;
 
        struct st_data *st;
 
-#ifdef STDEBUG
-       if(scsi_debug & PRINTROUTINES) printf("stattach: ");
-#endif /*STDEBUG*/
-       /*******************************************************\
-       * Check we have the resources for another drive         *
-       \*******************************************************/
+       SC_DEBUG(sc_link, SDEV_DB2, ("stattach: "));
+       /*
+        * Check we have the resources for another drive
+        */
        unit = next_st_unit++;
        unit = next_st_unit++;
-       if( unit >= NST)
-       {
+
+       if (unit >= NST) {
                printf("Too many scsi tapes..(%d > %d) reconfigure kernel\n",
                printf("Too many scsi tapes..(%d > %d) reconfigure kernel\n",
-                               (unit + 1),NST);
-               return(0);
+                   (unit + 1), NST);
+               return 0;
        }
        }
-       if(st_data[unit])
-       {
-               printf("st%d: Already has storage!\n",unit);
-               return(0);
+       if (st_data[unit]) {
+               printf("st%d: Already has storage!\n", unit);
+               return 0;
        }
        }
-       st = st_data[unit] = malloc(sizeof(struct st_data),M_DEVBUF,M_NOWAIT);
-       if(!st)
-       {
-               printf("st%d: malloc failed in st.c\n",unit);
-               return(0);
+       sc_link->device = &st_switch;
+       sc_link->dev_unit = unit;
+       st = st_data[unit] = malloc(sizeof(struct st_data), M_DEVBUF, M_NOWAIT);
+       if (!st) {
+               printf("st%d: malloc failed in st.c\n", unit);
+               return 0;
        }
        }
-       bzero(st,sizeof(struct st_data));
-
-       /*******************************************************\
-       * Store information needed to contact our base driver   *
-       \*******************************************************/
-       st->sc_sw       =       scsi_switch;
-       st->ctlr        =       ctlr;
-       st->targ        =       targ;
-       st->lu          =       lu;
-
-       /*******************************************************\
-       * Store information about default densities             *
-       \*******************************************************/
-       st->modes[DSTY1].density        =       QIC_525;
-       st->modes[DSTY2].density        =       QIC_150;
-       st->modes[DSTY3].density        =       QIC_120;
-
-       /*******************************************************\
-       * Check if the drive is a known criminal and take       *
-       * Any steps needed to bring it into line                *
-       \*******************************************************/
+       bzero(st, sizeof(struct st_data));
+
+       /*
+        * Store information needed to contact our base driver
+        */
+       st->sc_link = sc_link;
+
+       /*
+        * Check if the drive is a known criminal and take
+        * Any steps needed to bring it into line
+        */
        st_identify_drive(unit);
 
        st_identify_drive(unit);
 
-       /*******************************************************\
-       * Use the subdriver to request information regarding    *
-       * the drive. We cannot use interrupts yet, so the       *
-       * request must specify this.                            *
-       \*******************************************************/
-       if(st_mode_sense(unit, SCSI_NOSLEEP |  SCSI_NOMASK | SCSI_SILENT))
-       {
+       /*
+        * Use the subdriver to request information regarding
+        * the drive. We cannot use interrupts yet, so the
+        * request must specify this.
+        */
+       if (st_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT)) {
                printf("st%d: drive offline\n", unit);
                printf("st%d: drive offline\n", unit);
-       }
-       else
-       {
-               if(!st_test_ready(unit,SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT))
-               {
-                       printf("st%d: density code 0x%x, ",
-                           unit, st->media_density);
-                       if (st->media_blksiz)
-                       {
+       } else {
+               printf("st%d: density code 0x%x, ", unit, st->media_density);
+               if (!scsi_test_unit_ready(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT)) {
+                       if (st->media_blksiz) {
                                printf("%d-byte", st->media_blksiz);
                                printf("%d-byte", st->media_blksiz);
-                       }
-                       else
-                       {
+                       } else {
                                printf("variable");
                        }
                        printf(" blocks, write-%s\n",
                                printf("variable");
                        }
                        printf(" blocks, write-%s\n",
-                           st->flags & ST_READONLY ? "protected" : "enabled");
-               }
-               else
-               {
-                       printf("st%d: drive empty\n", unit);
+                           (st->flags & ST_READONLY) ? "protected" : "enabled");
+               } else {
+                       printf(" drive empty\n");
                }
        }
                }
        }
-       /*******************************************************\
-       * Set up the bufs for this device                       *
-       \*******************************************************/
-       st->buf_queue   =       0;
-
-
+       /*
+        * Set up the buf queue for this device
+        */
+       st->buf_queue = 0;
        st->flags |= ST_INITIALIZED;
        st->flags |= ST_INITIALIZED;
-       return;
-
+       return 0;
 }
 
 }
 
-/***********************************************************************\
-* Use the identify routine in 'scsiconf' to get drive info so we can   *
-* Further tailor our behaviour.                                                *
-\***********************************************************************/
-
+/*
+ * Use the inquiry routine in 'scsi_base' to get drive info so we can
+ * Further tailor our behaviour.
+ */
+void
 st_identify_drive(unit)
 st_identify_drive(unit)
-int    unit;
+       u_int32 unit;
 {
 {
-
-       struct  st_data *st = st_data[unit];
-       struct scsi_inquiry_data        inqbuf;
-       struct  rogues *finger;
-        char    manu[32];
-        char    model[32];
-        char    model2[32];
-        char    version[32];
-       int     model_len;
-
-
-       /*******************************************************\
-       * Get the device type information                       *
-       \*******************************************************/
-       if (scsi_inquire(st->ctlr, st->targ, st->lu, st->sc_sw, &inqbuf,
-               SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT) != COMPLETE)
-       {
+       struct st_data *st = st_data[unit];
+       struct scsi_inquiry_data inqbuf;
+       struct rogues *finger;
+       char    manu[32];
+       char    model[32];
+       char    model2[32];
+       char    version[32];
+       u_int32 model_len;
+
+       /*
+        * Get the device type information
+        */
+       if (scsi_inquire(st->sc_link, &inqbuf,
+               SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT) != 0) {
                printf("st%d: couldn't get device type, using default\n", unit);
                return;
        }
                printf("st%d: couldn't get device type, using default\n", unit);
                return;
        }
-       if((inqbuf.version & SID_ANSII) == 0)
-       {
-               /***********************************************\
-               * If not advanced enough, use default values    *
-               \***********************************************/
-               strncpy(manu,"pre-scsi",8);manu[8]=0;
-               strncpy(model," unknown model  ",16);model[16]=0;
-               strncpy(version,"????",4);version[4]=0;
-       }
-       else
-       {
-               strncpy(manu,inqbuf.vendor,8);manu[8]=0;
-               strncpy(model,inqbuf.product,16);model[16]=0;
-               strncpy(version,inqbuf.revision,4);version[4]=0;
+       if ((inqbuf.version & SID_ANSII) == 0) {
+               /*
+                * If not advanced enough, use default values
+                */
+               strncpy(manu, "pre-scsi", 8);
+               manu[8] = 0;
+               strncpy(model, " unknown model  ", 16);
+               model[16] = 0;
+               strncpy(version, "????", 4);
+               version[4] = 0;
+       } else {
+               strncpy(manu, inqbuf.vendor, 8);
+               manu[8] = 0;
+               strncpy(model, inqbuf.product, 16);
+               model[16] = 0;
+               strncpy(version, inqbuf.revision, 4);
+               version[4] = 0;
        }
        }
-        
-       /*******************************************************\
-       * Load the parameters for this kind of device, so we    *
-       * treat it as appropriate for each operating mode       *
-       * Only check the number of characters in the array's    *
-       * model entry, not the entire model string returned.    *
-       \*******************************************************/
+
+       /*
+        * Load the parameters for this kind of device, so we
+        * treat it as appropriate for each operating mode.
+        * Only check the number of characters in the array's
+        * model entry, not the entire model string returned.
+        */
        finger = gallery;
        finger = gallery;
-       while(finger->name)
-       {
+       while (finger->name) {
                model_len = 0;
                model_len = 0;
-               while(finger->model[model_len] && (model_len < 32))
-               {
+               while (finger->model[model_len] && (model_len < 32)) {
                        model2[model_len] = model[model_len];
                        model_len++;
                }
                model2[model_len] = 0;
                        model2[model_len] = model[model_len];
                        model_len++;
                }
                model2[model_len] = 0;
-               if ((strcmp(manu, finger->manu) == 0 )
-                       && (strcmp(model2, finger->model) == 0 ||
-                          strcmp("????????????????", finger->model) == 0)
-                       && (strcmp(version, finger->version) == 0 ||
-                          strcmp("????", finger->version) == 0))
-               {
-                       printf("st%d: %s is a known rogue\n", unit,finger->name);
-                       st->modes[0]    =       finger->modes[0];
-                       st->modes[1]    =       finger->modes[1];
-                       st->modes[2]    =       finger->modes[2];
-                       st->modes[3]    =       finger->modes[3];
-                       st->drive_quirks=       finger->quirks;
-                       st->quirks      =       finger->quirks; /*start value*/
+               if ((strcmp(manu, finger->manu) == 0)
+                   && (strcmp(model2, finger->model) == 0 ||
+                       strcmp("????????????????", finger->model) == 0)
+                   && (strcmp(version, finger->version) == 0 ||
+                       strcmp("????", finger->version) == 0)) {
+                       printf("st%d: %s is a known rogue\n", unit, finger->name);
+                       st->rogues = finger;
+                       st->drive_quirks = finger->quirks;
+                       st->quirks = finger->quirks;    /*start value */
+                       st_loadquirks(st);
                        break;
                        break;
-               }
-               else
-               {
+               } else {
                        finger++;       /* go to next suspect */
                }
        }
 }
 
                        finger++;       /* go to next suspect */
                }
        }
 }
 
-/*******************************************************\
-*      open the device.                                *
-\*******************************************************/
+/*
+ * initialise the subdevices to the default (QUIRK) state.
+ * this will remove any setting made by the system operator or previous
+ * operations.
+ */
+void
+st_loadquirks(st)
+       struct st_data *st;
+{
+       int     i;
+       struct  modes *mode;
+       struct  modes *mode2;
+
+       if (!st->rogues)
+               return;
+       mode = st->rogues->modes;
+       mode2 = st->modes;
+       for (i = 0; i < 4; i++) {
+               bzero(mode2, sizeof(struct modes));
+               st->modeflags[i] &= ~(BLKSIZE_SET_BY_QUIRK
+                   | DENSITY_SET_BY_QUIRK
+                   | BLKSIZE_SET_BY_USER
+                   | DENSITY_SET_BY_USER);
+               if (mode->blksiz && ((mode->quirks | st->drive_quirks)
+                       & (ST_Q_FORCE_FIXED_MODE))) {
+                       mode2->blksiz = mode->blksiz;
+                       st->modeflags[i] |= BLKSIZE_SET_BY_QUIRK;
+               } else {
+                       if ((mode->quirks | st->drive_quirks)
+                           & ST_Q_FORCE_VAR_MODE) {
+                               mode2->blksiz = 0;
+                               st->modeflags[i] |= BLKSIZE_SET_BY_QUIRK;
+                       }
+               }
+               if (mode->density) {
+                       mode2->density = mode->density;
+                       st->modeflags[i] |= DENSITY_SET_BY_QUIRK;
+               }
+               mode++;
+               mode2++;
+       }
+}
+
+/*
+ * open the device.
+ */
+errval 
 stopen(dev, flags)
 stopen(dev, flags)
-int    dev, flags;
+       dev_t   dev;
+       u_int32 flags;
 {
 {
-       int unit,mode,dsty;
-       int     errno = 0;
+       u_int32 unit, mode, dsty;
+       errval  errno = 0;
        struct st_data *st;
        struct st_data *st;
+       struct scsi_link *sc_link;
        unit = UNIT(dev);
        mode = MODE(dev);
        dsty = DSTY(dev);
 
        unit = UNIT(dev);
        mode = MODE(dev);
        dsty = DSTY(dev);
 
-       /*******************************************************\
-       * Check the unit is legal                               *
-       \*******************************************************/
-       if ( unit >= NST )
-       {
-               return(ENXIO);
+       /*
+        * Check the unit is legal
+        */
+       if (unit >= NST) {
+               return (ENXIO);
        }
        st = st_data[unit];
        }
        st = st_data[unit];
-       /*******************************************************\
-       * Make sure the device has been initialised             *
-       \*******************************************************/
+       /*
+        * Make sure the device has been initialised
+        */
        if ((st == NULL) || (!(st->flags & ST_INITIALIZED)))
        if ((st == NULL) || (!(st->flags & ST_INITIALIZED)))
-               return(ENXIO);
-
-       /*******************************************************\
-       * Only allow one at a time                              *
-       \*******************************************************/
-       if(st->flags & ST_OPEN)
-       {
-               return(ENXIO);
-       }
-
-       /*******************************************************\
-       * Throw out a dummy instruction to catch 'Unit attention*
-       * errors (the error handling will invalidate all our    *
-       * device info if we get one, but otherwise, ignore it   *
-       \*******************************************************/
-       st_test_ready(unit, SCSI_SILENT); 
-
-       /***************************************************************\
-       * Check that the device is ready to use  (media loaded?)        *
-       * This time take notice of the return result                    *
-       \***************************************************************/
-       if(errno = (st_test_ready(unit,0))) 
-       {
-               printf("st%d: not ready\n",unit);
-               return(errno);
-       }
-
-       /*******************************************************\
-       * Set up the mode flags according to the minor number   *
-       * ensure all open flags are in a known state            *
-       * if it's a different mode, dump all cached parameters  *
-       \*******************************************************/
-       if(st->last_dsty != dsty || !(st->flags & ST_INFO_VALID))
-       {
-               st->flags &= ~ST_INFO_VALID;
-               st->last_dsty = dsty;
-               st->quirks = st->drive_quirks | st->modes[dsty].quirks;
-               st->density = st->modes[dsty].density;
-       }
-       st->flags &= ~ST_PER_OPEN;
-
-#ifdef STDEBUG
-       if(scsi_debug & (PRINTROUTINES | TRACEOPENS))
-               printf("stopen: dev=0x%x (unit %d (of %d))\n"
-                               ,   dev,      unit,   NST);
-#endif /*STDEBUG*/
-       /***************************************************************\
-       * If the media is new, then make sure we give it a chance to    *
-       * to do a 'load' instruction.                                   *
-       \***************************************************************/
-       if(!(st->flags & ST_INFO_VALID))                /* is media new? */
-       {
-               if(errno = st_load(unit,LD_LOAD,0))
-               {
-                       return(errno);
-               }
-               st_test_ready(unit,0);
-               if(st->quirks & ST_Q_SNS_HLP)
-               {
-                       /***********************************************\
-                       * The quirk here is that the drive returns some *
-                       * value to st_mode_sense incorrectly until the  *
-                       * tape has actually passed by the head.         *
-                       *                                               *
-                       * The method is to set the drive to large       *
-                       * fixed-block state (user-specified density and *
-                       * 1024-byte blocks), then read and rewind to    *
-                       * get it to sense the tape.  If that doesn't    *
-                       * work, try 512-byte fixed blocks.  If that     *
-                       * doesn't work, as a last resort, try variable- *
-                       * length blocks.  The result will be the        *
-                       * ability to do an accurate st_mode_sense.      *
-                       *                                               *
-                       * We pretend not to be at beginning of medium   *
-                       * to keep st_read from calling st_decide_mode.  *
-                       *                                               *
-                       * We know we can do a rewind because we just    *
-                       * did a load, which implies rewind.  Rewind     *
-                       * seems preferable to space backward if we have *
-                       * a virgin tape.                                *
-                       *                                               *
-                       * The rest of the code for this quirk is in ILI *
-                       * processing and BLANK CHECK error processing,  *
-                       * both part of st_interpret_sense.              *
-                       \***********************************************/
-                       char    *buf;
-                       int     readsiz;
-
-                       buf = malloc(1024,M_TEMP,M_NOWAIT);
-                       if(!buf) return(ENOMEM);
-
-                       if (errno = st_mode_sense(unit, 0))
-                       {
-                               goto bad;
-                       }
-                       st->blksiz = 1024;
-                       do {
-                               switch (st->blksiz)
-                               {
-                               case    512:
-                               case    1024:
-                                       readsiz = st->blksiz;
-                                       st->flags |= ST_FIXEDBLOCKS;
-                                       break;
-                               default:
-                                       readsiz = 1;
-                                       st->flags &= ~ST_FIXEDBLOCKS;
-                               }
-                               if (errno = st_mode_select(unit, 0))
-                               {
-                                       goto bad;
-                               }
-                               st->flags &= ~ST_AT_BOM;
-                               st_read(unit, buf, readsiz, SCSI_SILENT);
-                               if (errno = st_rewind(unit, FALSE, 0))
-                               {
-bad:                                   free(buf,M_TEMP);
-                                       return(errno);
-                               }
-                       } while (readsiz != 1 && readsiz > st->blksiz);
-                       free(buf,M_TEMP);
-               }
+               return (ENXIO);
+
+       sc_link = st->sc_link;
+       SC_DEBUG(sc_link, SDEV_DB1, ("open: dev=0x%x (unit %d (of %d))\n"
+               ,dev, unit, NST));
+       /*
+        * Only allow one at a time
+        */
+       if (st->flags & ST_OPEN) {
+               return (ENXIO);
        }
        }
-
-       /*******************************************************\
-       * Load the physical device parameters                   *
-       * loads: blkmin, blkmax                                 *
-       \*******************************************************/
-       if(errno = st_rd_blk_lim(unit,0))
-       {
-               return(errno);
-       }
-
-       /*******************************************************\
-       * Load the media dependent parameters                   *
-       * includes: media_blksiz,media_density,numblks          *
-       \*******************************************************/
-       if(errno = st_mode_sense(unit,0))
-       {
-               return(errno);
+       /*
+        * Throw out a dummy instruction to catch 'Unit attention
+        * errors (the error handling will invalidate all our
+        * device info if we get one, but otherwise, ignore it)
+        */
+       scsi_test_unit_ready(sc_link, SCSI_SILENT);
+
+       sc_link->flags |= SDEV_OPEN;    /* unit attn are now errors */
+       /*
+        * If the mode is 3 (e.g. minor = 3,7,11,15)
+        * then the device has been openned to set defaults
+        * This mode does NOT ALLOW I/O, only ioctls
+        */
+       if (mode == CTLMODE)
+               return 0;
+
+       /*
+        * Check that the device is ready to use (media loaded?)
+        * This time take notice of the return result
+        */
+       if (errno = (scsi_test_unit_ready(sc_link, 0))) {
+               printf("st%d: not ready\n", unit);
+               st_unmount(unit, NOEJECT);
+               return (errno);
        }
        }
-
-       if (!(st->flags & ST_INFO_VALID) && dsty == 0)
-       {
-               /*******************************************************\
-               * If the user defaulted the density, use the drive's    *
-               * opinion of it.                                        *
-               \*******************************************************/
-               st->quirks = st->drive_quirks;
-               st->density = st->media_density;
-               do {
-                       if (st->density == st->modes[dsty].density)
-                       {
-                               st->quirks |= st->modes[dsty].quirks;
-#ifdef STDEBUG
-                               if(st_debug) printf("selected density %d\n", dsty);
-#endif /*STDEBUG*/
-                               break; /* only out of the loop*/
-                       }
-               } while (++dsty < 4);
-               /*******************************************************\
-               * If dsty got to 4, the drive must have reported a      *
-               * density which isn't in our density list (e.g. QIC-24  *
-               * for a default drive).  We can handle that, except     *
-               * there'd better be no density-specific quirks in the   *
-               * drive's behavior.                                     *
-               \*******************************************************/
+       /*
+        * if it's a different mode, or if the media has been
+        * invalidated, unmount the tape from the previous
+        * session but continue with open processing
+        */
+       if ((st->last_dsty != dsty)
+           || (!(sc_link->flags & SDEV_MEDIA_LOADED))) {
+               st_unmount(unit, NOEJECT);
        }
        }
-
-       /***************************************************************\
-       * Decide whether or not to write two file marks to signify end- *
-       * of-data.  Make the decision as a function of density.  If     *
-       * the decision is not to use a second file mark, the SCSI BLANK *
-       * CHECK condition code will be recognized as end-of-data when   *
-       * first read.                                                   *
-       \***************************************************************/
-       switch (st->density)
-       {
-/*     case    8 mm:   What is the SCSI density code for 8 mm, anyway? */
-       case    QIC_11:
-       case    QIC_24:
-       case    QIC_120:
-       case    QIC_150:
-       case    QIC_525:
-       case    QIC_1320:
-               st->flags &= ~ST_2FM_AT_EOD;
-               break;
-       default:
-               st->flags |= ST_2FM_AT_EOD;
+       /*
+        * If we are not mounted, then we should start a new 
+        * mount session.
+        */
+       if (!(st->flags & ST_MOUNTED)) {
+               st_mount_tape(dev, flags);
+               st->last_dsty = dsty;
        }
        }
-
-       /***************************************************************\
-       * Make sure that a tape opened in write-only mode will have     *
-       * file marks written on it.  This is the only way to write a    *
-       * zero-length file on tape.                                     *
-       \***************************************************************/
+       /*
+        * Make sure that a tape opened in write-only mode will have
+        * file marks written on it when closed, even if not written to.
+        * This is for SUN compatibility
+        */
        if ((flags & O_ACCMODE) == FWRITE)
                st->flags |= ST_WRITTEN;
 
        if ((flags & O_ACCMODE) == FWRITE)
                st->flags |= ST_WRITTEN;
 
-       st->flags |= ST_INFO_VALID;
-
-       st_prevent(unit,PR_PREVENT,0); /* who cares if it fails? */
-
-#ifdef STDEBUG
-       if(scsi_debug & TRACEOPENS)
-               printf("Params loaded ");
-#endif /*STDEBUG*/
+       SC_DEBUG(sc_link, SDEV_DB2, ("Open complete\n"));
 
        st->flags |= ST_OPEN;
 
        st->flags |= ST_OPEN;
-       return(0);
+       return (0);
 }
 
 }
 
-/*******************************************************\
-* 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
+ */
+errval 
 stclose(dev)
 stclose(dev)
+       dev_t   dev;
 {
 {
-       unsigned char unit,mode;
-       struct  st_data *st;
+       unsigned char unit, mode;
+       struct st_data *st;
+       struct scsi_link *sc_link;
 
        unit = UNIT(dev);
        mode = MODE(dev);
        st = st_data[unit];
 
        unit = UNIT(dev);
        mode = MODE(dev);
        st = st_data[unit];
-
-#ifdef STDEBUG
-       if(scsi_debug & TRACEOPENS)
-               printf("Closing device");
-#endif /*STDEBUG*/
-       switch(mode)
-       {
-       case    0:
-               st_rewind(unit,FALSE,SCSI_SILENT);
-               st_prevent(unit,PR_ALLOW,SCSI_SILENT);
-               st->flags &= ~ST_PER_MEDIA;
+       sc_link = st->sc_link;
+
+       SC_DEBUG(sc_link, SDEV_DB1, ("closing\n"));
+       if ((st->flags & (ST_WRITTEN | ST_FM_WRITTEN)) == ST_WRITTEN)
+               st_write_filemarks(unit, 1, 0);
+       switch (mode & 0x3) {
+       case 0:
+       case 3:         /* for now */
+               st_unmount(unit, NOEJECT);
                break;
                break;
-       case    1: /*non rewind*/
-               if((st->flags & (ST_WRITTEN | ST_FM_WRITTEN)) == ST_WRITTEN)
-                       st_write_filemarks(unit, 1, 0);
-               break;
-       case    2:
-               st_rewind(unit,FALSE,SCSI_SILENT);
-               st_prevent(unit,PR_ALLOW,SCSI_SILENT);
-               st_load(unit,LD_UNLOAD,SCSI_SILENT);
-               st->flags &= ~ST_PER_MEDIA;
+       case 1:         /*leave mounted unless media seems to have been removed */
+               if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
+                       st_unmount(unit, NOEJECT);
+               }
                break;
                break;
-       case    3:/* a bit silly really */
-               st_prevent(unit,PR_ALLOW,SCSI_SILENT);
-               st_load(unit,LD_UNLOAD,SCSI_SILENT);
-               st->flags &= ~ST_PER_MEDIA;
+       case 2:
+               st_unmount(unit, EJECT);
                break;
                break;
-       default:
-               printf("st%d: close: Bad mode (minor number)%d how's it open?\n"
-                               ,unit,mode);
-               return(EINVAL);
        }
        }
-       st->flags &= ~ST_PER_OPEN;
-       return(0);
+       sc_link->flags &= ~SDEV_OPEN;
+       st->flags &= ~ST_OPEN;
+       return (0);
 }
 
 }
 
-/***************************************************************\
-* Given all we know about the device, media, mode, 'quirks' and        *
-* initial operation, make a decision as to how we should be set        *
-* up.  First, choose the density, then variable/fixed blocks.  *
-\***************************************************************/
-st_decide_mode(unit, first_read)
-int    unit, first_read;
+/*
+ * Start a new mount session.
+ * Copy in all the default parameters from the selected device mode.
+ * and try guess any that seem to be defaulted.
+ */
+errval
+st_mount_tape(dev, flags)
+       dev_t   dev;
+       u_int32 flags;
 {
 {
-       int dsty, error;
-       struct st_data *st = st_data[unit];
+       u_int32 unit, mode, dsty;
+       struct st_data *st;
+       struct scsi_link *sc_link;
+       errval  errno = 0;
 
 
-       /***************************************************************\
-       * First, if our information about the tape is out of date, get  *
-       * new information.                                              *
-       \***************************************************************/
-       if (!(st->flags & ST_INFO_VALID))
-       {
-               if (error = st_mode_sense(unit, 0))
-                       return (error);
-               st->flags |= ST_INFO_VALID;
+       unit = UNIT(dev);
+       mode = MODE(dev);
+       dsty = DSTY(dev);
+       st = st_data[unit];
+       sc_link = st->sc_link;
+
+       if (st->flags & ST_MOUNTED)
+               return 0;
+
+       SC_DEBUG(sc_link, SDEV_DB1, ("mounting\n "));
+       st->flags |= ST_NEW_MOUNT;
+       st->quirks = st->drive_quirks | st->modes[dsty].quirks;
+       /*
+        * If the media is new, then make sure we give it a chance to
+        * to do a 'load' instruction. ( We assume it is new)
+        */
+       if (errno = st_load(unit, LD_LOAD, 0)) {
+               return (errno);
        }
        }
-#ifdef STDEBUG
-       if(st_debug) printf("starting mode decision\n");
-#endif /*STDEBUG*/
-
-       /***************************************************************\
-       * If the user has already specified fixed or variable-length    *
-       * blocks using an ioctl, just believe him. OVERRIDE ALL         *
-       \***************************************************************/
-       if (st->flags & ST_BLOCK_SET)
-       {
-#ifdef STDEBUG
-       if(st_debug) printf("user has specified %s mode\n",
-               st->flags & ST_FIXEDBLOCKS ?  "fixed" : "variable");
-#endif /*STDEBUG*/
-               goto done;
+       /*
+        * Throw another dummy instruction to catch
+        * 'Unit attention' errors. Some drives appear to give
+        * these after doing a Load instruction.
+        * (noteably some DAT drives)
+        */
+       scsi_test_unit_ready(sc_link, SCSI_SILENT);
+
+       /*
+        * Some devices can't tell you much until they have been
+        * asked to look at the media. This quirk does this.
+        */
+       if (st->quirks & ST_Q_SNS_HLP) {
+               if (errno = st_touch_tape(unit))
+                       return errno;
+       }
+       /*
+        * Load the physical device parameters
+        * loads: blkmin, blkmax
+        */
+       if (errno = st_rd_blk_lim(unit, 0)) {
+               return errno;
+       }
+       /*
+        * Load the media dependent parameters
+        * includes: media_blksiz,media_density,numblks
+        * As we have a tape in, it should be reflected here.
+        * If not you may need the "quirk" above.
+        */
+       if (errno = st_mode_sense(unit, 0)) {
+               return errno;
+       }
+       /*
+        * If we have gained a permanent density from somewhere,
+        * then use it in preference to the one supplied by
+        * default by the driver.
+        */
+       if (st->modeflags[dsty] & (DENSITY_SET_BY_QUIRK | DENSITY_SET_BY_USER)) {
+               st->density = st->modes[dsty].density;
+       } else {
+               st->density = st->media_density;
+       }
+       /*
+        * If we have gained a permanent blocksize
+        * then use it in preference to the one supplied by
+        * default by the driver.
+        */
+       st->flags &= ~ST_FIXEDBLOCKS;
+       if (st->modeflags[dsty] & (BLKSIZE_SET_BY_QUIRK | BLKSIZE_SET_BY_USER)) {
+               st->blksiz = st->modes[dsty].blksiz;
+               if (st->blksiz) {
+                       st->flags |= ST_FIXEDBLOCKS;
+               }
+       } else {
+               if (errno = st_decide_mode(unit, FALSE)) {
+                       return errno;
+               }
        }
        }
+       if (errno = st_mode_select(unit, 0)) {
+               printf("st%d: Cannot set selected mode", unit);
+               return errno;
+       }
+       scsi_prevent(sc_link, PR_PREVENT, 0);   /* who cares if it fails? */
+       st->flags &= ~ST_NEW_MOUNT;
+       st->flags |= ST_MOUNTED;
+       sc_link->flags |= SDEV_MEDIA_LOADED;    /* move earlier? */
 
 
-       /***************************************************************\
-       * If the user hasn't already specified fixed or variable-length *
-       * blocks and the block size (zero if variable-length), we'll    *
-       * have to try to figure them out ourselves.                     *
-       *                                                               *
-       * Our first shot at a method is, "The quirks made me do it!"    *
-       \***************************************************************/
-       switch (st->quirks & (ST_Q_FORCE_FIXED_MODE | ST_Q_FORCE_VAR_MODE))
-       {
-       case    (ST_Q_FORCE_FIXED_MODE | ST_Q_FORCE_VAR_MODE):
-               printf("st%d: bad quirks\n",unit);
+       return 0;
+}
+
+/*
+ * End the present mount session.
+ * Rewind, and optionally eject the tape.
+ * Reset various flags to indicate that all new
+ * operations require another mount operation
+ */
+void
+st_unmount(int unit, boolean eject)
+{
+       struct st_data *st = st_data[unit];
+       struct scsi_link *sc_link = st->sc_link;
+       int32   nmarks;
+
+       if (!(st->flags & ST_MOUNTED))
+               return;
+       SC_DEBUG(sc_link, SDEV_DB1, ("unmounting\n"));
+       st_chkeod(unit, FALSE, &nmarks, SCSI_SILENT);
+       st_rewind(unit, FALSE, SCSI_SILENT);
+       scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
+       if (eject) {
+               st_load(unit, LD_UNLOAD, SCSI_SILENT);
+       }
+       st->flags &= ~(ST_MOUNTED | ST_NEW_MOUNT);
+       sc_link->flags &= ~SDEV_MEDIA_LOADED;
+}
+
+/*
+ * Given all we know about the device, media, mode, 'quirks' and
+ * initial operation, make a decision as to how we should be set
+ * to run (regarding blocking and EOD marks)
+ */
+errval 
+st_decide_mode(unit, first_read)
+       u_int32 unit;
+       boolean first_read;
+{
+       struct st_data *st = st_data[unit];
+#ifdef SCSIDEBUG
+       struct scsi_link *sc_link = st->sc_link;
+#endif
+
+       SC_DEBUG(sc_link, SDEV_DB2, ("starting block mode decision\n"));
+
+       /*
+        * If the user hasn't already specified fixed or variable-length
+        * blocks and the block size (zero if variable-length), we'll
+        * have to try to figure them out ourselves.
+        *
+        * Our first shot at a method is, "The quirks made me do it!"
+        */
+       switch (st->quirks & (ST_Q_FORCE_FIXED_MODE | ST_Q_FORCE_VAR_MODE)) {
+       case (ST_Q_FORCE_FIXED_MODE | ST_Q_FORCE_VAR_MODE):
+               printf("st%d: bad quirks\n", unit);
                return (EINVAL);
                return (EINVAL);
-       case    ST_Q_FORCE_FIXED_MODE:
+       case ST_Q_FORCE_FIXED_MODE:     /*specified fixed, but not what size */
                st->flags |= ST_FIXEDBLOCKS;
                if (st->blkmin && (st->blkmin == st->blkmax))
                        st->blksiz = st->blkmin;
                st->flags |= ST_FIXEDBLOCKS;
                if (st->blkmin && (st->blkmin == st->blkmax))
                        st->blksiz = st->blkmin;
-               else if(st->media_blksiz > 0)
+               else if (st->media_blksiz > 0)
                        st->blksiz = st->media_blksiz;
                else
                        st->blksiz = DEF_FIXED_BSIZE;
                        st->blksiz = st->media_blksiz;
                else
                        st->blksiz = DEF_FIXED_BSIZE;
-#ifdef STDEBUG
-               if(st_debug) printf("Quirks force fixed mode\n");
-#endif /*STDEBUG*/
+               SC_DEBUG(sc_link, SDEV_DB3, ("Quirks force fixed mode(%d)\n",
+                       st->blksiz));
                goto done;
                goto done;
-       case    ST_Q_FORCE_VAR_MODE:
+       case ST_Q_FORCE_VAR_MODE:
                st->flags &= ~ST_FIXEDBLOCKS;
                st->blksiz = 0;
                st->flags &= ~ST_FIXEDBLOCKS;
                st->blksiz = 0;
-#ifdef STDEBUG
-               if(st_debug) printf("Quirks force variable mode\n");
-#endif /*STDEBUG*/
+               SC_DEBUG(sc_link, SDEV_DB3, ("Quirks force variable mode\n"));
                goto done;
        }
                goto done;
        }
-
-       /***************************************************************\
-       * If the drive can only handle fixed-length blocks and only at  *
-       * one size, perhaps we should just do that.                     *
-       \***************************************************************/
-       if (st->blkmin && (st->blkmin == st->blkmax))
-       {
+               /*
+                * If the drive can only handle fixed-length blocks and only at
+                * one size, perhaps we should just do that.
+                */
+               if (st->blkmin && (st->blkmin == st->blkmax)) {
                st->flags |= ST_FIXEDBLOCKS;
                st->blksiz = st->blkmin;
                st->flags |= ST_FIXEDBLOCKS;
                st->blksiz = st->blkmin;
-#ifdef STDEBUG
-               if(st_debug) printf("blkmin == blkmax of %d\n",st->blkmin);
-#endif /*STDEBUG*/
+               SC_DEBUG(sc_link, SDEV_DB3,
+                   ("blkmin == blkmax of %d\n", st->blkmin));
                goto done;
        }
                goto done;
        }
-
-       /***************************************************************\
-       * If the tape density mandates use of fixed or variable-length  *
-       * blocks, comply.                                               *
-       \***************************************************************/
-       switch (st->density)
-       {
-       case    HALFINCH_800:
-       case    HALFINCH_1600:
-       case    HALFINCH_6250:
-       case    DDS:
+       /*
+        * If the tape density mandates (or even suggests) use of fixed
+        * or variable-length blocks, comply.
+        */
+       switch (st->density) {
+       case HALFINCH_800:
+       case HALFINCH_1600:
+       case HALFINCH_6250:
+       case DDS:
                st->flags &= ~ST_FIXEDBLOCKS;
                st->blksiz = 0;
                st->flags &= ~ST_FIXEDBLOCKS;
                st->blksiz = 0;
-#ifdef STDEBUG
-       if(st_debug) printf("density specified variable\n");
-#endif /*STDEBUG*/
+               SC_DEBUG(sc_link, SDEV_DB3, ("density specified variable\n"));
                goto done;
                goto done;
-       case    QIC_11:
-       case    QIC_24:
-       case    QIC_120:
-       case    QIC_150:
+       case QIC_11:
+       case QIC_24:
+       case QIC_120:
+       case QIC_150:
+       case QIC_525:
+       case QIC_1320:
                st->flags |= ST_FIXEDBLOCKS;
                st->flags |= ST_FIXEDBLOCKS;
-               if (st->media_blksiz > 0)
+               if (st->media_blksiz > 0) {
                        st->blksiz = st->media_blksiz;
                        st->blksiz = st->media_blksiz;
-               else
+               } else {
                        st->blksiz = DEF_FIXED_BSIZE;
                        st->blksiz = DEF_FIXED_BSIZE;
-#ifdef STDEBUG
-       if(st_debug) printf("density specified fixed\n");
-#endif /*STDEBUG*/
+               }
+               SC_DEBUG(sc_link, SDEV_DB3, ("density specified fixed\n"));
                goto done;
        }
                goto done;
        }
-
-       /***************************************************************\
-       * If we're about to read the tape, perhaps we should choose     *
-       * fixed or variable-length blocks and block size according to   *
-       * what the drive found on the tape.                             *
-       \***************************************************************/
-       if (first_read && (!(st->quirks & ST_Q_BLKSIZ) || st->media_blksiz == 0
-           || st->media_blksiz == DEF_FIXED_BSIZE || st->media_blksiz == 1024))
-       {
-               if (st->media_blksiz == 0)
+       /*
+        * If we're about to read the tape, perhaps we should choose
+        * fixed or variable-length blocks and block size according to
+        * what the drive found on the tape.
+        */
+       if (first_read
+           && (!(st->quirks & ST_Q_BLKSIZ)
+               || (st->media_blksiz == 0)
+               || (st->media_blksiz == DEF_FIXED_BSIZE)
+               || (st->media_blksiz == 1024))) {
+               if (st->media_blksiz == 0) {
                        st->flags &= ~ST_FIXEDBLOCKS;
                        st->flags &= ~ST_FIXEDBLOCKS;
-               else
+               } else {
                        st->flags |= ST_FIXEDBLOCKS;
                        st->flags |= ST_FIXEDBLOCKS;
+               }
                st->blksiz = st->media_blksiz;
                st->blksiz = st->media_blksiz;
-#ifdef STDEBUG
-               if(st_debug) printf("Used media_blksiz of %d\n",st->media_blksiz);
-#endif /*STDEBUG*/
+               SC_DEBUG(sc_link, SDEV_DB3,
+                   ("Used media_blksiz of %d\n", st->media_blksiz));
                goto done;
        }
                goto done;
        }
-
-       /***************************************************************\
-       * We're getting no hints from any direction.  Choose variable-  *
-       * length blocks arbitrarily.                                    *
-       \***************************************************************/
+       /*
+        * We're getting no hints from any direction.  Choose variable-
+        * length blocks arbitrarily.
+        */
        st->flags &= ~ST_FIXEDBLOCKS;
        st->blksiz = 0;
        st->flags &= ~ST_FIXEDBLOCKS;
        st->blksiz = 0;
-#ifdef STDEBUG
-       if(st_debug) printf("Give up and default to variable mode\n");
-#endif /*STDEBUG*/
+       SC_DEBUG(sc_link, SDEV_DB3, ("Give up and default to variable mode\n"));
 done:
 done:
-       st->flags &= ~ST_AT_BOM;
-       return (st_mode_select(unit, 0));
+
+       /*
+        * Decide whether or not to write two file marks to signify end-
+        * of-data.  Make the decision as a function of density.  If
+        * the decision is not to use a second file mark, the SCSI BLANK
+        * CHECK condition code will be recognized as end-of-data when
+        * first read.
+        * (I think this should be a by-product of fixed/variable..julian)
+        */
+       switch (st->density) {
+/*      case    8 mm:   What is the SCSI density code for 8 mm, anyway? */
+       case QIC_11:
+       case QIC_24:
+       case QIC_120:
+       case QIC_150:
+       case QIC_525:
+       case QIC_1320:
+               st->flags &= ~ST_2FM_AT_EOD;
+               break;
+       default:
+               st->flags |= ST_2FM_AT_EOD;
+       }
+       return 0;
 }
 
 }
 
-/*******************************************************\
-* trim the size of the transfer if needed,             *
-* called by physio                                     *
-* basically the smaller of our min and the scsi driver's*
-* minphys                                              *
-\*******************************************************/
-void   stminphys(bp)
-struct buf     *bp;
+/*
+ * trim the size of the transfer if needed,
+ * called by physio
+ * basically the smaller of our min and the scsi driver's
+ * minphys
+ */
+void 
+stminphys(bp)
+       struct buf *bp;
 {
 {
-       (*(st_data[UNIT(bp->b_dev)]->sc_sw->scsi_minphys))(bp);
+       (*(st_data[UNIT(bp->b_dev)]->sc_link->adapter->scsi_minphys)) (bp);
 }
 
 }
 
-/*******************************************************\
-* Actually translate the requested transfer into       *
-* one the physical driver can understand               *
-* The transfer is described by a buf and will include  *
-* only one physical transfer.                          *
-\*******************************************************/
-
-int    ststrategy(bp)
-struct buf     *bp;
+/*
+ * Actually translate the requested transfer into
+ * one the physical driver can understand
+ * The transfer is described by a buf and will include
+ * only one physical transfer.
+ */
+void 
+ststrategy(bp)
+       struct buf *bp;
 {
 {
-       struct  buf     **dp;
+       struct buf **dp;
        unsigned char unit;
        unsigned char unit;
-       unsigned int opri;
+       u_int32 opri;
        struct st_data *st;
 
        ststrats++;
        unit = UNIT((bp->b_dev));
        st = st_data[unit];
        struct st_data *st;
 
        ststrats++;
        unit = UNIT((bp->b_dev));
        st = st_data[unit];
-#ifdef STDEBUG
-       if(scsi_debug & PRINTROUTINES) printf("\nststrategy ");
-       if(scsi_debug & SHOWREQUESTS) printf("st%d: %d bytes @ blk%d\n",
-                                       unit,bp->b_bcount,bp->b_blkno);
-#endif /*STDEBUG*/
-       /*******************************************************\
-       * If it's a null transfer, return immediatly            *
-       \*******************************************************/
-       if (bp->b_bcount == 0)
-       {
+       SC_DEBUG(st->sc_link, SDEV_DB1,
+           (" strategy: %d bytes @ blk%d\n", bp->b_bcount, bp->b_blkno));
+       /*
+        * If it's a null transfer, return immediatly
+        */
+       if (bp->b_bcount == 0) {
                goto done;
        }
                goto done;
        }
-
-       /*******************************************************\
-       * If we're at beginning of medium, now is the time to   *
-       * set medium access density, fixed or variable-blocks   *
-       * and, if fixed, the block size.                        *
-       \*******************************************************/
-       if (st->flags & ST_AT_BOM &&
-           (bp->b_error = st_decide_mode(unit, (bp->b_flags & B_READ) != 0)))
-               goto bad;
-
-       /*******************************************************\
-       * Odd sized request on fixed drives are verboten        *
-       \*******************************************************/
-       if(st->flags & ST_FIXEDBLOCKS)
-       {
-               if(bp->b_bcount % st->blksiz)
-               {
+       /*
+        * Odd sized request on fixed drives are verboten
+        */
+       if (st->flags & ST_FIXEDBLOCKS) {
+               if (bp->b_bcount % st->blksiz) {
                        printf("st%d: bad request, must be multiple of %d\n",
                        printf("st%d: bad request, must be multiple of %d\n",
-                               unit, st->blksiz);
+                           unit, st->blksiz);
                        bp->b_error = EIO;
                        goto bad;
                }
        }
                        bp->b_error = EIO;
                        goto bad;
                }
        }
-       /*******************************************************\
-       * as are out-of-range requests on variable drives.      *
-       \*******************************************************/
-       else if(bp->b_bcount < st->blkmin || bp->b_bcount > st->blkmax)
-       {
+       /*
+        * as are out-of-range requests on variable drives.
+        */
+       else if (bp->b_bcount < st->blkmin || bp->b_bcount > st->blkmax) {
                printf("st%d: bad request, must be between %d and %d\n",
                printf("st%d: bad request, must be between %d and %d\n",
-                       unit, st->blkmin, st->blkmax);
+                   unit, st->blkmin, st->blkmax);
                bp->b_error = EIO;
                goto bad;
        }
                bp->b_error = EIO;
                goto bad;
        }
-
        stminphys(bp);
        opri = splbio();
 
        stminphys(bp);
        opri = splbio();
 
-       /*******************************************************\
-       * Place it in the queue of activities for this tape     *
-       * at the end (a bit silly because we only have on user..*
-       * (but it could fork() ))                               *
-       \*******************************************************/
+       /*
+        * Place it in the queue of activities for this tape
+        * at the end (a bit silly because we only have on user..
+        * (but it could fork() ))
+        */
        dp = &(st->buf_queue);
        dp = &(st->buf_queue);
-       while (*dp) 
-       {
+       while (*dp) {
                dp = &((*dp)->b_actf);
                dp = &((*dp)->b_actf);
-       }       
+       }
        *dp = bp;
        bp->b_actf = NULL;
 
        *dp = bp;
        bp->b_actf = NULL;
 
-       /*******************************************************\
-       * Tell the device to get going on the transfer if it's  *
-       * not doing anything, otherwise just wait for completion*
-       * (All a bit silly if we're only allowing 1 open but..) *
-       \*******************************************************/
+       /*
+        * Tell the device to get going on the transfer if it's
+        * not doing anything, otherwise just wait for completion
+        * (All a bit silly if we're only allowing 1 open but..)
+        */
        ststart(unit);
 
        splx(opri);
        ststart(unit);
 
        splx(opri);
@@ -928,1443 +935,993 @@ struct buf     *bp;
 bad:
        bp->b_flags |= B_ERROR;
 done:
 bad:
        bp->b_flags |= B_ERROR;
 done:
-       /*******************************************************\
-       * Correctly set the buf to indicate a completed xfer    *
-       \*******************************************************/
+       /*
+        * Correctly set the buf to indicate a completed xfer
+        */
        iodone(bp);
        return;
 }
 
        iodone(bp);
        return;
 }
 
+/*
+ * ststart looks to see if there is a buf waiting for the device
+ * and that the device is not already busy. If both are true,
+ * It dequeues the buf and creates a scsi command to perform the
+ * transfer required. The transfer request will call scsi_done
+ * on completion, which will in turn call this routine again
+ * so that the next queued transfer is performed.
+ * The bufs are queued by the strategy routine (ststrategy)
+ *
+ * This routine is also called after other non-queued requests
+ * have been made of the scsi driver, to ensure that the queue
+ * continues to be drained.
+ * ststart() is called at splbio
+ */
+void 
+ststart(unit)
+       u_int32 unit;
+{
+       struct st_data *st = st_data[unit];
+       struct scsi_link *sc_link = st->sc_link;
+       register struct buf *bp = 0;
+       struct scsi_rw_tape cmd;
+       u_int32 flags;
+
+       SC_DEBUG(sc_link, SDEV_DB2, ("ststart "));
+       /*
+        * See if there is a buf to do and we are not already
+        * doing one
+        */
+       while (sc_link->opennings != 0) {
+
+               /* if a special awaits, let it proceed first */
+               if (sc_link->flags & SDEV_WAITING) {
+                       wakeup((caddr_t)sc_link);
+                       return;
+               }
+               if ((bp = st->buf_queue) == NULL) {
+                       return; /* no work to bother with */
+               }
+               st->buf_queue = bp->b_actf;
+
+               /*
+                * if the device has been unmounted byt the user
+                * then throw away all requests until done
+                */
+               if ((!(st->flags & ST_MOUNTED))
+                   || (!(sc_link->flags & SDEV_MEDIA_LOADED))) {
+                       /* make sure that one implies the other.. */
+                       sc_link->flags &= ~SDEV_MEDIA_LOADED;
+                       goto badnews;
+               }
+               /*
+                * only FIXEDBLOCK devices have pending operations
+                */
+               if (st->flags & ST_FIXEDBLOCKS) {
+                       /*
+                        * If we are at a filemark but have not reported it yet
+                        * then we should report it now
+                        */
+                       if (st->flags & ST_AT_FILEMARK) {
+                               if ((bp->b_flags & B_READ) == B_WRITE) {
+                                       /*
+                                        * Handling of ST_AT_FILEMARK in
+                                        * st_space will fill in the right file
+                                        * mark count.
+                                        * Back up over filemark
+                                        */
+                                       if (st_space(unit, 0, SP_FILEMARKS, 0) !=
+                                           ESUCCESS)
+                                               goto badnews;
+                               } else {
+                                       bp->b_resid = bp->b_bcount;
+                                       bp->b_error = 0;
+                                       bp->b_flags &= ~B_ERROR;
+                                       st->flags &= ~ST_AT_FILEMARK;
+                                       biodone(bp);
+                                       continue;       /* seek more work */
+                               }
+                       }
+                       /*
+                        * If we are at EIO (e.g. EOM) but have not reported it
+                        * yet then we should report it now
+                        */
+                       if (st->flags & ST_EIO_PENDING) {
+                               bp->b_resid = bp->b_bcount;
+                               bp->b_error = EIO;
+                               bp->b_flags |= B_ERROR;
+                               st->flags &= ~ST_EIO_PENDING;
+                               biodone(bp);
+                               continue;       /* seek more work */
+                       }
+               }
+               /*
+                *  Fill out the scsi command
+                */
+               bzero(&cmd, sizeof(cmd));
+               if ((bp->b_flags & B_READ) == B_WRITE) {
+                       cmd.op_code = WRITE_COMMAND_TAPE;
+                       st->flags &= ~ST_FM_WRITTEN;
+                       st->flags |= ST_WRITTEN;
+                       flags = SCSI_DATA_OUT;
+               } else {
+                       cmd.op_code = READ_COMMAND_TAPE;
+                       flags = SCSI_DATA_IN;
+               }
+               /*
+                * Handle "fixed-block-mode" tape drives by using the
+                * block count instead of the length.
+                */
+               if (st->flags & ST_FIXEDBLOCKS) {
+                       cmd.byte2 |= SRWT_FIXED;
+                       lto3b(bp->b_bcount / st->blksiz, cmd.len);
+               } else {
+                       lto3b(bp->b_bcount, cmd.len);
+               }
+               /*
+                * go ask the adapter to do all this for us
+                */
+               if (scsi_scsi_cmd(sc_link,
+                       (struct scsi_generic *) &cmd,
+                       sizeof(cmd),
+                       (u_char *) bp->b_un.b_addr,
+                       bp->b_bcount,
+                       0,      /* can't retry a read on a tape really */
+                       100000,
+                       bp,
+                       flags | SCSI_NOSLEEP) == SUCCESSFULLY_QUEUED) {
+                       stqueues++;
+               } else {
+badnews:
+                       printf("st%d: oops not queued\n", unit);
+                       bp->b_flags |= B_ERROR;
+                       bp->b_error = EIO;
+                       biodone(bp);
+               }
+       } /* go back and see if we can cram more work in.. */
+}
 
 
-
-/*******************************************************\
-* Perform special action on behalf of the user         *
-* Knows about the internals of this device             *
-\*******************************************************/
-stioctl(dev, cmd, arg, mode)
-dev_t dev;
-int cmd;
-caddr_t arg;
+/*
+ * Perform special action on behalf of the user;
+ * knows about the internals of this device
+ */
+errval 
+stioctl(dev, cmd, arg, flag)
+       dev_t   dev;
+       int     cmd;
+       caddr_t arg;
+       int     flag;
 {
 {
-       int errcode = 0;
+       errval  errcode = 0;
        unsigned char unit;
        unsigned char unit;
-       int number,flags,dsty;
-        struct  st_data *st;
-       
-
-       /*******************************************************\
-       * Find the device that the user is talking about        *
-       \*******************************************************/
-       flags = 0;      /* give error messages, act on errors etc. */
+       u_int32 number, flags, dsty;
+       struct st_data *st;
+       u_int32 hold_blksiz;
+       u_int32 hold_density;
+       int32   nmarks;
+       struct mtop *mt = (struct mtop *) arg;
+
+       /*
+        * Find the device that the user is talking about
+        */
+       flags = 0;              /* give error messages, act on errors etc. */
        unit = UNIT(dev);
        dsty = DSTY(dev);
        unit = UNIT(dev);
        dsty = DSTY(dev);
-        st = st_data[unit];
+       st = st_data[unit];
+       hold_blksiz = st->blksiz;
+       hold_density = st->density;
 
 
-       switch(cmd)
-       {
+       switch (cmd) {
 
        case MTIOCGET:
 
        case MTIOCGET:
-           {
-               struct mtget *g = (struct mtget *) arg;
-
-               bzero(g, sizeof(struct mtget));
-               g->mt_type = 0x7;       /* Ultrix compat */ /*?*/
-                if (st->flags & ST_FIXEDBLOCKS) { 
-                        g->mt_bsiz = st->blksiz;
-                } else {
-                        g->mt_bsiz = 0;
-                }
-               g->mt_dns_dflt          = st->modes[0].density;
-               g->mt_dns_dsty1         = st->modes[DSTY1].density;
-               g->mt_dns_dsty2         = st->modes[DSTY2].density;
-               g->mt_dns_dsty3         = st->modes[DSTY3].density;
-               break;
-           }
-
-
+               {
+                       struct mtget *g = (struct mtget *) arg;
+
+                       SC_DEBUG(st->sc_link, SDEV_DB1, ("[ioctl: get status]\n"));
+                       bzero(g, sizeof(struct mtget));
+                       g->mt_type = 0x7;       /* Ultrix compat *//*? */
+                       g->mt_density = st->density;
+                       g->mt_blksiz = st->blksiz;
+                       g->mt_density0 = st->modes[0].density;
+                       g->mt_density1 = st->modes[1].density;
+                       g->mt_density2 = st->modes[2].density;
+                       g->mt_density3 = st->modes[3].density;
+                       g->mt_blksiz0 = st->modes[0].blksiz;
+                       g->mt_blksiz1 = st->modes[1].blksiz;
+                       g->mt_blksiz2 = st->modes[2].blksiz;
+                       g->mt_blksiz3 = st->modes[3].blksiz;
+                       break;
+               }
        case MTIOCTOP:
        case MTIOCTOP:
-           {
-               int nmarks;
-               struct mtop *mt = (struct mtop *) arg;
-
-#ifdef STDEBUG
-               if (st_debug)
-                       printf("[sctape_sstatus: %x %x]\n",
-                                mt->mt_op, mt->mt_count);
-#endif /*STDEBUG*/
-
+               {
 
 
+                       SC_DEBUG(st->sc_link, SDEV_DB1, ("[ioctl: op=0x%x count=0x%x]\n",
+                               mt->mt_op, mt->mt_count));
 
 
-               /* compat: in U*x it is a short */
-               number = mt->mt_count;
-               switch ((short)(mt->mt_op))
-               {
-               case MTWEOF:    /* write an end-of-file record */
-                       errcode = st_write_filemarks(unit,number,flags);
-                       break;
-               case MTBSF:     /* backward space file */
-                       number = -number;
-               case MTFSF:     /* forward space file */
-                       errcode = st_chkeod(unit, FALSE, &nmarks, flags);
-                       if (errcode == ESUCCESS)
-                               errcode = st_space(unit, number - nmarks,
-                                   SP_FILEMARKS, flags);
-                       break;
-               case MTBSR:     /* backward space record */
-                       number = -number;
-               case MTFSR:     /* forward space record */
-                       errcode = st_chkeod(unit, TRUE, &nmarks, flags);
-                       if (errcode == ESUCCESS)
-                               errcode = st_space(unit,number,SP_BLKS,flags);
-                       break;
-               case MTREW:     /* rewind */
-                       errcode = st_rewind(unit,FALSE,flags);
-                       break;
-               case MTOFFL:    /* rewind and put the drive offline */
-                       if(st_rewind(unit,FALSE,flags))
-                       {
-                               printf("st%d: rewind failed, unit still loaded\n",
-                                       unit);
-                       }
-                       else
-                       {
-                               st_prevent(unit,PR_ALLOW,0);
-                               st_load(unit,LD_UNLOAD,flags);
-                       }
-                       break;
-               case MTNOP:     /* no operation, sets status only */
-               case MTCACHE:   /* enable controller cache */
-               case MTNOCACHE: /* disable controller cache */
-                       break;
-               case MTSETBSIZ: /* Set block size for device */
-                       if (!(st->flags & ST_AT_BOM))
-                       {
-                               errcode =  EINVAL;
+                       /* compat: in U*x it is a short */
+                       number = mt->mt_count;
+                       switch ((short) (mt->mt_op)) {
+                       case MTWEOF:    /* write an end-of-file record */
+                               errcode = st_write_filemarks(unit, number, flags);
                                break;
                                break;
-                       }
-                       if (number == 0)
-                       {
-                               st->flags &= ~ST_FIXEDBLOCKS;
-                       }
-                       else
-                       {
-                               if ((st->blkmin || st->blkmax) /* they exist */
-                                 && ((number < st->blkmin 
-                                   || number > st->blkmax)))
-                               {
+                       case MTBSF:     /* backward space file */
+                               number = -number;
+                       case MTFSF:     /* forward space file */
+                               errcode = st_chkeod(unit, FALSE, &nmarks, flags);
+                               if (errcode == ESUCCESS)
+                                       errcode = st_space(unit, number - nmarks,
+                                           SP_FILEMARKS, flags);
+                               break;
+                       case MTBSR:     /* backward space record */
+                               number = -number;
+                       case MTFSR:     /* forward space record */
+                               errcode = st_chkeod(unit, TRUE, &nmarks, flags);
+                               if (errcode == ESUCCESS)
+                                       errcode = st_space(unit, number, SP_BLKS, flags);
+                               break;
+                       case MTREW:     /* rewind */
+                               errcode = st_rewind(unit, FALSE, flags);
+                               break;
+                       case MTOFFL:    /* rewind and put the drive offline */
+                               st_unmount(unit, EJECT);
+                               break;
+                       case MTNOP:     /* no operation, sets status only */
+                       case MTCACHE:   /* enable controller cache */
+                       case MTNOCACHE: /* disable controller cache */
+                               break;
+                       case MTSETBSIZ: /* Set block size for device */
+#ifdef NOTYET
+                               if (!(st->flags & ST_NEW_MOUNT)) {
+                                       uprintf("re-mount tape before changing blocksize");
                                        errcode = EINVAL;
                                        break;
                                }
                                        errcode = EINVAL;
                                        break;
                                }
-                               st->flags |= ST_FIXEDBLOCKS;
-                       }
-                       st->blksiz = number;
-                       st->flags |= ST_BLOCK_SET;
-                        break;
+#endif
+                               if (number == 0) {
+                                       st->flags &= ~ST_FIXEDBLOCKS;
+                               } else {
+                                       if ((st->blkmin || st->blkmax)  /* they exist */
+                                           &&((number < st->blkmin
+                                                   || number > st->blkmax))) {
+                                               errcode = EINVAL;
+                                               break;
+                                       }
+                                       st->flags |= ST_FIXEDBLOCKS;
+                               }
+                               st->blksiz = number;
+                               st->flags |= ST_BLOCK_SET;      /*XXX */
+                               goto try_new_value;
 
 
-                       /* How do we check that the drive can handle
-                          the requested density ? */
+                       case MTSETDNSTY:        /* Set density for device and mode */
+                               if (number > SCSI_2_MAX_DENSITY_CODE) {
+                                       errcode = EINVAL;
+                               } else {
+                                       st->density = number;
+                               }
+                               goto try_new_value;
 
 
-                case MTSETDNSTY: /* Set density for device and mode */
-                       if (number < 0 || number > SCSI_2_MAX_DENSITY_CODE)
-                       {
+                       default:
                                errcode = EINVAL;
                        }
                                errcode = EINVAL;
                        }
-                       else
-                       { 
-                               st->modes[dsty].density = number;
-                       }
                        break;
                        break;
-
-               default:
-                       errcode = EINVAL;
                }
                }
-               break;
-           }
        case MTIOCIEOT:
        case MTIOCEEOT:
                break;
        default:
        case MTIOCIEOT:
        case MTIOCEEOT:
                break;
        default:
-               errcode = EINVAL;
+               if(MODE(dev) == CTLMODE)
+                       errcode = scsi_do_ioctl(st->sc_link,cmd,arg,flag);
+               else
+                       errcode = ENOTTY;
+               break;
        }
        }
-
        return errcode;
        return errcode;
+/*-----------------------------*/
+try_new_value:
+       /*
+        * Check that the mode being asked for is aggreeable to the
+        * drive. If not, put it back the way it was.
+        */
+       if (errcode = st_mode_select(unit, 0)) {        /* put it back as it was */
+               printf("st%d: Cannot set selected mode", unit);
+               st->density = hold_density;
+               st->blksiz = hold_blksiz;
+               if (st->blksiz) {
+                       st->flags |= ST_FIXEDBLOCKS;
+               } else {
+                       st->flags &= ~ST_FIXEDBLOCKS;
+               }
+               return (errcode);
+       }
+       /*
+        * As the drive liked it, if we are setting a new default,
+        * set it into the structures as such.
+        * 
+        * The means for deciding this are not finalised yet
+        */
+       if (MODE(dev) == 0x03) {
+               /* special mode */
+               /* XXX */
+               switch ((short) (mt->mt_op)) {
+               case MTSETBSIZ:
+                       st->modes[dsty].blksiz = st->blksiz;
+                       st->modeflags[dsty] |= BLKSIZE_SET_BY_USER;
+                       break;
+               case MTSETDNSTY:
+                       st->modes[dsty].density = st->density;
+                       st->modeflags[dsty] |= DENSITY_SET_BY_USER;
+                       break;
+               }
+       }
+       return 0;
 }
 
 }
 
-/*******************************************************\
-* Do a synchronous read.                               *
-\*******************************************************/
-int st_read(unit, buf, size, flags)
-int    unit, size, flags;
-char   *buf;
+/*
+ * Do a synchronous read.
+ */
+errval 
+st_read(unit, buf, size, flags)
+       u_int32 unit, size, flags;
+       char   *buf;
 {
 {
-       int error;
        struct scsi_rw_tape scsi_cmd;
        struct st_data *st = st_data[unit];
 
        struct scsi_rw_tape scsi_cmd;
        struct st_data *st = st_data[unit];
 
-       /*******************************************************\
-       * If it's a null transfer, return immediatly            *
-       \*******************************************************/
-       if (size == 0)
-       {
-               return(ESUCCESS);
+       /*
+        * If it's a null transfer, return immediatly
+        */
+       if (size == 0) {
+               return (ESUCCESS);
        }
        }
-
-       /*******************************************************\
-       * If we're at beginning of medium, now is the time to   *
-       * set medium access density, fixed or variable-blocks   *
-       * and, if fixed, the block size.                        *
-       \*******************************************************/
-       if (st->flags & ST_AT_BOM && (error = st_decide_mode(unit, TRUE)))
-               return (error);
-
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = READ_COMMAND_TAPE;
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = READ_COMMAND_TAPE;
-       scsi_cmd.byte2 |= st->flags & ST_FIXEDBLOCKS ? SRWT_FIXED : 0;
-       lto3b(scsi_cmd.byte2 & SRWT_FIXED ?
-           size / (st->blksiz ? st->blksiz : DEF_FIXED_BSIZE) : size,
-           scsi_cmd.len);
-       return (st_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       buf,
-                       size,
-                       100000,
-                       NULL,
-                       flags | SCSI_DATA_IN));
-}
-
-/*******************************************************\
-* Get scsi driver to send a "are you ready" command    *
-\*******************************************************/
-st_test_ready(unit,flags)
-int    unit,flags;
-{
-       struct  scsi_test_unit_ready scsi_cmd;
-
-       bzero(&scsi_cmd, sizeof(scsi_cmd));
-       scsi_cmd.op_code = TEST_UNIT_READY;
-
-       return (st_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       0,
-                       0,
-                       100000,
-                       NULL,
-                       flags));
+       if (st->flags & ST_FIXEDBLOCKS) {
+               scsi_cmd.byte2 |= SRWT_FIXED;
+               lto3b(size / (st->blksiz ? st->blksiz : DEF_FIXED_BSIZE),
+                   scsi_cmd.len);
+       } else {
+               lto3b(size, scsi_cmd.len);
+       }
+       return (scsi_scsi_cmd(st->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               (u_char *) buf,
+               size,
+               0,              /* not on io commands */
+               100000,
+               NULL,
+               flags | SCSI_DATA_IN));
 }
 }
-
-
 #ifdef __STDC__
 #define b2tol(a)       (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
 #else
 #define b2tol(a)       (((unsigned)(a/**/_1) << 8) + (unsigned)a/**/_0 )
 #endif
 
 #ifdef __STDC__
 #define b2tol(a)       (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
 #else
 #define b2tol(a)       (((unsigned)(a/**/_1) << 8) + (unsigned)a/**/_0 )
 #endif
 
-/*******************************************************\
-* Ask the drive what it's min and max blk sizes are.   *
-\*******************************************************/
+/*
+ * Ask the drive what it's min and max blk sizes are.
+ */
+errval 
 st_rd_blk_lim(unit, flags)
 st_rd_blk_lim(unit, flags)
-int    unit,flags;
+       u_int32 unit, flags;
 {
 {
-       struct  scsi_blk_limits scsi_cmd;
+       struct scsi_blk_limits scsi_cmd;
        struct scsi_blk_limits_data scsi_blkl;
        struct st_data *st = st_data[unit];
        struct scsi_blk_limits_data scsi_blkl;
        struct st_data *st = st_data[unit];
-       int     errno;
-
-       /*******************************************************\
-       * First check if we have it all loaded                  *
-       \*******************************************************/
-       if ((st->flags & ST_INFO_VALID)) return 0;
-
-       /*******************************************************\
-       * do a 'Read Block Limits'                              *
-       \*******************************************************/
+       errval  errno;
+       struct scsi_link *sc_link = st->sc_link;
+
+       /*
+        * First check if we have it all loaded
+        */
+       if ((sc_link->flags & SDEV_MEDIA_LOADED))
+               return 0;
+
+       /*
+        * do a 'Read Block Limits'
+        */
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = READ_BLK_LIMITS;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = READ_BLK_LIMITS;
 
-       /*******************************************************\
-       * do the command,       update the global values        *
-       \*******************************************************/
-       if ( errno = st_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       &scsi_blkl,
-                       sizeof(scsi_blkl),
-                       5000,
-                       NULL,
-                       flags | SCSI_DATA_IN))
-       {
+       /*
+        * do the command, update the global values
+        */
+       if (errno = scsi_scsi_cmd(sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               (u_char *) & scsi_blkl,
+               sizeof(scsi_blkl),
+               ST_RETRIES,
+               5000,
+               NULL,
+               flags | SCSI_DATA_IN)) {
                return errno;
                return errno;
-       } 
+       }
        st->blkmin = b2tol(scsi_blkl.min_length);
        st->blkmax = _3btol(&scsi_blkl.max_length_2);
 
        st->blkmin = b2tol(scsi_blkl.min_length);
        st->blkmax = _3btol(&scsi_blkl.max_length_2);
 
-#ifdef STDEBUG
-       if (st_debug)
-       {
-               printf("(%d <= blksiz <= %d)\n", st->blkmin, st->blkmax);
-       }
-#endif /*STDEBUG*/
+       SC_DEBUG(sc_link, SDEV_DB3,
+           ("(%d <= blksiz <= %d)\n", st->blkmin, st->blkmax));
        return 0;
 }
 
        return 0;
 }
 
-/*******************************************************\
-* Get the scsi driver to send a full inquiry to the    *
-* device and use the results to fill out the global    *
-* parameter structure.                                 *
-*                                                      *
-* called from:                                         *
-* attach                                               *
-* open                                                 *
-* ioctl (to reset original blksize)                    *
-\*******************************************************/
+/*
+ * Get the scsi driver to send a full inquiry to the
+ * device and use the results to fill out the global 
+ * parameter structure.
+ *
+ * called from:
+ * attach
+ * open
+ * ioctl (to reset original blksize)
+ */
+errval 
 st_mode_sense(unit, flags)
 st_mode_sense(unit, flags)
-int    unit,flags;
+       u_int32 unit, flags;
 {
 {
-       int     scsi_sense_len;
-       int     errno;
-       char    *scsi_sense_ptr;
-       struct scsi_mode_sense          scsi_cmd;
-       struct scsi_sense
-       {
-               struct  scsi_mode_header header;
-               struct  blk_desc        blk_desc;
-       }scsi_sense;
+       u_int32 scsi_sense_len;
+       errval  errno;
+       char   *scsi_sense_ptr;
+       struct scsi_mode_sense scsi_cmd;
+       struct scsi_sense {
+               struct scsi_mode_header header;
+               struct blk_desc blk_desc;
+       } scsi_sense;
+
+       struct scsi_sense_page_0 {
+               struct scsi_mode_header header;
+               struct blk_desc blk_desc;
+               unsigned char sense_data[PAGE_0_SENSE_DATA_SIZE];
+                       /* Tandberg tape drives returns page 00
+                        * with the sense data, whether or not
+                        * you want it( ie the don't like you
+                        * saying you want anything less!!!!!
+                        * They also expect page 00
+                        * back when you issue a mode select
+                        */
+       } scsi_sense_page_0;
+       struct st_data *st = st_data[unit];
+       struct scsi_link *sc_link = st->sc_link;
 
 
-       struct scsi_sense_page_0
-       {
-               struct  scsi_mode_header header;
-               struct  blk_desc        blk_desc;
-                unsigned char   sense_data[PAGE_0_SENSE_DATA_SIZE];
-                        /* Tandberg tape drives returns page 00 */
-                        /* with the sense data, whether or not */
-                        /* you want it( ie the don't like you  */
-                        /* saying you want anything less!!!!!  */
-                        /* They also expect page 00 */
-                        /* back when you issue a mode select */
-       }scsi_sense_page_0;
-       struct  st_data *st = st_data[unit];
-       
-       /*******************************************************\
-       * First check if we have it all loaded                  *
-       \*******************************************************/
-       if ((st->flags & ST_INFO_VALID)) return 0;
-
-       /*******************************************************\
-       * Define what sort of structure we're working with      *
-       \*******************************************************/
-       if (st->quirks & ST_Q_NEEDS_PAGE_0)
-       {
+       /*
+        * Define what sort of structure we're working with
+        */
+       if (st->quirks & ST_Q_NEEDS_PAGE_0) {
                scsi_sense_len = sizeof(scsi_sense_page_0);
                scsi_sense_ptr = (char *) &scsi_sense_page_0;
                scsi_sense_len = sizeof(scsi_sense_page_0);
                scsi_sense_ptr = (char *) &scsi_sense_page_0;
-       }
-       else
-       {
+       } else {
                scsi_sense_len = sizeof(scsi_sense);
                scsi_sense_ptr = (char *) &scsi_sense;
        }
                scsi_sense_len = sizeof(scsi_sense);
                scsi_sense_ptr = (char *) &scsi_sense;
        }
-
-       /*******************************************************\
-       * Set up a mode sense                                   *
-       \*******************************************************/
+       /*
+        * Set up a mode sense 
+        */
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = MODE_SENSE;
        scsi_cmd.length = scsi_sense_len;
 
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = MODE_SENSE;
        scsi_cmd.length = scsi_sense_len;
 
-       /*******************************************************\
-       * do the command, but we don't need the results         *
-       * just print them for our interest's sake, if asked,    *
-       * or if we need it as a template for the mode select    *
-       * store it away.                                        *
-       \*******************************************************/
-       if (errno = st_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       scsi_sense_ptr,
-                       scsi_sense_len,
-                       5000,
-                       NULL,
-                       flags | SCSI_DATA_IN) )
-       {
+       /*
+        * do the command, but we don't need the results
+        * just print them for our interest's sake, if asked,
+        * or if we need it as a template for the mode select
+        * store it away.
+        */
+       if (errno = scsi_scsi_cmd(sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               (u_char *) scsi_sense_ptr,
+               scsi_sense_len,
+               ST_RETRIES,
+               5000,
+               NULL,
+               flags | SCSI_DATA_IN)) {
                return errno;
                return errno;
-       } 
-       st->numblks = _3btol(&(((struct scsi_sense *)scsi_sense_ptr)->blk_desc.nblocks));
-       st->media_blksiz = _3btol(&(((struct scsi_sense *)scsi_sense_ptr)->blk_desc.blklen));
-       st->media_density = ((struct scsi_sense *)scsi_sense_ptr)->blk_desc.density;
-       if (((struct scsi_sense *)scsi_sense_ptr)->header.dev_spec &
-           SMH_DSP_WRITE_PROT)
+       }
+       st->numblks = _3btol(((struct scsi_sense *)scsi_sense_ptr)->blk_desc.nblocks);
+       st->media_blksiz = _3btol(((struct scsi_sense *)scsi_sense_ptr)->blk_desc.blklen);
+       st->media_density = ((struct scsi_sense *) scsi_sense_ptr)->blk_desc.density;
+       if (((struct scsi_sense *) scsi_sense_ptr)->header.dev_spec &
+           SMH_DSP_WRITE_PROT) {
                st->flags |= ST_READONLY;
                st->flags |= ST_READONLY;
-#ifdef STDEBUG
-       if (st_debug)
-       {
-               printf("st%d: density code 0x%x, %d-byte blocks, write-%s, ",
-                   unit, st->media_density, st->media_blksiz,
-                   st->flags & ST_READONLY ? "protected" : "enabled");
-               printf("%sbuffered\n",
-                   ((struct scsi_sense *)scsi_sense_ptr)->header.dev_spec
-                   & SMH_DSP_BUFF_MODE ? "" : "un");
        }
        }
-#endif /*STDEBUG*/
-       if (st->quirks & ST_Q_NEEDS_PAGE_0)
-       {
-               bcopy(((struct scsi_sense_page_0 *)scsi_sense_ptr)->sense_data, 
-                       st->sense_data, 
-                       sizeof(((struct scsi_sense_page_0 *)scsi_sense_ptr)->sense_data));
+       SC_DEBUG(sc_link, SDEV_DB3,
+           ("density code 0x%x, %d-byte blocks, write-%s, ",
+               st->media_density, st->media_blksiz,
+               st->flags & ST_READONLY ? "protected" : "enabled"));
+       SC_DEBUG(sc_link, SDEV_DB3,
+           ("%sbuffered\n",
+               ((struct scsi_sense *) scsi_sense_ptr)->header.dev_spec
+               & SMH_DSP_BUFF_MODE ? "" : "un"));
+       if (st->quirks & ST_Q_NEEDS_PAGE_0) {
+               bcopy(((struct scsi_sense_page_0 *) scsi_sense_ptr)->sense_data,
+                   st->sense_data,
+                   sizeof(((struct scsi_sense_page_0 *) scsi_sense_ptr)->sense_data));
        }
        }
+       sc_link->flags |= SDEV_MEDIA_LOADED;
        return 0;
 }
 
        return 0;
 }
 
-/*******************************************************\
-* Send a filled out parameter structure to the drive to        *
-* set it into the desire modes etc.                    *
-\*******************************************************/
+/*
+ * Send a filled out parameter structure to the drive to
+ * set it into the desire modes etc.
+ */
+errval 
 st_mode_select(unit, flags)
 st_mode_select(unit, flags)
-int    unit, flags;
+       u_int32 unit, flags;
 {
 {
-       int     dat_len;
-       char    *dat_ptr;
+       u_int32 dat_len;
+       char   *dat_ptr;
        struct scsi_mode_select scsi_cmd;
        struct scsi_mode_select scsi_cmd;
-       struct dat
-       {
-               struct  scsi_mode_header header;
-               struct  blk_desc        blk_desc;
-       }dat;
-       struct dat_page_0
-       {
-               struct  scsi_mode_header header;
-               struct  blk_desc        blk_desc;
-                unsigned char   sense_data[PAGE_0_SENSE_DATA_SIZE];
-       }dat_page_0;
-       struct  st_data *st = st_data[unit];
-
-       /*******************************************************\
-       * Define what sort of structure we're working with      *
-       \*******************************************************/
-       if (st->quirks & ST_Q_NEEDS_PAGE_0)
-       {
+       struct dat {
+               struct scsi_mode_header header;
+               struct blk_desc blk_desc;
+       } dat;
+       struct dat_page_0 {
+               struct scsi_mode_header header;
+               struct blk_desc blk_desc;
+               unsigned char sense_data[PAGE_0_SENSE_DATA_SIZE];
+       } dat_page_0;
+       struct st_data *st = st_data[unit];
+
+       /*
+        * Define what sort of structure we're working with
+        */
+       if (st->quirks & ST_Q_NEEDS_PAGE_0) {
                dat_len = sizeof(dat_page_0);
                dat_ptr = (char *) &dat_page_0;
                dat_len = sizeof(dat_page_0);
                dat_ptr = (char *) &dat_page_0;
-       }
-       else
-       {
+       } else {
                dat_len = sizeof(dat);
                dat_ptr = (char *) &dat;
        }
                dat_len = sizeof(dat);
                dat_ptr = (char *) &dat;
        }
-               
-       /*******************************************************\
-       * Set up for a mode select                              *
-       \*******************************************************/
+       /*
+        * Set up for a mode select
+        */
        bzero(dat_ptr, dat_len);
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = MODE_SELECT;
        scsi_cmd.length = dat_len;
        bzero(dat_ptr, dat_len);
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = MODE_SELECT;
        scsi_cmd.length = dat_len;
-       ((struct dat *)dat_ptr)->header.blk_desc_len = sizeof(struct  blk_desc);
-       ((struct dat *)dat_ptr)->header.dev_spec |= SMH_DSP_BUFF_MODE_ON;
-       ((struct dat *)dat_ptr)->blk_desc.density = st->density;
-       if(st->flags & ST_FIXEDBLOCKS)
-       {
-               lto3b( st->blksiz , ((struct dat *)dat_ptr)->blk_desc.blklen);
+       ((struct dat *) dat_ptr)->header.blk_desc_len = sizeof(struct blk_desc);
+       ((struct dat *) dat_ptr)->header.dev_spec |= SMH_DSP_BUFF_MODE_ON;
+       ((struct dat *) dat_ptr)->blk_desc.density = st->density;
+       if (st->flags & ST_FIXEDBLOCKS) {
+               lto3b(st->blksiz, ((struct dat *) dat_ptr)->blk_desc.blklen);
        }
        }
-       if (st->quirks & ST_Q_NEEDS_PAGE_0)
-       {
-               bcopy(st->sense_data, ((struct dat_page_0 *)dat_ptr)->sense_data, 
-                       sizeof(((struct dat_page_0 *)dat_ptr)->sense_data));
-                       /* the Tandberg tapes need the block size to */
-                       /* be set on each mode sense/select. */
+       if (st->quirks & ST_Q_NEEDS_PAGE_0) {
+               bcopy(st->sense_data, ((struct dat_page_0 *) dat_ptr)->sense_data,
+                   sizeof(((struct dat_page_0 *) dat_ptr)->sense_data));
+               /* the Tandberg tapes need the block size to */
+               /* be set on each mode sense/select. */
        }
        }
-       /*******************************************************\
-       * do the command                                        *
-       \*******************************************************/
-       return (st_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       dat_ptr,
-                       dat_len,
-                       5000,
-                       NULL,
-                       flags | SCSI_DATA_OUT) );
+       /*
+        * do the command
+        */
+       return (scsi_scsi_cmd(st->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               (u_char *) dat_ptr,
+               dat_len,
+               ST_RETRIES,
+               5000,
+               NULL,
+               flags | SCSI_DATA_OUT));
 }
 
 }
 
-/*******************************************************\
-* skip N blocks/filemarks/seq filemarks/eom            *
-\*******************************************************/
-st_space(unit,number,what,flags)
-int    unit,number,what,flags;
+/*
+ * skip N blocks/filemarks/seq filemarks/eom
+ */
+errval 
+st_space(unit, number, what, flags)
+       u_int32 unit, what, flags;
+       int32   number;
 {
 {
-       int error;
+       errval  error;
        struct scsi_space scsi_cmd;
        struct scsi_space scsi_cmd;
-       struct  st_data *st = st_data[unit];
-
-       /*******************************************************\
-       * If we're at beginning of medium, now is the time to   *
-       * set medium access density, fixed or variable-blocks   *
-       * and, if fixed, the block size.                        *
-       \*******************************************************/
-       if (st->flags & ST_AT_BOM &&
-           (error = st_decide_mode(unit, TRUE)))
-               return (error);
+       struct st_data *st = st_data[unit];
 
 
-       switch (what)
-       {
-       case    SP_BLKS:
-               if (st->flags & ST_PER_ACTION)
-               {
-                       if (number > 0)
-                       {
+       switch (what) {
+       case SP_BLKS:
+               if (st->flags & ST_PER_ACTION) {
+                       if (number > 0) {
                                st->flags &= ~ST_PER_ACTION;
                                st->flags &= ~ST_PER_ACTION;
-                               return(EIO);
-                       }
-                       else if (number < 0)
-                       {
-                               if (st->flags & ST_AT_FILEMARK)
-                               {
-                                       /*******************************\
-                                       * Handling of ST_AT_FILEMARK    *
-                                       * in st_space will fill in the  *
-                                       * right file mark count.        *
-                                       \*******************************/
+                               return (EIO);
+                       } else if (number < 0) {
+                               if (st->flags & ST_AT_FILEMARK) {
+                                       /*
+                                        * Handling of ST_AT_FILEMARK
+                                        * in st_space will fill in the
+                                        * right file mark count.
+                                        */
                                        error = st_space(unit, 0, SP_FILEMARKS,
                                            flags);
                                        error = st_space(unit, 0, SP_FILEMARKS,
                                            flags);
-                                       if (error) return(error);
+                                       if (error)
+                                               return (error);
                                }
                                }
-                               if (st->flags & ST_BLANK_READ)
-                               {
+                               if (st->flags & ST_BLANK_READ) {
                                        st->flags &= ~ST_BLANK_READ;
                                        st->flags &= ~ST_BLANK_READ;
-                                       return(EIO);
+                                       return (EIO);
                                }
                                st->flags &= ~ST_EIO_PENDING;
                        }
                }
                break;
                                }
                                st->flags &= ~ST_EIO_PENDING;
                        }
                }
                break;
-       case    SP_FILEMARKS:
-               if (st->flags & ST_EIO_PENDING)
-               {
-                       if (number > 0)
-                       {
+       case SP_FILEMARKS:
+               if (st->flags & ST_EIO_PENDING) {
+                       if (number > 0) {       /* pretend we just discover the error */
                                st->flags &= ~ST_EIO_PENDING;
                                st->flags &= ~ST_EIO_PENDING;
-                               return(EIO);
-                       }
-                       else if (number < 0)
+                               return (EIO);
+                       } else if (number < 0) {        /* back away from the error */
                                st->flags &= ~ST_EIO_PENDING;
                                st->flags &= ~ST_EIO_PENDING;
+                       }
                }
                }
-               if (st->flags & ST_AT_FILEMARK)
-               {
+               if (st->flags & ST_AT_FILEMARK) {
                        st->flags &= ~ST_AT_FILEMARK;
                        number--;
                }
                        st->flags &= ~ST_AT_FILEMARK;
                        number--;
                }
-               if (st->flags & ST_BLANK_READ && number < 0)
-               {
+               if ((st->flags & ST_BLANK_READ) && (number < 0)) {      /* back away from unwritten tape */
                        st->flags &= ~ST_BLANK_READ;
                        st->flags &= ~ST_BLANK_READ;
-                       number++;
+                       number++;       /* dubious */
                }
        }
                }
        }
-       if (number == 0)
-               return(ESUCCESS);
+       if (number == 0) {
+               return (ESUCCESS);
+       }
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = SPACE;
        scsi_cmd.byte2 = what & SS_CODE;
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = SPACE;
        scsi_cmd.byte2 = what & SS_CODE;
-       lto3b(number,scsi_cmd.number);
-       return (st_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       0,
-                       0,
-                       600000, /* 10 mins enough? */
-                       NULL,
-                       flags));
+       lto3b(number, scsi_cmd.number);
+       return (scsi_scsi_cmd(st->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               0,
+               0,
+               0,              /* no retries please , just fail */
+               600000,         /* 10 mins enough? */
+               NULL,
+               flags));
 }
 }
-/*******************************************************\
-* write N filemarks                                    *
-\*******************************************************/
-st_write_filemarks(unit,number,flags)
-int    unit,number,flags;
+
+/*
+ * write N filemarks
+ */
+errval 
+st_write_filemarks(unit, number, flags)
+       u_int32 unit, flags;
+       int32   number;
 {
 {
-       int error;
        struct scsi_write_filemarks scsi_cmd;
        struct scsi_write_filemarks scsi_cmd;
-       struct  st_data *st = st_data[unit];
-
-       /*******************************************************\
-       * It's hard to write a negative number of file marks.   *
-       * Don't try.                                            *
-       \*******************************************************/
-       if (number < 0)
-               return (EINVAL);
-
-       /*******************************************************\
-       * If we're at beginning of medium, now is the time to   *
-       * set medium access density, fixed or variable-blocks   *
-       * and, if fixed, the block size.                        *
-       \*******************************************************/
-       if (st->flags & ST_AT_BOM && number > 0 &&
-           (error = st_decide_mode(unit, FALSE)))
-               return (error);
+       struct st_data *st = st_data[unit];
 
 
-       switch (number)
-       {
-       case    0:      /* really a command to sync the drive's buffers */
+       /*
+        * It's hard to write a negative number of file marks.
+        * Don't try.
+        */
+       if (number < 0) {
+               return EINVAL;
+       }
+       switch (number) {
+       case 0:         /* really a command to sync the drive's buffers */
                break;
                break;
-       case    1:
-               if (st->flags & ST_FM_WRITTEN)
+       case 1:
+               if (st->flags & ST_FM_WRITTEN) {        /* already have one down */
                        st->flags &= ~ST_WRITTEN;
                        st->flags &= ~ST_WRITTEN;
-               else
+               } else {
                        st->flags |= ST_FM_WRITTEN;
                        st->flags |= ST_FM_WRITTEN;
+               }
                st->flags &= ~ST_PER_ACTION;
                break;
        default:
                st->flags &= ~(ST_PER_ACTION | ST_WRITTEN);
        }
                st->flags &= ~ST_PER_ACTION;
                break;
        default:
                st->flags &= ~(ST_PER_ACTION | ST_WRITTEN);
        }
-
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = WRITE_FILEMARKS;
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = WRITE_FILEMARKS;
-       lto3b(number,scsi_cmd.number);
-       return (st_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       0,
-                       0,
-                       100000, /* 10 secs.. (may need to repos head )*/
-                       NULL,
-                       flags) );
+       lto3b(number, scsi_cmd.number);
+       return scsi_scsi_cmd(st->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               0,
+               0,
+               0,              /* no retries, just fail */
+               100000,         /* 10 secs.. (may need to repos head ) */
+               NULL,
+               flags);
 }
 
 }
 
-/***************************************************************\
-* Make sure the right number of file marks is on tape if the   *
-* tape has been written.  If the position argument is true,    *
-* leave the tape positioned where it was originally.           *
-*                                                              *
-* nmarks returns the number of marks to skip (or, if position  *
-* true, which were skipped) to get back original position.     *
-\***************************************************************/
+/*
+ * Make sure the right number of file marks is on tape if the
+ * tape has been written.  If the position argument is true,
+ * leave the tape positioned where it was originally.
+ *
+ * nmarks returns the number of marks to skip (or, if position
+ * true, which were skipped) to get back original position.
+ */
+int32 
 st_chkeod(unit, position, nmarks, flags)
 st_chkeod(unit, position, nmarks, flags)
-int    unit;
-int    position;
-int    *nmarks;
-int    flags;
+       u_int32 unit;
+       boolean position;
+       int32  *nmarks;
+       u_int32 flags;
 {
 {
-       int     error;
-       struct  st_data *st = st_data[unit];
+       errval  error;
+       struct st_data *st = st_data[unit];
 
 
-       switch (st->flags & (ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD))
-       {
+       switch (st->flags & (ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD)) {
        default:
                *nmarks = 0;
        default:
                *nmarks = 0;
-               return(ESUCCESS);
-       case    ST_WRITTEN:
-       case    ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD:
+               return (ESUCCESS);
+       case ST_WRITTEN:
+       case ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD:
                *nmarks = 1;
                break;
                *nmarks = 1;
                break;
-       case    ST_WRITTEN | ST_2FM_AT_EOD:
+       case ST_WRITTEN | ST_2FM_AT_EOD:
                *nmarks = 2;
        }
        error = st_write_filemarks(unit, *nmarks, flags);
                *nmarks = 2;
        }
        error = st_write_filemarks(unit, *nmarks, flags);
-       if (position && error == ESUCCESS)
+       if (position && (error == ESUCCESS))
                error = st_space(unit, -*nmarks, SP_FILEMARKS, flags);
        return (error);
 }
 
                error = st_space(unit, -*nmarks, SP_FILEMARKS, flags);
        return (error);
 }
 
-/*******************************************************\
-* load/unload (with retension if true)                 *
-\*******************************************************/
-st_load(unit,type,flags)
-int    unit,type,flags;
+/*
+ * load/unload (with retension if true)
+ */
+errval 
+st_load(unit, type, flags)
+       u_int32 unit, type, flags;
 {
 {
-       struct  scsi_load  scsi_cmd;
-       struct  st_data *st = st_data[unit];
+       struct scsi_load scsi_cmd;
+       struct st_data *st = st_data[unit];
+       struct scsi_link *sc_link = st->sc_link;
 
 
-       st->flags &= ~ST_PER_MEDIA;
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        bzero(&scsi_cmd, sizeof(scsi_cmd));
-       if (type == LD_LOAD)
-       {
-               /*scsi_cmd.how |= LD_RETEN;*/
-               st->flags |= ST_AT_BOM;
-       }
-       else
-       {
-               int     error, nmarks;
+       if (type != LD_LOAD) {
+               errval  error;
+               int32   nmarks;
 
                error = st_chkeod(unit, FALSE, &nmarks, flags);
 
                error = st_chkeod(unit, FALSE, &nmarks, flags);
-               if (error != ESUCCESS) return(error);
-               st->flags &= ~ST_INFO_VALID;
+               if (error != ESUCCESS)
+                       return (error);
+               sc_link->flags &= ~SDEV_MEDIA_LOADED;
        }
        }
-       if(st->quirks & ST_Q_IGNORE_LOADS) return(0);
+       if (st->quirks & ST_Q_IGNORE_LOADS)
+               return (0);
        scsi_cmd.op_code = LOAD_UNLOAD;
        scsi_cmd.how |= type;
        scsi_cmd.op_code = LOAD_UNLOAD;
        scsi_cmd.how |= type;
-       return (st_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       0,
-                       0,
-                       300000, /* 5 min */
-                       NULL,
-                       flags));
+       return (scsi_scsi_cmd(st->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               0,
+               0,
+               ST_RETRIES,
+               300000,         /* 5 min */
+               NULL,
+               flags));
 }
 }
-/*******************************************************\
-* Prevent or allow the user to remove the tape         *
-\*******************************************************/
-st_prevent(unit,type,flags)
-int    unit,type,flags;
-{
-       struct  scsi_prevent    scsi_cmd;
-
-       if (type == PR_ALLOW)
-       {
-               int     error, nmarks;
 
 
-               error = st_chkeod(unit, TRUE, &nmarks, flags);
-               if (error != ESUCCESS) return(error);
-               st_data[unit]->flags &= ~ST_INFO_VALID;
-       }
-       bzero(&scsi_cmd, sizeof(scsi_cmd));
-       scsi_cmd.op_code = PREVENT_ALLOW;
-       scsi_cmd.how=type;
-       return (st_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       0,
-                       0,
-                       5000,
-                       NULL,
-                       flags));
-}
-/*******************************************************\
-*  Rewind the device                                   *
-\*******************************************************/
-st_rewind(unit,immed,flags)
-int    unit,immed,flags;
+/*
+ *  Rewind the device
+ */
+errval 
+st_rewind(unit, immed, flags)
+       u_int32 unit, flags;
+       boolean immed;
 {
 {
-       struct  scsi_rewind     scsi_cmd;
-       struct  st_data *st = st_data[unit];
-       int     error, nmarks;
+       struct scsi_rewind scsi_cmd;
+       struct st_data *st = st_data[unit];
+       errval  error;
+       int32   nmarks;
 
        error = st_chkeod(unit, FALSE, &nmarks, flags);
 
        error = st_chkeod(unit, FALSE, &nmarks, flags);
-       if (error != ESUCCESS) return(error);
+       if (error != ESUCCESS)
+               return (error);
        st->flags &= ~ST_PER_ACTION;
        st->flags &= ~ST_PER_ACTION;
-       st->flags |= ST_AT_BOM;
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = REWIND;
        scsi_cmd.byte2 = immed ? SR_IMMED : 0;
        bzero(&scsi_cmd, sizeof(scsi_cmd));
        scsi_cmd.op_code = REWIND;
        scsi_cmd.byte2 = immed ? SR_IMMED : 0;
-       return (st_scsi_cmd(unit,
-                       &scsi_cmd,
-                       sizeof(scsi_cmd),
-                       0,
-                       0,
-                       immed?5000:300000, /* 5 sec or 5 min */
-                       NULL,
-                       flags));
-}
-
-/***************************************************************\
-* ststart 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  *
-* transfer in the buf. The transfer request will call st_done  *
-* on completion, which will in turn call this routine again    *
-* so that the next queued transfer is performed.               *
-* The bufs are queued by the strategy routine (ststrategy)     *
-*                                                              *
-* This routine is also called after other non-queued requests  *
-* have been made of the scsi driver, to ensure that the queue  *
-* continues to be drained.                                     *
-\***************************************************************/
-/* ststart() is called at splbio */
-ststart(unit)
-{
-       int                     drivecount;
-       register struct buf     *bp = 0;
-       register struct buf     *dp;
-       struct  scsi_rw_tape    cmd;
-       int                     blkno, nblk;
-       struct  st_data         *st = st_data[unit];
-       int                     flags;
-
-
-
-#ifdef STDEBUG
-       if(scsi_debug & PRINTROUTINES) printf("ststart%d ",unit);
-#endif /*STDEBUG*/
-       /*******************************************************\
-       * See if there is a buf to do and we are not already    *
-       * doing one                                             *
-       \*******************************************************/
-       if(st->scsi_xfer.flags & INUSE)
-       {
-               return;    /* unit already underway */
-       }
-trynext:
-       if(st->xfer_block_wait) /* a special awaits, let it proceed first */
-       {
-               wakeup(&(st->xfer_block_wait));
-               return;
-       }
-
-       if ((bp = st->buf_queue) == NULL)
-       {
-               return; /* no work to bother with */
-       }
-       st->buf_queue = bp->b_actf;
-
-
-
-       /*******************************************************\
-       * only FIXEDBLOCK devices have pending operations       *
-       \*******************************************************/
-       if(st->flags & ST_FIXEDBLOCKS)
-       {
-               /*******************************************************\
-               *  If we are at a filemark but have not reported it yet *
-               * then we should report it now                          *
-               \*******************************************************/
-               if(st->flags & ST_AT_FILEMARK)
-               {
-                       if ((bp->b_flags & B_READ) == B_WRITE)
-                       {
-                               /***************************************\
-                               * Handling of ST_AT_FILEMARK in         *
-                               * st_space will fill in the right file  *
-                               * mark count.                           *
-                               \***************************************/
-                               if (st_space(unit, 0, SP_FILEMARKS, 0) !=
-                                   ESUCCESS) goto badnews;
-                       }
-                       else
-                       {
-                               bp->b_resid = bp->b_bcount;
-                               bp->b_error = 0;
-                               bp->b_flags &= ~B_ERROR;
-                               st->flags &= ~ST_AT_FILEMARK;
-                               biodone(bp);
-                               goto trynext;
-                       }
-               }
-               /*******************************************************\
-               *  If we are at EIO (e.g. EOM) but have not reported it *
-               * yet then we should report it now                      *
-               \*******************************************************/
-               if(st->flags & ST_EIO_PENDING)
-               {
-                       bp->b_resid = bp->b_bcount;
-                       bp->b_error = EIO;
-                       bp->b_flags |= B_ERROR;
-                       st->flags &= ~ST_EIO_PENDING;
-                       biodone(bp);
-                       goto trynext;
-               }
-       }
-       /*******************************************************\
-       *  Fill out the scsi command                            *
-       \*******************************************************/
-       bzero(&cmd, sizeof(cmd));
-       if((bp->b_flags & B_READ) == B_WRITE)
-       {
-               cmd.op_code = WRITE_COMMAND_TAPE;
-               st->flags &= ~ST_FM_WRITTEN;
-               st->flags |= ST_WRITTEN;
-               flags = SCSI_DATA_OUT;
-       }
-       else
-       {
-               cmd.op_code = READ_COMMAND_TAPE;
-               flags = SCSI_DATA_IN;
-       }
-
-       /*******************************************************\
-       * Handle "fixed-block-mode" tape drives by using the    *
-       * block count instead of the length.                    *
-       \*******************************************************/
-       if(st->flags & ST_FIXEDBLOCKS)
-       {
-               cmd.byte2 |= SRWT_FIXED;
-               lto3b(bp->b_bcount/st->blksiz,cmd.len);
-       }
-       else
-       {
-               lto3b(bp->b_bcount,cmd.len);
-       }
-
-       /*******************************************************\
-       * go ask the adapter to do all this for us              *
-       \*******************************************************/
-       if (st_scsi_cmd(unit,
-                       &cmd,
-                       sizeof(cmd),
-                       (u_char *)bp->b_un.b_addr,
-                       bp->b_bcount,
-                       100000,
-                       bp,
-                       flags | SCSI_NOSLEEP ) != SUCCESSFULLY_QUEUED)
-
-       {
-badnews:
-               printf("st%d: oops not queued\n",unit);
-               bp->b_flags |= B_ERROR;
-               bp->b_error = EIO;
-               biodone(bp);
-               return;
-       }
-       stqueues++;
+       return (scsi_scsi_cmd(st->sc_link,
+               (struct scsi_generic *) &scsi_cmd,
+               sizeof(scsi_cmd),
+               0,
+               0,
+               ST_RETRIES,
+               immed ? 5000 : 300000,  /* 5 sec or 5 min */
+               NULL,
+               flags));
 }
 
 }
 
-/*******************************************************\
-* This routine is called by the scsi interrupt when    *
-* the transfer is complete.
-\*******************************************************/
-int    st_done(unit,xs)
-int    unit;
-struct scsi_xfer       *xs;
-{
-       struct  buf             *bp;
-       int     retval;
-       struct  st_data *st = st_data[unit];
-
-#ifdef STDEBUG
-       if(scsi_debug & PRINTROUTINES) printf("st_done%d ",unit);
-#endif /*STDEBUG*/
-#ifdef PARANOID
-       if (! (xs->flags & INUSE))
-               panic("scsi_xfer not in use!");
-#endif /*PARANOID*/
-       if((bp = xs->bp)== NULL)
-       {
-               wakeup(xs);
-               return;
-       }
-       switch(xs->error)
-       {
-       case    XS_NOERROR:
-               bp->b_flags &= ~B_ERROR;
-               bp->b_error = 0;
-               bp->b_resid = 0;
-               break;
-       case    XS_SENSE:
-               retval = (st_interpret_sense(unit,xs));
-               bp->b_resid = xs->resid; /* already multiplied by blksiz */
-               if(retval)
-               {
-                       /***************************************\
-                       * We have a real error, the bit should  *
-                       * be set to indicate this. The return   *
-                       * value will contain the unix error code*
-                       * that the error interpretation routine *
-                       * thought was suitable, so pass this    *
-                       * value back in the buf structure.      *
-                       * Furthermore we return information     *
-                       * saying that no data was transferred   *
-                       * All status is now suspect             *
-                       \***************************************/
-                       bp->b_flags |= B_ERROR;
-                       bp->b_error = retval;
-                       bp->b_resid =  bp->b_bcount;
-                       st->flags &= ~ST_PER_ACTION;
-               }
-               else
-               {
-               /***********************************************\
-               * The error interpretation code has declared    *
-               * that it wasn't a real error, or at least that *
-               * we should be ignoring it if it was.           *
-               \***********************************************/
-                   if(xs->resid == 0)
-                   {
-                       /***************************************\
-                       * we apparently had a corrected error   *
-                       * or something.                         *
-                       * pretend the error never happenned     *
-                       \***************************************/
-                       bp->b_flags &= ~B_ERROR;
-                       bp->b_error = 0;
-                       break;
-                   }
-                   if ( xs->resid != xs->datalen )
-                   {
-                       /***************************************\
-                       * Here we have the tricky part..        *
-                       * We successfully read less data than   *
-                       * we requested. (but not 0)             *
-                       *------for variable blocksize tapes:----*
-                       * UNDER 386BSD:                         *
-                       * We should legitimatly have the error  *
-                       * bit set, with the error value set to  *
-                       * zero.. This is to indicate to the     *
-                       * physio code that while we didn't get  *
-                       * as much information as was requested, *
-                       * we did reach the end of the record    *
-                       * and so physio should not call us      *
-                       * again for more data... we have it all *
-                       * SO SET THE ERROR BIT!                 *
-                       *                                       *
-                       * UNDER NetBSD:                         *
-                       * To indicate the same as above, we     *
-                       * need only have a non 0 resid that is  *
-                       * less than the b_bcount, but the       *
-                       * ERROR BIT MUST BE CLEAR! (sigh)       *
-                       *                                       *
-                       *-------for fixed blocksize device------*
-                       * We read some successful records       *
-                       * before hitting the EOF or EOT. These  *
-                       * must be passed to the user, before we *
-                       * report the EOx.  We will report the   *
-                       * EOx NEXT time.                        *
-                       \***************************************/
-#ifdef NETBSD 
-                       bp->b_flags &= ~B_ERROR;
+#ifdef NETBSD
+#define        SIGNAL_SHORT_READ
 #else
 #else
-                       bp->b_flags |= B_ERROR;
-#endif 
-                       bp->b_error = 0;
-                       xs->error = XS_NOERROR;
-                       break;
-                   }
-                   else
-                   {
-                       /***************************************\
-                       * We have come out of the error handler *
-                       * with no error code.  We have also not *
-                       * transferred any data (would have gone *
-                       * to the previous clause).              *
-                       * This must be an EOF                   *
-                       *  Any caller request to read no        *
-                       * data would have been short-circuited  *
-                       * at st_read or ststrategy.             *
-                       *                                       *
-                       * At least all o/s agree that:          *
-                       * 0 bytes read with no error is EOF     *
-                       \***************************************/
-
-                       bp->b_error = 0;
-                       bp->b_flags &= ~B_ERROR;
-                       st->flags &= ~ST_AT_FILEMARK;
-                       break;
-                   }
-               }
-               break;
-
-       case    XS_TIMEOUT:
-               printf("st%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->flags &= ~ITSDONE;
-                       xs->error = XS_NOERROR;
-                       if ( (*(st->sc_sw->scsi_cmd))(xs)
-                               == SUCCESSFULLY_QUEUED)
-                       {       /* don't wake the job, ok? */
-                               return;
-                       }
-                       printf("st%d: device busy\n",unit);
-                       xs->flags |= ITSDONE;
-               }
-
-       case    XS_DRIVER_STUFFUP:
-               bp->b_flags |= B_ERROR;
-               bp->b_error = EIO;
-               break;
-       default:
-               printf("st%d: unknown error category from scsi driver\n"
-                       ,unit);
-       }       
-       biodone(bp);
-       xs->flags = 0;  /* no longer in use */
-       ststart(unit);          /* If there's another waiting.. do it */
-}
-
-
+#define        SIGNAL_SHORT_READ bp->b_flags |= B_ERROR;
+#endif
 
 
-/*******************************************************\
-* ask the scsi driver to perform a command for us.     *
-* 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.                                     *
-* Also tell it where to read/write the data, and how   *
-* long the data is supposed to be                      *
-\*******************************************************/
-int    st_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,bp,flags)
-
-int    unit,flags;
-struct scsi_generic *scsi_cmd;
-int    cmdlen;
-int    timeout;
-u_char *data_addr;
-struct buf *bp;
-int    datalen;
+/*
+ * Look at the returned sense and act on the error and detirmine
+ * The unix error number to pass back... (0 = report no error)
+ *                            (-1 = continue processing)
+ */
+errval 
+st_interpret_sense(xs)
+       struct scsi_xfer *xs;
 {
 {
-       struct  scsi_xfer *xs;
-       int     retval;
-       int     s;
-       struct  st_data *st = st_data[unit];
-
-#ifdef STDEBUG
-       if(scsi_debug & PRINTROUTINES) printf("\nst_scsi_cmd%d ",unit);
-#endif /*STDEBUG*/
-#ifdef PARANOID
-       if(st->sc_sw == NULL)   /* If we have no scsi driver */
-       {
-               printf("st%d: not set up\n",unit);
-               return(EINVAL);
+       struct scsi_link *sc_link = xs->sc_link;
+       struct scsi_sense_data *sense = &(xs->sense);
+       boolean silent = xs->flags & SCSI_SILENT;
+       struct buf *bp = xs->bp;
+       u_int32 unit = sc_link->dev_unit;
+       struct st_data *st = st_data[unit];
+       u_int32 key;
+       int32   info;
+
+       /*
+        * Get the sense fields and work out what code
+        */
+       if (sense->error_code & SSD_ERRCODE_VALID) {
+               info = ntohl(*((int32 *) sense->ext.extended.info));
+       } else {
+               info = xs->datalen;     /* bad choice if fixed blocks */
        }
        }
-#endif /*PARANOID*/
-
-       xs = &(st->scsi_xfer);
-       if(!(flags & SCSI_NOMASK))
-               s = splbio();
-       st->xfer_block_wait++;  /* there is someone waiting */
-       while (xs->flags & INUSE)
-       {
-               if(flags & SCSI_NOSLEEP)
-                       return EBUSY;
-               sleep(&(st->xfer_block_wait),PRIBIO+1);
+       if ((sense->error_code & SSD_ERRCODE) != 0x70) {
+               return (-1);    /* let the generic code handle it */
        }
        }
-       st->xfer_block_wait--;
-       xs->flags = INUSE;
-       if(!(flags & SCSI_NOMASK))
-               splx(s);
-
-       /*******************************************************\
-       * Fill out the scsi_xfer structure                      *
-       \*******************************************************/
-       xs->flags       |=      flags;
-       xs->adapter     =       st->ctlr;
-       xs->targ        =       st->targ;
-       xs->lu          =       st->lu;
-       xs->retries     =       bp?0:ST_RETRIES;/*can't retry on IO*/
-       xs->timeout     =       timeout;
-       xs->cmd         =       scsi_cmd;
-       xs->cmdlen      =       cmdlen;
-       xs->data        =       data_addr;
-       xs->datalen     =       datalen;
-       xs->resid       =       datalen;
-       xs->when_done   =       st_done;
-       xs->done_arg    =       unit;
-       xs->done_arg2   =       (int)xs;
-       xs->bp          =       bp;
-retry: xs->error       =       XS_NOERROR;
-
-       /***********************************************\
-       * Ask the adapter to do the command for us      *
-       \***********************************************/
-       retval = (*(st->sc_sw->scsi_cmd))(xs);
-
-       /***********************************************\
-       * IO operations are handled differently..       *
-       * Physio does the sleep, and error handling is  *
-       * Done in st_done at interrupt time             *
-       \***********************************************/
-       if(bp) return retval;   
-
-       /***********************************************\
-       * Wait for the result if queued, or handle the  *
-       * error if it was rejected..                    *
-       \***********************************************/
-       switch(retval)
-       {
-       case    SUCCESSFULLY_QUEUED:
-               s = splbio();
-               while(!(xs->flags & ITSDONE))
-                       sleep(xs,PRIBIO+1);
-               splx(s);
-               /*******************************\
-               * finished.. check for failure  *
-               * Fall through......            *
-               \*******************************/
-       case    HAD_ERROR:
-       case    COMPLETE:
-               switch(xs->error)
-               {
-               case    XS_NOERROR:
-                       retval = ESUCCESS;
-                       break;
-               case    XS_SENSE:
-                       retval = (st_interpret_sense(unit,xs));
-                       /* only useful for reads *//* why did I say that?*/
-                       if (retval)
-                       { /* error... don't care about filemarks */
-                               st->flags &= ~ST_PER_ACTION;
-                       }
-                       else
-                       {
-                               xs->error = XS_NOERROR;
-                               retval = ESUCCESS;
+       if (st->flags & ST_FIXEDBLOCKS) {
+               xs->resid = info * st->blksiz;
+               if (sense->ext.extended.flags & SSD_EOM) {
+                       st->flags |= ST_EIO_PENDING;
+                       if (bp) {
+                               bp->b_resid = xs->resid;
+                               SIGNAL_SHORT_READ
                        }
                        }
-                       break;
-               case    XS_DRIVER_STUFFUP:
-                       retval = EIO;
-                       break;
-               case    XS_BUSY:
-                       /* should sleep 1 sec here */
-               case    XS_TIMEOUT:
-                       if(xs->retries-- )
-                       {
-                               xs->flags &= ~ITSDONE;
-                               goto retry;
-                       }
-                       retval = EIO;
-                       break;
-               default:
-                       retval = EIO;
-                       printf("st%d: unknown error category from scsi driver\n"
-                               ,unit);
-                       break;
-               }       
-               break;
-       case    TRY_AGAIN_LATER:
-               if(xs->retries-- )
-               {
-                       xs->flags &= ~ITSDONE;
-                       /* should delay here */
-                       goto retry;
                }
                }
-               retval = EIO;
-               break;
-       default:
-               retval = EIO;
-       }
-       xs->flags = 0;  /* it's free! */
-       ststart(unit);
-       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)  *
-\***************************************************************/
-
-int    st_interpret_sense(unit,xs)
-int    unit;
-struct scsi_xfer       *xs;
-{
-       struct  scsi_sense_data *sense;
-       int     key;
-       int     silent = xs->flags & SCSI_SILENT;
-       struct  st_data *st = st_data[unit];
-       int     info;
-       static char *error_mes[] = {            "soft error (corrected)",
-               "not ready",                    "medium error",
-               "non-media hardware failure",   "illegal request",
-               "unit attention",               "tape is write-protected",
-               "no data found",                "vendor unique",
-               "copy aborted",                 "command aborted",
-               "search returned equal",        "volume overflow",
-               "verify miscompare",            "unknown error key"
-       };
-
-       /***************************************************************\
-       * If errors are ok, report a success                            *
-       \***************************************************************/
-       if(xs->flags & SCSI_ERR_OK) return(ESUCCESS);
-
-       /***************************************************************\
-       * Get the sense fields and work out what code                   *
-       \***************************************************************/
-       sense = &(xs->sense);
-#ifdef STDEBUG
-       if(st_debug)
-       {
-               int count = 0;
-               printf("code%x valid%x\n"
-                               ,sense->error_code & SSD_ERRCODE
-                               ,sense->error_code & SSD_ERRCODE_VALID ? 1 : 0);
-               printf("seg%x key%x ili%x eom%x fmark%x\n"
-                               ,sense->ext.extended.segment
-                               ,sense->ext.extended.flags & SSD_KEY
-                               ,sense->ext.extended.flags & SSD_ILI ? 1 : 0
-                               ,sense->ext.extended.flags & SSD_EOM ? 1 : 0
-                               ,sense->ext.extended.flags & SSD_FILEMARK ? 1 : 0);
-               printf("info: %x %x %x %x followed by %d extra bytes\n"
-                               ,sense->ext.extended.info[0]
-                               ,sense->ext.extended.info[1]
-                               ,sense->ext.extended.info[2]
-                               ,sense->ext.extended.info[3]
-                               ,sense->ext.extended.extra_len);
-               printf("extra: ");
-               while(count < sense->ext.extended.extra_len)
-               {
-                       printf ("%x ",sense->ext.extended.extra_bytes[count++]);
+               if (sense->ext.extended.flags & SSD_FILEMARK) {
+                       st->flags |= ST_AT_FILEMARK;
+                       if (bp) {
+                               bp->b_resid = xs->resid;
+                               SIGNAL_SHORT_READ
+                       }
                }
                }
-               printf("\n");
-       }
-#endif /*STDEBUG*/
-       if(sense->error_code & SSD_ERRCODE_VALID)
-       {
-               info = ntohl(*((long *)sense->ext.extended.info));
-       }
-       else
-       {
-               info = xs->datalen; /* bad choice if fixed blocks */
-       }
-
-
-       switch(sense->error_code & SSD_ERRCODE)
-       {
-       /***************************************************************\
-       * If it's code 70, use the extended stuff and interpret the key *
-       \***************************************************************/
-       case 0x70:
-               if(st->flags & ST_FIXEDBLOCKS)
-               {
-                       xs->resid = info * st->blksiz;
-                       if(sense->ext.extended.flags & SSD_EOM)
-                       {
-                               st->flags |= ST_EIO_PENDING;
+               if (sense->ext.extended.flags & SSD_ILI) {
+                       st->flags |= ST_EIO_PENDING;
+                       if (bp) {
+                               bp->b_resid = xs->resid;
+                               SIGNAL_SHORT_READ
                        }
                        }
-                       if(sense->ext.extended.flags & SSD_FILEMARK)
-                       {
-                               st->flags |= ST_AT_FILEMARK;
+                       if (sense->error_code & SSD_ERRCODE_VALID &&
+                           !silent)
+                               printf("st%d: block wrong size"
+                                   ", %d blocks residual\n", unit
+                                   ,info);
+
+                       /*
+                        * This quirk code helps the drive read
+                        * the first tape block, regardless of
+                        * format.  That is required for these
+                        * drives to return proper MODE SENSE
+                        * information.
+                        */
+                       if ((st->quirks & ST_Q_SNS_HLP) &&
+                           !(sc_link->flags & SDEV_MEDIA_LOADED)) {
+                               st->blksiz -= 512;
                        }
                        }
-                       if(sense->ext.extended.flags & SSD_ILI)
-                       {
-                               st->flags |= ST_EIO_PENDING;
-                               if (sense->error_code & SSD_ERRCODE_VALID &&
-                                   !silent)
-                                       printf("st%d: %d-byte block wrong size"
-                                           "\n", unit, xs->datalen - info);
-
-                               /***************************************\
-                               * This quirk code helps the drive read  *
-                               * the first tape block, regardless of   *
-                               * format.  That is required for these   *
-                               * drives to return proper MODE SENSE    *
-                               * information.                          *
-                               \***************************************/
-                               if ((st->quirks & ST_Q_SNS_HLP) &&
-                                   !(st->flags & ST_INFO_VALID))
-                               {
-                                       st->blksiz -= 512;
-                               }
+               }
+               /*
+                * If no data was tranfered, do it immediatly
+                */
+               if (xs->resid >= xs->datalen) {
+                       if (st->flags & ST_EIO_PENDING) {
+                               return EIO;
                        }
                        }
-                       /***********************************************\
-                       * If no data was tranfered, do it immediatly    *
-                       \***********************************************/
-                       if(xs->resid >= xs->datalen)
-                       {
-                               if(st->flags & ST_EIO_PENDING) 
-                               {
-                                       return EIO;
-                               }
-                               if(st->flags & ST_AT_FILEMARK) 
-                               {
-                                       return 0;
+                       if (st->flags & ST_AT_FILEMARK) {
+                               if (bp) {
+                                       bp->b_resid = xs->resid;
+                                       SIGNAL_SHORT_READ
                                }
                                }
+                               return 0;
                        }
                }
                        }
                }
-               else
-               {
-                       xs->resid = xs->datalen; /* to be sure */
-                       if(sense->ext.extended.flags & SSD_EOM)
-                       {
-                               return(EIO);
+       } else {                /* must be variable mode */
+               xs->resid = xs->datalen;        /* to be sure */
+               if (sense->ext.extended.flags & SSD_EOM) {
+                       return (EIO);
+               }
+               if (sense->ext.extended.flags & SSD_FILEMARK) {
+                       if (bp)
+                               bp->b_resid = bp->b_bcount;
+                       return 0;
+               }
+               if (sense->ext.extended.flags & SSD_ILI) {
+                       if (info < 0) {
+                               /*
+                                * the record was bigger than the read
+                                */
+                               if (!silent)
+                                       printf("st%d: %d-byte record "
+                                           "too big\n", unit,
+                                           xs->datalen - info);
+                               return (EIO);
                        }
                        }
-                       if(sense->ext.extended.flags & SSD_FILEMARK)
-                       {
-                               return 0;
+                       xs->resid = info;
+                       if (bp) {
+                               bp->b_resid = info;
+                               SIGNAL_SHORT_READ
                        }
                        }
-                       if(sense->ext.extended.flags & SSD_ILI)
-                       {
-                               if(info < 0)
-                               /***************************************\
-                               * the record was bigger than the read   *
-                               \***************************************/
-                               {
-                                       if (!silent)
-                                               printf("st%d: %d-byte record "
-                                                   "too big\n", unit,
-                                                   xs->datalen - info);
-                                       return(EIO);
-                               }
-                               xs->resid = info;
+               }
+       }
+       key = sense->ext.extended.flags & SSD_KEY;
+
+       if (key == 0x8) {
+               /*
+                * This quirk code helps the drive read the
+                * first tape block, regardless of format.  That
+                * is required for these drives to return proper
+                * MODE SENSE information.
+                */
+               if ((st->quirks & ST_Q_SNS_HLP) &&
+                   !(sc_link->flags & SDEV_MEDIA_LOADED)) {    /* still starting */
+                       st->blksiz -= 512;
+               } else if (!(st->flags & (ST_2FM_AT_EOD | ST_BLANK_READ))) {
+                       st->flags |= ST_BLANK_READ;
+                       xs->resid = xs->datalen;
+                       if (bp) {
+                               bp->b_resid = xs->resid;
+                               /*return an EOF */
                        }
                        }
-               }/* there may be some other error. check the rest */
+                       return (ESUCCESS);
+               }
+       }
+       return (-1);            /* let the default/generic handler handle it */
+}
 
 
-               key=sense->ext.extended.flags & SSD_KEY;
+/*
+ * The quirk here is that the drive returns some value to st_mode_sense
+ * incorrectly until the tape has actually passed by the head.
+ *
+ * The method is to set the drive to large fixed-block state (user-specified
+ * density and 1024-byte blocks), then read and rewind to get it to sense the
+ * tape.  If that doesn't work, try 512-byte fixed blocks.  If that doesn't
+ * work, as a last resort, try variable- length blocks.  The result will be
+ * the ability to do an accurate st_mode_sense.
+ *
+ * We know we can do a rewind because we just did a load, which implies rewind.
+ * Rewind seems preferable to space backward if we have a virgin tape.
+ *
+ * The rest of the code for this quirk is in ILI processing and BLANK CHECK
+ * error processing, both part of st_interpret_sense.
+ */
+errval
+st_touch_tape(unit)
+       u_int32 unit;
+{
+       struct st_data *st = st_data[unit];
+       char   *buf;
+       u_int32 readsiz;
+       errval  errno;
 
 
-               if (!silent && key > 0 && (key != 0x8 ||
-                   st->flags & (ST_2FM_AT_EOD | ST_BLANK_READ)))
-               {
-                       printf("st%d: %s", unit, error_mes[key - 1]);
-                       if(sense->error_code & SSD_ERRCODE_VALID)
-                       {
-                               switch (key)
-                               {
-                               case    0x2:            /* NOT READY */
-                               case    0x5:            /* ILLEGAL REQUEST */
-                               case    0x6:            /* UNIT ATTENTION */
-                               case    0x7:            /* DATA PROTECT */
-                                       break;
-                               case    0x8:            /* BLANK CHECK */
-                                       printf(", requested size: %d (decimal)",
-                                           info);
-                                       break;
-                               default:
-                                       printf(", info = %d (decimal)", info);
-                               }
-                       }
-                       printf("\n");
-               }
+       buf = malloc(1024, M_TEMP, M_NOWAIT);
+       if (!buf)
+               return (ENOMEM);
 
 
-               switch (key)
-               {
-               case    0x0:                            /* NO SENSE */
-               case    0x1:                            /* RECOVERED ERROR */
-                       if(xs->resid == xs->datalen) xs->resid = 0;
-               case    0xc:                            /* EQUAL */
-                       return(ESUCCESS);
-               case    0x2:                            /* NOT READY */
-                       return(ENODEV);
-               case    0x5:                            /* ILLEGAL REQUEST */
-                       return(EINVAL);
-               case    0x6:                            /* UNIT ATTENTION */
-                       st->flags &= ~ST_PER_MEDIA;
-                       if (st->flags & ST_OPEN) /* TEMP!!!! */
-                               return(EIO);
-                       else
-                               return(ESUCCESS);
-               case    0x7:                            /* DATA PROTECT */
-                       return(EACCES);
-               case    0xd:                            /* VOLUME OVERFLOW */
-                       return(ENOSPC);
-               case    0x8:                            /* BLANK CHECK */
-                       /***********************************************\
-                       * This quirk code helps the drive read the      *
-                       * first tape block, regardless of format.  That *
-                       * is required for these drives to return proper *
-                       * MODE SENSE information.                       *
-                       \***********************************************/
-                       if ((st->quirks & ST_Q_SNS_HLP) &&
-                           !(st->flags & ST_INFO_VALID))
-                       {
-                               st->blksiz -= 512;
-                       }
-                       else if (!(st->flags & (ST_2FM_AT_EOD | ST_BLANK_READ)))
-                       {
-                               st->flags |= ST_BLANK_READ;
-                               xs->resid = xs->datalen;
-                               return(ESUCCESS);
-                       }
+       if (errno = st_mode_sense(unit, 0)) {
+               goto bad;
+       }
+       st->blksiz = 1024;
+       do {
+               switch (st->blksiz) {
+               case 512:
+               case 1024:
+                       readsiz = st->blksiz;
+                       st->flags |= ST_FIXEDBLOCKS;
+                       break;
                default:
                default:
-                       return(EIO);
+                       readsiz = 1;
+                       st->flags &= ~ST_FIXEDBLOCKS;
+               } if (errno = st_mode_select(unit, 0)) {
+                       goto bad;
                }
                }
-       /***************************************************************\
-       * If it's NOT code 70, just report it.                          *
-       \***************************************************************/
-       default:
-               if (!silent)
-               {
-                       printf("st%d: error code %d", unit,
-                               sense->error_code & SSD_ERRCODE);
-                       if(sense->error_code & SSD_ERRCODE_VALID)
-                       {
-                               printf(" at block no. %d (decimal)",
-                                       (sense->ext.unextended.blockhi << 16) +
-                                       (sense->ext.unextended.blockmed << 8) +
-                                       sense->ext.unextended.blocklow);
-                       }
-                       printf("\n");
+               st_read(unit, buf, readsiz, SCSI_SILENT);
+               if (errno = st_rewind(unit, FALSE, 0)) {
+bad:                   free(buf, M_TEMP);
+                       return (errno);
                }
                }
-               return(EIO);
-       }
+       } while (readsiz != 1 && readsiz > st->blksiz);
+       free(buf, M_TEMP);
+       return 0;
 }
 }
diff --git a/sys/scsi/su.c b/sys/scsi/su.c
new file mode 100644 (file)
index 0000000..de4f017
--- /dev/null
@@ -0,0 +1,4 @@
+
+/* this will be a special user scsi device */
+/* not written yet */
+
diff --git a/sys/scsi/uk.c b/sys/scsi/uk.c
new file mode 100644 (file)
index 0000000..5c48d01
--- /dev/null
@@ -0,0 +1,156 @@
+/* 
+ * Dummy driver for a device we can't identify.
+ * by Julian Elischer (julian@tfs.com)
+ *
+ *      $Id: uk.c,v 1.2 93/10/11 11:53:28 julian Exp Locker: julian $
+ */
+
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#define NUK 16
+
+/*
+ * This driver is so simple it uses all the default services
+ */
+struct scsi_device uk_switch =
+{
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    "uk",
+    0,
+    0, 0
+};
+
+struct uk_data {
+       u_int32 flags;
+       struct scsi_link *sc_link;      /* all the inter level info */
+} uk_data[NUK];
+
+#define UK_KNOWN       0x02
+
+static u_int32 next_uk_unit = 0;
+
+/*
+ * The routine called by the low level scsi routine when it discovers
+ * a device suitable for this driver.
+ */
+errval 
+ukattach(sc_link)
+       struct scsi_link *sc_link;
+{
+       u_int32 unit, i, stat;
+       unsigned char *tbl;
+
+       SC_DEBUG(sc_link, SDEV_DB2, ("ukattach: "));
+       /*
+        * Check we have the resources for another drive
+        */
+       unit = next_uk_unit++;
+       if (unit >= NUK) {
+               printf("Too many unknown devices..(%d > %d) reconfigure kernel\n",
+                               (unit + 1), NUK);
+               return (0);
+       }
+       /*
+        * Store information needed to contact our base driver
+        */
+       uk_data[unit].sc_link = sc_link;
+       sc_link->device = &uk_switch;
+       sc_link->dev_unit = unit;
+
+       printf("uk%d: unknown device\n", unit);
+       uk_data[unit].flags = UK_KNOWN;
+
+       return;
+
+}
+
+/*
+ *    open the device.
+ */
+errval 
+ukopen(dev)
+{
+       errval  errcode = 0;
+       u_int32 unit, mode;
+       struct scsi_link *sc_link;
+       unit = minor(dev);
+
+       /*
+        * Check the unit is legal 
+        */
+       if (unit >= NUK) {
+               printf("uk%d: uk %d  > %d\n", unit, unit, NUK);
+               return ENXIO;
+       }
+
+       /*
+        * Make sure the device has been initialised
+        */
+       if((uk_data[unit].flags & UK_KNOWN) == 0) {
+               printf("uk%d: not set up\n", unit);
+               return ENXIO;
+       }
+               
+       /*
+        * Only allow one at a time
+        */
+       sc_link = uk_data[unit].sc_link;
+       if (sc_link->flags & SDEV_OPEN) {
+               printf("uk%d: already open\n", unit);
+               return ENXIO;
+       }
+       sc_link->flags |= SDEV_OPEN;
+       SC_DEBUG(sc_link, SDEV_DB1, ("ukopen: dev=0x%x (unit %d (of %d))\n"
+               ,dev, unit, NUK));
+       /*
+        * Catch any unit attention errors.
+        */
+       return 0;
+}
+
+/*
+ * close the device.. only called if we are the LAST
+ * occurence of an open device
+ */
+errval 
+ukclose(dev)
+{
+       unsigned char unit, mode;
+       struct scsi_link *sc_link;
+
+       sc_link = uk_data[unit].sc_link;
+
+       SC_DEBUG(sc_link, SDEV_DB1, ("Closing device"));
+       sc_link->flags &= ~SDEV_OPEN;
+       return (0);
+}
+
+/*
+ * Perform special action on behalf of the user
+ * Only does generic scsi ioctls.
+ */
+errval 
+ukioctl(dev, cmd, arg, mode)
+       dev_t   dev;
+       u_int32 cmd;
+       caddr_t arg;
+{
+       unsigned char unit;
+       struct scsi_link *sc_link;
+
+       /*
+        * Find the device that the user is talking about
+        */
+       unit = minor(dev);
+       sc_link = uk_data[unit].sc_link;
+       return(scsi_do_ioctl(sc_link,cmd,arg,mode));
+}
+
index 0f8685e..6031683 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)buf.h 7.11 (Berkeley) 5/9/90
  * SUCH DAMAGE.
  *
  *     from: @(#)buf.h 7.11 (Berkeley) 5/9/90
- *     $Id: buf.h,v 1.2 1993/10/16 17:16:21 rgrimes Exp $
+ *     $Id: buf.h,v 1.3 1993/11/07 17:52:21 wollman Exp $
  */
 
 #ifndef _SYS_BUF_H_
  */
 
 #ifndef _SYS_BUF_H_
@@ -102,6 +102,8 @@ struct buf
        int     b_dirtyoff;             /* offset in buffer of dirty region */
        int     b_dirtyend;             /* offset of end of dirty region */
        caddr_t b_saveaddr;             /* original b_addr for PHYSIO */
        int     b_dirtyoff;             /* offset in buffer of dirty region */
        int     b_dirtyend;             /* offset of end of dirty region */
        caddr_t b_saveaddr;             /* original b_addr for PHYSIO */
+       void *  b_driver1;              /* for private use by the driver */
+       void *  b_driver2;              /* for private use by the driver */
 };
 
 #define        BQUEUES         4               /* number of free buffer queues */
 };
 
 #define        BQUEUES         4               /* number of free buffer queues */
@@ -178,6 +180,11 @@ void allocbuf(struct buf *, int);
 #define        B_CALL          0x200000        /* call b_iodone from iodone */
 #define        B_RAW           0x400000        /* set by physio for raw transfers */
 #define        B_NOCACHE       0x800000        /* do not cache block after use */
 #define        B_CALL          0x200000        /* call b_iodone from iodone */
 #define        B_RAW           0x400000        /* set by physio for raw transfers */
 #define        B_NOCACHE       0x800000        /* do not cache block after use */
+#define        B_DRIVER       0xF000000        /* Four bits for the driver to use */
+#define        B_DRIVER1      0x1000000        /* bits for the driver to use */
+#define        B_DRIVER2      0x2000000        /* bits for the driver to use */
+#define        B_DRIVER4      0x3000000        /* bits for the driver to use */
+#define        B_DRIVER8      0x4000000        /* bits for the driver to use */
 
 /*
  * Insq/Remq for the buffer hash lists.
 
 /*
  * Insq/Remq for the buffer hash lists.
index 1106e2f..10fa51d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 16 Feb 93   Julian Elischer         ADDED for SCSI system
  *
 /*
  * 16 Feb 93   Julian Elischer         ADDED for SCSI system
  *
- *     $Id$
+ *     $Id: chio.h,v 1.3 1993/10/16 17:16:27 rgrimes Exp $
  */
 
 /* This is a "convertet" mtio.h from 386BSD 
  */
 
 /* This is a "convertet" mtio.h from 386BSD 
@@ -11,8 +11,8 @@
 /*
  * Structures and definitions for changer io control commands
  */
 /*
  * Structures and definitions for changer io control commands
  */
-#ifndef _CHIO_H_
-#define _CHIO_H_
+#ifndef _SYS_CHIO_H_
+#define _SYS_CHIO_H_
 
 #define CH_INVERT              0x10000
 #define CH_ADDR_MASK           0xffff
 
 #define CH_INVERT              0x10000
 #define CH_ADDR_MASK           0xffff
@@ -88,4 +88,5 @@ struct chop {
 
 /* Changer IO control command */
 #define        CHIOOP  _IOWR('c', 1, struct chop)      /* do a mag tape op */
 
 /* Changer IO control command */
 #define        CHIOOP  _IOWR('c', 1, struct chop)      /* do a mag tape op */
-#endif
+
+#endif /*_SYS_CHIO_H*/
index d9dafd7..969c30f 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)mtio.h        7.6 (Berkeley) 2/5/91
  * SUCH DAMAGE.
  *
  *     from: @(#)mtio.h        7.6 (Berkeley) 2/5/91
- *     $Id: mtio.h,v 1.4 1993/10/16 17:17:16 rgrimes Exp $
+ *     $Id: mtio.h,v 1.5 1993/11/07 17:52:52 wollman Exp $
  */
 
 #ifndef _SYS_MTIO_H_
  */
 
 #ifndef _SYS_MTIO_H_
@@ -64,8 +64,7 @@ struct mtop {
 /* a non zero parameter will change the device to a fixed block size   */
 /* device with block size set to that of the parameter passed in.      */
 /* Resetting the block size to 0 will restore the device to a variable */
 /* a non zero parameter will change the device to a fixed block size   */
 /* device with block size set to that of the parameter passed in.      */
 /* Resetting the block size to 0 will restore the device to a variable */
-/* block size device.  At this time this command works across all modes        */ 
-/* unlike the density command below.. this may change                  */
+/* block size device. */
 
 #define MTSETBSIZ      10
 
 
 #define MTSETBSIZ      10
 
@@ -85,11 +84,16 @@ struct mtget {
 /* end device-dependent registers */
        short   mt_resid;       /* residual count */
 #if defined (__386BSD__)
 /* end device-dependent registers */
        short   mt_resid;       /* residual count */
 #if defined (__386BSD__)
-       daddr_t mt_bsiz;        /* block size, 0 is variable */
-       short   mt_dns_dflt;    /* density setting for default density */
-       short   mt_dns_dsty1;   /* density setting for high density */
-       short   mt_dns_dsty2;   /* density setting for medium density */
-       short   mt_dns_dsty3;   /* density setting for low density */
+       daddr_t mt_blksiz;      /* presently operatin blocksize */
+       daddr_t mt_density;     /* presently operatin density */
+       daddr_t mt_blksiz0;     /* blocksize for mode 0 */
+       daddr_t mt_blksiz1;     /* blocksize for mode 1 */
+       daddr_t mt_blksiz2;     /* blocksize for mode 2 */
+       daddr_t mt_blksiz3;     /* blocksize for mode 3 */
+       daddr_t mt_density0;    /* density for mode 0 */
+       daddr_t mt_density1;    /* density for mode 1 */
+       daddr_t mt_density2;    /* density for mode 2 */
+       daddr_t mt_density3;    /* density for mode 3 */
 #endif
 /* the following two are not yet implemented */
        daddr_t mt_fileno;      /* file number of current position */
 #endif
 /* the following two are not yet implemented */
        daddr_t mt_fileno;      /* file number of current position */
@@ -126,7 +130,7 @@ struct mtget {
 #define MTIOCEEOT      _IO('m', 4)                     /* enable EOT error */
 
 #ifndef KERNEL
 #define MTIOCEEOT      _IO('m', 4)                     /* enable EOT error */
 
 #ifndef KERNEL
-#define        DEFTAPE "/dev/rst0"
+#define        DEFTAPE "/dev/nrst0"
 #endif
 
 #ifdef KERNEL
 #endif
 
 #ifdef KERNEL
diff --git a/sys/sys/scsiio.h b/sys/sys/scsiio.h
new file mode 100644 (file)
index 0000000..05753e4
--- /dev/null
@@ -0,0 +1,63 @@
+
+#ifndef _SYS_SCSIIO_H_
+#define _SYS_SCSIIO_H_
+
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#define        SENSEBUFLEN 48
+
+typedef struct scsireq {
+       u_long  flags;          /* info about the request status and type */
+       u_long  timeout;
+       u_char  cmd[16];        /* 12 is actually the max */
+       u_char  cmdlen;
+       caddr_t databuf;        /* address in user space of buffer */
+       u_long  datalen;        /* size of user buffer (request) */
+       u_long  datalen_used;   /* size of user buffer (used)*/
+       u_char  sense[SENSEBUFLEN]; /* returned sense will be in here */
+       u_char  senselen;       /* sensedata request size (MAX of SENSEBUFLEN)*/
+       u_char  senselen_used;  /* return value only */
+       u_char  status;         /* what the scsi status was from the adapter */
+       u_char  retsts;         /* the return status for the command */
+       int     error;          /* error bits */
+} scsireq_t;
+
+/* bit defintions for flags */
+#define SCCMD_READ             0x00000001
+#define SCCMD_WRITE            0x00000002
+#define SCCMD_IOV              0x00000004
+#define SCCMD_ESCAPE           0x00000010
+#define SCCMD_TARGET           0x00000020
+
+
+/* definitions for the return status (retsts) */
+#define SCCMD_OK       0x00
+#define SCCMD_TIMEOUT  0x01
+#define SCCMD_BUSY     0x02
+#define SCCMD_SENSE    0x03
+#define SCCMD_UNKNOWN  0x04
+
+#define SCIOCCOMMAND   _IOWR('Q', 1, scsireq_t)
+
+#define SC_DB_CMDS     0x00000001      /* show all scsi cmds and errors */
+#define SC_DB_FLOW     0x00000002      /* show routines entered        */
+#define SC_DB_FLOW2    0x00000004      /* show path INSIDE routines    */
+#define SC_DB_DMA      0x00000008      /* show DMA segments etc        */
+#define SCIOCDEBUG     _IOW('Q', 2, int)       /* from 0 to 15 */
+
+struct scsi_addr {
+       int     scbus;          /* -1 if wildcard */
+       int     target;         /* -1 if wildcard */
+       int     lun;            /* -1 if wildcard */
+} ;
+
+#define SCIOCREPROBE   _IOW('Q', 3, struct scsi_addr) /* look for new devs */
+#define SCIOCIDENTIFY  _IOR('Q', 4, struct scsi_addr) /* where are you? */
+#define SCIOCDECONFIG  _IO('Q', 5)     /* please dissappear */
+#define SCIOCRECONFIG  _IO('Q', 6)     /* please check again */
+#define SCIOCRESET     _IO('Q', 7)     /* reset the device */
+
+
+#endif /* _SYS_SCSIIO_H_ */