Updates to aic7xxx driver ; from pr port-i386/2600

This commit is contained in:
explorer 1996-07-10 22:50:44 +00:00
parent 9c8111508d
commit c62a6661a1
8 changed files with 429 additions and 309 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ahc_eisa.c,v 1.4 1996/05/20 00:55:44 thorpej Exp $ */
/* $NetBSD: ahc_eisa.c,v 1.5 1996/07/10 22:52:36 explorer Exp $ */
/*
* Product specific probe and attach routines for:
@ -30,6 +30,8 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from Id: aic7770.c,v 1.29 1996/05/30 07:18:52 gibbs Exp
*/
#if defined(__FreeBSD__)
@ -189,6 +191,7 @@ aic7770probe(void)
#define bootverbose 1
int ahc_eisa_irq __P((bus_chipset_tag_t, bus_io_handle_t));
int ahc_eisa_match __P((struct device *, void *, void *));
void ahc_eisa_attach __P((struct device *, struct device *, void *));
@ -371,8 +374,7 @@ ahc_eisa_attach(parent, self, aux)
* usefull for debugging irq problems
*/
if(bootverbose) {
printf(
"%s: Using %s Interrupts\n",
printf("%s: Using %s Interrupts\n",
ahc_name(ahc),
ahc->pause & IRQMS ?
"Level Sensitive" : "Edge Triggered");

View File

@ -1,10 +1,10 @@
/* $NetBSD: aic7xxx.c,v 1.8 1996/05/20 00:58:07 thorpej Exp $ */
/* $NetBSD: aic7xxx.c,v 1.9 1996/07/10 22:50:44 explorer Exp $ */
/*
* Generic driver for the aic7xxx based adaptec SCSI controllers
* Product specific probe and attach routines can be found in:
* i386/eisa/aic7770.c 27/284X and aic7770 motherboard controllers
* pci/aic7870.c 3940, 2940, aic7870 and aic7850 controllers
* pci/aic7870.c 3940, 2940, aic7880, aic7870 and aic7850 controllers
*
* Copyright (c) 1994, 1995, 1996 Justin T. Gibbs.
* All rights reserved.
@ -32,6 +32,8 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from Id: aic7xxx.c,v 1.75 1996/06/23 20:02:37 gibbs Exp
*/
/*
* TODO:
@ -158,8 +160,6 @@
#endif
#endif /* defined(__NetBSD__) */
#define PAGESIZ NBPG
#include <sys/kernel.h>
#define KVTOPHYS(x) vtophys(x)
@ -171,7 +171,7 @@ u_long ahc_unit = 0;
#endif
#ifdef AHC_DEBUG
static int ahc_debug = AHC_SHOWSENSE;
static int ahc_debug = AHC_DEBUG;
#endif
#ifdef AHC_BROKEN_CACHE
@ -239,8 +239,8 @@ static struct scsi_device ahc_dev =
#define RESTART_SEQUENCER(ahc) \
do { \
AHC_OUTB(ahc, SEQCTL, SEQRESET|FASTMODE); \
} while (AHC_INB(ahc, SEQADDR0) != 0 && \
AHC_INB(ahc, SEQADDR1) != 0); \
} while((AHC_INB(ahc, SEQADDR0) != 0) \
|| (AHC_INB(ahc, SEQADDR1) != 0)); \
\
UNPAUSE_SEQUENCER(ahc);
@ -288,7 +288,8 @@ static int ahc_reset_device __P((struct ahc_data *ahc, int target,
static void ahc_reset_current_bus __P((struct ahc_data *ahc));
static void ahc_run_done_queue __P((struct ahc_data *ahc));
static void ahc_scsirate __P((struct ahc_data* ahc, u_char *scsirate,
int period, int offset, int target));
int period, int offset, char channel,
int target));
#if defined(__FreeBSD__)
static timeout_t
ahc_timeout;
@ -366,11 +367,6 @@ static struct {
{ 0x100, 50, "20.0" },
{ 0x110, 62, "16.0" },
{ 0x120, 75, "13.4" },
{ 0x130, 175, "5.7" },
{ 0x140, 200, "5.0" },
{ 0x150, 225, "4.4" },
{ 0x160, 250, "4.0" },
{ 0x170, 275, "3.6" },
{ 0x000, 100, "10.0" },
{ 0x010, 125, "8.0" },
{ 0x020, 150, "6.67" },
@ -424,12 +420,14 @@ ahc_construct(ahc, bc, ioh, type, flags)
}
bzero(ahc, sizeof(struct ahc_data));
#endif
SIMPLEQ_INIT(&ahc->free_scbs);
SIMPLEQ_INIT(&ahc->page_scbs);
SIMPLEQ_INIT(&ahc->waiting_scbs);
SIMPLEQ_INIT(&ahc->assigned_scbs);
STAILQ_INIT(&ahc->free_scbs);
STAILQ_INIT(&ahc->page_scbs);
STAILQ_INIT(&ahc->waiting_scbs);
STAILQ_INIT(&ahc->assigned_scbs);
#if defined(__FreeBSD__)
ahc->unit = unit;
#endif
#if defined(__FreeBSD__)
ahc->baseport = iobase;
#elif defined(__NetBSD__)
ahc->sc_bc = bc;
@ -509,39 +507,59 @@ ahc_reset(devname, bc, ioh)
* Look up the valid period to SCSIRATE conversion in our table.
*/
static void
ahc_scsirate(ahc, scsirate, period, offset, target )
ahc_scsirate(ahc, scsirate, period, offset, channel, target )
struct ahc_data *ahc;
u_char *scsirate;
short period;
u_char offset;
char channel;
int target;
{
int i;
for (i = 0; i < ahc_num_syncrates; i++) {
u_char ultra_enb;
u_char sxfrctl0;
u_long ultra_enb_addr;
if ((ahc_syncrates[i].period - period) >= 0) {
/*
* Watch out for Ultra speeds when ultra is not
* enabled and vice-versa.
*/
if (ahc->type & AHC_ULTRA) {
if (!(ahc_syncrates[i].sxfr & ULTRA_SXFR))
break; /* Use Async */
}
else {
if (ahc_syncrates[i].sxfr & ULTRA_SXFR) {
/*
* This should only happen if the
* drive is the first to negotiate
* and chooses a high rate. We'll
* just move down the table util
* we hit a non ultra speed.
*/
continue;
}
if(!(ahc->type & AHC_ULTRA)
&& (ahc_syncrates[i].sxfr & ULTRA_SXFR)) {
/*
* This should only happen if the
* drive is the first to negotiate
* and chooses a high rate. We'll
* just move down the table util
* we hit a non ultra speed.
*/
continue;
}
*scsirate = (ahc_syncrates[i].sxfr) | (offset & 0x0f);
/*
* Ensure Ultra mode is set properly for
* this target.
*/
ultra_enb_addr = ULTRA_ENB;
if(channel == 'B' || target > 7)
ultra_enb_addr++;
ultra_enb = AHC_INB(ahc, ultra_enb_addr);
sxfrctl0 = AHC_INB(ahc, SXFRCTL0);
if (ahc_syncrates[i].sxfr & ULTRA_SXFR) {
ultra_enb |= 0x01 << (target & 0x07);
sxfrctl0 |= ULTRAEN;
}
else {
ultra_enb &= ~(0x01 << (target & 0x07));
sxfrctl0 &= ~ULTRAEN;
}
AHC_OUTB(ahc, ultra_enb_addr, ultra_enb);
AHC_OUTB(ahc, SXFRCTL0, sxfrctl0);
if(bootverbose) {
printf("%s: target %d synchronous at %sMHz,"
" offset = 0x%x\n",
@ -760,7 +778,7 @@ ahc_run_waiting_queues(ahc)
struct scb* scb;
u_char cur_scb;
if(!(ahc->assigned_scbs.sqh_first || ahc->waiting_scbs.sqh_first))
if(!(ahc->assigned_scbs.stqh_first || ahc->waiting_scbs.stqh_first))
return;
PAUSE_SEQUENCER(ahc);
@ -770,13 +788,13 @@ ahc_run_waiting_queues(ahc)
* First handle SCBs that are waiting but have been
* assigned a slot.
*/
while((scb = ahc->assigned_scbs.sqh_first) != NULL) {
SIMPLEQ_REMOVE_HEAD(&ahc->assigned_scbs, scb, links);
while((scb = ahc->assigned_scbs.stqh_first) != NULL) {
STAILQ_REMOVE_HEAD(&ahc->assigned_scbs, links);
AHC_OUTB(ahc, SCBPTR, scb->position);
ahc_send_scb(ahc, scb);
/* Mark this as an active command */
scb->flags = SCB_ACTIVE;
scb->flags ^= SCB_ASSIGNEDQ|SCB_ACTIVE;
AHC_OUTB(ahc, QINFIFO, scb->position);
if (!(scb->xs->flags & SCSI_NOMASK)) {
@ -786,7 +804,7 @@ ahc_run_waiting_queues(ahc)
SC_DEBUG(scb->xs->sc_link, SDEV_DB3, ("cmd_sent\n"));
}
/* Now deal with SCBs that require paging */
if((scb = ahc->waiting_scbs.sqh_first) != NULL) {
if((scb = ahc->waiting_scbs.stqh_first) != NULL) {
u_char disc_scb = AHC_INB(ahc, DISCONNECTED_SCBH);
u_char active = AHC_INB(ahc, FLAGS) & (SELECTED|IDENTIFY_SEEN);
int count = 0;
@ -799,8 +817,7 @@ ahc_run_waiting_queues(ahc)
break;
/*
* Advance disc_scb to the next on in the
* list.
* Check the next SCB on in the list.
*/
AHC_OUTB(ahc, SCBPTR, disc_scb);
next_scb = AHC_INB(ahc, SCB_NEXT);
@ -823,8 +840,7 @@ ahc_run_waiting_queues(ahc)
u_char out_scbi;
struct scb* out_scbp;
SIMPLEQ_REMOVE_HEAD(&ahc->waiting_scbs, scb,
links);
STAILQ_REMOVE_HEAD(&ahc->waiting_scbs, links);
/*
* Find the in-core SCB for the one
@ -837,7 +853,7 @@ ahc_run_waiting_queues(ahc)
ahc_page_scb(ahc, out_scbp, scb);
/* Mark this as an active command */
scb->flags = SCB_ACTIVE;
scb->flags ^= SCB_WAITINGQ|SCB_ACTIVE;
/* Queue the command */
AHC_OUTB(ahc, QINFIFO, scb->position);
@ -854,7 +870,7 @@ ahc_run_waiting_queues(ahc)
}
else
break;
} while((scb = ahc->waiting_scbs.sqh_first) != NULL);
} while((scb = ahc->waiting_scbs.stqh_first) != NULL);
if(count) {
/*
@ -906,11 +922,11 @@ ahc_intr(arg)
{
int intstat;
u_char status;
struct scb *scb = NULL;
struct scsi_xfer *xs = NULL;
struct ahc_data *ahc = (struct ahc_data *)arg;
struct scb *scb;
struct scsi_xfer *xs;
struct ahc_data *ahc = (struct ahc_data *)arg;
intstat = AHC_INB(ahc, INTSTAT);
intstat = AHC_INB(ahc, INTSTAT);
/*
* Is this interrupt for me? or for
* someone who is sharing my interrupt
@ -936,11 +952,6 @@ ahc_intr(arg)
AHC_INB(ahc, SEQADDR0));
}
if (intstat & SEQINT) {
/*
* This code isn't used by the SCB page-in code. It
* should probably be moved to cut out the extra
* inb.
*/
u_short targ_mask;
u_char target = (AHC_INB(ahc, SCSIID) >> 4) & 0x0f;
u_char scratch_offset = target;
@ -952,39 +963,6 @@ ahc_intr(arg)
targ_mask = (0x01 << scratch_offset);
switch (intstat & SEQINT_MASK) {
case BAD_PHASE:
panic("%s:%c:%d: unknown scsi bus phase. "
"Attempting to continue\n",
ahc_name(ahc), channel, target);
break;
case SEND_REJECT:
{
u_char rejbyte = AHC_INB(ahc, REJBYTE);
if(( rejbyte & 0xf0) == 0x20) {
/* Tagged Message */
printf("\n%s:%c:%d: Tagged message "
"received without identify. "
"Disabling tagged commands "
"for this target.\n",
ahc_name(ahc),
channel, target);
ahc->tagenable &= ~targ_mask;
}
else
printf("%s:%c:%d: Warning - "
"unknown message recieved from "
"target (0x%x - 0x%x). Rejecting\n",
ahc_name(ahc), channel, target,
rejbyte,
AHC_INB(ahc, REJBYTE_EXT));
break;
}
case NO_IDENT:
panic("%s:%c:%d: Target did not send an IDENTIFY "
"message. SAVED_TCL == 0x%x\n",
ahc_name(ahc), channel, target,
AHC_INB(ahc, SAVED_TCL));
break;
case NO_MATCH:
if(ahc->flags & AHC_PAGESCBS) {
/* SCB Page-in request */
@ -993,6 +971,18 @@ ahc_intr(arg)
u_char disc_scb;
struct scb *outscb;
u_char arg_1 = AHC_INB(ahc, ARG_1);
/*
* We should succeed, so set this now.
* If we don't, and one of the methods
* we use to aquire an SCB calls ahc_done,
* we may wind up in our start routine
* and unpause the adapter without giving
* it the correct return value, which will
* cause a hang.
*/
AHC_OUTB(ahc, RETURN_1, SCB_PAGEDIN);
if(arg_1 == SCB_LIST_NULL) {
/* Non-tagged command */
int index = target |
@ -1002,6 +992,10 @@ ahc_intr(arg)
else
scb = ahc->scbarray[arg_1];
if(!(scb->flags & SCB_PAGED_OUT))
panic("%s: Request to page in a"
"non paged out SCB.",
ahc_name(ahc));
/*
* Now to pick the SCB to page out.
* Either take a free SCB, an assigned SCB,
@ -1009,26 +1003,29 @@ ahc_intr(arg)
* one on the disconnected SCB list, or
* as a last resort a queued SCB.
*/
if((outscb = ahc->free_scbs.sqh_first) != NULL) {
SIMPLEQ_REMOVE_HEAD(&ahc->free_scbs,
outscb, links);
if(ahc->free_scbs.stqh_first) {
outscb = ahc->free_scbs.stqh_first;
STAILQ_REMOVE_HEAD(&ahc->free_scbs,
links);
scb->position = outscb->position;
outscb->position = SCB_LIST_NULL;
SIMPLEQ_INSERT_HEAD(&ahc->page_scbs,
outscb, links);
STAILQ_INSERT_HEAD(&ahc->page_scbs,
outscb, links);
AHC_OUTB(ahc, SCBPTR, scb->position);
ahc_send_scb(ahc, scb);
scb->flags &= ~SCB_PAGED_OUT;
goto pagein_done;
}
if((outscb = ahc->assigned_scbs.sqh_first) != NULL) {
SIMPLEQ_REMOVE_HEAD(&ahc->assigned_scbs,
outscb, links);
if(ahc->assigned_scbs.stqh_first) {
outscb = ahc->assigned_scbs.stqh_first;
STAILQ_REMOVE_HEAD(&ahc->assigned_scbs,
links);
outscb->flags ^= SCB_ASSIGNEDQ
|SCB_WAITINGQ;
scb->position = outscb->position;
outscb->position = SCB_LIST_NULL;
SIMPLEQ_INSERT_HEAD(&ahc->waiting_scbs,
outscb, links);
outscb->flags = SCB_WAITINGQ;
STAILQ_INSERT_HEAD(&ahc->waiting_scbs,
outscb, links);
AHC_OUTB(ahc, SCBPTR, scb->position);
ahc_send_scb(ahc, scb);
scb->flags &= ~SCB_PAGED_OUT;
@ -1037,7 +1034,6 @@ ahc_intr(arg)
if(intstat & CMDCMPLT) {
int scb_index;
printf("PIC\n");
AHC_OUTB(ahc, CLRINT, CLRCMDINT);
scb_index = AHC_INB(ahc, QOUTFIFO);
if(!(AHC_INB(ahc, QOUTCNT) & ahc->qcntmask))
@ -1091,8 +1087,8 @@ ahc_intr(arg)
* end of the queue instead.
*/
int i;
int saved_queue[AHC_SCB_MAX];
int queued = AHC_INB(ahc, QINCNT) & ahc->qcntmask;
u_char saved_queue[AHC_SCB_MAX];
u_char queued = AHC_INB(ahc, QINCNT) & ahc->qcntmask;
/* Count the command we removed already */
saved_queue[0] = disc_scb;
@ -1114,16 +1110,17 @@ ahc_intr(arg)
untimeout(ahc_timeout, (caddr_t)outscb);
scb->position = outscb->position;
outscb->position = SCB_LIST_NULL;
SIMPLEQ_INSERT_HEAD(&ahc->waiting_scbs,
STAILQ_INSERT_HEAD(&ahc->waiting_scbs,
outscb, links);
outscb->flags = SCB_WAITINGQ;
outscb->flags |= SCB_WAITINGQ;
ahc_send_scb(ahc, scb);
scb->flags &= ~SCB_PAGED_OUT;
}
else
else {
panic("Page-in request with no candidates");
AHC_OUTB(ahc, RETURN_1, 0);
}
pagein_done:
AHC_OUTB(ahc, RETURN_1, SCB_PAGEDIN);
}
else {
printf("%s:%c:%d: no active SCB for "
@ -1138,6 +1135,39 @@ pagein_done:
AHC_OUTB(ahc, RETURN_1, 0);
}
break;
case SEND_REJECT:
{
u_char rejbyte = AHC_INB(ahc, REJBYTE);
if(( rejbyte & 0xf0) == 0x20) {
/* Tagged Message */
printf("\n%s:%c:%d: Tagged message "
"received without identify. "
"Disabling tagged commands "
"for this target.\n",
ahc_name(ahc),
channel, target);
ahc->tagenable &= ~targ_mask;
}
else
printf("%s:%c:%d: Warning - "
"unknown message recieved from "
"target (0x%x - 0x%x). Rejecting\n",
ahc_name(ahc), channel, target,
rejbyte,
AHC_INB(ahc, REJBYTE_EXT));
break;
}
case NO_IDENT:
panic("%s:%c:%d: Target did not send an IDENTIFY "
"message. SAVED_TCL == 0x%x\n",
ahc_name(ahc), channel, target,
AHC_INB(ahc, SAVED_TCL));
break;
case BAD_PHASE:
printf("%s:%c:%d: unknown scsi bus phase. "
"Attempting to continue\n",
ahc_name(ahc), channel, target);
break;
case SDTR_MSG:
{
short period;
@ -1159,9 +1189,9 @@ pagein_done:
maxoffset = 0x08;
else
maxoffset = 0x0f;
ahc_scsirate(ahc, &rate, period,
MIN(offset,maxoffset),
target);
ahc_scsirate(ahc, &rate, period,
MIN(offset, maxoffset),
channel, target);
/* Preserve the WideXfer flag */
targ_scratch = rate | (targ_scratch & WIDEXFER);
AHC_OUTB(ahc, TARG_SCRATCH + scratch_offset,
@ -1471,26 +1501,17 @@ pagein_done:
sc_print_addr(xs->sc_link);
printf("Target Busy\n");
break;
#if defined(__FreeBSD__)
case SCSI_QUEUE_FULL:
/*
* The upper level SCSI code will eventually
* The upper level SCSI code will someday
* handle this properly.
*/
sc_print_addr(xs->sc_link);
printf("Queue Full\n");
scb->flags = SCB_ASSIGNEDQ;
SIMPLEQ_INSERT_TAIL(&ahc->assigned_scbs,
scb->flags |= SCB_ASSIGNEDQ;
STAILQ_INSERT_TAIL(&ahc->assigned_scbs,
scb, links);
break;
#elif defined(__NetBSD__)
/*
* XXX -
* Do we need to handle this ?
* But FreeBSD MI SCSI code seems to
* do nothing about this.
*/
#endif
default:
sc_print_addr(xs->sc_link);
printf("unexpected targ_status: %x\n",
@ -1630,6 +1651,31 @@ pagein_done:
"unknown operation.");
break;
}
case DATA_OVERRUN:
{
/*
* When the sequencer detects an overrun, it
* sets STCNT to 0x00ffffff and allows the
* target to complete its transfer in
* BITBUCKET mode.
*/
u_char scbindex = AHC_INB(ahc, SCB_TAG);
u_int32_t overrun;
scb = ahc->scbarray[scbindex];
overrun = AHC_INB(ahc, STCNT0)
| (AHC_INB(ahc, STCNT1) << 8)
| (AHC_INB(ahc, STCNT2) << 16);
overrun = 0x00ffffff - overrun;
sc_print_addr(scb->xs->sc_link);
printf("data overrun of %d bytes detected."
" Forcing a retry.\n", overrun);
/*
* Set this and it will take affect when the
* target does a command complete.
*/
scb->xs->error = XS_DRIVER_STUFFUP;
break;
}
#if NOT_YET
/* XXX Fill these in later */
case MESG_BUFFER_BUSY:
@ -1663,10 +1709,7 @@ clear:
int scb_index = AHC_INB(ahc, SCB_TAG);
status = AHC_INB(ahc, SSTAT1);
scb = ahc->scbarray[scb_index];
if (scb != NULL) /* XXX - is this case exist ? */
xs = scb->xs;
if (status & SCSIRSTI) {
char channel;
@ -1699,6 +1742,7 @@ clear:
u_char mesg_out = MSG_NOP;
u_char lastphase = AHC_INB(ahc, LASTPHASE);
xs = scb->xs;
sc_print_addr(xs->sc_link);
switch(lastphase) {
@ -1730,10 +1774,10 @@ clear:
printf("parity error during %s phase.\n", phase);
/*
* We've set the hardware to assert ATN if we
* get a parity error on "in" phases, so all we
* We've set the hardware to assert ATN if we
* get a parity error on "in" phases, so all we
* need to do is stuff the message buffer with
* the appropriate message. In phases have set
* the appropriate message. "In" phases have set
* mesg_out to something other than MSG_NOP.
*/
if(mesg_out != MSG_NOP) {
@ -1750,7 +1794,9 @@ clear:
else if (status & SELTO) {
u_char waiting;
u_char flags;
xs->error = XS_SELTIMEOUT;
xs = scb->xs;
xs->error = XS_SELTIMEOUT;
/*
* Clear any pending messages for the timed out
* target, and mark the target as free
@ -1764,6 +1810,8 @@ clear:
IS_SCSIBUS_B(ahc, xs->sc_link)
#endif
? 'B' : 'A');
/* Stop the selection */
AHC_OUTB(ahc, SCSISEQ, 0);
AHC_OUTB(ahc, SCB_CONTROL, 0);
@ -1780,7 +1828,7 @@ clear:
RESTART_SEQUENCER(ahc);
}
else if (!(status & BUSFREE)) {
sc_print_addr(xs->sc_link);
sc_print_addr(scb->xs->sc_link);
printf("Unknown SCSIINT. Status = 0x%x\n", status);
AHC_OUTB(ahc, CLRSINT1, status);
UNPAUSE_SEQUENCER(ahc);
@ -1909,6 +1957,7 @@ ahc_init(ahc)
struct ahc_data *ahc;
{
u_char scsi_conf, sblkctl, i;
u_short ultraenable = 0;
int max_targ = 15;
/*
* Assume we have a board at this stage and it has been reset.
@ -2115,6 +2164,22 @@ ahc_init(ahc)
*/
target_settings &= 0x7f;
}
if(ahc->type & AHC_ULTRA) {
/*
* Enable Ultra for any target that
* has a valid ultra syncrate setting.
*/
u_char rate = target_settings & 0x70;
if(rate == 0x00 || rate == 0x10 ||
rate == 0x20 || rate == 0x40) {
if(rate == 0x40) {
/* Treat 10MHz specially */
target_settings &= ~0x70;
}
else
ultraenable |= (0x01 << i);
}
}
}
AHC_OUTB(ahc, TARG_SCRATCH+i,target_settings);
}
@ -2133,6 +2198,9 @@ ahc_init(ahc)
ahc->tagenable = 0;
ahc->orderedtag = 0;
AHC_OUTB(ahc, ULTRA_ENB, ultraenable & 0xff);
AHC_OUTB(ahc, ULTRA_ENB + 1, (ultraenable >> 8) & 0xff);
#ifdef AHC_DEBUG
/* How did we do? */
if(ahc_debug & AHC_SHOWMISC)
@ -2206,8 +2274,8 @@ ahcminphys(bp)
* discontinuous physically, hense the "page per segment" limit
* enforced here.
*/
if (bp->b_bcount > ((AHC_NSEG - 1) * PAGESIZ)) {
bp->b_bcount = ((AHC_NSEG - 1) * PAGESIZ);
if (bp->b_bcount > ((AHC_NSEG - 1) * PAGE_SIZE)) {
bp->b_bcount = ((AHC_NSEG - 1) * PAGE_SIZE);
}
#if defined(__NetBSD__)
minphys(bp);
@ -2223,49 +2291,49 @@ static int32_t
ahc_scsi_cmd(xs)
struct scsi_xfer *xs;
{
struct scb *scb;
struct ahc_dma_seg *sg;
int seg; /* scatter gather seg being worked on */
int thiskv;
physaddr thisphys, nextphys;
int bytes_this_seg, bytes_this_page, datalen, flags;
struct ahc_data *ahc;
struct scb *scb;
struct ahc_dma_seg *sg;
int seg; /* scatter gather seg being worked on */
int thiskv;
physaddr thisphys, nextphys;
int bytes_this_seg, bytes_this_page, datalen, flags;
struct ahc_data *ahc;
u_short mask;
int s;
int s;
ahc = (struct ahc_data *)xs->sc_link->adapter_softc;
mask = (0x01 << (xs->sc_link->target
mask = (0x01 << (xs->sc_link->target
#if defined(__FreeBSD__)
| ((u_long)xs->sc_link->fordriver & 0x08)));
#elif defined(__NetBSD__)
| (IS_SCSIBUS_B(ahc, xs->sc_link) ? SELBUSB : 0) ));
#endif
SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahc_scsi_cmd\n"));
/*
* get an scb to use. If the transfer
* is from a buf (possibly from interrupt time)
* then we can't allow it to sleep
*/
flags = xs->flags;
if (flags & ITSDONE) {
printf("%s: Already done?", ahc_name(ahc));
xs->flags &= ~ITSDONE;
}
if (!(flags & INUSE)) {
printf("%s: Not in use?", ahc_name(ahc));
xs->flags |= INUSE;
}
if (!(scb = ahc_get_scb(ahc, flags))) {
xs->error = XS_DRIVER_STUFFUP;
return (TRY_AGAIN_LATER);
}
SC_DEBUG(xs->sc_link, SDEV_DB3, ("start scb(%p)\n", scb));
scb->xs = xs;
if (flags & SCSI_RESET)
SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahc_scsi_cmd\n"));
/*
* get an scb to use. If the transfer
* is from a buf (possibly from interrupt time)
* then we can't allow it to sleep
*/
flags = xs->flags;
if (flags & ITSDONE) {
printf("%s: Already done?", ahc_name(ahc));
xs->flags &= ~ITSDONE;
}
if (!(flags & INUSE)) {
printf("%s: Not in use?", ahc_name(ahc));
xs->flags |= INUSE;
}
if (!(scb = ahc_get_scb(ahc, flags))) {
xs->error = XS_DRIVER_STUFFUP;
return (TRY_AGAIN_LATER);
}
SC_DEBUG(xs->sc_link, SDEV_DB3, ("start scb(%p)\n", scb));
scb->xs = xs;
if (flags & SCSI_RESET)
scb->flags |= SCB_DEVICE_RESET|SCB_IMMED;
/*
* Put all the arguments for the xfer in the scb
*/
/*
* Put all the arguments for the xfer in the scb
*/
if(ahc->tagenable & mask) {
scb->control |= TAG_ENB;
@ -2328,8 +2396,8 @@ ahc_scsi_cmd(xs)
* length
*/
/* how far to the end of the page */
nextphys = (thisphys & (~(PAGESIZ - 1)))
+ PAGESIZ;
nextphys = (thisphys & (~(PAGE_SIZE- 1)))
+ PAGE_SIZE;
bytes_this_page = nextphys - thisphys;
/**** or the data ****/
bytes_this_page = min(bytes_this_page ,datalen);
@ -2337,8 +2405,8 @@ ahc_scsi_cmd(xs)
datalen -= bytes_this_page;
/* get more ready for the next page */
thiskv = (thiskv & (~(PAGESIZ - 1)))
+ PAGESIZ;
thiskv = (thiskv & (~(PAGE_SIZE - 1)))
+ PAGE_SIZE;
if (datalen)
thisphys = KVTOPHYS(thiskv);
}
@ -2398,7 +2466,7 @@ ahc_scsi_cmd(xs)
AHC_OUTB(ahc, SCBPTR, curscb);
AHC_OUTB(ahc, QINFIFO, scb->position);
UNPAUSE_SEQUENCER(ahc);
scb->flags = SCB_ACTIVE;
scb->flags |= SCB_ACTIVE;
if (!(flags & SCSI_NOMASK)) {
timeout(ahc_timeout, (caddr_t)scb,
(xs->timeout * hz) / 1000);
@ -2406,8 +2474,8 @@ ahc_scsi_cmd(xs)
SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_sent\n"));
}
else {
scb->flags = SCB_WAITINGQ;
SIMPLEQ_INSERT_TAIL(&ahc->waiting_scbs, scb, links);
scb->flags |= SCB_WAITINGQ;
STAILQ_INSERT_TAIL(&ahc->waiting_scbs, scb, links);
ahc_run_waiting_queues(ahc);
}
if (!(flags & SCSI_NOMASK)) {
@ -2446,10 +2514,14 @@ ahc_free_scb(ahc, scb, flags)
opri = splbio();
/* Clean up for the next user */
scb->flags = SCB_FREE;
scb->control = 0;
scb->status = 0;
if(scb->position == SCB_LIST_NULL) {
SIMPLEQ_INSERT_HEAD(&ahc->page_scbs, scb, links);
if(!scb->links.sqe_next && !ahc->free_scbs.sqh_first)
STAILQ_INSERT_HEAD(&ahc->page_scbs, scb, links);
if(!scb->links.stqe_next && !ahc->free_scbs.stqh_first)
/*
* If there were no SCBs availible, wake anybody waiting
* for one to come free.
@ -2463,11 +2535,11 @@ ahc_free_scb(ahc, scb, flags)
* completes for a particular interrupt are completed
* or when we start another command.
*/
else if((wscb = ahc->waiting_scbs.sqh_first) != NULL) {
SIMPLEQ_REMOVE_HEAD(&ahc->waiting_scbs, wscb, links);
else if((wscb = ahc->waiting_scbs.stqh_first) != NULL) {
STAILQ_REMOVE_HEAD(&ahc->waiting_scbs, links);
wscb->position = scb->position;
SIMPLEQ_INSERT_HEAD(&ahc->assigned_scbs, wscb, links);
wscb->flags = SCB_ASSIGNEDQ;
STAILQ_INSERT_HEAD(&ahc->assigned_scbs, wscb, links);
wscb->flags ^= SCB_WAITINGQ|SCB_ASSIGNEDQ;
/*
* The "freed" SCB will need to be assigned a slot
@ -2475,8 +2547,8 @@ ahc_free_scb(ahc, scb, flags)
* queue.
*/
scb->position = SCB_LIST_NULL;
SIMPLEQ_INSERT_HEAD(&ahc->page_scbs, scb, links);
if(!scb->links.sqe_next && !ahc->free_scbs.sqh_first)
STAILQ_INSERT_HEAD(&ahc->page_scbs, scb, links);
if(!scb->links.stqe_next && !ahc->free_scbs.stqh_first)
/*
* If there were no SCBs availible, wake anybody waiting
* for one to come free.
@ -2484,17 +2556,17 @@ ahc_free_scb(ahc, scb, flags)
wakeup((caddr_t)&ahc->free_scbs);
}
else {
SIMPLEQ_INSERT_HEAD(&ahc->free_scbs, scb, links);
#ifdef AHC_DEBUG
ahc->activescbs--;
#endif
if(!scb->links.sqe_next && !ahc->page_scbs.sqh_first)
STAILQ_INSERT_HEAD(&ahc->free_scbs, scb, links);
if(!scb->links.stqe_next && !ahc->page_scbs.stqh_first)
/*
* If there were no SCBs availible, wake anybody waiting
* for one to come free.
*/
wakeup((caddr_t)&ahc->free_scbs);
}
#ifdef AHC_DEBUG
ahc->activescbs--;
#endif
splx(opri);
}
@ -2518,13 +2590,13 @@ ahc_get_scb(ahc, flags)
* but only if we can't allocate a new one.
*/
while (1) {
if((scbp = ahc->free_scbs.sqh_first)) {
SIMPLEQ_REMOVE_HEAD(&ahc->free_scbs, scbp, links);
if((scbp = ahc->free_scbs.stqh_first)) {
STAILQ_REMOVE_HEAD(&ahc->free_scbs, links);
}
else if((scbp = ahc->page_scbs.sqh_first)) {
SIMPLEQ_REMOVE_HEAD(&ahc->page_scbs, scbp, links);
else if((scbp = ahc->page_scbs.stqh_first)) {
STAILQ_REMOVE_HEAD(&ahc->page_scbs, links);
}
else if (ahc->numscbs < ahc->maxscbs) {
else if(ahc->numscbs < ahc->maxscbs) {
scbp = (struct scb *) malloc(sizeof(struct scb),
M_TEMP, M_NOWAIT);
if (scbp) {
@ -2556,17 +2628,14 @@ ahc_get_scb(ahc, flags)
break;
}
if (scbp) {
scbp->control = 0;
scbp->status = 0;
scbp->flags = 0;
#ifdef AHC_DEBUG
if (scbp) {
ahc->activescbs++;
if((ahc_debug & AHC_SHOWSCBCNT)
&& (ahc->activescbs == ahc->maxhscbs))
printf("%s: Max SCBs active\n", ahc_name(ahc));
#endif
}
#endif
splx(opri);
@ -2576,7 +2645,7 @@ ahc_get_scb(ahc, flags)
static void ahc_loadseq(ahc)
struct ahc_data *ahc;
{
static unsigned char seqprog[] = {
static u_char seqprog[] = {
# include "aic7xxx_seq.h"
};
@ -2584,12 +2653,10 @@ static void ahc_loadseq(ahc)
AHC_OUTSB(ahc, SEQRAM, seqprog, sizeof(seqprog));
AHC_OUTB(ahc, SEQCTL, FASTMODE|SEQRESET);
do {
AHC_OUTB(ahc, SEQCTL, SEQRESET|FASTMODE);
} while (AHC_INB(ahc, SEQADDR0) != 0 &&
AHC_INB(ahc, SEQADDR1) != 0);
} while((AHC_INB(ahc, SEQADDR0) != 0)
|| (AHC_INB(ahc, SEQADDR1) != 0));
}
/*
@ -2606,7 +2673,7 @@ ahc_poll(ahc, wait)
if (AHC_INB(ahc, INTSTAT) & INT_PEND)
break;
} if (wait == 0) {
printf("%s: board not responding\n", ahc_name(ahc));
printf("%s: board is not responding\n", ahc_name(ahc));
return (EIO);
}
ahc_intr((void *)ahc);
@ -2619,17 +2686,14 @@ ahc_timeout(arg)
{
struct scb *scb = (struct scb *)arg;
struct ahc_data *ahc;
int s, h, found;
int s, found;
u_char bus_state;
char channel;
s = splbio();
h = splhigh();
if (!(scb->flags & SCB_ACTIVE)) {
/* Previous timeout took care of me already */
splx(h);
splx(s);
return;
}
@ -2661,13 +2725,11 @@ ahc_timeout(arg)
scb->flags |= SCB_TIMEDOUT;
timeout(ahc_timeout, (caddr_t)scb,
(scb->xs->timeout * hz) / 1000);
splx(h);
splx(s);
return;
}
}
ahc->in_timeout = TRUE;
splx(h);
/*
* Ensure that the card doesn't do anything
@ -2884,8 +2946,8 @@ ahc_reset_device(ahc, target, channel, timedout_scb, xs_error)
* Search the QINFIFO.
*/
{
int saved_queue[AHC_SCB_MAX];
int queued = AHC_INB(ahc, QINCNT) & ahc->qcntmask;
u_char saved_queue[AHC_SCB_MAX];
u_char queued = AHC_INB(ahc, QINCNT) & ahc->qcntmask;
for (i = 0; i < (queued - found); i++) {
saved_queue[i] = AHC_INB(ahc, QINFIFO);

View File

@ -1,4 +1,4 @@
/* $NetBSD: aic7xxxreg.h,v 1.2 1996/05/20 00:58:10 thorpej Exp $ */
/* $NetBSD: aic7xxxreg.h,v 1.3 1996/07/10 22:50:46 explorer Exp $ */
/*
* Aic7xxx register and scratch ram definitions.
@ -29,6 +29,8 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from Id: aic7xxx_reg.h,v 1.12 1996/06/09 17:29:12 gibbs Exp
*/
/*
@ -434,6 +436,11 @@
* when we were expecting
* another msgin byte.
*/
#define DATA_OVERRUN 0xe1 /*
* Target attempted to write
* beyond the bounds of its
* command.
*/
#define BRKADRINT 0x08
#define SCSIINT 0x04
#define CMDCMPLT 0x02
@ -739,6 +746,8 @@
#define SAVED_LINKPTR 0x050
#define SAVED_SCBPTR 0x051
#define ULTRA_ENB 0x052
#define ULTRA_ENB_B 0x053
#define SCSICONF 0x05a
#define RESET_SCSI 0x40

View File

@ -1,4 +1,4 @@
/* $NetBSD: aic7xxxvar.h,v 1.7 1996/05/20 00:58:11 thorpej Exp $ */
/* $NetBSD: aic7xxxvar.h,v 1.8 1996/07/10 22:50:48 explorer Exp $ */
/*
* Interface to the generic driver for the aic7xxx based adaptec
@ -31,6 +31,8 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from Id: aic7xxx.h,v 1.28 1996/05/30 07:19:59 gibbs Exp
*/
#ifndef _AIC7XXX_H_
@ -40,6 +42,21 @@
#include "ahc.h" /* for NAHC from config */
#endif
#if defined(__NetBSD__)
/*
* convert FreeBSD's <sys/queue.h> symbols to NetBSD's
*/
#define STAILQ_ENTRY SIMPLEQ_ENTRY
#define STAILQ_HEAD SIMPLEQ_HEAD
#define STAILQ_INIT SIMPLEQ_INIT
#define STAILQ_INSERT_HEAD SIMPLEQ_INSERT_HEAD
#define STAILQ_INSERT_TAIL SIMPLEQ_INSERT_TAIL
#define STAILQ_REMOVE_HEAD(head, field) \
SIMPLEQ_REMOVE_HEAD(head, (head)->sqh_first, field)
#define stqh_first sqh_first
#define stqe_next sqe_next
#endif
#if defined(__FreeBSD__)
#define AHC_INB(ahc, port) \
inb((ahc)->baseport+(port))
@ -177,7 +194,7 @@ struct scb {
*/
/*27*/ u_char prev;
/*-----------------end of hardware supported fields----------------*/
SIMPLEQ_ENTRY(scb) links; /* for chaining */
STAILQ_ENTRY(scb) links; /* for chaining */
struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
scb_flag flags;
u_char position; /* Position in card's scbarray */
@ -204,19 +221,19 @@ struct ahc_data {
* Paged out, non-tagged scbs
* indexed by target.
*/
SIMPLEQ_HEAD(, scb) free_scbs; /*
STAILQ_HEAD(, scb) free_scbs; /*
* SCBs assigned to free slots
* on the card. (no paging required)
*/
SIMPLEQ_HEAD(, scb) page_scbs; /*
STAILQ_HEAD(, scb) page_scbs; /*
* SCBs that will require paging
* before use (no assigned slot)
*/
SIMPLEQ_HEAD(, scb) waiting_scbs;/*
STAILQ_HEAD(, scb) waiting_scbs;/*
* SCBs waiting to be paged in
* and started.
*/
SIMPLEQ_HEAD(, scb)assigned_scbs;/*
STAILQ_HEAD(, scb)assigned_scbs;/*
* SCBs that were waiting but have
* now been assigned a slot by
* ahc_free_scb.

View File

@ -1,4 +1,4 @@
/* $NetBSD: smc93cx6.c,v 1.1 1996/05/16 03:59:10 mycroft Exp $ */
/* $NetBSD: smc93cx6.c,v 1.2 1996/07/10 22:50:49 explorer Exp $ */
/*
* Interface for the 93C46/26/06 serial eeprom parts.
@ -19,6 +19,8 @@
* Daniel M. Eischen.
* 4. Modifications may be freely made to this file if the above conditions
* are met.
*
* from Id: 93cx6.c,v 1.5 1996/05/30 07:19:54 gibbs Exp
*/
/*
@ -72,16 +74,6 @@ static struct seeprom_cmd {
unsigned char bits[3];
} seeprom_read = {3, {1, 1, 0}};
#if defined(__FreeBSD__)
#define SEEPROM_INB(sd) inb(sd->sd_iobase)
#define SEEPROM_OUTB(sd, value) outb(sd->sd_iobase, value)
#elif defined(__NetBSD__)
#define SEEPROM_INB(sd) \
bus_io_read_1(sd->sd_bc, sd->sd_ioh, sd->sd_offset)
#define SEEPROM_OUTB(sd, value) \
bus_io_write_1(sd->sd_bc, sd->sd_ioh, sd->sd_offset, value)
#endif
/*
* Wait for the SEERDY to go high; about 800 ns.
*/
@ -187,36 +179,3 @@ read_seeprom(sd, buf, start_addr, count)
#endif
return (1);
}
int
acquire_seeprom(sd)
struct seeprom_descriptor *sd;
{
int wait;
/*
* Request access of the memory port. When access is
* granted, SEERDY will go high. We use a 1 second
* timeout which should be near 1 second more than
* is needed. Reason: after the chip reset, there
* should be no contention.
*/
SEEPROM_OUTB(sd, sd->sd_MS);
wait = 1000; /* 1 second timeout in msec */
while (--wait && ((SEEPROM_INB(sd) & sd->sd_RDY) == 0)) {
DELAY (1000); /* delay 1 msec */
}
if ((SEEPROM_INB(sd) & sd->sd_RDY) == 0) {
SEEPROM_OUTB(sd, 0);
return (0);
}
return(1);
}
void
release_seeprom(sd)
struct seeprom_descriptor *sd;
{
/* Release access to the memory port and the serial EEPROM. */
SEEPROM_OUTB(sd, 0);
}

View File

@ -1,3 +1,5 @@
/* $NetBSD: smc93cx6var.h,v 1.2 1996/07/10 22:50:50 explorer Exp $ */
/*
* Interface to the 93C46 serial EEPROM that is used to store BIOS
* settings for the aic7xxx based adaptec SCSI controllers. It can
@ -20,7 +22,7 @@
* 4. Modifications may be freely made to this file if the above conditions
* are met.
*
* $Id: smc93cx6var.h,v 1.1 1996/05/16 03:59:11 mycroft Exp $
* from Id: 93cx6.h,v 1.3 1996/05/30 07:19:55 gibbs Exp
*/
#include <sys/param.h>
@ -59,6 +61,17 @@ struct seeprom_descriptor {
*
* A failed read attempt returns 0, and a successful read returns 1.
*/
#if defined(__FreeBSD__)
#define SEEPROM_INB(sd) inb(sd->sd_iobase)
#define SEEPROM_OUTB(sd, value) outb(sd->sd_iobase, value)
#elif defined(__NetBSD__)
#define SEEPROM_INB(sd) \
bus_io_read_1(sd->sd_bc, sd->sd_ioh, sd->sd_offset)
#define SEEPROM_OUTB(sd, value) \
bus_io_write_1(sd->sd_bc, sd->sd_ioh, sd->sd_offset, value)
#endif
#if defined(__FreeBSD__)
int read_seeprom __P((struct seeprom_descriptor *sd,
u_int16_t *buf, u_int start_addr, int count));
@ -66,5 +79,3 @@ int read_seeprom __P((struct seeprom_descriptor *sd,
int read_seeprom __P((struct seeprom_descriptor *sd,
u_int16_t *buf, bus_io_size_t start_addr, bus_io_size_t count));
#endif
int acquire_seeprom __P((struct seeprom_descriptor *sd));
void release_seeprom __P((struct seeprom_descriptor *sd));

View File

@ -1,4 +1,4 @@
/* $NetBSD: aic7xxx.seq,v 1.3 1996/05/20 00:48:45 thorpej Exp $ */
/* $NetBSD: aic7xxx.seq,v 1.4 1996/07/10 22:51:23 explorer Exp $ */
/*+M***********************************************************************
*Adaptec 274x/284x/294x device driver for Linux and FreeBSD.
@ -39,9 +39,11 @@
*OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
*SUCH DAMAGE.
*
* from Id: aic7xxx.seq,v 1.42 1996/06/09 17:29:11 gibbs Exp
*
*-M************************************************************************/
VERSION AIC7XXX_SEQ_VER "$NetBSD: aic7xxx.seq,v 1.3 1996/05/20 00:48:45 thorpej Exp $"
VERSION AIC7XXX_SEQ_VER "$NetBSD: aic7xxx.seq,v 1.4 1996/07/10 22:51:23 explorer Exp $"
#if defined(__NetBSD__)
#include "../../../../dev/ic/aic7xxxreg.h"
@ -85,6 +87,11 @@ reset:
start:
and FLAGS,0x0f /* clear target specific flags */
mvi SCSISEQ,ENRSELI /* Always allow reselection */
clr SCSIRATE /*
* We don't know the target we will
* connect to, so default to narrow
* transfers to avoid parity problems.
*/
poll_for_work:
/*
* Are we a twin channel device?
@ -259,13 +266,29 @@ select2:
call ndx_dtr
mov SCSIRATE,SINDIR
/*
* Initialize Ultra mode setting.
*/
mov FUNCTION1,SCSIID
mov A,FUNCTION1
and SINDEX,0xdf,SXFRCTL0 /* default to Ultra disabled */
test SCSIID, 0x80 jnz ultra_b /* Target ID > 7 */
test SBLKCTL, SELBUSB jnz ultra_b /* Second channel device */
test ULTRA_ENB,A jz set_sxfrctl0
or SINDEX, ULTRAEN jmp set_sxfrctl0
ultra_b:
test ULTRA_ENB_B,A jz set_sxfrctl0
or SINDEX, ULTRAEN
set_sxfrctl0:
mov SXFRCTL0,SINDEX
mvi SCSISEQ,ENAUTOATNP /*
* ATN on parity errors
* for "in" phases
*/
mvi CLRSINT1,CLRBUSFREE
mvi CLRSINT0,0x60 /* CLRSELDI|CLRSELDO */
/*
* Main loop for information transfer phases. If BSY is false, then
* we have a bus free condition, expected or not. Otherwise, wait
@ -289,6 +312,7 @@ ITloop:
cmp A,P_MESGIN je p_mesgin
mvi INTSTAT,BAD_PHASE /* unknown phase - signal driver */
jmp ITloop /* Try reading the bus again. */
p_dataout:
mvi DMAPARAMS,0x7d /*
@ -320,12 +344,29 @@ data_phase_init:
or FLAGS, DPHASE /* We have seen a data phase */
data_phase_loop:
/* Guard against overruns */
test SG_COUNT, 0xff jnz data_phase_inbounds
/*
* Turn on 'Bit Bucket' mode, set the transfer count to
* 16meg and let the target run until it changes phase.
* When the transfer completes, notify the host that we
* had an overrun.
*/
or SXFRCTL1,BITBUCKET
mvi STCNT0,0xff
mvi STCNT1,0xff
mvi STCNT2,0xff
data_phase_inbounds:
/* If we are the last SG block, don't set wideodd. */
cmp SG_COUNT,0x01 jne data_phase_wideodd
and DMAPARAMS, 0xbf /* Turn off WIDEODD */
data_phase_wideodd:
mov DMAPARAMS call dma
/* Go tell the host about any overruns */
test SXFRCTL1,BITBUCKET jnz data_phase_overrun
/* Exit if we had an underrun */
test SSTAT0,SDONE jz data_phase_finish /* underrun STCNT != 0 */
@ -427,6 +468,14 @@ data_phase_finish:
mov SCB_RESID_SGCNT, SG_COUNT
jmp ITloop
data_phase_overrun:
/*
* Turn off BITBUCKET mode and notify the host
*/
and SXFRCTL1,0x7f /* ~BITBUCKET */
mvi INTSTAT,DATA_OVERRUN
jmp ITloop
/*
* Command phase. Set up the DMA registers and let 'er rip.
*/
@ -486,6 +535,7 @@ p_mesgout_start:
p_mesgout_loop:
test SSTAT1,PHASEMIS jnz p_mesgout_phasemis
test SSTAT0,SPIORDY jz p_mesgout_loop
test SSTAT1,PHASEMIS jnz p_mesgout_phasemis
cmp DINDEX,1 jne p_mesgout_outb /* last byte? */
mvi CLRSINT1,CLRATNO /* drop ATN */
p_mesgout_outb:
@ -855,6 +905,7 @@ inb_next_wait:
test SSTAT0,SPIORDY jz inb_next_wait /* wait for next byte */
inb_first:
mov DINDEX,SINDEX
test SSTAT1,PHASEMIS jnz mesgin_phasemis
mov DINDIR,SCSIBUSL ret /*read byte directly from bus*/
inb_last:
mov NONE,SCSIDATL ret /*dummy read from latch to ACK*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: ahc_pci.c,v 1.2 1996/05/20 00:56:39 thorpej Exp $ */
/* $NetBSD: ahc_pci.c,v 1.3 1996/07/10 22:53:55 explorer Exp $ */
/*
* Product specific probe and attach routines for:
@ -30,6 +30,8 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from Id: aic7870.c,v 1.37 1996/06/08 06:55:55 gibbs Exp
*/
#if defined(__FreeBSD__)
@ -44,9 +46,7 @@
#if defined(__NetBSD__)
#include <sys/device.h>
#include <machine/bus.h>
#ifdef __alpha__
#include <machine/intr.h>
#endif
#endif /* defined(__NetBSD__) */
#include <scsi/scsi_all.h>
@ -176,6 +176,8 @@ struct seeprom_config {
};
static void load_seeprom __P((struct ahc_data *ahc));
static int acquire_seeprom __P((struct seeprom_descriptor *sd));
static void release_seeprom __P((struct seeprom_descriptor *sd));
static u_char aic3940_count;
@ -421,41 +423,6 @@ ahc_pci_attach(parent, self, aux)
}
}
/*
* Ensure that we are using good values for the PCI burst size
* and latency timer.
*/
{
#if defined(__FreeBSD__)
u_long csize_lattime = pci_conf_read(config_id, CSIZE_LATTIME);
#elif defined(__NetBSD__)
u_long csize_lattime =
pci_conf_read(pa->pa_pc, pa->pa_tag, CSIZE_LATTIME);
#endif
if((csize_lattime & CACHESIZE) == 0) {
/* default to 8DWDs. What's the PCI define for this? */
csize_lattime |= 8;
}
if((csize_lattime & LATTIME) == 0) {
/* Default to 64 PCLKS (is this a good value?) */
/* This may also be availble in the SEEPROM?? */
csize_lattime |= (64 << 8);
}
if(bootverbose)
printf("ahc%d: BurstLen = %ldDWDs, "
"Latency Timer = %ldPCLKS\n",
unit,
csize_lattime & CACHESIZE,
(csize_lattime >> 8) & 0xff);
#if defined(__FreeBSD__)
pci_conf_write(config_id, CSIZE_LATTIME, csize_lattime);
#elif defined(__NetBSD__)
pci_conf_write(pa->pa_pc, pa->pa_tag, CSIZE_LATTIME,
csize_lattime);
#endif
}
#if defined(__FreeBSD__)
if(!(ahc = ahc_alloc(unit, io_port, ahc_t, ahc_f)))
return; /* XXX PCI code should take return status */
@ -572,10 +539,20 @@ ahc_pci_attach(parent, self, aux)
/* See if someone else set us up already */
u_long i;
for(i = TARG_SCRATCH; i < 0x60; i++) {
if(AHC_INB(ahc, i) != 0xff)
if(AHC_INB(ahc, i) != 0x00)
break;
}
if(i != 0x60) {
if(i == TARG_SCRATCH) {
/*
* Try looking for all ones. You can get
* either.
*/
for (i = TARG_SCRATCH; i < 0x60; i++) {
if(AHC_INB(ahc, i) != 0xff)
break;
}
}
if((i != 0x60) && (our_id != 0)) {
printf("%s: Using left over BIOS settings\n",
ahc_name(ahc));
ahc->flags &= ~AHC_USEDEFAULTS;
@ -608,7 +585,6 @@ ahc_pci_attach(parent, self, aux)
splx(opri);
ahc_attach(ahc);
return;
}
/*
@ -677,7 +653,7 @@ load_seeprom(ahc)
int i;
int max_targ = sc.max_targets & CFMAXTARG;
for(i = 0; i <= max_targ; i++){
for(i = 0; i < max_targ; i++){
u_char target_settings;
target_settings = (sc.device_flags[i] & CFXFER) << 4;
if (sc.device_flags[i] & CFSYNCH)
@ -712,4 +688,37 @@ load_seeprom(ahc)
}
}
static int
acquire_seeprom(sd)
struct seeprom_descriptor *sd;
{
int wait;
/*
* Request access of the memory port. When access is
* granted, SEERDY will go high. We use a 1 second
* timeout which should be near 1 second more than
* is needed. Reason: after the chip reset, there
* should be no contention.
*/
SEEPROM_OUTB(sd, sd->sd_MS);
wait = 1000; /* 1 second timeout in msec */
while (--wait && ((SEEPROM_INB(sd) & sd->sd_RDY) == 0)) {
DELAY (1000); /* delay 1 msec */
}
if ((SEEPROM_INB(sd) & sd->sd_RDY) == 0) {
SEEPROM_OUTB(sd, 0);
return (0);
}
return(1);
}
static void
release_seeprom(sd)
struct seeprom_descriptor *sd;
{
/* Release access to the memory port and the serial EEPROM. */
SEEPROM_OUTB(sd, 0);
}
#endif /* NPCI > 0 */