Commit e1f5aa3d authored by Justin T. Gibbs's avatar Justin T. Gibbs

Update aic79xx Driver to 1.3.4

 o Fix stray PCI target abort interrupt on startup due to accessing a
   register prior to pausing the controller.
 o Add cfg4icmd implementation.
 o Fix PCI-X issues on rev A hardware due to improper accesses to
   scb ram.
 o Correct a race condition in the error recovery path.
parent 6d1101b3
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES. * POSSIBILITY OF SUCH DAMAGES.
* *
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#81 $ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#85 $
* *
* $FreeBSD$ * $FreeBSD$
*/ */
...@@ -258,27 +258,30 @@ typedef enum { ...@@ -258,27 +258,30 @@ typedef enum {
AHD_PCIX_CHIPRST_BUG = 0x0040, AHD_PCIX_CHIPRST_BUG = 0x0040,
/* MMAPIO is not functional in PCI-X mode. */ /* MMAPIO is not functional in PCI-X mode. */
AHD_PCIX_MMAPIO_BUG = 0x0080, AHD_PCIX_MMAPIO_BUG = 0x0080,
/* Reads to SCBRAM fail to reset the discard timer. */
AHD_PCIX_SCBRAM_RD_BUG = 0x0100,
/* Bug workarounds that can be disabled on non-PCIX busses. */ /* Bug workarounds that can be disabled on non-PCIX busses. */
AHD_PCIX_BUG_MASK = AHD_PCIX_CHIPRST_BUG AHD_PCIX_BUG_MASK = AHD_PCIX_CHIPRST_BUG
| AHD_PCIX_MMAPIO_BUG, | AHD_PCIX_MMAPIO_BUG
| AHD_PCIX_SCBRAM_RD_BUG,
/* /*
* LQOSTOP0 status set even for forced selections with ATN * LQOSTOP0 status set even for forced selections with ATN
* to perform non-packetized message delivery. * to perform non-packetized message delivery.
*/ */
AHD_LQO_ATNO_BUG = 0x0100, AHD_LQO_ATNO_BUG = 0x0200,
/* FIFO auto-flush does not always trigger. */ /* FIFO auto-flush does not always trigger. */
AHD_AUTOFLUSH_BUG = 0x0200, AHD_AUTOFLUSH_BUG = 0x0400,
/* The CLRLQO registers are not self-clearing. */ /* The CLRLQO registers are not self-clearing. */
AHD_CLRLQO_AUTOCLR_BUG = 0x0400, AHD_CLRLQO_AUTOCLR_BUG = 0x0800,
/* The PACKETIZED status bit refers to the previous connection. */ /* The PACKETIZED status bit refers to the previous connection. */
AHD_PKTIZED_STATUS_BUG = 0x0800, AHD_PKTIZED_STATUS_BUG = 0x1000,
/* "Short Luns" are not placed into outgoing LQ packets correctly. */ /* "Short Luns" are not placed into outgoing LQ packets correctly. */
AHD_PKT_LUN_BUG = 0x1000, AHD_PKT_LUN_BUG = 0x2000,
/* /*
* Only the FIFO allocated to the non-packetized connection may * Only the FIFO allocated to the non-packetized connection may
* be in use during a non-packetzied connection. * be in use during a non-packetzied connection.
*/ */
AHD_NONPACKFIFO_BUG = 0x2000, AHD_NONPACKFIFO_BUG = 0x4000,
/* /*
* Writing to a DFF SCBPTR register may fail if concurent with * Writing to a DFF SCBPTR register may fail if concurent with
* a hardware write to the other DFF SCBPTR register. This is * a hardware write to the other DFF SCBPTR register. This is
...@@ -286,40 +289,40 @@ typedef enum { ...@@ -286,40 +289,40 @@ typedef enum {
* this bug have the AHD_NONPACKFIFO_BUG and all writes of concern * this bug have the AHD_NONPACKFIFO_BUG and all writes of concern
* occur in non-packetized connections. * occur in non-packetized connections.
*/ */
AHD_MDFF_WSCBPTR_BUG = 0x4000, AHD_MDFF_WSCBPTR_BUG = 0x8000,
/* SGHADDR updates are slow. */ /* SGHADDR updates are slow. */
AHD_REG_SLOW_SETTLE_BUG = 0x8000, AHD_REG_SLOW_SETTLE_BUG = 0x10000,
/* /*
* Changing the MODE_PTR coincident with an interrupt that * Changing the MODE_PTR coincident with an interrupt that
* switches to a different mode will cause the interrupt to * switches to a different mode will cause the interrupt to
* be in the mode written outside of interrupt context. * be in the mode written outside of interrupt context.
*/ */
AHD_SET_MODE_BUG = 0x10000, AHD_SET_MODE_BUG = 0x20000,
/* Non-packetized busfree revision does not work. */ /* Non-packetized busfree revision does not work. */
AHD_BUSFREEREV_BUG = 0x20000, AHD_BUSFREEREV_BUG = 0x40000,
/* /*
* Paced transfers are indicated with a non-standard PPR * Paced transfers are indicated with a non-standard PPR
* option bit in the neg table, 160MHz is indicated by * option bit in the neg table, 160MHz is indicated by
* sync factor 0x7, and the offset if off by a factor of 2. * sync factor 0x7, and the offset if off by a factor of 2.
*/ */
AHD_PACED_NEGTABLE_BUG = 0x40000, AHD_PACED_NEGTABLE_BUG = 0x80000,
/* LQOOVERRUN false positives. */ /* LQOOVERRUN false positives. */
AHD_LQOOVERRUN_BUG = 0x80000, AHD_LQOOVERRUN_BUG = 0x100000,
/* /*
* Controller write to INTSTAT will lose to a host * Controller write to INTSTAT will lose to a host
* write to CLRINT. * write to CLRINT.
*/ */
AHD_INTCOLLISION_BUG = 0x100000, AHD_INTCOLLISION_BUG = 0x200000,
/* /*
* The GEM318 violates the SCSI spec by not waiting * The GEM318 violates the SCSI spec by not waiting
* the mandated bus settle delay between phase changes * the mandated bus settle delay between phase changes
* in some situations. Some aic79xx chip revs. are more * in some situations. Some aic79xx chip revs. are more
* strict in this regard and will treat REQ assertions * strict in this regard and will treat REQ assertions
* that fall within the bus settle delay window as * that fall within the bus settle delay window as
* glitches. This flag enables causes the firmware * glitches. This flag tells the firmware to tolerate
* to tolerate early REQ assertions. * early REQ assertions.
*/ */
AHD_EARLY_REQ_BUG = 0x200000 AHD_EARLY_REQ_BUG = 0x400000
} ahd_bug; } ahd_bug;
/* /*
...@@ -421,7 +424,10 @@ typedef uint32_t sense_addr_t; ...@@ -421,7 +424,10 @@ typedef uint32_t sense_addr_t;
#define MAX_CDB_LEN 16 #define MAX_CDB_LEN 16
#define MAX_CDB_LEN_WITH_SENSE_ADDR (MAX_CDB_LEN - sizeof(sense_addr_t)) #define MAX_CDB_LEN_WITH_SENSE_ADDR (MAX_CDB_LEN - sizeof(sense_addr_t))
union initiator_data { union initiator_data {
uint64_t cdbptr; struct {
uint64_t cdbptr;
uint8_t cdblen;
} cdb_from_host;
uint8_t cdb[MAX_CDB_LEN]; uint8_t cdb[MAX_CDB_LEN];
struct { struct {
uint8_t cdb[MAX_CDB_LEN_WITH_SENSE_ADDR]; uint8_t cdb[MAX_CDB_LEN_WITH_SENSE_ADDR];
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
* *
* $FreeBSD$ * $FreeBSD$
*/ */
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#61 $" VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#64 $"
/* /*
* This file is processed by the aic7xxx_asm utility for use in assembling * This file is processed by the aic7xxx_asm utility for use in assembling
...@@ -2071,14 +2071,14 @@ register LQIMODE1 { ...@@ -2071,14 +2071,14 @@ register LQIMODE1 {
address 0x051 address 0x051
access_mode RW access_mode RW
modes M_CFG modes M_CFG
field ENLQIPHASE_LQ 0x80 field ENLQIPHASE_LQ 0x80 /* LQIPHASE1 */
field ENLQIPHASE_NLQ 0x40 field ENLQIPHASE_NLQ 0x40 /* LQIPHASE2 */
field ENLIQABORT 0x20 field ENLIQABORT 0x20
field ENLQICRCI_LQ 0x10 field ENLQICRCI_LQ 0x10 /* LQICRCI1 */
field ENLQICRCI_NLQ 0x08 field ENLQICRCI_NLQ 0x08 /* LQICRCI2 */
field ENLQIBADLQI 0x04 field ENLQIBADLQI 0x04
field ENLQIOVERI_LQ 0x02 field ENLQIOVERI_LQ 0x02 /* LQIOVERI1 */
field ENLQIOVERI_NLQ 0x01 field ENLQIOVERI_NLQ 0x01 /* LQIOVERI2 */
} }
/* /*
...@@ -3769,16 +3769,17 @@ scb { ...@@ -3769,16 +3769,17 @@ scb {
SCB_RESIDUAL_DATACNT { SCB_RESIDUAL_DATACNT {
size 4 size 4
alias SCB_CDB_STORE alias SCB_CDB_STORE
alias SCB_HOST_CDB_PTR
} }
SCB_RESIDUAL_SGPTR { SCB_RESIDUAL_SGPTR {
size 4 size 4
alias SCB_CDB_PTR
field SG_ADDR_MASK 0xf8 /* In the last byte */ field SG_ADDR_MASK 0xf8 /* In the last byte */
field SG_OVERRUN_RESID 0x02 /* In the first byte */ field SG_OVERRUN_RESID 0x02 /* In the first byte */
field SG_LIST_NULL 0x01 /* In the first byte */ field SG_LIST_NULL 0x01 /* In the first byte */
} }
SCB_SCSI_STATUS { SCB_SCSI_STATUS {
size 1 size 1
alias SCB_HOST_CDB_LEN
} }
SCB_TARGET_PHASES { SCB_TARGET_PHASES {
size 1 size 1
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
* $FreeBSD$ * $FreeBSD$
*/ */
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#86 $" VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#88 $"
PATCH_ARG_LIST = "struct ahd_softc *ahd" PATCH_ARG_LIST = "struct ahd_softc *ahd"
PREFIX = "ahd_" PREFIX = "ahd_"
...@@ -708,7 +708,7 @@ SET_DST_MODE M_DFF1; ...@@ -708,7 +708,7 @@ SET_DST_MODE M_DFF1;
add NONE, -17, SCB_CDB_LEN; add NONE, -17, SCB_CDB_LEN;
jnc p_command_embedded; jnc p_command_embedded;
p_command_from_host: p_command_from_host:
bmov HADDR[0], SCB_CDB_PTR, 11; bmov HADDR[0], SCB_HOST_CDB_PTR, 9;
mvi SG_CACHE_PRE, LAST_SEG; mvi SG_CACHE_PRE, LAST_SEG;
mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN); mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN);
jmp p_command_xfer; jmp p_command_xfer;
...@@ -1693,6 +1693,18 @@ cfg4istat_no_taskmgmt_func: ...@@ -1693,6 +1693,18 @@ cfg4istat_no_taskmgmt_func:
call pkt_handle_status; call pkt_handle_status;
or SEQINTCTL, IRET ret; or SEQINTCTL, IRET ret;
cfg4icmd_intr:
/*
* In the case of DMAing a CDB from the host, the normal
* CDB buffer is formatted with an 8 byte address followed
* by a 1 byte count.
*/
bmov HADDR[0], SCB_HOST_CDB_PTR, 9;
mvi SG_CACHE_PRE, LAST_SEG;
mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN);
call pkt_handle_cdb;
or SEQINTCTL, IRET ret;
/* /*
* See if the target has gone on in this context creating an * See if the target has gone on in this context creating an
* overrun condition. For the write case, the hardware cannot * overrun condition. For the write case, the hardware cannot
...@@ -1825,13 +1837,15 @@ BEGIN_CRITICAL; ...@@ -1825,13 +1837,15 @@ BEGIN_CRITICAL;
mvi DFFSXFRCTL, CLRCHN ret; mvi DFFSXFRCTL, CLRCHN ret;
END_CRITICAL; END_CRITICAL;
check_status_overrun: /*
test SHCNT[2], 0xFF jz status_IU_done; * Watch over the status transfer. Our host sense buffer is
SET_SEQINTCODE(STATUS_OVERRUN) * large enough to take the maximum allowed status packet.
jmp status_IU_done; * None-the-less, we must still catch and report overruns to
* the host.
*/
pkt_handle_status: pkt_handle_status:
call setjmp_setscb; call setjmp_setscb;
test MDFFSTAT, LASTSDONE jnz check_status_overrun; test SG_CACHE_SHADOW, LAST_SEG_DONE jz check_status_overrun;
test SEQINTSRC, CTXTDONE jz return; test SEQINTSRC, CTXTDONE jz return;
status_IU_done: status_IU_done:
BEGIN_CRITICAL; BEGIN_CRITICAL;
...@@ -1843,6 +1857,21 @@ BEGIN_CRITICAL; ...@@ -1843,6 +1857,21 @@ BEGIN_CRITICAL;
or SCB_CONTROL, STATUS_RCVD; or SCB_CONTROL, STATUS_RCVD;
jmp last_pkt_complete; jmp last_pkt_complete;
END_CRITICAL; END_CRITICAL;
check_status_overrun:
/*
* We've filled the entire sense buffer.
* Wait for either context done or a negative
* shaddow count. If the context completes without
* causing the shaddow count to go negative, then
* this was a successful transfer up to the status
* limit. Otherwise we report the error.
*/
test SHCNT[2], 0xFF jnz report_status_overrun;
test SEQINTSRC, CTXTDONE jz return;
test SHCNT[2], 0xFF jz status_IU_done;
report_status_overrun:
SET_SEQINTCODE(STATUS_OVERRUN)
jmp status_IU_done;
SET_SRC_MODE M_DFF0; SET_SRC_MODE M_DFF0;
SET_DST_MODE M_DFF0; SET_DST_MODE M_DFF0;
...@@ -1856,6 +1885,16 @@ check_fifo: ...@@ -1856,6 +1885,16 @@ check_fifo:
stc ret; stc ret;
END_CRITICAL; END_CRITICAL;
/*
* Must wait until CDB xfer is over before issuing the
* clear channel.
*/
pkt_handle_cdb:
call setjmp_setscb;
test SG_CACHE_SHADOW, LAST_SEG_DONE jz return;
or LONGJMP_ADDR[1], INVALID_ADDR;
mvi DFFSXFRCTL, CLRCHN ret;
/* /*
* Nonpackreq is a polled status. It can come true in three situations: * Nonpackreq is a polled status. It can come true in three situations:
* we have received an L_Q, we have sent one or more L_Qs, or there is no * we have received an L_Q, we have sent one or more L_Qs, or there is no
...@@ -1925,6 +1964,7 @@ pkt_overrun_end: ...@@ -1925,6 +1964,7 @@ pkt_overrun_end:
or SCB_RESIDUAL_SGPTR, SG_OVERRUN_RESID; or SCB_RESIDUAL_SGPTR, SG_OVERRUN_RESID;
test SEQINTSRC, CTXTDONE jz unexpected_nonpkt_phase; test SEQINTSRC, CTXTDONE jz unexpected_nonpkt_phase;
test SCB_CONTROL, STATUS_RCVD jnz last_pkt_queue_scb; test SCB_CONTROL, STATUS_RCVD jnz last_pkt_queue_scb;
or LONGJMP_ADDR[1], INVALID_ADDR;
mvi DFFSXFRCTL, CLRCHN ret; mvi DFFSXFRCTL, CLRCHN ret;
if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) { if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) {
...@@ -1945,5 +1985,3 @@ load_overrun_buf: ...@@ -1945,5 +1985,3 @@ load_overrun_buf:
mvi HCNT[1], ((PKT_OVERRUN_BUFSIZE >> 8) & 0xFF); mvi HCNT[1], ((PKT_OVERRUN_BUFSIZE >> 8) & 0xFF);
clr HCNT[2] ret; clr HCNT[2] ret;
} }
cfg4icmd_intr:
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES. * POSSIBILITY OF SUCH DAMAGES.
* *
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#163 $ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#172 $
* *
* $FreeBSD$ * $FreeBSD$
*/ */
...@@ -406,7 +406,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) ...@@ -406,7 +406,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
u_int i; u_int i;
ahd_set_scbptr(ahd, scbid); ahd_set_scbptr(ahd, scbid);
next_scbid = ahd_inw(ahd, SCB_NEXT_COMPLETE); next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
scb = ahd_lookup_scb(ahd, scbid); scb = ahd_lookup_scb(ahd, scbid);
if (scb == NULL) { if (scb == NULL) {
printf("%s: Warning - DMA-up and complete " printf("%s: Warning - DMA-up and complete "
...@@ -415,7 +415,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) ...@@ -415,7 +415,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
} }
hscb_ptr = (uint8_t *)scb->hscb; hscb_ptr = (uint8_t *)scb->hscb;
for (i = 0; i < sizeof(struct hardware_scb); i++) for (i = 0; i < sizeof(struct hardware_scb); i++)
*hscb_ptr++ = ahd_inb(ahd, SCB_BASE + i); *hscb_ptr++ = ahd_inb_scbram(ahd, SCB_BASE + i);
ahd_complete_scb(ahd, scb); ahd_complete_scb(ahd, scb);
scbid = next_scbid; scbid = next_scbid;
...@@ -426,7 +426,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) ...@@ -426,7 +426,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
while (!SCBID_IS_NULL(scbid)) { while (!SCBID_IS_NULL(scbid)) {
ahd_set_scbptr(ahd, scbid); ahd_set_scbptr(ahd, scbid);
next_scbid = ahd_inw(ahd, SCB_NEXT_COMPLETE); next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
scb = ahd_lookup_scb(ahd, scbid); scb = ahd_lookup_scb(ahd, scbid);
if (scb == NULL) { if (scb == NULL) {
printf("%s: Warning - Complete SCB %d invalid\n", printf("%s: Warning - Complete SCB %d invalid\n",
...@@ -1292,9 +1292,9 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) ...@@ -1292,9 +1292,9 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
scbid = ahd_get_scbptr(ahd); scbid = ahd_get_scbptr(ahd);
scb = ahd_lookup_scb(ahd, scbid); scb = ahd_lookup_scb(ahd, scbid);
if (scb == NULL) { if (scb == NULL) {
printf("%s: Invalid SCB in DFF%d " printf("%s: Invalid SCB %d in DFF%d "
"during unexpected busfree\n", "during unexpected busfree\n",
ahd_name(ahd), mode); ahd_name(ahd), scbid, mode);
packetized = 0; packetized = 0;
} else } else
packetized = (scb->flags & SCB_PACKETIZED) != 0; packetized = (scb->flags & SCB_PACKETIZED) != 0;
...@@ -1667,7 +1667,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime) ...@@ -1667,7 +1667,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
next = SCB_LIST_NULL; next = SCB_LIST_NULL;
} else { } else {
ahd_set_scbptr(ahd, waiting_h); ahd_set_scbptr(ahd, waiting_h);
next = ahd_inw(ahd, SCB_NEXT2); next = ahd_inw_scbram(ahd, SCB_NEXT2);
} }
ahd_set_scbptr(ahd, scbid); ahd_set_scbptr(ahd, scbid);
ahd_outw(ahd, SCB_NEXT2, next); ahd_outw(ahd, SCB_NEXT2, next);
...@@ -1998,7 +1998,8 @@ ahd_handle_proto_violation(struct ahd_softc *ahd) ...@@ -1998,7 +1998,8 @@ ahd_handle_proto_violation(struct ahd_softc *ahd)
if ((seq_flags & NO_CDB_SENT) != 0) { if ((seq_flags & NO_CDB_SENT) != 0) {
ahd_print_path(ahd, scb); ahd_print_path(ahd, scb);
printf("No or incomplete CDB sent to device.\n"); printf("No or incomplete CDB sent to device.\n");
} else if ((ahd_inb(ahd, SCB_CONTROL) & STATUS_RCVD) == 0) { } else if ((ahd_inb_scbram(ahd, SCB_CONTROL)
& STATUS_RCVD) == 0) {
/* /*
* The target never bothered to provide status to * The target never bothered to provide status to
* us prior to completing the command. Since we don't * us prior to completing the command. Since we don't
...@@ -2615,8 +2616,12 @@ ahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ...@@ -2615,8 +2616,12 @@ ahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
ahd_name(ahd), devinfo->target, ahd_name(ahd), devinfo->target,
period, offset); period, offset);
options = 0; options = 0;
if ((ppr_options & MSG_EXT_PPR_RD_STRM) != 0) {
printf("(RDSTRM");
options++;
}
if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) { if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {
printf("(DT"); printf("%s", options ? "|DT" : "(DT");
options++; options++;
} }
if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
...@@ -4990,6 +4995,8 @@ ahd_reset(struct ahd_softc *ahd) ...@@ -4990,6 +4995,8 @@ ahd_reset(struct ahd_softc *ahd)
* to disturb the integrity of the bus. * to disturb the integrity of the bus.
*/ */
ahd_pause(ahd); ahd_pause(ahd);
ahd_update_modes(ahd);
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
sxfrctl1 = ahd_inb(ahd, SXFRCTL1); sxfrctl1 = ahd_inb(ahd, SXFRCTL1);
cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);
...@@ -5038,13 +5045,16 @@ ahd_reset(struct ahd_softc *ahd) ...@@ -5038,13 +5045,16 @@ ahd_reset(struct ahd_softc *ahd)
ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
cmd, /*bytes*/2); cmd, /*bytes*/2);
} }
/* After a reset, we know the state of the mode register. */
ahd_known_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
/* Determine chip configuration */ /*
ahd->features &= ~AHD_WIDE; * Mode should be SCSI after a chip reset, but lets
if ((ahd_inb(ahd, SBLKCTL) & SELWIDE) != 0) * set it just to be safe. We touch the MODE_PTR
ahd->features |= AHD_WIDE; * register directly so as to bypass the lazy update
* code in ahd_set_modes().
*/
ahd_known_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
ahd_outb(ahd, MODE_PTR,
ahd_build_mode_state(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI));
/* /*
* Restore SXFRCTL1. * Restore SXFRCTL1.
...@@ -5057,6 +5067,11 @@ ahd_reset(struct ahd_softc *ahd) ...@@ -5057,6 +5067,11 @@ ahd_reset(struct ahd_softc *ahd)
ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN); ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN);
ahd_outb(ahd, SXFRCTL1, sxfrctl1); ahd_outb(ahd, SXFRCTL1, sxfrctl1);
/* Determine chip configuration */
ahd->features &= ~AHD_WIDE;
if ((ahd_inb(ahd, SBLKCTL) & SELWIDE) != 0)
ahd->features |= AHD_WIDE;
/* /*
* If a recovery action has forced a chip reset, * If a recovery action has forced a chip reset,
* re-initialize the chip to our liking. * re-initialize the chip to our liking.
...@@ -5803,7 +5818,9 @@ ahd_init(struct ahd_softc *ahd) ...@@ -5803,7 +5818,9 @@ ahd_init(struct ahd_softc *ahd)
/* DMA tag for mapping buffers into device visible space. */ /* DMA tag for mapping buffers into device visible space. */
if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
/*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
/*lowaddr*/BUS_SPACE_MAXADDR, /*lowaddr*/ahd->flags & AHD_39BIT_ADDRESSING
? (bus_addr_t)0x7FFFFFFFFFULL
: BUS_SPACE_MAXADDR_32BIT,
/*highaddr*/BUS_SPACE_MAXADDR, /*highaddr*/BUS_SPACE_MAXADDR,
/*filter*/NULL, /*filterarg*/NULL, /*filter*/NULL, /*filterarg*/NULL,
/*maxsize*/(AHD_NSEG - 1) * PAGE_SIZE, /*maxsize*/(AHD_NSEG - 1) * PAGE_SIZE,
...@@ -7683,7 +7700,6 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) ...@@ -7683,7 +7700,6 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
{ {
struct hardware_scb *hscb; struct hardware_scb *hscb;
u_int qfreeze_cnt; u_int qfreeze_cnt;
ahd_mode_state saved_modes;
/* /*
* The sequencer freezes its select-out queue * The sequencer freezes its select-out queue
...@@ -7695,7 +7711,6 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) ...@@ -7695,7 +7711,6 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
/* Freeze the queue until the client sees the error. */ /* Freeze the queue until the client sees the error. */
ahd_pause(ahd); ahd_pause(ahd);
saved_modes = ahd_save_modes(ahd);
ahd_clear_critical_section(ahd); ahd_clear_critical_section(ahd);
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
ahd_freeze_devq(ahd, scb); ahd_freeze_devq(ahd, scb);
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES. * POSSIBILITY OF SUCH DAMAGES.
* *
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#42 $ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#44 $
* *
* $FreeBSD$ * $FreeBSD$
*/ */
...@@ -678,7 +678,8 @@ ahd_inb_scbram(struct ahd_softc *ahd, u_int offset) ...@@ -678,7 +678,8 @@ ahd_inb_scbram(struct ahd_softc *ahd, u_int offset)
* Razor #528 * Razor #528
*/ */
value = ahd_inb(ahd, offset); value = ahd_inb(ahd, offset);
ahd_inb(ahd, MODE_PTR); if ((ahd->flags & AHD_PCIX_SCBRAM_RD_BUG) != 0)
ahd_inb(ahd, MODE_PTR);
return (value); return (value);
} }
......
/* /*
* Adaptec AIC79xx device driver for Linux. * Adaptec AIC79xx device driver for Linux.
* *
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#124 $ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#128 $
* *
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Copyright (c) 1994-2000 Justin T. Gibbs. * Copyright (c) 1994-2000 Justin T. Gibbs.
...@@ -1462,14 +1462,14 @@ ahd_linux_abort(Scsi_Cmnd *cmd) ...@@ -1462,14 +1462,14 @@ ahd_linux_abort(Scsi_Cmnd *cmd)
struct timer_list timer; struct timer_list timer;
int ret; int ret;
ahd->platform_data->flags |= AHD_UP_EH_SEMAPHORE; pending_scb->platform_data->flags |= AHD_SCB_UP_EH_SEM;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
ahd_unlock(ahd, &s); ahd_unlock(ahd, &s);
#else #else
spin_unlock_irq(ahd->platform_data->host->host_lock); spin_unlock_irq(ahd->platform_data->host->host_lock);
#endif #endif
init_timer(&timer); init_timer(&timer);
timer.data = (u_long)ahd; timer.data = (u_long)pending_scb;
timer.expires = jiffies + (5 * HZ); timer.expires = jiffies + (5 * HZ);
timer.function = ahd_linux_sem_timeout; timer.function = ahd_linux_sem_timeout;
add_timer(&timer); add_timer(&timer);
...@@ -1583,14 +1583,14 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd) ...@@ -1583,14 +1583,14 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd)
LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links); LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
ahd_queue_scb(ahd, scb); ahd_queue_scb(ahd, scb);
ahd->platform_data->flags |= AHD_UP_EH_SEMAPHORE; scb->platform_data->flags |= AHD_SCB_UP_EH_SEM;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
ahd_unlock(ahd, &s); ahd_unlock(ahd, &s);
#else #else
spin_unlock_irq(ahd->platform_data->host->host_lock); spin_unlock_irq(ahd->platform_data->host->host_lock);
#endif #endif
init_timer(&timer); init_timer(&timer);
timer.data = (u_long)ahd; timer.data = (u_long)scb;
timer.expires = jiffies + (5 * HZ); timer.expires = jiffies + (5 * HZ);
timer.function = ahd_linux_sem_timeout; timer.function = ahd_linux_sem_timeout;
add_timer(&timer); add_timer(&timer);
...@@ -1697,7 +1697,7 @@ Scsi_Host_Template aic79xx_driver_template = { ...@@ -1697,7 +1697,7 @@ Scsi_Host_Template aic79xx_driver_template = {
.max_sectors = 8192, .max_sectors = 8192,
#endif #endif
#if defined CONFIG_HIGHIO || LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #if defined CONFIG_HIGHIO || LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10)
/* Assume RedHat Distribution with its different HIGHIO conventions. */ /* Assume RedHat Distribution with its different HIGHIO conventions. */
.can_dma_32 = 1, .can_dma_32 = 1,
.single_sg_okay = 1, .single_sg_okay = 1,
...@@ -3050,6 +3050,7 @@ ahd_linux_dv_target(struct ahd_softc *ahd, u_int target_offset) ...@@ -3050,6 +3050,7 @@ ahd_linux_dv_target(struct ahd_softc *ahd, u_int target_offset)
} }
case AHD_DV_STATE_TUR: case AHD_DV_STATE_TUR:
case AHD_DV_STATE_BUSY: case AHD_DV_STATE_BUSY:
timeout = 5 * HZ;
ahd_linux_dv_tur(ahd, cmd, &devinfo); ahd_linux_dv_tur(ahd, cmd, &devinfo);
break; break;
case AHD_DV_STATE_REBD: case AHD_DV_STATE_REBD:
...@@ -4776,8 +4777,8 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb) ...@@ -4776,8 +4777,8 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
if (ahd_get_transaction_status(scb) == CAM_BDR_SENT if (ahd_get_transaction_status(scb) == CAM_BDR_SENT
|| ahd_get_transaction_status(scb) == CAM_REQ_ABORTED) || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED)
ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
if ((ahd->platform_data->flags & AHD_UP_EH_SEMAPHORE) != 0) { if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
ahd->platform_data->flags &= ~AHD_UP_EH_SEMAPHORE; scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
up(&ahd->platform_data->eh_sem); up(&ahd->platform_data->eh_sem);
} }
} }
...@@ -5279,13 +5280,15 @@ ahd_release_simq(struct ahd_softc *ahd) ...@@ -5279,13 +5280,15 @@ ahd_release_simq(struct ahd_softc *ahd)
static void static void
ahd_linux_sem_timeout(u_long arg) ahd_linux_sem_timeout(u_long arg)
{ {
struct scb *scb;
struct ahd_softc *ahd; struct ahd_softc *ahd;
u_long s; u_long s;
ahd = (struct ahd_softc *)arg; scb = (struct scb *)arg;
ahd = scb->ahd_softc;
ahd_lock(ahd, &s); ahd_lock(ahd, &s);
if ((ahd->platform_data->flags & AHD_UP_EH_SEMAPHORE) != 0) { if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
ahd->platform_data->flags &= ~AHD_UP_EH_SEMAPHORE; scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
up(&ahd->platform_data->eh_sem); up(&ahd->platform_data->eh_sem);
} }
ahd_unlock(ahd, &s); ahd_unlock(ahd, &s);
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES. * POSSIBILITY OF SUCH DAMAGES.
* *
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#113 $ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#117 $
* *
*/ */
#ifndef _AIC79XX_LINUX_H_ #ifndef _AIC79XX_LINUX_H_
...@@ -286,7 +286,7 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec) ...@@ -286,7 +286,7 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec)
#include <linux/smp.h> #include <linux/smp.h>
#endif #endif
#define AIC79XX_DRIVER_VERSION "1.3.2" #define AIC79XX_DRIVER_VERSION "1.3.4"
/**************************** Front End Queues ********************************/ /**************************** Front End Queues ********************************/
/* /*
...@@ -487,7 +487,7 @@ struct ahd_linux_target { ...@@ -487,7 +487,7 @@ struct ahd_linux_target {
* Per-SCB OSM storage. * Per-SCB OSM storage.
*/ */
typedef enum { typedef enum {
AHD_UP_EH_SEMAPHORE = 0x1 AHD_SCB_UP_EH_SEM = 0x1
} ahd_linux_scb_flags; } ahd_linux_scb_flags;
struct scb_platform_data { struct scb_platform_data {
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES. * POSSIBILITY OF SUCH DAMAGES.
* *
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#66 $ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#67 $
* *
* $FreeBSD$ * $FreeBSD$
*/ */
...@@ -385,12 +385,10 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) ...@@ -385,12 +385,10 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
int int
ahd_pci_test_register_access(struct ahd_softc *ahd) ahd_pci_test_register_access(struct ahd_softc *ahd)
{ {
ahd_mode_state saved_modes;
uint32_t cmd; uint32_t cmd;
int error; int error;
uint8_t hcntrl; uint8_t hcntrl;
saved_modes = ahd_save_modes(ahd);
error = EIO; error = EIO;
/* /*
...@@ -456,7 +454,6 @@ ahd_pci_test_register_access(struct ahd_softc *ahd) ...@@ -456,7 +454,6 @@ ahd_pci_test_register_access(struct ahd_softc *ahd)
ahd_outb(ahd, CLRINT, CLRPCIINT); ahd_outb(ahd, CLRINT, CLRPCIINT);
} }
ahd_restore_modes(ahd, saved_modes);
ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS); ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS);
ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);
return (error); return (error);
...@@ -886,11 +883,11 @@ ahd_aic7902_setup(struct ahd_softc *ahd) ...@@ -886,11 +883,11 @@ ahd_aic7902_setup(struct ahd_softc *ahd)
| AHD_NLQICRC_DELAYED_BUG|AHD_SCSIRST_BUG | AHD_NLQICRC_DELAYED_BUG|AHD_SCSIRST_BUG
| AHD_LQO_ATNO_BUG|AHD_AUTOFLUSH_BUG | AHD_LQO_ATNO_BUG|AHD_AUTOFLUSH_BUG
| AHD_CLRLQO_AUTOCLR_BUG|AHD_PCIX_MMAPIO_BUG | AHD_CLRLQO_AUTOCLR_BUG|AHD_PCIX_MMAPIO_BUG
| AHD_PCIX_CHIPRST_BUG|AHD_PKTIZED_STATUS_BUG | AHD_PCIX_CHIPRST_BUG|AHD_PCIX_SCBRAM_RD_BUG
| AHD_PKT_LUN_BUG|AHD_MDFF_WSCBPTR_BUG | AHD_PKTIZED_STATUS_BUG|AHD_PKT_LUN_BUG
| AHD_REG_SLOW_SETTLE_BUG|AHD_SET_MODE_BUG | AHD_MDFF_WSCBPTR_BUG|AHD_REG_SLOW_SETTLE_BUG
| AHD_BUSFREEREV_BUG|AHD_NONPACKFIFO_BUG | AHD_SET_MODE_BUG|AHD_BUSFREEREV_BUG
| AHD_PACED_NEGTABLE_BUG; | AHD_NONPACKFIFO_BUG|AHD_PACED_NEGTABLE_BUG;
/* /*
* IO Cell paramter setup. * IO Cell paramter setup.
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* String handling code courtesy of Gerard Roudier's <groudier@club-internet.fr> * String handling code courtesy of Gerard Roudier's <groudier@club-internet.fr>
* sym driver. * sym driver.
* *
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#12 $ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#13 $
*/ */
#include "aic79xx_osm.h" #include "aic79xx_osm.h"
#include "aic79xx_inline.h" #include "aic79xx_inline.h"
...@@ -124,8 +124,12 @@ ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo) ...@@ -124,8 +124,12 @@ ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo)
printed_options = 0; printed_options = 0;
copy_info(info, " (%d.%03dMHz", freq / 1000, freq % 1000); copy_info(info, " (%d.%03dMHz", freq / 1000, freq % 1000);
if ((tinfo->ppr_options & MSG_EXT_PPR_RD_STRM) != 0) {
copy_info(info, " RDSTRM");
printed_options++;
}
if ((tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0) { if ((tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {
copy_info(info, " DT"); copy_info(info, "%s", printed_options ? "|DT" : " DT");
printed_options++; printed_options++;
} }
if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated * DO NOT EDIT - This file is automatically generated
* from the following source files: * from the following source files:
* *
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#86 $ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#87 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#61 $ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#62 $
*/ */
typedef int (ahd_reg_print_t)(u_int, u_int *, u_int); typedef int (ahd_reg_print_t)(u_int, u_int *, u_int);
typedef struct ahd_reg_parse_entry { typedef struct ahd_reg_parse_entry {
...@@ -3638,13 +3638,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; ...@@ -3638,13 +3638,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SCB_RESIDUAL_DATACNT 0x180 #define SCB_RESIDUAL_DATACNT 0x180
#define SCB_CDB_STORE 0x180 #define SCB_CDB_STORE 0x180
#define SCB_HOST_CDB_PTR 0x180
#define SCB_RESIDUAL_SGPTR 0x184 #define SCB_RESIDUAL_SGPTR 0x184
#define SCB_CDB_PTR 0x184
#define SG_ADDR_MASK 0xf8 #define SG_ADDR_MASK 0xf8
#define SG_OVERRUN_RESID 0x02 #define SG_OVERRUN_RESID 0x02
#define SCB_SCSI_STATUS 0x188 #define SCB_SCSI_STATUS 0x188
#define SCB_HOST_CDB_LEN 0x188
#define SCB_TARGET_PHASES 0x189 #define SCB_TARGET_PHASES 0x189
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated * DO NOT EDIT - This file is automatically generated
* from the following source files: * from the following source files:
* *
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#86 $ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#87 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#61 $ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#62 $
*/ */
#include "aic79xx_osm.h" #include "aic79xx_osm.h"
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment