Adapt to some changes in the register definitions. Clear the selection

enable in SCSISEQ during error recovery to deal with the way the
sequencer leaves selections enabled now.  Add code to perform "patching"
during sequencer program download.

Spelling fixes obtained from NetBSD.
This commit is contained in:
Justin T. Gibbs 1997-03-16 07:12:07 +00:00
parent 25f864c494
commit f9380a619e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=23928

View File

@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: aic7xxx.c,v 1.104 1997/02/28 03:58:21 gibbs Exp $
* $Id: aic7xxx.c,v 1.105 1997/03/01 06:50:41 gibbs Exp $
*/
/*
* TODO:
@ -117,8 +117,9 @@
#if defined(__FreeBSD__)
#include <i386/scsi/aic7xxx.h>
#include <dev/aic7xxx/aic7xxx_reg.h>
#include <dev/aic7xxx/sequencer.h>
#include <aic7xxx_reg.h>
#include <aic7xxx_seq.h>
#endif /* defined(__FreeBSD__) */
#if defined(__NetBSD__)
@ -127,7 +128,7 @@
#define bootverbose 1
#if DEBUGTARGET < 0 /* Negative numbrs for disabling cause warnings */
#if DEBUGTARGET < 0 /* Negative numbers for disabling cause warnings */
#define DEBUGTARGET 17
#endif
#endif /* defined(__NetBSD__) */
@ -272,6 +273,11 @@ static void ahc_handle_scsiint __P((struct ahc_softc *ahc,
static void ahc_handle_devreset __P((struct ahc_softc *ahc,
struct scb *scb));
static void ahc_loadseq __P((struct ahc_softc *ahc));
static struct patch *
ahc_next_patch __P((struct patch *cur_patch, int options,
int instrptr));
static void ahc_download_instr __P((struct ahc_softc *ahc, int options,
int instrptr));
static int ahc_match_scb __P((struct scb *scb, int target, char channel,
int lun, u_int8_t tag));
static int ahc_poll __P((struct ahc_softc *ahc, int wait));
@ -409,7 +415,7 @@ static int ahc_num_syncrates =
sizeof(ahc_syncrates) / sizeof(ahc_syncrates[0]);
/*
* Allocate a controller structures for a new device and initialize it.
* Allocate a controller structure for a new device and initialize it.
*/
#if defined(__FreeBSD__)
struct ahc_softc *
@ -572,12 +578,12 @@ ahc_scsirate(ahc, scsirate, period, offset, channel, target )
}
}
if (i >= ahc_num_syncrates) {
/* Use asyncronous transfers. */
/* Use asynchronous transfers. */
*scsirate = 0;
*period = 0;
*offset = 0;
if (bootverbose)
printf("%s: target %d using asyncronous transfers\n",
printf("%s: target %d using asynchronous transfers\n",
ahc_name(ahc), target );
}
/*
@ -748,7 +754,7 @@ ahc_intr(arg)
intstat = ahc_inb(ahc, INTSTAT);
/*
* Is this interrupt for me? or for
* someone who is sharing my interrupt
* someone who is sharing my interrupt?
*/
if (!(intstat & INT_PEND))
#if defined(__FreeBSD__)
@ -860,7 +866,7 @@ ahc_handle_seqint(ahc, intstat)
int scratch_offset;
char channel;
if ((ahc_inb(ahc, FLAGS) & RESELECTED) != 0)
if ((ahc_inb(ahc, SEQ_FLAGS) & RESELECTED) != 0)
target = ahc_inb(ahc, SELID);
else
target = ahc_inb(ahc, SCSIID);
@ -869,7 +875,7 @@ ahc_handle_seqint(ahc, intstat)
channel = ahc_inb(ahc, SBLKCTL) & SELBUSB ? 'B': 'A';
if (channel == 'B')
scratch_offset += 8;
targ_mask = (0x01 << scratch_offset);
targ_mask = (0x01 << scratch_offset);
switch (intstat & SEQINT_MASK) {
case NO_MATCH:
@ -903,7 +909,7 @@ ahc_handle_seqint(ahc, intstat)
* handler knows that there is an SCB to
* cleanup.
*/
ahc_outb(ahc, FLAGS, ahc_inb(ahc, FLAGS)
ahc_outb(ahc, SEQ_FLAGS, ahc_inb(ahc, SEQ_FLAGS)
| IDENTIFY_SEEN);
sc_print_addr(scb->xs->sc_link);
printf("reconnect SCB abort successfull\n");
@ -946,7 +952,7 @@ ahc_handle_seqint(ahc, intstat)
case SEND_REJECT:
{
u_int8_t rejbyte = ahc_inb(ahc, REJBYTE);
printf("%s:%c:%d: Warning - unknown message recieved from "
printf("%s:%c:%d: Warning - unknown message received from "
"target (0x%x). Rejecting\n",
ahc_name(ahc), channel, target, rejbyte);
break;
@ -967,13 +973,20 @@ ahc_handle_seqint(ahc, intstat)
ahc_name(ahc), channel, target, ahc_inb(ahc, LASTPHASE),
ahc_inb(ahc, SAVED_TCL));
found = ahc_reset_channel(ahc, channel, XS_TIMEOUT,
/*initiate reset*/TRUE);
/*initiate reset*/TRUE);
printf("%s: Issued Channel %c Bus Reset. "
"%d SCBs aborted\n", ahc_name(ahc), channel, found);
break;
}
case BAD_PHASE:
printf("%s:%c:%d: unknown scsi bus phase. Attempting to "
"continue\n", ahc_name(ahc), channel, target);
if (ahc_inb(ahc, LASTPHASE) == P_BUSFREE) {
printf("%s:%c:%d: Missed busfree.\n", ahc_name(ahc),
channel, target);
restart_sequencer(ahc);
} else {
printf("%s:%c:%d: unknown scsi bus phase. Attempting "
"to continue\n", ahc_name(ahc), channel, target);
}
break;
case EXTENDED_MSG:
{
@ -999,8 +1012,8 @@ ahc_handle_seqint(ahc, intstat)
ahc_outb(ahc, RETURN_1, SEND_REJ);
break;
}
period = ahc_inb(ahc, MSGIN_EXT_BYTE0);
saved_offset = ahc_inb(ahc, MSGIN_EXT_BYTE1);
period = ahc_inb(ahc, MSGIN_EXT_BYTES);
saved_offset = ahc_inb(ahc, MSGIN_EXT_BYTES + 1);
targ_scratch = ahc_inb(ahc, TARG_SCRATCH
+ scratch_offset);
if (targ_scratch & WIDEXFER)
@ -1058,7 +1071,7 @@ ahc_handle_seqint(ahc, intstat)
break;
}
bus_width = ahc_inb(ahc, MSGIN_EXT_BYTE0);
bus_width = ahc_inb(ahc, MSGIN_EXT_BYTES);
scratch = ahc_inb(ahc, TARG_SCRATCH + scratch_offset);
if ((scb->flags & SCB_MSGOUT_WDTR) != 0) {
@ -1161,8 +1174,8 @@ ahc_handle_seqint(ahc, intstat)
/* note asynch xfers and clear flag */
targ_scratch &= 0xf0;
ahc->needsdtr &= ~targ_mask;
printf("%s:%c:%d: refuses syncronous negotiation. "
"Using asyncronous transfers\n",
printf("%s:%c:%d: refuses synchronous negotiation. "
"Using asynchronous transfers\n",
ahc_name(ahc),
channel, target);
} else {
@ -1361,16 +1374,17 @@ ahc_handle_seqint(ahc, intstat)
*/
message_offset = ahc_inb(ahc, MSG_LEN);
if (scb->flags & SCB_DEVICE_RESET) {
ahc_outb(ahc, MSG0, MSG_BUS_DEV_RESET);
ahc_outb(ahc, MSG_OUT, MSG_BUS_DEV_RESET);
ahc_outb(ahc, MSG_LEN, 1);
sc_print_addr(scb->xs->sc_link);
printf("Bus Device Reset Message Sent\n");
} else if (scb->flags & SCB_ABORT) {
if ((scb->hscb->control & TAG_ENB) != 0)
ahc_outb(ahc, MSG0 + message_offset,
ahc_outb(ahc, MSG_OUT + message_offset,
MSG_ABORT_TAG);
else
ahc_outb(ahc, MSG0 + message_offset, MSG_ABORT);
ahc_outb(ahc, MSG_OUT + message_offset,
MSG_ABORT);
ahc_outb(ahc, MSG_LEN, message_offset + 1);
sc_print_addr(scb->xs->sc_link);
printf("Abort Message Sent\n");
@ -1420,9 +1434,9 @@ ahc_handle_seqint(ahc, intstat)
u_int32_t overrun;
int i;
scb = ahc->scb_data->scbarray[scbindex];
overrun = ahc_inb(ahc, STCNT0)
| (ahc_inb(ahc, STCNT1) << 8)
| (ahc_inb(ahc, STCNT2) << 16);
overrun = ahc_inb(ahc, STCNT)
| (ahc_inb(ahc, STCNT + 1) << 8)
| (ahc_inb(ahc, STCNT + 2) << 16);
overrun = 0x00ffffff - overrun;
sc_print_addr(scb->xs->sc_link);
printf("data overrun of %d bytes detected in %s phase."
@ -1431,7 +1445,7 @@ ahc_handle_seqint(ahc, intstat)
scb->hscb->tag);
sc_print_addr(scb->xs->sc_link);
printf("%s seen Data Phase. Length = %d. NumSGs = %d.\n",
ahc_inb(ahc, FLAGS) & DPHASE ? "Have" : "Haven't",
ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't",
scb->xs->datalen, scb->sg_count);
for (i = 0; i < scb->sg_count; i++) {
printf("sg[%d] - Addr 0x%x : Length %d\n",
@ -1568,8 +1582,9 @@ ahc_handle_scsiint(ahc, intstat)
char channel = ahc_inb(ahc, SBLKCTL) & SELBUSB ? 'B': 'A';
int printerror = 1;
ahc_outb(ahc, SCSISEQ, 0);
if (lastphase != P_BUSFREE) {
u_int8_t flags = ahc_inb(ahc, FLAGS)
u_int8_t flags = ahc_inb(ahc, SEQ_FLAGS)
& (IDENTIFY_SEEN|RESELECTED);
if (flags == 0 || flags == (IDENTIFY_SEEN|RESELECTED)) {
@ -1643,8 +1658,10 @@ ahc_handle_scsiint(ahc, intstat)
scb = NULL;
} else
printf("%s: ", ahc_name(ahc));
printf("Unexpected busfree. LASTPHASE == 0x%x\n",
lastphase);
printf("Unexpected busfree. LASTPHASE == 0x%x\n"
"SEQADDR == 0x%x\n",
lastphase, (ahc_inb(ahc, SEQADDR1) << 8)
| ahc_inb(ahc, SEQADDR0));
}
ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
ahc_outb(ahc, CLRSINT1, CLRBUSFREE);
@ -1652,8 +1669,13 @@ ahc_handle_scsiint(ahc, intstat)
ahc_outb(ahc, CLRINT, CLRSCSIINT);
} else if (scb == NULL) {
printf("%s: ahc_intr - referenced scb not "
"valid during scsiint 0x%x scb(%d)\n",
ahc_name(ahc), status, scb_index);
"valid during scsiint 0x%x scb(%d)\n"
"SIMODE0 = 0x%x, SIMODE1 = 0x%x, SSTAT0 = 0x%x\n"
"SEQADDR = 0x%x\n", ahc_name(ahc),
status, scb_index, ahc_inb(ahc, SIMODE0),
ahc_inb(ahc, SIMODE1), ahc_inb(ahc, SSTAT0),
(ahc_inb(ahc, SEQADDR1) << 8)
| ahc_inb(ahc, SEQADDR0));
ahc_outb(ahc, CLRSINT1, status);
unpause_sequencer(ahc, /*unpause_always*/TRUE);
ahc_outb(ahc, CLRINT, CLRSCSIINT);
@ -1707,7 +1729,7 @@ ahc_handle_scsiint(ahc, intstat)
* mesg_out to something other than MSG_NOP.
*/
if (mesg_out != MSG_NOOP) {
ahc_outb(ahc, MSG0, mesg_out);
ahc_outb(ahc, MSG_OUT, mesg_out);
ahc_outb(ahc, MSG_LEN, 1);
scb = NULL;
} else
@ -1727,15 +1749,17 @@ ahc_handle_scsiint(ahc, intstat)
struct scsi_xfer *xs;
u_int8_t scbptr;
u_int8_t nextscb;
u_int8_t flags;
/*
* XXX If we queued an abort tag, go clean up the
* disconnected list.
*/
xs = scb->xs;
xs->error = XS_SELTIMEOUT;
/*
* Clear any pending messages for the timed out
* target, and mark the target as free
*/
flags = ahc_inb(ahc, FLAGS);
ahc_outb(ahc, MSG_LEN, 0);
ahc_index_busy_target(ahc, xs->sc_link->target,
IS_SCSIBUS_B(ahc, xs->sc_link) ? 'B' : 'A',
@ -1906,7 +1930,15 @@ ahc_done(ahc, scb)
}
untimeout(ahc_timeout, (caddr_t)scb);
ahc_free_scb(ahc, scb);
scsi_done(xs);
/*
* If we're polling, we rely on the ITS_DONE flag in the xs structure
* to know that the command has completed. Unfortunately, scsi_done
* can cause the same xs to get requeued putting us in an infinite
* loop. So, we defer the scsi_done call until the poll routine exits
* its loop. I hate the way this works.
*/
if ((xs->flags & SCSI_NOMASK) == 0)
scsi_done(xs);
}
/*
@ -1942,7 +1974,7 @@ ahc_init(ahc)
ahc->our_id);
} else
printf("Single Channel, SCSI Id=%d, ", ahc->our_id);
ahc_outb(ahc, FLAGS, SINGLE_BUS | (ahc->flags & AHC_PAGESCBS));
ahc_outb(ahc, SEQ_FLAGS, ahc->flags & AHC_PAGESCBS);
break;
case 2:
ahc->our_id = (ahc_inb(ahc, SCSICONF + 1) & HWSCSIID);
@ -1957,7 +1989,7 @@ ahc_init(ahc)
} else
printf("Wide Channel, SCSI Id=%d, ", ahc->our_id);
ahc->type |= AHC_WIDE;
ahc_outb(ahc, FLAGS, WIDE_BUS | (ahc->flags & AHC_PAGESCBS));
ahc_outb(ahc, SEQ_FLAGS, WIDE_BUS | (ahc->flags & AHC_PAGESCBS));
break;
case 8:
ahc->our_id = (ahc_inb(ahc, SCSICONF) & HSCSIID);
@ -1965,7 +1997,7 @@ ahc_init(ahc)
printf("Twin Channel, A SCSI Id=%d, B SCSI Id=%d, ",
ahc->our_id, ahc->our_id_b);
ahc->type |= AHC_TWIN;
ahc_outb(ahc, FLAGS, TWIN_BUS | (ahc->flags & AHC_PAGESCBS));
ahc_outb(ahc, SEQ_FLAGS, TWIN_BUS | (ahc->flags & AHC_PAGESCBS));
break;
default:
printf(" Unsupported adapter type. Ignoring\n");
@ -1997,10 +2029,10 @@ ahc_init(ahc)
ahc_outb(ahc, SCB_TAG, SCB_LIST_NULL);
/* No Busy non-tagged targets yet */
ahc_outb(ahc, SCB_ACTIVE0, SCB_LIST_NULL);
ahc_outb(ahc, SCB_ACTIVE1, SCB_LIST_NULL);
ahc_outb(ahc, SCB_ACTIVE2, SCB_LIST_NULL);
ahc_outb(ahc, SCB_ACTIVE3, SCB_LIST_NULL);
ahc_outb(ahc, SCB_BUSYTARGETS, SCB_LIST_NULL);
ahc_outb(ahc, SCB_BUSYTARGETS + 1, SCB_LIST_NULL);
ahc_outb(ahc, SCB_BUSYTARGETS + 2, SCB_LIST_NULL);
ahc_outb(ahc, SCB_BUSYTARGETS + 3, SCB_LIST_NULL);
}
/* Make that the last SCB terminates the free list */
@ -2062,7 +2094,7 @@ ahc_init(ahc)
if (scsi_conf & RESET_SCSI) {
/* Reset the bus */
if (bootverbose)
printf("%s: Reseting Channel B\n",
printf("%s: Resetting Channel B\n",
ahc_name(ahc));
ahc_reset_current_bus(ahc);
}
@ -2085,7 +2117,7 @@ ahc_init(ahc)
if (scsi_conf & RESET_SCSI) {
/* Reset the bus */
if (bootverbose)
printf("%s: Reseting Channel A\n", ahc_name(ahc));
printf("%s: Resetting Channel A\n", ahc_name(ahc));
ahc_reset_current_bus(ahc);
}
@ -2094,8 +2126,8 @@ ahc_init(ahc)
* Look at the information that board initialization or
* the board bios has left us. In the lower four bits of each
* target's scratch space any value other than 0 indicates
* that we should initiate syncronous transfers. If it's zero,
* the user or the BIOS has decided to disable syncronous
* that we should initiate synchronous transfers. If it's zero,
* the user or the BIOS has decided to disable synchronous
* negotiation to that target so we don't activate the needsdtr
* flag.
*/
@ -2128,7 +2160,7 @@ ahc_init(ahc)
if (target_settings & 0x0f) {
ahc->needsdtr_orig |= (0x01 << i);
/*Default to a asyncronous transfers(0 offset)*/
/*Default to a asynchronous transfers(0 offset)*/
target_settings &= 0xf0;
}
if (target_settings & 0x80) {
@ -2185,7 +2217,7 @@ ahc_init(ahc)
ahc->needwdtr, ahc->discenable);
#endif
/*
* Set the number of availible hardware SCBs
* Set the number of available hardware SCBs
*/
ahc_outb(ahc, SCBCOUNT, ahc->scb_data->maxhscbs);
@ -2228,10 +2260,10 @@ ahc_init(ahc)
/* Tell the sequencer where it can find the hscb array. */
hscb_physaddr = vtophys(ahc->scb_data->hscbs);
ahc_outb(ahc, HSCB_ADDR0, hscb_physaddr & 0xFF);
ahc_outb(ahc, HSCB_ADDR1, (hscb_physaddr >> 8)& 0xFF);
ahc_outb(ahc, HSCB_ADDR2, (hscb_physaddr >> 16)& 0xFF);
ahc_outb(ahc, HSCB_ADDR3, (hscb_physaddr >> 24)& 0xFF);
ahc_outb(ahc, HSCB_ADDR, hscb_physaddr & 0xFF);
ahc_outb(ahc, HSCB_ADDR + 1, (hscb_physaddr >> 8)& 0xFF);
ahc_outb(ahc, HSCB_ADDR + 2, (hscb_physaddr >> 16)& 0xFF);
ahc_outb(ahc, HSCB_ADDR + 3, (hscb_physaddr >> 24)& 0xFF);
}
/*
@ -2256,7 +2288,7 @@ ahc_init(ahc)
/*
* QCount mask to deal with broken aic7850s that
* sporatically get garbage in the upper bits of
* sporadically get garbage in the upper bits of
* their QCount registers.
*/
ahc_outb(ahc, QCNTMASK, ahc->qcntmask);
@ -2519,6 +2551,7 @@ ahc_scsi_cmd(xs)
break;
}
} while ((xs->flags & ITSDONE) == 0); /* a non command complete intr */
scsi_done(xs);
splx(s);
return (COMPLETE);
}
@ -2559,7 +2592,7 @@ ahc_run_waiting_queue(ahc)
}
/*
* A scb (and hence an scb entry on the board is put onto the
* An scb (and hence an scb entry on the board) is put onto the
* free list.
*/
static void
@ -2582,7 +2615,7 @@ ahc_free_scb(ahc, scb)
STAILQ_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links);
if (scb->links.stqe_next == NULL) {
/*
* If there were no SCBs availible, wake anybody waiting
* If there were no SCBs available, wake anybody waiting
* for one to come free.
*/
wakeup((caddr_t)&ahc->scb_data->free_scbs);
@ -2700,19 +2733,133 @@ static void
ahc_loadseq(ahc)
struct ahc_softc *ahc;
{
static u_char seqprog[] = {
# include "aic7xxx_seq.h"
};
int options;
struct patch *cur_patch;
int i;
int downloaded;
options = 1; /* Code for all options */
downloaded = 0;
if ((ahc->type & AHC_ULTRA) != 0)
options |= ULTRA;
if ((ahc->type & AHC_TWIN) != 0)
options |= TWIN_CHANNEL;
if (ahc->scb_data->maxscbs > ahc->scb_data->maxhscbs)
options |= SCB_PAGING;
cur_patch = patches;
ahc_outb(ahc, SEQCTL, PERRORDIS|LOADRAM);
ahc_outb(ahc, SEQADDR0, 0);
ahc_outb(ahc, SEQADDR1, 0);
ahc_outsb(ahc, SEQRAM, seqprog, sizeof(seqprog));
for(i = 0; i < sizeof(seqprog)/4; i++) {
cur_patch = ahc_next_patch(cur_patch, options, i);
if (cur_patch && cur_patch->begin <= i && cur_patch->end > i)
/* Skip this instruction for this configuration */
continue;
ahc_download_instr(ahc, options, i);
downloaded++;
}
ahc_outb(ahc, SEQCTL, FASTMODE);
ahc_outb(ahc, SEQADDR0, 0);
ahc_outb(ahc, SEQADDR1, 0);
if (bootverbose)
printf("%s: %d instructions downloaded\n", ahc_name(ahc),
downloaded);
}
static struct patch *
ahc_next_patch(cur_patch, options, instrptr)
struct patch *cur_patch;
int options;
int instrptr;
{
while(cur_patch != NULL) {
if (((cur_patch->options & options) != 0
&& cur_patch->negative == FALSE)
|| ((cur_patch->options & options) == 0
&& cur_patch->negative == TRUE)
|| (instrptr >= cur_patch->end)) {
/*
* Either we want to keep this section of code,
* or we have consumed this patch. Skip to the
* next patch.
*/
cur_patch++;
if (cur_patch->options == 0)
/* Out of patches */
cur_patch = NULL;
} else
/* Found an okay patch */
break;
}
return (cur_patch);
}
static void
ahc_download_instr(ahc, options, instrptr)
struct ahc_softc *ahc;
int options;
int instrptr;
{
u_int8_t opcode;
struct ins_format3 *instr;
instr = (struct ins_format3 *)&seqprog[instrptr * 4];
/* Pull the opcode */
opcode = instr->opcode_addr >> 1;
switch (opcode) {
case AIC_OP_JMP:
case AIC_OP_JC:
case AIC_OP_JNC:
case AIC_OP_CALL:
case AIC_OP_JNE:
case AIC_OP_JNZ:
case AIC_OP_JE:
case AIC_OP_JZ:
{
int address_offset;
struct ins_format3 new_instr;
u_int address;
struct patch *patch;
int i;
address_offset = 0;
new_instr = *instr; /* structure copy */
address = new_instr.address;
address |= (new_instr.opcode_addr & ADDR_HIGH_BIT) << 8;
for (i = 0; i < sizeof(patches)/sizeof(patches[0]); i++) {
patch = &patches[i];
if (((patch->options & options) == 0
&& patch->negative == FALSE)
|| ((patch->options & options) != 0
&& patch->negative == TRUE)) {
if (address >= patch->end)
address_offset +=
patch->end - patch->begin;
}
}
address -= address_offset;
new_instr.address = address & 0xFF;
new_instr.opcode_addr &= ~ADDR_HIGH_BIT;
new_instr.opcode_addr |= (address >> 8) & ADDR_HIGH_BIT;
ahc_outsb(ahc, SEQRAM, &new_instr.immediate, 4);
break;
}
case AIC_OP_OR:
case AIC_OP_AND:
case AIC_OP_XOR:
case AIC_OP_ADD:
case AIC_OP_ADC:
case AIC_OP_ROL:
ahc_outsb(ahc, SEQRAM, &instr->immediate, 4);
break;
default:
panic("Unknown opcode encountered in seq program");
break;
}
}
/*
@ -2918,9 +3065,17 @@ bus_reset:
active_scb = ahc->scb_data->scbarray[active_scb_index];
if (bus_state != P_BUSFREE) {
if (active_scb_index >= ahc->scb_data->numscbs) {
/* Go "immediatly" to the bus reset */
sc_print_addr(scb->xs->sc_link);
printf("SCB %d: Yucky Immediate reset. "
"Flags = 0x%x\n", scb->hscb->tag,
scb->flags);
goto bus_reset;
}
/* Send the abort to the active SCB */
ahc_outb(ahc, MSG_LEN, 1);
ahc_outb(ahc, MSG0,
ahc_outb(ahc, MSG_OUT,
(active_scb->hscb->control & TAG_ENB) == 0 ?
MSG_ABORT : MSG_ABORT_TAG);
ahc_outb(ahc, SCSISIGO, bus_state|ATNO);
@ -2954,7 +3109,8 @@ bus_reset:
if (disconnected) {
/* Simply set the ABORT_SCB control bit */
scb->hscb->control |= ABORT_SCB|MK_MESSAGE;
scb->hscb->control &= ~DISCONNECTED;
if ((ahc->flags & AHC_PAGESCBS) == 0)
scb->hscb->control &= ~DISCONNECTED;
scb->flags |= SCB_QUEUED_ABORT
| SCB_ABORT|SCB_RECOVERY_SCB;
if (hscb_index != SCB_LIST_NULL) {
@ -2962,7 +3118,8 @@ bus_reset:
scb_control = ahc_inb(ahc, SCB_CONTROL);
ahc_outb(ahc, SCB_CONTROL,
scb_control | ABORT_SCB);
scb_control | MK_MESSAGE
| ABORT_SCB);
}
/*
* Actually re-queue this SCB in case we can
@ -2977,9 +3134,6 @@ bus_reset:
target = scb->xs->sc_link->target;
lun = scb->xs->sc_link->lun;
ahc_index_busy_target(ahc, target,
channel,
/*unbusy*/TRUE);
ahc_search_qinfifo(ahc, target,
channel,
lun,
@ -3381,7 +3535,7 @@ ahc_index_busy_target(ahc, target, channel, unbusy)
info_scb += 2;
active_scb = ahc_inb(ahc, SCBPTR);
ahc_outb(ahc, SCBPTR, info_scb);
scb_offset = SCB_ACTIVE0 + (target & 0x03);
scb_offset = SCB_BUSYTARGETS + (target & 0x03);
busy_scbid = ahc_inb(ahc, scb_offset);
if (unbusy)
ahc_outb(ahc, scb_offset, SCB_LIST_NULL);
@ -3406,7 +3560,7 @@ ahc_busy_target(ahc, target, channel, scbid)
info_scb += 2;
active_scb = ahc_inb(ahc, SCBPTR);
ahc_outb(ahc, SCBPTR, info_scb);
scb_offset = SCB_ACTIVE0 + (target & 0x03);
scb_offset = SCB_BUSYTARGETS + (target & 0x03);
ahc_outb(ahc, scb_offset, scbid);
ahc_outb(ahc, SCBPTR, active_scb);
return;
@ -3595,6 +3749,7 @@ ahc_reset_channel(ahc, channel, xs_error, initiate_reset)
ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
if (initiate_reset)
ahc_reset_current_bus(ahc);
ahc_outb(ahc, SCSISEQ, 0);
ahc_clear_intstat(ahc);
ahc_outb(ahc, SBLKCTL, sblkctl);
unpause_sequencer(ahc, /*unpause_always*/FALSE);
@ -3603,6 +3758,7 @@ ahc_reset_channel(ahc, channel, xs_error, initiate_reset)
ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
if (initiate_reset)
ahc_reset_current_bus(ahc);
ahc_outb(ahc, SCSISEQ, 0);
ahc_clear_intstat(ahc);
restart_sequencer(ahc);
}
@ -3655,11 +3811,11 @@ ahc_construct_sdtr(ahc, start_byte, period, offset)
u_int8_t period;
u_int8_t offset;
{
ahc_outb(ahc, MSG0 + start_byte, MSG_EXTENDED);
ahc_outb(ahc, MSG1 + start_byte, MSG_EXT_SDTR_LEN);
ahc_outb(ahc, MSG2 + start_byte, MSG_EXT_SDTR);
ahc_outb(ahc, MSG3 + start_byte, period);
ahc_outb(ahc, MSG4 + start_byte, offset);
ahc_outb(ahc, MSG_OUT + start_byte, MSG_EXTENDED);
ahc_outb(ahc, MSG_OUT + 1 + start_byte, MSG_EXT_SDTR_LEN);
ahc_outb(ahc, MSG_OUT + 2 + start_byte, MSG_EXT_SDTR);
ahc_outb(ahc, MSG_OUT + 3 + start_byte, period);
ahc_outb(ahc, MSG_OUT + 4 + start_byte, offset);
ahc_outb(ahc, MSG_LEN, start_byte + 5);
}
@ -3669,10 +3825,10 @@ ahc_construct_wdtr(ahc, start_byte, bus_width)
int start_byte;
u_int8_t bus_width;
{
ahc_outb(ahc, MSG0 + start_byte, MSG_EXTENDED);
ahc_outb(ahc, MSG1 + start_byte, MSG_EXT_WDTR_LEN);
ahc_outb(ahc, MSG2 + start_byte, MSG_EXT_WDTR);
ahc_outb(ahc, MSG3 + start_byte, bus_width);
ahc_outb(ahc, MSG_OUT + start_byte, MSG_EXTENDED);
ahc_outb(ahc, MSG_OUT + 1 + start_byte, MSG_EXT_WDTR_LEN);
ahc_outb(ahc, MSG_OUT + 2 + start_byte, MSG_EXT_WDTR);
ahc_outb(ahc, MSG_OUT + 3 + start_byte, bus_width);
ahc_outb(ahc, MSG_LEN, start_byte + 4);
}