summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1996-05-26 00:27:57 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1996-05-26 00:27:57 +0000
commit729a9d7ceffba9e7e741540048479eed9907601e (patch)
tree716f1614729ffc0b602e2fdfece3bc84b3e930b1 /sys/dev/ic
parent8102ec86d426fccfffa292d80d3e50914c22a932 (diff)
sync 0521
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/aic7xxx.c1110
-rw-r--r--sys/dev/ic/aic7xxxreg.h776
-rw-r--r--sys/dev/ic/aic7xxxvar.h172
-rw-r--r--sys/dev/ic/com.c10
-rw-r--r--sys/dev/ic/elink3.c17
-rw-r--r--sys/dev/ic/elink3reg.h4
-rw-r--r--sys/dev/ic/elink3var.h6
-rw-r--r--sys/dev/ic/ncr5380sbc.c43
-rw-r--r--sys/dev/ic/ncr5380var.h7
-rw-r--r--sys/dev/ic/pdq.c395
-rw-r--r--sys/dev/ic/pdq_ifsubr.c137
-rw-r--r--sys/dev/ic/pdqreg.h122
-rw-r--r--sys/dev/ic/pdqvar.h216
-rw-r--r--sys/dev/ic/smc93cx6.c222
-rw-r--r--sys/dev/ic/smc93cx6var.h70
-rw-r--r--sys/dev/ic/z8530sc.c6
-rw-r--r--sys/dev/ic/z8530sc.h9
-rw-r--r--sys/dev/ic/z8530tty.c414
18 files changed, 2459 insertions, 1277 deletions
diff --git a/sys/dev/ic/aic7xxx.c b/sys/dev/ic/aic7xxx.c
index 793ac9eac73..614cd0616df 100644
--- a/sys/dev/ic/aic7xxx.c
+++ b/sys/dev/ic/aic7xxx.c
@@ -1,3 +1,5 @@
+/* $NetBSD: aic7xxx.c,v 1.8 1996/05/20 00:58:07 thorpej Exp $ */
+
/*
* Generic driver for the aic7xxx based adaptec SCSI controllers
* Product specific probe and attach routines can be found in:
@@ -30,8 +32,6 @@
* 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.
- *
- * $Id: aic7xxx.c,v 1.5 1996/05/05 12:42:29 deraadt Exp $
*/
/*
* TODO:
@@ -117,14 +117,8 @@
#include <sys/systm.h>
#if defined(__NetBSD__)
#include <sys/device.h>
-#if NetBSD1_1 < 3
-#include <machine/pio.h>
-#else
#include <machine/bus.h>
-#ifdef __alpha__
#include <machine/intr.h>
-#endif
-#endif
#endif /* defined(__NetBSD__) */
#include <sys/malloc.h>
@@ -149,14 +143,11 @@
#include <i386/scsi/aic7xxx.h>
#include <dev/aic7xxx/aic7xxx_reg.h>
-
-#define AHCNAME_FMT "ahc%d"
-#define AHCNAME_VAR(ahc) (ahc)->unit
#endif /* defined(__FreeBSD__) */
#if defined(__NetBSD__)
+#include <dev/ic/aic7xxxreg.h>
#include <dev/ic/aic7xxxvar.h>
-#include <dev/microcode/aic7xxx/aic7xxx_reg.h>
#define bootverbose 1
@@ -165,9 +156,6 @@
#undef DEBUGTARG
#define DEBUGTARG 9
#endif
-
-#define AHCNAME_FMT "%s"
-#define AHCNAME_VAR(ahc) (ahc)->sc_dev.dv_xname
#endif /* defined(__NetBSD__) */
#define PAGESIZ NBPG
@@ -178,14 +166,16 @@
#define MIN(a,b) ((a < b) ? a : b)
#define ALL_TARGETS -1
+#if defined(__FreeBSD__)
u_long ahc_unit = 0;
+#endif
#ifdef AHC_DEBUG
static int ahc_debug = AHC_SHOWSENSE;
#endif
-#ifdef AIC7XXX_BROKEN_CACHE
-int aic7xxx_broken_cache = 1;
+#ifdef AHC_BROKEN_CACHE
+int ahc_broken_cache = 1;
/*
* "wbinvd" cause writing back whole cache (both CPU internal & external)
@@ -235,22 +225,22 @@ static struct scsi_device ahc_dev =
* XXX Should add a timeout in here??
*/
#define PAUSE_SEQUENCER(ahc) \
- outb(HCNTRL + ahc->baseport, ahc->pause); \
+ AHC_OUTB(ahc, HCNTRL, ahc->pause); \
\
- while ((inb(HCNTRL + ahc->baseport) & PAUSE) == 0) \
+ while ((AHC_INB(ahc, HCNTRL) & PAUSE) == 0) \
;
#define UNPAUSE_SEQUENCER(ahc) \
- outb( HCNTRL + ahc->baseport, ahc->unpause )
+ AHC_OUTB(ahc, HCNTRL, ahc->unpause )
/*
* Restart the sequencer program from address zero
*/
#define RESTART_SEQUENCER(ahc) \
do { \
- outb( SEQCTL + ahc->baseport, SEQRESET|FASTMODE ); \
- } while (inb(SEQADDR0 + ahc->baseport) != 0 && \
- inb(SEQADDR1 + ahc->baseport) != 0); \
+ AHC_OUTB(ahc, SEQCTL, SEQRESET|FASTMODE); \
+ } while (AHC_INB(ahc, SEQADDR0) != 0 && \
+ AHC_INB(ahc, SEQADDR1) != 0); \
\
UNPAUSE_SEQUENCER(ahc);
@@ -269,9 +259,10 @@ static struct scsi_device ahc_dev =
#endif
static u_char ahc_abort_wscb __P((struct ahc_data *ahc, struct scb *scbp,
- u_char prev, u_long iobase,
+ u_char prev,
u_char timedout_scb, u_int32_t xs_error));
-static void ahc_add_waiting_scb __P((u_long iobase, struct scb *scb));
+static void ahc_add_waiting_scb __P((struct ahc_data *ahc,
+ struct scb *scb));
static void ahc_done __P((struct ahc_data *ahc, struct scb *scbp));
static void ahc_free_scb __P((struct ahc_data *ahc, struct scb *scb,
int flags));
@@ -282,7 +273,7 @@ static inline void ahc_page_scb __P((struct ahc_data *ahc, struct scb *out_scb,
static inline void ahc_run_waiting_queues __P((struct ahc_data *ahc));
static struct scb *
ahc_get_scb __P((struct ahc_data *ahc, int flags));
-static void ahc_loadseq __P((u_long iobase));
+static void ahc_loadseq __P((struct ahc_data *ahc));
static int ahc_match_scb __P((struct scb *scb, int target, char channel));
static int ahc_poll __P((struct ahc_data *ahc, int wait));
#ifdef AHC_DEBUG
@@ -294,7 +285,7 @@ static int ahc_reset_channel __P((struct ahc_data *ahc, char channel,
static int ahc_reset_device __P((struct ahc_data *ahc, int target,
char channel, u_char timedout_scb,
u_int32_t xs_error));
-static void ahc_reset_current_bus __P((u_long iobase));
+static void ahc_reset_current_bus __P((struct ahc_data *ahc));
static void ahc_run_done_queue __P((struct ahc_data *ahc));
static void ahc_scsirate __P((struct ahc_data* ahc, u_char *scsirate,
int period, int offset, int target));
@@ -304,10 +295,27 @@ static timeout_t
#elif defined(__NetBSD__)
static void ahc_timeout __P((void *));
#endif
-static void ahc_busy_target __P((int target, char channel,
- u_long iobase));
-static void ahc_unbusy_target __P((int target, char channel,
- u_long iobase));
+static void ahc_busy_target __P((struct ahc_data *ahc,
+ int target, char channel));
+static void ahc_unbusy_target __P((struct ahc_data *ahc,
+ int target, char channel));
+
+#if defined(__FreeBSD__)
+
+char *ahc_name(ahc)
+ struct ahc_data *ahc;
+{
+ static char name[10];
+
+ sprintf(name, "ahc%d", ahc->unit);
+ return (name);
+}
+
+#elif defined(__NetBSD__)
+struct cfdriver ahc_cd = {
+ NULL, "ahc", DV_DULL
+};
+#endif
#ifdef AHC_DEBUG
static void
@@ -358,11 +366,11 @@ static struct {
{ 0x100, 50, "20.0" },
{ 0x110, 62, "16.0" },
{ 0x120, 75, "13.4" },
- { 0x130, 87, "11.4" },
- { 0x140, 100, "10.0" },
- { 0x150, 112, "8.8" },
- { 0x160, 125, "8.0" },
- { 0x170, 137, "7.2" },
+ { 0x130, 175, "5.7" },
+ { 0x140, 200, "5.0" },
+ { 0x150, 225, "4.4" },
+ { 0x160, 250, "4.0" },
+ { 0x170, 275, "3.6" },
{ 0x000, 100, "10.0" },
{ 0x010, 125, "8.0" },
{ 0x020, 150, "6.67" },
@@ -385,15 +393,15 @@ static int ahc_num_syncrates =
#if defined(__FreeBSD__)
struct ahc_data *
ahc_alloc(unit, iobase, type, flags)
+ int unit;
u_long iobase;
#elif defined(__NetBSD__)
void
-ahc_construct(ahc, unit, bc, iobase, type, flags)
+ahc_construct(ahc, bc, ioh, type, flags)
struct ahc_data *ahc;
bus_chipset_tag_t bc;
- bus_io_handle_t iobase; /* XXX - ioh */
+ bus_io_handle_t ioh;
#endif
- int unit;
ahc_type type;
ahc_flag flags;
{
@@ -416,18 +424,20 @@ ahc_construct(ahc, unit, bc, iobase, type, flags)
}
bzero(ahc, sizeof(struct ahc_data));
#endif
- STAILQ_INIT(&ahc->free_scbs);
- STAILQ_INIT(&ahc->page_scbs);
- STAILQ_INIT(&ahc->waiting_scbs);
- STAILQ_INIT(&ahc->assigned_scbs);
+ SIMPLEQ_INIT(&ahc->free_scbs);
+ SIMPLEQ_INIT(&ahc->page_scbs);
+ SIMPLEQ_INIT(&ahc->waiting_scbs);
+ SIMPLEQ_INIT(&ahc->assigned_scbs);
+#if defined(__FreeBSD__)
ahc->unit = unit;
-#if defined(__NetBSD__)
+ ahc->baseport = iobase;
+#elif defined(__NetBSD__)
ahc->sc_bc = bc;
+ ahc->sc_ioh = ioh;
#endif
- ahc->baseport = iobase;
ahc->type = type;
ahc->flags = flags;
- ahc->unpause = (inb(HCNTRL + iobase) & IRQMS) | INTEN;
+ ahc->unpause = (AHC_INB(ahc, HCNTRL) & IRQMS) | INTEN;
ahc->pause = ahc->unpause | PAUSE;
#if defined(__FreeBSD__)
@@ -450,27 +460,35 @@ void
ahc_reset(iobase)
u_long iobase;
#elif defined(__NetBSD__)
-ahc_reset(devname, bc, iobase)
+ahc_reset(devname, bc, ioh)
char *devname;
bus_chipset_tag_t bc;
- bus_io_handle_t iobase; /* XXX - ioh */
+ bus_io_handle_t ioh;
#endif
{
u_char hcntrl;
int wait;
/* Retain the IRQ type accross the chip reset */
+#if defined(__FreeBSD__)
hcntrl = (inb(HCNTRL + iobase) & IRQMS) | INTEN;
+
outb(HCNTRL + iobase, CHIPRST | PAUSE);
+#elif defined(__NetBSD__)
+ hcntrl = (bus_io_read_1(bc, ioh, HCNTRL) & IRQMS) | INTEN;
+
+ bus_io_write_1(bc, ioh, HCNTRL, CHIPRST | PAUSE);
+#endif
/*
* Ensure that the reset has finished
*/
wait = 1000;
- while (wait--) {
+#if defined(__FreeBSD__)
+ while (--wait && !(inb(HCNTRL + iobase) & CHIPRSTACK))
+#elif defined(__NetBSD__)
+ while (--wait && !(bus_io_read_1(bc, ioh, HCNTRL) & CHIPRSTACK))
+#endif
DELAY(1000);
- if(!(inb(HCNTRL + iobase) & CHIPRST))
- break;
- }
if(wait == 0) {
#if defined(__FreeBSD__)
printf("ahc at 0x%lx: WARNING - Failed chip reset! "
@@ -480,7 +498,11 @@ ahc_reset(devname, bc, iobase)
"Trying to initialize anyway.\n", devname);
#endif
}
+#if defined(__FreeBSD__)
outb(HCNTRL + iobase, hcntrl | PAUSE);
+#elif defined(__NetBSD__)
+ bus_io_write_1(bc, ioh, HCNTRL, hcntrl | PAUSE);
+#endif
}
/*
@@ -504,16 +526,8 @@ ahc_scsirate(ahc, scsirate, period, offset, target )
* enabled and vice-versa.
*/
if (ahc->type & AHC_ULTRA) {
- if (!(ahc_syncrates[i].sxfr & ULTRA_SXFR)) {
- printf(AHCNAME_FMT
- ": target %d requests "
- "%sMHz transfers, but adapter "
- "in Ultra mode can only sync at "
- "7.2MHz or above\n",
- AHCNAME_VAR(ahc),
- target, ahc_syncrates[i].rate);
+ if (!(ahc_syncrates[i].sxfr & ULTRA_SXFR))
break; /* Use Async */
- }
}
else {
if (ahc_syncrates[i].sxfr & ULTRA_SXFR) {
@@ -529,10 +543,9 @@ ahc_scsirate(ahc, scsirate, period, offset, target )
}
*scsirate = (ahc_syncrates[i].sxfr) | (offset & 0x0f);
if(bootverbose) {
- printf(AHCNAME_FMT
- ": target %d synchronous at %sMHz,"
+ printf("%s: target %d synchronous at %sMHz,"
" offset = 0x%x\n",
- AHCNAME_VAR(ahc), target,
+ ahc_name(ahc), target,
ahc_syncrates[i].rate, offset );
}
return;
@@ -541,8 +554,8 @@ ahc_scsirate(ahc, scsirate, period, offset, target )
/* Default to asyncronous transfers. Also reject this SDTR request. */
*scsirate = 0;
if(bootverbose) {
- printf(AHCNAME_FMT ": target %d using asyncronous transfers\n",
- AHCNAME_VAR(ahc), target );
+ printf("%s: target %d using asyncronous transfers\n",
+ ahc_name(ahc), target );
}
}
@@ -568,12 +581,12 @@ ahc_attach(ahc)
{
struct scsibus_data *scbus;
-#ifdef AIC7XXX_BROKEN_CACHE
+#ifdef AHC_BROKEN_CACHE
if (cpu_class == CPUCLASS_386) /* doesn't have "wbinvd" instruction */
- aic7xxx_broken_cache = 0;
+ ahc_broken_cache = 0;
#endif
/*
- * fill in the prototype scsi_link.
+ * fill in the prototype scsi_links.
*/
#if defined(__FreeBSD__)
ahc->sc_link.adapter_unit = ahc->unit;
@@ -588,69 +601,91 @@ ahc_attach(ahc)
ahc->sc_link.device = &ahc_dev;
ahc->sc_link.flags = DEBUGLEVEL;
+ if(ahc->type & AHC_TWIN) {
+ /* Configure the second scsi bus */
+ ahc->sc_link_b = ahc->sc_link;
+#if defined(__FreeBSD__)
+ ahc->sc_link_b.adapter_targ = ahc->our_id_b;
+ ahc->sc_link_b.adapter_bus = 1;
+ ahc->sc_link_b.fordriver = (void *)SELBUSB;
+#elif defined(__NetBSD__)
+ ahc->sc_link_b.adapter_target = ahc->our_id_b;
+#endif
+ }
+
+
+#if defined(__FreeBSD__)
/*
* Prepare the scsibus_data area for the upperlevel
* scsi code.
*/
-#if defined(__FreeBSD__)
scbus = scsi_alloc_bus();
if(!scbus)
return 0;
- scbus->adapter_link = &ahc->sc_link;
+ scbus->adapter_link = (ahc->flags & AHC_CHANNEL_B_PRIMARY) ?
+ &ahc->sc_link_b : &ahc->sc_link;
if(ahc->type & AHC_WIDE)
scbus->maxtarg = 15;
-#elif defined(__NetBSD__)
- /*
- * XXX - Update MI SCSI code
- *
- * if(ahc->type & AHC_WIDE)
- * XXX max target XXX = 15;
- */
-#endif
/*
* ask the adapter what subunits are present
*/
-#if defined(__FreeBSD__)
if(bootverbose)
- printf("ahc%d: Probing channel A\n", ahc->unit);
+ printf("ahc%d: Probing channel %c\n", ahc->unit,
+ (ahc->flags & AHC_CHANNEL_B_PRIMARY) ? 'B' : 'A');
scsi_attachdevs(scbus);
scbus = NULL; /* Upper-level SCSI code owns this now */
-#elif defined(__NetBSD__)
- ahc->sc_link_b.scsibus = 0xff; /* for IS_SCSIBUS_B(), never match */
- printf("%s: Probing channel A\n", ahc->sc_dev.dv_xname);
- config_found((void *)ahc, &ahc->sc_link, ahcprint);
-#endif
if(ahc->type & AHC_TWIN) {
- /* Configure the second scsi bus */
- ahc->sc_link_b = ahc->sc_link;
-#if defined(__FreeBSD__)
- ahc->sc_link_b.adapter_targ = ahc->our_id_b;
- ahc->sc_link_b.adapter_bus = 1;
- ahc->sc_link_b.fordriver = (void *)SELBUSB;
scbus = scsi_alloc_bus();
if(!scbus)
return 0;
- scbus->adapter_link = &ahc->sc_link_b;
+ scbus->adapter_link = (ahc->flags & AHC_CHANNEL_B_PRIMARY) ?
+ &ahc->sc_link : &ahc->sc_link_b;
if(ahc->type & AHC_WIDE)
scbus->maxtarg = 15;
if(bootverbose)
- printf("ahc%d: Probing Channel B\n", ahc->unit);
+ printf("ahc%d: Probing Channel %c\n", ahc->unit,
+ (ahc->flags & AHC_CHANNEL_B_PRIMARY) ? 'A': 'B');
scsi_attachdevs(scbus);
scbus = NULL; /* Upper-level SCSI code owns this now */
+ }
#elif defined(__NetBSD__)
+ /*
+ * XXX - Update MI SCSI code
+ *
+ * if(ahc->type & AHC_WIDE)
+ * max target of both channel A and B = 15;
+ */
+
+ /*
+ * ask the adapter what subunits are present
+ */
+ if ((ahc->flags & AHC_CHANNEL_B_PRIMARY) == 0) {
+ /* make IS_SCSIBUS_B() == false, while probing channel A */
+ ahc->sc_link_b.scsibus = 0xff;
+
+ if (ahc->type & AHC_TWIN)
+ printf("%s: Probing channel A\n", ahc_name(ahc));
+ config_found((void *)ahc, &ahc->sc_link, ahcprint);
+ if (ahc->type & AHC_TWIN) {
+ printf("%s: Probing channel B\n", ahc_name(ahc));
+ config_found((void *)ahc, &ahc->sc_link_b, ahcprint);
+ }
+ } else {
/*
- * XXX - Update MI SCSI code
- *
- * if(ahc->type & AHC_WIDE)
- * XXX max target XXX = 15;
+ * if implementation of IS_SCSIBUS_B() is changed to use
+ * ahc->sc_link.scsibus, then "ahc->sc_link.scsibus = 0xff;"
+ * is needed, here.
*/
- ahc->sc_link_b.adapter_target = ahc->our_id_b;
- printf("%s: Probing channel B\n", ahc->sc_dev.dv_xname);
+
+ /* assert(ahc->type & AHC_TWIN); */
+ printf("%s: Probing channel B\n", ahc_name(ahc));
config_found((void *)ahc, &ahc->sc_link_b, ahcprint);
-#endif
+ printf("%s: Probing channel A\n", ahc_name(ahc));
+ config_found((void *)ahc, &ahc->sc_link, ahcprint);
}
+#endif
return 1;
}
@@ -663,16 +698,14 @@ ahc_send_scb(ahc, scb)
struct ahc_data *ahc;
struct scb *scb;
{
- u_long iobase = ahc->baseport;
-
- outb(SCBCNT + iobase, SCBAUTO);
+ AHC_OUTB(ahc, SCBCNT, SCBAUTO);
if( ahc->type == AHC_284 )
/* Can only do 8bit PIO */
- outsb(SCBARRAY+iobase, scb, SCB_PIO_TRANSFER_SIZE);
+ AHC_OUTSB(ahc, SCBARRAY, scb, SCB_PIO_TRANSFER_SIZE);
else
- outsl(SCBARRAY+iobase, scb,
+ AHC_OUTSL(ahc, SCBARRAY, scb,
(SCB_PIO_TRANSFER_SIZE + 3) / 4);
- outb(SCBCNT + iobase, 0);
+ AHC_OUTB(ahc, SCBCNT, 0);
}
/*
@@ -684,14 +717,12 @@ ahc_fetch_scb(ahc, scb)
struct ahc_data *ahc;
struct scb *scb;
{
- u_long iobase = ahc->baseport;
-
- outb(SCBCNT + iobase, 0x80); /* SCBAUTO */
+ AHC_OUTB(ahc, SCBCNT, 0x80); /* SCBAUTO */
/* Can only do 8bit PIO for reads */
- insb(SCBARRAY+iobase, scb, SCB_PIO_TRANSFER_SIZE);
+ AHC_INSB(ahc, SCBARRAY, scb, SCB_PIO_TRANSFER_SIZE);
- outb(SCBCNT + iobase, 0);
+ AHC_OUTB(ahc, SCBCNT, 0);
}
/*
@@ -728,27 +759,26 @@ ahc_run_waiting_queues(ahc)
{
struct scb* scb;
u_char cur_scb;
- u_long iobase = ahc->baseport;
- if(!(ahc->assigned_scbs.stqh_first || ahc->waiting_scbs.stqh_first))
+ if(!(ahc->assigned_scbs.sqh_first || ahc->waiting_scbs.sqh_first))
return;
PAUSE_SEQUENCER(ahc);
- cur_scb = inb(SCBPTR + iobase);
+ cur_scb = AHC_INB(ahc, SCBPTR);
/*
* First handle SCBs that are waiting but have been
* assigned a slot.
*/
- while((scb = ahc->assigned_scbs.stqh_first) != NULL) {
- STAILQ_REMOVE_HEAD(&ahc->assigned_scbs, links);
- outb(SCBPTR + iobase, scb->position);
+ while((scb = ahc->assigned_scbs.sqh_first) != NULL) {
+ SIMPLEQ_REMOVE_HEAD(&ahc->assigned_scbs, scb, links);
+ AHC_OUTB(ahc, SCBPTR, scb->position);
ahc_send_scb(ahc, scb);
/* Mark this as an active command */
scb->flags = SCB_ACTIVE;
- outb(QINFIFO + iobase, scb->position);
+ AHC_OUTB(ahc, QINFIFO, scb->position);
if (!(scb->xs->flags & SCSI_NOMASK)) {
timeout(ahc_timeout, (caddr_t)scb,
(scb->xs->timeout * hz) / 1000);
@@ -756,9 +786,9 @@ ahc_run_waiting_queues(ahc)
SC_DEBUG(scb->xs->sc_link, SDEV_DB3, ("cmd_sent\n"));
}
/* Now deal with SCBs that require paging */
- if((scb = ahc->waiting_scbs.stqh_first) != NULL) {
- u_char disc_scb = inb(DISCONNECTED_SCBH + iobase);
- u_char active = inb(FLAGS+iobase) & (SELECTED|IDENTIFY_SEEN);
+ if((scb = ahc->waiting_scbs.sqh_first) != NULL) {
+ u_char disc_scb = AHC_INB(ahc, DISCONNECTED_SCBH);
+ u_char active = AHC_INB(ahc, FLAGS) & (SELECTED|IDENTIFY_SEEN);
int count = 0;
do {
@@ -772,8 +802,8 @@ ahc_run_waiting_queues(ahc)
* Advance disc_scb to the next on in the
* list.
*/
- outb(SCBPTR + iobase, disc_scb);
- next_scb = inb(SCB_NEXT + iobase);
+ AHC_OUTB(ahc, SCBPTR, disc_scb);
+ next_scb = AHC_INB(ahc, SCB_NEXT);
/*
* We have to be careful about when we allow
@@ -793,13 +823,14 @@ ahc_run_waiting_queues(ahc)
u_char out_scbi;
struct scb* out_scbp;
- STAILQ_REMOVE_HEAD(&ahc->waiting_scbs, links);
+ SIMPLEQ_REMOVE_HEAD(&ahc->waiting_scbs, scb,
+ links);
/*
* Find the in-core SCB for the one
* we're paging out.
*/
- out_scbi = inb(SCB_TAG + iobase);
+ out_scbi = AHC_INB(ahc, SCB_TAG);
out_scbp = ahc->scbarray[out_scbi];
/* Do the page out */
@@ -809,7 +840,7 @@ ahc_run_waiting_queues(ahc)
scb->flags = SCB_ACTIVE;
/* Queue the command */
- outb(QINFIFO + iobase, scb->position);
+ AHC_OUTB(ahc, QINFIFO, scb->position);
if (!(scb->xs->flags & SCSI_NOMASK)) {
timeout(ahc_timeout, (caddr_t)scb,
(scb->xs->timeout * hz) / 1000);
@@ -823,21 +854,21 @@ ahc_run_waiting_queues(ahc)
}
else
break;
- } while((scb = ahc->waiting_scbs.stqh_first) != NULL);
+ } while((scb = ahc->waiting_scbs.sqh_first) != NULL);
if(count) {
/*
* Update the head of the disconnected list.
*/
- outb(DISCONNECTED_SCBH + iobase, disc_scb);
+ AHC_OUTB(ahc, DISCONNECTED_SCBH, disc_scb);
if(disc_scb != SCB_LIST_NULL) {
- outb(SCBPTR + iobase, disc_scb);
- outb(SCB_PREV + iobase, SCB_LIST_NULL);
+ AHC_OUTB(ahc, SCBPTR, disc_scb);
+ AHC_OUTB(ahc, SCB_PREV, SCB_LIST_NULL);
}
}
}
/* Restore old position */
- outb(SCBPTR + iobase, cur_scb);
+ AHC_OUTB(ahc, SCBPTR, cur_scb);
UNPAUSE_SEQUENCER(ahc);
}
@@ -845,21 +876,21 @@ ahc_run_waiting_queues(ahc)
* Add this SCB to the head of the "waiting for selection" list.
*/
static
-void ahc_add_waiting_scb (iobase, scb)
- u_long iobase;
+void ahc_add_waiting_scb(ahc, scb)
+ struct ahc_data *ahc;
struct scb *scb;
{
u_char next;
u_char curscb;
- curscb = inb(SCBPTR + iobase);
- next = inb(WAITING_SCBH + iobase);
+ curscb = AHC_INB(ahc, SCBPTR);
+ next = AHC_INB(ahc, WAITING_SCBH);
- outb(SCBPTR+iobase, scb->position);
- outb(SCB_NEXT+iobase, next);
- outb(WAITING_SCBH + iobase, scb->position);
+ AHC_OUTB(ahc, SCBPTR, scb->position);
+ AHC_OUTB(ahc, SCB_NEXT, next);
+ AHC_OUTB(ahc, WAITING_SCBH, scb->position);
- outb(SCBPTR + iobase, curscb);
+ AHC_OUTB(ahc, SCBPTR, curscb);
}
/*
@@ -875,13 +906,11 @@ ahc_intr(arg)
{
int intstat;
u_char status;
- u_long iobase;
struct scb *scb = NULL;
struct scsi_xfer *xs = NULL;
struct ahc_data *ahc = (struct ahc_data *)arg;
- iobase = ahc->baseport;
- intstat = inb(INTSTAT + iobase);
+ intstat = AHC_INB(ahc, INTSTAT);
/*
* Is this interrupt for me? or for
* someone who is sharing my interrupt
@@ -897,14 +926,14 @@ ahc_intr(arg)
/* We upset the sequencer :-( */
/* Lookup the error message */
- int i, error = inb(ERROR + iobase);
+ int i, error = AHC_INB(ahc, ERROR);
int num_errors = sizeof(hard_error)/sizeof(hard_error[0]);
for(i = 0; error != 1 && i < num_errors; i++)
error >>= 1;
- panic(AHCNAME_FMT ": brkadrint, %s at seqaddr = 0x%x\n",
- AHCNAME_VAR(ahc), hard_error[i].errmesg,
- (inb(SEQADDR1 + iobase) << 8) |
- inb(SEQADDR0 + iobase));
+ panic("%s: brkadrint, %s at seqaddr = 0x%x\n",
+ ahc_name(ahc), hard_error[i].errmesg,
+ (AHC_INB(ahc, SEQADDR1) << 8) |
+ AHC_INB(ahc, SEQADDR0));
}
if (intstat & SEQINT) {
/*
@@ -913,10 +942,10 @@ ahc_intr(arg)
* inb.
*/
u_short targ_mask;
- u_char target = (inb(SCSIID + iobase) >> 4) & 0x0f;
+ u_char target = (AHC_INB(ahc, SCSIID) >> 4) & 0x0f;
u_char scratch_offset = target;
char channel =
- inb(SBLKCTL + iobase) & SELBUSB ? 'B': 'A';
+ AHC_INB(ahc, SBLKCTL) & SELBUSB ? 'B': 'A';
if (channel == 'B')
scratch_offset += 8;
@@ -924,45 +953,46 @@ ahc_intr(arg)
switch (intstat & SEQINT_MASK) {
case BAD_PHASE:
- panic(AHCNAME_FMT ":%c:%d: unknown scsi bus phase. "
+ panic("%s:%c:%d: unknown scsi bus phase. "
"Attempting to continue\n",
- AHCNAME_VAR(ahc), channel, target);
+ ahc_name(ahc), channel, target);
break;
case SEND_REJECT:
{
- u_char rejbyte = inb(REJBYTE + iobase);
+ u_char rejbyte = AHC_INB(ahc, REJBYTE);
if(( rejbyte & 0xf0) == 0x20) {
/* Tagged Message */
- printf("\n" AHCNAME_FMT
- ":%c:%d: Tagged message "
+ printf("\n%s:%c:%d: Tagged message "
"received without identify. "
"Disabling tagged commands "
"for this target.\n",
- AHCNAME_VAR(ahc),
+ ahc_name(ahc),
channel, target);
ahc->tagenable &= ~targ_mask;
}
else
- printf(AHCNAME_FMT ":%c:%d: Warning - "
+ printf("%s:%c:%d: Warning - "
"unknown message recieved from "
"target (0x%x - 0x%x). Rejecting\n",
- AHCNAME_VAR(ahc),
- channel, target,
- rejbyte, inb(REJBYTE_EXT + iobase));
+ ahc_name(ahc), channel, target,
+ rejbyte,
+ AHC_INB(ahc, REJBYTE_EXT));
break;
}
case NO_IDENT:
- panic(AHCNAME_FMT
- ":%c:%d: Target did not send an IDENTIFY "
+ panic("%s:%c:%d: Target did not send an IDENTIFY "
"message. SAVED_TCL == 0x%x\n",
- AHCNAME_VAR(ahc), channel, target,
- inb(SAVED_TCL + iobase));
+ ahc_name(ahc), channel, target,
+ AHC_INB(ahc, SAVED_TCL));
break;
case NO_MATCH:
if(ahc->flags & AHC_PAGESCBS) {
/* SCB Page-in request */
+ u_char tag;
+ u_char next;
+ u_char disc_scb;
struct scb *outscb;
- u_char arg_1 = inb(ARG_1 + iobase);
+ u_char arg_1 = AHC_INB(ahc, ARG_1);
if(arg_1 == SCB_LIST_NULL) {
/* Non-tagged command */
int index = target |
@@ -975,98 +1005,137 @@ ahc_intr(arg)
/*
* Now to pick the SCB to page out.
* Either take a free SCB, an assigned SCB,
- * an SCB that just completed or the first
- * one on the disconnected SCB list.
+ * an SCB that just completed, the first
+ * one on the disconnected SCB list, or
+ * as a last resort a queued SCB.
*/
- if(ahc->free_scbs.stqh_first) {
- outscb = ahc->free_scbs.stqh_first;
- STAILQ_REMOVE_HEAD(&ahc->free_scbs,
- links);
+ if((outscb = ahc->free_scbs.sqh_first) != NULL) {
+ SIMPLEQ_REMOVE_HEAD(&ahc->free_scbs,
+ outscb, links);
scb->position = outscb->position;
outscb->position = SCB_LIST_NULL;
- STAILQ_INSERT_HEAD(&ahc->page_scbs,
- outscb, links);
- outb(SCBPTR + iobase, scb->position);
+ SIMPLEQ_INSERT_HEAD(&ahc->page_scbs,
+ outscb, links);
+ AHC_OUTB(ahc, SCBPTR, scb->position);
ahc_send_scb(ahc, scb);
scb->flags &= ~SCB_PAGED_OUT;
+ goto pagein_done;
}
- else if(ahc->assigned_scbs.stqh_first) {
- outscb = ahc->assigned_scbs.stqh_first;
- STAILQ_REMOVE_HEAD(&ahc->assigned_scbs,
- links);
+ if((outscb = ahc->assigned_scbs.sqh_first) != NULL) {
+ SIMPLEQ_REMOVE_HEAD(&ahc->assigned_scbs,
+ outscb, links);
scb->position = outscb->position;
outscb->position = SCB_LIST_NULL;
- STAILQ_INSERT_HEAD(&ahc->waiting_scbs,
- outscb, links);
+ SIMPLEQ_INSERT_HEAD(&ahc->waiting_scbs,
+ outscb, links);
outscb->flags = SCB_WAITINGQ;
- outb(SCBPTR + iobase, scb->position);
+ AHC_OUTB(ahc, SCBPTR, scb->position);
ahc_send_scb(ahc, scb);
scb->flags &= ~SCB_PAGED_OUT;
+ goto pagein_done;
}
- else if(intstat & CMDCMPLT) {
+ if(intstat & CMDCMPLT) {
int scb_index;
printf("PIC\n");
- outb(CLRINT + iobase, CLRCMDINT);
- scb_index = inb(QOUTFIFO + iobase);
- if(!(inb(QOUTCNT + iobase) & ahc->qcntmask))
+ AHC_OUTB(ahc, CLRINT, CLRCMDINT);
+ scb_index = AHC_INB(ahc, QOUTFIFO);
+ if(!(AHC_INB(ahc, QOUTCNT) & ahc->qcntmask))
intstat &= ~CMDCMPLT;
outscb = ahc->scbarray[scb_index];
if (!outscb || !(outscb->flags & SCB_ACTIVE)) {
- printf(AHCNAME_FMT
- ": WARNING "
+ printf("%s: WARNING "
"no command for scb %d (cmdcmplt)\n",
- AHCNAME_VAR(ahc),
- scb_index );
- goto use_disconnected_scb;
+ ahc_name(ahc),
+ scb_index);
+ /* Fall through in hopes of finding another SCB */
}
else {
scb->position = outscb->position;
outscb->position = SCB_LIST_NULL;
- outb(SCBPTR + iobase, scb->position);
+ AHC_OUTB(ahc, SCBPTR, scb->position);
ahc_send_scb(ahc, scb);
scb->flags &= ~SCB_PAGED_OUT;
untimeout(ahc_timeout, (caddr_t)outscb);
ahc_done(ahc, outscb);
+ goto pagein_done;
}
}
- else {
- u_char tag;
- u_char next;
- u_char disc_scb;
-use_disconnected_scb:
- disc_scb =
- inb(DISCONNECTED_SCBH + iobase);
- if(disc_scb == SCB_LIST_NULL)
- panic("Page-in request with no "
- "candidates");
- outb(SCBPTR + iobase, disc_scb);
- tag = inb(SCB_TAG + iobase);
+ disc_scb = AHC_INB(ahc, DISCONNECTED_SCBH);
+ if(disc_scb != SCB_LIST_NULL) {
+ AHC_OUTB(ahc, SCBPTR, disc_scb);
+ tag = AHC_INB(ahc, SCB_TAG);
outscb = ahc->scbarray[tag];
- next = inb(SCB_NEXT + iobase);
+ next = AHC_INB(ahc, SCB_NEXT);
if(next != SCB_LIST_NULL) {
- outb(SCBPTR + iobase, next);
- outb(SCB_PREV + iobase,
+ AHC_OUTB(ahc, SCBPTR, next);
+ AHC_OUTB(ahc, SCB_PREV,
SCB_LIST_NULL);
- outb(SCBPTR + iobase, disc_scb);
+ AHC_OUTB(ahc, SCBPTR, disc_scb);
}
- outb(DISCONNECTED_SCBH + iobase, next);
+ AHC_OUTB(ahc, DISCONNECTED_SCBH, next);
ahc_page_scb(ahc, outscb, scb);
}
- outb(RETURN_1 + iobase, SCB_PAGEDIN);
+ else if(AHC_INB(ahc, QINCNT) & ahc->qcntmask) {
+ /* Pull one of our queued commands as a last resort */
+ disc_scb = AHC_INB(ahc, QINFIFO);
+ AHC_OUTB(ahc, SCBPTR, disc_scb);
+ tag = AHC_INB(ahc, SCB_TAG);
+ outscb = ahc->scbarray[tag];
+ if((outscb->control & 0x23) != TAG_ENB) {
+ /*
+ * This is not a simple tagged command
+ * so its position in the queue
+ * matters. Take the command at the
+ * end of the queue instead.
+ */
+ int i;
+ int saved_queue[AHC_SCB_MAX];
+ int queued = AHC_INB(ahc, QINCNT) & ahc->qcntmask;
+
+ /* Count the command we removed already */
+ saved_queue[0] = disc_scb;
+ queued++;
+
+ /* Empty the input queue */
+ for (i = 1; i < queued; i++)
+ saved_queue[i] = AHC_INB(ahc, QINFIFO);
+
+ /* Put everyone back put the last entry */
+ queued--;
+ for (i = 0; i < queued; i++)
+ AHC_OUTB(ahc, QINFIFO, saved_queue[i]);
+
+ AHC_OUTB(ahc, SCBPTR, saved_queue[queued]);
+ tag = AHC_INB(ahc, SCB_TAG);
+ outscb = ahc->scbarray[tag];
+ }
+ untimeout(ahc_timeout, (caddr_t)outscb);
+ scb->position = outscb->position;
+ outscb->position = SCB_LIST_NULL;
+ SIMPLEQ_INSERT_HEAD(&ahc->waiting_scbs,
+ outscb, links);
+ outscb->flags = SCB_WAITINGQ;
+ ahc_send_scb(ahc, scb);
+ scb->flags &= ~SCB_PAGED_OUT;
+ }
+ else
+ panic("Page-in request with no candidates");
+pagein_done:
+ AHC_OUTB(ahc, RETURN_1, SCB_PAGEDIN);
}
else {
- printf(AHCNAME_FMT ":%c:%d: no active SCB for "
+ printf("%s:%c:%d: no active SCB for "
"reconnecting target - "
"issuing ABORT\n",
- AHCNAME_VAR(ahc), channel, target);
+ ahc_name(ahc), channel, target);
printf("SAVED_TCL == 0x%x\n",
- inb(SAVED_TCL + iobase));
- ahc_unbusy_target(target, channel, iobase);
- outb(SCB_CONTROL + iobase, 0);
- outb(CLRSINT1 + iobase, CLRSELTIMEO);
- outb(RETURN_1 + iobase, 0);
+ AHC_INB(ahc, SAVED_TCL));
+ ahc_unbusy_target(ahc, target, channel);
+ AHC_OUTB(ahc, SCB_CONTROL, 0);
+ AHC_OUTB(ahc, CLRSINT1, CLRSELTIMEO);
+ AHC_OUTB(ahc, RETURN_1, 0);
}
break;
case SDTR_MSG:
@@ -1082,9 +1151,9 @@ use_disconnected_scb:
* the sync negotiation message. So, we must
* multiply by four
*/
- period = inb(ARG_1 + iobase) << 2;
- offset = inb(ACCUM + iobase);
- targ_scratch = inb(TARG_SCRATCH + iobase
+ period = AHC_INB(ahc, ARG_1) << 2;
+ offset = AHC_INB(ahc, ACCUM);
+ targ_scratch = AHC_INB(ahc, TARG_SCRATCH
+ scratch_offset);
if(targ_scratch & WIDEXFER)
maxoffset = 0x08;
@@ -1095,9 +1164,9 @@ use_disconnected_scb:
target);
/* Preserve the WideXfer flag */
targ_scratch = rate | (targ_scratch & WIDEXFER);
- outb(TARG_SCRATCH + iobase + scratch_offset,
+ AHC_OUTB(ahc, TARG_SCRATCH + scratch_offset,
targ_scratch);
- outb(SCSIRATE + iobase, targ_scratch);
+ AHC_OUTB(ahc, SCSIRATE, targ_scratch);
if( (targ_scratch & 0x0f) == 0 )
{
/*
@@ -1109,7 +1178,7 @@ use_disconnected_scb:
* ensure we go to asyncronous
* transfers.
*/
- outb(RETURN_1 + iobase, SEND_REJ);
+ AHC_OUTB(ahc, RETURN_1, SEND_REJ);
}
/* See if we initiated Sync Negotiation */
else if(ahc->sdtrpending & targ_mask)
@@ -1118,7 +1187,7 @@ use_disconnected_scb:
* Don't send an SDTR back to
* the target
*/
- outb(RETURN_1 + iobase, 0);
+ AHC_OUTB(ahc, RETURN_1, 0);
}
else{
/*
@@ -1128,7 +1197,7 @@ use_disconnected_scb:
if(ahc_debug & AHC_SHOWMISC)
printf("Sending SDTR!!\n");
#endif
- outb(RETURN_1 + iobase, SEND_SDTR);
+ AHC_OUTB(ahc, RETURN_1, SEND_SDTR);
}
/*
* Negate the flags
@@ -1141,9 +1210,9 @@ use_disconnected_scb:
{
u_char scratch, bus_width;
- bus_width = inb(ARG_1 + iobase);
+ bus_width = AHC_INB(ahc, ARG_1);
- scratch = inb(TARG_SCRATCH + iobase
+ scratch = AHC_INB(ahc, TARG_SCRATCH
+ scratch_offset);
if(ahc->wdtrpending & targ_mask)
@@ -1152,7 +1221,7 @@ use_disconnected_scb:
* Don't send a WDTR back to the
* target, since we asked first.
*/
- outb(RETURN_1 + iobase, 0);
+ AHC_OUTB(ahc, RETURN_1, 0);
switch(bus_width)
{
case BUS_8_BIT:
@@ -1160,11 +1229,10 @@ use_disconnected_scb:
break;
case BUS_16_BIT:
if(bootverbose)
- printf(AHCNAME_FMT
- ": target "
+ printf("%s: target "
"%d using 16Bit "
"transfers\n",
- AHCNAME_VAR(ahc),
+ ahc_name(ahc),
target);
scratch |= 0x80;
break;
@@ -1174,14 +1242,13 @@ use_disconnected_scb:
* transfers on a 16bit
* bus?
*/
- outb(RETURN_1 + iobase,
+ AHC_OUTB(ahc, RETURN_1,
SEND_REJ);
- printf(AHCNAME_FMT
- ": target "
+ printf("%s: target "
"%d requested 32Bit "
"transfers. "
"Rejecting...\n",
- AHCNAME_VAR(ahc),
+ ahc_name(ahc),
target);
break;
default:
@@ -1203,12 +1270,11 @@ use_disconnected_scb:
/* Negotiate 16_BITS */
bus_width = BUS_16_BIT;
if(bootverbose)
- printf(AHCNAME_FMT
- ": "
+ printf("%s: "
"target %d "
"using 16Bit "
"transfers\n",
- AHCNAME_VAR(ahc),
+ ahc_name(ahc),
target);
scratch |= 0x80;
}
@@ -1218,14 +1284,14 @@ use_disconnected_scb:
default:
break;
}
- outb(RETURN_1 + iobase,
+ AHC_OUTB(ahc, RETURN_1,
bus_width | SEND_WDTR);
}
ahc->needwdtr &= ~targ_mask;
ahc->wdtrpending &= ~targ_mask;
- outb(TARG_SCRATCH + iobase + scratch_offset,
+ AHC_OUTB(ahc, TARG_SCRATCH + scratch_offset,
scratch);
- outb(SCSIRATE + iobase, scratch);
+ AHC_OUTB(ahc, SCSIRATE, scratch);
break;
}
case REJECT_MSG:
@@ -1239,7 +1305,7 @@ use_disconnected_scb:
u_char targ_scratch;
- targ_scratch = inb(TARG_SCRATCH + iobase
+ targ_scratch = AHC_INB(ahc, TARG_SCRATCH
+ scratch_offset);
if(ahc->wdtrpending & targ_mask){
@@ -1247,10 +1313,10 @@ use_disconnected_scb:
targ_scratch &= 0x7f;
ahc->needwdtr &= ~targ_mask;
ahc->wdtrpending &= ~targ_mask;
- printf(AHCNAME_FMT ":%c:%d: refuses "
+ printf("%s:%c:%d: refuses "
"WIDE negotiation. Using "
"8bit transfers\n",
- AHCNAME_VAR(ahc),
+ ahc_name(ahc),
channel, target);
}
else if(ahc->sdtrpending & targ_mask){
@@ -1258,10 +1324,10 @@ use_disconnected_scb:
targ_scratch &= 0xf0;
ahc->needsdtr &= ~targ_mask;
ahc->sdtrpending &= ~targ_mask;
- printf(AHCNAME_FMT ":%c:%d: refuses "
+ printf("%s:%c:%d: refuses "
"syncronous negotiation. Using "
"asyncronous transfers\n",
- AHCNAME_VAR(ahc),
+ ahc_name(ahc),
channel, target);
}
else {
@@ -1270,17 +1336,16 @@ use_disconnected_scb:
*/
#ifdef AHC_DEBUG
if(ahc_debug & AHC_SHOWMISC)
- printf(AHCNAME_FMT
- ":%c:%d: Message "
+ printf("%s:%c:%d: Message "
"reject -- ignored\n",
- AHCNAME_VAR(ahc),
+ ahc_name(ahc),
channel, target);
#endif
break;
}
- outb(TARG_SCRATCH + iobase + scratch_offset,
+ AHC_OUTB(ahc, TARG_SCRATCH + scratch_offset,
targ_scratch);
- outb(SCSIRATE + iobase, targ_scratch);
+ AHC_OUTB(ahc, SCSIRATE, targ_scratch);
break;
}
case BAD_STATUS:
@@ -1294,7 +1359,7 @@ use_disconnected_scb:
* without error.
*/
- scb_index = inb(SCB_TAG + iobase);
+ scb_index = AHC_INB(ahc, SCB_TAG);
scb = ahc->scbarray[scb_index];
/*
@@ -1303,11 +1368,11 @@ use_disconnected_scb:
* this if needed and this reduces code
* duplication.
*/
- outb(RETURN_1 + iobase, 0);
+ AHC_OUTB(ahc, RETURN_1, 0);
if (!(scb && (scb->flags & SCB_ACTIVE))) {
- printf(AHCNAME_FMT ":%c:%d: ahc_intr - referenced scb "
+ printf("%s:%c:%d: ahc_intr - referenced scb "
"not valid during seqint 0x%x scb(%d)\n",
- AHCNAME_VAR(ahc),
+ ahc_name(ahc),
channel, target, intstat,
scb_index);
goto clear;
@@ -1315,7 +1380,7 @@ use_disconnected_scb:
xs = scb->xs;
- scb->status = inb(SCB_TARGET_STATUS + iobase);
+ scb->status = AHC_INB(ahc, SCB_TARGET_STATUS);
#ifdef AHC_DEBUG
if((ahc_debug & AHC_SHOWSCBS)
@@ -1325,8 +1390,8 @@ use_disconnected_scb:
xs->status = scb->status;
switch(scb->status){
case SCSI_OK:
- printf(AHCNAME_FMT ": Interrupted for staus of"
- " 0???\n", AHCNAME_VAR(ahc));
+ printf("%s: Interrupted for staus of"
+ " 0???\n", ahc_name(ahc));
break;
case SCSI_CHECK:
#ifdef AHC_DEBUG
@@ -1366,8 +1431,8 @@ use_disconnected_scb:
scb->SG_list_pointer = KVTOPHYS(sg);
scb->data = sg->addr;
scb->datalen = sg->len;
-#ifdef AIC7XXX_BROKEN_CACHE
- if (aic7xxx_broken_cache)
+#ifdef AHC_BROKEN_CACHE
+ if (ahc_broken_cache)
INVALIDATE_CACHE();
#endif
scb->cmdpointer = KVTOPHYS(sc);
@@ -1381,13 +1446,13 @@ use_disconnected_scb:
* commands if we happen to be doing
* tagged I/O.
*/
- ahc_busy_target(target,channel,iobase);
+ ahc_busy_target(ahc, target, channel);
/*
* Make us the next command to run
*/
- ahc_add_waiting_scb(iobase, scb);
- outb(RETURN_1 + iobase, SEND_SENSE);
+ ahc_add_waiting_scb(ahc, scb);
+ AHC_OUTB(ahc, RETURN_1, SEND_SENSE);
break;
}
/*
@@ -1415,7 +1480,7 @@ use_disconnected_scb:
sc_print_addr(xs->sc_link);
printf("Queue Full\n");
scb->flags = SCB_ASSIGNEDQ;
- STAILQ_INSERT_TAIL(&ahc->assigned_scbs,
+ SIMPLEQ_INSERT_TAIL(&ahc->assigned_scbs,
scb, links);
break;
#elif defined(__NetBSD__)
@@ -1438,7 +1503,7 @@ use_disconnected_scb:
case RESIDUAL:
{
int scb_index;
- scb_index = inb(SCB_TAG + iobase);
+ scb_index = AHC_INB(ahc, SCB_TAG);
scb = ahc->scbarray[scb_index];
xs = scb->xs;
/*
@@ -1454,16 +1519,16 @@ use_disconnected_scb:
* stopped.
*/
xs->resid =
- (inb(iobase+SCB_RESID_DCNT2)<<16) |
- (inb(iobase+SCB_RESID_DCNT1)<<8) |
- inb(iobase+SCB_RESID_DCNT0);
+ (AHC_INB(ahc, SCB_RESID_DCNT2)<<16) |
+ (AHC_INB(ahc, SCB_RESID_DCNT1)<<8) |
+ AHC_INB(ahc, SCB_RESID_DCNT0);
/*
* Add up the contents of all residual
* SG segments that are after the SG where
* the transfer stopped.
*/
- resid_sgs = inb(SCB_RESID_SGCNT + iobase) - 1;
+ resid_sgs = AHC_INB(ahc, SCB_RESID_SGCNT) - 1;
while(resid_sgs > 0) {
int sg;
@@ -1490,7 +1555,7 @@ use_disconnected_scb:
case ABORT_TAG:
{
int scb_index;
- scb_index = inb(SCB_TAG + iobase);
+ scb_index = AHC_INB(ahc, SCB_TAG);
scb = ahc->scbarray[scb_index];
xs = scb->xs;
/*
@@ -1507,7 +1572,7 @@ use_disconnected_scb:
case AWAITING_MSG:
{
int scb_index;
- scb_index = inb(SCB_TAG + iobase);
+ scb_index = AHC_INB(ahc, SCB_TAG);
scb = ahc->scbarray[scb_index];
/*
* This SCB had a zero length command, informing
@@ -1517,9 +1582,9 @@ use_disconnected_scb:
*/
if(scb->flags & SCB_DEVICE_RESET)
{
- outb(MSG0 + iobase,
+ AHC_OUTB(ahc, MSG0,
MSG_BUS_DEVICE_RESET);
- outb(MSG_LEN + iobase, 1);
+ AHC_OUTB(ahc, MSG_LEN, 1);
printf("Bus Device Reset Message Sent\n");
}
else
@@ -1532,7 +1597,7 @@ use_disconnected_scb:
/*
* Take care of device reset messages
*/
- u_char scbindex = inb(SCB_TAG + iobase);
+ u_char scbindex = AHC_INB(ahc, SCB_TAG);
scb = ahc->scbarray[scbindex];
if(scb->flags & SCB_DEVICE_RESET) {
u_char targ_scratch;
@@ -1541,15 +1606,15 @@ use_disconnected_scb:
* Go back to async/narrow transfers and
* renegotiate.
*/
- ahc_unbusy_target(target, channel, iobase);
+ ahc_unbusy_target(ahc, target, channel);
ahc->needsdtr |= ahc->needsdtr_orig & targ_mask;
ahc->needwdtr |= ahc->needwdtr_orig & targ_mask;
ahc->sdtrpending &= ~targ_mask;
ahc->wdtrpending &= ~targ_mask;
- targ_scratch = inb(TARG_SCRATCH + iobase
+ targ_scratch = AHC_INB(ahc, TARG_SCRATCH
+ scratch_offset);
targ_scratch &= SXFR;
- outb(TARG_SCRATCH + iobase + scratch_offset,
+ AHC_OUTB(ahc, TARG_SCRATCH + scratch_offset,
targ_scratch);
found = ahc_reset_device(ahc, target,
channel, SCB_LIST_NULL,
@@ -1575,7 +1640,7 @@ use_disconnected_scb:
default:
printf("ahc_intr: seqint, "
"intstat == 0x%x, scsisigi = 0x%x\n",
- intstat, inb(SCSISIGI + iobase));
+ intstat, AHC_INB(ahc, SCSISIGI));
break;
}
clear:
@@ -1583,7 +1648,7 @@ clear:
* Clear the upper byte that holds SEQINT status
* codes and clear the SEQINT bit.
*/
- outb(CLRINT + iobase, CLRSEQINT);
+ AHC_OUTB(ahc, CLRINT, CLRSEQINT);
/*
* The sequencer is paused immediately on
@@ -1596,8 +1661,8 @@ clear:
if (intstat & SCSIINT) {
- int scb_index = inb(SCB_TAG + iobase);
- status = inb(SSTAT1 + iobase);
+ int scb_index = AHC_INB(ahc, SCB_TAG);
+ status = AHC_INB(ahc, SSTAT1);
scb = ahc->scbarray[scb_index];
if (scb != NULL) /* XXX - is this case exist ? */
@@ -1605,10 +1670,10 @@ clear:
if (status & SCSIRSTI) {
char channel;
- channel = inb(SBLKCTL + iobase);
+ channel = AHC_INB(ahc, SBLKCTL);
channel = channel & SELBUSB ? 'B' : 'A';
- printf(AHCNAME_FMT ": Someone reset channel %c\n",
- AHCNAME_VAR(ahc), channel);
+ printf("%s: Someone reset channel %c\n",
+ ahc_name(ahc), channel);
ahc_reset_channel(ahc,
channel,
SCB_LIST_NULL,
@@ -1617,12 +1682,12 @@ clear:
scb = NULL;
}
else if (!(scb && (scb->flags & SCB_ACTIVE))){
- printf(AHCNAME_FMT ": ahc_intr - referenced scb not "
+ printf("%s: ahc_intr - referenced scb not "
"valid during scsiint 0x%x scb(%d)\n",
- AHCNAME_VAR(ahc), status, scb_index);
- outb(CLRSINT1 + iobase, status);
+ ahc_name(ahc), status, scb_index);
+ AHC_OUTB(ahc, CLRSINT1, status);
UNPAUSE_SEQUENCER(ahc);
- outb(CLRINT + iobase, CLRSCSIINT);
+ AHC_OUTB(ahc, CLRINT, CLRSCSIINT);
scb = NULL;
}
else if (status & SCSIPERR) {
@@ -1632,7 +1697,7 @@ clear:
*/
char *phase;
u_char mesg_out = MSG_NOP;
- u_char lastphase = inb(LASTPHASE + iobase);
+ u_char lastphase = AHC_INB(ahc, LASTPHASE);
sc_print_addr(xs->sc_link);
@@ -1672,8 +1737,8 @@ clear:
* mesg_out to something other than MSG_NOP.
*/
if(mesg_out != MSG_NOP) {
- outb(MSG0 + iobase, mesg_out);
- outb(MSG_LEN + iobase, 1);
+ AHC_OUTB(ahc, MSG0, mesg_out);
+ AHC_OUTB(ahc, MSG_LEN, 1);
}
else
/*
@@ -1690,37 +1755,36 @@ clear:
* Clear any pending messages for the timed out
* target, and mark the target as free
*/
- flags = inb(FLAGS + iobase);
- outb(MSG_LEN + iobase, 0);
- ahc_unbusy_target(xs->sc_link->target,
+ flags = AHC_INB(ahc, FLAGS);
+ AHC_OUTB(ahc, MSG_LEN, 0);
+ ahc_unbusy_target(ahc, xs->sc_link->target,
#if defined(__FreeBSD__)
((long)xs->sc_link->fordriver & SELBUSB)
#elif defined(__NetBSD__)
IS_SCSIBUS_B(ahc, xs->sc_link)
#endif
- ? 'B' : 'A',
- iobase);
+ ? 'B' : 'A');
- outb(SCB_CONTROL + iobase, 0);
+ AHC_OUTB(ahc, SCB_CONTROL, 0);
- outb(CLRSINT1 + iobase, CLRSELTIMEO);
+ AHC_OUTB(ahc, CLRSINT1, CLRSELTIMEO);
- outb(CLRINT + iobase, CLRSCSIINT);
+ AHC_OUTB(ahc, CLRINT, CLRSCSIINT);
/* Shift the waiting for selection queue forward */
- waiting = inb(WAITING_SCBH + iobase);
- outb(SCBPTR + iobase, waiting);
- waiting = inb(SCB_NEXT + iobase);
- outb(WAITING_SCBH + iobase, waiting);
+ waiting = AHC_INB(ahc, WAITING_SCBH);
+ AHC_OUTB(ahc, SCBPTR, waiting);
+ waiting = AHC_INB(ahc, SCB_NEXT);
+ AHC_OUTB(ahc, WAITING_SCBH, waiting);
RESTART_SEQUENCER(ahc);
}
else if (!(status & BUSFREE)) {
sc_print_addr(xs->sc_link);
printf("Unknown SCSIINT. Status = 0x%x\n", status);
- outb(CLRSINT1 + iobase, status);
+ AHC_OUTB(ahc, CLRSINT1, status);
UNPAUSE_SEQUENCER(ahc);
- outb(CLRINT + iobase, CLRSCSIINT);
+ AHC_OUTB(ahc, CLRINT, CLRSCSIINT);
scb = NULL;
}
if(scb != NULL) {
@@ -1733,22 +1797,22 @@ clear:
int scb_index;
do {
- scb_index = inb(QOUTFIFO + iobase);
+ scb_index = AHC_INB(ahc, QOUTFIFO);
scb = ahc->scbarray[scb_index];
if (!scb || !(scb->flags & SCB_ACTIVE)) {
- printf(AHCNAME_FMT ": WARNING "
+ printf("%s: WARNING "
"no command for scb %d (cmdcmplt)\n"
"QOUTCNT == %d\n",
- AHCNAME_VAR(ahc), scb_index,
- inb(QOUTCNT + iobase));
- outb(CLRINT + iobase, CLRCMDINT);
+ ahc_name(ahc), scb_index,
+ AHC_INB(ahc, QOUTCNT));
+ AHC_OUTB(ahc, CLRINT, CLRCMDINT);
continue;
}
- outb(CLRINT + iobase, CLRCMDINT);
+ AHC_OUTB(ahc, CLRINT, CLRCMDINT);
untimeout(ahc_timeout, (caddr_t)scb);
ahc_done(ahc, scb);
- } while (inb(QOUTCNT + iobase) & ahc->qcntmask);
+ } while (AHC_INB(ahc, QOUTCNT) & ahc->qcntmask);
ahc_run_waiting_queues(ahc);
}
@@ -1811,9 +1875,8 @@ ahc_done(ahc, scb)
inq_data = (struct scsi_inquiry_data *)xs->data;
if((inq_data->flags & SID_CmdQue) && !(ahc->tagenable & mask))
{
- printf(AHCNAME_FMT
- ": target %d Tagged Queuing Device\n",
- AHCNAME_VAR(ahc), xs->sc_link->target);
+ printf("%s: target %d Tagged Queuing Device\n",
+ ahc_name(ahc), xs->sc_link->target);
ahc->tagenable |= mask;
if(ahc->maxhscbs >= 16 || (ahc->flags & AHC_PAGESCBS)) {
/* Default to 8 tags */
@@ -1845,7 +1908,6 @@ int
ahc_init(ahc)
struct ahc_data *ahc;
{
- u_long iobase = ahc->baseport;
u_char scsi_conf, sblkctl, i;
int max_targ = 15;
/*
@@ -1858,19 +1920,21 @@ ahc_init(ahc)
#endif
/* Determine channel configuration and who we are on the scsi bus. */
- switch ( (sblkctl = inb(SBLKCTL + iobase) & 0x0a) ) {
+ switch ( (sblkctl = AHC_INB(ahc, SBLKCTL) & 0x0a) ) {
case 0:
- ahc->our_id = (inb(SCSICONF + iobase) & HSCSIID);
+ ahc->our_id = (AHC_INB(ahc, SCSICONF) & HSCSIID);
+ ahc->flags &= ~AHC_CHANNEL_B_PRIMARY;
if(ahc->type == AHC_394)
printf("Channel %c, SCSI Id=%d, ",
ahc->flags & AHC_CHNLB ? 'B' : 'A',
ahc->our_id);
else
printf("Single Channel, SCSI Id=%d, ", ahc->our_id);
- outb(FLAGS + iobase, SINGLE_BUS | (ahc->flags & AHC_PAGESCBS));
+ AHC_OUTB(ahc, FLAGS, SINGLE_BUS | (ahc->flags & AHC_PAGESCBS));
break;
case 2:
- ahc->our_id = (inb(SCSICONF + 1 + iobase) & HWSCSIID);
+ ahc->our_id = (AHC_INB(ahc, SCSICONF + 1) & HWSCSIID);
+ ahc->flags &= ~AHC_CHANNEL_B_PRIMARY;
if(ahc->type == AHC_394)
printf("Wide Channel %c, SCSI Id=%d, ",
ahc->flags & AHC_CHNLB ? 'B' : 'A',
@@ -1878,15 +1942,15 @@ ahc_init(ahc)
else
printf("Wide Channel, SCSI Id=%d, ", ahc->our_id);
ahc->type |= AHC_WIDE;
- outb(FLAGS + iobase, WIDE_BUS | (ahc->flags & AHC_PAGESCBS));
+ AHC_OUTB(ahc, FLAGS, WIDE_BUS | (ahc->flags & AHC_PAGESCBS));
break;
case 8:
- ahc->our_id = (inb(SCSICONF + iobase) & HSCSIID);
- ahc->our_id_b = (inb(SCSICONF + 1 + iobase) & HSCSIID);
+ ahc->our_id = (AHC_INB(ahc, SCSICONF) & HSCSIID);
+ ahc->our_id_b = (AHC_INB(ahc, SCSICONF + 1) & HSCSIID);
printf("Twin Channel, A SCSI Id=%d, B SCSI Id=%d, ",
ahc->our_id, ahc->our_id_b);
ahc->type |= AHC_TWIN;
- outb(FLAGS + iobase, TWIN_BUS | (ahc->flags & AHC_PAGESCBS));
+ AHC_OUTB(ahc, FLAGS, TWIN_BUS | (ahc->flags & AHC_PAGESCBS));
break;
default:
printf(" Unsupported adapter type. Ignoring\n");
@@ -1896,26 +1960,26 @@ ahc_init(ahc)
/* Determine the number of SCBs */
{
- outb(SCBPTR + iobase, 0);
- outb(SCB_CONTROL + iobase, 0);
+ AHC_OUTB(ahc, SCBPTR, 0);
+ AHC_OUTB(ahc, SCB_CONTROL, 0);
for(i = 1; i < AHC_SCB_MAX; i++) {
- outb(SCBPTR + iobase, i);
- outb(SCB_CONTROL + iobase, i);
- if(inb(SCB_CONTROL + iobase) != i)
+ AHC_OUTB(ahc, SCBPTR, i);
+ AHC_OUTB(ahc, SCB_CONTROL, i);
+ if(AHC_INB(ahc, SCB_CONTROL) != i)
break;
- outb(SCBPTR + iobase, 0);
- if(inb(SCB_CONTROL + iobase) != 0)
+ AHC_OUTB(ahc, SCBPTR, 0);
+ if(AHC_INB(ahc, SCB_CONTROL) != 0)
break;
/* Clear the control byte. */
- outb(SCBPTR + iobase, i);
- outb(SCB_CONTROL + iobase, 0);
+ AHC_OUTB(ahc, SCBPTR, i);
+ AHC_OUTB(ahc, SCB_CONTROL, 0);
ahc->qcntmask |= i; /* Update the count mask. */
}
/* Ensure we clear the 0 SCB's control byte. */
- outb(SCBPTR + iobase, 0);
- outb(SCB_CONTROL + iobase, 0);
+ AHC_OUTB(ahc, SCBPTR, 0);
+ AHC_OUTB(ahc, SCB_CONTROL, 0);
ahc->qcntmask |= i;
ahc->maxhscbs = i;
@@ -1933,9 +1997,9 @@ ahc_init(ahc)
#ifdef AHC_DEBUG
if(ahc_debug & AHC_SHOWMISC) {
struct scb test;
- printf(AHCNAME_FMT ": hardware scb %ld bytes; kernel scb; "
+ printf("%s: hardware scb %ld bytes; kernel scb; "
"ahc_dma %d bytes\n",
- AHCNAME_VAR(ahc),
+ ahc_name(ahc),
(u_long)&(test.next) - (u_long)(&test),
sizeof(test),
sizeof(struct ahc_dma_seg));
@@ -1949,44 +2013,56 @@ ahc_init(ahc)
* The device is gated to channel B after a chip reset,
* so set those values first
*/
- outb(SCSIID + iobase, ahc->our_id_b);
- scsi_conf = inb(SCSICONF + 1 + iobase) & (ENSPCHK|STIMESEL);
- outb(SXFRCTL1 + iobase, scsi_conf|ENSTIMER|ACTNEGEN|STPWEN);
- outb(SIMODE1 + iobase, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
+ AHC_OUTB(ahc, SCSIID, ahc->our_id_b);
+ scsi_conf = AHC_INB(ahc, SCSICONF + 1);
+ AHC_OUTB(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL))
+ | ENSTIMER|ACTNEGEN|STPWEN);
+ AHC_OUTB(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
if(ahc->type & AHC_ULTRA)
- outb(SXFRCTL0 + iobase, DFON|SPIOEN|ULTRAEN);
+ AHC_OUTB(ahc, SXFRCTL0, DFON|SPIOEN|ULTRAEN);
else
- outb(SXFRCTL0 + iobase, DFON|SPIOEN);
-
- /* Reset the bus */
- outb(SCSISEQ + iobase, SCSIRSTO);
- DELAY(1000);
- outb(SCSISEQ + iobase, 0);
-
- /* Ensure we don't get a RSTI interrupt from this */
- outb(CLRSINT1 + iobase, CLRSCSIRSTI);
- outb(CLRINT + iobase, CLRSCSIINT);
+ AHC_OUTB(ahc, SXFRCTL0, DFON|SPIOEN);
+
+ if(scsi_conf & RESET_SCSI) {
+ /* Reset the bus */
+ if(bootverbose)
+ printf("%s: Reseting Channel B\n",
+ ahc_name(ahc));
+ AHC_OUTB(ahc, SCSISEQ, SCSIRSTO);
+ DELAY(1000);
+ AHC_OUTB(ahc, SCSISEQ, 0);
+
+ /* Ensure we don't get a RSTI interrupt from this */
+ AHC_OUTB(ahc, CLRSINT1, CLRSCSIRSTI);
+ AHC_OUTB(ahc, CLRINT, CLRSCSIINT);
+ }
/* Select Channel A */
- outb(SBLKCTL + iobase, 0);
+ AHC_OUTB(ahc, SBLKCTL, 0);
}
- outb(SCSIID + iobase, ahc->our_id);
- scsi_conf = inb(SCSICONF + iobase) & (ENSPCHK|STIMESEL);
- outb(SXFRCTL1 + iobase, scsi_conf|ENSTIMER|ACTNEGEN|STPWEN);
- outb(SIMODE1 + iobase, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
+ AHC_OUTB(ahc, SCSIID, ahc->our_id);
+ scsi_conf = AHC_INB(ahc, SCSICONF);
+ AHC_OUTB(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL))
+ | ENSTIMER|ACTNEGEN|STPWEN);
+ AHC_OUTB(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
if(ahc->type & AHC_ULTRA)
- outb(SXFRCTL0 + iobase, DFON|SPIOEN|ULTRAEN);
+ AHC_OUTB(ahc, SXFRCTL0, DFON|SPIOEN|ULTRAEN);
else
- outb(SXFRCTL0 + iobase, DFON|SPIOEN);
+ AHC_OUTB(ahc, SXFRCTL0, DFON|SPIOEN);
- /* Reset the bus */
- outb(SCSISEQ + iobase, SCSIRSTO);
- DELAY(1000);
- outb(SCSISEQ + iobase, 0);
+ if(scsi_conf & RESET_SCSI) {
+ /* Reset the bus */
+ if(bootverbose)
+ printf("%s: Reseting Channel A\n", ahc_name(ahc));
+
+ AHC_OUTB(ahc, SCSISEQ, SCSIRSTO);
+ DELAY(1000);
+ AHC_OUTB(ahc, SCSISEQ, 0);
- /* Ensure we don't get a RSTI interrupt from this */
- outb(CLRSINT1 + iobase, CLRSCSIRSTI);
- outb(CLRINT + iobase, CLRSCSIINT);
+ /* Ensure we don't get a RSTI interrupt from this */
+ AHC_OUTB(ahc, CLRSINT1, CLRSCSIRSTI);
+ AHC_OUTB(ahc, CLRINT, CLRSCSIINT);
+ }
/*
* Look at the information that board initialization or
@@ -2002,14 +2078,13 @@ ahc_init(ahc)
/* Grab the disconnection disable table and invert it for our needs */
if(ahc->flags & AHC_USEDEFAULTS) {
- printf(AHCNAME_FMT
- ": Host Adapter Bios disabled. Using default SCSI "
- "device parameters\n", AHCNAME_VAR(ahc));
+ printf("%s: Host Adapter Bios disabled. Using default SCSI "
+ "device parameters\n", ahc_name(ahc));
ahc->discenable = 0xff;
}
else
- ahc->discenable = ~((inb(DISC_DSB + iobase + 1) << 8)
- | inb(DISC_DSB + iobase));
+ ahc->discenable = ~((AHC_INB(ahc, DISC_DSB + 1) << 8)
+ | AHC_INB(ahc, DISC_DSB));
if(!(ahc->type & (AHC_WIDE|AHC_TWIN)))
max_targ = 7;
@@ -2023,7 +2098,7 @@ ahc_init(ahc)
}
else {
/* Take the settings leftover in scratch RAM. */
- target_settings = inb(TARG_SCRATCH + i + iobase);
+ target_settings = AHC_INB(ahc, TARG_SCRATCH + i);
if(target_settings & 0x0f){
ahc->needsdtr_orig |= (0x01 << i);
@@ -2041,7 +2116,7 @@ ahc_init(ahc)
target_settings &= 0x7f;
}
}
- outb(TARG_SCRATCH+i+iobase,target_settings);
+ AHC_OUTB(ahc, TARG_SCRATCH+i,target_settings);
}
/*
* If we are not a WIDE device, forget WDTR. This
@@ -2068,50 +2143,50 @@ ahc_init(ahc)
/*
* Set the number of availible SCBs
*/
- outb(SCBCOUNT + iobase, ahc->maxhscbs);
+ AHC_OUTB(ahc, SCBCOUNT, ahc->maxhscbs);
/*
* 2's compliment of maximum tag value
*/
i = ahc->maxscbs;
- outb(COMP_SCBCOUNT + iobase, -i & 0xff);
+ AHC_OUTB(ahc, COMP_SCBCOUNT, -i & 0xff);
/*
* QCount mask to deal with broken aic7850s that
* sporatically get garbage in the upper bits of
* their QCount registers.
*/
- outb(QCNTMASK + iobase, ahc->qcntmask);
+ AHC_OUTB(ahc, QCNTMASK, ahc->qcntmask);
/* We don't have any busy targets right now */
- outb(ACTIVE_A + iobase, 0);
- outb(ACTIVE_B + iobase, 0);
+ AHC_OUTB(ahc, ACTIVE_A, 0);
+ AHC_OUTB(ahc, ACTIVE_B, 0);
/* We don't have any waiting selections */
- outb(WAITING_SCBH + iobase, SCB_LIST_NULL);
+ AHC_OUTB(ahc, WAITING_SCBH, SCB_LIST_NULL);
/* Our disconnection list is empty too */
- outb(DISCONNECTED_SCBH + iobase, SCB_LIST_NULL);
+ AHC_OUTB(ahc, DISCONNECTED_SCBH, SCB_LIST_NULL);
/* Message out buffer starts empty */
- outb(MSG_LEN + iobase, 0x00);
+ AHC_OUTB(ahc, MSG_LEN, 0x00);
/*
* Load the Sequencer program and Enable the adapter
* in "fast" mode.
*/
if(bootverbose)
- printf(AHCNAME_FMT ": Downloading Sequencer Program...",
- AHCNAME_VAR(ahc));
+ printf("%s: Downloading Sequencer Program...",
+ ahc_name(ahc));
- ahc_loadseq(iobase);
+ ahc_loadseq(ahc);
if(bootverbose)
printf("Done\n");
- outb(SEQCTL + iobase, FASTMODE);
+ AHC_OUTB(ahc, SEQCTL, FASTMODE);
- UNPAUSE_SEQUENCER(ahc);
+ UNPAUSE_SEQUENCER(ahc);
/*
* Note that we are going and return (to probe)
@@ -2173,11 +2248,11 @@ ahc_scsi_cmd(xs)
*/
flags = xs->flags;
if (flags & ITSDONE) {
- printf(AHCNAME_FMT ": Already done?", AHCNAME_VAR(ahc));
+ printf("%s: Already done?", ahc_name(ahc));
xs->flags &= ~ITSDONE;
}
if (!(flags & INUSE)) {
- printf(AHCNAME_FMT ": Not in use?", AHCNAME_VAR(ahc));
+ printf("%s: Not in use?", ahc_name(ahc));
xs->flags |= INUSE;
}
if (!(scb = ahc_get_scb(ahc, flags))) {
@@ -2284,15 +2359,14 @@ ahc_scsi_cmd(xs)
SC_DEBUGN(xs->sc_link, SDEV_DB4, ("\n"));
if (datalen) {
/* there's still data, must have run out of segs! */
- printf(AHCNAME_FMT
- ": ahc_scsi_cmd: more than %d DMA segs\n",
- AHCNAME_VAR(ahc), AHC_NSEG);
+ printf("%s: ahc_scsi_cmd: more than %d DMA segs\n",
+ ahc_name(ahc), AHC_NSEG);
xs->error = XS_DRIVER_STUFFUP;
ahc_free_scb(ahc, scb, flags);
return (COMPLETE);
}
-#ifdef AIC7XXX_BROKEN_CACHE
- if (aic7xxx_broken_cache)
+#ifdef AHC_BROKEN_CACHE
+ if (ahc_broken_cache)
INVALIDATE_CACHE();
#endif
}
@@ -2315,15 +2389,14 @@ ahc_scsi_cmd(xs)
if( scb->position != SCB_LIST_NULL )
{
/* We already have a valid slot */
- u_long iobase = ahc->baseport;
u_char curscb;
PAUSE_SEQUENCER(ahc);
- curscb = inb(SCBPTR + iobase);
- outb(SCBPTR + iobase, scb->position);
+ curscb = AHC_INB(ahc, SCBPTR);
+ AHC_OUTB(ahc, SCBPTR, scb->position);
ahc_send_scb(ahc, scb);
- outb(SCBPTR + iobase, curscb);
- outb(QINFIFO + iobase, scb->position);
+ AHC_OUTB(ahc, SCBPTR, curscb);
+ AHC_OUTB(ahc, QINFIFO, scb->position);
UNPAUSE_SEQUENCER(ahc);
scb->flags = SCB_ACTIVE;
if (!(flags & SCSI_NOMASK)) {
@@ -2334,7 +2407,7 @@ ahc_scsi_cmd(xs)
}
else {
scb->flags = SCB_WAITINGQ;
- STAILQ_INSERT_TAIL(&ahc->waiting_scbs, scb, links);
+ SIMPLEQ_INSERT_TAIL(&ahc->waiting_scbs, scb, links);
ahc_run_waiting_queues(ahc);
}
if (!(flags & SCSI_NOMASK)) {
@@ -2375,8 +2448,8 @@ ahc_free_scb(ahc, scb, flags)
scb->flags = SCB_FREE;
if(scb->position == SCB_LIST_NULL) {
- STAILQ_INSERT_HEAD(&ahc->page_scbs, scb, links);
- if(!scb->links.stqe_next && !ahc->free_scbs.stqh_first)
+ SIMPLEQ_INSERT_HEAD(&ahc->page_scbs, scb, links);
+ if(!scb->links.sqe_next && !ahc->free_scbs.sqh_first)
/*
* If there were no SCBs availible, wake anybody waiting
* for one to come free.
@@ -2390,10 +2463,10 @@ ahc_free_scb(ahc, scb, flags)
* completes for a particular interrupt are completed
* or when we start another command.
*/
- else if((wscb = ahc->waiting_scbs.stqh_first) != NULL) {
+ else if((wscb = ahc->waiting_scbs.sqh_first) != NULL) {
+ SIMPLEQ_REMOVE_HEAD(&ahc->waiting_scbs, wscb, links);
wscb->position = scb->position;
- STAILQ_REMOVE_HEAD(&ahc->waiting_scbs, links);
- STAILQ_INSERT_HEAD(&ahc->assigned_scbs, wscb, links);
+ SIMPLEQ_INSERT_HEAD(&ahc->assigned_scbs, wscb, links);
wscb->flags = SCB_ASSIGNEDQ;
/*
@@ -2402,8 +2475,8 @@ ahc_free_scb(ahc, scb, flags)
* queue.
*/
scb->position = SCB_LIST_NULL;
- STAILQ_INSERT_HEAD(&ahc->page_scbs, scb, links);
- if(!scb->links.stqe_next && !ahc->free_scbs.stqh_first)
+ SIMPLEQ_INSERT_HEAD(&ahc->page_scbs, scb, links);
+ if(!scb->links.sqe_next && !ahc->free_scbs.sqh_first)
/*
* If there were no SCBs availible, wake anybody waiting
* for one to come free.
@@ -2411,11 +2484,11 @@ ahc_free_scb(ahc, scb, flags)
wakeup((caddr_t)&ahc->free_scbs);
}
else {
- STAILQ_INSERT_HEAD(&ahc->free_scbs, scb, links);
+ SIMPLEQ_INSERT_HEAD(&ahc->free_scbs, scb, links);
#ifdef AHC_DEBUG
ahc->activescbs--;
#endif
- if(!scb->links.stqe_next && !ahc->page_scbs.stqh_first)
+ if(!scb->links.sqe_next && !ahc->page_scbs.sqh_first)
/*
* If there were no SCBs availible, wake anybody waiting
* for one to come free.
@@ -2445,11 +2518,11 @@ ahc_get_scb(ahc, flags)
* but only if we can't allocate a new one.
*/
while (1) {
- if((scbp = ahc->free_scbs.stqh_first)) {
- STAILQ_REMOVE_HEAD(&ahc->free_scbs, links);
+ if((scbp = ahc->free_scbs.sqh_first)) {
+ SIMPLEQ_REMOVE_HEAD(&ahc->free_scbs, scbp, links);
}
- else if((scbp = ahc->page_scbs.stqh_first)) {
- STAILQ_REMOVE_HEAD(&ahc->page_scbs, links);
+ else if((scbp = ahc->page_scbs.sqh_first)) {
+ SIMPLEQ_REMOVE_HEAD(&ahc->page_scbs, scbp, links);
}
else if (ahc->numscbs < ahc->maxscbs) {
scbp = (struct scb *) malloc(sizeof(struct scb),
@@ -2469,8 +2542,8 @@ ahc_get_scb(ahc, flags)
ahc->scbarray[scbp->tag] = scbp;
}
else {
- printf(AHCNAME_FMT ": Can't malloc SCB\n",
- AHCNAME_VAR(ahc));
+ printf("%s: Can't malloc SCB\n",
+ ahc_name(ahc));
}
}
else {
@@ -2491,8 +2564,7 @@ ahc_get_scb(ahc, flags)
ahc->activescbs++;
if((ahc_debug & AHC_SHOWSCBCNT)
&& (ahc->activescbs == ahc->maxhscbs))
- printf(AHCNAME_FMT ": Max SCBs active\n",
- AHCNAME_VAR(ahc));
+ printf("%s: Max SCBs active\n", ahc_name(ahc));
#endif
}
@@ -2501,23 +2573,23 @@ ahc_get_scb(ahc, flags)
return (scbp);
}
-static void ahc_loadseq(iobase)
- u_long iobase;
+static void ahc_loadseq(ahc)
+ struct ahc_data *ahc;
{
static unsigned char seqprog[] = {
# include "aic7xxx_seq.h"
};
- outb(SEQCTL + iobase, PERRORDIS|SEQRESET|LOADRAM);
+ AHC_OUTB(ahc, SEQCTL, PERRORDIS|SEQRESET|LOADRAM);
- outsb(SEQRAM + iobase, seqprog, sizeof(seqprog));
+ AHC_OUTSB(ahc, SEQRAM, seqprog, sizeof(seqprog));
- outb(SEQCTL + iobase, FASTMODE|SEQRESET);
+ AHC_OUTB(ahc, SEQCTL, FASTMODE|SEQRESET);
do {
- outb(SEQCTL + iobase, SEQRESET|FASTMODE);
+ AHC_OUTB(ahc, SEQCTL, SEQRESET|FASTMODE);
- } while (inb(SEQADDR0 + iobase) != 0 &&
- inb(SEQADDR1 + iobase) != 0);
+ } while (AHC_INB(ahc, SEQADDR0) != 0 &&
+ AHC_INB(ahc, SEQADDR1) != 0);
}
/*
@@ -2529,16 +2601,12 @@ ahc_poll(ahc, wait)
struct ahc_data *ahc;
int wait; /* in msec */
{
- u_long iobase = ahc->baseport;
- u_long stport = INTSTAT + iobase;
-
while (--wait) {
DELAY(1000);
- if (inb(stport) & INT_PEND)
+ if (AHC_INB(ahc, INTSTAT) & INT_PEND)
break;
} if (wait == 0) {
- printf(AHCNAME_FMT ": board not responding\n",
- AHCNAME_VAR(ahc));
+ printf("%s: board not responding\n", ahc_name(ahc));
return (EIO);
}
ahc_intr((void *)ahc);
@@ -2553,7 +2621,6 @@ ahc_timeout(arg)
struct ahc_data *ahc;
int s, h, found;
u_char bus_state;
- u_long iobase;
char channel;
s = splbio();
@@ -2580,8 +2647,8 @@ ahc_timeout(arg)
* recovery SCB. Cut our losses and panic. Its
* better to do this than trash a filesystem.
*/
- panic(AHCNAME_FMT ": Timed-out command times out "
- "again\n", AHCNAME_VAR(ahc));
+ panic("%s: Timed-out command times out "
+ "again\n", ahc_name(ahc));
}
else if (!(scb->flags & SCB_ABORTED))
{
@@ -2614,8 +2681,7 @@ ahc_timeout(arg)
* Take a snapshot of the bus state and print out
* some information so we can track down driver bugs.
*/
- iobase = ahc->baseport;
- bus_state = inb(iobase + LASTPHASE);
+ bus_state = AHC_INB(ahc, LASTPHASE);
switch(bus_state & PHASE_MASK)
{
@@ -2648,7 +2714,7 @@ ahc_timeout(arg)
break;
}
- printf(", SCSISIGI == 0x%x\n", inb(iobase + SCSISIGI));
+ printf(", SCSISIGI == 0x%x\n", AHC_INB(ahc, SCSISIGI));
/* Decide our course of action */
@@ -2662,8 +2728,8 @@ ahc_timeout(arg)
? 'B': 'A';
found = ahc_reset_channel(ahc, channel, scb->tag,
XS_TIMEOUT, /*Initiate Reset*/TRUE);
- printf(AHCNAME_FMT ": Issued Channel %c Bus Reset #1. "
- "%d SCBs aborted\n", AHCNAME_VAR(ahc), channel, found);
+ printf("%s: Issued Channel %c Bus Reset #1. "
+ "%d SCBs aborted\n", ahc_name(ahc), channel, found);
ahc->in_timeout = FALSE;
}
else if(scb->control & TAG_ENB) {
@@ -2706,33 +2772,33 @@ ahc_timeout(arg)
u_char active_scb;
struct scb *active_scbp;
- active_scb = inb(SCBPTR + iobase);
- active_scbp = ahc->scbarray[inb(SCB_TAG + iobase)];
- outb(SCBPTR + iobase, scb->position);
+ active_scb = AHC_INB(ahc, SCBPTR);
+ active_scbp = ahc->scbarray[AHC_INB(ahc, SCB_TAG)];
+ AHC_OUTB(ahc, SCBPTR, scb->position);
- if(inb(SCB_CONTROL + iobase) & DISCONNECTED) {
+ if(AHC_INB(ahc, SCB_CONTROL) & DISCONNECTED) {
if(ahc->flags & AHC_PAGESCBS) {
/*
* Pull this SCB out of the
* disconnected list.
*/
- u_char prev = inb(SCB_PREV + iobase);
- u_char next = inb(SCB_NEXT + iobase);
+ u_char prev = AHC_INB(ahc, SCB_PREV);
+ u_char next = AHC_INB(ahc, SCB_NEXT);
if(prev == SCB_LIST_NULL) {
/* At the head */
- outb(DISCONNECTED_SCBH + iobase,
+ AHC_OUTB(ahc, DISCONNECTED_SCBH,
next );
}
else {
- outb(SCBPTR + iobase, prev);
- outb(SCB_NEXT + iobase, next);
+ AHC_OUTB(ahc, SCBPTR, prev);
+ AHC_OUTB(ahc, SCB_NEXT, next);
if(next != SCB_LIST_NULL) {
- outb(SCBPTR + iobase,
+ AHC_OUTB(ahc, SCBPTR,
next);
- outb(SCB_PREV + iobase,
+ AHC_OUTB(ahc, SCB_PREV,
prev);
}
- outb(SCBPTR + iobase,
+ AHC_OUTB(ahc, SCBPTR,
scb->position);
}
}
@@ -2744,19 +2810,19 @@ ahc_timeout(arg)
scb->data = 0;
scb->datalen = 0;
ahc_send_scb(ahc, scb);
- ahc_add_waiting_scb(iobase, scb);
+ ahc_add_waiting_scb(ahc, scb);
timeout(ahc_timeout, (caddr_t)scb, (2 * hz));
sc_print_addr(scb->xs->sc_link);
printf("BUS DEVICE RESET message queued.\n");
- outb(SCBPTR + iobase, active_scb);
+ AHC_OUTB(ahc, SCBPTR, active_scb);
UNPAUSE_SEQUENCER(ahc);
goto done;
}
/* Is the active SCB really active? */
else if((active_scbp->flags & SCB_ACTIVE) && bus_state){
- outb(MSG_LEN + iobase, 1);
- outb(MSG0 + iobase, MSG_BUS_DEVICE_RESET);
- outb(SCSISIGO + iobase, bus_state|ATNO);
+ AHC_OUTB(ahc, MSG_LEN, 1);
+ AHC_OUTB(ahc, MSG0, MSG_BUS_DEVICE_RESET);
+ AHC_OUTB(ahc, SCSISIGO, bus_state|ATNO);
sc_print_addr(active_scbp->xs->sc_link);
printf("asserted ATN - device reset in "
"message buffer\n");
@@ -2771,7 +2837,7 @@ ahc_timeout(arg)
}
timeout(ahc_timeout, (caddr_t)active_scbp,
(2 * hz));
- outb(SCBPTR + iobase, active_scb);
+ AHC_OUTB(ahc, SCBPTR, active_scb);
UNPAUSE_SEQUENCER(ahc);
goto done;
}
@@ -2784,8 +2850,8 @@ ahc_timeout(arg)
found = ahc_reset_channel(ahc, channel, scb->tag,
XS_TIMEOUT,
/*Initiate Reset*/TRUE);
- printf(AHCNAME_FMT ": Issued Channel %c Bus Reset #2. "
- "%d SCBs aborted\n", AHCNAME_VAR(ahc), channel,
+ printf("%s: Issued Channel %c Bus Reset #2. "
+ "%d SCBs aborted\n", ahc_name(ahc), channel,
found);
ahc->in_timeout = FALSE;
}
@@ -2806,26 +2872,25 @@ ahc_reset_device(ahc, target, channel, timedout_scb, xs_error)
u_char timedout_scb;
u_int32_t xs_error;
{
- u_long iobase = ahc->baseport;
struct scb *scbp;
u_char active_scb;
int i = 0;
int found = 0;
/* restore this when we're done */
- active_scb = inb(SCBPTR + iobase);
+ active_scb = AHC_INB(ahc, SCBPTR);
/*
* Search the QINFIFO.
*/
{
int saved_queue[AHC_SCB_MAX];
- int queued = inb(QINCNT + iobase) & ahc->qcntmask;
+ int queued = AHC_INB(ahc, QINCNT) & ahc->qcntmask;
for (i = 0; i < (queued - found); i++) {
- saved_queue[i] = inb(QINFIFO + iobase);
- outb(SCBPTR + iobase, saved_queue[i]);
- scbp = ahc->scbarray[inb(SCB_TAG + iobase)];
+ saved_queue[i] = AHC_INB(ahc, QINFIFO);
+ AHC_OUTB(ahc, SCBPTR, saved_queue[i]);
+ scbp = ahc->scbarray[AHC_INB(ahc, SCB_TAG)];
if (ahc_match_scb (scbp, target, channel)){
/*
* We found an scb that needs to be aborted.
@@ -2834,14 +2899,14 @@ ahc_reset_device(ahc, target, channel, timedout_scb, xs_error)
scbp->xs->error |= xs_error;
if(scbp->position != timedout_scb)
untimeout(ahc_timeout, (caddr_t)scbp);
- outb(SCB_CONTROL + iobase, 0);
+ AHC_OUTB(ahc, SCB_CONTROL, 0);
i--;
found++;
}
}
/* Now put the saved scbs back. */
for (queued = 0; queued < i; queued++) {
- outb (QINFIFO + iobase, saved_queue[queued]);
+ AHC_OUTB(ahc, QINFIFO, saved_queue[queued]);
}
}
@@ -2851,23 +2916,23 @@ ahc_reset_device(ahc, target, channel, timedout_scb, xs_error)
{
u_char next, prev;
- next = inb(WAITING_SCBH + iobase); /* Start at head of list. */
+ next = AHC_INB(ahc, WAITING_SCBH); /* Start at head of list. */
prev = SCB_LIST_NULL;
while (next != SCB_LIST_NULL) {
- outb(SCBPTR + iobase, next);
- scbp = ahc->scbarray[inb(SCB_TAG + iobase)];
+ AHC_OUTB(ahc, SCBPTR, next);
+ scbp = ahc->scbarray[AHC_INB(ahc, SCB_TAG)];
/*
* Select the SCB.
*/
if (ahc_match_scb(scbp, target, channel)) {
next = ahc_abort_wscb(ahc, scbp, prev,
- iobase, timedout_scb, xs_error);
+ timedout_scb, xs_error);
found++;
}
else {
prev = next;
- next = inb(SCB_NEXT + iobase);
+ next = AHC_INB(ahc, SCB_NEXT);
}
}
}
@@ -2882,11 +2947,11 @@ ahc_reset_device(ahc, target, channel, timedout_scb, xs_error)
if((scbp->flags & SCB_ACTIVE)
&& ahc_match_scb(scbp, target, channel)) {
/* Ensure the target is "free" */
- ahc_unbusy_target(target, channel, iobase);
+ ahc_unbusy_target(ahc, target, channel);
if( !(scbp->flags & SCB_PAGED_OUT) )
{
- outb(SCBPTR + iobase, scbp->position);
- outb(SCB_CONTROL + iobase, 0);
+ AHC_OUTB(ahc, SCBPTR, scbp->position);
+ AHC_OUTB(ahc, SCB_CONTROL, 0);
}
scbp->flags = SCB_ABORTED|SCB_QUEUED_FOR_DONE;
scbp->xs->error |= xs_error;
@@ -2895,7 +2960,7 @@ ahc_reset_device(ahc, target, channel, timedout_scb, xs_error)
found++;
}
}
- outb(SCBPTR + iobase, active_scb);
+ AHC_OUTB(ahc, SCBPTR, active_scb);
return found;
}
@@ -2904,11 +2969,10 @@ ahc_reset_device(ahc, target, channel, timedout_scb, xs_error)
* scb that follows the one that we remove.
*/
static u_char
-ahc_abort_wscb (ahc, scbp, prev, iobase, timedout_scb, xs_error)
+ahc_abort_wscb (ahc, scbp, prev, timedout_scb, xs_error)
struct ahc_data *ahc;
struct scb *scbp;
u_char prev;
- u_long iobase;
u_char timedout_scb;
u_int32_t xs_error;
{
@@ -2919,33 +2983,33 @@ ahc_abort_wscb (ahc, scbp, prev, iobase, timedout_scb, xs_error)
* Select the SCB we want to abort and
* pull the next pointer out of it.
*/
- curscbp = inb(SCBPTR + iobase);
- outb(SCBPTR + iobase, scbp->position);
- next = inb(SCB_NEXT + iobase);
+ curscbp = AHC_INB(ahc, SCBPTR);
+ AHC_OUTB(ahc, SCBPTR, scbp->position);
+ next = AHC_INB(ahc, SCB_NEXT);
/* Clear the necessary fields */
- outb(SCB_CONTROL + iobase, 0);
- outb(SCB_NEXT + iobase, SCB_LIST_NULL);
- ahc_unbusy_target(target, channel, iobase);
+ AHC_OUTB(ahc, SCB_CONTROL, 0);
+ AHC_OUTB(ahc, SCB_NEXT, SCB_LIST_NULL);
+ ahc_unbusy_target(ahc, target, channel);
/* update the waiting list */
if( prev == SCB_LIST_NULL )
/* First in the list */
- outb(WAITING_SCBH + iobase, next);
+ AHC_OUTB(ahc, WAITING_SCBH, next);
else {
/*
* Select the scb that pointed to us
* and update its next pointer.
*/
- outb(SCBPTR + iobase, prev);
- outb(SCB_NEXT + iobase, next);
+ AHC_OUTB(ahc, SCBPTR, prev);
+ AHC_OUTB(ahc, SCB_NEXT, next);
}
/*
* Point us back at the original scb position
* and inform the SCSI system that the command
* has been aborted.
*/
- outb(SCBPTR + iobase, curscbp);
+ AHC_OUTB(ahc, SCBPTR, curscbp);
scbp->flags = SCB_ABORTED|SCB_QUEUED_FOR_DONE;
scbp->xs->error |= xs_error;
if(scbp->tag != timedout_scb)
@@ -2954,13 +3018,14 @@ ahc_abort_wscb (ahc, scbp, prev, iobase, timedout_scb, xs_error)
}
static void
-ahc_busy_target(target, channel, iobase)
+ahc_busy_target(ahc, target, channel)
+ struct ahc_data *ahc;
u_char target;
char channel;
- u_long iobase;
{
u_char active;
- u_long active_port = ACTIVE_A + iobase;
+ u_long active_port = ACTIVE_A;
+
if(target > 0x07 || channel == 'B') {
/*
* targets on the Second channel or
@@ -2969,19 +3034,20 @@ ahc_busy_target(target, channel, iobase)
*/
active_port++;
}
- active = inb(active_port);
+ active = AHC_INB(ahc, active_port);
active |= (0x01 << (target & 0x07));
- outb(active_port, active);
+ AHC_OUTB(ahc, active_port, active);
}
static void
-ahc_unbusy_target(target, channel, iobase)
+ahc_unbusy_target(ahc, target, channel)
+ struct ahc_data *ahc;
u_char target;
char channel;
- u_long iobase;
{
u_char active;
- u_long active_port = ACTIVE_A + iobase;
+ u_long active_port = ACTIVE_A;
+
if(target > 0x07 || channel == 'B') {
/*
* targets on the Second channel or
@@ -2990,18 +3056,18 @@ ahc_unbusy_target(target, channel, iobase)
*/
active_port++;
}
- active = inb(active_port);
+ active = AHC_INB(ahc, active_port);
active &= ~(0x01 << (target & 0x07));
- outb(active_port, active);
+ AHC_OUTB(ahc, active_port, active);
}
static void
-ahc_reset_current_bus(iobase)
- u_long iobase;
+ahc_reset_current_bus(ahc)
+ struct ahc_data *ahc;
{
- outb(SCSISEQ + iobase, SCSIRSTO);
+ AHC_OUTB(ahc, SCSISEQ, SCSIRSTO);
DELAY(1000);
- outb(SCSISEQ + iobase, 0);
+ AHC_OUTB(ahc, SCSISEQ, 0);
}
static int
@@ -3012,7 +3078,6 @@ ahc_reset_channel(ahc, channel, timedout_scb, xs_error, initiate_reset)
u_int32_t xs_error;
u_char initiate_reset;
{
- u_long iobase = ahc->baseport;
u_char sblkctl;
char cur_channel;
u_long offset, offset_max;
@@ -3027,26 +3092,26 @@ ahc_reset_channel(ahc, channel, timedout_scb, xs_error, initiate_reset)
if(channel == 'B'){
ahc->needsdtr |= (ahc->needsdtr_orig & 0xff00);
ahc->sdtrpending &= 0x00ff;
- outb(ACTIVE_B + iobase, 0);
- offset = TARG_SCRATCH + iobase + 8;
- offset_max = TARG_SCRATCH + iobase + 16;
+ AHC_OUTB(ahc, ACTIVE_B, 0);
+ offset = TARG_SCRATCH + 8;
+ offset_max = TARG_SCRATCH + 16;
}
else if (ahc->type & AHC_WIDE){
ahc->needsdtr = ahc->needsdtr_orig;
ahc->needwdtr = ahc->needwdtr_orig;
ahc->sdtrpending = 0;
ahc->wdtrpending = 0;
- outb(ACTIVE_A + iobase, 0);
- outb(ACTIVE_B + iobase, 0);
- offset = TARG_SCRATCH + iobase;
- offset_max = TARG_SCRATCH + iobase + 16;
+ AHC_OUTB(ahc, ACTIVE_A, 0);
+ AHC_OUTB(ahc, ACTIVE_B, 0);
+ offset = TARG_SCRATCH;
+ offset_max = TARG_SCRATCH + 16;
}
else{
ahc->needsdtr |= (ahc->needsdtr_orig & 0x00ff);
ahc->sdtrpending &= 0xff00;
- outb(ACTIVE_A + iobase, 0);
- offset = TARG_SCRATCH + iobase;
- offset_max = TARG_SCRATCH + iobase + 8;
+ AHC_OUTB(ahc, ACTIVE_A, 0);
+ offset = TARG_SCRATCH;
+ offset_max = TARG_SCRATCH + 8;
}
for(;offset < offset_max;offset++) {
/*
@@ -3054,9 +3119,10 @@ ahc_reset_channel(ahc, channel, timedout_scb, xs_error, initiate_reset)
* until we renegotiate.
*/
u_char targ_scratch;
- targ_scratch = inb(offset);
+
+ targ_scratch = AHC_INB(ahc, offset);
targ_scratch &= SXFR;
- outb(offset, targ_scratch);
+ AHC_OUTB(ahc, offset, targ_scratch);
}
/*
@@ -3064,7 +3130,7 @@ ahc_reset_channel(ahc, channel, timedout_scb, xs_error, initiate_reset)
* restart/unpause the sequencer
*/
/* Case 1: Command for another bus is active */
- sblkctl = inb(SBLKCTL + iobase);
+ sblkctl = AHC_INB(ahc, SBLKCTL);
cur_channel = (sblkctl & SELBUSB) ? 'B' : 'A';
if(cur_channel != channel)
{
@@ -3072,24 +3138,24 @@ ahc_reset_channel(ahc, channel, timedout_scb, xs_error, initiate_reset)
* Stealthily reset the other bus
* without upsetting the current bus
*/
- outb(SBLKCTL + iobase, sblkctl ^ SELBUSB);
+ AHC_OUTB(ahc, SBLKCTL, sblkctl ^ SELBUSB);
if( initiate_reset )
{
- ahc_reset_current_bus(iobase);
+ ahc_reset_current_bus(ahc);
}
- outb(CLRSINT1 + iobase, CLRSCSIRSTI|CLRSELTIMEO);
- outb(CLRINT + iobase, CLRSCSIINT);
- outb(SBLKCTL + iobase, sblkctl);
+ AHC_OUTB(ahc, CLRSINT1, CLRSCSIRSTI|CLRSELTIMEO);
+ AHC_OUTB(ahc, CLRINT, CLRSCSIINT);
+ AHC_OUTB(ahc, SBLKCTL, sblkctl);
UNPAUSE_SEQUENCER(ahc);
}
/* Case 2: A command from this bus is active or we're idle */
else {
if( initiate_reset )
{
- ahc_reset_current_bus(iobase);
+ ahc_reset_current_bus(ahc);
}
- outb(CLRSINT1 + iobase, CLRSCSIRSTI|CLRSELTIMEO);
- outb(CLRINT + iobase, CLRSCSIINT);
+ AHC_OUTB(ahc, CLRSINT1, CLRSCSIRSTI|CLRSELTIMEO);
+ AHC_OUTB(ahc, CLRINT, CLRSCSIINT);
RESTART_SEQUENCER(ahc);
}
ahc_run_done_queue(ahc);
diff --git a/sys/dev/ic/aic7xxxreg.h b/sys/dev/ic/aic7xxxreg.h
new file mode 100644
index 00000000000..240d1f57a93
--- /dev/null
+++ b/sys/dev/ic/aic7xxxreg.h
@@ -0,0 +1,776 @@
+/* $NetBSD: aic7xxxreg.h,v 1.2 1996/05/20 00:58:10 thorpej Exp $ */
+
+/*
+ * Aic7xxx register and scratch ram definitions.
+ *
+ * Copyright (c) 1994, 1995, 1996 Justin T. Gibbs.
+ * 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 immediately at the beginning of the file, without modification,
+ * 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. 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 header is shared by the sequencer code and the kernel level driver.
+ *
+ * All page numbers refer to the Adaptec AIC-7770 Data Book availible from
+ * Adaptec's Technical Documents Department 1-800-934-2766
+ */
+
+/*
+ * SCSI Sequence Control (p. 3-11).
+ * Each bit, when set starts a specific SCSI sequence on the bus
+ */
+#define SCSISEQ 0x000
+#define TEMODEO 0x80
+#define ENSELO 0x40
+#define ENSELI 0x20
+#define ENRSELI 0x10
+#define ENAUTOATNO 0x08
+#define ENAUTOATNI 0x04
+#define ENAUTOATNP 0x02
+#define SCSIRSTO 0x01
+
+/*
+ * SCSI Transfer Control 0 Register (pp. 3-13).
+ * Controls the SCSI module data path.
+ */
+#define SXFRCTL0 0x001
+#define DFON 0x80
+#define DFPEXP 0x40
+#define ULTRAEN 0x20
+#define CLRSTCNT 0x10
+#define SPIOEN 0x08
+#define SCAMEN 0x04
+#define CLRCHN 0x02
+/* UNUSED 0x01 */
+
+/*
+ * SCSI Transfer Control 1 Register (pp. 3-14,15).
+ * Controls the SCSI module data path.
+ */
+#define SXFRCTL1 0x002
+#define BITBUCKET 0x80
+#define SWRAPEN 0x40
+#define ENSPCHK 0x20
+#define STIMESEL 0x18
+#define ENSTIMER 0x04
+#define ACTNEGEN 0x02
+#define STPWEN 0x01 /* Powered Termination */
+
+/*
+ * SCSI Control Signal Read Register (p. 3-15).
+ * Reads the actual state of the SCSI bus pins
+ */
+#define SCSISIGI 0x003
+#define CDI 0x80
+#define IOI 0x40
+#define MSGI 0x20
+#define ATNI 0x10
+#define SELI 0x08
+#define BSYI 0x04
+#define REQI 0x02
+#define ACKI 0x01
+
+/*
+ * Possible phases in SCSISIGI
+ */
+#define PHASE_MASK 0xe0
+#define P_DATAOUT 0x00
+#define P_DATAIN 0x40
+#define P_COMMAND 0x80
+#define P_MESGOUT 0xa0
+#define P_STATUS 0xc0
+#define P_MESGIN 0xe0
+/*
+ * SCSI Contol Signal Write Register (p. 3-16).
+ * Writing to this register modifies the control signals on the bus. Only
+ * those signals that are allowed in the current mode (Initiator/Target) are
+ * asserted.
+ */
+#define SCSISIGO 0x003
+#define CDO 0x80
+#define IOO 0x40
+#define MSGO 0x20
+#define ATNO 0x10
+#define SELO 0x08
+#define BSYO 0x04
+#define REQO 0x02
+#define ACKO 0x01
+
+/*
+ * SCSI Rate Control (p. 3-17).
+ * Contents of this register determine the Synchronous SCSI data transfer
+ * rate and the maximum synchronous Req/Ack offset. An offset of 0 in the
+ * SOFS (3:0) bits disables synchronous data transfers. Any offset value
+ * greater than 0 enables synchronous transfers.
+ */
+#define SCSIRATE 0x004
+#define WIDEXFER 0x80 /* Wide transfer control */
+#define SXFR 0x70 /* Sync transfer rate */
+#define SOFS 0x0f /* Sync offset */
+
+/*
+ * SCSI ID (p. 3-18).
+ * Contains the ID of the board and the current target on the
+ * selected channel.
+ */
+#define SCSIID 0x005
+#define TID 0xf0 /* Target ID mask */
+#define OID 0x0f /* Our ID mask */
+
+/*
+ * SCSI Latched Data (p. 3-19).
+ * Read/Write latchs used to transfer data on the SCSI bus during
+ * Automatic or Manual PIO mode. SCSIDATH can be used for the
+ * upper byte of a 16bit wide asyncronouse data phase transfer.
+ */
+#define SCSIDATL 0x006
+#define SCSIDATH 0x007
+
+/*
+ * SCSI Transfer Count (pp. 3-19,20)
+ * These registers count down the number of bytes transfered
+ * across the SCSI bus. The counter is decremented only once
+ * the data has been safely transfered. SDONE in SSTAT0 is
+ * set when STCNT goes to 0
+ */
+#define STCNT 0x008
+#define STCNT0 0x008
+#define STCNT1 0x009
+#define STCNT2 0x00a
+
+/*
+ * Clear SCSI Interrupt 0 (p. 3-20)
+ * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT0.
+ */
+#define CLRSINT0 0x00b
+#define CLRSELDO 0x40
+#define CLRSELDI 0x20
+#define CLRSELINGO 0x10
+#define CLRSWRAP 0x08
+/* UNUSED 0x04 */
+#define CLRSPIORDY 0x02
+/* UNUSED 0x01 */
+
+/*
+ * SCSI Status 0 (p. 3-21)
+ * Contains one set of SCSI Interrupt codes
+ * These are most likely of interest to the sequencer
+ */
+#define SSTAT0 0x00b
+#define TARGET 0x80 /* Board acting as target */
+#define SELDO 0x40 /* Selection Done */
+#define SELDI 0x20 /* Board has been selected */
+#define SELINGO 0x10 /* Selection In Progress */
+#define SWRAP 0x08 /* 24bit counter wrap */
+#define SDONE 0x04 /* STCNT = 0x000000 */
+#define SPIORDY 0x02 /* SCSI PIO Ready */
+#define DMADONE 0x01 /* DMA transfer completed */
+
+/*
+ * Clear SCSI Interrupt 1 (p. 3-23)
+ * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT1.
+ */
+#define CLRSINT1 0x00c
+#define CLRSELTIMEO 0x80
+#define CLRATNO 0x40
+#define CLRSCSIRSTI 0x20
+/* UNUSED 0x10 */
+#define CLRBUSFREE 0x08
+#define CLRSCSIPERR 0x04
+#define CLRPHASECHG 0x02
+#define CLRREQINIT 0x01
+
+/*
+ * SCSI Status 1 (p. 3-24)
+ */
+#define SSTAT1 0x00c
+#define SELTO 0x80
+#define ATNTARG 0x40
+#define SCSIRSTI 0x20
+#define PHASEMIS 0x10
+#define BUSFREE 0x08
+#define SCSIPERR 0x04
+#define PHASECHG 0x02
+#define REQINIT 0x01
+
+/*
+ * SCSI Interrupt Mode 1 (pp. 3-28,29)
+ * Setting any bit will enable the corresponding function
+ * in SIMODE1 to interrupt via the IRQ pin.
+ */
+#define SIMODE1 0x011
+#define ENSELTIMO 0x80
+#define ENATNTARG 0x40
+#define ENSCSIRST 0x20
+#define ENPHASEMIS 0x10
+#define ENBUSFREE 0x08
+#define ENSCSIPERR 0x04
+#define ENPHASECHG 0x02
+#define ENREQINIT 0x01
+
+/*
+ * SCSI Data Bus (High) (p. 3-29)
+ * This register reads data on the SCSI Data bus directly.
+ */
+#define SCSIBUSL 0x012
+#define SCSIBUSH 0x013
+
+/*
+ * SCSI/Host Address (p. 3-30)
+ * These registers hold the host address for the byte about to be
+ * transfered on the SCSI bus. They are counted up in the same
+ * manner as STCNT is counted down. SHADDR should always be used
+ * to determine the address of the last byte transfered since HADDR
+ * can be squewed by write ahead.
+ */
+#define SHADDR 0x014
+#define SHADDR0 0x014
+#define SHADDR1 0x015
+#define SHADDR2 0x016
+#define SHADDR3 0x017
+
+/*
+ * Selection/Reselection ID (p. 3-31)
+ * Upper four bits are the device id. The ONEBIT is set when the re/selecting
+ * device did not set its own ID.
+ */
+#define SELID 0x019
+#define SELID_MASK 0xf0
+#define ONEBIT 0x08
+/* UNUSED 0x07 */
+
+/*
+ * SCSI Block Control (p. 3-32)
+ * Controls Bus type and channel selection. In a twin channel configuration
+ * addresses 0x00-0x1e are gated to the appropriate channel based on this
+ * register. SELWIDE allows for the coexistence of 8bit and 16bit devices
+ * on a wide bus.
+ */
+#define SBLKCTL 0x01f
+#define DIAGLEDEN 0x80 /* Aic78X0 only */
+#define DIAGLEDON 0x40 /* Aic78X0 only */
+#define AUTOFLUSHDIS 0x20
+/* UNUSED 0x10 */
+#define SELBUS_MASK 0x0a
+#define SELBUSB 0x08
+/* UNUSED 0x04 */
+#define SELWIDE 0x02
+/* UNUSED 0x01 */
+#define SELNARROW 0x00
+
+/*
+ * Sequencer Control (p. 3-33)
+ * Error detection mode and speed configuration
+ */
+#define SEQCTL 0x060
+#define PERRORDIS 0x80
+#define PAUSEDIS 0x40
+#define FAILDIS 0x20
+#define FASTMODE 0x10
+#define BRKADRINTEN 0x08
+#define STEP 0x04
+#define SEQRESET 0x02
+#define LOADRAM 0x01
+
+/*
+ * Sequencer RAM Data (p. 3-34)
+ * Single byte window into the Scratch Ram area starting at the address
+ * specified by SEQADDR0 and SEQADDR1. To write a full word, simply write
+ * four bytes in sucessesion. The SEQADDRs will increment after the most
+ * significant byte is written
+ */
+#define SEQRAM 0x061
+
+/*
+ * Sequencer Address Registers (p. 3-35)
+ * Only the first bit of SEQADDR1 holds addressing information
+ */
+#define SEQADDR0 0x062
+#define SEQADDR1 0x063
+#define SEQADDR1_MASK 0x01
+
+/*
+ * Accumulator
+ * We cheat by passing arguments in the Accumulator up to the kernel driver
+ */
+#define ACCUM 0x064
+
+#define SINDEX 0x065
+#define DINDEX 0x066
+#define ALLZEROS 0x06a
+#define NONE 0x06a
+#define SINDIR 0x06c
+#define DINDIR 0x06d
+#define FUNCTION1 0x06e
+
+/*
+ * Host Address (p. 3-48)
+ * This register contains the address of the byte about
+ * to be transfered across the host bus.
+ */
+#define HADDR 0x088
+#define HADDR0 0x088
+#define HADDR1 0x089
+#define HADDR2 0x08a
+#define HADDR3 0x08b
+
+#define HCNT 0x08c
+#define HCNT0 0x08c
+#define HCNT1 0x08d
+#define HCNT2 0x08e
+/*
+ * SCB Pointer (p. 3-49)
+ * Gate one of the four SCBs into the SCBARRAY window.
+ */
+#define SCBPTR 0x090
+
+/*
+ * Board Control (p. 3-43)
+ */
+#define BCTL 0x084
+/* RSVD 0xf0 */
+#define ACE 0x08 /* Support for external processors */
+/* RSVD 0x06 */
+#define ENABLE 0x01
+
+/*
+ * On the aic78X0 chips, Board Control is replaced by the DSCommand
+ * register (p. 4-64)
+ */
+#define DSCOMMAND 0x084
+#define CACHETHEN 0x80 /* Cache Threshold enable */
+#define DPARCKEN 0x40 /* Data Parity Check Enable */
+#define MPARCKEN 0x20 /* Memory Parity Check Enable */
+#define EXTREQLCK 0x10 /* External Request Lock */
+
+/*
+ * Bus On/Off Time (p. 3-44)
+ */
+#define BUSTIME 0x085
+#define BOFF 0xf0
+#define BON 0x0f
+
+/*
+ * Bus Speed (p. 3-45)
+ */
+#define BUSSPD 0x086
+#define DFTHRSH 0xc0
+#define STBOFF 0x38
+#define STBON 0x07
+#define DFTHRSH_100 0xc0
+
+/*
+ * Host Control (p. 3-47) R/W
+ * Overal host control of the device.
+ */
+#define HCNTRL 0x087
+/* UNUSED 0x80 */
+#define POWRDN 0x40
+/* UNUSED 0x20 */
+#define SWINT 0x10
+#define IRQMS 0x08
+#define PAUSE 0x04
+#define INTEN 0x02
+#define CHIPRST 0x01
+#define CHIPRSTACK 0x01
+
+/*
+ * Interrupt Status (p. 3-50)
+ * Status for system interrupts
+ */
+#define INTSTAT 0x091
+#define SEQINT_MASK 0xf1 /* SEQINT Status Codes */
+#define BAD_PHASE 0x01 /* unknown scsi bus phase */
+#define SEND_REJECT 0x11 /* sending a message reject */
+#define NO_IDENT 0x21 /* no IDENTIFY after reconnect*/
+#define NO_MATCH 0x31 /* no cmd match for reconnect */
+#define SDTR_MSG 0x41 /* SDTR message received */
+#define WDTR_MSG 0x51 /* WDTR message received */
+#define REJECT_MSG 0x61 /* Reject message received */
+#define BAD_STATUS 0x71 /* Bad status from target */
+#define RESIDUAL 0x81 /* Residual byte count != 0 */
+#define ABORT_TAG 0x91 /* Sent an ABORT_TAG message */
+#define AWAITING_MSG 0xa1 /*
+ * Kernel requested to specify
+ * a message to this target
+ * (command was null), so tell
+ * it that it can fill the
+ * message buffer.
+ */
+#define IMMEDDONE 0xb1 /*
+ * An immediate command has
+ * completed
+ */
+#define MSG_BUFFER_BUSY 0xc1 /*
+ * Sequencer wants to use the
+ * message buffer, but it
+ * already contains a message
+ */
+#define MSGIN_PHASEMIS 0xd1 /*
+ * Target changed phase on us
+ * when we were expecting
+ * another msgin byte.
+ */
+#define BRKADRINT 0x08
+#define SCSIINT 0x04
+#define CMDCMPLT 0x02
+#define SEQINT 0x01
+#define INT_PEND (BRKADRINT | SEQINT | SCSIINT | CMDCMPLT)
+
+/*
+ * Hard Error (p. 3-53)
+ * Reporting of catastrophic errors. You usually cannot recover from
+ * these without a full board reset.
+ */
+#define ERROR 0x092
+/* UNUSED 0xf0 */
+#define PARERR 0x08
+#define ILLOPCODE 0x04
+#define ILLSADDR 0x02
+#define ILLHADDR 0x01
+
+/*
+ * Clear Interrupt Status (p. 3-52)
+ */
+#define CLRINT 0x092
+#define CLRBRKADRINT 0x08
+#define CLRSCSIINT 0x04
+#define CLRCMDINT 0x02
+#define CLRSEQINT 0x01
+
+#define DFCNTRL 0x093
+#define WIDEODD 0x40
+#define SCSIEN 0x20
+#define SDMAEN 0x10
+#define SDMAENACK 0x10
+#define HDMAEN 0x08
+#define HDMAENACK 0x08
+#define DIRECTION 0x04
+#define FIFOFLUSH 0x02
+#define FIFORESET 0x01
+
+#define DFSTATUS 0x094
+#define HDONE 0x08
+#define FIFOEMP 0x01
+
+#define DFDAT 0x099
+
+/*
+ * SCB Auto Increment (p. 3-59)
+ * Byte offset into the SCB Array and an optional bit to allow auto
+ * incrementing of the address during download and upload operations
+ */
+#define SCBCNT 0x09a
+#define SCBAUTO 0x80
+#define SCBCNT_MASK 0x1f
+
+/*
+ * Queue In FIFO (p. 3-60)
+ * Input queue for queued SCBs (commands that the seqencer has yet to start)
+ */
+#define QINFIFO 0x09b
+
+/*
+ * Queue In Count (p. 3-60)
+ * Number of queued SCBs
+ */
+#define QINCNT 0x09c
+
+/*
+ * Queue Out FIFO (p. 3-61)
+ * Queue of SCBs that have completed and await the host
+ */
+#define QOUTFIFO 0x09d
+
+/*
+ * Queue Out Count (p. 3-61)
+ * Number of queued SCBs in the Out FIFO
+ */
+#define QOUTCNT 0x09e
+
+/*
+ * SCB Definition (p. 5-4)
+ * The two reserved bytes at SCBARRAY+1[23] are expected to be set to
+ * zero. Bit 3 in SCBARRAY+0 is used as an internal flag to indicate
+ * whether or not to DMA an SCB from host ram. This flag prevents the
+ * "re-fetching" of transactions that are requed because the target is
+ * busy with another command. We also use bits 6 & 7 to indicate whether
+ * or not to initiate SDTR or WDTR repectively when starting this command.
+ */
+#define SCBARRAY 0x0a0
+#define SCB_CONTROL 0x0a0
+#define NEEDWDTR 0x80
+#define DISCENB 0x40
+#define TAG_ENB 0x20
+#define NEEDSDTR 0x10
+#define DISCONNECTED 0x04
+#define SCB_TAG_TYPE 0x03
+#define SCB_TCL 0x0a1
+#define SCB_TARGET_STATUS 0x0a2
+#define SCB_SGCOUNT 0x0a3
+#define SCB_SGPTR 0x0a4
+#define SCB_SGPTR0 0x0a4
+#define SCB_SGPTR1 0x0a5
+#define SCB_SGPTR2 0x0a6
+#define SCB_SGPTR3 0x0a7
+#define SCB_RESID_SGCNT 0x0a8
+#define SCB_RESID_DCNT 0x0a9
+#define SCB_RESID_DCNT0 0x0a9
+#define SCB_RESID_DCNT1 0x0aa
+#define SCB_RESID_DCNT2 0x0ab
+#define SCB_DATAPTR 0x0ac
+#define SCB_DATAPTR0 0x0ac
+#define SCB_DATAPTR1 0x0ad
+#define SCB_DATAPTR2 0x0ae
+#define SCB_DATAPTR3 0x0af
+#define SCB_DATACNT 0x0b0
+#define SCB_DATACNT0 0x0b0
+#define SCB_DATACNT1 0x0b1
+#define SCB_DATACNT2 0x0b2
+/* UNUSED - QUAD PADDING 0x0b3 */
+#define SCB_CMDPTR 0x0b4
+#define SCB_CMDPTR0 0x0b4
+#define SCB_CMDPTR1 0x0b5
+#define SCB_CMDPTR2 0x0b6
+#define SCB_CMDPTR3 0x0b7
+#define SCB_CMDLEN 0x0b8
+#define SCB_TAG 0x0b9
+#define SCB_NEXT 0x0ba
+#define SCB_PREV 0x0bb
+
+#ifdef __linux__
+#define SG_SIZEOF 0x0c /* sizeof(struct scatterlist) */
+#else
+#define SG_SIZEOF 0x08 /* sizeof(struct ahc_dma) */
+#endif
+
+/* --------------------- AHA-2840-only definitions -------------------- */
+
+#define SEECTL_2840 0x0c0
+/* UNUSED 0xf8 */
+#define CS_2840 0x04
+#define CK_2840 0x02
+#define DO_2840 0x01
+
+#define STATUS_2840 0x0c1
+#define EEPROM_TF 0x80
+#define BIOS_SEL 0x60
+#define ADSEL 0x1e
+#define DI_2840 0x01
+
+/* --------------------- AIC-7870-only definitions -------------------- */
+
+#define DSPCISTATUS 0x086
+
+/*
+ * Serial EEPROM Control (p. 4-92 in 7870 Databook)
+ * Controls the reading and writing of an external serial 1-bit
+ * EEPROM Device. In order to access the serial EEPROM, you must
+ * first set the SEEMS bit that generates a request to the memory
+ * port for access to the serial EEPROM device. When the memory
+ * port is not busy servicing another request, it reconfigures
+ * to allow access to the serial EEPROM. When this happens, SEERDY
+ * gets set high to verify that the memory port access has been
+ * granted.
+ *
+ * After successful arbitration for the memory port, the SEECS bit of
+ * the SEECTL register is connected to the chip select. The SEECK,
+ * SEEDO, and SEEDI are connected to the clock, data out, and data in
+ * lines respectively. The SEERDY bit of SEECTL is useful in that it
+ * gives us an 800 nsec timer. After a write to the SEECTL register,
+ * the SEERDY goes high 800 nsec later. The one exception to this is
+ * when we first request access to the memory port. The SEERDY goes
+ * high to signify that access has been granted and, for this case, has
+ * no implied timing.
+ *
+ * See 93cx6.c for detailed information on the protocol necessary to
+ * read the serial EEPROM.
+ */
+#define SEECTL 0x01e
+#define EXTARBACK 0x80
+#define EXTARBREQ 0x40
+#define SEEMS 0x20
+#define SEERDY 0x10
+#define SEECS 0x08
+#define SEECK 0x04
+#define SEEDO 0x02
+#define SEEDI 0x01
+
+/* ---------------------- Scratch RAM Offsets ------------------------- */
+/* These offsets are either to values that are initialized by the board's
+ * BIOS or are specified by the sequencer code.
+ *
+ * The host adapter card (at least the BIOS) uses 20-2f for SCSI
+ * device information, 32-33 and 5a-5f as well. As it turns out, the
+ * BIOS trashes 20-2f, writing the synchronous negotiation results
+ * on top of the BIOS values, so we re-use those for our per-target
+ * scratchspace (actually a value that can be copied directly into
+ * SCSIRATE). The kernel driver will enable synchronous negotiation
+ * for all targets that have a value other than 0 in the lower four
+ * bits of the target scratch space. This should work regardless of
+ * whether the bios has been installed.
+ */
+
+/*
+ * 1 byte per target starting at this address for configuration values
+ */
+#define TARG_SCRATCH 0x020
+
+/*
+ * The sequencer will stick the frist byte of any rejected message here so
+ * we can see what is getting thrown away. Extended messages put the
+ * extended message type in REJBYTE_EXT.
+ */
+#define REJBYTE 0x030
+#define REJBYTE_EXT 0x031
+
+/*
+ * Bit vector of targets that have disconnection disabled.
+ */
+#define DISC_DSB 0x032
+#define DISC_DSB_A 0x032
+#define DISC_DSB_B 0x033
+
+/*
+ * Length of pending message
+ */
+#define MSG_LEN 0x034
+
+/* We reserve 8bytes to store outgoing messages */
+#define MSG0 0x035
+#define COMP_MSG0 0xcb /* 2's complement of MSG0 */
+#define MSG1 0x036
+#define MSG2 0x037
+#define MSG3 0x038
+#define MSG4 0x039
+#define MSG5 0x03a
+#define MSG6 0x03b
+#define MSG7 0x03c
+
+/*
+ * These are offsets into the card's scratch ram. Some of the values are
+ * specified in the AHA2742 technical reference manual and are initialized
+ * by the BIOS at boot time.
+ */
+#define LASTPHASE 0x03d
+#define ARG_1 0x03e
+#define MAXOFFSET 0x01
+#define RETURN_1 0x03f
+#define SEND_WDTR 0x80
+#define SEND_SDTR 0x60
+#define SEND_SENSE 0x40
+#define SEND_REJ 0x20
+#define SCB_PAGEDIN 0x10
+
+#define SIGSTATE 0x040
+
+#define DMAPARAMS 0x041 /* Parameters for DMA Logic */
+
+#define SG_COUNT 0x042
+#define SG_NEXT 0x043 /* working value of SG pointer */
+#define SG_NEXT0 0x043
+#define SG_NEXT1 0x044
+#define SG_NEXT2 0x045
+#define SG_NEXT3 0x046
+
+#define SCBCOUNT 0x047 /*
+ * Number of SCBs supported by
+ * this card.
+ */
+#define COMP_SCBCOUNT 0x048 /*
+ * Two's compliment of SCBCOUNT
+ */
+#define QCNTMASK 0x049 /*
+ * Mask of bits to test against
+ * when looking at the Queue Count
+ * registers. Works around a bug
+ * on aic7850 chips.
+ */
+#define FLAGS 0x04a
+#define SINGLE_BUS 0x00
+#define TWIN_BUS 0x01
+#define WIDE_BUS 0x02
+#define PAGESCBS 0x04
+#define DPHASE 0x10
+#define SELECTED 0x20
+#define IDENTIFY_SEEN 0x40
+#define RESELECTED 0x80
+
+#define SAVED_TCL 0x04b /*
+ * Temporary storage for the
+ * target/channel/lun of a
+ * reconnecting target
+ */
+#define ACTIVE_A 0x04c
+#define ACTIVE_B 0x04d
+#define WAITING_SCBH 0x04e /*
+ * head of list of SCBs awaiting
+ * selection
+ */
+#define DISCONNECTED_SCBH 0x04f /*
+ * head of list of SCBs that are
+ * disconnected. Used for SCB
+ * paging.
+ */
+#define SCB_LIST_NULL 0xff
+
+#define SAVED_LINKPTR 0x050
+#define SAVED_SCBPTR 0x051
+
+#define SCSICONF 0x05a
+#define RESET_SCSI 0x40
+
+#define HOSTCONF 0x05d
+
+#define HA_274_BIOSCTRL 0x05f
+#define BIOSMODE 0x30
+#define BIOSDISABLED 0x30
+#define CHANNEL_B_PRIMARY 0x08
+
+/* Message codes */
+#define MSG_EXTENDED 0x01
+#define MSG_SDTR 0x01
+#define MSG_WDTR 0x03
+#define MSG_SDPTRS 0x02
+#define MSG_RDPTRS 0x03
+#define MSG_DISCONNECT 0x04
+#define MSG_INITIATOR_DET_ERROR 0x05
+#define MSG_ABORT 0x06
+#define MSG_REJECT 0x07
+#define MSG_NOP 0x08
+#define MSG_MSG_PARITY_ERROR 0x09
+#define MSG_BUS_DEVICE_RESET 0x0c
+#define MSG_ABORT_TAG 0x0d
+#define MSG_SIMPLE_TAG 0x20
+#define MSG_IDENTIFY 0x80
+
+/* WDTR Message values */
+#define BUS_8_BIT 0x00
+#define BUS_16_BIT 0x01
+#define BUS_32_BIT 0x02
+
+#define MAX_OFFSET_8BIT 0x0f
+#define MAX_OFFSET_16BIT 0x08
diff --git a/sys/dev/ic/aic7xxxvar.h b/sys/dev/ic/aic7xxxvar.h
index 8338785c59f..90fe40dfb1f 100644
--- a/sys/dev/ic/aic7xxxvar.h
+++ b/sys/dev/ic/aic7xxxvar.h
@@ -1,3 +1,5 @@
+/* $NetBSD: aic7xxxvar.h,v 1.7 1996/05/20 00:58:11 thorpej Exp $ */
+
/*
* Interface to the generic driver for the aic7xxx based adaptec
* SCSI controllers. This is used to implement product specific
@@ -29,8 +31,6 @@
* 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.
- *
- * $Id: aic7xxxvar.h,v 1.4 1996/05/05 12:42:31 deraadt Exp $
*/
#ifndef _AIC7XXX_H_
@@ -40,74 +40,7 @@
#include "ahc.h" /* for NAHC from config */
#endif
-#ifndef STAILQ_ENTRY /* for NetBSD, from FreeBSD <sys/queue.h> */
-/*
- * Singly-linked Tail queue definitions.
- */
-#define STAILQ_HEAD(name, type) \
-struct name { \
- struct type *stqh_first;/* first element */ \
- struct type **stqh_last;/* addr of last next element */ \
-}
-
-#define STAILQ_ENTRY(type) \
-struct { \
- struct type *stqe_next; /* next element */ \
-}
-
-/*
- * Singly-linked Tail queue functions.
- */
-#define STAILQ_INIT(head) { \
- (head)->stqh_first = NULL; \
- (head)->stqh_last = &(head)->stqh_first; \
-}
-
-#define STAILQ_INSERT_HEAD(head, elm, field) { \
- if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
- (head)->stqh_last = &(elm)->field.stqe_next; \
- (head)->stqh_first = (elm); \
-}
-
-#define STAILQ_INSERT_TAIL(head, elm, field) { \
- (elm)->field.stqe_next = NULL; \
- *(head)->stqh_last = (elm); \
- (head)->stqh_last = &(elm)->field.stqe_next; \
-}
-
-#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) { \
- if (((elm)->field.stqe_next = (tqelm)->field.stqe_next) == NULL)\
- (head)->stqh_last = &(elm)->field.stqe_next; \
- (tqelm)->field.stqe_next = (elm); \
-}
-
-#define STAILQ_REMOVE_HEAD(head, field) { \
- if (((head)->stqh_first = \
- (head)->stqh_first->field.stqe_next) == NULL) \
- (head)->stqh_last = &(head)->stqh_first; \
-}
-
-#define STAILQ_REMOVE(head, elm, type, field) { \
- if ((head)->stqh_first == (elm)) { \
- STAILQ_REMOVE_HEAD(head, field); \
- } \
- else { \
- struct type *curelm = (head)->stqh_first; \
- while( curelm->field.stqe_next != (elm) ) \
- curelm = curelm->field.stqe_next; \
- if((curelm->field.stqe_next = \
- curelm->field.stqe_next->field.stqe_next) == NULL) \
- (head)->stqh_last = &(curelm)->field.stqe_next; \
- } \
-}
-
-#endif /* STAILQ_ENTRY */
-
-#ifndef NetBSD1_1
-#define NetBSD1_1 0
-#endif
-
-#if defined(__FreeBSD__) || NetBSD1_1 < 3
+#if defined(__FreeBSD__)
#define AHC_INB(ahc, port) \
inb((ahc)->baseport+(port))
#define AHC_INSB(ahc, port, valp, size) \
@@ -120,15 +53,15 @@ struct { \
outsl((ahc)->baseport+(port), valp, size)
#elif defined(__NetBSD__)
#define AHC_INB(ahc, port) \
- bus_io_read_1((ahc)->sc_bc, ahc->baseport, port)
+ bus_io_read_1((ahc)->sc_bc, (ahc)->sc_ioh, port)
#define AHC_INSB(ahc, port, valp, size) \
- bus_io_read_multi_1((ahc)->sc_bc, ahc->baseport, port, valp, size)
+ bus_io_read_multi_1((ahc)->sc_bc, (ahc)->sc_ioh, port, valp, size)
#define AHC_OUTB(ahc, port, val) \
- bus_io_write_1((ahc)->sc_bc, ahc->baseport, port, val)
+ bus_io_write_1((ahc)->sc_bc, (ahc)->sc_ioh, port, val)
#define AHC_OUTSB(ahc, port, valp, size) \
- bus_io_write_multi_1((ahc)->sc_bc, ahc->baseport, port, valp, size)
+ bus_io_write_multi_1((ahc)->sc_bc, (ahc)->sc_ioh, port, valp, size)
#define AHC_OUTSL(ahc, port, valp, size) \
- bus_io_write_multi_4((ahc)->sc_bc, ahc->baseport, port, valp, size)
+ bus_io_write_multi_4((ahc)->sc_bc, (ahc)->sc_ioh, port, valp, size)
#endif
#define AHC_NSEG 256 /* number of dma segments supported */
@@ -143,7 +76,9 @@ struct { \
typedef unsigned long int physaddr;
+#if defined(__FreeBSD__)
extern u_long ahc_unit;
+#endif
struct ahc_dma_seg {
physaddr addr;
@@ -170,27 +105,47 @@ typedef enum {
}ahc_type;
typedef enum {
- AHC_FNONE = 0x00,
- AHC_INIT = 0x01,
- AHC_RUNNING = 0x02,
- AHC_PAGESCBS = 0x04, /* Enable SCB paging */
- AHC_USEDEFAULTS = 0x10, /*
+ AHC_FNONE = 0x00,
+ AHC_INIT = 0x01,
+ AHC_RUNNING = 0x02,
+ AHC_PAGESCBS = 0x04, /* Enable SCB paging */
+ AHC_CHANNEL_B_PRIMARY = 0x08, /*
+ * On twin channel adapters, probe
+ * channel B first since it is the
+ * primary bus.
+ */
+ AHC_USEDEFAULTS = 0x10, /*
* For cards without an seeprom
* or a BIOS to initialize the chip's
- * SRAM, we use the default chip and
- * target settings.
+ * SRAM, we use the default target
+ * settings.
*/
- AHC_CHNLB = 0x20, /*
+ AHC_CHNLB = 0x20, /*
* Second controller on 3940
* Also encodes the offset in the
* SEEPROM for CHNLB info (32)
*/
}ahc_flag;
+typedef enum {
+ SCB_FREE = 0x000,
+ SCB_ACTIVE = 0x001,
+ SCB_ABORTED = 0x002,
+ SCB_DEVICE_RESET = 0x004,
+ SCB_IMMED = 0x008,
+ SCB_SENSE = 0x010,
+ SCB_TIMEDOUT = 0x020,
+ SCB_QUEUED_FOR_DONE = 0x040,
+ SCB_PAGED_OUT = 0x080,
+ SCB_WAITINGQ = 0x100,
+ SCB_ASSIGNEDQ = 0x200,
+ SCB_SENTORDEREDTAG = 0x400
+}scb_flag;
+
/*
* The driver keeps up to MAX_SCB scb structures per card in memory. Only the
- * first 26 bytes of the structure need to be transfered to the card during
- * normal operation. The fields starting at byte 32 are used for kernel level
+ * first 28 bytes of the structure need to be transfered to the card during
+ * normal operation. The fields starting at byte 28 are used for kernel level
* bookkeeping.
*/
struct scb {
@@ -222,61 +177,46 @@ struct scb {
*/
/*27*/ u_char prev;
/*-----------------end of hardware supported fields----------------*/
- STAILQ_ENTRY(scb) links; /* for chaining */
+ SIMPLEQ_ENTRY(scb) links; /* for chaining */
struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
- int flags;
-#define SCB_FREE 0x000
-#define SCB_ACTIVE 0x001
-#define SCB_ABORTED 0x002
-#define SCB_DEVICE_RESET 0x004
-#define SCB_IMMED 0x008
-#define SCB_SENSE 0x010
-#define SCB_TIMEDOUT 0x020
-#define SCB_QUEUED_FOR_DONE 0x040
-#define SCB_PAGED_OUT 0x080
-#define SCB_WAITINGQ 0x100
-#define SCB_ASSIGNEDQ 0x200
-#define SCB_SENTORDEREDTAG 0x400
+ scb_flag flags;
u_char position; /* Position in card's scbarray */
struct ahc_dma_seg ahc_dma[AHC_NSEG] __attribute__ ((packed));
struct scsi_sense sense_cmd; /* SCSI command block */
};
-#if defined(__NetBSD__)
-#if NetBSD1_1 < 3 /* NetBSD-1.1 */
-typedef int bus_chipset_tag_t;
-typedef int bus_io_handle_t;
-#endif
-#endif
-
struct ahc_data {
-#if defined(__NetBSD__)
+#if defined(__FreeBSD__)
+ int unit;
+#elif defined(__NetBSD__)
struct device sc_dev;
void *sc_ih;
bus_chipset_tag_t sc_bc;
+ bus_io_handle_t sc_ioh;
#endif
- int unit;
ahc_type type;
ahc_flag flags;
+#if defined(__FreeBSD__)
u_long baseport;
+#endif
struct scb *scbarray[AHC_SCB_MAX]; /* Mirror boards scbarray */
struct scb *pagedout_ntscbs[16];/*
* Paged out, non-tagged scbs
* indexed by target.
*/
- STAILQ_HEAD(, scb) free_scbs; /*
+ SIMPLEQ_HEAD(, scb) free_scbs; /*
* SCBs assigned to free slots
* on the card. (no paging required)
*/
- STAILQ_HEAD(, scb) page_scbs; /*
+ SIMPLEQ_HEAD(, scb) page_scbs; /*
* SCBs that will require paging
* before use (no assigned slot)
*/
- STAILQ_HEAD(, scb) waiting_scbs;/*
+ SIMPLEQ_HEAD(, scb) waiting_scbs;/*
* SCBs waiting to be paged in
* and started.
*/
- STAILQ_HEAD(, scb)assigned_scbs;/*
+ SIMPLEQ_HEAD(, scb)assigned_scbs;/*
* SCBs that were waiting but have
* now been assigned a slot by
* ahc_free_scb.
@@ -321,11 +261,17 @@ extern int ahc_debug; /* Initialized in i386/scsi/aic7xxx.c */
#endif
#if defined(__FreeBSD__)
+
+char *ahc_name __P((struct ahc_data *ahc));
+
void ahc_reset __P((u_long iobase));
struct ahc_data *ahc_alloc __P((int unit, u_long io_base, ahc_type type, ahc_flag flags));
#elif defined(__NetBSD__)
+
+#define ahc_name(ahc) (ahc)->sc_dev.dv_xname
+
void ahc_reset __P((char *devname, bus_chipset_tag_t bc, bus_io_handle_t ioh));
-void ahc_construct __P((struct ahc_data *ahc, int unit, bus_chipset_tag_t bc, bus_io_handle_t ioh, ahc_type type, ahc_flag flags));
+void ahc_construct __P((struct ahc_data *ahc, bus_chipset_tag_t bc, bus_io_handle_t ioh, ahc_type type, ahc_flag flags));
#endif
void ahc_free __P((struct ahc_data *));
int ahc_init __P((struct ahc_data *));
diff --git a/sys/dev/ic/com.c b/sys/dev/ic/com.c
index 409afeb3c58..e5da21469df 100644
--- a/sys/dev/ic/com.c
+++ b/sys/dev/ic/com.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: com.c,v 1.14 1996/05/10 12:37:13 deraadt Exp $ */
-/* $NetBSD: com.c,v 1.81 1996/05/05 19:50:44 christos Exp $ */
+/* $OpenBSD: com.c,v 1.15 1996/05/26 00:27:14 deraadt Exp $ */
+/* $NetBSD: com.c,v 1.82 1996/05/12 23:52:00 mycroft Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995, 1996
@@ -57,12 +57,8 @@
#include <sys/types.h>
#include <sys/device.h>
-#ifdef i386 /* XXX */
-#include <machine/cpu.h> /* XXX */
-#else /* XXX */
-#include <machine/intr.h>
-#endif /* XXX */
#include <machine/bus.h>
+#include <machine/intr.h>
#include <dev/isa/isavar.h>
#include <dev/isa/comreg.h>
diff --git a/sys/dev/ic/elink3.c b/sys/dev/ic/elink3.c
index 8eeba382af5..8d51ec0467f 100644
--- a/sys/dev/ic/elink3.c
+++ b/sys/dev/ic/elink3.c
@@ -1,7 +1,7 @@
-/* $NetBSD: elink3.c,v 1.5 1996/05/07 01:43:13 thorpej Exp $ */
+/* $NetBSD: elink3.c,v 1.7 1996/05/14 22:22:05 thorpej Exp $ */
/*
- * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
+ * Copyright (c) 1994 Herb Peyerl <hpeyerl@beer.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -63,6 +63,7 @@
#include <machine/cpu.h>
#include <machine/bus.h>
+#include <machine/intr.h>
#include <dev/ic/elink3var.h>
#include <dev/ic/elink3reg.h>
@@ -94,12 +95,12 @@ static int epbusyeeprom __P((struct ep_softc *));
void
epconfig(sc, conn)
struct ep_softc *sc;
- u_int conn;
+ u_int16_t conn;
{
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
- u_short i;
+ u_int16_t i;
sc->ep_connectors = 0;
if (conn & IS_AUI) {
@@ -125,7 +126,7 @@ epconfig(sc, conn)
* Read the station address from the eeprom
*/
for (i = 0; i < 3; i++) {
- u_short x;
+ u_int16_t x;
if (epbusyeeprom(sc))
return;
bus_io_write_2(bc, ioh, EP_W0_EEPROM_COMMAND, READ_EEPROM | i);
@@ -398,7 +399,7 @@ startagain:
readcheck:
if ((bus_io_read_2(bc, ioh, EP_W1_RX_STATUS) & ERR_INCOMPLETE) == 0) {
/* We received a complete packet. */
- u_short status = bus_io_read_2(bc, ioh, EP_STATUS);
+ u_int16_t status = bus_io_read_2(bc, ioh, EP_STATUS);
if ((status & S_INTR_LATCH) == 0) {
/*
@@ -439,7 +440,7 @@ epstatus(sc)
{
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
- u_short fifost;
+ u_int16_t fifost;
/*
* Check the FIFO status and act accordingly
@@ -527,7 +528,7 @@ epintr(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;
- u_short status;
+ u_int16_t status;
int ret = 0;
for (;;) {
diff --git a/sys/dev/ic/elink3reg.h b/sys/dev/ic/elink3reg.h
index 721ee04f163..48dccc48339 100644
--- a/sys/dev/ic/elink3reg.h
+++ b/sys/dev/ic/elink3reg.h
@@ -1,7 +1,7 @@
-/* $NetBSD: elink3reg.h,v 1.2 1996/04/30 22:32:39 thorpej Exp $ */
+/* $NetBSD: elink3reg.h,v 1.3 1996/05/10 05:28:09 thorpej Exp $ */
/*
- * Copyright (c) 1995 Herb Peyerl <hpeyerl@novatel.ca>
+ * Copyright (c) 1995 Herb Peyerl <hpeyerl@beer.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/ic/elink3var.h b/sys/dev/ic/elink3var.h
index 534c68d8c66..19296129b76 100644
--- a/sys/dev/ic/elink3var.h
+++ b/sys/dev/ic/elink3var.h
@@ -1,7 +1,7 @@
-/* $NetBSD: elink3var.h,v 1.3 1996/05/03 19:08:48 christos Exp $ */
+/* $NetBSD: elink3var.h,v 1.5 1996/05/14 22:22:06 thorpej Exp $ */
/*
- * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
+ * Copyright (c) 1994 Herb Peyerl <hpeyerl@beer.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -62,6 +62,6 @@ struct ep_softc {
};
u_int16_t epreadeeprom __P((bus_chipset_tag_t, bus_io_handle_t, int));
-void epconfig __P((struct ep_softc *, u_int));
+void epconfig __P((struct ep_softc *, u_int16_t));
int epintr __P((void *));
void epstop __P((struct ep_softc *));
diff --git a/sys/dev/ic/ncr5380sbc.c b/sys/dev/ic/ncr5380sbc.c
index a7e356d4bac..56c3ab8cc1e 100644
--- a/sys/dev/ic/ncr5380sbc.c
+++ b/sys/dev/ic/ncr5380sbc.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ncr5380sbc.c,v 1.5 1996/04/21 22:21:21 deraadt Exp $ */
-/* $NetBSD: ncr5380sbc.c,v 1.9 1996/03/18 23:09:02 gwr Exp $ */
+/* $OpenBSD: ncr5380sbc.c,v 1.6 1996/05/26 00:27:01 deraadt Exp $ */
+/* $NetBSD: ncr5380sbc.c,v 1.11 1996/05/13 14:10:21 christos Exp $ */
/*
* Copyright (c) 1995 David Jones, Gordon W. Ross
@@ -917,7 +917,7 @@ next_job:
case XS_BUSY:
/* XXX - Reset and try again. */
- printf("%s: SCSI bus busy, resetting...\n",
+ printf("%s: select found SCSI bus busy, resetting...\n",
sc->sc_dev.dv_xname);
ncr5380_reset_scsibus(sc);
/* fallthrough */
@@ -1057,6 +1057,7 @@ ncr5380_reselect(sc)
{
struct sci_req *sr;
int target, lun, phase, timo;
+ int target_mask;
u_char bus, data, icmd, msg;
#ifdef DIAGNOSTIC
@@ -1125,6 +1126,7 @@ ncr5380_reselect(sc)
printf("%s: selected as target, data=0x%x\n",
sc->sc_dev.dv_xname, data);
/* Not much we can do. Reset the bus. */
+ /* XXX: send some sort of message? */
ncr5380_reset_scsibus(sc);
return;
}
@@ -1132,11 +1134,12 @@ ncr5380_reselect(sc)
/*
* OK, this is a reselection.
*/
- for (target = 0; target < 7; target++)
- if (data & (1 << target))
+ for (target = 0; target < 7; target++) {
+ target_mask = (1 << target);
+ if (data & target_mask)
break;
-
- if ((data & 0x7F) != (1 << target)) {
+ }
+ if ((data & 0x7F) != target_mask) {
/* No selecting ID? or >2 IDs on bus? */
printf("%s: bad reselect, data=0x%x\n",
sc->sc_dev.dv_xname, data);
@@ -1218,6 +1221,13 @@ ncr5380_reselect(sc)
sc->sc_msgoutq = 0;
sc->sc_msgout = 0;
+ /* XXX: Restore the normal mode register. */
+ /* If this target's bit is set, do NOT check parity. */
+ if (sc->sc_parity_disable & target_mask)
+ *sc->sci_mode = (SCI_MODE_MONBSY);
+ else
+ *sc->sci_mode = (SCI_MODE_MONBSY | SCI_MODE_PAR_CHK);
+
/*
* Another hack for the Sun3 "si", which needs
* some setup done to its DMA engine before the
@@ -1280,7 +1290,7 @@ ncr5380_select(sc, sr)
struct ncr5380_softc *sc;
struct sci_req *sr;
{
- int timo, s;
+ int timo, s, target_mask;
u_char data, icmd;
/* Check for reselect */
@@ -1409,7 +1419,8 @@ ncr5380_select(sc, sr)
* the host and target. Also set ATN now, to
* ask the target for a message out phase.
*/
- data = 0x80 | (1 << sr->sr_target);
+ target_mask = (1 << sr->sr_target);
+ data = 0x80 | target_mask;
*(sc->sci_odata) = data;
icmd |= (SCI_ICMD_DATA | SCI_ICMD_ATN);
*(sc->sci_icmd) = icmd;
@@ -1464,8 +1475,11 @@ success:
icmd &= ~(SCI_ICMD_DATA | SCI_ICMD_SEL);
*sc->sci_icmd = icmd;
- /* XXX - Make parity checking optional? */
- *sc->sci_mode = (SCI_MODE_MONBSY | SCI_MODE_PAR_CHK);
+ /* If this target's bit is set, do NOT check parity. */
+ if (sc->sc_parity_disable & target_mask)
+ *sc->sci_mode = (SCI_MODE_MONBSY);
+ else
+ *sc->sci_mode = (SCI_MODE_MONBSY | SCI_MODE_PAR_CHK);
return XS_NOERROR;
}
@@ -2333,7 +2347,7 @@ do_actions:
* We have to wait here for BSY to drop, otherwise
* the next command may decide we need a bus reset.
*/
- timo = ncr5380_wait_nrq_timo; /* XXX */
+ timo = ncr5380_wait_req_timo; /* XXX */
for (;;) {
if (!SCI_BUSY(sc))
goto busfree;
@@ -2342,8 +2356,9 @@ do_actions:
delay(2);
}
/* Device is sitting on the bus! */
- printf("%s: SCSI job did not finish, resetting...\n",
- sc->sc_dev.dv_xname);
+ printf("%s: Target %d LUN %d stuck busy, resetting...\n",
+ sc->sc_dev.dv_xname,
+ sr->sr_target, sr->sr_lun);
ncr5380_reset_scsibus(sc);
busfree:
NCR_TRACE("machine: discon, waited %d\n",
diff --git a/sys/dev/ic/ncr5380var.h b/sys/dev/ic/ncr5380var.h
index ec9086c3df8..534105dfc29 100644
--- a/sys/dev/ic/ncr5380var.h
+++ b/sys/dev/ic/ncr5380var.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: ncr5380var.h,v 1.3 1996/04/18 23:47:21 niklas Exp $ */
-/* $NetBSD: ncr5380var.h,v 1.5 1996/03/01 01:42:07 gwr Exp $ */
+/* $OpenBSD: ncr5380var.h,v 1.4 1996/05/26 00:27:02 deraadt Exp $ */
+/* $NetBSD: ncr5380var.h,v 1.6 1996/05/10 18:04:06 gwr Exp $ */
/*
* Copyright (c) 1995 David Jones, Gordon W. Ross
@@ -111,6 +111,9 @@ struct ncr5380_softc {
#define NCR5380_PERMIT_RESELECT 1 /* Allow disconnect/reselect */
#define NCR5380_FORCE_POLLING 2 /* Do not use interrupts. */
+ /* Set bits in this to disable parity for some target. */
+ int sc_parity_disable;
+
int sc_min_dma_len; /* Smaller than this is done with PIO */
/* Begin MI shared data */
diff --git a/sys/dev/ic/pdq.c b/sys/dev/ic/pdq.c
index 1ee64d8d4a1..099ea3247a1 100644
--- a/sys/dev/ic/pdq.c
+++ b/sys/dev/ic/pdq.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: pdq.c,v 1.2 1996/04/18 23:47:22 niklas Exp $ */
-/* $NetBSD: pdq.c,v 1.3 1996/03/11 21:41:28 thorpej Exp $ */
+/* $OpenBSD: pdq.c,v 1.3 1996/05/26 00:27:02 deraadt Exp $ */
+/* $NetBSD: pdq.c,v 1.5 1996/05/20 00:26:15 thorpej Exp $ */
/*-
- * Copyright (c) 1995 Matt Thomas (matt@lkg.dec.com)
+ * Copyright (c) 1995,1996 Matt Thomas <matt@3am-software.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,103 +24,43 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * from Id: pdq.c,v 1.18 1995/08/20 18:59:00 thomas Exp thomas
- *
- * Log: pdq.c,v
- * Revision 1.18 1995/08/20 18:59:00 thomas
- * Changes for NetBSD
- *
- * Revision 1.17 1995/08/16 22:57:28 thomas
- * Add support for NetBSD
- *
- * Revision 1.16 1995/08/04 21:54:56 thomas
- * Clean IRQ processing under BSD/OS.
- * A receive tweaks. (print source of MAC CRC errors, etc.)
- *
- * Revision 1.15 1995/06/30 23:36:21 thomas
- * Optimize fix.
- *
- * Revision 1.14 1995/06/30 23:35:39 thomas
- * Fix severe bug in transmit path (corruption of ring).
- *
- * Revision 1.13 1995/06/21 18:29:27 thomas
- * SVR4.2 changes
- *
- * Revision 1.12 1995/06/05 23:49:36 thomas
- * Fix bonehead error. Don't try to queue a command if there
- * is a command.
- *
- * Revision 1.11 1995/06/03 15:43:26 thomas
- * Fix the command submission logic to only submit one
- * command at a time no matter what. This simplies the
- * code significantly thereby allowing us to do some up
- * front optimizations.
- *
- * Revision 1.10 1995/06/02 22:18:34 thomas
- * Don't know why but on some motherboards, the PDQ just can't
- * multiple outstanding commands.
- *
- * Revision 1.9 1995/04/20 20:17:33 thomas
- * Add PCI support for BSD/OS.
- * Fix BSD/OS EISA support.
- * Set latency timer for DEFPA to recommended value if 0.
- *
- * Revision 1.8 1995/03/14 01:52:52 thomas
- * Update for new FreeBSD PCI Interrupt interface
- *
- * Revision 1.7 1995/03/07 23:03:16 thomas
- * Fix SMT queue processing
- *
- * Revision 1.6 1995/03/06 18:03:47 thomas
- * restart trasmitter once link is available
- *
- * Revision 1.5 1995/03/06 17:07:56 thomas
- * Add copyright/disclaimer
- * Add error recovery code.
- * Add BPF SMT support
- *
- * Revision 1.3 1995/03/03 13:48:35 thomas
- * more fixes
- *
+ * Id: pdq.c,v 1.26 1996/05/17 01:15:18 thomas Exp
*
*/
/*
* DEC PDQ FDDI Controller O/S independent code
*
- * Written by Matt Thomas <matt@lkg.dec.com>
- *
* This module should work any PDQ based board. Note that changes for
* MIPS and Alpha architectures (or any other architecture which requires
* a flushing of memory or write buffers and/or has incoherent caches)
* have yet to be made.
+ *
+ * However, it is expected that the PDQ_CSR_WRITE macro will cause a
+ * flushing of the write buffers.
*/
#define PDQ_HWSUPPORT /* for pdq.h */
-#include "pdqreg.h"
-#if defined(__NetBSD__)
#include "pdqvar.h"
-#else
-#include "pdq_os.h"
-#endif
+#include "pdqreg.h"
#define PDQ_ROUNDUP(n, x) (((n) + ((x) - 1)) & ~((x) - 1))
#define PDQ_CMD_RX_ALIGNMENT 16
-#if defined(PDQTEST) && !defined(PDQ_NOPRINTF)
+#if (defined(PDQTEST) && !defined(PDQ_NOPRINTF)) || defined(PDQVERBOSE)
#define PDQ_PRINTF(x) printf x
#else
#define PDQ_PRINTF(x) do { } while (0)
#endif
-const char * const pdq_halt_codes[] = {
+static const char * const pdq_halt_codes[] = {
"Selftest Timeout", "Host Bus Parity Error", "Host Directed Fault",
"Software Fault", "Hardware Fault", "PC Trace Path Test",
"DMA Error", "Image CRC Error", "Adapter Processer Error"
};
-const char * const pdq_adapter_states[] = {
+static const char * const pdq_adapter_states[] = {
"Reset", "Upgrade", "DMA Unavailable", "DMA Available",
"Link Available", "Link Unavailable", "Halted", "Ring Member"
};
@@ -129,19 +69,19 @@ const char * const pdq_adapter_states[] = {
* The following are used in conjunction with
* unsolicited events
*/
-const char * const pdq_entities[] = {
+static const char * const pdq_entities[] = {
"Station", "Link", "Phy Port"
};
-const char * const pdq_station_events[] = {
+static const char * const pdq_station_events[] = {
"Trace Received"
};
-const char * const pdq_station_arguments[] = {
+static const char * const pdq_station_arguments[] = {
"Reason"
};
-const char * const pdq_link_events[] = {
+static const char * const pdq_link_events[] = {
"Transmit Underrun",
"Transmit Failed",
"Block Check Error (CRC)",
@@ -163,63 +103,63 @@ const char * const pdq_link_events[] = {
"Directed Beacon Received",
};
-const char * const pdq_link_arguments[] = {
+static const char * const pdq_link_arguments[] = {
"Reason",
"Data Link Header",
"Source",
"Upstream Neighbor"
};
-const char * const pdq_phy_events[] = {
+static const char * const pdq_phy_events[] = {
"LEM Error Monitor Reject",
"Elasticy Buffer Error",
"Link Confidence Test Reject"
};
-const char * const pdq_phy_arguments[] = {
+static const char * const pdq_phy_arguments[] = {
"Direction"
};
-const char * const * const pdq_event_arguments[] = {
+static const char * const * const pdq_event_arguments[] = {
pdq_station_arguments,
pdq_link_arguments,
pdq_phy_arguments
};
-const char * const * const pdq_event_codes[] = {
+static const char * const * const pdq_event_codes[] = {
pdq_station_events,
pdq_link_events,
pdq_phy_events
};
-const char * const pdq_station_types[] = {
+static const char * const pdq_station_types[] = {
"SAS", "DAC", "SAC", "NAC", "DAS"
};
-const char * const pdq_smt_versions[] = { "", "V6.2", "V7.2", "V7.3" };
+static const char * const pdq_smt_versions[] = { "", "V6.2", "V7.2", "V7.3" };
-const char pdq_phy_types[] = "ABSM";
+static const char pdq_phy_types[] = "ABSM";
-const char * const pdq_pmd_types0[] = {
+static const char * const pdq_pmd_types0[] = {
"ANSI Multi-Mode", "ANSI Single-Mode Type 1", "ANSI Single-Mode Type 2",
"ANSI Sonet"
};
-const char * const pdq_pmd_types100[] = {
+static const char * const pdq_pmd_types100[] = {
"Low Power", "Thin Wire", "Shielded Twisted Pair",
"Unshielded Twisted Pair"
};
-const char * const * const pdq_pmd_types[] = {
+static const char * const * const pdq_pmd_types[] = {
pdq_pmd_types0, pdq_pmd_types100
};
-const char * const pdq_descriptions[] = {
+static const char * const pdq_descriptions[] = {
"DEFPA PCI",
"DEFEA EISA",
};
-void
+static void
pdq_print_fddi_chars(
pdq_t *pdq,
const pdq_response_status_chars_get_t *rsp)
@@ -275,44 +215,46 @@ pdq_print_fddi_chars(
printf("\n");
}
-void
+static void
pdq_init_csrs(
pdq_csrs_t *csrs,
- void *csr_va,
+ pdq_bus_t bus,
+ pdq_bus_memaddr_t csr_base,
size_t csrsize)
{
- volatile pdq_uint32_t *csr_base = (volatile pdq_uint32_t *) csr_va;
-
- csrs->csr_port_reset = &csr_base[0 * csrsize];
- csrs->csr_host_data = &csr_base[1 * csrsize];
- csrs->csr_port_control = &csr_base[2 * csrsize];
- csrs->csr_port_data_a = &csr_base[3 * csrsize];
- csrs->csr_port_data_b = &csr_base[4 * csrsize];
- csrs->csr_port_status = &csr_base[5 * csrsize];
- csrs->csr_host_int_type_0 = &csr_base[6 * csrsize];
- csrs->csr_host_int_enable = &csr_base[7 * csrsize];
- csrs->csr_type_2_producer = &csr_base[8 * csrsize];
- csrs->csr_cmd_response_producer = &csr_base[10 * csrsize];
- csrs->csr_cmd_request_producer = &csr_base[11 * csrsize];
- csrs->csr_host_smt_producer = &csr_base[12 * csrsize];
- csrs->csr_unsolicited_producer = &csr_base[13 * csrsize];
+ csrs->csr_bus = bus;
+ csrs->csr_base = csr_base;
+ csrs->csr_port_reset = PDQ_CSR_OFFSET(csr_base, 0 * csrsize);
+ csrs->csr_host_data = PDQ_CSR_OFFSET(csr_base, 1 * csrsize);
+ csrs->csr_port_control = PDQ_CSR_OFFSET(csr_base, 2 * csrsize);
+ csrs->csr_port_data_a = PDQ_CSR_OFFSET(csr_base, 3 * csrsize);
+ csrs->csr_port_data_b = PDQ_CSR_OFFSET(csr_base, 4 * csrsize);
+ csrs->csr_port_status = PDQ_CSR_OFFSET(csr_base, 5 * csrsize);
+ csrs->csr_host_int_type_0 = PDQ_CSR_OFFSET(csr_base, 6 * csrsize);
+ csrs->csr_host_int_enable = PDQ_CSR_OFFSET(csr_base, 7 * csrsize);
+ csrs->csr_type_2_producer = PDQ_CSR_OFFSET(csr_base, 8 * csrsize);
+ csrs->csr_cmd_response_producer = PDQ_CSR_OFFSET(csr_base, 10 * csrsize);
+ csrs->csr_cmd_request_producer = PDQ_CSR_OFFSET(csr_base, 11 * csrsize);
+ csrs->csr_host_smt_producer = PDQ_CSR_OFFSET(csr_base, 12 * csrsize);
+ csrs->csr_unsolicited_producer = PDQ_CSR_OFFSET(csr_base, 13 * csrsize);
}
-void
+static void
pdq_init_pci_csrs(
pdq_pci_csrs_t *csrs,
- void *csr_va,
+ pdq_bus_t bus,
+ pdq_bus_memaddr_t csr_base,
size_t csrsize)
{
- volatile pdq_uint32_t *csr_base = (volatile pdq_uint32_t *) csr_va;
-
- csrs->csr_pfi_mode_control = &csr_base[16 * csrsize];
- csrs->csr_pfi_status = &csr_base[17 * csrsize];
- csrs->csr_fifo_write = &csr_base[18 * csrsize];
- csrs->csr_fifo_read = &csr_base[19 * csrsize];
+ csrs->csr_bus = bus;
+ csrs->csr_base = csr_base;
+ csrs->csr_pfi_mode_control = PDQ_CSR_OFFSET(csr_base, 16 * csrsize);
+ csrs->csr_pfi_status = PDQ_CSR_OFFSET(csr_base, 17 * csrsize);
+ csrs->csr_fifo_write = PDQ_CSR_OFFSET(csr_base, 18 * csrsize);
+ csrs->csr_fifo_read = PDQ_CSR_OFFSET(csr_base, 19 * csrsize);
}
-void
+static void
pdq_flush_databuf_queue(
pdq_databuf_queue_t *q)
{
@@ -325,51 +267,51 @@ pdq_flush_databuf_queue(
}
}
-pdq_boolean_t
+static pdq_boolean_t
pdq_do_port_control(
const pdq_csrs_t * const csrs,
pdq_uint32_t cmd)
{
int cnt = 0;
- *csrs->csr_host_int_type_0 = PDQ_HOST_INT_CSR_CMD_DONE;
- *csrs->csr_port_control = PDQ_PCTL_CMD_ERROR | cmd;
- while ((*csrs->csr_host_int_type_0 & PDQ_HOST_INT_CSR_CMD_DONE) == 0 && cnt < 33000000)
+ PDQ_CSR_WRITE(csrs, csr_host_int_type_0, PDQ_HOST_INT_CSR_CMD_DONE);
+ PDQ_CSR_WRITE(csrs, csr_port_control, PDQ_PCTL_CMD_ERROR | cmd);
+ while ((PDQ_CSR_READ(csrs, csr_host_int_type_0) & PDQ_HOST_INT_CSR_CMD_DONE) == 0 && cnt < 33000000)
cnt++;
PDQ_PRINTF(("CSR cmd spun %d times\n", cnt));
- if (*csrs->csr_host_int_type_0 & PDQ_HOST_INT_CSR_CMD_DONE) {
- *csrs->csr_host_int_type_0 = PDQ_HOST_INT_CSR_CMD_DONE;
- return (*csrs->csr_port_control & PDQ_PCTL_CMD_ERROR) ? PDQ_FALSE : PDQ_TRUE;
+ if (PDQ_CSR_READ(csrs, csr_host_int_type_0) & PDQ_HOST_INT_CSR_CMD_DONE) {
+ PDQ_CSR_WRITE(csrs, csr_host_int_type_0, PDQ_HOST_INT_CSR_CMD_DONE);
+ return (PDQ_CSR_READ(csrs, csr_port_control) & PDQ_PCTL_CMD_ERROR) ? PDQ_FALSE : PDQ_TRUE;
}
/* adapter failure */
PDQ_ASSERT(0);
return PDQ_FALSE;
}
-void
+static void
pdq_read_mla(
const pdq_csrs_t * const csrs,
pdq_lanaddr_t *hwaddr)
{
pdq_uint32_t data;
- *csrs->csr_port_data_a = 0;
+ PDQ_CSR_WRITE(csrs, csr_port_data_a, 0);
pdq_do_port_control(csrs, PDQ_PCTL_MLA_READ);
- data = *csrs->csr_host_data;
+ data = PDQ_CSR_READ(csrs, csr_host_data);
hwaddr->lanaddr_bytes[0] = (data >> 0) & 0xFF;
hwaddr->lanaddr_bytes[1] = (data >> 8) & 0xFF;
hwaddr->lanaddr_bytes[2] = (data >> 16) & 0xFF;
hwaddr->lanaddr_bytes[3] = (data >> 24) & 0xFF;
- *csrs->csr_port_data_a = 1;
+ PDQ_CSR_WRITE(csrs, csr_port_data_a, 1);
pdq_do_port_control(csrs, PDQ_PCTL_MLA_READ);
- data = *csrs->csr_host_data;
+ data = PDQ_CSR_READ(csrs, csr_host_data);
hwaddr->lanaddr_bytes[4] = (data >> 0) & 0xFF;
hwaddr->lanaddr_bytes[5] = (data >> 8) & 0xFF;
}
-void
+static void
pdq_read_fwrev(
const pdq_csrs_t * const csrs,
pdq_fwrev_t *fwrev)
@@ -377,7 +319,7 @@ pdq_read_fwrev(
pdq_uint32_t data;
pdq_do_port_control(csrs, PDQ_PCTL_FW_REV_READ);
- data = *csrs->csr_host_data;
+ data = PDQ_CSR_READ(csrs, csr_host_data);
fwrev->fwrev_bytes[3] = (data >> 0) & 0xFF;
fwrev->fwrev_bytes[2] = (data >> 8) & 0xFF;
@@ -385,7 +327,7 @@ pdq_read_fwrev(
fwrev->fwrev_bytes[0] = (data >> 24) & 0xFF;
}
-pdq_boolean_t
+static pdq_boolean_t
pdq_read_error_log(
pdq_t *pdq,
pdq_response_error_log_get_t *log_entry)
@@ -396,22 +338,22 @@ pdq_read_error_log(
pdq_do_port_control(csrs, PDQ_PCTL_ERROR_LOG_START);
while (pdq_do_port_control(csrs, PDQ_PCTL_FW_REV_READ) == PDQ_TRUE) {
- *ptr++ = *csrs->csr_host_data;
+ *ptr++ = PDQ_CSR_READ(csrs, csr_host_data);
if ((pdq_uint8_t *) ptr - (pdq_uint8_t *) log_entry == sizeof(*log_entry))
break;
}
return (ptr == (pdq_uint32_t *) log_entry) ? PDQ_FALSE : PDQ_TRUE;
}
-pdq_chip_rev_t
+static pdq_chip_rev_t
pdq_read_chiprev(
const pdq_csrs_t * const csrs)
{
pdq_uint32_t data;
- *csrs->csr_port_data_a = PDQ_SUB_CMD_PDQ_REV_GET;
+ PDQ_CSR_WRITE(csrs, csr_port_data_a, PDQ_SUB_CMD_PDQ_REV_GET);
pdq_do_port_control(csrs, PDQ_PCTL_SUB_CMD);
- data = *csrs->csr_host_data;
+ data = PDQ_CSR_READ(csrs, csr_host_data);
return (pdq_chip_rev_t) data;
}
@@ -499,7 +441,7 @@ static const struct {
#endif
};
-void
+static void
pdq_queue_commands(
pdq_t *pdq)
{
@@ -603,11 +545,11 @@ pdq_queue_commands(
pdq_cmd_info[op].cmd_name));
ci->ci_command_active++;
- *csrs->csr_cmd_response_producer = ci->ci_response_producer | (ci->ci_response_completion << 8);
- *csrs->csr_cmd_request_producer = ci->ci_request_producer | (ci->ci_request_completion << 8);
+ PDQ_CSR_WRITE(csrs, csr_cmd_response_producer, ci->ci_response_producer | (ci->ci_response_completion << 8));
+ PDQ_CSR_WRITE(csrs, csr_cmd_request_producer, ci->ci_request_producer | (ci->ci_request_completion << 8));
}
-void
+static void
pdq_process_command_responses(
pdq_t * const pdq)
{
@@ -650,8 +592,10 @@ pdq_process_command_responses(
if (ci->ci_pending_commands != 0) {
pdq_queue_commands(pdq);
} else {
- *csrs->csr_cmd_response_producer = ci->ci_response_producer | (ci->ci_response_completion << 8);
- *csrs->csr_cmd_request_producer = ci->ci_request_producer | (ci->ci_request_completion << 8);
+ PDQ_CSR_WRITE(csrs, csr_cmd_response_producer,
+ ci->ci_response_producer | (ci->ci_response_completion << 8));
+ PDQ_CSR_WRITE(csrs, csr_cmd_request_producer,
+ ci->ci_request_producer | (ci->ci_request_completion << 8));
}
}
@@ -661,7 +605,7 @@ pdq_process_command_responses(
* event buffers so it can be used to initialize the queue
* as well.
*/
-void
+static void
pdq_process_unsolicited_events(
pdq_t *pdq)
{
@@ -686,7 +630,7 @@ pdq_process_unsolicited_events(
PDQ_OS_PREFIX_ARGS,
pdq_entities[event->event_entity],
pdq_event_codes[event->event_entity][event->event_code.value]);
- if (event->event_type == PDQ_ENTITY_PHY_PORT)
+ if (event->event_entity == PDQ_ENTITY_PHY_PORT)
printf("[%d]", event->event_index);
printf("\n");
break;
@@ -705,10 +649,11 @@ pdq_process_unsolicited_events(
PDQ_ADVANCE(ui->ui_producer, ui->ui_free, PDQ_RING_MASK(dbp->pdqdb_unsolicited_events));
ui->ui_free = 0;
- *csrs->csr_unsolicited_producer = ui->ui_producer | (ui->ui_completion << 8);
+ PDQ_CSR_WRITE(csrs, csr_unsolicited_producer,
+ ui->ui_producer | (ui->ui_completion << 8));
}
-void
+static void
pdq_process_received_data(
pdq_t *pdq,
pdq_rx_info_t *rx,
@@ -950,7 +895,7 @@ pdq_queue_transmit_data(
return PDQ_TRUE;
}
-void
+static void
pdq_process_transmitted_data(
pdq_t *pdq)
{
@@ -1010,22 +955,23 @@ pdq_hwreset(
pdq_state_t state;
int cnt;
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
+ state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
if (state == PDQS_DMA_UNAVAILABLE)
return;
- *csrs->csr_port_data_a = (state == PDQS_HALTED) ? 0 : PDQ_PRESET_SKIP_SELFTEST;
- *csrs->csr_port_reset = 1;
+ PDQ_CSR_WRITE(csrs, csr_port_data_a,
+ (state == PDQS_HALTED) ? 0 : PDQ_PRESET_SKIP_SELFTEST);
+ PDQ_CSR_WRITE(csrs, csr_port_reset, 1);
PDQ_OS_USEC_DELAY(100);
- *csrs->csr_port_reset = 0;
+ PDQ_CSR_WRITE(csrs, csr_port_reset, 0);
for (cnt = 45000;;cnt--) {
PDQ_OS_USEC_DELAY(1000);
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
+ state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
if (state == PDQS_DMA_UNAVAILABLE || cnt == 0)
break;
}
PDQ_PRINTF(("PDQ Reset spun %d cycles\n", 45000 - cnt));
PDQ_OS_USEC_DELAY(10000);
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
+ state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
PDQ_ASSERT(state == PDQS_DMA_UNAVAILABLE);
PDQ_ASSERT(cnt > 0);
}
@@ -1044,10 +990,10 @@ pdq_stop(
PDQ_OS_DATABUF_T **buffers;
restart:
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
+ state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
if (state != PDQS_DMA_UNAVAILABLE) {
pdq_hwreset(pdq);
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
+ state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
PDQ_ASSERT(state == PDQS_DMA_UNAVAILABLE);
}
#if 0
@@ -1055,18 +1001,18 @@ pdq_stop(
case PDQS_RING_MEMBER:
case PDQS_LINK_UNAVAILABLE:
case PDQS_LINK_AVAILABLE: {
- *csrs->csr_port_data_a = PDQ_SUB_CMD_LINK_UNINIT;
- *csrs->csr_port_data_b = 0;
+ PDQ_CSR_WRITE(csrs, csr_port_data_a, PDQ_SUB_CMD_LINK_UNINIT);
+ PDQ_CSR_WRITE(csrs, csr_port_data_b, 0);
pdq_do_port_control(csrs, PDQ_PCTL_SUB_CMD);
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
+ state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
PDQ_ASSERT(state == PDQS_DMA_AVAILABLE);
/* FALL THROUGH */
}
case PDQS_DMA_AVAILABLE: {
- *csrs->csr_port_data_a = 0;
- *csrs->csr_port_data_b = 0;
+ PDQ_CSR_WRITE(csrs, csr_port_data_a, 0);
+ PDQ_CSR_WRITE(csrs, csr_port_data_b, 0);
pdq_do_port_control(csrs, PDQ_PCTL_DMA_UNINIT);
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
+ state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
PDQ_ASSERT(state == PDQS_DMA_UNAVAILABLE);
/* FALL THROUGH */
}
@@ -1092,14 +1038,15 @@ pdq_stop(
/*
* Disable interrupts and DMA.
*/
- *pdq->pdq_pci_csrs.csr_pfi_mode_control = 0;
- *pdq->pdq_pci_csrs.csr_pfi_status = 0x10;
+ PDQ_CSR_WRITE(&pdq->pdq_pci_csrs, csr_pfi_mode_control, 0);
+ PDQ_CSR_WRITE(&pdq->pdq_pci_csrs, csr_pfi_status, 0x10);
}
/*
* Flush all the databuf queues.
*/
pdq_flush_databuf_queue(&pdq->pdq_tx_info.tx_txq);
+ pdq->pdq_flags &= ~PDQ_TXOK;
buffers = (PDQ_OS_DATABUF_T **) pdq->pdq_rx_info.rx_buffers;
for (idx = 0; idx < PDQ_RING_SIZE(pdq->pdq_dbp->pdqdb_receives); idx++) {
if (buffers[idx] != NULL) {
@@ -1153,32 +1100,38 @@ pdq_stop(
*/
if (pdq->pdq_type == PDQ_DEFPA) {
#ifdef PDQTEST
- *pdq->pdq_pci_csrs.csr_pfi_mode_control = PDQ_PFI_MODE_DMA_ENABLE;
+ PDQ_CSR_WRITE(&pdq->pdq_pci_csrs, csr_pfi_mode_control,
+ PDQ_PFI_MODE_DMA_ENABLE);
#else
- *pdq->pdq_pci_csrs.csr_pfi_mode_control = PDQ_PFI_MODE_DMA_ENABLE
- |PDQ_PFI_MODE_PFI_PCI_INTR|PDQ_PFI_MODE_PDQ_PCI_INTR;
+ PDQ_CSR_WRITE(&pdq->pdq_pci_csrs, csr_pfi_mode_control,
+ PDQ_PFI_MODE_DMA_ENABLE
+ /*|PDQ_PFI_MODE_PFI_PCI_INTR*/|PDQ_PFI_MODE_PDQ_PCI_INTR);
#endif
}
/*
- * Make the unsolicited queue has events ...
+ * Make sure the unsolicited queue has events ...
*/
pdq_process_unsolicited_events(pdq);
- *csrs->csr_port_data_b = PDQ_DMA_BURST_8LW;
- *csrs->csr_port_data_a = PDQ_SUB_CMD_DMA_BURST_SIZE_SET;
+ if (pdq->pdq_type == PDQ_DEFEA && pdq->pdq_chip_rev == PDQ_CHIP_REV_E)
+ PDQ_CSR_WRITE(csrs, csr_port_data_b, PDQ_DMA_BURST_16LW);
+ else
+ PDQ_CSR_WRITE(csrs, csr_port_data_b, PDQ_DMA_BURST_8LW);
+ PDQ_CSR_WRITE(csrs, csr_port_data_a, PDQ_SUB_CMD_DMA_BURST_SIZE_SET);
pdq_do_port_control(csrs, PDQ_PCTL_SUB_CMD);
- *csrs->csr_port_data_b = 0;
- *csrs->csr_port_data_a = PDQ_OS_VA_TO_PA(pdq->pdq_cbp);
+ PDQ_CSR_WRITE(csrs, csr_port_data_b, 0);
+ PDQ_CSR_WRITE(csrs, csr_port_data_a, PDQ_OS_VA_TO_PA(pdq->pdq_cbp));
pdq_do_port_control(csrs, PDQ_PCTL_CONSUMER_BLOCK);
- *csrs->csr_port_data_b = 0;
- *csrs->csr_port_data_a = PDQ_OS_VA_TO_PA(pdq->pdq_dbp) | PDQ_DMA_INIT_LW_BSWAP_DATA;
+ PDQ_CSR_WRITE(csrs, csr_port_data_b, 0);
+ PDQ_CSR_WRITE(csrs, csr_port_data_a,
+ PDQ_OS_VA_TO_PA(pdq->pdq_dbp) | PDQ_DMA_INIT_LW_BSWAP_DATA);
pdq_do_port_control(csrs, PDQ_PCTL_DMA_INIT);
for (cnt = 0; cnt < 1000; cnt++) {
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
+ state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
if (state == PDQS_HALTED) {
if (pass > 0)
return PDQS_HALTED;
@@ -1193,8 +1146,8 @@ pdq_stop(
}
PDQ_ASSERT(state == PDQS_DMA_AVAILABLE);
- *csrs->csr_host_int_type_0 = 0xFF;
- *csrs->csr_host_int_enable = 0 /* PDQ_HOST_INT_STATE_CHANGE
+ PDQ_CSR_WRITE(csrs, csr_host_int_type_0, 0xFF);
+ PDQ_CSR_WRITE(csrs, csr_host_int_enable, 0) /* PDQ_HOST_INT_STATE_CHANGE
|PDQ_HOST_INT_FATAL_ERROR|PDQ_HOST_INT_CMD_RSP_ENABLE
|PDQ_HOST_INT_UNSOL_ENABLE */;
@@ -1216,7 +1169,7 @@ pdq_stop(
break;
PDQ_OS_USEC_DELAY(1000);
}
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
+ state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
}
return state;
@@ -1229,7 +1182,7 @@ pdq_run(
const pdq_csrs_t * const csrs = &pdq->pdq_csrs;
pdq_state_t state;
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
+ state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
PDQ_ASSERT(state != PDQS_DMA_UNAVAILABLE);
PDQ_ASSERT(state != PDQS_RESET);
PDQ_ASSERT(state != PDQS_HALTED);
@@ -1242,10 +1195,10 @@ pdq_run(
* So we need to clear all the errors/interrupts so the real
* ones will get through.
*/
- *csrs->csr_host_int_type_0 = 0xFF;
- *csrs->csr_host_int_enable = PDQ_HOST_INT_STATE_CHANGE|PDQ_HOST_INT_XMT_DATA_FLUSH
+ PDQ_CSR_WRITE(csrs, csr_host_int_type_0, 0xFF);
+ PDQ_CSR_WRITE(csrs, csr_host_int_enable, PDQ_HOST_INT_STATE_CHANGE|PDQ_HOST_INT_XMT_DATA_FLUSH
|PDQ_HOST_INT_FATAL_ERROR|PDQ_HOST_INT_CMD_RSP_ENABLE|PDQ_HOST_INT_UNSOL_ENABLE
- |PDQ_HOST_INT_RX_ENABLE|PDQ_HOST_INT_TX_ENABLE|PDQ_HOST_INT_HOST_SMT_ENABLE;
+ |PDQ_HOST_INT_RX_ENABLE|PDQ_HOST_INT_TX_ENABLE|PDQ_HOST_INT_HOST_SMT_ENABLE);
/*
* Set the MAC and address filters and start up the PDQ.
*/
@@ -1260,7 +1213,9 @@ pdq_run(
pdq->pdq_dbp->pdqdb_host_smt,
pdq->pdq_cbp->pdqcb_host_smt,
PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt));
- *csrs->csr_host_smt_producer = pdq->pdq_host_smt_info.rx_producer | (pdq->pdq_host_smt_info.rx_completion << 8);
+ PDQ_CSR_WRITE(csrs, csr_host_smt_producer,
+ pdq->pdq_host_smt_info.rx_producer
+ | (pdq->pdq_host_smt_info.rx_completion << 8));
}
pdq->pdq_command_info.ci_pending_commands = PDQ_BITMASK(PDQC_FILTER_SET)
| PDQ_BITMASK(PDQC_ADDR_FILTER_SET) | PDQ_BITMASK(PDQC_START);
@@ -1280,7 +1235,9 @@ pdq_run(
pdq->pdq_dbp->pdqdb_host_smt,
pdq->pdq_cbp->pdqcb_host_smt,
PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt));
- *csrs->csr_host_smt_producer = pdq->pdq_host_smt_info.rx_producer | (pdq->pdq_host_smt_info.rx_completion << 8);
+ PDQ_CSR_WRITE(csrs, csr_host_smt_producer,
+ pdq->pdq_host_smt_info.rx_producer
+ | (pdq->pdq_host_smt_info.rx_completion << 8));
}
pdq_process_unsolicited_events(pdq);
pdq_queue_commands(pdq);
@@ -1300,10 +1257,9 @@ pdq_interrupt(
int progress = 0;
if (pdq->pdq_type == PDQ_DEFPA)
- if (*pdq->pdq_pci_csrs.csr_pfi_status & 0x10)
- *pdq->pdq_pci_csrs.csr_pfi_status = 0x10;
+ PDQ_CSR_WRITE(&pdq->pdq_pci_csrs, csr_pfi_status, 0x18);
- while ((data = *csrs->csr_port_status) & PDQ_PSTS_INTR_PENDING) {
+ while ((data = PDQ_CSR_READ(csrs, csr_port_status)) & PDQ_PSTS_INTR_PENDING) {
progress = 1;
PDQ_PRINTF(("PDQ Interrupt: Status = 0x%08x\n", data));
if (data & PDQ_PSTS_RCV_DATA_PENDING) {
@@ -1318,7 +1274,7 @@ pdq_interrupt(
pdq->pdq_dbp->pdqdb_host_smt,
pdq->pdq_cbp->pdqcb_host_smt,
PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt));
- *csrs->csr_host_smt_producer = pdq->pdq_host_smt_info.rx_producer | (pdq->pdq_host_smt_info.rx_completion << 8);
+ PDQ_DO_HOST_SMT_PRODUCER(pdq);
}
if (data & PDQ_PSTS_XMT_DATA_PENDING)
pdq_process_transmitted_data(pdq);
@@ -1327,9 +1283,9 @@ pdq_interrupt(
if (data & PDQ_PSTS_CMD_RSP_PENDING)
pdq_process_command_responses(pdq);
if (data & PDQ_PSTS_TYPE_0_PENDING) {
- data = *csrs->csr_host_int_type_0;
+ data = PDQ_CSR_READ(csrs, csr_host_int_type_0);
if (data & PDQ_HOST_INT_STATE_CHANGE) {
- pdq_state_t state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
+ pdq_state_t state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
printf(PDQ_OS_PREFIX "%s", PDQ_OS_PREFIX_ARGS, pdq_adapter_states[state]);
if (state == PDQS_LINK_UNAVAILABLE) {
pdq->pdq_flags &= ~PDQ_TXOK;
@@ -1338,12 +1294,12 @@ pdq_interrupt(
pdq_os_restart_transmitter(pdq);
} else if (state == PDQS_HALTED) {
pdq_response_error_log_get_t log_entry;
- pdq_halt_code_t halt_code = PDQ_PSTS_HALT_ID(*csrs->csr_port_status);
+ pdq_halt_code_t halt_code = PDQ_PSTS_HALT_ID(PDQ_CSR_READ(csrs, csr_port_status));
printf(": halt code = %d (%s)\n",
halt_code, pdq_halt_codes[halt_code]);
- if (halt_code == PDQH_DMA_ERROR) {
+ if (halt_code == PDQH_DMA_ERROR && pdq->pdq_type == PDQ_DEFPA) {
PDQ_PRINTF(("\tPFI status = 0x%x, Host 0 Fatal Interrupt = 0x%x\n",
- *pdq->pdq_pci_csrs.csr_pfi_status,
+ PDQ_CSR_READ(&pdq->pdq_pci_csrs, csr_pfi_status),
data & PDQ_HOST_INT_FATAL_ERROR));
}
pdq_read_error_log(pdq, &log_entry);
@@ -1353,7 +1309,7 @@ pdq_interrupt(
return 1;
}
printf("\n");
- *csrs->csr_host_int_type_0 = PDQ_HOST_INT_STATE_CHANGE;
+ PDQ_CSR_WRITE(csrs, csr_host_int_type_0, PDQ_HOST_INT_STATE_CHANGE);
}
if (data & PDQ_HOST_INT_FATAL_ERROR) {
pdq_stop(pdq);
@@ -1366,19 +1322,19 @@ pdq_interrupt(
pdq->pdq_flags &= ~PDQ_TXOK;
pdq_flush_transmitter(pdq);
pdq_do_port_control(csrs, PDQ_PCTL_XMT_DATA_FLUSH_DONE);
- *csrs->csr_host_int_type_0 = PDQ_HOST_INT_XMT_DATA_FLUSH;
+ PDQ_CSR_WRITE(csrs, csr_host_int_type_0, PDQ_HOST_INT_XMT_DATA_FLUSH);
}
}
if (pdq->pdq_type == PDQ_DEFPA)
- if (*pdq->pdq_pci_csrs.csr_pfi_status & 0x10)
- *pdq->pdq_pci_csrs.csr_pfi_status = 0x10;
+ PDQ_CSR_WRITE(&pdq->pdq_pci_csrs, csr_pfi_status, 0x18);
}
return progress;
}
pdq_t *
pdq_initialize(
- void *csr_va,
+ pdq_bus_t bus,
+ pdq_bus_memaddr_t csr_base,
const char *name,
int unit,
void *ctx,
@@ -1489,42 +1445,39 @@ pdq_initialize(
/*
* Initialize the CSR references.
+ * the DEFAA (FutureBus+) skips a longword between registers
*/
- pdq_init_csrs(&pdq->pdq_csrs, csr_va, 1);
- switch (pdq->pdq_type) {
- case PDQ_DEFPA: pdq_init_pci_csrs(&pdq->pdq_pci_csrs, csr_va, 1); break;
-#ifdef PDQ_DO_EISA
- case PDQ_DEFEA: pdq_init_esia_csrs(&pdq->pdq_eisa_csrs, csr_va, 1); break;
-#endif
- }
+ pdq_init_csrs(&pdq->pdq_csrs, bus, csr_base, pdq->pdq_type == PDQ_DEFAA ? 2 : 1);
+ if (pdq->pdq_type == PDQ_DEFPA)
+ pdq_init_pci_csrs(&pdq->pdq_pci_csrs, bus, csr_base, 1);
- PDQ_PRINTF(("PDQ CSRs:\n"));
+ PDQ_PRINTF(("PDQ CSRs: BASE = %x\n", pdq->pdq_csrs.csr_base));
PDQ_PRINTF((" Port Reset = %x [0x%08x]\n",
- pdq->pdq_csrs.csr_port_reset, *pdq->pdq_csrs.csr_port_reset));
+ pdq->pdq_csrs.csr_port_reset, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_reset)));
PDQ_PRINTF((" Host Data = %x [0x%08x]\n",
- pdq->pdq_csrs.csr_host_data, *pdq->pdq_csrs.csr_host_data));
+ pdq->pdq_csrs.csr_host_data, PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_data)));
PDQ_PRINTF((" Port Control = %x [0x%08x]\n",
- pdq->pdq_csrs.csr_port_control, *pdq->pdq_csrs.csr_port_control));
+ pdq->pdq_csrs.csr_port_control, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_control)));
PDQ_PRINTF((" Port Data A = %x [0x%08x]\n",
- pdq->pdq_csrs.csr_port_data_a, *pdq->pdq_csrs.csr_port_data_a));
+ pdq->pdq_csrs.csr_port_data_a, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_data_a)));
PDQ_PRINTF((" Port Data B = %x [0x%08x]\n",
- pdq->pdq_csrs.csr_port_data_b, *pdq->pdq_csrs.csr_port_data_b));
+ pdq->pdq_csrs.csr_port_data_b, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_data_b)));
PDQ_PRINTF((" Port Status = %x [0x%08x]\n",
- pdq->pdq_csrs.csr_port_status, *pdq->pdq_csrs.csr_port_status));
+ pdq->pdq_csrs.csr_port_status, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_status)));
PDQ_PRINTF((" Host Int Type 0 = %x [0x%08x]\n",
- pdq->pdq_csrs.csr_host_int_type_0, *pdq->pdq_csrs.csr_host_int_type_0));
+ pdq->pdq_csrs.csr_host_int_type_0, PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_int_type_0)));
PDQ_PRINTF((" Host Int Enable = %x [0x%08x]\n",
- pdq->pdq_csrs.csr_host_int_enable, *pdq->pdq_csrs.csr_host_int_enable));
+ pdq->pdq_csrs.csr_host_int_enable, PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_int_enable)));
PDQ_PRINTF((" Type 2 Producer = %x [0x%08x]\n",
- pdq->pdq_csrs.csr_type_2_producer, *pdq->pdq_csrs.csr_type_2_producer));
+ pdq->pdq_csrs.csr_type_2_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_type_2_producer)));
PDQ_PRINTF((" Command Response Producer = %x [0x%08x]\n",
- pdq->pdq_csrs.csr_cmd_response_producer, *pdq->pdq_csrs.csr_cmd_response_producer));
+ pdq->pdq_csrs.csr_cmd_response_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_cmd_response_producer)));
PDQ_PRINTF((" Command Request Producer = %x [0x%08x]\n",
- pdq->pdq_csrs.csr_cmd_request_producer, *pdq->pdq_csrs.csr_cmd_request_producer));
+ pdq->pdq_csrs.csr_cmd_request_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_cmd_request_producer)));
PDQ_PRINTF((" Host SMT Producer = %x [0x%08x]\n",
- pdq->pdq_csrs.csr_host_smt_producer, *pdq->pdq_csrs.csr_host_smt_producer));
+ pdq->pdq_csrs.csr_host_smt_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_smt_producer)));
PDQ_PRINTF((" Unsolicited Producer = %x [0x%08x]\n",
- pdq->pdq_csrs.csr_unsolicited_producer, *pdq->pdq_csrs.csr_unsolicited_producer));
+ pdq->pdq_csrs.csr_unsolicited_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_unsolicited_producer)));
/*
* Initialize the command information block
@@ -1582,7 +1535,7 @@ pdq_initialize(
pdq->pdq_tx_info.tx_hdrdesc.txd_sop = 1;
pdq->pdq_tx_info.tx_hdrdesc.txd_pa_lo = PDQ_OS_VA_TO_PA(pdq->pdq_tx_hdr);
- state = PDQ_PSTS_ADAPTER_STATE(*pdq->pdq_csrs.csr_port_status);
+ state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_status));
PDQ_PRINTF(("PDQ Adapter State = %s\n", pdq_adapter_states[state]));
/*
@@ -1596,6 +1549,16 @@ pdq_initialize(
* If the adapter is not the state we expect, then the initialization
* failed. Cleanup and exit.
*/
+#if defined(PDQVERBOSE)
+ if (state == PDQS_HALTED) {
+ pdq_halt_code_t halt_code = PDQ_PSTS_HALT_ID(PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_status));
+ printf("Halt code = %d (%s)\n", halt_code, pdq_halt_codes[halt_code]);
+ if (halt_code == PDQH_DMA_ERROR && pdq->pdq_type == PDQ_DEFPA)
+ PDQ_PRINTF(("PFI status = 0x%x, Host 0 Fatal Interrupt = 0x%x\n",
+ PDQ_CSR_READ(&pdq->pdq_pci_csrs, csr_pfi_status),
+ PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_int_type_0) & PDQ_HOST_INT_FATAL_ERROR));
+ }
+#endif
if (state == PDQS_RESET || state == PDQS_HALTED || state == PDQS_UPGRADE)
goto cleanup_and_return;
diff --git a/sys/dev/ic/pdq_ifsubr.c b/sys/dev/ic/pdq_ifsubr.c
index 4526538ab41..9435e716c18 100644
--- a/sys/dev/ic/pdq_ifsubr.c
+++ b/sys/dev/ic/pdq_ifsubr.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: pdq_ifsubr.c,v 1.2 1996/05/10 12:41:12 deraadt Exp $ */
-/* $NetBSD: pdq_ifsubr.c,v 1.3 1996/05/07 01:43:15 thorpej Exp $ */
+/* $OpenBSD: pdq_ifsubr.c,v 1.3 1996/05/26 00:27:03 deraadt Exp $ */
+/* $NetBSD: pdq_ifsubr.c,v 1.5 1996/05/20 00:26:21 thorpej Exp $ */
/*-
- * Copyright (c) 1995 Matt Thomas (thomas@lkg.dec.com)
+ * Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,80 +24,19 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * from Id: pdq_ifsubr.c,v 1.2 1995/08/20 18:59:00 thomas Exp
- *
- * Log: pdq_ifsubr.c,v
- * Revision 1.2 1995/08/20 18:59:00 thomas
- * Changes for NetBSD
- *
- * Revision 1.1 1995/08/20 15:43:49 thomas
- * Initial revision
- *
- * Revision 1.13 1995/08/04 21:54:56 thomas
- * Clean IRQ processing under BSD/OS.
- * A receive tweaks. (print source of MAC CRC errors, etc.)
- *
- * Revision 1.12 1995/06/02 16:04:22 thomas
- * Use correct PCI defs for BSDI now that they have fixed them.
- * Increment the slot number 0x1000, not one! (*duh*)
- *
- * Revision 1.11 1995/04/21 13:23:55 thomas
- * Fix a few pub in the DEFPA BSDI support
- *
- * Revision 1.10 1995/04/20 21:46:42 thomas
- * Why???
- * ,
- *
- * Revision 1.9 1995/04/20 20:17:33 thomas
- * Add PCI support for BSD/OS.
- * Fix BSD/OS EISA support.
- * Set latency timer for DEFPA to recommended value if 0.
- *
- * Revision 1.8 1995/04/04 22:54:29 thomas
- * Fix DEFEA support
- *
- * Revision 1.7 1995/03/14 01:52:52 thomas
- * Update for new FreeBSD PCI Interrupt interface
- *
- * Revision 1.6 1995/03/10 17:06:59 thomas
- * Update for latest version of FreeBSD.
- * Compensate for the fast that the ifp will not be first thing
- * in softc on BSDI.
- *
- * Revision 1.5 1995/03/07 19:59:42 thomas
- * First pass at BSDI EISA support
- *
- * Revision 1.4 1995/03/06 17:06:03 thomas
- * Add transmit timeout support.
- * Add support DEFEA (untested).
- *
- * Revision 1.3 1995/03/03 13:48:35 thomas
- * more fixes
- *
+ * Id: pdq_ifsubr.c,v 1.6 1996/05/16 14:25:26 thomas Exp
*
*/
/*
* DEC PDQ FDDI Controller; code for BSD derived operating systems
*
- * Written by Matt Thomas
- *
- * This driver supports the following FDDI controllers:
- *
- * Device: Config file entry:
- * DEC DEFPA (PCI) device fpa0
- * DEC DEFEA (EISA) device fea0 at isa0 net irq ? vector feaintr
- *
- * Eventually, the following adapters will also be supported:
- *
- * DEC DEFTA (TC) device fta0 at tc? slot * vector ftaintr
- * DEC DEFQA (Q-Bus) device fta0 at uba? csr 0?? vector fqaintr
- * DEC DEFAA (FB+) device faa0 at fbus? slot * vector faaintr
+ * This module provide bus independent BSD specific O/S functions.
+ * (ie. it provides an ifnet interface to the rest of the system)
*/
#include <sys/param.h>
-#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
@@ -135,6 +74,10 @@
#include <net/if_fddi.h>
#endif
+#if defined(__bsdi__) && _BSDI_VERSION < 199401
+#include <i386/isa/isavar.h>
+#endif
+
#ifdef NS
#include <netns/ns.h>
#include <netns/ns_if.h>
@@ -144,12 +87,23 @@
#include <vm/vm_kern.h>
#include <vm/vm_param.h>
-#include "pdqreg.h"
-#if defined(__NetBSD__)
#include "pdqvar.h"
-#else
-#include "pdq_os.h"
+#include "pdqreg.h"
+
+#if defined(__bsdi__) && _BSDI_VERSION < 199506 /* XXX */
+static void
+arp_ifinit(
+ struct arpcom *ac,
+ struct ifaddr *ifa)
+{
+ sc->sc_ac.ac_ipaddr = IA_SIN(ifa)->sin_addr;
+ arpwhohas(&sc->sc_ac, &IA_SIN(ifa)->sin_addr);
+#if _BSDI_VERSION >= 199401
+ ifa->ifa_rtrequest = arp_rtrequest;
+ ifa->ifa_flags |= RTF_CLONING;
#endif
+#endif
+
void
pdq_ifinit(
@@ -183,18 +137,18 @@ pdq_ifinit(
void
pdq_ifwatchdog(
- pdq_softc_t *sc)
+ struct ifnet *ifp)
{
- struct mbuf *m;
/*
* No progress was made on the transmit queue for PDQ_OS_TX_TRANSMIT
* seconds. Remove all queued packets.
*/
- sc->sc_if.if_flags &= ~IFF_OACTIVE;
- sc->sc_if.if_timer = 0;
+ ifp->if_flags &= ~IFF_OACTIVE;
+ ifp->if_timer = 0;
for (;;) {
- IF_DEQUEUE(&sc->sc_if.if_snd, m);
+ struct mbuf *m;
+ IF_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
return;
m_freem(m);
@@ -247,7 +201,7 @@ pdq_os_receive_pdu(
sc->sc_if.if_ipackets++;
#if NBPFILTER > 0
if (sc->sc_bpf != NULL)
- bpf_mtap(sc->sc_bpf, m);
+ PDQ_BPF_MTAP(sc, m);
if ((fh->fddi_fc & (FDDIFC_L|FDDIFC_F)) != FDDIFC_LLC_ASYNC) {
m_freem(m);
return;
@@ -283,7 +237,7 @@ pdq_os_transmit_done(
pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
#if NBPFILTER > 0
if (sc->sc_bpf != NULL)
- bpf_mtap(sc->sc_bpf, m);
+ PDQ_BPF_MTAP(sc, m);
#endif
m_freem(m);
sc->sc_if.if_opackets++;
@@ -327,22 +281,15 @@ pdq_ifioctl(
ifp->if_flags |= IFF_UP;
switch(ifa->ifa_addr->sa_family) {
-#ifdef INET
+#if defined(INET)
case AF_INET: {
- sc->sc_ac.ac_ipaddr = IA_SIN(ifa)->sin_addr;
pdq_ifinit(sc);
-#if !defined(__bsdi__)
arp_ifinit(&sc->sc_ac, ifa);
-#else
- arpwhohas(&sc->sc_ac, &IA_SIN(ifa)->sin_addr);
- ifa->ifa_rtrequest = arp_rtrequest;
- ifa->ifa_flags |= RTF_CLONING;
-#endif
break;
}
#endif /* INET */
-#ifdef NS
+#if defined(NS)
/* This magic copied from if_is.c; I don't use XNS,
* so I have no way of telling if this actually
* works or not.
@@ -404,20 +351,24 @@ pdq_ifioctl(
return error;
}
+#ifndef IFF_NOTRAILERS
+#define IFF_NOTRAILERS 0
+#endif
+
void
pdq_ifattach(
pdq_softc_t *sc,
- pdq_ifinit_t ifinit,
- pdq_ifwatchdog_t ifwatchdog)
+ ifnet_ret_t (*ifwatchdog)(int unit))
{
struct ifnet *ifp = &sc->sc_if;
ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST;
-#if !defined(__NetBSD__)
- ifp->if_init = ifinit;
-#endif
+#if (defined(__FreeBSD__) && BSD >= 199506) || defined(__NetBSD__)
+ ifp->if_watchdog = pdq_ifwatchdog;
+#else
ifp->if_watchdog = ifwatchdog;
+#endif
ifp->if_ioctl = pdq_ifioctl;
ifp->if_output = fddi_output;
@@ -426,6 +377,6 @@ pdq_ifattach(
if_attach(ifp);
fddi_ifattach(ifp);
#if NBPFILTER > 0
- bpfattach(&sc->sc_bpf, ifp, DLT_FDDI, sizeof(struct fddi_header));
+ PDQ_BPFATTACH(sc, DLT_FDDI, sizeof(struct fddi_header));
#endif
}
diff --git a/sys/dev/ic/pdqreg.h b/sys/dev/ic/pdqreg.h
index 8dd9a28dd58..a8850f08b19 100644
--- a/sys/dev/ic/pdqreg.h
+++ b/sys/dev/ic/pdqreg.h
@@ -1,8 +1,8 @@
-/* $OpenBSD: pdqreg.h,v 1.2 1996/04/18 23:47:24 niklas Exp $ */
-/* $NetBSD: pdqreg.h,v 1.3 1996/03/11 21:41:33 thorpej Exp $ */
+/* $OpenBSD: pdqreg.h,v 1.3 1996/05/26 00:27:04 deraadt Exp $ */
+/* $NetBSD: pdqreg.h,v 1.4 1996/05/20 00:26:23 thorpej Exp $ */
/*-
- * Copyright (c) 1995 Matt Thomas (thomas@lkg.dec.com)
+ * Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,33 +24,13 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * Id: pdqreg.h,v 1.6 1995/06/03 15:43:26 thomas Exp
- *
- * Log: pdqreg.h,v
- * Revision 1.6 1995/06/03 15:43:26 thomas
- * Fix the command submission logic to only submit one
- * command at a time no matter what. This simplies the
- * code significantly thereby allowing us to do some up
- * front optimizations.
- *
- * Revision 1.5 1995/03/10 17:41:55 thomas
- * Add DEFTA, DEFQA, and DEFAA
- *
- * Revision 1.4 1995/03/06 17:07:05 thomas
- * Add copyright/disclaimer
- * Add EISA register definitions
- *
- * Revision 1.3 1995/03/03 13:48:35 thomas
- * more fixes
- *
+ * Id: pdqreg.h,v 1.9 1996/05/16 14:25:26 thomas Exp
*
*/
/*
* DEC PDQ FDDI Controller; PDQ port driver definitions
*
- * Written by Matt Thomas
- *
*/
#ifndef _PDQREG_H
@@ -88,21 +68,17 @@
#define PDQ_FDDI_PH1 0x38
#define PDQ_FDDI_PH2 0x00
-typedef unsigned int pdq_uint32_t;
-typedef unsigned short pdq_uint16_t;
-typedef unsigned char pdq_uint8_t;
-
typedef pdq_uint32_t pdq_physaddr_t;
-typedef struct {
+struct _pdq_lanaddr_t {
pdq_uint8_t lanaddr_bytes[8];
-} pdq_lanaddr_t;
+};
typedef struct {
pdq_uint8_t fwrev_bytes[4];
} pdq_fwrev_t;
-typedef enum {
+enum _pdq_state_t {
PDQS_RESET=0,
PDQS_UPGRADE=1,
PDQS_DMA_UNAVAILABLE=2,
@@ -111,30 +87,34 @@ typedef enum {
PDQS_LINK_UNAVAILABLE=5,
PDQS_HALTED=6,
PDQS_RING_MEMBER=7
-} pdq_state_t;
+};
-typedef struct {
- volatile pdq_uint32_t *csr_port_reset; /* 0x00 [RW] */
- volatile pdq_uint32_t *csr_host_data; /* 0x04 [R] */
- volatile pdq_uint32_t *csr_port_control; /* 0x08 [RW] */
- volatile pdq_uint32_t *csr_port_data_a; /* 0x0C [RW] */
- volatile pdq_uint32_t *csr_port_data_b; /* 0x10 [RW] */
- volatile pdq_uint32_t *csr_port_status; /* 0x14 [R] */
- volatile pdq_uint32_t *csr_host_int_type_0; /* 0x18 [RW] */
- volatile pdq_uint32_t *csr_host_int_enable; /* 0x1C [RW] */
- volatile pdq_uint32_t *csr_type_2_producer; /* 0x20 [RW] */
- volatile pdq_uint32_t *csr_cmd_response_producer; /* 0x28 [RW] */
- volatile pdq_uint32_t *csr_cmd_request_producer; /* 0x2C [RW] */
- volatile pdq_uint32_t *csr_host_smt_producer; /* 0x30 [RW] */
- volatile pdq_uint32_t *csr_unsolicited_producer; /* 0x34 [RW] */
-} pdq_csrs_t;
+struct _pdq_csrs_t {
+ pdq_bus_memoffset_t csr_port_reset; /* 0x00 [RW] */
+ pdq_bus_memoffset_t csr_host_data; /* 0x04 [R] */
+ pdq_bus_memoffset_t csr_port_control; /* 0x08 [RW] */
+ pdq_bus_memoffset_t csr_port_data_a; /* 0x0C [RW] */
+ pdq_bus_memoffset_t csr_port_data_b; /* 0x10 [RW] */
+ pdq_bus_memoffset_t csr_port_status; /* 0x14 [R] */
+ pdq_bus_memoffset_t csr_host_int_type_0; /* 0x18 [RW] */
+ pdq_bus_memoffset_t csr_host_int_enable; /* 0x1C [RW] */
+ pdq_bus_memoffset_t csr_type_2_producer; /* 0x20 [RW] */
+ pdq_bus_memoffset_t csr_cmd_response_producer; /* 0x28 [RW] */
+ pdq_bus_memoffset_t csr_cmd_request_producer; /* 0x2C [RW] */
+ pdq_bus_memoffset_t csr_host_smt_producer; /* 0x30 [RW] */
+ pdq_bus_memoffset_t csr_unsolicited_producer; /* 0x34 [RW] */
+ pdq_bus_t csr_bus;
+ pdq_bus_memaddr_t csr_base;
+};
-typedef struct {
- volatile pdq_uint32_t *csr_pfi_mode_control; /* 0x40 [RW] */
- volatile pdq_uint32_t *csr_pfi_status; /* 0x44 [RW] */
- volatile pdq_uint32_t *csr_fifo_write; /* 0x48 [RW] */
- volatile pdq_uint32_t *csr_fifo_read; /* 0x4C [RW] */
-} pdq_pci_csrs_t;
+struct _pdq_pci_csrs_t {
+ pdq_bus_memoffset_t csr_pfi_mode_control; /* 0x40 [RW] */
+ pdq_bus_memoffset_t csr_pfi_status; /* 0x44 [RW] */
+ pdq_bus_memoffset_t csr_fifo_write; /* 0x48 [RW] */
+ pdq_bus_memoffset_t csr_fifo_read; /* 0x4C [RW] */
+ pdq_bus_t csr_bus;
+ pdq_bus_memaddr_t csr_base;
+};
#define PDQ_PFI_MODE_DMA_ENABLE 0x01 /* DMA Enable */
#define PDQ_PFI_MODE_PFI_PCI_INTR 0x02 /* PFI-to-PCI Int Enable */
@@ -189,6 +169,11 @@ typedef struct {
#define PDQ_EISA_OUTPUT_PORT 0x0CAD
#define PDQ_EISA_FUNCTION_CTRL 0x0CAE
+#define PDQ_TC_CSR_OFFSET 0x00100000
+#define PDQ_TC_CSR_SPACE 0x0040
+#define PDQ_FBUS_CSR_OFFSET 0x00200000
+#define PDQ_FBUS_CSR_SPACE 0x0080
+
/*
* Port Reset Data A Definitions
*/
@@ -370,14 +355,6 @@ typedef struct {
#endif
} pdq_descriptor_block_t;
-typedef enum {
- PDQ_DEFPA, /* PCI-bus */
- PDQ_DEFEA, /* EISA-bus */
- PDQ_DEFTA, /* TurboChannel */
- PDQ_DEFAA, /* FutureBus+ */
- PDQ_DEFQA /* Q-bus */
-} pdq_type_t;
-
typedef struct {
/*
* These value manage the available space in command/response
@@ -416,10 +393,17 @@ typedef struct {
#define PDQ_RX_FC_OFFSET (sizeof(pdq_rxstatus_t) + 3)
#define PDQ_RX_SEGCNT ((PDQ_FDDI_MAX + PDQ_OS_DATABUF_SIZE - 1) / PDQ_OS_DATABUF_SIZE)
#define PDQ_DO_TYPE2_PRODUCER(pdq) \
- (*pdq->pdq_csrs.csr_type_2_producer = (pdq->pdq_rx_info.rx_producer << 0) \
- | (pdq->pdq_tx_info.tx_producer << 8) \
- | (pdq->pdq_rx_info.rx_completion << 16) \
- | (pdq->pdq_tx_info.tx_completion << 24))
+ PDQ_CSR_WRITE(&(pdq)->pdq_csrs, csr_type_2_producer, \
+ ((pdq)->pdq_rx_info.rx_producer << 0) \
+ | ((pdq)->pdq_tx_info.tx_producer << 8) \
+ | ((pdq)->pdq_rx_info.rx_completion << 16) \
+ | ((pdq)->pdq_tx_info.tx_completion << 24))
+
+#define PDQ_DO_HOST_SMT_PRODUCER(pdq) \
+ PDQ_CSR_WRITE(&(pdq)->pdq_csrs, csr_host_smt_producer, \
+ ((pdq)->pdq_host_smt_info.rx_producer << 0) \
+ | ((pdq)->pdq_host_smt_info.rx_completion << 8))\
+
#define PDQ_ADVANCE(n, a, m) ((n) = ((n) + (a)) & (m))
typedef struct {
@@ -446,7 +430,7 @@ typedef struct {
pdq_uint32_t tx_completion;
} pdq_tx_info_t;
-typedef struct {
+struct _pdq_t {
pdq_csrs_t pdq_csrs;
pdq_pci_csrs_t pdq_pci_csrs;
pdq_type_t pdq_type;
@@ -471,7 +455,7 @@ typedef struct {
pdq_rx_info_t pdq_rx_info;
pdq_rx_info_t pdq_host_smt_info;
pdq_uint8_t pdq_tx_hdr[3];
-} pdq_t;
+};
typedef enum {
PDQC_START=0,
@@ -576,10 +560,10 @@ typedef enum {
PDQI_FULL_DUPLEX_ENABLE=44
} pdq_item_code_t;
-typedef enum {
+enum _pdq_boolean_t {
PDQ_FALSE=0,
PDQ_TRUE=1
-} pdq_boolean_t;
+};
typedef enum {
PDQ_FILTER_BLOCK=0,
diff --git a/sys/dev/ic/pdqvar.h b/sys/dev/ic/pdqvar.h
index 3b40d483578..b8eaab5d6da 100644
--- a/sys/dev/ic/pdqvar.h
+++ b/sys/dev/ic/pdqvar.h
@@ -1,8 +1,8 @@
-/* $OpenBSD: pdqvar.h,v 1.3 1996/05/10 12:41:13 deraadt Exp $ */
-/* $NetBSD: pdqvar.h,v 1.5 1996/05/07 01:43:17 thorpej Exp $ */
+/* $OpenBSD: pdqvar.h,v 1.4 1996/05/26 00:27:05 deraadt Exp $ */
+/* $NetBSD: pdqvar.h,v 1.6 1996/05/20 00:26:26 thorpej Exp $ */
/*-
- * Copyright (c) 1995 Matt Thomas (thomas@lkg.dec.com)
+ * Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,40 +24,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * from Id: pdq_os.h,v 1.11 1995/08/20 18:59:00 thomas Exp
- *
- * Log: pdq_os.h,v
- * Revision 1.11 1995/08/20 18:59:00 thomas
- * Changes for NetBSD
- *
- * Revision 1.10 1995/08/16 22:57:28 thomas
- * Add support for NetBSD
- *
- * Revision 1.9 1995/06/21 18:29:27 thomas
- * SVR4.2 changes
- *
- * Revision 1.8 1995/06/12 17:49:37 thomas
- * Add SVR4.2 support
- *
- * Revision 1.7 1995/04/20 20:17:33 thomas
- * Add PCI support for BSD/OS.
- * Fix BSD/OS EISA support.
- * Set latency timer for DEFPA to recommended value if 0.
- *
- * Revision 1.6 1995/03/14 01:52:52 thomas
- * Update for new FreeBSD PCI Interrupt interface
- * Use inl/inb/... inline macros provided by FreeBSD and BSDI
- *
- * Revision 1.5 1995/03/10 17:42:24 thomas
- * More changes for BSDI
- *
- * Revision 1.4 1995/03/06 17:08:56 thomas
- * Add copyright/disclaimer
- * Add inx/outx macros
- *
- * Revision 1.3 1995/03/03 13:48:35 thomas
- * more fixes
- *
+ * Id: pdqvar.h,v 1.17 1996/05/17 01:15:18 thomas Exp
*
*/
@@ -73,11 +40,31 @@
#define PDQ_OS_TX_TIMEOUT 5 /* seconds */
+typedef struct _pdq_t pdq_t;
+typedef struct _pdq_csrs_t pdq_csrs_t;
+typedef struct _pdq_pci_csrs_t pdq_pci_csrs_t;
+typedef struct _pdq_lanaddr_t pdq_lanaddr_t;
+typedef unsigned int pdq_uint32_t;
+typedef unsigned short pdq_uint16_t;
+typedef unsigned char pdq_uint8_t;
+typedef enum _pdq_boolean_t pdq_boolean_t;
+typedef enum _pdq_type_t pdq_type_t;
+typedef enum _pdq_state_t pdq_state_t;
+
+enum _pdq_type_t {
+ PDQ_DEFPA, /* PCI-bus */
+ PDQ_DEFEA, /* EISA-bus */
+ PDQ_DEFTA, /* TurboChannel */
+ PDQ_DEFAA, /* FutureBus+ */
+ PDQ_DEFQA /* Q-bus */
+};
+
#if defined(PDQTEST)
#include <pdq_os_test.h>
#elif defined(__FreeBSD__) || defined(__bsdi__) || defined(__NetBSD__)
#include <sys/param.h>
+#include <sys/systm.h>
#ifndef M_MCAST
#include <sys/mbuf.h>
#endif /* M_CAST */
@@ -86,13 +73,21 @@
#include <vm/vm_kern.h>
#define PDQ_USE_MBUFS
+#if defined(__NetBSD__)
+#define PDQ_OS_PREFIX "%s: "
+#define PDQ_OS_PREFIX_ARGS pdq->pdq_os_name
+#else
#define PDQ_OS_PREFIX "%s%d: "
#define PDQ_OS_PREFIX_ARGS pdq->pdq_os_name, pdq->pdq_unit
-
+#endif
#define PDQ_OS_PAGESIZE NBPG
#define PDQ_OS_USEC_DELAY(n) DELAY(n)
#define PDQ_OS_MEMZERO(p, n) bzero((caddr_t)(p), (n))
+#if defined(__NetBSD__) && defined(__alpha__)
+#define PDQ_OS_VA_TO_PA(p) (vtophys(p) | 0x40000000)
+#else
#define PDQ_OS_VA_TO_PA(p) vtophys(p)
+#endif
#define PDQ_OS_MEMALLOC(n) malloc(n, M_DEVBUF, M_NOWAIT)
#define PDQ_OS_MEMFREE(p, n) free((void *) p, M_DEVBUF)
#ifdef __FreeBSD__
@@ -104,27 +99,93 @@
#endif /* __FreeBSD__ */
#if defined(__FreeBSD__)
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
#include <machine/cpufunc.h>
#include <machine/clock.h>
typedef void ifnet_ret_t;
typedef int ioctl_cmd_t;
+typedef enum { PDQ_BUS_EISA, PDQ_BUS_PCI } pdq_bus_t;
+typedef u_int16_t pdq_bus_ioport_t;
+typedef volatile pdq_uint32_t *pdq_bus_memaddr_t;
+typedef pdq_bus_memaddr_t pdq_bus_memoffset_t;
+#if BSD >= 199506 /* __FreeBSD__ */
+#define PDQ_BPF_MTAP(sc, m) bpf_mtap(&(sc)->sc_if, m)
+#define PDQ_BPFATTACH(sc, t, s) bpfattach(&(sc)->sc_if, t, s)
+#endif
+
+
#elif defined(__bsdi__)
#include <machine/inline.h>
typedef int ifnet_ret_t;
typedef int ioctl_cmd_t;
+typedef enum { PDQ_BUS_EISA, PDQ_BUS_PCI } pdq_bus_t;
+typedef u_int16_t pdq_bus_ioport_t;
+typedef volatile pdq_uint32_t *pdq_bus_memaddr_t;
+typedef pdq_bus_memaddr_t pdq_bus_memoffset_t;
+
+
#elif defined(__NetBSD__)
+#include <machine/bus.h>
+#include <machine/intr.h>
typedef void ifnet_ret_t;
typedef u_long ioctl_cmd_t;
+typedef bus_chipset_tag_t pdq_bus_t;
+typedef bus_io_handle_t pdq_bus_ioport_t;
+#if defined(PDQ_IOMAPPED)
+typedef bus_io_handle_t pdq_bus_memaddr_t;
+#else
+typedef bus_mem_handle_t pdq_bus_memaddr_t;
+#endif
+typedef pdq_uint32_t pdq_bus_memoffset_t;
+#define PDQ_OS_IOMEM
+#define PDQ_OS_IORD_32(t, base, offset) bus_io_read_4 (t, base, offset)
+#define PDQ_OS_IOWR_32(t, base, offset, data) bus_io_write_4 (t, base, offset, data)
+#define PDQ_OS_IORD_8(t, base, offset) bus_io_read_1 (t, base, offset)
+#define PDQ_OS_IOWR_8(t, base, offset, data) bus_io_write_1 (t, base, offset, data)
+#define PDQ_OS_MEMRD_32(t, base, offset) bus_mem_read_4(t, base, offset)
+#define PDQ_OS_MEMWR_32(t, base, offset, data) bus_mem_write_4(t, base, offset, data)
+#define PDQ_CSR_OFFSET(base, offset) (0 + (offset)*sizeof(pdq_uint32_t))
+
+#if defined(PDQ_IOMAPPED)
+#define PDQ_CSR_WRITE(csr, name, data) PDQ_OS_IOWR_32((csr)->csr_bus, (csr)->csr_base, (csr)->name, data)
+#define PDQ_CSR_READ(csr, name) PDQ_OS_IORD_32((csr)->csr_bus, (csr)->csr_base, (csr)->name)
+#else
+#define PDQ_CSR_WRITE(csr, name, data) PDQ_OS_MEMWR_32((csr)->csr_bus, (csr)->csr_base, (csr)->name, data)
+#define PDQ_CSR_READ(csr, name) PDQ_OS_MEMRD_32((csr)->csr_bus, (csr)->csr_base, (csr)->name)
+#endif
+
+#endif
+
+#if !defined(PDQ_BPF_MTAP)
+#define PDQ_BPF_MTAP(sc, m) bpf_mtap((sc)->sc_bpf, m)
+#endif
+
+#if !defined(PDQ_BPFATTACH)
+#define PDQ_BPFATTACH(sc, t, s) bpfattach(&(sc)->sc_bpf, &(sc)->sc_if, t, s)
+#endif
+
+#if !defined(PDQ_OS_IOMEM)
+#define PDQ_OS_IORD_32(t, base, offset) inl((base) + (offset))
+#define PDQ_OS_IOWR_32(t, base, offset, data) outl((base) + (offset), data)
+#define PDQ_OS_IORD_8(t, base, offset) inb((base) + (offset))
+#define PDQ_OS_IOWR_8(t, base, offset, data) outb((base) + (offset), data)
+#define PDQ_OS_MEMRD_32(t, base, offset) (0 + *((base) + (offset)))
+#define PDQ_OS_MEMWR_32(t, base, offset, data) do *((base) + (offset)) = (data); while (0)
+#endif
+#ifndef PDQ_CSR_OFFSET
+#define PDQ_CSR_OFFSET(base, offset) (0 + (base) + (offset))
+#endif
+
+#ifndef PDQ_CSR_WRITE
+#define PDQ_CSR_WRITE(csr, name, data) PDQ_OS_MEMWR_32((csr)->csr_bus, (csr)->name, 0, data)
+#define PDQ_CSR_READ(csr, name) PDQ_OS_MEMRD_32((csr)->csr_bus, (csr)->name, 0)
#endif
#if !defined(PDQ_HWSUPPORT)
-#define PDQ_OS_IORD_32(port) inl(port)
-#define PDQ_OS_IOWR_32(port, data) outl(port, data)
-#define PDQ_OS_IORD_8(port) inb(port)
-#define PDQ_OS_IOWR_8(port, data) outb(port, data)
typedef struct {
-#ifdef __bsdi__
+#if defined(__bsdi__)
struct device sc_dev; /* base device */
struct isadev sc_id; /* ISA device */
struct intrhand sc_ih; /* interrupt vectoring */
@@ -133,31 +194,38 @@ typedef struct {
struct device sc_dev; /* base device */
void *sc_ih; /* interrupt vectoring */
void *sc_ats; /* shutdown hook */
+#elif defined(__FreeBSD__)
+ struct kern_devconf *sc_kdc; /* freebsd cruft */
#endif
struct arpcom sc_ac;
- pdq_t *sc_pdq;
- unsigned sc_iobase;
-} pdq_softc_t;
-
#define sc_if sc_ac.ac_if
+ pdq_t *sc_pdq;
+#if defined(__alpha__) || defined(__i386__)
+ pdq_bus_ioport_t sc_iobase;
+#endif
+#ifdef PDQ_IOMAPPED
+#define sc_membase sc_iobase
+#else
+ pdq_bus_memaddr_t sc_membase;
+#endif
+ pdq_bus_t sc_bc;
+#if !defined(__bsdi__) || _BSDI_VERSION >= 199401
#define sc_bpf sc_if.if_bpf
-
-#if defined(__NetBSD__)
-typedef ifnet_ret_t (*pdq_ifwatchdog_t)(struct ifnet *ifp);
-typedef ifnet_ret_t (*pdq_ifinit_t)(struct ifnet *ifp);
#else
-typedef ifnet_ret_t (*pdq_ifwatchdog_t)(int unit);
-typedef ifnet_ret_t (*pdq_ifinit_t)(int unit);
+ caddr_t sc_bpf;
#endif
+} pdq_softc_t;
+
extern void pdq_ifreset(pdq_softc_t *sc);
extern void pdq_ifinit(pdq_softc_t *sc);
-extern void pdq_ifwatchdog(pdq_softc_t *sc);
+extern void pdq_ifwatchdog(struct ifnet *ifp);
extern ifnet_ret_t pdq_ifstart(struct ifnet *ifp);
extern int pdq_ifioctl(struct ifnet *ifp, ioctl_cmd_t cmd, caddr_t data);
-extern void pdq_ifattach(pdq_softc_t *sc, pdq_ifinit_t ifinit,
- pdq_ifwatchdog_t ifwatchdog);
-#endif /* PDQ_HWSUPPORT */
+extern void pdq_ifattach(pdq_softc_t *sc, ifnet_ret_t (*ifwatchdog)(int unit));
+#endif /* !PDQ_HWSUPPORT */
+
+
#elif defined(DLPI_PDQ)
#include <sys/param.h>
#include <sys/kmem.h>
@@ -263,39 +331,15 @@ extern void pdq_os_receive_pdu(pdq_t *, PDQ_OS_DATABUF_T *pdu, size_t pdulen);
extern void pdq_os_restart_transmitter(pdq_t *pdq);
extern void pdq_os_transmit_done(pdq_t *pdq, PDQ_OS_DATABUF_T *pdu);
-extern void pdq_print_fddi_chars(pdq_t *pdq, const pdq_response_status_chars_get_t *rsp);
-
-extern void pdq_init_csrs(pdq_csrs_t *csrs, void *csrs_va, size_t csr_size);
-extern void pdq_init_pci_csrs(pdq_pci_csrs_t *csrs, void *csrs_va, size_t csr_size);
-
-extern void pdq_flush_databuf_queue(pdq_databuf_queue_t *q);
-
-extern pdq_boolean_t pdq_do_port_control(const pdq_csrs_t * const csrs, pdq_uint32_t cmd);
-extern void pdq_read_mla(const pdq_csrs_t * const csrs, pdq_lanaddr_t *hwaddr);
-extern void pdq_read_fwrev(const pdq_csrs_t * const csrs, pdq_fwrev_t *fwrev);
-extern pdq_boolean_t pdq_read_error_log(pdq_t *pdq, pdq_response_error_log_get_t *log_entry);
-extern pdq_chip_rev_t pdq_read_chiprev(const pdq_csrs_t * const csrs);
-
-extern void pdq_queue_commands(pdq_t *pdq);
-extern void pdq_process_command_responses(pdq_t *pdq);
-extern void pdq_process_unsolicited_events(pdq_t *pdq);
-
-extern void pdq_process_received_data(pdq_t *pdq, pdq_rx_info_t *rx,
- pdq_rxdesc_t *receives,
- pdq_uint32_t completion_goal,
- pdq_uint32_t ring_mask);
-
extern pdq_boolean_t pdq_queue_transmit_data(pdq_t *pdq, PDQ_OS_DATABUF_T *pdu);
-extern void pdq_process_transmitted_data(pdq_t *pdq);
extern void pdq_flush_transmitter(pdq_t *pdq);
-
-extern void pdq_hwreset(pdq_t *pdq);
-extern pdq_state_t pdq_stop(pdq_t *pdq);
extern void pdq_run(pdq_t *pdq);
+extern pdq_state_t pdq_stop(pdq_t *pdq);
+extern void pdq_hwreset(pdq_t *pdq);
extern int pdq_interrupt(pdq_t *pdq);
-extern pdq_t *pdq_initialize(void *csr_va, const char *name, int unit, void *ctx, pdq_type_t type);
-
-
+extern pdq_t *pdq_initialize(pdq_bus_t bus, pdq_bus_memaddr_t csr_va,
+ const char *name, int unit,
+ void *ctx, pdq_type_t type);
#endif /* _PDQ_OS_H */
diff --git a/sys/dev/ic/smc93cx6.c b/sys/dev/ic/smc93cx6.c
new file mode 100644
index 00000000000..10405cd0289
--- /dev/null
+++ b/sys/dev/ic/smc93cx6.c
@@ -0,0 +1,222 @@
+/* $NetBSD: smc93cx6.c,v 1.1 1996/05/16 03:59:10 mycroft Exp $ */
+
+/*
+ * Interface for the 93C46/26/06 serial eeprom parts.
+ *
+ * Copyright (c) 1995 Daniel M. Eischen
+ * 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 immediately at the beginning of the file, without modification,
+ * 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. Absolutely no warranty of function or purpose is made by the author
+ * Daniel M. Eischen.
+ * 4. Modifications may be freely made to this file if the above conditions
+ * are met.
+ */
+
+/*
+ * The instruction set of the 93C46/26/06 chips are as follows:
+ *
+ * Start OP
+ * Function Bit Code Address Data Description
+ * -------------------------------------------------------------------
+ * READ 1 10 A5 - A0 Reads data stored in memory,
+ * starting at specified address
+ * EWEN 1 00 11XXXX Write enable must preceed
+ * all programming modes
+ * ERASE 1 11 A5 - A0 Erase register A5A4A3A2A1A0
+ * WRITE 1 01 A5 - A0 D15 - D0 Writes register
+ * ERAL 1 00 10XXXX Erase all registers
+ * WRAL 1 00 01XXXX D15 - D0 Writes to all registers
+ * EWDS 1 00 00XXXX Disables all programming
+ * instructions
+ * *Note: A value of X for address is a don't care condition.
+ *
+ * The 93C46 has a four wire interface: clock, chip select, data in, and
+ * data out. In order to perform one of the above functions, you need
+ * to enable the chip select for a clock period (typically a minimum of
+ * 1 usec, with the clock high and low a minimum of 750 and 250 nsec
+ * respectively. While the chip select remains high, you can clock in
+ * the instructions (above) starting with the start bit, followed by the
+ * OP code, Address, and Data (if needed). For the READ instruction, the
+ * requested 16-bit register contents is read from the data out line but
+ * is preceded by an initial zero (leading 0, followed by 16-bits, MSB
+ * first). The clock cycling from low to high initiates the next data
+ * bit to be sent from the chip.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#if defined(__FreeBSD__)
+#include <machine/clock.h>
+#include <i386/scsi/93cx6.h>
+#elif defined(__NetBSD__)
+#include <machine/bus.h>
+#include <dev/ic/smc93cx6var.h>
+#endif
+
+/*
+ * Right now, we only have to read the SEEPROM. But we make it easier to
+ * add other 93Cx6 functions.
+ */
+static struct seeprom_cmd {
+ unsigned char len;
+ unsigned char bits[3];
+} seeprom_read = {3, {1, 1, 0}};
+
+#if defined(__FreeBSD__)
+#define SEEPROM_INB(sd) inb(sd->sd_iobase)
+#define SEEPROM_OUTB(sd, value) outb(sd->sd_iobase, value)
+#elif defined(__NetBSD__)
+#define SEEPROM_INB(sd) \
+ bus_io_read_1(sd->sd_bc, sd->sd_ioh, sd->sd_offset)
+#define SEEPROM_OUTB(sd, value) \
+ bus_io_write_1(sd->sd_bc, sd->sd_ioh, sd->sd_offset, value)
+#endif
+
+/*
+ * Wait for the SEERDY to go high; about 800 ns.
+ */
+#define CLOCK_PULSE(sd, rdy) \
+ while ((SEEPROM_INB(sd) & rdy) == 0) { \
+ ; /* Do nothing */ \
+ }
+
+/*
+ * Read the serial EEPROM and returns 1 if successful and 0 if
+ * not successful.
+ */
+int
+read_seeprom(sd, buf, start_addr, count)
+ struct seeprom_descriptor *sd;
+ u_int16_t *buf;
+#if defined(__FreeBSD__)
+ u_int start_addr;
+ int count;
+#elif defined(__NetBSD__)
+ bus_io_size_t start_addr;
+ bus_io_size_t count;
+#endif
+{
+ int i = 0, k = 0;
+ u_int16_t v;
+ u_int8_t temp;
+
+ /*
+ * Read the requested registers of the seeprom. The loop
+ * will range from 0 to count-1.
+ */
+ for (k = start_addr; k < count + start_addr; k++) {
+ /* Send chip select for one clock cycle. */
+ temp = sd->sd_MS ^ sd->sd_CS;
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+
+ /*
+ * Now we're ready to send the read command followed by the
+ * address of the 16-bit register we want to read.
+ */
+ for (i = 0; i < seeprom_read.len; i++) {
+ if (seeprom_read.bits[i] != 0)
+ temp ^= sd->sd_DO;
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ if (seeprom_read.bits[i] != 0)
+ temp ^= sd->sd_DO;
+ }
+ /* Send the 6 bit address (MSB first, LSB last). */
+ for (i = 5; i >= 0; i--) {
+ if ((k & (1 << i)) != 0)
+ temp ^= sd->sd_DO;
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ if ((k & (1 << i)) != 0)
+ temp ^= sd->sd_DO;
+ }
+
+ /*
+ * Now read the 16 bit register. An initial 0 precedes the
+ * register contents which begins with bit 15 (MSB) and ends
+ * with bit 0 (LSB). The initial 0 will be shifted off the
+ * top of our word as we let the loop run from 0 to 16.
+ */
+ v = 0;
+ for (i = 16; i >= 0; i--) {
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ v <<= 1;
+ if (SEEPROM_INB(sd) & sd->sd_DI)
+ v |= 1;
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ }
+
+ buf[k - start_addr] = v;
+
+ /* Reset the chip select for the next command cycle. */
+ temp = sd->sd_MS;
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ }
+#if 0
+ printf ("Serial EEPROM:");
+ for (k = 0; k < count; k = k + 1) {
+ if (((k % 8) == 0) && (k != 0))
+ {
+ printf ("\n ");
+ }
+ printf (" 0x%x", buf[k]);
+ }
+ printf ("\n");
+#endif
+ return (1);
+}
+
+int
+acquire_seeprom(sd)
+ struct seeprom_descriptor *sd;
+{
+ int wait;
+
+ /*
+ * Request access of the memory port. When access is
+ * granted, SEERDY will go high. We use a 1 second
+ * timeout which should be near 1 second more than
+ * is needed. Reason: after the chip reset, there
+ * should be no contention.
+ */
+ SEEPROM_OUTB(sd, sd->sd_MS);
+ wait = 1000; /* 1 second timeout in msec */
+ while (--wait && ((SEEPROM_INB(sd) & sd->sd_RDY) == 0)) {
+ DELAY (1000); /* delay 1 msec */
+ }
+ if ((SEEPROM_INB(sd) & sd->sd_RDY) == 0) {
+ SEEPROM_OUTB(sd, 0);
+ return (0);
+ }
+ return(1);
+}
+
+void
+release_seeprom(sd)
+ struct seeprom_descriptor *sd;
+{
+ /* Release access to the memory port and the serial EEPROM. */
+ SEEPROM_OUTB(sd, 0);
+}
diff --git a/sys/dev/ic/smc93cx6var.h b/sys/dev/ic/smc93cx6var.h
new file mode 100644
index 00000000000..d1c7c0162cc
--- /dev/null
+++ b/sys/dev/ic/smc93cx6var.h
@@ -0,0 +1,70 @@
+/*
+ * Interface to the 93C46 serial EEPROM that is used to store BIOS
+ * settings for the aic7xxx based adaptec SCSI controllers. It can
+ * also be used for 93C26 and 93C06 serial EEPROMS.
+ *
+ * Copyright (c) 1994, 1995 Justin T. Gibbs.
+ * 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 immediately at the beginning of the file, without modification,
+ * 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. Absolutely no warranty of function or purpose is made by the author
+ * Justin T. Gibbs.
+ * 4. Modifications may be freely made to this file if the above conditions
+ * are met.
+ *
+ * $Id: smc93cx6var.h,v 1.1 1996/05/26 00:27:06 deraadt Exp $
+ */
+
+#include <sys/param.h>
+#if !defined(__NetBSD__)
+#include <sys/systm.h>
+#endif
+
+struct seeprom_descriptor {
+#if defined(__FreeBSD__)
+ u_long sd_iobase;
+#elif defined(__NetBSD__)
+ bus_chipset_tag_t sd_bc;
+ bus_io_handle_t sd_ioh;
+ bus_io_size_t sd_offset;
+#endif
+ u_int16_t sd_MS;
+ u_int16_t sd_RDY;
+ u_int16_t sd_CS;
+ u_int16_t sd_CK;
+ u_int16_t sd_DO;
+ u_int16_t sd_DI;
+};
+
+/*
+ * This function will read count 16-bit words from the serial EEPROM and
+ * return their value in buf. The port address of the aic7xxx serial EEPROM
+ * control register is passed in as offset. The following parameters are
+ * also passed in:
+ *
+ * CS - Chip select
+ * CK - Clock
+ * DO - Data out
+ * DI - Data in
+ * RDY - SEEPROM ready
+ * MS - Memory port mode select
+ *
+ * A failed read attempt returns 0, and a successful read returns 1.
+ */
+#if defined(__FreeBSD__)
+int read_seeprom __P((struct seeprom_descriptor *sd,
+ u_int16_t *buf, u_int start_addr, int count));
+#elif defined(__NetBSD__)
+int read_seeprom __P((struct seeprom_descriptor *sd,
+ u_int16_t *buf, bus_io_size_t start_addr, bus_io_size_t count));
+#endif
+int acquire_seeprom __P((struct seeprom_descriptor *sd));
+void release_seeprom __P((struct seeprom_descriptor *sd));
diff --git a/sys/dev/ic/z8530sc.c b/sys/dev/ic/z8530sc.c
index 387f2b8aaf7..59e9b22f3cd 100644
--- a/sys/dev/ic/z8530sc.c
+++ b/sys/dev/ic/z8530sc.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: z8530sc.c,v 1.2 1996/04/21 22:21:35 deraadt Exp $ */
-/* $NetBSD: z8530sc.c,v 1.3 1996/04/10 21:44:35 gwr Exp $ */
+/* $OpenBSD: z8530sc.c,v 1.3 1996/05/26 00:27:06 deraadt Exp $ */
+/* $NetBSD: z8530sc.c,v 1.4 1996/05/17 19:30:34 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@@ -99,7 +99,7 @@ zs_getspeed(cs)
tconst = zs_read_reg(cs, 12);
tconst |= zs_read_reg(cs, 13) << 8;
- return (TCONST_TO_BPS(cs->cs_pclk_div16, tconst));
+ return (TCONST_TO_BPS(cs->cs_brg_clk, tconst));
}
/*
diff --git a/sys/dev/ic/z8530sc.h b/sys/dev/ic/z8530sc.h
index f271fe46bde..3af19f88141 100644
--- a/sys/dev/ic/z8530sc.h
+++ b/sys/dev/ic/z8530sc.h
@@ -1,4 +1,4 @@
-/* $NetBSD: z8530sc.h,v 1.2 1996/04/10 21:44:44 gwr Exp $ */
+/* $NetBSD: z8530sc.h,v 1.3 1996/05/17 19:29:37 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@@ -69,10 +69,11 @@ struct zs_chanstate {
volatile u_char *cs_reg_data; /* data or numbered register */
int cs_channel; /* sub-unit number */
- void *cs_private; /* sub-driver data pointer */
+ void *cs_private; /* sub-driver data pointer */
struct zsops *cs_ops;
- int cs_pclk_div16; /* PCLK / 16 */
+ int cs_brg_clk; /* BAUD Rate Generator clock
+ * (usually PCLK / 16) */
int cs_defspeed; /* default baud rate (from PROM) */
/*
@@ -93,7 +94,7 @@ struct zs_chanstate {
u_char cs_heldchange; /* change pending (creg != preg) */
u_char cs_rr0; /* last rr0 processed */
- u_char cs_rr0_new; /* rr0 saved in status interrupt. */
+ u_char cs_rr0_new; /* rr0 saved in status interrupt. */
char cs_softreq; /* need soft interrupt call */
};
diff --git a/sys/dev/ic/z8530tty.c b/sys/dev/ic/z8530tty.c
index db07810fdf9..9a62a507339 100644
--- a/sys/dev/ic/z8530tty.c
+++ b/sys/dev/ic/z8530tty.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: z8530tty.c,v 1.3 1996/04/21 22:21:46 deraadt Exp $ */
-/* $NetBSD: z8530tty.c,v 1.6 1996/04/10 21:44:47 gwr Exp $ */
+/* $OpenBSD: z8530tty.c,v 1.4 1996/05/26 00:27:08 deraadt Exp $ */
+/* $NetBSD: z8530tty.c,v 1.8 1996/05/17 22:49:23 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@@ -51,6 +51,19 @@
*
* This is the "slave" driver that will be attached to
* the "zsc" driver for plain "tty" async. serial lines.
+ *
+ * Credits, history:
+ *
+ * The original version of this code was the sparc/dev/zs.c driver
+ * as distributed with the Berkeley 4.4 Lite release. Since then,
+ * Gordon Ross reorganized the code into the current parent/child
+ * driver scheme, separating the Sun keyboard and mouse support
+ * into independent child drivers.
+ *
+ * RTS/CTS flow-control support was a collaboration of:
+ * Gordon Ross <gwr@netbsd.org>,
+ * Bill Studenmund <wrstuden@loki.stanford.edu>
+ * Ian Dall <Ian.Dall@dsto.defence.gov.au>
*/
#include <sys/param.h>
@@ -96,6 +109,9 @@ extern int zs_check_kgdb();
*/
int zstty_rbuf_size = ZSTTY_RING_SIZE;
+/* This should usually be 3/4 of ZSTTY_RING_SIZE */
+int zstty_rbuf_hiwat = (ZSTTY_RING_SIZE - (ZSTTY_RING_SIZE >> 2));
+
struct zstty_softc {
struct device zst_dev; /* required first: base device */
struct tty *zst_tty;
@@ -104,22 +120,6 @@ struct zstty_softc {
int zst_hwflags; /* see z8530var.h */
int zst_swflags; /* TIOCFLAG_SOFTCAR, ... <ttycom.h> */
- /* Flags to communicate with zstty_softint() */
- volatile int zst_intr_flags;
-#define INTR_RX_OVERRUN 1
-#define INTR_TX_EMPTY 2
-#define INTR_ST_CHECK 4
-
- /*
- * The transmit byte count and address are used for pseudo-DMA
- * output in the hardware interrupt code. PDMA can be suspended
- * to get pending changes done; heldtbc is used for this. It can
- * also be stopped for ^S; this sets TS_TTSTOP in tp->t_state.
- */
- int zst_tbc; /* transmit byte count */
- caddr_t zst_tba; /* transmit buffer address */
- int zst_heldtbc; /* held tbc while xmission stopped */
-
/*
* Printing an overrun error message often takes long enough to
* cause another overrun, so we only print one per second.
@@ -130,10 +130,31 @@ struct zstty_softc {
/*
* The receive ring buffer.
*/
- u_int zst_rbget; /* ring buffer `get' index */
- volatile u_int zst_rbput; /* ring buffer `put' index */
- u_int zst_ringmask;
+ int zst_rbget; /* ring buffer `get' index */
+ volatile int zst_rbput; /* ring buffer `put' index */
+ int zst_ringmask;
+ int zst_rbhiwat;
+
u_short *zst_rbuf; /* rr1, data pairs */
+
+ /*
+ * The transmit byte count and address are used for pseudo-DMA
+ * output in the hardware interrupt code. PDMA can be suspended
+ * to get pending changes done; heldtbc is used for this. It can
+ * also be stopped for ^S; this sets TS_TTSTOP in tp->t_state.
+ */
+ int zst_tbc; /* transmit byte count */
+ caddr_t zst_tba; /* transmit buffer address */
+ int zst_heldtbc; /* held tbc while xmission stopped */
+
+ /* Flags to communicate with zstty_softint() */
+ volatile char zst_rx_blocked; /* input block at ring */
+ volatile char zst_rx_overrun; /* ring overrun */
+ volatile char zst_tx_busy; /* working on an output chunk */
+ volatile char zst_tx_done; /* done with one output chunk */
+ volatile char zst_tx_stopped; /* H/W level stop (lost CTS) */
+ volatile char zst_st_check; /* got a status interrupt */
+ char pad[2];
};
@@ -157,6 +178,8 @@ cdev_decl(zs); /* open, close, read, write, ioctl, stop, ... */
static void zsstart(struct tty *);
static int zsparam(struct tty *, struct termios *);
static void zs_modem(struct zstty_softc *zst, int onoff);
+static int zshwiflow(struct tty *, int);
+static void zs_hwiflow(struct zstty_softc *, int);
/*
* zstty_match: how is this zs channel configured?
@@ -235,8 +258,10 @@ zstty_attach(parent, self, aux)
tp->t_dev = dev;
tp->t_oproc = zsstart;
tp->t_param = zsparam;
+ tp->t_hwiflow = zshwiflow;
zst->zst_tty = tp;
+ zst->zst_rbhiwat = zstty_rbuf_size; /* impossible value */
zst->zst_ringmask = zstty_rbuf_size - 1;
zst->zst_rbuf = malloc(zstty_rbuf_size * sizeof(zst->zst_rbuf[0]),
M_DEVBUF, M_WAITOK);
@@ -566,6 +591,13 @@ zsstart(tp)
goto out;
/*
+ * If under CRTSCTS hfc and halted, do nothing
+ */
+ if (tp->t_cflag & CRTSCTS)
+ if (zst->zst_tx_stopped)
+ goto out;
+
+ /*
* If there are sleepers, and output has drained below low
* water mark, awaken.
*/
@@ -578,15 +610,16 @@ zsstart(tp)
}
nch = ndqb(&tp->t_outq, 0); /* XXX */
+ (void) splzs();
+
if (nch) {
register char *p = tp->t_outq.c_cf;
/* mark busy, enable tx done interrupts, & send first byte */
tp->t_state |= TS_BUSY;
- (void) splzs();
-
+ zst->zst_tx_busy = 1;
cs->cs_preg[1] |= ZSWR1_TIE;
- cs->cs_creg[1] |= ZSWR1_TIE;
+ cs->cs_creg[1] = cs->cs_preg[1];
zs_write_reg(cs, 1, cs->cs_creg[1]);
zs_write_data(cs, *p);
zst->zst_tba = p + 1;
@@ -596,9 +629,8 @@ zsstart(tp)
* Nothing to send, turn off transmit done interrupts.
* This is useful if something is doing polled output.
*/
- (void) splzs();
cs->cs_preg[1] &= ~ZSWR1_TIE;
- cs->cs_creg[1] &= ~ZSWR1_TIE;
+ cs->cs_creg[1] = cs->cs_preg[1];
zs_write_reg(cs, 1, cs->cs_creg[1]);
}
out:
@@ -624,8 +656,11 @@ zsstop(tp, flag)
if (tp->t_state & TS_BUSY) {
/*
* Device is transmitting; must stop it.
+ * Also clear _heldtbc to prevent any
+ * flow-control event from resuming.
*/
zst->zst_tbc = 0;
+ zst->zst_heldtbc = 0;
if ((tp->t_state & TS_TTSTOP) == 0)
tp->t_state |= TS_FLUSH;
}
@@ -652,12 +687,7 @@ zsparam(tp, t)
zst = zstty_cd.cd_devs[minor(tp->t_dev)];
cs = zst->zst_cs;
- /*
- * Because PCLK is only run at 4.9 MHz, the fastest we
- * can go is 51200 baud (this corresponds to TC=1).
- * This is somewhat unfortunate as there is no real
- * reason we should not be able to handle higher rates.
- */
+ /* XXX: Need to use an MD function for this. */
bps = t->c_ospeed;
if (bps < 0 || (t->c_ispeed && t->c_ispeed != bps))
return (EINVAL);
@@ -666,12 +696,12 @@ zsparam(tp, t)
zs_modem(zst, 0);
return (0);
}
- tconst = BPS_TO_TCONST(cs->cs_pclk_div16, bps);
+ tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps);
if (tconst < 0)
return (EINVAL);
/* Convert back to make sure we can do it. */
- bps = TCONST_TO_BPS(cs->cs_pclk_div16, tconst);
+ bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst);
if (bps != t->c_ospeed)
return (EINVAL);
tp->t_ispeed = tp->t_ospeed = bps;
@@ -714,18 +744,7 @@ zsparam(tp, t)
break;
}
- /*
- * Output hardware flow control on the chip is horrendous: if
- * carrier detect drops, the receiver is disabled. Hence we
- * can only do this when the carrier is on.
- */
- tmp3 |= ZSWR3_RX_ENABLE;
- if (cflag & CCTS_OFLOW) {
- if (zs_read_csr(cs) & ZSRR0_DCD)
- tmp3 |= ZSWR3_HFC;
- }
-
- cs->cs_preg[3] = tmp3;
+ cs->cs_preg[3] = tmp3 | ZSWR3_RX_ENABLE;
cs->cs_preg[5] = tmp5 | ZSWR5_TX_ENABLE | ZSWR5_DTR | ZSWR5_RTS;
tmp4 = ZSWR4_CLK_X16 | (cflag & CSTOPB ? ZSWR4_TWOSB : ZSWR4_ONESB);
@@ -736,14 +755,28 @@ zsparam(tp, t)
cs->cs_preg[4] = tmp4;
/*
+ * Output hardware flow control on the chip is horrendous:
+ * if carrier detect drops, the receiver is disabled.
+ * Therefore, NEVER set the HFC bit, and instead use
+ * the status interrupts to detect CTS changes.
+ */
+ if (cflag & CRTSCTS) {
+ zst->zst_rbhiwat = zstty_rbuf_hiwat;
+ cs->cs_preg[15] |= ZSWR15_CTS_IE;
+ } else {
+ zst->zst_rbhiwat = zstty_rbuf_size; /* impossible value */
+ cs->cs_preg[15] &= ~ZSWR15_CTS_IE;
+ }
+
+ /*
* If nothing is being transmitted, set up new current values,
* else mark them as pending.
*/
if (cs->cs_heldchange == 0) {
- if (tp->t_state & TS_BUSY) {
+ if (zst->zst_tx_busy) {
zst->zst_heldtbc = zst->zst_tbc;
zst->zst_tbc = 0;
- cs->cs_heldchange = 1;
+ cs->cs_heldchange = 0xFFFF;
} else {
zs_loadchannelregs(cs);
}
@@ -778,37 +811,113 @@ zs_modem(zst, onoff)
s = splzs();
cs->cs_preg[5] = (cs->cs_preg[5] | bis) & and;
if (cs->cs_heldchange == 0) {
- if (tp->t_state & TS_BUSY) {
+ if (zst->zst_tx_busy) {
zst->zst_heldtbc = zst->zst_tbc;
zst->zst_tbc = 0;
- cs->cs_heldchange = 1;
+ cs->cs_heldchange = (1<<5);
} else {
- cs->cs_creg[5] = (cs->cs_creg[5] | bis) & and;
+ cs->cs_creg[5] = cs->cs_preg[5];
zs_write_reg(cs, 5, cs->cs_creg[5]);
}
}
splx(s);
}
+/*
+ * Try to block or unblock input using hardware flow-control.
+ * This is called by kern/tty.c if MDMBUF|CRTSCTS is set, and
+ * if this function returns non-zero, the TS_TBLOCK flag will
+ * be set or cleared according to the "stop" arg passed.
+ */
+int
+zshwiflow(tp, stop)
+ struct tty *tp;
+ int stop;
+{
+ register struct zstty_softc *zst;
+ int s;
+
+ zst = zstty_cd.cd_devs[minor(tp->t_dev)];
+
+ s = splzs();
+ if (stop) {
+ /*
+ * The tty layer is asking us to block input.
+ * If we already did it, just return TRUE.
+ */
+ if (zst->zst_rx_blocked)
+ goto out;
+ zst->zst_rx_blocked = 1;
+ } else {
+ /*
+ * The tty layer is asking us to resume input.
+ * The input ring is always empty by now.
+ */
+ zst->zst_rx_blocked = 0;
+ }
+ zs_hwiflow(zst, stop);
+ out:
+ splx(s);
+ return 1;
+}
+
+/*
+ * Internal version of zshwiflow
+ * called at splzs
+ */
+static void
+zs_hwiflow(zst, stop)
+ register struct zstty_softc *zst;
+ int stop;
+{
+ register struct zs_chanstate *cs;
+ register struct tty *tp;
+ register int bis, and;
+
+ cs = zst->zst_cs;
+ tp = zst->zst_tty;
+
+ if (stop) {
+ /* Block input (Lower RTS) */
+ bis = 0;
+ and = ~ZSWR5_RTS;
+ } else {
+ /* Unblock input (Raise RTS) */
+ bis = ZSWR5_RTS;
+ and = ~0;
+ }
+
+ cs->cs_preg[5] = (cs->cs_preg[5] | bis) & and;
+ if (cs->cs_heldchange == 0) {
+ if (zst->zst_tx_busy) {
+ zst->zst_heldtbc = zst->zst_tbc;
+ zst->zst_tbc = 0;
+ cs->cs_heldchange = (1<<5);
+ } else {
+ cs->cs_creg[5] = cs->cs_preg[5];
+ zs_write_reg(cs, 5, cs->cs_creg[5]);
+ }
+ }
+}
+
/****************************************************************
* Interface to the lower layer (zscc)
****************************************************************/
-/*
- * XXX: need to do input flow-control to avoid ring overrun.
- */
/*
- * receiver ready interrupt. (splzs)
+ * receiver ready interrupt.
+ * called at splzs
*/
static void
zstty_rxint(cs)
register struct zs_chanstate *cs;
{
register struct zstty_softc *zst;
- register put, put_next, ringmask;
+ register int cc, put, put_next, ringmask;
register u_char c, rr0, rr1;
+ register u_short ch_rr1;
zst = cs->cs_private;
put = zst->zst_rbput;
@@ -822,18 +931,21 @@ nextchar:
*/
rr1 = zs_read_reg(cs, 1);
c = zs_read_data(cs);
+ ch_rr1 = (c << 8) | rr1;
- if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
+ if (ch_rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
/* Clear the receive error. */
zs_write_csr(cs, ZSWR0_RESET_ERRORS);
}
- zst->zst_rbuf[put] = (c << 8) | rr1;
+ /* XXX: Check for the stop character? */
+
+ zst->zst_rbuf[put] = ch_rr1;
put_next = (put + 1) & ringmask;
/* Would overrun if increment makes (put==get). */
if (put_next == zst->zst_rbget) {
- zst->zst_intr_flags |= INTR_RX_OVERRUN;
+ zst->zst_rx_overrun = 1;
} else {
/* OK, really increment. */
put = put_next;
@@ -847,6 +959,17 @@ nextchar:
/* Done reading. */
zst->zst_rbput = put;
+ /*
+ * If ring is getting too full, try to block input.
+ */
+ cc = put - zst->zst_rbget;
+ if (cc < 0)
+ cc += zstty_rbuf_size;
+ if ((cc > zst->zst_rbhiwat) && (zst->zst_rx_blocked == 0)) {
+ zst->zst_rx_blocked = 1;
+ zs_hwiflow(zst, 1);
+ }
+
/* Ask for softint() call. */
cs->cs_softreq = 1;
}
@@ -862,7 +985,26 @@ zstty_txint(cs)
register int count;
zst = cs->cs_private;
- count = zst->zst_tbc;
+
+ /*
+ * If we suspended output for a "held" change,
+ * then handle that now and resume.
+ * Do flow-control changes ASAP.
+ * When the only change is for flow control,
+ * avoid hitting other registers, because that
+ * often makes the stupid zs drop input...
+ */
+ if (cs->cs_heldchange) {
+ if (cs->cs_heldchange == (1<<5)) {
+ /* Avoid whacking the chip... */
+ cs->cs_creg[5] = cs->cs_preg[5];
+ zs_write_reg(cs, 5, cs->cs_creg[5]);
+ } else
+ zs_loadchannelregs(cs);
+ cs->cs_heldchange = 0;
+ count = zst->zst_heldtbc;
+ } else
+ count = zst->zst_tbc;
/*
* If our transmit buffer still has data,
@@ -879,7 +1021,8 @@ zstty_txint(cs)
zs_write_csr(cs, ZSWR0_RESET_TXINT);
/* Ask the softint routine for more output. */
- zst->zst_intr_flags |= INTR_TX_EMPTY;
+ zst->zst_tx_busy = 0;
+ zst->zst_tx_done = 1;
cs->cs_softreq = 1;
}
@@ -901,26 +1044,6 @@ zstty_stint(cs)
zs_write_csr(cs, ZSWR0_RESET_STATUS);
/*
- * The chip's hardware flow control is, as noted in zsreg.h,
- * busted---if the DCD line goes low the chip shuts off the
- * receiver (!). If we want hardware CTS flow control but do
- * not have it, and carrier is now on, turn HFC on; if we have
- * HFC now but carrier has gone low, turn it off.
- */
- if (rr0 & ZSRR0_DCD) {
- if (tp->t_cflag & CCTS_OFLOW &&
- (cs->cs_creg[3] & ZSWR3_HFC) == 0) {
- cs->cs_creg[3] |= ZSWR3_HFC;
- zs_write_reg(cs, 3, cs->cs_creg[3]);
- }
- } else {
- if (cs->cs_creg[3] & ZSWR3_HFC) {
- cs->cs_creg[3] &= ~ZSWR3_HFC;
- zs_write_reg(cs, 3, cs->cs_creg[3]);
- }
- }
-
- /*
* Check here for console break, so that we can abort
* even when interrupts are locking up the machine.
*/
@@ -931,8 +1054,21 @@ zstty_stint(cs)
return;
}
+ /*
+ * Need to handle CTS output flow control here.
+ * Output remains stopped as long as either the
+ * zst_tx_stopped or TS_TTSTOP flag is set.
+ * Never restart here; the softint routine will
+ * do that after things are ready to move.
+ */
+ if (((rr0 & ZSRR0_CTS) == 0) && (tp->t_cflag & CRTSCTS)) {
+ zst->zst_tbc = 0;
+ zst->zst_heldtbc = 0;
+ zst->zst_tx_stopped = 1;
+ }
+
cs->cs_rr0_new = rr0;
- zst->zst_intr_flags |= INTR_ST_CHECK;
+ zst->zst_st_check = 1;
/* Ask for softint() call. */
cs->cs_softreq = 1;
@@ -957,6 +1093,15 @@ zsoverrun(zst, ptime, what)
/*
* Software interrupt. Called at zssoft
+ *
+ * The main job to be done here is to empty the input ring
+ * by passing its contents up to the tty layer. The ring is
+ * always emptied during this operation, therefore the ring
+ * must not be larger than the space after "high water" in
+ * the tty layer, or the tty layer might drop our input.
+ *
+ * Note: an "input blockage" condition is assumed to exist if
+ * EITHER the TS_TBLOCK flag or zst_rx_blocked flag is set.
*/
static void
zstty_softint(cs)
@@ -966,28 +1111,23 @@ zstty_softint(cs)
register struct linesw *line;
register struct tty *tp;
register int get, c, s;
- int intr_flags, ringmask;
+ int ringmask, overrun;
register u_short ring_data;
- register u_char rr0, rr1;
+ register u_char rr0, rr1, delta;
zst = cs->cs_private;
tp = zst->zst_tty;
line = &linesw[tp->t_line];
ringmask = zst->zst_ringmask;
-
- /* Atomically get and clear flags. */
- s = splzs();
- intr_flags = zst->zst_intr_flags;
- zst->zst_intr_flags = 0;
+ overrun = 0;
/*
- * Lower to tty priority while servicing the ring.
+ * Raise to tty priority while servicing the ring.
*/
- (void) spltty();
+ s = spltty();
- if (intr_flags & INTR_RX_OVERRUN) {
- /* May turn this on again below. */
- intr_flags &= ~INTR_RX_OVERRUN;
+ if (zst->zst_rx_overrun) {
+ zst->zst_rx_overrun = 0;
zsoverrun(zst, &zst->zst_rotime, "ring");
}
@@ -1000,7 +1140,7 @@ zstty_softint(cs)
get = (get + 1) & ringmask;
if (ring_data & ZSRR1_DO)
- intr_flags |= INTR_RX_OVERRUN;
+ overrun++;
/* low byte of ring_data is rr1 */
c = (ring_data >> 8) & 0xff;
if (ring_data & ZSRR1_FE)
@@ -1017,57 +1157,61 @@ zstty_softint(cs)
* copying char/status pairs from the ring, which
* means this was a hardware (fifo) overrun.
*/
- if (intr_flags & INTR_RX_OVERRUN) {
+ if (overrun) {
zsoverrun(zst, &zst->zst_fotime, "fifo");
}
- if (intr_flags & INTR_TX_EMPTY) {
- /*
- * The transmitter output buffer count is zero.
- * If we suspended output for a "held" change,
- * then handle that now and resume. Otherwise,
- * try to start a new output chunk.
- */
- if (cs->cs_heldchange) {
- (void) splzs();
- rr0 = zs_read_csr(cs);
- if ((rr0 & ZSRR0_DCD) == 0)
- cs->cs_preg[3] &= ~ZSWR3_HFC;
- zs_loadchannelregs(cs);
- (void) spltty();
- cs->cs_heldchange = 0;
- if (zst->zst_heldtbc &&
- (tp->t_state & TS_TTSTOP) == 0)
- {
- zst->zst_tbc = zst->zst_heldtbc - 1;
- zs_write_data(cs, *zst->zst_tba);
- zst->zst_tba++;
- goto tx_resumed;
+ /*
+ * We have emptied the input ring. Maybe unblock input.
+ * Note: an "input blockage" condition is assumed to exist
+ * when EITHER zst_rx_blocked or the TS_TBLOCK flag is set,
+ * so unblock here ONLY if TS_TBLOCK has not been set.
+ */
+ if (zst->zst_rx_blocked && ((tp->t_state & TS_TBLOCK) == 0)) {
+ (void) splzs();
+ zst->zst_rx_blocked = 0;
+ zs_hwiflow(zst, 0); /* unblock input */
+ (void) spltty();
+ }
+
+ /*
+ * Do any deferred work for status interrupts.
+ * The rr0 was saved in the h/w interrupt to
+ * avoid another splzs in here.
+ */
+ if (zst->zst_st_check) {
+ zst->zst_st_check = 0;
+
+ rr0 = cs->cs_rr0_new;
+ delta = rr0 ^ cs->cs_rr0;
+ cs->cs_rr0 = rr0;
+ if (delta & ZSRR0_DCD) {
+ c = ((rr0 & ZSRR0_DCD) != 0);
+ if (line->l_modem(tp, c) == 0)
+ zs_modem(zst, c);
+ }
+ if ((delta & ZSRR0_CTS) && (tp->t_cflag & CRTSCTS)) {
+ /*
+ * Only do restart here. Stop is handled
+ * at the h/w interrupt level.
+ */
+ if (rr0 & ZSRR0_CTS) {
+ zst->zst_tx_stopped = 0;
+ tp->t_state &= ~TS_TTSTOP;
+ (*line->l_start)(tp);
}
}
+ }
+
+ if (zst->zst_tx_done) {
+ zst->zst_tx_done = 0;
tp->t_state &= ~TS_BUSY;
if (tp->t_state & TS_FLUSH)
tp->t_state &= ~TS_FLUSH;
else
ndflush(&tp->t_outq, zst->zst_tba -
- (caddr_t) tp->t_outq.c_cf);
+ (caddr_t) tp->t_outq.c_cf);
line->l_start(tp);
- tx_resumed:
- }
-
- if (intr_flags & INTR_ST_CHECK) {
- /*
- * Status line change. HFC bit is run in
- * hardware interrupt, to avoid locking
- * at splzs here.
- */
- rr0 = cs->cs_rr0_new;
- if ((rr0 ^ cs->cs_rr0) & ZSRR0_DCD) {
- c = ((rr0 & ZSRR0_DCD) != 0);
- if (line->l_modem(tp, c) == 0)
- zs_modem(zst, c);
- }
- cs->cs_rr0 = rr0;
}
splx(s);