diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1996-05-26 00:27:57 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1996-05-26 00:27:57 +0000 |
commit | 729a9d7ceffba9e7e741540048479eed9907601e (patch) | |
tree | 716f1614729ffc0b602e2fdfece3bc84b3e930b1 /sys/dev/ic | |
parent | 8102ec86d426fccfffa292d80d3e50914c22a932 (diff) |
sync 0521
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/aic7xxx.c | 1110 | ||||
-rw-r--r-- | sys/dev/ic/aic7xxxreg.h | 776 | ||||
-rw-r--r-- | sys/dev/ic/aic7xxxvar.h | 172 | ||||
-rw-r--r-- | sys/dev/ic/com.c | 10 | ||||
-rw-r--r-- | sys/dev/ic/elink3.c | 17 | ||||
-rw-r--r-- | sys/dev/ic/elink3reg.h | 4 | ||||
-rw-r--r-- | sys/dev/ic/elink3var.h | 6 | ||||
-rw-r--r-- | sys/dev/ic/ncr5380sbc.c | 43 | ||||
-rw-r--r-- | sys/dev/ic/ncr5380var.h | 7 | ||||
-rw-r--r-- | sys/dev/ic/pdq.c | 395 | ||||
-rw-r--r-- | sys/dev/ic/pdq_ifsubr.c | 137 | ||||
-rw-r--r-- | sys/dev/ic/pdqreg.h | 122 | ||||
-rw-r--r-- | sys/dev/ic/pdqvar.h | 216 | ||||
-rw-r--r-- | sys/dev/ic/smc93cx6.c | 222 | ||||
-rw-r--r-- | sys/dev/ic/smc93cx6var.h | 70 | ||||
-rw-r--r-- | sys/dev/ic/z8530sc.c | 6 | ||||
-rw-r--r-- | sys/dev/ic/z8530sc.h | 9 | ||||
-rw-r--r-- | sys/dev/ic/z8530tty.c | 414 |
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); |