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

Merge http://linux.bkbits.net/linux-2.5

into overdrive.btc.adaptec.com:/usr/home/gibbs/bk/linux-2.5
parents bcd8c64b 59b52f22
......@@ -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/aic7770.c#29 $
* $Id: //depot/aic7xxx/aic7xxx/aic7770.c#30 $
*
* $FreeBSD$
*/
......@@ -314,7 +314,7 @@ aha2840_load_seeprom(struct ahc_softc *ahc)
if (bootverbose)
printf("%s: Reading SEEPROM...", ahc_name(ahc));
have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc,
/*start_addr*/0, sizeof(sc)/2);
/*start_addr*/0, sizeof(*sc)/2);
if (have_seeprom) {
......
......@@ -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#88 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#89 $
*
* $FreeBSD$
*/
......@@ -494,13 +494,11 @@ struct hardware_scb {
* transfer.
*/
#define SG_PTR_MASK 0xFFFFFFF8
/*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. */
/*36*/ uint32_t sgptr;
/*16*/ uint64_t dataptr;
/*24*/ uint32_t datacnt; /* Byte 3 is spare. */
/*28*/ uint32_t sgptr;
/*32*/ uint32_t hscb_busaddr;
/*36*/ uint32_t next_hscb_busaddr;
/*40*/ uint8_t control; /* See SCB_CONTROL in aic79xx.reg for details */
/*41*/ uint8_t scsiid; /*
* Selection out Id
......@@ -508,8 +506,10 @@ struct hardware_scb {
*/
/*42*/ uint8_t lun;
/*43*/ uint8_t task_attribute;
/*44*/ uint32_t hscb_busaddr;
/******* Long lun field only downloaded for full 8 byte lun support *******/
/*44*/ uint8_t cdb_len;
/*45*/ uint8_t task_management;
/*46*/ uint16_t tag; /* Reused by Sequencer. */
/********** Long lun field only downloaded for full 8 byte lun support ********/
/*48*/ uint8_t pkt_long_lun[8];
/******* Fields below are not Downloaded (Sequencer may use for scratch) ******/
/*56*/ uint8_t spare[8];
......
......@@ -39,7 +39,7 @@
*
* $FreeBSD$
*/
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#65 $"
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#67 $"
/*
* This file is processed by the aic7xxx_asm utility for use in assembling
......@@ -194,7 +194,8 @@ register SEQINTCODE {
TRACEPOINT1,
TRACEPOINT2,
TRACEPOINT3,
SAW_HWERR
SAW_HWERR,
BAD_SCB_STATUS
}
}
......@@ -3484,9 +3485,6 @@ scratch_ram {
LONGJMP_ADDR {
size 2
}
LONGJMP_SCB {
size 2
}
ACCUM_SAVE {
size 1
}
......@@ -3799,23 +3797,6 @@ 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 */
}
SCB_TASK_MANAGEMENT {
size 1
}
SCB_NEXT {
alias SCB_NEXT_SCB_BUSADDR
size 2
}
SCB_NEXT2 {
size 2
}
SCB_DATAPTR {
size 8
}
......@@ -3834,6 +3815,16 @@ scb {
field SG_FULL_RESID 0x02 /* In the first byte */
field SG_LIST_NULL 0x01 /* In the first byte */
}
SCB_BUSADDR {
size 4
}
SCB_NEXT {
alias SCB_NEXT_SCB_BUSADDR
size 2
}
SCB_NEXT2 {
size 2
}
SCB_CONTROL {
size 1
field TARGET_SCB 0x80
......@@ -3856,8 +3847,16 @@ scb {
SCB_TASK_ATTRIBUTE {
size 1
}
SCB_BUSADDR {
size 4
SCB_CDB_LEN {
size 1
field SCB_CDB_LEN_PTR 0x80 /* CDB in host memory */
}
SCB_TASK_MANAGEMENT {
size 1
}
SCB_TAG {
alias SCB_FIFO_USE_COUNT
size 2
}
SCB_SPARE {
size 8
......
......@@ -40,7 +40,7 @@
* $FreeBSD$
*/
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#89 $"
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#91 $"
PATCH_ARG_LIST = "struct ahd_softc *ahd"
PREFIX = "ahd_"
......@@ -108,8 +108,8 @@ idle_loop_gsfifo_in_scsi_mode:
test LQISTAT2, LQIGSAVAIL jz return;
/*
* We have received good status for this transaction. There may
* still be data in our FIFOs draining to the host. Setup
* monitoring of the draining process or complete the SCB.
* still be data in our FIFOs draining to the host. Complete
* the SCB only if all data has transferred to the host.
*/
good_status_IU_done:
bmov SCBPTR, GSFIFO, 2;
......@@ -135,42 +135,20 @@ gsfifo_complete_normally:
* 1) Configured and draining to the host, with a FIFO handler.
* 2) Pending cfg4data, fifo not empty.
*
* Case 1 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 1 can be detected by noticing a non-zero FIFO active
* count in the SCB. In this case, we allow the routine servicing
* the FIFO to complete the SCB.
*
* Case 2 implies either a pending or yet to occur save data
* pointers for this same context in the other FIFO. So, if
* we detect case 1, we will properly defer the post of the SCB
* and achieve the desired result. The pending cfg4data will
* notice that status has been received and complete the SCB.
*
* If the data-transfer has been completed, or no data transfer
* was needed for this SCB, it is safe to complete the command.
*/
test SCB_SGPTR, SG_LIST_NULL jz good_status_check_fifos;
/*
* All segments have been loaded (or no data transfer), so
* it is safe to complete the command. Since this was a
* cheap command to check for completion, loop to see if
* more entries can be removed from the GSFIFO.
*/
test SCB_FIFO_USE_COUNT, 0xFF jnz idle_loop_gsfifo_in_scsi_mode;
call complete;
END_CRITICAL;
jmp idle_loop_gsfifo_in_scsi_mode;
BEGIN_CRITICAL;
good_status_check_fifos:
clc;
bmov ARG_1, SCBPTR, 2;
SET_MODE(M_DFF0, M_DFF0)
call check_fifo;
jc return;
SET_MODE(M_DFF1, M_DFF1)
call check_fifo;
jc return;
SET_MODE(M_SCSI, M_SCSI)
jmp queue_scb_completion;
END_CRITICAL;
idle_loop_service_fifos:
SET_MODE(M_DFF0, M_DFF0)
......@@ -179,6 +157,7 @@ idle_loop_service_fifos:
idle_loop_next_fifo:
SET_MODE(M_DFF1, M_DFF1)
test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp;
return:
ret;
idle_loop_cchan:
......@@ -196,12 +175,31 @@ END_CRITICAL;
scbdma_tohost_done:
test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone;
/*
* A complete SCB upload requires no intervention.
* The SCB is already on the COMPLETE_SCB list
* and its completion notification will now be
* handled just like any other SCB.
* An SCB has been succesfully uploaded to the host.
* If the SCB was uploaded for some reason other than
* bad SCSI status (currently only for underruns), we
* queue the SCB for normal completion. Otherwise, we
* wait until any select-out activity has halted, and
* then notify the host so that the transaction can be
* dealt with.
*/
and CCSCBCTL, ~(CCARREN|CCSCBEN) ret;
test SCB_SCSI_STATUS, 0xff jnz scbdma_notify_host;
and CCSCBCTL, ~(CCARREN|CCSCBEN);
bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
scbdma_notify_host:
SET_MODE(M_SCSI, M_SCSI)
test SCSISEQ0, ENSELO jnz return;
test SSTAT0, (SELDO|SELINGO) jnz return;
SET_MODE(M_CCHAN, M_CCHAN)
/*
* Remove SCB and notify host.
*/
and CCSCBCTL, ~(CCARREN|CCSCBEN);
bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
SET_SEQINTCODE(BAD_SCB_STATUS)
ret;
fill_qoutfifo_dmadone:
and CCSCBCTL, ~(CCARREN|CCSCBEN);
call qoutfifo_updated;
......@@ -263,6 +261,13 @@ fetch_new_scb_done:
clr A;
add CMDS_PENDING, 1;
adc CMDS_PENDING[1], A;
/*
* The FIFO use count field is shared with the
* tag set by the host so that our SCB dma engine
* knows the correct location to store the SCB.
* Set it to zero before processing the SCB.
*/
mov SCB_FIFO_USE_COUNT, ALLZEROS;
/* Update the next SCB address to download. */
bmov NEXT_QUEUED_SCB_ADDR, SCB_NEXT_SCB_BUSADDR, 4;
mvi SCB_NEXT[1], SCB_LIST_NULL;
......@@ -339,15 +344,7 @@ fetch_new_scb:
dma_complete_scb:
bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2;
bmov SCBHADDR, SCB_BUSADDR, 4;
mvi CCARREN|CCSCBEN|CCSCBRESET call dma_scb;
/*
* Now that we've started the DMA, push us onto
* the normal completion queue to have our SCBID
* posted to the kernel.
*/
bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb;
END_CRITICAL;
/*
......@@ -366,8 +363,6 @@ dma_scb:
mov CCSCBCTL, SINDEX ret;
BEGIN_CRITICAL;
setjmp_setscb:
bmov LONGJMP_SCB, SCBPTR, 2;
setjmp:
bmov LONGJMP_ADDR, STACK, 2 ret;
setjmp_inline:
......@@ -1035,9 +1030,18 @@ freeze_queue:
or SEQ_FLAGS2, SELECTOUT_QFROZEN;
mov A, ACCUM_SAVE ret;
queue_arg1_scb_completion:
/*
* Complete the current FIFO's SCB if data for this same
* SCB is not transferring in the other FIFO.
*/
SET_SRC_MODE M_DFF1;
SET_DST_MODE M_DFF1;
pkt_complete_scb_if_fifos_idle:
bmov ARG_1, SCBPTR, 2;
mvi DFFSXFRCTL, CLRCHN;
SET_MODE(M_SCSI, M_SCSI)
bmov SCBPTR, ARG_1, 2;
test SCB_FIFO_USE_COUNT, 0xFF jnz return;
queue_scb_completion:
test SCB_SCSI_STATUS,0xff jnz bad_status;
/*
......@@ -1053,6 +1057,12 @@ bad_status:
cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb;
call freeze_queue;
upload_scb:
/*
* Restore SCB TAG since we reuse this field
* in the sequencer. We don't want to corrupt
* it on the host.
*/
bmov SCB_TAG, SCBPTR, 2;
bmov SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2;
bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2;
or SCB_SGPTR, SG_STATUS_VALID ret;
......@@ -1363,7 +1373,7 @@ load_first_seg:
clr SG_STATE ret;
p_data_handle_xfer:
call setjmp_setscb;
call setjmp;
test SG_STATE, LOADING_NEEDED jnz service_fifo;
p_data_clear_handler:
or LONGJMP_ADDR[1], INVALID_ADDR ret;
......@@ -1616,25 +1626,32 @@ export seq_isr:
* and deffer the test by one instruction.
*/
mov REG_ISR, LQISTAT2;
test REG_ISR, LQIWORKONLQ jz data_valid;
test SEQINTSRC, SAVEPTRS jz data_valid;
test REG_ISR, LQIWORKONLQ jz main_isr;
test SEQINTSRC, SAVEPTRS jz main_isr;
test LONGJMP_ADDR[1], INVALID_ADDR jz saveptr_active_fifo;
/*
* Switch to the active FIFO.
* Switch to the active FIFO after clearing the snapshot
* savepointer in the current FIFO. We do this so that
* a pending CTXTDONE or SAVEPTR is visible in the active
* FIFO. This status is the only way we can detect if we
* have lost the race (e.g. host paused us) and our attepts
* to disable the channel occurred after all REQs were
* already seen and acked (REQINIT never comes true).
*/
mvi DFFSXFRCTL, CLRCHN;
xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
test DFCNTRL, DIRECTION jz snapshot_other_fifo;
test DFCNTRL, DIRECTION jz interrupt_return;
and DFCNTRL, ~SCSIEN;
test SSTAT1, REQINIT jz .;
snapshot_wait_data_valid:
test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz snapshot_data_valid;
test SSTAT1, REQINIT jz snapshot_wait_data_valid;
snapshot_data_valid:
or DFCNTRL, SCSIEN;
/* FALLTHROUGH */
snapshot_other_fifo:
xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
/* FALLTHROUGH */
or SEQINTCTL, IRET ret;
snapshot_saveptr:
mvi DFFSXFRCTL, CLRCHN;
or SEQINTCTL, IRET ret;
data_valid:
main_isr:
}
test SEQINTSRC, CFG4DATA jnz cfg4data_intr;
test SEQINTSRC, CFG4ISTAT jnz cfg4istat_intr;
......@@ -1667,9 +1684,11 @@ saveptr_active_fifo:
or SEQINTCTL, IRET ret;
cfg4data_intr:
test SCB_SGPTR[0], SG_LIST_NULL jnz pkt_handle_overrun;
test SCB_SGPTR[0], SG_LIST_NULL jnz pkt_handle_overrun_inc_use_count;
call load_first_seg;
call pkt_handle_xfer;
inc SCB_FIFO_USE_COUNT;
interrupt_return:
or SEQINTCTL, IRET ret;
cfg4istat_intr:
......@@ -1729,7 +1748,6 @@ cfg4icmd_intr:
test DFSTATUS, FIFOEMP jz pkt_handle_overrun
pkt_handle_xfer:
bmov LONGJMP_SCB, SCBPTR, 2;
test SG_STATE, LOADING_NEEDED jz pkt_last_seg;
call setjmp;
test SEQINTSRC, SAVEPTRS jnz pkt_saveptrs;
......@@ -1751,7 +1769,7 @@ pkt_service_fifo:
pkt_last_seg:
call setjmp;
test SEQINTSRC, SAVEPTRS jnz pkt_saveptrs;
test SG_CACHE_SHADOW, LAST_SEG_DONE jnz last_pkt_xfer_done;
test SG_CACHE_SHADOW, LAST_SEG_DONE jnz pkt_last_seg_done;
test SCSIPHASE, ~DATA_PHASE_MASK jz . + 2;
test SCSISIGO, ATNO jnz . + 2;
test SSTAT2, NONPACKREQ jz return;
......@@ -1760,7 +1778,7 @@ pkt_last_seg:
/*
* Either a SAVEPTRS interrupt condition is pending for this FIFO
* or we have a pending nonpackreq for this FIFO. We differentiate
* 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.
......@@ -1789,118 +1807,134 @@ pkt_saveptrs_wait_fifoemp:
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:
dec SCB_FIFO_USE_COUNT;
test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle;
mvi DFFSXFRCTL, CLRCHN ret;
END_CRITICAL;
last_pkt_xfer_done:
/*
* LAST_SEG_DONE status has been seen in the current FIFO.
* This indicates that all of the allowed data for this
* command has transferred across the SCSI and host buses.
* Check for overrun and see if we can complete this command.
*/
pkt_last_seg_done:
BEGIN_CRITICAL;
if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) {
or DFCNTRL, FIFOFLUSH;
}
test SCB_CONTROL, STATUS_RCVD jz wait_pkt_end;
check_overrun;
or SCB_SGPTR, SG_LIST_NULL;
/*
* 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.
* Mark transfer as completed.
*/
last_pkt_queue_scb:
or LONGJMP_ADDR[1], INVALID_ADDR;
bmov ARG_1, SCBPTR, 2;
mvi DFFSXFRCTL, CLRCHN;
jmp queue_arg1_scb_completion;
last_pkt_complete:
bmov ARG_1, SCBPTR, 2;
mvi DFFSXFRCTL, CLRCHN;
check_other_fifo:
clc;
TOGGLE_DFF_MODE
call check_fifo;
jnc queue_arg1_scb_completion;
return:
ret;
or SCB_SGPTR, SG_LIST_NULL;
wait_pkt_end:
/*
* Wait for the current context to finish to verify that
* no overrun condition has occurred.
*/
test SEQINTSRC, CTXTDONE jnz pkt_ctxt_done;
call setjmp;
END_CRITICAL;
wait_pkt_end_loop:
test SEQINTSRC, CTXTDONE jnz pkt_end;
pkt_wait_ctxt_done_loop:
test SEQINTSRC, CTXTDONE jnz pkt_ctxt_done;
/*
* A sufficiently large overrun or a NONPACKREQ may
* prevent CTXTDONE from ever asserting, so we must
* poll for these statuses too.
*/
check_overrun;
test SSTAT2, NONPACKREQ jz return;
test SEQINTSRC, CTXTDONE jz unexpected_nonpkt_phase;
pkt_end:
BEGIN_CRITICAL;
/* FALLTHROUGH */
pkt_ctxt_done:
check_overrun;
or LONGJMP_ADDR[1], INVALID_ADDR;
or SCB_SGPTR, SG_LIST_NULL;
test SCB_CONTROL, STATUS_RCVD jnz last_pkt_complete;
/*
* If status has been received, it is safe to skip
* the check to see if another FIFO is active because
* LAST_SEG_DONE has been observed. However, we check
* the FIFO anyway since it costs us only one extra
* instruction to leverage common code to perform the
* SCB completion.
*/
dec SCB_FIFO_USE_COUNT;
test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle;
mvi DFFSXFRCTL, CLRCHN ret;
END_CRITICAL;
/*
* Must wait until CDB xfer is over before issuing the
* clear channel.
*/
pkt_handle_cdb:
call setjmp;
test SG_CACHE_SHADOW, LAST_SEG_DONE jz return;
or LONGJMP_ADDR[1], INVALID_ADDR;
mvi DFFSXFRCTL, CLRCHN ret;
/*
* Watch over the status transfer. Our host sense buffer is
* large enough to take the maximum allowed status packet.
* None-the-less, we must still catch and report overruns to
* the host.
* the host. Additionally, properly catch unexpected non-packet
* phases that are typically caused by CRC errors in status packet
* transmission.
*/
pkt_handle_status:
call setjmp_setscb;
test SG_CACHE_SHADOW, LAST_SEG_DONE jz check_status_overrun;
test SEQINTSRC, CTXTDONE jz return;
status_IU_done:
BEGIN_CRITICAL;
call setjmp;
test SG_CACHE_SHADOW, LAST_SEG_DONE jnz pkt_status_check_overrun;
test SEQINTSRC, CTXTDONE jz pkt_status_check_nonpackreq;
test SG_CACHE_SHADOW, LAST_SEG_DONE jnz pkt_status_check_overrun;
pkt_status_IU_done:
if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) {
or DFCNTRL, FIFOFLUSH;
}
test DFSTATUS, FIFOEMP jz return;
BEGIN_CRITICAL;
or LONGJMP_ADDR[1], INVALID_ADDR;
mvi SCB_SCSI_STATUS, STATUS_PKT_SENSE;
or SCB_CONTROL, STATUS_RCVD;
jmp last_pkt_complete;
jmp pkt_complete_scb_if_fifos_idle;
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:
pkt_status_check_overrun:
/*
* Status PKT overruns are uncerimoniously recovered with a
* bus reset. If we've overrun, let the host know so that
* recovery can be performed.
*
* LAST_SEG_DONE has been observed. If either CTXTDONE or
* a NONPACKREQ phase change have occurred and the FIFO is
* empty, there is no overrun.
*/
test DFSTATUS, FIFOEMP jz pkt_status_report_overrun;
test SEQINTSRC, CTXTDONE jz . + 2;
test DFSTATUS, FIFOEMP jnz pkt_status_IU_done;
test SCSIPHASE, ~DATA_PHASE_MASK jz return;
test DFSTATUS, FIFOEMP jnz pkt_status_check_nonpackreq;
pkt_status_report_overrun:
SET_SEQINTCODE(STATUS_OVERRUN)
jmp status_IU_done;
SET_SRC_MODE M_DFF0;
SET_DST_MODE M_DFF0;
BEGIN_CRITICAL;
check_fifo:
test LONGJMP_ADDR[1], INVALID_ADDR jnz return;
mov A, ARG_2;
cmp LONGJMP_SCB[1], A jne return;
mov A, ARG_1;
cmp LONGJMP_SCB[0], A jne return;
stc ret;
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;
/* SEQUENCER RESTARTED */
pkt_status_check_nonpackreq:
/*
* CTXTDONE may be held off if a NONPACKREQ is associated with
* the current context. If a NONPACKREQ is observed, decide
* if it is for the current context. If it is for the current
* context, we must defer NONPACKREQ processing until all data
* has transferred to the host.
*/
test SCSIPHASE, ~DATA_PHASE_MASK jz return;
test SCSISIGO, ATNO jnz . + 2;
test SSTAT2, NONPACKREQ jz return;
test SEQINTSRC, CTXTDONE jnz pkt_status_IU_done;
test DFSTATUS, FIFOEMP jz return;
/*
* The unexpected nonpkt phase handler assumes that any
* data channel use will have a FIFO reference count. It
* turns out that the status handler doesn't need a refernce
* count since the status received flag, and thus completion
* processing, cannot be set until the handler is finished.
* We increment the count here to make the nonpkt handler
* happy.
*/
inc SCB_FIFO_USE_COUNT;
/* FALLTHROUGH */
/*
* Nonpackreq is a polled status. It can come true in three situations:
......@@ -1929,6 +1963,7 @@ unexpected_nonpkt_phase:
SET_SRC_MODE M_DFF0;
SET_DST_MODE M_DFF0;
or LONGJMP_ADDR[1], INVALID_ADDR;
dec SCB_FIFO_USE_COUNT;
mvi DFFSXFRCTL, CLRCHN;
mvi CLRSINT2, CLRNONPACKREQ;
test SCSIPHASE, ~(MSG_IN_PHASE|MSG_OUT_PHASE) jnz illegal_phase;
......@@ -1945,6 +1980,8 @@ illegal_phase:
* data. Otherwise use an overrun buffer in the host to simulate
* BITBUCKET.
*/
pkt_handle_overrun_inc_use_count:
inc SCB_FIFO_USE_COUNT;
pkt_handle_overrun:
SET_SEQINTCODE(CFG4OVERRUN)
call freeze_queue;
......@@ -1970,8 +2007,9 @@ overrun_load_done:
pkt_overrun_end:
or SCB_RESIDUAL_SGPTR, SG_OVERRUN_RESID;
test SEQINTSRC, CTXTDONE jz unexpected_nonpkt_phase;
test SCB_CONTROL, STATUS_RCVD jnz last_pkt_queue_scb;
dec SCB_FIFO_USE_COUNT;
or LONGJMP_ADDR[1], INVALID_ADDR;
test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle;
mvi DFFSXFRCTL, CLRCHN ret;
if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) {
......
......@@ -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#178 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#189 $
*
* $FreeBSD$
*/
......@@ -556,6 +556,26 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
ahd_name(ahd), seqintcode);
#endif
switch (seqintcode) {
case BAD_SCB_STATUS:
{
struct scb *scb;
u_int scbid;
int cmds_pending;
scbid = ahd_get_scbptr(ahd);
scb = ahd_lookup_scb(ahd, scbid);
if (scb != NULL) {
ahd_complete_scb(ahd, scb);
} else {
printf("%s: WARNING no command for scb %d "
"(bad status)\n", ahd_name(ahd), scbid);
ahd_dump_card_state(ahd);
}
cmds_pending = ahd_inw(ahd, CMDS_PENDING);
if (cmds_pending > 0)
ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1);
break;
}
case ENTERING_NONPACK:
{
struct scb *scb;
......@@ -604,7 +624,16 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
break;
case STATUS_OVERRUN:
{
printf("%s: Status Overrun", ahd_name(ahd));
struct scb *scb;
u_int scbid;
scbid = ahd_get_scbptr(ahd);
scb = ahd_lookup_scb(ahd, scbid);
if (scb != NULL)
ahd_print_path(ahd, scb);
else
printf("%s: ", ahd_name(ahd));
printf("SCB %d Packetized Status Overrun", scbid);
ahd_dump_card_state(ahd);
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
break;
......@@ -1166,7 +1195,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
/*
* A change in I/O mode is equivalent to a bus reset.
*/
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE);
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
ahd_pause(ahd);
ahd_setup_iocell_workaround(ahd);
ahd_unpause(ahd);
......@@ -2183,6 +2212,13 @@ ahd_clear_critical_section(struct ahd_softc *ahd)
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) & ~STEP);
ahd_outb(ahd, SIMODE1, simode1);
/*
* SCSIINT seems to glitch occassionally when
* the interrupt masks are restored. Clear SCSIINT
* one more time so that only persistent errors
* are seen as a real interrupt.
*/
ahd_outb(ahd, CLRINT, CLRSCSIINT);
}
ahd_restore_modes(ahd, saved_modes);
}
......@@ -4887,7 +4923,6 @@ ahd_free(struct ahd_softc *ahd)
{
int i;
ahd_fini_scbdata(ahd);
switch (ahd->init_level) {
default:
case 5:
......@@ -4919,6 +4954,7 @@ ahd_free(struct ahd_softc *ahd)
ahd_dma_tag_destroy(ahd, ahd->parent_dmat);
#endif
ahd_platform_free(ahd);
ahd_fini_scbdata(ahd);
for (i = 0; i < AHD_NUM_TARGETS; i++) {
struct ahd_tmode_tstate *tstate;
......@@ -5584,8 +5620,8 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
if (scb_data->sgs_left != 0) {
int offset;
offset = ahd_sglist_allocsize(ahd)
- (scb_data->sgs_left * ahd_sglist_size(ahd));
offset = ((ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd))
- scb_data->sgs_left) * ahd_sglist_size(ahd);
sg_map = SLIST_FIRST(&scb_data->sg_maps);
segs = sg_map->vaddr + offset;
sg_busaddr = sg_map->physaddr + offset;
......@@ -6056,7 +6092,6 @@ ahd_chip_init(struct ahd_softc *ahd)
for (i = 0; i < 2; i++) {
ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);
ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
ahd_outw(ahd, LONGJMP_SCB, SCB_LIST_NULL);
ahd_outb(ahd, SG_STATE, 0);
ahd_outb(ahd, CLRSEQINTSRC, 0xFF);
ahd_outb(ahd, SEQIMODE,
......@@ -6605,24 +6640,29 @@ ahd_enable_coalessing(struct ahd_softc *ahd, int enable)
void
ahd_pause_and_flushwork(struct ahd_softc *ahd)
{
ahd_mode_state saved_modes;
u_int intstat;
u_int maxloops;
int paused;
u_int intstat;
u_int maxloops;
u_int qfreeze_cnt;
maxloops = 1000;
ahd->flags |= AHD_ALL_INTERRUPTS;
paused = FALSE;
ahd_pause(ahd);
/*
* Increment the QFreeze Count so that the sequencer
* will not start new selections. We do this only
* until we are safely paused without further selections
* pending.
*/
ahd_outw(ahd, QFREEZE_COUNT, ahd_inw(ahd, QFREEZE_COUNT) + 1);
ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN);
do {
struct scb *waiting_scb;
if (paused)
ahd_unpause(ahd);
ahd_unpause(ahd);
ahd_intr(ahd);
ahd_pause(ahd);
paused = TRUE;
ahd_clear_critical_section(ahd);
saved_modes = ahd_save_modes(ahd);
intstat = ahd_inb(ahd, INTSTAT);
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
if ((ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)
ahd_outb(ahd, SCSISEQ0,
......@@ -6639,22 +6679,32 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
&& (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0)
ahd_outb(ahd, SCSISEQ0,
ahd_inb(ahd, SCSISEQ0) | ENSELO);
intstat = ahd_inb(ahd, INTSTAT);
} while (--maxloops
&& (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0)
&& ((intstat & INT_PEND) != 0
|| (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO))));
|| (ahd_inb(ahd, SCSISEQ0) & ENSELO) != 0
|| (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0));
if (maxloops == 0) {
printf("Infinite interrupt loop, INTSTAT = %x",
ahd_inb(ahd, INTSTAT));
}
qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT);
if (qfreeze_cnt == 0) {
printf("%s: ahd_pause_and_flushwork with 0 qfreeze count!\n",
ahd_name(ahd));
} else {
qfreeze_cnt--;
}
ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt);
if (qfreeze_cnt == 0)
ahd_outb(ahd, SEQ_FLAGS2,
ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN);
ahd_flush_qoutfifo(ahd);
ahd_platform_flushwork(ahd);
ahd->flags &= ~AHD_ALL_INTERRUPTS;
ahd_restore_modes(ahd, saved_modes);
}
int
......@@ -7514,14 +7564,17 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
ahd_outb(ahd, DFFSTAT, next_fifo);
} while (next_fifo != fifo);
/*
* Reset the bus if we are initiating this reset
*/
ahd_clear_msg_state(ahd);
ahd_outb(ahd, SIMODE1,
ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE));
if (initiate_reset)
ahd_reset_current_bus(ahd);
ahd_clear_intstat(ahd);
/*
......@@ -7719,9 +7772,6 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
hscb = scb->hscb;
/* Freeze the queue until the client sees the error. */
ahd_pause(ahd);
ahd_clear_critical_section(ahd);
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
ahd_freeze_devq(ahd, scb);
ahd_freeze_scb(scb);
qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT);
......@@ -7734,7 +7784,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
if (qfreeze_cnt == 0)
ahd_outb(ahd, SEQ_FLAGS2,
ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN);
ahd_unpause(ahd);
/* Don't want to clobber the original sense code */
if ((scb->flags & SCB_SENSE) != 0) {
/*
......@@ -8592,11 +8642,11 @@ ahd_dump_card_state(struct ahd_softc *ahd)
LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
if (i++ > AHD_SCB_MAX)
break;
cur_col = printf("\n%3d ", SCB_GET_TAG(scb));
cur_col = printf("\n%3d FIFO_USE[0x%x] ", SCB_GET_TAG(scb),
ahd_inb(ahd, SCB_FIFO_USE_COUNT));
ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
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("\nTotal %d\n", i);
......@@ -8659,12 +8709,10 @@ ahd_dump_card_state(struct ahd_softc *ahd)
ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);
fifo_scbptr = ahd_get_scbptr(ahd);
printf("\n%s: FIFO%d %s, LONGJMP == 0x%x, "
"SCB 0x%x, LJSCB 0x%x\n",
printf("\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n",
ahd_name(ahd), i,
(dffstat & (FIFO0FREE << i)) ? "Free" : "Active",
ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr,
ahd_inw(ahd, LONGJMP_SCB));
ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr);
cur_col = 0;
ahd_seqimode_print(ahd_inb(ahd, SEQIMODE), &cur_col, 50);
ahd_seqintsrc_print(ahd_inb(ahd, SEQINTSRC), &cur_col, 50);
......
......@@ -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#44 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#45 $
*
* $FreeBSD$
*/
......@@ -223,7 +223,7 @@ ahd_unpause(struct ahd_softc *ahd)
ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
}
if ((ahd_inb(ahd, INTSTAT) & ~(SWTMINT | CMDCMPLT)) == 0)
if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0)
ahd_outb(ahd, HCNTRL, ahd->unpause);
ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN);
......
/*
* Adaptec AIC79xx device driver for Linux.
*
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#141 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#156 $
*
* --------------------------------------------------------------------------
* Copyright (c) 1994-2000 Justin T. Gibbs.
......@@ -67,12 +67,10 @@
#include <linux/unistd.h>
static int errno;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
/*
* Lock protecting manipulation of the ahd softc list.
*/
spinlock_t ahd_list_spinlock;
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
struct proc_dir_entry proc_scsi_aic79xx = {
......@@ -82,6 +80,11 @@ struct proc_dir_entry proc_scsi_aic79xx = {
};
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
/* For dynamic sglist size calculation. */
u_int ahd_linux_nseg;
#endif
/*
* Bucket size for counting good commands in between bad ones.
*/
......@@ -352,14 +355,14 @@ static uint32_t aic79xx_no_reset;
* disabled at the very end. That should fix everyone up unless there are
* really strange cirumstances.
*/
static int aic79xx_reverse_scan = 0;
static uint32_t aic79xx_reverse_scan;
/*
* Should we force EXTENDED translation on a controller.
* 0 == Use whatever is in the SEEPROM or default to off
* 1 == Use whatever is in the SEEPROM or default to on
*/
static uint32_t aic79xx_extended = 0;
static uint32_t aic79xx_extended;
/*
* PCI bus parity checking of the Adaptec controllers. This is somewhat
......@@ -367,16 +370,15 @@ static uint32_t aic79xx_extended = 0;
* solved a PCI parity problem, but on certain machines with broken PCI
* chipset configurations, it can generate tons of false error messages.
* It's included in the driver for completeness.
* 0 = Shut off PCI parity check
* -1 = Normal polarity pci parity checking
* 1 = reverse polarity pci parity checking
* 0 = Shut off PCI parity check
* non-0 = Enable PCI parity check
*
* NOTE: you can't actually pass -1 on the lilo prompt. So, to set this
* variable to -1 you would actually want to simply pass the variable
* name without a number. That will invert the 0 which will result in
* -1.
*/
static int aic79xx_pci_parity = 0;
static uint32_t aic79xx_pci_parity = ~0;
/*
* There are lots of broken chipsets in the world. Some of them will
......@@ -384,7 +386,7 @@ static int aic79xx_pci_parity = 0;
* controller. I/O mapped register access, if allowed by the given
* platform, will work in almost all cases.
*/
int aic79xx_allow_memio = 1;
uint32_t aic79xx_allow_memio = ~0;
/*
* aic79xx_detect() has been run, so register all device arrivals
......@@ -403,7 +405,7 @@ int aic79xx_detect_complete;
* We default to 256ms because some older devices need a longer time
* to respond to initial selection.
*/
static int aic79xx_seltime = 0x00;
static uint32_t aic79xx_seltime;
/*
* Certain devices do not perform any aging on commands. Should the
......@@ -413,7 +415,7 @@ static int aic79xx_seltime = 0x00;
* force all outstanding transactions to be serviced prior to a new
* transaction.
*/
int aic79xx_periodic_otag;
uint32_t aic79xx_periodic_otag;
/*
* Module information and settable options.
......@@ -478,6 +480,7 @@ static void ahd_linux_filter_inquiry(struct ahd_softc *ahd,
static void ahd_linux_dev_timed_unfreeze(u_long arg);
static void ahd_linux_sem_timeout(u_long arg);
static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd);
static void ahd_linux_size_nseg(void);
static void ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd);
static void ahd_linux_start_dv(struct ahd_softc *ahd);
static void ahd_linux_dv_timeout(struct scsi_cmnd *cmd);
......@@ -548,20 +551,17 @@ static aic_option_callback_t ahd_linux_setup_dv;
static aic_option_callback_t ahd_linux_setup_iocell_info;
static int ahd_linux_next_unit(void);
static void ahd_runq_tasklet(unsigned long data);
static int ahd_linux_halt(struct notifier_block *nb, u_long event, void *buf);
static int aic79xx_setup(char *c);
/****************************** Inlines ***************************************/
static __inline void ahd_schedule_completeq(struct ahd_softc *ahd,
struct ahd_cmd *acmd);
static __inline void ahd_schedule_completeq(struct ahd_softc *ahd);
static __inline void ahd_schedule_runq(struct ahd_softc *ahd);
static __inline void ahd_setup_runq_tasklet(struct ahd_softc *ahd);
static __inline void ahd_teardown_runq_tasklet(struct ahd_softc *ahd);
static __inline struct ahd_linux_device*
ahd_linux_get_device(struct ahd_softc *ahd, u_int channel,
u_int target, u_int lun, int alloc);
static struct ahd_cmd *ahd_linux_run_complete_queue(struct ahd_softc *ahd,
struct ahd_cmd *acmd);
static struct ahd_cmd *ahd_linux_run_complete_queue(struct ahd_softc *ahd);
static __inline void ahd_linux_check_device_queue(struct ahd_softc *ahd,
struct ahd_linux_device *dev);
static __inline struct ahd_linux_device *
......@@ -574,26 +574,8 @@ static __inline int ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb,
bus_addr_t addr, bus_size_t len);
static __inline void
ahd_schedule_completeq(struct ahd_softc *ahd, struct ahd_cmd *acmd)
ahd_schedule_completeq(struct ahd_softc *ahd)
{
while (acmd != NULL) {
struct ahd_completeq *completeq;
struct ahd_cmd *list_cmd;
struct ahd_cmd *next_cmd;
next_cmd = TAILQ_NEXT(acmd, acmd_links.tqe);
completeq = &ahd->platform_data->completeq;
list_cmd = TAILQ_FIRST(completeq);
while (list_cmd != NULL
&& acmd_scsi_cmd(list_cmd).serial_number
< acmd_scsi_cmd(acmd).serial_number)
list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe);
if (list_cmd != NULL)
TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe);
else
TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe);
acmd = next_cmd;
}
if ((ahd->platform_data->flags & AHD_RUN_CMPLT_Q_TIMER) == 0) {
ahd->platform_data->flags |= AHD_RUN_CMPLT_Q_TIMER;
ahd->platform_data->completeq_timer.expires = jiffies;
......@@ -662,25 +644,17 @@ ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, u_int target,
#define AHD_LINUX_MAX_RETURNED_ERRORS 4
static struct ahd_cmd *
ahd_linux_run_complete_queue(struct ahd_softc *ahd, struct ahd_cmd *acmd)
ahd_linux_run_complete_queue(struct ahd_softc *ahd)
{
struct ahd_cmd *acmd;
u_long done_flags;
int with_errors;
with_errors = 0;
ahd_done_lock(ahd, &done_flags);
while (acmd != NULL) {
while ((acmd = TAILQ_FIRST(&ahd->platform_data->completeq)) != NULL) {
Scsi_Cmnd *cmd;
cmd = &acmd_scsi_cmd(acmd);
acmd = TAILQ_NEXT(acmd, acmd_links.tqe);
cmd->host_scribble = NULL;
if (ahd_cmd_get_transaction_status(cmd) != DID_OK
|| (cmd->result & 0xFF) != SCSI_STATUS_OK)
with_errors++;
cmd->scsi_done(cmd);
if (with_errors > AHD_LINUX_MAX_RETURNED_ERRORS) {
/*
* Linux uses stack recursion to requeue
......@@ -690,8 +664,19 @@ ahd_linux_run_complete_queue(struct ahd_softc *ahd, struct ahd_cmd *acmd)
* the operating system in case they are going
* to be retried. "ick"
*/
ahd_schedule_completeq(ahd);
break;
}
TAILQ_REMOVE(&ahd->platform_data->completeq,
acmd, acmd_links.tqe);
cmd = &acmd_scsi_cmd(acmd);
acmd = TAILQ_NEXT(acmd, acmd_links.tqe);
cmd->host_scribble = NULL;
if (ahd_cmd_get_transaction_status(cmd) != DID_OK
|| (cmd->result & 0xFF) != SCSI_STATUS_OK)
with_errors++;
cmd->scsi_done(cmd);
}
ahd_done_unlock(ahd, &done_flags);
return (acmd);
......@@ -824,6 +809,67 @@ static int ahd_linux_bus_reset(Scsi_Cmnd *);
static int ahd_linux_dev_reset(Scsi_Cmnd *);
static int ahd_linux_abort(Scsi_Cmnd *);
/*
* Calculate a safe value for AHD_NSEG (as expressed through ahd_linux_nseg).
*
* In pre-2.5.X...
* The midlayer allocates an S/G array dynamically when a command is issued
* using SCSI malloc. This array, which is in an OS dependent format that
* must later be copied to our private S/G list, is sized to house just the
* number of segments needed for the current transfer. Since the code that
* sizes the SCSI malloc pool does not take into consideration fragmentation
* of the pool, executing transactions numbering just a fraction of our
* concurrent transaction limit with SG list lengths aproaching AHC_NSEG will
* quickly depleat the SCSI malloc pool of usable space. Unfortunately, the
* mid-layer does not properly handle this scsi malloc failures for the S/G
* array and the result can be a lockup of the I/O subsystem. We try to size
* our S/G list so that it satisfies our drivers allocation requirements in
* addition to avoiding fragmentation of the SCSI malloc pool.
*/
static void
ahd_linux_size_nseg(void)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
u_int cur_size;
u_int best_size;
/*
* The SCSI allocator rounds to the nearest 512 bytes
* an cannot allocate across a page boundary. Our algorithm
* is to start at 1K of scsi malloc space per-command and
* loop through all factors of the PAGE_SIZE and pick the best.
*/
best_size = 0;
for (cur_size = 1024; cur_size <= PAGE_SIZE; cur_size *= 2) {
u_int nseg;
nseg = cur_size / sizeof(struct scatterlist);
if (nseg < AHD_LINUX_MIN_NSEG)
continue;
if (best_size == 0) {
best_size = cur_size;
ahd_linux_nseg = nseg;
} else {
u_int best_rem;
u_int cur_rem;
/*
* Compare the traits of the current "best_size"
* with the current size to determine if the
* current size is a better size.
*/
best_rem = best_size % sizeof(struct scatterlist);
cur_rem = cur_size % sizeof(struct scatterlist);
if (cur_rem < best_rem) {
best_size = cur_size;
ahd_linux_nseg = nseg;
}
}
}
#endif
}
/*
* Try to detect an Adaptec 79XX controller.
*/
......@@ -852,6 +898,10 @@ ahd_linux_detect(Scsi_Host_Template *template)
printf("ahd_linux_detect: Unable to attach\n");
return (0);
}
/*
* Determine an appropriate size for our Scatter Gatther lists.
*/
ahd_linux_size_nseg();
#ifdef MODULE
/*
* If we've been passed any parameters, process them now.
......@@ -991,7 +1041,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
ahd_linux_queue_cmd_complete(ahd, cmd);
ahd_schedule_completeq(ahd, NULL);
ahd_schedule_completeq(ahd);
ahd_midlayer_entrypoint_unlock(ahd, &flags);
return (0);
}
......@@ -1001,7 +1051,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
if (dev == NULL) {
ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
ahd_linux_queue_cmd_complete(ahd, cmd);
ahd_schedule_completeq(ahd, NULL);
ahd_schedule_completeq(ahd);
ahd_midlayer_entrypoint_unlock(ahd, &flags);
printf("%s: aic79xx_linux_queue - Unable to allocate device!\n",
ahd_name(ahd));
......@@ -1087,7 +1137,8 @@ ahd_linux_slave_destroy(Scsi_Device *device)
&& (dev->flags & AHD_DEV_SLAVE_CONFIGURED) != 0) {
dev->flags |= AHD_DEV_UNCONFIGURED;
if (TAILQ_EMPTY(&dev->busyq)
&& dev->active == 0)
&& dev->active == 0
&& (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0)
ahd_linux_free_device(ahd, dev);
}
ahd_midlayer_entrypoint_unlock(ahd, &flags);
......@@ -1102,15 +1153,30 @@ ahd_linux_select_queue_depth(struct Scsi_Host * host,
Scsi_Device * scsi_devs)
{
Scsi_Device *device;
Scsi_Device *ldev;
struct ahd_softc *ahd;
u_long flags;
int scbnum;
ahd = *((struct ahd_softc **)host->hostdata);
ahd_lock(ahd, &flags);
scbnum = 0;
for (device = scsi_devs; device != NULL; device = device->next) {
/*
* Watch out for duplicate devices. This works around
* some quirks in how the SCSI scanning code does its
* device management.
*/
for (ldev = scsi_devs; ldev != device; ldev = ldev->next) {
if (ldev->host == device->host
&& ldev->channel == device->channel
&& ldev->id == device->id
&& ldev->lun == device->lun)
break;
}
/* Skip duplicate. */
if (ldev != device)
continue;
if (device->host == host) {
struct ahd_linux_device *dev;
......@@ -1265,7 +1331,7 @@ ahd_linux_abort(Scsi_Cmnd *cmd)
* Start by searching the device queue. If not found
* there, check the pending_scb list. If not found
* at all, and the system wanted us to just abort the
* command return success.
* command, return success.
*/
dev = ahd_linux_get_device(ahd, cmd->device->channel,
cmd->device->id, cmd->device->lun,
......@@ -1476,21 +1542,15 @@ ahd_linux_abort(Scsi_Cmnd *cmd)
printf("Recovery code sleeping\n");
down(&ahd->platform_data->eh_sem);
printf("Recovery code awake\n");
ret = del_timer(&timer);
ret = del_timer_sync(&timer);
if (ret == 0) {
printf("Timer Expired\n");
retval = FAILED;
}
spin_lock_irq(&ahd->platform_data->spin_lock);
}
acmd = TAILQ_FIRST(&ahd->platform_data->completeq);
TAILQ_INIT(&ahd->platform_data->completeq);
ahd_schedule_runq(ahd);
if (acmd != NULL) {
acmd = ahd_linux_run_complete_queue(ahd, acmd);
if (acmd != NULL)
ahd_schedule_completeq(ahd, acmd);
}
ahd_linux_run_complete_queue(ahd);
ahd_midlayer_entrypoint_unlock(ahd, &s);
return (retval);
}
......@@ -1515,7 +1575,6 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd)
struct ahd_tmode_tstate *tstate;
struct scb *scb;
struct hardware_scb *hscb;
struct ahd_cmd *acmd;
u_long s;
struct timer_list timer;
int retval;
......@@ -1581,19 +1640,13 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd)
down(&ahd->platform_data->eh_sem);
printf("Recovery code awake\n");
retval = SUCCESS;
if (del_timer(&timer) == 0) {
if (del_timer_sync(&timer) == 0) {
printf("Timer Expired\n");
retval = FAILED;
}
spin_lock_irq(&ahd->platform_data->spin_lock);
acmd = TAILQ_FIRST(&ahd->platform_data->completeq);
TAILQ_INIT(&ahd->platform_data->completeq);
ahd_schedule_runq(ahd);
if (acmd != NULL) {
acmd = ahd_linux_run_complete_queue(ahd, acmd);
if (acmd != NULL)
ahd_schedule_completeq(ahd, acmd);
}
ahd_linux_run_complete_queue(ahd);
ahd_midlayer_entrypoint_unlock(ahd, &s);
printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval);
return (retval);
......@@ -1606,7 +1659,6 @@ static int
ahd_linux_bus_reset(Scsi_Cmnd *cmd)
{
struct ahd_softc *ahd;
struct ahd_cmd *acmd;
u_long s;
int found;
......@@ -1619,14 +1671,7 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd)
ahd_midlayer_entrypoint_lock(ahd, &s);
found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
/*initiate reset*/TRUE);
acmd = TAILQ_FIRST(&ahd->platform_data->completeq);
TAILQ_INIT(&ahd->platform_data->completeq);
if (acmd != NULL) {
acmd = ahd_linux_run_complete_queue(ahd, acmd);
if (acmd != NULL)
ahd_schedule_completeq(ahd, acmd);
}
ahd_linux_run_complete_queue(ahd);
ahd_midlayer_entrypoint_unlock(ahd, &s);
if (bootverbose)
......@@ -1650,7 +1695,6 @@ Scsi_Host_Template aic79xx_driver_template = {
#endif
.can_queue = AHD_MAX_QUEUE,
.this_id = -1,
.sg_tablesize = AHD_NSEG,
.cmd_per_lun = 2,
.use_clustering = ENABLE_CLUSTERING,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
......@@ -1717,35 +1761,6 @@ ahd_runq_tasklet(unsigned long data)
#endif
}
/************************ Shutdown/halt/reboot hook ***************************/
#include <linux/notifier.h>
#include <linux/reboot.h>
static struct notifier_block ahd_linux_notifier = {
ahd_linux_halt, NULL, 0
};
static int ahd_linux_halt(struct notifier_block *nb, u_long event, void *buf)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
struct ahd_softc *ahd;
/*
* In 2.5.X, this is called prior to the filesystems
* being synced and the SCSI layer being properly
* shutdown. A different API is required there,
* but the device hooks for this don't quite look
* right.
*/
if (event == SYS_DOWN || event == SYS_HALT) {
TAILQ_FOREACH(ahd, &ahd_tailq, links) {
ahd_shutdown(ahd);
}
}
#endif
return (NOTIFY_OK);
}
/******************************** Bus DMA *************************************/
int
ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent,
......@@ -1927,7 +1942,7 @@ ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
}
static void
ahd_linux_setup_tag_info(void *arg, int instance, int targ, int32_t value)
ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
{
if ((instance >= 0) && (targ >= 0)
......@@ -1940,18 +1955,18 @@ ahd_linux_setup_tag_info(void *arg, int instance, int targ, int32_t value)
}
static void
ahd_linux_setup_rd_strm_info(void *arg, int instance, int targ, int32_t value)
ahd_linux_setup_rd_strm_info(u_long arg, int instance, int targ, int32_t value)
{
if ((instance >= 0)
&& (instance < NUM_ELEMENTS(aic79xx_rd_strm_info))) {
aic79xx_rd_strm_info[instance] = value * 0xFFFF;
aic79xx_rd_strm_info[instance] = value & 0xFFFF;
if (bootverbose)
printf("rd_strm[%d] = 0x%x\n", instance, value);
}
}
static void
ahd_linux_setup_dv(void *arg, int instance, int targ, int32_t value)
ahd_linux_setup_dv(u_long arg, int instance, int targ, int32_t value)
{
if ((instance >= 0)
&& (instance < NUM_ELEMENTS(aic79xx_dv_settings))) {
......@@ -1962,11 +1977,9 @@ ahd_linux_setup_dv(void *arg, int instance, int targ, int32_t value)
}
static void
ahd_linux_setup_iocell_info(void *arg, int instance, int targ, int32_t value)
ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value)
{
u_int index;
index = (u_int)arg;
if ((instance >= 0)
&& (instance < NUM_ELEMENTS(aic79xx_iocell_info))) {
uint8_t *iocell_info;
......@@ -1974,7 +1987,7 @@ ahd_linux_setup_iocell_info(void *arg, int instance, int targ, int32_t value)
iocell_info = (uint8_t*)&aic79xx_iocell_info[instance];
iocell_info[index] = value & 0xFFFF;
if (bootverbose)
printf("iocell[%d:%d] = %d\n", instance, index, value);
printf("iocell[%d:%ld] = %d\n", instance, index, value);
}
}
......@@ -2053,32 +2066,31 @@ aic79xx_setup(char *s)
ahd_linux_setup_tag_info_global(p + n);
} else if (strncmp(p, "tag_info", n) == 0) {
s = aic_parse_brace_option("tag_info", p + n, end,
2, ahd_linux_setup_tag_info, NULL);
2, ahd_linux_setup_tag_info, 0);
} else if (strncmp(p, "rd_strm", n) == 0) {
printf("Calling brace parse for %s\n", p);
s = aic_parse_brace_option("rd_strm", p + n, end,
1, ahd_linux_setup_rd_strm_info, NULL);
1, ahd_linux_setup_rd_strm_info, 0);
} else if (strncmp(p, "dv", n) == 0) {
s = aic_parse_brace_option("dv", p + n, end, 1,
ahd_linux_setup_dv, NULL);
ahd_linux_setup_dv, 0);
} else if (strncmp(p, "slewrate", n) == 0) {
s = aic_parse_brace_option("slewrate",
p + n, end, 1, ahd_linux_setup_iocell_info,
(void *)AIC79XX_SLEWRATE_INDEX);
AIC79XX_SLEWRATE_INDEX);
} else if (strncmp(p, "precomp", n) == 0) {
s = aic_parse_brace_option("precomp",
p + n, end, 1, ahd_linux_setup_iocell_info,
(void *)AIC79XX_PRECOMP_INDEX);
AIC79XX_PRECOMP_INDEX);
} else if (strncmp(p, "amplitude", n) == 0) {
s = aic_parse_brace_option("amplitude",
p + n, end, 1, ahd_linux_setup_iocell_info,
(void *)AIC79XX_AMPLITUDE_INDEX);
AIC79XX_AMPLITUDE_INDEX);
} else if (p[n] == ':') {
*(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0);
} else if (!strncmp(p, "verbose", n)) {
*(options[i].flag) = 1;
} else {
*(options[i].flag) = ~(*(options[i].flag));
*(options[i].flag) ^= 0xFFFFFFFF;
}
}
return 1;
......@@ -2088,7 +2100,7 @@ aic79xx_setup(char *s)
__setup("aic79xx=", aic79xx_setup);
#endif
int aic79xx_verbose;
uint32_t aic79xx_verbose;
int
ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
......@@ -2120,6 +2132,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
host->max_id = (ahd->features & AHD_WIDE) ? 16 : 8;
host->max_lun = AHD_NUM_LUNS;
host->max_channel = 0;
host->sg_tablesize = AHD_NSEG;
ahd_set_unit(ahd, ahd_linux_next_unit());
sprintf(buf, "scsi%d", host->host_no);
new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
......@@ -2291,8 +2304,6 @@ ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
#endif
ahd_setup_runq_tasklet(ahd);
ahd->seltime = (aic79xx_seltime & 0x3) << 4;
if (TAILQ_EMPTY(&ahd_tailq))
register_reboot_notifier(&ahd_linux_notifier);
return (0);
}
......@@ -2304,6 +2315,7 @@ ahd_platform_free(struct ahd_softc *ahd)
int i, j;
if (ahd->platform_data != NULL) {
del_timer_sync(&ahd->platform_data->completeq_timer);
ahd_linux_kill_dv_thread(ahd);
ahd_teardown_runq_tasklet(ahd);
if (ahd->platform_data->host != NULL) {
......@@ -2317,15 +2329,20 @@ ahd_platform_free(struct ahd_softc *ahd)
for (i = 0; i < AHD_NUM_TARGETS; i++) {
targ = ahd->platform_data->targets[i];
if (targ != NULL) {
/* Keep target around through the loop. */
targ->refcount++;
for (j = 0; j < AHD_NUM_LUNS; j++) {
if (targ->devices[j] != NULL) {
dev = targ->devices[j];
ahd_linux_free_device(ahd, dev);
}
if (ahd->platform_data->targets[i] ==
NULL)
break;
if (targ->devices[j] == NULL)
continue;
dev = targ->devices[j];
ahd_linux_free_device(ahd, dev);
}
/*
* Forcibly free the target now that
* all devices are gone.
*/
ahd_linux_free_target(ahd, targ);
}
}
......@@ -2546,19 +2563,12 @@ ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel,
static void
ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd)
{
struct ahd_cmd *acmd;
u_long flags;
ahd_lock(ahd, &flags);
del_timer(&ahd->platform_data->completeq_timer);
ahd->platform_data->flags &= ~AHD_RUN_CMPLT_Q_TIMER;
acmd = TAILQ_FIRST(&ahd->platform_data->completeq);
TAILQ_INIT(&ahd->platform_data->completeq);
if (acmd != NULL) {
acmd = ahd_linux_run_complete_queue(ahd, acmd);
if (acmd != NULL)
ahd_schedule_completeq(ahd, acmd);
}
ahd_linux_run_complete_queue(ahd);
ahd_unlock(ahd, &flags);
}
......@@ -2921,10 +2931,14 @@ ahd_linux_dv_target(struct ahd_softc *ahd, u_int target_offset)
}
ahd_lock(ahd, &s);
if (targ->dv_buffer != NULL)
if (targ->dv_buffer != NULL) {
free(targ->dv_buffer, M_DEVBUF);
if (targ->dv_buffer1 != NULL)
targ->dv_buffer = NULL;
}
if (targ->dv_buffer1 != NULL) {
free(targ->dv_buffer1, M_DEVBUF);
targ->dv_buffer1 = NULL;
}
targ->flags &= ~AHD_DV_REQUIRED;
if (targ->refcount == 0)
ahd_linux_free_target(ahd, targ);
......@@ -3760,7 +3774,6 @@ static void
ahd_linux_dv_timeout(struct scsi_cmnd *cmd)
{
struct ahd_softc *ahd;
struct ahd_cmd *acmd;
struct scb *scb;
u_long flags;
......@@ -3807,16 +3820,9 @@ ahd_linux_dv_timeout(struct scsi_cmnd *cmd)
ahd->platform_data->reset_timer.function =
(ahd_linux_callback_t *)ahd_release_simq;
add_timer(&ahd->platform_data->reset_timer);
acmd = TAILQ_FIRST(&ahd->platform_data->completeq);
TAILQ_INIT(&ahd->platform_data->completeq);
if (ahd_linux_next_device_to_run(ahd) != NULL)
ahd_schedule_runq(ahd);
if (acmd != NULL) {
acmd = ahd_linux_run_complete_queue(ahd, acmd);
if (acmd != NULL) {
ahd_schedule_completeq(ahd, acmd);
}
}
ahd_linux_run_complete_queue(ahd);
ahd_unlock(ahd, &flags);
}
......@@ -4025,9 +4031,8 @@ ahd_linux_device_queue_depth(struct ahd_softc *ahd,
&& dev->scsi_device->tagged_supported != 0) {
ahd_set_tags(ahd, &devinfo, AHD_QUEUE_TAGGED);
printf("scsi%d:%c:%d:%d: Tagged Queuing enabled. Depth %d\n",
ahd->platform_data->host->host_no, devinfo.channel,
devinfo.target, devinfo.lun, tags);
ahd_print_devinfo(ahd, &devinfo);
printf("Tagged Queuing enabled. Depth %d\n", tags);
} else {
ahd_set_tags(ahd, &devinfo, AHD_QUEUE_NONE);
}
......@@ -4205,34 +4210,23 @@ void
ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
{
struct ahd_softc *ahd;
struct ahd_cmd *acmd;
u_long flags;
ahd = (struct ahd_softc *) dev_id;
ahd_lock(ahd, &flags);
ahd_intr(ahd);
acmd = TAILQ_FIRST(&ahd->platform_data->completeq);
TAILQ_INIT(&ahd->platform_data->completeq);
if (ahd_linux_next_device_to_run(ahd) != NULL)
ahd_schedule_runq(ahd);
if (acmd != NULL) {
acmd = ahd_linux_run_complete_queue(ahd, acmd);
if (acmd != NULL) {
ahd_schedule_completeq(ahd, acmd);
}
}
ahd_linux_run_complete_queue(ahd);
ahd_unlock(ahd, &flags);
}
void
ahd_platform_flushwork(struct ahd_softc *ahd)
{
struct ahd_cmd *acmd;
acmd = TAILQ_FIRST(&ahd->platform_data->completeq);
TAILQ_INIT(&ahd->platform_data->completeq);
while (acmd != NULL)
acmd = ahd_linux_run_complete_queue(ahd, acmd);
while (ahd_linux_run_complete_queue(ahd) != NULL)
;
}
static struct ahd_linux_target*
......@@ -4542,7 +4536,8 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
if (TAILQ_EMPTY(&dev->busyq)) {
if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0
&& dev->active == 0)
&& dev->active == 0
&& (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0)
ahd_linux_free_device(ahd, dev);
} else if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) {
TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links);
......@@ -5065,6 +5060,9 @@ ahd_linux_dev_timed_unfreeze(u_long arg)
if (dev->qfrozen == 0
&& (dev->flags & AHD_DEV_ON_RUN_LIST) == 0)
ahd_linux_run_device_queue(ahd, dev);
if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0
&& dev->active == 0)
ahd_linux_free_device(ahd, dev);
ahd_unlock(ahd, &s);
}
......@@ -5143,8 +5141,6 @@ ahd_linux_exit(void)
scsi_unregister_module(MODULE_SCSI_HA, &aic79xx_driver_template);
#endif
ahd_linux_pci_exit();
unregister_reboot_notifier(&ahd_linux_notifier);
}
module_init(ahd_linux_init);
......
......@@ -36,7 +36,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#121 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#128 $
*
*/
#ifndef _AIC79XX_LINUX_H_
......@@ -139,7 +139,7 @@ typedef Scsi_Cmnd *ahd_io_ctx_t;
#endif /* BYTE_ORDER */
/************************* Configuration Data *********************************/
extern int aic79xx_allow_memio;
extern uint32_t aic79xx_allow_memio;
extern int aic79xx_detect_complete;
extern Scsi_Host_Template aic79xx_driver_template;
......@@ -255,7 +255,7 @@ typedef struct timer_list ahd_timer_t;
/***************************** Timer Facilities *******************************/
#define ahd_timer_init init_timer
#define ahd_timer_stop del_timer
#define ahd_timer_stop del_timer_sync
typedef void ahd_linux_callback_t (u_long);
static __inline void ahd_timer_reset(ahd_timer_t *timer, u_int usec,
ahd_callback_t *func, void *arg);
......@@ -293,7 +293,7 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec)
#define AHD_SCSI_HAS_HOST_LOCK 0
#endif
#define AIC79XX_DRIVER_VERSION "1.3.5"
#define AIC79XX_DRIVER_VERSION "1.3.7"
/**************************** Front End Queues ********************************/
/*
......@@ -488,7 +488,18 @@ struct ahd_linux_target {
* manner and are allocated below 4GB, the number of S/G segments is
* unrestricted.
*/
#define AHD_NSEG 128
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
/*
* We dynamically adjust the number of segments in pre-2.5 kernels to
* avoid fragmentation issues in the SCSI mid-layer's private memory
* allocator. See aic79xx_osm.c ahd_linux_size_nseg() for details.
*/
extern u_int ahd_linux_nseg;
#define AHD_NSEG ahd_linux_nseg
#define AHD_LINUX_MIN_NSEG 64
#else
#define AHD_NSEG 128
#endif
/*
* Per-SCB OSM storage.
......@@ -532,9 +543,7 @@ struct ahd_platform_data {
TAILQ_HEAD(, ahd_linux_device) device_runq;
struct ahd_completeq completeq;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93)
spinlock_t spin_lock;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
struct tasklet_struct runq_tasklet;
#endif
......@@ -730,7 +739,6 @@ static __inline void ahd_list_lockinit(void);
static __inline void ahd_list_lock(unsigned long *flags);
static __inline void ahd_list_unlock(unsigned long *flags);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93)
static __inline void
ahd_lockinit(struct ahd_softc *ahd)
{
......@@ -818,63 +826,6 @@ ahd_list_unlock(unsigned long *flags)
spin_unlock_irqrestore(&ahd_list_spinlock, *flags);
}
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) */
ahd_lockinit(struct ahd_softc *ahd)
{
}
static __inline void
ahd_lock(struct ahd_softc *ahd, unsigned long *flags)
{
save_flags(*flags);
cli();
}
static __inline void
ahd_unlock(struct ahd_softc *ahd, unsigned long *flags)
{
restore_flags(*flags);
}
ahd_done_lockinit(struct ahd_softc *ahd)
{
}
static __inline void
ahd_done_lock(struct ahd_softc *ahd, unsigned long *flags)
{
/*
* The done lock is always held while
* the ahd lock is held so blocking
* interrupts again would have no effect.
*/
}
static __inline void
ahd_done_unlock(struct ahd_softc *ahd, unsigned long *flags)
{
}
static __inline void
ahd_list_lockinit()
{
}
static __inline void
ahd_list_lock(unsigned long *flags)
{
save_flags(*flags);
cli();
}
static __inline void
ahd_list_unlock(unsigned long *flags)
{
restore_flags(*flags);
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) */
/******************************* PCI Definitions ******************************/
/*
* PCIM_xxx: mask to locate subfield in register
......@@ -945,16 +896,6 @@ void ahd_power_state_change(struct ahd_softc *ahd,
ahd_power_state new_state);
/******************************* PCI Routines *********************************/
/*
* We need to use the bios32.h routines if we are kernel version 2.1.92 or less.
*/
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,92)
#if defined(__sparc_v9__) || defined(__powerpc__)
#error "PPC and Sparc platforms are only supported under 2.1.92 and above"
#endif
#include <linux/bios32.h>
#endif
int ahd_linux_pci_init(void);
void ahd_linux_pci_exit(void);
int ahd_pci_map_registers(struct ahd_softc *ahd);
......@@ -1285,5 +1226,5 @@ void ahd_platform_dump_card_state(struct ahd_softc *ahd);
#define AHD_PCI_CONFIG 0
#endif
#define bootverbose aic79xx_verbose
extern int aic79xx_verbose;
extern uint32_t aic79xx_verbose;
#endif /* _AIC79XX_LINUX_H_ */
......@@ -37,7 +37,7 @@
* String handling code courtesy of Gerard Roudier's <groudier@club-internet.fr>
* sym driver.
*
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#14 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#16 $
*/
#include "aic79xx_osm.h"
#include "aic79xx_inline.h"
......@@ -173,8 +173,7 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
tinfo = ahd_fetch_transinfo(ahd, channel, our_id,
target_id, &tstate);
copy_info(info, "Channel %c Target %d Negotiation Settings\n",
channel, target_id);
copy_info(info, "Target %d Negotiation Settings\n", target_id);
copy_info(info, "\tUser: ");
ahd_format_transinfo(info, &tinfo->user);
targ = ahd->platform_data->targets[target_offset];
......@@ -318,7 +317,11 @@ ahd_linux_proc_info(char *buffer, char **start, off_t offset,
AIC79XX_DRIVER_VERSION);
copy_info(&info, "%s\n", ahd->description);
ahd_controller_info(ahd, ahd_info);
copy_info(&info, "%s\n\n", ahd_info);
copy_info(&info, "%s\n", ahd_info);
copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n",
ahd->scb_data.numscbs, ahd_linux_nseg);
max_targ = 15;
if (ahd->seep_config == NULL)
copy_info(&info, "No Serial EEPROM\n");
......@@ -335,7 +338,6 @@ ahd_linux_proc_info(char *buffer, char **start, off_t offset,
}
copy_info(&info, "\n");
max_targ = 15;
if ((ahd->features & AHD_WIDE) == 0)
max_targ = 7;
......
......@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#89 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#65 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#91 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#67 $
*/
typedef int (ahd_reg_print_t)(u_int, u_int *, u_int);
typedef struct ahd_reg_parse_entry {
......@@ -1923,18 +1923,11 @@ ahd_reg_print_t ahd_longjmp_addr_print;
ahd_print_register(NULL, 0, "LONGJMP_ADDR", 0xf8, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_longjmp_scb_print;
#else
#define ahd_longjmp_scb_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "LONGJMP_SCB", 0xfa, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_accum_save_print;
#else
#define ahd_accum_save_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "ACCUM_SAVE", 0xfc, regvalue, cur_col, wrap)
ahd_print_register(NULL, 0, "ACCUM_SAVE", 0xfa, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
......@@ -2246,59 +2239,45 @@ ahd_reg_print_t ahd_scb_sense_busaddr_print;
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_tag_print;
#else
#define ahd_scb_tag_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_TAG", 0x190, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_cdb_len_print;
#else
#define ahd_scb_cdb_len_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_CDB_LEN", 0x192, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_task_management_print;
ahd_reg_print_t ahd_scb_dataptr_print;
#else
#define ahd_scb_task_management_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_TASK_MANAGEMENT", 0x193, regvalue, cur_col, wrap)
#define ahd_scb_dataptr_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_DATAPTR", 0x190, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_next_print;
ahd_reg_print_t ahd_scb_datacnt_print;
#else
#define ahd_scb_next_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_NEXT", 0x194, regvalue, cur_col, wrap)
#define ahd_scb_datacnt_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_DATACNT", 0x198, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_next2_print;
ahd_reg_print_t ahd_scb_sgptr_print;
#else
#define ahd_scb_next2_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_NEXT2", 0x196, regvalue, cur_col, wrap)
#define ahd_scb_sgptr_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_SGPTR", 0x19c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_dataptr_print;
ahd_reg_print_t ahd_scb_busaddr_print;
#else
#define ahd_scb_dataptr_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_DATAPTR", 0x198, regvalue, cur_col, wrap)
#define ahd_scb_busaddr_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_BUSADDR", 0x1a0, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_datacnt_print;
ahd_reg_print_t ahd_scb_next_print;
#else
#define ahd_scb_datacnt_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_DATACNT", 0x1a0, regvalue, cur_col, wrap)
#define ahd_scb_next_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_NEXT", 0x1a4, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_sgptr_print;
ahd_reg_print_t ahd_scb_next2_print;
#else
#define ahd_scb_sgptr_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_SGPTR", 0x1a4, regvalue, cur_col, wrap)
#define ahd_scb_next2_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_NEXT2", 0x1a6, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
......@@ -2330,10 +2309,24 @@ ahd_reg_print_t ahd_scb_task_attribute_print;
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_busaddr_print;
ahd_reg_print_t ahd_scb_cdb_len_print;
#else
#define ahd_scb_busaddr_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_BUSADDR", 0x1ac, regvalue, cur_col, wrap)
#define ahd_scb_cdb_len_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_CDB_LEN", 0x1ac, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_task_management_print;
#else
#define ahd_scb_task_management_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_TASK_MANAGEMENT", 0x1ad, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_tag_print;
#else
#define ahd_scb_tag_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_TAG", 0x1ae, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
......@@ -2367,6 +2360,7 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SPLTINT 0x01
#define SEQINTCODE 0x02
#define BAD_SCB_STATUS 0x1a
#define SAW_HWERR 0x19
#define TRACEPOINT3 0x18
#define TRACEPOINT2 0x17
......@@ -3508,9 +3502,7 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define LONGJMP_ADDR 0xf8
#define LONGJMP_SCB 0xfa
#define ACCUM_SAVE 0xfc
#define ACCUM_SAVE 0xfa
#define WAITING_SCB_TAILS 0x100
......@@ -3656,29 +3648,24 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SCB_SENSE_BUSADDR 0x18c
#define SCB_NEXT_COMPLETE 0x18c
#define SCB_TAG 0x190
#define SCB_CDB_LEN 0x192
#define SCB_CDB_LEN_PTR 0x80
#define SCB_TASK_MANAGEMENT 0x193
#define SCB_NEXT 0x194
#define SCB_NEXT_SCB_BUSADDR 0x194
#define SCB_DATAPTR 0x190
#define SCB_NEXT2 0x196
#define SCB_DATAPTR 0x198
#define SCB_DATACNT 0x1a0
#define SCB_DATACNT 0x198
#define SG_LAST_SEG 0x80
#define SG_HIGH_ADDR_BITS 0x7f
#define SCB_SGPTR 0x1a4
#define SCB_SGPTR 0x19c
#define SG_STATUS_VALID 0x04
#define SG_FULL_RESID 0x02
#define SG_LIST_NULL 0x01
#define SCB_BUSADDR 0x1a0
#define SCB_NEXT 0x1a4
#define SCB_NEXT_SCB_BUSADDR 0x1a4
#define SCB_NEXT2 0x1a6
#define SCB_CONTROL 0x1a8
#define TARGET_SCB 0x80
#define DISCENB 0x40
......@@ -3697,7 +3684,13 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SCB_TASK_ATTRIBUTE 0x1ab
#define SCB_BUSADDR 0x1ac
#define SCB_CDB_LEN 0x1ac
#define SCB_CDB_LEN_PTR 0x80
#define SCB_TASK_MANAGEMENT 0x1ad
#define SCB_TAG 0x1ae
#define SCB_FIFO_USE_COUNT 0x1ae
#define SCB_SPARE 0x1b0
#define SCB_PKT_LUN 0x1b0
......@@ -3775,5 +3768,5 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
/* Exported Labels */
#define LABEL_seq_isr 0x26d
#define LABEL_timer_isr 0x269
#define LABEL_seq_isr 0x270
#define LABEL_timer_isr 0x26c
......@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#89 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#65 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#91 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#67 $
*/
#include "aic79xx_osm.h"
......@@ -65,13 +65,14 @@ static ahd_reg_parse_entry_t SEQINTCODE_parse_table[] = {
{ "TRACEPOINT1", 0x16, 0xff },
{ "TRACEPOINT2", 0x17, 0xff },
{ "TRACEPOINT3", 0x18, 0xff },
{ "SAW_HWERR", 0x19, 0xff }
{ "SAW_HWERR", 0x19, 0xff },
{ "BAD_SCB_STATUS", 0x1a, 0xff }
};
int
ahd_seqintcode_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(SEQINTCODE_parse_table, 26, "SEQINTCODE",
return (ahd_print_register(SEQINTCODE_parse_table, 27, "SEQINTCODE",
0x02, regvalue, cur_col, wrap));
}
......@@ -3097,18 +3098,11 @@ ahd_longjmp_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xf8, regvalue, cur_col, wrap));
}
int
ahd_longjmp_scb_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "LONGJMP_SCB",
0xfa, regvalue, cur_col, wrap));
}
int
ahd_accum_save_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "ACCUM_SAVE",
0xfc, regvalue, cur_col, wrap));
0xfa, regvalue, cur_col, wrap));
}
int
......@@ -3491,50 +3485,11 @@ ahd_scb_sense_busaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x18c, regvalue, cur_col, wrap));
}
int
ahd_scb_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_TAG",
0x190, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t SCB_CDB_LEN_parse_table[] = {
{ "SCB_CDB_LEN_PTR", 0x80, 0x80 }
};
int
ahd_scb_cdb_len_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(SCB_CDB_LEN_parse_table, 1, "SCB_CDB_LEN",
0x192, regvalue, cur_col, wrap));
}
int
ahd_scb_task_management_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_TASK_MANAGEMENT",
0x193, regvalue, cur_col, wrap));
}
int
ahd_scb_next_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_NEXT",
0x194, regvalue, cur_col, wrap));
}
int
ahd_scb_next2_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_NEXT2",
0x196, regvalue, cur_col, wrap));
}
int
ahd_scb_dataptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_DATAPTR",
0x198, regvalue, cur_col, wrap));
0x190, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t SCB_DATACNT_parse_table[] = {
......@@ -3546,7 +3501,7 @@ int
ahd_scb_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(SCB_DATACNT_parse_table, 2, "SCB_DATACNT",
0x1a0, regvalue, cur_col, wrap));
0x198, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t SCB_SGPTR_parse_table[] = {
......@@ -3559,9 +3514,30 @@ int
ahd_scb_sgptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(SCB_SGPTR_parse_table, 3, "SCB_SGPTR",
0x19c, regvalue, cur_col, wrap));
}
int
ahd_scb_busaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_BUSADDR",
0x1a0, regvalue, cur_col, wrap));
}
int
ahd_scb_next_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_NEXT",
0x1a4, regvalue, cur_col, wrap));
}
int
ahd_scb_next2_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_NEXT2",
0x1a6, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
{ "SCB_TAG_TYPE", 0x03, 0x03 },
{ "DISCONNECTED", 0x04, 0x04 },
......@@ -3609,13 +3585,31 @@ ahd_scb_task_attribute_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x1ab, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t SCB_CDB_LEN_parse_table[] = {
{ "SCB_CDB_LEN_PTR", 0x80, 0x80 }
};
int
ahd_scb_busaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
ahd_scb_cdb_len_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_BUSADDR",
return (ahd_print_register(SCB_CDB_LEN_parse_table, 1, "SCB_CDB_LEN",
0x1ac, regvalue, cur_col, wrap));
}
int
ahd_scb_task_management_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_TASK_MANAGEMENT",
0x1ad, regvalue, cur_col, wrap));
}
int
ahd_scb_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_TAG",
0x1ae, regvalue, cur_col, wrap));
}
int
ahd_scb_spare_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
......
......@@ -2,102 +2,104 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#89 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#65 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#91 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#67 $
*/
static uint8_t seqprog[] = {
0xff, 0x02, 0x06, 0x78,
0x00, 0xea, 0x50, 0x59,
0x00, 0xea, 0x4e, 0x59,
0x01, 0xea, 0x04, 0x30,
0xff, 0x04, 0x0c, 0x78,
0x19, 0xea, 0x50, 0x59,
0x19, 0xea, 0x4e, 0x59,
0x19, 0xea, 0x04, 0x00,
0x33, 0xea, 0x44, 0x59,
0x33, 0xea, 0x42, 0x59,
0x33, 0xea, 0x00, 0x00,
0x60, 0x3a, 0x1a, 0x68,
0x04, 0x47, 0x1b, 0x68,
0xff, 0x21, 0x1b, 0x70,
0x40, 0x4b, 0x92, 0x69,
0x00, 0xe2, 0x54, 0x59,
0x40, 0x4b, 0x92, 0x69,
0x20, 0x4b, 0x82, 0x69,
0x40, 0x4b, 0x90, 0x69,
0x00, 0xe2, 0x52, 0x59,
0x40, 0x4b, 0x90, 0x69,
0x20, 0x4b, 0x80, 0x69,
0xfc, 0x42, 0x24, 0x78,
0x10, 0x40, 0x24, 0x78,
0x00, 0xe2, 0xe0, 0x5d,
0x00, 0xe2, 0xd2, 0x5d,
0x20, 0x4d, 0x28, 0x78,
0x00, 0xe2, 0xe0, 0x5d,
0x00, 0xe2, 0xd2, 0x5d,
0x30, 0x3f, 0xc0, 0x09,
0x30, 0xe0, 0x30, 0x60,
0x7f, 0x4a, 0x94, 0x08,
0x00, 0xe2, 0x32, 0x40,
0xc0, 0x4a, 0x94, 0x00,
0x00, 0xe2, 0x3e, 0x58,
0x00, 0xe2, 0x70, 0x58,
0x00, 0xe2, 0x80, 0x58,
0x00, 0xe2, 0x56, 0x58,
0x00, 0xe2, 0x66, 0x58,
0x00, 0xe2, 0x06, 0x40,
0x33, 0xea, 0x44, 0x59,
0x33, 0xea, 0x42, 0x59,
0x33, 0xea, 0x00, 0x00,
0x01, 0x52, 0x96, 0x7d,
0x01, 0x52, 0x64, 0x78,
0x02, 0x58, 0x50, 0x31,
0xff, 0xea, 0x10, 0x0b,
0xff, 0x93, 0x4f, 0x78,
0xff, 0xad, 0x4f, 0x78,
0x50, 0x4b, 0x4a, 0x68,
0xbf, 0x3a, 0x74, 0x08,
0x14, 0xea, 0x50, 0x59,
0x14, 0xea, 0x4e, 0x59,
0x14, 0xea, 0x04, 0x00,
0x08, 0xa8, 0x51, 0x03,
0x01, 0xa4, 0x57, 0x78,
0x00, 0xe2, 0x4c, 0x5b,
0xff, 0xae, 0x3f, 0x68,
0x00, 0xe2, 0x50, 0x5b,
0x00, 0xe2, 0x3e, 0x40,
0xff, 0xea, 0xd4, 0x19,
0x02, 0xa8, 0x84, 0x32,
0x00, 0xea, 0x44, 0x59,
0x00, 0xea, 0x42, 0x59,
0x01, 0xea, 0x00, 0x30,
0x00, 0xe2, 0xcc, 0x5d,
0x00, 0xe2, 0x96, 0x4d,
0x11, 0xea, 0x44, 0x59,
0x80, 0xf9, 0x5e, 0x68,
0x00, 0xe2, 0x40, 0x59,
0x11, 0xea, 0x42, 0x59,
0x11, 0xea, 0x00, 0x00,
0x00, 0xe2, 0xcc, 0x5d,
0x00, 0xe2, 0x96, 0x4d,
0x33, 0xea, 0x44, 0x59,
0x33, 0xea, 0x00, 0x00,
0x00, 0xe2, 0x44, 0x43,
0x00, 0xea, 0x44, 0x59,
0x01, 0xea, 0x00, 0x30,
0x80, 0xf9, 0x78, 0x68,
0x00, 0xe2, 0x42, 0x59,
0x11, 0xea, 0x44, 0x59,
0x11, 0xea, 0x00, 0x00,
0x80, 0xf9, 0x42, 0x79,
0x80, 0xf9, 0x40, 0x79,
0xff, 0xea, 0xd4, 0x0d,
0x22, 0xea, 0x44, 0x59,
0x22, 0xea, 0x42, 0x59,
0x22, 0xea, 0x00, 0x00,
0x10, 0x16, 0x8a, 0x78,
0x10, 0x16, 0x70, 0x78,
0x01, 0x0b, 0xa2, 0x32,
0x10, 0x16, 0x2c, 0x00,
0x18, 0xad, 0xf8, 0x78,
0x04, 0xad, 0xc6, 0x68,
0x80, 0xad, 0x96, 0x7d,
0x10, 0xad, 0x94, 0x78,
0xe7, 0xad, 0x5a, 0x0d,
0x18, 0xad, 0xfe, 0x78,
0x04, 0xad, 0xca, 0x68,
0x80, 0xad, 0x64, 0x78,
0x10, 0xad, 0x98, 0x78,
0xff, 0x88, 0x83, 0x68,
0xe7, 0xad, 0x5a, 0x09,
0x02, 0x8c, 0x59, 0x32,
0x02, 0x28, 0x19, 0x33,
0x02, 0xa8, 0x50, 0x36,
0x33, 0xea, 0x42, 0x59,
0x33, 0xea, 0x00, 0x00,
0x40, 0x3a, 0x64, 0x68,
0x50, 0x4b, 0x64, 0x68,
0x22, 0xea, 0x42, 0x59,
0x22, 0xea, 0x00, 0x00,
0xe7, 0xad, 0x5a, 0x09,
0x00, 0xe2, 0xa2, 0x58,
0x02, 0x8c, 0x59, 0x32,
0x1a, 0xea, 0x4e, 0x59,
0x1a, 0xea, 0x04, 0x00,
0xff, 0xea, 0xd4, 0x0d,
0xe7, 0xad, 0x5a, 0x09,
0x00, 0xe2, 0xa6, 0x58,
0xff, 0xea, 0x56, 0x02,
0x04, 0x7c, 0x78, 0x32,
0x20, 0x16, 0x96, 0x7d,
0x20, 0x16, 0x64, 0x78,
0x04, 0x38, 0x79, 0x32,
0x80, 0x37, 0x6f, 0x16,
0xff, 0x2d, 0xb1, 0x60,
0xff, 0x29, 0xb1, 0x60,
0x40, 0x51, 0xc1, 0x78,
0xff, 0x4f, 0xb1, 0x68,
0xff, 0x2d, 0xb5, 0x60,
0xff, 0x29, 0xb5, 0x60,
0x40, 0x51, 0xc5, 0x78,
0xff, 0x4f, 0xb5, 0x68,
0xff, 0x4d, 0xc1, 0x19,
0x00, 0x4e, 0xd5, 0x19,
0x00, 0xe2, 0xc0, 0x50,
0x00, 0xe2, 0xc4, 0x50,
0x01, 0x4c, 0xc1, 0x31,
0x00, 0x50, 0xd5, 0x19,
0x00, 0xe2, 0xc0, 0x48,
0x80, 0x18, 0x96, 0x7d,
0x00, 0xe2, 0xc4, 0x48,
0x80, 0x18, 0x64, 0x78,
0x02, 0x4a, 0x1d, 0x30,
0x10, 0xea, 0x18, 0x00,
0x60, 0x18, 0x30, 0x00,
......@@ -105,35 +107,36 @@ static uint8_t seqprog[] = {
0x02, 0xea, 0x02, 0x00,
0xff, 0xea, 0xa0, 0x0a,
0x80, 0x18, 0x30, 0x04,
0x40, 0xad, 0x96, 0x7d,
0x40, 0xad, 0x64, 0x78,
0xe7, 0xad, 0x5a, 0x09,
0x02, 0xa8, 0x40, 0x31,
0xff, 0xea, 0xc0, 0x09,
0x01, 0x4e, 0x9d, 0x1a,
0x00, 0x4f, 0x9f, 0x22,
0x04, 0x94, 0x49, 0x32,
0xff, 0xea, 0x2a, 0x03,
0xff, 0xea, 0x2e, 0x03,
0x01, 0xea, 0x5c, 0x33,
0x04, 0xa4, 0x49, 0x32,
0xff, 0xea, 0x4a, 0x03,
0xff, 0xea, 0x4e, 0x03,
0x01, 0x10, 0xd4, 0x31,
0x10, 0xa8, 0xed, 0x68,
0x10, 0xa8, 0xf3, 0x68,
0x3d, 0xa9, 0xc5, 0x29,
0xfe, 0xe2, 0xc4, 0x09,
0x01, 0xea, 0xc6, 0x01,
0x02, 0xe2, 0xc8, 0x31,
0x02, 0xec, 0x50, 0x31,
0x02, 0xa0, 0xda, 0x31,
0xff, 0xa9, 0xec, 0x70,
0x02, 0xa0, 0x28, 0x37,
0xff, 0x21, 0xf5, 0x70,
0xff, 0xa9, 0xf2, 0x70,
0x02, 0xa0, 0x48, 0x37,
0xff, 0x21, 0xfb, 0x70,
0x02, 0x22, 0x51, 0x31,
0x02, 0xa0, 0x2c, 0x33,
0x02, 0xa0, 0x4c, 0x33,
0x02, 0xa0, 0x44, 0x36,
0x02, 0xa0, 0x40, 0x32,
0x02, 0xa0, 0x44, 0x36,
0x04, 0x47, 0xfd, 0x68,
0x40, 0x16, 0x28, 0x69,
0xff, 0x2d, 0x2d, 0x61,
0xff, 0x29, 0x97, 0x75,
0x04, 0x47, 0x03, 0x69,
0x40, 0x16, 0x2e, 0x69,
0xff, 0x2d, 0x33, 0x61,
0xff, 0x29, 0x65, 0x70,
0x01, 0x37, 0xc1, 0x31,
0x02, 0x28, 0x55, 0x32,
0x01, 0xea, 0x5a, 0x01,
......@@ -145,11 +148,11 @@ static uint8_t seqprog[] = {
0x01, 0x50, 0xa1, 0x1a,
0xff, 0x4e, 0x9d, 0x1a,
0xff, 0x4f, 0x9f, 0x22,
0xff, 0x8d, 0x21, 0x71,
0x80, 0xac, 0x20, 0x71,
0x20, 0x16, 0x20, 0x69,
0xff, 0x8d, 0x27, 0x71,
0x80, 0xac, 0x26, 0x71,
0x20, 0x16, 0x26, 0x69,
0x02, 0x8c, 0x51, 0x31,
0x00, 0xe2, 0x0a, 0x41,
0x00, 0xe2, 0x10, 0x41,
0x01, 0xac, 0x08, 0x31,
0x09, 0xea, 0x5a, 0x01,
0x02, 0x8c, 0x51, 0x32,
......@@ -157,14 +160,10 @@ static uint8_t seqprog[] = {
0x04, 0x24, 0xf9, 0x30,
0x1d, 0xea, 0x38, 0x41,
0x02, 0x2c, 0x51, 0x31,
0x04, 0xac, 0xf9, 0x30,
0x19, 0xea, 0x38, 0x59,
0x02, 0x8c, 0x59, 0x32,
0x02, 0x28, 0x19, 0x33,
0x02, 0xa8, 0x50, 0x36,
0x04, 0xa0, 0xf9, 0x30,
0x19, 0xea, 0x38, 0x41,
0x06, 0xea, 0x08, 0x81,
0x01, 0xe2, 0x5a, 0x35,
0x02, 0xa8, 0xf4, 0x31,
0x02, 0xf2, 0xf0, 0x35,
0x02, 0xf2, 0xf0, 0x31,
0x02, 0xf8, 0xe4, 0x35,
......@@ -180,23 +179,23 @@ static uint8_t seqprog[] = {
0x02, 0x20, 0xb9, 0x30,
0x02, 0x20, 0x51, 0x31,
0x4c, 0xa9, 0xd7, 0x28,
0x10, 0xa8, 0x63, 0x79,
0x10, 0xa8, 0x61, 0x79,
0x01, 0x6b, 0xc0, 0x30,
0x02, 0x64, 0xc8, 0x00,
0x40, 0x3a, 0x74, 0x04,
0x00, 0xe2, 0x70, 0x58,
0x33, 0xea, 0x44, 0x59,
0x00, 0xe2, 0x56, 0x58,
0x33, 0xea, 0x42, 0x59,
0x33, 0xea, 0x00, 0x00,
0x30, 0x3f, 0xc0, 0x09,
0x30, 0xe0, 0x64, 0x61,
0x20, 0x3f, 0x7a, 0x69,
0x10, 0x3f, 0x64, 0x79,
0x30, 0xe0, 0x62, 0x61,
0x20, 0x3f, 0x78, 0x69,
0x10, 0x3f, 0x62, 0x79,
0x02, 0xea, 0x7e, 0x00,
0x00, 0xea, 0x44, 0x59,
0x00, 0xea, 0x42, 0x59,
0x01, 0xea, 0x00, 0x30,
0x02, 0x48, 0x51, 0x35,
0x01, 0xea, 0x7e, 0x00,
0x11, 0xea, 0x44, 0x59,
0x11, 0xea, 0x42, 0x59,
0x11, 0xea, 0x00, 0x00,
0x02, 0x48, 0x51, 0x35,
0x08, 0xea, 0x98, 0x00,
......@@ -206,11 +205,11 @@ static uint8_t seqprog[] = {
0x0f, 0x67, 0xc0, 0x09,
0x00, 0x34, 0x69, 0x02,
0x20, 0xea, 0x96, 0x00,
0x00, 0xe2, 0xf8, 0x41,
0x40, 0x3a, 0xae, 0x69,
0x00, 0xe2, 0xf6, 0x41,
0x40, 0x3a, 0xac, 0x69,
0x02, 0x55, 0x06, 0x68,
0x02, 0x56, 0xae, 0x69,
0xff, 0x5b, 0xae, 0x61,
0x02, 0x56, 0xac, 0x69,
0xff, 0x5b, 0xac, 0x61,
0x02, 0x20, 0x51, 0x31,
0x80, 0xea, 0xb2, 0x01,
0x44, 0xea, 0x00, 0x00,
......@@ -218,36 +217,36 @@ static uint8_t seqprog[] = {
0x33, 0xea, 0x00, 0x00,
0xff, 0xea, 0xb2, 0x09,
0xff, 0xe0, 0xc0, 0x19,
0xff, 0xe0, 0xb0, 0x79,
0x02, 0x94, 0x51, 0x31,
0x00, 0xe2, 0xa6, 0x41,
0xff, 0xe0, 0xae, 0x79,
0x02, 0xa4, 0x51, 0x31,
0x00, 0xe2, 0xa4, 0x41,
0x02, 0x5e, 0x50, 0x31,
0x02, 0xa8, 0xb8, 0x30,
0x02, 0x5c, 0x50, 0x31,
0xff, 0x95, 0xc1, 0x71,
0x02, 0x94, 0x41, 0x31,
0xff, 0xa5, 0xbf, 0x71,
0x02, 0xa4, 0x41, 0x31,
0x02, 0x22, 0x51, 0x31,
0x02, 0xa0, 0x2c, 0x33,
0x02, 0xa0, 0x4c, 0x33,
0x02, 0xa0, 0x44, 0x32,
0x00, 0xe2, 0xca, 0x41,
0x10, 0xa8, 0xcb, 0x69,
0x00, 0xe2, 0xc8, 0x41,
0x10, 0xa8, 0xc9, 0x69,
0x3d, 0xa9, 0xc9, 0x29,
0x01, 0xe4, 0xc8, 0x01,
0x01, 0xea, 0xca, 0x01,
0xff, 0xea, 0xda, 0x01,
0x02, 0x20, 0x51, 0x31,
0x02, 0x96, 0x41, 0x32,
0xff, 0x21, 0xd3, 0x61,
0x02, 0xa6, 0x41, 0x32,
0xff, 0x21, 0xd1, 0x61,
0xff, 0xea, 0x46, 0x02,
0x02, 0x5c, 0x50, 0x31,
0x40, 0xea, 0x96, 0x00,
0x02, 0x56, 0xe8, 0x6d,
0x01, 0x55, 0xe8, 0x6d,
0x10, 0xa8, 0xdf, 0x79,
0x10, 0x40, 0xe8, 0x69,
0x01, 0x56, 0xe8, 0x79,
0xff, 0x93, 0x07, 0x78,
0x13, 0xea, 0x50, 0x59,
0x02, 0x56, 0xda, 0x6d,
0x01, 0x55, 0xda, 0x6d,
0x10, 0xa8, 0xdd, 0x79,
0x10, 0x40, 0xe6, 0x69,
0x01, 0x56, 0xe6, 0x79,
0xff, 0xad, 0x07, 0x78,
0x13, 0xea, 0x4e, 0x59,
0x13, 0xea, 0x04, 0x00,
0x00, 0xe2, 0x06, 0x40,
0xbf, 0x3a, 0x74, 0x08,
......@@ -258,104 +257,104 @@ static uint8_t seqprog[] = {
0x40, 0xea, 0x66, 0x02,
0x08, 0x3c, 0x78, 0x00,
0x80, 0xea, 0x62, 0x02,
0x00, 0xe2, 0xac, 0x5b,
0x00, 0xe2, 0xb2, 0x5b,
0x01, 0x36, 0xc1, 0x31,
0x9f, 0xe0, 0x4e, 0x7c,
0x80, 0xe0, 0x0c, 0x72,
0xa0, 0xe0, 0x44, 0x72,
0xc0, 0xe0, 0x3a, 0x72,
0xe0, 0xe0, 0x74, 0x72,
0x01, 0xea, 0x50, 0x59,
0x9f, 0xe0, 0x54, 0x7c,
0x80, 0xe0, 0x0a, 0x72,
0xa0, 0xe0, 0x42, 0x72,
0xc0, 0xe0, 0x38, 0x72,
0xe0, 0xe0, 0x72, 0x72,
0x01, 0xea, 0x4e, 0x59,
0x01, 0xea, 0x04, 0x00,
0x00, 0xe2, 0xf8, 0x41,
0x80, 0x33, 0x13, 0x7a,
0x03, 0xea, 0x50, 0x59,
0x00, 0xe2, 0xf6, 0x41,
0x80, 0x33, 0x11, 0x7a,
0x03, 0xea, 0x4e, 0x59,
0x03, 0xea, 0x04, 0x00,
0xee, 0x00, 0x1a, 0x6a,
0xee, 0x00, 0x18, 0x6a,
0x05, 0xea, 0xb4, 0x00,
0x33, 0xea, 0x44, 0x59,
0x33, 0xea, 0x42, 0x59,
0x33, 0xea, 0x00, 0x00,
0x02, 0xa8, 0x90, 0x32,
0x00, 0xe2, 0x6a, 0x59,
0xef, 0x92, 0xd5, 0x19,
0x00, 0xe2, 0x2a, 0x52,
0x00, 0xe2, 0x68, 0x59,
0xef, 0xac, 0xd5, 0x19,
0x00, 0xe2, 0x28, 0x52,
0x09, 0x80, 0xe1, 0x30,
0x02, 0xea, 0x36, 0x00,
0xa8, 0xea, 0x32, 0x00,
0x00, 0xe2, 0x30, 0x42,
0x01, 0x92, 0xd1, 0x30,
0x00, 0xe2, 0x2e, 0x42,
0x01, 0xac, 0xd1, 0x30,
0x10, 0x80, 0x89, 0x31,
0x20, 0xea, 0x32, 0x00,
0xbf, 0x33, 0x67, 0x0a,
0x20, 0x19, 0x32, 0x6a,
0x02, 0x4d, 0xf8, 0x69,
0x20, 0x19, 0x30, 0x6a,
0x02, 0x4d, 0xf6, 0x69,
0x40, 0x33, 0x67, 0x02,
0x00, 0xe2, 0xf8, 0x41,
0x80, 0x33, 0xb1, 0x6a,
0x00, 0xe2, 0xf6, 0x41,
0x80, 0x33, 0xaf, 0x6a,
0x01, 0x44, 0x10, 0x33,
0x08, 0xa8, 0x51, 0x03,
0x00, 0xe2, 0xf8, 0x41,
0x00, 0xe2, 0xf6, 0x41,
0x10, 0xea, 0x80, 0x00,
0x01, 0x31, 0xc5, 0x31,
0x80, 0xe2, 0x60, 0x62,
0x10, 0xa8, 0x85, 0x6a,
0x80, 0xe2, 0x5e, 0x62,
0x10, 0xa8, 0x83, 0x6a,
0xc0, 0xaa, 0xc5, 0x01,
0x40, 0xa8, 0x51, 0x6a,
0x40, 0xa8, 0x4f, 0x6a,
0xbf, 0xe2, 0xc4, 0x09,
0x20, 0xa8, 0x65, 0x7a,
0x20, 0xa8, 0x63, 0x7a,
0x01, 0xe2, 0x88, 0x30,
0x00, 0xe2, 0xac, 0x5b,
0xa0, 0x36, 0x6d, 0x62,
0x00, 0xe2, 0xb2, 0x5b,
0xa0, 0x36, 0x6b, 0x62,
0x23, 0xa8, 0x89, 0x08,
0x00, 0xe2, 0xac, 0x5b,
0xa0, 0x36, 0x6d, 0x62,
0x00, 0xa8, 0x64, 0x42,
0xff, 0xe2, 0x64, 0x62,
0x00, 0xe2, 0x84, 0x42,
0x00, 0xe2, 0xb2, 0x5b,
0xa0, 0x36, 0x6b, 0x62,
0x00, 0xa8, 0x62, 0x42,
0xff, 0xe2, 0x62, 0x62,
0x00, 0xe2, 0x82, 0x42,
0x40, 0xea, 0x98, 0x00,
0x01, 0xe2, 0x88, 0x30,
0x00, 0xe2, 0xac, 0x5b,
0xa0, 0x36, 0x43, 0x72,
0x00, 0xe2, 0xb2, 0x5b,
0xa0, 0x36, 0x41, 0x72,
0x40, 0xea, 0x98, 0x00,
0x01, 0x31, 0x89, 0x32,
0x08, 0xea, 0x62, 0x02,
0x00, 0xe2, 0xf8, 0x41,
0xe0, 0xea, 0xc8, 0x5b,
0x80, 0xe0, 0xbc, 0x6a,
0x04, 0xe0, 0x5a, 0x73,
0x02, 0xe0, 0x8a, 0x73,
0x00, 0xea, 0x1a, 0x73,
0x03, 0xe0, 0x9a, 0x73,
0x23, 0xe0, 0x96, 0x72,
0x08, 0xe0, 0xb8, 0x72,
0x00, 0xe2, 0xac, 0x5b,
0x07, 0xea, 0x50, 0x59,
0x00, 0xe2, 0xf6, 0x41,
0xe0, 0xea, 0xce, 0x5b,
0x80, 0xe0, 0xba, 0x6a,
0x04, 0xe0, 0x60, 0x73,
0x02, 0xe0, 0x90, 0x73,
0x00, 0xea, 0x18, 0x73,
0x03, 0xe0, 0xa0, 0x73,
0x23, 0xe0, 0x94, 0x72,
0x08, 0xe0, 0xb6, 0x72,
0x00, 0xe2, 0xb2, 0x5b,
0x07, 0xea, 0x4e, 0x59,
0x07, 0xea, 0x04, 0x00,
0x08, 0x42, 0xf9, 0x71,
0x04, 0x42, 0x93, 0x62,
0x08, 0x42, 0xf7, 0x71,
0x04, 0x42, 0x91, 0x62,
0x01, 0x43, 0x89, 0x30,
0x00, 0xe2, 0x84, 0x42,
0x00, 0xe2, 0x82, 0x42,
0x01, 0x44, 0xd4, 0x31,
0x00, 0xe2, 0x84, 0x42,
0x00, 0xe2, 0x82, 0x42,
0x01, 0x00, 0x60, 0x32,
0x33, 0xea, 0x44, 0x59,
0x33, 0xea, 0x42, 0x59,
0x33, 0xea, 0x00, 0x00,
0x4c, 0x34, 0xc1, 0x28,
0x01, 0x64, 0xc0, 0x31,
0x00, 0x30, 0x45, 0x59,
0x00, 0x30, 0x43, 0x59,
0x01, 0x30, 0x01, 0x30,
0x01, 0xe0, 0xb6, 0x7a,
0xa0, 0xea, 0xbe, 0x5b,
0x01, 0xa0, 0xb6, 0x62,
0x01, 0x84, 0xaf, 0x7a,
0x01, 0xa7, 0xb8, 0x7a,
0x00, 0xe2, 0xb8, 0x42,
0x03, 0xea, 0x50, 0x59,
0x01, 0xe0, 0xb4, 0x7a,
0xa0, 0xea, 0xc4, 0x5b,
0x01, 0xa0, 0xb4, 0x62,
0x01, 0x84, 0xad, 0x7a,
0x01, 0xa7, 0xb6, 0x7a,
0x00, 0xe2, 0xb6, 0x42,
0x03, 0xea, 0x4e, 0x59,
0x03, 0xea, 0x04, 0x00,
0x00, 0xe2, 0xb8, 0x42,
0x07, 0xea, 0xd0, 0x5b,
0x00, 0xe2, 0xb6, 0x42,
0x07, 0xea, 0xd6, 0x5b,
0x01, 0x44, 0xd4, 0x31,
0x00, 0xe2, 0xf8, 0x41,
0x00, 0xe2, 0xf6, 0x41,
0x3f, 0xe0, 0x6a, 0x0a,
0xc0, 0x34, 0xc1, 0x09,
0x00, 0x35, 0x51, 0x01,
......@@ -366,78 +365,82 @@ static uint8_t seqprog[] = {
0x01, 0xea, 0xc6, 0x01,
0x02, 0xe2, 0xc8, 0x31,
0x02, 0xec, 0x40, 0x31,
0xff, 0xa1, 0xd8, 0x72,
0xff, 0xa1, 0xd6, 0x72,
0x02, 0xe8, 0xda, 0x31,
0x02, 0xa0, 0x50, 0x31,
0x00, 0xe2, 0xfa, 0x42,
0x00, 0xe2, 0xf8, 0x42,
0x80, 0x33, 0x67, 0x02,
0x01, 0x44, 0xd4, 0x31,
0x00, 0xe2, 0xac, 0x5b,
0x00, 0xe2, 0xb2, 0x5b,
0x01, 0x33, 0x67, 0x02,
0xe0, 0x36, 0x15, 0x63,
0xe0, 0x36, 0x13, 0x63,
0x02, 0x33, 0x67, 0x02,
0x20, 0x46, 0x0e, 0x63,
0x20, 0x46, 0x0c, 0x63,
0xff, 0xea, 0x52, 0x09,
0xa8, 0xea, 0xbe, 0x5b,
0x04, 0xa8, 0xf5, 0x7a,
0xa8, 0xea, 0xc4, 0x5b,
0x04, 0xa8, 0xf3, 0x7a,
0x01, 0x34, 0xc1, 0x31,
0x00, 0xa9, 0xf5, 0x62,
0x00, 0xa9, 0xf3, 0x62,
0x01, 0x35, 0xc1, 0x31,
0x00, 0xaa, 0xff, 0x72,
0x00, 0xaa, 0xfd, 0x72,
0x01, 0xa9, 0x52, 0x11,
0xff, 0xa9, 0xea, 0x6a,
0x00, 0xe2, 0x0e, 0x43,
0xff, 0xa9, 0xe8, 0x6a,
0x00, 0xe2, 0x0c, 0x43,
0x10, 0x33, 0x67, 0x02,
0x04, 0xa8, 0x0f, 0x7b,
0x04, 0xa8, 0x0d, 0x7b,
0xfb, 0xa8, 0x51, 0x0b,
0xff, 0xea, 0x66, 0x0a,
0x01, 0xa4, 0x09, 0x6b,
0x01, 0x9c, 0x07, 0x6b,
0x02, 0xa8, 0x90, 0x32,
0x00, 0xe2, 0x6a, 0x59,
0x10, 0xa8, 0xb9, 0x7a,
0xff, 0xea, 0xd0, 0x5b,
0x00, 0xe2, 0xb8, 0x42,
0x04, 0xea, 0x50, 0x59,
0x00, 0xe2, 0x68, 0x59,
0x10, 0xa8, 0xb7, 0x7a,
0xff, 0xea, 0xd6, 0x5b,
0x00, 0xe2, 0xb6, 0x42,
0x04, 0xea, 0x4e, 0x59,
0x04, 0xea, 0x04, 0x00,
0x00, 0xe2, 0xb8, 0x42,
0x04, 0xea, 0x50, 0x59,
0x00, 0xe2, 0xb6, 0x42,
0x04, 0xea, 0x4e, 0x59,
0x04, 0xea, 0x04, 0x00,
0x00, 0xe2, 0xf8, 0x41,
0x08, 0xa8, 0xb1, 0x7a,
0xc0, 0x33, 0x25, 0x7b,
0x80, 0x33, 0xb1, 0x6a,
0xff, 0x88, 0x25, 0x6b,
0x40, 0x33, 0xb1, 0x6a,
0x10, 0xa8, 0x2b, 0x7b,
0x0a, 0xea, 0x50, 0x59,
0x00, 0xe2, 0xf6, 0x41,
0x08, 0xa8, 0xaf, 0x7a,
0xc0, 0x33, 0x23, 0x7b,
0x80, 0x33, 0xaf, 0x6a,
0xff, 0x88, 0x23, 0x6b,
0x40, 0x33, 0xaf, 0x6a,
0x10, 0xa8, 0x29, 0x7b,
0x0a, 0xea, 0x4e, 0x59,
0x0a, 0xea, 0x04, 0x00,
0x00, 0xe2, 0x44, 0x5b,
0x00, 0xe2, 0x76, 0x43,
0x50, 0x4b, 0x32, 0x6b,
0x00, 0xe2, 0x48, 0x5b,
0x00, 0xe2, 0x7c, 0x43,
0x50, 0x4b, 0x30, 0x6b,
0xbf, 0x3a, 0x74, 0x08,
0x01, 0xe0, 0xf8, 0x31,
0x01, 0xe0, 0xf4, 0x31,
0xff, 0xea, 0xc0, 0x09,
0x01, 0x2e, 0x5d, 0x1a,
0x00, 0x2f, 0x5f, 0x22,
0x04, 0x47, 0x8f, 0x02,
0x01, 0xfc, 0xc0, 0x35,
0x33, 0xea, 0x44, 0x59,
0x01, 0xfa, 0xc0, 0x35,
0x02, 0xa8, 0x84, 0x32,
0x02, 0xea, 0xb4, 0x00,
0x33, 0xea, 0x42, 0x59,
0x33, 0xea, 0x00, 0x00,
0x02, 0x42, 0x51, 0x31,
0xff, 0x88, 0x51, 0x6b,
0x01, 0xa4, 0x4d, 0x6b,
0x02, 0xa4, 0x55, 0x6b,
0x01, 0x84, 0x55, 0x7b,
0xff, 0xae, 0x65, 0x68,
0xff, 0x88, 0x55, 0x6b,
0x01, 0x9c, 0x51, 0x6b,
0x02, 0x9c, 0x59, 0x6b,
0x01, 0x84, 0x59, 0x7b,
0x02, 0x28, 0x19, 0x33,
0x02, 0xa8, 0x50, 0x36,
0xff, 0x88, 0x55, 0x73,
0x00, 0xe2, 0x2e, 0x5b,
0xff, 0x88, 0x59, 0x73,
0x00, 0xe2, 0x2c, 0x5b,
0x02, 0xa8, 0x5c, 0x33,
0x02, 0x2c, 0x19, 0x33,
0x02, 0xa8, 0x58, 0x32,
0x04, 0xa4, 0x49, 0x07,
0xc0, 0x33, 0xb1, 0x6a,
0x04, 0x9c, 0x39, 0x07,
0xc0, 0x33, 0xaf, 0x6a,
0x04, 0xa8, 0x51, 0x03,
0x20, 0xa8, 0x77, 0x6b,
0x20, 0xa8, 0x7d, 0x6b,
0x02, 0xa8, 0x40, 0x31,
0xc0, 0x34, 0xc1, 0x09,
0x00, 0x35, 0x51, 0x01,
......@@ -452,73 +455,73 @@ static uint8_t seqprog[] = {
0xf7, 0x57, 0xae, 0x08,
0x08, 0xea, 0x98, 0x00,
0x01, 0x44, 0xd4, 0x31,
0xee, 0x00, 0x80, 0x6b,
0xee, 0x00, 0x86, 0x6b,
0x02, 0xea, 0xb4, 0x00,
0x00, 0xe2, 0xa8, 0x5b,
0x09, 0x4c, 0x82, 0x7b,
0x00, 0xe2, 0xae, 0x5b,
0x09, 0x4c, 0x88, 0x7b,
0x08, 0x4c, 0x06, 0x68,
0x0b, 0xea, 0x50, 0x59,
0x0b, 0xea, 0x4e, 0x59,
0x0b, 0xea, 0x04, 0x00,
0x01, 0x44, 0xd4, 0x31,
0x20, 0x33, 0xf9, 0x79,
0x00, 0xe2, 0x92, 0x5b,
0x00, 0xe2, 0xf8, 0x41,
0x01, 0x84, 0x97, 0x7b,
0x01, 0xa4, 0x49, 0x07,
0x08, 0x60, 0x30, 0x33,
0x08, 0x80, 0x41, 0x37,
0x20, 0x33, 0xf7, 0x79,
0x00, 0xe2, 0x98, 0x5b,
0x00, 0xe2, 0xf6, 0x41,
0x01, 0x84, 0x9d, 0x7b,
0x01, 0x9c, 0x39, 0x07,
0x08, 0x60, 0x20, 0x33,
0x08, 0x80, 0x31, 0x37,
0xdf, 0x33, 0x67, 0x0a,
0xee, 0x00, 0xa4, 0x6b,
0xee, 0x00, 0xaa, 0x6b,
0x05, 0xea, 0xb4, 0x00,
0x33, 0xea, 0x44, 0x59,
0x33, 0xea, 0x42, 0x59,
0x33, 0xea, 0x00, 0x00,
0x00, 0xe2, 0x6a, 0x59,
0x00, 0xe2, 0xb8, 0x42,
0x00, 0xe2, 0x68, 0x59,
0x00, 0xe2, 0xb6, 0x42,
0x01, 0xea, 0x6c, 0x02,
0xc0, 0xea, 0x66, 0x06,
0xff, 0x42, 0xb8, 0x6b,
0x01, 0x41, 0xac, 0x6b,
0x02, 0x41, 0xac, 0x7b,
0xff, 0x42, 0xb8, 0x6b,
0x01, 0x41, 0xac, 0x6b,
0x02, 0x41, 0xac, 0x7b,
0xff, 0x42, 0xb8, 0x7b,
0x04, 0x4c, 0xac, 0x6b,
0xff, 0x42, 0xbe, 0x6b,
0x01, 0x41, 0xb2, 0x6b,
0x02, 0x41, 0xb2, 0x7b,
0xff, 0x42, 0xbe, 0x6b,
0x01, 0x41, 0xb2, 0x6b,
0x02, 0x41, 0xb2, 0x7b,
0xff, 0x42, 0xbe, 0x7b,
0x04, 0x4c, 0xb2, 0x6b,
0xe0, 0x41, 0x6c, 0x0e,
0x01, 0x44, 0xd4, 0x31,
0xff, 0x42, 0xc0, 0x7b,
0x04, 0x4c, 0xc0, 0x6b,
0xff, 0x42, 0xc6, 0x7b,
0x04, 0x4c, 0xc6, 0x6b,
0xe0, 0x41, 0x6c, 0x0a,
0xe0, 0x36, 0xf9, 0x61,
0xe0, 0x36, 0xf7, 0x61,
0xff, 0xea, 0xca, 0x09,
0x01, 0xe2, 0xc8, 0x31,
0x01, 0x46, 0xda, 0x35,
0x01, 0x44, 0xd4, 0x35,
0x10, 0xea, 0x80, 0x00,
0x01, 0xe2, 0x62, 0x36,
0x04, 0xa6, 0xd8, 0x7b,
0x04, 0xa6, 0xde, 0x7b,
0xff, 0xea, 0x5a, 0x09,
0xff, 0xea, 0x4c, 0x0d,
0x01, 0xa6, 0xf6, 0x6b,
0x10, 0xad, 0x96, 0x7d,
0x80, 0xad, 0xee, 0x6b,
0x08, 0xad, 0x96, 0x6d,
0x01, 0xa6, 0xfc, 0x6b,
0x10, 0xad, 0x64, 0x78,
0x80, 0xad, 0xf4, 0x6b,
0x08, 0xad, 0x64, 0x68,
0x04, 0x84, 0xf9, 0x30,
0x00, 0xea, 0x08, 0x81,
0xff, 0xea, 0xd4, 0x09,
0x02, 0x84, 0xf9, 0x88,
0x0d, 0xea, 0x5a, 0x01,
0x04, 0xa6, 0x4c, 0x05,
0x04, 0xa6, 0x96, 0x7d,
0x04, 0xa6, 0x64, 0x78,
0xff, 0xea, 0x5a, 0x09,
0x03, 0x84, 0x59, 0x89,
0x03, 0xea, 0x4c, 0x01,
0x80, 0x1a, 0x96, 0x7d,
0x08, 0x19, 0x96, 0x7d,
0x80, 0x1a, 0x64, 0x78,
0x08, 0x19, 0x64, 0x78,
0x08, 0xb0, 0xe0, 0x30,
0x04, 0xb0, 0xe0, 0x30,
0x03, 0xb0, 0xf0, 0x30,
0x01, 0x78, 0x04, 0x7c,
0x01, 0x78, 0x0a, 0x7c,
0x01, 0xa7, 0x4e, 0x11,
0x01, 0xb0, 0x06, 0x33,
0x7f, 0x83, 0xe9, 0x08,
......@@ -529,275 +532,268 @@ static uint8_t seqprog[] = {
0x00, 0x86, 0x0d, 0x23,
0x00, 0x87, 0x0f, 0x23,
0x01, 0x84, 0xc5, 0x31,
0x01, 0xa7, 0x1a, 0x7c,
0x01, 0xa7, 0x20, 0x7c,
0x04, 0xe2, 0xc4, 0x01,
0x80, 0x83, 0x21, 0x7c,
0x80, 0x83, 0x27, 0x7c,
0x02, 0xe2, 0xc4, 0x01,
0xff, 0xea, 0x4c, 0x09,
0x01, 0xe2, 0x36, 0x30,
0xc8, 0x19, 0x32, 0x00,
0x88, 0x19, 0x32, 0x00,
0x01, 0xac, 0xd4, 0x99,
0x00, 0xe2, 0x96, 0x55,
0x00, 0xe2, 0x64, 0x50,
0xfe, 0xa6, 0x4c, 0x0d,
0x0b, 0x98, 0xe1, 0x30,
0x01, 0xa0, 0x4f, 0x09,
0xfd, 0xa4, 0x49, 0x09,
0x80, 0xa3, 0x37, 0x7c,
0x0b, 0x90, 0xe1, 0x30,
0x01, 0x98, 0x4f, 0x09,
0xfd, 0x9c, 0x49, 0x09,
0x80, 0x9b, 0x3d, 0x7c,
0x02, 0xa4, 0x48, 0x01,
0x01, 0xa7, 0x3a, 0x7c,
0x01, 0xa7, 0x40, 0x7c,
0x04, 0xa4, 0x48, 0x01,
0x01, 0xa4, 0x36, 0x30,
0xa8, 0xea, 0x32, 0x00,
0xfd, 0xa4, 0x49, 0x0b,
0x05, 0xa3, 0x07, 0x33,
0x80, 0x83, 0x47, 0x6c,
0xfd, 0x9c, 0x39, 0x0b,
0x05, 0x9b, 0x07, 0x33,
0x80, 0x83, 0x4d, 0x6c,
0x02, 0xea, 0x4c, 0x05,
0xff, 0xea, 0x4c, 0x0d,
0x00, 0xe2, 0x3c, 0x59,
0x02, 0xa6, 0xda, 0x6b,
0x02, 0xa6, 0xe0, 0x6b,
0x80, 0xf9, 0xf2, 0x05,
0xc0, 0x33, 0x55, 0x7c,
0x03, 0xea, 0x50, 0x59,
0xc0, 0x33, 0x5b, 0x7c,
0x03, 0xea, 0x4e, 0x59,
0x03, 0xea, 0x04, 0x00,
0x20, 0x33, 0x79, 0x7c,
0x01, 0x84, 0x5f, 0x6c,
0x06, 0xea, 0x50, 0x59,
0x20, 0x33, 0x7f, 0x7c,
0x01, 0x84, 0x65, 0x6c,
0x06, 0xea, 0x4e, 0x59,
0x06, 0xea, 0x04, 0x00,
0x00, 0xe2, 0x7c, 0x44,
0x00, 0xe2, 0x82, 0x44,
0x01, 0x00, 0x60, 0x32,
0xee, 0x00, 0x68, 0x6c,
0xee, 0x00, 0x6e, 0x6c,
0x05, 0xea, 0xb4, 0x00,
0x33, 0xea, 0x44, 0x59,
0x33, 0xea, 0x42, 0x59,
0x33, 0xea, 0x00, 0x00,
0x80, 0x3d, 0x7a, 0x00,
0xfc, 0x42, 0x6a, 0x7c,
0xfc, 0x42, 0x70, 0x7c,
0x7f, 0x3d, 0x7a, 0x08,
0x00, 0x30, 0x45, 0x59,
0x00, 0x30, 0x43, 0x59,
0x01, 0x30, 0x01, 0x30,
0x09, 0xea, 0x50, 0x59,
0x09, 0xea, 0x4e, 0x59,
0x09, 0xea, 0x04, 0x00,
0x00, 0xe2, 0xf8, 0x41,
0x01, 0xa4, 0x5f, 0x6c,
0x00, 0xe2, 0x2c, 0x5c,
0x00, 0xe2, 0xf6, 0x41,
0x01, 0x9c, 0x65, 0x6c,
0x00, 0xe2, 0x32, 0x5c,
0x20, 0x33, 0x67, 0x02,
0x01, 0x00, 0x60, 0x32,
0x02, 0xa6, 0x84, 0x7c,
0x00, 0xe2, 0x48, 0x5c,
0x00, 0xe2, 0x70, 0x58,
0x00, 0xe2, 0x80, 0x58,
0x02, 0xa6, 0x8a, 0x7c,
0x00, 0xe2, 0x4e, 0x5c,
0x00, 0xe2, 0x56, 0x58,
0x00, 0xe2, 0x66, 0x58,
0x00, 0xe2, 0x3a, 0x58,
0x00, 0x30, 0x45, 0x59,
0x00, 0x30, 0x43, 0x59,
0x01, 0x30, 0x01, 0x30,
0x20, 0x19, 0x84, 0x6c,
0x00, 0xe2, 0xb4, 0x5c,
0x04, 0x19, 0x9e, 0x6c,
0x20, 0x19, 0x8a, 0x6c,
0x00, 0xe2, 0xba, 0x5c,
0x04, 0x19, 0xa4, 0x6c,
0x02, 0x19, 0x32, 0x00,
0x01, 0x84, 0x9f, 0x7c,
0x01, 0x1b, 0x98, 0x7c,
0x01, 0x1a, 0x9e, 0x6c,
0x00, 0xe2, 0x4e, 0x44,
0x80, 0x4b, 0xa4, 0x6c,
0x01, 0x4c, 0xa0, 0x7c,
0x03, 0x42, 0x4e, 0x6c,
0x00, 0xe2, 0xd4, 0x5b,
0x01, 0x84, 0xa5, 0x7c,
0x01, 0x1b, 0x9e, 0x7c,
0x01, 0x1a, 0xa4, 0x6c,
0x00, 0xe2, 0x54, 0x44,
0x80, 0x4b, 0xaa, 0x6c,
0x01, 0x4c, 0xa6, 0x7c,
0x03, 0x42, 0x54, 0x6c,
0x00, 0xe2, 0xda, 0x5b,
0x80, 0xf9, 0xf2, 0x01,
0x04, 0x33, 0xf9, 0x79,
0x00, 0xe2, 0xf8, 0x41,
0x08, 0x5d, 0xbc, 0x6c,
0x00, 0xe2, 0x70, 0x58,
0x00, 0x30, 0x45, 0x59,
0x04, 0x33, 0xf7, 0x79,
0x00, 0xe2, 0xf6, 0x41,
0x08, 0x5d, 0xc2, 0x6c,
0x00, 0xe2, 0x56, 0x58,
0x00, 0x30, 0x43, 0x59,
0x01, 0x30, 0x01, 0x30,
0x02, 0x1b, 0xac, 0x7c,
0x08, 0x5d, 0xba, 0x7c,
0x02, 0x1b, 0xb2, 0x7c,
0x08, 0x5d, 0xc0, 0x7c,
0x03, 0x68, 0x00, 0x37,
0x01, 0x84, 0x09, 0x07,
0x80, 0x1b, 0xc6, 0x7c,
0x80, 0x84, 0xc7, 0x6c,
0x80, 0x1b, 0xcc, 0x7c,
0x80, 0x84, 0xcd, 0x6c,
0xff, 0x85, 0x0b, 0x1b,
0xff, 0x86, 0x0d, 0x23,
0xff, 0x87, 0x0f, 0x23,
0xf8, 0x1b, 0x08, 0x0b,
0xff, 0xea, 0x4e, 0x09,
0x04, 0x1b, 0xce, 0x7c,
0x04, 0x1b, 0xd4, 0x7c,
0x01, 0xa7, 0x4e, 0x01,
0xff, 0xea, 0x06, 0x0b,
0x03, 0x68, 0x00, 0x37,
0x00, 0xe2, 0xc0, 0x58,
0x00, 0xe2, 0xc4, 0x58,
0x10, 0xea, 0x18, 0x00,
0xf9, 0xd9, 0xb2, 0x0d,
0x01, 0xd9, 0xb2, 0x05,
0x01, 0x52, 0x48, 0x31,
0x20, 0xa4, 0xf2, 0x7c,
0x20, 0x5b, 0xf2, 0x7c,
0x80, 0xf9, 0x00, 0x7d,
0x20, 0xa4, 0xfc, 0x7c,
0x20, 0x5b, 0xfc, 0x7c,
0x80, 0xf9, 0x0a, 0x7d,
0x02, 0xea, 0xb4, 0x00,
0x11, 0x00, 0x00, 0x10,
0x04, 0x19, 0xec, 0x7c,
0x04, 0x19, 0x16, 0x7d,
0xdf, 0x19, 0x32, 0x08,
0x01, 0x4c, 0xe8, 0x7c,
0x60, 0x5b, 0xf4, 0x6c,
0x01, 0x4c, 0xf0, 0x7c,
0x20, 0x19, 0x32, 0x00,
0x11, 0x00, 0x00, 0x10,
0x01, 0xd9, 0xb2, 0x05,
0x02, 0xea, 0xb4, 0x00,
0x01, 0xd9, 0xb2, 0x05,
0x10, 0x5b, 0x04, 0x6d,
0x08, 0x5b, 0x0c, 0x6d,
0x20, 0x5b, 0xfe, 0x6c,
0x02, 0x5b, 0x2c, 0x6d,
0x0e, 0xea, 0x50, 0x59,
0x10, 0x5b, 0x0e, 0x6d,
0x08, 0x5b, 0x18, 0x6d,
0x20, 0x5b, 0x08, 0x6d,
0x02, 0x5b, 0x38, 0x6d,
0x0e, 0xea, 0x4e, 0x59,
0x0e, 0xea, 0x04, 0x00,
0x80, 0xf9, 0xee, 0x6c,
0x80, 0xf9, 0xf8, 0x6c,
0xdf, 0x5c, 0xb8, 0x08,
0x01, 0xd9, 0xb2, 0x05,
0x01, 0xa4, 0xff, 0x6d,
0x00, 0xe2, 0x2c, 0x5c,
0x00, 0xe2, 0x36, 0x5d,
0x01, 0x9c, 0xf3, 0x6d,
0x00, 0xe2, 0x32, 0x5c,
0x00, 0xe2, 0x42, 0x5d,
0x01, 0xae, 0x5d, 0x1b,
0x01, 0xd9, 0xb2, 0x05,
0x00, 0xe2, 0x2e, 0x5b,
0xf3, 0x92, 0xd5, 0x19,
0x00, 0xe2, 0x1a, 0x55,
0x80, 0x92, 0x1b, 0x6d,
0x0f, 0xea, 0x50, 0x59,
0x00, 0xe2, 0x2c, 0x5b,
0xf3, 0xac, 0xd5, 0x19,
0x00, 0xe2, 0x26, 0x55,
0x80, 0xac, 0x27, 0x6d,
0x0f, 0xea, 0x4e, 0x59,
0x0f, 0xea, 0x04, 0x00,
0x00, 0xe2, 0x22, 0x45,
0x00, 0xe2, 0x2e, 0x45,
0x04, 0x8c, 0xe1, 0x30,
0x01, 0xea, 0xf2, 0x00,
0x02, 0xea, 0x36, 0x00,
0xa8, 0xea, 0x32, 0x00,
0xff, 0x93, 0x29, 0x7d,
0x14, 0xea, 0x50, 0x59,
0xff, 0xad, 0x35, 0x7d,
0x14, 0xea, 0x4e, 0x59,
0x14, 0xea, 0x04, 0x00,
0x00, 0xe2, 0xb0, 0x5d,
0x00, 0xe2, 0xa4, 0x5d,
0x01, 0xd9, 0xb2, 0x05,
0x09, 0x80, 0xe1, 0x30,
0x02, 0xea, 0x36, 0x00,
0xa8, 0xea, 0x32, 0x00,
0x00, 0xe2, 0xd8, 0x5d,
0x00, 0xe2, 0x9c, 0x5d,
0x01, 0xd9, 0xb2, 0x05,
0x02, 0xa8, 0xf4, 0x31,
0x02, 0xa6, 0x48, 0x7d,
0x00, 0xe2, 0x3e, 0x59,
0x20, 0x5b, 0x56, 0x6d,
0xfc, 0x42, 0x42, 0x7d,
0x10, 0x40, 0x44, 0x6d,
0x20, 0x4d, 0x46, 0x7d,
0x08, 0x5d, 0x56, 0x6d,
0x02, 0xa6, 0xda, 0x6b,
0x00, 0xe2, 0x3e, 0x59,
0x20, 0x5b, 0x56, 0x6d,
0x01, 0x1b, 0x76, 0x6d,
0xfc, 0x42, 0x52, 0x7d,
0x10, 0x40, 0x54, 0x6d,
0x20, 0x4d, 0x96, 0x7d,
0x08, 0x5d, 0x96, 0x7d,
0x02, 0xa6, 0x52, 0x7d,
0x00, 0xe2, 0x3c, 0x59,
0x20, 0x5b, 0x60, 0x6d,
0xfc, 0x42, 0x4c, 0x7d,
0x10, 0x40, 0x4e, 0x6d,
0x20, 0x4d, 0x50, 0x7d,
0x08, 0x5d, 0x60, 0x6d,
0x02, 0xa6, 0xe0, 0x6b,
0x00, 0xe2, 0x3c, 0x59,
0x20, 0x5b, 0x60, 0x6d,
0x01, 0x1b, 0x80, 0x6d,
0xfc, 0x42, 0x5c, 0x7d,
0x10, 0x40, 0x5e, 0x6d,
0x20, 0x4d, 0x64, 0x78,
0x08, 0x5d, 0x64, 0x78,
0x02, 0x19, 0x32, 0x00,
0x01, 0x5b, 0x40, 0x31,
0x00, 0xe2, 0xb4, 0x5c,
0x00, 0xe2, 0x92, 0x5b,
0x00, 0xe2, 0xba, 0x5c,
0x00, 0xe2, 0x98, 0x5b,
0x20, 0xea, 0xb6, 0x00,
0x00, 0xe2, 0xd4, 0x5b,
0x00, 0xe2, 0xda, 0x5b,
0x20, 0x5c, 0xb8, 0x00,
0x04, 0x19, 0x6c, 0x6d,
0x01, 0x1a, 0x6c, 0x6d,
0x00, 0xe2, 0x3e, 0x59,
0x01, 0x1a, 0x96, 0x7d,
0x04, 0x19, 0x76, 0x6d,
0x01, 0x1a, 0x76, 0x6d,
0x00, 0xe2, 0x3c, 0x59,
0x01, 0x1a, 0x64, 0x78,
0x80, 0xf9, 0xf2, 0x01,
0x20, 0xa0, 0xe8, 0x7d,
0x08, 0xa8, 0x75, 0x7d,
0x00, 0xe2, 0x88, 0x45,
0x20, 0xa0, 0xda, 0x7d,
0xff, 0xae, 0x5d, 0x1b,
0x08, 0xa8, 0x3d, 0x6b,
0x02, 0xea, 0xb4, 0x04,
0x02, 0x19, 0x32, 0x00,
0x08, 0xa8, 0x99, 0x7d,
0x04, 0x5d, 0xfe, 0x7d,
0x01, 0x1a, 0xfe, 0x7d,
0x01, 0xa4, 0x49, 0x03,
0x01, 0x9c, 0x39, 0x03,
0x40, 0x5b, 0x90, 0x6d,
0x00, 0xe2, 0x3c, 0x59,
0x40, 0x5b, 0x90, 0x6d,
0x04, 0x5d, 0xf4, 0x7d,
0x01, 0x1a, 0xf4, 0x7d,
0x20, 0x4d, 0x64, 0x78,
0x40, 0x5b, 0xda, 0x7d,
0x04, 0x5d, 0xf4, 0x7d,
0x01, 0x1a, 0xf4, 0x7d,
0x80, 0xf9, 0xf2, 0x01,
0x02, 0xa8, 0x84, 0x32,
0x02, 0xea, 0xb4, 0x00,
0x00, 0xe2, 0x3e, 0x43,
0x02, 0xa8, 0x84, 0x32,
0x02, 0xea, 0xb4, 0x00,
0xff, 0xea, 0xd4, 0x19,
0x00, 0xe2, 0x4a, 0x59,
0x11, 0x00, 0x00, 0x10,
0x00, 0xe2, 0xcc, 0x5d,
0x00, 0xe2, 0x3e, 0x53,
0xff, 0xea, 0xd4, 0x0d,
0x00, 0xe2, 0x3e, 0x59,
0x40, 0x5b, 0xa4, 0x6d,
0x04, 0x5d, 0xfe, 0x7d,
0x01, 0x1a, 0xfe, 0x7d,
0x20, 0x4d, 0x96, 0x7d,
0x40, 0x5b, 0xe8, 0x7d,
0x04, 0x5d, 0xfe, 0x7d,
0x01, 0x1a, 0xfe, 0x7d,
0xff, 0xae, 0x5d, 0x1b,
0x08, 0xa8, 0x3d, 0x6b,
0x02, 0xea, 0xb4, 0x04,
0x00, 0xe2, 0x3c, 0x59,
0x01, 0x1b, 0x64, 0x78,
0x80, 0xf9, 0xf2, 0x01,
0x01, 0xa4, 0x49, 0x03,
0x08, 0xa8, 0x89, 0x6d,
0x02, 0xea, 0xb4, 0x04,
0x00, 0xe2, 0x3c, 0x59,
0x01, 0x1b, 0xc0, 0x7d,
0x40, 0x5b, 0x96, 0x7d,
0x01, 0x1b, 0xb8, 0x6d,
0x40, 0x5b, 0xc6, 0x7d,
0x01, 0x1b, 0xb8, 0x6d,
0x02, 0x19, 0x32, 0x00,
0x01, 0x1a, 0x64, 0x78,
0x80, 0xf9, 0xf2, 0x01,
0xff, 0xea, 0x10, 0x03,
0x08, 0xa8, 0x51, 0x03,
0x00, 0xe2, 0x88, 0x45,
0xff, 0x6a, 0xc6, 0x6d,
0x40, 0x5b, 0x96, 0x7d,
0xff, 0x6a, 0xb6, 0x7d,
0x10, 0xea, 0x50, 0x59,
0x00, 0xe2, 0x3c, 0x43,
0x01, 0x1a, 0xc2, 0x7d,
0x40, 0x5b, 0xbe, 0x7d,
0x01, 0x1a, 0xac, 0x6d,
0xfc, 0x42, 0x64, 0x78,
0x01, 0x1a, 0xc6, 0x6d,
0x10, 0xea, 0x4e, 0x59,
0x10, 0xea, 0x04, 0x00,
0x00, 0xe2, 0xb6, 0x45,
0x80, 0xf9, 0x96, 0x6d,
0x01, 0x43, 0xc1, 0x31,
0x00, 0xfb, 0x96, 0x65,
0x01, 0x42, 0xc1, 0x31,
0x00, 0xfa, 0x96, 0x65,
0x01, 0xe8, 0xd4, 0x1d,
0x00, 0xe2, 0x3c, 0x59,
0x01, 0x1b, 0x96, 0x7d,
0x80, 0xf9, 0xf2, 0x01,
0x02, 0xea, 0xb4, 0x04,
0xfc, 0x42, 0x64, 0x78,
0x10, 0x40, 0xcc, 0x6d,
0x20, 0x4d, 0x64, 0x78,
0x40, 0x5b, 0xac, 0x6d,
0x01, 0x1a, 0x64, 0x78,
0x01, 0xae, 0x5d, 0x1b,
0x30, 0x3f, 0xc0, 0x09,
0x30, 0xe0, 0x96, 0x65,
0x40, 0x4b, 0x96, 0x6d,
0x30, 0xe0, 0x64, 0x60,
0x40, 0x4b, 0x64, 0x68,
0xff, 0xea, 0x52, 0x01,
0xee, 0x00, 0xee, 0x6d,
0xee, 0x00, 0xe0, 0x6d,
0x80, 0xf9, 0xf2, 0x01,
0xff, 0xae, 0x5d, 0x1b,
0x02, 0xea, 0xb4, 0x00,
0x20, 0xea, 0x9a, 0x00,
0xf3, 0x42, 0xf8, 0x6d,
0x12, 0xea, 0x50, 0x59,
0xf3, 0x42, 0xec, 0x6d,
0x12, 0xea, 0x4e, 0x59,
0x12, 0xea, 0x04, 0x00,
0x00, 0xe2, 0xf8, 0x41,
0x0d, 0xea, 0x50, 0x59,
0x00, 0xe2, 0xf6, 0x41,
0x0d, 0xea, 0x4e, 0x59,
0x0d, 0xea, 0x04, 0x00,
0x00, 0xe2, 0xf8, 0x41,
0x11, 0xea, 0x50, 0x59,
0x00, 0xe2, 0xf6, 0x41,
0x01, 0xae, 0x5d, 0x1b,
0x11, 0xea, 0x4e, 0x59,
0x11, 0xea, 0x04, 0x00,
0x00, 0xe2, 0x2e, 0x5b,
0x00, 0xe2, 0x2c, 0x5b,
0x08, 0x5a, 0xb4, 0x00,
0x00, 0xe2, 0x22, 0x5e,
0x00, 0xe2, 0x1a, 0x5e,
0xa8, 0xea, 0x32, 0x00,
0x00, 0xe2, 0x3e, 0x59,
0x80, 0x1a, 0x12, 0x7e,
0x00, 0xe2, 0x22, 0x5e,
0x00, 0xe2, 0x3c, 0x59,
0x80, 0x1a, 0x08, 0x7e,
0x00, 0xe2, 0x1a, 0x5e,
0x80, 0x19, 0x32, 0x00,
0x40, 0x5b, 0x18, 0x6e,
0x08, 0x5a, 0x18, 0x7e,
0x20, 0x4d, 0x96, 0x7d,
0x40, 0x5b, 0x0e, 0x6e,
0x08, 0x5a, 0x0e, 0x7e,
0x20, 0x4d, 0x64, 0x78,
0x02, 0x84, 0x09, 0x03,
0x40, 0x5b, 0xe8, 0x7d,
0x08, 0xa8, 0x81, 0x6d,
0x40, 0x5b, 0xda, 0x7d,
0xff, 0xae, 0x5d, 0x1b,
0x80, 0xf9, 0xf2, 0x01,
0x08, 0xa8, 0x3d, 0x6b,
0x02, 0xea, 0xb4, 0x04,
0x01, 0x38, 0xe1, 0x30,
0x05, 0x39, 0xe3, 0x98,
0x01, 0xe0, 0xf8, 0x31,
0x01, 0xe0, 0xf4, 0x31,
0xff, 0xea, 0xc0, 0x09,
0x00, 0x3a, 0xe5, 0x20,
0x00, 0x3b, 0xe7, 0x20,
0x01, 0xfc, 0xc0, 0x31,
0x01, 0xfa, 0xc0, 0x31,
0x04, 0xea, 0xe8, 0x30,
0xff, 0xea, 0xf0, 0x08,
0x02, 0xea, 0xf2, 0x00,
......@@ -1000,124 +996,121 @@ static struct patch {
{ ahd_patch0_func, 30, 1, 1 },
{ ahd_patch1_func, 37, 1, 2 },
{ ahd_patch0_func, 38, 1, 1 },
{ ahd_patch2_func, 45, 1, 2 },
{ ahd_patch0_func, 46, 1, 1 },
{ ahd_patch2_func, 49, 1, 2 },
{ ahd_patch0_func, 50, 1, 1 },
{ ahd_patch2_func, 53, 1, 2 },
{ ahd_patch0_func, 54, 1, 1 },
{ ahd_patch2_func, 56, 1, 2 },
{ ahd_patch0_func, 57, 1, 1 },
{ ahd_patch2_func, 60, 1, 2 },
{ ahd_patch0_func, 61, 1, 1 },
{ ahd_patch2_func, 64, 1, 2 },
{ ahd_patch0_func, 65, 1, 1 },
{ ahd_patch2_func, 162, 6, 1 },
{ ahd_patch1_func, 168, 2, 1 },
{ ahd_patch4_func, 170, 1, 1 },
{ ahd_patch2_func, 179, 1, 2 },
{ ahd_patch0_func, 180, 1, 1 },
{ ahd_patch5_func, 181, 2, 2 },
{ ahd_patch0_func, 183, 6, 3 },
{ ahd_patch2_func, 186, 1, 2 },
{ ahd_patch0_func, 187, 1, 1 },
{ ahd_patch2_func, 190, 1, 2 },
{ ahd_patch0_func, 191, 1, 1 },
{ ahd_patch6_func, 193, 2, 1 },
{ ahd_patch4_func, 201, 16, 2 },
{ ahd_patch0_func, 217, 1, 1 },
{ ahd_patch7_func, 237, 2, 1 },
{ ahd_patch1_func, 241, 1, 2 },
{ ahd_patch0_func, 242, 1, 1 },
{ ahd_patch6_func, 245, 2, 1 },
{ ahd_patch1_func, 259, 1, 2 },
{ ahd_patch0_func, 260, 1, 1 },
{ ahd_patch1_func, 263, 1, 2 },
{ ahd_patch0_func, 264, 1, 1 },
{ ahd_patch2_func, 267, 1, 2 },
{ ahd_patch0_func, 268, 1, 1 },
{ ahd_patch1_func, 323, 1, 2 },
{ ahd_patch0_func, 324, 1, 1 },
{ ahd_patch2_func, 332, 1, 2 },
{ ahd_patch0_func, 333, 1, 1 },
{ ahd_patch2_func, 336, 1, 2 },
{ ahd_patch0_func, 337, 1, 1 },
{ ahd_patch1_func, 344, 1, 2 },
{ ahd_patch0_func, 345, 1, 1 },
{ ahd_patch8_func, 364, 1, 1 },
{ ahd_patch8_func, 367, 1, 1 },
{ ahd_patch8_func, 369, 1, 1 },
{ ahd_patch8_func, 381, 1, 1 },
{ ahd_patch1_func, 391, 1, 2 },
{ ahd_patch0_func, 392, 1, 1 },
{ ahd_patch1_func, 394, 1, 2 },
{ ahd_patch0_func, 395, 1, 1 },
{ ahd_patch1_func, 403, 1, 2 },
{ ahd_patch0_func, 404, 1, 1 },
{ ahd_patch2_func, 415, 1, 2 },
{ ahd_patch0_func, 416, 1, 1 },
{ ahd_patch9_func, 444, 1, 1 },
{ ahd_patch1_func, 451, 1, 2 },
{ ahd_patch0_func, 452, 1, 1 },
{ ahd_patch2_func, 464, 1, 2 },
{ ahd_patch0_func, 465, 1, 1 },
{ ahd_patch10_func, 470, 6, 2 },
{ ahd_patch0_func, 476, 1, 1 },
{ ahd_patch11_func, 499, 1, 1 },
{ ahd_patch12_func, 508, 1, 1 },
{ ahd_patch13_func, 509, 1, 2 },
{ ahd_patch0_func, 510, 1, 1 },
{ ahd_patch14_func, 515, 1, 1 },
{ ahd_patch13_func, 516, 1, 1 },
{ ahd_patch15_func, 529, 1, 2 },
{ ahd_patch0_func, 530, 1, 1 },
{ ahd_patch1_func, 552, 1, 2 },
{ ahd_patch0_func, 553, 1, 1 },
{ ahd_patch1_func, 556, 1, 2 },
{ ahd_patch0_func, 557, 1, 1 },
{ ahd_patch2_func, 562, 1, 2 },
{ ahd_patch0_func, 563, 1, 1 },
{ ahd_patch2_func, 567, 1, 2 },
{ ahd_patch0_func, 568, 1, 1 },
{ ahd_patch1_func, 569, 1, 2 },
{ ahd_patch0_func, 570, 1, 1 },
{ ahd_patch2_func, 581, 1, 2 },
{ ahd_patch0_func, 582, 1, 1 },
{ ahd_patch16_func, 586, 1, 1 },
{ ahd_patch17_func, 591, 1, 1 },
{ ahd_patch18_func, 592, 2, 1 },
{ ahd_patch17_func, 596, 1, 2 },
{ ahd_patch0_func, 597, 1, 1 },
{ ahd_patch2_func, 600, 1, 2 },
{ ahd_patch0_func, 601, 1, 1 },
{ ahd_patch2_func, 619, 1, 2 },
{ ahd_patch0_func, 620, 1, 1 },
{ ahd_patch19_func, 621, 12, 1 },
{ ahd_patch1_func, 637, 1, 2 },
{ ahd_patch0_func, 638, 1, 1 },
{ ahd_patch19_func, 639, 1, 1 },
{ ahd_patch1_func, 650, 1, 2 },
{ ahd_patch0_func, 651, 1, 1 },
{ ahd_patch1_func, 658, 1, 2 },
{ ahd_patch0_func, 659, 1, 1 },
{ ahd_patch16_func, 683, 1, 1 },
{ ahd_patch16_func, 699, 1, 1 },
{ ahd_patch2_func, 711, 1, 2 },
{ ahd_patch0_func, 712, 1, 1 },
{ ahd_patch16_func, 731, 1, 1 },
{ ahd_patch1_func, 739, 1, 2 },
{ ahd_patch0_func, 740, 1, 1 },
{ ahd_patch1_func, 761, 1, 2 },
{ ahd_patch0_func, 762, 1, 1 },
{ ahd_patch1_func, 764, 1, 2 },
{ ahd_patch0_func, 765, 1, 1 },
{ ahd_patch1_func, 767, 1, 2 },
{ ahd_patch0_func, 768, 1, 1 },
{ ahd_patch20_func, 770, 1, 2 },
{ ahd_patch0_func, 771, 2, 1 },
{ ahd_patch21_func, 774, 4, 2 },
{ ahd_patch0_func, 778, 1, 1 },
{ ahd_patch21_func, 785, 11, 1 }
{ ahd_patch2_func, 43, 1, 2 },
{ ahd_patch0_func, 44, 1, 1 },
{ ahd_patch2_func, 47, 1, 2 },
{ ahd_patch0_func, 48, 1, 1 },
{ ahd_patch2_func, 51, 1, 2 },
{ ahd_patch0_func, 52, 1, 1 },
{ ahd_patch2_func, 65, 1, 2 },
{ ahd_patch0_func, 66, 1, 1 },
{ ahd_patch2_func, 69, 1, 2 },
{ ahd_patch0_func, 70, 1, 1 },
{ ahd_patch1_func, 73, 1, 2 },
{ ahd_patch0_func, 74, 1, 1 },
{ ahd_patch2_func, 161, 6, 1 },
{ ahd_patch1_func, 167, 2, 1 },
{ ahd_patch4_func, 169, 1, 1 },
{ ahd_patch2_func, 178, 1, 2 },
{ ahd_patch0_func, 179, 1, 1 },
{ ahd_patch5_func, 180, 2, 2 },
{ ahd_patch0_func, 182, 6, 3 },
{ ahd_patch2_func, 185, 1, 2 },
{ ahd_patch0_func, 186, 1, 1 },
{ ahd_patch2_func, 189, 1, 2 },
{ ahd_patch0_func, 190, 1, 1 },
{ ahd_patch6_func, 192, 2, 1 },
{ ahd_patch4_func, 200, 16, 2 },
{ ahd_patch0_func, 216, 1, 1 },
{ ahd_patch7_func, 236, 2, 1 },
{ ahd_patch1_func, 240, 1, 2 },
{ ahd_patch0_func, 241, 1, 1 },
{ ahd_patch6_func, 244, 2, 1 },
{ ahd_patch1_func, 258, 1, 2 },
{ ahd_patch0_func, 259, 1, 1 },
{ ahd_patch1_func, 262, 1, 2 },
{ ahd_patch0_func, 263, 1, 1 },
{ ahd_patch2_func, 266, 1, 2 },
{ ahd_patch0_func, 267, 1, 1 },
{ ahd_patch1_func, 322, 1, 2 },
{ ahd_patch0_func, 323, 1, 1 },
{ ahd_patch2_func, 331, 1, 2 },
{ ahd_patch0_func, 332, 1, 1 },
{ ahd_patch2_func, 335, 1, 2 },
{ ahd_patch0_func, 336, 1, 1 },
{ ahd_patch1_func, 343, 1, 2 },
{ ahd_patch0_func, 344, 1, 1 },
{ ahd_patch8_func, 363, 1, 1 },
{ ahd_patch8_func, 366, 1, 1 },
{ ahd_patch8_func, 368, 1, 1 },
{ ahd_patch8_func, 380, 1, 1 },
{ ahd_patch1_func, 390, 1, 2 },
{ ahd_patch0_func, 391, 1, 1 },
{ ahd_patch1_func, 393, 1, 2 },
{ ahd_patch0_func, 394, 1, 1 },
{ ahd_patch1_func, 402, 1, 2 },
{ ahd_patch0_func, 403, 1, 1 },
{ ahd_patch2_func, 416, 1, 2 },
{ ahd_patch0_func, 417, 1, 1 },
{ ahd_patch9_func, 447, 1, 1 },
{ ahd_patch1_func, 454, 1, 2 },
{ ahd_patch0_func, 455, 1, 1 },
{ ahd_patch2_func, 467, 1, 2 },
{ ahd_patch0_func, 468, 1, 1 },
{ ahd_patch10_func, 473, 6, 2 },
{ ahd_patch0_func, 479, 1, 1 },
{ ahd_patch11_func, 502, 1, 1 },
{ ahd_patch12_func, 511, 1, 1 },
{ ahd_patch13_func, 512, 1, 2 },
{ ahd_patch0_func, 513, 1, 1 },
{ ahd_patch14_func, 518, 1, 1 },
{ ahd_patch13_func, 519, 1, 1 },
{ ahd_patch15_func, 532, 1, 2 },
{ ahd_patch0_func, 533, 1, 1 },
{ ahd_patch1_func, 555, 1, 2 },
{ ahd_patch0_func, 556, 1, 1 },
{ ahd_patch1_func, 559, 1, 2 },
{ ahd_patch0_func, 560, 1, 1 },
{ ahd_patch2_func, 565, 1, 2 },
{ ahd_patch0_func, 566, 1, 1 },
{ ahd_patch2_func, 570, 1, 2 },
{ ahd_patch0_func, 571, 1, 1 },
{ ahd_patch1_func, 572, 1, 2 },
{ ahd_patch0_func, 573, 1, 1 },
{ ahd_patch2_func, 584, 1, 2 },
{ ahd_patch0_func, 585, 1, 1 },
{ ahd_patch16_func, 589, 1, 1 },
{ ahd_patch17_func, 594, 1, 1 },
{ ahd_patch18_func, 595, 2, 1 },
{ ahd_patch17_func, 599, 1, 2 },
{ ahd_patch0_func, 600, 1, 1 },
{ ahd_patch2_func, 603, 1, 2 },
{ ahd_patch0_func, 604, 1, 1 },
{ ahd_patch2_func, 622, 1, 2 },
{ ahd_patch0_func, 623, 1, 1 },
{ ahd_patch19_func, 624, 14, 1 },
{ ahd_patch1_func, 642, 1, 2 },
{ ahd_patch0_func, 643, 1, 1 },
{ ahd_patch19_func, 644, 1, 1 },
{ ahd_patch1_func, 656, 1, 2 },
{ ahd_patch0_func, 657, 1, 1 },
{ ahd_patch1_func, 664, 1, 2 },
{ ahd_patch0_func, 665, 1, 1 },
{ ahd_patch16_func, 688, 1, 1 },
{ ahd_patch16_func, 726, 1, 1 },
{ ahd_patch1_func, 737, 1, 2 },
{ ahd_patch0_func, 738, 1, 1 },
{ ahd_patch1_func, 755, 1, 2 },
{ ahd_patch0_func, 756, 1, 1 },
{ ahd_patch1_func, 758, 1, 2 },
{ ahd_patch0_func, 759, 1, 1 },
{ ahd_patch1_func, 762, 1, 2 },
{ ahd_patch0_func, 763, 1, 1 },
{ ahd_patch20_func, 765, 1, 2 },
{ ahd_patch0_func, 766, 2, 1 },
{ ahd_patch21_func, 769, 4, 2 },
{ ahd_patch0_func, 773, 1, 1 },
{ ahd_patch21_func, 781, 11, 1 }
};
static struct cs {
......@@ -1127,18 +1120,15 @@ static struct cs {
{ 11, 12 },
{ 13, 14 },
{ 29, 42 },
{ 43, 56 },
{ 69, 72 },
{ 99, 124 },
{ 125, 156 },
{ 158, 162 },
{ 170, 178 },
{ 201, 250 },
{ 683, 699 },
{ 699, 717 },
{ 722, 728 },
{ 731, 736 },
{ 742, 748 }
{ 56, 59 },
{ 101, 127 },
{ 128, 156 },
{ 158, 161 },
{ 169, 177 },
{ 200, 249 },
{ 688, 704 },
{ 704, 718 },
{ 728, 732 }
};
static const int num_critical_sections = sizeof(critical_sections)
......
......@@ -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/aic7xxx.h#74 $
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#75 $
*
* $FreeBSD$
*/
......@@ -1082,6 +1082,14 @@ struct ahc_softc {
/* PCI cacheline size. */
u_int pci_cachesize;
/*
* Count of parity errors we have seen as a target.
* We auto-disable parity error checking after seeing
* AHC_PCI_TARGET_PERR_THRESH number of errors.
*/
u_int pci_target_perr_count;
#define AHC_PCI_TARGET_PERR_THRESH 10
/* Maximum number of sequencer instructions supported. */
u_int instruction_ram_size;
......
......@@ -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/aic7xxx.c#124 $
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#128 $
*
* $FreeBSD$
*/
......@@ -3949,7 +3949,6 @@ ahc_free(struct ahc_softc *ahc)
{
int i;
ahc_fini_scbdata(ahc);
switch (ahc->init_level) {
default:
case 5:
......@@ -3981,6 +3980,7 @@ ahc_free(struct ahc_softc *ahc)
ahc_dma_tag_destroy(ahc, ahc->parent_dmat);
#endif
ahc_platform_free(ahc);
ahc_fini_scbdata(ahc);
for (i = 0; i < AHC_NUM_TARGETS; i++) {
struct ahc_tmode_tstate *tstate;
......@@ -5100,7 +5100,7 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc)
} while (--maxloops
&& (intstat != 0xFF || (ahc->features & AHC_REMOVABLE) == 0)
&& ((intstat & INT_PEND) != 0
|| (ahc_inb(ahc, SSTAT0) & (SELDO|SELINGO))));
|| (ahc_inb(ahc, SSTAT0) & (SELDO|SELINGO)) != 0));
if (maxloops == 0) {
printf("Infinite interrupt loop, INTSTAT = %x",
ahc_inb(ahc, INTSTAT));
......
/*
* Adaptec AIC7xxx device driver for Linux.
*
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#206 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#217 $
*
* Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science.
......@@ -146,18 +146,15 @@
#include <linux/unistd.h>
static int errno;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
/*
* Lock protecting manipulation of the ahc softc list.
*/
spinlock_t ahc_list_spinlock;
#endif
/*
* To generate the correct addresses for the controller to issue
* on the bus. Originally added for DEC Alpha support.
*/
#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a))
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
/* For dynamic sglist size calculation. */
u_int ahc_linux_nseg;
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
struct proc_dir_entry proc_scsi_aic7xxx = {
......@@ -367,31 +364,26 @@ static uint32_t aic7xxx_no_reset;
* disabled at the very end. That should fix everyone up unless there are
* really strange cirumstances.
*/
static int aic7xxx_reverse_scan = 0;
static uint32_t aic7xxx_reverse_scan;
/*
* Should we force EXTENDED translation on a controller.
* 0 == Use whatever is in the SEEPROM or default to off
* 1 == Use whatever is in the SEEPROM or default to on
*/
static uint32_t aic7xxx_extended = 0;
static uint32_t aic7xxx_extended;
/*
* PCI bus parity checking of the Adaptec controllers. This is somewhat
* dubious at best. To my knowledge, this option has never actually
* solved a PCI parity problem, but on certain machines with broken PCI
* chipset configurations, it can generate tons of false error messages.
* chipset configurations where stray PCI transactions with bad parity are
* the norm rather than the exception, the error messages can be overwelming.
* It's included in the driver for completeness.
* 0 = Shut off PCI parity check
* -1 = Normal polarity pci parity checking
* 1 = reverse polarity pci parity checking
*
* NOTE: you can't actually pass -1 on the lilo prompt. So, to set this
* variable to -1 you would actually want to simply pass the variable
* name without a number. That will invert the 0 which will result in
* -1.
* 0 = Shut off PCI parity check
* non-0 = reverse polarity pci parity checking
*/
static int aic7xxx_pci_parity = 0;
static uint32_t aic7xxx_pci_parity = ~0;
/*
* Certain newer motherboards have put new PCI based devices into the
......@@ -407,9 +399,9 @@ static int aic7xxx_pci_parity = 0;
#define CONFIG_AIC7XXX_PROBE_EISA_VL n
#endif
#if CONFIG_AIC7XXX_PROBE_EISA_VL == n
static int aic7xxx_no_probe = 1;
static uint32_t aic7xxx_probe_eisa_vl;
#else
static int aic7xxx_no_probe;
static uint32_t aic7xxx_probe_eisa_vl = ~0;
#endif
/*
......@@ -418,7 +410,7 @@ static int aic7xxx_no_probe;
* controller. I/O mapped register access, if allowed by the given
* platform, will work in almost all cases.
*/
int aic7xxx_allow_memio = 1;
uint32_t aic7xxx_allow_memio = ~0;
/*
* aic7xxx_detect() has been run, so register all device arrivals
......@@ -437,7 +429,7 @@ int aic7xxx_detect_complete;
* We default to 256ms because some older devices need a longer time
* to respond to initial selection.
*/
static int aic7xxx_seltime = 0x00;
static uint32_t aic7xxx_seltime;
/*
* Certain devices do not perform any aging on commands. Should the
......@@ -447,7 +439,7 @@ static int aic7xxx_seltime = 0x00;
* force all outstanding transactions to be serviced prior to a new
* transaction.
*/
int aic7xxx_periodic_otag;
uint32_t aic7xxx_periodic_otag;
/*
* Module information and settable options.
......@@ -472,7 +464,8 @@ MODULE_PARM_DESC(aic7xxx,
" verbose Enable verbose/diagnostic logging\n"
" allow_memio Allow device registers to be memory mapped\n"
" debug Bitmask of debug values to enable\n"
" no_probe Disable EISA/VLB controller probing\n"
" no_probe Toggle EISA/VLB controller probing\n"
" eisa_vl_probe Toggle EISA/VLB controller probing\n"
" no_reset Supress initial bus resets\n"
" extended Enable extended geometry on all controllers\n"
" periodic_otag Send an ordered tagged transaction\n"
......@@ -489,10 +482,10 @@ MODULE_PARM_DESC(aic7xxx,
"\n"
" Sample /etc/modules.conf line:\n"
" Toggle EISA/VLB probing\n"
" Set tag depth on Controller 1/Target 2 to 10 tags\n"
" Set tag depth on Controller 1/Target 1 to 10 tags\n"
" Shorten the selection timeout to 128ms\n"
"\n"
" options aic7xxx 'aic7xxx=no_probe.tag_info:{{}.{..10}}.seltime:1'\n"
" options aic7xxx 'aic7xxx=eisa_vl_probe.tag_info:{{}.{.10}}.seltime:1'\n"
);
#endif
......@@ -508,6 +501,7 @@ static void ahc_linux_release_simq(u_long arg);
static void ahc_linux_dev_timed_unfreeze(u_long arg);
static int ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag);
static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
static void ahc_linux_size_nseg(void);
static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc);
static void ahc_linux_start_dv(struct ahc_softc *ahc);
static void ahc_linux_dv_timeout(struct scsi_cmnd *cmd);
......@@ -571,16 +565,14 @@ static aic_option_callback_t ahc_linux_setup_dv;
static int aic7xxx_setup(char *s);
static int ahc_linux_next_unit(void);
static void ahc_runq_tasklet(unsigned long data);
static int ahc_linux_halt(struct notifier_block *nb, u_long event, void *buf);
static void ahc_schedule_completeq(struct ahc_softc *ahc, struct ahc_cmd *acmd);
static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc);
/********************************* Inlines ************************************/
static __inline void ahc_schedule_runq(struct ahc_softc *ahc);
static __inline struct ahc_linux_device*
ahc_linux_get_device(struct ahc_softc *ahc, u_int channel,
u_int target, u_int lun, int alloc);
static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc,
struct ahc_cmd *acmd);
static __inline void ahc_schedule_completeq(struct ahc_softc *ahc);
static __inline void ahc_linux_check_device_queue(struct ahc_softc *ahc,
struct ahc_linux_device *dev);
static __inline struct ahc_linux_device *
......@@ -592,27 +584,9 @@ static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
struct ahc_dma_seg *sg,
bus_addr_t addr, bus_size_t len);
static void
ahc_schedule_completeq(struct ahc_softc *ahc, struct ahc_cmd *acmd)
static __inline void
ahc_schedule_completeq(struct ahc_softc *ahc)
{
while (acmd != NULL) {
struct ahc_completeq *completeq;
struct ahc_cmd *list_cmd;
struct ahc_cmd *next_cmd;
next_cmd = TAILQ_NEXT(acmd, acmd_links.tqe);
completeq = &ahc->platform_data->completeq;
list_cmd = TAILQ_FIRST(completeq);
while (list_cmd != NULL
&& acmd_scsi_cmd(list_cmd).serial_number
< acmd_scsi_cmd(acmd).serial_number)
list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe);
if (list_cmd != NULL)
TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe);
else
TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe);
acmd = next_cmd;
}
if ((ahc->platform_data->flags & AHC_RUN_CMPLT_Q_TIMER) == 0) {
ahc->platform_data->flags |= AHC_RUN_CMPLT_Q_TIMER;
ahc->platform_data->completeq_timer.expires = jiffies;
......@@ -664,25 +638,17 @@ ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target,
#define AHC_LINUX_MAX_RETURNED_ERRORS 4
static struct ahc_cmd *
ahc_linux_run_complete_queue(struct ahc_softc *ahc, struct ahc_cmd *acmd)
{
ahc_linux_run_complete_queue(struct ahc_softc *ahc)
{
struct ahc_cmd *acmd;
u_long done_flags;
int with_errors;
with_errors = 0;
ahc_done_lock(ahc, &done_flags);
while (acmd != NULL) {
while ((acmd = TAILQ_FIRST(&ahc->platform_data->completeq)) != NULL) {
Scsi_Cmnd *cmd;
cmd = &acmd_scsi_cmd(acmd);
acmd = TAILQ_NEXT(acmd, acmd_links.tqe);
cmd->host_scribble = NULL;
if (ahc_cmd_get_transaction_status(cmd) != DID_OK
|| (cmd->result & 0xFF) != SCSI_STATUS_OK)
with_errors++;
cmd->scsi_done(cmd);
if (with_errors > AHC_LINUX_MAX_RETURNED_ERRORS) {
/*
* Linux uses stack recursion to requeue
......@@ -692,8 +658,19 @@ ahc_linux_run_complete_queue(struct ahc_softc *ahc, struct ahc_cmd *acmd)
* the operating system in case they are going
* to be retried. "ick"
*/
ahc_schedule_completeq(ahc);
break;
}
TAILQ_REMOVE(&ahc->platform_data->completeq,
acmd, acmd_links.tqe);
cmd = &acmd_scsi_cmd(acmd);
acmd = TAILQ_NEXT(acmd, acmd_links.tqe);
cmd->host_scribble = NULL;
if (ahc_cmd_get_transaction_status(cmd) != DID_OK
|| (cmd->result & 0xFF) != SCSI_STATUS_OK)
with_errors++;
cmd->scsi_done(cmd);
}
ahc_done_unlock(ahc, &done_flags);
return (acmd);
......@@ -823,6 +800,67 @@ static int ahc_linux_bus_reset(Scsi_Cmnd *);
static int ahc_linux_dev_reset(Scsi_Cmnd *);
static int ahc_linux_abort(Scsi_Cmnd *);
/*
* Calculate a safe value for AHC_NSEG (as expressed through ahc_linux_nseg).
*
* In pre-2.5.X...
* The midlayer allocates an S/G array dynamically when a command is issued
* using SCSI malloc. This array, which is in an OS dependent format that
* must later be copied to our private S/G list, is sized to house just the
* number of segments needed for the current transfer. Since the code that
* sizes the SCSI malloc pool does not take into consideration fragmentation
* of the pool, executing transactions numbering just a fraction of our
* concurrent transaction limit with list lengths aproaching AHC_NSEG will
* quickly depleat the SCSI malloc pool of usable space. Unfortunately, the
* mid-layer does not properly handle this scsi malloc failures for the S/G
* array and the result can be a lockup of the I/O subsystem. We try to size
* our S/G list so that it satisfies our drivers allocation requirements in
* addition to avoiding fragmentation of the SCSI malloc pool.
*/
static void
ahc_linux_size_nseg(void)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
u_int cur_size;
u_int best_size;
/*
* The SCSI allocator rounds to the nearest 512 bytes
* an cannot allocate across a page boundary. Our algorithm
* is to start at 1K of scsi malloc space per-command and
* loop through all factors of the PAGE_SIZE and pick the best.
*/
best_size = 0;
for (cur_size = 1024; cur_size <= PAGE_SIZE; cur_size *= 2) {
u_int nseg;
nseg = cur_size / sizeof(struct scatterlist);
if (nseg < AHC_LINUX_MIN_NSEG)
continue;
if (best_size == 0) {
best_size = cur_size;
ahc_linux_nseg = nseg;
} else {
u_int best_rem;
u_int cur_rem;
/*
* Compare the traits of the current "best_size"
* with the current size to determine if the
* current size is a better size.
*/
best_rem = best_size % sizeof(struct scatterlist);
cur_rem = cur_size % sizeof(struct scatterlist);
if (cur_rem < best_rem) {
best_size = cur_size;
ahc_linux_nseg = nseg;
}
}
}
#endif
}
/*
* Try to detect an Adaptec 7XXX controller.
*/
......@@ -851,6 +889,7 @@ ahc_linux_detect(Scsi_Host_Template *template)
printf("ahc_linux_detect: Unable to attach\n");
return (0);
}
ahc_linux_size_nseg();
#ifdef MODULE
/*
* If we've been passed any parameters, process them now.
......@@ -881,7 +920,7 @@ ahc_linux_detect(Scsi_Host_Template *template)
ahc_linux_pci_init();
#endif
if (aic7xxx_no_probe == 0)
if (aic7xxx_probe_eisa_vl != 0)
aic7770_linux_probe(template);
/*
......@@ -991,7 +1030,7 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
ahc_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
ahc_linux_queue_cmd_complete(ahc, cmd);
ahc_schedule_completeq(ahc, NULL);
ahc_schedule_completeq(ahc);
ahc_midlayer_entrypoint_unlock(ahc, &flags);
return (0);
}
......@@ -1000,7 +1039,7 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
if (dev == NULL) {
ahc_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
ahc_linux_queue_cmd_complete(ahc, cmd);
ahc_schedule_completeq(ahc, NULL);
ahc_schedule_completeq(ahc);
ahc_midlayer_entrypoint_unlock(ahc, &flags);
printf("%s: aic7xxx_linux_queue - Unable to allocate device!\n",
ahc_name(ahc));
......@@ -1082,7 +1121,8 @@ ahc_linux_slave_destroy(Scsi_Device *device)
&& (dev->flags & AHC_DEV_SLAVE_CONFIGURED) != 0) {
dev->flags |= AHC_DEV_UNCONFIGURED;
if (TAILQ_EMPTY(&dev->busyq)
&& dev->active == 0)
&& dev->active == 0
&& (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)
ahc_linux_free_device(ahc, dev);
}
ahc_midlayer_entrypoint_unlock(ahc, &flags);
......@@ -1093,16 +1133,33 @@ ahc_linux_slave_destroy(Scsi_Device *device)
* off the input host adapter.
*/
static void
ahc_linux_select_queue_depth(struct Scsi_Host * host,
Scsi_Device * scsi_devs)
ahc_linux_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs)
{
Scsi_Device *device;
Scsi_Device *ldev;
struct ahc_softc *ahc;
u_long flags;
ahc = *((struct ahc_softc **)host->hostdata);
ahc_lock(ahc, &flags);
for (device = scsi_devs; device != NULL; device = device->next) {
/*
* Watch out for duplicate devices. This works around
* some quirks in how the SCSI scanning code does its
* device management.
*/
for (ldev = scsi_devs; ldev != device; ldev = ldev->next) {
if (ldev->host == device->host
&& ldev->channel == device->channel
&& ldev->id == device->id
&& ldev->lun == device->lun)
break;
}
/* Skip duplicate. */
if (ldev != device)
continue;
if (device->host == host) {
struct ahc_linux_device *dev;
......@@ -1240,7 +1297,6 @@ static int
ahc_linux_bus_reset(Scsi_Cmnd *cmd)
{
struct ahc_softc *ahc;
struct ahc_cmd *acmd;
u_long s;
int found;
......@@ -1248,14 +1304,7 @@ ahc_linux_bus_reset(Scsi_Cmnd *cmd)
ahc_midlayer_entrypoint_lock(ahc, &s);
found = ahc_reset_channel(ahc, cmd->device->channel + 'A',
/*initiate reset*/TRUE);
acmd = TAILQ_FIRST(&ahc->platform_data->completeq);
TAILQ_INIT(&ahc->platform_data->completeq);
if (acmd != NULL) {
acmd = ahc_linux_run_complete_queue(ahc, acmd);
if (acmd != NULL)
ahc_schedule_completeq(ahc, acmd);
}
ahc_linux_run_complete_queue(ahc);
ahc_midlayer_entrypoint_unlock(ahc, &s);
if (bootverbose)
......@@ -1279,7 +1328,6 @@ Scsi_Host_Template aic7xxx_driver_template = {
#endif
.can_queue = AHC_MAX_QUEUE,
.this_id = -1,
.sg_tablesize = AHC_NSEG,
.cmd_per_lun = 2,
.use_clustering = ENABLE_CLUSTERING,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
......@@ -1346,35 +1394,6 @@ ahc_runq_tasklet(unsigned long data)
#endif
}
/************************ Shutdown/halt/reboot hook ***************************/
#include <linux/notifier.h>
#include <linux/reboot.h>
static struct notifier_block ahc_linux_notifier = {
ahc_linux_halt, NULL, 0
};
static int ahc_linux_halt(struct notifier_block *nb, u_long event, void *buf)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
struct ahc_softc *ahc;
/*
* In 2.5.X, this is called prior to the filesystems
* being synced and the SCSI layer being properly
* shutdown. A different API is required there,
* but the device hooks for this don't quite look
* right.
*/
if (event == SYS_DOWN || event == SYS_HALT) {
TAILQ_FOREACH(ahc, &ahc_tailq, links) {
ahc_shutdown(ahc);
}
}
#endif
return (NOTIFY_OK);
}
/******************************** Macros **************************************/
#define BUILD_SCSIID(ahc, cmd) \
((((cmd)->device->id << TID_SHIFT) & TID) \
......@@ -1482,6 +1501,7 @@ ahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
stack_sg.ds_addr = map->bus_addr;
#else
#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a))
stack_sg.ds_addr = VIRT_TO_BUS(buf);
#endif
stack_sg.ds_len = dmat->maxsize;
......@@ -1613,7 +1633,7 @@ ahc_linux_setup_tag_info_global(char *p)
}
static void
ahc_linux_setup_tag_info(void *arg, int instance, int targ, int32_t value)
ahc_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
{
if ((instance >= 0) && (targ >= 0)
......@@ -1626,7 +1646,7 @@ ahc_linux_setup_tag_info(void *arg, int instance, int targ, int32_t value)
}
static void
ahc_linux_setup_dv(void *arg, int instance, int targ, int32_t value)
ahc_linux_setup_dv(u_long arg, int instance, int targ, int32_t value)
{
if ((instance >= 0)
......@@ -1661,7 +1681,8 @@ aic7xxx_setup(char *s)
{ "debug", &ahc_debug },
#endif
{ "reverse_scan", &aic7xxx_reverse_scan },
{ "no_probe", &aic7xxx_no_probe },
{ "no_probe", &aic7xxx_probe_eisa_vl },
{ "probe_eisa_vlb", &aic7xxx_probe_eisa_vl },
{ "periodic_otag", &aic7xxx_periodic_otag },
{ "pci_parity", &aic7xxx_pci_parity },
{ "seltime", &aic7xxx_seltime },
......@@ -1694,16 +1715,16 @@ aic7xxx_setup(char *s)
ahc_linux_setup_tag_info_global(p + n);
} else if (strncmp(p, "tag_info", n) == 0) {
s = aic_parse_brace_option("tag_info", p + n, end,
2, ahc_linux_setup_tag_info, NULL);
2, ahc_linux_setup_tag_info, 0);
} else if (strncmp(p, "dv", n) == 0) {
s = aic_parse_brace_option("dv", p + n, end, 1,
ahc_linux_setup_dv, NULL);
ahc_linux_setup_dv, 0);
} else if (p[n] == ':') {
*(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0);
} else if (strncmp(p, "verbose", n) == 0) {
*(options[i].flag) = 1;
} else {
*(options[i].flag) = ~(*(options[i].flag));
*(options[i].flag) ^= 0xFFFFFFFF;
}
}
return 1;
......@@ -1713,7 +1734,7 @@ aic7xxx_setup(char *s)
__setup("aic7xxx=", aic7xxx_setup);
#endif
int aic7xxx_verbose;
uint32_t aic7xxx_verbose;
int
ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
......@@ -1739,13 +1760,13 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
ahc->platform_data->host = host;
host->can_queue = AHC_MAX_QUEUE;
host->cmd_per_lun = 2;
host->sg_tablesize = AHC_NSEG;
/* XXX No way to communicate the ID for multiple channels */
host->this_id = ahc->our_id;
host->irq = ahc->platform_data->irq;
host->max_id = (ahc->features & AHC_WIDE) ? 16 : 8;
host->max_lun = AHC_NUM_LUNS;
host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0;
host->sg_tablesize = AHC_NSEG;
ahc_set_unit(ahc, ahc_linux_next_unit());
sprintf(buf, "scsi%d", host->host_no);
new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
......@@ -1953,8 +1974,6 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg)
if (aic7xxx_pci_parity == 0)
ahc->flags |= AHC_DISABLE_PCI_PERR;
if (TAILQ_EMPTY(&ahc_tailq))
register_reboot_notifier(&ahc_linux_notifier);
return (0);
}
......@@ -1966,6 +1985,7 @@ ahc_platform_free(struct ahc_softc *ahc)
int i, j;
if (ahc->platform_data != NULL) {
del_timer_sync(&ahc->platform_data->completeq_timer);
ahc_linux_kill_dv_thread(ahc);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
tasklet_kill(&ahc->platform_data->runq_tasklet);
......@@ -1981,17 +2001,22 @@ ahc_platform_free(struct ahc_softc *ahc)
for (i = 0; i < AHC_NUM_TARGETS; i++) {
targ = ahc->platform_data->targets[i];
if (targ != NULL) {
/* Keep target around through the loop. */
targ->refcount++;
for (j = 0; j < AHC_NUM_LUNS; j++) {
if (targ->devices[j] != NULL) {
dev = targ->devices[j];
ahc_linux_free_device(ahc, dev);
}
if (ahc->platform_data->targets[i] ==
NULL)
break;
if (targ->devices[j] == NULL)
continue;
dev = targ->devices[j];
ahc_linux_free_device(ahc, dev);
}
}
}
/*
* Forcibly free the target now that
* all devices are gone.
*/
ahc_linux_free_target(ahc, targ);
}
}
if (ahc->platform_data->irq != AHC_LINUX_NOIRQ)
free_irq(ahc->platform_data->irq, ahc);
......@@ -2200,19 +2225,12 @@ ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel,
static void
ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc)
{
struct ahc_cmd *acmd;
u_long flags;
ahc_lock(ahc, &flags);
del_timer(&ahc->platform_data->completeq_timer);
ahc->platform_data->flags &= ~AHC_RUN_CMPLT_Q_TIMER;
acmd = TAILQ_FIRST(&ahc->platform_data->completeq);
TAILQ_INIT(&ahc->platform_data->completeq);
if (acmd != NULL) {
acmd = ahc_linux_run_complete_queue(ahc, acmd);
if (acmd != NULL)
ahc_schedule_completeq(ahc, acmd);
}
ahc_linux_run_complete_queue(ahc);
ahc_unlock(ahc, &flags);
}
......@@ -2575,10 +2593,14 @@ ahc_linux_dv_target(struct ahc_softc *ahc, u_int target_offset)
}
ahc_lock(ahc, &s);
if (targ->dv_buffer != NULL)
if (targ->dv_buffer != NULL) {
free(targ->dv_buffer, M_DEVBUF);
if (targ->dv_buffer1 != NULL)
targ->dv_buffer = NULL;
}
if (targ->dv_buffer1 != NULL) {
free(targ->dv_buffer1, M_DEVBUF);
targ->dv_buffer1 = NULL;
}
targ->flags &= ~AHC_DV_REQUIRED;
if (targ->refcount == 0)
ahc_linux_free_target(ahc, targ);
......@@ -3408,7 +3430,6 @@ static void
ahc_linux_dv_timeout(struct scsi_cmnd *cmd)
{
struct ahc_softc *ahc;
struct ahc_cmd *acmd;
struct scb *scb;
u_long flags;
......@@ -3455,15 +3476,9 @@ ahc_linux_dv_timeout(struct scsi_cmnd *cmd)
ahc->platform_data->reset_timer.function =
(ahc_linux_callback_t *)ahc_linux_release_simq;
add_timer(&ahc->platform_data->reset_timer);
acmd = TAILQ_FIRST(&ahc->platform_data->completeq);
TAILQ_INIT(&ahc->platform_data->completeq);
if (ahc_linux_next_device_to_run(ahc) != NULL)
ahc_schedule_runq(ahc);
if (acmd != NULL) {
acmd = ahc_linux_run_complete_queue(ahc, acmd);
if (acmd != NULL)
ahc_schedule_completeq(ahc, acmd);
}
ahc_linux_run_complete_queue(ahc);
ahc_unlock(ahc, &flags);
}
......@@ -3639,9 +3654,8 @@ ahc_linux_device_queue_depth(struct ahc_softc *ahc,
&& dev->scsi_device->tagged_supported != 0) {
ahc_set_tags(ahc, &devinfo, AHC_QUEUE_TAGGED);
printf("scsi%d:%c:%d:%d: Tagged Queuing enabled. Depth %d\n",
ahc->platform_data->host->host_no, devinfo.channel,
devinfo.target, devinfo.lun, tags);
ahc_print_devinfo(ahc, &devinfo);
printf("Tagged Queuing enabled. Depth %d\n", tags);
} else {
ahc_set_tags(ahc, &devinfo, AHC_QUEUE_NONE);
}
......@@ -3867,21 +3881,14 @@ irqreturn_t
ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
{
struct ahc_softc *ahc;
struct ahc_cmd *acmd;
u_long flags;
ahc = (struct ahc_softc *) dev_id;
ahc_lock(ahc, &flags);
ahc_intr(ahc);
acmd = TAILQ_FIRST(&ahc->platform_data->completeq);
TAILQ_INIT(&ahc->platform_data->completeq);
if (ahc_linux_next_device_to_run(ahc) != NULL)
ahc_schedule_runq(ahc);
if (acmd != NULL) {
acmd = ahc_linux_run_complete_queue(ahc, acmd);
if (acmd != NULL)
ahc_schedule_completeq(ahc, acmd);
}
ahc_linux_run_complete_queue(ahc);
ahc_unlock(ahc, &flags);
/* FIXME! Was it really ours? */
return IRQ_HANDLED;
......@@ -3890,12 +3897,9 @@ ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
void
ahc_platform_flushwork(struct ahc_softc *ahc)
{
struct ahc_cmd *acmd;
acmd = TAILQ_FIRST(&ahc->platform_data->completeq);
TAILQ_INIT(&ahc->platform_data->completeq);
while (acmd != NULL)
acmd = ahc_linux_run_complete_queue(ahc, acmd);
while (ahc_linux_run_complete_queue(ahc) != NULL)
;
}
static struct ahc_linux_target*
......@@ -4229,7 +4233,8 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
if (TAILQ_EMPTY(&dev->busyq)) {
if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0
&& dev->active == 0)
&& dev->active == 0
&& (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)
ahc_linux_free_device(ahc, dev);
} else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) {
TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links);
......@@ -4709,6 +4714,9 @@ ahc_linux_dev_timed_unfreeze(u_long arg)
if (dev->qfrozen == 0
&& (dev->flags & AHC_DEV_ON_RUN_LIST) == 0)
ahc_linux_run_device_queue(ahc, dev);
if (TAILQ_EMPTY(&dev->busyq)
&& dev->active == 0)
ahc_linux_free_device(ahc, dev);
ahc_unlock(ahc, &s);
}
......@@ -4768,7 +4776,7 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
* Start by searching the device queue. If not found
* there, check the pending_scb list. If not found
* at all, and the system wanted us to just abort the
* command return success.
* command, return success.
*/
dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,
cmd->device->lun, /*alloc*/FALSE);
......@@ -5026,21 +5034,15 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
printf("Recovery code sleeping\n");
down(&ahc->platform_data->eh_sem);
printf("Recovery code awake\n");
ret = del_timer(&timer);
ret = del_timer_sync(&timer);
if (ret == 0) {
printf("Timer Expired\n");
retval = FAILED;
}
spin_lock_irq(&ahc->platform_data->spin_lock);
}
acmd = TAILQ_FIRST(&ahc->platform_data->completeq);
TAILQ_INIT(&ahc->platform_data->completeq);
ahc_schedule_runq(ahc);
if (acmd != NULL) {
acmd = ahc_linux_run_complete_queue(ahc, acmd);
if (acmd != NULL)
ahc_schedule_completeq(ahc, acmd);
}
ahc_linux_run_complete_queue(ahc);
ahc_midlayer_entrypoint_unlock(ahc, &s);
return (retval);
}
......@@ -5140,8 +5142,6 @@ ahc_linux_exit(void)
*/
ahc_linux_pci_exit();
#endif
unregister_reboot_notifier(&ahc_linux_notifier);
}
module_init(ahc_linux_init);
......
......@@ -53,7 +53,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#131 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#138 $
*
*/
#ifndef _AIC7XXX_LINUX_H_
......@@ -150,8 +150,8 @@ typedef Scsi_Cmnd *ahc_io_ctx_t;
#endif /* BYTE_ORDER */
/************************* Configuration Data *********************************/
extern int aic7xxx_no_probe;
extern int aic7xxx_allow_memio;
extern u_int aic7xxx_no_probe;
extern u_int aic7xxx_allow_memio;
extern int aic7xxx_detect_complete;
extern Scsi_Host_Template aic7xxx_driver_template;
......@@ -267,7 +267,7 @@ typedef struct timer_list ahc_timer_t;
/***************************** Timer Facilities *******************************/
#define ahc_timer_init init_timer
#define ahc_timer_stop del_timer
#define ahc_timer_stop del_timer_sync
typedef void ahc_linux_callback_t (u_long);
static __inline void ahc_timer_reset(ahc_timer_t *timer, int usec,
ahc_callback_t *func, void *arg);
......@@ -305,7 +305,7 @@ ahc_scb_timer_reset(struct scb *scb, u_int usec)
#define AHC_SCSI_HAS_HOST_LOCK 0
#endif
#define AIC7XXX_DRIVER_VERSION "6.2.31"
#define AIC7XXX_DRIVER_VERSION "6.2.32"
/**************************** Front End Queues ********************************/
/*
......@@ -494,7 +494,18 @@ struct ahc_linux_target {
* manner and are allocated below 4GB, the number of S/G segments is
* unrestricted.
*/
#define AHC_NSEG 128
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
/*
* We dynamically adjust the number of segments in pre-2.5 kernels to
* avoid fragmentation issues in the SCSI mid-layer's private memory
* allocator. See aic7xxx_osm.c ahc_linux_size_nseg() for details.
*/
extern u_int ahc_linux_nseg;
#define AHC_NSEG ahc_linux_nseg
#define AHC_LINUX_MIN_NSEG 64
#else
#define AHC_NSEG 128
#endif
/*
* Per-SCB OSM storage.
......@@ -538,9 +549,7 @@ struct ahc_platform_data {
TAILQ_HEAD(, ahc_linux_device) device_runq;
struct ahc_completeq completeq;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93)
spinlock_t spin_lock;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
struct tasklet_struct runq_tasklet;
#endif
......@@ -699,7 +708,6 @@ static __inline void ahc_list_lockinit(void);
static __inline void ahc_list_lock(unsigned long *flags);
static __inline void ahc_list_unlock(unsigned long *flags);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93)
static __inline void
ahc_lockinit(struct ahc_softc *ahc)
{
......@@ -785,65 +793,6 @@ ahc_list_unlock(unsigned long *flags)
spin_unlock_irqrestore(&ahc_list_spinlock, *flags);
}
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,93) */
static __inline void
ahc_lockinit(struct ahc_softc *ahc)
{
}
static __inline void
ahc_lock(struct ahc_softc *ahc, unsigned long *flags)
{
save_flags(*flags);
cli();
}
static __inline void
ahc_unlock(struct ahc_softc *ahc, unsigned long *flags)
{
restore_flags(*flags);
}
static __inline void
ahc_done_lockinit(struct ahc_softc *ahc)
{
}
static __inline void
ahc_done_lock(struct ahc_softc *ahc, unsigned long *flags)
{
/*
* The done lock is always held while
* the ahc lock is held so blocking
* interrupts again would have no effect.
*/
}
static __inline void
ahc_done_unlock(struct ahc_softc *ahc, unsigned long *flags)
{
}
static __inline void
ahc_list_lockinit()
{
}
static __inline void
ahc_list_lock(unsigned long *flags)
{
save_flags(*flags);
cli();
}
static __inline void
ahc_list_unlock(unsigned long *flags)
{
restore_flags(*flags);
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) */
/******************************* PCI Definitions ******************************/
/*
* PCIM_xxx: mask to locate subfield in register
......@@ -902,16 +851,6 @@ int aic7770_map_registers(struct ahc_softc *ahc,
int aic7770_map_int(struct ahc_softc *ahc, u_int irq);
/******************************* PCI Routines *********************************/
/*
* We need to use the bios32.h routines if we are kernel version 2.1.92 or less.
*/
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,92)
#if defined(__sparc_v9__) || defined(__powerpc__)
#error "PPC and Sparc platforms are only supported under 2.1.92 and above"
#endif
#include <linux/bios32.h>
#endif
int ahc_linux_pci_init(void);
void ahc_linux_pci_exit(void);
int ahc_pci_map_registers(struct ahc_softc *ahc);
......@@ -1239,5 +1178,5 @@ void ahc_platform_dump_card_state(struct ahc_softc *ahc);
#define AHC_PCI_CONFIG 0
#endif
#define bootverbose aic7xxx_verbose
extern int aic7xxx_verbose;
extern u_int aic7xxx_verbose;
#endif /* _AIC7XXX_LINUX_H_ */
......@@ -39,7 +39,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#62 $
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#63 $
*
* $FreeBSD$
*/
......@@ -837,14 +837,6 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1);
command |= PCIM_CMD_BUSMASTEREN;
/*
* Disable PCI parity error reporting. Users typically
* do this to work around broken PCI chipsets that get
* the parity timing wrong and thus generate lots of spurious
* errors.
*/
if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0)
command &= ~PCIM_CMD_PERRESPEN;
ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/1);
/* On all PCI adapters, we allow SCB paging */
......@@ -854,6 +846,19 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
if (error != 0)
return (error);
/*
* Disable PCI parity error checking. Users typically
* do this to work around broken PCI chipsets that get
* the parity timing wrong and thus generate lots of spurious
* errors. The chip only allows us to disable *all* parity
* error reporting when doing this, so CIO bus, scb ram, and
* scratch ram parity errors will be ignored too.
*/
if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0) {
ahc->pause |= FAILDIS;
ahc->unpause |= FAILDIS;
}
ahc->bus_intr = ahc_pci_intr;
ahc->bus_chip_init = ahc_pci_chip_init;
ahc->bus_suspend = ahc_pci_suspend;
......@@ -1998,6 +2003,7 @@ ahc_pci_intr(struct ahc_softc *ahc)
ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
if (status1 & DPE) {
ahc->pci_target_perr_count++;
printf("%s: Data Parity Error Detected during address "
"or write data phase\n", ahc_name(ahc));
}
......@@ -2029,6 +2035,19 @@ ahc_pci_intr(struct ahc_softc *ahc)
ahc_outb(ahc, CLRINT, CLRPARERR);
}
if (ahc->pci_target_perr_count > AHC_PCI_TARGET_PERR_THRESH) {
printf(
"%s: WARNING WARNING WARNING WARNING\n"
"%s: Too many PCI parity errors observed as a target.\n"
"%s: Some device on this bus is generating bad parity.\n"
"%s: This is an error *observed by*, not *generated by*, this controller.\n"
"%s: PCI parity error checking has been disabled.\n"
"%s: WARNING WARNING WARNING WARNING\n",
ahc_name(ahc), ahc_name(ahc), ahc_name(ahc),
ahc_name(ahc), ahc_name(ahc), ahc_name(ahc));
ahc->pause |= FAILDIS;
ahc->unpause |= FAILDIS;
}
ahc_unpause(ahc);
}
......
......@@ -37,7 +37,7 @@
* String handling code courtesy of Gerard Roudier's <groudier@club-internet.fr>
* sym driver.
*
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#24 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#26 $
*/
#include "aic7xxx_osm.h"
#include "aic7xxx_inline.h"
......@@ -148,8 +148,9 @@ ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info,
tinfo = ahc_fetch_transinfo(ahc, channel, our_id,
target_id, &tstate);
copy_info(info, "Channel %c Target %d Negotiation Settings\n",
channel, target_id);
if ((ahc->features & AHC_TWIN) != 0)
copy_info(info, "Channel %c ", channel);
copy_info(info, "Target %d Negotiation Settings\n", target_id);
copy_info(info, "\tUser: ");
ahc_format_transinfo(info, &tinfo->user);
targ = ahc->platform_data->targets[target_offset];
......@@ -327,7 +328,10 @@ ahc_linux_proc_info(char *buffer, char **start, off_t offset,
AIC7XXX_DRIVER_VERSION);
copy_info(&info, "%s\n", ahc->description);
ahc_controller_info(ahc, ahc_info);
copy_info(&info, "%s\n\n", ahc_info);
copy_info(&info, "%s\n", ahc_info);
copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n",
ahc->scb_data->numscbs, ahc_linux_nseg);
if (ahc->seep_config == NULL)
copy_info(&info, "No Serial EEPROM\n");
......
......@@ -1335,7 +1335,7 @@ aic_error_action(struct scsi_cmnd *cmd, struct scsi_inquiry_data *inq_data,
char *
aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
aic_option_callback_t *callback, void *callback_arg)
aic_option_callback_t *callback, u_long callback_arg)
{
char *tok_end;
char *tok_end2;
......
......@@ -906,10 +906,10 @@ int aic_inquiry_match(caddr_t /*inqbuffer*/,
int aic_static_inquiry_match(caddr_t /*inqbuffer*/,
caddr_t /*table_entry*/);
typedef void aic_option_callback_t(void *, int, int, int32_t);
typedef void aic_option_callback_t(u_long, int, int, int32_t);
char * aic_parse_brace_option(char *opt_name, char *opt_arg,
char *end, int depth,
aic_option_callback_t *, void *);
aic_option_callback_t *, u_long);
static __inline void scsi_extract_sense(struct scsi_sense_data *sense,
int *error_code, int *sense_key,
......
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