Upgrade to version 1.1 of the aic79xx U320 driver.
aic79xx.c: o Remove redundant ahd_update_modes() call. o Correct panic in diagnostic should state corruption cause the SCB Id to be invalid during a selection timeout. o Add workaround for missing BUSFREEREV feature in Rev A silicon. o Corect formatting nits. o Use register pretty printing in more places. o Save and restore our SCB pointer when updating the waiting queue list for an "expected" LQ-out busfree. o In ahd_clear_intstat, deal with the missing autoclear in the CLRLQO* registers. o BE fixup in a diagnostic printf. o Make sure that we are in the proper mode before disabling selections in ahd_update_pending_scbs. o Add more diagnostics. o task_attribute_nonpkt_tag -> task_attribute: we don't need a nonpkt_tag field anymore for allowing all 512 SCBs to be used in non-packetized connections. o Negotiate HOLD_MCS to U320 devices. o Add a few additional mode assertions. o Restore the chip mode after clearing out the qinfifo so that code using ahd_abort_scbs sees a consistent mode. o Simplify the DMA engine shutdown routine prior to performing a bus reset. o Perform the sequencer restart after a chip reset prior to setting up our timer to poll for the reset to be complete. On some OSes, the timer could actually pre-empt us and order is important here. o Have our "reset poller" set the expected mode since there is no guarantee of what mode will be in force when we are called from the OS timer. o Save and restore the SCB pointer in ahd_dump_card_state(). This routine must not modify card state. o Ditto for ahd_dump_scbs(). aic79xx.h: o Add a few more chip bug definitions. o Align our tag on a 32bit boundary. aic79xx.reg: aic79xx.seq: o Start work on removing workarounds for Rev B. o Use a special location in scratch from for stroring our SCBPTR during legacy FIFO allocations. This corrects problems in mixed packetized/non-packetized configurations where calling into a FIFO task corrupted our SCBPTR. o Don't rely on DMA priority to guarantee that all data in our FIFOs will flush prior to a command completion notification going out of the command channel. We've never seen this assumption fail, but better safe than sorry. o Deal with missing BUSFREEREV feature in H2A. o Simplify disconnect list code now that the list will always have only a single entry. o Implement the AHD_REG_SLOW_SETTLE_BUG workaround. o Swith to using "REG_ISR" for local mode scratch during our ISR. o Add a missing jmp to the data_group_dma_loop after our data pointers have been re-initialized by the kernel. o Correct test in the bitbucket code so that we actually wait for the bitbucket to complete before signaling the kernel of the overrun condition. o Reposition pkt_saveptrs to avoid a jmp instruction. o Update a comment to reflect that the code now waits for a FIFO to drain prior to issuing a CLRCHN. aic79xx_inline.h: o Remove unused untagged queue handling code. o Don't attempt to htole64 what could be a 32bit value. aic79xx_pci.c: o Set additional bug flags for rev A chips.
This commit is contained in:
parent
0889fb1da5
commit
c59c8a72cf
@ -37,7 +37,7 @@
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#102 $
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#113 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -488,7 +488,6 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
|
||||
struct scb *scb;
|
||||
u_int scbid;
|
||||
|
||||
ahd_update_modes(ahd);
|
||||
scbid = ahd_get_scbptr(ahd);
|
||||
scb = ahd_lookup_scb(ahd, scbid);
|
||||
if (scb == NULL) {
|
||||
@ -933,12 +932,6 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
|
||||
ahd_outb(ahd, CLRSINT0, CLRSELINGO);
|
||||
|
||||
scbid = ahd_inw(ahd, WAITING_TID_HEAD);
|
||||
#ifdef AHD_DEBUG
|
||||
if ((ahd_debug & AHD_SHOW_SELTO) != 0) {
|
||||
ahd_print_path(ahd, scb);
|
||||
printf("Saw Selection Timeout for SCB 0x%x\n", scbid);
|
||||
}
|
||||
#endif
|
||||
scb = ahd_lookup_scb(ahd, scbid);
|
||||
if (scb == NULL) {
|
||||
printf("%s: ahd_intr - referenced scb not "
|
||||
@ -947,6 +940,13 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
|
||||
ahd_dump_card_state(ahd);
|
||||
panic("For diagnostics");
|
||||
} else {
|
||||
#ifdef AHD_DEBUG
|
||||
if ((ahd_debug & AHD_SHOW_SELTO) != 0) {
|
||||
ahd_print_path(ahd, scb);
|
||||
printf("Saw Selection Timeout for SCB 0x%x\n",
|
||||
scbid);
|
||||
}
|
||||
#endif
|
||||
ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT);
|
||||
ahd_freeze_devq(ahd, scb);
|
||||
}
|
||||
@ -1033,22 +1033,31 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
|
||||
if (packetized && ahd_inb(ahd, LASTPHASE) == P_BUSFREE) {
|
||||
restart = ahd_handle_pkt_busfree(ahd, busfreetime);
|
||||
} else {
|
||||
packetized = 0;
|
||||
restart = ahd_handle_nonpkt_busfree(ahd);
|
||||
}
|
||||
/*
|
||||
* Clear the busfree interrupt status. The setting of
|
||||
* the interrupt is a pulse, so we do not need to muck
|
||||
* with the ENBUSFREE logic. This also ensures that if
|
||||
* the bus has moved on to another connection, busfree
|
||||
* protection is still in force.
|
||||
* the interrupt is a pulse, so in a perfect world, we
|
||||
* would not need to muck with the ENBUSFREE logic. This
|
||||
* would ensure that if the bus moves on to another
|
||||
* connection, busfree protection is still in force. If
|
||||
* BUSFREEREV is broken, however, we must manually clear
|
||||
* the ENBUSFREE if the busfree occurred during a non-pack
|
||||
* connection so that we don't get false positives during
|
||||
* future, packetized, connections.
|
||||
*/
|
||||
ahd_outb(ahd, CLRSINT1, CLRBUSFREE|CLRSCSIPERR);
|
||||
ahd_outb(ahd, CLRSINT1, CLRBUSFREE);
|
||||
if (packetized == 0
|
||||
&& (ahd->bugs & AHD_BUSFREEREV_BUG) != 0)
|
||||
ahd_outb(ahd, SIMODE1,
|
||||
ahd_inb(ahd, SIMODE1) & ~ENBUSFREE);
|
||||
|
||||
if (clear_fifo)
|
||||
ahd_clear_fifo(ahd, mode);
|
||||
|
||||
ahd_clear_msg_state(ahd);
|
||||
ahd_clear_intstat(ahd);
|
||||
ahd_outb(ahd, CLRINT, CLRSCSIINT);
|
||||
if (restart) {
|
||||
ahd_restart(ahd);
|
||||
} else {
|
||||
@ -1066,12 +1075,13 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
|
||||
static void
|
||||
ahd_handle_transmission_error(struct ahd_softc *ahd)
|
||||
{
|
||||
u_int lqistat1;
|
||||
u_int lqistat2;
|
||||
u_int msg_out;
|
||||
u_int curphase;
|
||||
u_int lastphase;
|
||||
u_int perrdiag;
|
||||
u_int lqistat1;
|
||||
u_int lqistat2;
|
||||
u_int msg_out;
|
||||
u_int curphase;
|
||||
u_int lastphase;
|
||||
u_int perrdiag;
|
||||
u_int cur_col;
|
||||
|
||||
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
|
||||
lqistat1 = ahd_inb(ahd, LQISTAT1) & ~(LQIPHASE_LQ|LQIPHASE_NLQ);
|
||||
@ -1098,9 +1108,12 @@ ahd_handle_transmission_error(struct ahd_softc *ahd)
|
||||
msg_out = MSG_INITIATOR_DET_ERR;
|
||||
ahd_outb(ahd, CLRSINT1, CLRSCSIPERR);
|
||||
printf("%s: Transmission error detected\n", ahd_name(ahd));
|
||||
printf("%s: lqistat1 == 0x%x, LASTPHASE == 0x0%x, "
|
||||
"curphase = 0x%x, perrdiag == 0x%x\n",
|
||||
ahd_name(ahd), lqistat1, lastphase, curphase, perrdiag);
|
||||
cur_col = 0;
|
||||
ahd_lqistat1_print(lqistat1, &cur_col, 50);
|
||||
ahd_lastphase_print(lastphase, &cur_col, 50);
|
||||
ahd_scsisigi_print(curphase, &cur_col, 50);
|
||||
ahd_perrdiag_print(perrdiag, &cur_col, 50);
|
||||
printf("\n");
|
||||
ahd_dump_card_state(ahd);
|
||||
if ((lqistat1 & (LQIOVERI_LQ|LQIOVERI_NLQ)) != 0) {
|
||||
printf("%s: Gross protocol error during incoming "
|
||||
@ -1261,7 +1274,7 @@ ahd_handle_lqiphase_error(struct ahd_softc *ahd, u_int lqistat1)
|
||||
|
||||
/*
|
||||
* Packetized unexpected or expected busfree.
|
||||
* Entered in MODE_SCSI.
|
||||
* Entered in mode based on busfreetime.
|
||||
*/
|
||||
static int
|
||||
ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
|
||||
@ -1274,6 +1287,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
|
||||
if ((lqostat1 & LQOBUSFREE) != 0) {
|
||||
struct scb *scb;
|
||||
u_int scbid;
|
||||
u_int saved_scbptr;
|
||||
u_int waiting_h;
|
||||
u_int waiting_t;
|
||||
u_int next;
|
||||
@ -1282,8 +1296,23 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
|
||||
printf("%s: Warning, BUSFREE time is 0x%x. "
|
||||
"Expected BUSFREE_LQO.\n",
|
||||
ahd_name(ahd), busfreetime);
|
||||
|
||||
scbid = ahd_get_scbptr(ahd);
|
||||
/*
|
||||
* The LQO manager detected an unexpected busfree
|
||||
* either:
|
||||
*
|
||||
* 1) During an outgoing LQ.
|
||||
* 2) After an outgoing LQ but before the first
|
||||
* REQ of the command packet.
|
||||
* 3) During an outgoing command packet.
|
||||
*
|
||||
* In all cases, CURRSCB is pointing to the
|
||||
* SCB that encountered the failure. Clean
|
||||
* up the queue, clear SELDO and LQOBUSFREE,
|
||||
* and allow the sequencer to restart the select
|
||||
* out at its lesure.
|
||||
*/
|
||||
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
|
||||
scbid = ahd_inw(ahd, CURRSCB);
|
||||
scb = ahd_lookup_scb(ahd, scbid);
|
||||
if (scb == NULL)
|
||||
panic("SCB not valid during LQOBUSFREE");
|
||||
@ -1302,27 +1331,17 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
|
||||
* Clear the status.
|
||||
*/
|
||||
ahd_outb(ahd, CLRLQOINT1, CLRLQOBUSFREE);
|
||||
if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {
|
||||
if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)
|
||||
ahd_outb(ahd, CLRLQOINT1, 0);
|
||||
}
|
||||
/*
|
||||
* The LQO manager detected an unexpected busfree
|
||||
* either:
|
||||
*
|
||||
* 1) During an outgoing LQ.
|
||||
* 2) After an outgoing LQ but before the first
|
||||
* REQ of the command packet.
|
||||
* 3) During an outgoing command packet.
|
||||
*
|
||||
* In all cases, CURRSCB is pointing to the
|
||||
* SCB that encountered the failure. Clean
|
||||
* up the queue, clear SELDO and LQOBUSFREE,
|
||||
* and allow the sequencer to restart the select
|
||||
* out at its lesure.
|
||||
*/
|
||||
ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
|
||||
ahd_outb(ahd, CLRSINT0, CLRSELDO);
|
||||
|
||||
/*
|
||||
* Update the waiting for selection queue so
|
||||
* we restart on the correct SCB.
|
||||
*/
|
||||
waiting_h = ahd_inw(ahd, WAITING_TID_HEAD);
|
||||
saved_scbptr = ahd_get_scbptr(ahd);
|
||||
if (waiting_h != scbid) {
|
||||
|
||||
ahd_outw(ahd, WAITING_TID_HEAD, scbid);
|
||||
@ -1337,7 +1356,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
|
||||
ahd_set_scbptr(ahd, scbid);
|
||||
ahd_outw(ahd, SCB_NEXT2, next);
|
||||
}
|
||||
|
||||
ahd_set_scbptr(ahd, saved_scbptr);
|
||||
/* Return unpausing the sequencer. */
|
||||
return (0);
|
||||
}
|
||||
@ -1769,6 +1788,10 @@ ahd_clear_intstat(struct ahd_softc *ahd)
|
||||
|CLRLQOATNPKT|CLRLQOTCRC);
|
||||
ahd_outb(ahd, CLRLQOINT1, CLRLQOINITSCBPERR|CLRLQOSTOPI2|CLRLQOBADQAS
|
||||
|CLRLQOBUSFREE|CLRLQOPHACHGINPKT);
|
||||
if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {
|
||||
ahd_outb(ahd, CLRLQOINT0, 0);
|
||||
ahd_outb(ahd, CLRLQOINT1, 0);
|
||||
}
|
||||
ahd_outb(ahd, CLRSINT3, CLRNTRAMPERR|CLROSRAMPERR);
|
||||
ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI
|
||||
|CLRBUSFREE|CLRSCSIPERR|CLRREQINIT);
|
||||
@ -1817,26 +1840,32 @@ ahd_dump_sglist(struct scb *scb)
|
||||
sg_list = (struct ahd_dma64_seg*)scb->sg_list;
|
||||
for (i = 0; i < scb->sg_count; i++) {
|
||||
uint64_t addr;
|
||||
uint32_t len;
|
||||
|
||||
addr = ahd_le64toh(sg_list[i].addr);
|
||||
printf("sg[%d] - Addr 0x%x%x : Length %d\n",
|
||||
len = ahd_le32toh(sg_list[i].len);
|
||||
printf("sg[%d] - Addr 0x%x%x : Length %d%s\n",
|
||||
i,
|
||||
(uint32_t)((addr >> 32) & 0xFFFFFFFF),
|
||||
(uint32_t)(addr & 0xFFFFFFFF),
|
||||
ahd_le32toh(sg_list[i].len));
|
||||
sg_list[i].len & AHD_SG_LEN_MASK,
|
||||
(sg_list[i].len & AHD_DMA_LAST_SEG)
|
||||
? " Last" : "");
|
||||
}
|
||||
} else {
|
||||
struct ahd_dma_seg *sg_list;
|
||||
|
||||
sg_list = (struct ahd_dma_seg*)scb->sg_list;
|
||||
for (i = 0; i < scb->sg_count; i++) {
|
||||
printf("sg[%d] - Addr 0x%x%x : Length %d\n",
|
||||
uint32_t len;
|
||||
|
||||
len = ahd_le32toh(sg_list[i].len);
|
||||
printf("sg[%d] - Addr 0x%x%x : Length %d%s\n",
|
||||
i,
|
||||
(ahd_le32toh(sg_list[i].len) >> 24
|
||||
& SG_HIGH_ADDR_BITS),
|
||||
(len >> 24) & SG_HIGH_ADDR_BITS,
|
||||
ahd_le32toh(sg_list[i].addr),
|
||||
ahd_le32toh(sg_list[i].len)
|
||||
& AHD_SG_LEN_MASK);
|
||||
len & AHD_SG_LEN_MASK,
|
||||
len & AHD_DMA_LAST_SEG ? " Last" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2396,9 +2425,9 @@ ahd_update_pending_scbs(struct ahd_softc *ahd)
|
||||
* has already been setup. The negotiation changes may
|
||||
* effect whether we select-out with ATN.
|
||||
*/
|
||||
ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
|
||||
saved_modes = ahd_save_modes(ahd);
|
||||
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
|
||||
ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
|
||||
saved_scbptr = ahd_get_scbptr(ahd);
|
||||
/* Ensure that the hscbs down on the card match the new information */
|
||||
for (i = 0; i < ahd->scb_data.maxhscbs; i++) {
|
||||
@ -2418,7 +2447,7 @@ ahd_update_pending_scbs(struct ahd_softc *ahd)
|
||||
control |= pending_hscb->control & MK_MESSAGE;
|
||||
ahd_outb(ahd, SCB_CONTROL, control);
|
||||
}
|
||||
ahd_set_scbptr(ahd,saved_scbptr);
|
||||
ahd_set_scbptr(ahd, saved_scbptr);
|
||||
ahd_restore_modes(ahd, saved_modes);
|
||||
|
||||
if (paused == 0)
|
||||
@ -4725,6 +4754,10 @@ ahd_setup_iocell_workaround(struct ahd_softc *ahd)
|
||||
ahd_outb(ahd, DSPDATACTL, ahd_inb(ahd, DSPDATACTL)
|
||||
| BYPASSENAB | RCVROFFSTDIS | XMITOFFSTDIS);
|
||||
ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) | (ENSELDO|ENSELDI));
|
||||
#ifdef AHD_DEBUG
|
||||
if ((ahd_debug & AHD_SHOW_MISC) != 0)
|
||||
printf("%s: Setting up iocell workaround\n", ahd_name(ahd));
|
||||
#endif
|
||||
ahd_restore_modes(ahd, saved_modes);
|
||||
}
|
||||
|
||||
@ -4738,9 +4771,17 @@ ahd_iocell_first_selection(struct ahd_softc *ahd)
|
||||
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
|
||||
sblkctl = ahd_inb(ahd, SBLKCTL);
|
||||
ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
|
||||
#ifdef AHD_DEBUG
|
||||
if ((ahd_debug & AHD_SHOW_MISC) != 0)
|
||||
printf("%s: iocell first selection\n", ahd_name(ahd));
|
||||
#endif
|
||||
if ((sblkctl & ENAB40) != 0) {
|
||||
ahd_outb(ahd, DSPDATACTL,
|
||||
ahd_inb(ahd, DSPDATACTL) & ~BYPASSENAB);
|
||||
#ifdef AHD_DEBUG
|
||||
if ((ahd_debug & AHD_SHOW_MISC) != 0)
|
||||
printf("%s: BYPASS now disabled\n", ahd_name(ahd));
|
||||
#endif
|
||||
}
|
||||
ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) & ~(ENSELDO|ENSELDI));
|
||||
ahd_outb(ahd, CLRINT, CLRSCSIINT);
|
||||
@ -5409,7 +5450,11 @@ ahd_chip_init(struct ahd_softc *ahd)
|
||||
ahd_outb(ahd, DFF_THRSH, RD_DFTHRSH_75|WR_DFTHRSH_75);
|
||||
ahd_outb(ahd, SIMODE0, ENIOERR|ENOVERRUN);
|
||||
ahd_outb(ahd, SIMODE3, ENNTRAMPERR|ENOSRAMPERR);
|
||||
ahd_outb(ahd, OPTIONMODE, AUTOACKEN|BUSFREEREV|AUTO_MSGOUT_DE);
|
||||
if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
|
||||
ahd_outb(ahd, OPTIONMODE, AUTOACKEN|AUTO_MSGOUT_DE);
|
||||
} else {
|
||||
ahd_outb(ahd, OPTIONMODE, AUTOACKEN|BUSFREEREV|AUTO_MSGOUT_DE);
|
||||
}
|
||||
if ((ahd->chip & AHD_BUS_MASK) == AHD_PCIX)
|
||||
/*
|
||||
* Do not issue a target abort when a split completion
|
||||
@ -5426,6 +5471,11 @@ ahd_chip_init(struct ahd_softc *ahd)
|
||||
ahd_outb(ahd, DSPSELECT, i);
|
||||
ahd_outb(ahd, WRTBIASCTL, WRTBIASCTL_CPQ_DEFAULT);
|
||||
}
|
||||
#ifdef AHD_DEBUG
|
||||
if ((ahd_debug & AHD_SHOW_MISC) != 0)
|
||||
printf("%s: WRTBIASCTL now 0x%x\n", ahd_name(ahd),
|
||||
WRTBIASCTL_CPQ_DEFAULT);
|
||||
#endif
|
||||
}
|
||||
ahd_setup_iocell_workaround(ahd);
|
||||
|
||||
@ -5460,8 +5510,7 @@ ahd_chip_init(struct ahd_softc *ahd)
|
||||
ahd_outb(ahd, LUNPTR, offsetof(struct hardware_scb, lun));
|
||||
}
|
||||
ahd_outb(ahd, CMDLENPTR, offsetof(struct hardware_scb, cdb_len));
|
||||
ahd_outb(ahd, ATTRPTR,
|
||||
offsetof(struct hardware_scb, task_attribute_nonpkt_tag));
|
||||
ahd_outb(ahd, ATTRPTR, offsetof(struct hardware_scb, task_attribute));
|
||||
ahd_outb(ahd, FLAGPTR, offsetof(struct hardware_scb, task_management));
|
||||
ahd_outb(ahd, CMDPTR, offsetof(struct hardware_scb,
|
||||
shared_data.idata.cdb));
|
||||
@ -5678,6 +5727,7 @@ ahd_default_config(struct ahd_softc *ahd)
|
||||
tinfo->user.offset= ~0;
|
||||
tinfo->user.ppr_options = MSG_EXT_PPR_RD_STRM
|
||||
| MSG_EXT_PPR_WR_FLOW
|
||||
| MSG_EXT_PPR_HOLD_MCS
|
||||
| MSG_EXT_PPR_IU_REQ
|
||||
| MSG_EXT_PPR_QAS_REQ
|
||||
| MSG_EXT_PPR_DT_REQ;
|
||||
@ -5785,6 +5835,7 @@ ahd_parse_cfgdata(struct ahd_softc *ahd, struct seeprom_config *sc)
|
||||
if ((sc->device_flags[targ] & CFPACKETIZED) != 0)
|
||||
user_tinfo->ppr_options |= MSG_EXT_PPR_RD_STRM
|
||||
| MSG_EXT_PPR_WR_FLOW
|
||||
| MSG_EXT_PPR_HOLD_MCS
|
||||
| MSG_EXT_PPR_IU_REQ;
|
||||
|
||||
if ((sc->device_flags[targ] & CFQAS) != 0)
|
||||
@ -6051,12 +6102,11 @@ ahd_resume(struct ahd_softc *ahd)
|
||||
static __inline u_int
|
||||
ahd_index_busy_tcl(struct ahd_softc *ahd, u_int *saved_scbid, u_int tcl)
|
||||
{
|
||||
|
||||
*saved_scbid = ahd_get_scbptr(ahd);
|
||||
|
||||
/*
|
||||
* Index to the SCB that contains the busy entry.
|
||||
*/
|
||||
AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
|
||||
*saved_scbid = ahd_get_scbptr(ahd);
|
||||
ahd_set_scbptr(ahd, TCL_LUN(tcl)
|
||||
| ((TCL_TARGET_OFFSET(tcl) & 0xC) << 4));
|
||||
|
||||
@ -6547,19 +6597,21 @@ int
|
||||
ahd_abort_scbs(struct ahd_softc *ahd, int target, char channel,
|
||||
int lun, u_int tag, role_t role, uint32_t status)
|
||||
{
|
||||
struct scb *scbp;
|
||||
struct scb *scbp_next;
|
||||
u_int active_scb;
|
||||
u_int i, j;
|
||||
u_int maxtarget;
|
||||
u_int minlun;
|
||||
u_int maxlun;
|
||||
struct scb *scbp;
|
||||
struct scb *scbp_next;
|
||||
u_int active_scb;
|
||||
u_int i, j;
|
||||
u_int maxtarget;
|
||||
u_int minlun;
|
||||
u_int maxlun;
|
||||
int found;
|
||||
ahd_mode_state saved_modes;
|
||||
|
||||
int found;
|
||||
|
||||
/* restore this when we're done */
|
||||
/* restore these when we're done */
|
||||
active_scb = ahd_get_scbptr(ahd);
|
||||
saved_modes = ahd_save_modes(ahd);
|
||||
|
||||
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
|
||||
found = ahd_search_qinfifo(ahd, target, channel, lun, SCB_LIST_NULL,
|
||||
role, CAM_REQUEUE_REQ, SEARCH_COMPLETE);
|
||||
|
||||
@ -6628,6 +6680,7 @@ ahd_abort_scbs(struct ahd_softc *ahd, int target, char channel,
|
||||
}
|
||||
}
|
||||
ahd_set_scbptr(ahd, active_scb);
|
||||
ahd_restore_modes(ahd, saved_modes);
|
||||
ahd_platform_abort_scbs(ahd, target, channel, lun, tag, role, status);
|
||||
return found;
|
||||
}
|
||||
@ -6712,10 +6765,8 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
|
||||
do {
|
||||
next_fifo = next_fifo ^ CURRFIFO;
|
||||
ahd_set_modes(ahd, next_fifo, next_fifo);
|
||||
ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) & ~SCSIEN);
|
||||
while ((ahd_inb(ahd, DFCNTRL) & SCSIENACK) != 0)
|
||||
ahd_delay(10);
|
||||
ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) & ~HDMAEN);
|
||||
ahd_outb(ahd, DFCNTRL,
|
||||
ahd_inb(ahd, DFCNTRL) & ~(SCSIEN|HDMAEN));
|
||||
while ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0)
|
||||
ahd_delay(10);
|
||||
/*
|
||||
@ -6729,7 +6780,8 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
|
||||
* Reset the bus if we are initiating this reset
|
||||
*/
|
||||
ahd_clear_msg_state(ahd);
|
||||
ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST));
|
||||
ahd_outb(ahd, SIMODE1,
|
||||
ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE));
|
||||
if (initiate_reset)
|
||||
ahd_reset_current_bus(ahd);
|
||||
ahd_clear_intstat(ahd);
|
||||
@ -6800,7 +6852,7 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
|
||||
/* Notify the XPT that a bus reset occurred */
|
||||
ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD,
|
||||
CAM_LUN_WILDCARD, AC_BUS_RESET, NULL);
|
||||
|
||||
ahd_restart(ahd);
|
||||
/*
|
||||
* Freeze the SIMQ until our poller can determine that
|
||||
* the bus reset has really gone away. We set the initial
|
||||
@ -6812,7 +6864,6 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
|
||||
ahd_freeze_simq(ahd);
|
||||
ahd_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd);
|
||||
}
|
||||
ahd_restart(ahd);
|
||||
return (found);
|
||||
}
|
||||
|
||||
@ -6835,6 +6886,8 @@ ahd_reset_poll(void *arg)
|
||||
}
|
||||
ahd_lock(ahd, &s);
|
||||
ahd_pause(ahd);
|
||||
ahd_update_modes(ahd);
|
||||
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
|
||||
ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);
|
||||
if ((ahd_inb(ahd, SSTAT1) & SCSIRSTI) != 0) {
|
||||
ahd_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_US,
|
||||
@ -7655,6 +7708,7 @@ ahd_dump_card_state(struct ahd_softc *ahd)
|
||||
u_int dffstat;
|
||||
int paused;
|
||||
u_int scb_index;
|
||||
u_int saved_scb_index;
|
||||
u_int i;
|
||||
u_int cur_col;
|
||||
|
||||
@ -7683,6 +7737,7 @@ ahd_dump_card_state(struct ahd_softc *ahd)
|
||||
ahd_seqintctl_print(ahd_inb(ahd, SEQINTCTL), &cur_col, 50);
|
||||
ahd_scsisigi_print(ahd_inb(ahd, SCSISIGI), &cur_col, 50);
|
||||
ahd_scsiphase_print(ahd_inb(ahd, SCSIPHASE), &cur_col, 50);
|
||||
ahd_scsibus_print(ahd_inb(ahd, SCSIBUS), &cur_col, 50);
|
||||
ahd_lastphase_print(ahd_inb(ahd, LASTPHASE), &cur_col, 50);
|
||||
ahd_seq_flags_print(ahd_inb(ahd, SEQ_FLAGS), &cur_col, 50);
|
||||
ahd_seq_flags2_print(ahd_inb(ahd, SEQ_FLAGS2), &cur_col, 50);
|
||||
@ -7691,6 +7746,14 @@ ahd_dump_card_state(struct ahd_softc *ahd)
|
||||
ahd_sstat2_print(ahd_inb(ahd, SSTAT2), &cur_col, 50);
|
||||
ahd_sstat3_print(ahd_inb(ahd, SSTAT3), &cur_col, 50);
|
||||
ahd_perrdiag_print(ahd_inb(ahd, PERRDIAG), &cur_col, 50);
|
||||
ahd_simode1_print(ahd_inb(ahd, SIMODE1), &cur_col, 50);
|
||||
ahd_lqistat0_print(ahd_inb(ahd, LQISTAT0), &cur_col, 50);
|
||||
ahd_lqistat1_print(ahd_inb(ahd, LQISTAT1), &cur_col, 50);
|
||||
ahd_lqistat2_print(ahd_inb(ahd, LQISTAT2), &cur_col, 50);
|
||||
ahd_lqostat0_print(ahd_inb(ahd, LQOSTAT0), &cur_col, 50);
|
||||
ahd_lqostat1_print(ahd_inb(ahd, LQOSTAT1), &cur_col, 50);
|
||||
ahd_lqostat2_print(ahd_inb(ahd, LQOSTAT2), &cur_col, 50);
|
||||
printf("\n");
|
||||
printf("\nSCB Count = %d LASTSCB 0x%x CURRSCB 0x%x NEXTSCB 0x%x\n",
|
||||
ahd->scb_data.numscbs, ahd_inw(ahd, LASTSCB),
|
||||
ahd_inw(ahd, CURRSCB), ahd_inw(ahd, NEXTSCB));
|
||||
@ -7699,17 +7762,17 @@ ahd_dump_card_state(struct ahd_softc *ahd)
|
||||
ahd_search_qinfifo(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,
|
||||
CAM_LUN_WILDCARD, SCB_LIST_NULL,
|
||||
ROLE_UNKNOWN, /*status*/0, SEARCH_PRINT);
|
||||
saved_scb_index = ahd_get_scbptr(ahd);
|
||||
printf("Pending list:");
|
||||
i = 0;
|
||||
LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
|
||||
if (i++ > AHD_SCB_MAX)
|
||||
break;
|
||||
if (scb != LIST_FIRST(&ahd->pending_scbs))
|
||||
printf(", ");
|
||||
cur_col = printf("\n%3d", SCB_GET_TAG(scb));
|
||||
cur_col = printf("\n%3d ", SCB_GET_TAG(scb));
|
||||
ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
|
||||
ahd_scb_control_print(ahd_inb(ahd, SCB_CONTROL), &cur_col, 50);
|
||||
ahd_scb_scsiid_print(ahd_inb(ahd, SCB_SCSIID), &cur_col, 50);
|
||||
ahd_scb_control_print(ahd_inb(ahd, SCB_CONTROL), &cur_col, 60);
|
||||
ahd_scb_scsiid_print(ahd_inb(ahd, SCB_SCSIID), &cur_col, 60);
|
||||
ahd_scb_tag_print(ahd_inb(ahd, SCB_TAG), &cur_col, 60);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
@ -7762,11 +7825,7 @@ ahd_dump_card_state(struct ahd_softc *ahd)
|
||||
scb_index = ahd_inw(ahd, SCB_NEXT_COMPLETE);
|
||||
}
|
||||
printf("\n");
|
||||
cur_col = 0;
|
||||
ahd_simode1_print(ahd_inb(ahd, SIMODE1), &cur_col, 50);
|
||||
ahd_lqistat0_print(ahd_inb(ahd, LQISTAT0), &cur_col, 50);
|
||||
ahd_lqistat1_print(ahd_inb(ahd, LQISTAT1), &cur_col, 50);
|
||||
ahd_lqistat2_print(ahd_inb(ahd, LQISTAT2), &cur_col, 50);
|
||||
ahd_set_scbptr(ahd, saved_scb_index);
|
||||
dffstat = ahd_inb(ahd, DFFSTAT);
|
||||
for (i = 0; i < 2; i++) {
|
||||
#ifdef AHD_DEBUG
|
||||
@ -7775,7 +7834,7 @@ ahd_dump_card_state(struct ahd_softc *ahd)
|
||||
u_int fifo_scbptr;
|
||||
|
||||
ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);
|
||||
fifo_scbptr = ahd_inb(ahd, SCBPTR);
|
||||
fifo_scbptr = ahd_get_scbptr(ahd);
|
||||
printf("\n%s: FIFO%d %s, LONGJMP == 0x%x, "
|
||||
"SCB 0x%x, LJSCB 0x%x\n",
|
||||
ahd_name(ahd), i,
|
||||
@ -7822,7 +7881,7 @@ ahd_dump_card_state(struct ahd_softc *ahd)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
printf("LQIN: ");
|
||||
printf("\nLQIN: ");
|
||||
for (i = 0; i < 20; i++)
|
||||
printf("0x%x ", ahd_inb(ahd, LQIN + i));
|
||||
printf("\n");
|
||||
@ -7861,10 +7920,12 @@ void
|
||||
ahd_dump_scbs(struct ahd_softc *ahd)
|
||||
{
|
||||
ahd_mode_state saved_modes;
|
||||
u_int saved_scb_index;
|
||||
int i;
|
||||
|
||||
saved_modes = ahd_save_modes(ahd);
|
||||
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
|
||||
saved_scb_index = ahd_get_scbptr(ahd);
|
||||
for (i = 0; i < AHD_SCB_MAX; i++) {
|
||||
ahd_set_scbptr(ahd, i);
|
||||
printf("%3d", i);
|
||||
@ -7875,6 +7936,7 @@ ahd_dump_scbs(struct ahd_softc *ahd)
|
||||
ahd_inl(ahd, SCB_RESIDUAL_SGPTR));
|
||||
}
|
||||
printf("\n");
|
||||
ahd_set_scbptr(ahd, saved_scb_index);
|
||||
ahd_restore_modes(ahd, saved_modes);
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#56 $
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#61 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -243,7 +243,11 @@ typedef enum {
|
||||
AHD_AUTOFLUSH_BUG = 0x0200,
|
||||
AHD_CLRLQO_AUTOCLR_BUG = 0x0400,
|
||||
AHD_PKTIZED_STATUS_BUG = 0x0800,
|
||||
AHD_PKT_LUN_BUG = 0x1000
|
||||
AHD_PKT_LUN_BUG = 0x1000,
|
||||
AHD_MDFF_WSCBPTR_BUG = 0x2000,
|
||||
AHD_REG_SLOW_SETTLE_BUG = 0x4000,
|
||||
AHD_SET_MODE_BUG = 0x8000,
|
||||
AHD_BUSFREEREV_BUG = 0x10000
|
||||
} ahd_bug;
|
||||
|
||||
/*
|
||||
@ -409,9 +413,9 @@ struct hardware_scb {
|
||||
* transfer.
|
||||
*/
|
||||
#define SG_PTR_MASK 0xFFFFFFF8
|
||||
/*16*/ uint8_t cdb_len;
|
||||
/*17*/ uint8_t task_management;
|
||||
/*18*/ uint16_t tag;
|
||||
/*16*/ uint16_t tag;
|
||||
/*18*/ uint8_t cdb_len;
|
||||
/*19*/ uint8_t task_management;
|
||||
/*20*/ uint32_t next_hscb_busaddr;
|
||||
/*24*/ uint64_t dataptr;
|
||||
/*32*/ uint32_t datacnt; /* Byte 3 is spare. */
|
||||
@ -422,7 +426,7 @@ struct hardware_scb {
|
||||
* Our Id (bits 0-3) Their ID (bits 4-7)
|
||||
*/
|
||||
/*42*/ uint8_t lun;
|
||||
/*43*/ uint8_t task_attribute_nonpkt_tag;
|
||||
/*43*/ uint8_t task_attribute;
|
||||
/*44*/ uint32_t hscb_busaddr;
|
||||
/******* Long lun field only downloaded for full 8 byte lun support *******/
|
||||
/*48*/ uint8_t pkt_long_lun[8];
|
||||
|
@ -39,7 +39,7 @@
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#39 $"
|
||||
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#45 $"
|
||||
|
||||
/*
|
||||
* This file is processed by the aic7xxx_asm utility for use in assembling
|
||||
@ -56,10 +56,22 @@ VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#39 $"
|
||||
#define M_DST_SHIFT 4
|
||||
|
||||
#define MK_MODE(src, dst) ((src) | ((dst) << M_DST_SHIFT))
|
||||
#define SET_MODE(src, dst) \
|
||||
SET_SRC_MODE src; \
|
||||
SET_DST_MODE dst; \
|
||||
mvi MK_MODE(src, dst) call set_mode_work_around
|
||||
#define SET_MODE(src, dst) \
|
||||
SET_SRC_MODE src; \
|
||||
SET_DST_MODE dst; \
|
||||
if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \
|
||||
mvi MK_MODE(src, dst) call set_mode_work_around; \
|
||||
} else { \
|
||||
mvi MODE_PTR, MK_MODE(src, dst); \
|
||||
}
|
||||
|
||||
#define TOGGLE_DFF_MODE \
|
||||
if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \
|
||||
call toggle_dff_mode_work_around; \
|
||||
} else { \
|
||||
xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Mode Pointer
|
||||
@ -1807,7 +1819,7 @@ register SSTAT1 {
|
||||
* Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT1.
|
||||
*/
|
||||
register CLRSINT1 {
|
||||
address 0x04c
|
||||
address 0x04C
|
||||
access_mode WO
|
||||
modes M_DFF0, M_DFF1, M_SCSI
|
||||
field CLRSELTIMEO 0x80
|
||||
@ -3347,7 +3359,7 @@ scratch_ram {
|
||||
REG1 {
|
||||
size 2
|
||||
}
|
||||
REG2 {
|
||||
REG_ISR {
|
||||
size 2
|
||||
}
|
||||
SG_STATE {
|
||||
@ -3464,8 +3476,8 @@ scratch_ram {
|
||||
SEQ_FLAGS {
|
||||
size 1
|
||||
field NOT_IDENTIFIED 0x80
|
||||
field TARGET_CMD_IS_TAGGED 0x40
|
||||
field NO_CDB_SENT 0x40
|
||||
field TARGET_CMD_IS_TAGGED 0x40
|
||||
field DPHASE 0x20
|
||||
/* Target flags */
|
||||
field TARG_CMD_PENDING 0x10
|
||||
@ -3493,6 +3505,7 @@ scratch_ram {
|
||||
field CDI 0x80
|
||||
field IOI 0x40
|
||||
field MSGI 0x20
|
||||
field P_BUSFREE 0x01
|
||||
enum PHASE_MASK CDO|IOO|MSGO {
|
||||
P_DATAOUT 0x0,
|
||||
P_DATAIN IOO,
|
||||
@ -3501,8 +3514,7 @@ scratch_ram {
|
||||
P_COMMAND CDO,
|
||||
P_MESGOUT CDO|MSGO,
|
||||
P_STATUS CDO|IOO,
|
||||
P_MESGIN CDO|IOO|MSGO,
|
||||
P_BUSFREE 0x01
|
||||
P_MESGIN CDO|IOO|MSGO
|
||||
}
|
||||
}
|
||||
/*
|
||||
@ -3586,10 +3598,14 @@ scratch_ram {
|
||||
|
||||
SEQ_FLAGS2 {
|
||||
size 1
|
||||
field SCB_DMA 0x01
|
||||
field TARGET_MSG_PENDING 0x02
|
||||
field SELECTOUT_QFROZEN 0x04
|
||||
}
|
||||
|
||||
ALLOCFIFO_SCBPTR {
|
||||
size 2
|
||||
}
|
||||
|
||||
/*
|
||||
* Target-mode CDB type to CDB length table used
|
||||
* in non-packetized operation.
|
||||
@ -3636,6 +3652,9 @@ scb {
|
||||
size 4
|
||||
alias SCB_NEXT_COMPLETE
|
||||
}
|
||||
SCB_TAG {
|
||||
size 2
|
||||
}
|
||||
SCB_CDB_LEN {
|
||||
size 1
|
||||
field SCB_CDB_LEN_PTR 0x80 /* CDB in host memory */
|
||||
@ -3643,9 +3662,6 @@ scb {
|
||||
SCB_TASK_MANAGEMENT {
|
||||
size 1
|
||||
}
|
||||
SCB_TAG {
|
||||
size 2
|
||||
}
|
||||
SCB_NEXT {
|
||||
alias SCB_NEXT_SCB_BUSADDR
|
||||
size 2
|
||||
|
@ -40,7 +40,7 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#51 $"
|
||||
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#60 $"
|
||||
PATCH_ARG_LIST = "struct ahd_softc *ahd"
|
||||
PREFIX = "ahd_"
|
||||
|
||||
@ -48,7 +48,7 @@ PREFIX = "ahd_"
|
||||
#include "scsi_message.h"
|
||||
|
||||
idle_loop:
|
||||
SET_MODE(M_SCSI, M_SCSI);
|
||||
SET_MODE(M_SCSI, M_SCSI)
|
||||
test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus;
|
||||
test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz idle_loop_checkbus;
|
||||
cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus;
|
||||
@ -94,14 +94,9 @@ good_status_IU_done:
|
||||
* 2) Configured and draining to the host, no pending CLRCHN.
|
||||
* 3) Pending cfg4data, fifo not empty.
|
||||
*
|
||||
* For case 1, we assume that our DMA post of the completed command
|
||||
* will occur after the FIFO finishes draining due to the higher
|
||||
* priority of data FIFO transfers relative to command channel
|
||||
* transfers.
|
||||
*
|
||||
* Case 2 can be detected by noticing that a longjmp is active for the
|
||||
* FIFO and LONGJMP_SCB matches our SCB. In this case, we allow
|
||||
* the routine servicing the FIFO to complete the SCB.
|
||||
* Cases 1 and 2 can be detected by noticing that a longjmp is
|
||||
* active for the FIFO and LONGJMP_SCB matches our SCB. In this
|
||||
* case, we allow the routine servicing the FIFO to complete the SCB.
|
||||
*
|
||||
* Case 3 implies either a pending or yet to occur save data
|
||||
* pointers for this same context in the other FIFO. So, if
|
||||
@ -123,21 +118,21 @@ BEGIN_CRITICAL;
|
||||
good_status_check_fifos:
|
||||
clc;
|
||||
bmov ARG_1, SCBPTR, 2;
|
||||
SET_MODE(M_DFF0, M_DFF0);
|
||||
SET_MODE(M_DFF0, M_DFF0)
|
||||
call check_fifo;
|
||||
jc idle_loop_service_fifos;
|
||||
SET_MODE(M_DFF1, M_DFF1);
|
||||
SET_MODE(M_DFF1, M_DFF1)
|
||||
call check_fifo;
|
||||
jc idle_loop_service_fifos;
|
||||
SET_MODE(M_SCSI, M_SCSI);
|
||||
SET_MODE(M_SCSI, M_SCSI)
|
||||
call queue_scb_completion;
|
||||
END_CRITICAL;
|
||||
idle_loop_service_fifos:
|
||||
SET_MODE(M_DFF0, M_DFF0);
|
||||
SET_MODE(M_DFF0, M_DFF0)
|
||||
test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo;
|
||||
call longjmp;
|
||||
idle_loop_next_fifo:
|
||||
SET_MODE(M_DFF1, M_DFF1);
|
||||
SET_MODE(M_DFF1, M_DFF1)
|
||||
test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_last_fifo_done;
|
||||
call longjmp;
|
||||
idle_loop_last_fifo_done:
|
||||
@ -145,10 +140,12 @@ idle_loop_last_fifo_done:
|
||||
jmp idle_loop;
|
||||
|
||||
idle_loop_cchan:
|
||||
SET_MODE(M_CCHAN, M_CCHAN);
|
||||
SET_MODE(M_CCHAN, M_CCHAN)
|
||||
BEGIN_CRITICAL;
|
||||
test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle;
|
||||
test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog;
|
||||
test CCSCBCTL, CCSCBDONE jz return;
|
||||
END_CRITICAL;
|
||||
/* FALLTHROUGH */
|
||||
scbdma_tohost_done:
|
||||
test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone;
|
||||
@ -168,6 +165,7 @@ fill_qoutfifo_dmadone:
|
||||
bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4;
|
||||
xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret;
|
||||
|
||||
BEGIN_CRITICAL;
|
||||
fetch_new_scb_inprog:
|
||||
test CCSCBCTL, ARRDONE jz return;
|
||||
fetch_new_scb_done:
|
||||
@ -207,6 +205,7 @@ first_new_scb:
|
||||
bmov WAITING_TID_TAIL, REG0, 2;
|
||||
/* Increment our position in the QINFIFO. */
|
||||
mov NONE, SNSCB_QOFF ret;
|
||||
END_CRITICAL;
|
||||
|
||||
scbdma_idle:
|
||||
/*
|
||||
@ -278,8 +277,7 @@ SET_SRC_MODE M_CCHAN;
|
||||
SET_DST_MODE M_CCHAN;
|
||||
dma_scb:
|
||||
mvi SCBHCNT, SCB_TRANSFER_SIZE;
|
||||
mov CCSCBCTL, SINDEX;
|
||||
or SEQ_FLAGS2, SCB_DMA ret;
|
||||
mov CCSCBCTL, SINDEX ret;
|
||||
|
||||
BEGIN_CRITICAL;
|
||||
setjmp_setscb:
|
||||
@ -299,11 +297,18 @@ END_CRITICAL;
|
||||
* fail to store the new mode value for restoration on
|
||||
* an iret.
|
||||
*/
|
||||
if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) {
|
||||
set_mode_work_around:
|
||||
mvi SEQINTCTL, INTVEC1DSL;
|
||||
mov MODE_PTR, SINDEX;
|
||||
clr SEQINTCTL ret;
|
||||
|
||||
toggle_dff_mode_work_around:
|
||||
mvi SEQINTCTL, INTVEC1DSL;
|
||||
xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
|
||||
clr SEQINTCTL ret;
|
||||
}
|
||||
|
||||
SET_SRC_MODE M_SCSI;
|
||||
SET_DST_MODE M_SCSI;
|
||||
start_selection:
|
||||
@ -361,21 +366,20 @@ allocate_fifo_loop:
|
||||
/*
|
||||
* Do whatever work is required to free a FIFO.
|
||||
*/
|
||||
SET_MODE(M_DFF0, M_DFF0);
|
||||
SET_MODE(M_DFF0, M_DFF0)
|
||||
test LONGJMP_ADDR[1], INVALID_ADDR jnz . + 2;
|
||||
call longjmp;
|
||||
SET_MODE(M_DFF1, M_DFF1);
|
||||
SET_MODE(M_DFF1, M_DFF1)
|
||||
test LONGJMP_ADDR[1], INVALID_ADDR jnz . + 2;
|
||||
call longjmp;
|
||||
SET_MODE(M_SCSI, M_SCSI);
|
||||
SET_MODE(M_SCSI, M_SCSI)
|
||||
allocate_fifo:
|
||||
and A, FIFO0FREE|FIFO1FREE, DFFSTAT;
|
||||
cmp A, FIFO0FREE|FIFO1FREE jne allocate_fifo_loop;
|
||||
take_fifo:
|
||||
bmov ARG_1, SCBPTR, 2;
|
||||
or DFFSTAT, CURRFIFO;
|
||||
SET_MODE(M_DFF1, M_DFF1);
|
||||
bmov SCBPTR, ARG_1, 2 ret;
|
||||
SET_MODE(M_DFF1, M_DFF1)
|
||||
bmov SCBPTR, ALLOCFIFO_SCBPTR, 2 ret;
|
||||
|
||||
/*
|
||||
* We have been reselected as an initiator
|
||||
@ -384,6 +388,17 @@ take_fifo:
|
||||
SET_SRC_MODE M_SCSI;
|
||||
SET_DST_MODE M_SCSI;
|
||||
select_in:
|
||||
if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
|
||||
/*
|
||||
* This exposes a window whereby a
|
||||
* busfree just after a selection will
|
||||
* be missed, but there is not other safe
|
||||
* way to enable busfree detection if
|
||||
* the busfreerev function is broken.
|
||||
*/
|
||||
mvi CLRSINT1,CLRBUSFREE;
|
||||
or SIMODE1, ENBUSFREE;
|
||||
}
|
||||
or SXFRCTL0, SPIOEN;
|
||||
and SAVED_SCSIID, SELID_MASK, SELID;
|
||||
and A, OID, IOWNID;
|
||||
@ -493,7 +508,6 @@ select_out_list_done:
|
||||
*/
|
||||
test SCB_CONTROL, MK_MESSAGE jnz select_out_inc_tid_q;
|
||||
shr DINDEX, 3, SCB_SCSIID;
|
||||
/* XXX When we switch to SCB_SELOID, put +1 in addition below. */
|
||||
or DINDEX, 1; /* Want only the second byte */
|
||||
mvi DINDEX[1], ((WAITING_SCB_TAILS) >> 8);
|
||||
mvi DINDIR, SCB_LIST_NULL;
|
||||
@ -529,6 +543,17 @@ select_out_no_message:
|
||||
select_out_non_packetized:
|
||||
/* Non packetized request. */
|
||||
and SCSISEQ0, ~ENSELO;
|
||||
if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
|
||||
/*
|
||||
* This exposes a window whereby a
|
||||
* busfree just after a selection will
|
||||
* be missed, but there is not other safe
|
||||
* way to enable busfree detection if
|
||||
* the busfreerev function is broken.
|
||||
*/
|
||||
mvi CLRSINT1,CLRBUSFREE;
|
||||
or SIMODE1, ENBUSFREE;
|
||||
}
|
||||
mov SAVED_SCSIID, SCB_SCSIID;
|
||||
mov SAVED_LUN, SCB_LUN;
|
||||
or SXFRCTL0, SPIOEN;
|
||||
@ -576,6 +601,7 @@ SET_DST_MODE M_DFF1;
|
||||
*/
|
||||
mvi DFFSXFRCTL, RSTCHN|CLRSHCNT;
|
||||
p_command_allocate_fifo:
|
||||
bmov ALLOCFIFO_SCBPTR, SCBPTR, 2;
|
||||
call allocate_fifo;
|
||||
add NONE, -17, SCB_CDB_LEN;
|
||||
jnc p_command_embedded;
|
||||
@ -744,13 +770,10 @@ mesgin_done:
|
||||
mov NONE,SCSIDAT; /*dummy read from latch to ACK*/
|
||||
jmp ITloop;
|
||||
|
||||
#define INDEX_DISC_LIST_SCB(scsiid, lun) \
|
||||
#define INDEX_DISC_LIST(scsiid, lun) \
|
||||
and A, 0xC0, scsiid; \
|
||||
or SCBPTR, A, lun; \
|
||||
clr SCBPTR[1]
|
||||
|
||||
#define INDEX_DISC_LIST(scsiid, lun) \
|
||||
INDEX_DISC_LIST_SCB(scsiid, lun); \
|
||||
clr SCBPTR[1]; \
|
||||
and SINDEX, 0x30, scsiid; \
|
||||
shr SINDEX, 3; /* Multiply by 2 */ \
|
||||
add SINDEX, (SCB_DISCONNECTED_LISTS & 0xFF); \
|
||||
@ -819,7 +842,8 @@ setup_SCB:
|
||||
setup_SCB_disconnected:
|
||||
and SCB_CONTROL,~DISCONNECTED;
|
||||
clr SEQ_FLAGS; /* make note of IDENTIFY */
|
||||
test SCB_SGPTR, SG_LIST_NULL jnz . + 2;
|
||||
test SCB_SGPTR, SG_LIST_NULL jnz . + 3;
|
||||
bmov ALLOCFIFO_SCBPTR, SCBPTR, 2;
|
||||
call allocate_fifo;
|
||||
/* See if the host wants to send a message upon reconnection */
|
||||
test SCB_CONTROL, MK_MESSAGE jz mesgin_done;
|
||||
@ -910,7 +934,7 @@ freeze_queue:
|
||||
mov A, ACCUM_SAVE ret;
|
||||
|
||||
queue_arg1_scb_completion:
|
||||
SET_MODE(M_SCSI, M_SCSI);
|
||||
SET_MODE(M_SCSI, M_SCSI)
|
||||
bmov SCBPTR, ARG_1, 2;
|
||||
queue_scb_completion:
|
||||
test SCB_SCSI_STATUS,0xff jnz bad_status;
|
||||
@ -962,8 +986,15 @@ queue_disc_scb:
|
||||
/* FALLTHROUGH */
|
||||
await_busfree:
|
||||
and SIMODE1, ~ENBUSFREE;
|
||||
if ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0) {
|
||||
/*
|
||||
* In the BUSFREEREV_BUG case, the
|
||||
* busfree status was cleared at the
|
||||
* beginning of the connection.
|
||||
*/
|
||||
mvi CLRSINT1,CLRBUSFREE;
|
||||
}
|
||||
mov NONE, SCSIDAT; /* Ack the last byte */
|
||||
call clear_target_state;
|
||||
test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1))
|
||||
jnz await_busfree_not_m_dff;
|
||||
SET_SRC_MODE M_DFF1;
|
||||
@ -971,6 +1002,7 @@ SET_DST_MODE M_DFF1;
|
||||
await_busfree_clrchn:
|
||||
mvi DFFSXFRCTL, CLRCHN;
|
||||
await_busfree_not_m_dff:
|
||||
call clear_target_state;
|
||||
test SSTAT1,REQINIT|BUSFREE jz .;
|
||||
test SSTAT1, BUSFREE jnz idle_loop;
|
||||
mvi SEQINTCODE, MISSED_BUSFREE;
|
||||
@ -1080,20 +1112,19 @@ disable_ccsgen:
|
||||
disable_ccsgen_fetch_done:
|
||||
clr SG_STATE ret;
|
||||
|
||||
toggle_dff_mode:
|
||||
mvi SEQINTCTL, INTVEC1DSL;
|
||||
xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
|
||||
clr SEQINTCTL ret;
|
||||
|
||||
data_group_idle_loop:
|
||||
mov SAVED_MODE, MODE_PTR;
|
||||
test SG_STATE, LOADING_NEEDED jz . + 2;
|
||||
call service_fifo;
|
||||
call toggle_dff_mode;
|
||||
TOGGLE_DFF_MODE
|
||||
test SG_STATE, LOADING_NEEDED jz . + 2;
|
||||
call service_fifo;
|
||||
call idle_loop_cchan;
|
||||
mov SAVED_MODE jmp set_mode_work_around;
|
||||
if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) {
|
||||
mov SAVED_MODE jmp set_mode_work_around;
|
||||
} else {
|
||||
mov MODE_PTR, SAVED_MODE ret;
|
||||
}
|
||||
|
||||
service_fifo:
|
||||
/*
|
||||
@ -1120,8 +1151,16 @@ service_fifo:
|
||||
* set the prefetch amount to a reasonable level if the
|
||||
* cacheline size is unknown.
|
||||
*/
|
||||
mvi SGHCNT, SG_PREFETCH_CNT;
|
||||
and SGHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR;
|
||||
mvi SGHCNT, SG_PREFETCH_CNT;
|
||||
if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) {
|
||||
/*
|
||||
* Need two instruction between "touches" of SGHADDR.
|
||||
* Note the setting of SGHCNT counts as one of
|
||||
* these two instructions.
|
||||
*/
|
||||
nop;
|
||||
}
|
||||
bmov SGHADDR[1], SCB_RESIDUAL_SGPTR[1], 3;
|
||||
mvi CCSGCTL, CCSGEN|SG_CACHE_AVAIL|CCSGRESET;
|
||||
or SG_STATE, FETCH_INPROG ret;
|
||||
@ -1190,12 +1229,12 @@ sg_advance:
|
||||
load_first_seg:
|
||||
bmov HADDR, SCB_DATAPTR, 11;
|
||||
and DATA_COUNT_ODD, 0x1, SCB_DATACNT[0];
|
||||
and REG0, ~SG_FULL_RESID, SCB_SGPTR[0];
|
||||
and REG_ISR, ~SG_FULL_RESID, SCB_SGPTR[0];
|
||||
test SCB_DATACNT[3], SG_LAST_SEG jz . + 2;
|
||||
or REG0, LAST_SEG;
|
||||
or REG_ISR, LAST_SEG;
|
||||
test DATA_COUNT_ODD, 0x1 jz . + 2;
|
||||
or REG0, ODD_SEG;
|
||||
mov SG_CACHE_PRE, REG0;
|
||||
or REG_ISR, ODD_SEG;
|
||||
mov SG_CACHE_PRE, REG_ISR;
|
||||
mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN);
|
||||
/*
|
||||
* Since we've are entering a data phase, we will
|
||||
@ -1225,6 +1264,7 @@ p_data_allowed:
|
||||
*/
|
||||
test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jnz p_data_bitbucket;
|
||||
mvi SEQINTCODE, PDATA_REINIT;
|
||||
jmp data_group_dma_loop;
|
||||
|
||||
p_data_bitbucket:
|
||||
/*
|
||||
@ -1239,12 +1279,13 @@ p_data_bitbucket:
|
||||
* doesn't discard data already in the FIFO.
|
||||
*/
|
||||
mvi DFFSXFRCTL, RSTCHN|CLRSHCNT;
|
||||
SET_MODE(M_SCSI, M_SCSI);
|
||||
SET_MODE(M_SCSI, M_SCSI)
|
||||
bitbucket_not_m_dff:
|
||||
or SXFRCTL1,BITBUCKET;
|
||||
test SCSIPHASE, DATA_PHASE_MASK jnz .;
|
||||
/* Wait for non-data phase. */
|
||||
test SCSIPHASE, ~DATA_PHASE_MASK jz .;
|
||||
and SXFRCTL1, ~BITBUCKET;
|
||||
SET_MODE(M_DFF1, M_DFF1);
|
||||
SET_MODE(M_DFF1, M_DFF1)
|
||||
mvi SEQINTCODE, DATA_OVERRUN;
|
||||
jmp ITloop;
|
||||
|
||||
@ -1327,7 +1368,7 @@ data_phase_done:
|
||||
test DFCNTRL, DIRECTION jz target_ITloop;
|
||||
test SSTAT1, REQINIT jnz .;
|
||||
test DATA_COUNT_ODD, 0x1 jz target_ITloop;
|
||||
SET_MODE(M_SCSI, M_SCSI);
|
||||
SET_MODE(M_SCSI, M_SCSI)
|
||||
test NEGCONOPTS, WIDEXFER jz target_ITloop;
|
||||
*/
|
||||
/*
|
||||
@ -1463,7 +1504,7 @@ cfg4istat_setup_handler:
|
||||
/*
|
||||
* See if the target has gone on in this context creating an
|
||||
* overrun condition. For the write case, the hardware cannot
|
||||
* ack bytes until data is provided. So, if the target begins
|
||||
* ack bytes until data are provided. So, if the target begins
|
||||
* another packet without changing contexts, implying we are
|
||||
* not sitting on a packet boundary, we are in an overrun
|
||||
* situation. For the read case, the hardware will continue to
|
||||
@ -1503,8 +1544,46 @@ pkt_last_seg:
|
||||
test SCSIPHASE, ~DATA_PHASE_MASK jz . + 2;
|
||||
test SCSISIGO, ATNO jnz . + 2;
|
||||
test SSTAT2, NONPACKREQ jz return;
|
||||
test MDFFSTAT, SHVALID jnz pkt_saveptrs;
|
||||
jmp return;
|
||||
test MDFFSTAT, SHVALID jz return;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
/*
|
||||
* Either a SAVEPTRS interrupt condition is pending for this FIFO
|
||||
* or we have a pending nonpackreq for this FIFO. We differentiate
|
||||
* between the two by capturing the state of the SAVEPTRS interrupt
|
||||
* prior to clearing this status and executing the common code for
|
||||
* these two cases.
|
||||
*/
|
||||
pkt_saveptrs:
|
||||
BEGIN_CRITICAL;
|
||||
if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) {
|
||||
or DFCNTRL, FIFOFLUSH;
|
||||
}
|
||||
mov REG0, SEQINTSRC;
|
||||
call calc_residual;
|
||||
call save_pointers;
|
||||
mvi CLRSEQINTSRC, CLRSAVEPTRS;
|
||||
call disable_ccsgen;
|
||||
or SEQIMODE, ENSAVEPTRS;
|
||||
test DFCNTRL, DIRECTION jnz pkt_saveptrs_check_status;
|
||||
test DFSTATUS, FIFOEMP jnz pkt_saveptrs_check_status;
|
||||
/*
|
||||
* Keep a handler around for this FIFO until it drains
|
||||
* to the host to guarantee that we don't complete the
|
||||
* command to the host before the data arrives.
|
||||
*/
|
||||
pkt_saveptrs_wait_fifoemp:
|
||||
call setjmp;
|
||||
test DFSTATUS, FIFOEMP jz return;
|
||||
pkt_saveptrs_check_status:
|
||||
or LONGJMP_ADDR[1], INVALID_ADDR;
|
||||
test REG0, SAVEPTRS jz unexpected_nonpkt_phase;
|
||||
test SCB_CONTROL, STATUS_RCVD jz pkt_saveptrs_clrchn;
|
||||
jmp last_pkt_complete;
|
||||
pkt_saveptrs_clrchn:
|
||||
mvi DFFSXFRCTL, CLRCHN ret;
|
||||
END_CRITICAL;
|
||||
|
||||
last_pkt_done:
|
||||
BEGIN_CRITICAL;
|
||||
if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) {
|
||||
@ -1514,10 +1593,11 @@ BEGIN_CRITICAL;
|
||||
check_overrun;
|
||||
or SCB_SGPTR, SG_LIST_NULL;
|
||||
/*
|
||||
* I think it is safe to skip the FIFO check.
|
||||
* in this case as LAST_SEG_DONE implies
|
||||
* the other FIFO, if ever active for this transfer,
|
||||
* has completed.
|
||||
* It is safe to skip the other FIFO check since
|
||||
* we defer CLRCHN on SAVEPTRS until all data in
|
||||
* the FIFO are seen by the host and a CFG4DATA
|
||||
* in this FIFO for the same context is held off
|
||||
* by hardware.
|
||||
*/
|
||||
last_pkt_queue_scb:
|
||||
or LONGJMP_ADDR[1], INVALID_ADDR;
|
||||
@ -1530,7 +1610,7 @@ last_pkt_complete:
|
||||
mvi DFFSXFRCTL, CLRCHN;
|
||||
check_other_fifo:
|
||||
clc;
|
||||
call toggle_dff_mode;
|
||||
TOGGLE_DFF_MODE
|
||||
call check_fifo;
|
||||
jnc queue_arg1_scb_completion;
|
||||
return:
|
||||
@ -1553,32 +1633,6 @@ BEGIN_CRITICAL;
|
||||
mvi DFFSXFRCTL, CLRCHN ret;
|
||||
END_CRITICAL;
|
||||
|
||||
/*
|
||||
* Either a SAVEPTRS interrupt condition is pending for this FIFO
|
||||
* or we have a pending nonpackreq for this FIFO. We differentiate
|
||||
* between the two by capturing the state of the SAVEPTRS interrupt
|
||||
* prior to clearing and handling the common code of these two cases.
|
||||
*/
|
||||
pkt_saveptrs:
|
||||
BEGIN_CRITICAL;
|
||||
if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) {
|
||||
or DFCNTRL, FIFOFLUSH;
|
||||
}
|
||||
mov REG0, SEQINTSRC;
|
||||
mvi CLRSEQINTSRC, CLRSAVEPTRS;
|
||||
call calc_residual;
|
||||
call save_pointers;
|
||||
call disable_ccsgen;
|
||||
or SEQIMODE, ENSAVEPTRS;
|
||||
or LONGJMP_ADDR[1], INVALID_ADDR;
|
||||
pkt_saveptrs_check_status:
|
||||
test REG0, SAVEPTRS jz unexpected_nonpkt_phase;
|
||||
test SCB_CONTROL, STATUS_RCVD jz pkt_saveptrs_clrchn;
|
||||
jmp last_pkt_complete;
|
||||
pkt_saveptrs_clrchn:
|
||||
mvi DFFSXFRCTL, CLRCHN ret;
|
||||
END_CRITICAL;
|
||||
|
||||
check_status_overrun:
|
||||
test SHCNT[2], 0xFF jz status_IU_done;
|
||||
mvi SEQINTCODE, STATUS_OVERRUN;
|
||||
@ -1657,7 +1711,7 @@ pkt_handle_overrun:
|
||||
mvi SEQINTCODE, CFG4OVERRUN;
|
||||
call freeze_queue;
|
||||
if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0) {
|
||||
SET_MODE(M_SCSI, M_SCSI);
|
||||
SET_MODE(M_SCSI, M_SCSI)
|
||||
or SXFRCTL1,BITBUCKET;
|
||||
SET_SRC_MODE M_DFF1;
|
||||
SET_DST_MODE M_DFF1;
|
||||
|
@ -37,7 +37,7 @@
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#34 $
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#36 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -226,48 +226,6 @@ ahd_unpause(struct ahd_softc *ahd)
|
||||
ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN);
|
||||
}
|
||||
|
||||
/*********************** Untagged Transaction Routines ************************/
|
||||
static __inline void ahd_freeze_untagged_queues(struct ahd_softc *ahd);
|
||||
static __inline void ahd_release_untagged_queues(struct ahd_softc *ahd);
|
||||
|
||||
/*
|
||||
* Block our completion routine from starting the next untagged
|
||||
* transaction for this target or target lun.
|
||||
*/
|
||||
static __inline void
|
||||
ahd_freeze_untagged_queues(struct ahd_softc *ahd)
|
||||
{
|
||||
/*
|
||||
* Assume we have enough space in the card's SCB
|
||||
* to obviate the need for a per target untagged
|
||||
* transaction limit.
|
||||
*/
|
||||
#if 0
|
||||
ahd->untagged_queue_lock++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow the next untagged transaction for this target or target lun
|
||||
* to be executed. We use a counting semaphore to allow the lock
|
||||
* to be acquired recursively. Once the count drops to zero, the
|
||||
* transaction queues will be run.
|
||||
*/
|
||||
static __inline void
|
||||
ahd_release_untagged_queues(struct ahd_softc *ahd)
|
||||
{
|
||||
/*
|
||||
* Assume we have enough space in the card's SCB
|
||||
* to obviate the need for a per target untagged
|
||||
* transaction limit.
|
||||
*/
|
||||
#if 0
|
||||
ahd->untagged_queue_lock--;
|
||||
if (ahd->untagged_queue_lock == 0)
|
||||
ahd_run_untagged_queues(ahd);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************** Scatter Gather List Handling *************************/
|
||||
static __inline void *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
|
||||
void *sgptr, bus_addr_t addr,
|
||||
@ -296,7 +254,7 @@ ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
|
||||
struct ahd_dma_seg *sg;
|
||||
|
||||
sg = (struct ahd_dma_seg *)sgptr;
|
||||
sg->addr = ahd_htole64(addr);
|
||||
sg->addr = ahd_htole32(addr & 0xFFFFFFFF);
|
||||
sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000)
|
||||
| (last ? AHD_DMA_LAST_SEG : 0));
|
||||
return (sg + 1);
|
||||
@ -309,15 +267,12 @@ ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb)
|
||||
/* XXX Handle target mode SCBs. */
|
||||
if ((scb->flags & SCB_PACKETIZED) != 0) {
|
||||
/* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */
|
||||
scb->hscb->task_attribute_nonpkt_tag =
|
||||
scb->hscb->control & SCB_TAG_TYPE;
|
||||
scb->hscb->task_attribute= scb->hscb->control & SCB_TAG_TYPE;
|
||||
scb->hscb->task_management = 0;
|
||||
/*
|
||||
* For Rev A short lun workaround.
|
||||
*/
|
||||
scb->hscb->pkt_long_lun[6] = scb->hscb->lun;
|
||||
} else {
|
||||
scb->hscb->task_attribute_nonpkt_tag = SCB_GET_TAG(scb);
|
||||
}
|
||||
|
||||
if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR
|
||||
@ -783,7 +738,6 @@ ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
|
||||
scb->hscb = q_hscb;
|
||||
|
||||
/* Now define the mapping from tag to SCB in the scbindex */
|
||||
/* XXX This should be constant now. Can we avoid the mapping? */
|
||||
ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#41 $
|
||||
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#44 $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -791,7 +791,9 @@ ahd_aic7902_setup(struct ahd_softc *ahd)
|
||||
| AHD_LQO_ATNO_BUG|AHD_AUTOFLUSH_BUG
|
||||
| AHD_CLRLQO_AUTOCLR_BUG|AHD_PCIX_MMAPIO_BUG
|
||||
| AHD_PCIX_CHIPRST_BUG|AHD_PKTIZED_STATUS_BUG
|
||||
| AHD_PKT_LUN_BUG;
|
||||
| AHD_PKT_LUN_BUG|AHD_MDFF_WSCBPTR_BUG
|
||||
| AHD_REG_SLOW_SETTLE_BUG|AHD_SET_MODE_BUG
|
||||
| AHD_BUSFREEREV_BUG;
|
||||
}
|
||||
|
||||
ahd->channel = ahd_get_pci_function(pci) + 'A';
|
||||
|
Loading…
x
Reference in New Issue
Block a user