Use `{in.out}b(iobase + ...' rather than including the base address in
the register definitions.
This commit is contained in:
parent
bd6e60f0d5
commit
778f21db6a
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue