summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrgrimes <rgrimes@FreeBSD.org>1993-11-18 05:03:27 +0000
committerrgrimes <rgrimes@FreeBSD.org>1993-11-18 05:03:27 +0000
commit73dd2628a2d9f88e008196681e15c6d3a0dc11be (patch)
tree6d93e911e7337a8936028ed9a12d64183f6766d3
parentdbf6b5a2db39d182aba158f88c9cd5005db5d6e0 (diff)
downloadFreeBSD-src-73dd2628a2d9f88e008196681e15c6d3a0dc11be.zip
FreeBSD-src-73dd2628a2d9f88e008196681e15c6d3a0dc11be.tar.gz
New version of scsi code from Julian
-rw-r--r--sys/conf/NOTES3
-rw-r--r--sys/i386/conf/LINT3
-rw-r--r--sys/i386/conf/NOTES3
-rw-r--r--sys/i386/eisa/aha1742.c1768
-rw-r--r--sys/i386/i386/conf.c47
-rw-r--r--sys/i386/include/param.h6
-rw-r--r--sys/i386/isa/aha1542.c1929
-rw-r--r--sys/i386/isa/aha1742.c1768
-rw-r--r--sys/i386/isa/bt742a.c2026
-rw-r--r--sys/i386/isa/ultra14f.c1626
-rw-r--r--sys/i386/isa/wd.c4
-rw-r--r--sys/scsi/README189
-rw-r--r--sys/scsi/cd.c2246
-rw-r--r--sys/scsi/ch.c1204
-rw-r--r--sys/scsi/scsi_all.h93
-rw-r--r--sys/scsi/scsi_base.c852
-rw-r--r--sys/scsi/scsi_cd.h10
-rw-r--r--sys/scsi/scsi_changer.h9
-rw-r--r--sys/scsi/scsi_debug.h53
-rw-r--r--sys/scsi/scsi_disk.h11
-rw-r--r--sys/scsi/scsi_ioctl.c329
-rw-r--r--sys/scsi/scsi_tape.h12
-rw-r--r--sys/scsi/scsiconf.c1110
-rw-r--r--sys/scsi/scsiconf.h259
-rw-r--r--sys/scsi/sd.c2072
-rw-r--r--sys/scsi/st.c3439
-rw-r--r--sys/scsi/su.c4
-rw-r--r--sys/scsi/uk.c156
-rw-r--r--sys/sys/chio.h9
-rw-r--r--sys/sys/scsiio.h63
30 files changed, 10105 insertions, 11198 deletions
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index a48a73b..ef33ef5 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -4,7 +4,7 @@
#
# 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"
@@ -87,6 +87,7 @@ options "SHMMAXPGS=64" # 256Kb of sharable memory
#pseudo-device tb #tablet line discipline.
pseudo-device tpip
#pseudo-device tun
+device uk0 #unknown scsi devices
pseudo-device vnodepager
#
diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT
index a48a73b..ef33ef5 100644
--- a/sys/i386/conf/LINT
+++ b/sys/i386/conf/LINT
@@ -4,7 +4,7 @@
#
# 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"
@@ -87,6 +87,7 @@ options "SHMMAXPGS=64" # 256Kb of sharable memory
#pseudo-device tb #tablet line discipline.
pseudo-device tpip
#pseudo-device tun
+device uk0 #unknown scsi devices
pseudo-device vnodepager
#
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index a48a73b..ef33ef5 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -4,7 +4,7 @@
#
# 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"
@@ -87,6 +87,7 @@ options "SHMMAXPGS=64" # 256Kb of sharable memory
#pseudo-device tb #tablet line discipline.
pseudo-device tpip
#pseudo-device tun
+device uk0 #unknown scsi devices
pseudo-device vnodepager
#
diff --git a/sys/i386/eisa/aha1742.c b/sys/i386/eisa/aha1742.c
index 1e3e154..dda5042 100644
--- a/sys/i386/eisa/aha1742.c
+++ b/sys/i386/eisa/aha1742.c
@@ -14,88 +14,74 @@
*
* 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 <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/malloc.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>
+#endif /*KERNEL */
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
-#endif __386BSD__
-/* */
+/* */
-#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();
-#else NDDB
+#else /* NDDB */
#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;
-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)
-#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() */
-/* */
-/***********************************************************************\
-* 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)|'@')
@@ -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 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
@@ -123,18 +109,18 @@ extern int delaycount; /* from clock setup code */
#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 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 ****/
-#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
-/***********************************************************************\
-* 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
@@ -152,9 +138,9 @@ extern int delaycount; /* from clock setup code */
#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
@@ -181,138 +167,130 @@ extern int delaycount; /* from clock setup code */
#define G2STAT_MBOX_EMPTY 0x04
#define G2STAT2_HOST_READY 0x01
-/* */
-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];
};
-/* */
-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----------------*/
- 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
- 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 */
};
-/* */
-
-struct ahb_data
-{
- int flags;
+struct ahb_data {
+ int flags;
#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;
-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
-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
@@ -321,7 +299,15 @@ int ahb_debug = 0;
#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,
@@ -329,400 +315,395 @@ struct scsi_switch ahb_switch =
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 }
};
-/* */
-/***********************************************************************\
-* 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();
}
-
- 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);
}
-/***********************************************************************\
-* 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);
- 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();
}
-
- 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);
}
-/* */
-
-/*******************************************************\
-* 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)
-struct isa_dev *dev;
+ struct isa_device *dev;
{
- int port;
- u_char byte1,byte2,byte3;
+ int port;
+ u_char byte1, byte2, byte3;
+
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);
- if(byte1 == 0xff)
- {
+ if (byte1 == 0xff) {
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++;
}
- 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)
-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++;
- return(1);
+ return 0x1000;
}
-/***********************************************\
-* Attach all the sub-devices we can find *
-\***********************************************/
+/*
+ * Attach all the sub-devices we can find
+ */
+int
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)
+ 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
- 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;
- 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
- 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;
- case AHB_IMMED_ERR:
- ecb = ahb_data[unit].immed_ecb;
+ case AHB_IMMED_ERR:
+ ecb = ahb->immed_ecb;
ecb->flags |= ECB_IMMED_FAIL;
- ahb_data[unit].immed_ecb = 0;
+ ahb->immed_ecb = 0;
break;
- case AHB_ASN: /* for target mode */
+ case AHB_ASN: /* for target mode */
printf("ahb%d: Unexpected ASN interrupt(%x)\n",
- unit, mboxval);
+ unit, mboxval);
ecb = 0;
break;
- case AHB_HW_ERR:
+ case AHB_HW_ERR:
printf("ahb%d: Hardware error interrupt(%x)\n",
- unit, mboxval);
+ unit, mboxval);
ecb = 0;
break;
- case AHB_ECB_RECOVERED:
- ecb = (struct ecb *)PHYSTOKV(mboxval);
+ case AHB_ECB_RECOVERED:
+ ecb = ahb_ecb_phys_kv(ahb, mboxval);
break;
- case AHB_ECB_ERR:
- ecb = (struct ecb *)PHYSTOKV(mboxval);
+ case AHB_ECB_ERR:
+ ecb = ahb_ecb_phys_kv(ahb, mboxval);
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
- 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;
}
- 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;
- }
- else
- {
+ } else {
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;
- case HS_SCSI_RESET_INCOMING:
+ case HS_SCSI_RESET_INCOMING:
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;
- case HS_TIMED_OUT: /* No response */
+ case HS_TIMED_OUT: /* No response */
#ifdef AHBDEBUG
- if (ahb_debug & AHB_SHOWMISC)
- {
+ if (ahb_debug & AHB_SHOWMISC) {
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
- if (ahb_debug & AHB_SHOWMISC)
- {
+ if (ahb_debug & AHB_SHOWMISC) {
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:
- /* structure copy!!!!!*/
- *s2=*s1;
+ /* structure copy!!!!! */
+ *s2 = *s1;
xs->error = XS_SENSE;
break;
case TS_BUSY:
@@ -730,352 +711,339 @@ struct ecb *ecb;
break;
default:
#ifdef AHBDEBUG
- if (ahb_debug & AHB_SHOWMISC)
- {
+ if (ahb_debug & AHB_SHOWMISC) {
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;
- 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;
-
-#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;
- /***********************************************\
- * 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) {
- wakeup(&ahb_data[unit].free_ecb);
+ wakeup((caddr_t)&ahb->free_ecb);
}
- if (!(flags & SCSI_NOMASK))
+ if (!(flags & SCSI_NOMASK))
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 *
-ahb_get_ecb(unit,flags)
+ahb_get_ecb(unit, flags)
+ int unit, flags;
{
+ struct ahb_data *ahb = ahbdata[unit];
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);
- 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)
-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
- /***********************************************\
- * 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)
- 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;
- 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
- while( inb(stport) & G2STAT_INT_PEND)
- {
+ while (inb(stport) & G2STAT_INT_PEND) {
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);
- switch(intdef & 0x07)
- {
- case INT9:
- ahb_data[unit].vect = 9;
+ switch (intdef & 0x07) {
+ case INT9:
+ ahb->vect = 9;
break;
- case INT10:
- ahb_data[unit].vect = 10;
+ case INT10:
+ ahb->vect = 10;
break;
- case INT11:
- ahb_data[unit].vect = 11;
+ case INT11:
+ ahb->vect = 11;
break;
- case INT12:
- ahb_data[unit].vect = 12;
+ case INT12:
+ ahb->vect = 12;
break;
- case INT14:
- ahb_data[unit].vect = 14;
+ case INT14:
+ ahb->vect = 14;
break;
- case INT15:
- ahb_data[unit].vect = 15;
+ case INT15:
+ ahb->vect = 15;
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)
-#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;
- 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;
- 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;
}
- if(!(flags & INUSE))
- {
- printf("ahb%d: Not in use?",unit);
+ if (!(flags & INUSE)) {
+ printf("ahb%d: Not in use?", unit);
xs->flags |= INUSE;
}
- if (!(ecb = ahb_get_ecb(unit,flags)))
- {
+ if (!(ecb = ahb_get_ecb(unit, flags))) {
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;
- /***********************************************\
- * 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;
- 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();
- 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);
- 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;
- 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->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->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;
- 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++;
@@ -1083,240 +1051,198 @@ cheat = ecb;
}
}
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;
-
-#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 */
- 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 */
- nextphys= (thisphys & (~(PAGESIZ - 1)))
- + PAGESIZ;
- bytes_this_page = nextphys - thisphys;
+ nextphys = (thisphys & (~(PAGESIZ - 1)))
+ + PAGESIZ;
+ 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;
-
+ 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 */
- thiskv = (thiskv & (~(PAGESIZ - 1)))
- + PAGESIZ;
- if(datalen)
+ thiskv = (thiskv & (~(PAGESIZ - 1)))
+ + PAGESIZ;
+ if (datalen)
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);
-#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",
- unit,AHB_NSEG);
+ unit, AHB_NSEG);
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->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);
- /***********************************************\
- * Usually return SUCCESSFULLY QUEUED *
- \***********************************************/
- if (!(flags & SCSI_NOMASK))
- {
+ /*
+ * Usually return SUCCESSFULLY QUEUED
+ */
+ if (!(flags & SCSI_NOMASK)) {
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);
-#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");
- ahb_free_ecb(unit,ecb,flags);
+ ahb_free_ecb(unit, ecb, flags);
}
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
- if(ahb_debug & AHB_SHOWECBS)
+ if (ahb_debug & AHB_SHOWECBS)
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;
- ahb_done(unit,ecb,FAIL);
+ ahb_done(unit, ecb, FAIL);
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");
- ecb->xs->retries = 0; /* I MEAN IT ! */
+ ecb->xs->retries = 0; /* I MEAN IT ! */
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");
- 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
-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)
-struct ecb *ecb;
+ struct ecb *ecb;
{
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"
- ,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)
{
- 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 */
diff --git a/sys/i386/i386/conf.c b/sys/i386/i386/conf.c
index 755a0dd..ae333fd 100644
--- a/sys/i386/i386/conf.c
+++ b/sys/i386/i386/conf.c
@@ -1,4 +1,4 @@
-/*-
+/*
* 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
- * $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"
@@ -126,20 +126,6 @@ int chopen(),chclose(),chioctl();
#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();
@@ -377,6 +363,26 @@ extern struct tty sio_tty[];
#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*/
@@ -433,9 +439,9 @@ struct cdevsw cdevsw[] =
{ 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 },
@@ -472,6 +478,9 @@ struct cdevsw cdevsw[] =
{ 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'.
diff --git a/sys/i386/include/param.h b/sys/i386/include/param.h
index c9e77b2..8f46b47 100644
--- a/sys/i386/include/param.h
+++ b/sys/i386/include/param.h
@@ -34,7 +34,7 @@
* 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_
@@ -157,8 +157,4 @@
#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_ */
diff --git a/sys/i386/isa/aha1542.c b/sys/i386/isa/aha1542.c
index c242624..b731ed6 100644
--- a/sys/i386/isa/aha1542.c
+++ b/sys/i386/isa/aha1542.c
@@ -12,97 +12,49 @@
* 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
*/
-/*
- * 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>
+#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 <sys/malloc.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>
+#endif /* KERNEL */
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
-#endif __386BSD__
-
-#ifdef __386BSD__
+#ifdef KERNEL
#include "ddb.h"
#if NDDB > 0
-int Debugger();
-#else NDDB
+int Debugger();
+#else /* NDDB */
#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 *******************************/
+
/*
* 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 */
@@ -155,7 +107,7 @@ extern int delaycount; /* from clock setup code */
#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];
- } 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];
@@ -193,60 +145,59 @@ struct aha_mbx {
#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 */
-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 {
- 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];
- 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
-
};
-
/*
* 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 */
-
/*
* 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
-
-
-
-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
@@ -331,58 +276,82 @@ struct aha_extbios
#define CHAN6 0x40
#define CHAN7 0x80
-
/*********************************** 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)
-#else __386BSD__
-#endif __386BSD__
-#endif MACH
#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
-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; \
@@ -391,330 +360,307 @@ static int ahaunit = 0;
(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;
- u_char oc;
+ u_char oc;
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
- 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);
- if (sts & AHA_IDLE)
- {
+ if (sts & AHA_IDLE) {
break;
}
+ DELAY(50);
}
- if (!i)
- {
+ if (!i) {
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);
}
-
- /*******************************************************\
- * 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);
- for (i=0; i< wait; i++)
- {
+ for (i = wait; i; i--) {
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);
- for (i=0; i< wait; i++)
- {
+ for (i = wait; i; i--) {
sts = inb(AHA_CTRL_STAT_PORT);
- if (sts & AHA_DF)
+ if (sts & AHA_DF)
break;
+ DELAY(50);
}
- if (i >= wait)
- {
+ if (i == 0) {
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;
}
- /*******************************************************\
- * 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);
- if (sts & AHA_HACC)
- {
+ if (sts & AHA_HACC) {
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);
- 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)
-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)
-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;
+ struct aha_data *aha = ahadata[unit];
#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);
+ if (!(stat & AHA_MBIF))
+ return 1;
#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
- if(aha_debug)
- printf("abort");
-#endif /*AHADEBUG*/
+ if (aha_debug)
+ printf("abort");
+#endif /*AHADEBUG */
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
- 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 */
- case AHA_MBI_ERROR:
+ case AHA_MBI_ERROR:
break;
default:
@@ -722,214 +668,191 @@ ahaintr(unit)
}
#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"
- , aha_mbx[unit].mbi[i].stat, i);
+ ,aha->aha_mbx.mbi[i].stat, i);
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;
-
-#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;
- /***********************************************\
- * 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) {
- wakeup(&aha_ccb_free[unit]);
+ wakeup(&aha->aha_ccb_free);
}
- if (!(flags & SCSI_NOMASK))
+ if (!(flags & SCSI_NOMASK))
splx(opri);
}
-/***********************************************\
-* Get a free ccb (and hence mbox-out entry) *
-\***********************************************/
+/*
+ * Get a free ccb (and hence mbox-out entry)
+ */
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;
-#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;
}
- if (!(flags & SCSI_NOMASK))
+ if (!(flags & SCSI_NOMASK))
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();
}
- 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);
- 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;
-#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:
- /* structure copy!!!!!*/
- *s2=*s1;
+ /* structure copy!!!!! */
+ *s2 = *s1;
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;
}
}
- }
- else /* All went correctly OR errors expected */
- {
+ } else {
+ /* All went correctly OR errors expected */
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)
-int unit;
+ int unit;
{
+ struct aha_data *aha = ahadata[unit];
unsigned char ad[3];
- volatile int i,sts;
+ volatile int i, sts;
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;
+ 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");
-#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
@@ -967,514 +890,399 @@ int unit;
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)
-#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);
- aha_dma[unit] = 0;
+ aha->aha_dma = 0;
PRNT("dma=0 ");
break;
- case CHAN5:
+ case CHAN5:
outb(0xd6, 0xc1);
outb(0xd4, 0x01);
- aha_dma[unit] = 5;
+ aha->aha_dma = 5;
PRNT("dma=5 ");
break;
- case CHAN6:
+ case CHAN6:
outb(0xd6, 0xc2);
outb(0xd4, 0x02);
- aha_dma[unit] = 6;
+ aha->aha_dma = 6;
PRNT("dma=6 ");
break;
- case CHAN7:
+ case CHAN7:
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");
- 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;
- case INT10:
- aha_int[unit] = 10;
+ case INT10:
+ aha->aha_int = 10;
PRNT("int=10 ");
break;
- case INT11:
- aha_int[unit] = 11;
+ case INT11:
+ aha->aha_int = 11;
PRNT("int=11 ");
break;
- case INT12:
- aha_int[unit] = 12;
+ case INT12:
+ aha->aha_int = 12;
PRNT("int=12 ");
break;
- case INT14:
- aha_int[unit] = 14;
+ case INT14:
+ aha->aha_int = 14;
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");
- 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");
-#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);
}
}
-
-/***********************************************\
-* 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;
- 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;
- 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;
- return(TRY_AGAIN_LATER);
+ return (TRY_AGAIN_LATER);
}
-
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 */
- 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--;
}
- }
- 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 */
- 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 */
- 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)))
- + PAGESIZ;
- bytes_this_page = nextphys - thisphys;
+ + PAGESIZ;
+ 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;
-
+ 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 ****/
- thiskv = (thiskv & (~(PAGESIZ - 1)))
- + PAGESIZ;
- if(datalen)
+ thiskv = (thiskv & (~(PAGESIZ - 1)))
+ + PAGESIZ;
+ if (datalen)
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++;
}
}
- 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",
- unit,AHA_NSEG);
+ unit, AHA_NSEG);
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);
-#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);
- /***********************************************\
- * Usually return SUCCESSFULLY QUEUED *
- \***********************************************/
+ /*
+ * Usually return SUCCESSFULLY QUEUED
+ */
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);
-#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;
@@ -1490,93 +1298,146 @@ static struct bus_speed
{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();
}
- /***************************************\
- * 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");
- ccb->xfer->retries = 0; /* I MEAN IT ! */
+ ccb->xfer->retries = 0; /* I MEAN IT ! */
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);
- /* 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;
- }
- splx(s);
+ } splx(s);
}
+#endif /* KERNEL */
diff --git a/sys/i386/isa/aha1742.c b/sys/i386/isa/aha1742.c
index 1e3e154..dda5042 100644
--- a/sys/i386/isa/aha1742.c
+++ b/sys/i386/isa/aha1742.c
@@ -14,88 +14,74 @@
*
* 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 <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/malloc.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>
+#endif /*KERNEL */
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
-#endif __386BSD__
-/* */
+/* */
-#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();
-#else NDDB
+#else /* NDDB */
#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;
-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)
-#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() */
-/* */
-/***********************************************************************\
-* 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)|'@')
@@ -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 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
@@ -123,18 +109,18 @@ extern int delaycount; /* from clock setup code */
#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 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 ****/
-#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
-/***********************************************************************\
-* 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
@@ -152,9 +138,9 @@ extern int delaycount; /* from clock setup code */
#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
@@ -181,138 +167,130 @@ extern int delaycount; /* from clock setup code */
#define G2STAT_MBOX_EMPTY 0x04
#define G2STAT2_HOST_READY 0x01
-/* */
-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];
};
-/* */
-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----------------*/
- 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
- 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 */
};
-/* */
-
-struct ahb_data
-{
- int flags;
+struct ahb_data {
+ int flags;
#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;
-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
-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
@@ -321,7 +299,15 @@ int ahb_debug = 0;
#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,
@@ -329,400 +315,395 @@ struct scsi_switch ahb_switch =
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 }
};
-/* */
-/***********************************************************************\
-* 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();
}
-
- 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);
}
-/***********************************************************************\
-* 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);
- 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();
}
-
- 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);
}
-/* */
-
-/*******************************************************\
-* 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)
-struct isa_dev *dev;
+ struct isa_device *dev;
{
- int port;
- u_char byte1,byte2,byte3;
+ int port;
+ u_char byte1, byte2, byte3;
+
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);
- if(byte1 == 0xff)
- {
+ if (byte1 == 0xff) {
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++;
}
- 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)
-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++;
- return(1);
+ return 0x1000;
}
-/***********************************************\
-* Attach all the sub-devices we can find *
-\***********************************************/
+/*
+ * Attach all the sub-devices we can find
+ */
+int
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)
+ 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
- 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;
- 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
- 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;
- case AHB_IMMED_ERR:
- ecb = ahb_data[unit].immed_ecb;
+ case AHB_IMMED_ERR:
+ ecb = ahb->immed_ecb;
ecb->flags |= ECB_IMMED_FAIL;
- ahb_data[unit].immed_ecb = 0;
+ ahb->immed_ecb = 0;
break;
- case AHB_ASN: /* for target mode */
+ case AHB_ASN: /* for target mode */
printf("ahb%d: Unexpected ASN interrupt(%x)\n",
- unit, mboxval);
+ unit, mboxval);
ecb = 0;
break;
- case AHB_HW_ERR:
+ case AHB_HW_ERR:
printf("ahb%d: Hardware error interrupt(%x)\n",
- unit, mboxval);
+ unit, mboxval);
ecb = 0;
break;
- case AHB_ECB_RECOVERED:
- ecb = (struct ecb *)PHYSTOKV(mboxval);
+ case AHB_ECB_RECOVERED:
+ ecb = ahb_ecb_phys_kv(ahb, mboxval);
break;
- case AHB_ECB_ERR:
- ecb = (struct ecb *)PHYSTOKV(mboxval);
+ case AHB_ECB_ERR:
+ ecb = ahb_ecb_phys_kv(ahb, mboxval);
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
- 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;
}
- 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;
- }
- else
- {
+ } else {
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;
- case HS_SCSI_RESET_INCOMING:
+ case HS_SCSI_RESET_INCOMING:
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;
- case HS_TIMED_OUT: /* No response */
+ case HS_TIMED_OUT: /* No response */
#ifdef AHBDEBUG
- if (ahb_debug & AHB_SHOWMISC)
- {
+ if (ahb_debug & AHB_SHOWMISC) {
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
- if (ahb_debug & AHB_SHOWMISC)
- {
+ if (ahb_debug & AHB_SHOWMISC) {
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:
- /* structure copy!!!!!*/
- *s2=*s1;
+ /* structure copy!!!!! */
+ *s2 = *s1;
xs->error = XS_SENSE;
break;
case TS_BUSY:
@@ -730,352 +711,339 @@ struct ecb *ecb;
break;
default:
#ifdef AHBDEBUG
- if (ahb_debug & AHB_SHOWMISC)
- {
+ if (ahb_debug & AHB_SHOWMISC) {
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;
- 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;
-
-#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;
- /***********************************************\
- * 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) {
- wakeup(&ahb_data[unit].free_ecb);
+ wakeup((caddr_t)&ahb->free_ecb);
}
- if (!(flags & SCSI_NOMASK))
+ if (!(flags & SCSI_NOMASK))
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 *
-ahb_get_ecb(unit,flags)
+ahb_get_ecb(unit, flags)
+ int unit, flags;
{
+ struct ahb_data *ahb = ahbdata[unit];
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);
- 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)
-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
- /***********************************************\
- * 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)
- 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;
- 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
- while( inb(stport) & G2STAT_INT_PEND)
- {
+ while (inb(stport) & G2STAT_INT_PEND) {
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);
- switch(intdef & 0x07)
- {
- case INT9:
- ahb_data[unit].vect = 9;
+ switch (intdef & 0x07) {
+ case INT9:
+ ahb->vect = 9;
break;
- case INT10:
- ahb_data[unit].vect = 10;
+ case INT10:
+ ahb->vect = 10;
break;
- case INT11:
- ahb_data[unit].vect = 11;
+ case INT11:
+ ahb->vect = 11;
break;
- case INT12:
- ahb_data[unit].vect = 12;
+ case INT12:
+ ahb->vect = 12;
break;
- case INT14:
- ahb_data[unit].vect = 14;
+ case INT14:
+ ahb->vect = 14;
break;
- case INT15:
- ahb_data[unit].vect = 15;
+ case INT15:
+ ahb->vect = 15;
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)
-#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;
- 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;
- 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;
}
- if(!(flags & INUSE))
- {
- printf("ahb%d: Not in use?",unit);
+ if (!(flags & INUSE)) {
+ printf("ahb%d: Not in use?", unit);
xs->flags |= INUSE;
}
- if (!(ecb = ahb_get_ecb(unit,flags)))
- {
+ if (!(ecb = ahb_get_ecb(unit, flags))) {
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;
- /***********************************************\
- * 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;
- 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();
- 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);
- 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;
- 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->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->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;
- 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++;
@@ -1083,240 +1051,198 @@ cheat = ecb;
}
}
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;
-
-#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 */
- 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 */
- nextphys= (thisphys & (~(PAGESIZ - 1)))
- + PAGESIZ;
- bytes_this_page = nextphys - thisphys;
+ nextphys = (thisphys & (~(PAGESIZ - 1)))
+ + PAGESIZ;
+ 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;
-
+ 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 */
- thiskv = (thiskv & (~(PAGESIZ - 1)))
- + PAGESIZ;
- if(datalen)
+ thiskv = (thiskv & (~(PAGESIZ - 1)))
+ + PAGESIZ;
+ if (datalen)
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);
-#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",
- unit,AHB_NSEG);
+ unit, AHB_NSEG);
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->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);
- /***********************************************\
- * Usually return SUCCESSFULLY QUEUED *
- \***********************************************/
- if (!(flags & SCSI_NOMASK))
- {
+ /*
+ * Usually return SUCCESSFULLY QUEUED
+ */
+ if (!(flags & SCSI_NOMASK)) {
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);
-#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");
- ahb_free_ecb(unit,ecb,flags);
+ ahb_free_ecb(unit, ecb, flags);
}
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
- if(ahb_debug & AHB_SHOWECBS)
+ if (ahb_debug & AHB_SHOWECBS)
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;
- ahb_done(unit,ecb,FAIL);
+ ahb_done(unit, ecb, FAIL);
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");
- ecb->xs->retries = 0; /* I MEAN IT ! */
+ ecb->xs->retries = 0; /* I MEAN IT ! */
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");
- 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
-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)
-struct ecb *ecb;
+ struct ecb *ecb;
{
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"
- ,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)
{
- 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 */
diff --git a/sys/i386/isa/bt742a.c b/sys/i386/isa/bt742a.c
index ebf6504c..fa46753 100644
--- a/sys/i386/isa/bt742a.c
+++ b/sys/i386/isa/bt742a.c
@@ -12,7 +12,7 @@
* 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 $
*/
/*
@@ -20,69 +20,45 @@
*/
#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/malloc.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>
-#endif __386BSD__
-
-#ifdef __386BSD__
+#ifdef KERNEL
#include "ddb.h"
#if NDDB > 0
-int Debugger();
-#else NDDB
+int Debugger();
+#else /* NDDB */
#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 delaycount; /* from clock setup code */
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)
@@ -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_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 {
- u_char byte[16];
+ u_char byte[16];
};
/*
@@ -151,41 +127,45 @@ struct bt_cmd_buf {
#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 ) \
- if ( (wmb) == &((mbx)->mbio[BT_MBX_SIZE - 1 ]) ) { \
+ if ( (wmb) == &((mbx)->mbio[BT_MBX_SIZE - 1 ]) ) \
(wmb) = &((mbx)->mbio[0]); \
- } else { \
- (wmb)++; \
- }
-
+ else \
+ (wmb)++;
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;
-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;
-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 */
+/*
+ * 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 */
-extern struct bt_mbx bt_mbx[];
-
#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
-#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 {
- 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 */
- unsigned long data_length;
+ unsigned long data_length;
/*------------------------------------longword boundary */
- physaddr data_addr;
+ physaddr data_addr;
/*------------------------------------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 */
- 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 */
- physaddr link_addr;
+ physaddr link_addr;
/*------------------------------------longword boundary */
- physaddr sense_ptr;
+ physaddr sense_ptr;
+/*-----end of HW fields-------------------------------longword boundary */
+ struct scsi_sense_data scsi_sense;
/*------------------------------------longword boundary */
- struct scsi_sense_data scsi_sense;
+ struct bt_scat_gath scat_gath[BT_NSEG];
/*------------------------------------longword boundary */
- struct bt_scat_gath scat_gath[BT_NSEG];
+ struct bt_ccb *next;
/*------------------------------------longword boundary */
- struct bt_ccb *next;
+ struct scsi_xfer *xfer; /* the scsi_xfer for this cmd */
/*------------------------------------longword boundary */
- struct scsi_xfer *xfer; /* the scsi_xfer for this cmd */
+ struct bt_mbx_out *mbx; /* pointer to mail box */
/*------------------------------------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
+ /*------------------------------------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_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 */
-
/*
* 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 */
-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 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 {
- 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;
};
@@ -332,398 +317,385 @@ struct bt_config
#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" ); }
+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
-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
- 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);
- if (sts & BT_IDLE)
- {
+ if (sts & BT_IDLE) {
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);
}
-
- /*******************************************************\
- * 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);
- for (i=0; i< wait; i++)
- {
+ for (i = wait; i; i--) {
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);
- for (i=0; i< wait; i++)
- {
+ for (i = wait; i; i--) {
sts = inb(BT_CTRL_STAT_PORT);
- if (sts & BT_DF)
+ if (sts & BT_DF)
break;
+ DELAY(10);
}
- if (i >= wait)
- {
+ if (i == 0) {
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;
}
- /*******************************************************\
- * 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);
- if (sts & BT_HACC)
- {
+ if (sts & BT_HACC) {
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);
- 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)
-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;
-#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++;
- return(1);
+ return 1;
}
-/***********************************************\
-* Attach all the sub-devices we can find *
-\***********************************************/
+/*
+ * Attach all the sub-devices we can find
+ */
+int
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)
+ 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;
- int i,wait;
- int found = 0;
+ int i, wait;
+ int found = 0;
#ifdef UTEST
- if(scsi_debug & PRINTROUTINES)
- printf("btintr ");
+ printf("btintr ");
#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 ? */
- 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;
+ 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 */
- wakeup(&bt_mbx[unit]);
+ wakeup(&bt->bt_mbx);
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;
}
-#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;
-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++;
- 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
- if(bt_debug & BT_SHOWMISC)
+ if (bt_debug & BT_SHOWMISC)
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
- if(bt_debug & BT_SHOWMISC)
+ if (bt_debug & BT_SHOWMISC)
printf("unknown ccb for abort");
#endif
break;
- case BT_MBI_ERROR:
+ case BT_MBI_ERROR:
break;
default:
@@ -731,40 +703,36 @@ AGAIN:
}
#ifdef UTEST
- if((bt_debug & BT_SHOWCMDS ) && ccb)
- {
- u_char *cp;
+ if ((bt_debug & BT_SHOWCMDS) && ccb) {
+ u_char *cp;
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"
- , wmbi->stat, wmbi );
+ ,wmbi->stat, wmbi);
printf("addr = 0x%x\n", ccb);
}
-#endif
+#endif
}
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;
}
- 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",
- unit, wmbi, stat );
+ unit, wmbi, stat);
} else {
found = 0;
goto AGAIN;
@@ -772,846 +740,772 @@ AGAIN:
}
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;
-#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;
- /***********************************************\
- * 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) {
- wakeup(&bt_ccb_free[unit]);
+ wakeup(&bt->bt_ccb_free);
}
- if (!(flags & SCSI_NOMASK))
+
+ if (!(flags & SCSI_NOMASK))
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 *
-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 */
- 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 */
- 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);
-
- 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;
- 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.
- */
- 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;
+ 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 */
- sleep( wmbx, PRIBIO);
+ sleep(wmbx, PRIBIO); /*XXX *//*can't do this! */
+ /* May be servicing an int */
}
-
/* 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);
- if (!(flags & SCSI_NOMASK))
+ if (!(flags & SCSI_NOMASK))
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);
- 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;
-#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:
- /* structure copy!!!!!*/
- *s2=*s1;
+ *s2 = *s1;
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;
}
}
- }
- else /* All went correctly OR errors expected */
- {
+ } else { /* All went correctly OR errors expected */
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)
-int unit;
+ int unit;
{
+ struct bt_data *bt = btdata[unit];
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;
+ 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
- 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;
- case CHAN0:
+ case CHAN0:
outb(0x0b, 0x0c);
outb(0x0a, 0x00);
- bt_dma[unit] = 0;
+ bt->bt_dma = 0;
break;
- case CHAN5:
+ case CHAN5:
outb(0xd6, 0xc1);
outb(0xd4, 0x01);
- bt_dma[unit] = 5;
+ bt->bt_dma = 5;
break;
- case CHAN6:
+ case CHAN6:
outb(0xd6, 0xc2);
outb(0xd4, 0x02);
- bt_dma[unit] = 6;
+ bt->bt_dma = 6;
break;
- case CHAN7:
+ case CHAN7:
outb(0xd6, 0xc3);
outb(0xd4, 0x03);
- bt_dma[unit] = 7;
+ bt->bt_dma = 7;
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("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;
- case INT10:
- bt_int[unit] = 10;
+ case INT10:
+ bt->bt_int = 10;
break;
- case INT11:
- bt_int[unit] = 11;
+ case INT11:
+ bt->bt_int = 11;
break;
- case INT12:
- bt_int[unit] = 12;
+ case INT12:
+ bt->bt_int = 12;
break;
- case INT14:
- bt_int[unit] = 14;
+ case INT14:
+ bt->bt_int = 14;
break;
- case INT15:
- bt_int[unit] = 15;
+ case INT15:
+ bt->bt_int = 15;
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 */
- 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",
- 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;
- /* 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, ",
- 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, ");
}
-
- if ( setup.parity ) {
+ if (setup.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].valid )
+ !setup.sync[i].valid)
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)
-#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;
- 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;
-#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;
- 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;
}
- 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;
}
- if (!(ccb = bt_get_ccb(unit,flags)))
- {
+ if (!(ccb = bt_get_ccb(unit, flags))) {
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 */
- 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);
- 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;
- 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--;
}
- }
- 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;
-
-#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 */
- nextphys = thisphys;
+ nextphys = thisphys;
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)))
- + PAGESIZ;
- bytes_this_page = nextphys - thisphys;
+ nextphys = (thisphys & (~(PAGESIZ - 1)))
+ + PAGESIZ;
+ 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;
-
+ 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 */
- thiskv = (thiskv & (~(PAGESIZ - 1)))
- + PAGESIZ;
- if(datalen)
+ thiskv = (thiskv & (~(PAGESIZ - 1)))
+ + PAGESIZ;
+ if (datalen)
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++;
}
- } /*end of iov/kv decision */
+ }
+ /* end of iov/kv decision */
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",
- unit,BT_NSEG);
+ unit, BT_NSEG);
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->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);
}
-#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;
- 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
- if(bt_debug & BT_SHOWCCBS)
- bt_print_active_ccbs(unit);
+ bt_print_active_ccbs(unit);
#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
+void
bt_print_ccb(ccb)
-struct bt_ccb *ccb;
+ struct bt_ccb *ccb;
{
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"
- ,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)
{
- 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 */
diff --git a/sys/i386/isa/ultra14f.c b/sys/i386/isa/ultra14f.c
index 0d9b08c..76dc115 100644
--- a/sys/i386/isa/ultra14f.c
+++ b/sys/i386/isa/ultra14f.c
@@ -1,5 +1,6 @@
/*
* 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)
@@ -18,274 +19,241 @@
* 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>
+
+#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 <sys/malloc.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>
+#endif /*KERNEL */
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
-#endif __386BSD__
-/* */
+/* */
-#ifdef __386BSD__
+#ifdef KERNEL
#include "ddb.h"
#if NDDB > 0
int Debugger();
-#else NDDB
+#else /* NDDB */
#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() */
-/* */
/************************** 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 */
-
-/* */
-
-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;
};
-/* */
-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----------------*/
- 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
- 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;
};
-/* */
-
-struct uha_data
-{
+struct uha_data {
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 dma;
-} uha_data[NUHA];
+ int dma;
+ int nummscps;
+ struct scsi_link sc_link;
+} *uhadata[NUHA];
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();
-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;
-
-#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
@@ -294,7 +262,15 @@ int uha_debug = 0;
#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,
@@ -302,401 +278,447 @@ struct scsi_switch uha_switch =
0,
uha_adapter_info,
"uha",
- 0,0
+ 0, 0
};
-/* */
-/***********************************************************************\
-* 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();
-
- 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();
}
-
- outl(port + UHA_OGM0,KVTOPHYS(mscp));
+ outl(port + UHA_OGM0, KVTOPHYS(mscp));
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();
}
+ 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);
- 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)
-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)
-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)
{
- 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
- 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);
- 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
- 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;
- }
- else
- {
+ } else {
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;
- 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;
- 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;
- default: /* Other scsi protocol messes */
+ default: /* Other scsi protocol messes */
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)
-/**************************************************************************\
-* 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;
}
}
- }
-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;
-
-#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();
- 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;
- /***********************************************\
- * 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) {
- wakeup(&uha_data[unit].free_mscp);
+ wakeup(&uha->free_mscp);
}
- if (!(flags & SCSI_NOMASK))
+ if (!(flags & SCSI_NOMASK))
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 *
-uha_get_mscp(unit,flags)
+uha_get_mscp(unit, flags)
+ int unit, flags;
{
+ struct uha_data *uha = uhadata[unit];
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();
- /***********************************************\
- * 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);
- 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)
-int unit;
-{
+ int unit;
+{
+ struct uha_data *uha = uhadata[unit];
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;
- 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);
- 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);
@@ -726,307 +745,256 @@ int unit;
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;
- case UHA_DMA_CH6:
- uha_data[unit].dma = 6;
+ case UHA_DMA_CH6:
+ uha->dma = 6;
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");
- 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;
- case UHA_IRQ11:
- uha_data[unit].vect = 11;
+ case UHA_IRQ11:
+ uha->vect = 11;
printf("int=11 ");
break;
- case UHA_IRQ14:
- uha_data[unit].vect = 14;
+ case UHA_IRQ14:
+ uha->vect = 14;
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");
- return(EIO);
+ return (EIO);
}
+
/* 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)
-#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;
- 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 port = uha_data[unit].baseport;
+ int port = uha->baseport;
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;
- 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;
}
- if(!(flags & INUSE))
- {
- printf("uha%d: Not in use?",unit);
+ if (!(flags & INUSE)) {
+ printf("uha%d: Not in use?", unit);
xs->flags |= INUSE;
}
- if (!(mscp = uha_get_mscp(unit,flags)))
- {
+ if (!(mscp = uha_get_mscp(unit, flags))) {
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;
- /***********************************************\
- * 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;
- }
- else
- {
+ } else {
mscp->opcode = 0x02;
mscp->ca = 0x01;
- }
-
- if (flags & SCSI_DATA_IN)
- {
+ }
+ if (flags & SCSI_DATA_IN) {
mscp->xdir = 0x01;
}
- if (flags & SCSI_DATA_OUT)
- {
+ if (flags & SCSI_DATA_OUT) {
mscp->xdir = 0x02;
}
-
- if (xs->lu != 0)
- {
+#ifdef GOTTABEJOKING
+ if (xs->sc_link->lun != 0) {
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;
- 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);
- 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--;
}
- }
- 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);
-
-#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 */
- nextphys = thisphys;
+ nextphys = thisphys;
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)))
- + PAGESIZ;
+ + PAGESIZ;
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 */
- thiskv = (thiskv & (~(PAGESIZ - 1)))
- + PAGESIZ;
- if(datalen)
+ thiskv = (thiskv & (~(PAGESIZ - 1)))
+ + PAGESIZ;
+ if (datalen)
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);
@@ -1035,29 +1003,24 @@ cheat = mscp;
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;
-#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",
- unit,UHA_NSEG);
+ unit, UHA_NSEG);
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;
@@ -1068,142 +1031,119 @@ cheat = mscp;
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();
- 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);
-#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))
- 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;
- 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;
- 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
- 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");
- 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");
- timeout(uha_timeout,mscp,2 * hz);
+ timeout(uha_timeout, mscp, 2 * hz);
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)
-struct mscp *mscp;
+ struct mscp *mscp;
{
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"
- ,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)
{
- 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 */
diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c
index beb4d7d..95c3db6 100644
--- a/sys/i386/isa/wd.c
+++ b/sys/i386/isa/wd.c
@@ -34,7 +34,7 @@
* 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 */
@@ -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;
- 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;
diff --git a/sys/scsi/README b/sys/scsi/README
index fbd1e6e..b110930 100644
--- a/sys/scsi/README
+++ b/sys/scsi/README
@@ -1,46 +1,55 @@
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 *
-Kodak IL900 scanner *
+Generic scsi-II scanners *
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)
-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 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
@@ -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:
-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)
+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
@@ -120,25 +116,7 @@ e.g.
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
@@ -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).
+General scsi ioctls are found in sys/scsiio.h.
-----------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.
+***IMPORTANT***
+Cdrom audio is only suported at all for cdroms that use SCSI2 audio
+definitions.
-------------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
@@ -178,20 +160,6 @@ and program.
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
@@ -206,4 +174,23 @@ have particular problems so they can be handled specially.
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.
+
+
diff --git a/sys/scsi/cd.c b/sys/scsi/cd.c
index f5de591..68b09ba 100644
--- a/sys/scsi/cd.c
+++ b/sys/scsi/cd.c
@@ -14,7 +14,7 @@
*
* Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
*
- * $Id: cd.c,v 1.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
@@ -40,898 +40,697 @@
#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
-int Debugger();
-#else NDDB > 0
+int Debugger();
+#else /* NDDB > 0 */
#define Debugger()
-#endif NDDB > 0
-
+#endif /* NDDB > 0 */
#define PAGESIZ 4096
-#define SECSIZE 2048 /* XXX */ /* default only */
+#define SECSIZE 2048 /* XXX */ /* default only */
#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) )
+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
- 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
-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++;
+ 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
- * 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 =
- 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 */
- 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",
- 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;
- 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)
{
- int errcode = 0;
- int unit, part;
+ errval errcode = 0;
+ u_int32 unit, part;
struct cd_parms cd_parms;
struct cd_data *cd;
+ struct scsi_link *sc_link;
+ u_int32 heldflags;
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)))
- 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);
-#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;
- 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++;
- 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);
- /*******************************************************\
- * 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;
}
- /*******************************************************\
- * 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 it's a null transfer, return immediatly *
- \*******************************************************/
+ /*
+ * If it's a null transfer, return immediatly
+ */
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
*/
- 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 */
}
-
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);
- /*******************************************************\
- * 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;
-bad:
+ bad:
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);
- 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)
-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;
- if ((bp = dp->b_actf) != NULL) /* yes, an assign */
- {
+ if ((bp = dp->b_actf) != NULL) { /* yes, an assign */
dp->b_actf = bp->av_forw;
- }
- else
- {
+ } else {
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);
- /* 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));
- 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;
- 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)
{
- 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;
-
- /*******************************************************\
- * Find the device that the user is talking about *
- \*******************************************************/
+ /*
+ * Find the device that the user is talking about
+ */
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:
- error = EINVAL;
+ error = EINVAL;
break;
case DIOCGDINFO:
- *(struct disklabel *)addr = cd->disklabel;
+ *(struct disklabel *) addr = cd->disklabel;
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:
{
- 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;
- if(error = cd_set_mode(unit,&data))
+ if (error = cd_set_mode(unit, &data))
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:
{
- 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;
- if(error = cd_set_mode(unit,&data))
+ if (error = cd_set_mode(unit, &data))
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:
{
- 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;
- if(error = cd_set_mode(unit,&data))
+ if (error = cd_set_mode(unit, &data))
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
- = (struct ioc_read_subchannel *)addr;
+ = (struct ioc_read_subchannel *) addr;
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;
}
- 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;
}
- 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;
- if( error = cd_read_toc(unit,0,0,&th,sizeof(th)))
+ if (error = cd_read_toc(unit, 0, 0, &th, sizeof(th)))
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:
{
- 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;
- 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;
- 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:
{
- 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];
- if(error = cd_set_mode(unit,&data))
- break;
+ if (error = cd_set_mode(unit, &data))
+ break; /* eh? */
}
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;
@@ -941,148 +740,146 @@ cdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
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];
- if(error = cd_set_mode(unit,&data))
+ if (error = cd_set_mode(unit, &data))
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;
- 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;
- if(error = cd_set_mode(unit,&data))
+ if (error = cd_set_mode(unit, &data))
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;
- if(error = cd_set_mode(unit,&data))
+ if (error = cd_set_mode(unit, &data))
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;
- if(error = cd_set_mode(unit,&data))
+ if (error = cd_set_mode(unit, &data))
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;
- if(error = cd_set_mode(unit,&data))
+ if (error = cd_set_mode(unit, &data))
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;
- if(error = cd_set_mode(unit,&data))
+ if (error = cd_set_mode(unit, &data))
break;
}
break;
case CDIOCRESUME:
- error = cd_pause(unit,1);
+ error = cd_pause(unit, 1);
break;
case CDIOCPAUSE:
- error = cd_pause(unit,0);
+ error = cd_pause(unit, 0);
break;
case CDIOCSTART:
- error = cd_start_unit(unit,part,CD_START);
+ error = scsi_start_unit(cd->sc_link, 0);
break;
case CDIOCSTOP:
- error = cd_start_unit(unit,part,CD_STOP);
+ error = scsi_start_unit(cd->sc_link, 0);
break;
case CDIOCEJECT:
- error = cd_start_unit(unit,part,CD_EJECT);
+ error = scsi_start_unit(cd->sc_link, 0);
break;
case CDIOCSETDEBUG:
- scsi_debug = 0xfff; cd_debug = 0xfff;
+ cd->sc_link->flags |= (SDEV_DB1 | SDEV_DB2);
break;
case CDIOCCLRDEBUG:
- scsi_debug = 0; cd_debug = 0;
+ cd->sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
break;
case CDIOCRESET:
- return(cd_reset(unit));
+ return (cd_reset(unit));
break;
default:
- error = ENOTTY;
+ if(part == RAW_PART)
+ error = scsi_do_ioctl(cd->sc_link,cmd,addr,flag);
+ else
+ error = ENOTTY;
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;
- 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;
@@ -1092,129 +889,118 @@ unsigned char unit;
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_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));
- /*******************************************************\
- * 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)
{
- 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;
- /*******************************************************\
- * 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);
- return(0);
+ return (0);
} 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;
- blksize = rdcap.length_0 ;
+ blksize = rdcap.length_0;
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;
- int retval;
+ errval retval;
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;
- 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);
}
-/*******************************************************\
-* 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;
@@ -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;
- /*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;
- int retval;
+ errval retval;
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;
- 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;
- int retval;
+ errval retval;
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;
- 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;
- int retval;
+ errval retval;
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;
- 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;
- 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;
@@ -1353,534 +1149,132 @@ int unit,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;
- 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.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,
+ CDRETRIES,
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;
- 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))
- 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,
- 0);
+ SCSI_DATA_IN));
}
-
#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);
}
-
-#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
diff --git a/sys/scsi/ch.c b/sys/scsi/ch.c
index a76d522..c403fe5 100644
--- a/sys/scsi/ch.c
+++ b/sys/scsi/ch.c
@@ -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>
@@ -17,965 +18,464 @@
#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>
-
-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 CH_RETRIES 4
-
+#define CHRETRIES 2
#define MODE(z) ( (minor(z) & 0x0F) )
#define UNIT(z) ( (minor(z) >> 4) )
-#ifndef MACH
#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
-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;
- 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++;
- 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);
- 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;
}
-
-
-/*******************************************************\
-* open the device. *
-\*******************************************************/
+/*
+ * open the device.
+ */
+errval
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);
- /*******************************************************\
- * 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;
- 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;
- 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)
{
- unsigned char unit,mode;
+ unsigned char unit, mode;
+ struct scsi_link *sc_link;
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;
- 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)
-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;
- register i,j;
- unsigned int opri;
- int errcode = 0;
+ register i, j;
+ u_int32 opri;
+ errval errcode = 0;
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);
-
- 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:
- 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;
- 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;
- 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;
}
-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;
- int ret;
+ errval ret;
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;
}
-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;
- int ret;
+ errval ret;
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
-/*******************************************************\
-* 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)
-int unit,flags;
+ u_int32 unit, flags;
{
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;
- 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);
- 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
- 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
- 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;
- 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:
- 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);
}
-
-
-
diff --git a/sys/scsi/scsi_all.h b/sys/scsi/scsi_all.h
index 8de19b0..2e7bdcf 100644
--- a/sys/scsi/scsi_all.h
+++ b/sys/scsi/scsi_all.h
@@ -18,12 +18,11 @@
*
* 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
*/
@@ -31,10 +30,10 @@
/*
* 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 */
@@ -103,7 +102,7 @@ struct scsi_mode_sense
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];
@@ -124,7 +123,7 @@ struct scsi_mode_select
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;
@@ -159,6 +158,19 @@ struct scsi_prevent
#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
*/
@@ -173,6 +185,7 @@ struct scsi_prevent
#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
@@ -234,62 +247,62 @@ struct scsi_inquiry_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
{
- u_char blockhi;
- u_char blockmed;
- u_char blocklow;
+/* 2*/ u_char blockhi;
+/* 3*/ u_char blockmed;
+/* 4*/ u_char blocklow;
} 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
- ( 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;
-};
+}; /* total of 32 bytes */
struct scsi_sense_data_new
{
- u_char error_code;
+/* 1*/ u_char error_code;
#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
{
- 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
- 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
- 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;
-};
+}; /* total of 32 bytes */
struct blk_desc
{
@@ -324,4 +337,4 @@ struct scsi_mode_header_big
#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
index 0000000..a1361ec
--- /dev/null
+++ b/sys/scsi/scsi_base.c
@@ -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 */
diff --git a/sys/scsi/scsi_cd.h b/sys/scsi/scsi_cd.h
index e9e80de..0a4759b 100644
--- a/sys/scsi/scsi_cd.h
+++ b/sys/scsi/scsi_cd.h
@@ -14,11 +14,10 @@
*
* 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)
@@ -142,6 +141,7 @@ struct scsi_read_toc
u_char data_len[2];
u_char control;
};
+;
struct scsi_read_cd_capacity
{
@@ -225,5 +225,5 @@ struct cd_mode_data
struct blk_desc blk_desc;
union cd_pages page;
};
+#endif /*_SCSI_SCSI_CD_H*/
-#endif /* _SCSI_SCSI_CD_H_ */
diff --git a/sys/scsi/scsi_changer.h b/sys/scsi/scsi_changer.h
index dda22ee..85819c8 100644
--- a/sys/scsi/scsi_changer.h
+++ b/sys/scsi/scsi_changer.h
@@ -19,11 +19,10 @@
*
* 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
@@ -95,5 +94,5 @@ struct element_status_page
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
index 0000000..480ff14
--- /dev/null
+++ b/sys/scsi/scsi_debug.h
@@ -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 */
+
diff --git a/sys/scsi/scsi_disk.h b/sys/scsi/scsi_disk.h
index e9cb724..60d0bcc 100644
--- a/sys/scsi/scsi_disk.h
+++ b/sys/scsi/scsi_disk.h
@@ -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.
*
@@ -46,16 +46,15 @@
*
* 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
*/
+#ifndef _SCSI_SCSI_DISK_H
+#define _SCSI_SCSI_DISK_H 1
struct scsi_reassign_blocks
{
@@ -214,4 +213,4 @@ union disk_pages /* this is the structure copied from osf */
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
index 0000000..c1b576d
--- /dev/null
+++ b/sys/scsi/scsi_ioctl.c
@@ -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;
+}
+
diff --git a/sys/scsi/scsi_tape.h b/sys/scsi/scsi_tape.h
index 103e116..ac417c2 100644
--- a/sys/scsi/scsi_tape.h
+++ b/sys/scsi/scsi_tape.h
@@ -21,13 +21,12 @@
/*
* 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
@@ -200,7 +199,6 @@ struct blk_desc_cipher
#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*/
diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c
index 70765b0..708cc7c 100644
--- a/sys/scsi/scsiconf.c
+++ b/sys/scsi/scsiconf.c
@@ -14,768 +14,686 @@
*
* 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/param.h>
+#include <sys/systm.h>
+
+#include <sys/malloc.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>
-#if !defined(OSF) && !defined(__386BSD__)
+#ifdef TFS
#include "bll.h"
#include "cals.h"
#include "kil.h"
-#else
+#include "scan.h"
+#else /* TFS */
#define NBLL 0
#define NCALS 0
#define NKIL 0
-#endif /* !defined(OSF) && !defined(__386BSD__) */
+#define NSCAN 0
+#endif /* TFS */
#if NSD > 0
-extern sdattach();
-#endif NSD
+extern sdattach();
+#endif /* NSD */
#if NST > 0
-extern stattach();
-#endif NST
+extern stattach();
+#endif /* NST */
#if NCH > 0
-extern chattach();
-#endif NCH
+extern chattach();
+#endif /* NCH */
#if NCD > 0
-extern cdattach();
-#endif NCD
+extern cdattach();
+#endif /* NCD */
#if NBLL > 0
-extern bllattach();
-#endif NBLL
+extern bllattach();
+#endif /* NBLL */
#if NCALS > 0
-extern calsattach();
-#endif NCALS
+extern calsattach();
+#endif /* NCALS */
#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
- {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
-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
- { 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
- { 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
- { 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
- { 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
- { 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
- { 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
- { 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",
- 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
-#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;
}
- 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 */
}
- /* 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;
- if(pd[upto].dev != target)
+ if (pd[upto].dev != target)
continue;
- if(pd[upto].lu != lu)
+ if (pd[upto].lu != lu)
continue;
-
+
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;
- 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
- 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;
-
- /* 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:
- qtype="";
+ qtype = "";
break;
case SID_QUAL_LU_OFFLINE:
- qtype=", Unit not Connected!";
+ qtype = ", Unit not Connected!";
break;
case SID_QUAL_RSVD:
- qtype=", Reserved Peripheral Qualifier!";
+ qtype = ", Reserved Peripheral Qualifier!";
*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
- * 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;
- return (struct scsidevs *)0;
+ return (struct scsidevs *) 0;
default:
- dtype="vendor specific";
- qtype="";
+ dtype = "vendor specific";
+ qtype = "";
*maybe_more = 1;
break;
}
-
- if (dtype == 0)
- {
- switch(type)
- {
+ if (dtype == 0) {
+ switch (type) {
case T_DIRECT:
- dtype="direct";
+ dtype = "direct";
break;
case T_SEQUENTIAL:
- dtype="sequential";
+ dtype = "sequential";
break;
case T_PRINTER:
- dtype="printer";
+ dtype = "printer";
break;
case T_PROCESSOR:
- dtype="processor";
+ dtype = "processor";
break;
case T_READONLY:
- dtype="readonly";
+ dtype = "readonly";
break;
case T_WORM:
- dtype="worm";
+ dtype = "worm";
break;
case T_SCANNER:
- dtype="scanner";
+ dtype = "scanner";
break;
case T_OPTICAL:
- dtype="optical";
+ dtype = "optical";
break;
case T_CHANGER:
- dtype="changer";
+ dtype = "changer";
break;
case T_COMM:
- dtype="communication";
+ dtype = "communication";
break;
case T_NODEVICE:
*maybe_more = 1;
- return (struct scsidevs *)0;
+ return (struct scsidevs *) 0;
default:
- dtype="unknown";
+ dtype = "unknown";
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"
- ,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"
- ,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"
- ,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;
}
- 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--;
- while( count++ < numents)
- {
+ while (count++ < numents) {
thisentry++;
- if(type != thisentry->type)
- {
+ if (type != thisentry->type) {
continue;
}
- if(bestmatches < 1)
- {
+ if (bestmatches < 1) {
bestmatches = 1;
bestmatch = thisentry;
}
- if(remov != thisentry->removable)
- {
+ if (remov != thisentry->removable) {
continue;
}
- if(bestmatches < 2)
- {
+ if (bestmatches < 2) {
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;
}
- if(bestmatches < 3)
- {
+ if (bestmatches < 3) {
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;
}
- if(bestmatches < 4)
- {
+ if (bestmatches < 4) {
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;
}
- if(bestmatches < 5)
- {
+ if (bestmatches < 5) {
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);
-}
-
diff --git a/sys/scsi/scsiconf.h b/sys/scsi/scsiconf.h
index 5738de5..856fe89 100644
--- a/sys/scsi/scsiconf.h
+++ b/sys/scsi/scsiconf.h
@@ -14,88 +14,179 @@
*
* 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 HAD_ERROR 3
+#define HAD_ERROR 3 /* do not use this, use COMPLETE */
#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 *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.
*/
- 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_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 */
@@ -107,18 +198,18 @@ struct scsi_xfer
#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
-/********************************/
-/* 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 */
@@ -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? */
-#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 */
diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c
index 6717449..b3320aa3 100644
--- a/sys/scsi/sd.c
+++ b/sys/scsi/sd.c
@@ -14,7 +14,7 @@
*
* 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
@@ -37,20 +37,26 @@
#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
-int Debugger();
-#else NDDB > 0
+int Debugger();
+#else /* NDDB > 0 */
#define Debugger()
-#endif NDDB > 0
-
+#endif /* NDDB > 0 */
+#endif
#define PAGESIZ 4096
#define SECSIZE 512
-#define PDLOCATION 29
+#define PDLOCATION 29
#define BOOTRECORDSIGNATURE (0x55aa & 0x00ff)
#define SDOUTSTANDING 2
#define SDQSIZE 4
@@ -64,838 +70,704 @@ int Debugger();
#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
- 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;
- long int ad_info;
- struct scsi_xfer *sd_scsi_xfer;
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");
- 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;
}
- }
- else
- {
+ } else {
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",
- 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;
- 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)
+ 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];
-#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();
- 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);
-#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];
-#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);
- /*******************************************************\
- * 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;
}
- /*******************************************************\
- * "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 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;
}
-
- /*******************************************************\
- * 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;
}
-
/*
* 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 */
}
-
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);
- /*******************************************************\
- * 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);
- return;
+ return 0;
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);
- 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)
-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),
- (u_char *)bp->b_un.b_addr,
+ (u_char *) bp->b_un.b_addr,
bp->b_bcount,
+ SD_RETRIES,
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:
- 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)
{
- /* 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;
-
- /*******************************************************\
- * 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];
-#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:
- error = EINVAL;
+ error = EINVAL;
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;
- 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;
}
- break;
+ break;
- case DIOCWLABEL:
+ case DIOCWLABEL:
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;
- 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:
- error = ENOTTY;
+ if (part == RAW_PART)
+ error = scsi_do_ioctl(sd->sc_link, cmd, addr, flag);
+ else
+ error = ENOTTY;
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];
- /*******************************************************\
- * 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_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;
- if (sd->disklabel.d_secpercyl == 0)
- {
+ if (sd->disklabel.d_secpercyl == 0) {
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)
+ int unit, flags;
{
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;
- /*******************************************************\
- * 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);
- return(0);
+ return (0);
} 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;
}
- 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));
@@ -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.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 )
-/*******************************************************\
-* 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 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;
- /*******************************************************\
- * 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");
/*
@@ -1017,631 +848,212 @@ int sd_get_parms(unit, flags)
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;
- }
- 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),
- 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->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);
- 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;
- 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>
-/***********************************************************************\
-* 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 */
- 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;
- struct scsi_rw_big cmd;
+ struct scsi_rw_big cmd;
extern int Maxmem;
- static sddoingadump = 0 ;
- extern caddr_t CADDR1; /* map the page we are about to write, here*/
- struct scsi_xfer *xs = &sx;
- int retval;
+ 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 */
- while (sgetc(1))
- ;
+ while ((c = sgetc(1)) && (c != 0x100)); /*syscons and pccons differ */
/* 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 */
- if (unit >= NSD) return(ENXIO); /* 31 Jul 92*/
+ if (unit >= NSD)
+ return (ENXIO); /* 31 Jul 92 */
sd = sd_data[unit];
- if(!sd) return (ENXIO);
+ if (!sd)
+ return (ENXIO);
/* was it ever initialized etc. ? */
- if (!(sd->flags & SDINIT)) return (ENXIO);
- if (sd->flags & SDVALID != SDVALID) return (ENXIO) ;
- if (sd->flags & SDWRITEPROT) return (ENXIO);
+ 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 */
- num = (u_long) num * NBPG / sd->disklabel.d_secsize;
+ num = (u_int32) num * NBPG / sd->disklabel.d_secsize;
/* 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))
- return(EINVAL);
+ return (EINVAL);
- sddoingadump = 1 ;
+ sddoingadump = 1;
blknum = dumplo + blkoff;
- while (num > 0)
- {
- if (blkcnt > MAXTRANSFER) blkcnt = MAXTRANSFER;
- pmap_enter( kernel_pmap,
- CADDR1,
- trunc_page(addr),
- VM_PROT_READ,
- TRUE);
+ /* blkcnt = initialise_me; */
+ while (num > 0) {
+ pmap_enter(kernel_pmap,
+ MAPTO,
+ trunc_page(addr),
+ VM_PROT_READ,
+ TRUE);
#ifndef NOT_TRUSTED
- /*******************************************************\
- * Fill out the scsi command *
- \*******************************************************/
+ /*
+ * Fill out the scsi command
+ */
bzero(&cmd, sizeof(cmd));
- cmd.op_code = WRITE_BIG;
- cmd.addr_3 = (blknum & 0xff000000) >> 24;
- cmd.addr_2 = (blknum & 0xff0000) >> 16;
- cmd.addr_1 = (blknum & 0xff00) >> 8;
- cmd.addr_0 = blknum & 0xff;
- cmd.length2 = (blkcnt & 0xff00) >> 8;
- cmd.length1 = (blkcnt & 0xff);
- /*******************************************************\
- * Fill out the scsi_xfer structure *
- * Note: we cannot sleep as we may be an interrupt *
- \*******************************************************/
+ 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));
- 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:
- 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 */
- num -= MAXTRANSFER;
- blknum += MAXTRANSFER ;
- (int) addr += 512 * MAXTRANSFER;
+ num -= blkcnt;
+ blknum += blkcnt;
+ (int) addr += 512 * blkcnt;
/* 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");
- DELAY(20000000); /* 20 seconds */
- return(-1);
+ DELAY(60000000); /* 60 seconds */
+ return -1;
}
-#endif SCSIDUMP
-
+#endif /* SCSIDUMP */
diff --git a/sys/scsi/st.c b/sys/scsi/st.c
index e367389..08c8d467 100644
--- a/sys/scsi/st.c
+++ b/sys/scsi/st.c
@@ -12,13 +12,24 @@
* 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
*
- * $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
@@ -41,886 +52,882 @@
#include <sys/user.h>
#include <sys/mtio.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
-#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 DSTY3 3
-#define DSTY2 2
-#define DSTY1 1
+#define CTLMODE 3
#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 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_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 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.----------------*/
- 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----------------------------------*/
- 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 ----------------------*/
- 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--------*/
- 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------------------------------*/
- 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----*/
- 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------------*/
- 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_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_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_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)
-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;
-#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++;
- if( unit >= NST)
- {
+
+ if (unit >= NST) {
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);
- /*******************************************************\
- * 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);
- }
- 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);
- }
- else
- {
+ } else {
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;
- 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)
-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;
}
- 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;
+ 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;
}
- 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;
- while(finger->name)
- {
+ while (finger->name) {
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;
- 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;
- }
- else
- {
+ } else {
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)
-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 scsi_link *sc_link;
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];
- /*******************************************************\
- * Make sure the device has been initialised *
- \*******************************************************/
+ /*
+ * Make sure the device has been initialised
+ */
if ((st == NULL) || (!(st->flags & ST_INITIALIZED)))
- return(ENXIO);
-
- /*******************************************************\
- * Only allow one at a time *
- \*******************************************************/
- if(st->flags & ST_OPEN)
- {
- return(ENXIO);
+ 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);
}
-
- /*******************************************************\
- * 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);
+ /*
+ * 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);
}
-
- /*******************************************************\
- * 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;
+ /*
+ * 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);
}
- 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);
- }
- }
-
- /*******************************************************\
- * 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);
- }
-
- 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. *
- \*******************************************************/
- }
-
- /***************************************************************\
- * 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;
- 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;
- 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)
+ 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];
-
-#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;
- break;
- case 1: /*non rewind*/
- if((st->flags & (ST_WRITTEN | ST_FM_WRITTEN)) == ST_WRITTEN)
- st_write_filemarks(unit, 1, 0);
+ 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;
- 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;
- 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;
- 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);
- 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;
- else if(st->media_blksiz > 0)
+ else if (st->media_blksiz > 0)
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;
- case ST_Q_FORCE_VAR_MODE:
+ case ST_Q_FORCE_VAR_MODE:
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;
}
-
- /***************************************************************\
- * 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;
-#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;
}
-
- /***************************************************************\
- * 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;
-#ifdef STDEBUG
- if(st_debug) printf("density specified variable\n");
-#endif /*STDEBUG*/
+ SC_DEBUG(sc_link, SDEV_DB3, ("density specified variable\n"));
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;
- if (st->media_blksiz > 0)
+ if (st->media_blksiz > 0) {
st->blksiz = st->media_blksiz;
- else
+ } else {
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;
}
-
- /***************************************************************\
- * 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;
- else
+ } else {
st->flags |= ST_FIXEDBLOCKS;
+ }
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;
}
-
- /***************************************************************\
- * 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;
-#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:
- 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 int opri;
+ u_int32 opri;
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;
}
-
- /*******************************************************\
- * 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",
- unit, st->blksiz);
+ unit, st->blksiz);
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",
- unit, st->blkmin, st->blkmax);
+ unit, st->blkmin, st->blkmax);
bp->b_error = EIO;
goto bad;
}
-
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);
- while (*dp)
- {
+ while (*dp) {
dp = &((*dp)->b_actf);
- }
+ }
*dp = bp;
bp->b_actf = NULL;
- /*******************************************************\
- * Tell the device to get going on the transfer if it's *
- * not doing anything, otherwise just wait for completion*
- * (All a bit silly if we're only allowing 1 open but..) *
- \*******************************************************/
+ /*
+ * 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);
@@ -928,1443 +935,993 @@ struct buf *bp;
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;
}
+/*
+ * 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;
- 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);
- st = st_data[unit];
+ st = st_data[unit];
+ hold_blksiz = st->blksiz;
+ hold_density = st->density;
- switch(cmd)
- {
+ switch (cmd) {
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:
- {
- 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;
- }
- 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;
}
- 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;
}
- else
- {
- st->modes[dsty].density = number;
- }
break;
-
- default:
- errcode = EINVAL;
}
- break;
- }
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;
+/*-----------------------------*/
+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];
- /*******************************************************\
- * 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;
- 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
-/*******************************************************\
-* 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)
-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];
- 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;
- /*******************************************************\
- * 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;
- }
+ }
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;
}
-/*******************************************************\
-* 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)
-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;
- }
- else
- {
+ } else {
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;
- /*******************************************************\
- * 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;
- }
- 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;
-#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;
}
-/*******************************************************\
-* 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)
-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 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;
- }
- else
- {
+ } else {
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;
- ((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 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;
- 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);
- 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;
- return(EIO);
+ return (EIO);
}
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;
- return(EIO);
- }
- else if (number < 0)
+ return (EIO);
+ } else if (number < 0) { /* back away from the error */
st->flags &= ~ST_EIO_PENDING;
+ }
}
- if (st->flags & ST_AT_FILEMARK)
- {
+ if (st->flags & ST_AT_FILEMARK) {
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;
- 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;
- 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 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;
- case 1:
- if (st->flags & ST_FM_WRITTEN)
+ case 1:
+ if (st->flags & ST_FM_WRITTEN) { /* already have one down */
st->flags &= ~ST_WRITTEN;
- else
+ } else {
st->flags |= ST_FM_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;
- 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)
-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;
- 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;
- case ST_WRITTEN | ST_2FM_AT_EOD:
+ case ST_WRITTEN | ST_2FM_AT_EOD:
*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);
}
-/*******************************************************\
-* 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));
- 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);
- 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;
- 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);
- if (error != ESUCCESS) return(error);
+ if (error != ESUCCESS)
+ return (error);
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;
- 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
- 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;
- }
- 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;
+ 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
}
- 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:
- 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
index 0000000..de4f017
--- /dev/null
+++ b/sys/scsi/su.c
@@ -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
index 0000000..5c48d01
--- /dev/null
+++ b/sys/scsi/uk.c
@@ -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));
+}
+
diff --git a/sys/sys/chio.h b/sys/sys/chio.h
index 1106e2f..10fa51d 100644
--- a/sys/sys/chio.h
+++ b/sys/sys/chio.h
@@ -1,7 +1,7 @@
/*
* 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
@@ -11,8 +11,8 @@
/*
* 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
@@ -88,4 +88,5 @@ struct chop {
/* Changer IO control command */
#define CHIOOP _IOWR('c', 1, struct chop) /* do a mag tape op */
-#endif
+
+#endif /*_SYS_CHIO_H*/
diff --git a/sys/sys/scsiio.h b/sys/sys/scsiio.h
new file mode 100644
index 0000000..05753e4
--- /dev/null
+++ b/sys/sys/scsiio.h
@@ -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_ */
OpenPOWER on IntegriCloud