Use `{in.out}b(iobase + ...' rather than including the base address in

the register definitions.
This commit is contained in:
mycroft 1996-03-30 16:13:24 +00:00
parent bd6e60f0d5
commit 778f21db6a
2 changed files with 456 additions and 400 deletions

View File

@ -1,7 +1,9 @@
/* $NetBSD: aic6360.c,v 1.39 1996/03/17 00:53:01 thorpej Exp $ */
/* $NetBSD: aic6360.c,v 1.40 1996/03/30 16:13:24 mycroft Exp $ */
#define integrate static inline
/*
* Copyright (c) 1994, 1995 Charles Hannum. All rights reserved.
* Copyright (c) 1994, 1995, 1996 Charles M. Hannum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -13,7 +15,7 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles Hannum.
* This product includes software developed by Charles M. Hannum.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
@ -136,45 +138,44 @@
*/
/* AIC6360 definitions */
#define IOBASE sc->sc_iobase
#define SCSISEQ (IOBASE + 0x00) /* SCSI sequence control */
#define SXFRCTL0 (IOBASE + 0x01) /* SCSI transfer control 0 */
#define SXFRCTL1 (IOBASE + 0x02) /* SCSI transfer control 1 */
#define SCSISIG (IOBASE + 0x03) /* SCSI signal in/out */
#define SCSIRATE (IOBASE + 0x04) /* SCSI rate control */
#define SCSIID (IOBASE + 0x05) /* SCSI ID */
#define SELID (IOBASE + 0x05) /* Selection/Reselection ID */
#define SCSIDAT (IOBASE + 0x06) /* SCSI Latched Data */
#define SCSIBUS (IOBASE + 0x07) /* SCSI Data Bus*/
#define STCNT0 (IOBASE + 0x08) /* SCSI transfer count */
#define STCNT1 (IOBASE + 0x09)
#define STCNT2 (IOBASE + 0x0a)
#define CLRSINT0 (IOBASE + 0x0b) /* Clear SCSI interrupts 0 */
#define SSTAT0 (IOBASE + 0x0b) /* SCSI interrupt status 0 */
#define CLRSINT1 (IOBASE + 0x0c) /* Clear SCSI interrupts 1 */
#define SSTAT1 (IOBASE + 0x0c) /* SCSI status 1 */
#define SSTAT2 (IOBASE + 0x0d) /* SCSI status 2 */
#define SCSITEST (IOBASE + 0x0e) /* SCSI test control */
#define SSTAT3 (IOBASE + 0x0e) /* SCSI status 3 */
#define CLRSERR (IOBASE + 0x0f) /* Clear SCSI errors */
#define SSTAT4 (IOBASE + 0x0f) /* SCSI status 4 */
#define SIMODE0 (IOBASE + 0x10) /* SCSI interrupt mode 0 */
#define SIMODE1 (IOBASE + 0x11) /* SCSI interrupt mode 1 */
#define DMACNTRL0 (IOBASE + 0x12) /* DMA control 0 */
#define DMACNTRL1 (IOBASE + 0x13) /* DMA control 1 */
#define DMASTAT (IOBASE + 0x14) /* DMA status */
#define FIFOSTAT (IOBASE + 0x15) /* FIFO status */
#define DMADATA (IOBASE + 0x16) /* DMA data */
#define DMADATAL (IOBASE + 0x16) /* DMA data low byte */
#define DMADATAH (IOBASE + 0x17) /* DMA data high byte */
#define BRSTCNTRL (IOBASE + 0x18) /* Burst Control */
#define DMADATALONG (IOBASE + 0x18)
#define PORTA (IOBASE + 0x1a) /* Port A */
#define PORTB (IOBASE + 0x1b) /* Port B */
#define REV (IOBASE + 0x1c) /* Revision (001 for 6360) */
#define STACK (IOBASE + 0x1d) /* Stack */
#define TEST (IOBASE + 0x1e) /* Test register */
#define ID (IOBASE + 0x1f) /* ID register */
#define SCSISEQ 0x00 /* SCSI sequence control */
#define SXFRCTL0 0x01 /* SCSI transfer control 0 */
#define SXFRCTL1 0x02 /* SCSI transfer control 1 */
#define SCSISIG 0x03 /* SCSI signal in/out */
#define SCSIRATE 0x04 /* SCSI rate control */
#define SCSIID 0x05 /* SCSI ID */
#define SELID 0x05 /* Selection/Reselection ID */
#define SCSIDAT 0x06 /* SCSI Latched Data */
#define SCSIBUS 0x07 /* SCSI Data Bus*/
#define STCNT0 0x08 /* SCSI transfer count */
#define STCNT1 0x09
#define STCNT2 0x0a
#define CLRSINT0 0x0b /* Clear SCSI interrupts 0 */
#define SSTAT0 0x0b /* SCSI interrupt status 0 */
#define CLRSINT1 0x0c /* Clear SCSI interrupts 1 */
#define SSTAT1 0x0c /* SCSI status 1 */
#define SSTAT2 0x0d /* SCSI status 2 */
#define SCSITEST 0x0e /* SCSI test control */
#define SSTAT3 0x0e /* SCSI status 3 */
#define CLRSERR 0x0f /* Clear SCSI errors */
#define SSTAT4 0x0f /* SCSI status 4 */
#define SIMODE0 0x10 /* SCSI interrupt mode 0 */
#define SIMODE1 0x11 /* SCSI interrupt mode 1 */
#define DMACNTRL0 0x12 /* DMA control 0 */
#define DMACNTRL1 0x13 /* DMA control 1 */
#define DMASTAT 0x14 /* DMA status */
#define FIFOSTAT 0x15 /* FIFO status */
#define DMADATA 0x16 /* DMA data */
#define DMADATAL 0x16 /* DMA data low byte */
#define DMADATAH 0x17 /* DMA data high byte */
#define BRSTCNTRL 0x18 /* Burst Control */
#define DMADATALONG 0x18
#define PORTA 0x1a /* Port A */
#define PORTB 0x1b /* Port B */
#define REV 0x1c /* Revision (001 for 6360) */
#define STACK 0x1d /* Stack */
#define TEST 0x1e /* Test register */
#define ID 0x1f /* ID register */
#define IDSTRING "(C)1991ADAPTECAIC6360 "
@ -580,6 +581,8 @@ void aic_done __P((struct aic_softc *, struct aic_acb *));
void aic_dequeue __P((struct aic_softc *, struct aic_acb *));
int aic_scsi_cmd __P((struct scsi_xfer *));
int aic_poll __P((struct aic_softc *, struct scsi_xfer *, int));
integrate void aic_sched_msgout __P((struct aic_softc *, u_char));
integrate void aic_setsync __P((struct aic_softc *, struct aic_tinfo *));
void aic_select __P((struct aic_softc *, struct aic_acb *));
void aic_timeout __P((void *));
int aic_find __P((struct aic_softc *));
@ -672,12 +675,13 @@ int
aic_find(sc)
struct aic_softc *sc;
{
int iobase = sc->sc_iobase;
char chip_id[sizeof(IDSTRING)]; /* For chips that support it */
char *start;
int i;
/* Remove aic6360 from possible powerdown mode */
outb(DMACNTRL0, 0);
outb(iobase + DMACNTRL0, 0);
/* Thanks to mark@aggregate.com for the new method for detecting
* whether the chip is present or not. Bonus: may also work for
@ -691,13 +695,13 @@ aic_find(sc)
*/
/* Push the sequence 0,1,..,15 on the stack */
#define STSIZE 16
outb(DMACNTRL1, 0); /* Reset stack pointer */
outb(iobase + DMACNTRL1, 0); /* Reset stack pointer */
for (i = 0; i < STSIZE; i++)
outb(STACK, i);
outb(iobase + STACK, i);
/* See if we can pull out the same sequence */
outb(DMACNTRL1, 0);
for (i = 0; i < STSIZE && inb(STACK) == i; i++)
outb(iobase + DMACNTRL1, 0);
for (i = 0; i < STSIZE && inb(iobase + STACK) == i; i++)
;
if (i != STSIZE) {
AIC_START(("STACK futzed at %d.\n", i));
@ -708,10 +712,10 @@ aic_find(sc)
* now only used for informational purposes.
*/
bzero(chip_id, sizeof(chip_id));
insb(ID, chip_id, sizeof(IDSTRING)-1);
insb(iobase + ID, chip_id, sizeof(IDSTRING)-1);
AIC_START(("AIC found at 0x%x ", sc->sc_iobase));
AIC_START(("ID: %s ",chip_id));
AIC_START(("chip revision %d\n",(int)inb(REV)));
AIC_START(("chip revision %d\n",(int)inb(iobase + REV)));
sc->sc_initiator = 7;
sc->sc_freq = 20; /* XXXX Assume 20 MHz. */
@ -786,32 +790,33 @@ void
aic_reset(sc)
struct aic_softc *sc;
{
int iobase = sc->sc_iobase;
outb(SCSITEST, 0); /* Doc. recommends to clear these two */
outb(TEST, 0); /* registers before operations commence */
outb(iobase + SCSITEST, 0); /* Doc. recommends to clear these two */
outb(iobase + TEST, 0); /* registers before operations commence */
/* Reset SCSI-FIFO and abort any transfers */
outb(SXFRCTL0, CHEN|CLRCH|CLRSTCNT);
outb(iobase + SXFRCTL0, CHEN | CLRCH | CLRSTCNT);
/* Reset DMA-FIFO */
outb(DMACNTRL0, RSTFIFO);
outb(DMACNTRL1, 0);
outb(iobase + DMACNTRL0, RSTFIFO);
outb(iobase + DMACNTRL1, 0);
outb(SCSISEQ, 0); /* Disable all selection features */
outb(SXFRCTL1, 0);
outb(iobase + SCSISEQ, 0); /* Disable all selection features */
outb(iobase + SXFRCTL1, 0);
outb(SIMODE0, 0x00); /* Disable some interrupts */
outb(CLRSINT0, 0x7f); /* Clear a slew of interrupts */
outb(iobase + SIMODE0, 0x00); /* Disable some interrupts */
outb(iobase + CLRSINT0, 0x7f); /* Clear a slew of interrupts */
outb(SIMODE1, 0x00); /* Disable some more interrupts */
outb(CLRSINT1, 0xef); /* Clear another slew of interrupts */
outb(iobase + SIMODE1, 0x00); /* Disable some more interrupts */
outb(iobase + CLRSINT1, 0xef); /* Clear another slew of interrupts */
outb(SCSIRATE, 0); /* Disable synchronous transfers */
outb(iobase + SCSIRATE, 0); /* Disable synchronous transfers */
outb(CLRSERR, 0x07); /* Haven't seen ant errors (yet) */
outb(iobase + CLRSERR, 0x07); /* Haven't seen ant errors (yet) */
outb(SCSIID, sc->sc_initiator << OID_S); /* Set our SCSI-ID */
outb(BRSTCNTRL, EISA_BRST_TIM);
outb(iobase + SCSIID, sc->sc_initiator << OID_S); /* Set our SCSI-ID */
outb(iobase + BRSTCNTRL, EISA_BRST_TIM);
}
/* Pull the SCSI RST line for 500 us */
@ -819,10 +824,11 @@ void
aic_scsi_reset(sc)
struct aic_softc *sc;
{
int iobase = sc->sc_iobase;
outb(SCSISEQ, SCSIRSTO);
outb(iobase + SCSISEQ, SCSIRSTO);
delay(500);
outb(SCSISEQ, 0);
outb(iobase + SCSISEQ, 0);
delay(50);
}
@ -833,6 +839,7 @@ void
aic_init(sc)
struct aic_softc *sc;
{
int iobase = sc->sc_iobase;
struct aic_acb *acb;
int r;
@ -889,7 +896,7 @@ aic_init(sc)
}
sc->sc_state = AIC_IDLE;
outb(DMACNTRL0, INTEN);
outb(iobase + DMACNTRL0, INTEN);
}
void
@ -977,7 +984,7 @@ aic_scsi_cmd(xs)
sc_link->target));
flags = xs->flags;
if ((flags & (ITSDONE|INUSE)) != INUSE) {
if ((flags & (ITSDONE | INUSE)) != INUSE) {
printf("%s: done or not in use?\n", sc->sc_dev.dv_xname);
xs->flags &= ~ITSDONE;
xs->flags |= INUSE;
@ -1042,6 +1049,7 @@ aic_poll(sc, xs, count)
struct scsi_xfer *xs;
int count;
{
int iobase = sc->sc_iobase;
AIC_TRACE(("aic_poll "));
while (count) {
@ -1049,7 +1057,7 @@ aic_poll(sc, xs, count)
* If we had interrupts enabled, would we
* have got an interrupt?
*/
if ((inb(DMASTAT) & INTSTAT) != 0)
if ((inb(iobase + DMASTAT) & INTSTAT) != 0)
aicintr(sc);
if ((xs->flags & ITSDONE) != 0)
return 0;
@ -1063,32 +1071,36 @@ aic_poll(sc, xs, count)
* LOW LEVEL SCSI UTILITIES
*/
#define aic_sched_msgout(m) \
do { \
if (sc->sc_msgpriq == 0) \
outb(SCSISIG, sc->sc_phase|ATNO); \
sc->sc_msgpriq |= (m); \
} while (0)
integrate void
aic_sched_msgout(sc, m)
struct aic_softc *sc;
u_char m;
{
int iobase = sc->sc_iobase;
if (sc->sc_msgpriq == 0)
outb(iobase + SCSISIG, sc->sc_phase | ATNO);
sc->sc_msgpriq |= m;
}
#if AIC_USE_SYNCHRONOUS
/*
* Set synchronous transfer offset and period.
*/
static inline void
integrate void
aic_setsync(sc, ti)
struct aic_softc *sc;
struct aic_tinfo *ti;
{
#if AIC_USE_SYNCHRONOUS
int iobase = sc->sc_iobase;
if (ti->offset != 0)
outb(SCSIRATE,
outb(iobase + SCSIRATE,
((ti->period * sc->sc_freq) / 250 - 2) << 4 | ti->offset);
else
outb(SCSIRATE, 0);
}
#else
#define aic_setsync(sc, ti)
outb(iobase + SCSIRATE, 0);
#endif
}
/*
* Start a selection. This is used by aic_sched() to select an idle target,
@ -1102,15 +1114,16 @@ aic_select(sc, acb)
struct scsi_link *sc_link = acb->xs->sc_link;
int target = sc_link->target;
struct aic_tinfo *ti = &sc->sc_tinfo[target];
int iobase = sc->sc_iobase;
outb(SCSIID, sc->sc_initiator << OID_S | target);
outb(iobase + SCSIID, sc->sc_initiator << OID_S | target);
aic_setsync(sc, ti);
outb(SXFRCTL1, STIMO_256ms|ENSTIMER);
outb(iobase + SXFRCTL1, STIMO_256ms | ENSTIMER);
/* Always enable reselections. */
outb(SIMODE0, ENSELDI|ENSELDO);
outb(SIMODE1, ENSCSIRST|ENSELTIMO);
outb(SCSISEQ, ENRESELI|ENSELO|ENAUTOATNO);
outb(iobase + SIMODE0, ENSELDI | ENSELDO);
outb(iobase + SIMODE1, ENSCSIRST | ENSELTIMO);
outb(iobase + SCSISEQ, ENRESELI | ENSELO | ENAUTOATNO);
sc->sc_state = AIC_SELECTING;
}
@ -1176,12 +1189,12 @@ aic_reselect(sc, message)
reset:
sc->sc_flags |= AIC_ABORTING;
aic_sched_msgout(SEND_DEV_RESET);
aic_sched_msgout(sc, SEND_DEV_RESET);
return (1);
abort:
sc->sc_flags |= AIC_ABORTING;
aic_sched_msgout(SEND_ABORT);
aic_sched_msgout(sc, SEND_ABORT);
return (1);
}
@ -1198,12 +1211,13 @@ aic_sched(sc)
struct aic_acb *acb;
struct scsi_link *sc_link;
struct aic_tinfo *ti;
int iobase = sc->sc_iobase;
/*
* Find first acb in ready queue that is for a target/lunit pair that
* is not busy.
*/
outb(CLRSINT1, CLRSELTIMO|CLRBUSFREE|CLRSCSIPERR);
outb(iobase + CLRSINT1, CLRSELTIMO | CLRBUSFREE | CLRSCSIPERR);
for (acb = sc->ready_list.tqh_first; acb != NULL;
acb = acb->chain.tqe_next) {
sc_link = acb->xs->sc_link;
@ -1221,9 +1235,9 @@ aic_sched(sc)
}
AIC_MISC(("idle "));
/* Nothing to start; just enable reselections and wait. */
outb(SIMODE0, ENSELDI);
outb(SIMODE1, ENSCSIRST);
outb(SCSISEQ, ENRESELI);
outb(iobase + SIMODE0, ENSELDI);
outb(iobase + SIMODE1, ENSCSIRST);
outb(iobase + SCSISEQ, ENRESELI);
}
/*
@ -1362,6 +1376,7 @@ int
aic_msgin(sc)
register struct aic_softc *sc;
{
int iobase = sc->sc_iobase;
u_char sstat1;
int n;
@ -1388,12 +1403,12 @@ nextbyte:
*/
for (;;) {
for (;;) {
sstat1 = inb(SSTAT1);
if ((sstat1 & (REQINIT|BUSFREE)) != 0)
sstat1 = inb(iobase + SSTAT1);
if ((sstat1 & (REQINIT | BUSFREE)) != 0)
break;
/* Wait for REQINIT. XXX Need timeout. */
}
if ((sstat1 & (PHASECHG|BUSFREE)) != 0) {
if ((sstat1 & (PHASECHG | BUSFREE)) != 0) {
/*
* Target left MESSAGE IN, probably because it
* a) noticed our ATN signal, or
@ -1404,18 +1419,18 @@ nextbyte:
/* If parity error, just dump everything on the floor. */
if ((sstat1 & SCSIPERR) != 0) {
aic_sched_msgout(SEND_PARITY_ERROR);
sc->sc_flags |= AIC_DROP_MSGIN;
aic_sched_msgout(sc, SEND_PARITY_ERROR);
}
/* Gather incoming message bytes if needed. */
if ((sc->sc_flags & AIC_DROP_MSGIN) == 0) {
if (n >= AIC_MAX_MSG_LEN) {
(void) inb(SCSIDAT);
aic_sched_msgout(SEND_REJECT);
(void) inb(iobase + SCSIDAT);
sc->sc_flags |= AIC_DROP_MSGIN;
aic_sched_msgout(sc, SEND_REJECT);
} else {
*sc->sc_imp++ = inb(SCSIDAT);
*sc->sc_imp++ = inb(iobase + SCSIDAT);
n++;
/*
* This testing is suboptimal, but most
@ -1432,18 +1447,18 @@ nextbyte:
break;
}
} else
(void) inb(SCSIDAT);
(void) inb(iobase + SCSIDAT);
/*
* If we reach this spot we're either:
* a) in the middle of a multi-byte message, or
* b) dropping bytes.
*/
outb(SXFRCTL0, CHEN|SPIOEN);
outb(iobase + SXFRCTL0, CHEN | SPIOEN);
/* Ack the last byte read. */
(void) inb(SCSIDAT);
outb(SXFRCTL0, CHEN);
while ((inb(SCSISIG) & ACKI) != 0)
(void) inb(iobase + SCSIDAT);
outb(iobase + SXFRCTL0, CHEN);
while ((inb(iobase + SCSISIG) & ACKI) != 0)
;
}
@ -1475,7 +1490,7 @@ nextbyte:
case MSG_PARITY_ERROR:
/* Resend the last message. */
aic_sched_msgout(sc->sc_lastmsg);
aic_sched_msgout(sc, sc->sc_lastmsg);
break;
case MSG_MESSAGE_REJECT:
@ -1483,7 +1498,7 @@ nextbyte:
switch (sc->sc_lastmsg) {
#if AIC_USE_SYNCHRONOUS + AIC_USE_WIDE
case SEND_IDENTIFY:
ti->flags &= ~(DO_SYNC|DO_WIDE);
ti->flags &= ~(DO_SYNC | DO_WIDE);
ti->period = ti->offset = 0;
aic_setsync(sc, ti);
ti->width = 0;
@ -1504,7 +1519,7 @@ nextbyte:
#endif
case SEND_INIT_DET_ERR:
sc->sc_flags |= AIC_ABORTING;
aic_sched_msgout(SEND_ABORT);
aic_sched_msgout(sc, SEND_ABORT);
break;
}
break;
@ -1543,7 +1558,7 @@ nextbyte:
ti->period > sc->sc_maxsync ||
ti->offset > 8) {
ti->period = ti->offset = 0;
aic_sched_msgout(SEND_SDTR);
aic_sched_msgout(sc, SEND_SDTR);
} else {
sc_print_addr(acb->xs->sc_link);
printf("sync, offset %d, period %dnsec\n",
@ -1562,7 +1577,7 @@ nextbyte:
if (ti->width == 0) {
} else if (ti->width > AIC_MAX_WIDTH) {
ti->width = 0;
aic_sched_msgout(SEND_WDTR);
aic_sched_msgout(sc, SEND_WDTR);
} else {
sc_print_addr(acb->xs->sc_link);
printf("wide, width %d\n",
@ -1584,7 +1599,7 @@ nextbyte:
sc->sc_dev.dv_xname);
AIC_BREAK();
reject:
aic_sched_msgout(SEND_REJECT);
aic_sched_msgout(sc, SEND_REJECT);
break;
}
break;
@ -1606,20 +1621,20 @@ nextbyte:
AIC_BREAK();
reset:
sc->sc_flags |= AIC_ABORTING;
aic_sched_msgout(SEND_DEV_RESET);
aic_sched_msgout(sc, SEND_DEV_RESET);
break;
abort:
sc->sc_flags |= AIC_ABORTING;
aic_sched_msgout(SEND_ABORT);
aic_sched_msgout(sc, SEND_ABORT);
break;
}
outb(SXFRCTL0, CHEN|SPIOEN);
outb(iobase + SXFRCTL0, CHEN | SPIOEN);
/* Ack the last message byte. */
(void) inb(SCSIDAT);
outb(SXFRCTL0, CHEN);
while ((inb(SCSISIG) & ACKI) != 0)
(void) inb(iobase + SCSIDAT);
outb(iobase + SXFRCTL0, CHEN);
while ((inb(iobase + SCSISIG) & ACKI) != 0)
;
/* Go get the next message, if any. */
@ -1637,6 +1652,7 @@ void
aic_msgout(sc)
register struct aic_softc *sc;
{
int iobase = sc->sc_iobase;
struct aic_acb *acb;
struct aic_tinfo *ti;
u_char sstat1;
@ -1648,11 +1664,11 @@ aic_msgout(sc)
* Set ATN. If we're just sending a trivial 1-byte message, we'll
* clear ATN later on anyway.
*/
outb(SCSISIG, PH_MSGOUT|ATNO);
outb(iobase + SCSISIG, PH_MSGOUT | ATNO);
/* Reset the FIFO. */
outb(DMACNTRL0, RSTFIFO);
outb(iobase + DMACNTRL0, RSTFIFO);
/* Enable REQ/ACK protocol. */
outb(SXFRCTL0, CHEN|SPIOEN);
outb(iobase + SXFRCTL0, CHEN | SPIOEN);
if (sc->sc_prevphase == PH_MSGOUT) {
if (sc->sc_omp == sc->sc_omess) {
@ -1786,12 +1802,12 @@ nextbyte:
/* Send message bytes. */
for (;;) {
for (;;) {
sstat1 = inb(SSTAT1);
if ((sstat1 & (REQINIT|BUSFREE)) != 0)
sstat1 = inb(iobase + SSTAT1);
if ((sstat1 & (REQINIT | BUSFREE)) != 0)
break;
/* Wait for REQINIT. XXX Need timeout. */
}
if ((sstat1 & (PHASECHG|BUSFREE)) != 0) {
if ((sstat1 & (PHASECHG | BUSFREE)) != 0) {
/*
* Target left MESSAGE OUT, possibly to reject
* our message.
@ -1801,14 +1817,14 @@ nextbyte:
/* Clear ATN before last byte if this is the last message. */
if (n == 1 && sc->sc_msgpriq == 0)
outb(CLRSINT1, CLRATNO);
outb(iobase + CLRSINT1, CLRATNO);
/* Send message byte. */
outb(SCSIDAT, *--sc->sc_omp);
outb(iobase + SCSIDAT, *--sc->sc_omp);
--n;
/* Keep track of the last message we've sent any bytes of. */
sc->sc_lastmsg = sc->sc_currmsg;
/* Wait for ACK to be negated. XXX Need timeout. */
while ((inb(SCSISIG) & ACKI) != 0)
while ((inb(iobase + SCSISIG) & ACKI) != 0)
;
if (n == 0)
@ -1831,7 +1847,7 @@ nextbyte:
out:
/* Disable REQ/ACK protocol. */
outb(SXFRCTL0, CHEN);
outb(iobase + SXFRCTL0, CHEN);
}
/* aic_dataout_pio: perform a data transfer using the FIFO datapath in the aic6360
@ -1846,18 +1862,20 @@ aic_dataout_pio(sc, p, n)
u_char *p;
int n;
{
int iobase = sc->sc_iobase;
register u_char dmastat;
int out = 0;
#define DOUTAMOUNT 128 /* Full FIFO */
/* Clear host FIFO and counter. */
outb(DMACNTRL0, RSTFIFO|WRITE);
outb(iobase + DMACNTRL0, RSTFIFO | WRITE);
/* Enable FIFOs. */
outb(SXFRCTL0, SCSIEN|DMAEN|CHEN);
outb(DMACNTRL0, ENDMA|DWORDPIO|WRITE);
outb(iobase + SXFRCTL0, SCSIEN | DMAEN | CHEN);
outb(iobase + DMACNTRL0, ENDMA | DWORDPIO | WRITE);
/* Turn off ENREQINIT for now. */
outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENPHASECHG);
outb(iobase + SIMODE1,
ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENPHASECHG);
/* I have tried to make the main loop as tight as possible. This
* means that some of the code following the loop is a bit more
@ -1867,7 +1885,7 @@ aic_dataout_pio(sc, p, n)
int xfer;
for (;;) {
dmastat = inb(DMASTAT);
dmastat = inb(iobase + DMASTAT);
if ((dmastat & DFIFOEMP) != 0)
break;
if ((dmastat & INTSTAT) != 0)
@ -1883,40 +1901,40 @@ aic_dataout_pio(sc, p, n)
#if AIC_USE_DWORDS
if (xfer >= 12) {
outsl(DMADATALONG, p, xfer>>2);
outsl(iobase + DMADATALONG, p, xfer>>2);
p += xfer & ~3;
xfer &= 3;
}
#else
if (xfer >= 8) {
outsw(DMADATA, p, xfer>>1);
outsw(iobase + DMADATA, p, xfer>>1);
p += xfer & ~1;
xfer &= 1;
}
#endif
if (xfer > 0) {
outb(DMACNTRL0, ENDMA|B8MODE|WRITE);
outsb(DMADATA, p, xfer);
outb(iobase + DMACNTRL0, ENDMA | B8MODE | WRITE);
outsb(iobase + DMADATA, p, xfer);
p += xfer;
outb(DMACNTRL0, ENDMA|DWORDPIO|WRITE);
outb(iobase + DMACNTRL0, ENDMA | DWORDPIO | WRITE);
}
}
if (out == 0) {
outb(SXFRCTL1, BITBUCKET);
outb(iobase + SXFRCTL1, BITBUCKET);
for (;;) {
if ((inb(DMASTAT) & INTSTAT) != 0)
if ((inb(iobase + DMASTAT) & INTSTAT) != 0)
break;
}
outb(SXFRCTL1, 0);
outb(iobase + SXFRCTL1, 0);
AIC_MISC(("extra data "));
} else {
/* See the bytes off chip */
for (;;) {
dmastat = inb(DMASTAT);
dmastat = inb(iobase + DMASTAT);
if ((dmastat & DFIFOEMP) != 0 &&
(inb(SSTAT2) & SEMPTY) != 0)
(inb(iobase + SSTAT2) & SEMPTY) != 0)
break;
if ((dmastat & INTSTAT) != 0)
goto phasechange;
@ -1925,8 +1943,8 @@ aic_dataout_pio(sc, p, n)
phasechange:
/* Stop the FIFO data path. */
outb(SXFRCTL0, CHEN);
while ((inb(SXFRCTL0) & SCSIEN) != 0)
outb(iobase + SXFRCTL0, CHEN);
while ((inb(iobase + SXFRCTL0) & SCSIEN) != 0)
;
if ((dmastat & INTSTAT) != 0) {
@ -1934,16 +1952,17 @@ phasechange:
int amount;
/* Stop transfers, do some accounting */
amount = inb(FIFOSTAT) + (inb(SSTAT2) & 15);
amount = inb(iobase + FIFOSTAT) + (inb(iobase + SSTAT2) & 15);
if (amount > 0) {
out -= amount;
outb(SXFRCTL0, CHEN|CLRSTCNT|CLRCH);
outb(iobase + SXFRCTL0, CHEN | CLRSTCNT | CLRCH);
AIC_MISC(("+%d ", amount));
}
}
/* Turn on ENREQINIT again. */
outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENREQINIT|ENPHASECHG);
outb(iobase + SIMODE1,
ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENREQINIT | ENPHASECHG);
return out;
}
@ -1961,18 +1980,20 @@ aic_datain_pio(sc, p, n)
u_char *p;
int n;
{
int iobase = sc->sc_iobase;
register u_char dmastat;
int in = 0;
#define DINAMOUNT 128 /* Full FIFO */
/* Clear host FIFO and counter. */
outb(DMACNTRL0, RSTFIFO);
outb(iobase + DMACNTRL0, RSTFIFO);
/* Enable FIFOs */
outb(SXFRCTL0, SCSIEN|DMAEN|CHEN);
outb(DMACNTRL0, ENDMA|DWORDPIO);
outb(iobase + SXFRCTL0, SCSIEN | DMAEN | CHEN);
outb(iobase + DMACNTRL0, ENDMA | DWORDPIO);
/* Turn off ENREQINIT for now. */
outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENPHASECHG);
outb(iobase + SIMODE1,
ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENPHASECHG);
/* We leave this loop if one or more of the following is true:
* a) phase != PH_DATAIN && FIFOs are empty
@ -1983,15 +2004,15 @@ aic_datain_pio(sc, p, n)
/* Wait for fifo half full or phase mismatch */
for (;;) {
dmastat = inb(DMASTAT);
if ((dmastat & (DFIFOFULL|INTSTAT)) != 0)
dmastat = inb(iobase + DMASTAT);
if ((dmastat & (DFIFOFULL | INTSTAT)) != 0)
break;
}
if ((dmastat & DFIFOFULL) != 0)
xfer = min(DINAMOUNT, n);
else
xfer = min(inb(FIFOSTAT), n);
xfer = min(inb(iobase + FIFOSTAT), n);
AIC_MISC((">%d ", xfer));
@ -2000,23 +2021,23 @@ aic_datain_pio(sc, p, n)
#if AIC_USE_DWORDS
if (xfer >= 12) {
insl(DMADATALONG, p, xfer>>2);
insl(iobase + DMADATALONG, p, xfer>>2);
p += xfer & ~3;
xfer &= 3;
}
#else
if (xfer >= 8) {
insw(DMADATA, p, xfer>>1);
insw(iobase + DMADATA, p, xfer>>1);
p += xfer & ~1;
xfer &= 1;
}
#endif
if (xfer > 0) {
outb(DMACNTRL0, ENDMA|B8MODE);
insb(DMADATA, p, xfer);
outb(iobase + DMACNTRL0, ENDMA | B8MODE);
insb(iobase + DMADATA, p, xfer);
p += xfer;
outb(DMACNTRL0, ENDMA|DWORDPIO);
outb(iobase + DMACNTRL0, ENDMA | DWORDPIO);
}
if ((dmastat & INTSTAT) != 0)
@ -2030,23 +2051,24 @@ aic_datain_pio(sc, p, n)
* FIFO is not empty, waste some bytes....
*/
if (in == 0) {
outb(SXFRCTL1, BITBUCKET);
outb(iobase + SXFRCTL1, BITBUCKET);
for (;;) {
if ((inb(DMASTAT) & INTSTAT) != 0)
if ((inb(iobase + DMASTAT) & INTSTAT) != 0)
break;
}
outb(SXFRCTL1, 0);
outb(iobase + SXFRCTL1, 0);
AIC_MISC(("extra data "));
}
phasechange:
/* Stop the FIFO data path. */
outb(SXFRCTL0, CHEN);
while ((inb(SXFRCTL0) & SCSIEN) != 0)
outb(iobase + SXFRCTL0, CHEN);
while ((inb(iobase + SXFRCTL0) & SCSIEN) != 0)
;
/* Turn on ENREQINIT again. */
outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENREQINIT|ENPHASECHG);
outb(iobase + SIMODE1,
ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENREQINIT | ENPHASECHG);
return in;
}
@ -2061,6 +2083,7 @@ aicintr(arg)
void *arg;
{
register struct aic_softc *sc = arg;
int iobase = sc->sc_iobase;
u_char sstat0, sstat1;
register struct aic_acb *acb;
register struct scsi_link *sc_link;
@ -2071,7 +2094,7 @@ aicintr(arg)
* Clear INTEN. We enable it again before returning. This makes the
* interrupt esssentially level-triggered.
*/
outb(DMACNTRL0, 0);
outb(iobase + DMACNTRL0, 0);
AIC_TRACE(("aicintr "));
@ -2080,7 +2103,7 @@ gotintr:
/*
* First check for abnormal conditions, such as reset.
*/
sstat1 = inb(SSTAT1);
sstat1 = inb(iobase + SSTAT1);
AIC_MISC(("sstat1:0x%02x ", sstat1));
if ((sstat1 & SCSIRSTI) != 0) {
@ -2093,12 +2116,12 @@ gotintr:
*/
if ((sstat1 & SCSIPERR) != 0) {
printf("%s: SCSI bus parity error\n", sc->sc_dev.dv_xname);
outb(CLRSINT1, CLRSCSIPERR);
outb(iobase + CLRSINT1, CLRSCSIPERR);
if (sc->sc_prevphase == PH_MSGIN) {
aic_sched_msgout(SEND_PARITY_ERROR);
sc->sc_flags |= AIC_DROP_MSGIN;
aic_sched_msgout(sc, SEND_PARITY_ERROR);
} else
aic_sched_msgout(SEND_INIT_DET_ERR);
aic_sched_msgout(sc, SEND_INIT_DET_ERR);
}
/*
@ -2114,7 +2137,7 @@ gotintr:
switch (sc->sc_state) {
case AIC_IDLE:
case AIC_SELECTING:
sstat0 = inb(SSTAT0);
sstat0 = inb(iobase + SSTAT0);
AIC_MISC(("sstat0:0x%02x ", sstat0));
if ((sstat0 & TARGET) != 0) {
@ -2123,7 +2146,7 @@ gotintr:
*/
printf("%s: target mode selected; going to bus free\n",
sc->sc_dev.dv_xname);
outb(SCSISIG, 0);
outb(iobase + SCSISIG, 0);
sc->sc_state = AIC_IDLE;
aic_sched(sc);
@ -2144,7 +2167,7 @@ gotintr:
}
/* Save reselection ID. */
sc->sc_selid = inb(SELID);
sc->sc_selid = inb(iobase + SELID);
sc->sc_state = AIC_RESELECTED;
} else if ((sstat0 & SELDO) != 0) {
@ -2205,9 +2228,9 @@ gotintr:
AIC_ASSERT(sc->sc_nexus != NULL);
acb = sc->sc_nexus;
outb(SXFRCTL1, 0);
outb(SCSISEQ, ENRESELI);
outb(CLRSINT1, CLRSELTIMO);
outb(iobase + SXFRCTL1, 0);
outb(iobase + SCSISEQ, ENRESELI);
outb(iobase + CLRSINT1, CLRSELTIMO);
acb->xs->error = XS_SELTIMEOUT;
untimeout(aic_timeout, acb);
@ -2232,23 +2255,24 @@ gotintr:
* Turn off selection stuff, and prepare to catch bus free
* interrupts, parity errors, and phase changes.
*/
outb(SXFRCTL1, 0);
outb(SCSISEQ, ENAUTOATNP);
outb(CLRSINT0, CLRSELDI|CLRSELDO);
outb(CLRSINT1, CLRBUSFREE|CLRPHASECHG);
outb(SIMODE0, 0);
outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENREQINIT|ENPHASECHG);
outb(iobase + SXFRCTL1, 0);
outb(iobase + SCSISEQ, ENAUTOATNP);
outb(iobase + CLRSINT0, CLRSELDI | CLRSELDO);
outb(iobase + CLRSINT1, CLRBUSFREE | CLRPHASECHG);
outb(iobase + SIMODE0, 0);
outb(iobase + SIMODE1,
ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENREQINIT | ENPHASECHG);
sc->sc_flags = 0;
sc->sc_prevphase = PH_INVALID;
goto dophase;
}
outb(CLRSINT1, CLRPHASECHG);
outb(iobase + CLRSINT1, CLRPHASECHG);
if ((sstat1 & BUSFREE) != 0) {
/* We've gone to BUS FREE phase. */
outb(CLRSINT1, CLRBUSFREE);
outb(iobase + CLRSINT1, CLRBUSFREE);
switch (sc->sc_state) {
case AIC_RESELECTED:
@ -2293,8 +2317,8 @@ dophase:
goto out;
}
sc->sc_phase = inb(SCSISIG) & PH_MASK;
outb(SCSISIG, sc->sc_phase);
sc->sc_phase = inb(iobase + SCSISIG) & PH_MASK;
outb(iobase + SCSISIG, sc->sc_phase);
switch (sc->sc_phase) {
case PH_MSGOUT:
@ -2307,7 +2331,7 @@ dophase:
goto loop;
case PH_MSGIN:
if ((sc->sc_state & (AIC_CONNECTED|AIC_RESELECTED)) == 0)
if ((sc->sc_state & (AIC_CONNECTED | AIC_RESELECTED)) == 0)
break;
if (aic_msgin(sc)) {
sc->sc_prevphase = PH_MSGIN;
@ -2359,12 +2383,12 @@ dophase:
AIC_ASSERT(sc->sc_nexus != NULL);
acb = sc->sc_nexus;
/* XXXX Don't clear FIFO. Wait for byte to come in. */
outb(SXFRCTL0, CHEN|SPIOEN);
outb(DMACNTRL0, RSTFIFO);
acb->target_stat = inb(SCSIDAT);
outb(SXFRCTL0, CHEN);
outb(DMACNTRL0, RSTFIFO);
while ((inb(SXFRCTL0) & SCSIEN) != 0)
outb(iobase + SXFRCTL0, CHEN | SPIOEN);
outb(iobase + DMACNTRL0, RSTFIFO);
acb->target_stat = inb(iobase + SCSIDAT);
outb(iobase + SXFRCTL0, CHEN);
outb(iobase + DMACNTRL0, RSTFIFO);
while ((inb(iobase + SXFRCTL0) & SCSIEN) != 0)
;
AIC_MISC(("target_stat=0x%02x ", acb->target_stat));
sc->sc_prevphase = PH_STAT;
@ -2378,7 +2402,7 @@ reset:
return 1;
out:
outb(DMACNTRL0, INTEN);
outb(iobase + DMACNTRL0, INTEN);
return 1;
}
@ -2391,7 +2415,7 @@ aic_abort(sc, acb)
if (sc->sc_nexus == acb) {
if (sc->sc_state == AIC_CONNECTED) {
sc->sc_flags |= AIC_ABORTING;
aic_sched_msgout(SEND_ABORT);
aic_sched_msgout(sc, SEND_ABORT);
}
} else {
aic_dequeue(sc, acb);
@ -2495,16 +2519,20 @@ void
aic_dump6360(sc)
struct aic_softc *sc;
{
int iobase = sc->sc_iobase;
printf("aic6360: SCSISEQ=%x SXFRCTL0=%x SXFRCTL1=%x SCSISIG=%x\n",
inb(SCSISEQ), inb(SXFRCTL0), inb(SXFRCTL1), inb(SCSISIG));
inb(iobase + SCSISEQ), inb(iobase + SXFRCTL0),
inb(iobase + SXFRCTL1), inb(iobase + SCSISIG));
printf(" SSTAT0=%x SSTAT1=%x SSTAT2=%x SSTAT3=%x SSTAT4=%x\n",
inb(SSTAT0), inb(SSTAT1), inb(SSTAT2), inb(SSTAT3), inb(SSTAT4));
inb(iobase + SSTAT0), inb(iobase + SSTAT1), inb(iobase + SSTAT2),
inb(iobase + SSTAT3), inb(iobase + SSTAT4));
printf(" SIMODE0=%x SIMODE1=%x DMACNTRL0=%x DMACNTRL1=%x DMASTAT=%x\n",
inb(SIMODE0), inb(SIMODE1), inb(DMACNTRL0), inb(DMACNTRL1),
inb(DMASTAT));
inb(iobase + SIMODE0), inb(iobase + SIMODE1),
inb(iobase + DMACNTRL0), inb(iobase + DMACNTRL1),
inb(iobase + DMASTAT));
printf(" FIFOSTAT=%d SCSIBUS=0x%x\n",
inb(FIFOSTAT), inb(SCSIBUS));
inb(iobase + FIFOSTAT), inb(iobase + SCSIBUS));
}
void

View File

@ -1,7 +1,9 @@
/* $NetBSD: aic6360.c,v 1.39 1996/03/17 00:53:01 thorpej Exp $ */
/* $NetBSD: aic6360.c,v 1.40 1996/03/30 16:13:24 mycroft Exp $ */
#define integrate static inline
/*
* Copyright (c) 1994, 1995 Charles Hannum. All rights reserved.
* Copyright (c) 1994, 1995, 1996 Charles M. Hannum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -13,7 +15,7 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles Hannum.
* This product includes software developed by Charles M. Hannum.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
@ -136,45 +138,44 @@
*/
/* AIC6360 definitions */
#define IOBASE sc->sc_iobase
#define SCSISEQ (IOBASE + 0x00) /* SCSI sequence control */
#define SXFRCTL0 (IOBASE + 0x01) /* SCSI transfer control 0 */
#define SXFRCTL1 (IOBASE + 0x02) /* SCSI transfer control 1 */
#define SCSISIG (IOBASE + 0x03) /* SCSI signal in/out */
#define SCSIRATE (IOBASE + 0x04) /* SCSI rate control */
#define SCSIID (IOBASE + 0x05) /* SCSI ID */
#define SELID (IOBASE + 0x05) /* Selection/Reselection ID */
#define SCSIDAT (IOBASE + 0x06) /* SCSI Latched Data */
#define SCSIBUS (IOBASE + 0x07) /* SCSI Data Bus*/
#define STCNT0 (IOBASE + 0x08) /* SCSI transfer count */
#define STCNT1 (IOBASE + 0x09)
#define STCNT2 (IOBASE + 0x0a)
#define CLRSINT0 (IOBASE + 0x0b) /* Clear SCSI interrupts 0 */
#define SSTAT0 (IOBASE + 0x0b) /* SCSI interrupt status 0 */
#define CLRSINT1 (IOBASE + 0x0c) /* Clear SCSI interrupts 1 */
#define SSTAT1 (IOBASE + 0x0c) /* SCSI status 1 */
#define SSTAT2 (IOBASE + 0x0d) /* SCSI status 2 */
#define SCSITEST (IOBASE + 0x0e) /* SCSI test control */
#define SSTAT3 (IOBASE + 0x0e) /* SCSI status 3 */
#define CLRSERR (IOBASE + 0x0f) /* Clear SCSI errors */
#define SSTAT4 (IOBASE + 0x0f) /* SCSI status 4 */
#define SIMODE0 (IOBASE + 0x10) /* SCSI interrupt mode 0 */
#define SIMODE1 (IOBASE + 0x11) /* SCSI interrupt mode 1 */
#define DMACNTRL0 (IOBASE + 0x12) /* DMA control 0 */
#define DMACNTRL1 (IOBASE + 0x13) /* DMA control 1 */
#define DMASTAT (IOBASE + 0x14) /* DMA status */
#define FIFOSTAT (IOBASE + 0x15) /* FIFO status */
#define DMADATA (IOBASE + 0x16) /* DMA data */
#define DMADATAL (IOBASE + 0x16) /* DMA data low byte */
#define DMADATAH (IOBASE + 0x17) /* DMA data high byte */
#define BRSTCNTRL (IOBASE + 0x18) /* Burst Control */
#define DMADATALONG (IOBASE + 0x18)
#define PORTA (IOBASE + 0x1a) /* Port A */
#define PORTB (IOBASE + 0x1b) /* Port B */
#define REV (IOBASE + 0x1c) /* Revision (001 for 6360) */
#define STACK (IOBASE + 0x1d) /* Stack */
#define TEST (IOBASE + 0x1e) /* Test register */
#define ID (IOBASE + 0x1f) /* ID register */
#define SCSISEQ 0x00 /* SCSI sequence control */
#define SXFRCTL0 0x01 /* SCSI transfer control 0 */
#define SXFRCTL1 0x02 /* SCSI transfer control 1 */
#define SCSISIG 0x03 /* SCSI signal in/out */
#define SCSIRATE 0x04 /* SCSI rate control */
#define SCSIID 0x05 /* SCSI ID */
#define SELID 0x05 /* Selection/Reselection ID */
#define SCSIDAT 0x06 /* SCSI Latched Data */
#define SCSIBUS 0x07 /* SCSI Data Bus*/
#define STCNT0 0x08 /* SCSI transfer count */
#define STCNT1 0x09
#define STCNT2 0x0a
#define CLRSINT0 0x0b /* Clear SCSI interrupts 0 */
#define SSTAT0 0x0b /* SCSI interrupt status 0 */
#define CLRSINT1 0x0c /* Clear SCSI interrupts 1 */
#define SSTAT1 0x0c /* SCSI status 1 */
#define SSTAT2 0x0d /* SCSI status 2 */
#define SCSITEST 0x0e /* SCSI test control */
#define SSTAT3 0x0e /* SCSI status 3 */
#define CLRSERR 0x0f /* Clear SCSI errors */
#define SSTAT4 0x0f /* SCSI status 4 */
#define SIMODE0 0x10 /* SCSI interrupt mode 0 */
#define SIMODE1 0x11 /* SCSI interrupt mode 1 */
#define DMACNTRL0 0x12 /* DMA control 0 */
#define DMACNTRL1 0x13 /* DMA control 1 */
#define DMASTAT 0x14 /* DMA status */
#define FIFOSTAT 0x15 /* FIFO status */
#define DMADATA 0x16 /* DMA data */
#define DMADATAL 0x16 /* DMA data low byte */
#define DMADATAH 0x17 /* DMA data high byte */
#define BRSTCNTRL 0x18 /* Burst Control */
#define DMADATALONG 0x18
#define PORTA 0x1a /* Port A */
#define PORTB 0x1b /* Port B */
#define REV 0x1c /* Revision (001 for 6360) */
#define STACK 0x1d /* Stack */
#define TEST 0x1e /* Test register */
#define ID 0x1f /* ID register */
#define IDSTRING "(C)1991ADAPTECAIC6360 "
@ -580,6 +581,8 @@ void aic_done __P((struct aic_softc *, struct aic_acb *));
void aic_dequeue __P((struct aic_softc *, struct aic_acb *));
int aic_scsi_cmd __P((struct scsi_xfer *));
int aic_poll __P((struct aic_softc *, struct scsi_xfer *, int));
integrate void aic_sched_msgout __P((struct aic_softc *, u_char));
integrate void aic_setsync __P((struct aic_softc *, struct aic_tinfo *));
void aic_select __P((struct aic_softc *, struct aic_acb *));
void aic_timeout __P((void *));
int aic_find __P((struct aic_softc *));
@ -672,12 +675,13 @@ int
aic_find(sc)
struct aic_softc *sc;
{
int iobase = sc->sc_iobase;
char chip_id[sizeof(IDSTRING)]; /* For chips that support it */
char *start;
int i;
/* Remove aic6360 from possible powerdown mode */
outb(DMACNTRL0, 0);
outb(iobase + DMACNTRL0, 0);
/* Thanks to mark@aggregate.com for the new method for detecting
* whether the chip is present or not. Bonus: may also work for
@ -691,13 +695,13 @@ aic_find(sc)
*/
/* Push the sequence 0,1,..,15 on the stack */
#define STSIZE 16
outb(DMACNTRL1, 0); /* Reset stack pointer */
outb(iobase + DMACNTRL1, 0); /* Reset stack pointer */
for (i = 0; i < STSIZE; i++)
outb(STACK, i);
outb(iobase + STACK, i);
/* See if we can pull out the same sequence */
outb(DMACNTRL1, 0);
for (i = 0; i < STSIZE && inb(STACK) == i; i++)
outb(iobase + DMACNTRL1, 0);
for (i = 0; i < STSIZE && inb(iobase + STACK) == i; i++)
;
if (i != STSIZE) {
AIC_START(("STACK futzed at %d.\n", i));
@ -708,10 +712,10 @@ aic_find(sc)
* now only used for informational purposes.
*/
bzero(chip_id, sizeof(chip_id));
insb(ID, chip_id, sizeof(IDSTRING)-1);
insb(iobase + ID, chip_id, sizeof(IDSTRING)-1);
AIC_START(("AIC found at 0x%x ", sc->sc_iobase));
AIC_START(("ID: %s ",chip_id));
AIC_START(("chip revision %d\n",(int)inb(REV)));
AIC_START(("chip revision %d\n",(int)inb(iobase + REV)));
sc->sc_initiator = 7;
sc->sc_freq = 20; /* XXXX Assume 20 MHz. */
@ -786,32 +790,33 @@ void
aic_reset(sc)
struct aic_softc *sc;
{
int iobase = sc->sc_iobase;
outb(SCSITEST, 0); /* Doc. recommends to clear these two */
outb(TEST, 0); /* registers before operations commence */
outb(iobase + SCSITEST, 0); /* Doc. recommends to clear these two */
outb(iobase + TEST, 0); /* registers before operations commence */
/* Reset SCSI-FIFO and abort any transfers */
outb(SXFRCTL0, CHEN|CLRCH|CLRSTCNT);
outb(iobase + SXFRCTL0, CHEN | CLRCH | CLRSTCNT);
/* Reset DMA-FIFO */
outb(DMACNTRL0, RSTFIFO);
outb(DMACNTRL1, 0);
outb(iobase + DMACNTRL0, RSTFIFO);
outb(iobase + DMACNTRL1, 0);
outb(SCSISEQ, 0); /* Disable all selection features */
outb(SXFRCTL1, 0);
outb(iobase + SCSISEQ, 0); /* Disable all selection features */
outb(iobase + SXFRCTL1, 0);
outb(SIMODE0, 0x00); /* Disable some interrupts */
outb(CLRSINT0, 0x7f); /* Clear a slew of interrupts */
outb(iobase + SIMODE0, 0x00); /* Disable some interrupts */
outb(iobase + CLRSINT0, 0x7f); /* Clear a slew of interrupts */
outb(SIMODE1, 0x00); /* Disable some more interrupts */
outb(CLRSINT1, 0xef); /* Clear another slew of interrupts */
outb(iobase + SIMODE1, 0x00); /* Disable some more interrupts */
outb(iobase + CLRSINT1, 0xef); /* Clear another slew of interrupts */
outb(SCSIRATE, 0); /* Disable synchronous transfers */
outb(iobase + SCSIRATE, 0); /* Disable synchronous transfers */
outb(CLRSERR, 0x07); /* Haven't seen ant errors (yet) */
outb(iobase + CLRSERR, 0x07); /* Haven't seen ant errors (yet) */
outb(SCSIID, sc->sc_initiator << OID_S); /* Set our SCSI-ID */
outb(BRSTCNTRL, EISA_BRST_TIM);
outb(iobase + SCSIID, sc->sc_initiator << OID_S); /* Set our SCSI-ID */
outb(iobase + BRSTCNTRL, EISA_BRST_TIM);
}
/* Pull the SCSI RST line for 500 us */
@ -819,10 +824,11 @@ void
aic_scsi_reset(sc)
struct aic_softc *sc;
{
int iobase = sc->sc_iobase;
outb(SCSISEQ, SCSIRSTO);
outb(iobase + SCSISEQ, SCSIRSTO);
delay(500);
outb(SCSISEQ, 0);
outb(iobase + SCSISEQ, 0);
delay(50);
}
@ -833,6 +839,7 @@ void
aic_init(sc)
struct aic_softc *sc;
{
int iobase = sc->sc_iobase;
struct aic_acb *acb;
int r;
@ -889,7 +896,7 @@ aic_init(sc)
}
sc->sc_state = AIC_IDLE;
outb(DMACNTRL0, INTEN);
outb(iobase + DMACNTRL0, INTEN);
}
void
@ -977,7 +984,7 @@ aic_scsi_cmd(xs)
sc_link->target));
flags = xs->flags;
if ((flags & (ITSDONE|INUSE)) != INUSE) {
if ((flags & (ITSDONE | INUSE)) != INUSE) {
printf("%s: done or not in use?\n", sc->sc_dev.dv_xname);
xs->flags &= ~ITSDONE;
xs->flags |= INUSE;
@ -1042,6 +1049,7 @@ aic_poll(sc, xs, count)
struct scsi_xfer *xs;
int count;
{
int iobase = sc->sc_iobase;
AIC_TRACE(("aic_poll "));
while (count) {
@ -1049,7 +1057,7 @@ aic_poll(sc, xs, count)
* If we had interrupts enabled, would we
* have got an interrupt?
*/
if ((inb(DMASTAT) & INTSTAT) != 0)
if ((inb(iobase + DMASTAT) & INTSTAT) != 0)
aicintr(sc);
if ((xs->flags & ITSDONE) != 0)
return 0;
@ -1063,32 +1071,36 @@ aic_poll(sc, xs, count)
* LOW LEVEL SCSI UTILITIES
*/
#define aic_sched_msgout(m) \
do { \
if (sc->sc_msgpriq == 0) \
outb(SCSISIG, sc->sc_phase|ATNO); \
sc->sc_msgpriq |= (m); \
} while (0)
integrate void
aic_sched_msgout(sc, m)
struct aic_softc *sc;
u_char m;
{
int iobase = sc->sc_iobase;
if (sc->sc_msgpriq == 0)
outb(iobase + SCSISIG, sc->sc_phase | ATNO);
sc->sc_msgpriq |= m;
}
#if AIC_USE_SYNCHRONOUS
/*
* Set synchronous transfer offset and period.
*/
static inline void
integrate void
aic_setsync(sc, ti)
struct aic_softc *sc;
struct aic_tinfo *ti;
{
#if AIC_USE_SYNCHRONOUS
int iobase = sc->sc_iobase;
if (ti->offset != 0)
outb(SCSIRATE,
outb(iobase + SCSIRATE,
((ti->period * sc->sc_freq) / 250 - 2) << 4 | ti->offset);
else
outb(SCSIRATE, 0);
}
#else
#define aic_setsync(sc, ti)
outb(iobase + SCSIRATE, 0);
#endif
}
/*
* Start a selection. This is used by aic_sched() to select an idle target,
@ -1102,15 +1114,16 @@ aic_select(sc, acb)
struct scsi_link *sc_link = acb->xs->sc_link;
int target = sc_link->target;
struct aic_tinfo *ti = &sc->sc_tinfo[target];
int iobase = sc->sc_iobase;
outb(SCSIID, sc->sc_initiator << OID_S | target);
outb(iobase + SCSIID, sc->sc_initiator << OID_S | target);
aic_setsync(sc, ti);
outb(SXFRCTL1, STIMO_256ms|ENSTIMER);
outb(iobase + SXFRCTL1, STIMO_256ms | ENSTIMER);
/* Always enable reselections. */
outb(SIMODE0, ENSELDI|ENSELDO);
outb(SIMODE1, ENSCSIRST|ENSELTIMO);
outb(SCSISEQ, ENRESELI|ENSELO|ENAUTOATNO);
outb(iobase + SIMODE0, ENSELDI | ENSELDO);
outb(iobase + SIMODE1, ENSCSIRST | ENSELTIMO);
outb(iobase + SCSISEQ, ENRESELI | ENSELO | ENAUTOATNO);
sc->sc_state = AIC_SELECTING;
}
@ -1176,12 +1189,12 @@ aic_reselect(sc, message)
reset:
sc->sc_flags |= AIC_ABORTING;
aic_sched_msgout(SEND_DEV_RESET);
aic_sched_msgout(sc, SEND_DEV_RESET);
return (1);
abort:
sc->sc_flags |= AIC_ABORTING;
aic_sched_msgout(SEND_ABORT);
aic_sched_msgout(sc, SEND_ABORT);
return (1);
}
@ -1198,12 +1211,13 @@ aic_sched(sc)
struct aic_acb *acb;
struct scsi_link *sc_link;
struct aic_tinfo *ti;
int iobase = sc->sc_iobase;
/*
* Find first acb in ready queue that is for a target/lunit pair that
* is not busy.
*/
outb(CLRSINT1, CLRSELTIMO|CLRBUSFREE|CLRSCSIPERR);
outb(iobase + CLRSINT1, CLRSELTIMO | CLRBUSFREE | CLRSCSIPERR);
for (acb = sc->ready_list.tqh_first; acb != NULL;
acb = acb->chain.tqe_next) {
sc_link = acb->xs->sc_link;
@ -1221,9 +1235,9 @@ aic_sched(sc)
}
AIC_MISC(("idle "));
/* Nothing to start; just enable reselections and wait. */
outb(SIMODE0, ENSELDI);
outb(SIMODE1, ENSCSIRST);
outb(SCSISEQ, ENRESELI);
outb(iobase + SIMODE0, ENSELDI);
outb(iobase + SIMODE1, ENSCSIRST);
outb(iobase + SCSISEQ, ENRESELI);
}
/*
@ -1362,6 +1376,7 @@ int
aic_msgin(sc)
register struct aic_softc *sc;
{
int iobase = sc->sc_iobase;
u_char sstat1;
int n;
@ -1388,12 +1403,12 @@ nextbyte:
*/
for (;;) {
for (;;) {
sstat1 = inb(SSTAT1);
if ((sstat1 & (REQINIT|BUSFREE)) != 0)
sstat1 = inb(iobase + SSTAT1);
if ((sstat1 & (REQINIT | BUSFREE)) != 0)
break;
/* Wait for REQINIT. XXX Need timeout. */
}
if ((sstat1 & (PHASECHG|BUSFREE)) != 0) {
if ((sstat1 & (PHASECHG | BUSFREE)) != 0) {
/*
* Target left MESSAGE IN, probably because it
* a) noticed our ATN signal, or
@ -1404,18 +1419,18 @@ nextbyte:
/* If parity error, just dump everything on the floor. */
if ((sstat1 & SCSIPERR) != 0) {
aic_sched_msgout(SEND_PARITY_ERROR);
sc->sc_flags |= AIC_DROP_MSGIN;
aic_sched_msgout(sc, SEND_PARITY_ERROR);
}
/* Gather incoming message bytes if needed. */
if ((sc->sc_flags & AIC_DROP_MSGIN) == 0) {
if (n >= AIC_MAX_MSG_LEN) {
(void) inb(SCSIDAT);
aic_sched_msgout(SEND_REJECT);
(void) inb(iobase + SCSIDAT);
sc->sc_flags |= AIC_DROP_MSGIN;
aic_sched_msgout(sc, SEND_REJECT);
} else {
*sc->sc_imp++ = inb(SCSIDAT);
*sc->sc_imp++ = inb(iobase + SCSIDAT);
n++;
/*
* This testing is suboptimal, but most
@ -1432,18 +1447,18 @@ nextbyte:
break;
}
} else
(void) inb(SCSIDAT);
(void) inb(iobase + SCSIDAT);
/*
* If we reach this spot we're either:
* a) in the middle of a multi-byte message, or
* b) dropping bytes.
*/
outb(SXFRCTL0, CHEN|SPIOEN);
outb(iobase + SXFRCTL0, CHEN | SPIOEN);
/* Ack the last byte read. */
(void) inb(SCSIDAT);
outb(SXFRCTL0, CHEN);
while ((inb(SCSISIG) & ACKI) != 0)
(void) inb(iobase + SCSIDAT);
outb(iobase + SXFRCTL0, CHEN);
while ((inb(iobase + SCSISIG) & ACKI) != 0)
;
}
@ -1475,7 +1490,7 @@ nextbyte:
case MSG_PARITY_ERROR:
/* Resend the last message. */
aic_sched_msgout(sc->sc_lastmsg);
aic_sched_msgout(sc, sc->sc_lastmsg);
break;
case MSG_MESSAGE_REJECT:
@ -1483,7 +1498,7 @@ nextbyte:
switch (sc->sc_lastmsg) {
#if AIC_USE_SYNCHRONOUS + AIC_USE_WIDE
case SEND_IDENTIFY:
ti->flags &= ~(DO_SYNC|DO_WIDE);
ti->flags &= ~(DO_SYNC | DO_WIDE);
ti->period = ti->offset = 0;
aic_setsync(sc, ti);
ti->width = 0;
@ -1504,7 +1519,7 @@ nextbyte:
#endif
case SEND_INIT_DET_ERR:
sc->sc_flags |= AIC_ABORTING;
aic_sched_msgout(SEND_ABORT);
aic_sched_msgout(sc, SEND_ABORT);
break;
}
break;
@ -1543,7 +1558,7 @@ nextbyte:
ti->period > sc->sc_maxsync ||
ti->offset > 8) {
ti->period = ti->offset = 0;
aic_sched_msgout(SEND_SDTR);
aic_sched_msgout(sc, SEND_SDTR);
} else {
sc_print_addr(acb->xs->sc_link);
printf("sync, offset %d, period %dnsec\n",
@ -1562,7 +1577,7 @@ nextbyte:
if (ti->width == 0) {
} else if (ti->width > AIC_MAX_WIDTH) {
ti->width = 0;
aic_sched_msgout(SEND_WDTR);
aic_sched_msgout(sc, SEND_WDTR);
} else {
sc_print_addr(acb->xs->sc_link);
printf("wide, width %d\n",
@ -1584,7 +1599,7 @@ nextbyte:
sc->sc_dev.dv_xname);
AIC_BREAK();
reject:
aic_sched_msgout(SEND_REJECT);
aic_sched_msgout(sc, SEND_REJECT);
break;
}
break;
@ -1606,20 +1621,20 @@ nextbyte:
AIC_BREAK();
reset:
sc->sc_flags |= AIC_ABORTING;
aic_sched_msgout(SEND_DEV_RESET);
aic_sched_msgout(sc, SEND_DEV_RESET);
break;
abort:
sc->sc_flags |= AIC_ABORTING;
aic_sched_msgout(SEND_ABORT);
aic_sched_msgout(sc, SEND_ABORT);
break;
}
outb(SXFRCTL0, CHEN|SPIOEN);
outb(iobase + SXFRCTL0, CHEN | SPIOEN);
/* Ack the last message byte. */
(void) inb(SCSIDAT);
outb(SXFRCTL0, CHEN);
while ((inb(SCSISIG) & ACKI) != 0)
(void) inb(iobase + SCSIDAT);
outb(iobase + SXFRCTL0, CHEN);
while ((inb(iobase + SCSISIG) & ACKI) != 0)
;
/* Go get the next message, if any. */
@ -1637,6 +1652,7 @@ void
aic_msgout(sc)
register struct aic_softc *sc;
{
int iobase = sc->sc_iobase;
struct aic_acb *acb;
struct aic_tinfo *ti;
u_char sstat1;
@ -1648,11 +1664,11 @@ aic_msgout(sc)
* Set ATN. If we're just sending a trivial 1-byte message, we'll
* clear ATN later on anyway.
*/
outb(SCSISIG, PH_MSGOUT|ATNO);
outb(iobase + SCSISIG, PH_MSGOUT | ATNO);
/* Reset the FIFO. */
outb(DMACNTRL0, RSTFIFO);
outb(iobase + DMACNTRL0, RSTFIFO);
/* Enable REQ/ACK protocol. */
outb(SXFRCTL0, CHEN|SPIOEN);
outb(iobase + SXFRCTL0, CHEN | SPIOEN);
if (sc->sc_prevphase == PH_MSGOUT) {
if (sc->sc_omp == sc->sc_omess) {
@ -1786,12 +1802,12 @@ nextbyte:
/* Send message bytes. */
for (;;) {
for (;;) {
sstat1 = inb(SSTAT1);
if ((sstat1 & (REQINIT|BUSFREE)) != 0)
sstat1 = inb(iobase + SSTAT1);
if ((sstat1 & (REQINIT | BUSFREE)) != 0)
break;
/* Wait for REQINIT. XXX Need timeout. */
}
if ((sstat1 & (PHASECHG|BUSFREE)) != 0) {
if ((sstat1 & (PHASECHG | BUSFREE)) != 0) {
/*
* Target left MESSAGE OUT, possibly to reject
* our message.
@ -1801,14 +1817,14 @@ nextbyte:
/* Clear ATN before last byte if this is the last message. */
if (n == 1 && sc->sc_msgpriq == 0)
outb(CLRSINT1, CLRATNO);
outb(iobase + CLRSINT1, CLRATNO);
/* Send message byte. */
outb(SCSIDAT, *--sc->sc_omp);
outb(iobase + SCSIDAT, *--sc->sc_omp);
--n;
/* Keep track of the last message we've sent any bytes of. */
sc->sc_lastmsg = sc->sc_currmsg;
/* Wait for ACK to be negated. XXX Need timeout. */
while ((inb(SCSISIG) & ACKI) != 0)
while ((inb(iobase + SCSISIG) & ACKI) != 0)
;
if (n == 0)
@ -1831,7 +1847,7 @@ nextbyte:
out:
/* Disable REQ/ACK protocol. */
outb(SXFRCTL0, CHEN);
outb(iobase + SXFRCTL0, CHEN);
}
/* aic_dataout_pio: perform a data transfer using the FIFO datapath in the aic6360
@ -1846,18 +1862,20 @@ aic_dataout_pio(sc, p, n)
u_char *p;
int n;
{
int iobase = sc->sc_iobase;
register u_char dmastat;
int out = 0;
#define DOUTAMOUNT 128 /* Full FIFO */
/* Clear host FIFO and counter. */
outb(DMACNTRL0, RSTFIFO|WRITE);
outb(iobase + DMACNTRL0, RSTFIFO | WRITE);
/* Enable FIFOs. */
outb(SXFRCTL0, SCSIEN|DMAEN|CHEN);
outb(DMACNTRL0, ENDMA|DWORDPIO|WRITE);
outb(iobase + SXFRCTL0, SCSIEN | DMAEN | CHEN);
outb(iobase + DMACNTRL0, ENDMA | DWORDPIO | WRITE);
/* Turn off ENREQINIT for now. */
outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENPHASECHG);
outb(iobase + SIMODE1,
ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENPHASECHG);
/* I have tried to make the main loop as tight as possible. This
* means that some of the code following the loop is a bit more
@ -1867,7 +1885,7 @@ aic_dataout_pio(sc, p, n)
int xfer;
for (;;) {
dmastat = inb(DMASTAT);
dmastat = inb(iobase + DMASTAT);
if ((dmastat & DFIFOEMP) != 0)
break;
if ((dmastat & INTSTAT) != 0)
@ -1883,40 +1901,40 @@ aic_dataout_pio(sc, p, n)
#if AIC_USE_DWORDS
if (xfer >= 12) {
outsl(DMADATALONG, p, xfer>>2);
outsl(iobase + DMADATALONG, p, xfer>>2);
p += xfer & ~3;
xfer &= 3;
}
#else
if (xfer >= 8) {
outsw(DMADATA, p, xfer>>1);
outsw(iobase + DMADATA, p, xfer>>1);
p += xfer & ~1;
xfer &= 1;
}
#endif
if (xfer > 0) {
outb(DMACNTRL0, ENDMA|B8MODE|WRITE);
outsb(DMADATA, p, xfer);
outb(iobase + DMACNTRL0, ENDMA | B8MODE | WRITE);
outsb(iobase + DMADATA, p, xfer);
p += xfer;
outb(DMACNTRL0, ENDMA|DWORDPIO|WRITE);
outb(iobase + DMACNTRL0, ENDMA | DWORDPIO | WRITE);
}
}
if (out == 0) {
outb(SXFRCTL1, BITBUCKET);
outb(iobase + SXFRCTL1, BITBUCKET);
for (;;) {
if ((inb(DMASTAT) & INTSTAT) != 0)
if ((inb(iobase + DMASTAT) & INTSTAT) != 0)
break;
}
outb(SXFRCTL1, 0);
outb(iobase + SXFRCTL1, 0);
AIC_MISC(("extra data "));
} else {
/* See the bytes off chip */
for (;;) {
dmastat = inb(DMASTAT);
dmastat = inb(iobase + DMASTAT);
if ((dmastat & DFIFOEMP) != 0 &&
(inb(SSTAT2) & SEMPTY) != 0)
(inb(iobase + SSTAT2) & SEMPTY) != 0)
break;
if ((dmastat & INTSTAT) != 0)
goto phasechange;
@ -1925,8 +1943,8 @@ aic_dataout_pio(sc, p, n)
phasechange:
/* Stop the FIFO data path. */
outb(SXFRCTL0, CHEN);
while ((inb(SXFRCTL0) & SCSIEN) != 0)
outb(iobase + SXFRCTL0, CHEN);
while ((inb(iobase + SXFRCTL0) & SCSIEN) != 0)
;
if ((dmastat & INTSTAT) != 0) {
@ -1934,16 +1952,17 @@ phasechange:
int amount;
/* Stop transfers, do some accounting */
amount = inb(FIFOSTAT) + (inb(SSTAT2) & 15);
amount = inb(iobase + FIFOSTAT) + (inb(iobase + SSTAT2) & 15);
if (amount > 0) {
out -= amount;
outb(SXFRCTL0, CHEN|CLRSTCNT|CLRCH);
outb(iobase + SXFRCTL0, CHEN | CLRSTCNT | CLRCH);
AIC_MISC(("+%d ", amount));
}
}
/* Turn on ENREQINIT again. */
outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENREQINIT|ENPHASECHG);
outb(iobase + SIMODE1,
ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENREQINIT | ENPHASECHG);
return out;
}
@ -1961,18 +1980,20 @@ aic_datain_pio(sc, p, n)
u_char *p;
int n;
{
int iobase = sc->sc_iobase;
register u_char dmastat;
int in = 0;
#define DINAMOUNT 128 /* Full FIFO */
/* Clear host FIFO and counter. */
outb(DMACNTRL0, RSTFIFO);
outb(iobase + DMACNTRL0, RSTFIFO);
/* Enable FIFOs */
outb(SXFRCTL0, SCSIEN|DMAEN|CHEN);
outb(DMACNTRL0, ENDMA|DWORDPIO);
outb(iobase + SXFRCTL0, SCSIEN | DMAEN | CHEN);
outb(iobase + DMACNTRL0, ENDMA | DWORDPIO);
/* Turn off ENREQINIT for now. */
outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENPHASECHG);
outb(iobase + SIMODE1,
ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENPHASECHG);
/* We leave this loop if one or more of the following is true:
* a) phase != PH_DATAIN && FIFOs are empty
@ -1983,15 +2004,15 @@ aic_datain_pio(sc, p, n)
/* Wait for fifo half full or phase mismatch */
for (;;) {
dmastat = inb(DMASTAT);
if ((dmastat & (DFIFOFULL|INTSTAT)) != 0)
dmastat = inb(iobase + DMASTAT);
if ((dmastat & (DFIFOFULL | INTSTAT)) != 0)
break;
}
if ((dmastat & DFIFOFULL) != 0)
xfer = min(DINAMOUNT, n);
else
xfer = min(inb(FIFOSTAT), n);
xfer = min(inb(iobase + FIFOSTAT), n);
AIC_MISC((">%d ", xfer));
@ -2000,23 +2021,23 @@ aic_datain_pio(sc, p, n)
#if AIC_USE_DWORDS
if (xfer >= 12) {
insl(DMADATALONG, p, xfer>>2);
insl(iobase + DMADATALONG, p, xfer>>2);
p += xfer & ~3;
xfer &= 3;
}
#else
if (xfer >= 8) {
insw(DMADATA, p, xfer>>1);
insw(iobase + DMADATA, p, xfer>>1);
p += xfer & ~1;
xfer &= 1;
}
#endif
if (xfer > 0) {
outb(DMACNTRL0, ENDMA|B8MODE);
insb(DMADATA, p, xfer);
outb(iobase + DMACNTRL0, ENDMA | B8MODE);
insb(iobase + DMADATA, p, xfer);
p += xfer;
outb(DMACNTRL0, ENDMA|DWORDPIO);
outb(iobase + DMACNTRL0, ENDMA | DWORDPIO);
}
if ((dmastat & INTSTAT) != 0)
@ -2030,23 +2051,24 @@ aic_datain_pio(sc, p, n)
* FIFO is not empty, waste some bytes....
*/
if (in == 0) {
outb(SXFRCTL1, BITBUCKET);
outb(iobase + SXFRCTL1, BITBUCKET);
for (;;) {
if ((inb(DMASTAT) & INTSTAT) != 0)
if ((inb(iobase + DMASTAT) & INTSTAT) != 0)
break;
}
outb(SXFRCTL1, 0);
outb(iobase + SXFRCTL1, 0);
AIC_MISC(("extra data "));
}
phasechange:
/* Stop the FIFO data path. */
outb(SXFRCTL0, CHEN);
while ((inb(SXFRCTL0) & SCSIEN) != 0)
outb(iobase + SXFRCTL0, CHEN);
while ((inb(iobase + SXFRCTL0) & SCSIEN) != 0)
;
/* Turn on ENREQINIT again. */
outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENREQINIT|ENPHASECHG);
outb(iobase + SIMODE1,
ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENREQINIT | ENPHASECHG);
return in;
}
@ -2061,6 +2083,7 @@ aicintr(arg)
void *arg;
{
register struct aic_softc *sc = arg;
int iobase = sc->sc_iobase;
u_char sstat0, sstat1;
register struct aic_acb *acb;
register struct scsi_link *sc_link;
@ -2071,7 +2094,7 @@ aicintr(arg)
* Clear INTEN. We enable it again before returning. This makes the
* interrupt esssentially level-triggered.
*/
outb(DMACNTRL0, 0);
outb(iobase + DMACNTRL0, 0);
AIC_TRACE(("aicintr "));
@ -2080,7 +2103,7 @@ gotintr:
/*
* First check for abnormal conditions, such as reset.
*/
sstat1 = inb(SSTAT1);
sstat1 = inb(iobase + SSTAT1);
AIC_MISC(("sstat1:0x%02x ", sstat1));
if ((sstat1 & SCSIRSTI) != 0) {
@ -2093,12 +2116,12 @@ gotintr:
*/
if ((sstat1 & SCSIPERR) != 0) {
printf("%s: SCSI bus parity error\n", sc->sc_dev.dv_xname);
outb(CLRSINT1, CLRSCSIPERR);
outb(iobase + CLRSINT1, CLRSCSIPERR);
if (sc->sc_prevphase == PH_MSGIN) {
aic_sched_msgout(SEND_PARITY_ERROR);
sc->sc_flags |= AIC_DROP_MSGIN;
aic_sched_msgout(sc, SEND_PARITY_ERROR);
} else
aic_sched_msgout(SEND_INIT_DET_ERR);
aic_sched_msgout(sc, SEND_INIT_DET_ERR);
}
/*
@ -2114,7 +2137,7 @@ gotintr:
switch (sc->sc_state) {
case AIC_IDLE:
case AIC_SELECTING:
sstat0 = inb(SSTAT0);
sstat0 = inb(iobase + SSTAT0);
AIC_MISC(("sstat0:0x%02x ", sstat0));
if ((sstat0 & TARGET) != 0) {
@ -2123,7 +2146,7 @@ gotintr:
*/
printf("%s: target mode selected; going to bus free\n",
sc->sc_dev.dv_xname);
outb(SCSISIG, 0);
outb(iobase + SCSISIG, 0);
sc->sc_state = AIC_IDLE;
aic_sched(sc);
@ -2144,7 +2167,7 @@ gotintr:
}
/* Save reselection ID. */
sc->sc_selid = inb(SELID);
sc->sc_selid = inb(iobase + SELID);
sc->sc_state = AIC_RESELECTED;
} else if ((sstat0 & SELDO) != 0) {
@ -2205,9 +2228,9 @@ gotintr:
AIC_ASSERT(sc->sc_nexus != NULL);
acb = sc->sc_nexus;
outb(SXFRCTL1, 0);
outb(SCSISEQ, ENRESELI);
outb(CLRSINT1, CLRSELTIMO);
outb(iobase + SXFRCTL1, 0);
outb(iobase + SCSISEQ, ENRESELI);
outb(iobase + CLRSINT1, CLRSELTIMO);
acb->xs->error = XS_SELTIMEOUT;
untimeout(aic_timeout, acb);
@ -2232,23 +2255,24 @@ gotintr:
* Turn off selection stuff, and prepare to catch bus free
* interrupts, parity errors, and phase changes.
*/
outb(SXFRCTL1, 0);
outb(SCSISEQ, ENAUTOATNP);
outb(CLRSINT0, CLRSELDI|CLRSELDO);
outb(CLRSINT1, CLRBUSFREE|CLRPHASECHG);
outb(SIMODE0, 0);
outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENREQINIT|ENPHASECHG);
outb(iobase + SXFRCTL1, 0);
outb(iobase + SCSISEQ, ENAUTOATNP);
outb(iobase + CLRSINT0, CLRSELDI | CLRSELDO);
outb(iobase + CLRSINT1, CLRBUSFREE | CLRPHASECHG);
outb(iobase + SIMODE0, 0);
outb(iobase + SIMODE1,
ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENREQINIT | ENPHASECHG);
sc->sc_flags = 0;
sc->sc_prevphase = PH_INVALID;
goto dophase;
}
outb(CLRSINT1, CLRPHASECHG);
outb(iobase + CLRSINT1, CLRPHASECHG);
if ((sstat1 & BUSFREE) != 0) {
/* We've gone to BUS FREE phase. */
outb(CLRSINT1, CLRBUSFREE);
outb(iobase + CLRSINT1, CLRBUSFREE);
switch (sc->sc_state) {
case AIC_RESELECTED:
@ -2293,8 +2317,8 @@ dophase:
goto out;
}
sc->sc_phase = inb(SCSISIG) & PH_MASK;
outb(SCSISIG, sc->sc_phase);
sc->sc_phase = inb(iobase + SCSISIG) & PH_MASK;
outb(iobase + SCSISIG, sc->sc_phase);
switch (sc->sc_phase) {
case PH_MSGOUT:
@ -2307,7 +2331,7 @@ dophase:
goto loop;
case PH_MSGIN:
if ((sc->sc_state & (AIC_CONNECTED|AIC_RESELECTED)) == 0)
if ((sc->sc_state & (AIC_CONNECTED | AIC_RESELECTED)) == 0)
break;
if (aic_msgin(sc)) {
sc->sc_prevphase = PH_MSGIN;
@ -2359,12 +2383,12 @@ dophase:
AIC_ASSERT(sc->sc_nexus != NULL);
acb = sc->sc_nexus;
/* XXXX Don't clear FIFO. Wait for byte to come in. */
outb(SXFRCTL0, CHEN|SPIOEN);
outb(DMACNTRL0, RSTFIFO);
acb->target_stat = inb(SCSIDAT);
outb(SXFRCTL0, CHEN);
outb(DMACNTRL0, RSTFIFO);
while ((inb(SXFRCTL0) & SCSIEN) != 0)
outb(iobase + SXFRCTL0, CHEN | SPIOEN);
outb(iobase + DMACNTRL0, RSTFIFO);
acb->target_stat = inb(iobase + SCSIDAT);
outb(iobase + SXFRCTL0, CHEN);
outb(iobase + DMACNTRL0, RSTFIFO);
while ((inb(iobase + SXFRCTL0) & SCSIEN) != 0)
;
AIC_MISC(("target_stat=0x%02x ", acb->target_stat));
sc->sc_prevphase = PH_STAT;
@ -2378,7 +2402,7 @@ reset:
return 1;
out:
outb(DMACNTRL0, INTEN);
outb(iobase + DMACNTRL0, INTEN);
return 1;
}
@ -2391,7 +2415,7 @@ aic_abort(sc, acb)
if (sc->sc_nexus == acb) {
if (sc->sc_state == AIC_CONNECTED) {
sc->sc_flags |= AIC_ABORTING;
aic_sched_msgout(SEND_ABORT);
aic_sched_msgout(sc, SEND_ABORT);
}
} else {
aic_dequeue(sc, acb);
@ -2495,16 +2519,20 @@ void
aic_dump6360(sc)
struct aic_softc *sc;
{
int iobase = sc->sc_iobase;
printf("aic6360: SCSISEQ=%x SXFRCTL0=%x SXFRCTL1=%x SCSISIG=%x\n",
inb(SCSISEQ), inb(SXFRCTL0), inb(SXFRCTL1), inb(SCSISIG));
inb(iobase + SCSISEQ), inb(iobase + SXFRCTL0),
inb(iobase + SXFRCTL1), inb(iobase + SCSISIG));
printf(" SSTAT0=%x SSTAT1=%x SSTAT2=%x SSTAT3=%x SSTAT4=%x\n",
inb(SSTAT0), inb(SSTAT1), inb(SSTAT2), inb(SSTAT3), inb(SSTAT4));
inb(iobase + SSTAT0), inb(iobase + SSTAT1), inb(iobase + SSTAT2),
inb(iobase + SSTAT3), inb(iobase + SSTAT4));
printf(" SIMODE0=%x SIMODE1=%x DMACNTRL0=%x DMACNTRL1=%x DMASTAT=%x\n",
inb(SIMODE0), inb(SIMODE1), inb(DMACNTRL0), inb(DMACNTRL1),
inb(DMASTAT));
inb(iobase + SIMODE0), inb(iobase + SIMODE1),
inb(iobase + DMACNTRL0), inb(iobase + DMACNTRL1),
inb(iobase + DMASTAT));
printf(" FIFOSTAT=%d SCSIBUS=0x%x\n",
inb(FIFOSTAT), inb(SCSIBUS));
inb(iobase + FIFOSTAT), inb(iobase + SCSIBUS));
}
void