summaryrefslogtreecommitdiffstats
path: root/sys/dev/isa
diff options
context:
space:
mode:
authorderaadt <deraadt@openbsd.org>1996-04-21 22:14:33 +0000
committerderaadt <deraadt@openbsd.org>1996-04-21 22:14:33 +0000
commitd724e01ae4dac35949585b9083e28ff2ba35b0b5 (patch)
tree37282f1ae947a4e9508b73ff86cad13f75eb9860 /sys/dev/isa
parentno need to remove limits.h; another workaround exists (diff)
downloadwireguard-openbsd-d724e01ae4dac35949585b9083e28ff2ba35b0b5.tar.xz
wireguard-openbsd-d724e01ae4dac35949585b9083e28ff2ba35b0b5.zip
partial sync with netbsd 960418, more to come
Diffstat (limited to 'sys/dev/isa')
-rw-r--r--sys/dev/isa/aha.c1662
-rw-r--r--sys/dev/isa/aha1542.c1587
-rw-r--r--sys/dev/isa/aha284x.c19
-rw-r--r--sys/dev/isa/ahareg.h264
-rw-r--r--sys/dev/isa/aic6360.c939
-rw-r--r--sys/dev/isa/ast.c33
-rw-r--r--sys/dev/isa/boca.c33
-rw-r--r--sys/dev/isa/bt.c1194
-rw-r--r--sys/dev/isa/bt742a.c1528
-rw-r--r--sys/dev/isa/btreg.h304
-rw-r--r--sys/dev/isa/com.c116
-rw-r--r--sys/dev/isa/comvar.h5
-rw-r--r--sys/dev/isa/fd.c36
-rw-r--r--sys/dev/isa/files.isa134
-rw-r--r--sys/dev/isa/gus.c21
-rw-r--r--sys/dev/isa/if_ed.c777
-rw-r--r--sys/dev/isa/if_eg.c22
-rw-r--r--sys/dev/isa/if_el.c25
-rw-r--r--sys/dev/isa/if_ep.c50
-rw-r--r--sys/dev/isa/if_fe.c22
-rw-r--r--sys/dev/isa/if_ie.c24
-rw-r--r--sys/dev/isa/if_le.c50
-rw-r--r--sys/dev/isa/isa.c20
-rw-r--r--sys/dev/isa/isadma.c13
-rw-r--r--sys/dev/isa/isavar.h29
-rw-r--r--sys/dev/isa/lpt.c50
-rw-r--r--sys/dev/isa/mcd.c26
-rw-r--r--sys/dev/isa/pas.c20
-rw-r--r--sys/dev/isa/pss.c56
-rw-r--r--sys/dev/isa/rtfps.c33
-rw-r--r--sys/dev/isa/sb.c26
-rw-r--r--sys/dev/isa/seagate.c16
-rw-r--r--sys/dev/isa/ultra14f.c16
-rw-r--r--sys/dev/isa/wd.c44
-rw-r--r--sys/dev/isa/wd7000.c747
-rw-r--r--sys/dev/isa/wds.c1306
-rw-r--r--sys/dev/isa/wdsreg.h147
-rw-r--r--sys/dev/isa/wss.c20
-rw-r--r--sys/dev/isa/wt.c26
39 files changed, 4859 insertions, 6581 deletions
diff --git a/sys/dev/isa/aha.c b/sys/dev/isa/aha.c
index 4a0bb77f998..d8a95ec3f85 100644
--- a/sys/dev/isa/aha.c
+++ b/sys/dev/isa/aha.c
@@ -1,8 +1,10 @@
-/* $OpenBSD: aha.c,v 1.13 1996/03/20 01:00:35 mickey Exp $ */
-/* $NetBSD: aha1542.c,v 1.55 1995/12/24 02:31:06 mycroft Exp $ */
+/* $NetBSD: aha.c,v 1.7 1996/04/11 22:27:59 cgd Exp $ */
+
+#define AHADIAG
+#define integrate
/*
- * Copyright (c) 1994 Charles Hannum. All rights reserved.
+ * Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -14,7 +16,7 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by Charles Hannum.
+ * This product includes software developed by Charles M. Hannum.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
@@ -45,13 +47,8 @@
* functioning of this software in any circumstances.
*/
-/*
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- */
-
#include <sys/types.h>
#include <sys/param.h>
-#include <sys/syslog.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/errno.h>
@@ -64,99 +61,25 @@
#include <machine/pio.h>
-#include <dev/isa/isavar.h>
-#include <dev/isa/isadmavar.h>
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
+#include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
+#include <dev/isa/ahareg.h>
+
#ifndef DDB
#define Debugger() panic("should call debugger here (aha1542.c)")
#endif /* ! DDB */
-/* XXX fixme:
- * on i386 at least, xfers to/from user memory
- * cannot be serviced at interrupt time.
- */
-#ifdef i386
-#define VOLATILE_XS(xs) \
- ((xs)->datalen > 0 && (xs)->bp == NULL && \
- ((xs)->flags & SCSI_POLL) == 0)
-#else
-#define VOLATILE_XS(xs) 0
-#endif
-
-#undef TUNE_1542 /* if bus speed check breaks the machine, undefine it */
-
-/************************** board definitions *******************************/
-
-/*
- * I/O Port Interface
- */
-#define AHA_BASE aha->sc_iobase
-#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 */
-
-/*
- * AHA_CTRL_STAT bits (write)
- */
-#define AHA_HRST 0x80 /* Hardware reset */
-#define AHA_SRST 0x40 /* Software reset */
-#define AHA_IRST 0x20 /* Interrupt reset */
-#define AHA_SCRST 0x10 /* SCSI bus reset */
-
-/*
- * AHA_CTRL_STAT bits (read)
- */
-#define AHA_STST 0x80 /* Self test in Progress */
-#define AHA_DIAGF 0x40 /* Diagnostic Failure */
-#define AHA_INIT 0x20 /* Mbx Init required */
-#define AHA_IDLE 0x10 /* Host Adapter Idle */
-#define AHA_CDF 0x08 /* cmd/data out port full */
-#define AHA_DF 0x04 /* Data in port full */
-#define AHA_INVDCMD 0x01 /* Invalid command */
-
/*
- * AHA_CMD_DATA bits (write)
- */
-#define AHA_NOP 0x00 /* No operation */
-#define AHA_MBX_INIT 0x01 /* Mbx initialization */
-#define AHA_START_SCSI 0x02 /* start scsi command */
-#define AHA_START_BIOS 0x03 /* start bios command */
-#define AHA_INQUIRE 0x04 /* Adapter Inquiry */
-#define AHA_MBO_INTR_EN 0x05 /* Enable MBO available interrupt */
-#define AHA_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
-#define AHA_BUS_ON_TIME_SET 0x07 /* set bus-on time */
-#define AHA_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
-#define AHA_SPEED_SET 0x09 /* set transfer speed */
-#define AHA_DEV_GET 0x0a /* return installed devices */
-#define AHA_CONF_GET 0x0b /* return configuration data */
-#define AHA_TARGET_EN 0x0c /* enable target mode */
-#define AHA_SETUP_GET 0x0d /* return setup data */
-#define AHA_WRITE_CH2 0x1a /* write channel 2 buffer */
-#define AHA_READ_CH2 0x1b /* read channel 2 buffer */
-#define AHA_WRITE_FIFO 0x1c /* write fifo buffer */
-#define AHA_READ_FIFO 0x1d /* read fifo buffer */
-#define AHA_ECHO 0x1e /* Echo command data */
-#define AHA_EXT_BIOS 0x28 /* return extended bios info */
-#define AHA_MBX_ENABLE 0x29 /* enable mail box interface */
-
-/*
- * AHA_INTR_PORT bits (read)
- */
-#define AHA_ANY_INTR 0x80 /* Any interrupt */
-#define AHA_SCRD 0x08 /* SCSI reset detected */
-#define AHA_HACC 0x04 /* Command complete */
-#define AHA_MBOA 0x02 /* MBX out empty */
-#define AHA_MBIF 0x01 /* MBX in full */
-
-/*
- * Mail box defs
+ * Mail box defs etc.
+ * these could be bigger but we need the aha_softc to fit on a single page..
*/
#define AHA_MBX_SIZE 16 /* mail box size */
-#define AHA_CCB_MAX 32 /* store up to 32 CCBs at one time */
-#define CCB_HASH_SIZE 32 /* hash table size for phystokv */
+#define AHA_CCB_MAX 16 /* store up to 32 CCBs at one time */
+#define CCB_HASH_SIZE 16 /* hash table size for phystokv */
#define CCB_HASH_SHIFT 9
#define CCB_HASH(x) ((((long)(x))>>CCB_HASH_SHIFT) & (CCB_HASH_SIZE - 1))
@@ -166,165 +89,15 @@
else \
(wmb)++;
-struct aha_mbx_out {
- u_char cmd;
- u_char ccb_addr[3];
-};
-
-struct aha_mbx_in {
- u_char stat;
- u_char ccb_addr[3];
-};
-
struct aha_mbx {
struct aha_mbx_out mbo[AHA_MBX_SIZE];
struct aha_mbx_in mbi[AHA_MBX_SIZE];
+ struct aha_mbx_out *cmbo; /* Collection Mail Box out */
struct aha_mbx_out *tmbo; /* Target Mail Box out */
struct aha_mbx_in *tmbi; /* Target Mail Box in */
};
-/*
- * mbo.cmd values
- */
-#define AHA_MBO_FREE 0x0 /* MBO entry is free */
-#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 */
-
-/* FOR OLD VERSIONS OF THE !%$@ this may have to be 16 (yuk) */
-#define AHA_NSEG 17 /* Number of scatter gather segments <= 16 */
- /* allow 60 K i/o (min) */
-
-struct aha_ccb {
- u_char opcode;
- u_char lun:3;
- u_char data_in:1; /* must be 0 */
- u_char data_out:1; /* must be 0 */
- u_char target:3;
- u_char scsi_cmd_length;
- u_char req_sense_length;
- u_char data_length[3];
- u_char data_addr[3];
- u_char link_addr[3];
- u_char link_id;
- u_char host_stat;
- u_char target_stat;
- u_char reserved[2];
- struct scsi_generic scsi_cmd;
- struct scsi_sense_data scsi_sense;
- struct aha_scat_gath {
- u_char seg_len[3];
- u_char seg_addr[3];
- } scat_gath[AHA_NSEG];
- /*----------------------------------------------------------------*/
-#define CCB_PHYS_SIZE ((int)&((struct aha_ccb *)0)->chain)
- TAILQ_ENTRY(aha_ccb) chain;
- struct aha_ccb *nexthash;
- struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
- int flags;
-#define CCB_FREE 0
-#define CCB_ACTIVE 1
-#define CCB_ABORTED 2
- struct aha_mbx_out *mbx; /* pointer to mail box */
- struct isadma_seg ccb_phys[1]; /* phys segment of this ccb */
- struct isadma_seg data_phys[AHA_NSEG]; /* phys segments of data */
- int data_nseg; /* number of phys segments of data */
-};
-
-/*
- * 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 scatter gather */
-#define AHA_RESET_CCB 0x81 /* SCSI Bus reset */
-
-/*
- * aha_ccb.host_stat values
- */
-#define AHA_OK 0x00 /* cmd ok */
-#define AHA_LINK_OK 0x0a /* Link cmd ok */
-#define AHA_LINK_IT 0x0b /* Link cmd ok + int */
-#define AHA_SEL_TIMEOUT 0x11 /* Selection time out */
-#define AHA_OVER_UNDER 0x12 /* Data over/under run */
-#define AHA_BUS_FREE 0x13 /* Bus dropped at unexpected time */
-#define AHA_INV_BUS 0x14 /* Invalid bus phase/sequence */
-#define AHA_BAD_MBO 0x15 /* Incorrect MBO cmd */
-#define AHA_BAD_CCB 0x16 /* Incorrect ccb opcode */
-#define AHA_BAD_LINK 0x17 /* Not same values of LUN for links */
-#define AHA_INV_TARGET 0x18 /* Invalid target direction */
-#define AHA_CCB_DUP 0x19 /* Duplicate CCB received */
-#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_config {
- u_char chan;
- u_char intr;
- u_char scsi_dev:3;
- u_char:5;
-};
-
-struct aha_inquire {
- u_char boardid; /* type of board */
- /* 0x31 = AHA-1540 */
- /* 0x41 = AHA-1540A/1542A/1542B */
- /* 0x42 = AHA-1640 */
- /* 0x43 = AHA-1542C */
- /* 0x44 = AHA-1542CF */
- /* 0x45 = AHA-1542CF, BIOS v2.01 */
- u_char spec_opts; /* special options ID */
- /* 0x41 = Board is standard model */
- u_char revision_1; /* firmware revision [0-9A-Z] */
- u_char revision_2; /* firmware revision [0-9A-Z] */
-};
-
-struct aha_extbios {
- u_char flags; /* Bit 3 == 1 extended bios enabled */
- u_char mailboxlock; /* mail box lock code to unlock it */
-};
-
-#define INT9 0x01
-#define INT10 0x02
-#define INT11 0x04
-#define INT12 0x08
-#define INT14 0x20
-#define INT15 0x40
-
-#define CHAN0 0x01
-#define CHAN5 0x20
-#define CHAN6 0x40
-#define CHAN7 0x80
-
-/*********************************** end of board definitions***************/
-
-#ifdef AHADEBUG
-int aha_debug = 1;
-#endif /*AHADEBUG */
+#define KVTOPHYS(x) vtophys(x)
struct aha_softc {
struct device sc_dev;
@@ -334,28 +107,40 @@ struct aha_softc {
int sc_iobase;
int sc_irq, sc_drq;
- struct aha_mbx aha_mbx; /* all the mailboxes */
- struct aha_ccb *ccbhash[CCB_HASH_SIZE];
- TAILQ_HEAD(, aha_ccb) free_ccb;
- int numccbs;
- int aha_scsi_dev; /* our scsi id */
+ char sc_model[18],
+ sc_firmware[4];
+
+ struct aha_mbx sc_mbx; /* all the mailboxes */
+#define wmbx (&sc->sc_mbx)
+ struct aha_ccb *sc_ccbhash[CCB_HASH_SIZE];
+ TAILQ_HEAD(, aha_ccb) sc_free_ccb, sc_waiting_ccb;
+ int sc_numccbs, sc_mbofull;
+ int sc_scsi_dev; /* our scsi id */
struct scsi_link sc_link;
};
-int aha_cmd(); /* XXX must be varargs to prototype */
+#ifdef AHADEBUG
+int aha_debug = 1;
+#endif /* AHADEBUG */
+
+int aha_cmd __P((int, struct aha_softc *, int, u_char *, int, u_char *));
+integrate void aha_finish_ccbs __P((struct aha_softc *));
int ahaintr __P((void *));
-void aha_free_ccb __P((struct aha_softc *, struct aha_ccb *, int));
+integrate void aha_reset_ccb __P((struct aha_softc *, struct aha_ccb *));
+void aha_free_ccb __P((struct aha_softc *, struct aha_ccb *));
+integrate void aha_init_ccb __P((struct aha_softc *, struct aha_ccb *));
struct aha_ccb *aha_get_ccb __P((struct aha_softc *, int));
struct aha_ccb *aha_ccb_phys_kv __P((struct aha_softc *, u_long));
-struct aha_mbx_out *aha_send_mbo __P((struct aha_softc *, int, struct aha_ccb *));
+void aha_queue_ccb __P((struct aha_softc *, struct aha_ccb *));
+void aha_collect_mbo __P((struct aha_softc *));
+void aha_start_ccbs __P((struct aha_softc *));
void aha_done __P((struct aha_softc *, struct aha_ccb *));
-int aha_find __P((struct aha_softc *));
+int aha_find __P((struct isa_attach_args *, struct aha_softc *));
void aha_init __P((struct aha_softc *));
+void aha_inquire_setup_information __P((struct aha_softc *));
void ahaminphys __P((struct buf *));
int aha_scsi_cmd __P((struct scsi_xfer *));
int aha_poll __P((struct aha_softc *, struct scsi_xfer *, int));
-int aha_set_bus_speed __P((struct aha_softc *));
-int aha_bus_speed_check __P((struct aha_softc *, int));
void aha_timeout __P((void *arg));
struct scsi_adapter aha_switch = {
@@ -377,64 +162,75 @@ int ahaprobe __P((struct device *, void *, void *));
void ahaattach __P((struct device *, struct device *, void *));
int ahaprint __P((void *, char *));
-struct cfdriver ahacd = {
- NULL, "aha", ahaprobe, ahaattach, DV_DULL, sizeof(struct aha_softc)
+struct cfattach aha_ca = {
+ sizeof(struct aha_softc), ahaprobe, ahaattach
+};
+
+struct cfdriver aha_cd = {
+ NULL, "aha", DV_DULL
};
#define AHA_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */
+#define AHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
/*
- * aha_cmd(aha,icnt, ocnt,wait, retval, opcode, args)
+ * aha_cmd(iobase, sc, icnt, ibuf, ocnt, obuf)
+ *
* Activate Adapter command
- * icnt: number of args (outbound bytes written after opcode)
+ * icnt: number of args (outbound bytes including opcode)
+ * ibuf: argument buffer
* ocnt: number of expected returned bytes
+ * obuf: result buffer
* 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.
+ * 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
-aha_cmd(aha, icnt, ocnt, wait, retval, opcode, args)
- struct aha_softc *aha;
- int icnt, ocnt, wait;
- u_char *retval;
- unsigned opcode;
- u_char args;
+aha_cmd(iobase, sc, icnt, ibuf, ocnt, obuf)
+ int iobase;
+ struct aha_softc *sc;
+ int icnt, ocnt;
+ u_char *ibuf, *obuf;
{
- unsigned *ic = &opcode;
- u_char oc;
- register i;
- int sts;
+ const char *name;
+ register int i;
+ int wait;
+ u_char sts;
+ u_char opcode = ibuf[0];
+
+ if (sc == NULL)
+ name = sc->sc_dev.dv_xname;
+ else
+ name = "(probe)";
/*
- * multiply the wait argument by a big constant
- * zero defaults to 1 sec..
- * all wait loops are in 50uSec cycles
+ * Calculate a reasonable timeout for the command.
*/
- if (wait)
- wait *= 20000;
- else
- wait = 20000;
+ switch (opcode) {
+ case AHA_INQUIRE_DEVICES:
+ wait = 15 * 20000;
+ break;
+ default:
+ wait = 1 * 20000;
+ break;
+ }
+
/*
* 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 (opcode != AHA_MBO_INTR_EN) {
+ for (i = 20000; i; i--) { /* 1 sec? */
+ sts = inb(iobase + AHA_STAT_PORT);
+ if (sts & AHA_STAT_IDLE)
break;
delay(50);
}
if (!i) {
printf("%s: aha_cmd, host not idle(0x%x)\n",
- aha->sc_dev.dv_xname, sts);
+ name, sts);
return ENXIO;
}
}
@@ -443,71 +239,68 @@ aha_cmd(aha, icnt, ocnt, wait, retval, opcode, args)
* queue feeding to us.
*/
if (ocnt) {
- while ((inb(AHA_CTRL_STAT_PORT)) & AHA_DF)
- inb(AHA_CMD_DATA_PORT);
+ while ((inb(iobase + AHA_STAT_PORT)) & AHA_STAT_DF)
+ inb(iobase + AHA_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--) {
- sts = inb(AHA_CTRL_STAT_PORT);
for (i = wait; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (!(sts & AHA_CDF))
+ sts = inb(iobase + AHA_STAT_PORT);
+ if (!(sts & AHA_STAT_CDF))
break;
delay(50);
}
if (!i) {
- if (opcode != AHA_INQUIRE)
- printf("%s: aha_cmd, cmd/data port full\n",
- aha->sc_dev.dv_xname);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
+ if (opcode != AHA_INQUIRE_REVISION)
+ printf("%s: aha_cmd, cmd/data port full\n", name);
+ outb(iobase + AHA_CTRL_PORT, AHA_CTRL_SRST);
return ENXIO;
}
- outb(AHA_CMD_DATA_PORT, (u_char) (*ic++));
+ outb(iobase + AHA_CMD_PORT, *ibuf++);
}
/*
* 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 = wait; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts & AHA_DF)
+ sts = inb(iobase + AHA_STAT_PORT);
+ if (sts & AHA_STAT_DF)
break;
delay(50);
}
if (!i) {
- if (opcode != AHA_INQUIRE)
+ if (opcode != AHA_INQUIRE_REVISION)
printf("%s: aha_cmd, cmd/data port empty %d\n",
- aha->sc_dev.dv_xname, ocnt);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
+ name, ocnt);
+ outb(iobase + AHA_CTRL_PORT, AHA_CTRL_SRST);
return ENXIO;
}
- oc = inb(AHA_CMD_DATA_PORT);
- if (retval)
- *retval++ = oc;
+ *obuf++ = inb(iobase + AHA_DATA_PORT);
}
/*
- * Wait for the board to report a finised instruction
+ * Wait for the board to report a finished instruction.
+ * We may get an extra interrupt for the HACC signal, but this is
+ * unimportant.
*/
- i = 20000;
- while (--i) {
- sts = inb(AHA_INTR_PORT);
- if (sts & AHA_HACC)
- break;
- delay(50);
- }
- if (!i) {
- printf("%s: aha_cmd, host not finished(0x%x)\n",
- aha->sc_dev.dv_xname, sts);
- return ENXIO;
+ if (opcode != AHA_MBO_INTR_EN) {
+ for (i = 20000; i; i--) { /* 1 sec? */
+ sts = inb(iobase + AHA_INTR_PORT);
+ /* XXX Need to save this in the interrupt handler? */
+ if (sts & AHA_INTR_HACC)
+ break;
+ delay(50);
+ }
+ if (!i) {
+ printf("%s: aha_cmd, host not finished(0x%x)\n",
+ name, sts);
+ return ENXIO;
+ }
}
- outb(AHA_CTRL_STAT_PORT, AHA_IRST);
+ outb(iobase + AHA_CTRL_PORT, AHA_CTRL_IRST);
return 0;
}
@@ -522,43 +315,20 @@ ahaprobe(parent, match, aux)
struct device *parent;
void *match, *aux;
{
- struct aha_softc *aha = match;
- struct isa_attach_args *ia = aux;
+ register struct isa_attach_args *ia = aux;
#ifdef NEWCONFIG
if (ia->ia_iobase == IOBASEUNK)
return 0;
#endif
- aha->sc_iobase = ia->ia_iobase;
-
- /*
- * Try initialise a unit at this location
- * sets up dma and bus speed, loads aha->sc_irq
- */
- if (aha_find(aha) != 0)
+ /* See if there is a unit at this location. */
+ if (aha_find(ia, NULL) != 0)
return 0;
- if (ia->ia_irq != IRQUNK) {
- if (ia->ia_irq != aha->sc_irq) {
- printf("%s: irq mismatch; kernel configured %d != board configured %d\n",
- aha->sc_dev.dv_xname, ia->ia_irq, aha->sc_irq);
- return 0;
- }
- } else
- ia->ia_irq = aha->sc_irq;
-
- if (ia->ia_drq != DRQUNK) {
- if (ia->ia_drq != aha->sc_drq) {
- printf("%s: drq mismatch; kernel configured %d != board configured %d\n",
- aha->sc_dev.dv_xname, ia->ia_drq, aha->sc_drq);
- return 0;
- }
- } else
- ia->ia_drq = aha->sc_drq;
-
ia->ia_msize = 0;
ia->ia_iosize = 4;
+ /* IRQ and DRQ set by aha_find(). */
return 1;
}
@@ -567,6 +337,7 @@ ahaprint(aux, name)
void *aux;
char *name;
{
+
if (name != NULL)
printf("%s: scsibus ", name);
return UNCONF;
@@ -581,274 +352,272 @@ ahaattach(parent, self, aux)
void *aux;
{
struct isa_attach_args *ia = aux;
- struct aha_softc *aha = (void *)self;
+ struct aha_softc *sc = (void *)self;
- if (ia->ia_drq != DRQUNK)
- isadma_cascade(ia->ia_drq);
+ if (aha_find(ia, sc) != 0)
+ panic("ahaattach: aha_find of %s failed", self->dv_xname);
+ sc->sc_iobase = ia->ia_iobase;
- aha_init(aha);
- TAILQ_INIT(&aha->free_ccb);
+ if (sc->sc_drq != DRQUNK)
+ isa_dmacascade(sc->sc_drq);
+
+ aha_inquire_setup_information(sc);
+ aha_init(sc);
+ TAILQ_INIT(&sc->sc_free_ccb);
+ TAILQ_INIT(&sc->sc_waiting_ccb);
/*
* fill in the prototype scsi_link.
*/
- aha->sc_link.adapter_softc = aha;
- aha->sc_link.adapter_target = aha->aha_scsi_dev;
- aha->sc_link.adapter = &aha_switch;
- aha->sc_link.device = &aha_dev;
- aha->sc_link.openings = 2;
-
- printf("\n");
+ sc->sc_link.adapter_softc = sc;
+ sc->sc_link.adapter_target = sc->sc_scsi_dev;
+ sc->sc_link.adapter = &aha_switch;
+ sc->sc_link.device = &aha_dev;
+ sc->sc_link.openings = 2;
#ifdef NEWCONFIG
- isa_establish(&aha->sc_id, &aha->sc_dev);
+ isa_establish(&sc->sc_id, &sc->sc_dev);
#endif
- aha->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO, ahaintr,
- aha, aha->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, sc->sc_irq, IST_EDGE,
+ IPL_BIO, ahaintr, sc);
/*
* ask the adapter what subunits are present
*/
- config_found(self, &aha->sc_link, ahaprint);
+ config_found(self, &sc->sc_link, ahaprint);
}
-/*
- * Catch an interrupt from the adaptor
- */
-int
-ahaintr(arg)
- void *arg;
+integrate void
+aha_finish_ccbs(sc)
+ struct aha_softc *sc;
{
- struct aha_softc *aha = arg;
struct aha_mbx_in *wmbi;
- struct aha_mbx *wmbx;
struct aha_ccb *ccb;
- u_char stat;
int i;
- int found = 0;
-#ifdef AHADEBUG
- printf("%s: ahaintr ", aha->sc_dev.dv_xname);
-#endif /*AHADEBUG */
-
- /*
- * First acknowlege the interrupt, Then if it's not telling about
- * a completed operation just return.
- */
- stat = inb(AHA_INTR_PORT);
- if ((stat & (AHA_MBOA | AHA_MBIF)) == 0) {
- outb(AHA_CTRL_STAT_PORT, AHA_IRST);
- return -1; /* XXX */
- }
+ wmbi = wmbx->tmbi;
- /* Mail box out empty? */
- if (stat & AHA_MBOA) {
- /* Disable MBO available interrupt. */
- outb(AHA_CMD_DATA_PORT, AHA_MBO_INTR_EN);
- for (i = 100000; i; i--) {
- if (!(inb(AHA_CTRL_STAT_PORT) & AHA_CDF))
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: ahaintr, cmd/data port full\n",
- aha->sc_dev.dv_xname);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
- return 1;
+ if (wmbi->stat == AHA_MBI_FREE) {
+ for (i = 0; i < AHA_MBX_SIZE; i++) {
+ if (wmbi->stat != AHA_MBI_FREE) {
+ printf("%s: mbi not in round-robin order\n",
+ sc->sc_dev.dv_xname);
+ goto AGAIN;
+ }
+ aha_nextmbx(wmbi, wmbx, mbi);
}
- outb(AHA_CMD_DATA_PORT, 0x00); /* Disable */
- wakeup(&aha->aha_mbx);
+#ifdef AHADIAGnot
+ printf("%s: mbi interrupt with no full mailboxes\n",
+ sc->sc_dev.dv_xname);
+#endif
+ return;
}
- /* Mail box in full? */
- if ((stat & AHA_MBIF) == 0)
- return 1;
- wmbx = &aha->aha_mbx;
- wmbi = wmbx->tmbi;
AGAIN:
- while (wmbi->stat != AHA_MBI_FREE) {
- ccb = aha_ccb_phys_kv(aha, _3btol(wmbi->ccb_addr));
+ do {
+ ccb = aha_ccb_phys_kv(sc, phystol(wmbi->ccb_addr));
if (!ccb) {
- wmbi->stat = AHA_MBI_FREE;
- printf("%s: BAD CCB ADDR!\n", aha->sc_dev.dv_xname);
- continue;
+ printf("%s: bad mbi ccb pointer; skipping\n",
+ sc->sc_dev.dv_xname);
+ goto next;
}
- found++;
+
+#ifdef AHADEBUG
+ if (aha_debug) {
+ u_char *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("stat %x for mbi addr = 0x%08x, ",
+ wmbi->stat, wmbi);
+ printf("ccb addr = 0x%x\n", ccb);
+ }
+#endif /* AHADEBUG */
+
switch (wmbi->stat) {
case AHA_MBI_OK:
case AHA_MBI_ERROR:
+ if ((ccb->flags & CCB_ABORT) != 0) {
+ /*
+ * If we already started an abort, wait for it
+ * to complete before clearing the CCB. We
+ * could instead just clear CCB_SENDING, but
+ * what if the mailbox was already received?
+ * The worst that happens here is that we clear
+ * the CCB a bit later than we need to. BFD.
+ */
+ goto next;
+ }
break;
case AHA_MBI_ABORT:
- ccb->host_stat = AHA_ABORTED;
- break;
-
case AHA_MBI_UNKNOWN:
- ccb = 0;
+ /*
+ * Even if the CCB wasn't found, we clear it anyway.
+ * See preceeding comment.
+ */
break;
default:
- panic("Impossible mbxi status");
- }
-#ifdef AHADEBUG
- if (aha_debug && ccb) {
- u_char *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("stat %x for mbi addr = 0x%08x, ",
- wmbi->stat, wmbi);
- printf("ccb addr = 0x%x\n", ccb);
+ printf("%s: bad mbi status %02x; skipping\n",
+ sc->sc_dev.dv_xname, wmbi->stat);
+ goto next;
}
-#endif /* AHADEBUG */
+
+ untimeout(aha_timeout, ccb);
+ aha_done(sc, ccb);
+
+ next:
wmbi->stat = AHA_MBI_FREE;
- if (ccb) {
- untimeout(aha_timeout, ccb);
- aha_done(aha, ccb);
- }
aha_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
- for (i = 0; i < AHA_MBX_SIZE; i++) {
- if (wmbi->stat != AHA_MBI_FREE) {
- found++;
- break;
- }
- aha_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
-#if 0
- printf("%s: mbi interrupt with no full mailboxes\n",
- aha->sc_dev.dv_xname);
+ } while (wmbi->stat != AHA_MBI_FREE);
+
+ wmbx->tmbi = wmbi;
+}
+
+/*
+ * Catch an interrupt from the adaptor
+ */
+int
+ahaintr(arg)
+ void *arg;
+{
+ struct aha_softc *sc = arg;
+ int iobase = sc->sc_iobase;
+ u_char sts;
+
+#ifdef AHADEBUG
+ printf("%s: ahaintr ", sc->sc_dev.dv_xname);
+#endif /*AHADEBUG */
+
+ /*
+ * First acknowlege the interrupt, Then if it's not telling about
+ * a completed operation just return.
+ */
+ sts = inb(iobase + AHA_INTR_PORT);
+ if ((sts & AHA_INTR_ANYINTR) == 0)
+ return 0;
+ outb(iobase + AHA_CTRL_PORT, AHA_CTRL_IRST);
+
+#ifdef AHADIAG
+ /* Make sure we clear CCB_SENDING before finishing a CCB. */
+ aha_collect_mbo(sc);
#endif
- } else {
- found = 0;
- goto AGAIN;
- }
+
+ /* Mail box out empty? */
+ if (sts & AHA_INTR_MBOA) {
+ struct aha_toggle toggle;
+
+ toggle.cmd.opcode = AHA_MBO_INTR_EN;
+ toggle.cmd.enable = 0;
+ aha_cmd(iobase, sc, sizeof(toggle.cmd), (u_char *)&toggle.cmd, 0,
+ (u_char *)0);
+ aha_start_ccbs(sc);
}
- wmbx->tmbi = wmbi;
- outb(AHA_CTRL_STAT_PORT, AHA_IRST);
+
+ /* Mail box in full? */
+ if (sts & AHA_INTR_MBIF)
+ aha_finish_ccbs(sc);
+
return 1;
}
+integrate void
+aha_reset_ccb(sc, ccb)
+ struct aha_softc *sc;
+ struct aha_ccb *ccb;
+{
+
+ ccb->flags = 0;
+}
+
/*
- * A ccb (and hence a mbx-out is put onto the
- * free list.
+ * A ccb is put onto the free list.
*/
void
-aha_free_ccb(aha, ccb, flags)
- struct aha_softc *aha;
+aha_free_ccb(sc, ccb)
+ struct aha_softc *sc;
struct aha_ccb *ccb;
- int flags;
{
- int s, hashnum;
- struct aha_ccb **hashccb;
+ int s;
s = splbio();
- if (ccb->ccb_phys[0].addr)
- isadma_unmap((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys);
-
- /* remove from hash table */
-
- hashnum = CCB_HASH(ccb->ccb_phys[0].addr);
- hashccb = &aha->ccbhash[hashnum];
-
- while (*hashccb) {
- if ((*hashccb)->ccb_phys[0].addr == ccb->ccb_phys[0].addr) {
- *hashccb = (*hashccb)->nexthash;
- break;
- }
- hashccb = &(*hashccb)->nexthash;
- }
-
- ccb->flags = CCB_FREE;
- TAILQ_INSERT_HEAD(&aha->free_ccb, ccb, chain);
+ aha_reset_ccb(sc, ccb);
+ TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
/*
* If there were none, wake anybody waiting for one to come free,
* starting with queued entries.
*/
if (ccb->chain.tqe_next == 0)
- wakeup(&aha->free_ccb);
+ wakeup(&sc->sc_free_ccb);
splx(s);
}
-static inline void
-aha_init_ccb(aha, ccb)
- struct aha_softc *aha;
- struct aha_ccb *ccb;
-{
- bzero(ccb, sizeof(struct aha_ccb));
-}
-
-static inline void
-aha_reset_ccb(aha, ccb)
- struct aha_softc *aha;
+integrate void
+aha_init_ccb(sc, ccb)
+ struct aha_softc *sc;
struct aha_ccb *ccb;
{
+ int hashnum;
+ bzero(ccb, sizeof(struct aha_ccb));
+ /*
+ * put in the phystokv hash table
+ * Never gets taken out.
+ */
+ ccb->hashkey = KVTOPHYS(ccb);
+ hashnum = CCB_HASH(ccb->hashkey);
+ ccb->nexthash = sc->sc_ccbhash[hashnum];
+ sc->sc_ccbhash[hashnum] = ccb;
+ aha_reset_ccb(sc, 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 aha_ccb *
-aha_get_ccb(aha, flags)
- struct aha_softc *aha;
+aha_get_ccb(sc, flags)
+ struct aha_softc *sc;
int flags;
{
struct aha_ccb *ccb;
- int hashnum, mflags, s;
+ int s;
s = splbio();
- if (flags & SCSI_NOSLEEP)
- mflags = ISADMA_MAP_BOUNCE;
- else
- mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK;
-
/*
- * If we can and have to, sleep waiting for one
- * to come free
+ * If we can and have to, sleep waiting for one to come free
+ * but only if we can't allocate a new one.
*/
for (;;) {
- ccb = aha->free_ccb.tqh_first;
+ ccb = sc->sc_free_ccb.tqh_first;
if (ccb) {
- TAILQ_REMOVE(&aha->free_ccb, ccb, chain);
+ TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);
break;
}
- if (aha->numccbs < AHA_CCB_MAX) {
- if (ccb = (struct aha_ccb *) malloc(sizeof(struct aha_ccb),
- M_TEMP, M_NOWAIT)) {
- aha_init_ccb(aha, ccb);
- aha->numccbs++;
- } else {
+ if (sc->sc_numccbs < AHA_CCB_MAX) {
+ ccb = (struct aha_ccb *) malloc(sizeof(struct aha_ccb),
+ M_TEMP, M_NOWAIT);
+ if (!ccb) {
printf("%s: can't malloc ccb\n",
- aha->sc_dev.dv_xname);
+ sc->sc_dev.dv_xname);
goto out;
}
+ aha_init_ccb(sc, ccb);
+ sc->sc_numccbs++;
break;
}
if ((flags & SCSI_NOSLEEP) != 0)
goto out;
- tsleep(&aha->free_ccb, PRIBIO, "ahaccb", 0);
+ tsleep(&sc->sc_free_ccb, PRIBIO, "ahaccb", 0);
}
- aha_reset_ccb(aha, ccb);
- ccb->flags = CCB_ACTIVE;
-
- if (isadma_map((caddr_t)ccb, CCB_PHYS_SIZE, ccb->ccb_phys,
- mflags | ISADMA_MAP_CONTIG) == 1) {
- hashnum = CCB_HASH(ccb->ccb_phys[0].addr);
- ccb->nexthash = aha->ccbhash[hashnum];
- aha->ccbhash[hashnum] = ccb;
- } else {
- ccb->ccb_phys[0].addr = 0;
- aha_free_ccb(aha, ccb, flags);
- ccb = 0;
- }
+ ccb->flags |= CCB_ALLOC;
out:
splx(s);
@@ -856,74 +625,116 @@ out:
}
/*
- * given a physical address, find the ccb that it corresponds to.
+ * Given a physical address, find the ccb that it corresponds to.
*/
struct aha_ccb *
-aha_ccb_phys_kv(aha, ccb_phys)
- struct aha_softc *aha;
+aha_ccb_phys_kv(sc, ccb_phys)
+ struct aha_softc *sc;
u_long ccb_phys;
{
int hashnum = CCB_HASH(ccb_phys);
- struct aha_ccb *res = aha->ccbhash[hashnum];
+ struct aha_ccb *ccb = sc->sc_ccbhash[hashnum];
- while (res) {
- if (res->ccb_phys[0].addr == ccb_phys)
+ while (ccb) {
+ if (ccb->hashkey == ccb_phys)
break;
- res = res->nexthash;
+ ccb = ccb->nexthash;
}
+ return ccb;
+}
- return res;
+/*
+ * Queue a CCB to be sent to the controller, and send it if possible.
+ */
+void
+aha_queue_ccb(sc, ccb)
+ struct aha_softc *sc;
+ struct aha_ccb *ccb;
+{
+
+ TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
+ aha_start_ccbs(sc);
}
/*
- * Get a mbo and send the ccb.
+ * Garbage collect mailboxes that are no longer in use.
*/
-struct aha_mbx_out *
-aha_send_mbo(aha, cmd, ccb)
- struct aha_softc *aha;
- int cmd;
+void
+aha_collect_mbo(sc)
+ struct aha_softc *sc;
+{
+ struct aha_mbx_out *wmbo; /* Mail Box Out pointer */
struct aha_ccb *ccb;
+
+ wmbo = wmbx->cmbo;
+
+ while (sc->sc_mbofull > 0) {
+ if (wmbo->cmd != AHA_MBO_FREE)
+ break;
+
+#ifdef AHADIAG
+ ccb = aha_ccb_phys_kv(sc, phystol(wmbo->ccb_addr));
+ ccb->flags &= ~CCB_SENDING;
+#endif
+
+ --sc->sc_mbofull;
+ aha_nextmbx(wmbo, wmbx, mbo);
+ }
+
+ wmbx->cmbo = wmbo;
+}
+
+/*
+ * Send as many CCBs as we have empty mailboxes for.
+ */
+void
+aha_start_ccbs(sc)
+ struct aha_softc *sc;
{
+ int iobase = sc->sc_iobase;
struct aha_mbx_out *wmbo; /* Mail Box Out pointer */
- struct aha_mbx *wmbx; /* Mail Box pointer specified unit */
+ struct aha_ccb *ccb;
int i;
- /* Get the target out mail box pointer and increment. */
- wmbx = &aha->aha_mbx;
wmbo = wmbx->tmbo;
- aha_nextmbx(wmbx->tmbo, wmbx, mbo);
- /*
- * Check the outmail box is free or not.
- * Note: Under the normal operation, it shuld NOT happen to wait.
- */
- while (wmbo->cmd != AHA_MBO_FREE) {
- /* Enable mbo available interrupt. */
- outb(AHA_CMD_DATA_PORT, AHA_MBO_INTR_EN);
- for (i = 100000; i; i--) {
- if (!(inb(AHA_CTRL_STAT_PORT) & AHA_CDF))
+ while (ccb = sc->sc_waiting_ccb.tqh_first) {
+ if (sc->sc_mbofull >= AHA_MBX_SIZE) {
+ aha_collect_mbo(sc);
+ if (sc->sc_mbofull >= AHA_MBX_SIZE) {
+ struct aha_toggle toggle;
+
+ toggle.cmd.opcode = AHA_MBO_INTR_EN;
+ toggle.cmd.enable = 1;
+ aha_cmd(iobase, sc, sizeof(toggle.cmd),
+ (u_char *)&toggle.cmd, 0, (u_char *)0);
break;
- delay(10);
- }
- if (!i) {
- printf("%s: aha_send_mbo, cmd/data port full\n",
- aha->sc_dev.dv_xname);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
- return NULL;
+ }
}
- outb(AHA_CMD_DATA_PORT, 0x01); /* Enable */
- tsleep(wmbx, PRIBIO, "ahasnd", 0);/*XXX can't do this */
- }
- /* Link ccb to mbo. */
- lto3b(ccb->ccb_phys[0].addr, wmbo->ccb_addr);
- ccb->mbx = wmbo;
- wmbo->cmd = cmd;
+ TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
+#ifdef AHADIAG
+ ccb->flags |= CCB_SENDING;
+#endif
+
+ /* Link ccb to mbo. */
+ ltophys(KVTOPHYS(ccb), wmbo->ccb_addr);
+ if (ccb->flags & CCB_ABORT)
+ wmbo->cmd = AHA_MBO_ABORT;
+ else
+ wmbo->cmd = AHA_MBO_START;
- /* Sent it! */
- outb(AHA_CMD_DATA_PORT, AHA_START_SCSI);
+ /* Tell the card to poll immediately. */
+ outb(iobase + AHA_CMD_PORT, AHA_START_SCSI);
- return wmbo;
+ if ((ccb->xs->flags & SCSI_POLL) == 0)
+ timeout(aha_timeout, ccb, (ccb->timeout * hz) / 1000);
+
+ ++sc->sc_mbofull;
+ aha_nextmbx(wmbo, wmbx, mbo);
+ }
+
+ wmbx->tmbo = wmbo;
}
/*
@@ -932,8 +743,8 @@ aha_send_mbo(aha, cmd, ccb)
* went. Wake up the owner if waiting
*/
void
-aha_done(aha, ccb)
- struct aha_softc *aha;
+aha_done(sc, ccb)
+ struct aha_softc *sc;
struct aha_ccb *ccb;
{
struct scsi_sense_data *s1, *s2;
@@ -944,23 +755,29 @@ aha_done(aha, ccb)
* Otherwise, put the results of the operation
* into the xfer and call whoever started it
*/
- if ((xs->flags & INUSE) == 0) {
- printf("%s: exiting but not in use!\n", aha->sc_dev.dv_xname);
+#ifdef AHADIAG
+ if (ccb->flags & CCB_SENDING) {
+ printf("%s: exiting ccb still in transit!\n", sc->sc_dev.dv_xname);
+ Debugger();
+ return;
+ }
+#endif
+ if ((ccb->flags & CCB_ALLOC) == 0) {
+ printf("%s: exiting ccb not allocated!\n", sc->sc_dev.dv_xname);
Debugger();
+ return;
}
if (xs->error == XS_NOERROR) {
if (ccb->host_stat != AHA_OK) {
switch (ccb->host_stat) {
- case AHA_ABORTED:
- xs->error = XS_DRIVER_STUFFUP;
- break;
case AHA_SEL_TIMEOUT: /* No response */
xs->error = XS_SELTIMEOUT;
break;
default: /* Other scsi protocol messes */
printf("%s: host_stat %x\n",
- aha->sc_dev.dv_xname, ccb->host_stat);
+ sc->sc_dev.dv_xname, ccb->host_stat);
xs->error = XS_DRIVER_STUFFUP;
+ break;
}
} else if (ccb->target_stat != SCSI_OK) {
switch (ccb->target_stat) {
@@ -976,27 +793,15 @@ aha_done(aha, ccb)
break;
default:
printf("%s: target_stat %x\n",
- aha->sc_dev.dv_xname, ccb->target_stat);
+ sc->sc_dev.dv_xname, ccb->target_stat);
xs->error = XS_DRIVER_STUFFUP;
+ break;
}
} else
xs->resid = 0;
}
+ aha_free_ccb(sc, ccb);
xs->flags |= ITSDONE;
-
- if (VOLATILE_XS(xs)) {
- wakeup(ccb);
- return;
- }
-
- if (ccb->data_nseg) {
- if (xs->flags & SCSI_DATA_IN)
- isadma_copyfrombuf(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- isadma_unmap(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- }
- aha_free_ccb(aha, ccb, xs->flags);
scsi_done(xs);
}
@@ -1004,147 +809,108 @@ aha_done(aha, ccb)
* Find the board and find its irq/drq
*/
int
-aha_find(aha)
- struct aha_softc *aha;
+aha_find(ia, sc)
+ struct isa_attach_args *ia;
+ struct aha_softc *sc;
{
- volatile int i, sts;
- struct aha_config conf;
- struct aha_inquire inquire;
- struct aha_extbios extbios;
+ int iobase = ia->ia_iobase;
+ int i;
+ u_char sts;
+ struct aha_config config;
+ int irq, drq;
/*
* 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(iobase + AHA_CTRL_PORT, AHA_CTRL_HRST | AHA_CTRL_SRST);
+ delay(100);
for (i = AHA_RESET_TIMEOUT; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts == (AHA_IDLE | AHA_INIT))
+ sts = inb(iobase + AHA_STAT_PORT);
+ if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT))
break;
delay(1000); /* calibrated in msec */
}
if (!i) {
-#ifdef AHADEBUG
+#ifdef AHADEBUG
if (aha_debug)
printf("aha_find: No answer from adaptec board\n");
-#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. If the command
- * fails, we assume it's either a crusty board or an old 1542
- * clone, and skip the board-specific stuff.
- */
- if (aha_cmd(aha, 0, sizeof(inquire), 1, &inquire, AHA_INQUIRE)) {
- /*
- * aha_cmd() already started the reset. It's not clear we
- * even need to bother here.
- */
- for (i = AHA_RESET_TIMEOUT; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts == (AHA_IDLE | AHA_INIT))
- break;
- delay(1000);
- }
- if (!i) {
-#ifdef AHADEBUG
- printf("aha_init: soft reset failed\n");
-#endif /* AHADEBUG */
- return ENXIO;
- }
-#ifdef AHADEBUG
- printf("aha_init: inquire command failed\n");
#endif /* AHADEBUG */
- goto noinquire;
- }
-#ifdef AHADEBUG
- printf("%s: inquire %x, %x, %x, %x\n",
- aha->sc_dev.dv_xname,
- inquire.boardid, inquire.spec_opts,
- inquire.revision_1, inquire.revision_2);
-#endif /* AHADEBUG */
- /*
- * If we are a 1542C or 1542CF disable the extended bios so that the
- * mailbox interface is unlocked.
- * No need to check the extended bios flags as some of the
- * extensions that cause us problems are not flagged in that byte.
- */
- if (inquire.boardid == 0x43 || inquire.boardid == 0x44 ||
- inquire.boardid == 0x45) {
- aha_cmd(aha, 0, sizeof(extbios), 0, &extbios, AHA_EXT_BIOS);
-#ifdef AHADEBUG
- printf("%s: extended bios flags %x\n", aha->sc_dev.dv_xname,
- extbios.flags);
-#endif /* AHADEBUG */
- printf("%s: 1542C/CF detected, unlocking mailbox\n",
- aha->sc_dev.dv_xname);
- aha_cmd(aha, 2, 0, 0, 0, AHA_MBX_ENABLE,
- 0, extbios.mailboxlock);
+ return 1;
}
-noinquire:
/*
* setup dma channel from jumpers and save int
* level
*/
delay(1000); /* for Bustek 545 */
- aha_cmd(aha, 0, sizeof(conf), 0, &conf, AHA_CONF_GET);
- switch (conf.chan) {
+ config.cmd.opcode = AHA_INQUIRE_CONFIG;
+ aha_cmd(iobase, sc, sizeof(config.cmd), (u_char *)&config.cmd,
+ sizeof(config.reply), (u_char *)&config.reply);
+ switch (config.reply.chan) {
+ case EISADMA:
+ drq = DRQUNK; /* for EISA/VLB/PCI clones */
+ break;
case CHAN0:
- aha->sc_drq = 0;
+ drq = 0;
break;
case CHAN5:
- aha->sc_drq = 5;
+ drq = 5;
break;
case CHAN6:
- aha->sc_drq = 6;
+ drq = 6;
break;
case CHAN7:
- aha->sc_drq = 7;
+ drq = 7;
break;
default:
- printf("%s: illegal drq setting %x\n", aha->sc_dev.dv_xname,
- conf.chan);
- return EIO;
+ printf("aha_find: illegal drq setting %x\n", config.reply.chan);
+ return 1;
}
- switch (conf.intr) {
+ switch (config.reply.intr) {
case INT9:
- aha->sc_irq = 9;
+ irq = 9;
break;
case INT10:
- aha->sc_irq = 10;
+ irq = 10;
break;
case INT11:
- aha->sc_irq = 11;
+ irq = 11;
break;
case INT12:
- aha->sc_irq = 12;
+ irq = 12;
break;
case INT14:
- aha->sc_irq = 14;
+ irq = 14;
break;
case INT15:
- aha->sc_irq = 15;
+ irq = 15;
break;
default:
- printf("%s: illegal irq setting %x\n", aha->sc_dev.dv_xname,
- conf.intr);
+ printf("aha_find: illegal irq setting %x\n", config.reply.intr);
return EIO;
}
- /* who are we on the scsi bus? */
- aha->aha_scsi_dev = conf.scsi_dev;
+ if (sc != NULL) {
+ /* who are we on the scsi bus? */
+ sc->sc_scsi_dev = config.reply.scsi_dev;
- /*
- * Change the bus on/off times to not clash with other dma users.
- */
- aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7);
- aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4);
+ sc->sc_iobase = iobase;
+ sc->sc_irq = irq;
+ sc->sc_drq = drq;
+ } else {
+ if (ia->ia_irq == IRQUNK)
+ ia->ia_irq = irq;
+ else if (ia->ia_irq != irq)
+ return 1;
+ if (ia->ia_drq == DRQUNK)
+ ia->ia_drq = drq;
+ else if (ia->ia_drq != drq)
+ return 1;
+ }
return 0;
}
@@ -1153,43 +919,176 @@ noinquire:
* Start the board, ready for normal operation
*/
void
-aha_init(aha)
- struct aha_softc *aha;
+aha_init(sc)
+ struct aha_softc *sc;
{
- u_char ad[3];
- struct isadma_seg mbx_phys[1];
+ int iobase = sc->sc_iobase;
+ struct aha_devices devices;
+ struct aha_setup setup;
+ struct aha_mailbox mailbox;
int i;
-#ifdef TUNE_1542
/*
- * Initialize memory transfer speed
- * Not compiled in by default because it breaks some machines
+ * XXX
+ * If we are a 1542C or later, disable the extended BIOS so that the
+ * mailbox interface is unlocked.
+ * No need to check the extended BIOS flags as some of the
+ * extensions that cause us problems are not flagged in that byte.
*/
- if (!aha_set_bus_speed(aha))
- panic("aha_init: cannot set bus speed");
-#endif /* TUNE_1542 */
+ if (!strncmp(sc->sc_model, "1542C", 5)) {
+ struct aha_extbios extbios;
+ struct aha_unlock unlock;
+
+ printf("%s: unlocking mailbox interface\n", sc->sc_dev.dv_xname);
+ extbios.cmd.opcode = AHA_EXT_BIOS;
+ aha_cmd(iobase, sc, sizeof(extbios.cmd), (u_char *)&extbios.cmd,
+ sizeof(extbios.reply), (u_char *)&extbios.reply);
+
+#ifdef AHADEBUG
+ printf("%s: flags=%02x, mailboxlock=%02x\n",
+ sc->sc_dev.dv_xname,
+ extbios.reply.flags, extbios.reply.mailboxlock);
+#endif /* AHADEBUG */
+ unlock.cmd.opcode = AHA_MBX_ENABLE;
+ unlock.cmd.junk = 0;
+ unlock.cmd.magic = extbios.reply.mailboxlock;
+ aha_cmd(iobase, sc, sizeof(unlock.cmd), (u_char *)&unlock.cmd,
+ 0, (u_char *)0);
+ }
+
+#if 0
/*
- * Initialize mail box. This mapping will never be undone.
+ * Change the bus on/off times to not clash with other dma users.
*/
- if (isadma_map((caddr_t)(&aha->aha_mbx), sizeof(struct aha_mbx),
- mbx_phys, ISADMA_MAP_CONTIG) != 1)
- panic("aha_init: cannot map mail box");
- lto3b(mbx_phys[0].addr, ad);
+ aha_cmd(sc, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7);
+ aha_cmd(sc, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4);
+#endif
- aha_cmd(aha, 4, 0, 0, 0, AHA_MBX_INIT, AHA_MBX_SIZE,
- ad[0], ad[1], ad[2]);
+ /* Inquire Installed Devices (to force synchronous negotiation). */
+ devices.cmd.opcode = AHA_INQUIRE_DEVICES;
+ aha_cmd(iobase, sc, sizeof(devices.cmd), (u_char *)&devices.cmd,
+ sizeof(devices.reply), (u_char *)&devices.reply);
+
+ /* Obtain setup information from. */
+ setup.cmd.opcode = AHA_INQUIRE_SETUP;
+ setup.cmd.len = sizeof(setup.reply);
+ aha_cmd(iobase, sc, sizeof(setup.cmd), (u_char *)&setup.cmd,
+ sizeof(setup.reply), (u_char *)&setup.reply);
+
+ printf("%s: %s, %s\n",
+ sc->sc_dev.dv_xname,
+ setup.reply.sync_neg ? "sync" : "async",
+ setup.reply.parity ? "parity" : "no parity");
+
+ for (i = 0; i < 8; i++) {
+ if (!setup.reply.sync[i].valid ||
+ (!setup.reply.sync[i].offset && !setup.reply.sync[i].period))
+ continue;
+ printf("%s targ %d: sync, offset %d, period %dnsec\n",
+ sc->sc_dev.dv_xname, i,
+ setup.reply.sync[i].offset, setup.reply.sync[i].period * 50 + 200);
+ }
+ /*
+ * Set up initial mail box for round-robin operation.
+ */
for (i = 0; i < AHA_MBX_SIZE; i++) {
- aha->aha_mbx.mbo[i].cmd = AHA_MBO_FREE;
- aha->aha_mbx.mbi[i].stat = AHA_MBO_FREE;
+ wmbx->mbo[i].cmd = AHA_MBO_FREE;
+ wmbx->mbi[i].stat = AHA_MBO_FREE;
}
+ wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
+ wmbx->tmbi = &wmbx->mbi[0];
+ sc->sc_mbofull = 0;
+
+ /* Initialize mail box. */
+ mailbox.cmd.opcode = AHA_MBX_INIT;
+ mailbox.cmd.nmbx = AHA_MBX_SIZE;
+ ltophys(KVTOPHYS(wmbx), mailbox.cmd.addr);
+ aha_cmd(iobase, sc, sizeof(mailbox.cmd), (u_char *)&mailbox.cmd,
+ 0, (u_char *)0);
+}
+
+void
+aha_inquire_setup_information(sc)
+ struct aha_softc *sc;
+{
+ int iobase = sc->sc_iobase;
+ struct aha_revision revision;
+ u_char sts;
+ int i;
+ char *p;
+
+ strcpy(sc->sc_model, "unknown");
/*
- * Set up initial mail box for round-robin operation.
+ * Assume we have a board at this stage, do an adapter inquire
+ * to find out what type of controller it is. If the command
+ * fails, we assume it's either a crusty board or an old 1542
+ * clone, and skip the board-specific stuff.
*/
- aha->aha_mbx.tmbo = &aha->aha_mbx.mbo[0];
- aha->aha_mbx.tmbi = &aha->aha_mbx.mbi[0];
+ revision.cmd.opcode = AHA_INQUIRE_REVISION;
+ if (aha_cmd(iobase, sc, sizeof(revision.cmd), (u_char *)&revision.cmd,
+ sizeof(revision.reply), (u_char *)&revision.reply)) {
+ /*
+ * aha_cmd() already started the reset. It's not clear we
+ * even need to bother here.
+ */
+ for (i = AHA_RESET_TIMEOUT; i; i--) {
+ sts = inb(iobase + AHA_STAT_PORT);
+ if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT))
+ break;
+ delay(1000);
+ }
+ if (!i) {
+#ifdef AHADEBUG
+ printf("aha_init: soft reset failed\n");
+#endif /* AHADEBUG */
+ return;
+ }
+#ifdef AHADEBUG
+ printf("aha_init: inquire command failed\n");
+#endif /* AHADEBUG */
+ goto noinquire;
+ }
+
+#ifdef AHADEBUG
+ printf("%s: inquire %x, %x, %x, %x\n",
+ sc->sc_dev.dv_xname,
+ revision.reply.boardid, revision.reply.spec_opts,
+ revision.reply.revision_1, revision.reply.revision_2);
+#endif /* AHADEBUG */
+
+ switch (revision.reply.boardid) {
+ case 0x31:
+ strcpy(sc->sc_model, "1540");
+ break;
+ case 0x41:
+ strcpy(sc->sc_model, "1540A/1542A/1542B");
+ break;
+ case 0x42:
+ strcpy(sc->sc_model, "1640");
+ break;
+ case 0x43:
+ strcpy(sc->sc_model, "1542C");
+ break;
+ case 0x44:
+ case 0x45:
+ strcpy(sc->sc_model, "1542CF");
+ break;
+ case 0x46:
+ strcpy(sc->sc_model, "1542CP");
+ break;
+ }
+
+ p = sc->sc_firmware;
+ *p++ = revision.reply.revision_1;
+ *p++ = '.';
+ *p++ = revision.reply.revision_2;
+ *p = '\0';
+
+noinquire:
+ printf(": model AHA-%s, firmware %s\n", sc->sc_model, sc->sc_firmware);
}
void
@@ -1211,12 +1110,13 @@ aha_scsi_cmd(xs)
struct scsi_xfer *xs;
{
struct scsi_link *sc_link = xs->sc_link;
- struct aha_softc *aha = sc_link->adapter_softc;
+ struct aha_softc *sc = sc_link->adapter_softc;
struct aha_ccb *ccb;
struct aha_scat_gath *sg;
- int seg, datalen, flags, mflags;
+ int seg; /* scatter gather seg being worked on */
+ u_long thiskv, thisphys, nextphys;
+ int bytes_this_seg, bytes_this_page, datalen, flags;
struct iovec *iovp;
- struct aha_mbx_out *mbo;
int s;
SC_DEBUG(sc_link, SDEV_DB2, ("aha_scsi_cmd\n"));
@@ -1226,44 +1126,28 @@ aha_scsi_cmd(xs)
* then we can't allow it to sleep
*/
flags = xs->flags;
- if (flags & SCSI_NOSLEEP)
- mflags = ISADMA_MAP_BOUNCE;
- else
- mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK;
- if ((flags & (ITSDONE|INUSE)) != INUSE) {
- printf("%s: done or not in use?\n", aha->sc_dev.dv_xname);
- xs->flags &= ~ITSDONE;
- xs->flags |= INUSE;
- }
- if ((ccb = aha_get_ccb(aha, flags)) == NULL) {
+ if ((ccb = aha_get_ccb(sc, flags)) == NULL) {
xs->error = XS_DRIVER_STUFFUP;
return TRY_AGAIN_LATER;
}
ccb->xs = xs;
+ ccb->timeout = xs->timeout;
/*
* Put all the arguments for the xfer in the ccb
*/
if (flags & SCSI_RESET) {
ccb->opcode = AHA_RESET_CCB;
+ ccb->scsi_cmd_length = 0;
} else {
/* can't use S/G if zero length */
ccb->opcode = (xs->datalen ? AHA_INIT_SCAT_GATH_CCB
: AHA_INITIATOR_CCB);
+ bcopy(xs->cmd, &ccb->scsi_cmd,
+ ccb->scsi_cmd_length = xs->cmdlen);
}
- ccb->data_out = 0;
- ccb->data_in = 0;
- ccb->target = sc_link->target;
- ccb->lun = sc_link->lun;
- ccb->scsi_cmd_length = xs->cmdlen;
- ccb->req_sense_length = sizeof(ccb->scsi_sense);
- ccb->host_stat = 0x00;
- ccb->target_stat = 0x00;
- ccb->data_nseg = 0;
- if (xs->datalen && (flags & SCSI_RESET) == 0) {
- sg = ((struct aha_ccb *)(ccb->ccb_phys[0].addr))->scat_gath;
- lto3b((vm_offset_t)sg, ccb->data_addr);
+ if (xs->datalen) {
sg = ccb->scat_gath;
seg = 0;
#ifdef TFS
@@ -1272,8 +1156,8 @@ aha_scsi_cmd(xs)
datalen = ((struct uio *)xs->data)->uio_iovcnt;
xs->datalen = 0;
while (datalen && seg < AHA_NSEG) {
- lto3b(iovp->iov_base, sg->seg_addr);
- lto3b(iovp->iov_len, sg->seg_len);
+ ltophys(iovp->iov_base, sg->seg_addr);
+ ltophys(iovp->iov_len, sg->seg_len);
xs->datalen += iovp->iov_len;
SC_DEBUGN(sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)",
iovp->iov_len, iovp->iov_base));
@@ -1283,109 +1167,129 @@ aha_scsi_cmd(xs)
datalen--;
}
} else
-#endif /*TFS_ONLY */
+#endif /* TFS */
{
/*
- * Set up the scatter gather block
+ * Set up the scatter-gather block.
*/
+ SC_DEBUG(sc_link, SDEV_DB4,
+ ("%d @0x%x:- ", xs->datalen, xs->data));
+
+ datalen = xs->datalen;
+ thiskv = (int)xs->data;
+ thisphys = KVTOPHYS(thiskv);
- ccb->data_nseg = isadma_map(xs->data, xs->datalen,
- ccb->data_phys, mflags);
- for (seg = 0; seg < ccb->data_nseg; seg++) {
- lto3b(ccb->data_phys[seg].addr,
- sg[seg].seg_addr);
- lto3b(ccb->data_phys[seg].length,
- sg[seg].seg_len);
+ while (datalen && seg < AHA_NSEG) {
+ bytes_this_seg = 0;
+
+ /* put in the base address */
+ ltophys(thisphys, sg->seg_addr);
+
+ SC_DEBUGN(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
+ */
+ /* check it fits on the ISA bus */
+ if (thisphys > 0xFFFFFF) {
+ printf("%s: DMA beyond"
+ " end of ISA\n",
+ sc->sc_dev.dv_xname);
+ goto bad;
+ }
+ /* how far to the end of the page */
+ nextphys = (thisphys & ~PGOFSET) + NBPG;
+ 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;
+
+ /* get more ready for the next page */
+ thiskv = (thiskv & ~PGOFSET) + NBPG;
+ if (datalen)
+ thisphys = KVTOPHYS(thiskv);
+ }
+ /*
+ * next page isn't contiguous, finish the seg
+ */
+ SC_DEBUGN(sc_link, SDEV_DB4,
+ ("(0x%x)", bytes_this_seg));
+ ltophys(bytes_this_seg, sg->seg_len);
+ sg++;
+ seg++;
}
}
- lto3b(ccb->data_nseg * sizeof(struct aha_scat_gath), ccb->data_length);
- if (ccb->data_nseg == 0) {
- printf("%s: aha_scsi_cmd, cannot map\n",
- aha->sc_dev.dv_xname);
- xs->error = XS_DRIVER_STUFFUP;
- aha_free_ccb(aha, ccb, flags);
- return COMPLETE;
- } else if (flags & SCSI_DATA_OUT)
- isadma_copytobuf(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
+ /* end of iov/kv decision */
+ SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
+ if (datalen) {
+ /*
+ * there's still data, must have run out of segs!
+ */
+ printf("%s: aha_scsi_cmd, more than %d dma segs\n",
+ sc->sc_dev.dv_xname, AHA_NSEG);
+ goto bad;
+ }
+ ltophys(KVTOPHYS(ccb->scat_gath), ccb->data_addr);
+ ltophys(seg * sizeof(struct aha_scat_gath), ccb->data_length);
} else { /* No data xfer, use non S/G values */
- lto3b(0, ccb->data_addr);
- lto3b(0, ccb->data_length);
+ ltophys(0, ccb->data_addr);
+ ltophys(0, ccb->data_length);
}
- ccb->link_id = 0;
- lto3b(0, ccb->link_addr);
- /*
- * Put the scsi command in the ccb and start it
- */
- if ((flags & SCSI_RESET) == 0)
- bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmd_length);
+ ccb->data_out = 0;
+ ccb->data_in = 0;
+ ccb->target = sc_link->target;
+ ccb->lun = sc_link->lun;
+ ccb->req_sense_length = sizeof(ccb->scsi_sense);
+ ccb->host_stat = 0x00;
+ ccb->target_stat = 0x00;
+ ccb->link_id = 0;
+ ltophys(0, ccb->link_addr);
s = splbio();
-
- isadma_copytobuf((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys);
-
- if (aha_send_mbo(aha, AHA_MBO_START, ccb) == NULL) {
- splx(s);
- xs->error = XS_DRIVER_STUFFUP;
- if (ccb->data_nseg)
- isadma_unmap(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- aha_free_ccb(aha, ccb, flags);
- return TRY_AGAIN_LATER;
- }
+ aha_queue_ccb(sc, ccb);
+ splx(s);
/*
* Usually return SUCCESSFULLY QUEUED
*/
SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
-
- if (VOLATILE_XS(xs)) {
- timeout(aha_timeout, ccb, (xs->timeout * hz) / 1000);
- while ((ccb->xs->flags & ITSDONE) == 0) {
- tsleep(ccb, PRIBIO, "ahawait", 0);
- }
- splx(s);
- if (ccb->data_nseg) {
- if (flags & SCSI_DATA_IN)
- isadma_copyfrombuf(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- isadma_unmap(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- }
- aha_free_ccb(aha, ccb, xs->flags);
- scsi_done(xs);
- return COMPLETE;
- }
-
- if ((flags & SCSI_POLL) == 0) {
- timeout(aha_timeout, ccb, (xs->timeout * hz) / 1000);
- splx(s);
+ if ((flags & SCSI_POLL) == 0)
return SUCCESSFULLY_QUEUED;
- }
-
- splx(s);
/*
* If we can't use interrupts, poll on completion
*/
- if (aha_poll(aha, xs, xs->timeout)) {
+ if (aha_poll(sc, xs, ccb->timeout)) {
aha_timeout(ccb);
- if (aha_poll(aha, xs, 2000))
+ if (aha_poll(sc, xs, ccb->timeout))
aha_timeout(ccb);
}
return COMPLETE;
+
+bad:
+ xs->error = XS_DRIVER_STUFFUP;
+ aha_free_ccb(sc, ccb);
+ return COMPLETE;
}
/*
* Poll a particular unit, looking for a particular xs
*/
int
-aha_poll(aha, xs, count)
- struct aha_softc *aha;
+aha_poll(sc, xs, count)
+ struct aha_softc *sc;
struct scsi_xfer *xs;
int count;
{
+ int iobase = sc->sc_iobase;
/* timeouts are in msec, so we loop in 1000 usec cycles */
while (count) {
@@ -1393,8 +1297,8 @@ aha_poll(aha, xs, count)
* If we had interrupts enabled, would we
* have got an interrupt?
*/
- if (inb(AHA_INTR_PORT) & AHA_ANY_INTR)
- ahaintr(aha);
+ if (inb(iobase + AHA_INTR_PORT) & AHA_INTR_ANYINTR)
+ ahaintr(sc);
if (xs->flags & ITSDONE)
return 0;
delay(1000); /* only happens in boot so ok */
@@ -1403,141 +1307,6 @@ aha_poll(aha, xs, count)
return 1;
}
-#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 {
- u_char arg;
- int nsecs;
-} aha_bus_speeds[] = {
- {0x88, 100},
- {0x99, 150},
- {0xaa, 200},
- {0xbb, 250},
- {0xcc, 300},
- {0xdd, 350},
- {0xee, 400},
- {0xff, 450}
-};
-
-int
-aha_set_bus_speed(aha)
- struct aha_softc *aha;
-{
- int speed;
- int lastworking;
-
- lastworking = -1;
- for (speed = 7; speed >= 0; speed--) {
- if (!aha_bus_speed_check(aha, speed))
- break;
- lastworking = speed;
- }
- if (lastworking == -1) {
- printf(" no working bus speed");
- return 0;
- }
- printf(", %d nsec ", aha_bus_speeds[lastworking].nsecs);
- if (lastworking == 7) /* is slowest already */
- printf("marginal");
- else {
- lastworking++;
- printf("ok, using %d nsec", aha_bus_speeds[lastworking].nsecs);
- }
- if (!aha_bus_speed_check(aha, lastworking)) {
- printf("test retry failed.. aborting.");
- return 0;
- }
- return 1;
-}
-
-/*
- * 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 COMPLETE.
- */
-char aha_scratch_buf[256];
-char aha_test_string[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz!@";
-
-int
-aha_bus_speed_check(aha, speed)
- struct aha_softc *aha;
- int speed;
-{
- int numspeeds = sizeof(aha_bus_speeds) / sizeof(struct bus_speed);
- int result, loopcount;
- struct isadma_seg test_phys[1], scratch_phys[1];
- u_char ad[3];
-
- result = 1;
-
- if (isadma_map(aha_scratch_buf, sizeof(aha_scratch_buf),
- scratch_phys, ISADMA_MAP_CONTIG) != 1)
- return 0;
- if (isadma_map(aha_test_string, sizeof(aha_test_string),
- test_phys, ISADMA_MAP_CONTIG) != 1) {
- isadma_unmap(aha_scratch_buf, sizeof(aha_scratch_buf),
- 1, scratch_phys);
- return 0;
- }
- isadma_copytobuf(aha_test_string, sizeof(aha_test_string),
- 1, test_phys);
-
- /*
- * Set the dma-speed
- */
- aha_cmd(aha, 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
- */
- for (loopcount = 100; loopcount; loopcount--) {
- lto3b(test_phys[0].addr, ad);
- aha_cmd(aha, 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);
- isadma_copytobuf(aha_scratch_buf, sizeof(aha_scratch_buf),
- 1, scratch_phys);
-
- lto3b(scratch_phys[0].addr, ad);
- aha_cmd(aha, 3, 0, 0, 0, AHA_READ_FIFO, ad[0], ad[1], ad[2]);
- isadma_copyfrombuf(aha_scratch_buf, sizeof(aha_scratch_buf),
- 1, scratch_phys);
-
- /*
- * Compare the original data and the final data and return the
- * correct value depending upon the result. We only check the
- * first 54 bytes, because that's all the board copies during
- * WRITE_FIFO and READ_FIFO.
- */
- if (bcmp(aha_test_string, aha_scratch_buf, 54)) {
- result = 0; /* failed test */
- break;
- }
- }
-
- isadma_unmap(aha_scratch_buf, sizeof(aha_scratch_buf),
- 1, scratch_phys);
- isadma_unmap(aha_test_string, sizeof(aha_test_string),
- 1, test_phys);
-
- /* copy succeeded; assume speed ok */
- return result;
-}
-#endif /* TUNE_1542 */
-
void
aha_timeout(arg)
void *arg;
@@ -1545,7 +1314,7 @@ aha_timeout(arg)
struct aha_ccb *ccb = arg;
struct scsi_xfer *xs = ccb->xs;
struct scsi_link *sc_link = xs->sc_link;
- struct aha_softc *aha = sc_link->adapter_softc;
+ struct aha_softc *sc = sc_link->adapter_softc;
int s;
sc_print_addr(sc_link);
@@ -1553,34 +1322,33 @@ aha_timeout(arg)
s = splbio();
+#ifdef AHADIAG
/*
* If The ccb's mbx is not free, then the board has gone south?
*/
- if (aha_ccb_phys_kv(aha, _3btol(ccb->mbx->ccb_addr)) == ccb &&
- ccb->mbx->cmd != AHA_MBO_FREE) {
- printf("%s: not taking commands!\n", aha->sc_dev.dv_xname);
+ aha_collect_mbo(sc);
+ if (ccb->flags & CCB_SENDING) {
+ printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
Debugger();
}
+#endif
/*
* If it has been through before, then
* a previous abort has failed, don't
* try abort again
*/
- if (ccb->flags == CCB_ABORTED) {
+ if (ccb->flags & CCB_ABORT) {
/* abort timed out */
printf(" AGAIN\n");
- ccb->xs->retries = 0;
- aha_done(aha, ccb);
+ /* XXX Must reset! */
} else {
/* abort the operation that has timed out */
printf("\n");
ccb->xs->error = XS_TIMEOUT;
- ccb->flags = CCB_ABORTED;
- aha_send_mbo(aha, AHA_MBO_ABORT, ccb);
- /* 2 secs for the abort */
- if ((xs->flags & SCSI_POLL) == 0)
- timeout(aha_timeout, ccb, 2 * hz);
+ ccb->timeout = AHA_ABORT_TIMEOUT;
+ ccb->flags |= CCB_ABORT;
+ aha_queue_ccb(sc, ccb);
}
splx(s);
diff --git a/sys/dev/isa/aha1542.c b/sys/dev/isa/aha1542.c
deleted file mode 100644
index a1c559ad646..00000000000
--- a/sys/dev/isa/aha1542.c
+++ /dev/null
@@ -1,1587 +0,0 @@
-/* $OpenBSD: aha1542.c,v 1.13 1996/03/20 01:00:35 mickey Exp $ */
-/* $NetBSD: aha1542.c,v 1.55 1995/12/24 02:31:06 mycroft Exp $ */
-
-/*
- * Copyright (c) 1994 Charles Hannum. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Charles Hannum.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Originally written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems for use under the MACH(2.5) operating system.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- */
-
-/*
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/syslog.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/errno.h>
-#include <sys/ioctl.h>
-#include <sys/device.h>
-#include <sys/malloc.h>
-#include <sys/buf.h>
-#include <sys/proc.h>
-#include <sys/user.h>
-
-#include <machine/pio.h>
-
-#include <dev/isa/isavar.h>
-#include <dev/isa/isadmavar.h>
-#include <scsi/scsi_all.h>
-#include <scsi/scsiconf.h>
-
-#ifndef DDB
-#define Debugger() panic("should call debugger here (aha1542.c)")
-#endif /* ! DDB */
-
-/* XXX fixme:
- * on i386 at least, xfers to/from user memory
- * cannot be serviced at interrupt time.
- */
-#ifdef i386
-#define VOLATILE_XS(xs) \
- ((xs)->datalen > 0 && (xs)->bp == NULL && \
- ((xs)->flags & SCSI_POLL) == 0)
-#else
-#define VOLATILE_XS(xs) 0
-#endif
-
-#undef TUNE_1542 /* if bus speed check breaks the machine, undefine it */
-
-/************************** board definitions *******************************/
-
-/*
- * I/O Port Interface
- */
-#define AHA_BASE aha->sc_iobase
-#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 */
-
-/*
- * AHA_CTRL_STAT bits (write)
- */
-#define AHA_HRST 0x80 /* Hardware reset */
-#define AHA_SRST 0x40 /* Software reset */
-#define AHA_IRST 0x20 /* Interrupt reset */
-#define AHA_SCRST 0x10 /* SCSI bus reset */
-
-/*
- * AHA_CTRL_STAT bits (read)
- */
-#define AHA_STST 0x80 /* Self test in Progress */
-#define AHA_DIAGF 0x40 /* Diagnostic Failure */
-#define AHA_INIT 0x20 /* Mbx Init required */
-#define AHA_IDLE 0x10 /* Host Adapter Idle */
-#define AHA_CDF 0x08 /* cmd/data out port full */
-#define AHA_DF 0x04 /* Data in port full */
-#define AHA_INVDCMD 0x01 /* Invalid command */
-
-/*
- * AHA_CMD_DATA bits (write)
- */
-#define AHA_NOP 0x00 /* No operation */
-#define AHA_MBX_INIT 0x01 /* Mbx initialization */
-#define AHA_START_SCSI 0x02 /* start scsi command */
-#define AHA_START_BIOS 0x03 /* start bios command */
-#define AHA_INQUIRE 0x04 /* Adapter Inquiry */
-#define AHA_MBO_INTR_EN 0x05 /* Enable MBO available interrupt */
-#define AHA_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
-#define AHA_BUS_ON_TIME_SET 0x07 /* set bus-on time */
-#define AHA_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
-#define AHA_SPEED_SET 0x09 /* set transfer speed */
-#define AHA_DEV_GET 0x0a /* return installed devices */
-#define AHA_CONF_GET 0x0b /* return configuration data */
-#define AHA_TARGET_EN 0x0c /* enable target mode */
-#define AHA_SETUP_GET 0x0d /* return setup data */
-#define AHA_WRITE_CH2 0x1a /* write channel 2 buffer */
-#define AHA_READ_CH2 0x1b /* read channel 2 buffer */
-#define AHA_WRITE_FIFO 0x1c /* write fifo buffer */
-#define AHA_READ_FIFO 0x1d /* read fifo buffer */
-#define AHA_ECHO 0x1e /* Echo command data */
-#define AHA_EXT_BIOS 0x28 /* return extended bios info */
-#define AHA_MBX_ENABLE 0x29 /* enable mail box interface */
-
-/*
- * AHA_INTR_PORT bits (read)
- */
-#define AHA_ANY_INTR 0x80 /* Any interrupt */
-#define AHA_SCRD 0x08 /* SCSI reset detected */
-#define AHA_HACC 0x04 /* Command complete */
-#define AHA_MBOA 0x02 /* MBX out empty */
-#define AHA_MBIF 0x01 /* MBX in full */
-
-/*
- * Mail box defs
- */
-#define AHA_MBX_SIZE 16 /* mail box size */
-
-#define AHA_CCB_MAX 32 /* store up to 32 CCBs at one time */
-#define CCB_HASH_SIZE 32 /* hash table size for phystokv */
-#define CCB_HASH_SHIFT 9
-#define CCB_HASH(x) ((((long)(x))>>CCB_HASH_SHIFT) & (CCB_HASH_SIZE - 1))
-
-#define aha_nextmbx(wmb, mbx, mbio) \
- if ((wmb) == &(mbx)->mbio[AHA_MBX_SIZE - 1]) \
- (wmb) = &(mbx)->mbio[0]; \
- else \
- (wmb)++;
-
-struct aha_mbx_out {
- u_char cmd;
- u_char ccb_addr[3];
-};
-
-struct aha_mbx_in {
- u_char stat;
- u_char ccb_addr[3];
-};
-
-struct aha_mbx {
- struct aha_mbx_out mbo[AHA_MBX_SIZE];
- struct aha_mbx_in mbi[AHA_MBX_SIZE];
- struct aha_mbx_out *tmbo; /* Target Mail Box out */
- struct aha_mbx_in *tmbi; /* Target Mail Box in */
-};
-
-/*
- * mbo.cmd values
- */
-#define AHA_MBO_FREE 0x0 /* MBO entry is free */
-#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 */
-
-/* FOR OLD VERSIONS OF THE !%$@ this may have to be 16 (yuk) */
-#define AHA_NSEG 17 /* Number of scatter gather segments <= 16 */
- /* allow 60 K i/o (min) */
-
-struct aha_ccb {
- u_char opcode;
- u_char lun:3;
- u_char data_in:1; /* must be 0 */
- u_char data_out:1; /* must be 0 */
- u_char target:3;
- u_char scsi_cmd_length;
- u_char req_sense_length;
- u_char data_length[3];
- u_char data_addr[3];
- u_char link_addr[3];
- u_char link_id;
- u_char host_stat;
- u_char target_stat;
- u_char reserved[2];
- struct scsi_generic scsi_cmd;
- struct scsi_sense_data scsi_sense;
- struct aha_scat_gath {
- u_char seg_len[3];
- u_char seg_addr[3];
- } scat_gath[AHA_NSEG];
- /*----------------------------------------------------------------*/
-#define CCB_PHYS_SIZE ((int)&((struct aha_ccb *)0)->chain)
- TAILQ_ENTRY(aha_ccb) chain;
- struct aha_ccb *nexthash;
- struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
- int flags;
-#define CCB_FREE 0
-#define CCB_ACTIVE 1
-#define CCB_ABORTED 2
- struct aha_mbx_out *mbx; /* pointer to mail box */
- struct isadma_seg ccb_phys[1]; /* phys segment of this ccb */
- struct isadma_seg data_phys[AHA_NSEG]; /* phys segments of data */
- int data_nseg; /* number of phys segments of data */
-};
-
-/*
- * 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 scatter gather */
-#define AHA_RESET_CCB 0x81 /* SCSI Bus reset */
-
-/*
- * aha_ccb.host_stat values
- */
-#define AHA_OK 0x00 /* cmd ok */
-#define AHA_LINK_OK 0x0a /* Link cmd ok */
-#define AHA_LINK_IT 0x0b /* Link cmd ok + int */
-#define AHA_SEL_TIMEOUT 0x11 /* Selection time out */
-#define AHA_OVER_UNDER 0x12 /* Data over/under run */
-#define AHA_BUS_FREE 0x13 /* Bus dropped at unexpected time */
-#define AHA_INV_BUS 0x14 /* Invalid bus phase/sequence */
-#define AHA_BAD_MBO 0x15 /* Incorrect MBO cmd */
-#define AHA_BAD_CCB 0x16 /* Incorrect ccb opcode */
-#define AHA_BAD_LINK 0x17 /* Not same values of LUN for links */
-#define AHA_INV_TARGET 0x18 /* Invalid target direction */
-#define AHA_CCB_DUP 0x19 /* Duplicate CCB received */
-#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_config {
- u_char chan;
- u_char intr;
- u_char scsi_dev:3;
- u_char:5;
-};
-
-struct aha_inquire {
- u_char boardid; /* type of board */
- /* 0x31 = AHA-1540 */
- /* 0x41 = AHA-1540A/1542A/1542B */
- /* 0x42 = AHA-1640 */
- /* 0x43 = AHA-1542C */
- /* 0x44 = AHA-1542CF */
- /* 0x45 = AHA-1542CF, BIOS v2.01 */
- u_char spec_opts; /* special options ID */
- /* 0x41 = Board is standard model */
- u_char revision_1; /* firmware revision [0-9A-Z] */
- u_char revision_2; /* firmware revision [0-9A-Z] */
-};
-
-struct aha_extbios {
- u_char flags; /* Bit 3 == 1 extended bios enabled */
- u_char mailboxlock; /* mail box lock code to unlock it */
-};
-
-#define INT9 0x01
-#define INT10 0x02
-#define INT11 0x04
-#define INT12 0x08
-#define INT14 0x20
-#define INT15 0x40
-
-#define CHAN0 0x01
-#define CHAN5 0x20
-#define CHAN6 0x40
-#define CHAN7 0x80
-
-/*********************************** end of board definitions***************/
-
-#ifdef AHADEBUG
-int aha_debug = 1;
-#endif /*AHADEBUG */
-
-struct aha_softc {
- struct device sc_dev;
- struct isadev sc_id;
- void *sc_ih;
-
- int sc_iobase;
- int sc_irq, sc_drq;
-
- struct aha_mbx aha_mbx; /* all the mailboxes */
- struct aha_ccb *ccbhash[CCB_HASH_SIZE];
- TAILQ_HEAD(, aha_ccb) free_ccb;
- int numccbs;
- int aha_scsi_dev; /* our scsi id */
- struct scsi_link sc_link;
-};
-
-int aha_cmd(); /* XXX must be varargs to prototype */
-int ahaintr __P((void *));
-void aha_free_ccb __P((struct aha_softc *, struct aha_ccb *, int));
-struct aha_ccb *aha_get_ccb __P((struct aha_softc *, int));
-struct aha_ccb *aha_ccb_phys_kv __P((struct aha_softc *, u_long));
-struct aha_mbx_out *aha_send_mbo __P((struct aha_softc *, int, struct aha_ccb *));
-void aha_done __P((struct aha_softc *, struct aha_ccb *));
-int aha_find __P((struct aha_softc *));
-void aha_init __P((struct aha_softc *));
-void ahaminphys __P((struct buf *));
-int aha_scsi_cmd __P((struct scsi_xfer *));
-int aha_poll __P((struct aha_softc *, struct scsi_xfer *, int));
-int aha_set_bus_speed __P((struct aha_softc *));
-int aha_bus_speed_check __P((struct aha_softc *, int));
-void aha_timeout __P((void *arg));
-
-struct scsi_adapter aha_switch = {
- aha_scsi_cmd,
- ahaminphys,
- 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 */
-};
-
-int ahaprobe __P((struct device *, void *, void *));
-void ahaattach __P((struct device *, struct device *, void *));
-int ahaprint __P((void *, char *));
-
-struct cfdriver ahacd = {
- NULL, "aha", ahaprobe, ahaattach, DV_DULL, sizeof(struct aha_softc)
-};
-
-#define AHA_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */
-
-/*
- * aha_cmd(aha,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(aha, icnt, ocnt, wait, retval, opcode, args)
- struct aha_softc *aha;
- int icnt, ocnt, wait;
- 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 sec..
- * all wait loops are in 50uSec cycles
- */
- if (wait)
- wait *= 20000;
- else
- 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)
- break;
- delay(50);
- }
- if (!i) {
- printf("%s: aha_cmd, host not idle(0x%x)\n",
- aha->sc_dev.dv_xname, 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)
- 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--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- for (i = wait; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (!(sts & AHA_CDF))
- break;
- delay(50);
- }
- if (!i) {
- if (opcode != AHA_INQUIRE)
- printf("%s: aha_cmd, cmd/data port full\n",
- aha->sc_dev.dv_xname);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
- return ENXIO;
- }
- 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--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- for (i = wait; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts & AHA_DF)
- break;
- delay(50);
- }
- if (!i) {
- if (opcode != AHA_INQUIRE)
- printf("%s: aha_cmd, cmd/data port empty %d\n",
- aha->sc_dev.dv_xname, ocnt);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
- return ENXIO;
- }
- oc = inb(AHA_CMD_DATA_PORT);
- if (retval)
- *retval++ = oc;
- }
- /*
- * Wait for the board to report a finised instruction
- */
- i = 20000;
- while (--i) {
- sts = inb(AHA_INTR_PORT);
- if (sts & AHA_HACC)
- break;
- delay(50);
- }
- if (!i) {
- printf("%s: aha_cmd, host not finished(0x%x)\n",
- aha->sc_dev.dv_xname, sts);
- return ENXIO;
- }
- outb(AHA_CTRL_STAT_PORT, AHA_IRST);
- 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_device structure from
- * autoconf.c
- */
-int
-ahaprobe(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- struct aha_softc *aha = match;
- struct isa_attach_args *ia = aux;
-
-#ifdef NEWCONFIG
- if (ia->ia_iobase == IOBASEUNK)
- return 0;
-#endif
-
- aha->sc_iobase = ia->ia_iobase;
-
- /*
- * Try initialise a unit at this location
- * sets up dma and bus speed, loads aha->sc_irq
- */
- if (aha_find(aha) != 0)
- return 0;
-
- if (ia->ia_irq != IRQUNK) {
- if (ia->ia_irq != aha->sc_irq) {
- printf("%s: irq mismatch; kernel configured %d != board configured %d\n",
- aha->sc_dev.dv_xname, ia->ia_irq, aha->sc_irq);
- return 0;
- }
- } else
- ia->ia_irq = aha->sc_irq;
-
- if (ia->ia_drq != DRQUNK) {
- if (ia->ia_drq != aha->sc_drq) {
- printf("%s: drq mismatch; kernel configured %d != board configured %d\n",
- aha->sc_dev.dv_xname, ia->ia_drq, aha->sc_drq);
- return 0;
- }
- } else
- ia->ia_drq = aha->sc_drq;
-
- ia->ia_msize = 0;
- ia->ia_iosize = 4;
- return 1;
-}
-
-int
-ahaprint(aux, name)
- void *aux;
- char *name;
-{
- if (name != NULL)
- printf("%s: scsibus ", name);
- return UNCONF;
-}
-
-/*
- * Attach all the sub-devices we can find
- */
-void
-ahaattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
-{
- struct isa_attach_args *ia = aux;
- struct aha_softc *aha = (void *)self;
-
- if (ia->ia_drq != DRQUNK)
- isadma_cascade(ia->ia_drq);
-
- aha_init(aha);
- TAILQ_INIT(&aha->free_ccb);
-
- /*
- * fill in the prototype scsi_link.
- */
- aha->sc_link.adapter_softc = aha;
- aha->sc_link.adapter_target = aha->aha_scsi_dev;
- aha->sc_link.adapter = &aha_switch;
- aha->sc_link.device = &aha_dev;
- aha->sc_link.openings = 2;
-
- printf("\n");
-
-#ifdef NEWCONFIG
- isa_establish(&aha->sc_id, &aha->sc_dev);
-#endif
- aha->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO, ahaintr,
- aha, aha->sc_dev.dv_xname);
-
- /*
- * ask the adapter what subunits are present
- */
- config_found(self, &aha->sc_link, ahaprint);
-}
-
-/*
- * Catch an interrupt from the adaptor
- */
-int
-ahaintr(arg)
- void *arg;
-{
- struct aha_softc *aha = arg;
- struct aha_mbx_in *wmbi;
- struct aha_mbx *wmbx;
- struct aha_ccb *ccb;
- u_char stat;
- int i;
- int found = 0;
-
-#ifdef AHADEBUG
- printf("%s: ahaintr ", aha->sc_dev.dv_xname);
-#endif /*AHADEBUG */
-
- /*
- * First acknowlege the interrupt, Then if it's not telling about
- * a completed operation just return.
- */
- stat = inb(AHA_INTR_PORT);
- if ((stat & (AHA_MBOA | AHA_MBIF)) == 0) {
- outb(AHA_CTRL_STAT_PORT, AHA_IRST);
- return -1; /* XXX */
- }
-
- /* Mail box out empty? */
- if (stat & AHA_MBOA) {
- /* Disable MBO available interrupt. */
- outb(AHA_CMD_DATA_PORT, AHA_MBO_INTR_EN);
- for (i = 100000; i; i--) {
- if (!(inb(AHA_CTRL_STAT_PORT) & AHA_CDF))
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: ahaintr, cmd/data port full\n",
- aha->sc_dev.dv_xname);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
- return 1;
- }
- outb(AHA_CMD_DATA_PORT, 0x00); /* Disable */
- wakeup(&aha->aha_mbx);
- }
-
- /* Mail box in full? */
- if ((stat & AHA_MBIF) == 0)
- return 1;
- wmbx = &aha->aha_mbx;
- wmbi = wmbx->tmbi;
-AGAIN:
- while (wmbi->stat != AHA_MBI_FREE) {
- ccb = aha_ccb_phys_kv(aha, _3btol(wmbi->ccb_addr));
- if (!ccb) {
- wmbi->stat = AHA_MBI_FREE;
- printf("%s: BAD CCB ADDR!\n", aha->sc_dev.dv_xname);
- continue;
- }
- found++;
- switch (wmbi->stat) {
- case AHA_MBI_OK:
- case AHA_MBI_ERROR:
- break;
-
- case AHA_MBI_ABORT:
- ccb->host_stat = AHA_ABORTED;
- break;
-
- case AHA_MBI_UNKNOWN:
- ccb = 0;
- break;
-
- default:
- panic("Impossible mbxi status");
- }
-#ifdef AHADEBUG
- if (aha_debug && ccb) {
- u_char *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("stat %x for mbi addr = 0x%08x, ",
- wmbi->stat, wmbi);
- printf("ccb addr = 0x%x\n", ccb);
- }
-#endif /* AHADEBUG */
- wmbi->stat = AHA_MBI_FREE;
- if (ccb) {
- untimeout(aha_timeout, ccb);
- aha_done(aha, ccb);
- }
- aha_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
- for (i = 0; i < AHA_MBX_SIZE; i++) {
- if (wmbi->stat != AHA_MBI_FREE) {
- found++;
- break;
- }
- aha_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
-#if 0
- printf("%s: mbi interrupt with no full mailboxes\n",
- aha->sc_dev.dv_xname);
-#endif
- } else {
- found = 0;
- goto AGAIN;
- }
- }
- wmbx->tmbi = wmbi;
- outb(AHA_CTRL_STAT_PORT, AHA_IRST);
- return 1;
-}
-
-/*
- * A ccb (and hence a mbx-out is put onto the
- * free list.
- */
-void
-aha_free_ccb(aha, ccb, flags)
- struct aha_softc *aha;
- struct aha_ccb *ccb;
- int flags;
-{
- int s, hashnum;
- struct aha_ccb **hashccb;
-
- s = splbio();
-
- if (ccb->ccb_phys[0].addr)
- isadma_unmap((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys);
-
- /* remove from hash table */
-
- hashnum = CCB_HASH(ccb->ccb_phys[0].addr);
- hashccb = &aha->ccbhash[hashnum];
-
- while (*hashccb) {
- if ((*hashccb)->ccb_phys[0].addr == ccb->ccb_phys[0].addr) {
- *hashccb = (*hashccb)->nexthash;
- break;
- }
- hashccb = &(*hashccb)->nexthash;
- }
-
- ccb->flags = CCB_FREE;
- TAILQ_INSERT_HEAD(&aha->free_ccb, ccb, chain);
-
- /*
- * If there were none, wake anybody waiting for one to come free,
- * starting with queued entries.
- */
- if (ccb->chain.tqe_next == 0)
- wakeup(&aha->free_ccb);
-
- splx(s);
-}
-
-static inline void
-aha_init_ccb(aha, ccb)
- struct aha_softc *aha;
- struct aha_ccb *ccb;
-{
- bzero(ccb, sizeof(struct aha_ccb));
-}
-
-static inline void
-aha_reset_ccb(aha, ccb)
- struct aha_softc *aha;
- struct aha_ccb *ccb;
-{
-
-}
-
-/*
- * Get a free ccb
- */
-struct aha_ccb *
-aha_get_ccb(aha, flags)
- struct aha_softc *aha;
- int flags;
-{
- struct aha_ccb *ccb;
- int hashnum, mflags, s;
-
- s = splbio();
-
- if (flags & SCSI_NOSLEEP)
- mflags = ISADMA_MAP_BOUNCE;
- else
- mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK;
-
- /*
- * If we can and have to, sleep waiting for one
- * to come free
- */
- for (;;) {
- ccb = aha->free_ccb.tqh_first;
- if (ccb) {
- TAILQ_REMOVE(&aha->free_ccb, ccb, chain);
- break;
- }
- if (aha->numccbs < AHA_CCB_MAX) {
- if (ccb = (struct aha_ccb *) malloc(sizeof(struct aha_ccb),
- M_TEMP, M_NOWAIT)) {
- aha_init_ccb(aha, ccb);
- aha->numccbs++;
- } else {
- printf("%s: can't malloc ccb\n",
- aha->sc_dev.dv_xname);
- goto out;
- }
- break;
- }
- if ((flags & SCSI_NOSLEEP) != 0)
- goto out;
- tsleep(&aha->free_ccb, PRIBIO, "ahaccb", 0);
- }
-
- aha_reset_ccb(aha, ccb);
- ccb->flags = CCB_ACTIVE;
-
- if (isadma_map((caddr_t)ccb, CCB_PHYS_SIZE, ccb->ccb_phys,
- mflags | ISADMA_MAP_CONTIG) == 1) {
- hashnum = CCB_HASH(ccb->ccb_phys[0].addr);
- ccb->nexthash = aha->ccbhash[hashnum];
- aha->ccbhash[hashnum] = ccb;
- } else {
- ccb->ccb_phys[0].addr = 0;
- aha_free_ccb(aha, ccb, flags);
- ccb = 0;
- }
-
-out:
- splx(s);
- return (ccb);
-}
-
-/*
- * given a physical address, find the ccb that it corresponds to.
- */
-struct aha_ccb *
-aha_ccb_phys_kv(aha, ccb_phys)
- struct aha_softc *aha;
- u_long ccb_phys;
-{
- int hashnum = CCB_HASH(ccb_phys);
- struct aha_ccb *res = aha->ccbhash[hashnum];
-
- while (res) {
- if (res->ccb_phys[0].addr == ccb_phys)
- break;
- res = res->nexthash;
- }
-
- return res;
-}
-
-/*
- * Get a mbo and send the ccb.
- */
-struct aha_mbx_out *
-aha_send_mbo(aha, cmd, ccb)
- struct aha_softc *aha;
- int cmd;
- struct aha_ccb *ccb;
-{
- struct aha_mbx_out *wmbo; /* Mail Box Out pointer */
- struct aha_mbx *wmbx; /* Mail Box pointer specified unit */
- int i;
-
- /* Get the target out mail box pointer and increment. */
- wmbx = &aha->aha_mbx;
- wmbo = wmbx->tmbo;
- aha_nextmbx(wmbx->tmbo, wmbx, mbo);
-
- /*
- * Check the outmail box is free or not.
- * Note: Under the normal operation, it shuld NOT happen to wait.
- */
- while (wmbo->cmd != AHA_MBO_FREE) {
- /* Enable mbo available interrupt. */
- outb(AHA_CMD_DATA_PORT, AHA_MBO_INTR_EN);
- for (i = 100000; i; i--) {
- if (!(inb(AHA_CTRL_STAT_PORT) & AHA_CDF))
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: aha_send_mbo, cmd/data port full\n",
- aha->sc_dev.dv_xname);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
- return NULL;
- }
- outb(AHA_CMD_DATA_PORT, 0x01); /* Enable */
- tsleep(wmbx, PRIBIO, "ahasnd", 0);/*XXX can't do this */
- }
-
- /* Link ccb to mbo. */
- lto3b(ccb->ccb_phys[0].addr, wmbo->ccb_addr);
- ccb->mbx = wmbo;
- wmbo->cmd = cmd;
-
- /* Sent it! */
- outb(AHA_CMD_DATA_PORT, AHA_START_SCSI);
-
- 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
- */
-void
-aha_done(aha, ccb)
- struct aha_softc *aha;
- struct aha_ccb *ccb;
-{
- struct scsi_sense_data *s1, *s2;
- struct scsi_xfer *xs = ccb->xs;
-
- 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) == 0) {
- printf("%s: exiting but not in use!\n", aha->sc_dev.dv_xname);
- Debugger();
- }
- if (xs->error == XS_NOERROR) {
- if (ccb->host_stat != AHA_OK) {
- switch (ccb->host_stat) {
- case AHA_ABORTED:
- xs->error = XS_DRIVER_STUFFUP;
- break;
- case AHA_SEL_TIMEOUT: /* No response */
- xs->error = XS_SELTIMEOUT;
- break;
- default: /* Other scsi protocol messes */
- printf("%s: host_stat %x\n",
- aha->sc_dev.dv_xname, ccb->host_stat);
- xs->error = XS_DRIVER_STUFFUP;
- }
- } else if (ccb->target_stat != SCSI_OK) {
- switch (ccb->target_stat) {
- case SCSI_CHECK:
- s1 = (struct scsi_sense_data *) (((char *) (&ccb->scsi_cmd)) +
- ccb->scsi_cmd_length);
- s2 = &xs->sense;
- *s2 = *s1;
- xs->error = XS_SENSE;
- break;
- case SCSI_BUSY:
- xs->error = XS_BUSY;
- break;
- default:
- printf("%s: target_stat %x\n",
- aha->sc_dev.dv_xname, ccb->target_stat);
- xs->error = XS_DRIVER_STUFFUP;
- }
- } else
- xs->resid = 0;
- }
- xs->flags |= ITSDONE;
-
- if (VOLATILE_XS(xs)) {
- wakeup(ccb);
- return;
- }
-
- if (ccb->data_nseg) {
- if (xs->flags & SCSI_DATA_IN)
- isadma_copyfrombuf(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- isadma_unmap(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- }
- aha_free_ccb(aha, ccb, xs->flags);
- scsi_done(xs);
-}
-
-/*
- * Find the board and find its irq/drq
- */
-int
-aha_find(aha)
- struct aha_softc *aha;
-{
- 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
- */
-
- outb(AHA_CTRL_STAT_PORT, AHA_HRST | AHA_SRST);
-
- 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) {
-#ifdef AHADEBUG
- if (aha_debug)
- printf("aha_find: No answer from adaptec board\n");
-#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. If the command
- * fails, we assume it's either a crusty board or an old 1542
- * clone, and skip the board-specific stuff.
- */
- if (aha_cmd(aha, 0, sizeof(inquire), 1, &inquire, AHA_INQUIRE)) {
- /*
- * aha_cmd() already started the reset. It's not clear we
- * even need to bother here.
- */
- for (i = AHA_RESET_TIMEOUT; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts == (AHA_IDLE | AHA_INIT))
- break;
- delay(1000);
- }
- if (!i) {
-#ifdef AHADEBUG
- printf("aha_init: soft reset failed\n");
-#endif /* AHADEBUG */
- return ENXIO;
- }
-#ifdef AHADEBUG
- printf("aha_init: inquire command failed\n");
-#endif /* AHADEBUG */
- goto noinquire;
- }
-#ifdef AHADEBUG
- printf("%s: inquire %x, %x, %x, %x\n",
- aha->sc_dev.dv_xname,
- inquire.boardid, inquire.spec_opts,
- inquire.revision_1, inquire.revision_2);
-#endif /* AHADEBUG */
- /*
- * If we are a 1542C or 1542CF disable the extended bios so that the
- * mailbox interface is unlocked.
- * No need to check the extended bios flags as some of the
- * extensions that cause us problems are not flagged in that byte.
- */
- if (inquire.boardid == 0x43 || inquire.boardid == 0x44 ||
- inquire.boardid == 0x45) {
- aha_cmd(aha, 0, sizeof(extbios), 0, &extbios, AHA_EXT_BIOS);
-#ifdef AHADEBUG
- printf("%s: extended bios flags %x\n", aha->sc_dev.dv_xname,
- extbios.flags);
-#endif /* AHADEBUG */
- printf("%s: 1542C/CF detected, unlocking mailbox\n",
- aha->sc_dev.dv_xname);
- aha_cmd(aha, 2, 0, 0, 0, AHA_MBX_ENABLE,
- 0, extbios.mailboxlock);
- }
-noinquire:
-
- /*
- * setup dma channel from jumpers and save int
- * level
- */
- delay(1000); /* for Bustek 545 */
- aha_cmd(aha, 0, sizeof(conf), 0, &conf, AHA_CONF_GET);
- switch (conf.chan) {
- case CHAN0:
- aha->sc_drq = 0;
- break;
- case CHAN5:
- aha->sc_drq = 5;
- break;
- case CHAN6:
- aha->sc_drq = 6;
- break;
- case CHAN7:
- aha->sc_drq = 7;
- break;
- default:
- printf("%s: illegal drq setting %x\n", aha->sc_dev.dv_xname,
- conf.chan);
- return EIO;
- }
-
- switch (conf.intr) {
- case INT9:
- aha->sc_irq = 9;
- break;
- case INT10:
- aha->sc_irq = 10;
- break;
- case INT11:
- aha->sc_irq = 11;
- break;
- case INT12:
- aha->sc_irq = 12;
- break;
- case INT14:
- aha->sc_irq = 14;
- break;
- case INT15:
- aha->sc_irq = 15;
- break;
- default:
- printf("%s: illegal irq setting %x\n", aha->sc_dev.dv_xname,
- conf.intr);
- return EIO;
- }
-
- /* who are we on the scsi bus? */
- aha->aha_scsi_dev = conf.scsi_dev;
-
- /*
- * Change the bus on/off times to not clash with other dma users.
- */
- aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7);
- aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4);
-
- return 0;
-}
-
-/*
- * Start the board, ready for normal operation
- */
-void
-aha_init(aha)
- struct aha_softc *aha;
-{
- u_char ad[3];
- struct isadma_seg mbx_phys[1];
- int i;
-
-#ifdef TUNE_1542
- /*
- * Initialize memory transfer speed
- * Not compiled in by default because it breaks some machines
- */
- if (!aha_set_bus_speed(aha))
- panic("aha_init: cannot set bus speed");
-#endif /* TUNE_1542 */
-
- /*
- * Initialize mail box. This mapping will never be undone.
- */
- if (isadma_map((caddr_t)(&aha->aha_mbx), sizeof(struct aha_mbx),
- mbx_phys, ISADMA_MAP_CONTIG) != 1)
- panic("aha_init: cannot map mail box");
- lto3b(mbx_phys[0].addr, ad);
-
- aha_cmd(aha, 4, 0, 0, 0, AHA_MBX_INIT, AHA_MBX_SIZE,
- ad[0], ad[1], ad[2]);
-
- for (i = 0; i < AHA_MBX_SIZE; i++) {
- aha->aha_mbx.mbo[i].cmd = AHA_MBO_FREE;
- aha->aha_mbx.mbi[i].stat = AHA_MBO_FREE;
- }
-
- /*
- * Set up initial mail box for round-robin operation.
- */
- aha->aha_mbx.tmbo = &aha->aha_mbx.mbo[0];
- aha->aha_mbx.tmbi = &aha->aha_mbx.mbi[0];
-}
-
-void
-ahaminphys(bp)
- struct buf *bp;
-{
-
- if (bp->b_bcount > ((AHA_NSEG - 1) << PGSHIFT))
- bp->b_bcount = ((AHA_NSEG - 1) << PGSHIFT);
- minphys(bp);
-}
-
-/*
- * 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;
-{
- struct scsi_link *sc_link = xs->sc_link;
- struct aha_softc *aha = sc_link->adapter_softc;
- struct aha_ccb *ccb;
- struct aha_scat_gath *sg;
- int seg, datalen, flags, mflags;
- struct iovec *iovp;
- struct aha_mbx_out *mbo;
- int s;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("aha_scsi_cmd\n"));
- /*
- * get a ccb 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 & SCSI_NOSLEEP)
- mflags = ISADMA_MAP_BOUNCE;
- else
- mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK;
- if ((flags & (ITSDONE|INUSE)) != INUSE) {
- printf("%s: done or not in use?\n", aha->sc_dev.dv_xname);
- xs->flags &= ~ITSDONE;
- xs->flags |= INUSE;
- }
- if ((ccb = aha_get_ccb(aha, flags)) == NULL) {
- xs->error = XS_DRIVER_STUFFUP;
- return TRY_AGAIN_LATER;
- }
- ccb->xs = xs;
-
- /*
- * Put all the arguments for the xfer in the ccb
- */
- 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->data_out = 0;
- ccb->data_in = 0;
- ccb->target = sc_link->target;
- ccb->lun = sc_link->lun;
- ccb->scsi_cmd_length = xs->cmdlen;
- ccb->req_sense_length = sizeof(ccb->scsi_sense);
- ccb->host_stat = 0x00;
- ccb->target_stat = 0x00;
- ccb->data_nseg = 0;
-
- if (xs->datalen && (flags & SCSI_RESET) == 0) {
- sg = ((struct aha_ccb *)(ccb->ccb_phys[0].addr))->scat_gath;
- lto3b((vm_offset_t)sg, ccb->data_addr);
- 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 < AHA_NSEG) {
- lto3b(iovp->iov_base, sg->seg_addr);
- lto3b(iovp->iov_len, sg->seg_len);
- xs->datalen += iovp->iov_len;
- SC_DEBUGN(sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)",
- iovp->iov_len, iovp->iov_base));
- sg++;
- iovp++;
- seg++;
- datalen--;
- }
- } else
-#endif /*TFS_ONLY */
- {
- /*
- * Set up the scatter gather block
- */
-
- ccb->data_nseg = isadma_map(xs->data, xs->datalen,
- ccb->data_phys, mflags);
- for (seg = 0; seg < ccb->data_nseg; seg++) {
- lto3b(ccb->data_phys[seg].addr,
- sg[seg].seg_addr);
- lto3b(ccb->data_phys[seg].length,
- sg[seg].seg_len);
- }
- }
- lto3b(ccb->data_nseg * sizeof(struct aha_scat_gath), ccb->data_length);
- if (ccb->data_nseg == 0) {
- printf("%s: aha_scsi_cmd, cannot map\n",
- aha->sc_dev.dv_xname);
- xs->error = XS_DRIVER_STUFFUP;
- aha_free_ccb(aha, ccb, flags);
- return COMPLETE;
- } else if (flags & SCSI_DATA_OUT)
- isadma_copytobuf(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- } else { /* No data xfer, use non S/G values */
- lto3b(0, ccb->data_addr);
- lto3b(0, ccb->data_length);
- }
- ccb->link_id = 0;
- lto3b(0, ccb->link_addr);
-
- /*
- * Put the scsi command in the ccb and start it
- */
- if ((flags & SCSI_RESET) == 0)
- bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmd_length);
-
- s = splbio();
-
- isadma_copytobuf((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys);
-
- if (aha_send_mbo(aha, AHA_MBO_START, ccb) == NULL) {
- splx(s);
- xs->error = XS_DRIVER_STUFFUP;
- if (ccb->data_nseg)
- isadma_unmap(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- aha_free_ccb(aha, ccb, flags);
- return TRY_AGAIN_LATER;
- }
-
- /*
- * Usually return SUCCESSFULLY QUEUED
- */
- SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
-
- if (VOLATILE_XS(xs)) {
- timeout(aha_timeout, ccb, (xs->timeout * hz) / 1000);
- while ((ccb->xs->flags & ITSDONE) == 0) {
- tsleep(ccb, PRIBIO, "ahawait", 0);
- }
- splx(s);
- if (ccb->data_nseg) {
- if (flags & SCSI_DATA_IN)
- isadma_copyfrombuf(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- isadma_unmap(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- }
- aha_free_ccb(aha, ccb, xs->flags);
- scsi_done(xs);
- return COMPLETE;
- }
-
- if ((flags & SCSI_POLL) == 0) {
- timeout(aha_timeout, ccb, (xs->timeout * hz) / 1000);
- splx(s);
- return SUCCESSFULLY_QUEUED;
- }
-
- splx(s);
-
- /*
- * If we can't use interrupts, poll on completion
- */
- if (aha_poll(aha, xs, xs->timeout)) {
- aha_timeout(ccb);
- if (aha_poll(aha, xs, 2000))
- aha_timeout(ccb);
- }
- return COMPLETE;
-}
-
-/*
- * Poll a particular unit, looking for a particular xs
- */
-int
-aha_poll(aha, xs, count)
- struct aha_softc *aha;
- struct scsi_xfer *xs;
- int count;
-{
-
- /* timeouts are in msec, so we loop in 1000 usec cycles */
- while (count) {
- /*
- * If we had interrupts enabled, would we
- * have got an interrupt?
- */
- if (inb(AHA_INTR_PORT) & AHA_ANY_INTR)
- ahaintr(aha);
- if (xs->flags & ITSDONE)
- return 0;
- delay(1000); /* only happens in boot so ok */
- count--;
- }
- return 1;
-}
-
-#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 {
- u_char arg;
- int nsecs;
-} aha_bus_speeds[] = {
- {0x88, 100},
- {0x99, 150},
- {0xaa, 200},
- {0xbb, 250},
- {0xcc, 300},
- {0xdd, 350},
- {0xee, 400},
- {0xff, 450}
-};
-
-int
-aha_set_bus_speed(aha)
- struct aha_softc *aha;
-{
- int speed;
- int lastworking;
-
- lastworking = -1;
- for (speed = 7; speed >= 0; speed--) {
- if (!aha_bus_speed_check(aha, speed))
- break;
- lastworking = speed;
- }
- if (lastworking == -1) {
- printf(" no working bus speed");
- return 0;
- }
- printf(", %d nsec ", aha_bus_speeds[lastworking].nsecs);
- if (lastworking == 7) /* is slowest already */
- printf("marginal");
- else {
- lastworking++;
- printf("ok, using %d nsec", aha_bus_speeds[lastworking].nsecs);
- }
- if (!aha_bus_speed_check(aha, lastworking)) {
- printf("test retry failed.. aborting.");
- return 0;
- }
- return 1;
-}
-
-/*
- * 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 COMPLETE.
- */
-char aha_scratch_buf[256];
-char aha_test_string[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz!@";
-
-int
-aha_bus_speed_check(aha, speed)
- struct aha_softc *aha;
- int speed;
-{
- int numspeeds = sizeof(aha_bus_speeds) / sizeof(struct bus_speed);
- int result, loopcount;
- struct isadma_seg test_phys[1], scratch_phys[1];
- u_char ad[3];
-
- result = 1;
-
- if (isadma_map(aha_scratch_buf, sizeof(aha_scratch_buf),
- scratch_phys, ISADMA_MAP_CONTIG) != 1)
- return 0;
- if (isadma_map(aha_test_string, sizeof(aha_test_string),
- test_phys, ISADMA_MAP_CONTIG) != 1) {
- isadma_unmap(aha_scratch_buf, sizeof(aha_scratch_buf),
- 1, scratch_phys);
- return 0;
- }
- isadma_copytobuf(aha_test_string, sizeof(aha_test_string),
- 1, test_phys);
-
- /*
- * Set the dma-speed
- */
- aha_cmd(aha, 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
- */
- for (loopcount = 100; loopcount; loopcount--) {
- lto3b(test_phys[0].addr, ad);
- aha_cmd(aha, 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);
- isadma_copytobuf(aha_scratch_buf, sizeof(aha_scratch_buf),
- 1, scratch_phys);
-
- lto3b(scratch_phys[0].addr, ad);
- aha_cmd(aha, 3, 0, 0, 0, AHA_READ_FIFO, ad[0], ad[1], ad[2]);
- isadma_copyfrombuf(aha_scratch_buf, sizeof(aha_scratch_buf),
- 1, scratch_phys);
-
- /*
- * Compare the original data and the final data and return the
- * correct value depending upon the result. We only check the
- * first 54 bytes, because that's all the board copies during
- * WRITE_FIFO and READ_FIFO.
- */
- if (bcmp(aha_test_string, aha_scratch_buf, 54)) {
- result = 0; /* failed test */
- break;
- }
- }
-
- isadma_unmap(aha_scratch_buf, sizeof(aha_scratch_buf),
- 1, scratch_phys);
- isadma_unmap(aha_test_string, sizeof(aha_test_string),
- 1, test_phys);
-
- /* copy succeeded; assume speed ok */
- return result;
-}
-#endif /* TUNE_1542 */
-
-void
-aha_timeout(arg)
- void *arg;
-{
- struct aha_ccb *ccb = arg;
- struct scsi_xfer *xs = ccb->xs;
- struct scsi_link *sc_link = xs->sc_link;
- struct aha_softc *aha = sc_link->adapter_softc;
- int s;
-
- sc_print_addr(sc_link);
- printf("timed out");
-
- s = splbio();
-
- /*
- * If The ccb's mbx is not free, then the board has gone south?
- */
- if (aha_ccb_phys_kv(aha, _3btol(ccb->mbx->ccb_addr)) == ccb &&
- ccb->mbx->cmd != AHA_MBO_FREE) {
- printf("%s: not taking commands!\n", aha->sc_dev.dv_xname);
- 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(" AGAIN\n");
- ccb->xs->retries = 0;
- aha_done(aha, ccb);
- } else {
- /* abort the operation that has timed out */
- printf("\n");
- ccb->xs->error = XS_TIMEOUT;
- ccb->flags = CCB_ABORTED;
- aha_send_mbo(aha, AHA_MBO_ABORT, ccb);
- /* 2 secs for the abort */
- if ((xs->flags & SCSI_POLL) == 0)
- timeout(aha_timeout, ccb, 2 * hz);
- }
-
- splx(s);
-}
diff --git a/sys/dev/isa/aha284x.c b/sys/dev/isa/aha284x.c
index 749f87840e0..bff15bed8e3 100644
--- a/sys/dev/isa/aha284x.c
+++ b/sys/dev/isa/aha284x.c
@@ -1,4 +1,4 @@
-/* $NetBSD: aha284x.c,v 1.2 1996/01/13 02:06:30 thorpej Exp $ */
+/* $NetBSD: aha284x.c,v 1.4 1996/04/11 22:28:04 cgd Exp $ */
/*
* Copyright (c) 1996 Michael Graff. All rights reserved.
@@ -47,13 +47,12 @@
static int ahe_probe __P((struct device *, void *, void *));
static void ahe_attach __P((struct device *, struct device *, void *));
-struct cfdriver ahecd = {
- NULL, /* devices found */
- "ahe", /* device name */
- ahe_probe, /* match routine */
- ahe_attach, /* attach routine */
- DV_DULL, /* device class */
- sizeof(struct ahc_softc), /* size of private dev data */
+struct cfattach ahe_ca = {
+ sizeof(struct ahc_softc), ahe_probe, ahe_attach
+};
+
+struct cfdriver ahe_cd = {
+ NULL, "ahe", DV_DULL
};
/*
@@ -179,8 +178,8 @@ ahe_attach(parent, self, aux)
#ifdef NEWCONFIG
isa_establish(&ahc->sc_id, &ahc->sc_dev);
#endif
- ahc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO,
- ahcintr, ahc, ahc->sc_dev.dv_xname);
+ ahc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, ahcintr, ahc, ahc->sc_dev.dv_xname);
/*
* attach the devices on the bus
diff --git a/sys/dev/isa/ahareg.h b/sys/dev/isa/ahareg.h
new file mode 100644
index 00000000000..a55684bf044
--- /dev/null
+++ b/sys/dev/isa/ahareg.h
@@ -0,0 +1,264 @@
+typedef u_int8_t physaddr[3];
+typedef u_int8_t physlen[3];
+#define ltophys _lto3b
+#define phystol _3btol
+
+/*
+ * I/O port offsets
+ */
+#define AHA_CTRL_PORT 0 /* control (wo) */
+#define AHA_STAT_PORT 0 /* status (ro) */
+#define AHA_CMD_PORT 1 /* command (wo) */
+#define AHA_DATA_PORT 1 /* data (ro) */
+#define AHA_INTR_PORT 2 /* interrupt status (ro) */
+
+/*
+ * AHA_CTRL bits
+ */
+#define AHA_CTRL_HRST 0x80 /* Hardware reset */
+#define AHA_CTRL_SRST 0x40 /* Software reset */
+#define AHA_CTRL_IRST 0x20 /* Interrupt reset */
+#define AHA_CTRL_SCRST 0x10 /* SCSI bus reset */
+
+/*
+ * AHA_STAT bits
+ */
+#define AHA_STAT_STST 0x80 /* Self test in Progress */
+#define AHA_STAT_DIAGF 0x40 /* Diagnostic Failure */
+#define AHA_STAT_INIT 0x20 /* Mbx Init required */
+#define AHA_STAT_IDLE 0x10 /* Host Adapter Idle */
+#define AHA_STAT_CDF 0x08 /* cmd/data out port full */
+#define AHA_STAT_DF 0x04 /* Data in port full */
+#define AHA_STAT_INVDCMD 0x01 /* Invalid command */
+
+/*
+ * AHA_CMD opcodes
+ */
+#define AHA_NOP 0x00 /* No operation */
+#define AHA_MBX_INIT 0x01 /* Mbx initialization */
+#define AHA_START_SCSI 0x02 /* start scsi command */
+#define AHA_INQUIRE_REVISION 0x04 /* Adapter Inquiry */
+#define AHA_MBO_INTR_EN 0x05 /* Enable MBO available interrupt */
+/*#define AHA_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
+/*#define AHA_BUS_ON_TIME_SET 0x07 /* set bus-on time */
+/*#define AHA_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
+/*#define AHA_SPEED_SET 0x09 /* set transfer speed */
+#define AHA_INQUIRE_DEVICES 0x0a /* return installed devices 0-7 */
+#define AHA_INQUIRE_CONFIG 0x0b /* return configuration data */
+#define AHA_TARGET_EN 0x0c /* enable target mode */
+#define AHA_INQUIRE_SETUP 0x0d /* return setup data */
+#define AHA_ECHO 0x1e /* Echo command data */
+#define AHA_INQUIRE_DEVICES_2 0x23 /* return installed devices 8-15 */
+#define AHA_EXT_BIOS 0x28 /* return extended bios info */
+#define AHA_MBX_ENABLE 0x29 /* enable mail box interface */
+
+/*
+ * AHA_INTR bits
+ */
+#define AHA_INTR_ANYINTR 0x80 /* Any interrupt */
+#define AHA_INTR_SCRD 0x08 /* SCSI reset detected */
+#define AHA_INTR_HACC 0x04 /* Command complete */
+#define AHA_INTR_MBOA 0x02 /* MBX out empty */
+#define AHA_INTR_MBIF 0x01 /* MBX in full */
+
+struct aha_mbx_out {
+ u_char cmd;
+ physaddr ccb_addr;
+};
+
+struct aha_mbx_in {
+ u_char stat;
+ physaddr ccb_addr;
+};
+
+/*
+ * mbo.cmd values
+ */
+#define AHA_MBO_FREE 0x0 /* MBO entry is free */
+#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 */
+
+/* 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_scat_gath {
+ physlen seg_len;
+ physaddr seg_addr;
+};
+
+struct aha_ccb {
+ u_char opcode;
+ u_char lun:3;
+ u_char data_in:1; /* must be 0 */
+ u_char data_out:1; /* must be 0 */
+ u_char target:3;
+ u_char scsi_cmd_length;
+ u_char req_sense_length;
+ physlen data_length;
+ physaddr data_addr;
+ physaddr link_addr;
+ u_char link_id;
+ u_char host_stat;
+ u_char target_stat;
+ u_char reserved[2];
+ struct scsi_generic scsi_cmd;
+ struct scsi_sense_data scsi_sense;
+ struct aha_scat_gath scat_gath[AHA_NSEG];
+ /*----------------------------------------------------------------*/
+ TAILQ_ENTRY(aha_ccb) chain;
+ struct aha_ccb *nexthash;
+ long hashkey;
+ struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
+ int flags;
+#define CCB_ALLOC 0x01
+#define CCB_ABORT 0x02
+#ifdef AHADIAG
+#define CCB_SENDING 0x04
+#endif
+ int timeout;
+};
+
+/*
+ * 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 scatter gather */
+#define AHA_RESET_CCB 0x81 /* SCSI Bus reset */
+
+/*
+ * aha_ccb.host_stat values
+ */
+#define AHA_OK 0x00 /* cmd ok */
+#define AHA_LINK_OK 0x0a /* Link cmd ok */
+#define AHA_LINK_IT 0x0b /* Link cmd ok + int */
+#define AHA_SEL_TIMEOUT 0x11 /* Selection time out */
+#define AHA_OVER_UNDER 0x12 /* Data over/under run */
+#define AHA_BUS_FREE 0x13 /* Bus dropped at unexpected time */
+#define AHA_INV_BUS 0x14 /* Invalid bus phase/sequence */
+#define AHA_BAD_MBO 0x15 /* Incorrect MBO cmd */
+#define AHA_BAD_CCB 0x16 /* Incorrect ccb opcode */
+#define AHA_BAD_LINK 0x17 /* Not same values of LUN for links */
+#define AHA_INV_TARGET 0x18 /* Invalid target direction */
+#define AHA_CCB_DUP 0x19 /* Duplicate CCB received */
+#define AHA_INV_CCB 0x1a /* Invalid CCB or segment list */
+
+struct aha_revision {
+ struct {
+ u_char opcode;
+ } cmd;
+ struct {
+ u_char boardid; /* type of board */
+ /* 0x31 = AHA-1540 */
+ /* 0x41 = AHA-1540A/1542A/1542B */
+ /* 0x42 = AHA-1640 */
+ /* 0x43 = AHA-1542C */
+ /* 0x44 = AHA-1542CF */
+ /* 0x45 = AHA-1542CF, BIOS v2.01 */
+ /* 0x46 = AHA-1542CP */
+ u_char spec_opts; /* special options ID */
+ /* 0x41 = Board is standard model */
+ u_char revision_1; /* firmware revision [0-9A-Z] */
+ u_char revision_2; /* firmware revision [0-9A-Z] */
+ } reply;
+};
+
+struct aha_extbios {
+ struct {
+ u_char opcode;
+ } cmd;
+ struct {
+ u_char flags; /* Bit 3 == 1 extended bios enabled */
+ u_char mailboxlock; /* mail box lock code to unlock it */
+ } reply;
+};
+
+struct aha_toggle {
+ struct {
+ u_char opcode;
+ u_char enable;
+ } cmd;
+};
+
+struct aha_config {
+ struct {
+ u_char opcode;
+ } cmd;
+ struct {
+ u_char chan;
+ u_char intr;
+ u_char scsi_dev:3;
+ u_char :5;
+ } reply;
+};
+
+struct aha_mailbox {
+ struct {
+ u_char opcode;
+ u_char nmbx;
+ physaddr addr;
+ } cmd;
+};
+
+struct aha_unlock {
+ struct {
+ u_char opcode;
+ u_char junk;
+ u_char magic;
+ } cmd;
+};
+
+struct aha_devices {
+ struct {
+ u_char opcode;
+ } cmd;
+ struct {
+ u_char junk[8];
+ } reply;
+};
+
+struct aha_setup {
+ struct {
+ u_char opcode;
+ u_char len;
+ } cmd;
+ struct {
+ 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;
+ } reply;
+};
+
+#define INT9 0x01
+#define INT10 0x02
+#define INT11 0x04
+#define INT12 0x08
+#define INT14 0x20
+#define INT15 0x40
+
+#define EISADMA 0x00
+#define CHAN0 0x01
+#define CHAN5 0x20
+#define CHAN6 0x40
+#define CHAN7 0x80
diff --git a/sys/dev/isa/aic6360.c b/sys/dev/isa/aic6360.c
index c159feff414..f88a484ea62 100644
--- a/sys/dev/isa/aic6360.c
+++ b/sys/dev/isa/aic6360.c
@@ -1,4 +1,7 @@
-/* $NetBSD: aic6360.c,v 1.36.2.1 1995/10/18 21:40:12 pk Exp $ */
+/* $OpenBSD: aic6360.c,v 1.7 1996/04/21 22:22:39 deraadt Exp $ */
+/* $NetBSD: aic6360.c,v 1.44 1996/04/11 22:28:08 cgd Exp $ */
+
+#define integrate static inline
/*
* Copyright (c) 1994, 1995 Charles Hannum. All rights reserved.
@@ -13,7 +16,7 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by Charles Hannum.
+ * This product includes software developed by Charles M. Hannum.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
@@ -105,6 +108,8 @@
*/
#define AIC_DEBUG 1
+#define AIC_ABORT_TIMEOUT 2000 /* time to wait for abort */
+
/* End of customizable parameters */
#if AIC_USE_EISA_DMA || AIC_USE_ISA_DMA
@@ -136,45 +141,44 @@
*/
/* AIC6360 definitions */
-#define IOBASE sc->sc_iobase
-#define SCSISEQ (IOBASE + 0x00) /* SCSI sequence control */
-#define SXFRCTL0 (IOBASE + 0x01) /* SCSI transfer control 0 */
-#define SXFRCTL1 (IOBASE + 0x02) /* SCSI transfer control 1 */
-#define SCSISIG (IOBASE + 0x03) /* SCSI signal in/out */
-#define SCSIRATE (IOBASE + 0x04) /* SCSI rate control */
-#define SCSIID (IOBASE + 0x05) /* SCSI ID */
-#define SELID (IOBASE + 0x05) /* Selection/Reselection ID */
-#define SCSIDAT (IOBASE + 0x06) /* SCSI Latched Data */
-#define SCSIBUS (IOBASE + 0x07) /* SCSI Data Bus*/
-#define STCNT0 (IOBASE + 0x08) /* SCSI transfer count */
-#define STCNT1 (IOBASE + 0x09)
-#define STCNT2 (IOBASE + 0x0a)
-#define CLRSINT0 (IOBASE + 0x0b) /* Clear SCSI interrupts 0 */
-#define SSTAT0 (IOBASE + 0x0b) /* SCSI interrupt status 0 */
-#define CLRSINT1 (IOBASE + 0x0c) /* Clear SCSI interrupts 1 */
-#define SSTAT1 (IOBASE + 0x0c) /* SCSI status 1 */
-#define SSTAT2 (IOBASE + 0x0d) /* SCSI status 2 */
-#define SCSITEST (IOBASE + 0x0e) /* SCSI test control */
-#define SSTAT3 (IOBASE + 0x0e) /* SCSI status 3 */
-#define CLRSERR (IOBASE + 0x0f) /* Clear SCSI errors */
-#define SSTAT4 (IOBASE + 0x0f) /* SCSI status 4 */
-#define SIMODE0 (IOBASE + 0x10) /* SCSI interrupt mode 0 */
-#define SIMODE1 (IOBASE + 0x11) /* SCSI interrupt mode 1 */
-#define DMACNTRL0 (IOBASE + 0x12) /* DMA control 0 */
-#define DMACNTRL1 (IOBASE + 0x13) /* DMA control 1 */
-#define DMASTAT (IOBASE + 0x14) /* DMA status */
-#define FIFOSTAT (IOBASE + 0x15) /* FIFO status */
-#define DMADATA (IOBASE + 0x16) /* DMA data */
-#define DMADATAL (IOBASE + 0x16) /* DMA data low byte */
-#define DMADATAH (IOBASE + 0x17) /* DMA data high byte */
-#define BRSTCNTRL (IOBASE + 0x18) /* Burst Control */
-#define DMADATALONG (IOBASE + 0x18)
-#define PORTA (IOBASE + 0x1a) /* Port A */
-#define PORTB (IOBASE + 0x1b) /* Port B */
-#define REV (IOBASE + 0x1c) /* Revision (001 for 6360) */
-#define STACK (IOBASE + 0x1d) /* Stack */
-#define TEST (IOBASE + 0x1e) /* Test register */
-#define ID (IOBASE + 0x1f) /* ID register */
+#define SCSISEQ 0x00 /* SCSI sequence control */
+#define SXFRCTL0 0x01 /* SCSI transfer control 0 */
+#define SXFRCTL1 0x02 /* SCSI transfer control 1 */
+#define SCSISIG 0x03 /* SCSI signal in/out */
+#define SCSIRATE 0x04 /* SCSI rate control */
+#define SCSIID 0x05 /* SCSI ID */
+#define SELID 0x05 /* Selection/Reselection ID */
+#define SCSIDAT 0x06 /* SCSI Latched Data */
+#define SCSIBUS 0x07 /* SCSI Data Bus*/
+#define STCNT0 0x08 /* SCSI transfer count */
+#define STCNT1 0x09
+#define STCNT2 0x0a
+#define CLRSINT0 0x0b /* Clear SCSI interrupts 0 */
+#define SSTAT0 0x0b /* SCSI interrupt status 0 */
+#define CLRSINT1 0x0c /* Clear SCSI interrupts 1 */
+#define SSTAT1 0x0c /* SCSI status 1 */
+#define SSTAT2 0x0d /* SCSI status 2 */
+#define SCSITEST 0x0e /* SCSI test control */
+#define SSTAT3 0x0e /* SCSI status 3 */
+#define CLRSERR 0x0f /* Clear SCSI errors */
+#define SSTAT4 0x0f /* SCSI status 4 */
+#define SIMODE0 0x10 /* SCSI interrupt mode 0 */
+#define SIMODE1 0x11 /* SCSI interrupt mode 1 */
+#define DMACNTRL0 0x12 /* DMA control 0 */
+#define DMACNTRL1 0x13 /* DMA control 1 */
+#define DMASTAT 0x14 /* DMA status */
+#define FIFOSTAT 0x15 /* FIFO status */
+#define DMADATA 0x16 /* DMA data */
+#define DMADATAL 0x16 /* DMA data low byte */
+#define DMADATAH 0x17 /* DMA data high byte */
+#define BRSTCNTRL 0x18 /* Burst Control */
+#define DMADATALONG 0x18
+#define PORTA 0x1a /* Port A */
+#define PORTB 0x1b /* Port B */
+#define REV 0x1c /* Revision (001 for 6360) */
+#define STACK 0x1d /* Stack */
+#define TEST 0x1e /* Test register */
+#define ID 0x1f /* ID register */
#define IDSTRING "(C)1991ADAPTECAIC6360 "
@@ -455,10 +459,12 @@ struct aic_acb {
TAILQ_ENTRY(aic_acb) chain;
struct scsi_xfer *xs; /* SCSI xfer ctrl block from above */
int flags;
-#define ACB_FREE 0
-#define ACB_ACTIVE 1
-#define ACB_CHKSENSE 2
-#define ACB_ABORTED 3
+#define ACB_ALLOC 0x01
+#define ACB_NEXUS 0x02
+#define ACB_SENSE 0x04
+#define ACB_ABORT 0x40
+#define ACB_RESET 0x80
+ int timeout;
};
/*
@@ -506,13 +512,14 @@ struct aic_softc {
u_char sc_phase; /* Current bus phase */
u_char sc_prevphase; /* Previous bus phase */
u_char sc_state; /* State applicable to the adapter */
-#define AIC_IDLE 0x01
-#define AIC_SELECTING 0x02 /* SCSI command is arbiting */
-#define AIC_RESELECTED 0x04 /* Has been reselected */
-#define AIC_CONNECTED 0x08 /* Actively using the SCSI bus */
-#define AIC_DISCONNECT 0x10 /* MSG_DISCONNECT received */
-#define AIC_CMDCOMPLETE 0x20 /* MSG_CMDCOMPLETE received */
-#define AIC_CLEANING 0x40
+#define AIC_INIT 0
+#define AIC_IDLE 1
+#define AIC_SELECTING 2 /* SCSI command is arbiting */
+#define AIC_RESELECTED 3 /* Has been reselected */
+#define AIC_CONNECTED 4 /* Actively using the SCSI bus */
+#define AIC_DISCONNECT 5 /* MSG_DISCONNECT received */
+#define AIC_CMDCOMPLETE 6 /* MSG_CMDCOMPLETE received */
+#define AIC_CLEANING 7
u_char sc_flags;
#define AIC_DROP_MSGIN 0x01 /* Discard all msgs (parity err detected) */
#define AIC_ABORTING 0x02 /* Bailing out */
@@ -526,10 +533,10 @@ struct aic_softc {
u_char sc_currmsg; /* Message currently ready to transmit */
#define SEND_DEV_RESET 0x01
#define SEND_PARITY_ERROR 0x02
-#define SEND_ABORT 0x04
+#define SEND_INIT_DET_ERR 0x04
#define SEND_REJECT 0x08
-#define SEND_INIT_DET_ERR 0x10
-#define SEND_IDENTIFY 0x20
+#define SEND_IDENTIFY 0x10
+#define SEND_ABORT 0x20
#define SEND_SDTR 0x40
#define SEND_WDTR 0x80
#define AIC_MAX_MSG_LEN 8
@@ -580,6 +587,8 @@ void aic_done __P((struct aic_softc *, struct aic_acb *));
void aic_dequeue __P((struct aic_softc *, struct aic_acb *));
int aic_scsi_cmd __P((struct scsi_xfer *));
int aic_poll __P((struct aic_softc *, struct scsi_xfer *, int));
+integrate void aic_sched_msgout __P((struct aic_softc *, u_char));
+integrate void aic_setsync __P((struct aic_softc *, struct aic_tinfo *));
void aic_select __P((struct aic_softc *, struct aic_acb *));
void aic_timeout __P((void *));
int aic_find __P((struct aic_softc *));
@@ -592,8 +601,12 @@ void aic_dump_driver();
void aic_dump6360();
#endif
-struct cfdriver aiccd = {
- NULL, "aic", aicprobe, aicattach, DV_DULL, sizeof(struct aic_softc)
+struct cfattach aic_ca = {
+ sizeof(struct aic_softc), aicprobe, aicattach
+};
+
+struct cfdriver aic_cd = {
+ NULL, "aic", DV_DULL
};
struct scsi_adapter aic_switch = {
@@ -668,12 +681,13 @@ int
aic_find(sc)
struct aic_softc *sc;
{
+ int iobase = sc->sc_iobase;
char chip_id[sizeof(IDSTRING)]; /* For chips that support it */
char *start;
int i;
/* Remove aic6360 from possible powerdown mode */
- outb(DMACNTRL0, 0);
+ outb(iobase + DMACNTRL0, 0);
/* Thanks to mark@aggregate.com for the new method for detecting
* whether the chip is present or not. Bonus: may also work for
@@ -687,13 +701,13 @@ aic_find(sc)
*/
/* Push the sequence 0,1,..,15 on the stack */
#define STSIZE 16
- outb(DMACNTRL1, 0); /* Reset stack pointer */
+ outb(iobase + DMACNTRL1, 0); /* Reset stack pointer */
for (i = 0; i < STSIZE; i++)
- outb(STACK, i);
+ outb(iobase + STACK, i);
/* See if we can pull out the same sequence */
- outb(DMACNTRL1, 0);
- for (i = 0; i < STSIZE && inb(STACK) == i; i++)
+ outb(iobase + DMACNTRL1, 0);
+ for (i = 0; i < STSIZE && inb(iobase + STACK) == i; i++)
;
if (i != STSIZE) {
AIC_START(("STACK futzed at %d.\n", i));
@@ -704,10 +718,10 @@ aic_find(sc)
* now only used for informational purposes.
*/
bzero(chip_id, sizeof(chip_id));
- insb(ID, chip_id, sizeof(IDSTRING)-1);
+ insb(iobase + ID, chip_id, sizeof(IDSTRING)-1);
AIC_START(("AIC found at 0x%x ", sc->sc_iobase));
AIC_START(("ID: %s ",chip_id));
- AIC_START(("chip revision %d\n",(int)inb(REV)));
+ AIC_START(("chip revision %d\n",(int)inb(iobase + REV)));
sc->sc_initiator = 7;
sc->sc_freq = 20; /* XXXX Assume 20 MHz. */
@@ -749,7 +763,7 @@ aicattach(parent, self, aux)
struct aic_softc *sc = (void *)self;
AIC_TRACE(("aicattach "));
- sc->sc_state = 0;
+ sc->sc_state = AIC_INIT;
aic_init(sc); /* Init chip and driver */
/*
@@ -766,8 +780,8 @@ aicattach(parent, self, aux)
#ifdef NEWCONFIG
isa_establish(&sc->sc_id, &sc->sc_dev);
#endif
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO, aicintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, aicintr, sc, sc->sc_dev.dv_xname);
config_found(self, &sc->sc_link, aicprint);
}
@@ -782,32 +796,33 @@ void
aic_reset(sc)
struct aic_softc *sc;
{
+ int iobase = sc->sc_iobase;
- outb(SCSITEST, 0); /* Doc. recommends to clear these two */
- outb(TEST, 0); /* registers before operations commence */
+ outb(iobase + SCSITEST, 0); /* Doc. recommends to clear these two */
+ outb(iobase + TEST, 0); /* registers before operations commence */
/* Reset SCSI-FIFO and abort any transfers */
- outb(SXFRCTL0, CHEN|CLRCH|CLRSTCNT);
+ outb(iobase + SXFRCTL0, CHEN | CLRCH | CLRSTCNT);
/* Reset DMA-FIFO */
- outb(DMACNTRL0, RSTFIFO);
- outb(DMACNTRL1, 0);
+ outb(iobase + DMACNTRL0, RSTFIFO);
+ outb(iobase + DMACNTRL1, 0);
- outb(SCSISEQ, 0); /* Disable all selection features */
- outb(SXFRCTL1, 0);
+ outb(iobase + SCSISEQ, 0); /* Disable all selection features */
+ outb(iobase + SXFRCTL1, 0);
- outb(SIMODE0, 0x00); /* Disable some interrupts */
- outb(CLRSINT0, 0x7f); /* Clear a slew of interrupts */
+ outb(iobase + SIMODE0, 0x00); /* Disable some interrupts */
+ outb(iobase + CLRSINT0, 0x7f); /* Clear a slew of interrupts */
- outb(SIMODE1, 0x00); /* Disable some more interrupts */
- outb(CLRSINT1, 0xef); /* Clear another slew of interrupts */
+ outb(iobase + SIMODE1, 0x00); /* Disable some more interrupts */
+ outb(iobase + CLRSINT1, 0xef); /* Clear another slew of interrupts */
- outb(SCSIRATE, 0); /* Disable synchronous transfers */
+ outb(iobase + SCSIRATE, 0); /* Disable synchronous transfers */
- outb(CLRSERR, 0x07); /* Haven't seen ant errors (yet) */
+ outb(iobase + CLRSERR, 0x07); /* Haven't seen ant errors (yet) */
- outb(SCSIID, sc->sc_initiator << OID_S); /* Set our SCSI-ID */
- outb(BRSTCNTRL, EISA_BRST_TIM);
+ outb(iobase + SCSIID, sc->sc_initiator << OID_S); /* Set our SCSI-ID */
+ outb(iobase + BRSTCNTRL, EISA_BRST_TIM);
}
/* Pull the SCSI RST line for 500 us */
@@ -815,10 +830,11 @@ void
aic_scsi_reset(sc)
struct aic_softc *sc;
{
+ int iobase = sc->sc_iobase;
- outb(SCSISEQ, SCSIRSTO);
+ outb(iobase + SCSISEQ, SCSIRSTO);
delay(500);
- outb(SCSISEQ, 0);
+ outb(iobase + SCSISEQ, 0);
delay(50);
}
@@ -829,6 +845,7 @@ void
aic_init(sc)
struct aic_softc *sc;
{
+ int iobase = sc->sc_iobase;
struct aic_acb *acb;
int r;
@@ -836,7 +853,7 @@ aic_init(sc)
aic_scsi_reset(sc);
aic_reset(sc);
- if (sc->sc_state == 0) {
+ if (sc->sc_state == AIC_INIT) {
/* First time through; initialize. */
TAILQ_INIT(&sc->ready_list);
TAILQ_INIT(&sc->nexus_list);
@@ -885,7 +902,7 @@ aic_init(sc)
}
sc->sc_state = AIC_IDLE;
- outb(DMACNTRL0, INTEN);
+ outb(iobase + DMACNTRL0, INTEN);
}
void
@@ -898,7 +915,7 @@ aic_free_acb(sc, acb, flags)
s = splbio();
- acb->flags = ACB_FREE;
+ acb->flags = 0;
TAILQ_INSERT_HEAD(&sc->free_list, acb, chain);
/*
@@ -926,7 +943,7 @@ aic_get_acb(sc, flags)
tsleep(&sc->free_list, PRIBIO, "aicacb", 0);
if (acb) {
TAILQ_REMOVE(&sc->free_list, acb, chain);
- acb->flags = ACB_ACTIVE;
+ acb->flags |= ACB_ALLOC;
}
splx(s);
@@ -973,12 +990,6 @@ aic_scsi_cmd(xs)
sc_link->target));
flags = xs->flags;
- if ((flags & (ITSDONE|INUSE)) != INUSE) {
- printf("%s: done or not in use?\n", sc->sc_dev.dv_xname);
- xs->flags &= ~ITSDONE;
- xs->flags |= INUSE;
- }
-
if ((acb = aic_get_acb(sc, flags)) == NULL) {
xs->error = XS_DRIVER_STUFFUP;
return TRY_AGAIN_LATER;
@@ -986,10 +997,18 @@ aic_scsi_cmd(xs)
/* Initialize acb */
acb->xs = xs;
- bcopy(xs->cmd, &acb->scsi_cmd, xs->cmdlen);
- acb->scsi_cmd_length = xs->cmdlen;
- acb->data_addr = xs->data;
- acb->data_length = xs->datalen;
+ acb->timeout = xs->timeout;
+
+ if (xs->flags & SCSI_RESET) {
+ acb->flags |= ACB_RESET;
+ acb->scsi_cmd_length = 0;
+ acb->data_length = 0;
+ } else {
+ bcopy(xs->cmd, &acb->scsi_cmd, xs->cmdlen);
+ acb->scsi_cmd_length = xs->cmdlen;
+ acb->data_addr = xs->data;
+ acb->data_length = xs->datalen;
+ }
acb->target_stat = 0;
s = splbio();
@@ -998,18 +1017,15 @@ aic_scsi_cmd(xs)
if (sc->sc_state == AIC_IDLE)
aic_sched(sc);
- if ((flags & SCSI_POLL) == 0) { /* Almost done. Wait outside */
- timeout(aic_timeout, acb, (xs->timeout * hz) / 1000);
- splx(s);
- return SUCCESSFULLY_QUEUED;
- }
-
splx(s);
+ if ((flags & SCSI_POLL) == 0)
+ return SUCCESSFULLY_QUEUED;
+
/* Not allowed to use interrupts, use polling instead */
- if (aic_poll(sc, xs, xs->timeout)) {
+ if (aic_poll(sc, xs, acb->timeout)) {
aic_timeout(acb);
- if (aic_poll(sc, xs, 2000))
+ if (aic_poll(sc, xs, acb->timeout))
aic_timeout(acb);
}
return COMPLETE;
@@ -1038,6 +1054,7 @@ aic_poll(sc, xs, count)
struct scsi_xfer *xs;
int count;
{
+ int iobase = sc->sc_iobase;
AIC_TRACE(("aic_poll "));
while (count) {
@@ -1045,7 +1062,7 @@ aic_poll(sc, xs, count)
* If we had interrupts enabled, would we
* have got an interrupt?
*/
- if ((inb(DMASTAT) & INTSTAT) != 0)
+ if ((inb(iobase + DMASTAT) & INTSTAT) != 0)
aicintr(sc);
if ((xs->flags & ITSDONE) != 0)
return 0;
@@ -1059,32 +1076,36 @@ aic_poll(sc, xs, count)
* LOW LEVEL SCSI UTILITIES
*/
-#define aic_sched_msgout(m) \
- do { \
- if (sc->sc_msgpriq == 0) \
- outb(SCSISIG, sc->sc_phase|ATNO); \
- sc->sc_msgpriq |= (m); \
- } while (0)
+integrate void
+aic_sched_msgout(sc, m)
+ struct aic_softc *sc;
+ u_char m;
+{
+ int iobase = sc->sc_iobase;
+
+ if (sc->sc_msgpriq == 0)
+ outb(iobase + SCSISIG, sc->sc_phase | ATNO);
+ sc->sc_msgpriq |= m;
+}
-#if AIC_USE_SYNCHRONOUS
/*
* Set synchronous transfer offset and period.
*/
-static inline void
+integrate void
aic_setsync(sc, ti)
struct aic_softc *sc;
struct aic_tinfo *ti;
{
+#if AIC_USE_SYNCHRONOUS
+ int iobase = sc->sc_iobase;
if (ti->offset != 0)
- outb(SCSIRATE,
+ outb(iobase + SCSIRATE,
((ti->period * sc->sc_freq) / 250 - 2) << 4 | ti->offset);
else
- outb(SCSIRATE, 0);
-}
-#else
-#define aic_setsync(sc, ti)
+ outb(iobase + SCSIRATE, 0);
#endif
+}
/*
* Start a selection. This is used by aic_sched() to select an idle target,
@@ -1098,15 +1119,16 @@ aic_select(sc, acb)
struct scsi_link *sc_link = acb->xs->sc_link;
int target = sc_link->target;
struct aic_tinfo *ti = &sc->sc_tinfo[target];
+ int iobase = sc->sc_iobase;
- outb(SCSIID, sc->sc_initiator << OID_S | target);
+ outb(iobase + SCSIID, sc->sc_initiator << OID_S | target);
aic_setsync(sc, ti);
- outb(SXFRCTL1, STIMO_256ms|ENSTIMER);
+ outb(iobase + SXFRCTL1, STIMO_256ms | ENSTIMER);
/* Always enable reselections. */
- outb(SIMODE0, ENSELDI|ENSELDO);
- outb(SIMODE1, ENSCSIRST|ENSELTIMO);
- outb(SCSISEQ, ENRESELI|ENSELO|ENAUTOATNO);
+ outb(iobase + SIMODE0, ENSELDI | ENSELDO);
+ outb(iobase + SIMODE1, ENSCSIRST | ENSELTIMO);
+ outb(iobase + SCSISEQ, ENRESELI | ENSELO | ENAUTOATNO);
sc->sc_state = AIC_SELECTING;
}
@@ -1162,6 +1184,11 @@ aic_reselect(sc, message)
ti->lubusy |= (1 << lun);
aic_setsync(sc, ti);
+ if (acb->flags & ACB_RESET)
+ aic_sched_msgout(sc, SEND_DEV_RESET);
+ else if (acb->flags & ACB_ABORT)
+ aic_sched_msgout(sc, SEND_ABORT);
+
/* Do an implicit RESTORE POINTERS. */
sc->sc_dp = acb->data_addr;
sc->sc_dleft = acb->data_length;
@@ -1171,13 +1198,11 @@ aic_reselect(sc, message)
return (0);
reset:
- sc->sc_flags |= AIC_ABORTING;
- aic_sched_msgout(SEND_DEV_RESET);
+ aic_sched_msgout(sc, SEND_DEV_RESET);
return (1);
abort:
- sc->sc_flags |= AIC_ABORTING;
- aic_sched_msgout(SEND_ABORT);
+ aic_sched_msgout(sc, SEND_ABORT);
return (1);
}
@@ -1194,12 +1219,13 @@ aic_sched(sc)
struct aic_acb *acb;
struct scsi_link *sc_link;
struct aic_tinfo *ti;
+ int iobase = sc->sc_iobase;
/*
* Find first acb in ready queue that is for a target/lunit pair that
* is not busy.
*/
- outb(CLRSINT1, CLRSELTIMO|CLRBUSFREE|CLRSCSIPERR);
+ outb(iobase + CLRSINT1, CLRSELTIMO | CLRBUSFREE | CLRSCSIPERR);
for (acb = sc->ready_list.tqh_first; acb != NULL;
acb = acb->chain.tqe_next) {
sc_link = acb->xs->sc_link;
@@ -1217,11 +1243,44 @@ aic_sched(sc)
}
AIC_MISC(("idle "));
/* Nothing to start; just enable reselections and wait. */
- outb(SIMODE0, ENSELDI);
- outb(SIMODE1, ENSCSIRST);
- outb(SCSISEQ, ENRESELI);
+ outb(iobase + SIMODE0, ENSELDI);
+ outb(iobase + SIMODE1, ENSCSIRST);
+ outb(iobase + SCSISEQ, ENRESELI);
}
+void
+aic_sense(sc, acb)
+ struct aic_softc *sc;
+ struct aic_acb *acb;
+{
+ struct scsi_xfer *xs = acb->xs;
+ struct scsi_link *sc_link = xs->sc_link;
+ struct aic_tinfo *ti = &sc->sc_tinfo[sc_link->target];
+ struct scsi_sense *ss = (void *)&acb->scsi_cmd;
+
+ AIC_MISC(("requesting sense "));
+ /* Next, setup a request sense command block */
+ bzero(ss, sizeof(*ss));
+ ss->opcode = REQUEST_SENSE;
+ ss->byte2 = sc_link->lun << 5;
+ ss->length = sizeof(struct scsi_sense_data);
+ acb->scsi_cmd_length = sizeof(*ss);
+ acb->data_addr = (char *)&xs->sense;
+ acb->data_length = sizeof(struct scsi_sense_data);
+ acb->flags |= ACB_SENSE;
+ ti->senses++;
+ if (acb->flags & ACB_NEXUS)
+ ti->lubusy &= ~(1 << sc_link->lun);
+ if (acb == sc->sc_nexus) {
+ aic_select(sc, acb);
+ } else {
+ aic_dequeue(sc, acb);
+ TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain);
+ if (sc->sc_state == AIC_IDLE)
+ aic_sched(sc);
+ }
+}
+
/*
* POST PROCESSING OF SCSI_CMD (usually current)
*/
@@ -1245,33 +1304,15 @@ aic_done(sc, acb)
* We don't support chk sense conditions for the request sense cmd.
*/
if (xs->error == XS_NOERROR) {
- if (acb->flags == ACB_ABORTED) {
+ if (acb->flags & ACB_ABORT) {
xs->error = XS_DRIVER_STUFFUP;
- } else if (acb->flags == ACB_CHKSENSE) {
+ } else if (acb->flags & ACB_SENSE) {
xs->error = XS_SENSE;
} else if (acb->target_stat == SCSI_CHECK) {
- struct scsi_sense *ss = (void *)&acb->scsi_cmd;
-
- AIC_MISC(("requesting sense "));
/* First, save the return values */
xs->resid = acb->data_length;
xs->status = acb->target_stat;
- /* Next, setup a request sense command block */
- bzero(ss, sizeof(*ss));
- ss->opcode = REQUEST_SENSE;
- ss->byte2 = sc_link->lun << 5;
- ss->length = sizeof(struct scsi_sense_data);
- acb->scsi_cmd_length = sizeof(*ss);
- acb->data_addr = (char *)&xs->sense;
- acb->data_length = sizeof(struct scsi_sense_data);
- acb->flags = ACB_CHKSENSE;
- ti->senses++;
- ti->lubusy &= ~(1<<sc_link->lun);
- if (acb == sc->sc_nexus) {
- aic_select(sc, acb);
- } else {
- TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain);
- }
+ aic_sense(sc, acb);
return;
} else {
xs->resid = acb->data_length;
@@ -1292,16 +1333,13 @@ aic_done(sc, acb)
#endif
/*
- * Remove the ACB from whatever queue it's on. We have to do a bit of
- * a hack to figure out which queue it's on. Note that it is *not*
- * necessary to cdr down the ready queue, but we must cdr down the
- * nexus queue and see if it's there, so we can mark the unit as no
- * longer busy. This code is sickening, but it works.
+ * Remove the ACB from whatever queue it happens to be on.
*/
- if (acb == sc->sc_nexus) {
+ if (acb->flags & ACB_NEXUS)
ti->lubusy &= ~(1 << sc_link->lun);
- sc->sc_state = AIC_IDLE;
+ if (acb == sc->sc_nexus) {
sc->sc_nexus = NULL;
+ sc->sc_state = AIC_IDLE;
aic_sched(sc);
} else
aic_dequeue(sc, acb);
@@ -1316,28 +1354,11 @@ aic_dequeue(sc, acb)
struct aic_softc *sc;
struct aic_acb *acb;
{
- struct scsi_link *sc_link = acb->xs->sc_link;
- struct aic_tinfo *ti = &sc->sc_tinfo[sc_link->target];
- if (sc->ready_list.tqh_last == &acb->chain.tqe_next) {
- TAILQ_REMOVE(&sc->ready_list, acb, chain);
+ if (acb->flags & ACB_NEXUS) {
+ TAILQ_REMOVE(&sc->nexus_list, acb, chain);
} else {
- register struct aic_acb *acb2;
- for (acb2 = sc->nexus_list.tqh_first; acb2 != NULL;
- acb2 = acb2->chain.tqe_next) {
- if (acb2 == acb)
- break;
- }
- if (acb2 != NULL) {
- TAILQ_REMOVE(&sc->nexus_list, acb, chain);
- ti->lubusy &= ~(1 << sc_link->lun);
- } else if (acb->chain.tqe_next) {
- TAILQ_REMOVE(&sc->ready_list, acb, chain);
- } else {
- printf("%s: can't find matching acb\n",
- sc->sc_dev.dv_xname);
- Debugger();
- }
+ TAILQ_REMOVE(&sc->ready_list, acb, chain);
}
}
@@ -1354,10 +1375,11 @@ aic_dequeue(sc, acb)
* The SCSI bus is already in the MSGI phase and there is a message byte
* on the bus, along with an asserted REQ signal.
*/
-int
+void
aic_msgin(sc)
register struct aic_softc *sc;
{
+ int iobase = sc->sc_iobase;
u_char sstat1;
int n;
@@ -1384,34 +1406,34 @@ nextbyte:
*/
for (;;) {
for (;;) {
- sstat1 = inb(SSTAT1);
- if ((sstat1 & (REQINIT|BUSFREE)) != 0)
+ sstat1 = inb(iobase + SSTAT1);
+ if ((sstat1 & (REQINIT | PHASECHG | BUSFREE)) != 0)
break;
/* Wait for REQINIT. XXX Need timeout. */
}
- if ((sstat1 & (PHASECHG|BUSFREE)) != 0) {
+ if ((sstat1 & (PHASECHG | BUSFREE)) != 0) {
/*
* Target left MESSAGE IN, probably because it
* a) noticed our ATN signal, or
* b) ran out of messages.
*/
- return (1);
+ goto out;
}
/* If parity error, just dump everything on the floor. */
if ((sstat1 & SCSIPERR) != 0) {
- aic_sched_msgout(SEND_PARITY_ERROR);
sc->sc_flags |= AIC_DROP_MSGIN;
+ aic_sched_msgout(sc, SEND_PARITY_ERROR);
}
/* Gather incoming message bytes if needed. */
if ((sc->sc_flags & AIC_DROP_MSGIN) == 0) {
if (n >= AIC_MAX_MSG_LEN) {
- (void) inb(SCSIDAT);
- aic_sched_msgout(SEND_REJECT);
+ (void) inb(iobase + SCSIDAT);
sc->sc_flags |= AIC_DROP_MSGIN;
+ aic_sched_msgout(sc, SEND_REJECT);
} else {
- *sc->sc_imp++ = inb(SCSIDAT);
+ *sc->sc_imp++ = inb(iobase + SCSIDAT);
n++;
/*
* This testing is suboptimal, but most
@@ -1428,18 +1450,18 @@ nextbyte:
break;
}
} else
- (void) inb(SCSIDAT);
+ (void) inb(iobase + SCSIDAT);
/*
* If we reach this spot we're either:
* a) in the middle of a multi-byte message, or
* b) dropping bytes.
*/
- outb(SXFRCTL0, CHEN|SPIOEN);
+ outb(iobase + SXFRCTL0, CHEN | SPIOEN);
/* Ack the last byte read. */
- (void) inb(SCSIDAT);
- outb(SXFRCTL0, CHEN);
- while ((inb(SCSISIG) & ACKI) != 0)
+ (void) inb(iobase + SCSIDAT);
+ outb(iobase + SXFRCTL0, CHEN);
+ while ((inb(iobase + SCSISIG) & ACKI) != 0)
;
}
@@ -1471,7 +1493,7 @@ nextbyte:
case MSG_PARITY_ERROR:
/* Resend the last message. */
- aic_sched_msgout(sc->sc_lastmsg);
+ aic_sched_msgout(sc, sc->sc_lastmsg);
break;
case MSG_MESSAGE_REJECT:
@@ -1479,7 +1501,7 @@ nextbyte:
switch (sc->sc_lastmsg) {
#if AIC_USE_SYNCHRONOUS + AIC_USE_WIDE
case SEND_IDENTIFY:
- ti->flags &= ~(DO_SYNC|DO_WIDE);
+ ti->flags &= ~(DO_SYNC | DO_WIDE);
ti->period = ti->offset = 0;
aic_setsync(sc, ti);
ti->width = 0;
@@ -1499,8 +1521,7 @@ nextbyte:
break;
#endif
case SEND_INIT_DET_ERR:
- sc->sc_flags |= AIC_ABORTING;
- aic_sched_msgout(SEND_ABORT);
+ aic_sched_msgout(sc, SEND_ABORT);
break;
}
break;
@@ -1539,7 +1560,7 @@ nextbyte:
ti->period > sc->sc_maxsync ||
ti->offset > 8) {
ti->period = ti->offset = 0;
- aic_sched_msgout(SEND_SDTR);
+ aic_sched_msgout(sc, SEND_SDTR);
} else {
sc_print_addr(acb->xs->sc_link);
printf("sync, offset %d, period %dnsec\n",
@@ -1558,7 +1579,7 @@ nextbyte:
if (ti->width == 0) {
} else if (ti->width > AIC_MAX_WIDTH) {
ti->width = 0;
- aic_sched_msgout(SEND_WDTR);
+ aic_sched_msgout(sc, SEND_WDTR);
} else {
sc_print_addr(acb->xs->sc_link);
printf("wide, width %d\n",
@@ -1580,7 +1601,7 @@ nextbyte:
sc->sc_dev.dv_xname);
AIC_BREAK();
reject:
- aic_sched_msgout(SEND_REJECT);
+ aic_sched_msgout(sc, SEND_REJECT);
break;
}
break;
@@ -1601,21 +1622,19 @@ nextbyte:
sc->sc_dev.dv_xname);
AIC_BREAK();
reset:
- sc->sc_flags |= AIC_ABORTING;
- aic_sched_msgout(SEND_DEV_RESET);
+ aic_sched_msgout(sc, SEND_DEV_RESET);
break;
abort:
- sc->sc_flags |= AIC_ABORTING;
- aic_sched_msgout(SEND_ABORT);
+ aic_sched_msgout(sc, SEND_ABORT);
break;
}
- outb(SXFRCTL0, CHEN|SPIOEN);
+ outb(iobase + SXFRCTL0, CHEN | SPIOEN);
/* Ack the last message byte. */
- (void) inb(SCSIDAT);
- outb(SXFRCTL0, CHEN);
- while ((inb(SCSISIG) & ACKI) != 0)
+ (void) inb(iobase + SCSIDAT);
+ outb(iobase + SXFRCTL0, CHEN);
+ while ((inb(iobase + SCSISIG) & ACKI) != 0)
;
/* Go get the next message, if any. */
@@ -1623,7 +1642,6 @@ nextbyte:
out:
AIC_MISC(("n=%d imess=0x%02x ", n, sc->sc_imess[0]));
- return (0);
}
/*
@@ -1633,22 +1651,17 @@ void
aic_msgout(sc)
register struct aic_softc *sc;
{
- struct aic_acb *acb;
+ int iobase = sc->sc_iobase;
struct aic_tinfo *ti;
u_char sstat1;
int n;
AIC_TRACE(("aic_msgout "));
- /*
- * Set ATN. If we're just sending a trivial 1-byte message, we'll
- * clear ATN later on anyway.
- */
- outb(SCSISIG, PH_MSGOUT|ATNO);
/* Reset the FIFO. */
- outb(DMACNTRL0, RSTFIFO);
+ outb(iobase + DMACNTRL0, RSTFIFO);
/* Enable REQ/ACK protocol. */
- outb(SXFRCTL0, CHEN|SPIOEN);
+ outb(iobase + SXFRCTL0, CHEN | SPIOEN);
if (sc->sc_prevphase == PH_MSGOUT) {
if (sc->sc_omp == sc->sc_omess) {
@@ -1665,6 +1678,11 @@ aic_msgout(sc)
*/
AIC_MISC(("retransmitting "));
sc->sc_msgpriq |= sc->sc_msgoutq;
+ /*
+ * Set ATN. If we're just sending a trivial 1-byte
+ * message, we'll clear ATN later on anyway.
+ */
+ outb(iobase + SCSISIG, PH_MSGOUT | ATNO);
} else {
/* This is a continuation of the previous message. */
n = sc->sc_omp - sc->sc_omess;
@@ -1685,26 +1703,14 @@ nextmsg:
/* Build the outgoing message data. */
switch (sc->sc_currmsg) {
case SEND_IDENTIFY:
- if (sc->sc_state != AIC_CONNECTED) {
- printf("%s: SEND_IDENTIFY while not connected; sending NOOP\n",
- sc->sc_dev.dv_xname);
- AIC_BREAK();
- goto noop;
- }
AIC_ASSERT(sc->sc_nexus != NULL);
- acb = sc->sc_nexus;
- sc->sc_omess[0] = MSG_IDENTIFY(acb->xs->sc_link->lun, 1);
+ sc->sc_omess[0] =
+ MSG_IDENTIFY(sc->sc_nexus->xs->sc_link->lun, 1);
n = 1;
break;
#if AIC_USE_SYNCHRONOUS
case SEND_SDTR:
- if (sc->sc_state != AIC_CONNECTED) {
- printf("%s: SEND_SDTR while not connected; sending NOOP\n",
- sc->sc_dev.dv_xname);
- AIC_BREAK();
- goto noop;
- }
AIC_ASSERT(sc->sc_nexus != NULL);
ti = &sc->sc_tinfo[sc->sc_nexus->xs->sc_link->target];
sc->sc_omess[4] = MSG_EXTENDED;
@@ -1718,12 +1724,6 @@ nextmsg:
#if AIC_USE_WIDE
case SEND_WDTR:
- if (sc->sc_state != AIC_CONNECTED) {
- printf("%s: SEND_WDTR while not connected; sending NOOP\n",
- sc->sc_dev.dv_xname);
- AIC_BREAK();
- goto noop;
- }
AIC_ASSERT(sc->sc_nexus != NULL);
ti = &sc->sc_tinfo[sc->sc_nexus->xs->sc_link->target];
sc->sc_omess[3] = MSG_EXTENDED;
@@ -1735,6 +1735,7 @@ nextmsg:
#endif
case SEND_DEV_RESET:
+ sc->sc_flags |= AIC_ABORTING;
sc->sc_omess[0] = MSG_BUS_DEV_RESET;
n = 1;
break;
@@ -1755,26 +1756,18 @@ nextmsg:
break;
case SEND_ABORT:
+ sc->sc_flags |= AIC_ABORTING;
sc->sc_omess[0] = MSG_ABORT;
n = 1;
break;
- case 0:
-#ifdef AIC_PICKY
+ default:
printf("%s: unexpected MESSAGE OUT; sending NOOP\n",
sc->sc_dev.dv_xname);
AIC_BREAK();
-#endif
- noop:
sc->sc_omess[0] = MSG_NOOP;
n = 1;
break;
-
- default:
- printf("%s: weird MESSAGE OUT; sending NOOP\n",
- sc->sc_dev.dv_xname);
- AIC_BREAK();
- goto noop;
}
sc->sc_omp = &sc->sc_omess[n];
@@ -1782,29 +1775,37 @@ nextbyte:
/* Send message bytes. */
for (;;) {
for (;;) {
- sstat1 = inb(SSTAT1);
- if ((sstat1 & (REQINIT|BUSFREE)) != 0)
+ sstat1 = inb(iobase + SSTAT1);
+ if ((sstat1 & (REQINIT | PHASECHG | BUSFREE)) != 0)
break;
/* Wait for REQINIT. XXX Need timeout. */
}
- if ((sstat1 & (PHASECHG|BUSFREE)) != 0) {
+ if ((sstat1 & (PHASECHG | BUSFREE)) != 0) {
/*
* Target left MESSAGE OUT, possibly to reject
* our message.
+ *
+ * If this is the last message being sent, then we
+ * deassert ATN, since either the target is going to
+ * ignore this message, or it's going to ask for a
+ * retransmission via MESSAGE PARITY ERROR (in which
+ * case we reassert ATN anyway).
*/
+ if (sc->sc_msgpriq == 0)
+ outb(iobase + CLRSINT1, CLRATNO);
goto out;
}
/* Clear ATN before last byte if this is the last message. */
if (n == 1 && sc->sc_msgpriq == 0)
- outb(CLRSINT1, CLRATNO);
+ outb(iobase + CLRSINT1, CLRATNO);
/* Send message byte. */
- outb(SCSIDAT, *--sc->sc_omp);
+ outb(iobase + SCSIDAT, *--sc->sc_omp);
--n;
/* Keep track of the last message we've sent any bytes of. */
sc->sc_lastmsg = sc->sc_currmsg;
/* Wait for ACK to be negated. XXX Need timeout. */
- while ((inb(SCSISIG) & ACKI) != 0)
+ while ((inb(iobase + SCSISIG) & ACKI) != 0)
;
if (n == 0)
@@ -1827,7 +1828,7 @@ nextbyte:
out:
/* Disable REQ/ACK protocol. */
- outb(SXFRCTL0, CHEN);
+ outb(iobase + SXFRCTL0, CHEN);
}
/* aic_dataout_pio: perform a data transfer using the FIFO datapath in the aic6360
@@ -1842,87 +1843,102 @@ aic_dataout_pio(sc, p, n)
u_char *p;
int n;
{
+ int iobase = sc->sc_iobase;
register u_char dmastat;
int out = 0;
#define DOUTAMOUNT 128 /* Full FIFO */
/* Clear host FIFO and counter. */
- outb(DMACNTRL0, RSTFIFO|WRITE);
+ outb(iobase + DMACNTRL0, RSTFIFO | WRITE);
/* Enable FIFOs. */
- outb(SXFRCTL0, SCSIEN|DMAEN|CHEN);
- outb(DMACNTRL0, ENDMA|DWORDPIO|WRITE);
+ outb(iobase + SXFRCTL0, SCSIEN | DMAEN | CHEN);
+ outb(iobase + DMACNTRL0, ENDMA | DWORDPIO | WRITE);
/* Turn off ENREQINIT for now. */
- outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENPHASECHG);
+ outb(iobase + SIMODE1,
+ ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENPHASECHG);
/* I have tried to make the main loop as tight as possible. This
* means that some of the code following the loop is a bit more
* complex than otherwise.
*/
while (n > 0) {
- int xfer;
-
for (;;) {
- dmastat = inb(DMASTAT);
- if ((dmastat & DFIFOEMP) != 0)
+ dmastat = inb(iobase + DMASTAT);
+ if ((dmastat & (DFIFOEMP | INTSTAT)) != 0)
break;
- if ((dmastat & INTSTAT) != 0)
- goto phasechange;
}
- xfer = min(DOUTAMOUNT, n);
+ if ((dmastat & INTSTAT) != 0)
+ goto phasechange;
+
+ if (n >= DOUTAMOUNT) {
+ n -= DOUTAMOUNT;
+ out += DOUTAMOUNT;
+
+#if AIC_USE_DWORDS
+ outsl(iobase + DMADATALONG, p, DOUTAMOUNT >> 2);
+#else
+ outsw(iobase + DMADATA, p, DOUTAMOUNT >> 1);
+#endif
+
+ p += DOUTAMOUNT;
+ } else {
+ register int xfer;
- AIC_MISC(("%d> ", xfer));
+ xfer = n;
+ AIC_MISC(("%d> ", xfer));
- n -= xfer;
- out += xfer;
+ n -= xfer;
+ out += xfer;
#if AIC_USE_DWORDS
- if (xfer >= 12) {
- outsl(DMADATALONG, p, xfer>>2);
- p += xfer & ~3;
- xfer &= 3;
- }
+ if (xfer >= 12) {
+ outsl(iobase + DMADATALONG, p, xfer >> 2);
+ p += xfer & ~3;
+ xfer &= 3;
+ }
#else
- if (xfer >= 8) {
- outsw(DMADATA, p, xfer>>1);
- p += xfer & ~1;
- xfer &= 1;
- }
+ if (xfer >= 8) {
+ outsw(iobase + DMADATA, p, xfer >> 1);
+ p += xfer & ~1;
+ xfer &= 1;
+ }
#endif
- if (xfer > 0) {
- outb(DMACNTRL0, ENDMA|B8MODE|WRITE);
- outsb(DMADATA, p, xfer);
- p += xfer;
- outb(DMACNTRL0, ENDMA|DWORDPIO|WRITE);
+ if (xfer > 0) {
+ outb(iobase + DMACNTRL0, ENDMA | B8MODE | WRITE);
+ outsb(iobase + DMADATA, p, xfer);
+ p += xfer;
+ outb(iobase + DMACNTRL0, ENDMA | DWORDPIO | WRITE);
+ }
}
}
if (out == 0) {
- outb(SXFRCTL1, BITBUCKET);
+ outb(iobase + SXFRCTL1, BITBUCKET);
for (;;) {
- if ((inb(DMASTAT) & INTSTAT) != 0)
+ if ((inb(iobase + DMASTAT) & INTSTAT) != 0)
break;
}
- outb(SXFRCTL1, 0);
+ outb(iobase + SXFRCTL1, 0);
AIC_MISC(("extra data "));
} else {
/* See the bytes off chip */
for (;;) {
- dmastat = inb(DMASTAT);
- if ((dmastat & DFIFOEMP) != 0 &&
- (inb(SSTAT2) & SEMPTY) != 0)
- break;
+ dmastat = inb(iobase + DMASTAT);
if ((dmastat & INTSTAT) != 0)
goto phasechange;
+ if ((dmastat & DFIFOEMP) != 0 &&
+ (inb(iobase + SSTAT2) & SEMPTY) != 0)
+ break;
}
}
phasechange:
/* Stop the FIFO data path. */
- outb(SXFRCTL0, CHEN);
- while ((inb(SXFRCTL0) & SCSIEN) != 0)
+ outb(iobase + SXFRCTL0, CHEN);
+ while ((inb(iobase + SXFRCTL0) & SCSIEN) != 0)
;
if ((dmastat & INTSTAT) != 0) {
@@ -1930,16 +1946,17 @@ phasechange:
int amount;
/* Stop transfers, do some accounting */
- amount = inb(FIFOSTAT) + (inb(SSTAT2) & 15);
+ amount = inb(iobase + FIFOSTAT) + (inb(iobase + SSTAT2) & 15);
if (amount > 0) {
out -= amount;
- outb(SXFRCTL0, CHEN|CLRSTCNT|CLRCH);
+ outb(iobase + SXFRCTL0, CHEN | CLRSTCNT | CLRCH);
AIC_MISC(("+%d ", amount));
}
}
/* Turn on ENREQINIT again. */
- outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENREQINIT|ENPHASECHG);
+ outb(iobase + SIMODE1,
+ ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENREQINIT | ENPHASECHG);
return out;
}
@@ -1957,62 +1974,73 @@ aic_datain_pio(sc, p, n)
u_char *p;
int n;
{
+ int iobase = sc->sc_iobase;
register u_char dmastat;
int in = 0;
#define DINAMOUNT 128 /* Full FIFO */
/* Clear host FIFO and counter. */
- outb(DMACNTRL0, RSTFIFO);
- /* Enable FIFOs */
- outb(SXFRCTL0, SCSIEN|DMAEN|CHEN);
- outb(DMACNTRL0, ENDMA|DWORDPIO);
+ outb(iobase + DMACNTRL0, RSTFIFO);
+ /* Enable FIFOs. */
+ outb(iobase + SXFRCTL0, SCSIEN | DMAEN | CHEN);
+ outb(iobase + DMACNTRL0, ENDMA | DWORDPIO);
/* Turn off ENREQINIT for now. */
- outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENPHASECHG);
+ outb(iobase + SIMODE1,
+ ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENPHASECHG);
/* We leave this loop if one or more of the following is true:
* a) phase != PH_DATAIN && FIFOs are empty
* b) SCSIRSTI is set (a reset has occurred) or busfree is detected.
*/
while (n > 0) {
- int xfer;
-
/* Wait for fifo half full or phase mismatch */
for (;;) {
- dmastat = inb(DMASTAT);
- if ((dmastat & (DFIFOFULL|INTSTAT)) != 0)
+ dmastat = inb(iobase + DMASTAT);
+ if ((dmastat & (DFIFOFULL | INTSTAT)) != 0)
break;
}
- if ((dmastat & DFIFOFULL) != 0)
- xfer = min(DINAMOUNT, n);
- else
- xfer = min(inb(FIFOSTAT), n);
+ if ((dmastat & DFIFOFULL) != 0) {
+ n -= DINAMOUNT;
+ in += DINAMOUNT;
+
+#if AIC_USE_DWORDS
+ insl(iobase + DMADATALONG, p, DINAMOUNT >> 2);
+#else
+ insw(iobase + DMADATA, p, DINAMOUNT >> 1);
+#endif
- AIC_MISC((">%d ", xfer));
+ p += DINAMOUNT;
+ } else {
+ register int xfer;
- n -= xfer;
- in += xfer;
+ xfer = min(inb(iobase + FIFOSTAT), n);
+ AIC_MISC((">%d ", xfer));
+
+ n -= xfer;
+ in += xfer;
#if AIC_USE_DWORDS
- if (xfer >= 12) {
- insl(DMADATALONG, p, xfer>>2);
- p += xfer & ~3;
- xfer &= 3;
- }
+ if (xfer >= 12) {
+ insl(iobase + DMADATALONG, p, xfer >> 2);
+ p += xfer & ~3;
+ xfer &= 3;
+ }
#else
- if (xfer >= 8) {
- insw(DMADATA, p, xfer>>1);
- p += xfer & ~1;
- xfer &= 1;
- }
+ if (xfer >= 8) {
+ insw(iobase + DMADATA, p, xfer >> 1);
+ p += xfer & ~1;
+ xfer &= 1;
+ }
#endif
- if (xfer > 0) {
- outb(DMACNTRL0, ENDMA|B8MODE);
- insb(DMADATA, p, xfer);
- p += xfer;
- outb(DMACNTRL0, ENDMA|DWORDPIO);
+ if (xfer > 0) {
+ outb(iobase + DMACNTRL0, ENDMA | B8MODE);
+ insb(iobase + DMADATA, p, xfer);
+ p += xfer;
+ outb(iobase + DMACNTRL0, ENDMA | DWORDPIO);
+ }
}
if ((dmastat & INTSTAT) != 0)
@@ -2026,23 +2054,24 @@ aic_datain_pio(sc, p, n)
* FIFO is not empty, waste some bytes....
*/
if (in == 0) {
- outb(SXFRCTL1, BITBUCKET);
+ outb(iobase + SXFRCTL1, BITBUCKET);
for (;;) {
- if ((inb(DMASTAT) & INTSTAT) != 0)
+ if ((inb(iobase + DMASTAT) & INTSTAT) != 0)
break;
}
- outb(SXFRCTL1, 0);
+ outb(iobase + SXFRCTL1, 0);
AIC_MISC(("extra data "));
}
phasechange:
/* Stop the FIFO data path. */
- outb(SXFRCTL0, CHEN);
- while ((inb(SXFRCTL0) & SCSIEN) != 0)
+ outb(iobase + SXFRCTL0, CHEN);
+ while ((inb(iobase + SXFRCTL0) & SCSIEN) != 0)
;
/* Turn on ENREQINIT again. */
- outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENREQINIT|ENPHASECHG);
+ outb(iobase + SIMODE1,
+ ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENREQINIT | ENPHASECHG);
return in;
}
@@ -2057,6 +2086,7 @@ aicintr(arg)
void *arg;
{
register struct aic_softc *sc = arg;
+ int iobase = sc->sc_iobase;
u_char sstat0, sstat1;
register struct aic_acb *acb;
register struct scsi_link *sc_link;
@@ -2067,16 +2097,15 @@ aicintr(arg)
* Clear INTEN. We enable it again before returning. This makes the
* interrupt esssentially level-triggered.
*/
- outb(DMACNTRL0, 0);
+ outb(iobase + DMACNTRL0, 0);
AIC_TRACE(("aicintr "));
loop:
-gotintr:
/*
* First check for abnormal conditions, such as reset.
*/
- sstat1 = inb(SSTAT1);
+ sstat1 = inb(iobase + SSTAT1);
AIC_MISC(("sstat1:0x%02x ", sstat1));
if ((sstat1 & SCSIRSTI) != 0) {
@@ -2089,12 +2118,12 @@ gotintr:
*/
if ((sstat1 & SCSIPERR) != 0) {
printf("%s: SCSI bus parity error\n", sc->sc_dev.dv_xname);
- outb(CLRSINT1, CLRSCSIPERR);
+ outb(iobase + CLRSINT1, CLRSCSIPERR);
if (sc->sc_prevphase == PH_MSGIN) {
- aic_sched_msgout(SEND_PARITY_ERROR);
sc->sc_flags |= AIC_DROP_MSGIN;
+ aic_sched_msgout(sc, SEND_PARITY_ERROR);
} else
- aic_sched_msgout(SEND_INIT_DET_ERR);
+ aic_sched_msgout(sc, SEND_INIT_DET_ERR);
}
/*
@@ -2110,20 +2139,18 @@ gotintr:
switch (sc->sc_state) {
case AIC_IDLE:
case AIC_SELECTING:
- sstat0 = inb(SSTAT0);
+ sstat0 = inb(iobase + SSTAT0);
AIC_MISC(("sstat0:0x%02x ", sstat0));
if ((sstat0 & TARGET) != 0) {
/*
* We don't currently support target mode.
*/
- printf("%s: target mode selected; going to bus free\n",
+ printf("%s: target mode selected; going to BUS FREE\n",
sc->sc_dev.dv_xname);
- outb(SCSISIG, 0);
+ outb(iobase + SCSISIG, 0);
- sc->sc_state = AIC_IDLE;
- aic_sched(sc);
- goto out;
+ goto sched;
} else if ((sstat0 & SELDI) != 0) {
AIC_MISC(("reselected "));
@@ -2140,7 +2167,7 @@ gotintr:
}
/* Save reselection ID. */
- sc->sc_selid = inb(SELID);
+ sc->sc_selid = inb(iobase + SELID);
sc->sc_state = AIC_RESELECTED;
} else if ((sstat0 & SELDO) != 0) {
@@ -2159,27 +2186,26 @@ gotintr:
}
AIC_ASSERT(sc->sc_nexus != NULL);
acb = sc->sc_nexus;
-
sc_link = acb->xs->sc_link;
ti = &sc->sc_tinfo[sc_link->target];
- if ((acb->xs->flags & SCSI_RESET) == 0) {
- sc->sc_msgpriq = SEND_IDENTIFY;
- if (acb->flags != ACB_ABORTED) {
+
+ sc->sc_msgpriq = SEND_IDENTIFY;
+ if (acb->flags & ACB_RESET)
+ sc->sc_msgpriq |= SEND_DEV_RESET;
+ else if (acb->flags & ACB_ABORT)
+ sc->sc_msgpriq |= SEND_ABORT;
+ else {
#if AIC_USE_SYNCHRONOUS
- if ((ti->flags & DO_SYNC) != 0)
- sc->sc_msgpriq |= SEND_SDTR;
+ if ((ti->flags & DO_SYNC) != 0)
+ sc->sc_msgpriq |= SEND_SDTR;
#endif
#if AIC_USE_WIDE
- if ((ti->flags & DO_WIDE) != 0)
- sc->sc_msgpriq |= SEND_WDTR;
+ if ((ti->flags & DO_WIDE) != 0)
+ sc->sc_msgpriq |= SEND_WDTR;
#endif
- } else {
- sc->sc_flags |= AIC_ABORTING;
- sc->sc_msgpriq |= SEND_ABORT;
- }
- } else
- sc->sc_msgpriq = SEND_DEV_RESET;
+ }
+ acb->flags |= ACB_NEXUS;
ti->lubusy |= (1 << sc_link->lun);
/* Do an implicit RESTORE POINTERS. */
@@ -2188,6 +2214,10 @@ gotintr:
sc->sc_cp = (u_char *)&acb->scsi_cmd;
sc->sc_cleft = acb->scsi_cmd_length;
+ /* On our first connection, schedule a timeout. */
+ if ((acb->xs->flags & SCSI_POLL) == 0)
+ timeout(aic_timeout, acb, (acb->timeout * hz) / 1000);
+
sc->sc_state = AIC_CONNECTED;
} else if ((sstat1 & SELTO) != 0) {
AIC_MISC(("selection timeout "));
@@ -2201,119 +2231,143 @@ gotintr:
AIC_ASSERT(sc->sc_nexus != NULL);
acb = sc->sc_nexus;
- outb(SXFRCTL1, 0);
- outb(SCSISEQ, ENRESELI);
- outb(CLRSINT1, CLRSELTIMO);
+ outb(iobase + SXFRCTL1, 0);
+ outb(iobase + SCSISEQ, ENRESELI);
+ outb(iobase + CLRSINT1, CLRSELTIMO);
+ delay(250);
acb->xs->error = XS_SELTIMEOUT;
- untimeout(aic_timeout, acb);
- delay(250);
- aic_done(sc, acb);
- goto out;
+ goto finish;
} else {
-#ifdef AIC_PICKY
if (sc->sc_state != AIC_IDLE) {
printf("%s: BUS FREE while not idle; state=%d\n",
sc->sc_dev.dv_xname, sc->sc_state);
AIC_BREAK();
goto out;
}
-#endif
- aic_sched(sc);
- goto out;
+ goto sched;
}
/*
* Turn off selection stuff, and prepare to catch bus free
* interrupts, parity errors, and phase changes.
*/
- outb(SXFRCTL1, 0);
- outb(SCSISEQ, ENAUTOATNP);
- outb(CLRSINT0, CLRSELDI|CLRSELDO);
- outb(CLRSINT1, CLRBUSFREE|CLRPHASECHG);
- outb(SIMODE0, 0);
- outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENREQINIT|ENPHASECHG);
+ outb(iobase + SXFRCTL0, CHEN | CLRSTCNT | CLRCH);
+ outb(iobase + SXFRCTL1, 0);
+ outb(iobase + SCSISEQ, ENAUTOATNP);
+ outb(iobase + CLRSINT0, CLRSELDI | CLRSELDO);
+ outb(iobase + CLRSINT1, CLRBUSFREE | CLRPHASECHG);
+ outb(iobase + SIMODE0, 0);
+ outb(iobase + SIMODE1,
+ ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENREQINIT | ENPHASECHG);
sc->sc_flags = 0;
sc->sc_prevphase = PH_INVALID;
goto dophase;
}
- outb(CLRSINT1, CLRPHASECHG);
-
if ((sstat1 & BUSFREE) != 0) {
/* We've gone to BUS FREE phase. */
- outb(CLRSINT1, CLRBUSFREE);
+ outb(iobase + CLRSINT1, CLRBUSFREE | CLRPHASECHG);
switch (sc->sc_state) {
case AIC_RESELECTED:
- sc->sc_state = AIC_IDLE;
- aic_sched(sc);
- break;
+ goto sched;
case AIC_CONNECTED:
+ AIC_ASSERT(sc->sc_nexus != NULL);
+ acb = sc->sc_nexus;
+
+#if AIC_USE_SYNCHRONOUS + AIC_USE_WIDE
+ if (sc->sc_prevphase == PH_MSGOUT) {
+ /*
+ * If the target went to BUS FREE phase during
+ * or immediately after sending a SDTR or WDTR
+ * message, disable negotiation.
+ */
+ sc_link = acb->xs->sc_link;
+ ti = &sc->sc_tinfo[sc_link->target];
+ switch (sc->sc_lastmsg) {
+#if AIC_USE_SYNCHRONOUS
+ case SEND_SDTR:
+ ti->flags &= ~DO_SYNC;
+ ti->period = ti->offset = 0;
+ break;
+#endif
+#if AIC_USE_WIDE
+ case SEND_WDTR:
+ ti->flags &= ~DO_WIDE;
+ ti->width = 0;
+ break;
+#endif
+ }
+ }
+#endif
+
if ((sc->sc_flags & AIC_ABORTING) == 0) {
- printf("%s: unexpected BUS FREE; aborting\n",
+ /*
+ * Section 5.1.1 of the SCSI 2 spec suggests
+ * issuing a REQUEST SENSE following an
+ * unexpected disconnect. Some devices go into
+ * a contingent allegiance condition when
+ * disconnecting, and this is necessary to
+ * clean up their state.
+ */
+ printf("%s: unexpected disconnect; sending REQUEST SENSE\n",
sc->sc_dev.dv_xname);
AIC_BREAK();
+ aic_sense(sc, acb);
+ goto out;
}
- AIC_ASSERT(sc->sc_nexus != NULL);
- acb = sc->sc_nexus;
+
acb->xs->error = XS_DRIVER_STUFFUP;
goto finish;
case AIC_DISCONNECT:
AIC_ASSERT(sc->sc_nexus != NULL);
acb = sc->sc_nexus;
- sc->sc_state = AIC_IDLE;
- sc->sc_nexus = NULL;
TAILQ_INSERT_HEAD(&sc->nexus_list, acb, chain);
- aic_sched(sc);
- break;
+ sc->sc_nexus = NULL;
+ goto sched;
case AIC_CMDCOMPLETE:
AIC_ASSERT(sc->sc_nexus != NULL);
acb = sc->sc_nexus;
- finish:
- untimeout(aic_timeout, acb);
- aic_done(sc, acb);
- break;
+ goto finish;
}
- goto out;
}
+ outb(iobase + CLRSINT1, CLRPHASECHG);
+
dophase:
if ((sstat1 & REQINIT) == 0) {
/* Wait for REQINIT. */
goto out;
}
- sc->sc_phase = inb(SCSISIG) & PH_MASK;
- outb(SCSISIG, sc->sc_phase);
+ sc->sc_phase = inb(iobase + SCSISIG) & PH_MASK;
+ outb(iobase + SCSISIG, sc->sc_phase);
switch (sc->sc_phase) {
case PH_MSGOUT:
- /* If aborting, always handle MESSAGE OUT. */
- if ((sc->sc_state & AIC_CONNECTED) == 0 &&
- (sc->sc_flags & AIC_ABORTING) == 0)
+ if (sc->sc_state != AIC_CONNECTED &&
+ sc->sc_state != AIC_RESELECTED)
break;
aic_msgout(sc);
sc->sc_prevphase = PH_MSGOUT;
goto loop;
case PH_MSGIN:
- if ((sc->sc_state & (AIC_CONNECTED|AIC_RESELECTED)) == 0)
+ if (sc->sc_state != AIC_CONNECTED &&
+ sc->sc_state != AIC_RESELECTED)
break;
- if (aic_msgin(sc)) {
- sc->sc_prevphase = PH_MSGIN;
- goto gotintr;
- }
+ aic_msgin(sc);
sc->sc_prevphase = PH_MSGIN;
goto loop;
case PH_CMD:
- if ((sc->sc_state & AIC_CONNECTED) == 0)
+ if (sc->sc_state != AIC_CONNECTED)
break;
#if AIC_DEBUG
if ((aic_debug & AIC_SHOWMISC) != 0) {
@@ -2330,7 +2384,7 @@ dophase:
goto loop;
case PH_DATAOUT:
- if ((sc->sc_state & AIC_CONNECTED) == 0)
+ if (sc->sc_state != AIC_CONNECTED)
break;
AIC_MISC(("dataout dleft=%d ", sc->sc_dleft));
n = aic_dataout_pio(sc, sc->sc_dp, sc->sc_dleft);
@@ -2340,7 +2394,7 @@ dophase:
goto loop;
case PH_DATAIN:
- if ((sc->sc_state & AIC_CONNECTED) == 0)
+ if (sc->sc_state != AIC_CONNECTED)
break;
AIC_MISC(("datain "));
n = aic_datain_pio(sc, sc->sc_dp, sc->sc_dleft);
@@ -2350,17 +2404,17 @@ dophase:
goto loop;
case PH_STAT:
- if ((sc->sc_state & AIC_CONNECTED) == 0)
+ if (sc->sc_state != AIC_CONNECTED)
break;
AIC_ASSERT(sc->sc_nexus != NULL);
acb = sc->sc_nexus;
/* XXXX Don't clear FIFO. Wait for byte to come in. */
- outb(SXFRCTL0, CHEN|SPIOEN);
- outb(DMACNTRL0, RSTFIFO);
- acb->target_stat = inb(SCSIDAT);
- outb(SXFRCTL0, CHEN);
- outb(DMACNTRL0, RSTFIFO);
- while ((inb(SXFRCTL0) & SCSIEN) != 0)
+ outb(iobase + SXFRCTL0, CHEN | SPIOEN);
+ outb(iobase + DMACNTRL0, RSTFIFO);
+ acb->target_stat = inb(iobase + SCSIDAT);
+ outb(iobase + SXFRCTL0, CHEN);
+ outb(iobase + DMACNTRL0, RSTFIFO);
+ while ((inb(iobase + SXFRCTL0) & SCSIEN) != 0)
;
AIC_MISC(("target_stat=0x%02x ", acb->target_stat));
sc->sc_prevphase = PH_STAT;
@@ -2373,8 +2427,18 @@ reset:
aic_init(sc);
return 1;
+finish:
+ untimeout(aic_timeout, acb);
+ aic_done(sc, acb);
+ goto out;
+
+sched:
+ sc->sc_state = AIC_IDLE;
+ aic_sched(sc);
+ goto out;
+
out:
- outb(DMACNTRL0, INTEN);
+ outb(iobase + DMACNTRL0, INTEN);
return 1;
}
@@ -2384,11 +2448,17 @@ aic_abort(sc, acb)
struct aic_acb *acb;
{
- if (sc->sc_nexus == acb) {
- if (sc->sc_state == AIC_CONNECTED) {
- sc->sc_flags |= AIC_ABORTING;
- aic_sched_msgout(SEND_ABORT);
- }
+ /* 2 secs for the abort */
+ acb->timeout = AIC_ABORT_TIMEOUT;
+ acb->flags |= ACB_ABORT;
+
+ if (acb == sc->sc_nexus) {
+ /*
+ * If we're still selecting, the message will be scheduled
+ * after selection is complete.
+ */
+ if (sc->sc_state == AIC_CONNECTED)
+ aic_sched_msgout(sc, SEND_ABORT);
} else {
aic_dequeue(sc, acb);
TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain);
@@ -2412,20 +2482,15 @@ aic_timeout(arg)
s = splbio();
- if (acb->flags == ACB_ABORTED) {
+ if (acb->flags & ACB_ABORT) {
/* abort timed out */
printf(" AGAIN\n");
- acb->xs->retries = 0;
- aic_done(sc, acb);
+ /* XXX Must reset! */
} else {
/* abort the operation that has timed out */
printf("\n");
acb->xs->error = XS_TIMEOUT;
- acb->flags = ACB_ABORTED;
aic_abort(sc, acb);
- /* 2 secs for the abort */
- if ((xs->flags & SCSI_POLL) == 0)
- timeout(aic_timeout, acb, 2 * hz);
}
splx(s);
@@ -2472,7 +2537,7 @@ void
aic_print_active_acb()
{
struct aic_acb *acb;
- struct aic_softc *sc = aiccd.cd_devs[0];
+ struct aic_softc *sc = aic_cd.cd_devs[0];
printf("ready list:\n");
for (acb = sc->ready_list.tqh_first; acb != NULL;
@@ -2491,16 +2556,20 @@ void
aic_dump6360(sc)
struct aic_softc *sc;
{
+ int iobase = sc->sc_iobase;
printf("aic6360: SCSISEQ=%x SXFRCTL0=%x SXFRCTL1=%x SCSISIG=%x\n",
- inb(SCSISEQ), inb(SXFRCTL0), inb(SXFRCTL1), inb(SCSISIG));
+ inb(iobase + SCSISEQ), inb(iobase + SXFRCTL0),
+ inb(iobase + SXFRCTL1), inb(iobase + SCSISIG));
printf(" SSTAT0=%x SSTAT1=%x SSTAT2=%x SSTAT3=%x SSTAT4=%x\n",
- inb(SSTAT0), inb(SSTAT1), inb(SSTAT2), inb(SSTAT3), inb(SSTAT4));
+ inb(iobase + SSTAT0), inb(iobase + SSTAT1), inb(iobase + SSTAT2),
+ inb(iobase + SSTAT3), inb(iobase + SSTAT4));
printf(" SIMODE0=%x SIMODE1=%x DMACNTRL0=%x DMACNTRL1=%x DMASTAT=%x\n",
- inb(SIMODE0), inb(SIMODE1), inb(DMACNTRL0), inb(DMACNTRL1),
- inb(DMASTAT));
+ inb(iobase + SIMODE0), inb(iobase + SIMODE1),
+ inb(iobase + DMACNTRL0), inb(iobase + DMACNTRL1),
+ inb(iobase + DMASTAT));
printf(" FIFOSTAT=%d SCSIBUS=0x%x\n",
- inb(FIFOSTAT), inb(SCSIBUS));
+ inb(iobase + FIFOSTAT), inb(iobase + SCSIBUS));
}
void
diff --git a/sys/dev/isa/ast.c b/sys/dev/isa/ast.c
index 654c5a77cb3..366e1bf5a4a 100644
--- a/sys/dev/isa/ast.c
+++ b/sys/dev/isa/ast.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ast.c,v 1.7 1996/04/18 23:47:29 niklas Exp $ */
-/* $NetBSD: ast.c,v 1.22 1996/03/10 09:01:20 cgd Exp $ */
+/* $OpenBSD: ast.c,v 1.8 1996/04/21 22:22:48 deraadt Exp $ */
+/* $NetBSD: ast.c,v 1.26 1996/04/15 18:55:23 cgd Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -36,7 +36,13 @@
#include <sys/param.h>
#include <sys/device.h>
+#include <sys/termios.h>
+#ifdef i386 /* XXX */
+#include <machine/cpu.h> /* XXX */
+#else /* XXX */
+#include <machine/intr.h>
+#endif /* XXX */
#include <machine/bus.h>
#include <dev/isa/isavar.h>
@@ -61,8 +67,12 @@ int astprobe();
void astattach();
int astintr __P((void *));
-struct cfdriver astcd = {
- NULL, "ast", astprobe, astattach, DV_TTY, sizeof(struct ast_softc)
+struct cfattach ast_ca = {
+ sizeof(struct ast_softc), astprobe, astattach
+};
+
+struct cfdriver ast_cd = {
+ NULL, "ast", DV_TTY
};
int
@@ -163,20 +173,13 @@ astattach(parent, self, aux)
ca.ca_iobase = sc->sc_iobase + i * COM_NPORTS;
ca.ca_noien = 1;
- /* mimic config_found(), but with special functionality */
- if ((match = config_search(NULL, self, &ca)) != NULL) {
- subunit = match->cf_unit; /* can change if unit == * */
- config_attach(self, match, &ca, astprint);
- sc->sc_slaves[i] = match->cf_driver->cd_devs[subunit];
+ sc->sc_slaves[i] = config_found(self, &ca, astprint);
+ if (sc->sc_slaves[i] != NULL)
sc->sc_alive |= 1 << i;
- } else {
- astprint(&ca, self->dv_xname);
- printf(" not configured\n");
- }
}
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_TTY, astintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_TTY, astintr, sc, sc->sc_dev.dv_xname);
}
int
diff --git a/sys/dev/isa/boca.c b/sys/dev/isa/boca.c
index d05fa84ae6f..c4ece6a26c5 100644
--- a/sys/dev/isa/boca.c
+++ b/sys/dev/isa/boca.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: boca.c,v 1.7 1996/04/18 23:47:30 niklas Exp $ */
-/* $NetBSD: boca.c,v 1.9 1996/03/10 09:01:22 cgd Exp $ */
+/* $OpenBSD: boca.c,v 1.8 1996/04/21 22:22:52 deraadt Exp $ */
+/* $NetBSD: boca.c,v 1.13 1996/04/15 18:55:28 cgd Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -36,7 +36,13 @@
#include <sys/param.h>
#include <sys/device.h>
+#include <sys/termios.h>
+#ifdef i386 /* XXX */
+#include <machine/cpu.h> /* XXX */
+#else /* XXX */
+#include <machine/intr.h>
+#endif /* XXX */
#include <machine/bus.h>
#include <dev/isa/isavar.h>
@@ -61,8 +67,12 @@ int bocaprobe();
void bocaattach();
int bocaintr __P((void *));
-struct cfdriver bocacd = {
- NULL, "boca", bocaprobe, bocaattach, DV_TTY, sizeof(struct boca_softc)
+struct cfattach boca_ca = {
+ sizeof(struct boca_softc), bocaprobe, bocaattach,
+};
+
+struct cfdriver boca_cd = {
+ NULL, "boca", DV_TTY
};
int
@@ -158,20 +168,13 @@ bocaattach(parent, self, aux)
ca.ca_iobase = sc->sc_iobase + i * COM_NPORTS;
ca.ca_noien = 0;
- /* mimic config_found(), but with special functionality */
- if ((match = config_search(NULL, self, &ca)) != NULL) {
- subunit = match->cf_unit; /* can change if unit == * */
- config_attach(self, match, &ca, bocaprint);
- sc->sc_slaves[i] = match->cf_driver->cd_devs[subunit];
+ sc->sc_slaves[i] = config_found(self, &ca, bocaprint);
+ if (sc->sc_slaves[i] != NULL)
sc->sc_alive |= 1 << i;
- } else {
- bocaprint(&ca, self->dv_xname);
- printf(" not configured\n");
- }
}
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_TTY, bocaintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_TTY, bocaintr, sc, sc->sc_dev.dv_xname);
}
int
diff --git a/sys/dev/isa/bt.c b/sys/dev/isa/bt.c
index 42638c6607f..1875d60eb93 100644
--- a/sys/dev/isa/bt.c
+++ b/sys/dev/isa/bt.c
@@ -1,8 +1,10 @@
-/* $OpenBSD: bt.c,v 1.7 1996/04/18 23:47:31 niklas Exp $ */
-/* $NetBSD: bt742a.c,v 1.55 1996/03/16 05:33:28 cgd Exp $ */
+/* $NetBSD: bt.c,v 1.7 1996/04/11 22:28:25 cgd Exp $ */
+
+#define BTDIAG
+#define integrate
/*
- * Copyright (c) 1994 Charles Hannum. All rights reserved.
+ * Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -14,7 +16,7 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by Charles Hannum.
+ * This product includes software developed by Charles M. Hannum.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
@@ -45,10 +47,6 @@
* functioning of this software in any circumstances.
*/
-/*
- * bt742a SCSI driver
- */
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
@@ -63,92 +61,17 @@
#include <machine/pio.h>
-#include <dev/isa/isavar.h>
-#include <dev/isa/isadmavar.h>
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
-/*
- * Note that stdarg.h and the ANSI style va_start macro is used for both
- * ANSI and traditional C compilers.
- */
-#include <machine/stdarg.h>
+#include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
+#include <dev/isa/btreg.h>
#ifndef DDB
#define Debugger() panic("should call debugger here (bt742a.c)")
#endif /* ! DDB */
-typedef u_long physaddr;
-typedef u_long physlen;
-
-/*
- * I/O Port Interface
- */
-#define BT_CTRL_STAT_PORT 0x0 /* control & status */
-#define BT_CMD_DATA_PORT 0x1 /* cmds and datas */
-#define BT_INTR_PORT 0x2 /* Intr. stat */
-
-/*
- * BT_CTRL_STAT bits (write)
- */
-#define BT_HRST 0x80 /* Hardware reset */
-#define BT_SRST 0x40 /* Software reset */
-#define BT_IRST 0x20 /* Interrupt reset */
-#define BT_SCRST 0x10 /* SCSI bus reset */
-
-/*
- * BT_CTRL_STAT bits (read)
- */
-#define BT_STST 0x80 /* Self test in Progress */
-#define BT_DIAGF 0x40 /* Diagnostic Failure */
-#define BT_INIT 0x20 /* Mbx Init required */
-#define BT_IDLE 0x10 /* Host Adapter Idle */
-#define BT_CDF 0x08 /* cmd/data out port full */
-#define BT_DF 0x04 /* Data in port full */
-#define BT_INVDCMD 0x01 /* Invalid command */
-
-/*
- * BT_CMD_DATA bits (write)
- */
-#define BT_NOP 0x00 /* No operation */
-#define BT_MBX_INIT 0x01 /* Mbx initialization */
-#define BT_START_SCSI 0x02 /* start scsi command */
-#define BT_START_BIOS 0x03 /* start bios command */
-#define BT_INQUIRE 0x04 /* Adapter Inquiry */
-#define BT_MBO_INTR_EN 0x05 /* Enable MBO available interrupt */
-#define BT_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
-#define BT_BUS_ON_TIME_SET 0x07 /* set bus-on time */
-#define BT_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
-#define BT_SPEED_SET 0x09 /* set transfer speed */
-#define BT_DEV_GET 0x0a /* return installed devices */
-#define BT_CONF_GET 0x0b /* return configuration data */
-#define BT_TARGET_EN 0x0c /* enable target mode */
-#define BT_SETUP_GET 0x0d /* return setup data */
-#define BT_WRITE_CH2 0x1a /* write channel 2 buffer */
-#define BT_READ_CH2 0x1b /* read channel 2 buffer */
-#define BT_WRITE_FIFO 0x1c /* write fifo buffer */
-#define BT_READ_FIFO 0x1d /* read fifo buffer */
-#define BT_ECHO 0x1e /* Echo command data */
-#define BT_MBX_INIT_EXTENDED 0x81 /* Mbx initialization */
-#define BT_INQUIRE_REV_THIRD 0x84 /* Get 3rd firmware version byte */
-#define BT_INQUIRE_REV_FOURTH 0x85 /* Get 4th firmware version byte */
-#define BT_GET_BOARD_INFO 0x8b /* Get hardware ID and revision */
-#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_DISABLE 0x00 /* Parameter value for Disable */
-#define BT_ENABLE 0x01 /* Parameter value for Enable */
-
-/*
- * BT_INTR_PORT bits (read)
- */
-#define BT_ANY_INTR 0x80 /* Any interrupt */
-#define BT_SCRD 0x08 /* SCSI reset detected */
-#define BT_HACC 0x04 /* Command complete */
-#define BT_MBOA 0x02 /* MBX out empty */
-#define BT_MBIF 0x01 /* MBX in full */
-
/*
* Mail box defs etc.
* these could be bigger but we need the bt_softc to fit on a single page..
@@ -166,180 +89,14 @@ typedef u_long physlen;
else \
(wmb)++;
-struct bt_mbx_out {
- physaddr ccb_addr;
- u_char dummy[3];
- u_char cmd;
-};
-
-struct bt_mbx_in {
- physaddr ccb_addr;
- u_char btstat;
- u_char sdstat;
- u_char dummy;
- u_char stat;
-};
-
struct bt_mbx {
struct bt_mbx_out mbo[BT_MBX_SIZE];
struct bt_mbx_in mbi[BT_MBX_SIZE];
+ struct bt_mbx_out *cmbo; /* Collection Mail Box out */
struct bt_mbx_out *tmbo; /* Target Mail Box out */
struct bt_mbx_in *tmbi; /* Target Mail Box in */
};
-/*
- * mbo.cmd values
- */
-#define BT_MBO_FREE 0x0 /* MBO entry is free */
-#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 */
-
-#if defined(BIG_DMA)
-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 {
- physlen seg_len;
- physaddr seg_addr;
-};
-
-struct bt_ccb {
- u_char opcode;
- u_char:3, data_in:1, data_out:1,:3;
- u_char scsi_cmd_length;
- u_char req_sense_length;
- /*------------------------------------longword boundary */
- physlen data_length;
- /*------------------------------------longword boundary */
- physaddr data_addr;
- /*------------------------------------longword boundary */
- u_char dummy1[2];
- u_char host_stat;
- u_char target_stat;
- /*------------------------------------longword boundary */
- u_char target;
- u_char lun;
- struct scsi_generic scsi_cmd;
- u_char dummy2[1];
- u_char link_id;
- /*------------------------------------longword boundary */
- physaddr link_addr;
- /*------------------------------------longword boundary */
- physaddr sense_ptr;
-/*-----end of HW fields-----------------------longword boundary */
- struct scsi_sense_data scsi_sense;
- /*------------------------------------longword boundary */
- struct bt_scat_gath scat_gath[BT_NSEG];
- /*------------------------------------longword boundary */
- TAILQ_ENTRY(bt_ccb) chain;
- struct bt_ccb *nexthash;
- long hashkey;
- struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
- int flags;
-#define CCB_FREE 0
-#define CCB_ACTIVE 1
-#define CCB_ABORTED 2
- struct bt_mbx_out *mbx; /* pointer to mail box */
-};
-
-/*
- * opcode fields
- */
-#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_RESET_CCB 0x81 /* SCSI Bus reset */
-
-/*
- * bt_ccb.host_stat values
- */
-#define BT_OK 0x00 /* cmd ok */
-#define BT_LINK_OK 0x0a /* Link cmd ok */
-#define BT_LINK_IT 0x0b /* Link cmd ok + int */
-#define BT_SEL_TIMEOUT 0x11 /* Selection time out */
-#define BT_OVER_UNDER 0x12 /* Data over/under run */
-#define BT_BUS_FREE 0x13 /* Bus dropped at unexpected time */
-#define BT_INV_BUS 0x14 /* Invalid bus phase/sequence */
-#define BT_BAD_MBO 0x15 /* Incorrect MBO cmd */
-#define BT_BAD_CCB 0x16 /* Incorrect ccb opcode */
-#define BT_BAD_LINK 0x17 /* Not same values of LUN for links */
-#define BT_INV_TARGET 0x18 /* Invalid target direction */
-#define BT_CCB_DUP 0x19 /* Duplicate CCB received */
-#define BT_INV_CCB 0x1a /* Invalid CCB or segment list */
-#define BT_ABORTED 42 /* pseudo value from driver */
-
-struct bt_extended_inquire {
- u_char bus_type; /* Type of bus connected to */
-#define BT_BUS_TYPE_24BIT 'A' /* ISA bus */
-#define BT_BUS_TYPE_32BIT 'E' /* EISA/VLB/PCI bus */
-#define BT_BUS_TYPE_MCA 'M' /* MicroChannel bus */
- u_char bios_address; /* Address of adapter BIOS */
- u_short max_segment; /* ? */
-};
-
-struct bt_boardID {
- u_char board_type;
- u_char custom_feture;
- char firm_revision;
- u_char firm_version;
-};
-
-struct bt_board_info {
- u_char id[4]; /* i.e bt742a -> '7','4','2','A' */
- u_char version[2]; /* i.e Board Revision 'H' -> 'H', 0x00 */
-};
-
-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]; /*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;
-};
-
-struct bt_config {
- u_char chan;
- u_char intr;
- u_char scsi_dev:3;
- u_char :5;
-};
-
-#define INT9 0x01
-#define INT10 0x02
-#define INT11 0x04
-#define INT12 0x08
-#define INT14 0x20
-#define INT15 0x40
-
-#define EISADMA 0x00
-#define CHAN0 0x01
-#define CHAN5 0x20
-#define CHAN6 0x40
-#define CHAN7 0x80
-
#define KVTOPHYS(x) vtophys(x)
struct bt_softc {
@@ -350,28 +107,33 @@ struct bt_softc {
int sc_iobase;
int sc_irq, sc_drq;
+ char sc_model[7],
+ sc_firmware[6];
+
struct bt_mbx sc_mbx; /* all our mailboxes */
+#define wmbx (&sc->sc_mbx)
struct bt_ccb *sc_ccbhash[CCB_HASH_SIZE];
- TAILQ_HEAD(, bt_ccb) sc_free_ccb;
- int sc_numccbs;
+ TAILQ_HEAD(, bt_ccb) sc_free_ccb, sc_waiting_ccb;
+ int sc_numccbs, sc_mbofull;
int sc_scsi_dev; /* adapters scsi id */
struct scsi_link sc_link; /* prototype for devs */
};
-/***********debug values *************/
-#define BT_SHOWCCBS 0x01
-#define BT_SHOWINTS 0x02
-#define BT_SHOWCMDS 0x04
-#define BT_SHOWMISC 0x08
+#ifdef BTDEBUG
int bt_debug = 0;
+#endif /* BTDEBUG */
-int bt_cmd __P((int, struct bt_softc *, int, int, int, u_char *,
- unsigned, ...));
+int bt_cmd __P((int, struct bt_softc *, int, u_char *, int, u_char *));
+integrate void bt_finish_ccbs __P((struct bt_softc *));
int btintr __P((void *));
-void bt_free_ccb __P((struct bt_softc *, struct bt_ccb *, int));
+integrate void bt_reset_ccb __P((struct bt_softc *, struct bt_ccb *));
+void bt_free_ccb __P((struct bt_softc *, struct bt_ccb *));
+integrate void bt_init_ccb __P((struct bt_softc *, struct bt_ccb *));
struct bt_ccb *bt_get_ccb __P((struct bt_softc *, int));
struct bt_ccb *bt_ccb_phys_kv __P((struct bt_softc *, u_long));
-struct bt_mbx_out *bt_send_mbo __P((struct bt_softc *, int, struct bt_ccb *));
+void bt_queue_ccb __P((struct bt_softc *, struct bt_ccb *));
+void bt_collect_mbo __P((struct bt_softc *));
+void bt_start_ccbs __P((struct bt_softc *));
void bt_done __P((struct bt_softc *, struct bt_ccb *));
int bt_find __P((struct isa_attach_args *, struct bt_softc *));
void bt_init __P((struct bt_softc *));
@@ -380,10 +142,6 @@ void btminphys __P((struct buf *));
int bt_scsi_cmd __P((struct scsi_xfer *));
int bt_poll __P((struct bt_softc *, struct scsi_xfer *, int));
void bt_timeout __P((void *arg));
-#ifdef UTEST
-void bt_print_ccb __P((struct bt_ccb *));
-void bt_print_active_ccbs __P((struct bt_softc *));
-#endif
struct scsi_adapter bt_switch = {
bt_scsi_cmd,
@@ -404,47 +162,43 @@ int btprobe __P((struct device *, void *, void *));
void btattach __P((struct device *, struct device *, void *));
int btprint __P((void *, char *));
-struct cfdriver btcd = {
- NULL, "bt", btprobe, btattach, DV_DULL, sizeof(struct bt_softc)
+struct cfattach bt_ca = {
+ sizeof(struct bt_softc), btprobe, btattach
+};
+
+struct cfdriver bt_cd = {
+ NULL, "bt", DV_DULL
};
-#define BT_RESET_TIMEOUT 1000
+#define BT_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */
+#define BT_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
/*
- * bt_cmd(iobase, sc, icnt, ocnt, wait, retval, opcode, ... args ...)
+ * bt_cmd(iobase, sc, icnt, ibuf, ocnt, obuf)
*
* Activate Adapter command
- * icnt: number of args (outbound bytes written after opcode)
+ * icnt: number of args (outbound bytes including opcode)
+ * ibuf: argument buffer
* ocnt: number of expected returned bytes
+ * obuf: result buffer
* 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: variable number of 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
-#ifdef __STDC__
-bt_cmd(int iobase, struct bt_softc *sc, int icnt, int ocnt, int wait,
- u_char *retval, unsigned opcode, ...)
-#else
-bt_cmd(iobase, sc, icnt, ocnt, wait, retval, opcode, va_alist)
+bt_cmd(iobase, sc, icnt, ibuf, ocnt, obuf)
int iobase;
struct bt_softc *sc;
- int icnt, ocnt, wait;
- u_char *retval;
- unsigned opcode;
- va_dcl
-#endif
+ int icnt, ocnt;
+ u_char *ibuf, *obuf;
{
- va_list ap;
- unsigned data;
const char *name;
- u_char oc;
- register i;
- int sts;
+ register int i;
+ int wait;
+ u_char sts;
+ u_char opcode = ibuf[0];
if (sc == NULL)
name = sc->sc_dev.dv_xname;
@@ -452,29 +206,31 @@ bt_cmd(iobase, sc, icnt, ocnt, wait, retval, opcode, va_alist)
name = "(probe)";
/*
- * multiply the wait argument by a big constant
- * zero defaults to 1
+ * Calculate a reasonable timeout for the command.
*/
- if (wait)
- wait *= 100000;
- else
- wait = 100000;
+ switch (opcode) {
+ case BT_INQUIRE_DEVICES:
+ wait = 15 * 20000;
+ break;
+ default:
+ wait = 1 * 20000;
+ break;
+ }
+
/*
* 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(iobase + BT_CTRL_STAT_PORT);
- if (sts & BT_IDLE) {
+ if (opcode != BT_MBO_INTR_EN) {
+ for (i = 20000; i; i--) { /* 1 sec? */
+ sts = inb(iobase + BT_STAT_PORT);
+ if (sts & BT_STAT_IDLE)
break;
- }
- delay(10);
+ delay(50);
}
if (!i) {
printf("%s: bt_cmd, host not idle(0x%x)\n",
- name, sts);
+ name, sts);
return ENXIO;
}
}
@@ -483,69 +239,68 @@ bt_cmd(iobase, sc, icnt, ocnt, wait, retval, opcode, va_alist)
* queue feeding to us.
*/
if (ocnt) {
- while ((inb(iobase + BT_CTRL_STAT_PORT)) & BT_DF)
- inb(iobase + BT_CMD_DATA_PORT);
+ while ((inb(iobase + BT_STAT_PORT)) & BT_STAT_DF)
+ inb(iobase + BT_DATA_PORT);
}
/*
* Output the command and the number of arguments given
* for each byte, first check the port is empty.
*/
- va_start(ap, opcode);
- /* test icnt >= 0, to include the command in data sent */
- for (data = opcode; icnt >= 0; icnt--, data = va_arg(ap, u_char)) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
+ while (icnt--) {
for (i = wait; i; i--) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- if (!(sts & BT_CDF))
+ sts = inb(iobase + BT_STAT_PORT);
+ if (!(sts & BT_STAT_CDF))
break;
- delay(10);
+ delay(50);
}
if (!i) {
- printf("%s: bt_cmd, cmd/data port full\n", name);
- outb(iobase + BT_CTRL_STAT_PORT, BT_SRST);
- va_end(ap);
+ if (opcode != BT_INQUIRE_REVISION)
+ printf("%s: bt_cmd, cmd/data port full\n", name);
+ outb(iobase + BT_CTRL_PORT, BT_CTRL_SRST);
return ENXIO;
}
- outb(iobase + BT_CMD_DATA_PORT, data);
+ outb(iobase + BT_CMD_PORT, *ibuf++);
}
- va_end(ap);
/*
* If we expect input, loop that many times, each time,
* looking for the data register to have valid data
*/
while (ocnt--) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
for (i = wait; i; i--) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- if (sts & BT_DF)
+ sts = inb(iobase + BT_STAT_PORT);
+ if (sts & BT_STAT_DF)
break;
- delay(10);
+ delay(50);
}
if (!i) {
- printf("bt%d: bt_cmd, cmd/data port empty %d\n",
- name, ocnt);
+ if (opcode != BT_INQUIRE_REVISION)
+ printf("%s: bt_cmd, cmd/data port empty %d\n",
+ name, ocnt);
+ outb(iobase + BT_CTRL_PORT, BT_CTRL_SRST);
return ENXIO;
}
- oc = inb(iobase + BT_CMD_DATA_PORT);
- if (retval)
- *retval++ = oc;
+ *obuf++ = inb(iobase + BT_DATA_PORT);
}
/*
- * Wait for the board to report a finised instruction
+ * Wait for the board to report a finished instruction.
+ * We may get an extra interrupt for the HACC signal, but this is
+ * unimportant.
*/
- i = 100000; /* 1 sec? */
- while (--i) {
- sts = inb(iobase + BT_INTR_PORT);
- if (sts & BT_HACC)
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: bt_cmd, host not finished(0x%x)\n",
- name, sts);
- return ENXIO;
+ if (opcode != BT_MBO_INTR_EN) {
+ for (i = 20000; i; i--) { /* 1 sec? */
+ sts = inb(iobase + BT_INTR_PORT);
+ /* XXX Need to save this in the interrupt handler? */
+ if (sts & BT_INTR_HACC)
+ break;
+ delay(50);
+ }
+ if (!i) {
+ printf("%s: bt_cmd, host not finished(0x%x)\n",
+ name, sts);
+ return ENXIO;
+ }
}
- outb(iobase + BT_CTRL_STAT_PORT, BT_IRST);
+ outb(iobase + BT_CTRL_PORT, BT_CTRL_IRST);
return 0;
}
@@ -560,7 +315,6 @@ btprobe(parent, match, aux)
struct device *parent;
void *match, *aux;
{
- struct bt_softc *sc = match;
register struct isa_attach_args *ia = aux;
#ifdef NEWCONFIG
@@ -568,16 +322,13 @@ btprobe(parent, match, aux)
return 0;
#endif
- /*
- * Try initialise a unit at this location
- * sets up dma and bus speed, loads sc->sc_irq
- */
+ /* See if there is a unit at this location. */
if (bt_find(ia, NULL) != 0)
return 0;
ia->ia_msize = 0;
ia->ia_iosize = 4;
- /* IRQ and DRQ set by bt_find() */
+ /* IRQ and DRQ set by bt_find(). */
return 1;
}
@@ -586,6 +337,7 @@ btprint(aux, name)
void *aux;
char *name;
{
+
if (name != NULL)
printf("%s: scsibus ", name);
return UNCONF;
@@ -600,7 +352,7 @@ btattach(parent, self, aux)
void *aux;
{
struct isa_attach_args *ia = aux;
- struct bt_softc *sc = (struct bt_softc *)self;
+ struct bt_softc *sc = (void *)self;
if (bt_find(ia, sc) != 0)
panic("btattach: bt_find of %s failed", self->dv_xname);
@@ -609,8 +361,10 @@ btattach(parent, self, aux)
if (sc->sc_drq != DRQUNK)
isa_dmacascade(sc->sc_drq);
+ bt_inquire_setup_information(sc);
bt_init(sc);
TAILQ_INIT(&sc->sc_free_ccb);
+ TAILQ_INIT(&sc->sc_waiting_ccb);
/*
* fill in the prototype scsi_link.
@@ -619,15 +373,13 @@ btattach(parent, self, aux)
sc->sc_link.adapter_target = sc->sc_scsi_dev;
sc->sc_link.adapter = &bt_switch;
sc->sc_link.device = &bt_dev;
- sc->sc_link.openings = 2;
-
- printf("\n");
+ sc->sc_link.openings = 4;
#ifdef NEWCONFIG
isa_establish(&sc->sc_id, &sc->sc_dev);
#endif
- sc->sc_ih = isa_intr_establish(sc->sc_irq, IST_EDGE, IPL_BIO, btintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, sc->sc_irq, IST_EDGE,
+ IPL_BIO, btintr, sc, sc->sc_dev.dv_xname);
/*
* ask the adapter what subunits are present
@@ -635,141 +387,162 @@ btattach(parent, self, aux)
config_found(self, &sc->sc_link, btprint);
}
-/*
- * Catch an interrupt from the adaptor
- */
-int
-btintr(arg)
- void *arg;
+integrate void
+bt_finish_ccbs(sc)
+ struct bt_softc *sc;
{
- struct bt_softc *sc = arg;
- int iobase = sc->sc_iobase;
struct bt_mbx_in *wmbi;
- struct bt_mbx *wmbx;
struct bt_ccb *ccb;
- u_char stat;
int i;
- int found = 0;
-#ifdef BTDEBUG
- printf("%s: btintr ", sc->sc_dev.dv_xname);
-#endif /* BTDEBUG */
-
- /*
- * First acknowlege the interrupt, Then if it's
- * not telling about a completed operation
- * just return.
- */
- stat = inb(iobase + BT_INTR_PORT);
- if ((stat & (BT_MBOA | BT_MBIF)) == 0) {
- outb(iobase + BT_CTRL_STAT_PORT, BT_IRST);
- return -1; /* XXX */
- }
+ wmbi = wmbx->tmbi;
- /* Mail box out empty? */
- if (stat & BT_MBOA) {
- /* Disable MBO available interrupt. */
- outb(iobase + BT_CMD_DATA_PORT, BT_MBO_INTR_EN);
- for (i = 100000; i; i--) {
- if (!(inb(iobase + BT_CTRL_STAT_PORT) & BT_CDF))
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: btintr, cmd/data port full\n",
- sc->sc_dev.dv_xname);
- outb(iobase + BT_CTRL_STAT_PORT, BT_SRST);
- return 1;
+ if (wmbi->stat == BT_MBI_FREE) {
+ for (i = 0; i < BT_MBX_SIZE; i++) {
+ if (wmbi->stat != BT_MBI_FREE) {
+ printf("%s: mbi not in round-robin order\n",
+ sc->sc_dev.dv_xname);
+ goto AGAIN;
+ }
+ bt_nextmbx(wmbi, wmbx, mbi);
}
- outb(iobase + BT_CMD_DATA_PORT, 0x00); /* Disable */
- wakeup(&sc->sc_mbx);
+#ifdef BTDIAGnot
+ printf("%s: mbi interrupt with no full mailboxes\n",
+ sc->sc_dev.dv_xname);
+#endif
+ return;
}
- /* Mail box in full? */
- if ((stat & BT_MBIF) == 0)
- return 1;
- wmbx = &sc->sc_mbx;
- wmbi = wmbx->tmbi;
AGAIN:
- while (wmbi->stat != BT_MBI_FREE) {
- ccb = bt_ccb_phys_kv(sc, wmbi->ccb_addr);
+ do {
+ ccb = bt_ccb_phys_kv(sc, phystol(wmbi->ccb_addr));
if (!ccb) {
- wmbi->stat = BT_MBI_FREE;
- printf("%s: BAD CCB ADDR!\n", sc->sc_dev.dv_xname);
- continue;
+ printf("%s: bad mbi ccb pointer; skipping\n",
+ sc->sc_dev.dv_xname);
+ goto next;
+ }
+
+#ifdef BTDEBUG
+ if (bt_debug) {
+ u_char *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("stat %x for mbi addr = 0x%08x, ",
+ wmbi->stat, wmbi);
+ printf("ccb addr = 0x%x\n", ccb);
}
- found++;
+#endif /* BTDEBUG */
+
switch (wmbi->stat) {
case BT_MBI_OK:
case BT_MBI_ERROR:
+ if ((ccb->flags & CCB_ABORT) != 0) {
+ /*
+ * If we already started an abort, wait for it
+ * to complete before clearing the CCB. We
+ * could instead just clear CCB_SENDING, but
+ * what if the mailbox was already received?
+ * The worst that happens here is that we clear
+ * the CCB a bit later than we need to. BFD.
+ */
+ goto next;
+ }
break;
case BT_MBI_ABORT:
- ccb->host_stat = BT_ABORTED;
- break;
-
case BT_MBI_UNKNOWN:
- ccb = 0;
+ /*
+ * Even if the CCB wasn't found, we clear it anyway.
+ * See preceeding comment.
+ */
break;
default:
- panic("Impossible mbxi status");
+ printf("%s: bad mbi status %02x; skipping\n",
+ sc->sc_dev.dv_xname, wmbi->stat);
+ goto next;
}
-#ifdef BTDEBUG
- if (bt_debug && ccb) {
- u_char *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("stat %x for mbi addr = 0x%08x, ",
- wmbi->stat, wmbi);
- printf("ccb addr = 0x%x\n", ccb);
- }
-#endif /* BTDEBUG */
+
+ untimeout(bt_timeout, ccb);
+ bt_done(sc, ccb);
+
+ next:
wmbi->stat = BT_MBI_FREE;
- if (ccb) {
- untimeout(bt_timeout, ccb);
- bt_done(sc, ccb);
- }
bt_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
- for (i = 0; i < BT_MBX_SIZE; i++) {
- if (wmbi->stat != BT_MBI_FREE) {
- found++;
- break;
- }
- bt_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
-#if 0
- printf("%s: mbi interrupt with no full mailboxes\n",
- sc->sc_dev.dv_xname);
+ } while (wmbi->stat != BT_MBI_FREE);
+
+ wmbx->tmbi = wmbi;
+}
+
+/*
+ * Catch an interrupt from the adaptor
+ */
+int
+btintr(arg)
+ void *arg;
+{
+ struct bt_softc *sc = arg;
+ int iobase = sc->sc_iobase;
+ u_char sts;
+
+#ifdef BTDEBUG
+ printf("%s: btintr ", sc->sc_dev.dv_xname);
+#endif /* BTDEBUG */
+
+ /*
+ * First acknowlege the interrupt, Then if it's not telling about
+ * a completed operation just return.
+ */
+ sts = inb(iobase + BT_INTR_PORT);
+ if ((sts & BT_INTR_ANYINTR) == 0)
+ return 0;
+ outb(iobase + BT_CTRL_PORT, BT_CTRL_IRST);
+
+#ifdef BTDIAG
+ /* Make sure we clear CCB_SENDING before finishing a CCB. */
+ bt_collect_mbo(sc);
#endif
- } else {
- found = 0;
- goto AGAIN;
- }
+
+ /* Mail box out empty? */
+ if (sts & BT_INTR_MBOA) {
+ struct bt_toggle toggle;
+
+ toggle.cmd.opcode = BT_MBO_INTR_EN;
+ toggle.cmd.enable = 0;
+ bt_cmd(iobase, sc, sizeof(toggle.cmd), (u_char *)&toggle.cmd, 0,
+ (u_char *)0);
+ bt_start_ccbs(sc);
}
- wmbx->tmbi = wmbi;
- outb(iobase + BT_CTRL_STAT_PORT, BT_IRST);
+
+ /* Mail box in full? */
+ if (sts & BT_INTR_MBIF)
+ bt_finish_ccbs(sc);
+
return 1;
}
+integrate void
+bt_reset_ccb(sc, ccb)
+ struct bt_softc *sc;
+ struct bt_ccb *ccb;
+{
+
+ ccb->flags = 0;
+}
+
/*
* A ccb is put onto the free list.
*/
void
-bt_free_ccb(sc, ccb, flags)
+bt_free_ccb(sc, ccb)
struct bt_softc *sc;
struct bt_ccb *ccb;
- int flags;
{
int s;
s = splbio();
- ccb->flags = CCB_FREE;
+ bt_reset_ccb(sc, ccb);
TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
/*
@@ -782,7 +555,7 @@ bt_free_ccb(sc, ccb, flags)
splx(s);
}
-static inline void
+integrate void
bt_init_ccb(sc, ccb)
struct bt_softc *sc;
struct bt_ccb *ccb;
@@ -798,14 +571,7 @@ bt_init_ccb(sc, ccb)
hashnum = CCB_HASH(ccb->hashkey);
ccb->nexthash = sc->sc_ccbhash[hashnum];
sc->sc_ccbhash[hashnum] = ccb;
-}
-
-static inline void
-bt_reset_ccb(sc, ccb)
- struct bt_softc *sc;
- struct bt_ccb *ccb;
-{
-
+ bt_reset_ccb(sc, ccb);
}
/*
@@ -835,15 +601,15 @@ bt_get_ccb(sc, flags)
break;
}
if (sc->sc_numccbs < BT_CCB_MAX) {
- if (ccb = (struct bt_ccb *) malloc(sizeof(struct bt_ccb),
- M_TEMP, M_NOWAIT)) {
- bt_init_ccb(sc, ccb);
- sc->sc_numccbs++;
- } else {
+ ccb = (struct bt_ccb *) malloc(sizeof(struct bt_ccb),
+ M_TEMP, M_NOWAIT);
+ if (!ccb) {
printf("%s: can't malloc ccb\n",
sc->sc_dev.dv_xname);
goto out;
}
+ bt_init_ccb(sc, ccb);
+ sc->sc_numccbs++;
break;
}
if ((flags & SCSI_NOSLEEP) != 0)
@@ -851,8 +617,7 @@ bt_get_ccb(sc, flags)
tsleep(&sc->sc_free_ccb, PRIBIO, "btccb", 0);
}
- bt_reset_ccb(sc, ccb);
- ccb->flags = CCB_ACTIVE;
+ ccb->flags |= CCB_ALLOC;
out:
splx(s);
@@ -860,8 +625,7 @@ out:
}
/*
- * given a physical address, find the ccb that
- * it corresponds to:
+ * Given a physical address, find the ccb that it corresponds to.
*/
struct bt_ccb *
bt_ccb_phys_kv(sc, ccb_phys)
@@ -880,55 +644,97 @@ bt_ccb_phys_kv(sc, ccb_phys)
}
/*
- * Get a mbo and send the ccb.
+ * Queue a CCB to be sent to the controller, and send it if possible.
+ */
+void
+bt_queue_ccb(sc, ccb)
+ struct bt_softc *sc;
+ struct bt_ccb *ccb;
+{
+
+ TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
+ bt_start_ccbs(sc);
+}
+
+/*
+ * Garbage collect mailboxes that are no longer in use.
*/
-struct bt_mbx_out *
-bt_send_mbo(sc, cmd, ccb)
+void
+bt_collect_mbo(sc)
struct bt_softc *sc;
- int cmd;
+{
+ struct bt_mbx_out *wmbo; /* Mail Box Out pointer */
struct bt_ccb *ccb;
+
+ wmbo = wmbx->cmbo;
+
+ while (sc->sc_mbofull > 0) {
+ if (wmbo->cmd != BT_MBO_FREE)
+ break;
+
+#ifdef BTDIAG
+ ccb = bt_ccb_phys_kv(sc, phystol(wmbo->ccb_addr));
+ ccb->flags &= ~CCB_SENDING;
+#endif
+
+ --sc->sc_mbofull;
+ bt_nextmbx(wmbo, wmbx, mbo);
+ }
+
+ wmbx->cmbo = wmbo;
+}
+
+/*
+ * Send as many CCBs as we have empty mailboxes for.
+ */
+void
+bt_start_ccbs(sc)
+ struct bt_softc *sc;
{
int iobase = sc->sc_iobase;
struct bt_mbx_out *wmbo; /* Mail Box Out pointer */
- struct bt_mbx *wmbx; /* Mail Box pointer specified unit */
+ struct bt_ccb *ccb;
int i;
- /* Get the target out mail box pointer and increment. */
- wmbx = &sc->sc_mbx;
wmbo = wmbx->tmbo;
- bt_nextmbx(wmbx->tmbo, wmbx, mbo);
- /*
- * 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) {
- /* Enable mbo available interrupt. */
- outb(iobase + BT_CMD_DATA_PORT, BT_MBO_INTR_EN);
- for (i = 100000; i; i--) {
- if (!(inb(iobase + BT_CTRL_STAT_PORT) & BT_CDF))
+ while (ccb = sc->sc_waiting_ccb.tqh_first) {
+ if (sc->sc_mbofull >= BT_MBX_SIZE) {
+ bt_collect_mbo(sc);
+ if (sc->sc_mbofull >= BT_MBX_SIZE) {
+ struct bt_toggle toggle;
+
+ toggle.cmd.opcode = BT_MBO_INTR_EN;
+ toggle.cmd.enable = 1;
+ bt_cmd(iobase, sc, sizeof(toggle.cmd),
+ (u_char *)&toggle.cmd, 0, (u_char *)0);
break;
- delay(10);
- }
- if (!i) {
- printf("%s: bt_send_mbo, cmd/data port full\n",
- sc->sc_dev.dv_xname);
- outb(iobase + BT_CTRL_STAT_PORT, BT_SRST);
- return NULL;
+ }
}
- outb(iobase + BT_CMD_DATA_PORT, 0x01); /* Enable */
- tsleep(wmbx, PRIBIO, "btsnd", 0);/*XXX can't do this */
- }
- /* Link ccb to mbo. */
- wmbo->ccb_addr = KVTOPHYS(ccb);
- ccb->mbx = wmbo;
- wmbo->cmd = cmd;
+ TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
+#ifdef BTDIAG
+ ccb->flags |= CCB_SENDING;
+#endif
+
+ /* Link ccb to mbo. */
+ ltophys(KVTOPHYS(ccb), wmbo->ccb_addr);
+ if (ccb->flags & CCB_ABORT)
+ wmbo->cmd = BT_MBO_ABORT;
+ else
+ wmbo->cmd = BT_MBO_START;
+
+ /* Tell the card to poll immediately. */
+ outb(iobase + BT_CMD_PORT, BT_START_SCSI);
+
+ if ((ccb->xs->flags & SCSI_POLL) == 0)
+ timeout(bt_timeout, ccb, (ccb->timeout * hz) / 1000);
- /* Send it! */
- outb(iobase + BT_CMD_DATA_PORT, BT_START_SCSI);
+ ++sc->sc_mbofull;
+ bt_nextmbx(wmbo, wmbx, mbo);
+ }
- return wmbo;
+ wmbx->tmbo = wmbo;
}
/*
@@ -949,16 +755,21 @@ bt_done(sc, ccb)
* Otherwise, put the results of the operation
* into the xfer and call whoever started it
*/
- if ((xs->flags & INUSE) == 0) {
- printf("%s: exiting but not in use!\n", sc->sc_dev.dv_xname);
+#ifdef BTDIAG
+ if (ccb->flags & CCB_SENDING) {
+ printf("%s: exiting ccb still in transit!\n", sc->sc_dev.dv_xname);
Debugger();
+ return;
+ }
+#endif
+ if ((ccb->flags & CCB_ALLOC) == 0) {
+ printf("%s: exiting ccb not allocated!\n", sc->sc_dev.dv_xname);
+ Debugger();
+ return;
}
if (xs->error == XS_NOERROR) {
if (ccb->host_stat != BT_OK) {
switch (ccb->host_stat) {
- case BT_ABORTED:
- xs->error = XS_DRIVER_STUFFUP;
- break;
case BT_SEL_TIMEOUT: /* No response */
xs->error = XS_SELTIMEOUT;
break;
@@ -966,6 +777,7 @@ bt_done(sc, ccb)
printf("%s: host_stat %x\n",
sc->sc_dev.dv_xname, ccb->host_stat);
xs->error = XS_DRIVER_STUFFUP;
+ break;
}
} else if (ccb->target_stat != SCSI_OK) {
switch (ccb->target_stat) {
@@ -982,12 +794,13 @@ bt_done(sc, ccb)
printf("%s: target_stat %x\n",
sc->sc_dev.dv_xname, ccb->target_stat);
xs->error = XS_DRIVER_STUFFUP;
+ break;
}
} else
xs->resid = 0;
}
+ bt_free_ccb(sc, ccb);
xs->flags |= ITSDONE;
- bt_free_ccb(sc, ccb, xs->flags);
scsi_done(xs);
}
@@ -1000,10 +813,10 @@ bt_find(ia, sc)
struct bt_softc *sc;
{
int iobase = ia->ia_iobase;
- u_char ad[4];
- volatile int i, sts;
- struct bt_extended_inquire info;
- struct bt_config conf;
+ int i;
+ u_char sts;
+ struct bt_extended_inquire inquire;
+ struct bt_config config;
int irq, drq;
/*
@@ -1011,18 +824,20 @@ bt_find(ia, sc)
* that it's not there.. good for the probe
*/
- outb(iobase + BT_CTRL_STAT_PORT, BT_HRST | BT_SRST);
+ outb(iobase + BT_CTRL_PORT, BT_CTRL_HRST | BT_CTRL_SRST);
+ delay(100);
for (i = BT_RESET_TIMEOUT; i; i--) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- if (sts == (BT_IDLE | BT_INIT))
+ sts = inb(iobase + BT_STAT_PORT);
+ if (sts == (BT_STAT_IDLE | BT_STAT_INIT))
break;
delay(1000);
}
if (!i) {
-#ifdef UTEST
- printf("bt_find: No answer from bt742a board\n");
-#endif
+#ifdef BTDEBUG
+ if (bt_debug)
+ printf("bt_find: No answer from buslogic board\n");
+#endif /* BTDEBUG */
return 1;
}
@@ -1030,9 +845,11 @@ bt_find(ia, sc)
* Check that we actually know how to use this board.
*/
delay(1000);
- bt_cmd(iobase, sc, 1, sizeof(info), 0, (u_char *)&info,
- BT_INQUIRE_EXTENDED, sizeof(info));
- switch (info.bus_type) {
+ inquire.cmd.opcode = BT_INQUIRE_EXTENDED;
+ inquire.cmd.len = sizeof(inquire.reply);
+ bt_cmd(iobase, sc, sizeof(inquire.cmd), (u_char *)&inquire.cmd,
+ sizeof(inquire.reply), (u_char *)&inquire.reply);
+ switch (inquire.reply.bus_type) {
case BT_BUS_TYPE_24BIT:
/* XXXX How do we avoid conflicting with the aha1542 probe? */
case BT_BUS_TYPE_32BIT:
@@ -1041,7 +858,7 @@ bt_find(ia, sc)
/* We don't grok MicroChannel (yet). */
return 1;
default:
- printf("bt_find: illegal bus type %c\n", info.bus_type);
+ printf("bt_find: illegal bus type %c\n", inquire.reply.bus_type);
return 1;
}
@@ -1050,8 +867,10 @@ bt_find(ia, sc)
* jumpers and save int level
*/
delay(1000);
- bt_cmd(iobase, sc, 0, sizeof(conf), 0, (u_char *)&conf, BT_CONF_GET);
- switch (conf.chan) {
+ config.cmd.opcode = BT_INQUIRE_CONFIG;
+ bt_cmd(iobase, sc, sizeof(config.cmd), (u_char *)&config.cmd,
+ sizeof(config.reply), (u_char *)&config.reply);
+ switch (config.reply.chan) {
case EISADMA:
drq = DRQUNK;
break;
@@ -1068,11 +887,11 @@ bt_find(ia, sc)
drq = 7;
break;
default:
- printf("bt_find: illegal dma setting %x\n", conf.chan);
+ printf("bt_find: illegal drq setting %x\n", config.reply.chan);
return 1;
}
- switch (conf.intr) {
+ switch (config.reply.intr) {
case INT9:
irq = 9;
break;
@@ -1092,13 +911,13 @@ bt_find(ia, sc)
irq = 15;
break;
default:
- printf("bt_find: illegal int setting %x\n", conf.intr);
+ printf("bt_find: illegal irq setting %x\n", config.reply.intr);
return 1;
}
if (sc != NULL) {
/* who are we on the scsi bus? */
- sc->sc_scsi_dev = conf.scsi_dev;
+ sc->sc_scsi_dev = config.reply.scsi_dev;
sc->sc_iobase = iobase;
sc->sc_irq = irq;
@@ -1125,29 +944,74 @@ bt_init(sc)
struct bt_softc *sc;
{
int iobase = sc->sc_iobase;
- u_char ad[4];
+ struct bt_devices devices;
+ struct bt_setup setup;
+ struct bt_mailbox mailbox;
+ struct bt_period period;
int i;
- /*
- * Initialize mail box
- */
- *((physaddr *)ad) = KVTOPHYS(&sc->sc_mbx);
+ /* Enable round-robin scheme - appeared at firmware rev. 3.31. */
+ if (strcmp(sc->sc_firmware, "3.31") >= 0) {
+ struct bt_toggle toggle;
- bt_cmd(iobase, sc, 5, 0, 0, 0, BT_MBX_INIT_EXTENDED, BT_MBX_SIZE,
- ad[0], ad[1], ad[2], ad[3]);
+ toggle.cmd.opcode = BT_ROUND_ROBIN;
+ toggle.cmd.enable = 1;
+ bt_cmd(iobase, sc, sizeof(toggle.cmd), (u_char *)&toggle.cmd,
+ 0, (u_char *)0);
+ }
- for (i = 0; i < BT_MBX_SIZE; i++) {
- sc->sc_mbx.mbo[i].cmd = BT_MBO_FREE;
- sc->sc_mbx.mbi[i].stat = BT_MBI_FREE;
+ /* Inquire Installed Devices (to force synchronous negotiation). */
+ devices.cmd.opcode = BT_INQUIRE_DEVICES;
+ bt_cmd(iobase, sc, sizeof(devices.cmd), (u_char *)&devices.cmd,
+ sizeof(devices.reply), (u_char *)&devices.reply);
+
+ /* Obtain setup information from. */
+ setup.cmd.opcode = BT_INQUIRE_SETUP;
+ setup.cmd.len = sizeof(setup.reply);
+ bt_cmd(iobase, sc, sizeof(setup.cmd), (u_char *)&setup.cmd,
+ sizeof(setup.reply), (u_char *)&setup.reply);
+
+ printf("%s: %s, %s\n",
+ sc->sc_dev.dv_xname,
+ setup.reply.sync_neg ? "sync" : "async",
+ setup.reply.parity ? "parity" : "no parity");
+
+ for (i = 0; i < 8; i++)
+ period.reply.period[i] = setup.reply.sync[i].period * 5 + 20;
+
+ if (sc->sc_firmware[0] >= '3') {
+ period.cmd.opcode = BT_INQUIRE_PERIOD;
+ period.cmd.len = sizeof(period.reply);
+ bt_cmd(iobase, sc, sizeof(period.cmd), (u_char *)&period.cmd,
+ sizeof(period.reply), (u_char *)&period.reply);
+ }
+
+ for (i = 0; i < 8; i++) {
+ if (!setup.reply.sync[i].valid ||
+ (!setup.reply.sync[i].offset && !setup.reply.sync[i].period))
+ continue;
+ printf("%s targ %d: sync, offset %d, period %dnsec\n",
+ sc->sc_dev.dv_xname, i,
+ setup.reply.sync[i].offset, period.reply.period[i] * 10);
}
/*
* Set up initial mail box for round-robin operation.
*/
- sc->sc_mbx.tmbo = &sc->sc_mbx.mbo[0];
- sc->sc_mbx.tmbi = &sc->sc_mbx.mbi[0];
-
- bt_inquire_setup_information(sc);
+ for (i = 0; i < BT_MBX_SIZE; i++) {
+ wmbx->mbo[i].cmd = BT_MBO_FREE;
+ wmbx->mbi[i].stat = BT_MBI_FREE;
+ }
+ wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
+ wmbx->tmbi = &wmbx->mbi[0];
+ sc->sc_mbofull = 0;
+
+ /* Initialize mail box. */
+ mailbox.cmd.opcode = BT_MBX_INIT_EXTENDED;
+ mailbox.cmd.nmbx = BT_MBX_SIZE;
+ ltophys(KVTOPHYS(wmbx), mailbox.cmd.addr);
+ bt_cmd(iobase, sc, sizeof(mailbox.cmd), (u_char *)&mailbox.cmd,
+ 0, (u_char *)0);
}
void
@@ -1155,72 +1019,61 @@ bt_inquire_setup_information(sc)
struct bt_softc *sc;
{
int iobase = sc->sc_iobase;
- struct bt_boardID bID;
- struct bt_board_info binfo;
- char dummy[8], sub_ver[3];
- struct bt_setup setup;
- int i, ver;
+ struct bt_model model;
+ struct bt_revision revision;
+ struct bt_digit digit;
+ char dummy[8];
+ char *p;
/*
- * Get and print board hardware information.
+ * Get the firmware revision.
*/
- bt_cmd(iobase, sc, 1, sizeof(binfo), 0, (u_char *)&binfo,
- BT_GET_BOARD_INFO, sizeof(binfo));
- printf(": Bt%c%c%c", binfo.id[0], binfo.id[1], binfo.id[2]);
- if (binfo.id[3] != ' ')
- printf("%c", binfo.id[3]);
- if (binfo.version[0] != ' ')
- printf("%c%s", binfo.version[0], binfo.version[1]);
- printf("\n");
-
- /*
- * Inquire Board ID to Bt742 for board type and firmware version.
- */
- bt_cmd(iobase, sc, 0, sizeof(bID), 0, (u_char *)&bID, BT_INQUIRE);
- ver = (bID.firm_revision - '0') * 10 + (bID.firm_version - '0');
+ p = sc->sc_firmware;
+ revision.cmd.opcode = BT_INQUIRE_REVISION;
+ bt_cmd(iobase, sc, sizeof(revision.cmd), (u_char *)&revision.cmd,
+ sizeof(revision.reply), (u_char *)&revision.reply);
+ *p++ = revision.reply.firm_revision;
+ *p++ = '.';
+ *p++ = revision.reply.firm_version;
+ digit.cmd.opcode = BT_INQUIRE_REVISION_3;
+ bt_cmd(iobase, sc, sizeof(digit.cmd), (u_char *)&digit.cmd,
+ sizeof(digit.reply), (u_char *)&digit.reply);
+ *p++ = digit.reply.digit;
+ if (revision.reply.firm_revision >= '3' ||
+ (revision.reply.firm_revision == '3' && revision.reply.firm_version >= '3')) {
+ digit.cmd.opcode = BT_INQUIRE_REVISION_4;
+ bt_cmd(iobase, sc, sizeof(digit.cmd), (u_char *)&digit.cmd,
+ sizeof(digit.reply), (u_char *)&digit.reply);
+ *p++ = digit.reply.digit;
+ }
+ while (p > sc->sc_firmware && (p[-1] == ' ' || p[-1] == '\0'))
+ p--;
+ *p = '\0';
/*
- * Get the rest of the firmware version. Firmware revisions
- * before 3.3 apparently don't accept the BT_INQUIRE_REV_FOURTH
- * command.
+ * Get the model number.
*/
- i = 0;
- bt_cmd(iobase, sc, 0, 1, 0, &sub_ver[i++], BT_INQUIRE_REV_THIRD);
- if (ver >= 33)
- bt_cmd(iobase, sc, 0, 1, 0, &sub_ver[i++],
- BT_INQUIRE_REV_FOURTH);
- if (sub_ver[i - 1] == ' ')
- i--;
- sub_ver[i] = '\0';
-
- printf("%s: firmware version %c.%c%s, ", sc->sc_dev.dv_xname,
- bID.firm_revision, bID.firm_version, sub_ver);
-
- /* Enable round-robin scheme - appeared at firmware rev. 3.31 */
- if (ver > 33 || (ver == 33 && sub_ver[0] >= 1)) {
- bt_cmd(iobase, sc, 1, 0, 0, 0, BT_ROUND_ROBIN, BT_ENABLE);
- }
-
- /* Inquire Installed Devices (to force synchronous negotiation) */
- bt_cmd(iobase, sc, 0, sizeof(dummy), 10, dummy, BT_DEV_GET);
-
- /* Obtain setup information from Bt742. */
- bt_cmd(iobase, sc, 1, sizeof(setup), 0, (u_char *)&setup, BT_SETUP_GET,
- sizeof(setup));
-
- printf("%s, %s, %d mailboxes",
- setup.sync_neg ? "sync" : "async",
- setup.parity ? "parity" : "no parity",
- setup.num_mbx);
-
- for (i = 0; i < 8; i++) {
- if (!setup.sync[i].valid ||
- (!setup.sync[i].offset && !setup.sync[i].period))
- continue;
- printf("\n%s targ %d: sync, offset %d, period %dnsec",
- sc->sc_dev.dv_xname, i,
- setup.sync[i].offset, setup.sync[i].period * 50 + 200);
- }
+ if (revision.reply.firm_revision >= '3') {
+ p = sc->sc_model;
+ model.cmd.opcode = BT_INQUIRE_MODEL;
+ model.cmd.len = sizeof(model.reply);
+ bt_cmd(iobase, sc, sizeof(model.cmd), (u_char *)&model.cmd,
+ sizeof(model.reply), (u_char *)&model.reply);
+ *p++ = model.reply.id[0];
+ *p++ = model.reply.id[1];
+ *p++ = model.reply.id[2];
+ *p++ = model.reply.id[3];
+ while (p > sc->sc_model && (p[-1] == ' ' || p[-1] == '\0'))
+ p--;
+ *p++ = model.reply.version[0];
+ *p++ = model.reply.version[1];
+ while (p > sc->sc_model && (p[-1] == ' ' || p[-1] == '\0'))
+ p--;
+ *p = '\0';
+ } else
+ strcpy(sc->sc_model, "542B");
+
+ printf(": model BT-%s, firmware %s\n", sc->sc_model, sc->sc_firmware);
}
void
@@ -1246,11 +1099,9 @@ bt_scsi_cmd(xs)
struct bt_ccb *ccb;
struct bt_scat_gath *sg;
int seg; /* scatter gather seg being worked on */
- int thiskv;
- physaddr thisphys, nextphys;
+ u_long thiskv, thisphys, nextphys;
int bytes_this_seg, bytes_this_page, datalen, flags;
struct iovec *iovp;
- struct bt_mbx_out *mbo;
int s;
SC_DEBUG(sc_link, SDEV_DB2, ("bt_scsi_cmd\n"));
@@ -1260,39 +1111,28 @@ bt_scsi_cmd(xs)
* then we can't allow it to sleep
*/
flags = xs->flags;
- if ((flags & (ITSDONE|INUSE)) != INUSE) {
- printf("%s: done or not in use?\n", sc->sc_dev.dv_xname);
- xs->flags &= ~ITSDONE;
- xs->flags |= INUSE;
- }
if ((ccb = bt_get_ccb(sc, flags)) == NULL) {
xs->error = XS_DRIVER_STUFFUP;
return TRY_AGAIN_LATER;
}
ccb->xs = xs;
+ ccb->timeout = xs->timeout;
/*
* Put all the arguments for the xfer in the ccb
*/
if (flags & SCSI_RESET) {
ccb->opcode = BT_RESET_CCB;
+ ccb->scsi_cmd_length = 0;
} else {
/* can't use S/G if zero length */
ccb->opcode = (xs->datalen ? BT_INIT_SCAT_GATH_CCB
: BT_INITIATOR_CCB);
+ bcopy(xs->cmd, &ccb->scsi_cmd,
+ ccb->scsi_cmd_length = xs->cmdlen);
}
- ccb->data_out = 0;
- ccb->data_in = 0;
- ccb->target = sc_link->target;
- ccb->lun = sc_link->lun;
- ccb->scsi_cmd_length = xs->cmdlen;
- ccb->sense_ptr = KVTOPHYS(&ccb->scsi_sense);
- ccb->req_sense_length = sizeof(ccb->scsi_sense);
- ccb->host_stat = 0x00;
- ccb->target_stat = 0x00;
- if (xs->datalen && (flags & SCSI_RESET) == 0) {
- ccb->data_addr = KVTOPHYS(ccb->scat_gath);
+ if (xs->datalen) {
sg = ccb->scat_gath;
seg = 0;
#ifdef TFS
@@ -1301,8 +1141,8 @@ bt_scsi_cmd(xs)
datalen = ((struct uio *)xs->data)->uio_iovcnt;
xs->datalen = 0;
while (datalen && seg < BT_NSEG) {
- sg->seg_addr = (physaddr)iovp->iov_base;
- sg->seg_len = iovp->iov_len;
+ ltophys(iovp->iov_base, sg->seg_addr);
+ ltophys(iovp->iov_len, sg->seg_len);
xs->datalen += iovp->iov_len;
SC_DEBUGN(sc_link, SDEV_DB4, ("(0x%x@0x%x)",
iovp->iov_len, iovp->iov_base));
@@ -1315,19 +1155,20 @@ bt_scsi_cmd(xs)
#endif /* TFS */
{
/*
- * Set up the scatter gather block
+ * Set up the scatter-gather block.
*/
SC_DEBUG(sc_link, SDEV_DB4,
("%d @0x%x:- ", xs->datalen, xs->data));
+
datalen = xs->datalen;
- thiskv = (int) xs->data;
+ 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;
+ ltophys(thisphys, sg->seg_addr);
SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys));
@@ -1358,13 +1199,12 @@ bt_scsi_cmd(xs)
*/
SC_DEBUGN(sc_link, SDEV_DB4,
("(0x%x)", bytes_this_seg));
- sg->seg_len = bytes_this_seg;
+ ltophys(bytes_this_seg, sg->seg_len);
sg++;
seg++;
}
}
/* end of iov/kv decision */
- ccb->data_length = seg * sizeof(struct bt_scat_gath);
SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
if (datalen) {
/*
@@ -1372,53 +1212,51 @@ bt_scsi_cmd(xs)
*/
printf("%s: bt_scsi_cmd, more than %d dma segs\n",
sc->sc_dev.dv_xname, BT_NSEG);
- xs->error = XS_DRIVER_STUFFUP;
- bt_free_ccb(sc, ccb, flags);
- return COMPLETE;
+ goto bad;
}
+ ltophys(KVTOPHYS(ccb->scat_gath), ccb->data_addr);
+ ltophys(seg * sizeof(struct bt_scat_gath), ccb->data_length);
} else { /* No data xfer, use non S/G values */
- ccb->data_addr = (physaddr)0;
- ccb->data_length = 0;
+ ltophys(0, ccb->data_addr);
+ ltophys(0, ccb->data_length);
}
- ccb->link_id = 0;
- ccb->link_addr = (physaddr)0;
- /*
- * Put the scsi command in the ccb and start it
- */
- if ((flags & SCSI_RESET) == 0)
- bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmd_length);
+ ccb->data_out = 0;
+ ccb->data_in = 0;
+ ccb->target = sc_link->target;
+ ccb->lun = sc_link->lun;
+ ltophys(KVTOPHYS(&ccb->scsi_sense), ccb->sense_ptr);
+ ccb->req_sense_length = sizeof(ccb->scsi_sense);
+ ccb->host_stat = 0x00;
+ ccb->target_stat = 0x00;
+ ccb->link_id = 0;
+ ltophys(0, ccb->link_addr);
s = splbio();
-
- if (bt_send_mbo(sc, BT_MBO_START, ccb) == NULL) {
- splx(s);
- xs->error = XS_DRIVER_STUFFUP;
- bt_free_ccb(sc, ccb, flags);
- return TRY_AGAIN_LATER;
- }
+ bt_queue_ccb(sc, ccb);
+ splx(s);
/*
* Usually return SUCCESSFULLY QUEUED
*/
SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
- if ((flags & SCSI_POLL) == 0) {
- timeout(bt_timeout, ccb, (xs->timeout * hz) / 1000);
- splx(s);
+ if ((flags & SCSI_POLL) == 0)
return SUCCESSFULLY_QUEUED;
- }
-
- splx(s);
/*
* If we can't use interrupts, poll on completion
*/
- if (bt_poll(sc, xs, xs->timeout)) {
+ if (bt_poll(sc, xs, ccb->timeout)) {
bt_timeout(ccb);
- if (bt_poll(sc, xs, 2000))
+ if (bt_poll(sc, xs, ccb->timeout))
bt_timeout(ccb);
}
return COMPLETE;
+
+bad:
+ xs->error = XS_DRIVER_STUFFUP;
+ bt_free_ccb(sc, ccb);
+ return COMPLETE;
}
/*
@@ -1438,7 +1276,7 @@ bt_poll(sc, xs, count)
* If we had interrupts enabled, would we
* have got an interrupt?
*/
- if (inb(iobase + BT_INTR_PORT) & BT_ANY_INTR)
+ if (inb(iobase + BT_INTR_PORT) & BT_INTR_ANYINTR)
btintr(sc);
if (xs->flags & ITSDONE)
return 0;
@@ -1463,66 +1301,34 @@ bt_timeout(arg)
s = splbio();
+#ifdef BTDIAG
/*
* If the ccb's mbx is not free, then the board has gone Far East?
*/
- if (bt_ccb_phys_kv(sc, ccb->mbx->ccb_addr) == ccb &&
- ccb->mbx->cmd != BT_MBO_FREE) {
+ bt_collect_mbo(sc);
+ if (ccb->flags & CCB_SENDING) {
printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
Debugger();
}
+#endif
/*
* If it has been through before, then
* a previous abort has failed, don't
* try abort again
*/
- if (ccb->flags == CCB_ABORTED) {
+ if (ccb->flags & CCB_ABORT) {
/* abort timed out */
printf(" AGAIN\n");
- ccb->xs->retries = 0;
- bt_done(sc, ccb);
+ /* XXX Must reset! */
} else {
/* abort the operation that has timed out */
printf("\n");
ccb->xs->error = XS_TIMEOUT;
- ccb->flags = CCB_ABORTED;
- bt_send_mbo(sc, BT_MBO_ABORT, ccb);
- /* 2 secs for the abort */
- if ((xs->flags & SCSI_POLL) == 0)
- timeout(bt_timeout, ccb, 2 * hz);
+ ccb->timeout = BT_ABORT_TIMEOUT;
+ ccb->flags |= CCB_ABORT;
+ bt_queue_ccb(sc, ccb);
}
splx(s);
}
-
-#ifdef UTEST
-void
-bt_print_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);
- printf(" datlen:%d hstat:%x tstat:%x flags:%x\n",
- ccb->data_length, ccb->host_stat, ccb->target_stat, ccb->flags);
-}
-
-void
-bt_print_active_ccbs(sc)
- struct bt_softc *sc;
-{
- struct bt_ccb *ccb;
- int i = 0;
-
- while (i < CCB_HASH_SIZE) {
- ccb = sc->sc_ccbhash[i];
- while (ccb) {
- if (ccb->flags != CCB_FREE)
- bt_print_ccb(ccb);
- ccb = ccb->nexthash;
- }
- i++;
- }
-}
-#endif /*UTEST */
diff --git a/sys/dev/isa/bt742a.c b/sys/dev/isa/bt742a.c
deleted file mode 100644
index 13798720e74..00000000000
--- a/sys/dev/isa/bt742a.c
+++ /dev/null
@@ -1,1528 +0,0 @@
-/* $OpenBSD: bt742a.c,v 1.7 1996/04/18 23:47:31 niklas Exp $ */
-/* $NetBSD: bt742a.c,v 1.55 1996/03/16 05:33:28 cgd Exp $ */
-
-/*
- * Copyright (c) 1994 Charles Hannum. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Charles Hannum.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Originally written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems for use under the MACH(2.5) operating system.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- */
-
-/*
- * bt742a SCSI driver
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/errno.h>
-#include <sys/ioctl.h>
-#include <sys/device.h>
-#include <sys/malloc.h>
-#include <sys/buf.h>
-#include <sys/proc.h>
-#include <sys/user.h>
-
-#include <machine/pio.h>
-
-#include <dev/isa/isavar.h>
-#include <dev/isa/isadmavar.h>
-#include <scsi/scsi_all.h>
-#include <scsi/scsiconf.h>
-
-/*
- * Note that stdarg.h and the ANSI style va_start macro is used for both
- * ANSI and traditional C compilers.
- */
-#include <machine/stdarg.h>
-
-#ifndef DDB
-#define Debugger() panic("should call debugger here (bt742a.c)")
-#endif /* ! DDB */
-
-typedef u_long physaddr;
-typedef u_long physlen;
-
-/*
- * I/O Port Interface
- */
-#define BT_CTRL_STAT_PORT 0x0 /* control & status */
-#define BT_CMD_DATA_PORT 0x1 /* cmds and datas */
-#define BT_INTR_PORT 0x2 /* Intr. stat */
-
-/*
- * BT_CTRL_STAT bits (write)
- */
-#define BT_HRST 0x80 /* Hardware reset */
-#define BT_SRST 0x40 /* Software reset */
-#define BT_IRST 0x20 /* Interrupt reset */
-#define BT_SCRST 0x10 /* SCSI bus reset */
-
-/*
- * BT_CTRL_STAT bits (read)
- */
-#define BT_STST 0x80 /* Self test in Progress */
-#define BT_DIAGF 0x40 /* Diagnostic Failure */
-#define BT_INIT 0x20 /* Mbx Init required */
-#define BT_IDLE 0x10 /* Host Adapter Idle */
-#define BT_CDF 0x08 /* cmd/data out port full */
-#define BT_DF 0x04 /* Data in port full */
-#define BT_INVDCMD 0x01 /* Invalid command */
-
-/*
- * BT_CMD_DATA bits (write)
- */
-#define BT_NOP 0x00 /* No operation */
-#define BT_MBX_INIT 0x01 /* Mbx initialization */
-#define BT_START_SCSI 0x02 /* start scsi command */
-#define BT_START_BIOS 0x03 /* start bios command */
-#define BT_INQUIRE 0x04 /* Adapter Inquiry */
-#define BT_MBO_INTR_EN 0x05 /* Enable MBO available interrupt */
-#define BT_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
-#define BT_BUS_ON_TIME_SET 0x07 /* set bus-on time */
-#define BT_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
-#define BT_SPEED_SET 0x09 /* set transfer speed */
-#define BT_DEV_GET 0x0a /* return installed devices */
-#define BT_CONF_GET 0x0b /* return configuration data */
-#define BT_TARGET_EN 0x0c /* enable target mode */
-#define BT_SETUP_GET 0x0d /* return setup data */
-#define BT_WRITE_CH2 0x1a /* write channel 2 buffer */
-#define BT_READ_CH2 0x1b /* read channel 2 buffer */
-#define BT_WRITE_FIFO 0x1c /* write fifo buffer */
-#define BT_READ_FIFO 0x1d /* read fifo buffer */
-#define BT_ECHO 0x1e /* Echo command data */
-#define BT_MBX_INIT_EXTENDED 0x81 /* Mbx initialization */
-#define BT_INQUIRE_REV_THIRD 0x84 /* Get 3rd firmware version byte */
-#define BT_INQUIRE_REV_FOURTH 0x85 /* Get 4th firmware version byte */
-#define BT_GET_BOARD_INFO 0x8b /* Get hardware ID and revision */
-#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_DISABLE 0x00 /* Parameter value for Disable */
-#define BT_ENABLE 0x01 /* Parameter value for Enable */
-
-/*
- * BT_INTR_PORT bits (read)
- */
-#define BT_ANY_INTR 0x80 /* Any interrupt */
-#define BT_SCRD 0x08 /* SCSI reset detected */
-#define BT_HACC 0x04 /* Command complete */
-#define BT_MBOA 0x02 /* MBX out empty */
-#define BT_MBIF 0x01 /* MBX in full */
-
-/*
- * Mail box defs etc.
- * these could be bigger but we need the bt_softc to fit on a single page..
- */
-#define BT_MBX_SIZE 32 /* mail box size (MAX 255 MBxs) */
- /* don't need that many really */
-#define BT_CCB_MAX 32 /* store up to 32 CCBs at one time */
-#define CCB_HASH_SIZE 32 /* hash table size for phystokv */
-#define CCB_HASH_SHIFT 9
-#define CCB_HASH(x) ((((long)(x))>>CCB_HASH_SHIFT) & (CCB_HASH_SIZE - 1))
-
-#define bt_nextmbx(wmb, mbx, mbio) \
- if ((wmb) == &(mbx)->mbio[BT_MBX_SIZE - 1]) \
- (wmb) = &(mbx)->mbio[0]; \
- else \
- (wmb)++;
-
-struct bt_mbx_out {
- physaddr ccb_addr;
- u_char dummy[3];
- u_char cmd;
-};
-
-struct bt_mbx_in {
- physaddr ccb_addr;
- u_char btstat;
- u_char sdstat;
- u_char dummy;
- u_char stat;
-};
-
-struct bt_mbx {
- struct bt_mbx_out mbo[BT_MBX_SIZE];
- struct bt_mbx_in mbi[BT_MBX_SIZE];
- struct bt_mbx_out *tmbo; /* Target Mail Box out */
- struct bt_mbx_in *tmbi; /* Target Mail Box in */
-};
-
-/*
- * mbo.cmd values
- */
-#define BT_MBO_FREE 0x0 /* MBO entry is free */
-#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 */
-
-#if defined(BIG_DMA)
-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 {
- physlen seg_len;
- physaddr seg_addr;
-};
-
-struct bt_ccb {
- u_char opcode;
- u_char:3, data_in:1, data_out:1,:3;
- u_char scsi_cmd_length;
- u_char req_sense_length;
- /*------------------------------------longword boundary */
- physlen data_length;
- /*------------------------------------longword boundary */
- physaddr data_addr;
- /*------------------------------------longword boundary */
- u_char dummy1[2];
- u_char host_stat;
- u_char target_stat;
- /*------------------------------------longword boundary */
- u_char target;
- u_char lun;
- struct scsi_generic scsi_cmd;
- u_char dummy2[1];
- u_char link_id;
- /*------------------------------------longword boundary */
- physaddr link_addr;
- /*------------------------------------longword boundary */
- physaddr sense_ptr;
-/*-----end of HW fields-----------------------longword boundary */
- struct scsi_sense_data scsi_sense;
- /*------------------------------------longword boundary */
- struct bt_scat_gath scat_gath[BT_NSEG];
- /*------------------------------------longword boundary */
- TAILQ_ENTRY(bt_ccb) chain;
- struct bt_ccb *nexthash;
- long hashkey;
- struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
- int flags;
-#define CCB_FREE 0
-#define CCB_ACTIVE 1
-#define CCB_ABORTED 2
- struct bt_mbx_out *mbx; /* pointer to mail box */
-};
-
-/*
- * opcode fields
- */
-#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_RESET_CCB 0x81 /* SCSI Bus reset */
-
-/*
- * bt_ccb.host_stat values
- */
-#define BT_OK 0x00 /* cmd ok */
-#define BT_LINK_OK 0x0a /* Link cmd ok */
-#define BT_LINK_IT 0x0b /* Link cmd ok + int */
-#define BT_SEL_TIMEOUT 0x11 /* Selection time out */
-#define BT_OVER_UNDER 0x12 /* Data over/under run */
-#define BT_BUS_FREE 0x13 /* Bus dropped at unexpected time */
-#define BT_INV_BUS 0x14 /* Invalid bus phase/sequence */
-#define BT_BAD_MBO 0x15 /* Incorrect MBO cmd */
-#define BT_BAD_CCB 0x16 /* Incorrect ccb opcode */
-#define BT_BAD_LINK 0x17 /* Not same values of LUN for links */
-#define BT_INV_TARGET 0x18 /* Invalid target direction */
-#define BT_CCB_DUP 0x19 /* Duplicate CCB received */
-#define BT_INV_CCB 0x1a /* Invalid CCB or segment list */
-#define BT_ABORTED 42 /* pseudo value from driver */
-
-struct bt_extended_inquire {
- u_char bus_type; /* Type of bus connected to */
-#define BT_BUS_TYPE_24BIT 'A' /* ISA bus */
-#define BT_BUS_TYPE_32BIT 'E' /* EISA/VLB/PCI bus */
-#define BT_BUS_TYPE_MCA 'M' /* MicroChannel bus */
- u_char bios_address; /* Address of adapter BIOS */
- u_short max_segment; /* ? */
-};
-
-struct bt_boardID {
- u_char board_type;
- u_char custom_feture;
- char firm_revision;
- u_char firm_version;
-};
-
-struct bt_board_info {
- u_char id[4]; /* i.e bt742a -> '7','4','2','A' */
- u_char version[2]; /* i.e Board Revision 'H' -> 'H', 0x00 */
-};
-
-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]; /*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;
-};
-
-struct bt_config {
- u_char chan;
- u_char intr;
- u_char scsi_dev:3;
- u_char :5;
-};
-
-#define INT9 0x01
-#define INT10 0x02
-#define INT11 0x04
-#define INT12 0x08
-#define INT14 0x20
-#define INT15 0x40
-
-#define EISADMA 0x00
-#define CHAN0 0x01
-#define CHAN5 0x20
-#define CHAN6 0x40
-#define CHAN7 0x80
-
-#define KVTOPHYS(x) vtophys(x)
-
-struct bt_softc {
- struct device sc_dev;
- struct isadev sc_id;
- void *sc_ih;
-
- int sc_iobase;
- int sc_irq, sc_drq;
-
- struct bt_mbx sc_mbx; /* all our mailboxes */
- struct bt_ccb *sc_ccbhash[CCB_HASH_SIZE];
- TAILQ_HEAD(, bt_ccb) sc_free_ccb;
- int sc_numccbs;
- int sc_scsi_dev; /* adapters scsi id */
- struct scsi_link sc_link; /* prototype for devs */
-};
-
-/***********debug values *************/
-#define BT_SHOWCCBS 0x01
-#define BT_SHOWINTS 0x02
-#define BT_SHOWCMDS 0x04
-#define BT_SHOWMISC 0x08
-int bt_debug = 0;
-
-int bt_cmd __P((int, struct bt_softc *, int, int, int, u_char *,
- unsigned, ...));
-int btintr __P((void *));
-void bt_free_ccb __P((struct bt_softc *, struct bt_ccb *, int));
-struct bt_ccb *bt_get_ccb __P((struct bt_softc *, int));
-struct bt_ccb *bt_ccb_phys_kv __P((struct bt_softc *, u_long));
-struct bt_mbx_out *bt_send_mbo __P((struct bt_softc *, int, struct bt_ccb *));
-void bt_done __P((struct bt_softc *, struct bt_ccb *));
-int bt_find __P((struct isa_attach_args *, struct bt_softc *));
-void bt_init __P((struct bt_softc *));
-void bt_inquire_setup_information __P((struct bt_softc *));
-void btminphys __P((struct buf *));
-int bt_scsi_cmd __P((struct scsi_xfer *));
-int bt_poll __P((struct bt_softc *, struct scsi_xfer *, int));
-void bt_timeout __P((void *arg));
-#ifdef UTEST
-void bt_print_ccb __P((struct bt_ccb *));
-void bt_print_active_ccbs __P((struct bt_softc *));
-#endif
-
-struct scsi_adapter bt_switch = {
- bt_scsi_cmd,
- btminphys,
- 0,
- 0,
-};
-
-/* 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 */
-};
-
-int btprobe __P((struct device *, void *, void *));
-void btattach __P((struct device *, struct device *, void *));
-int btprint __P((void *, char *));
-
-struct cfdriver btcd = {
- NULL, "bt", btprobe, btattach, DV_DULL, sizeof(struct bt_softc)
-};
-
-#define BT_RESET_TIMEOUT 1000
-
-/*
- * bt_cmd(iobase, sc, 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: variable number of 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
-#ifdef __STDC__
-bt_cmd(int iobase, struct bt_softc *sc, int icnt, int ocnt, int wait,
- u_char *retval, unsigned opcode, ...)
-#else
-bt_cmd(iobase, sc, icnt, ocnt, wait, retval, opcode, va_alist)
- int iobase;
- struct bt_softc *sc;
- int icnt, ocnt, wait;
- u_char *retval;
- unsigned opcode;
- va_dcl
-#endif
-{
- va_list ap;
- unsigned data;
- const char *name;
- u_char oc;
- register i;
- int sts;
-
- if (sc == NULL)
- name = sc->sc_dev.dv_xname;
- else
- name = "(probe)";
-
- /*
- * multiply the wait argument by a big constant
- * zero defaults to 1
- */
- if (wait)
- wait *= 100000;
- else
- 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(iobase + BT_CTRL_STAT_PORT);
- if (sts & BT_IDLE) {
- break;
- }
- delay(10);
- }
- if (!i) {
- printf("%s: bt_cmd, host not idle(0x%x)\n",
- name, sts);
- return ENXIO;
- }
- }
- /*
- * Now that it is idle, if we expect output, preflush the
- * queue feeding to us.
- */
- if (ocnt) {
- while ((inb(iobase + BT_CTRL_STAT_PORT)) & BT_DF)
- inb(iobase + BT_CMD_DATA_PORT);
- }
- /*
- * Output the command and the number of arguments given
- * for each byte, first check the port is empty.
- */
- va_start(ap, opcode);
- /* test icnt >= 0, to include the command in data sent */
- for (data = opcode; icnt >= 0; icnt--, data = va_arg(ap, u_char)) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- for (i = wait; i; i--) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- if (!(sts & BT_CDF))
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: bt_cmd, cmd/data port full\n", name);
- outb(iobase + BT_CTRL_STAT_PORT, BT_SRST);
- va_end(ap);
- return ENXIO;
- }
- outb(iobase + BT_CMD_DATA_PORT, data);
- }
- va_end(ap);
- /*
- * If we expect input, loop that many times, each time,
- * looking for the data register to have valid data
- */
- while (ocnt--) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- for (i = wait; i; i--) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- if (sts & BT_DF)
- break;
- delay(10);
- }
- if (!i) {
- printf("bt%d: bt_cmd, cmd/data port empty %d\n",
- name, ocnt);
- return ENXIO;
- }
- oc = inb(iobase + BT_CMD_DATA_PORT);
- if (retval)
- *retval++ = oc;
- }
- /*
- * Wait for the board to report a finised instruction
- */
- i = 100000; /* 1 sec? */
- while (--i) {
- sts = inb(iobase + BT_INTR_PORT);
- if (sts & BT_HACC)
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: bt_cmd, host not finished(0x%x)\n",
- name, sts);
- return ENXIO;
- }
- outb(iobase + BT_CTRL_STAT_PORT, BT_IRST);
- 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_device structure from
- * autoconf.c
- */
-int
-btprobe(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- struct bt_softc *sc = match;
- register struct isa_attach_args *ia = aux;
-
-#ifdef NEWCONFIG
- if (ia->ia_iobase == IOBASEUNK)
- return 0;
-#endif
-
- /*
- * Try initialise a unit at this location
- * sets up dma and bus speed, loads sc->sc_irq
- */
- if (bt_find(ia, NULL) != 0)
- return 0;
-
- ia->ia_msize = 0;
- ia->ia_iosize = 4;
- /* IRQ and DRQ set by bt_find() */
- return 1;
-}
-
-int
-btprint(aux, name)
- void *aux;
- char *name;
-{
- if (name != NULL)
- printf("%s: scsibus ", name);
- return UNCONF;
-}
-
-/*
- * Attach all the sub-devices we can find
- */
-void
-btattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
-{
- struct isa_attach_args *ia = aux;
- struct bt_softc *sc = (struct bt_softc *)self;
-
- if (bt_find(ia, sc) != 0)
- panic("btattach: bt_find of %s failed", self->dv_xname);
- sc->sc_iobase = ia->ia_iobase;
-
- if (sc->sc_drq != DRQUNK)
- isa_dmacascade(sc->sc_drq);
-
- bt_init(sc);
- TAILQ_INIT(&sc->sc_free_ccb);
-
- /*
- * fill in the prototype scsi_link.
- */
- sc->sc_link.adapter_softc = sc;
- sc->sc_link.adapter_target = sc->sc_scsi_dev;
- sc->sc_link.adapter = &bt_switch;
- sc->sc_link.device = &bt_dev;
- sc->sc_link.openings = 2;
-
- printf("\n");
-
-#ifdef NEWCONFIG
- isa_establish(&sc->sc_id, &sc->sc_dev);
-#endif
- sc->sc_ih = isa_intr_establish(sc->sc_irq, IST_EDGE, IPL_BIO, btintr,
- sc, sc->sc_dev.dv_xname);
-
- /*
- * ask the adapter what subunits are present
- */
- config_found(self, &sc->sc_link, btprint);
-}
-
-/*
- * Catch an interrupt from the adaptor
- */
-int
-btintr(arg)
- void *arg;
-{
- struct bt_softc *sc = arg;
- int iobase = sc->sc_iobase;
- struct bt_mbx_in *wmbi;
- struct bt_mbx *wmbx;
- struct bt_ccb *ccb;
- u_char stat;
- int i;
- int found = 0;
-
-#ifdef BTDEBUG
- printf("%s: btintr ", sc->sc_dev.dv_xname);
-#endif /* BTDEBUG */
-
- /*
- * First acknowlege the interrupt, Then if it's
- * not telling about a completed operation
- * just return.
- */
- stat = inb(iobase + BT_INTR_PORT);
- if ((stat & (BT_MBOA | BT_MBIF)) == 0) {
- outb(iobase + BT_CTRL_STAT_PORT, BT_IRST);
- return -1; /* XXX */
- }
-
- /* Mail box out empty? */
- if (stat & BT_MBOA) {
- /* Disable MBO available interrupt. */
- outb(iobase + BT_CMD_DATA_PORT, BT_MBO_INTR_EN);
- for (i = 100000; i; i--) {
- if (!(inb(iobase + BT_CTRL_STAT_PORT) & BT_CDF))
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: btintr, cmd/data port full\n",
- sc->sc_dev.dv_xname);
- outb(iobase + BT_CTRL_STAT_PORT, BT_SRST);
- return 1;
- }
- outb(iobase + BT_CMD_DATA_PORT, 0x00); /* Disable */
- wakeup(&sc->sc_mbx);
- }
-
- /* Mail box in full? */
- if ((stat & BT_MBIF) == 0)
- return 1;
- wmbx = &sc->sc_mbx;
- wmbi = wmbx->tmbi;
-AGAIN:
- while (wmbi->stat != BT_MBI_FREE) {
- ccb = bt_ccb_phys_kv(sc, wmbi->ccb_addr);
- if (!ccb) {
- wmbi->stat = BT_MBI_FREE;
- printf("%s: BAD CCB ADDR!\n", sc->sc_dev.dv_xname);
- continue;
- }
- found++;
- switch (wmbi->stat) {
- case BT_MBI_OK:
- case BT_MBI_ERROR:
- break;
-
- case BT_MBI_ABORT:
- ccb->host_stat = BT_ABORTED;
- break;
-
- case BT_MBI_UNKNOWN:
- ccb = 0;
- break;
-
- default:
- panic("Impossible mbxi status");
- }
-#ifdef BTDEBUG
- if (bt_debug && ccb) {
- u_char *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("stat %x for mbi addr = 0x%08x, ",
- wmbi->stat, wmbi);
- printf("ccb addr = 0x%x\n", ccb);
- }
-#endif /* BTDEBUG */
- wmbi->stat = BT_MBI_FREE;
- if (ccb) {
- untimeout(bt_timeout, ccb);
- bt_done(sc, ccb);
- }
- bt_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
- for (i = 0; i < BT_MBX_SIZE; i++) {
- if (wmbi->stat != BT_MBI_FREE) {
- found++;
- break;
- }
- bt_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
-#if 0
- printf("%s: mbi interrupt with no full mailboxes\n",
- sc->sc_dev.dv_xname);
-#endif
- } else {
- found = 0;
- goto AGAIN;
- }
- }
- wmbx->tmbi = wmbi;
- outb(iobase + BT_CTRL_STAT_PORT, BT_IRST);
- return 1;
-}
-
-/*
- * A ccb is put onto the free list.
- */
-void
-bt_free_ccb(sc, ccb, flags)
- struct bt_softc *sc;
- struct bt_ccb *ccb;
- int flags;
-{
- int s;
-
- s = splbio();
-
- ccb->flags = CCB_FREE;
- TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
-
- /*
- * If there were none, wake anybody waiting for one to come free,
- * starting with queued entries.
- */
- if (ccb->chain.tqe_next == 0)
- wakeup(&sc->sc_free_ccb);
-
- splx(s);
-}
-
-static inline void
-bt_init_ccb(sc, ccb)
- struct bt_softc *sc;
- struct bt_ccb *ccb;
-{
- int hashnum;
-
- bzero(ccb, sizeof(struct bt_ccb));
- /*
- * put in the phystokv hash table
- * Never gets taken out.
- */
- ccb->hashkey = KVTOPHYS(ccb);
- hashnum = CCB_HASH(ccb->hashkey);
- ccb->nexthash = sc->sc_ccbhash[hashnum];
- sc->sc_ccbhash[hashnum] = ccb;
-}
-
-static inline void
-bt_reset_ccb(sc, ccb)
- struct bt_softc *sc;
- struct bt_ccb *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(sc, flags)
- struct bt_softc *sc;
- int flags;
-{
- struct bt_ccb *ccb;
- int s;
-
- s = splbio();
-
- /*
- * If we can and have to, sleep waiting for one to come free
- * but only if we can't allocate a new one.
- */
- for (;;) {
- ccb = sc->sc_free_ccb.tqh_first;
- if (ccb) {
- TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);
- break;
- }
- if (sc->sc_numccbs < BT_CCB_MAX) {
- if (ccb = (struct bt_ccb *) malloc(sizeof(struct bt_ccb),
- M_TEMP, M_NOWAIT)) {
- bt_init_ccb(sc, ccb);
- sc->sc_numccbs++;
- } else {
- printf("%s: can't malloc ccb\n",
- sc->sc_dev.dv_xname);
- goto out;
- }
- break;
- }
- if ((flags & SCSI_NOSLEEP) != 0)
- goto out;
- tsleep(&sc->sc_free_ccb, PRIBIO, "btccb", 0);
- }
-
- bt_reset_ccb(sc, ccb);
- ccb->flags = CCB_ACTIVE;
-
-out:
- splx(s);
- return ccb;
-}
-
-/*
- * given a physical address, find the ccb that
- * it corresponds to:
- */
-struct bt_ccb *
-bt_ccb_phys_kv(sc, ccb_phys)
- struct bt_softc *sc;
- u_long ccb_phys;
-{
- int hashnum = CCB_HASH(ccb_phys);
- struct bt_ccb *ccb = sc->sc_ccbhash[hashnum];
-
- while (ccb) {
- if (ccb->hashkey == ccb_phys)
- break;
- ccb = ccb->nexthash;
- }
- return ccb;
-}
-
-/*
- * Get a mbo and send the ccb.
- */
-struct bt_mbx_out *
-bt_send_mbo(sc, cmd, ccb)
- struct bt_softc *sc;
- int cmd;
- struct bt_ccb *ccb;
-{
- int iobase = sc->sc_iobase;
- struct bt_mbx_out *wmbo; /* Mail Box Out pointer */
- struct bt_mbx *wmbx; /* Mail Box pointer specified unit */
- int i;
-
- /* Get the target out mail box pointer and increment. */
- wmbx = &sc->sc_mbx;
- wmbo = wmbx->tmbo;
- bt_nextmbx(wmbx->tmbo, wmbx, mbo);
-
- /*
- * 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) {
- /* Enable mbo available interrupt. */
- outb(iobase + BT_CMD_DATA_PORT, BT_MBO_INTR_EN);
- for (i = 100000; i; i--) {
- if (!(inb(iobase + BT_CTRL_STAT_PORT) & BT_CDF))
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: bt_send_mbo, cmd/data port full\n",
- sc->sc_dev.dv_xname);
- outb(iobase + BT_CTRL_STAT_PORT, BT_SRST);
- return NULL;
- }
- outb(iobase + BT_CMD_DATA_PORT, 0x01); /* Enable */
- tsleep(wmbx, PRIBIO, "btsnd", 0);/*XXX can't do this */
- }
-
- /* Link ccb to mbo. */
- wmbo->ccb_addr = KVTOPHYS(ccb);
- ccb->mbx = wmbo;
- wmbo->cmd = cmd;
-
- /* Send it! */
- outb(iobase + BT_CMD_DATA_PORT, BT_START_SCSI);
-
- 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
- */
-void
-bt_done(sc, ccb)
- struct bt_softc *sc;
- struct bt_ccb *ccb;
-{
- struct scsi_sense_data *s1, *s2;
- struct scsi_xfer *xs = ccb->xs;
-
- 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 ((xs->flags & INUSE) == 0) {
- printf("%s: exiting but not in use!\n", sc->sc_dev.dv_xname);
- Debugger();
- }
- if (xs->error == XS_NOERROR) {
- if (ccb->host_stat != BT_OK) {
- switch (ccb->host_stat) {
- case BT_ABORTED:
- xs->error = XS_DRIVER_STUFFUP;
- break;
- case BT_SEL_TIMEOUT: /* No response */
- xs->error = XS_SELTIMEOUT;
- break;
- default: /* Other scsi protocol messes */
- printf("%s: host_stat %x\n",
- sc->sc_dev.dv_xname, ccb->host_stat);
- xs->error = XS_DRIVER_STUFFUP;
- }
- } else if (ccb->target_stat != SCSI_OK) {
- switch (ccb->target_stat) {
- case SCSI_CHECK:
- s1 = &ccb->scsi_sense;
- s2 = &xs->sense;
- *s2 = *s1;
- xs->error = XS_SENSE;
- break;
- case SCSI_BUSY:
- xs->error = XS_BUSY;
- break;
- default:
- printf("%s: target_stat %x\n",
- sc->sc_dev.dv_xname, ccb->target_stat);
- xs->error = XS_DRIVER_STUFFUP;
- }
- } else
- xs->resid = 0;
- }
- xs->flags |= ITSDONE;
- bt_free_ccb(sc, ccb, xs->flags);
- scsi_done(xs);
-}
-
-/*
- * Find the board and find it's irq/drq
- */
-int
-bt_find(ia, sc)
- struct isa_attach_args *ia;
- struct bt_softc *sc;
-{
- int iobase = ia->ia_iobase;
- u_char ad[4];
- volatile int i, sts;
- struct bt_extended_inquire info;
- struct bt_config conf;
- int irq, drq;
-
- /*
- * reset board, If it doesn't respond, assume
- * that it's not there.. good for the probe
- */
-
- outb(iobase + BT_CTRL_STAT_PORT, BT_HRST | BT_SRST);
-
- for (i = BT_RESET_TIMEOUT; i; i--) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- if (sts == (BT_IDLE | BT_INIT))
- break;
- delay(1000);
- }
- if (!i) {
-#ifdef UTEST
- printf("bt_find: No answer from bt742a board\n");
-#endif
- return 1;
- }
-
- /*
- * Check that we actually know how to use this board.
- */
- delay(1000);
- bt_cmd(iobase, sc, 1, sizeof(info), 0, (u_char *)&info,
- BT_INQUIRE_EXTENDED, sizeof(info));
- switch (info.bus_type) {
- case BT_BUS_TYPE_24BIT:
- /* XXXX How do we avoid conflicting with the aha1542 probe? */
- case BT_BUS_TYPE_32BIT:
- break;
- case BT_BUS_TYPE_MCA:
- /* We don't grok MicroChannel (yet). */
- return 1;
- default:
- printf("bt_find: illegal bus type %c\n", info.bus_type);
- return 1;
- }
-
- /*
- * Assume we have a board at this stage setup dma channel from
- * jumpers and save int level
- */
- delay(1000);
- bt_cmd(iobase, sc, 0, sizeof(conf), 0, (u_char *)&conf, BT_CONF_GET);
- switch (conf.chan) {
- case EISADMA:
- drq = DRQUNK;
- break;
- case CHAN0:
- drq = 0;
- break;
- case CHAN5:
- drq = 5;
- break;
- case CHAN6:
- drq = 6;
- break;
- case CHAN7:
- drq = 7;
- break;
- default:
- printf("bt_find: illegal dma setting %x\n", conf.chan);
- return 1;
- }
-
- switch (conf.intr) {
- case INT9:
- irq = 9;
- break;
- case INT10:
- irq = 10;
- break;
- case INT11:
- irq = 11;
- break;
- case INT12:
- irq = 12;
- break;
- case INT14:
- irq = 14;
- break;
- case INT15:
- irq = 15;
- break;
- default:
- printf("bt_find: illegal int setting %x\n", conf.intr);
- return 1;
- }
-
- if (sc != NULL) {
- /* who are we on the scsi bus? */
- sc->sc_scsi_dev = conf.scsi_dev;
-
- sc->sc_iobase = iobase;
- sc->sc_irq = irq;
- sc->sc_drq = drq;
- } else {
- if (ia->ia_irq == IRQUNK)
- ia->ia_irq = irq;
- else if (ia->ia_irq != irq)
- return 1;
- if (ia->ia_drq == DRQUNK)
- ia->ia_drq = drq;
- else if (ia->ia_drq != drq)
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Start the board, ready for normal operation
- */
-void
-bt_init(sc)
- struct bt_softc *sc;
-{
- int iobase = sc->sc_iobase;
- u_char ad[4];
- int i;
-
- /*
- * Initialize mail box
- */
- *((physaddr *)ad) = KVTOPHYS(&sc->sc_mbx);
-
- bt_cmd(iobase, sc, 5, 0, 0, 0, BT_MBX_INIT_EXTENDED, BT_MBX_SIZE,
- ad[0], ad[1], ad[2], ad[3]);
-
- for (i = 0; i < BT_MBX_SIZE; i++) {
- sc->sc_mbx.mbo[i].cmd = BT_MBO_FREE;
- sc->sc_mbx.mbi[i].stat = BT_MBI_FREE;
- }
-
- /*
- * Set up initial mail box for round-robin operation.
- */
- sc->sc_mbx.tmbo = &sc->sc_mbx.mbo[0];
- sc->sc_mbx.tmbi = &sc->sc_mbx.mbi[0];
-
- bt_inquire_setup_information(sc);
-}
-
-void
-bt_inquire_setup_information(sc)
- struct bt_softc *sc;
-{
- int iobase = sc->sc_iobase;
- struct bt_boardID bID;
- struct bt_board_info binfo;
- char dummy[8], sub_ver[3];
- struct bt_setup setup;
- int i, ver;
-
- /*
- * Get and print board hardware information.
- */
- bt_cmd(iobase, sc, 1, sizeof(binfo), 0, (u_char *)&binfo,
- BT_GET_BOARD_INFO, sizeof(binfo));
- printf(": Bt%c%c%c", binfo.id[0], binfo.id[1], binfo.id[2]);
- if (binfo.id[3] != ' ')
- printf("%c", binfo.id[3]);
- if (binfo.version[0] != ' ')
- printf("%c%s", binfo.version[0], binfo.version[1]);
- printf("\n");
-
- /*
- * Inquire Board ID to Bt742 for board type and firmware version.
- */
- bt_cmd(iobase, sc, 0, sizeof(bID), 0, (u_char *)&bID, BT_INQUIRE);
- ver = (bID.firm_revision - '0') * 10 + (bID.firm_version - '0');
-
- /*
- * Get the rest of the firmware version. Firmware revisions
- * before 3.3 apparently don't accept the BT_INQUIRE_REV_FOURTH
- * command.
- */
- i = 0;
- bt_cmd(iobase, sc, 0, 1, 0, &sub_ver[i++], BT_INQUIRE_REV_THIRD);
- if (ver >= 33)
- bt_cmd(iobase, sc, 0, 1, 0, &sub_ver[i++],
- BT_INQUIRE_REV_FOURTH);
- if (sub_ver[i - 1] == ' ')
- i--;
- sub_ver[i] = '\0';
-
- printf("%s: firmware version %c.%c%s, ", sc->sc_dev.dv_xname,
- bID.firm_revision, bID.firm_version, sub_ver);
-
- /* Enable round-robin scheme - appeared at firmware rev. 3.31 */
- if (ver > 33 || (ver == 33 && sub_ver[0] >= 1)) {
- bt_cmd(iobase, sc, 1, 0, 0, 0, BT_ROUND_ROBIN, BT_ENABLE);
- }
-
- /* Inquire Installed Devices (to force synchronous negotiation) */
- bt_cmd(iobase, sc, 0, sizeof(dummy), 10, dummy, BT_DEV_GET);
-
- /* Obtain setup information from Bt742. */
- bt_cmd(iobase, sc, 1, sizeof(setup), 0, (u_char *)&setup, BT_SETUP_GET,
- sizeof(setup));
-
- printf("%s, %s, %d mailboxes",
- setup.sync_neg ? "sync" : "async",
- setup.parity ? "parity" : "no parity",
- setup.num_mbx);
-
- for (i = 0; i < 8; i++) {
- if (!setup.sync[i].valid ||
- (!setup.sync[i].offset && !setup.sync[i].period))
- continue;
- printf("\n%s targ %d: sync, offset %d, period %dnsec",
- sc->sc_dev.dv_xname, i,
- setup.sync[i].offset, setup.sync[i].period * 50 + 200);
- }
-}
-
-void
-btminphys(bp)
- struct buf *bp;
-{
-
- if (bp->b_bcount > ((BT_NSEG - 1) << PGSHIFT))
- bp->b_bcount = ((BT_NSEG - 1) << PGSHIFT);
- minphys(bp);
-}
-
-/*
- * 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;
-{
- struct scsi_link *sc_link = xs->sc_link;
- struct bt_softc *sc = sc_link->adapter_softc;
- struct bt_ccb *ccb;
- struct bt_scat_gath *sg;
- int seg; /* scatter gather seg being worked on */
- int thiskv;
- physaddr thisphys, nextphys;
- int bytes_this_seg, bytes_this_page, datalen, flags;
- struct iovec *iovp;
- struct bt_mbx_out *mbo;
- int s;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("bt_scsi_cmd\n"));
- /*
- * get a ccb 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 & (ITSDONE|INUSE)) != INUSE) {
- printf("%s: done or not in use?\n", sc->sc_dev.dv_xname);
- xs->flags &= ~ITSDONE;
- xs->flags |= INUSE;
- }
- if ((ccb = bt_get_ccb(sc, flags)) == NULL) {
- xs->error = XS_DRIVER_STUFFUP;
- return TRY_AGAIN_LATER;
- }
- ccb->xs = xs;
-
- /*
- * Put all the arguments for the xfer in the ccb
- */
- 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->data_out = 0;
- ccb->data_in = 0;
- ccb->target = sc_link->target;
- ccb->lun = sc_link->lun;
- ccb->scsi_cmd_length = xs->cmdlen;
- ccb->sense_ptr = KVTOPHYS(&ccb->scsi_sense);
- ccb->req_sense_length = sizeof(ccb->scsi_sense);
- ccb->host_stat = 0x00;
- ccb->target_stat = 0x00;
-
- if (xs->datalen && (flags & SCSI_RESET) == 0) {
- ccb->data_addr = KVTOPHYS(ccb->scat_gath);
- 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;
- sg->seg_len = iovp->iov_len;
- xs->datalen += iovp->iov_len;
- SC_DEBUGN(sc_link, SDEV_DB4, ("(0x%x@0x%x)",
- iovp->iov_len, iovp->iov_base));
- sg++;
- iovp++;
- seg++;
- datalen--;
- }
- } else
-#endif /* TFS */
- {
- /*
- * Set up the scatter gather block
- */
- SC_DEBUG(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;
-
- SC_DEBUGN(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
- */
- /* how far to the end of the page */
- nextphys = (thisphys & ~PGOFSET) + NBPG;
- 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;
-
- /* get more ready for the next page */
- thiskv = (thiskv & ~PGOFSET) + NBPG;
- if (datalen)
- thisphys = KVTOPHYS(thiskv);
- }
- /*
- * next page isn't contiguous, finish the seg
- */
- SC_DEBUGN(sc_link, SDEV_DB4,
- ("(0x%x)", bytes_this_seg));
- sg->seg_len = bytes_this_seg;
- sg++;
- seg++;
- }
- }
- /* end of iov/kv decision */
- ccb->data_length = seg * sizeof(struct bt_scat_gath);
- SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
- if (datalen) {
- /*
- * there's still data, must have run out of segs!
- */
- printf("%s: bt_scsi_cmd, more than %d dma segs\n",
- sc->sc_dev.dv_xname, BT_NSEG);
- xs->error = XS_DRIVER_STUFFUP;
- bt_free_ccb(sc, ccb, flags);
- return COMPLETE;
- }
- } 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) == 0)
- bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmd_length);
-
- s = splbio();
-
- if (bt_send_mbo(sc, BT_MBO_START, ccb) == NULL) {
- splx(s);
- xs->error = XS_DRIVER_STUFFUP;
- bt_free_ccb(sc, ccb, flags);
- return TRY_AGAIN_LATER;
- }
-
- /*
- * Usually return SUCCESSFULLY QUEUED
- */
- SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
- if ((flags & SCSI_POLL) == 0) {
- timeout(bt_timeout, ccb, (xs->timeout * hz) / 1000);
- splx(s);
- return SUCCESSFULLY_QUEUED;
- }
-
- splx(s);
-
- /*
- * If we can't use interrupts, poll on completion
- */
- if (bt_poll(sc, xs, xs->timeout)) {
- bt_timeout(ccb);
- if (bt_poll(sc, xs, 2000))
- bt_timeout(ccb);
- }
- return COMPLETE;
-}
-
-/*
- * Poll a particular unit, looking for a particular xs
- */
-int
-bt_poll(sc, xs, count)
- struct bt_softc *sc;
- struct scsi_xfer *xs;
- int count;
-{
- int iobase = sc->sc_iobase;
-
- /* timeouts are in msec, so we loop in 1000 usec cycles */
- while (count) {
- /*
- * If we had interrupts enabled, would we
- * have got an interrupt?
- */
- if (inb(iobase + BT_INTR_PORT) & BT_ANY_INTR)
- btintr(sc);
- if (xs->flags & ITSDONE)
- return 0;
- delay(1000); /* only happens in boot so ok */
- count--;
- }
- return 1;
-}
-
-void
-bt_timeout(arg)
- void *arg;
-{
- struct bt_ccb *ccb = arg;
- struct scsi_xfer *xs = ccb->xs;
- struct scsi_link *sc_link = xs->sc_link;
- struct bt_softc *sc = sc_link->adapter_softc;
- int s;
-
- sc_print_addr(sc_link);
- printf("timed out");
-
- s = splbio();
-
- /*
- * If the ccb's mbx is not free, then the board has gone Far East?
- */
- if (bt_ccb_phys_kv(sc, ccb->mbx->ccb_addr) == ccb &&
- ccb->mbx->cmd != BT_MBO_FREE) {
- printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
- 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(" AGAIN\n");
- ccb->xs->retries = 0;
- bt_done(sc, ccb);
- } else {
- /* abort the operation that has timed out */
- printf("\n");
- ccb->xs->error = XS_TIMEOUT;
- ccb->flags = CCB_ABORTED;
- bt_send_mbo(sc, BT_MBO_ABORT, ccb);
- /* 2 secs for the abort */
- if ((xs->flags & SCSI_POLL) == 0)
- timeout(bt_timeout, ccb, 2 * hz);
- }
-
- splx(s);
-}
-
-#ifdef UTEST
-void
-bt_print_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);
- printf(" datlen:%d hstat:%x tstat:%x flags:%x\n",
- ccb->data_length, ccb->host_stat, ccb->target_stat, ccb->flags);
-}
-
-void
-bt_print_active_ccbs(sc)
- struct bt_softc *sc;
-{
- struct bt_ccb *ccb;
- int i = 0;
-
- while (i < CCB_HASH_SIZE) {
- ccb = sc->sc_ccbhash[i];
- while (ccb) {
- if (ccb->flags != CCB_FREE)
- bt_print_ccb(ccb);
- ccb = ccb->nexthash;
- }
- i++;
- }
-}
-#endif /*UTEST */
diff --git a/sys/dev/isa/btreg.h b/sys/dev/isa/btreg.h
new file mode 100644
index 00000000000..886911afa7f
--- /dev/null
+++ b/sys/dev/isa/btreg.h
@@ -0,0 +1,304 @@
+typedef u_int8_t physaddr[4];
+typedef u_int8_t physlen[4];
+#define ltophys _lto4l
+#define phystol _4ltol
+
+/*
+ * I/O port offsets
+ */
+#define BT_CTRL_PORT 0 /* control (wo) */
+#define BT_STAT_PORT 0 /* status (ro) */
+#define BT_CMD_PORT 1 /* command (wo) */
+#define BT_DATA_PORT 1 /* data (ro) */
+#define BT_INTR_PORT 2 /* interrupt status (ro) */
+
+/*
+ * BT_CTRL bits
+ */
+#define BT_CTRL_HRST 0x80 /* Hardware reset */
+#define BT_CTRL_SRST 0x40 /* Software reset */
+#define BT_CTRL_IRST 0x20 /* Interrupt reset */
+#define BT_CTRL_SCRST 0x10 /* SCSI bus reset */
+
+/*
+ * BT_STAT bits
+ */
+#define BT_STAT_STST 0x80 /* Self test in Progress */
+#define BT_STAT_DIAGF 0x40 /* Diagnostic Failure */
+#define BT_STAT_INIT 0x20 /* Mbx Init required */
+#define BT_STAT_IDLE 0x10 /* Host Adapter Idle */
+#define BT_STAT_CDF 0x08 /* cmd/data out port full */
+#define BT_STAT_DF 0x04 /* Data in port full */
+#define BT_STAT_INVDCMD 0x01 /* Invalid command */
+
+/*
+ * BT_CMD opcodes
+ */
+#define BT_NOP 0x00 /* No operation */
+#define BT_MBX_INIT 0x01 /* Mbx initialization */
+#define BT_START_SCSI 0x02 /* start scsi command */
+#define BT_INQUIRE_REVISION 0x04 /* Adapter Inquiry */
+#define BT_MBO_INTR_EN 0x05 /* Enable MBO available interrupt */
+/*#define BT_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
+/*#define BT_BUS_ON_TIME_SET 0x07 /* set bus-on time */
+/*#define BT_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
+/*#define BT_SPEED_SET 0x09 /* set transfer speed */
+#define BT_INQUIRE_DEVICES 0x0a /* return installed devices 0-7 */
+#define BT_INQUIRE_CONFIG 0x0b /* return configuration data */
+#define BT_TARGET_EN 0x0c /* enable target mode */
+#define BT_INQUIRE_SETUP 0x0d /* return setup data */
+#define BT_ECHO 0x1e /* Echo command data */
+#define BT_INQUIRE_DEVICES_2 0x23 /* return installed devices 8-15 */
+#define BT_MBX_INIT_EXTENDED 0x81 /* Mbx initialization */
+#define BT_INQUIRE_REVISION_3 0x84 /* Get 3rd firmware version byte */
+#define BT_INQUIRE_REVISION_4 0x85 /* Get 4th firmware version byte */
+#define BT_INQUIRE_MODEL 0x8b /* Get hardware ID and revision */
+#define BT_INQUIRE_PERIOD 0x8c /* Get synchronous period */
+#define BT_INQUIRE_EXTENDED 0x8d /* Adapter Setup Inquiry */
+#define BT_ROUND_ROBIN 0x8f /* Enable/Disable(default) round robin */
+
+/*
+ * BT_INTR bits
+ */
+#define BT_INTR_ANYINTR 0x80 /* Any interrupt */
+#define BT_INTR_SCRD 0x08 /* SCSI reset detected */
+#define BT_INTR_HACC 0x04 /* Command complete */
+#define BT_INTR_MBOA 0x02 /* MBX out empty */
+#define BT_INTR_MBIF 0x01 /* MBX in full */
+
+struct bt_mbx_out {
+ physaddr ccb_addr;
+ u_char dummy[3];
+ u_char cmd;
+};
+
+struct bt_mbx_in {
+ physaddr ccb_addr;
+ u_char dummy[3];
+ u_char stat;
+};
+
+/*
+ * mbo.cmd values
+ */
+#define BT_MBO_FREE 0x0 /* MBO entry is free */
+#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 */
+
+#if defined(BIG_DMA)
+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 {
+ physlen seg_len;
+ physaddr seg_addr;
+};
+
+struct bt_ccb {
+ u_char opcode;
+ u_char:3, data_in:1, data_out:1,:3;
+ u_char scsi_cmd_length;
+ u_char req_sense_length;
+ /*------------------------------------longword boundary */
+ physlen data_length;
+ /*------------------------------------longword boundary */
+ physaddr data_addr;
+ /*------------------------------------longword boundary */
+ u_char dummy1[2];
+ u_char host_stat;
+ u_char target_stat;
+ /*------------------------------------longword boundary */
+ u_char target;
+ u_char lun;
+ struct scsi_generic scsi_cmd;
+ u_char dummy2[1];
+ u_char link_id;
+ /*------------------------------------longword boundary */
+ physaddr link_addr;
+ /*------------------------------------longword boundary */
+ physaddr sense_ptr;
+/*-----end of HW fields-----------------------longword boundary */
+ struct scsi_sense_data scsi_sense;
+ /*------------------------------------longword boundary */
+ struct bt_scat_gath scat_gath[BT_NSEG];
+ /*------------------------------------longword boundary */
+ TAILQ_ENTRY(bt_ccb) chain;
+ struct bt_ccb *nexthash;
+ long hashkey;
+ struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
+ int flags;
+#define CCB_ALLOC 0x01
+#define CCB_ABORT 0x02
+#ifdef BTDIAG
+#define CCB_SENDING 0x04
+#endif
+ int timeout;
+};
+
+/*
+ * opcode fields
+ */
+#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_RESET_CCB 0x81 /* SCSI Bus reset */
+
+/*
+ * bt_ccb.host_stat values
+ */
+#define BT_OK 0x00 /* cmd ok */
+#define BT_LINK_OK 0x0a /* Link cmd ok */
+#define BT_LINK_IT 0x0b /* Link cmd ok + int */
+#define BT_SEL_TIMEOUT 0x11 /* Selection time out */
+#define BT_OVER_UNDER 0x12 /* Data over/under run */
+#define BT_BUS_FREE 0x13 /* Bus dropped at unexpected time */
+#define BT_INV_BUS 0x14 /* Invalid bus phase/sequence */
+#define BT_BAD_MBO 0x15 /* Incorrect MBO cmd */
+#define BT_BAD_CCB 0x16 /* Incorrect ccb opcode */
+#define BT_BAD_LINK 0x17 /* Not same values of LUN for links */
+#define BT_INV_TARGET 0x18 /* Invalid target direction */
+#define BT_CCB_DUP 0x19 /* Duplicate CCB received */
+#define BT_INV_CCB 0x1a /* Invalid CCB or segment list */
+
+struct bt_extended_inquire {
+ struct {
+ u_char opcode;
+ u_char len;
+ } cmd;
+ struct {
+ u_char bus_type; /* Type of bus connected to */
+#define BT_BUS_TYPE_24BIT 'A' /* ISA bus */
+#define BT_BUS_TYPE_32BIT 'E' /* EISA/VLB/PCI bus */
+#define BT_BUS_TYPE_MCA 'M' /* MicroChannel bus */
+ u_char bios_address; /* Address of adapter BIOS */
+ u_short max_segment; /* ? */
+ } reply;
+};
+
+struct bt_config {
+ struct {
+ u_char opcode;
+ } cmd;
+ struct {
+ u_char chan;
+ u_char intr;
+ u_char scsi_dev:3;
+ u_char :5;
+ } reply;
+};
+
+struct bt_toggle {
+ struct {
+ u_char opcode;
+ u_char enable;
+ } cmd;
+};
+
+struct bt_mailbox {
+ struct {
+ u_char opcode;
+ u_char nmbx;
+ physaddr addr;
+ } cmd;
+};
+
+struct bt_model {
+ struct {
+ u_char opcode;
+ u_char len;
+ } cmd;
+ struct {
+ u_char id[4]; /* i.e bt742a -> '7','4','2','A' */
+ u_char version[2]; /* i.e Board Revision 'H' -> 'H', 0x00 */
+ } reply;
+};
+
+struct bt_revision {
+ struct {
+ u_char opcode;
+ } cmd;
+ struct {
+ u_char board_type;
+ u_char custom_feature;
+ char firm_revision;
+ u_char firm_version;
+ } reply;
+};
+
+struct bt_digit {
+ struct {
+ u_char opcode;
+ } cmd;
+ struct {
+ u_char digit;
+ } reply;
+};
+
+struct bt_devices {
+ struct {
+ u_char opcode;
+ } cmd;
+ struct {
+ u_char junk[8];
+ } reply;
+};
+
+struct bt_setup {
+ struct {
+ u_char opcode;
+ u_char len;
+ } cmd;
+ struct {
+ 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]; /*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;
+ } reply;
+};
+
+struct bt_period {
+ struct {
+ u_char opcode;
+ u_char len;
+ } cmd;
+ struct {
+ u_char period[8];
+ } reply;
+};
+
+#define INT9 0x01
+#define INT10 0x02
+#define INT11 0x04
+#define INT12 0x08
+#define INT14 0x20
+#define INT15 0x40
+
+#define EISADMA 0x00
+#define CHAN0 0x01
+#define CHAN5 0x20
+#define CHAN6 0x40
+#define CHAN7 0x80
diff --git a/sys/dev/isa/com.c b/sys/dev/isa/com.c
index d34ba82a096..77dd24748f4 100644
--- a/sys/dev/isa/com.c
+++ b/sys/dev/isa/com.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: com.c,v 1.10 1996/04/18 23:47:32 niklas Exp $ */
-/* $NetBSD: com.c,v 1.75 1996/03/10 09:01:24 cgd Exp $ */
+/* $OpenBSD: com.c,v 1.11 1996/04/21 22:23:15 deraadt Exp $ */
+/* $NetBSD: com.c,v 1.79 1996/04/15 18:54:31 cgd Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995, 1996
@@ -57,7 +57,11 @@
#include <sys/types.h>
#include <sys/device.h>
-#include <machine/cpu.h>
+#ifdef i386 /* XXX */
+#include <machine/cpu.h> /* XXX */
+#else /* XXX */
+#include <machine/intr.h>
+#endif /* XXX */
#include <machine/bus.h>
#include <dev/isa/isavar.h>
@@ -69,6 +73,8 @@
#endif
#define com_lcr com_cfcr
+#include "com.h"
+
#define COM_IBUFSIZE (2 * 512)
#define COM_IHIGHWATER ((3 * COM_IBUFSIZE) / 4)
@@ -109,11 +115,9 @@ struct com_softc {
u_char sc_ibufs[2][COM_IBUFSIZE];
};
-int comprobe __P((struct device *, void *, void *));
#ifdef COM_HAYESP
int comprobeHAYESP __P((bus_io_handle_t hayespioh, struct com_softc *sc));
#endif
-void comattach __P((struct device *, struct device *, void *));
int comopen __P((dev_t, int, int, struct proc *));
int comclose __P((dev_t, int, int, struct proc *));
void comdiag __P((void *));
@@ -122,11 +126,30 @@ void compoll __P((void *));
int comparam __P((struct tty *, struct termios *));
void comstart __P((struct tty *));
-int cominit __P((bus_chipset_tag_t, bus_io_handle_t, int));
+/*
+ * XXX the following two cfattach structs should be different, and possibly
+ * XXX elsewhere.
+ */
+int comprobe __P((struct device *, void *, void *));
+void comattach __P((struct device *, struct device *, void *));
+
+#if NCOM_ISA
+struct cfattach com_isa_ca = {
+ sizeof(struct com_softc), comprobe, comattach
+};
+#endif
-struct cfdriver comcd = {
- NULL, "com", comprobe, comattach, DV_TTY, sizeof(struct com_softc)
+#if NCOM_COMMULTI
+struct cfattach com_commulti_ca = {
+ sizeof(struct com_softc), comprobe, comattach
};
+#endif
+
+struct cfdriver com_cd = {
+ NULL, "com", DV_TTY
+};
+
+int cominit __P((bus_chipset_tag_t, bus_io_handle_t, int));
#ifdef COMCONSOLE
int comdefaultrate = CONSPEED; /* XXX why set default? */
@@ -138,6 +161,7 @@ int comconsinit;
int comconsattached;
bus_chipset_tag_t comconsbc;
bus_io_handle_t comconsioh;
+tcflag_t comconscflag = TTYDEF_CFLAG;
int commajor;
int comsopen = 0;
@@ -157,7 +181,7 @@ extern int kgdb_debug_init;
#define CLR(t, f) (t) &= ~(f)
#define ISSET(t, f) ((t) & (f))
-#include "pcmciabus.h"
+/*#include "pcmciabus.h"*/
#if NPCMCIABUS >0
/* additional setup needed for pcmcia devices */
#include <dev/pcmcia/pcmciabus.h>
@@ -327,13 +351,22 @@ comprobe(parent, match, aux)
int iobase, needioh;
int rv = 1;
+ /*
+ * XXX should be broken out into functions for isa probe and
+ * XXX for commulti probe, with a helper function that contains
+ * XXX most of the interesting stuff.
+ */
+#if NCOM_ISA
if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
struct isa_attach_args *ia = aux;
bc = ia->ia_bc;
iobase = ia->ia_iobase;
needioh = 1;
- } else {
+ } else
+#endif
+#if NCOM_COMMULTI
+ if (1) {
struct commulti_attach_args *ca = aux;
if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ca->ca_slave)
@@ -343,7 +376,9 @@ comprobe(parent, match, aux)
iobase = ca->ca_iobase;
ioh = ca->ca_ioh;
needioh = 0;
- }
+ } else
+#endif
+ return(0); /* This cannot happen */
/* if it's in use as console, it's there. */
if (iobase == comconsaddr && !comconsattached)
@@ -358,12 +393,14 @@ comprobe(parent, match, aux)
bus_io_unmap(bc, ioh, COM_NPORTS);
out:
+#if NCOM_ISA
if (rv && !strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
struct isa_attach_args *ia = aux;
ia->ia_iosize = COM_NPORTS;
ia->ia_msize = 0;
}
+#endif
return (rv);
}
@@ -383,8 +420,14 @@ comattach(parent, self, aux)
int *hayespp;
#endif
+ /*
+ * XXX should be broken out into functions for isa attach and
+ * XXX for commulti attach, with a helper function that contains
+ * XXX most of the interesting stuff.
+ */
sc->sc_hwflags = 0;
sc->sc_swflags = 0;
+#if NCOM_ISA
if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
struct isa_attach_args *ia = aux;
@@ -399,7 +442,10 @@ comattach(parent, self, aux)
} else
ioh = comconsioh;
irq = ia->ia_irq;
- } else {
+ } else
+#endif
+#if NCOM_COMMULTI
+ if (1) {
struct commulti_attach_args *ca = aux;
/*
@@ -412,7 +458,9 @@ comattach(parent, self, aux)
if (ca->ca_noien)
sc->sc_hwflags |= COM_HW_NOIEN;
- }
+ } else
+#endif
+ panic("comattach: impossible");
sc->sc_bc = bc;
sc->sc_ioh = ioh;
@@ -473,9 +521,18 @@ comattach(parent, self, aux)
bus_io_write_1(bc, ioh, com_ier, 0);
bus_io_write_1(bc, ioh, com_mcr, 0);
- if (irq != IRQUNK)
- sc->sc_ih = isa_intr_establish(irq, IST_EDGE, IPL_TTY,
- comintr, sc, sc->sc_dev.dv_xname);
+ if (irq != IRQUNK) {
+#if NCOM_ISA
+ if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
+ struct isa_attach_args *ia = aux;
+
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
+ IST_EDGE, IPL_TTY, comintr, sc,
+ sc->sc_dev.dv_xname);
+ } else
+#endif
+ panic("comattach: IRQ but can't have one");
+ }
#ifdef KGDB
if (kgdb_dev == makedev(commajor, unit)) {
@@ -516,9 +573,9 @@ comopen(dev, flag, mode, p)
int s;
int error = 0;
- if (unit >= comcd.cd_ndevs)
+ if (unit >= com_cd.cd_ndevs)
return ENXIO;
- sc = comcd.cd_devs[unit];
+ sc = com_cd.cd_devs[unit];
if (!sc)
return ENXIO;
@@ -535,7 +592,10 @@ comopen(dev, flag, mode, p)
ttychars(tp);
tp->t_iflag = TTYDEF_IFLAG;
tp->t_oflag = TTYDEF_OFLAG;
- tp->t_cflag = TTYDEF_CFLAG;
+ if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+ tp->t_cflag = comconscflag;
+ else
+ tp->t_cflag = TTYDEF_CFLAG;
if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
SET(tp->t_cflag, CLOCAL);
if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
@@ -644,7 +704,7 @@ comclose(dev, flag, mode, p)
struct proc *p;
{
int unit = COMUNIT(dev);
- struct com_softc *sc = comcd.cd_devs[unit];
+ struct com_softc *sc = com_cd.cd_devs[unit];
struct tty *tp = sc->sc_tty;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
@@ -684,7 +744,7 @@ comread(dev, uio, flag)
struct uio *uio;
int flag;
{
- struct com_softc *sc = comcd.cd_devs[COMUNIT(dev)];
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
struct tty *tp = sc->sc_tty;
return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
@@ -696,7 +756,7 @@ comwrite(dev, uio, flag)
struct uio *uio;
int flag;
{
- struct com_softc *sc = comcd.cd_devs[COMUNIT(dev)];
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
struct tty *tp = sc->sc_tty;
return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
@@ -706,7 +766,7 @@ struct tty *
comtty(dev)
dev_t dev;
{
- struct com_softc *sc = comcd.cd_devs[COMUNIT(dev)];
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
struct tty *tp = sc->sc_tty;
return (tp);
@@ -734,7 +794,7 @@ comioctl(dev, cmd, data, flag, p)
struct proc *p;
{
int unit = COMUNIT(dev);
- struct com_softc *sc = comcd.cd_devs[unit];
+ struct com_softc *sc = com_cd.cd_devs[unit];
struct tty *tp = sc->sc_tty;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
@@ -846,7 +906,7 @@ comparam(tp, t)
struct tty *tp;
struct termios *t;
{
- struct com_softc *sc = comcd.cd_devs[COMUNIT(tp->t_dev)];
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
int ospeed = comspeed(t->c_ospeed);
@@ -985,7 +1045,7 @@ void
comstart(tp)
struct tty *tp;
{
- struct com_softc *sc = comcd.cd_devs[COMUNIT(tp->t_dev)];
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
int s;
@@ -1106,8 +1166,8 @@ compoll(arg)
comevents = 0;
splx(s);
- for (unit = 0; unit < comcd.cd_ndevs; unit++) {
- sc = comcd.cd_devs[unit];
+ for (unit = 0; unit < com_cd.cd_ndevs; unit++) {
+ sc = com_cd.cd_devs[unit];
if (sc == 0 || sc->sc_ibufp == sc->sc_ibuf)
continue;
diff --git a/sys/dev/isa/comvar.h b/sys/dev/isa/comvar.h
index 9b412b06936..c3f8068caec 100644
--- a/sys/dev/isa/comvar.h
+++ b/sys/dev/isa/comvar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: comvar.h,v 1.1 1996/04/19 16:08:34 niklas Exp $ */
-/* $NetBSD: comvar.h,v 1.3 1996/03/10 09:01:26 cgd Exp $ */
+/* $OpenBSD: comvar.h,v 1.2 1996/04/21 22:23:20 deraadt Exp $ */
+/* $NetBSD: comvar.h,v 1.4 1996/04/15 18:54:35 cgd Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -46,3 +46,4 @@ extern int comconsaddr;
extern int comconsattached;
extern bus_chipset_tag_t comconsbc;
extern bus_io_handle_t comconsioh;
+extern tcflag_t comconscflag;
diff --git a/sys/dev/isa/fd.c b/sys/dev/isa/fd.c
index 45564bd20b9..a7b07df07c7 100644
--- a/sys/dev/isa/fd.c
+++ b/sys/dev/isa/fd.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: fd.c,v 1.12 1996/04/18 17:12:13 niklas Exp $ */
-/* $NetBSD: fd.c,v 1.85 1996/03/04 04:01:03 mycroft Exp $ */
+/* $OpenBSD: fd.c,v 1.13 1996/04/21 22:16:52 deraadt Exp $ */
+/* $NetBSD: fd.c,v 1.87 1996/04/11 22:15:16 cgd Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995 Charles Hannum.
@@ -112,8 +112,12 @@ void fdcforceintr __P((void *));
#endif
void fdcattach __P((struct device *, struct device *, void *));
-struct cfdriver fdccd = {
- NULL, "fdc", fdcprobe, fdcattach, DV_DULL, sizeof(struct fdc_softc)
+struct cfattach fdc_ca = {
+ sizeof(struct fdc_softc), fdcprobe, fdcattach
+};
+
+struct cfdriver fdc_cd = {
+ NULL, "fdc", DV_DULL
};
/*
@@ -179,8 +183,12 @@ struct fd_softc {
int fdprobe __P((struct device *, void *, void *));
void fdattach __P((struct device *, struct device *, void *));
-struct cfdriver fdcd = {
- NULL, "fd", fdprobe, fdattach, DV_DISK, sizeof(struct fd_softc)
+struct cfattach fd_ca = {
+ sizeof(struct fd_softc), fdprobe, fdattach
+};
+
+struct cfdriver fd_cd = {
+ NULL, "fd", DV_DISK
};
void fdgetdisklabel __P((struct fd_softc *));
@@ -308,8 +316,8 @@ fdcattach(parent, self, aux)
at_setup_dmachan(fdc->sc_drq, FDC_MAXIOSIZE);
isa_establish(&fdc->sc_id, &fdc->sc_dev);
#endif
- fdc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO, fdcintr,
- fdc, fdc->sc_dev.dv_xname);
+ fdc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, fdcintr, fdc, fdc->sc_dev.dv_xname);
/*
* The NVRAM info only tells us about the first two disks on the
@@ -477,8 +485,8 @@ fdstrategy(bp)
int s;
/* Valid unit, controller, and request? */
- if (unit >= fdcd.cd_ndevs ||
- (fd = fdcd.cd_devs[unit]) == 0 ||
+ if (unit >= fd_cd.cd_ndevs ||
+ (fd = fd_cd.cd_devs[unit]) == 0 ||
bp->b_blkno < 0 ||
(bp->b_bcount % FDC_BSIZE) != 0) {
bp->b_error = EINVAL;
@@ -705,9 +713,9 @@ Fdopen(dev, flags)
struct fd_type *type;
unit = FDUNIT(dev);
- if (unit >= fdcd.cd_ndevs)
+ if (unit >= fd_cd.cd_ndevs)
return ENXIO;
- fd = fdcd.cd_devs[unit];
+ fd = fd_cd.cd_devs[unit];
if (fd == 0)
return ENXIO;
type = fd_dev_to_type(fd, dev);
@@ -730,7 +738,7 @@ fdclose(dev, flags)
dev_t dev;
int flags;
{
- struct fd_softc *fd = fdcd.cd_devs[FDUNIT(dev)];
+ struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
fd->sc_flags &= ~FD_OPEN;
return 0;
@@ -1169,7 +1177,7 @@ fdioctl(dev, cmd, addr, flag)
caddr_t addr;
int flag;
{
- struct fd_softc *fd = fdcd.cd_devs[FDUNIT(dev)];
+ struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
struct disklabel buffer;
int error;
diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa
index 02c45fce533..47e4237a8b2 100644
--- a/sys/dev/isa/files.isa
+++ b/sys/dev/isa/files.isa
@@ -1,5 +1,5 @@
-# $OpenBSD: files.isa,v 1.7 1996/04/18 23:47:33 niklas Exp $
-# $NetBSD: files.isa,v 1.12 1996/03/04 03:29:16 cgd Exp $
+# $OpenBSD: files.isa,v 1.8 1996/04/21 22:23:23 deraadt Exp $
+# $NetBSD: files.isa,v 1.17 1996/03/29 20:53:30 mycroft Exp $
#
# Config.new file and device description for machine-independent ISA code.
# Included by ports that need it. Requires that the SCSI files be
@@ -9,11 +9,10 @@
# devices:
# mcd, scd, wd, wt
-define isa {[port = -1], [size = 0],
- [iomem = -1], [iosiz = 0],
- [irq = -1], [drq = -1]}
-
-device isa at isabus: isa
+device isa {[port = -1], [size = 0],
+ [iomem = -1], [iosiz = 0],
+ [irq = -1], [drq = -1]}
+attach isa at isabus
file dev/isa/isa.c isa needs-flag
# ISA DMA controller
@@ -28,7 +27,8 @@ file dev/isa/isadma.c isadma needs-flag
define pcicbus {[iomem = -1], [iosiz = 0]}
-device pcic at isa: pcicbus
+device pcic: pcicbus
+attach pcic at isa
file dev/isa/pcmcia_pcic.c pcic
file dev/isa/pcmcia_isa.c pcmcia
@@ -47,15 +47,18 @@ include "../../../dev/pcmcia/files.pcmcia"
define commulti {[slave = -1]}
# AST 4-port board
-device ast at isa: commulti
+device ast: commulti
+attach ast at isa
file dev/isa/ast.c ast
# BOCA 8-port board
-device boca at isa: commulti
+device boca: commulti
+attach boca at isa
file dev/isa/boca.c boca
# IBM RT PC 4-port board
-device rtfps at isa: commulti
+device rtfps: commulti
+attach rtfps at isa
file dev/isa/rtfps.c rtfps
#
@@ -63,16 +66,20 @@ file dev/isa/rtfps.c rtfps
#
# 8250/16[45]50-based "com" ports
-device com at isa, commulti: tty
-file dev/isa/com.c com needs-flag
+device com: tty
+attach com at isa with com_isa
+attach com at commulti with com_commulti
+file dev/isa/com.c com & (com_isa | com_commulti) needs-flag
# Cyclades Cyclom multiport serial cards
# XXX currently broken
-device cy at isa: tty
+device cy: tty
+attach cy at isa
file dev/isa/cy.c cy needs-count
# PC parallel ports (XXX what chip?)
-device lpt at isa
+device lpt
+attach lpt at isa
file dev/isa/lpt.c lpt needs-flag
#
@@ -80,53 +87,64 @@ file dev/isa/lpt.c lpt needs-flag
#
# Adaptec AHA-154x family
-device aha at isa: scsi, isadma
-file dev/isa/aha1542.c aha
+device aha: scsi, isadma
+attach aha at isa
+file dev/isa/aha.c aha
# Adapctec AIC-6[32]60 ICs
-device aic at isa: scsi, isadma
+device aic: scsi, isadma
+attach aic at isa
file dev/isa/aic6360.c aic
# Adaptec 7770-based EISA, VLB, etc. controllers
-device ahe at isa: scsi, aic7xxx
+device ahe: scsi, aic7xxx
+attach ahe at isa
file dev/isa/aha284x.c ahe
# BusLogic BT-74x EISA family (XXX; should be EISA. it's special)
-device bt at isa: scsi, isadma
-file dev/isa/bt742a.c bt
+device bt: scsi, isadma
+attach bt at isa
+file dev/isa/bt.c bt
# Seagate ST0[12] ICs
-device sea at isa: scsi, isadma
+device sea: scsi, isadma
+attach sea at isa
file dev/isa/seagate.c sea
# UltraStor UHA-[13]4f boards
-device uha at isa: scsi, isadma
+device uha: scsi, isadma
+attach uha at isa
file dev/isa/ultra14f.c uha
-# Western Digital WD7000 boards (XXX incomplete description)
-# XXX not yet working
-device wds at isa: scsi, isadma
-file dev/isa/wd7000.c wds
+# Western Digital WD7000 and Future Domain TMC-7000 boards
+device wds: scsi, isadma
+attach wds at isa
+file dev/isa/wds.c wds
#
# Other ISA disk controllers
#
# Mitsumi CD-ROM controllers
-device mcd at isa: disk
+device mcd: disk
+attach mcd at isa
file dev/isa/mcd.c mcd needs-flag
# Sony CDU-3[13]A CD-ROM drives
-device scd at isa: disk
+device scd: disk
+attach scd at isa
file dev/isa/scd.c scd needs-flag
# ISA "wd" (ESDI/IDE/etc.) controllers
-device wdc at isa {drive = -1}
-device wd at wdc: disk, isadma
+device wdc {drive = -1}
+attach wdc at isa
+device wd: disk, isadma
+attach wd at wdc
file dev/isa/wd.c wdc needs-flag
# Wangtek- and Archive-compatible tape controller boards
-device wt at isa: tape, isadma
+device wt: tape, isadma
+attach wt at isa
file dev/isa/wt.c wt needs-flag
#
@@ -140,45 +158,55 @@ file dev/isa/elink.c elink
# National Semiconductor DS8390/WD83C690-based boards
# (WD/SMC 80x3 family, SMC Ultra [8216], 3Com 3C503, NE[12]000, and clones)
# XXX conflicts with amiga if_ed.c
-#device ed at isa, pcmcia: ether, ifnet
-#file dev/isa/if_ed.c ed needs-flag
+device ed: ether, ifnet
+attach ed at isa
+file dev/isa/if_ed.c ed needs-flag
# 3Com 3C505
-device eg at isa: ether, ifnet
+device eg: ether, ifnet
+attach eg at isa
file dev/isa/if_eg.c eg
# 3Com 3C501
-device el at isa: ether, ifnet
+device el: ether, ifnet
+attach el at isa
file dev/isa/if_el.c el
# 3Com 3C5x9, 3c59x (EtherLink III) family
-device ep at isa, pci: ether, ifnet, elink
+device ep: ether, ifnet, elink
+attach ep at isa with ep_isa
+attach ep at pci with ep_pci
file dev/isa/if_ep.c ep needs-flag
# Fujitsu MB8696[05]-based boards
# (Allied Telesis AT1700)
-device fe at isa: ether, ifnet
+device fe: ether, ifnet
+attach fe at isa
file dev/isa/if_fe.c fe
# HP Lan Ethernet controllers
# XXX currently broken
-#device hp at isa: ether, ifnet
+#device hp: ether, ifnet
+#attach hp at isa
#file dev/isa/if_hp.c hp
# Intel i82586-based boards
# (AT&T StarLAN 10, AT&T EN100, AT&T StarLAN Fiber, 3Com 3C507)
-device ie at isa: ether, ifnet, elink
+device ie: ether, ifnet, elink
+attach ie at isa
file dev/isa/if_ie.c ie
# XXX ???
# XXX NOT IN TREE?
-#device ix at isa: ether, ifnet
+#device ix: ether, ifnet
+#attach ix at isa
#file dev/isa/if_ix.c ix
# AMD am7990 (Lance) -based boards
# (BICC Isolan, NE2100, DEPCA)
# XXX conflicts with alpha if_le.c
-#device le at isa: ether, ifnet, isadma
+#device le: ether, ifnet, isadma
+#attach le at isa with le_isa
#file dev/isa/if_le.c le
#
@@ -190,11 +218,13 @@ define sbdsp
file dev/isa/sbdsp.c sbdsp
# SoundBlaster family
-device sb at isa: audio, isadma, sbdsp, mulaw
+device sb: audio, isadma, sbdsp, mulaw
+attach sb at isa
file dev/isa/sb.c sb needs-flag
# ProAudio Spectrum
-device pas at isa: audio, isadma, sbdsp, mulaw
+device pas: audio, isadma, sbdsp, mulaw
+attach pas at isa
file dev/isa/pas.c pas needs-flag
# AD1848 (CS4248, CS4231, AD1845) audio codec support; used by other drivers
@@ -207,18 +237,22 @@ file dev/isa/ics2101.c ics2101
# Audio systems based on Echo Speech Corp. ESC61[45] ASICs
-device pss at isa {[port = -1], [size = 0],
- [iomem = -1], [iosiz = 0],
- [irq = -1], [drq = -1]}
-device sp at pss: audio, isadma, ad1848
+device pss {[port = -1], [size = 0],
+ [iomem = -1], [iosiz = 0],
+ [irq = -1], [drq = -1]}
+attach pss at isa
+device sp: audio, isadma, ad1848
+attach sp at pss
file dev/isa/pss.c pss needs-flag
# Microsoft Windows Sound System
-device wss at isa: audio, isadma, ad1848
+device wss: audio, isadma, ad1848
+attach wss at isa
file dev/isa/wss.c wss needs-flag
# Gravis UltraSound & UltraSound MAX.
# Use the "flags" keyword in a config file to specify an extra DMA
# channel for full-duplex operation.
-device gus at isa: audio, isadma, ics2101, ad1848, mulaw
+device gus: audio, isadma, ics2101, ad1848, mulaw
+attach gus at isa
file dev/isa/gus.c gus needs-flag
diff --git a/sys/dev/isa/gus.c b/sys/dev/isa/gus.c
index a2c1b4f2014..9a72f7a6182 100644
--- a/sys/dev/isa/gus.c
+++ b/sys/dev/isa/gus.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: gus.c,v 1.8 1996/04/18 23:47:34 niklas Exp $ */
-/* $NetBSD: gus.c,v 1.10 1996/03/01 04:08:31 mycroft Exp $ */
+/* $OpenBSD: gus.c,v 1.9 1996/04/21 22:23:28 deraadt Exp $ */
+/* $NetBSD: gus.c,v 1.13 1996/04/11 22:28:42 cgd Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -126,6 +126,7 @@
#include <dev/ic/ad1848reg.h>
#include <dev/isa/ics2101var.h>
#include <dev/isa/ad1848var.h>
+#include <dev/isa/cs4231var.h>
#include "gusreg.h"
#ifdef AUDIO_DEBUG
@@ -458,8 +459,12 @@ STATIC void gusics_cd_mute __P((struct ics2101_softc *, int));
int gusprobe __P((struct device *, void *, void *));
void gusattach __P((struct device *, struct device *, void *));
-struct cfdriver guscd = {
- NULL, "gus", gusprobe, gusattach, DV_DULL, sizeof(struct gus_softc)
+struct cfattach gus_ca = {
+ sizeof(struct gus_softc), gusprobe, gusattach,
+};
+
+struct cfdriver gus_cd = {
+ NULL, "gus", DV_DULL
};
@@ -927,8 +932,8 @@ gusattach(parent, self, aux)
/* XXX we shouldn't have to use splgus == splclock, nor should
* we use IPL_CLOCK.
*/
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_AUDIO, gusintr,
- sc /* sc->sc_gusdsp */, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_AUDIO, gusintr, sc /* sc->sc_gusdsp */, sc->sc_dev.dv_xname);
/*
* Set some default values
@@ -974,9 +979,9 @@ gusopen(dev, flags)
DPRINTF(("gusopen() called\n"));
- if (unit >= guscd.cd_ndevs)
+ if (unit >= gus_cd.cd_ndevs)
return ENXIO;
- sc = guscd.cd_devs[unit];
+ sc = gus_cd.cd_devs[unit];
if (!sc)
return ENXIO;
diff --git a/sys/dev/isa/if_ed.c b/sys/dev/isa/if_ed.c
index dc5993a34b7..b385c61d95a 100644
--- a/sys/dev/isa/if_ed.c
+++ b/sys/dev/isa/if_ed.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: if_ed.c,v 1.9 1996/04/18 23:47:37 niklas Exp $ */
-/* $NetBSD: if_ed.c,v 1.90 1996/03/16 07:24:15 cgd Exp $ */
+/* $OpenBSD: if_ed.c,v 1.10 1996/04/21 22:23:41 deraadt Exp $ */
+/* $NetBSD: if_ed.c,v 1.93 1996/04/11 22:28:55 cgd Exp $ */
/*
* Device driver for National Semiconductor DS8390/WD83C690 based ethernet
@@ -18,7 +18,6 @@
* similar clones.
*/
-#include "pcmciabus.h"
#include "bpfilter.h"
#include <sys/param.h>
@@ -54,11 +53,10 @@
#endif
#include <machine/cpu.h>
-#include <machine/pio.h>
+#include <machine/bus.h>
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
-#include <i386/isa/isa_machdep.h> /* XXX USES ISA HOLE DIRECTLY */
#define ED_BYTE_ORDER LITTLE_ENDIAN
#include <dev/ic/dp8390reg.h>
#include <dev/isa/if_edreg.h>
@@ -81,8 +79,12 @@ struct ed_softc {
#define ED_NOTPRESENT 0x0002 /* card not present; do not allow
reconfiguration */
- int asic_base; /* Base ASIC I/O port */
- int nic_base; /* Base NIC (DS8390) I/O port */
+ bus_chipset_tag_t sc_bc; /* bus identifier */
+ bus_io_handle_t sc_ioh; /* io handle */
+ bus_mem_handle_t sc_memh; /* bus memory handle */
+
+ bus_io_size_t asic_base; /* offset of ASIC I/O port */
+ bus_io_size_t nic_base; /* offset of NIC (DS8390) I/O port */
/*
* The following 'proto' variable is part of a work-around for 8013EBT asics
@@ -98,10 +100,10 @@ struct ed_softc {
u_char isa16bit; /* width of access to card 0=8 or 1=16 */
u_char is790; /* set by probe if NIC is a 790 */
- caddr_t mem_start; /* NIC memory start address */
- caddr_t mem_end; /* NIC memory end address */
- u_long mem_size; /* total NIC memory size */
- caddr_t mem_ring; /* start of RX ring-buffer (in NIC mem) */
+ int mem_start; /* offset of NIC memory */
+ int mem_end; /* offset of NIC memory end */
+ int mem_size; /* total NIC memory size */
+ int mem_ring; /* offset of RX ring-buffer (in NIC mem) */
u_char mem_shared; /* NIC memory is shared with host */
u_char txb_cnt; /* number of transmit buffers */
@@ -120,7 +122,7 @@ int edprobe __P((struct device *, void *, void *));
void edattach __P((struct device *, struct device *, void *));
int ed_find __P((struct ed_softc *, struct cfdata *,
struct isa_attach_args *ia));
-int ed_probe_generic8390 __P((int));
+int ed_probe_generic8390 __P((bus_chipset_tag_t, bus_io_handle_t, int));
int ed_find_WD80x3 __P((struct ed_softc *, struct cfdata *,
struct isa_attach_args *ia));
int ed_find_3Com __P((struct ed_softc *, struct cfdata *,
@@ -135,31 +137,41 @@ void edreset __P((struct ed_softc *));
void edinit __P((struct ed_softc *));
void edstop __P((struct ed_softc *));
+void ed_shared_writemem __P((struct ed_softc *, caddr_t, int, int));
+void ed_shared_readmem __P((struct ed_softc *, int, caddr_t, int));
+
#define inline /* XXX for debugging porpoises */
void ed_getmcaf __P((struct arpcom *, u_long *));
-void edread __P((struct ed_softc *, caddr_t, int));
-struct mbuf *edget __P((struct ed_softc *, caddr_t, int));
+void edread __P((struct ed_softc *, int, int));
+struct mbuf *edget __P((struct ed_softc *, int, int));
static inline void ed_rint __P((struct ed_softc *));
static inline void ed_xmit __P((struct ed_softc *));
-static inline caddr_t ed_ring_copy __P((struct ed_softc *, caddr_t, caddr_t,
+static inline int ed_ring_copy __P((struct ed_softc *, int, caddr_t,
u_short));
void ed_pio_readmem __P((struct ed_softc *, u_short, caddr_t, u_short));
void ed_pio_writemem __P((struct ed_softc *, caddr_t, u_short, u_short));
u_short ed_pio_write_mbufs __P((struct ed_softc *, struct mbuf *, u_short));
-struct cfdriver edcd = {
- NULL, "ed", edprobe, edattach, DV_IFNET, sizeof(struct ed_softc)
+struct cfattach ed_ca = {
+ sizeof(struct ed_softc), edprobe, edattach
+};
+
+struct cfdriver ed_cd = {
+ NULL, "ed", DV_IFNET
};
#define ETHER_MIN_LEN 64
#define ETHER_MAX_LEN 1518
#define ETHER_ADDR_LEN 6
-#define NIC_PUT(base, off, val) outb((base) + (off), (val))
-#define NIC_GET(base, off) inb((base) + (off))
+#define NIC_PUT(bc, ioh, nic, reg, val) \
+ bus_io_write_1((bc), (ioh), ((nic) + (reg)), (val))
+#define NIC_GET(bc, ioh, nic, reg) \
+ bus_io_read_1((bc), (ioh), ((nic) + (reg)))
+/*#include "pcmciabus.h"*/
#if NPCMCIABUS > 0
#include <dev/pcmcia/pcmciabus.h>
@@ -359,15 +371,17 @@ ed_find(sc, cf, ia)
* Return 1 if 8390 was found, 0 if not.
*/
int
-ed_probe_generic8390(nicbase)
+ed_probe_generic8390(bc, ioh, nicbase)
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
int nicbase;
{
- if ((NIC_GET(nicbase, ED_P0_CR) &
+ if ((NIC_GET(bc, ioh, nicbase, ED_P0_CR) &
(ED_CR_RD2 | ED_CR_TXP | ED_CR_STA | ED_CR_STP)) !=
(ED_CR_RD2 | ED_CR_STP))
return (0);
- if ((NIC_GET(nicbase, ED_P0_ISR) & ED_ISR_RST) != ED_ISR_RST)
+ if ((NIC_GET(bc, ioh, nicbase, ED_P0_ISR) & ED_ISR_RST) != ED_ISR_RST)
return (0);
return (1);
@@ -385,17 +399,26 @@ ed_find_WD80x3(sc, cf, ia)
struct cfdata *cf;
struct isa_attach_args *ia;
{
- int i;
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+ bus_mem_handle_t memh;
u_int memsize;
u_char iptr, isa16bit, sum;
+ int i, rv, mapped_mem = 0;
int asicbase, nicbase;
- sc->asic_base = asicbase = ia->ia_iobase;
+ bc = ia->ia_bc;
+ rv = 0;
+
+ if (bus_io_map(bc, ia->ia_iobase, ED_WD_IO_PORTS, &ioh))
+ return (0);
+
+ sc->asic_base = asicbase = 0;
sc->nic_base = nicbase = asicbase + ED_WD_NIC_OFFSET;
sc->is790 = 0;
#ifdef TOSH_ETHER
- outb(asicbase + ED_WD_MSR, ED_WD_MSR_POW);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR, ED_WD_MSR_POW);
delay(10000);
#endif
@@ -406,7 +429,7 @@ ed_find_WD80x3(sc, cf, ia)
* Danpex boards for one.
*/
for (sum = 0, i = 0; i < 8; ++i)
- sum += inb(asicbase + ED_WD_PROM + i);
+ sum += bus_io_read_1(bc, ioh, asicbase + ED_WD_PROM + i);
if (sum != ED_WD_ROM_CHECKSUM_TOTAL) {
/*
@@ -414,25 +437,27 @@ ed_find_WD80x3(sc, cf, ia)
* clones. In this case, the checksum byte (the eighth byte)
* seems to always be zero.
*/
- if (inb(asicbase + ED_WD_CARD_ID) != ED_TYPE_WD8003E ||
- inb(asicbase + ED_WD_PROM + 7) != 0)
- return (0);
+ if (bus_io_read_1(bc, ioh, asicbase + ED_WD_CARD_ID) !=
+ ED_TYPE_WD8003E ||
+ bus_io_read_1(bc, ioh, asicbase + ED_WD_PROM + 7) != 0)
+ goto out;
}
/* Reset card to force it into a known state. */
#ifdef TOSH_ETHER
- outb(asicbase + ED_WD_MSR, ED_WD_MSR_RST | ED_WD_MSR_POW);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR,
+ ED_WD_MSR_RST | ED_WD_MSR_POW);
#else
- outb(asicbase + ED_WD_MSR, ED_WD_MSR_RST);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR, ED_WD_MSR_RST);
#endif
delay(100);
- outb(asicbase + ED_WD_MSR,
- inb(asicbase + ED_WD_MSR) & ~ED_WD_MSR_RST);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR,
+ bus_io_read_1(bc, ioh, asicbase + ED_WD_MSR) & ~ED_WD_MSR_RST);
/* Wait in the case this card is reading it's EEROM. */
delay(5000);
sc->vendor = ED_VENDOR_WD_SMC;
- sc->type = inb(asicbase + ED_WD_CARD_ID);
+ sc->type = bus_io_read_1(bc, ioh, asicbase + ED_WD_CARD_ID);
/* Set initial values for width/size. */
memsize = 8192;
@@ -487,9 +512,11 @@ ed_find_WD80x3(sc, cf, ia)
case ED_TYPE_SMC8216T:
sc->type_str = (sc->type == ED_TYPE_SMC8216C) ?
"SMC8216/SMC8216C" : "SMC8216T";
- outb(asicbase + ED_WD790_HWR,
- inb(asicbase + ED_WD790_HWR) | ED_WD790_HWR_SWH);
- switch (inb(asicbase + ED_WD790_RAR) & ED_WD790_RAR_SZ64) {
+ bus_io_write_1(bc, ioh, asicbase + ED_WD790_HWR,
+ bus_io_read_1(bc, ioh, asicbase + ED_WD790_HWR)
+ | ED_WD790_HWR_SWH);
+ switch (bus_io_read_1(bc, ioh, asicbase + ED_WD790_RAR) &
+ ED_WD790_RAR_SZ64) {
case ED_WD790_RAR_SZ64:
memsize = 65536;
break;
@@ -506,8 +533,9 @@ ed_find_WD80x3(sc, cf, ia)
memsize = 8192;
break;
}
- outb(asicbase + ED_WD790_HWR,
- inb(asicbase + ED_WD790_HWR) & ~ED_WD790_HWR_SWH);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD790_HWR,
+ bus_io_read_1(bc, ioh,
+ asicbase + ED_WD790_HWR) & ~ED_WD790_HWR_SWH);
isa16bit = 1;
sc->is790 = 1;
@@ -536,7 +564,8 @@ ed_find_WD80x3(sc, cf, ia)
#ifdef TOSH_ETHER
(sc->type != ED_TYPE_TOSHIBA1) && (sc->type != ED_TYPE_TOSHIBA4) &&
#endif
- ((inb(asicbase + ED_WD_ICR) & ED_WD_ICR_16BIT) == 0)) {
+ ((bus_io_read_1(bc, ioh,
+ asicbase + ED_WD_ICR) & ED_WD_ICR_16BIT) == 0)) {
isa16bit = 0;
memsize = 8192;
}
@@ -567,13 +596,13 @@ ed_find_WD80x3(sc, cf, ia)
if (sc->is790) {
u_char x;
/* Assemble together the encoded interrupt number. */
- outb(ia->ia_iobase + ED_WD790_HWR,
- inb(ia->ia_iobase + ED_WD790_HWR) | ED_WD790_HWR_SWH);
- x = inb(ia->ia_iobase + ED_WD790_GCR);
+ bus_io_write_1(bc, ioh, ED_WD790_HWR,
+ bus_io_read_1(bc, ioh, ED_WD790_HWR) | ED_WD790_HWR_SWH);
+ x = bus_io_read_1(bc, ioh, ED_WD790_GCR);
iptr = ((x & ED_WD790_GCR_IR2) >> 4) |
((x & (ED_WD790_GCR_IR1|ED_WD790_GCR_IR0)) >> 2);
- outb(ia->ia_iobase + ED_WD790_HWR,
- inb(ia->ia_iobase + ED_WD790_HWR) & ~ED_WD790_HWR_SWH);
+ bus_io_write_1(bc, ioh, ED_WD790_HWR,
+ bus_io_read_1(bc, ioh, ED_WD790_HWR) & ~ED_WD790_HWR_SWH);
/*
* Translate it using translation table, and check for
* correctness.
@@ -583,17 +612,17 @@ ed_find_WD80x3(sc, cf, ia)
printf("%s: irq mismatch; kernel configured %d != board configured %d\n",
sc->sc_dev.dv_xname, ia->ia_irq,
ed_wd790_irq[iptr]);
- return (0);
+ goto out;
}
} else
ia->ia_irq = ed_wd790_irq[iptr];
/* Enable the interrupt. */
- outb(ia->ia_iobase + ED_WD790_ICR,
- inb(ia->ia_iobase + ED_WD790_ICR) | ED_WD790_ICR_EIL);
+ bus_io_write_1(bc, ioh, ED_WD790_ICR,
+ bus_io_read_1(bc, ioh, ED_WD790_ICR) | ED_WD790_ICR_EIL);
} else if (sc->type & ED_WD_SOFTCONFIG) {
/* Assemble together the encoded interrupt number. */
- iptr = (inb(ia->ia_iobase + ED_WD_ICR) & ED_WD_ICR_IR2) |
- ((inb(ia->ia_iobase + ED_WD_IRR) &
+ iptr = (bus_io_read_1(bc, ioh, ED_WD_ICR) & ED_WD_ICR_IR2) |
+ ((bus_io_read_1(bc, ioh, ED_WD_IRR) &
(ED_WD_IRR_IR0 | ED_WD_IRR_IR1)) >> 5);
/*
* Translate it using translation table, and check for
@@ -604,18 +633,18 @@ ed_find_WD80x3(sc, cf, ia)
printf("%s: irq mismatch; kernel configured %d != board configured %d\n",
sc->sc_dev.dv_xname, ia->ia_irq,
ed_wd584_irq[iptr]);
- return (0);
+ goto out;
}
} else
ia->ia_irq = ed_wd584_irq[iptr];
/* Enable the interrupt. */
- outb(ia->ia_iobase + ED_WD_IRR,
- inb(ia->ia_iobase + ED_WD_IRR) | ED_WD_IRR_IEN);
+ bus_io_write_1(bc, ioh, ED_WD_IRR,
+ bus_io_read_1(bc, ioh, ED_WD_IRR) | ED_WD_IRR_IEN);
} else {
if (ia->ia_irq == IRQUNK) {
printf("%s: %s does not have soft configuration\n",
sc->sc_dev.dv_xname, sc->type_str);
- return (0);
+ goto out;
}
}
@@ -624,7 +653,10 @@ ed_find_WD80x3(sc, cf, ia)
sc->isa16bit = isa16bit;
sc->mem_shared = 1;
ia->ia_msize = memsize;
- sc->mem_start = ISA_HOLE_VADDR(ia->ia_maddr);
+ if (bus_mem_map(bc, ia->ia_maddr, memsize, 0, &memh))
+ goto out;
+ mapped_mem = 1;
+ sc->mem_start = 0; /* offset */
/* Allocate one xmit buffer if < 16k, two buffers otherwise. */
if ((memsize < 16384) || (cf->cf_flags & ED_FLAGS_NO_MULTI_BUFFERING))
@@ -642,7 +674,7 @@ ed_find_WD80x3(sc, cf, ia)
/* Get station address from on-board ROM. */
for (i = 0; i < ETHER_ADDR_LEN; ++i)
sc->sc_arpcom.ac_enaddr[i] =
- inb(asicbase + ED_WD_PROM + i);
+ bus_io_read_1(bc, ioh, asicbase + ED_WD_PROM + i);
/*
* Set upper address bits and 8/16 bit access to shared memory.
@@ -650,15 +682,15 @@ ed_find_WD80x3(sc, cf, ia)
if (isa16bit) {
if (sc->is790) {
sc->wd_laar_proto =
- inb(asicbase + ED_WD_LAAR) &
+ bus_io_read_1(bc, ioh, asicbase + ED_WD_LAAR) &
~ED_WD_LAAR_M16EN;
} else {
sc->wd_laar_proto =
ED_WD_LAAR_L16EN |
- ((kvtop(sc->mem_start) >> 19) &
+ ((ia->ia_maddr >> 19) &
ED_WD_LAAR_ADDRHI);
}
- outb(asicbase + ED_WD_LAAR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR,
sc->wd_laar_proto | ED_WD_LAAR_M16EN);
} else {
if ((sc->type & ED_WD_SOFTCONFIG) ||
@@ -668,9 +700,9 @@ ed_find_WD80x3(sc, cf, ia)
#endif
(sc->type == ED_TYPE_WD8013EBT) && !sc->is790) {
sc->wd_laar_proto =
- ((kvtop(sc->mem_start) >> 19) &
+ ((ia->ia_maddr >> 19) &
ED_WD_LAAR_ADDRHI);
- outb(asicbase + ED_WD_LAAR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR,
sc->wd_laar_proto);
}
}
@@ -680,52 +712,53 @@ ed_find_WD80x3(sc, cf, ia)
*/
if (!sc->is790) {
#ifdef TOSH_ETHER
- outb(asicbase + ED_WD_MSR + 1,
- ((kvtop(sc->mem_start) >> 8) & 0xe0) | 4);
- outb(asicbase + ED_WD_MSR + 2,
- ((kvtop(sc->mem_start) >> 16) & 0x0f));
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR + 1,
+ ((ia->ia_maddr >> 8) & 0xe0) | 4);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR + 2,
+ ((ia->ia_maddr >> 16) & 0x0f));
sc->wd_msr_proto = ED_WD_MSR_POW;
#else
sc->wd_msr_proto =
- (kvtop(sc->mem_start) >> 13) & ED_WD_MSR_ADDR;
+ (ia->ia_maddr >> 13) & ED_WD_MSR_ADDR;
#endif
sc->cr_proto = ED_CR_RD2;
} else {
- outb(asicbase + 0x04,
- inb(asicbase + 0x04) | 0x80);
- outb(asicbase + 0x0b,
- ((kvtop(sc->mem_start) >> 13) & 0x0f) |
- ((kvtop(sc->mem_start) >> 11) & 0x40) |
- (inb(asicbase + 0x0b) & 0xb0));
- outb(asicbase + 0x04,
- inb(asicbase + 0x04) & ~0x80);
+ bus_io_write_1(bc, ioh, asicbase + 0x04,
+ bus_io_read_1(bc, ioh, asicbase + 0x04) | 0x80);
+ bus_io_write_1(bc, ioh, asicbase + 0x0b,
+ ((ia->ia_maddr >> 13) & 0x0f) |
+ ((ia->ia_maddr >> 11) & 0x40) |
+ (bus_io_read_1(bc, ioh, asicbase + 0x0b) & 0xb0));
+ bus_io_write_1(bc, ioh, asicbase + 0x04,
+ bus_io_read_1(bc, ioh, asicbase + 0x04) & ~0x80);
sc->wd_msr_proto = 0x00;
sc->cr_proto = 0;
}
- outb(asicbase + ED_WD_MSR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR,
sc->wd_msr_proto | ED_WD_MSR_MENB);
- (void) inb(0x84);
- (void) inb(0x84);
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
/* Now zero memory and verify that it is clear. */
- bzero(sc->mem_start, memsize);
+ for (i = 0; i < memsize; ++i)
+ bus_mem_write_1(bc, memh, sc->mem_start + i, 0);
for (i = 0; i < memsize; ++i)
- if (sc->mem_start[i]) {
+ if (bus_mem_read_1(bc, memh, sc->mem_start + i)) {
printf("%s: failed to clear shared memory at %x - check configuration\n",
sc->sc_dev.dv_xname,
- kvtop(sc->mem_start + i));
+ (ia->ia_maddr + sc->mem_start + i));
/* Disable 16 bit access to shared memory. */
- outb(asicbase + ED_WD_MSR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR,
sc->wd_msr_proto);
if (isa16bit)
- outb(asicbase + ED_WD_LAAR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR,
sc->wd_laar_proto);
- (void) inb(0x84);
- (void) inb(0x84);
- return (0);
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
+ goto out;
}
/*
@@ -736,14 +769,32 @@ ed_find_WD80x3(sc, cf, ia)
* and 2) so that other 8 bit devices with shared memory can be
* used in this 128k region, too.
*/
- outb(asicbase + ED_WD_MSR, sc->wd_msr_proto);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR, sc->wd_msr_proto);
if (isa16bit)
- outb(asicbase + ED_WD_LAAR, sc->wd_laar_proto);
- (void) inb(0x84);
- (void) inb(0x84);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR,
+ sc->wd_laar_proto);
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
ia->ia_iosize = ED_WD_IO_PORTS;
- return (1);
+ rv = 1;
+
+ out:
+ /*
+ * XXX Sould always unmap, but we can't yet.
+ * XXX Need to squish "indirect" first.
+ */
+ if (rv == 0) {
+ bus_io_unmap(bc, ioh, ED_WD_IO_PORTS);
+ if (mapped_mem)
+ bus_mem_unmap(bc, memh, memsize);
+ } else {
+ /* XXX this is all "indirect" brokenness */
+ sc->sc_bc = bc;
+ sc->sc_ioh = ioh;
+ sc->sc_memh = memh;
+ }
+ return (rv);
}
int ed_3com_iobase[] = {0x2e0, 0x2a0, 0x280, 0x250, 0x350, 0x330, 0x310, 0x300};
@@ -761,13 +812,22 @@ ed_find_3Com(sc, cf, ia)
struct cfdata *cf;
struct isa_attach_args *ia;
{
- int i;
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+ bus_mem_handle_t memh;
+ int i, rv, mapped_mem = 0;
u_int memsize;
u_char isa16bit, sum, x;
int ptr, asicbase, nicbase;
- sc->asic_base = asicbase = ia->ia_iobase + ED_3COM_ASIC_OFFSET;
- sc->nic_base = nicbase = ia->ia_iobase + ED_3COM_NIC_OFFSET;
+ bc = ia->ia_bc;
+ rv = 0;
+
+ if (bus_io_map(bc, ia->ia_iobase, ED_WD_IO_PORTS, &ioh))
+ return (0);
+
+ sc->asic_base = asicbase = ED_3COM_ASIC_OFFSET;
+ sc->nic_base = nicbase = ED_3COM_NIC_OFFSET;
/*
* Verify that the kernel configured I/O address matches the board
@@ -777,45 +837,46 @@ ed_find_3Com(sc, cf, ia)
* board is there; after all, we are already talking it at that
* address.
*/
- x = inb(asicbase + ED_3COM_BCFR);
+ x = bus_io_read_1(bc, ioh, asicbase + ED_3COM_BCFR);
if (x == 0 || (x & (x - 1)) != 0)
- return (0);
+ goto out;
ptr = ffs(x) - 1;
if (ia->ia_iobase != IOBASEUNK) {
if (ia->ia_iobase != ed_3com_iobase[ptr]) {
printf("%s: %s mismatch; kernel configured %x != board configured %x\n",
"iobase", sc->sc_dev.dv_xname, ia->ia_iobase,
ed_3com_iobase[ptr]);
- return (0);
+ goto out;
}
} else
- ia->ia_iobase = ed_3com_iobase[ptr];
+ ia->ia_iobase = ed_3com_iobase[ptr]; /* XXX --thorpej */
- x = inb(asicbase + ED_3COM_PCFR);
+ x = bus_io_read_1(bc, ioh, asicbase + ED_3COM_PCFR);
if (x == 0 || (x & (x - 1)) != 0)
- return (0);
+ goto out;
ptr = ffs(x) - 1;
if (ia->ia_maddr != MADDRUNK) {
if (ia->ia_maddr != ed_3com_maddr[ptr]) {
printf("%s: %s mismatch; kernel configured %x != board configured %x\n",
"maddr", sc->sc_dev.dv_xname, ia->ia_maddr,
ed_3com_maddr[ptr]);
- return (0);
+ goto out;
}
} else
ia->ia_maddr = ed_3com_maddr[ptr];
#if 0
- x = inb(asicbase + ED_3COM_IDCFR) & ED_3COM_IDCFR_IRQ;
+ x = bus_io_read_1(bc, ioh, asicbase + ED_3COM_IDCFR) &
+ ED_3COM_IDCFR_IRQ;
if (x == 0 || (x & (x - 1)) != 0)
- return (0);
+ goto out;
ptr = ffs(x) - 1;
if (ia->ia_irq != IRQUNK) {
if (ia->ia_irq != ed_3com_irq[ptr]) {
printf("%s: irq mismatch; kernel configured %d != board configured %d\n",
sc->sc_dev.dv_xname, ia->ia_irq,
ed_3com_irq[ptr]);
- return (0);
+ goto out;
}
} else
ia->ia_irq = ed_3com_irq[ptr];
@@ -826,7 +887,8 @@ ed_find_3Com(sc, cf, ia)
* sequence because it'll lock up if the cable isn't connected if we
* don't.
*/
- outb(asicbase + ED_3COM_CR, ED_3COM_CR_RST | ED_3COM_CR_XSEL);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_CR,
+ ED_3COM_CR_RST | ED_3COM_CR_XSEL);
/* Wait for a while, then un-reset it. */
delay(50);
@@ -836,7 +898,7 @@ ed_find_3Com(sc, cf, ia)
* reset - it's important to set it again after the following outb
* (this is done when we map the PROM below).
*/
- outb(asicbase + ED_3COM_CR, ED_3COM_CR_XSEL);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_CR, ED_3COM_CR_XSEL);
/* Wait a bit for the NIC to recover from the reset. */
delay(5000);
@@ -858,42 +920,49 @@ ed_find_3Com(sc, cf, ia)
* First, map ethernet address PROM over the top of where the NIC
* registers normally appear.
*/
- outb(asicbase + ED_3COM_CR, ED_3COM_CR_EALO | ED_3COM_CR_XSEL);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_CR,
+ ED_3COM_CR_EALO | ED_3COM_CR_XSEL);
for (i = 0; i < ETHER_ADDR_LEN; ++i)
- sc->sc_arpcom.ac_enaddr[i] = NIC_GET(nicbase, i);
+ sc->sc_arpcom.ac_enaddr[i] = NIC_GET(bc, ioh, nicbase, i);
/*
* Unmap PROM - select NIC registers. The proper setting of the
* tranceiver is set in edinit so that the attach code is given a
* chance to set the default based on a compile-time config option.
*/
- outb(asicbase + ED_3COM_CR, ED_3COM_CR_XSEL);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_CR, ED_3COM_CR_XSEL);
/* Determine if this is an 8bit or 16bit board. */
/* Select page 0 registers. */
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
/*
* Attempt to clear WTS bit. If it doesn't clear, then this is a
* 16-bit board.
*/
- NIC_PUT(nicbase, ED_P0_DCR, 0);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_DCR, 0);
/* Select page 2 registers. */
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_2 | ED_CR_STP);
+ NIC_PUT(bc, ioh, nicbase,
+ ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_2 | ED_CR_STP);
/* The 3c503 forces the WTS bit to a one if this is a 16bit board. */
- if (NIC_GET(nicbase, ED_P2_DCR) & ED_DCR_WTS)
+ if (NIC_GET(bc, ioh, nicbase, ED_P2_DCR) & ED_DCR_WTS)
isa16bit = 1;
else
isa16bit = 0;
/* Select page 0 registers. */
- NIC_PUT(nicbase, ED_P2_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
+ NIC_PUT(bc, ioh, nicbase, ED_P2_CR,
+ ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
- sc->mem_start = ISA_HOLE_VADDR(ia->ia_maddr);
+ if (bus_mem_map(bc, ia->ia_maddr, memsize, 0, &memh))
+ goto out;
+ mapped_mem = 1;
+ sc->mem_start = 0; /* offset */
sc->mem_size = memsize;
sc->mem_end = sc->mem_start + memsize;
@@ -934,34 +1003,38 @@ ed_find_3Com(sc, cf, ia)
* Initialize GA page start/stop registers. Probably only needed if
* doing DMA, but what the Hell.
*/
- outb(asicbase + ED_3COM_PSTR, sc->rec_page_start);
- outb(asicbase + ED_3COM_PSPR, sc->rec_page_stop);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_PSTR, sc->rec_page_start);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_PSPR, sc->rec_page_stop);
/* Set IRQ. 3c503 only allows a choice of irq 3-5 or 9. */
switch (ia->ia_irq) {
case 9:
- outb(asicbase + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ2);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_IDCFR,
+ ED_3COM_IDCFR_IRQ2);
break;
case 3:
- outb(asicbase + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ3);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_IDCFR,
+ ED_3COM_IDCFR_IRQ3);
break;
case 4:
- outb(asicbase + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ4);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_IDCFR,
+ ED_3COM_IDCFR_IRQ4);
break;
case 5:
- outb(asicbase + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ5);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_IDCFR,
+ ED_3COM_IDCFR_IRQ5);
break;
default:
printf("%s: invalid irq configuration (%d) must be 3-5 or 9 for 3c503\n",
sc->sc_dev.dv_xname, ia->ia_irq);
- return (0);
+ goto out;
}
/*
* Initialize GA configuration register. Set bank and enable shared
* mem.
*/
- outb(asicbase + ED_3COM_GACFR,
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_GACFR,
ED_3COM_GACFR_RSEL | ED_3COM_GACFR_MBS0);
/*
@@ -970,23 +1043,42 @@ ed_find_3Com(sc, cf, ia)
* shared memory is disabled. We set them to 0xffff0...allegedly the
* reset vector.
*/
- outb(asicbase + ED_3COM_VPTR2, 0xff);
- outb(asicbase + ED_3COM_VPTR1, 0xff);
- outb(asicbase + ED_3COM_VPTR0, 0x00);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_VPTR2, 0xff);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_VPTR1, 0xff);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_VPTR0, 0x00);
/* Zero memory and verify that it is clear. */
- bzero(sc->mem_start, memsize);
+ for (i = 0; i < memsize; ++i)
+ bus_mem_write_1(bc, memh, sc->mem_start + i, 0);
for (i = 0; i < memsize; ++i)
- if (sc->mem_start[i]) {
+ if (bus_mem_read_1(bc, memh, sc->mem_start + i)) {
printf("%s: failed to clear shared memory at %x - check configuration\n",
- sc->sc_dev.dv_xname, kvtop(sc->mem_start + i));
- return (0);
+ sc->sc_dev.dv_xname,
+ (ia->ia_maddr + sc->mem_start + i));
+ goto out;
}
ia->ia_msize = memsize;
ia->ia_iosize = ED_3COM_IO_PORTS;
- return (1);
+ rv = 1;
+
+ out:
+ /*
+ * XXX Sould always unmap, but we can't yet.
+ * XXX Need to squish "indirect" first.
+ */
+ if (rv == 0) {
+ bus_io_unmap(bc, ioh, ED_3COM_IO_PORTS);
+ if (mapped_mem)
+ bus_mem_unmap(bc, memh, memsize);
+ } else {
+ /* XXX this is all "indirect" brokenness */
+ sc->sc_bc = bc;
+ sc->sc_ioh = ioh;
+ sc->sc_memh = memh;
+ }
+ return (rv);
}
/*
@@ -998,23 +1090,32 @@ ed_find_Novell(sc, cf, ia)
struct cfdata *cf;
struct isa_attach_args *ia;
{
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+ bus_mem_handle_t memh;
u_int memsize, n;
u_char romdata[16], isa16bit = 0, tmp;
static u_char test_pattern[32] = "THIS is A memory TEST pattern";
u_char test_buffer[32];
- int asicbase, nicbase;
+ int rv, asicbase, nicbase;
- sc->asic_base = asicbase = ia->ia_iobase + ED_NOVELL_ASIC_OFFSET;
- sc->nic_base = nicbase = ia->ia_iobase + ED_NOVELL_NIC_OFFSET;
+ bc = ia->ia_bc;
+ rv = 0;
+
+ if (bus_io_map(bc, ia->ia_iobase, ED_NOVELL_IO_PORTS, &ioh))
+ return (0);
+
+ sc->asic_base = asicbase = ED_NOVELL_ASIC_OFFSET;
+ sc->nic_base = nicbase = ED_NOVELL_NIC_OFFSET;
/* XXX - do Novell-specific probe here */
/* Reset the board. */
#ifdef GWETHER
- outb(asicbase + ED_NOVELL_RESET, 0);
+ bus_io_write_1(bc, ioh, asicbase + ED_NOVELL_RESET, 0);
delay(200);
#endif /* GWETHER */
- tmp = inb(asicbase + ED_NOVELL_RESET);
+ tmp = bus_io_read_1(bc, ioh, asicbase + ED_NOVELL_RESET);
/*
* I don't know if this is necessary; probably cruft leftover from
@@ -1024,7 +1125,7 @@ ed_find_Novell(sc, cf, ia)
* complete documentation on what the 'right' thing to do is...so we do
* the invasive thing for now. Yuck.]
*/
- outb(asicbase + ED_NOVELL_RESET, tmp);
+ bus_io_write_1(bc, ioh, asicbase + ED_NOVELL_RESET, tmp);
delay(5000);
/*
@@ -1033,13 +1134,14 @@ ed_find_Novell(sc, cf, ia)
* XXX - this makes the probe invasive! ...Done against my better
* judgement. -DLG
*/
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
delay(5000);
/* Make sure that we really have an 8390 based board. */
- if (!ed_probe_generic8390(nicbase))
- return (0);
+ if (!ed_probe_generic8390(bc, ioh, nicbase))
+ goto out;
sc->vendor = ED_VENDOR_NOVELL;
sc->mem_shared = 0;
@@ -1055,17 +1157,23 @@ ed_find_Novell(sc, cf, ia)
* This prevents packets from being stored in the NIC memory when the
* readmem routine turns on the start bit in the CR.
*/
- NIC_PUT(nicbase, ED_P0_RCR, ED_RCR_MON);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RCR, ED_RCR_MON);
/* Temporarily initialize DCR for byte operations. */
- NIC_PUT(nicbase, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
- NIC_PUT(nicbase, ED_P0_PSTART, 8192 >> ED_PAGE_SHIFT);
- NIC_PUT(nicbase, ED_P0_PSTOP, 16384 >> ED_PAGE_SHIFT);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_PSTART, 8192 >> ED_PAGE_SHIFT);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_PSTOP, 16384 >> ED_PAGE_SHIFT);
sc->isa16bit = 0;
/*
+ * XXX indirect brokenness, used by ed_pio{read,write}mem()
+ */
+ sc->sc_bc = bc;
+ sc->sc_ioh = ioh;
+
+ /*
* Write a test pattern in byte mode. If this fails, then there
* probably isn't any memory at 8k - which likely means that the board
* is an NE2000.
@@ -1076,10 +1184,10 @@ ed_find_Novell(sc, cf, ia)
if (bcmp(test_pattern, test_buffer, sizeof(test_pattern))) {
/* not an NE1000 - try NE2000 */
- NIC_PUT(nicbase, ED_P0_DCR,
+ NIC_PUT(bc, ioh, nicbase, ED_P0_DCR,
ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
- NIC_PUT(nicbase, ED_P0_PSTART, 16384 >> ED_PAGE_SHIFT);
- NIC_PUT(nicbase, ED_P0_PSTOP, 32768 >> ED_PAGE_SHIFT);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_PSTART, 16384 >> ED_PAGE_SHIFT);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_PSTOP, 32768 >> ED_PAGE_SHIFT);
sc->isa16bit = 1;
@@ -1091,7 +1199,7 @@ ed_find_Novell(sc, cf, ia)
ed_pio_readmem(sc, 16384, test_buffer, sizeof(test_pattern));
if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)))
- return (0); /* not an NE2000 either */
+ goto out; /* not an NE2000 either */
sc->type = ED_TYPE_NE2000;
sc->type_str = "NE2000";
@@ -1103,7 +1211,7 @@ ed_find_Novell(sc, cf, ia)
if (ia->ia_irq == IRQUNK) {
printf("%s: %s does not have soft configuration\n",
sc->sc_dev.dv_xname, sc->type_str);
- return (0);
+ goto out;
}
/* 8k of memory plus an additional 8k if 16-bit. */
@@ -1117,7 +1225,7 @@ ed_find_Novell(sc, cf, ia)
/* NIC memory doesn't start at zero on an NE board. */
/* The start address is tied to the bus width. */
- sc->mem_start = (caddr_t)(8192 + sc->isa16bit * 8192);
+ sc->mem_start = (8192 + sc->isa16bit * 8192);
sc->tx_page_start = memsize >> ED_PAGE_SHIFT;
#ifdef GWETHER
@@ -1148,7 +1256,7 @@ ed_find_Novell(sc, cf, ia)
if (mstart == 0) {
printf("%s: cannot find start of RAM\n",
sc->sc_dev.dv_xname);
- return (0);
+ goto out;
}
/* Search for the end of RAM. */
@@ -1204,10 +1312,25 @@ ed_find_Novell(sc, cf, ia)
#endif /* GWETHER */
/* Clear any pending interrupts that might have occurred above. */
- NIC_PUT(nicbase, ED_P0_ISR, 0xff);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_ISR, 0xff);
ia->ia_iosize = ED_NOVELL_IO_PORTS;
- return (1);
+ rv = 1;
+
+ out:
+ /*
+ * XXX Sould always unmap, but we can't yet.
+ * XXX Need to squish "indirect" first.
+ */
+ if (rv == 0)
+ bus_io_unmap(bc, ioh, ED_NOVELL_IO_PORTS);
+ else {
+ /* XXX this is all "indirect" brokenness */
+ sc->sc_bc = bc;
+ sc->sc_ioh = ioh;
+ sc->sc_memh = memh;
+ }
+ return (rv);
}
/*
@@ -1218,12 +1341,20 @@ edattach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
struct ed_softc *sc = (void *)self;
struct isa_attach_args *ia = aux;
struct cfdata *cf = sc->sc_dev.dv_cfdata;
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
int asicbase;
+ /*
+ * XXX Should re-map io and mem, but can't
+ * XXX until we squish "indirect" brokenness.
+ */
+ bc = sc->sc_bc; /* XXX */
+ ioh = sc->sc_ioh; /* XXX */
asicbase = sc->asic_base;
@@ -1232,7 +1363,7 @@ edattach(parent, self, aux)
/* Initialize ifnet structure. */
ifp->if_unit = sc->sc_dev.dv_unit;
- ifp->if_name = edcd.cd_name;
+ ifp->if_name = ed_cd.cd_name;
ifp->if_start = edstart;
ifp->if_ioctl = edioctl;
ifp->if_watchdog = edwatchdog;
@@ -1251,7 +1382,8 @@ edattach(parent, self, aux)
case ED_VENDOR_WD_SMC:
if ((sc->type & ED_WD_SOFTCONFIG) == 0)
break;
- if ((inb(asicbase + ED_WD_IRR) & ED_WD_IRR_OUT2) == 0)
+ if ((bus_io_read_1(bc, ioh, asicbase + ED_WD_IRR) &
+ ED_WD_IRR_OUT2) == 0)
ifp->if_flags |= IFF_LINK0;
break;
}
@@ -1264,7 +1396,8 @@ edattach(parent, self, aux)
ether_ifattach(ifp);
/* Print additional info when attached. */
- printf(": address %s, ", ether_sprintf(sc->sc_arpcom.ac_enaddr));
+ printf("\n%s: address %s, ", sc->sc_dev.dv_xname,
+ ether_sprintf(sc->sc_arpcom.ac_enaddr));
if (sc->type_str)
printf("type %s ", sc->type_str);
@@ -1293,8 +1426,8 @@ edattach(parent, self, aux)
sizeof(struct ether_header));
#endif
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NET, edintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, edintr, sc, sc->sc_dev.dv_xname);
sc->sc_sh = shutdownhook_establish((void (*)(void *))edstop, sc);
}
@@ -1320,18 +1453,22 @@ void
edstop(sc)
struct ed_softc *sc;
{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
int nicbase = sc->nic_base;
int n = 5000;
/* Stop everything on the interface, and select page 0 registers. */
- NIC_PUT(nicbase, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
/*
* Wait for interface to enter stopped state, but limit # of checks to
* 'n' (about 5ms). It shouldn't even take 5us on modern DS8390's, but
* just in case it's an old one.
*/
- while (((NIC_GET(nicbase, ED_P0_ISR) & ED_ISR_RST) == 0) && --n);
+ while (((NIC_GET(bc, ioh, nicbase,
+ ED_P0_ISR) & ED_ISR_RST) == 0) && --n);
}
/*
@@ -1342,7 +1479,7 @@ void
edwatchdog(unit)
int unit;
{
- struct ed_softc *sc = edcd.cd_devs[unit];
+ struct ed_softc *sc = ed_cd.cd_devs[unit];
log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
++sc->sc_arpcom.ac_if.if_oerrors;
@@ -1357,6 +1494,8 @@ void
edinit(sc)
struct ed_softc *sc;
{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
int nicbase = sc->nic_base, asicbase = sc->asic_base;
int i;
@@ -1377,44 +1516,45 @@ edinit(sc)
sc->txb_next_tx = 0;
/* Set interface for page 0, remote DMA complete, stopped. */
- NIC_PUT(nicbase, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
if (sc->isa16bit) {
/*
* Set FIFO threshold to 8, No auto-init Remote DMA, byte
* order=80x86, word-wide DMA xfers,
*/
- NIC_PUT(nicbase, ED_P0_DCR,
+ NIC_PUT(bc, ioh, nicbase, ED_P0_DCR,
ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS);
} else {
/* Same as above, but byte-wide DMA xfers. */
- NIC_PUT(nicbase, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
}
/* Clear remote byte count registers. */
- NIC_PUT(nicbase, ED_P0_RBCR0, 0);
- NIC_PUT(nicbase, ED_P0_RBCR1, 0);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RBCR0, 0);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RBCR1, 0);
/* Tell RCR to do nothing for now. */
- NIC_PUT(nicbase, ED_P0_RCR, ED_RCR_MON);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RCR, ED_RCR_MON);
/* Place NIC in internal loopback mode. */
- NIC_PUT(nicbase, ED_P0_TCR, ED_TCR_LB0);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_TCR, ED_TCR_LB0);
/* Set lower bits of byte addressable framing to 0. */
if (sc->is790)
- NIC_PUT(nicbase, 0x09, 0);
+ NIC_PUT(bc, ioh, nicbase, 0x09, 0);
/* Initialize receive buffer ring. */
- NIC_PUT(nicbase, ED_P0_BNRY, sc->rec_page_start);
- NIC_PUT(nicbase, ED_P0_PSTART, sc->rec_page_start);
- NIC_PUT(nicbase, ED_P0_PSTOP, sc->rec_page_stop);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_BNRY, sc->rec_page_start);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_PSTART, sc->rec_page_start);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_PSTOP, sc->rec_page_stop);
/*
* Clear all interrupts. A '1' in each bit position clears the
* corresponding flag.
*/
- NIC_PUT(nicbase, ED_P0_ISR, 0xff);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_ISR, 0xff);
/*
* Enable the following interrupts: receive/transmit complete,
@@ -1422,31 +1562,34 @@ edinit(sc)
*
* Counter overflow and Remote DMA complete are *not* enabled.
*/
- NIC_PUT(nicbase, ED_P0_IMR,
+ NIC_PUT(bc, ioh, nicbase, ED_P0_IMR,
ED_IMR_PRXE | ED_IMR_PTXE | ED_IMR_RXEE | ED_IMR_TXEE |
ED_IMR_OVWE);
/* Program command register for page 1. */
- NIC_PUT(nicbase, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STP);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STP);
/* Copy out our station address. */
for (i = 0; i < ETHER_ADDR_LEN; ++i)
- NIC_PUT(nicbase, ED_P1_PAR0 + i, sc->sc_arpcom.ac_enaddr[i]);
+ NIC_PUT(bc, ioh, nicbase, ED_P1_PAR0 + i,
+ sc->sc_arpcom.ac_enaddr[i]);
/* Set multicast filter on chip. */
ed_getmcaf(&sc->sc_arpcom, mcaf);
for (i = 0; i < 8; i++)
- NIC_PUT(nicbase, ED_P1_MAR0 + i, ((u_char *)mcaf)[i]);
+ NIC_PUT(bc, ioh, nicbase, ED_P1_MAR0 + i, ((u_char *)mcaf)[i]);
/*
* Set current page pointer to one page after the boundary pointer, as
* recommended in the National manual.
*/
sc->next_packet = sc->rec_page_start + 1;
- NIC_PUT(nicbase, ED_P1_CURR, sc->next_packet);
+ NIC_PUT(bc, ioh, nicbase, ED_P1_CURR, sc->next_packet);
/* Program command register for page 0. */
- NIC_PUT(nicbase, ED_P1_CR, sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
+ NIC_PUT(bc, ioh, nicbase, ED_P1_CR,
+ sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
i = ED_RCR_AB | ED_RCR_AM;
if (ifp->if_flags & IFF_PROMISC) {
@@ -1456,10 +1599,10 @@ edinit(sc)
*/
i |= ED_RCR_PRO | ED_RCR_AR | ED_RCR_SEP;
}
- NIC_PUT(nicbase, ED_P0_RCR, i);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RCR, i);
/* Take interface out of loopback. */
- NIC_PUT(nicbase, ED_P0_TCR, 0);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_TCR, 0);
/*
* If this is a 3Com board, the tranceiver must be software enabled
@@ -1469,24 +1612,26 @@ edinit(sc)
u_char x;
case ED_VENDOR_3COM:
if (ifp->if_flags & IFF_LINK0)
- outb(asicbase + ED_3COM_CR, 0);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_CR, 0);
else
- outb(asicbase + ED_3COM_CR, ED_3COM_CR_XSEL);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_CR,
+ ED_3COM_CR_XSEL);
break;
case ED_VENDOR_WD_SMC:
if ((sc->type & ED_WD_SOFTCONFIG) == 0)
break;
- x = inb(asicbase + ED_WD_IRR);
+ x = bus_io_read_1(bc, ioh, asicbase + ED_WD_IRR);
if (ifp->if_flags & IFF_LINK0)
x &= ~ED_WD_IRR_OUT2;
else
x |= ED_WD_IRR_OUT2;
- outb(asicbase + ED_WD_IRR, x);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_IRR, x);
break;
}
/* Fire up the interface. */
- NIC_PUT(nicbase, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
/* Set 'running' flag, and clear output active flag. */
ifp->if_flags |= IFF_RUNNING;
@@ -1503,6 +1648,8 @@ static inline void
ed_xmit(sc)
struct ed_softc *sc;
{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
int nicbase = sc->nic_base;
u_short len;
@@ -1510,18 +1657,19 @@ ed_xmit(sc)
len = sc->txb_len[sc->txb_next_tx];
/* Set NIC for page 0 register access. */
- NIC_PUT(nicbase, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
/* Set TX buffer start page. */
- NIC_PUT(nicbase, ED_P0_TPSR, sc->tx_page_start +
+ NIC_PUT(bc, ioh, nicbase, ED_P0_TPSR, sc->tx_page_start +
sc->txb_next_tx * ED_TXBUF_SIZE);
/* Set TX length. */
- NIC_PUT(nicbase, ED_P0_TBCR0, len);
- NIC_PUT(nicbase, ED_P0_TBCR1, len >> 8);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_TBCR0, len);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_TBCR1, len >> 8);
/* Set page 0, remote DMA complete, transmit packet, and *start*. */
- NIC_PUT(nicbase, ED_P0_CR,
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
sc->cr_proto | ED_CR_PAGE_0 | ED_CR_TXP | ED_CR_STA);
/* Point to next transmit buffer slot and wrap if necessary. */
@@ -1546,11 +1694,13 @@ void
edstart(ifp)
struct ifnet *ifp;
{
- struct ed_softc *sc = edcd.cd_devs[ifp->if_unit];
+ struct ed_softc *sc = ed_cd.cd_devs[ifp->if_unit];
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
struct mbuf *m0, *m;
- caddr_t buffer;
+ int buffer;
int asicbase = sc->asic_base;
- int len;
+ int len, i;
if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
return;
@@ -1578,7 +1728,8 @@ outloop:
#endif
/* txb_new points to next open buffer slot. */
- buffer = sc->mem_start + ((sc->txb_new * ED_TXBUF_SIZE) << ED_PAGE_SHIFT);
+ buffer = sc->mem_start +
+ ((sc->txb_new * ED_TXBUF_SIZE) << ED_PAGE_SHIFT);
if (sc->mem_shared) {
/* Special case setup for 16 bit boards... */
@@ -1590,7 +1741,8 @@ outloop:
*/
case ED_VENDOR_3COM:
if (sc->isa16bit)
- outb(asicbase + ED_3COM_GACFR,
+ bus_io_write_1(bc, ioh,
+ asicbase + ED_3COM_GACFR,
ED_3COM_GACFR_RSEL);
break;
/*
@@ -1599,17 +1751,18 @@ outloop:
*/
case ED_VENDOR_WD_SMC:
if (sc->isa16bit)
- outb(asicbase + ED_WD_LAAR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR,
sc->wd_laar_proto | ED_WD_LAAR_M16EN);
- outb(asicbase + ED_WD_MSR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR,
sc->wd_msr_proto | ED_WD_MSR_MENB);
- (void) inb(0x84);
- (void) inb(0x84);
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
break;
}
for (m = m0; m != 0; m = m->m_next) {
- bcopy(mtod(m, caddr_t), buffer, m->m_len);
+ ed_shared_writemem(sc, mtod(m, caddr_t), buffer,
+ m->m_len);
buffer += m->m_len;
}
len = m0->m_pkthdr.len;
@@ -1618,17 +1771,18 @@ outloop:
switch (sc->vendor) {
case ED_VENDOR_3COM:
if (sc->isa16bit)
- outb(asicbase + ED_3COM_GACFR,
+ bus_io_write_1(bc, ioh,
+ asicbase + ED_3COM_GACFR,
ED_3COM_GACFR_RSEL | ED_3COM_GACFR_MBS0);
break;
case ED_VENDOR_WD_SMC:
- outb(asicbase + ED_WD_MSR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR,
sc->wd_msr_proto);
if (sc->isa16bit)
- outb(asicbase + ED_WD_LAAR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR,
sc->wd_laar_proto);
- (void) inb(0x84);
- (void) inb(0x84);
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
break;
}
} else
@@ -1657,16 +1811,19 @@ static inline void
ed_rint(sc)
struct ed_softc *sc;
{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
int nicbase = sc->nic_base;
u_char boundary, current;
u_short len;
u_char nlen;
struct ed_ring packet_hdr;
- caddr_t packet_ptr;
+ int packet_ptr;
loop:
/* Set NIC to page 1 registers to get 'current' pointer. */
- NIC_PUT(nicbase, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STA);
/*
* 'sc->next_packet' is the logical beginning of the ring-buffer - i.e.
@@ -1676,12 +1833,13 @@ loop:
* until the logical beginning equals the logical end (or in other
* words, until the ring-buffer is empty).
*/
- current = NIC_GET(nicbase, ED_P1_CURR);
+ current = NIC_GET(bc, ioh, nicbase, ED_P1_CURR);
if (sc->next_packet == current)
return;
/* Set NIC to page 0 registers to update boundary register. */
- NIC_PUT(nicbase, ED_P1_CR, sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P1_CR,
+ sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
do {
/* Get pointer to this buffer's header structure. */
@@ -1693,7 +1851,8 @@ loop:
* the NIC.
*/
if (sc->mem_shared)
- packet_hdr = *(struct ed_ring *)packet_ptr;
+ ed_shared_readmem(sc, packet_ptr, (caddr_t)&packet_hdr,
+ sizeof(packet_hdr));
else
ed_pio_readmem(sc, (long)packet_ptr,
(caddr_t) &packet_hdr, sizeof(packet_hdr));
@@ -1761,7 +1920,7 @@ loop:
boundary = sc->next_packet - 1;
if (boundary < sc->rec_page_start)
boundary = sc->rec_page_stop - 1;
- NIC_PUT(nicbase, ED_P0_BNRY, boundary);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_BNRY, boundary);
} while (sc->next_packet != current);
goto loop;
@@ -1773,14 +1932,17 @@ edintr(arg)
void *arg;
{
struct ed_softc *sc = arg;
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
int nicbase = sc->nic_base, asicbase = sc->asic_base;
u_char isr;
/* Set NIC to page 0 registers. */
- NIC_PUT(nicbase, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
- isr = NIC_GET(nicbase, ED_P0_ISR);
+ isr = NIC_GET(bc, ioh, nicbase, ED_P0_ISR);
if (!isr)
return (0);
@@ -1791,14 +1953,15 @@ edintr(arg)
* '1' to each bit position that was set.
* (Writing a '1' *clears* the bit.)
*/
- NIC_PUT(nicbase, ED_P0_ISR, isr);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_ISR, isr);
/*
* Handle transmitter interrupts. Handle these first because
* the receiver will reset the board under some conditions.
*/
if (isr & (ED_ISR_PTX | ED_ISR_TXE)) {
- u_char collisions = NIC_GET(nicbase, ED_P0_NCR) & 0x0f;
+ u_char collisions = NIC_GET(bc, ioh, nicbase,
+ ED_P0_NCR) & 0x0f;
/*
* Check for transmit error. If a TX completed with an
@@ -1809,13 +1972,13 @@ edintr(arg)
* course, with UDP we're screwed, but this is expected
* when a network is heavily loaded.
*/
- (void) NIC_GET(nicbase, ED_P0_TSR);
+ (void) NIC_GET(bc, ioh, nicbase, ED_P0_TSR);
if (isr & ED_ISR_TXE) {
/*
* Excessive collisions (16).
*/
- if ((NIC_GET(nicbase, ED_P0_TSR) & ED_TSR_ABT)
- && (collisions == 0)) {
+ if ((NIC_GET(bc, ioh, nicbase, ED_P0_TSR) &
+ ED_TSR_ABT) && (collisions == 0)) {
/*
* When collisions total 16, the P0_NCR
* will indicate 0, and the TSR_ABT is
@@ -1907,25 +2070,32 @@ edintr(arg)
*/
if (sc->vendor == ED_VENDOR_WD_SMC) {
if (sc->isa16bit)
- outb(asicbase + ED_WD_LAAR,
- sc->wd_laar_proto | ED_WD_LAAR_M16EN);
- outb(asicbase + ED_WD_MSR,
+ bus_io_write_1(bc, ioh,
+ asicbase + ED_WD_LAAR,
+ sc->wd_laar_proto |
+ ED_WD_LAAR_M16EN);
+ bus_io_write_1(bc, ioh,
+ asicbase + ED_WD_MSR,
sc->wd_msr_proto | ED_WD_MSR_MENB);
- (void) inb(0x84);
- (void) inb(0x84);
+ /* XXX */
+ (void) bus_io_read_1(bc, ioh, 0x84);
+ (void) bus_io_read_1(bc, ioh, 0x84);
}
ed_rint(sc);
/* Disable 16-bit access. */
if (sc->vendor == ED_VENDOR_WD_SMC) {
- outb(asicbase + ED_WD_MSR,
+ bus_io_write_1(bc, ioh,
+ asicbase + ED_WD_MSR,
sc->wd_msr_proto);
if (sc->isa16bit)
- outb(asicbase + ED_WD_LAAR,
+ bus_io_write_1(bc, ioh,
+ asicbase + ED_WD_LAAR,
sc->wd_laar_proto);
- (void) inb(0x84);
- (void) inb(0x84);
+ /* XXX */
+ (void) bus_io_read_1(bc, ioh, 0x84);
+ (void) bus_io_read_1(bc, ioh, 0x84);
}
}
}
@@ -1943,7 +2113,7 @@ edintr(arg)
* set in the transmit routine, is *okay* - it is 'edge'
* triggered from low to high).
*/
- NIC_PUT(nicbase, ED_P0_CR,
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
/*
@@ -1952,12 +2122,12 @@ edintr(arg)
* otherwise - resulting in an infinite loop.
*/
if (isr & ED_ISR_CNT) {
- (void) NIC_GET(nicbase, ED_P0_CNTR0);
- (void) NIC_GET(nicbase, ED_P0_CNTR1);
- (void) NIC_GET(nicbase, ED_P0_CNTR2);
+ (void) NIC_GET(bc, ioh, nicbase, ED_P0_CNTR0);
+ (void) NIC_GET(bc, ioh, nicbase, ED_P0_CNTR1);
+ (void) NIC_GET(bc, ioh, nicbase, ED_P0_CNTR2);
}
- isr = NIC_GET(nicbase, ED_P0_ISR);
+ isr = NIC_GET(bc, ioh, nicbase, ED_P0_ISR);
if (!isr)
return (1);
}
@@ -1972,7 +2142,7 @@ edioctl(ifp, cmd, data)
u_long cmd;
caddr_t data;
{
- struct ed_softc *sc = edcd.cd_devs[ifp->if_unit];
+ struct ed_softc *sc = ed_cd.cd_devs[ifp->if_unit];
register struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
@@ -2081,8 +2251,7 @@ edioctl(ifp, cmd, data)
void
edread(sc, buf, len)
struct ed_softc *sc;
- caddr_t buf;
- int len;
+ int buf, len;
{
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
struct mbuf *m;
@@ -2145,29 +2314,35 @@ ed_pio_readmem(sc, src, dst, amount)
caddr_t dst;
u_short amount;
{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
int nicbase = sc->nic_base;
/* Select page 0 registers. */
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
/* Round up to a word. */
if (amount & 1)
++amount;
/* Set up DMA byte count. */
- NIC_PUT(nicbase, ED_P0_RBCR0, amount);
- NIC_PUT(nicbase, ED_P0_RBCR1, amount >> 8);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RBCR0, amount);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RBCR1, amount >> 8);
/* Set up source address in NIC mem. */
- NIC_PUT(nicbase, ED_P0_RSAR0, src);
- NIC_PUT(nicbase, ED_P0_RSAR1, src >> 8);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RSAR0, src);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RSAR1, src >> 8);
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD0 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ ED_CR_RD0 | ED_CR_PAGE_0 | ED_CR_STA);
if (sc->isa16bit)
- insw(sc->asic_base + ED_NOVELL_DATA, dst, amount / 2);
+ bus_io_read_multi_2(bc, ioh, sc->asic_base + ED_NOVELL_DATA,
+ dst, amount / 2);
else
- insb(sc->asic_base + ED_NOVELL_DATA, dst, amount);
+ bus_io_read_multi_1(bc, ioh, sc->asic_base + ED_NOVELL_DATA,
+ dst, amount);
}
/*
@@ -2181,30 +2356,36 @@ ed_pio_writemem(sc, src, dst, len)
u_short dst;
u_short len;
{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
int nicbase = sc->nic_base;
int maxwait = 100; /* about 120us */
/* Select page 0 registers. */
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
/* Reset remote DMA complete flag. */
- NIC_PUT(nicbase, ED_P0_ISR, ED_ISR_RDC);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_ISR, ED_ISR_RDC);
/* Set up DMA byte count. */
- NIC_PUT(nicbase, ED_P0_RBCR0, len);
- NIC_PUT(nicbase, ED_P0_RBCR1, len >> 8);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RBCR0, len);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RBCR1, len >> 8);
/* Set up destination address in NIC mem. */
- NIC_PUT(nicbase, ED_P0_RSAR0, dst);
- NIC_PUT(nicbase, ED_P0_RSAR1, dst >> 8);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RSAR0, dst);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RSAR1, dst >> 8);
/* Set remote DMA write. */
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD1 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ ED_CR_RD1 | ED_CR_PAGE_0 | ED_CR_STA);
if (sc->isa16bit)
- outsw(sc->asic_base + ED_NOVELL_DATA, src, len / 2);
+ bus_io_write_multi_2(bc, ioh, sc->asic_base + ED_NOVELL_DATA,
+ src, len / 2);
else
- outsb(sc->asic_base + ED_NOVELL_DATA, src, len);
+ bus_io_write_multi_1(bc, ioh, sc->asic_base + ED_NOVELL_DATA,
+ src, len);
/*
* Wait for remote DMA complete. This is necessary because on the
@@ -2213,8 +2394,8 @@ ed_pio_writemem(sc, src, dst, len)
* waiting causes really bad things to happen - like the NIC
* irrecoverably jamming the ISA bus.
*/
- while (((NIC_GET(nicbase, ED_P0_ISR) & ED_ISR_RDC) != ED_ISR_RDC) &&
- --maxwait);
+ while (((NIC_GET(bc, ioh, nicbase, ED_P0_ISR) & ED_ISR_RDC) !=
+ ED_ISR_RDC) && --maxwait);
}
/*
@@ -2227,6 +2408,8 @@ ed_pio_write_mbufs(sc, m, dst)
struct mbuf *m;
u_short dst;
{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
int nicbase = sc->nic_base, asicbase = sc->asic_base;
u_short len;
struct mbuf *mp;
@@ -2235,21 +2418,23 @@ ed_pio_write_mbufs(sc, m, dst)
len = m->m_pkthdr.len;
/* Select page 0 registers. */
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
/* Reset remote DMA complete flag. */
- NIC_PUT(nicbase, ED_P0_ISR, ED_ISR_RDC);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_ISR, ED_ISR_RDC);
/* Set up DMA byte count. */
- NIC_PUT(nicbase, ED_P0_RBCR0, len);
- NIC_PUT(nicbase, ED_P0_RBCR1, len >> 8);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RBCR0, len);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RBCR1, len >> 8);
/* Set up destination address in NIC mem. */
- NIC_PUT(nicbase, ED_P0_RSAR0, dst);
- NIC_PUT(nicbase, ED_P0_RSAR1, dst >> 8);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RSAR0, dst);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RSAR1, dst >> 8);
/* Set remote DMA write. */
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD1 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ ED_CR_RD1 | ED_CR_PAGE_0 | ED_CR_STA);
/*
* Transfer the mbuf chain to the NIC memory.
@@ -2261,13 +2446,14 @@ ed_pio_write_mbufs(sc, m, dst)
/* NE1000s are easy. */
for (; m != 0; m = m->m_next) {
if (m->m_len) {
- outsb(asicbase + ED_NOVELL_DATA,
+ bus_io_write_multi_1(bc, ioh,
+ asicbase + ED_NOVELL_DATA,
mtod(m, u_char *), m->m_len);
}
}
} else {
/* NE2000s are a bit trickier. */
- u_char *data, savebyte[2];
+ u_int8_t *data, savebyte[2];
int len, wantbyte;
wantbyte = 0;
@@ -2275,20 +2461,23 @@ ed_pio_write_mbufs(sc, m, dst)
len = m->m_len;
if (len == 0)
continue;
- data = mtod(m, u_char *);
+ data = mtod(m, u_int8_t *);
/* Finish the last word. */
if (wantbyte) {
savebyte[1] = *data;
- outw(asicbase + ED_NOVELL_DATA,
- *(u_short *)savebyte);
+ bus_io_write_2(bc, ioh,
+ asicbase + ED_NOVELL_DATA,
+ *(u_int16_t *)savebyte);
data++;
len--;
wantbyte = 0;
}
/* Output contiguous words. */
- if (len > 1)
- outsw(asicbase + ED_NOVELL_DATA,
+ if (len > 1) {
+ bus_io_write_multi_2(bc, ioh,
+ asicbase + ED_NOVELL_DATA,
data, len >> 1);
+ }
/* Save last byte, if necessary. */
if (len & 1) {
data += len & ~1;
@@ -2299,7 +2488,8 @@ ed_pio_write_mbufs(sc, m, dst)
if (wantbyte) {
savebyte[1] = 0;
- outw(asicbase + ED_NOVELL_DATA, *(u_short *)savebyte);
+ bus_io_write_2(bc, ioh, asicbase + ED_NOVELL_DATA,
+ *(u_int16_t *)savebyte);
}
}
@@ -2310,8 +2500,8 @@ ed_pio_write_mbufs(sc, m, dst)
* waiting causes really bad things to happen - like the NIC
* irrecoverably jamming the ISA bus.
*/
- while (((NIC_GET(nicbase, ED_P0_ISR) & ED_ISR_RDC) != ED_ISR_RDC) &&
- --maxwait);
+ while (((NIC_GET(bc, ioh, nicbase, ED_P0_ISR) & ED_ISR_RDC) !=
+ ED_ISR_RDC) && --maxwait);
if (!maxwait) {
log(LOG_WARNING,
@@ -2327,10 +2517,11 @@ ed_pio_write_mbufs(sc, m, dst)
* Given a source and destination address, copy 'amount' of a packet from the
* ring buffer into a linear destination buffer. Takes into account ring-wrap.
*/
-static inline caddr_t
+static inline int
ed_ring_copy(sc, src, dst, amount)
struct ed_softc *sc;
- caddr_t src, dst;
+ int src;
+ caddr_t dst;
u_short amount;
{
u_short tmp_amount;
@@ -2341,7 +2532,7 @@ ed_ring_copy(sc, src, dst, amount)
/* Copy amount up to end of NIC memory. */
if (sc->mem_shared)
- bcopy(src, dst, tmp_amount);
+ ed_shared_readmem(sc, src, dst, tmp_amount);
else
ed_pio_readmem(sc, (long)src, dst, tmp_amount);
@@ -2351,7 +2542,7 @@ ed_ring_copy(sc, src, dst, amount)
}
if (sc->mem_shared)
- bcopy(src, dst, amount);
+ ed_shared_readmem(sc, src, dst, amount);
else
ed_pio_readmem(sc, (long)src, dst, amount);
@@ -2369,7 +2560,7 @@ ed_ring_copy(sc, src, dst, amount)
struct mbuf *
edget(sc, src, total_len)
struct ed_softc *sc;
- caddr_t src;
+ int src;
u_short total_len;
{
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
@@ -2480,3 +2671,37 @@ ed_getmcaf(ac, af)
}
ifp->if_flags &= ~IFF_ALLMULTI;
}
+
+void
+ed_shared_writemem(sc, buf, card, len)
+ struct ed_softc *sc;
+ caddr_t buf;
+ int card, len;
+{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_mem_handle_t memh = sc->sc_memh;
+ u_int8_t *ptr = (u_int8_t *)buf;
+ int i;
+
+ /* XXX should have bus_mem_copyout_{1,2,4,8}() */
+
+ for (i = 0; i < len; ++i)
+ bus_mem_write_1(bc, memh, card + i, ptr[i]);
+}
+
+void
+ed_shared_readmem(sc, card, buf, len)
+ struct ed_softc *sc;
+ caddr_t buf;
+ int card, len;
+{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_mem_handle_t memh = sc->sc_memh;
+ u_int8_t *ptr = (u_int8_t *)buf;
+ int i;
+
+ /* XXX should have bus_mem_copyin_{1,2,4,8}() */
+
+ for (i = 0; i < len; ++i)
+ ptr[i] = bus_mem_read_1(bc, memh, card + i);
+}
diff --git a/sys/dev/isa/if_eg.c b/sys/dev/isa/if_eg.c
index 3ecd3de9390..6a52e9d6f55 100644
--- a/sys/dev/isa/if_eg.c
+++ b/sys/dev/isa/if_eg.c
@@ -1,4 +1,4 @@
-/* $NetBSD: if_eg.c,v 1.22 1996/01/10 18:21:52 hpeyerl Exp $ */
+/* $NetBSD: if_eg.c,v 1.24 1996/04/11 22:29:03 cgd Exp $ */
/*
* Copyright (c) 1993 Dean Huxley <dean@fsa.ca>
@@ -117,8 +117,12 @@ struct eg_softc {
int egprobe __P((struct device *, void *, void *));
void egattach __P((struct device *, struct device *, void *));
-struct cfdriver egcd = {
- NULL, "eg", egprobe, egattach, DV_IFNET, sizeof(struct eg_softc)
+struct cfattach eg_ca = {
+ sizeof(struct eg_softc), egprobe, egattach
+};
+
+struct cfdriver eg_cd = {
+ NULL, "eg", DV_IFNET
};
int egintr __P((void *));
@@ -398,7 +402,7 @@ egattach(parent, self, aux)
/* Initialize ifnet structure. */
ifp->if_unit = sc->sc_dev.dv_unit;
- ifp->if_name = egcd.cd_name;
+ ifp->if_name = eg_cd.cd_name;
ifp->if_start = egstart;
ifp->if_ioctl = egioctl;
ifp->if_watchdog = egwatchdog;
@@ -412,8 +416,8 @@ egattach(parent, self, aux)
bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
#endif
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NET, egintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, egintr, sc, sc->sc_dev.dv_xname);
}
void
@@ -490,7 +494,7 @@ void
egstart(ifp)
struct ifnet *ifp;
{
- register struct eg_softc *sc = egcd.cd_devs[ifp->if_unit];
+ register struct eg_softc *sc = eg_cd.cd_devs[ifp->if_unit];
struct mbuf *m0, *m;
caddr_t buffer;
int len;
@@ -729,7 +733,7 @@ egioctl(ifp, cmd, data)
u_long cmd;
caddr_t data;
{
- struct eg_softc *sc = egcd.cd_devs[ifp->if_unit];
+ struct eg_softc *sc = eg_cd.cd_devs[ifp->if_unit];
struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
@@ -826,7 +830,7 @@ void
egwatchdog(unit)
int unit;
{
- struct eg_softc *sc = egcd.cd_devs[unit];
+ struct eg_softc *sc = eg_cd.cd_devs[unit];
log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
sc->sc_arpcom.ac_if.if_oerrors++;
diff --git a/sys/dev/isa/if_el.c b/sys/dev/isa/if_el.c
index b7f889b7c22..ea751159744 100644
--- a/sys/dev/isa/if_el.c
+++ b/sys/dev/isa/if_el.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: if_el.c,v 1.6 1996/03/20 01:00:48 mickey Exp $ */
-/* $NetBSD: if_el.c,v 1.34 1995/12/24 02:31:25 mycroft Exp $ */
+/* $OpenBSD: if_el.c,v 1.7 1996/04/21 22:23:48 deraadt Exp $ */
+/* $NetBSD: if_el.c,v 1.36 1996/04/11 22:29:07 cgd Exp $ */
/*
* Copyright (c) 1994, Matthew E. Kimmel. Permission is hereby granted
@@ -97,9 +97,12 @@ static inline void el_hardreset __P((struct el_softc *));
int elprobe __P((struct device *, void *, void *));
void elattach __P((struct device *, struct device *, void *));
-/* isa_driver structure for autoconf */
-struct cfdriver elcd = {
- NULL, "el", elprobe, elattach, DV_IFNET, sizeof(struct el_softc)
+struct cfattach el_ca = {
+ sizeof(struct el_softc), elprobe, elattach
+};
+
+struct cfdriver el_cd = {
+ NULL, "el", DV_IFNET
};
/*
@@ -186,7 +189,7 @@ elattach(parent, self, aux)
/* Initialize ifnet structure. */
ifp->if_unit = sc->sc_dev.dv_unit;
- ifp->if_name = elcd.cd_name;
+ ifp->if_name = el_cd.cd_name;
ifp->if_start = elstart;
ifp->if_ioctl = elioctl;
ifp->if_watchdog = elwatchdog;
@@ -206,8 +209,8 @@ elattach(parent, self, aux)
bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
#endif
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NET, elintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, elintr, sc, sc->sc_dev.dv_xname);
dprintf(("elattach() finished.\n"));
}
@@ -304,7 +307,7 @@ void
elstart(ifp)
struct ifnet *ifp;
{
- struct el_softc *sc = elcd.cd_devs[ifp->if_unit];
+ struct el_softc *sc = el_cd.cd_devs[ifp->if_unit];
int iobase = sc->sc_iobase;
struct mbuf *m, *m0;
int s, i, off, retries;
@@ -616,7 +619,7 @@ elioctl(ifp, cmd, data)
u_long cmd;
caddr_t data;
{
- struct el_softc *sc = elcd.cd_devs[ifp->if_unit];
+ struct el_softc *sc = el_cd.cd_devs[ifp->if_unit];
struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
@@ -700,7 +703,7 @@ void
elwatchdog(unit)
int unit;
{
- struct el_softc *sc = elcd.cd_devs[unit];
+ struct el_softc *sc = el_cd.cd_devs[unit];
log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
sc->sc_arpcom.ac_if.if_oerrors++;
diff --git a/sys/dev/isa/if_ep.c b/sys/dev/isa/if_ep.c
index 887bb575548..4102ad294e4 100644
--- a/sys/dev/isa/if_ep.c
+++ b/sys/dev/isa/if_ep.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: if_ep.c,v 1.10 1996/04/18 23:47:40 niklas Exp $ */
-/* $NetBSD: if_ep.c,v 1.87 1996/02/19 20:18:40 christos Exp $ */
+/* $OpenBSD: if_ep.c,v 1.11 1996/04/21 22:23:52 deraadt Exp $ */
+/* $NetBSD: if_ep.c,v 1.90 1996/04/11 22:29:15 cgd Exp $ */
/*
* Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
@@ -31,7 +31,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "pcmciabus.h"
+/*#include "pcmciabus.h"*/
#include "bpfilter.h"
#include <sys/param.h>
@@ -119,8 +119,17 @@ struct ep_softc {
static int epprobe __P((struct device *, void *, void *));
static void epattach __P((struct device *, struct device *, void *));
-struct cfdriver epcd = {
- NULL, "ep", epprobe, epattach, DV_IFNET, sizeof(struct ep_softc)
+/* XXX the following two structs should be different. */
+struct cfattach ep_isa_ca = {
+ sizeof(struct ep_softc), epprobe, epattach
+};
+
+struct cfattach ep_pci_ca = {
+ sizeof(struct ep_softc), epprobe, epattach
+};
+
+struct cfdriver ep_cd = {
+ NULL, "ep", DV_IFNET
};
int epintr __P((void *));
@@ -326,9 +335,9 @@ epprobe(parent, match, aux)
int k, k2;
#if NPCI > 0
- extern struct cfdriver pcicd;
+ extern struct cfdriver pci_cd;
- if (parent->dv_cfdata->cf_driver == &pcicd) {
+ if (parent->dv_cfdata->cf_driver == &pci_cd) {
struct pci_attach_args *pa = (struct pci_attach_args *) aux;
if (PCI_VENDORID(pa->pa_id) != PCI_VENDOR_3COM)
@@ -497,7 +506,7 @@ epconfig(sc, conn)
printf(" address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
ifp->if_unit = sc->sc_dev.dv_unit;
- ifp->if_name = epcd.cd_name;
+ ifp->if_name = ep_cd.cd_name;
ifp->if_start = epstart;
ifp->if_ioctl = epioctl;
ifp->if_watchdog = epwatchdog;
@@ -523,9 +532,9 @@ epattach(parent, self, aux)
struct ep_softc *sc = (void *)self;
u_short conn = 0;
#if NPCI > 0
- extern struct cfdriver pcicd;
+ extern struct cfdriver pci_cd;
- if (parent->dv_cfdata->cf_driver == &pcicd) {
+ if (parent->dv_cfdata->cf_driver == &pci_cd) {
struct pci_attach_args *pa = aux;
int iobase;
u_short i;
@@ -536,7 +545,7 @@ epattach(parent, self, aux)
}
sc->bustype = EP_BUS_PCI;
sc->ep_iobase = iobase; /* & 0xfffffff0 */
- i = pci_conf_read(pa->pa_tag, PCI_CONN);
+ i = pci_conf_read(pa->pa_bc, pa->pa_tag, PCI_CONN);
/*
* Bits 13,12,9 of the isa adapter are the same as bits
@@ -565,16 +574,15 @@ epattach(parent, self, aux)
#if NPCI > 0
- if (parent->dv_cfdata->cf_driver == &pcicd) {
+ if (parent->dv_cfdata->cf_driver == &pci_cd) {
struct pci_attach_args *pa = aux;
- pci_conf_write(pa->pa_tag, PCI_COMMAND_STATUS_REG,
- pci_conf_read(pa->pa_tag,
+ pci_conf_write(pa->pa_bc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
+ pci_conf_read(pa->pa_bc, pa->pa_tag,
PCI_COMMAND_STATUS_REG) |
PCI_COMMAND_MASTER_ENABLE);
- sc->sc_ih = pci_map_int(pa->pa_tag, IPL_NET, epintr, sc,
- sc->sc_dev.dv_xname);
+ sc->sc_ih = pci_map_int(pa->pa_tag, IPL_NET, epintr, sc);
if (sc->sc_ih == NULL) {
printf("%s: couldn't map interrupt\n",
sc->sc_dev.dv_xname);
@@ -586,8 +594,8 @@ epattach(parent, self, aux)
#endif
{
struct isa_attach_args *ia = aux;
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NET,
- epintr, sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq,
+ IST_EDGE, IPL_NET, epintr, sc, sc->sc_dev.dv_xname);
}
}
@@ -721,7 +729,7 @@ void
epstart(ifp)
struct ifnet *ifp;
{
- register struct ep_softc *sc = epcd.cd_devs[ifp->if_unit];
+ register struct ep_softc *sc = ep_cd.cd_devs[ifp->if_unit];
struct mbuf *m, *m0;
int sh, len, pad;
@@ -1205,7 +1213,7 @@ epioctl(ifp, cmd, data)
u_long cmd;
caddr_t data;
{
- struct ep_softc *sc = epcd.cd_devs[ifp->if_unit];
+ struct ep_softc *sc = ep_cd.cd_devs[ifp->if_unit];
struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
@@ -1315,7 +1323,7 @@ void
epwatchdog(unit)
int unit;
{
- struct ep_softc *sc = epcd.cd_devs[unit];
+ struct ep_softc *sc = ep_cd.cd_devs[unit];
log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
++sc->sc_arpcom.ac_if.if_oerrors;
diff --git a/sys/dev/isa/if_fe.c b/sys/dev/isa/if_fe.c
index 6201923066a..3c8a4f7ae91 100644
--- a/sys/dev/isa/if_fe.c
+++ b/sys/dev/isa/if_fe.c
@@ -227,8 +227,12 @@ void fe_loadmar __P((struct fe_softc *));
void fe_dump __P((int, struct fe_softc *));
#endif
-struct cfdriver fecd = {
- NULL, "fe", feprobe, feattach, DV_IFNET, sizeof(struct fe_softc)
+struct cfattach fe_ca = {
+ sizeof(struct fe_softc), feprobe, feattach
+};
+
+struct cfdriver fe_cd = {
+ NULL, "fe", DV_IFNET
};
/* Ethernet constants. To be defined in if_ehter.h? FIXME. */
@@ -993,7 +997,7 @@ feattach(parent, self, aux)
/* Initialize ifnet structure. */
ifp->if_unit = sc->sc_dev.dv_unit;
- ifp->if_name = fecd.cd_name;
+ ifp->if_name = fe_cd.cd_name;
ifp->if_start = fe_start;
ifp->if_ioctl = fe_ioctl;
ifp->if_watchdog = fe_watchdog;
@@ -1124,8 +1128,8 @@ feattach(parent, self, aux)
bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
#endif
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NET, feintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, feintr, sc, sc->sc_dev.dv_xname);
}
/*
@@ -1198,7 +1202,7 @@ void
fe_watchdog(unit)
int unit;
{
- struct fe_softc *sc = fecd.cd_devs[unit];
+ struct fe_softc *sc = fe_cd.cd_devs[unit];
log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
#if FE_DEBUG >= 3
@@ -1420,7 +1424,7 @@ void
fe_start(ifp)
struct ifnet *ifp;
{
- struct fe_softc *sc = fecd.cd_devs[ifp->if_unit];
+ struct fe_softc *sc = fe_cd.cd_devs[ifp->if_unit];
struct mbuf *m;
#if FE_DEBUG >= 1
@@ -1679,7 +1683,9 @@ fe_tint(sc, tstat)
*/
ifp->if_opackets += sc->txb_sched;
sc->txb_sched = 0;
+ }
+ if (sc->txb_sched == 0) {
/*
* The transmitter is no more active.
* Reset output active flag and watchdog timer.
@@ -1919,7 +1925,7 @@ fe_ioctl(ifp, command, data)
u_long command;
caddr_t data;
{
- struct fe_softc *sc = fecd.cd_devs[ifp->if_unit];
+ struct fe_softc *sc = fe_cd.cd_devs[ifp->if_unit];
register struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
diff --git a/sys/dev/isa/if_ie.c b/sys/dev/isa/if_ie.c
index 033d71b7bf3..49cd7b27064 100644
--- a/sys/dev/isa/if_ie.c
+++ b/sys/dev/isa/if_ie.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: if_ie.c,v 1.6 1996/03/20 01:00:52 mickey Exp $ */
-/* $NetBSD: if_ie.c,v 1.45 1995/12/24 02:31:33 mycroft Exp $ */
+/* $OpenBSD: if_ie.c,v 1.7 1996/04/21 22:24:03 deraadt Exp $ */
+/* $NetBSD: if_ie.c,v 1.47 1996/04/11 22:29:27 cgd Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995 Charles Hannum.
@@ -310,8 +310,12 @@ int in_ietint = 0;
int ieprobe __P((struct device *, void *, void *));
void ieattach __P((struct device *, struct device *, void *));
-struct cfdriver iecd = {
- NULL, "ie", ieprobe, ieattach, DV_IFNET, sizeof(struct ie_softc)
+struct cfattach ie_ca = {
+ sizeof(struct ie_softc), ieprobe, ieattach
+};
+
+struct cfdriver ie_cd = {
+ NULL, "ie", DV_IFNET
};
#define MK_24(base, ptr) ((caddr_t)((u_long)ptr - (u_long)base))
@@ -757,7 +761,7 @@ ieattach(parent, self, aux)
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
ifp->if_unit = sc->sc_dev.dv_unit;
- ifp->if_name = iecd.cd_name;
+ ifp->if_name = ie_cd.cd_name;
ifp->if_start = iestart;
ifp->if_ioctl = ieioctl;
ifp->if_watchdog = iewatchdog;
@@ -777,8 +781,8 @@ ieattach(parent, self, aux)
sizeof(struct ether_header));
#endif
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NET, ieintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, ieintr, sc, sc->sc_dev.dv_xname);
}
/*
@@ -789,7 +793,7 @@ void
iewatchdog(unit)
int unit;
{
- struct ie_softc *sc = iecd.cd_devs[unit];
+ struct ie_softc *sc = ie_cd.cd_devs[unit];
log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
++sc->sc_arpcom.ac_if.if_oerrors;
@@ -1441,7 +1445,7 @@ void
iestart(ifp)
struct ifnet *ifp;
{
- struct ie_softc *sc = iecd.cd_devs[ifp->if_unit];
+ struct ie_softc *sc = ie_cd.cd_devs[ifp->if_unit];
struct mbuf *m0, *m;
u_char *buffer;
u_short len;
@@ -2111,7 +2115,7 @@ ieioctl(ifp, cmd, data)
u_long cmd;
caddr_t data;
{
- struct ie_softc *sc = iecd.cd_devs[ifp->if_unit];
+ struct ie_softc *sc = ie_cd.cd_devs[ifp->if_unit];
struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
diff --git a/sys/dev/isa/if_le.c b/sys/dev/isa/if_le.c
index 61c47031e92..b6016b092cd 100644
--- a/sys/dev/isa/if_le.c
+++ b/sys/dev/isa/if_le.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: if_le.c,v 1.7 1996/03/20 01:00:54 mickey Exp $ */
-/* $NetBSD: if_le.c,v 1.38 1995/12/24 02:31:35 mycroft Exp $ */
+/* $OpenBSD: if_le.c,v 1.8 1996/04/21 22:24:09 deraadt Exp $ */
+/* $NetBSD: if_le.c,v 1.41 1996/04/11 22:29:34 cgd Exp $ */
/*-
* Copyright (c) 1995 Charles M. Hannum. All rights reserved.
@@ -83,7 +83,7 @@
char *card_type[] = {"unknown", "BICC Isolan", "NE2100", "DEPCA", "PCnet-ISA", "PCnet-PCI"};
-#define LE_SOFTC(unit) lecd.cd_devs[unit]
+#define LE_SOFTC(unit) le_cd.cd_devs[unit]
#define LE_DELAY(x) delay(x)
int leprobe __P((struct device *, void *, void *));
@@ -96,8 +96,17 @@ int leintr __P((void *));
int leintredge __P((void *));
void leshutdown __P((void *));
-struct cfdriver lecd = {
- NULL, "le", leprobe, leattach, DV_IFNET, sizeof(struct le_softc)
+/* XXX the following two structs should be different. */
+struct cfattach le_isa_ca = {
+ sizeof(struct le_softc), leprobe, leattach
+};
+
+struct cfattach le_pci_ca = {
+ sizeof(struct le_softc), leprobe, leattach
+};
+
+struct cfdriver le_cd = {
+ NULL, "le", DV_IFNET
};
integrate void
@@ -128,10 +137,10 @@ leprobe(parent, match, aux)
void *match, *aux;
{
struct le_softc *sc = match;
- extern struct cfdriver isacd, pcicd;
+ extern struct cfdriver isa_cd, pci_cd;
#if NISA > 0
- if (parent->dv_cfdata->cf_driver == &isacd) {
+ if (parent->dv_cfdata->cf_driver == &isa_cd) {
struct isa_attach_args *ia = aux;
if (bicc_probe(sc, ia))
@@ -144,7 +153,7 @@ leprobe(parent, match, aux)
#endif
#if NPCI > 0
- if (parent->dv_cfdata->cf_driver == &pcicd) {
+ if (parent->dv_cfdata->cf_driver == &pci_cd) {
struct pci_attach_args *pa = aux;
if (pa->pa_id == 0x20001022)
@@ -313,10 +322,10 @@ leattach(parent, self, aux)
void *aux;
{
struct le_softc *sc = (void *)self;
- extern struct cfdriver isacd, pcicd;
+ extern struct cfdriver isa_cd, pci_cd;
#if NPCI > 0
- if (parent->dv_cfdata->cf_driver == &pcicd) {
+ if (parent->dv_cfdata->cf_driver == &pci_cd) {
struct pci_attach_args *pa = aux;
int iobase;
@@ -386,33 +395,34 @@ leattach(parent, self, aux)
sc->sc_copyfrombuf = copyfrombuf_contig;
sc->sc_zerobuf = zerobuf_contig;
- sc->sc_arpcom.ac_if.if_name = lecd.cd_name;
+ sc->sc_arpcom.ac_if.if_name = le_cd.cd_name;
leconfig(sc);
printf("%s: type %s\n", sc->sc_dev.dv_xname, card_type[sc->sc_card]);
#if NISA > 0
- if (parent->dv_cfdata->cf_driver == &isacd) {
+ if (parent->dv_cfdata->cf_driver == &isa_cd) {
struct isa_attach_args *ia = aux;
if (ia->ia_drq != DRQUNK)
isa_dmacascade(ia->ia_drq);
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NET,
- leintredge, sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, leintredge, sc, sc->sc_dev.dv_xname);
}
#endif
#if NPCI > 0
- if (parent->dv_cfdata->cf_driver == &pcicd) {
+ if (parent->dv_cfdata->cf_driver == &pci_cd) {
struct pci_attach_args *pa = aux;
+ pcireg_t csr;
- pci_conf_write(pa->pa_tag, PCI_COMMAND_STATUS_REG,
- pci_conf_read(pa->pa_tag, PCI_COMMAND_STATUS_REG) |
- PCI_COMMAND_MASTER_ENABLE);
+ csr = pci_conf_read(pa->pa_bc, pa->pa_tag,
+ PCI_COMMAND_STATUS_REG);
+ pci_conf_write(pa->pa_bc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
+ csr | PCI_COMMAND_MASTER_ENABLE);
- sc->sc_ih = pci_map_int(pa->pa_tag, IPL_NET, leintr, sc,
- sc->sc_dev.dv_xname);
+ sc->sc_ih = pci_map_int(pa->pa_tag, IPL_NET, leintr, sc);
}
#endif
diff --git a/sys/dev/isa/isa.c b/sys/dev/isa/isa.c
index 5f55324d434..fa14cc051ff 100644
--- a/sys/dev/isa/isa.c
+++ b/sys/dev/isa/isa.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: isa.c,v 1.5 1996/04/18 23:47:41 niklas Exp $ */
-/* $NetBSD: isa.c,v 1.78 1996/03/08 20:36:21 cgd Exp $ */
+/* $OpenBSD: isa.c,v 1.6 1996/04/21 22:24:12 deraadt Exp $ */
+/* $NetBSD: isa.c,v 1.80 1996/04/11 22:25:44 cgd Exp $ */
/*-
* Copyright (c) 1993, 1994 Charles Hannum. All rights reserved.
@@ -36,6 +36,9 @@
#include <sys/conf.h>
#include <sys/malloc.h>
#include <sys/device.h>
+#ifndef i386 /* XXX */
+#include <machine/intr.h>
+#endif /* XXX */
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
@@ -43,8 +46,12 @@
int isamatch __P((struct device *, void *, void *));
void isaattach __P((struct device *, struct device *, void *));
-struct cfdriver isacd = {
- NULL, "isa", isamatch, isaattach, DV_DULL, sizeof(struct isa_softc), 1
+struct cfattach isa_ca = {
+ sizeof(struct isa_softc), isamatch, isaattach
+};
+
+struct cfdriver isa_cd = {
+ NULL, "isa", DV_DULL, 1
};
int
@@ -71,9 +78,11 @@ isaattach(parent, self, aux)
struct isa_softc *sc = (struct isa_softc *)self;
struct isabus_attach_args *iba = aux;
+ isa_attach_hook(parent, self, iba);
printf("\n");
sc->sc_bc = iba->iba_bc;
+ sc->sc_ic = iba->iba_ic;
TAILQ_INIT(&sc->sc_subdevs);
config_scan(isascan, self);
@@ -115,6 +124,7 @@ isascan(parent, match)
panic("clone devices not supported on ISA bus");
ia.ia_bc = sc->sc_bc;
+ ia.ia_ic = sc->sc_ic;
ia.ia_iobase = cf->cf_loc[0];
ia.ia_iosize = 0x666;
ia.ia_maddr = cf->cf_loc[2];
@@ -122,7 +132,7 @@ isascan(parent, match)
ia.ia_irq = cf->cf_loc[4] == 2 ? 9 : cf->cf_loc[4];
ia.ia_drq = cf->cf_loc[5];
- if ((*cf->cf_driver->cd_match)(parent, dev, &ia) > 0)
+ if ((*cf->cf_attach->ca_match)(parent, dev, &ia) > 0)
config_attach(parent, dev, &ia, isaprint);
else
free(dev, M_DEVBUF);
diff --git a/sys/dev/isa/isadma.c b/sys/dev/isa/isadma.c
index 37a0795745a..a1d5778dda8 100644
--- a/sys/dev/isa/isadma.c
+++ b/sys/dev/isa/isadma.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: isadma.c,v 1.3 1996/04/18 23:47:41 niklas Exp $ */
-/* $NetBSD: isadma.c,v 1.17 1996/03/01 04:35:27 mycroft Exp $ */
+/* $OpenBSD: isadma.c,v 1.4 1996/04/21 22:24:14 deraadt Exp $ */
+/* $NetBSD: isadma.c,v 1.18 1996/03/31 20:51:43 mycroft Exp $ */
#include <sys/param.h>
#include <sys/systm.h>
@@ -28,8 +28,9 @@ static struct dma_info dma_info[8];
static u_int8_t dma_finished;
/* high byte of address is stored in this port for i-th dma channel */
-static int dmapageport[8] = {
- 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a
+static int dmapageport[2][4] = {
+ {0x87, 0x83, 0x81, 0x82},
+ {0x8f, 0x8b, 0x89, 0x8a}
};
static u_int8_t dmamode[4] = {
@@ -123,7 +124,7 @@ isadma_start(addr, nbytes, chan, flags)
/* send start address */
waport = DMA1_CHN(chan);
- outb(dmapageport[chan], di->phys[0].addr>>16);
+ outb(dmapageport[0][chan], di->phys[0].addr>>16);
outb(waport, di->phys[0].addr);
outb(waport, di->phys[0].addr>>8);
@@ -144,7 +145,7 @@ isadma_start(addr, nbytes, chan, flags)
/* send start address */
waport = DMA2_CHN(chan & 3);
- outb(dmapageport[chan], di->phys[0].addr>>16);
+ outb(dmapageport[1][chan], di->phys[0].addr>>16);
outb(waport, di->phys[0].addr>>1);
outb(waport, di->phys[0].addr>>9);
diff --git a/sys/dev/isa/isavar.h b/sys/dev/isa/isavar.h
index 551375712f0..78b950248a9 100644
--- a/sys/dev/isa/isavar.h
+++ b/sys/dev/isa/isavar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: isavar.h,v 1.7 1996/04/18 23:47:43 niklas Exp $ */
-/* $NetBSD: isavar.h,v 1.20 1996/03/16 02:00:43 cgd Exp $ */
+/* $OpenBSD: isavar.h,v 1.8 1996/04/21 22:24:16 deraadt Exp $ */
+/* $NetBSD: isavar.h,v 1.21 1996/04/11 22:20:50 cgd Exp $ */
/*
* Copyright (c) 1995 Chris G. Demetriou
@@ -47,19 +47,36 @@
#include <sys/queue.h>
#include <machine/bus.h>
+/*
+ * Structures and definitions needed by the machine-dependent header.
+ */
+struct isabus_attach_args;
+
+#if (alpha + i386 != 1)
+ERROR: COMPILING FOR UNSUPPORTED MACHINE, OR MORE THAN ONE.
+#endif
+#if alpha
+#include <alpha/isa/isa_machdep.h>
+#endif
+#if i386
+#include <i386/isa/isa_machdep.h>
+#endif
+
/*
* ISA bus attach arguments
*/
struct isabus_attach_args {
char *iba_busname; /* XXX should be common */
bus_chipset_tag_t iba_bc; /* XXX should be common */
+ isa_chipset_tag_t iba_ic;
};
/*
* ISA driver attach arguments
*/
struct isa_attach_args {
- bus_chipset_tag_t ia_bc; /* bus chipset tag */
+ bus_chipset_tag_t ia_bc;
+ isa_chipset_tag_t ia_ic;
int ia_iobase; /* base i/o address */
int ia_iosize; /* span of ports used */
@@ -92,7 +109,8 @@ struct isa_softc {
TAILQ_HEAD(, isadev)
sc_subdevs; /* list of all children */
- bus_chipset_tag_t sc_bc; /* bus chipset tag */
+ bus_chipset_tag_t sc_bc;
+ isa_chipset_tag_t sc_ic;
};
#define cf_iobase cf_loc[0]
@@ -120,9 +138,6 @@ struct isa_softc {
/* ISA interrupt sharing types */
void isascan __P((struct device *parent, void *match));
-void *isa_intr_establish __P((int intr, int type, int level,
- int (*ih_fun)(void *), void *ih_arg, char *));
-void isa_intr_disestablish __P((void *handler));
char *isa_intr_typename __P((int type));
#ifdef NEWCONFIG
diff --git a/sys/dev/isa/lpt.c b/sys/dev/isa/lpt.c
index 3bcfd6ad241..24499ddbc45 100644
--- a/sys/dev/isa/lpt.c
+++ b/sys/dev/isa/lpt.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: lpt.c,v 1.8 1996/04/18 23:47:43 niklas Exp $ */
-/* $NetBSD: lpt.c,v 1.32 1996/03/08 22:17:58 cgd Exp $ */
+/* $OpenBSD: lpt.c,v 1.9 1996/04/21 22:24:18 deraadt Exp $ */
+/* $NetBSD: lpt.c,v 1.37 1996/04/11 22:29:37 cgd Exp $ */
/*
* Copyright (c) 1993, 1994 Charles Hannum.
@@ -65,7 +65,11 @@
#include <sys/device.h>
#include <sys/syslog.h>
-#include <machine/cpu.h>
+#ifdef i386 /* XXX */
+#include <machine/cpu.h> /* XXX */
+#else /* XXX */
+#include <machine/intr.h>
+#endif /* XXX */
#include <machine/bus.h>
#include <dev/isa/isavar.h>
@@ -112,8 +116,12 @@ int lptprobe __P((struct device *, void *, void *));
void lptattach __P((struct device *, struct device *, void *));
int lptintr __P((void *));
-struct cfdriver lptcd = {
- NULL, "lpt", lptprobe, lptattach, DV_TTY, sizeof(struct lpt_softc)
+struct cfattach lpt_ca = {
+ sizeof(struct lpt_softc), lptprobe, lptattach
+};
+
+struct cfdriver lpt_cd = {
+ NULL, "lpt", DV_TTY
};
#define LPTUNIT(s) (minor(s) & 0x1f)
@@ -128,15 +136,19 @@ static int not_ready __P((u_char, struct lpt_softc *));
static void lptwakeup __P((void *arg));
static int pushbytes __P((struct lpt_softc *));
+int lpt_port_test __P((bus_chipset_tag_t, bus_io_handle_t, bus_io_addr_t,
+ bus_io_size_t, u_char, u_char));
+
/*
* Internal routine to lptprobe to do port tests of one byte value.
*/
int
-lpt_port_test(ioh, off, data, mask, base)
+lpt_port_test(bc, ioh, base, off, data, mask)
+ bus_chipset_tag_t bc;
bus_io_handle_t ioh;
- size_t off;
+ bus_io_addr_t base;
+ bus_io_size_t off;
u_char data, mask;
- u_long base;
{
int timeout;
u_char temp;
@@ -202,22 +214,22 @@ lptprobe(parent, match, aux)
mask = 0xff;
data = 0x55; /* Alternating zeros */
- if (!lpt_port_test(ioh, lpt_data, data, mask, base))
+ if (!lpt_port_test(bc, ioh, base, lpt_data, data, mask))
ABORT;
data = 0xaa; /* Alternating ones */
- if (!lpt_port_test(ioh, lpt_data, data, mask, base))
+ if (!lpt_port_test(bc, ioh, base, lpt_data, data, mask))
ABORT;
for (i = 0; i < CHAR_BIT; i++) { /* Walking zero */
data = ~(1 << i);
- if (!lpt_port_test(ioh, lpt_data, data, mask, base))
+ if (!lpt_port_test(bc, ioh, base, lpt_data, data, mask))
ABORT;
}
for (i = 0; i < CHAR_BIT; i++) { /* Walking one */
data = (1 << i);
- if (!lpt_port_test(ioh, lpt_data, data, mask, base))
+ if (!lpt_port_test(bc, ioh, base, lpt_data, data, mask))
ABORT;
}
@@ -261,8 +273,8 @@ lptattach(parent, self, aux)
bus_io_write_1(bc, ioh, lpt_control, LPC_NINIT);
if (ia->ia_irq != IRQUNK)
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NONE,
- lptintr, sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_TTY, lptintr, sc, sc->sc_dev.dv_xname);
}
/*
@@ -282,9 +294,9 @@ lptopen(dev, flag)
int error;
int spin;
- if (unit >= lptcd.cd_ndevs)
+ if (unit >= lpt_cd.cd_ndevs)
return ENXIO;
- sc = lptcd.cd_devs[unit];
+ sc = lpt_cd.cd_devs[unit];
if (!sc)
return ENXIO;
@@ -386,12 +398,13 @@ lptwakeup(arg)
/*
* Close the device, and free the local line buffer.
*/
+int
lptclose(dev, flag)
dev_t dev;
int flag;
{
int unit = LPTUNIT(dev);
- struct lpt_softc *sc = lptcd.cd_devs[unit];
+ struct lpt_softc *sc = lpt_cd.cd_devs[unit];
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
@@ -476,11 +489,12 @@ pushbytes(sc)
* Copy a line from user space to a local buffer, then call putc to get the
* chars moved to the output queue.
*/
+int
lptwrite(dev, uio)
dev_t dev;
struct uio *uio;
{
- struct lpt_softc *sc = lptcd.cd_devs[LPTUNIT(dev)];
+ struct lpt_softc *sc = lpt_cd.cd_devs[LPTUNIT(dev)];
size_t n;
int error = 0;
diff --git a/sys/dev/isa/mcd.c b/sys/dev/isa/mcd.c
index 8fce277ec1d..cf5eeb3a812 100644
--- a/sys/dev/isa/mcd.c
+++ b/sys/dev/isa/mcd.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: mcd.c,v 1.8 1996/03/20 01:00:56 mickey Exp $ */
-/* $NetBSD: mcd.c,v 1.45 1996/01/30 18:28:05 thorpej Exp $ */
+/* $OpenBSD: mcd.c,v 1.9 1996/04/21 22:24:21 deraadt Exp $ */
+/* $NetBSD: mcd.c,v 1.47 1996/04/11 22:29:43 cgd Exp $ */
/*
* Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved.
@@ -178,8 +178,12 @@ int mcd_setlock __P((struct mcd_softc *, int));
int mcdprobe __P((struct device *, void *, void *));
void mcdattach __P((struct device *, struct device *, void *));
-struct cfdriver mcdcd = {
- NULL, "mcd", mcdprobe, mcdattach, DV_DISK, sizeof(struct mcd_softc)
+struct cfattach mcd_ca = {
+ sizeof(struct mcd_softc), mcdprobe, mcdattach
+};
+
+struct cfdriver mcd_cd = {
+ NULL, "mcd", DV_DISK
};
void mcdgetdisklabel __P((struct mcd_softc *));
@@ -228,8 +232,8 @@ mcdattach(parent, self, aux)
mcd_soft_reset(sc);
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO, mcdintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, mcdintr, sc, sc->sc_dev.dv_xname);
}
/*
@@ -279,9 +283,9 @@ mcdopen(dev, flag, fmt, p)
struct mcd_softc *sc;
unit = MCDUNIT(dev);
- if (unit >= mcdcd.cd_ndevs)
+ if (unit >= mcd_cd.cd_ndevs)
return ENXIO;
- sc = mcdcd.cd_devs[unit];
+ sc = mcd_cd.cd_devs[unit];
if (!sc)
return ENXIO;
@@ -379,7 +383,7 @@ mcdclose(dev, flag, fmt)
dev_t dev;
int flag, fmt;
{
- struct mcd_softc *sc = mcdcd.cd_devs[MCDUNIT(dev)];
+ struct mcd_softc *sc = mcd_cd.cd_devs[MCDUNIT(dev)];
int part = MCDPART(dev);
int error;
@@ -415,7 +419,7 @@ void
mcdstrategy(bp)
struct buf *bp;
{
- struct mcd_softc *sc = mcdcd.cd_devs[MCDUNIT(bp->b_dev)];
+ struct mcd_softc *sc = mcd_cd.cd_devs[MCDUNIT(bp->b_dev)];
int s;
/* Test validity. */
@@ -548,7 +552,7 @@ mcdioctl(dev, cmd, addr, flag, p)
int flag;
struct proc *p;
{
- struct mcd_softc *sc = mcdcd.cd_devs[MCDUNIT(dev)];
+ struct mcd_softc *sc = mcd_cd.cd_devs[MCDUNIT(dev)];
int error;
MCD_TRACE("ioctl: cmd=0x%x\n", cmd, 0, 0, 0);
diff --git a/sys/dev/isa/pas.c b/sys/dev/isa/pas.c
index 0d0fe136538..4227615cb36 100644
--- a/sys/dev/isa/pas.c
+++ b/sys/dev/isa/pas.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: pas.c,v 1.8 1996/04/18 23:47:44 niklas Exp $ */
-/* $NetBSD: pas.c,v 1.13 1996/03/01 04:08:43 mycroft Exp $ */
+/* $OpenBSD: pas.c,v 1.9 1996/04/21 22:24:23 deraadt Exp $ */
+/* $NetBSD: pas.c,v 1.15 1996/04/11 22:29:48 cgd Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -250,8 +250,12 @@ pasconf(int model, int sbbase, int sbirq, int sbdrq)
int pasprobe __P((struct device *, void *, void *));
void pasattach __P((struct device *, struct device *, void *));
-struct cfdriver pascd = {
- NULL, "pas", pasprobe, pasattach, DV_DULL, sizeof(struct pas_softc)
+struct cfattach pas_ca = {
+ sizeof(struct pas_softc), pasprobe, pasattach
+};
+
+struct cfdriver pas_cd = {
+ NULL, "pas", DV_DULL
};
/*
@@ -431,8 +435,8 @@ pasattach(parent, self, aux)
int err;
sc->sc_iobase = iobase;
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_AUDIO,
- sbdsp_intr, &sc->sc_sbdsp, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_AUDIO, sbdsp_intr, &sc->sc_sbdsp, sc->sc_dev.dv_xname);
printf(" ProAudio Spectrum %s [rev %d] ", pasnames[sc->model], sc->rev);
@@ -453,10 +457,10 @@ pasopen(dev, flags)
struct pas_softc *sc;
int unit = AUDIOUNIT(dev);
- if (unit >= pascd.cd_ndevs)
+ if (unit >= pas_cd.cd_ndevs)
return ENODEV;
- sc = pascd.cd_devs[unit];
+ sc = pas_cd.cd_devs[unit];
if (!sc)
return ENXIO;
diff --git a/sys/dev/isa/pss.c b/sys/dev/isa/pss.c
index 909db507342..9e551882061 100644
--- a/sys/dev/isa/pss.c
+++ b/sys/dev/isa/pss.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: pss.c,v 1.7 1996/03/20 01:00:59 mickey Exp $ */
-/* $NetBSD: pss.c,v 1.11 1995/12/24 02:31:45 mycroft Exp $ */
+/* $OpenBSD: pss.c,v 1.8 1996/04/21 22:24:26 deraadt Exp $ */
+/* $NetBSD: pss.c,v 1.13 1996/04/11 22:29:52 cgd Exp $ */
/*
* Copyright (c) 1994 John Brezak
@@ -238,20 +238,36 @@ static u_char wss_dma_bits[4] = {1, 2, 0, 3};
#define at_dma(flags, ptr, cc, chan) isa_dmastart(flags, ptr, cc, chan)
#endif
-struct cfdriver psscd = {
- NULL, "pss", pssprobe, pssattach, DV_DULL, sizeof(struct pss_softc), 1
+struct cfattach pss_ca = {
+ sizeof(struct pss_softc), pssprobe, pssattach
};
-struct cfdriver spcd = {
- NULL, "sp", spprobe, spattach, DV_DULL, sizeof(struct ad1848_softc)
+struct cfdriver pss_cd = {
+ NULL, "pss", DV_DULL, 1
};
-struct cfdriver mpucd = {
- NULL, "mpu", mpuprobe, mpuattach, DV_DULL, sizeof(struct mpu_softc)
+struct cfattach sp_ca = {
+ sizeof(struct ad1848_softc), spprobe, spattach
};
-struct cfdriver pcdcd = {
- NULL, "pcd", pcdprobe, pcdattach, DV_DULL, sizeof(struct cd_softc)
+struct cfdriver sp_cd = {
+ NULL, "sp", DV_DULL
+};
+
+struct cfattach mpu_ca = {
+ sizeof(struct mpu_softc), mpuprobe, mpuattach
+};
+
+struct cfdriver mpu_cd = {
+ NULL, "mpu", DV_DULL
+};
+
+struct cfattach pcd_ca = {
+ sizeof(struct cd_softc), pcdprobe, pcdattach
+};
+
+struct cfdriver pcd_cd = {
+ NULL, "pcd", DV_DULL
};
struct audio_device pss_device = {
@@ -1005,13 +1021,13 @@ pssattach(parent, self, aux)
#endif
/* Setup interrupt handler for PSS */
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_AUDIO, pssintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, IPL_AUDIO,
+ pssintr, sc, sc->sc_dev.dv_xname);
vers = (inw(sc->sc_iobase+PSS_ID_VERS)&0xff) - 1;
printf(": ESC614%c\n", (vers > 0)?'A'+vers:' ');
- (void)config_found(self, NULL, NULL);
+ (void)config_found(self, ia->ia_ic, NULL); /* XXX */
sc->out_port = PSS_MASTER_VOL;
@@ -1031,6 +1047,7 @@ spattach(parent, self, aux)
{
struct ad1848_softc *sc = (struct ad1848_softc *)self;
struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
+ isa_chipset_tag_t ic = aux; /* XXX */
int iobase = cf->cf_iobase;
sc->sc_iobase = iobase;
@@ -1040,8 +1057,8 @@ spattach(parent, self, aux)
isa_establish(&sc->sc_id, &sc->sc_dev);
#endif
- sc->sc_ih = isa_intr_establish(cf->cf_irq, IST_EDGE, IPL_AUDIO, ad1848_intr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ic, cf->cf_irq, IST_EDGE, IPL_AUDIO,
+ ad1848_intr, sc, sc->sc_dev.dv_xname);
/* XXX might use pssprint func ?? */
printf(" port 0x%x-0x%x irq %d drq %d",
@@ -1060,6 +1077,7 @@ mpuattach(parent, self, aux)
{
struct mpu_softc *sc = (struct mpu_softc *)self;
struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
+ isa_chipset_tag_t ic = aux; /* XXX */
int iobase = cf->cf_iobase;
sc->sc_iobase = iobase;
@@ -1068,8 +1086,8 @@ mpuattach(parent, self, aux)
isa_establish(&sc->sc_id, &sc->sc_dev);
#endif
- sc->sc_ih = isa_intr_establish(cf->cf_irq, IST_EDGE, IPL_AUDIO, mpuintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ic, cf->cf_irq, IST_EDGE, IPL_AUDIO,
+ mpuintr, sc, sc->sc_dev.dv_xname);
/* XXX might use pssprint func ?? */
printf(" port 0x%x-0x%x irq %d\n",
@@ -1145,10 +1163,10 @@ spopen(dev, flags)
struct ad1848_softc *sc;
int unit = AUDIOUNIT(dev);
- if (unit >= spcd.cd_ndevs)
+ if (unit >= sp_cd.cd_ndevs)
return ENODEV;
- sc = spcd.cd_devs[unit];
+ sc = sp_cd.cd_devs[unit];
if (!sc)
return ENXIO;
diff --git a/sys/dev/isa/rtfps.c b/sys/dev/isa/rtfps.c
index e0f7ef2abf4..1afdc1ccfda 100644
--- a/sys/dev/isa/rtfps.c
+++ b/sys/dev/isa/rtfps.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: rtfps.c,v 1.7 1996/04/18 23:47:45 niklas Exp $ */
-/* $NetBSD: rtfps.c,v 1.17 1996/03/10 09:01:28 cgd Exp $ */
+/* $OpenBSD: rtfps.c,v 1.8 1996/04/21 22:24:28 deraadt Exp $ */
+/* $NetBSD: rtfps.c,v 1.21 1996/04/15 18:55:31 cgd Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -36,7 +36,13 @@
#include <sys/param.h>
#include <sys/device.h>
+#include <sys/termios.h>
+#ifdef i386 /* XXX */
+#include <machine/cpu.h> /* XXX */
+#else /* XXX */
+#include <machine/intr.h>
+#endif /* XXX */
#include <machine/bus.h>
#include <dev/isa/isavar.h>
@@ -63,8 +69,12 @@ int rtfpsprobe();
void rtfpsattach();
int rtfpsintr __P((void *));
-struct cfdriver rtfpscd = {
- NULL, "rtfps", rtfpsprobe, rtfpsattach, DV_TTY, sizeof(struct rtfps_softc)
+struct cfattach rtfps_ca = {
+ sizeof(struct rtfps_softc), rtfpsprobe, rtfpsattach
+};
+
+struct cfdriver rtfps_cd = {
+ NULL, "rtfps", DV_TTY
};
int
@@ -176,20 +186,13 @@ rtfpsattach(parent, self, aux)
ca.ca_iobase = sc->sc_iobase + i * COM_NPORTS;
ca.ca_noien = 0;
- /* mimic config_found(), but with special functionality */
- if ((match = config_search(NULL, self, &ca)) != NULL) {
- subunit = match->cf_unit; /* can change if unit == * */
- config_attach(self, match, &ca, rtfpsprint);
- sc->sc_slaves[i] = match->cf_driver->cd_devs[subunit];
+ sc->sc_slaves[i] = config_found(self, &ca, rtfpsprint);
+ if (sc->sc_slaves[i] != NULL)
sc->sc_alive |= 1 << i;
- } else {
- rtfpsprint(&ca, self->dv_xname);
- printf(" not configured\n");
- }
}
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_TTY,
- rtfpsintr, sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_TTY, rtfpsintr, sc, sc->sc_dev.dv_xname);
}
int
diff --git a/sys/dev/isa/sb.c b/sys/dev/isa/sb.c
index 976eada8cc7..09fd816e061 100644
--- a/sys/dev/isa/sb.c
+++ b/sys/dev/isa/sb.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: sb.c,v 1.8 1996/04/18 23:47:46 niklas Exp $ */
-/* $NetBSD: sb.c,v 1.32 1996/03/16 04:00:09 jtk Exp $ */
+/* $OpenBSD: sb.c,v 1.9 1996/04/21 22:24:30 deraadt Exp $ */
+/* $NetBSD: sb.c,v 1.34 1996/04/11 22:30:01 cgd Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -75,8 +75,18 @@ struct sb_softc {
int sbprobe __P((struct device *, void *, void *));
void sbattach __P((struct device *, struct device *, void *));
-struct cfdriver sbcd = {
- NULL, "sb", sbprobe, sbattach, DV_DULL, sizeof(struct sbdsp_softc)
+struct cfattach sb_ca = {
+ sizeof(struct sbdsp_softc), sbprobe, sbattach
+};
+
+struct cfdriver sb_cd = {
+ NULL, "sb", DV_DULL
+};
+
+struct audio_device sb_device = {
+ "SoundBlaster",
+ "x",
+ "sb"
};
int sbopen __P((dev_t, int));
@@ -264,8 +274,8 @@ sbattach(parent, self, aux)
register int iobase = ia->ia_iobase;
int err;
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_AUDIO,
- sbdsp_intr, sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_AUDIO, sbdsp_intr, sc, sc->sc_dev.dv_xname);
sbdsp_attach(sc);
@@ -285,10 +295,10 @@ sbopen(dev, flags)
struct sbdsp_softc *sc;
int unit = AUDIOUNIT(dev);
- if (unit >= sbcd.cd_ndevs)
+ if (unit >= sb_cd.cd_ndevs)
return ENODEV;
- sc = sbcd.cd_devs[unit];
+ sc = sb_cd.cd_devs[unit];
if (!sc)
return ENXIO;
diff --git a/sys/dev/isa/seagate.c b/sys/dev/isa/seagate.c
index ccb16aa9165..67e70d04696 100644
--- a/sys/dev/isa/seagate.c
+++ b/sys/dev/isa/seagate.c
@@ -303,8 +303,12 @@ int seaprobe __P((struct device *, void *, void *));
void seaattach __P((struct device *, struct device *, void *));
int seaprint __P((void *, char *));
-struct cfdriver seacd = {
- NULL, "sea", seaprobe, seaattach, DV_DULL, sizeof(struct sea_softc)
+struct cfattach sea_ca = {
+ sizeof(struct sea_softc), seaprobe, seaattach
+};
+
+struct cfdriver sea_cd = {
+ NULL, "sea", DV_DULL
};
#ifdef SEA_DEBUGQUEUE
@@ -438,8 +442,8 @@ seaattach(parent, self, aux)
#ifdef NEWCONFIG
isa_establish(&sea->sc_id, &sea->sc_deV);
#endif
- sea->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO, seaintr,
- sea, sc->sc_dev.dv_xname);
+ sea->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, seaintr, sea, sea->sc_dev.dv_xname);
/*
* ask the adapter what subunits are present
@@ -685,8 +689,8 @@ sea_main()
*/
loop:
done = 1;
- for (unit = 0; unit < seacd.cd_ndevs; unit++) {
- sea = seacd.cd_devs[unit];
+ for (unit = 0; unit < sea_cd.cd_ndevs; unit++) {
+ sea = sea_cd.cd_devs[unit];
if (!sea)
continue;
s = splbio();
diff --git a/sys/dev/isa/ultra14f.c b/sys/dev/isa/ultra14f.c
index 948a2966654..79464cc4d6c 100644
--- a/sys/dev/isa/ultra14f.c
+++ b/sys/dev/isa/ultra14f.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ultra14f.c,v 1.12 1996/04/18 23:47:50 niklas Exp $ */
-/* $NetBSD: ultra14f.c,v 1.62 1996/02/24 05:27:49 mycroft Exp $ */
+/* $OpenBSD: ultra14f.c,v 1.13 1996/04/21 22:24:36 deraadt Exp $ */
+/* $NetBSD: ultra14f.c,v 1.64 1996/04/11 22:30:20 cgd Exp $ */
/*
* Copyright (c) 1994 Charles Hannum. All rights reserved.
@@ -328,8 +328,12 @@ int uhaprobe __P((struct device *, void *, void *));
void uhaattach __P((struct device *, struct device *, void *));
int uhaprint __P((void *, char *));
-struct cfdriver uhacd = {
- NULL, "uha", uhaprobe, uhaattach, DV_DULL, sizeof(struct uha_softc)
+struct cfattach uha_ca = {
+ sizeof(struct uha_softc), uhaprobe, uhaattach
+};
+
+struct cfdriver uha_cd = {
+ NULL, "uha", DV_DULL
};
/*
@@ -608,8 +612,8 @@ uhaattach(parent, self, aux)
#ifdef NEWCONFIG
isa_establish(&uha->sc_id, &uha->sc_dev);
#endif
- uha->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO,
- uha->intr, uha, uha->sc_dev.dv_xname);
+ uha->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, uha->intr, uha, uha->sc_dev.dv_xname);
/*
* ask the adapter what subunits are present
diff --git a/sys/dev/isa/wd.c b/sys/dev/isa/wd.c
index 96fedd9de01..76267053725 100644
--- a/sys/dev/isa/wd.c
+++ b/sys/dev/isa/wd.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: wd.c,v 1.9 1996/04/18 23:47:51 niklas Exp $ */
-/* $NetBSD: wd.c,v 1.146 1996/03/01 04:08:51 mycroft Exp $ */
+/* $OpenBSD: wd.c,v 1.10 1996/04/21 22:24:40 deraadt Exp $ */
+/* $NetBSD: wd.c,v 1.148 1996/04/11 22:30:31 cgd Exp $ */
/*
* Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
@@ -139,15 +139,23 @@ struct wdc_softc {
int wdcprobe __P((struct device *, void *, void *));
void wdcattach __P((struct device *, struct device *, void *));
-struct cfdriver wdccd = {
- NULL, "wdc", wdcprobe, wdcattach, DV_DULL, sizeof(struct wdc_softc)
+struct cfattach wdc_ca = {
+ sizeof(struct wdc_softc), wdcprobe, wdcattach
+};
+
+struct cfdriver wdc_cd = {
+ NULL, "wdc", DV_DULL
};
int wdprobe __P((struct device *, void *, void *));
void wdattach __P((struct device *, struct device *, void *));
-struct cfdriver wdcd = {
- NULL, "wd", wdprobe, wdattach, DV_DISK, sizeof(struct wd_softc)
+struct cfattach wd_ca = {
+ sizeof(struct wd_softc), wdprobe, wdattach
+};
+
+struct cfdriver wd_cd = {
+ NULL, "wd", DV_DISK
};
void wdgetdisklabel __P((struct wd_softc *));
@@ -249,8 +257,8 @@ wdcattach(parent, self, aux)
printf("\n");
- wdc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO, wdcintr,
- wdc, wdc->sc_dev.dv_xname);
+ wdc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, wdcintr, wdc, wdc->sc_dev.dv_xname);
for (wa.wa_drive = 0; wa.wa_drive < 2; wa.wa_drive++)
(void)config_found(self, (void *)&wa, wdprint);
@@ -354,7 +362,7 @@ void
wdstrategy(bp)
struct buf *bp;
{
- struct wd_softc *wd = wdcd.cd_devs[WDUNIT(bp->b_dev)];
+ struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(bp->b_dev)];
int s;
/* Valid request? */
@@ -889,9 +897,9 @@ wdopen(dev, flag, fmt)
int error;
unit = WDUNIT(dev);
- if (unit >= wdcd.cd_ndevs)
+ if (unit >= wd_cd.cd_ndevs)
return ENXIO;
- wd = wdcd.cd_devs[unit];
+ wd = wd_cd.cd_devs[unit];
if (wd == 0)
return ENXIO;
@@ -963,7 +971,7 @@ wdclose(dev, flag, fmt)
dev_t dev;
int flag, fmt;
{
- struct wd_softc *wd = wdcd.cd_devs[WDUNIT(dev)];
+ struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
int part = WDPART(dev);
int error;
@@ -1308,7 +1316,7 @@ wdioctl(dev, cmd, addr, flag, p)
int flag;
struct proc *p;
{
- struct wd_softc *wd = wdcd.cd_devs[WDUNIT(dev)];
+ struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
int error;
if ((wd->sc_flags & WDF_LOADED) == 0)
@@ -1424,7 +1432,7 @@ wdsize(dev)
if (wdopen(dev, 0, S_IFBLK) != 0)
return -1;
- wd = wdcd.cd_devs[WDUNIT(dev)];
+ wd = wd_cd.cd_devs[WDUNIT(dev)];
part = WDPART(dev);
if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
size = -1;
@@ -1463,9 +1471,9 @@ wddump(dev, blkno, va, size)
wddoingadump = 1;
unit = WDUNIT(dev);
- if (unit >= wdcd.cd_ndevs)
+ if (unit >= wd_cd.cd_ndevs)
return ENXIO;
- wd = wdcd.cd_devs[unit];
+ wd = wd_cd.cd_devs[unit];
if (wd == 0)
return ENXIO;
@@ -1657,8 +1665,8 @@ wdcunwedge(wdc)
(void) wdcreset(wdc);
/* Schedule recalibrate for all drives on this controller. */
- for (unit = 0; unit < wdcd.cd_ndevs; unit++) {
- struct wd_softc *wd = wdcd.cd_devs[unit];
+ for (unit = 0; unit < wd_cd.cd_ndevs; unit++) {
+ struct wd_softc *wd = wd_cd.cd_devs[unit];
if (!wd || (void *)wd->sc_dev.dv_parent != wdc)
continue;
if (wd->sc_state > RECAL)
diff --git a/sys/dev/isa/wd7000.c b/sys/dev/isa/wd7000.c
deleted file mode 100644
index cd86dd0e8ef..00000000000
--- a/sys/dev/isa/wd7000.c
+++ /dev/null
@@ -1,747 +0,0 @@
-/* $NetBSD: wd7000.c,v 1.22 1995/08/12 20:31:32 mycroft Exp $ */
-
-/* XXX THIS DRIVER IS BROKEN. IT WILL NOT EVEN COMPILE. */
-
-/*
- * UNFINISHED! UNFINISHED! UNFINISHED! UNFINISHED! UNFINISHED! UNFINISHED!
- *
- * deraadt@fsa.ca 93/04/02
- *
- * I was writing this driver for a wd7000-ASC. Yeah, the "-ASC" not the
- * "-FASST2". The difference is that the "-ASC" is missing scatter gather
- * support.
- *
- * In any case, the real reason why I never finished it is because the
- * motherboard I have has broken DMA. This card wants 8MHz 1 wait state
- * operation, and my board munges about 30% of the words transferred.
- *
- * Hopefully someone can finish this for the wd7000-FASST2. It should be
- * quite easy to do. Look at the Linux wd7000 device driver to see how
- * scatter gather is done by the board, then look at one of the Adaptec
- * drivers to finish off the job..
- */
-#include "wds.h"
-#if NWDS > 0
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/errno.h>
-#include <sys/ioctl.h>
-#include <sys/buf.h>
-#include <sys/proc.h>
-#include <sys/user.h>
-#include <sys/dkbad.h>
-#include <sys/disklabel.h>
-
-#include <scsi/scsi_all.h>
-#include <scsi/scsiconf.h>
-
-#include <machine/cpu.h>
-#include <machine/pio.h>
-
-#include <dev/isa/isadmavar.h>
-#include <i386/isa/isa_device.h> /* XXX BROKEN */
-
-extern int delaycount; /* from clock setup code */
-
-#define PHYSTOKV(x) ((x) + KERNBASE)
-#define KVTOPHYS(x) vtophys(x)
-#define PAGESIZ 4096
-
-
-/* WD7000 registers */
-#define WDS_STAT 0 /* read */
-#define WDS_IRQSTAT 1 /* read */
-
-#define WDS_CMD 0 /* write */
-#define WDS_IRQACK 1 /* write */
-#define WDS_HCR 2 /* write */
-
-/* WDS_STAT (read) defs */
-#define WDS_IRQ 0x80
-#define WDS_RDY 0x40
-#define WDS_REJ 0x20
-#define WDS_INIT 0x10
-
-/* WDS_IRQSTAT (read) defs */
-#define WDSI_MASK 0xc0
-#define WDSI_ERR 0x00
-#define WDSI_MFREE 0x80
-#define WDSI_MSVC 0xc0
-
-/* WDS_CMD (write) defs */
-#define WDSC_NOOP 0x00
-#define WDSC_INIT 0x01
-#define WDSC_DISUNSOL 0x02
-#define WDSC_ENAUNSOL 0x03
-#define WDSC_IRQMFREE 0x04
-#define WDSC_SCSIRESETSOFT 0x05
-#define WDSC_SCSIRESETHARD 0x06
-#define WDSC_MSTART(m) (0x80 + (m))
-#define WDSC_MMSTART(m) (0xc0 + (m))
-
-/* WDS_HCR (write) defs */
-#define WDSH_IRQEN 0x08
-#define WDSH_DRQEN 0x04
-#define WDSH_SCSIRESET 0x02
-#define WDSH_ASCRESET 0x01
-
-struct wds_cmd {
- u_char cmd;
- u_char targ;
- struct scsi_generic scb; /*u_char scb[12];*/
- u_char stat;
- u_char venderr;
- u_char len[3];
- u_char data[3];
- u_char next[3];
- u_char write;
- u_char xx[6];
-};
-
-struct wds_req {
- struct wds_cmd cmd;
- struct wds_cmd sense;
- struct scsi_xfer *sxp;
- int busy, polled;
- int done, ret, ombn;
-};
-
-#define WDSX_SCSICMD 0x00
-#define WDSX_OPEN_RCVBUF 0x80
-#define WDSX_RCV_CMD 0x81
-#define WDSX_RCV_DATA 0x82
-#define WDSX_RCV_DATASTAT 0x83
-#define WDSX_SND_DATA 0x84
-#define WDSX_SND_DATASTAT 0x85
-#define WDSX_SND_CMDSTAT 0x86
-#define WDSX_READINIT 0x88
-#define WDSX_READSCSIID 0x89
-#define WDSX_SETUNSOLIRQMASK 0x8a
-#define WDSX_GETUNSOLIRQMASK 0x8b
-#define WDSX_GETFIRMREV 0x8c
-#define WDSX_EXECDIAG 0x8d
-#define WDSX_SETEXECPARM 0x8e
-#define WDSX_GETEXECPARM 0x8f
-
-struct wds_mb {
- u_char stat;
- u_char addr[3];
-};
-/* ICMB status value */
-#define ICMB_OK 0x01
-#define ICMB_OKERR 0x02
-#define ICMB_ETIME 0x04
-#define ICMB_ERESET 0x05
-#define ICMB_ETARCMD 0x06
-#define ICMB_ERESEL 0x80
-#define ICMB_ESEL 0x81
-#define ICMB_EABORT 0x82
-#define ICMB_ESRESET 0x83
-#define ICMB_EHRESET 0x84
-
-struct wds_setup {
- u_char cmd;
- u_char scsi_id;
- u_char buson_t;
- u_char busoff_t;
- u_char xx;
- u_char mbaddr[3];
- u_char nomb;
- u_char nimb;
-};
-
-#define WDS_NOMB 16
-#define WDS_NIMB 8
-#define MAXSIMUL 8
-struct wds {
- int addr;
- struct wds_req wdsr[MAXSIMUL];
- struct wds_mb ombs[WDS_NOMB], imbs[WDS_NIMB];
-} wds[NWDS];
-
-static int wdsunit = 0;
-int wds_debug = 0;
-
-void p2x(u_char *, u_long);
-u_char *x2p(u_char *);
-int wdsprobe(struct isa_device *);
-void wds_minphys(struct buf *);
-struct wds_req *wdsr_alloc(int);
-int wds_scsi_cmd(struct scsi_xfer *);
-long wds_adapter_info(int);
-int wdsintr(int);
-int wds_done(int, struct wds_cmd *, u_char);
-int wdsattach(struct isa_device *);
-int wds_init(struct isa_device *);
-int wds_cmd(int, u_char *, int);
-void wds_wait(int, int, int);
-
-
-struct scsi_switch wds_switch[NWDS];
-
-struct isa_driver wdsdriver = {
- wdsprobe,
- wdsattach,
- "wds",
-};
-
-
-void
-flushcache(void)
-{
- extern main();
- volatile char *p, c;
- int i;
-
- for(p=(char *)main, i=0; i<256*1024; i++)
- c = *p++;
-}
-
-void
-p2x(u_char *p, u_long x)
-{
- p[0] = (x & 0x00ff0000) >> 16;
- p[1] = (x & 0x0000ff00) >> 8;
- p[2] = (x & 0x000000ff);
-}
-
-u_char *
-x2p(u_char *x)
-{
- u_long q;
-
- q = ((x[0]<<16) & 0x00ff0000) + ((x[1]<<8) & 0x0000ff00) + (x[2] & 0x000000ff);
- return (u_char *)q;
-}
-
-int
-wdsprobe(struct isa_device *dev)
-{
- /*scsi_debug = PRINTROUTINES | TRACEOPENS | TRACEINTERRUPTS |
- SHOWREQUESTS | SHOWSCATGATH | SHOWINQUIRY | SHOWCOMMANDS;*/
-
- if (dev->id_parent)
- return 1;
-
- if(wdsunit > NWDS)
- return 0;
-
- dev->id_unit = wdsunit;
- wds[wdsunit].addr = dev->id_iobase;
-
- if(wds_init(dev) != 0)
- return 0;
- wdsunit++;
- return 8;
-}
-
-void
-wds_minphys(struct buf *bp)
-{
- int base = (int)bp->b_data & (PAGESIZ-1);
-
- if (base + bp->b_bcount > PAGESIZ)
- bp->b_bcount = PAGESIZ - base;
- minphys(bp);
-}
-
-struct wds_req *
-wdsr_alloc(int unit)
-{
- struct wds_req *r;
- int x;
- int i;
-
- r = NULL;
- x = splbio();
- for(i=0; i<MAXSIMUL; i++)
- if(wds[unit].wdsr[i].busy == 0) {
- r = &wds[unit].wdsr[i];
- r->busy = 1;
- break;
- }
- if(r == NULL) {
- splx(x);
- return NULL;
- }
-
- r->ombn = -1;
- for(i=0; i<WDS_NOMB; i++)
- if(wds[unit].ombs[i].stat==0) {
- wds[unit].ombs[i].stat = 1;
- r->ombn = i;
- break;
- }
- if(r->ombn == -1 ) {
- r->busy = 0;
- splx(x);
- return NULL;
- }
- splx(x);
- return r;
-}
-
-int
-wds_scsi_cmd(struct scsi_xfer *sxp)
-{
- struct wds_req *r;
- int unit = sxp->adapter;
- int base;
- u_char c, *p;
- int i;
-
- base = wds[unit].addr;
-
- /*printf("scsi_cmd\n");*/
-
- if( sxp->flags & SCSI_RESET) {
- printf("reset!\n");
- return COMPLETE;
- }
-
- r = wdsr_alloc(unit);
- if(r==NULL) {
- printf("no request slot available!\n");
- sxp->error = XS_DRIVER_STUFFUP;
- return TRY_AGAIN_LATER;
- }
- r->done = 0;
- r->sxp = sxp;
-
- printf("wds%d: target %d/%d req %8x flags %08x len %d: ", unit,
- sxp->targ, sxp->lu, r, sxp->flags, sxp->cmdlen);
- for(i=0, p=(u_char *)sxp->cmd; i<sxp->cmdlen; i++)
- printf("%02x ", p[i]);
- printf("\n");
- printf(" data %08x datalen %08x\n", sxp->data, sxp->datalen);
-
- if(sxp->flags & SCSI_DATA_UIO) {
- printf("UIO!\n");
- sxp->error = XS_DRIVER_STUFFUP;
- return TRY_AGAIN_LATER;
- }
-
- p2x(&wds[unit].ombs[r->ombn].addr[0], KVTOPHYS(&r->cmd));
- printf("%08x/%08x mbox@%08x: %02x %02x %02x %02x\n",
- &r->cmd, KVTOPHYS(&r->cmd), &wds[unit].ombs[0],
- wds[unit].ombs[r->ombn].stat, wds[unit].ombs[r->ombn].addr[0],
- wds[unit].ombs[r->ombn].addr[1], wds[unit].ombs[r->ombn].addr[2]);
-
- bzero(&r->cmd, sizeof r->cmd);
- r->cmd.cmd = WDSX_SCSICMD;
- r->cmd.targ = (sxp->targ << 5) | sxp->lu;
- bcopy(sxp->cmd, &r->cmd.scb, sxp->cmdlen<12 ? sxp->cmdlen : 12);
- p2x(&r->cmd.len[0], sxp->datalen);
- p2x(&r->cmd.data[0], sxp->datalen ? KVTOPHYS(sxp->data) : 0);
- r->cmd.write = (sxp->flags&SCSI_DATA_IN)? 0x80 : 0x00;
- p2x(&r->cmd.next[0], KVTOPHYS(&r->sense));
-
- bzero(&r->sense, sizeof r->sense);
- r->sense.cmd = r->cmd.cmd;
- r->sense.targ = r->cmd.targ;
- r->sense.scb.opcode = REQUEST_SENSE;
- p2x(&r->sense.data[0], KVTOPHYS(&sxp->sense));
- p2x(&r->sense.len[0], sizeof sxp->sense);
- r->sense.write = 0x80;
-
- /*printf("wdscmd: ");
- for(i=0, p=(u_char *)&r->cmd; i<sizeof r->cmd; i++)
- printf("%02x ", p[i]);
- printf("\n");*/
-
- if(sxp->flags & SCSI_NOMASK) {
- outb(base+WDS_HCR, WDSH_DRQEN);
- r->polled = 1;
- } else
- r->polled = 0;
-
- c = WDSC_MSTART(r->ombn);
- flushcache();
- if( wds_cmd(base, &c, sizeof c) != 0) {
- printf("wds%d: unable to start outgoing mbox\n", unit);
- r->busy = 0;
- /* XXX need to free mailbox */
- return TRY_AGAIN_LATER;
- }
-
- delay(10000);
- /*printf("%08x/%08x mbox: %02x %02x %02x %02x\n", &r->cmd, KVTOPHYS(&r->cmd),
- wds[unit].ombs[r->ombn].stat, wds[unit].ombs[r->ombn].addr[0],
- wds[unit].ombs[r->ombn].addr[1], wds[unit].ombs[r->ombn].addr[2]);*/
-
- if(sxp->flags & SCSI_NOMASK) {
-repoll: printf("wds%d: polling.", unit);
- i = 0;
- while( (inb(base+WDS_STAT) & WDS_IRQ) == 0) {
- printf(".");
- delay(10000);
- if(++i == 10) {
- printf("failed %02x\n", inb(base+WDS_IRQSTAT));
- /*r->busy = 0;*/
- sxp->error = XS_TIMEOUT;
- return HAD_ERROR;
- }
- }
- flushcache();
- printf("got one!\n");
- wdsintr(unit);
- if(r->done) {
- r->sxp->flags |= ITSDONE;
- if(r->sxp->when_done)
- (*r->sxp->when_done)(r->sxp->done_arg,
- r->sxp->done_arg2);
- r->busy = 0;
- return r->ret;
- }
- goto repoll;
- }
-
- outb(base+WDS_HCR, WDSH_IRQEN|WDSH_DRQEN);
- printf("wds%d: successfully queued\n", unit);
- return SUCCESSFULLY_QUEUED;
-}
-
-long
-wds_adapter_info(int unit)
-{
- return 1;
-}
-
-int
-wdsintr(int unit)
-{
- struct wds_cmd *pc, *vc;
- struct wds_mb *in;
- u_char stat;
- u_char c;
-
- /*printf("stat=%02x\n", inb(wds[unit].addr + WDS_STAT));*/
- delay(1000);
- c = inb(wds[unit].addr + WDS_IRQSTAT);
- printf("wdsintr: %02x\n", c);
- if( (c&WDSI_MASK) == WDSI_MSVC) {
- delay(1000);
- c = c & ~WDSI_MASK;
- flushcache();
- in = &wds[unit].imbs[c];
-
- printf("incoming mailbox %02x@%08x: ", c, in);
- printf("%02x %02x %02x %02x\n",
- in->stat, in->addr[0], in->addr[1], in->addr[2]);
- pc = (struct wds_cmd *)x2p(&in->addr[0]);
- vc = (struct wds_cmd *)PHYSTOKV(pc);
- stat = in->stat;
- printf("p=%08x v=%08x stat %02x\n", pc, vc, stat);
- wds_done(unit, vc, stat);
- in->stat = 0;
-
- outb(wds[unit].addr + WDS_IRQACK, 0xff);
- }
- return 1;
-}
-
-int
-wds_done(int unit, struct wds_cmd *c, u_char stat)
-{
- struct wds_req *r;
- int i;
-
- r = (struct wds_req *)NULL;
- for(i=0; i<MAXSIMUL; i++)
- if( c == &wds[unit].wdsr[i].cmd ) {
- /*printf("found at req slot %d\n", i);*/
- r = &wds[unit].wdsr[i];
- break;
- }
- if(r == (struct wds_req *)NULL) {
- printf("failed to find request!\n");
- return 1;
- }
-
- printf("wds%d: cmd %8x stat %2x/%2x %2x/%2x\n", unit, c,
- r->cmd.stat, r->cmd.venderr, r->sense.stat, r->sense.venderr);
-
- r->done = 1;
- /* XXX need to free mailbox */
- r->ret = HAD_ERROR;
- switch(r->cmd.stat) {
- case ICMB_OK:
- /*XXX r->sxp->sense.valid = 0;
- r->sxp->error = 0;*/
- r->ret = COMPLETE;
- break;
- case ICMB_OKERR:
- printf("scsi err %02x\n", c->venderr);
- /*XXX r->sxp->sense.error_code = c->venderr;
- r->sxp->sense.valid = 1;*/
- r->ret = COMPLETE;
- break;
- case ICMB_ETIME:
- r->sxp->error = XS_TIMEOUT;
- r->ret = HAD_ERROR;
- break;
- case ICMB_ERESET:
- case ICMB_ETARCMD:
- case ICMB_ERESEL:
- case ICMB_ESEL:
- case ICMB_EABORT:
- case ICMB_ESRESET:
- case ICMB_EHRESET:
- r->sxp->error = XS_DRIVER_STUFFUP;
- r->ret = HAD_ERROR;
- break;
- }
- if(r->polled==0) {
- r->sxp->flags |= ITSDONE;
- if(r->sxp->when_done)
- (*r->sxp->when_done)(r->sxp->done_arg, r->sxp->done_arg2);
- r->busy = 0;
- }
- return 0;
-}
-
-int
-wds_getvers(int unit)
-{
- struct wds_req *r;
- int base;
- u_char c, *p;
- int i;
-
- base = wds[unit].addr;
-
- /*printf("scsi_cmd\n");*/
-
- r = wdsr_alloc(unit);
- if(r==NULL) {
- printf("wds%d: no request slot available!\n", unit);
- return -1;
- }
- r->done = 0;
- r->sxp = NULL;
-
- printf("wds%d: getvers req %8x\n", unit, r);
-
- p2x(&wds[unit].ombs[r->ombn].addr[0], KVTOPHYS(&r->cmd));
- printf("%08x/%08x mbox@%08x: %02x %02x %02x %02x\n",
- &r->cmd, KVTOPHYS(&r->cmd), &wds[unit].ombs[0],
- wds[unit].ombs[r->ombn].stat, wds[unit].ombs[r->ombn].addr[0],
- wds[unit].ombs[r->ombn].addr[1], wds[unit].ombs[r->ombn].addr[2]);
-
- bzero(&r->cmd, sizeof r->cmd);
- r->cmd.cmd = WDSX_GETFIRMREV;
- r->cmd.write = 0x80;
-
- printf("wdscmd: ");
- for(i=0, p=(u_char *)&r->cmd; i<sizeof r->cmd; i++)
- printf("%02x ", p[i]);
- printf("\n");
-
- outb(base+WDS_HCR, WDSH_DRQEN);
- r->polled = 1;
-
- c = WDSC_MSTART(r->ombn);
- flushcache();
- if( wds_cmd(base, &c, sizeof c) != 0) {
- printf("wds%d: unable to start outgoing mbox\n", unit);
- r->busy = 0;
- /* XXX need to free mailbox */
- return -1;
- }
-
- delay(10000);
- /*printf("%08x/%08x mbox: %02x %02x %02x %02x\n", &r->cmd, KVTOPHYS(&r->cmd),
- wds[unit].ombs[r->ombn].stat, wds[unit].ombs[r->ombn].addr[0],
- wds[unit].ombs[r->ombn].addr[1], wds[unit].ombs[r->ombn].addr[2]);*/
-
- while(1) {
- printf("wds%d: polling.", unit);
- i = 0;
- while( (inb(base+WDS_STAT) & WDS_IRQ) == 0) {
- printf(".");
- delay(10000);
- if(++i == 10) {
- printf("failed %02x\n", inb(base+WDS_IRQSTAT));
- /*r->busy = 0;*/
- return -1;
- }
- }
- flushcache();
- printf("got one!\n");
- wdsintr(unit);
- if(r->done) {
- printf("wds%d: version %02x %02x\n", unit,
- r->cmd.targ, r->cmd.scb.opcode);
- r->busy = 0;
- return 0;
- }
- }
-}
-
-int
-wdsattach(struct isa_device *dev)
-{
- int masunit;
- static int firstswitch[NWDS];
- static u_long versprobe /* max 32 controllers */
- int r;
-
- if (!dev->id_parent)
- return 1;
- masunit = dev->id_parent->id_unit;
-
- if( !(versprobe & (1<<masunit))) {
- versprobe |= (1<<masunit);
- if(wds_getvers(masunit)==-1)
- printf("wds%d: getvers failed\n", masunit);
- }
-
- if (!firstswitch[masunit]) {
- firstswitch[masunit] = 1;
- wds_switch[masunit].name = "wds";
- wds_switch[masunit].scsi_cmd = wds_scsi_cmd;
- wds_switch[masunit].scsi_minphys = wdsminphys;
- wds_switch[masunit].open_target_lu = 0;
- wds_switch[masunit].close_target_lu = 0;
- wds_switch[masunit].adapter_info = wds_adapter_info;
- for (r = 0; r < 8; r++) {
- wds_switch[masunit].empty[r] = 0;
- wds_switch[masunit].used[r] = 0;
- wds_switch[masunit].printed[r] = 0;
- }
- }
- r = scsi_attach(masunit, &wds_switch[masunit], &dev->id_physid,
- &dev->id_unit, dev->id_flags);
- return r;
-}
-
-int
-wds_init(struct isa_device *dev)
-{
- struct wds_setup init;
- int base;
- u_char *p, c;
- int unit, i;
-
- unit = dev->id_unit;
- base = wds[unit].addr;
-
- /*
- * Sending a command causes the CMDRDY bit to clear.
- */
- c = inb(base+WDS_STAT);
- for(i=0; i<4; i++)
- if( (inb(base+WDS_STAT) & WDS_RDY) != 0) {
- goto ready;
- delay(10);
- }
- return 1;
-
-ready:
- outb(base+WDS_CMD, WDSC_NOOP);
- if( inb(base+WDS_STAT) & WDS_RDY)
- return 1;
-
- /*
- * the controller exists. reset and init.
- */
- outb(base+WDS_HCR, WDSH_SCSIRESET|WDSH_ASCRESET);
- delay(3);
- outb(base+WDS_HCR, WDSH_DRQEN);
- delay(20000);
-
-#if 1
- outb(0xd6, 0xc3);
- outb(0xd4, 0x03);
-#else
- isa_dmacascade(dev->id_drq);
-#endif
-
- if( (inb(base+WDS_STAT) & (WDS_RDY)) != WDS_RDY) {
- printf("wds%d: waiting for controller to become ready", unit);
- for(i=0; i<6; i++) {
- if( (inb(base+WDS_STAT) & (WDS_RDY)) == WDS_RDY)
- break;
- printf(".");
- delay(10000);
- }
- if( (inb(base+WDS_STAT) & (WDS_RDY)) != WDS_RDY) {
- printf("failed\n");
- return 1;
- }
- }
-
- bzero(&init, sizeof init);
- init.cmd = WDSC_INIT;
- init.scsi_id = 0;
- init.buson_t = 24;
- init.busoff_t = 48;
- p2x(&init.mbaddr[0], KVTOPHYS(&wds[unit].ombs[0]));
- init.xx = 0;
- init.nomb = WDS_NOMB;
- init.nimb = WDS_NIMB;
-
- /*p = (u_char *)&init;
- printf("wds%d: %08x %08x init: ", unit,
- &wds[unit].ombs[0], KVTOPHYS(&wds[unit].ombs[0]));
- for(i=0; i<sizeof init; i++)
- printf("%02x ", p[i]);
- printf("\n");*/
-
- wds_wait(base+WDS_STAT, WDS_RDY, WDS_RDY);
- flushcache();
- if( wds_cmd(base, (u_char *)&init, sizeof init) != 0) {
- printf("wds%d: wds_cmd failed\n", unit);
- return 1;
- }
- wds_wait(base+WDS_STAT, WDS_INIT, WDS_INIT);
-
- wds_wait(base+WDS_STAT, WDS_RDY, WDS_RDY);
- c = WDSC_DISUNSOL;
- if( wds_cmd(base, &c, sizeof c) != 0) {
- printf("wds%d: wds_cmd failed\n", unit);
- return 1;
- }
-
- return 0;
-}
-
-int
-wds_cmd(int base, u_char *p, int l)
-{
- int i;
- u_char c;
-
- i = 0;
- while(i < l) {
- while( ((c=inb(base+WDS_STAT)) & WDS_RDY) == 0)
- ;
-
- outb(base+WDS_CMD, *p);
-
- while( ((c=inb(base+WDS_STAT)) & WDS_RDY) == 0)
- ;
-
- if(c & WDS_REJ)
- return 1;
- p++;
- i++;
- }
- while( ((c=inb(base+WDS_STAT)) & WDS_RDY) == 0)
- ;
- if(c & WDS_REJ)
- return 1;
- /*printf("wds_cmd: %02x\n", inb(base+WDS_STAT));*/
- return 0;
-}
-
-void
-wds_wait(int reg, int mask, int val)
-{
- while( (inb(reg) & mask) != val)
- ;
-}
-
-#endif
diff --git a/sys/dev/isa/wds.c b/sys/dev/isa/wds.c
new file mode 100644
index 00000000000..c102f7008af
--- /dev/null
+++ b/sys/dev/isa/wds.c
@@ -0,0 +1,1306 @@
+/* $NetBSD: wds.c,v 1.4 1996/04/11 22:30:38 cgd Exp $ */
+
+#define WDSDIAG
+#define integrate
+
+/*
+ * XXX
+ * sense data
+ * aborts
+ * resets
+ */
+
+/*
+ * Copyright (c) 1994, 1995 Julian Highfield. All rights reserved.
+ * Portions copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Julian Highfield.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This driver is for the WD7000 family of SCSI controllers:
+ * the WD7000-ASC, a bus-mastering DMA controller,
+ * the WD7000-FASST2, an -ASC with new firmware and scatter-gather,
+ * and the WD7000-ASE, which was custom manufactured for Apollo
+ * workstations and seems to include an -ASC as well as floppy
+ * and ESDI interfaces.
+ *
+ * Loosely based on Theo Deraadt's unfinished attempt.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+
+#include <machine/pio.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
+#include <dev/isa/wdsreg.h>
+
+#ifndef DDB
+#define Debugger() panic("should call debugger here (wds.c)")
+#endif /* ! DDB */
+
+#define WDS_MBX_SIZE 16
+
+#define WDS_SCB_MAX 32
+#define SCB_HASH_SIZE 32 /* hash table size for phystokv */
+#define SCB_HASH_SHIFT 9
+#define SCB_HASH(x) ((((long)(x))>>SCB_HASH_SHIFT) & (SCB_HASH_SIZE - 1))
+
+#define wds_nextmbx(wmb, mbx, mbio) \
+ if ((wmb) == &(mbx)->mbio[WDS_MBX_SIZE - 1]) \
+ (wmb) = &(mbx)->mbio[0]; \
+ else \
+ (wmb)++;
+
+struct wds_mbx {
+ struct wds_mbx_out mbo[WDS_MBX_SIZE];
+ struct wds_mbx_in mbi[WDS_MBX_SIZE];
+ struct wds_mbx_out *cmbo; /* Collection Mail Box out */
+ struct wds_mbx_out *tmbo; /* Target Mail Box out */
+ struct wds_mbx_in *tmbi; /* Target Mail Box in */
+};
+
+#define KVTOPHYS(x) vtophys(x)
+
+struct wds_softc {
+ struct device sc_dev;
+ struct isadev sc_id;
+ void *sc_ih;
+
+ int sc_iobase;
+ int sc_irq, sc_drq;
+
+ int sc_revision;
+
+ struct wds_mbx sc_mbx;
+#define wmbx (&sc->sc_mbx)
+ struct wds_scb *sc_scbhash[SCB_HASH_SIZE];
+ TAILQ_HEAD(, wds_scb) sc_free_scb, sc_waiting_scb;
+ int sc_numscbs, sc_mbofull;
+ int sc_scsi_dev;
+ struct scsi_link sc_link; /* prototype for subdevs */
+};
+
+/* Define the bounce buffer length... */
+#define BUFLEN (64*1024)
+/* ..and how many there are. One per device! Non-FASST boards need these. */
+#define BUFCNT 8
+/* The macro for deciding whether the board needs a buffer. */
+#define NEEDBUFFER(sc) (sc->sc_revision < 0x800)
+
+struct wds_buf {
+ u_char data[BUFLEN];
+ int busy;
+ TAILQ_ENTRY(wds_buf) chain;
+} wds_buffer[BUFCNT];
+
+TAILQ_HEAD(, wds_buf) wds_free_buffer;
+
+integrate void wds_wait __P((int, int, int));
+int wds_cmd __P((int, u_char *, int));
+integrate void wds_finish_scbs __P((struct wds_softc *));
+int wdsintr __P((void *));
+integrate void wds_reset_scb __P((struct wds_softc *, struct wds_scb *));
+void wds_free_scb __P((struct wds_softc *, struct wds_scb *));
+void wds_free_buf __P((struct wds_softc *, struct wds_buf *));
+integrate void wds_init_scb __P((struct wds_softc *, struct wds_scb *));
+struct wds_scb *wds_get_scb __P((struct wds_softc *, int, int));
+struct wds_buf *wds_get_buf __P((struct wds_softc *, int));
+struct wds_scb *wds_scb_phys_kv __P((struct wds_softc *, u_long));
+void wds_queue_scb __P((struct wds_softc *, struct wds_scb *));
+void wds_collect_mbo __P((struct wds_softc *));
+void wds_start_scbs __P((struct wds_softc *));
+void wds_done __P((struct wds_softc *, struct wds_scb *, u_char));
+int wds_find __P((struct isa_attach_args *, struct wds_softc *));
+void wds_init __P((struct wds_softc *));
+void wds_inquire_setup_information __P((struct wds_softc *));
+void wdsminphys __P((struct buf *));
+int wds_scsi_cmd __P((struct scsi_xfer *));
+void wds_sense __P((struct wds_softc *, struct wds_scb *));
+int wds_poll __P((struct wds_softc *, struct scsi_xfer *, int));
+int wds_ipoll __P((struct wds_softc *, struct wds_scb *, int));
+void wds_timeout __P((void *));
+
+struct scsi_adapter wds_switch = {
+ wds_scsi_cmd,
+ wdsminphys,
+ 0,
+ 0,
+};
+
+/* the below structure is so we have a default dev struct for our link struct */
+struct scsi_device wds_dev = {
+ NULL, /* Use default error handler */
+ NULL, /* have a queue, served by this */
+ NULL, /* have no async handler */
+ NULL, /* Use default 'done' routine */
+};
+
+int wdsprobe __P((struct device *, void *, void *));
+void wdsattach __P((struct device *, struct device *, void *));
+int wdsprint __P((void *, char *));
+
+struct cfattach wds_ca = {
+ sizeof(struct wds_softc), wdsprobe, wdsattach
+};
+
+struct cfdriver wds_cd = {
+ NULL, "wds", DV_DULL
+};
+
+#define WDS_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
+
+integrate void
+wds_wait(port, mask, val)
+ int port;
+ int mask;
+ int val;
+{
+
+ while ((inb(port) & mask) != val)
+ ;
+}
+
+/*
+ * Write a command to the board's I/O ports.
+ */
+int
+wds_cmd(iobase, ibuf, icnt)
+ int iobase;
+ u_char *ibuf;
+ int icnt;
+{
+ u_char c;
+
+ wds_wait(iobase + WDS_STAT, WDSS_RDY, WDSS_RDY);
+
+ while (icnt--) {
+ outb(iobase + WDS_CMD, *ibuf++);
+ wds_wait(iobase + WDS_STAT, WDSS_RDY, WDSS_RDY);
+ c = inb(iobase + WDS_STAT);
+ if (c & WDSS_REJ)
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Check for the presence of a WD7000 SCSI controller.
+ */
+int
+wdsprobe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ register struct isa_attach_args *ia = aux;
+
+#ifdef NEWCONFIG
+ if (ia->ia_iobase == IOBASEUNK)
+ return 0;
+#endif
+
+ /* See if there is a unit at this location. */
+ if (wds_find(ia, NULL) != 0)
+ return 0;
+
+ ia->ia_msize = 0;
+ ia->ia_iosize = 8;
+ return 1;
+}
+
+int
+wdsprint(aux, name)
+ void *aux;
+ char *name;
+{
+
+ if (name != NULL)
+ printf("%s: scsibus ", name);
+ return UNCONF;
+}
+
+/*
+ * Attach all available units.
+ */
+void
+wdsattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct isa_attach_args *ia = aux;
+ struct wds_softc *sc = (void *)self;
+
+ if (wds_find(ia, sc) != 0)
+ panic("wdsattach: wds_find of %s failed", self->dv_xname);
+ sc->sc_iobase = ia->ia_iobase;
+
+ if (sc->sc_drq != DRQUNK)
+ isa_dmacascade(sc->sc_drq);
+
+ wds_init(sc);
+ TAILQ_INIT(&sc->sc_free_scb);
+ TAILQ_INIT(&sc->sc_waiting_scb);
+ wds_inquire_setup_information(sc);
+
+ /*
+ * fill in the prototype scsi_link.
+ */
+ sc->sc_link.adapter_softc = sc;
+ sc->sc_link.adapter_target = sc->sc_scsi_dev;
+ sc->sc_link.adapter = &wds_switch;
+ sc->sc_link.device = &wds_dev;
+ /* XXX */
+ /* I don't think the -ASE can handle openings > 1. */
+ /* It gives Vendor Error 26 whenever I try it. */
+ sc->sc_link.openings = 1;
+
+#ifdef NEWCONFIG
+ isa_establish(&sc->sc_id, &sc->sc_dev);
+#endif
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, sc->sc_irq, IST_EDGE,
+ IPL_BIO, wdsintr, sc, sc->sc_dev.dv_xname);
+
+ /*
+ * ask the adapter what subunits are present
+ */
+ config_found(self, &sc->sc_link, wdsprint);
+}
+
+integrate void
+wds_finish_scbs(sc)
+ struct wds_softc *sc;
+{
+ struct wds_mbx_in *wmbi;
+ struct wds_scb *scb;
+ int i;
+
+ wmbi = wmbx->tmbi;
+
+ if (wmbi->stat == WDS_MBI_FREE) {
+ for (i = 0; i < WDS_MBX_SIZE; i++) {
+ if (wmbi->stat != WDS_MBI_FREE) {
+ printf("%s: mbi not in round-robin order\n",
+ sc->sc_dev.dv_xname);
+ goto AGAIN;
+ }
+ wds_nextmbx(wmbi, wmbx, mbi);
+ }
+#ifdef WDSDIAGnot
+ printf("%s: mbi interrupt with no full mailboxes\n",
+ sc->sc_dev.dv_xname);
+#endif
+ return;
+ }
+
+AGAIN:
+ do {
+ scb = wds_scb_phys_kv(sc, phystol(wmbi->scb_addr));
+ if (!scb) {
+ printf("%s: bad mbi scb pointer; skipping\n",
+ sc->sc_dev.dv_xname);
+ goto next;
+ }
+
+#ifdef WDSDEBUG
+ if (wds_debug) {
+ u_char *cp = &scb->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 addr = 0x%08x, ",
+ wmbi->stat, wmbi);
+ printf("scb addr = 0x%x\n", scb);
+ }
+#endif /* WDSDEBUG */
+
+ untimeout(wds_timeout, scb);
+ wds_done(sc, scb, wmbi->stat);
+
+ next:
+ wmbi->stat = WDS_MBI_FREE;
+ wds_nextmbx(wmbi, wmbx, mbi);
+ } while (wmbi->stat != WDS_MBI_FREE);
+
+ wmbx->tmbi = wmbi;
+}
+
+/*
+ * Process an interrupt.
+ */
+int
+wdsintr(arg)
+ void *arg;
+{
+ struct wds_softc *sc = arg;
+ int iobase = sc->sc_iobase;
+ u_char sts;
+
+ struct wds_mbx_in *in;
+ struct wds_scb *scb;
+ u_char stat, c;
+
+ /* Was it really an interrupt from the board? */
+ if ((inb(iobase + WDS_STAT) & WDSS_IRQ) == 0)
+ return 0;
+
+ /* Get the interrupt status byte. */
+ c = inb(iobase + WDS_IRQSTAT) & WDSI_MASK;
+
+ /* Acknowledge (which resets) the interrupt. */
+ outb(iobase + WDS_IRQACK, 0x00);
+
+ switch (c) {
+ case WDSI_MSVC:
+ wds_finish_scbs(sc);
+ break;
+
+ case WDSI_MFREE:
+ wds_start_scbs(sc);
+ break;
+
+ default:
+ printf("%s: unrecognized interrupt type %02x", c);
+ break;
+ }
+
+ return 1;
+}
+
+integrate void
+wds_reset_scb(sc, scb)
+ struct wds_softc *sc;
+ struct wds_scb *scb;
+{
+
+ scb->flags = 0;
+}
+
+/*
+ * Free the command structure, the outgoing mailbox and the data buffer.
+ */
+void
+wds_free_scb(sc, scb)
+ struct wds_softc *sc;
+ struct wds_scb *scb;
+{
+ int s;
+
+ if (scb->buf != 0) {
+ wds_free_buf(sc, scb->buf);
+ scb->buf = 0;
+ }
+
+ s = splbio();
+
+ wds_reset_scb(sc, scb);
+ TAILQ_INSERT_HEAD(&sc->sc_free_scb, scb, chain);
+
+ /*
+ * If there were none, wake anybody waiting for one to come free,
+ * starting with queued entries.
+ */
+ if (scb->chain.tqe_next == 0)
+ wakeup(&sc->sc_free_scb);
+
+ splx(s);
+}
+
+void
+wds_free_buf(sc, buf)
+ struct wds_softc *sc;
+ struct wds_buf *buf;
+{
+ int s;
+
+ s = splbio();
+
+ buf->busy = 0;
+ TAILQ_INSERT_HEAD(&wds_free_buffer, buf, chain);
+
+ /*
+ * If there were none, wake anybody waiting for one to come free,
+ * starting with queued entries.
+ */
+ if (buf->chain.tqe_next == 0)
+ wakeup(&wds_free_buffer);
+
+ splx(s);
+}
+
+integrate void
+wds_init_scb(sc, scb)
+ struct wds_softc *sc;
+ struct wds_scb *scb;
+{
+ int hashnum;
+
+ bzero(scb, sizeof(struct wds_scb));
+ /*
+ * put in the phystokv hash table
+ * Never gets taken out.
+ */
+ scb->hashkey = KVTOPHYS(scb);
+ hashnum = SCB_HASH(scb->hashkey);
+ scb->nexthash = sc->sc_scbhash[hashnum];
+ sc->sc_scbhash[hashnum] = scb;
+ wds_reset_scb(sc, scb);
+}
+
+/*
+ * Get a free scb
+ *
+ * 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 wds_scb *
+wds_get_scb(sc, flags, needbuffer)
+ struct wds_softc *sc;
+ int flags;
+ int needbuffer;
+{
+ struct wds_scb *scb;
+ int s;
+
+ s = splbio();
+
+ /*
+ * If we can and have to, sleep waiting for one to come free
+ * but only if we can't allocate a new one.
+ */
+ for (;;) {
+ scb = sc->sc_free_scb.tqh_first;
+ if (scb) {
+ TAILQ_REMOVE(&sc->sc_free_scb, scb, chain);
+ break;
+ }
+ if (sc->sc_numscbs < WDS_SCB_MAX) {
+ scb = (struct wds_scb *) malloc(sizeof(struct wds_scb),
+ M_TEMP, M_NOWAIT);
+ if (!scb) {
+ printf("%s: can't malloc scb\n",
+ sc->sc_dev.dv_xname);
+ goto out;
+ }
+ wds_init_scb(sc, scb);
+ sc->sc_numscbs++;
+ break;
+ }
+ if ((flags & SCSI_NOSLEEP) != 0)
+ goto out;
+ tsleep(&sc->sc_free_scb, PRIBIO, "wdsscb", 0);
+ }
+
+ scb->flags |= SCB_ALLOC;
+
+ if (needbuffer) {
+ scb->buf = wds_get_buf(sc, flags);
+ if (scb->buf == 0)
+ wds_free_scb(sc, scb);
+ scb = 0;
+ }
+
+out:
+ splx(s);
+ return (scb);
+}
+
+struct wds_buf *
+wds_get_buf(sc, flags)
+ struct wds_softc *sc;
+ int flags;
+{
+ struct wds_buf *buf;
+ int s;
+
+ s = splbio();
+
+ for (;;) {
+ buf = wds_free_buffer.tqh_first;
+ if (buf) {
+ TAILQ_REMOVE(&wds_free_buffer, buf, chain);
+ break;
+ }
+ if ((flags & SCSI_NOSLEEP) != 0)
+ goto out;
+ tsleep(&wds_free_buffer, PRIBIO, "wdsbuf", 0);
+ }
+
+ buf->busy = 1;
+
+out:
+ splx(s);
+ return (buf);
+}
+
+struct wds_scb *
+wds_scb_phys_kv(sc, scb_phys)
+ struct wds_softc *sc;
+ u_long scb_phys;
+{
+ int hashnum = SCB_HASH(scb_phys);
+ struct wds_scb *scb = sc->sc_scbhash[hashnum];
+
+ while (scb) {
+ if (scb->hashkey == scb_phys)
+ break;
+ /* XXX Check to see if it matches the sense command block. */
+ if (scb->hashkey == (scb_phys - sizeof(struct wds_cmd)))
+ break;
+ scb = scb->nexthash;
+ }
+ return scb;
+}
+
+/*
+ * Queue a SCB to be sent to the controller, and send it if possible.
+ */
+void
+wds_queue_scb(sc, scb)
+ struct wds_softc *sc;
+ struct wds_scb *scb;
+{
+
+ TAILQ_INSERT_TAIL(&sc->sc_waiting_scb, scb, chain);
+ wds_start_scbs(sc);
+}
+
+/*
+ * Garbage collect mailboxes that are no longer in use.
+ */
+void
+wds_collect_mbo(sc)
+ struct wds_softc *sc;
+{
+ struct wds_mbx_out *wmbo; /* Mail Box Out pointer */
+ struct wds_scb *scb;
+
+ wmbo = wmbx->cmbo;
+
+ while (sc->sc_mbofull > 0) {
+ if (wmbo->cmd != WDS_MBO_FREE)
+ break;
+
+#ifdef WDSDIAG
+ scb = wds_scb_phys_kv(sc, phystol(wmbo->scb_addr));
+ scb->flags &= ~SCB_SENDING;
+#endif
+
+ --sc->sc_mbofull;
+ wds_nextmbx(wmbo, wmbx, mbo);
+ }
+
+ wmbx->cmbo = wmbo;
+}
+
+/*
+ * Send as many SCBs as we have empty mailboxes for.
+ */
+void
+wds_start_scbs(sc)
+ struct wds_softc *sc;
+{
+ int iobase = sc->sc_iobase;
+ struct wds_mbx_out *wmbo; /* Mail Box Out pointer */
+ struct wds_scb *scb;
+ int i;
+ u_char c;
+
+ wmbo = wmbx->tmbo;
+
+ while (scb = sc->sc_waiting_scb.tqh_first) {
+ if (sc->sc_mbofull >= WDS_MBX_SIZE) {
+ wds_collect_mbo(sc);
+ if (sc->sc_mbofull >= WDS_MBX_SIZE) {
+ c = WDSC_IRQMFREE;
+ wds_cmd(iobase, &c, sizeof c);
+ break;
+ }
+ }
+
+ TAILQ_REMOVE(&sc->sc_waiting_scb, scb, chain);
+#ifdef WDSDIAG
+ scb->flags |= SCB_SENDING;
+#endif
+
+ /* Link scb to mbo. */
+ if (scb->flags & SCB_SENSE)
+ ltophys(KVTOPHYS(&scb->sense), wmbo->scb_addr);
+ else
+ ltophys(KVTOPHYS(&scb->cmd), wmbo->scb_addr);
+ /* XXX What about aborts? */
+ wmbo->cmd = WDS_MBO_START;
+
+ /* Tell the card to poll immediately. */
+ c = WDSC_MSTART(wmbo - wmbx->mbo);
+ wds_cmd(sc->sc_iobase, &c, sizeof c);
+
+ if ((scb->flags & SCB_POLLED) == 0)
+ timeout(wds_timeout, scb, (scb->timeout * hz) / 1000);
+
+ next:
+ ++sc->sc_mbofull;
+ wds_nextmbx(wmbo, wmbx, mbo);
+ }
+
+ wmbx->tmbo = wmbo;
+}
+
+/*
+ * Process the result of a SCSI command.
+ */
+void
+wds_done(sc, scb, stat)
+ struct wds_softc *sc;
+ struct wds_scb *scb;
+ u_char stat;
+{
+ struct scsi_xfer *xs = scb->xs;
+ int i, x;
+
+ /* XXXXX */
+
+ /* Don't release the SCB if it was an internal command. */
+ if (xs == 0) {
+ scb->flags |= SCB_DONE;
+ return;
+ }
+
+ /* Sense handling. */
+ if (xs->error == XS_SENSE) {
+ bcopy(&scb->sense_data, &xs->sense, sizeof (struct scsi_sense_data));
+ } else {
+ if (xs->error == XS_NOERROR) {
+ /* If all went well, or an error is acceptable. */
+ if (stat == WDS_MBI_OK) {
+ /* OK, set the result */
+ xs->resid = 0;
+ } else {
+ /* Check the mailbox status. */
+ switch (stat) {
+ case WDS_MBI_OKERR:
+ /* SCSI error recorded in scb, counts as WDS_MBI_OK */
+ switch (scb->cmd.venderr) {
+ case 0x00:
+ printf("%s: Is this an error?\n", sc->sc_dev.dv_xname);
+ xs->error = XS_DRIVER_STUFFUP; /* Experiment */
+ break;
+ case 0x01:
+ /*printf("%s: OK, see SCSI error field.\n", sc->sc_dev.dv_xname);*/
+ if (scb->cmd.stat == SCSI_CHECK) {
+ /* Do sense. */
+ wds_sense (sc, scb);
+ return;
+ } else if (scb->cmd.stat == SCSI_BUSY) {
+ xs->error = XS_BUSY;
+ }
+ break;
+ case 0x40:
+ /*printf("%s: DMA underrun!\n", sc->sc_dev.dv_xname);*/
+ /* Hits this if the target returns fewer that datalen bytes (eg my CD-ROM,
+ which returns a short version string, or if DMA is turned off etc. */
+ xs->resid = 0;
+ break;
+ default:
+ printf("%s: VENDOR ERROR %02x, scsi %02x\n", sc->sc_dev.dv_xname, scb->cmd.venderr, scb->cmd.stat);
+ xs->error = XS_DRIVER_STUFFUP; /* Experiment */
+ break;
+ }
+ break;
+ case WDS_MBI_ETIME:
+ /*
+ * The documentation isn't clear on
+ * what conditions might generate this,
+ * but selection timeouts are the only
+ * one I can think of.
+ */
+ xs->error = XS_SELTIMEOUT;
+ break;
+ case WDS_MBI_ERESET:
+ case WDS_MBI_ETARCMD:
+ case WDS_MBI_ERESEL:
+ case WDS_MBI_ESEL:
+ case WDS_MBI_EABORT:
+ case WDS_MBI_ESRESET:
+ case WDS_MBI_EHRESET:
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
+ }
+ }
+ } /* else sense */
+
+ if (NEEDBUFFER(sc) && xs->datalen) {
+ if (xs->flags & SCSI_DATA_IN)
+ bcopy(scb->buf->data, xs->data, xs->datalen);
+ }
+ } /* XS_NOERROR */
+
+ wds_free_scb(sc, scb);
+ xs->flags |= ITSDONE;
+ scsi_done(xs);
+}
+
+int
+wds_find(ia, sc)
+ struct isa_attach_args *ia;
+ struct wds_softc *sc;
+{
+ int iobase = ia->ia_iobase;
+ u_char c;
+ int i;
+
+ /* XXXXX */
+
+ /*
+ * Sending a command causes the CMDRDY bit to clear.
+ */
+ c = inb(iobase + WDS_STAT);
+ for (i = 0; i < 4; i++)
+ if ((inb(iobase+WDS_STAT) & WDSS_RDY) != 0) {
+ goto ready;
+ delay(10);
+ }
+ return 1;
+
+ready:
+ outb(iobase + WDS_CMD, WDSC_NOOP);
+ if (inb(iobase + WDS_STAT) & WDSS_RDY)
+ return 1;
+
+ outb(iobase + WDS_HCR, WDSH_SCSIRESET|WDSH_ASCRESET);
+ delay(10000);
+ outb(iobase + WDS_HCR, 0x00);
+ delay(500000);
+ wds_wait(iobase + WDS_STAT, WDSS_RDY, WDSS_RDY);
+ if (inb(iobase + WDS_IRQSTAT) != 1)
+ if (inb(iobase + WDS_IRQSTAT) != 7)
+ printf("%s: failed reset!!! %2x\n", sc->sc_dev.dv_xname, inb(iobase + WDS_IRQSTAT));
+
+ if ((inb(iobase + WDS_STAT) & (WDSS_RDY)) != WDSS_RDY) {
+ printf("%s: waiting for controller to become ready.", sc->sc_dev.dv_xname);
+ for (i = 0; i < 20; i++) {
+ if ((inb(iobase + WDS_STAT) & (WDSS_RDY)) == WDSS_RDY)
+ break;
+ printf(".");
+ delay(10000);
+ }
+ if ((inb(iobase + WDS_STAT) & (WDSS_RDY)) != WDSS_RDY) {
+ printf(" failed\n");
+ return 1;
+ }
+ printf("\n");
+ }
+
+ if (sc != NULL) {
+ /* XXX Can we do this better? */
+ /* who are we on the scsi bus? */
+ sc->sc_scsi_dev = 7;
+
+ sc->sc_iobase = iobase;
+ sc->sc_irq = ia->ia_irq;
+ sc->sc_drq = ia->ia_drq;
+ }
+
+ return 0;
+}
+
+/*
+ * Initialise the board and driver.
+ */
+void
+wds_init(sc)
+ struct wds_softc *sc;
+{
+ int iobase = sc->sc_iobase;
+ struct wds_setup init;
+ u_char c;
+ int i;
+
+ /*
+ * Set up initial mail box for round-robin operation.
+ */
+ for (i = 0; i < WDS_MBX_SIZE; i++) {
+ wmbx->mbo[i].cmd = WDS_MBO_FREE;
+ wmbx->mbi[i].stat = WDS_MBO_FREE;
+ }
+ wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
+ wmbx->tmbi = &wmbx->mbi[0];
+ sc->sc_mbofull = 0;
+
+ /* Clear the buffers. */
+ TAILQ_INIT(&wds_free_buffer);
+ for (i = 0; i < BUFCNT; i++) {
+ wds_buffer[i].busy = 0;
+ TAILQ_INSERT_HEAD(&wds_free_buffer, &wds_buffer[i], chain);
+ }
+
+ init.opcode = WDSC_INIT;
+ init.scsi_id = sc->sc_scsi_dev;
+ /* Record scsi id of controller for use in scsi_attach */
+ sc->sc_scsi_dev = init.scsi_id;
+ init.buson_t = 48;
+ init.busoff_t = 24;
+ init.xx = 0;
+ ltophys(KVTOPHYS(wmbx), init.mbaddr);
+ init.nomb = init.nimb = WDS_MBX_SIZE;
+ wds_cmd(iobase, (u_char *)&init, sizeof init);
+
+ wds_wait(iobase + WDS_STAT, WDSS_INIT, WDSS_INIT);
+
+ c = WDSC_DISUNSOL;
+ wds_cmd(iobase, &c, sizeof c);
+
+ outb(iobase + WDS_HCR, WDSH_DRQEN);
+}
+
+/*
+ * Read the board's firmware revision information.
+ */
+void
+wds_inquire_setup_information(sc)
+ struct wds_softc *sc;
+{
+ struct wds_scb *scb;
+ int iobase;
+ u_char *j;
+ int s;
+
+ iobase = sc->sc_iobase;
+
+ if ((scb = wds_get_scb(sc, SCSI_NOSLEEP, 0)) == NULL) {
+ printf("%s: no request slot available in getvers()!\n", sc->sc_dev.dv_xname);
+ return;
+ }
+ scb->xs = NULL;
+ scb->timeout = 40;
+
+ bzero(&scb->cmd, sizeof scb->cmd);
+ scb->cmd.write = 0x80;
+ scb->cmd.opcode = WDSX_GETFIRMREV;
+
+ /* Will poll card, await result. */
+ outb(iobase + WDS_HCR, WDSH_DRQEN);
+ scb->flags |= SCB_POLLED;
+
+ s = splbio();
+ wds_queue_scb(sc, scb);
+ splx(s);
+
+ if (wds_ipoll(sc, scb, scb->timeout))
+ goto out;
+
+ /* Print the version number. */
+ printf(": version %x.%02x ", scb->cmd.targ, scb->cmd.scb.opcode);
+ sc->sc_revision = (scb->cmd.targ << 8) | scb->cmd.scb.opcode;
+ /* Print out the version string. */
+ j = 2 + &(scb->cmd.targ);
+ while ((*j >= 32) && (*j < 128)) {
+ printf("%c", *j);
+ j++;
+ }
+
+out:
+ printf("\n");
+ wds_free_scb(sc, scb);
+}
+
+void
+wdsminphys(bp)
+ struct buf *bp;
+{
+
+ if (bp->b_bcount > ((WDS_NSEG - 1) << PGSHIFT))
+ bp->b_bcount = ((WDS_NSEG - 1) << PGSHIFT);
+ minphys(bp);
+}
+
+/*
+ * Send a SCSI command.
+ */
+int
+wds_scsi_cmd(xs)
+ struct scsi_xfer *xs;
+{
+ struct scsi_link *sc_link = xs->sc_link;
+ struct wds_softc *sc = sc_link->adapter_softc;
+ struct wds_scb *scb;
+ struct wds_scat_gath *sg;
+ int seg;
+ u_long thiskv, thisphys, nextphys;
+ int bytes_this_seg, bytes_this_page, datalen, flags;
+ struct iovec *iovp;
+ int s;
+
+ int iobase;
+
+ iobase = sc->sc_iobase;
+
+ if (xs->flags & SCSI_RESET) {
+ /* XXX Fix me! */
+ printf("%s: reset!\n", sc->sc_dev.dv_xname);
+ wds_init(sc);
+ return COMPLETE;
+ }
+
+ flags = xs->flags;
+ if ((scb = wds_get_scb(sc, flags, NEEDBUFFER(sc))) == NULL) {
+ xs->error = XS_DRIVER_STUFFUP;
+ return TRY_AGAIN_LATER;
+ }
+ scb->xs = xs;
+ scb->timeout = xs->timeout;
+
+ if (xs->flags & SCSI_DATA_UIO) {
+ /* XXX Fix me! */
+ /* Let's not worry about UIO. There isn't any code for the *
+ * non-SG boards anyway! */
+ printf("%s: UIO is untested and disabled!\n", sc->sc_dev.dv_xname);
+ goto bad;
+ }
+
+ /* Zero out the command structure. */
+ bzero(&scb->cmd, sizeof scb->cmd);
+ bcopy(xs->cmd, &scb->cmd.scb, xs->cmdlen < 12 ? xs->cmdlen : 12);
+
+ /* Set up some of the command fields. */
+ scb->cmd.targ = (xs->sc_link->target << 5) | xs->sc_link->lun;
+
+ /* NOTE: cmd.write may be OK as 0x40 (disable direction checking)
+ * on boards other than the WD-7000V-ASE. Need this for the ASE:
+ */
+ scb->cmd.write = (xs->flags & SCSI_DATA_IN) ? 0x80 : 0x00;
+
+ if (!NEEDBUFFER(sc) && xs->datalen) {
+ sg = scb->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 < WDS_NSEG) {
+ ltophys(iovp->iov_base, sg->seg_addr);
+ ltophys(iovp->iov_len, sg->seg_len);
+ xs->datalen += iovp->iov_len;
+ SC_DEBUGN(sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)",
+ iovp->iov_len, iovp->iov_base));
+ sg++;
+ iovp++;
+ seg++;
+ datalen--;
+ }
+ } else
+#endif /* TFS */
+ {
+ /*
+ * Set up the scatter-gather block.
+ */
+ SC_DEBUG(sc_link, SDEV_DB4,
+ ("%d @0x%x:- ", xs->datalen, xs->data));
+
+ datalen = xs->datalen;
+ thiskv = (int)xs->data;
+ thisphys = KVTOPHYS(xs->data);
+
+ while (datalen && seg < WDS_NSEG) {
+ bytes_this_seg = 0;
+
+ /* put in the base address */
+ ltophys(thisphys, sg->seg_addr);
+
+ SC_DEBUGN(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
+ */
+ /* check it fits on the ISA bus */
+ if (thisphys > 0xFFFFFF) {
+ printf("%s: DMA beyond"
+ " end of ISA\n",
+ sc->sc_dev.dv_xname);
+ goto bad;
+ }
+ /* how far to the end of the page */
+ nextphys = (thisphys & ~PGOFSET) + NBPG;
+ 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;
+
+ /* get more ready for the next page */
+ thiskv = (thiskv & ~PGOFSET) + NBPG;
+ if (datalen)
+ thisphys = KVTOPHYS(thiskv);
+ }
+ /*
+ * next page isn't contiguous, finish the seg
+ */
+ SC_DEBUGN(sc_link, SDEV_DB4,
+ ("(0x%x)", bytes_this_seg));
+ ltophys(bytes_this_seg, sg->seg_len);
+ sg++;
+ seg++;
+ }
+ }
+ /* end of iov/kv decision */
+ SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
+ if (datalen) {
+ /*
+ * there's still data, must have run out of segs!
+ */
+ printf("%s: wds_scsi_cmd, more than %d dma segs\n",
+ sc->sc_dev.dv_xname, WDS_NSEG);
+ goto bad;
+ }
+ scb->cmd.opcode = WDSX_SCSISG;
+ ltophys(KVTOPHYS(scb->scat_gath), scb->cmd.data);
+ ltophys(seg * sizeof(struct wds_scat_gath), scb->cmd.len);
+ } else if (xs->datalen > 0) {
+ /* The board is an ASC or ASE. Do not use scatter/gather. */
+ if (xs->datalen > BUFLEN) {
+ printf("%s: wds_scsi_cmd, I/O too large for bounce buffer\n",
+ sc->sc_dev.dv_xname);
+ goto bad;
+ }
+ if (xs->flags & SCSI_DATA_OUT)
+ bcopy(xs->data, scb->buf->data, xs->datalen);
+ else
+ bzero(scb->buf->data, xs->datalen);
+ scb->cmd.opcode = WDSX_SCSICMD;
+ ltophys(KVTOPHYS(scb->buf->data), scb->cmd.data);
+ ltophys(xs->datalen, scb->cmd.len);
+ } else {
+ scb->cmd.opcode = WDSX_SCSICMD;
+ ltophys(0, scb->cmd.data);
+ ltophys(0, scb->cmd.len);
+ }
+
+ scb->cmd.stat = 0x00;
+ scb->cmd.venderr = 0x00;
+ ltophys(0, scb->cmd.link);
+
+ /* XXX Do we really want to do this? */
+ if (flags & SCSI_POLL) {
+ /* Will poll card, await result. */
+ outb(iobase + WDS_HCR, WDSH_DRQEN);
+ scb->flags |= SCB_POLLED;
+ } else {
+ /* Will send command, let interrupt routine handle result. */
+ outb(iobase + WDS_HCR, WDSH_IRQEN | WDSH_DRQEN);
+ }
+
+ s = splbio();
+ wds_queue_scb(sc, scb);
+ splx(s);
+
+ if ((flags & SCSI_POLL) == 0)
+ return SUCCESSFULLY_QUEUED;
+
+ if (wds_poll(sc, xs, scb->timeout)) {
+ wds_timeout(scb);
+ if (wds_poll(sc, xs, scb->timeout))
+ wds_timeout(scb);
+ }
+ return COMPLETE;
+
+bad:
+ xs->error = XS_DRIVER_STUFFUP;
+ wds_free_scb(sc, scb);
+ return COMPLETE;
+}
+
+/*
+ * Send a sense request.
+ */
+void
+wds_sense(sc, scb)
+ struct wds_softc *sc;
+ struct wds_scb *scb;
+{
+ struct scsi_xfer *xs = scb->xs;
+ struct scsi_sense *ss = (void *)&scb->sense.scb;
+ int s;
+ u_char c;
+ int i;
+
+ /* XXXXX */
+
+ /* Send sense request SCSI command. */
+ xs->error = XS_SENSE;
+ scb->flags |= SCB_SENSE;
+
+ /* First, save the return values */
+ if (NEEDBUFFER(sc) && xs->datalen) {
+ if (xs->flags & SCSI_DATA_IN)
+ bcopy(scb->buf->data, xs->data, xs->datalen);
+ }
+
+ /* Next, setup a request sense command block */
+ bzero(ss, sizeof(*ss));
+ ss->opcode = REQUEST_SENSE;
+ ss->byte2 = xs->sc_link->lun << 5;
+ ss->length = sizeof(struct scsi_sense_data);
+
+ /* Set up some of the command fields. */
+ scb->sense.targ = scb->cmd.targ;
+ scb->sense.write = 0x80;
+ scb->sense.opcode = WDSX_SCSICMD;
+ ltophys(KVTOPHYS(&scb->sense_data), scb->sense.data);
+ ltophys(sizeof(struct scsi_sense_data), scb->sense.len);
+
+ s = splbio();
+ wds_queue_scb(sc, scb);
+ splx(s);
+
+ /*
+ * There's no reason for us to poll here. There are two cases:
+ * 1) If it's a polling operation, then we're called from the interrupt
+ * handler, and we return and continue polling.
+ * 2) If it's an interrupt-driven operation, then it gets completed
+ * later on when the REQUEST SENSE finishes.
+ */
+}
+
+/*
+ * Poll a particular unit, looking for a particular scb
+ */
+int
+wds_poll(sc, xs, count)
+ struct wds_softc *sc;
+ struct scsi_xfer *xs;
+ int count;
+{
+ int iobase = sc->sc_iobase;
+
+ /* timeouts are in msec, so we loop in 1000 usec cycles */
+ while (count) {
+ /*
+ * If we had interrupts enabled, would we
+ * have got an interrupt?
+ */
+ if (inb(iobase + WDS_STAT) & WDSS_IRQ)
+ wdsintr(sc);
+ if (xs->flags & ITSDONE)
+ return 0;
+ delay(1000); /* only happens in boot so ok */
+ count--;
+ }
+ return 1;
+}
+
+/*
+ * Poll a particular unit, looking for a particular scb
+ */
+int
+wds_ipoll(sc, scb, count)
+ struct wds_softc *sc;
+ struct wds_scb *scb;
+ int count;
+{
+ int iobase = sc->sc_iobase;
+
+ /* timeouts are in msec, so we loop in 1000 usec cycles */
+ while (count) {
+ /*
+ * If we had interrupts enabled, would we
+ * have got an interrupt?
+ */
+ if (inb(iobase + WDS_STAT) & WDSS_IRQ)
+ wdsintr(sc);
+ if (scb->flags & SCB_DONE)
+ return 0;
+ delay(1000); /* only happens in boot so ok */
+ count--;
+ }
+ return 1;
+}
+
+void
+wds_timeout(arg)
+ void *arg;
+{
+ struct wds_scb *scb = arg;
+ struct scsi_xfer *xs = scb->xs;
+ struct scsi_link *sc_link = xs->sc_link;
+ struct wds_softc *sc = sc_link->adapter_softc;
+ int s;
+
+ sc_print_addr(sc_link);
+ printf("timed out");
+
+ s = splbio();
+
+#ifdef WDSDIAG
+ /*
+ * If The scb's mbx is not free, then the board has gone south?
+ */
+ wds_collect_mbo(sc);
+ if (scb->flags & SCB_SENDING) {
+ printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
+ Debugger();
+ }
+#endif
+
+ /*
+ * If it has been through before, then
+ * a previous abort has failed, don't
+ * try abort again
+ */
+ if (scb->flags & SCB_ABORT) {
+ /* abort timed out */
+ printf(" AGAIN\n");
+ /* XXX Must reset! */
+ } else {
+ /* abort the operation that has timed out */
+ printf("\n");
+ scb->xs->error = XS_TIMEOUT;
+ scb->timeout = WDS_ABORT_TIMEOUT;
+ scb->flags |= SCB_ABORT;
+ wds_queue_scb(sc, scb);
+ }
+
+ splx(s);
+}
diff --git a/sys/dev/isa/wdsreg.h b/sys/dev/isa/wdsreg.h
new file mode 100644
index 00000000000..e4f7bdafce7
--- /dev/null
+++ b/sys/dev/isa/wdsreg.h
@@ -0,0 +1,147 @@
+typedef u_char physaddr[3];
+typedef u_char physlen[3];
+#define ltophys _lto3b
+#define phystol _3btol
+
+/* WD7000 registers */
+#define WDS_STAT 0 /* read */
+#define WDS_IRQSTAT 1 /* read */
+
+#define WDS_CMD 0 /* write */
+#define WDS_IRQACK 1 /* write */
+#define WDS_HCR 2 /* write */
+
+/* WDS_STAT (read) defs */
+#define WDSS_IRQ 0x80
+#define WDSS_RDY 0x40
+#define WDSS_REJ 0x20
+#define WDSS_INIT 0x10
+
+/* WDS_IRQSTAT (read) defs */
+#define WDSI_MASK 0xc0
+#define WDSI_ERR 0x00
+#define WDSI_MFREE 0x80
+#define WDSI_MSVC 0xc0
+
+/* WDS_CMD (write) defs */
+#define WDSC_NOOP 0x00
+#define WDSC_INIT 0x01
+#define WDSC_DISUNSOL 0x02
+#define WDSC_ENAUNSOL 0x03
+#define WDSC_IRQMFREE 0x04
+#define WDSC_SCSIRESETSOFT 0x05
+#define WDSC_SCSIRESETHARD 0x06
+#define WDSC_MSTART(m) (0x80 + (m))
+#define WDSC_MMSTART(m) (0xc0 + (m))
+
+/* WDS_HCR (write) defs */
+#define WDSH_IRQEN 0x08
+#define WDSH_DRQEN 0x04
+#define WDSH_SCSIRESET 0x02
+#define WDSH_ASCRESET 0x01
+
+#define WDS_NSEG 17
+
+struct wds_scat_gath {
+ physlen seg_len;
+ physaddr seg_addr;
+};
+
+struct wds_cmd {
+ u_char opcode;
+ u_char targ;
+ struct scsi_generic scb;
+ u_char stat;
+ u_char venderr;
+ physlen len;
+ physaddr data;
+ physaddr link;
+ u_char write;
+ u_char xx[6];
+};
+
+struct wds_scb {
+ struct wds_cmd cmd;
+ struct wds_cmd sense;
+
+ struct wds_scat_gath scat_gath[WDS_NSEG];
+ struct scsi_sense_data sense_data;
+
+ TAILQ_ENTRY(wds_scb) chain;
+ struct wds_scb *nexthash;
+ long hashkey;
+ struct scsi_xfer *xs;
+ int flags;
+#define SCB_ALLOC 0x01
+#define SCB_ABORT 0x02
+#ifdef WDSDIAG
+#define SCB_SENDING 0x04
+#endif
+#define SCB_POLLED 0x08
+#define SCB_SENSE 0x10
+#define SCB_DONE 0x20 /* for internal commands only */
+#define SCB_BUFFER 0x40
+ int timeout;
+
+ struct wds_buf *buf;
+};
+
+#define WDSX_SCSICMD 0x00
+#define WDSX_SCSISG 0x01
+#define WDSX_OPEN_RCVBUF 0x80
+#define WDSX_RCV_CMD 0x81
+#define WDSX_RCV_DATA 0x82
+#define WDSX_RCV_DATASTAT 0x83
+#define WDSX_SND_DATA 0x84
+#define WDSX_SND_DATASTAT 0x85
+#define WDSX_SND_CMDSTAT 0x86
+#define WDSX_READINIT 0x88
+#define WDSX_READSCSIID 0x89
+#define WDSX_SETUNSOLIRQMASK 0x8a
+#define WDSX_GETUNSOLIRQMASK 0x8b
+#define WDSX_GETFIRMREV 0x8c
+#define WDSX_EXECDIAG 0x8d
+#define WDSX_SETEXECPARM 0x8e
+#define WDSX_GETEXECPARM 0x8f
+
+struct wds_mbx_out {
+ u_char cmd;
+ physaddr scb_addr;
+};
+
+struct wds_mbx_in {
+ u_char stat;
+ physaddr scb_addr;
+};
+
+/*
+ * mbo.cmd values
+ */
+#define WDS_MBO_FREE 0x0 /* MBO entry is free */
+#define WDS_MBO_START 0x1 /* MBO activate entry */
+
+/*
+ * mbi.stat values
+ */
+#define WDS_MBI_FREE 0x00 /* MBI entry is free */
+#define WDS_MBI_OK 0x01 /* completed without error */
+#define WDS_MBI_OKERR 0x02 /* completed with error */
+#define WDS_MBI_ETIME 0x04
+#define WDS_MBI_ERESET 0x05
+#define WDS_MBI_ETARCMD 0x06
+#define WDS_MBI_ERESEL 0x80
+#define WDS_MBI_ESEL 0x81
+#define WDS_MBI_EABORT 0x82
+#define WDS_MBI_ESRESET 0x83
+#define WDS_MBI_EHRESET 0x84
+
+struct wds_setup {
+ u_char opcode;
+ u_char scsi_id;
+ u_char buson_t;
+ u_char busoff_t;
+ u_char xx;
+ physaddr mbaddr;
+ u_char nomb;
+ u_char nimb;
+};
diff --git a/sys/dev/isa/wss.c b/sys/dev/isa/wss.c
index 6080334ede5..ba0b2fb7df2 100644
--- a/sys/dev/isa/wss.c
+++ b/sys/dev/isa/wss.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: wss.c,v 1.7 1996/03/20 01:01:06 mickey Exp $ */
-/* $NetBSD: wss.c,v 1.9 1996/02/16 08:18:36 mycroft Exp $ */
+/* $OpenBSD: wss.c,v 1.8 1996/04/21 22:24:49 deraadt Exp $ */
+/* $NetBSD: wss.c,v 1.11 1996/04/11 22:30:46 cgd Exp $ */
/*
* Copyright (c) 1994 John Brezak
@@ -165,8 +165,12 @@ struct audio_hw_if wss_hw_if = {
int wssprobe __P((struct device *, void *, void *));
void wssattach __P((struct device *, struct device *, void *));
-struct cfdriver wsscd = {
- NULL, "wss", wssprobe, wssattach, DV_DULL, sizeof(struct wss_softc)
+struct cfattach wss_ca = {
+ sizeof(struct wss_softc), wssprobe, wssattach
+};
+
+struct cfdriver wss_cd = {
+ NULL, "wss", DV_DULL
};
/*
@@ -250,8 +254,8 @@ wssattach(parent, self, aux)
#ifdef NEWCONFIG
isa_establish(&sc->sc_id, &sc->sc_dev);
#endif
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_AUDIO, ad1848_intr,
- &sc->sc_ad1848, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, IPL_AUDIO,
+ ad1848_intr, &sc->sc_ad1848, sc->sc_dev.dv_xname);
ad1848_attach(&sc->sc_ad1848);
@@ -306,10 +310,10 @@ wssopen(dev, flags)
struct wss_softc *sc;
int unit = AUDIOUNIT(dev);
- if (unit >= wsscd.cd_ndevs)
+ if (unit >= wss_cd.cd_ndevs)
return ENODEV;
- sc = wsscd.cd_devs[unit];
+ sc = wss_cd.cd_devs[unit];
if (!sc)
return ENXIO;
diff --git a/sys/dev/isa/wt.c b/sys/dev/isa/wt.c
index 8fe5e81811f..70e051a7694 100644
--- a/sys/dev/isa/wt.c
+++ b/sys/dev/isa/wt.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: wt.c,v 1.7 1996/04/18 23:47:52 niklas Exp $ */
-/* $NetBSD: wt.c,v 1.29 1996/03/01 04:08:40 mycroft Exp $ */
+/* $OpenBSD: wt.c,v 1.8 1996/04/21 22:24:52 deraadt Exp $ */
+/* $NetBSD: wt.c,v 1.31 1996/04/11 22:30:49 cgd Exp $ */
/*
* Streamer tape driver.
@@ -168,8 +168,12 @@ int wtprobe __P((struct device *, void *, void *));
void wtattach __P((struct device *, struct device *, void *));
int wtintr __P((void *sc));
-struct cfdriver wtcd = {
- NULL, "wt", wtprobe, wtattach, DV_TAPE, sizeof(struct wt_softc)
+struct cfattach wt_ca = {
+ sizeof(struct wt_softc), wtprobe, wtattach
+};
+
+struct cfdriver wt_cd = {
+ NULL, "wt", DV_TAPE
};
/*
@@ -250,8 +254,8 @@ wtattach(parent, self, aux)
sc->flags = TPSTART; /* tape is rewound */
sc->dens = -1; /* unknown density */
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO, wtintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, wtintr, sc, sc->sc_dev.dv_xname);
}
int
@@ -287,9 +291,9 @@ wtopen(dev, flag)
struct wt_softc *sc;
int error;
- if (unit >= wtcd.cd_ndevs)
+ if (unit >= wt_cd.cd_ndevs)
return ENXIO;
- sc = wtcd.cd_devs[unit];
+ sc = wt_cd.cd_devs[unit];
if (!sc)
return ENXIO;
@@ -372,7 +376,7 @@ wtclose(dev)
dev_t dev;
{
int unit = minor(dev) & T_UNIT;
- struct wt_softc *sc = wtcd.cd_devs[unit];
+ struct wt_softc *sc = wt_cd.cd_devs[unit];
/* If rewind is pending, do nothing */
if (sc->flags & TPREW)
@@ -426,7 +430,7 @@ wtioctl(dev, cmd, addr, flag)
int flag;
{
int unit = minor(dev) & T_UNIT;
- struct wt_softc *sc = wtcd.cd_devs[unit];
+ struct wt_softc *sc = wt_cd.cd_devs[unit];
int error, count, op;
switch (cmd) {
@@ -526,7 +530,7 @@ wtstrategy(bp)
struct buf *bp;
{
int unit = minor(bp->b_dev) & T_UNIT;
- struct wt_softc *sc = wtcd.cd_devs[unit];
+ struct wt_softc *sc = wt_cd.cd_devs[unit];
int s;
bp->b_resid = bp->b_bcount;