Commit a649f9b4 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 eb0a5728 a4731d08
......@@ -371,9 +371,33 @@ The following information is available in this file:
- Fax Technical Support at +852-2869-7100
-------------------------------------------------------------------
(c) 2003 Adaptec, Inc. All Rights Reserved. No part of this
publication may be reproduced, stored in a retrieval system, or
transmitted in any form or by any means, electronic, mechanical,
photocopying, recording or otherwise, without prior written consent
of Adaptec, Inc., 691 South Milpitas Blvd., Milpitas, CA 95035.
/*
* Copyright (c) 2003 Adaptec Inc. 691 S. Milpitas Blvd., Milpitas CA 95035 USA.
* All rights reserved.
*
* You are permitted to redistribute, use and modify this README file in whole
* or in part in conjunction with redistribution of software governed by the
* General Public License, provided that the following conditions are met:
* 1. Redistributions of README file must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* 3. Modifications or new contributions must be attributed in a copyright
* notice identifying the author ("Contributor") and added below the
* original copyright notice. The copyright notice is for purposes of
* identifying contributors and should not be deemed as permission to alter
* the permissions given by Adaptec.
*
* THIS README FILE IS PROVIDED BY ADAPTEC AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ANY
* WARRANTIES OF NON-INFRINGEMENT OR THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* ADAPTEC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS README
* FILE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
......@@ -132,6 +132,16 @@ The following information is available in this file:
2. Version History
6.2.33 - Dynamically disable PCI parity error reporting after
10 errors are reported to the user. These errors are
the result of some other device issuing PCI transactions
with bad parity. Once the user has been informed of the
problem, continuing to report the errors just degrades
our performance.
6.2.32 - Dynamically sized S/G lists to avoid SCSI malloc
pool fragmentation and SCSI mid-layer deadlock.
6.2.28 - Domain Validation Fixes
PCI parity error disable
Enhanced Memory Mapped I/O probe
......@@ -160,6 +170,7 @@ The following information is available in this file:
Default Value: 0x0000
-----------------------------------------------------------------
Option: no_probe
Option: probe_eisa_vl
Definition: Do not probe for EISA/VLB controllers.
This is a toggle. If the driver is compiled
to not probe EISA/VLB controllers by default,
......@@ -339,9 +350,33 @@ The following information is available in this file:
- Fax Technical Support at +852-2869-7100
-------------------------------------------------------------------
(c) 2002 Adaptec, Inc. All Rights Reserved. No part of this
publication may be reproduced, stored in a retrieval system, or
transmitted in any form or by any means, electronic, mechanical,
photocopying, recording or otherwise, without prior written consent
of Adaptec, Inc., 691 South Milpitas Blvd., Milpitas, CA 95035.
/*
* Copyright (c) 2003 Adaptec Inc. 691 S. Milpitas Blvd., Milpitas CA 95035 USA.
* All rights reserved.
*
* You are permitted to redistribute, use and modify this README file in whole
* or in part in conjunction with redistribution of software governed by the
* General Public License, provided that the following conditions are met:
* 1. Redistributions of README file must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* 3. Modifications or new contributions must be attributed in a copyright
* notice identifying the author ("Contributor") and added below the
* original copyright notice. The copyright notice is for purposes of
* identifying contributors and should not be deemed as permission to alter
* the permissions given by Adaptec.
*
* THIS README FILE IS PROVIDED BY ADAPTEC AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ANY
* WARRANTIES OF NON-INFRINGEMENT OR THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* ADAPTEC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS README
* FILE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
......@@ -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.
/* 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.
*/
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;
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#190 $
*
* $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;
......@@ -1023,7 +1052,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
switch (scb->hscb->task_management) {
case SIU_TASKMGMT_ABORT_TASK:
tag = scb->hscb->tag;
tag = SCB_GET_TAG(scb);
case SIU_TASKMGMT_ABORT_TASK_SET:
case SIU_TASKMGMT_CLEAR_TASK_SET:
lun = scb->hscb->lun;
......@@ -1087,7 +1116,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
ahd_outb(ahd, SCB_TASK_MANAGEMENT, 0);
ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),
SCB_GET_CHANNEL(ahd, scb),
SCB_GET_LUN(scb), scb->hscb->tag,
SCB_GET_LUN(scb), SCB_GET_TAG(scb),
ROLE_INITIATOR, /*status*/0,
SEARCH_REMOVE);
}
......@@ -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;
......@@ -5481,7 +5517,7 @@ ahd_free_scb(struct ahd_softc *ahd, struct scb *scb)
/* Clean up for the next user */
scb->flags = SCB_FLAG_NONE;
scb->hscb->control = 0;
ahd->scb_data.scbindex[scb->hscb->tag] = NULL;
ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = NULL;
if (scb->col_scb == NULL) {
......@@ -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;
......@@ -5894,7 +5930,7 @@ ahd_init(struct ahd_softc *ahd)
* specially from the DMA safe memory chunk used for the QOUTFIFO.
*/
ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr;
ahd->next_queued_hscb->hscb_busaddr = next_baddr;
ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr);
ahd->init_level++;
......@@ -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 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_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#48 $
*
* $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);
......@@ -298,9 +298,12 @@ ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb)
scb->hscb->datacnt = sg->len;
} else {
struct ahd_dma_seg *sg;
uint32_t *dataptr_words;
sg = (struct ahd_dma_seg *)scb->sg_list;
scb->hscb->dataptr = sg->addr;
dataptr_words = (uint32_t*)&scb->hscb->dataptr;
dataptr_words[0] = sg->addr;
dataptr_words[1] = 0;
if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) {
uint64_t high_addr;
......@@ -777,12 +780,15 @@ ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb)
#ifdef AHD_DEBUG
if ((ahd_debug & AHD_SHOW_QUEUE) != 0) {
uint64_t host_dataptr;
host_dataptr = ahd_le64toh(scb->hscb->dataptr);
printf("%s: Queueing SCB 0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
ahd_name(ahd),
SCB_GET_TAG(scb), scb->hscb->hscb_busaddr,
(u_int)((scb->hscb->dataptr >> 32) & 0xFFFFFFFF),
(u_int)(scb->hscb->dataptr & 0xFFFFFFFF),
scb->hscb->datacnt);
SCB_GET_TAG(scb), ahd_le32toh(scb->hscb->hscb_busaddr),
(u_int)((host_dataptr >> 32) & 0xFFFFFFFF),
(u_int)(host_dataptr & 0xFFFFFFFF),
ahd_le32toh(scb->hscb->datacnt));
}
#endif
/* Tell the adapter about the newly queued SCB */
......@@ -805,7 +811,7 @@ ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb)
static __inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op);
static __inline void ahd_sync_tqinfifo(struct ahd_softc *ahd, int op);
static __inline u_int ahd_check_cmdcmpltqueues(struct ahd_softc *ahd);
static __inline void ahd_intr(struct ahd_softc *ahd);
static __inline int ahd_intr(struct ahd_softc *ahd);
static __inline void
ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
......@@ -864,7 +870,7 @@ ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
/*
* Catch an interrupt from the adapter
*/
static __inline void
static __inline int
ahd_intr(struct ahd_softc *ahd)
{
u_int intstat;
......@@ -876,7 +882,7 @@ ahd_intr(struct ahd_softc *ahd)
* so just return. This is likely just a shared
* interrupt.
*/
return;
return (0);
}
/*
......@@ -891,6 +897,9 @@ ahd_intr(struct ahd_softc *ahd)
else
intstat = ahd_inb(ahd, INTSTAT);
if ((intstat & INT_PEND) == 0)
return (0);
if (intstat & CMDCMPLT) {
ahd_outb(ahd, CLRINT, CLRCMDINT);
......@@ -924,28 +933,25 @@ ahd_intr(struct ahd_softc *ahd)
#endif
}
if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0)
/* Hot eject */
return;
if ((intstat & INT_PEND) == 0)
return;
if (intstat & HWERRINT) {
/*
* Handle statuses that may invalidate our cached
* copy of INTSTAT separately.
*/
if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) {
/* Hot eject. Do nothing */
} else if (intstat & HWERRINT) {
ahd_handle_hwerrint(ahd);
return;
}
if ((intstat & (PCIINT|SPLTINT)) != 0) {
} else if ((intstat & (PCIINT|SPLTINT)) != 0) {
ahd->bus_intr(ahd);
return;
}
} else {
if ((intstat & SEQINT) != 0)
ahd_handle_seqint(ahd, intstat);
if ((intstat & SCSIINT) != 0)
ahd_handle_scsiint(ahd, intstat);
}
return (1);
}
#endif /* _AIC79XX_INLINE_H_ */
/*
* 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#159 $
*
* --------------------------------------------------------------------------
* 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
......@@ -368,15 +371,14 @@ static uint32_t aic79xx_extended = 0;
* 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
* 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;
......@@ -1226,6 +1292,7 @@ ahd_linux_abort(Scsi_Cmnd *cmd)
u_int last_phase;
u_int cdb_byte;
int retval;
int was_paused;
int paused;
int wait;
int disconnected;
......@@ -1265,7 +1332,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,
......@@ -1328,6 +1395,7 @@ ahd_linux_abort(Scsi_Cmnd *cmd)
* didn't "just" miss an interrupt that would
* affect this cmd.
*/
was_paused = ahd_is_paused(ahd);
ahd_pause_and_flushwork(ahd);
paused = TRUE;
......@@ -1338,11 +1406,13 @@ ahd_linux_abort(Scsi_Cmnd *cmd)
goto no_cmd;
}
printf("%s: At time of recovery, card was %spaused\n",
was_paused ? "" : "not ");
ahd_dump_card_state(ahd);
disconnected = TRUE;
if (ahd_search_qinfifo(ahd, cmd->device->id, cmd->device->channel + 'A',
cmd->device->lun, pending_scb->hscb->tag,
cmd->device->lun, SCB_GET_TAG(pending_scb),
ROLE_INITIATOR, CAM_REQ_ABORTED,
SEARCH_COMPLETE) > 0) {
printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
......@@ -1371,7 +1441,7 @@ ahd_linux_abort(Scsi_Cmnd *cmd)
* bus or is in the disconnected state.
*/
if (last_phase != P_BUSFREE
&& pending_scb->hscb->tag == active_scbptr) {
&& SCB_GET_TAG(pending_scb) == active_scbptr) {
/*
* We're active on the bus, so assert ATN
......@@ -1392,7 +1462,7 @@ ahd_linux_abort(Scsi_Cmnd *cmd)
* to select the device before it reconnects.
*/
pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
ahd_set_scbptr(ahd, pending_scb->hscb->tag);
ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
pending_scb->hscb->cdb_len = 0;
pending_scb->hscb->task_attribute = 0;
pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;
......@@ -1476,21 +1546,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 +1579,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 +1644,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 +1663,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 +1675,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 +1699,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 +1765,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 +1946,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 +1959,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 +1981,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 +1991,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 +2070,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 +2104,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 +2136,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 +2308,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 +2319,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 +2333,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) {
if (targ->devices[j] == NULL)
continue;
dev = targ->devices[j];
ahd_linux_free_device(ahd, dev);
}
if (ahd->platform_data->targets[i] ==
NULL)
break;
}
/*
* Forcibly free the target now that
* all devices are gone.
*/
ahd_linux_free_target(ahd, targ);
}
}
......@@ -2546,19 +2567,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 +2935,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 +3778,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 +3824,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 +4035,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);
}
......@@ -4201,38 +4210,29 @@ ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev)
/*
* SCSI controller interrupt handler.
*/
void
AIC_LINUX_IRQRETURN_T
ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
{
struct ahd_softc *ahd;
struct ahd_cmd *acmd;
u_long flags;
int ours;
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);
ours = ahd_intr(ahd);
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);
AIC_LINUX_IRQRETURN(ours);
}
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*
......@@ -4452,13 +4452,12 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
Scsi_Cmnd *cmd;
struct ahd_linux_device *dev;
LIST_REMOVE(scb, pending_links);
if ((scb->flags & SCB_ACTIVE) == 0) {
printf("SCB %d done'd twice\n", scb->hscb->tag);
printf("SCB %d done'd twice\n", SCB_GET_TAG(scb));
ahd_dump_card_state(ahd);
panic("Stopping for safety");
}
LIST_REMOVE(scb, pending_links);
cmd = scb->io_ctx;
dev = scb->platform_data->dev;
dev->active--;
......@@ -4542,7 +4541,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 +5065,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 +5146,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#130 $
*
*/
#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.8"
/**************************** 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.
*/
#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);
......@@ -1270,7 +1211,8 @@ void ahd_platform_set_tags(struct ahd_softc *ahd,
int ahd_platform_abort_scbs(struct ahd_softc *ahd, int target,
char channel, int lun, u_int tag,
role_t role, uint32_t status);
void ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs);
AIC_LINUX_IRQRETURN_T
ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs);
void ahd_platform_flushwork(struct ahd_softc *ahd);
int ahd_softc_comp(struct ahd_softc *, struct ahd_softc *);
void ahd_done(struct ahd_softc*, struct scb*);
......@@ -1285,5 +1227,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_ */
......@@ -38,7 +38,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#70 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#71 $
*
* $FreeBSD$
*/
......@@ -565,14 +565,13 @@ ahd_check_extport(struct ahd_softc *ahd)
#if AHD_DEBUG
if (have_seeprom != 0
&& (ahd_debug & AHD_DUMP_SEEPROM) != 0) {
uint8_t *sc_data;
uint16_t *sc_data;
int i;
printf("%s: Seeprom Contents:", ahd_name(ahd));
sc_data = (uint8_t *)sc;
sc_data = (uint16_t *)sc;
for (i = 0; i < (sizeof(*sc)); i += 2)
printf("\n\t0x%.4x",
sc_data[i] | (sc_data[i+1] << 8));
printf("\n\t0x%.4x", sc_data[i]);
printf("\n");
}
#endif
......
......@@ -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#17 $
*/
#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_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));
......
......@@ -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_inline.h#40 $
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#42 $
*
* $FreeBSD$
*/
......@@ -500,7 +500,7 @@ ahc_get_sense_bufaddr(struct ahc_softc *ahc, struct scb *scb)
static __inline void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op);
static __inline void ahc_sync_tqinfifo(struct ahc_softc *ahc, int op);
static __inline u_int ahc_check_cmdcmpltqueues(struct ahc_softc *ahc);
static __inline void ahc_intr(struct ahc_softc *ahc);
static __inline int ahc_intr(struct ahc_softc *ahc);
static __inline void
ahc_sync_qoutfifo(struct ahc_softc *ahc, int op)
......@@ -558,7 +558,7 @@ ahc_check_cmdcmpltqueues(struct ahc_softc *ahc)
/*
* Catch an interrupt from the adapter
*/
static __inline void
static __inline int
ahc_intr(struct ahc_softc *ahc)
{
u_int intstat;
......@@ -570,7 +570,7 @@ ahc_intr(struct ahc_softc *ahc)
* so just return. This is likely just a shared
* interrupt.
*/
return;
return (0);
}
/*
* Instead of directly reading the interrupt status register,
......@@ -585,6 +585,20 @@ ahc_intr(struct ahc_softc *ahc)
intstat = ahc_inb(ahc, INTSTAT);
}
if ((intstat & INT_PEND) == 0) {
#if AHC_PCI_CONFIG > 0
if (ahc->unsolicited_ints > 500) {
ahc->unsolicited_ints = 0;
if ((ahc->chip & AHC_PCI) != 0
&& (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0)
ahc->bus_intr(ahc);
}
#endif
ahc->unsolicited_ints++;
return (0);
}
ahc->unsolicited_ints = 0;
if (intstat & CMDCMPLT) {
ahc_outb(ahc, CLRINT, CLRCMDINT);
......@@ -604,31 +618,16 @@ ahc_intr(struct ahc_softc *ahc)
#endif
}
if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0)
/* Hot eject */
return;
if ((intstat & INT_PEND) == 0) {
#if AHC_PCI_CONFIG > 0
if (ahc->unsolicited_ints > 500) {
ahc->unsolicited_ints = 0;
if ((ahc->chip & AHC_PCI) != 0
&& (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0)
ahc->bus_intr(ahc);
}
#endif
ahc->unsolicited_ints++;
return;
}
ahc->unsolicited_ints = 0;
if (intstat & BRKADRINT) {
/*
* Handle statuses that may invalidate our cached
* copy of INTSTAT separately.
*/
if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0) {
/* Hot eject. Do nothing */
} else if (intstat & BRKADRINT) {
ahc_handle_brkadrint(ahc);
/* Fatal error, no more interrupts to handle. */
return;
}
} else if ((intstat & (SEQINT|SCSIINT)) != 0) {
if ((intstat & (SEQINT|SCSIINT)) != 0)
ahc_pause_bug_fix(ahc);
if ((intstat & SEQINT) != 0)
......@@ -636,6 +635,8 @@ ahc_intr(struct ahc_softc *ahc)
if ((intstat & SCSIINT) != 0)
ahc_handle_scsiint(ahc, intstat);
}
return (1);
}
#endif /* _AIC7XXX_INLINE_H_ */
/*
* 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#220 $
*
* 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.
* 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"
" probe_eisa_vl 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=probe_eisa_vl.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_vl", &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,15 +2001,20 @@ 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) {
if (targ->devices[j] == NULL)
continue;
dev = targ->devices[j];
ahc_linux_free_device(ahc, dev);
}
if (ahc->platform_data->targets[i] ==
NULL)
break;
}
/*
* Forcibly free the target now that
* all devices are gone.
*/
ahc_linux_free_target(ahc, targ);
}
}
......@@ -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);
}
......@@ -3863,39 +3877,29 @@ ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev)
/*
* SCSI controller interrupt handler.
*/
irqreturn_t
AIC_LINUX_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;
int ours;
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);
ours = ahc_intr(ahc);
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;
AIC_LINUX_IRQRETURN(ours);
}
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);
}
......@@ -4727,6 +4735,7 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
u_int saved_scsiid;
u_int cdb_byte;
int retval;
int was_paused;
int paused;
int wait;
int disconnected;
......@@ -4768,7 +4777,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);
......@@ -4855,11 +4864,10 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
* behind our back and that we didn't "just" miss
* an interrupt that would affect this cmd.
*/
was_paused = ahc_is_paused(ahc);
ahc_pause_and_flushwork(ahc);
paused = TRUE;
ahc_dump_card_state(ahc);
if ((pending_scb->flags & SCB_ACTIVE) == 0) {
printf("%s:%d:%d:%d: Command already completed\n",
ahc_name(ahc), cmd->device->channel, cmd->device->id,
......@@ -4867,6 +4875,10 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
goto no_cmd;
}
printf("%s: At time of recovery, card was %spaused\n",
was_paused ? "" : "not ");
ahc_dump_card_state(ahc);
disconnected = TRUE;
if (flag == SCB_ABORT) {
if (ahc_search_qinfifo(ahc, cmd->device->id,
......@@ -5026,21 +5038,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 +5146,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#140 $
*
*/
#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.33"
/**************************** 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.
*/
#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);
......@@ -1224,7 +1163,8 @@ void ahc_platform_set_tags(struct ahc_softc *ahc,
int ahc_platform_abort_scbs(struct ahc_softc *ahc, int target,
char channel, int lun, u_int tag,
role_t role, uint32_t status);
irqreturn_t ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs);
AIC_LINUX_IRQRETURN_T
ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs);
void ahc_platform_flushwork(struct ahc_softc *ahc);
int ahc_softc_comp(struct ahc_softc *, struct ahc_softc *);
void ahc_done(struct ahc_softc*, struct scb*);
......@@ -1239,5 +1179,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#27 $
*/
#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_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;
......
......@@ -15,15 +15,58 @@
* Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
*
* $FreeBSD: src/sys/cam/scsi/scsi_all.h,v 1.21 2002/10/08 17:12:44 ken Exp $
*
* Copyright (c) 2003 Adaptec Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id$
*/
#ifndef _AICLIB_H
#define _AICLIB_H
/*
* SCSI general interface description
* Linux Interrupt Support.
*/
#ifndef _SCSI_SCSI_ALL_H
#define _SCSI_SCSI_ALL_H 1
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
#define AIC_LINUX_IRQRETURN_T irqreturn_t
#define AIC_LINUX_IRQRETURN(ours) return (IRQ_RETVAL(ours))
#else
#define AIC_LINUX_IRQRETURN_T void
#define AIC_LINUX_IRQRETURN(ours) return
#endif
/*
* SCSI command format
......@@ -906,10 +949,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,
......@@ -1003,4 +1046,4 @@ scsi_4btoul(uint8_t *bytes)
return (rv);
}
#endif /*_SCSI_SCSI_ALL_H*/
#endif /*_AICLIB_H */
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