Sync Perforce IDs, add tranceiver state change support, and correct
numerous error recovery buglets. Many thanks to Tor Egge for his assistance in diagnosing problems with the error recovery code. aic7xxx.c: Report missed bus free events using their own sequencer interrupt code to avoid confusion with other "bad phase" interrupts. Remove a delay used in debugging. This delay could only be hit in certain, very extreme, error recovery scenarios. Handle transceiver state changes correctly. You can now plug an SE device into a hot-plug LVD bus without hanging the controller. When stepping through a critical section, panic if we step more than a reasonable number of times. After a bus reset, disable bus reset interupts until we either our first attempt to (re)select another device, or another device attemps to select us. This removes the need to busy wait in kernel for the scsi reset line to fall yet still ensures we see any reset events that impact the state of either our initiator or target roles. Before this change, we had the potential of servicing a "storm" of reset interrupts if the reset line was held for a significant amount of time. Indicate the current sequencer address whenever we dump the card's state. aic7xxx.reg: Transceiver state change register definitions. Add the missed bussfree sequencer interrupt code. Re-enable the scsi reset interrupt if it has been disabled before every attempt to (re)select a device and when we have been selected as a target. When being (re)selected, check to see if the selection dissappeared just after we enabled our bus free interrupt. If the bus has gone free again, go back to the idle loop and wait for another selection. Note two locations where we should change our behavior if ATN is still raised. If ATN is raised during the presentation of a command complete or disconnect message, we should ignore the message and expect the target to put us in msgout phase. We don't currently do this as it requires some code re-arrangement so that critical sections can be properly placed around our handling of these two events. Otherwise, we cannot guarantee that the check of ATN is atomic relative to our acking of the message in byte (the kernel could assert ATN). Only set the IDENTIFY_SEEN flag after we have settled on the SCB for this transaction. The kernel looks at this flag before assuming that SCB_TAG is valid. This avoids confusion during certain types of error recovery. Add a critical section around findSCB. We cannot allow the kernel to remove an entry from the disconnected list while we are traversing it. Ditto for get_free_or_disc_scb. aic7xxx_freebsd.c: Only assume that SCB_TAG is accurate if IDENTIFY_SEEN is set in SEQ_FLAGS. Fix a typo that caused us to execute some code for the non-SCB paging case when paging SCBs. This only occurred during error recovery.
This commit is contained in:
parent
aaad27fdfe
commit
72df3c5621
@ -28,7 +28,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: //depot/src/aic7xxx/aic7xxx.c#9 $
|
||||
* $Id: //depot/src/aic7xxx/aic7xxx.c#18 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -617,19 +617,23 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
|
||||
u_int lastphase;
|
||||
|
||||
lastphase = ahc_inb(ahc, LASTPHASE);
|
||||
if (lastphase == P_BUSFREE) {
|
||||
printf("%s:%c:%d: Missed busfree. Curphase = 0x%x\n",
|
||||
ahc_name(ahc), devinfo.channel, devinfo.target,
|
||||
ahc_inb(ahc, SCSISIGI));
|
||||
restart_sequencer(ahc);
|
||||
return;
|
||||
} else {
|
||||
printf("%s:%c:%d: unknown scsi bus phase %x. "
|
||||
"Attempting to continue\n",
|
||||
ahc_name(ahc), devinfo.channel, devinfo.target,
|
||||
ahc_inb(ahc, SCSISIGI));
|
||||
}
|
||||
break;
|
||||
printf("%s:%c:%d: unknown scsi bus phase %x, "
|
||||
"lastphase = 0x%x. Attempting to continue\n",
|
||||
ahc_name(ahc), devinfo.channel, devinfo.target,
|
||||
lastphase, ahc_inb(ahc, SCSISIGI));
|
||||
break;
|
||||
}
|
||||
case MISSED_BUSFREE:
|
||||
{
|
||||
u_int lastphase;
|
||||
|
||||
lastphase = ahc_inb(ahc, LASTPHASE);
|
||||
printf("%s:%c:%d: Missed busfree. "
|
||||
"Lastphase = 0x%x, Curphase = 0x%x\n",
|
||||
ahc_name(ahc), devinfo.channel, devinfo.target,
|
||||
lastphase, ahc_inb(ahc, SCSISIGI));
|
||||
restart_sequencer(ahc);
|
||||
return;
|
||||
}
|
||||
case HOST_MSG_LOOP:
|
||||
{
|
||||
@ -798,7 +802,6 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
|
||||
case ABORT_QINSCB:
|
||||
{
|
||||
printf("%s: Abort QINSCB\n", ahc_name(ahc));
|
||||
DELAY(10000000);
|
||||
break;
|
||||
}
|
||||
case NO_FREE_SCB:
|
||||
@ -820,18 +823,6 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
|
||||
panic("for saftey");
|
||||
break;
|
||||
}
|
||||
case SCBPTR_MISMATCH:
|
||||
{
|
||||
u_int scbptr;
|
||||
|
||||
scbptr = ahc_inb(ahc, SCBPTR);
|
||||
printf("SCBPTR wrong. SCBPTR %d, tag %d, our tag %d\n",
|
||||
scbptr, ahc_inb(ahc, ARG_1),
|
||||
ahc->scb_data->hscbs[scbptr].tag);
|
||||
ahc_dump_card_state(ahc);
|
||||
panic("for safety");
|
||||
break;
|
||||
}
|
||||
case OUT_OF_RANGE:
|
||||
{
|
||||
printf("%s: BTT calculation out of range\n", ahc_name(ahc));
|
||||
@ -874,6 +865,7 @@ void
|
||||
ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
|
||||
{
|
||||
u_int scb_index;
|
||||
u_int status0;
|
||||
u_int status;
|
||||
struct scb *scb;
|
||||
char cur_channel;
|
||||
@ -889,8 +881,12 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
|
||||
cur_channel = 'A';
|
||||
intr_channel = cur_channel;
|
||||
|
||||
if ((ahc->features & AHC_ULTRA2) != 0)
|
||||
status0 = ahc_inb(ahc, SSTAT0) & IOERR;
|
||||
else
|
||||
status0 = 0;
|
||||
status = ahc_inb(ahc, SSTAT1);
|
||||
if (status == 0) {
|
||||
if (status == 0 && status0 == 0) {
|
||||
if ((ahc->features & AHC_TWIN) != 0) {
|
||||
/* Try the other channel */
|
||||
ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) ^ SELBUSB);
|
||||
@ -912,10 +908,30 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
|
||||
&& (ahc_inb(ahc, SEQ_FLAGS) & IDENTIFY_SEEN) == 0)
|
||||
scb = NULL;
|
||||
|
||||
if ((status & SCSIRSTI) != 0) {
|
||||
if ((ahc->features & AHC_ULTRA2) != 0
|
||||
&& (status0 & IOERR) != 0) {
|
||||
int now_lvd;
|
||||
|
||||
now_lvd = ahc_inb(ahc, SBLKCTL) & ENAB40;
|
||||
printf("%s: Transceiver State Has Changed to %s mode\n",
|
||||
ahc_name(ahc), now_lvd ? "LVD" : "SE");
|
||||
ahc_outb(ahc, CLRSINT0, CLRIOERR);
|
||||
/*
|
||||
* When transitioning to SE mode, the reset line
|
||||
* glitches, triggering an arbitration bug in some
|
||||
* Ultra2 controllers. This bug is cleared when we
|
||||
* assert the reset line. Since a reset glitch has
|
||||
* already occurred with this transition and a
|
||||
* transceiver state change is handled just like
|
||||
* a bus reset anyway, asserting the reset line
|
||||
* ourselves is safe.
|
||||
*/
|
||||
ahc_reset_channel(ahc, intr_channel,
|
||||
/*Initiate Reset*/now_lvd == 0);
|
||||
} else if ((status & SCSIRSTI) != 0) {
|
||||
printf("%s: Someone reset channel %c\n",
|
||||
ahc_name(ahc), intr_channel);
|
||||
ahc_reset_channel(ahc, intr_channel, /* Initiate Reset */FALSE);
|
||||
ahc_reset_channel(ahc, intr_channel, /*Initiate Reset*/FALSE);
|
||||
} else if ((status & SCSIPERR) != 0) {
|
||||
/*
|
||||
* Determine the bus phase and queue an appropriate message.
|
||||
@ -1157,10 +1173,12 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
|
||||
}
|
||||
}
|
||||
|
||||
#define AHC_MAX_STEPS 2000
|
||||
void
|
||||
ahc_clear_critical_section(struct ahc_softc *ahc)
|
||||
{
|
||||
int stepping;
|
||||
int steps;
|
||||
u_int simode0;
|
||||
u_int simode1;
|
||||
|
||||
@ -1168,6 +1186,7 @@ ahc_clear_critical_section(struct ahc_softc *ahc)
|
||||
return;
|
||||
|
||||
stepping = FALSE;
|
||||
steps = 0;
|
||||
simode0 = 0;
|
||||
simode1 = 0;
|
||||
for (;;) {
|
||||
@ -1188,6 +1207,14 @@ ahc_clear_critical_section(struct ahc_softc *ahc)
|
||||
if (i == ahc->num_critical_sections)
|
||||
break;
|
||||
|
||||
if (steps > AHC_MAX_STEPS) {
|
||||
printf("%s: Infinite loop in critical section\n",
|
||||
ahc_name(ahc));
|
||||
ahc_dump_card_state(ahc);
|
||||
panic("critical section loop");
|
||||
}
|
||||
|
||||
steps++;
|
||||
if (stepping == FALSE) {
|
||||
|
||||
/*
|
||||
@ -3998,6 +4025,8 @@ ahc_init(struct ahc_softc *ahc)
|
||||
scsi_conf = ahc_inb(ahc, SCSICONF + 1);
|
||||
ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL))
|
||||
|term|ENSTIMER|ACTNEGEN);
|
||||
if ((ahc->features & AHC_ULTRA2) != 0)
|
||||
ahc_outb(ahc, SIMODE0, ahc_inb(ahc, SIMODE0)|ENIOERR);
|
||||
ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
|
||||
ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);
|
||||
|
||||
@ -4017,6 +4046,8 @@ ahc_init(struct ahc_softc *ahc)
|
||||
ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL))
|
||||
|term
|
||||
|ENSTIMER|ACTNEGEN);
|
||||
if ((ahc->features & AHC_ULTRA2) != 0)
|
||||
ahc_outb(ahc, SIMODE0, ahc_inb(ahc, SIMODE0)|ENIOERR);
|
||||
ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
|
||||
ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);
|
||||
|
||||
@ -5027,7 +5058,8 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
|
||||
* upsetting the current bus.
|
||||
*/
|
||||
ahc_outb(ahc, SBLKCTL, sblkctl ^ SELBUSB);
|
||||
ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
|
||||
ahc_outb(ahc, SIMODE1,
|
||||
ahc_inb(ahc, SIMODE1) & ~(ENBUSFREE|ENSCSIRST));
|
||||
ahc_outb(ahc, SCSISEQ,
|
||||
ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP));
|
||||
if (initiate_reset)
|
||||
@ -5038,7 +5070,8 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
|
||||
} else {
|
||||
/* Case 2: A command from this bus is active or we're idle */
|
||||
ahc_clear_msg_state(ahc);
|
||||
ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
|
||||
ahc_outb(ahc, SIMODE1,
|
||||
ahc_inb(ahc, SIMODE1) & ~(ENBUSFREE|ENSCSIRST));
|
||||
ahc_outb(ahc, SCSISEQ,
|
||||
ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP));
|
||||
if (initiate_reset)
|
||||
@ -5603,6 +5636,10 @@ ahc_dump_card_state(struct ahc_softc *ahc)
|
||||
|
||||
saved_scbptr = ahc_inb(ahc, SCBPTR);
|
||||
|
||||
printf("%s: Dumping Card State at SEQADDR 0x%x\n",
|
||||
ahc_name(ahc),
|
||||
ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
|
||||
|
||||
printf("SCB count = %d\n", ahc->scb_data->numscbs);
|
||||
/* QINFIFO */
|
||||
printf("QINFIFO entries: ");
|
||||
|
@ -28,7 +28,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: //depot/src/aic7xxx/aic7xxx.h#6 $
|
||||
* $Id: //depot/src/aic7xxx/aic7xxx.h#13 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -95,6 +95,11 @@ struct scb_platform_data;
|
||||
#define BUILD_TCL(scsiid, lun) \
|
||||
((lun) | (((scsiid) & TID) << 4))
|
||||
|
||||
#ifndef AHC_TARGET_MODE
|
||||
#undef AHC_TMODE_ENABLE
|
||||
#define AHC_TMODE_ENABLE 0
|
||||
#endif
|
||||
|
||||
/**************************** Driver Constants ********************************/
|
||||
/*
|
||||
* The maximum number of supported targets.
|
||||
|
@ -28,7 +28,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: //depot/src/aic7xxx/aic7xxx.reg#5 $
|
||||
* $Id: //depot/src/aic7xxx/aic7xxx.reg#9 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -250,6 +250,7 @@ register CLRSINT0 {
|
||||
bit CLRSELDI 0x20
|
||||
bit CLRSELINGO 0x10
|
||||
bit CLRSWRAP 0x08
|
||||
bit CLRIOERR 0x08 /* Ultra2 Only */
|
||||
bit CLRSPIORDY 0x02
|
||||
}
|
||||
|
||||
@ -806,11 +807,11 @@ register INTSTAT {
|
||||
* without honoring our ATN
|
||||
* request to issue a message.
|
||||
*/
|
||||
mask SCBPTR_MISMATCH 0xb0|SEQINT /*
|
||||
* In the SCB paging case, our
|
||||
* SCBPTR is not the same as
|
||||
* we originally set prior to
|
||||
* download of a new scb.
|
||||
mask MISSED_BUSFREE 0xb0|SEQINT /*
|
||||
* The sequencer never saw
|
||||
* the bus go free after
|
||||
* either a command complete
|
||||
* or disconnect message.
|
||||
*/
|
||||
mask SCB_MISMATCH 0xc0|SEQINT /*
|
||||
* Downloaded SCB's tag does
|
||||
|
@ -28,7 +28,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: //depot/src/aic7xxx/aic7xxx.seq#7 $
|
||||
* $Id: //depot/src/aic7xxx/aic7xxx.seq#14 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -112,10 +112,6 @@ dma_queued_scb:
|
||||
BEGIN_CRITICAL
|
||||
cmp NEXT_QUEUED_SCB, A jne abort_qinscb;
|
||||
if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
|
||||
if ((ahc->flags & AHC_PAGESCBS) == 0) {
|
||||
cmp SCBPTR, A je . + 2;
|
||||
mvi SCBPTR_MISMATCH call set_seqint;
|
||||
}
|
||||
cmp SCB_TAG, A je . + 2;
|
||||
mvi SCB_MISMATCH call set_seqint;
|
||||
}
|
||||
@ -142,6 +138,16 @@ abort_qinscb:
|
||||
jmp poll_for_work_loop;
|
||||
|
||||
start_selection:
|
||||
/*
|
||||
* If bus reset interrupts have been disabled (from a previous
|
||||
* reset), re-enable them now. Resets are only of interest
|
||||
* when we have outstanding transactions, so we can safely
|
||||
* defer re-enabling the interrupt until, as an initiator,
|
||||
* we start sending out transactions again.
|
||||
*/
|
||||
test SIMODE1, ENSCSIRST jnz . + 3;
|
||||
mvi CLRSINT1, CLRSCSIRSTI;
|
||||
or SIMODE1, ENSCSIRST;
|
||||
if ((ahc->features & AHC_TWIN) != 0) {
|
||||
and SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */
|
||||
test SCB_SCSIID, TWIN_CHNLB jz . + 2;
|
||||
@ -195,7 +201,15 @@ selection:
|
||||
mvi CLRSINT1,CLRBUSFREE;
|
||||
or SIMODE1, ENBUSFREE;
|
||||
|
||||
/*
|
||||
* Guard against a bus free after (re)selection
|
||||
* but prior to enabling the busfree interrupt. SELDI
|
||||
* and SELDO will be cleared in that case.
|
||||
*/
|
||||
test SSTAT0,SELDO jnz select_out;
|
||||
test SSTAT0, SELDI jnz . + 3;
|
||||
and SIMODE1, ~ENBUSFREE;
|
||||
jmp poll_for_work;
|
||||
mvi CLRSINT0, CLRSELDI;
|
||||
select_in:
|
||||
if ((ahc->flags & AHC_TARGETROLE) != 0) {
|
||||
@ -207,7 +221,16 @@ select_in:
|
||||
* We've just been selected. Assert BSY and
|
||||
* setup the phase for receiving messages
|
||||
* from the target.
|
||||
*
|
||||
* If bus reset interrupts have been disabled (from a
|
||||
* previous reset), re-enable them now. Resets are only
|
||||
* of interest when we have outstanding transactions, so
|
||||
* we can safely defer re-enabling the interrupt until,
|
||||
* as a target, we start receiving transactions again.
|
||||
*/
|
||||
test SIMODE1, ENSCSIRST jnz . + 3;
|
||||
mvi CLRSINT1, CLRSCSIRSTI;
|
||||
or SIMODE1, ENSCSIRST;
|
||||
mvi SCSISIGO, P_MESGOUT|BSYO;
|
||||
|
||||
/*
|
||||
@ -616,7 +639,7 @@ await_busfree:
|
||||
and SXFRCTL0, ~SPIOEN;
|
||||
test SSTAT1,REQINIT|BUSFREE jz .;
|
||||
test SSTAT1, BUSFREE jnz poll_for_work;
|
||||
mvi BAD_PHASE call set_seqint;
|
||||
mvi MISSED_BUSFREE call set_seqint;
|
||||
}
|
||||
|
||||
clear_target_state:
|
||||
@ -1417,6 +1440,16 @@ mesgin_complete:
|
||||
* RETURN_1 to SEND_SENSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* If ATN is raised, we still want to give the target a message.
|
||||
* Perhaps there was a parity error on this last message byte.
|
||||
* Either way, the target should take us to message out phase
|
||||
* and then attempt to complete the command again.
|
||||
* XXX - Need a critical section to do this corrctly. Wait until
|
||||
* we queue completions.
|
||||
test SCSISIGI, ATNI jnz mesgin_done;
|
||||
*/
|
||||
|
||||
/*
|
||||
* See if we attempted to deliver a message but the target ingnored us.
|
||||
*/
|
||||
@ -1469,6 +1502,16 @@ if ((ahc->flags & AHC_INITIATORROLE) != 0) {
|
||||
* a reselction.
|
||||
*/
|
||||
mesgin_disconnect:
|
||||
/*
|
||||
* If ATN is raised, we still want to give the target a message.
|
||||
* Perhaps there was a parity error on this last message byte
|
||||
* or we want to abort this command. Either way, the target
|
||||
* should take us to message out phase and then attempt to
|
||||
* disconnect again.
|
||||
* XXX - Wait for more testing.
|
||||
test SCSISIGI, ATNI jnz mesgin_done;
|
||||
*/
|
||||
|
||||
or SCB_CONTROL,DISCONNECTED;
|
||||
if ((ahc->flags & AHC_PAGESCBS) != 0) {
|
||||
call add_scb_to_disc_list;
|
||||
@ -1568,7 +1611,7 @@ fetch_busy_target:
|
||||
mov ARG_1, SINDIR;
|
||||
cmp ARG_1, SCB_LIST_NULL je snoop_tag;
|
||||
if ((ahc->flags & AHC_PAGESCBS) != 0) {
|
||||
mov RETURN_1 call findSCB;
|
||||
mov ARG_1 call findSCB;
|
||||
} else {
|
||||
mov SCBPTR, RETURN_1;
|
||||
}
|
||||
@ -1631,13 +1674,13 @@ setup_SCB_id_lun_okay:
|
||||
}
|
||||
test SCB_CONTROL,DISCONNECTED jz not_found_cleanup_scb;
|
||||
and SCB_CONTROL,~DISCONNECTED;
|
||||
mvi SEQ_FLAGS,IDENTIFY_SEEN; /* make note of IDENTIFY */
|
||||
test SCB_CONTROL, TAG_ENB jnz setup_SCB_tagged;
|
||||
mov A, SCBPTR;
|
||||
mvi ARG_1, SCB_LIST_NULL;
|
||||
mov SAVED_SCSIID call set_busy_target;
|
||||
mov SCBPTR, A;
|
||||
setup_SCB_tagged:
|
||||
mvi SEQ_FLAGS,IDENTIFY_SEEN; /* make note of IDENTIFY */
|
||||
call set_transfer_settings;
|
||||
/* See if the host wants to send a message upon reconnection */
|
||||
test SCB_CONTROL, MK_MESSAGE jz mesgin_done;
|
||||
@ -1752,6 +1795,7 @@ assert:
|
||||
* removal of the found SCB from the disconnected list.
|
||||
*/
|
||||
if ((ahc->flags & AHC_PAGESCBS) != 0) {
|
||||
BEGIN_CRITICAL
|
||||
findSCB:
|
||||
mov A, SINDEX; /* Tag passed in SINDEX */
|
||||
cmp DISCONNECTED_SCBH, SCB_LIST_NULL je findSCB_notFound;
|
||||
@ -1773,6 +1817,7 @@ rem_scb_from_disc_list:
|
||||
mov SCBPTR, SINDEX ret;
|
||||
rHead:
|
||||
mov DISCONNECTED_SCBH,SCB_NEXT ret;
|
||||
END_CRITICAL
|
||||
findSCB_notFound:
|
||||
/*
|
||||
* We didn't find it. Page in the SCB.
|
||||
@ -1919,7 +1964,7 @@ dma_scb_tohost:
|
||||
mvi CCSCBCTL, CCSCBRESET;
|
||||
bmov CCSCBRAM, SCB_BASE, SCB_UPLOAD_SIZE;
|
||||
or CCSCBCTL, CCSCBEN|CCSCBRESET;
|
||||
cmp CCSCBCTL, CCSCBDONE|CCSCBEN jne .;
|
||||
test CCSCBCTL, CCSCBDONE jz .;
|
||||
} else if ((ahc->bugs & AHC_SCBCHAN_UPLOAD_BUG) != 0) {
|
||||
mvi CCSCBCTL, CCARREN|CCSCBRESET;
|
||||
cmp CCSCBCTL, ARRDONE|CCARREN jne .;
|
||||
@ -2055,6 +2100,7 @@ END_CRITICAL
|
||||
|
||||
if ((ahc->flags & AHC_PAGESCBS) != 0) {
|
||||
get_free_or_disc_scb:
|
||||
BEGIN_CRITICAL
|
||||
cmp FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb;
|
||||
cmp DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb;
|
||||
return_error:
|
||||
@ -2062,14 +2108,15 @@ return_error:
|
||||
mvi SINDEX, SCB_LIST_NULL ret;
|
||||
dequeue_disc_scb:
|
||||
mov SCBPTR, DISCONNECTED_SCBH;
|
||||
dma_up_scb:
|
||||
mov DISCONNECTED_SCBH, SCB_NEXT;
|
||||
END_CRITICAL
|
||||
mvi DMAPARAMS, FIFORESET;
|
||||
mov SCB_TAG call dma_scb;
|
||||
unlink_disc_scb:
|
||||
mov DISCONNECTED_SCBH, SCB_NEXT ret;
|
||||
mov SCB_TAG jmp dma_scb;
|
||||
BEGIN_CRITICAL
|
||||
dequeue_free_scb:
|
||||
mov SCBPTR, FREE_SCBH;
|
||||
mov FREE_SCBH, SCB_NEXT ret;
|
||||
END_CRITICAL
|
||||
|
||||
add_scb_to_disc_list:
|
||||
/*
|
||||
|
@ -28,7 +28,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: //depot/src/aic7xxx/aic7xxx_93cx6.c#3 $
|
||||
* $Id: //depot/src/aic7xxx/aic7xxx_93cx6.c#4 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
@ -30,7 +30,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: //depot/src/aic7xxx/aic7xxx_93cx6.h#3 $
|
||||
* $Id: //depot/src/aic7xxx/aic7xxx_93cx6.h#4 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
@ -1502,6 +1502,7 @@ ahc_timeout(void *arg)
|
||||
active_scb_index = ahc_inb(ahc, SCB_TAG);
|
||||
|
||||
if (last_phase != P_BUSFREE
|
||||
&& (ahc_inb(ahc, SEQ_FLAGS) & IDENTIFY_SEEN) != 0
|
||||
&& (active_scb_index < ahc->scb_data->numscbs)) {
|
||||
struct scb *active_scb;
|
||||
|
||||
@ -1628,7 +1629,7 @@ ahc_timeout(void *arg)
|
||||
* reslection, set the MK_MESSAGE flag in
|
||||
* the card's copy of the SCB.
|
||||
*/
|
||||
if ((ahc->flags & AHC_PAGESCBS) != 0) {
|
||||
if ((ahc->flags & AHC_PAGESCBS) == 0) {
|
||||
ahc_outb(ahc, SCBPTR, scb->hscb->tag);
|
||||
ahc_outb(ahc, SCB_CONTROL,
|
||||
ahc_inb(ahc, SCB_CONTROL)
|
||||
|
@ -28,7 +28,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: //depot/src/aic7xxx/aic7xxx_inline.h#5 $
|
||||
* $Id: //depot/src/aic7xxx/aic7xxx_inline.h#10 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
@ -1502,6 +1502,7 @@ ahc_timeout(void *arg)
|
||||
active_scb_index = ahc_inb(ahc, SCB_TAG);
|
||||
|
||||
if (last_phase != P_BUSFREE
|
||||
&& (ahc_inb(ahc, SEQ_FLAGS) & IDENTIFY_SEEN) != 0
|
||||
&& (active_scb_index < ahc->scb_data->numscbs)) {
|
||||
struct scb *active_scb;
|
||||
|
||||
@ -1628,7 +1629,7 @@ ahc_timeout(void *arg)
|
||||
* reslection, set the MK_MESSAGE flag in
|
||||
* the card's copy of the SCB.
|
||||
*/
|
||||
if ((ahc->flags & AHC_PAGESCBS) != 0) {
|
||||
if ((ahc->flags & AHC_PAGESCBS) == 0) {
|
||||
ahc_outb(ahc, SCBPTR, scb->hscb->tag);
|
||||
ahc_outb(ahc, SCB_CONTROL,
|
||||
ahc_inb(ahc, SCB_CONTROL)
|
||||
|
@ -30,7 +30,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: //depot/src/aic7xxx/aic7xxx_pci.c#5 $
|
||||
* $Id: //depot/src/aic7xxx/aic7xxx_pci.c#8 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user