Commit 8ab9f40f 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 91e2be46 21718980
#
# AIC7XXX and AIC79XX 2.5.X Kernel configuration File.
# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Kconfig.aic7xxx#5 $
# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Kconfig.aic7xxx#6 $
#
config SCSI_AIC7XXX
tristate "Adaptec AIC7xxx Fast -> U160 support (New Driver)"
......
......@@ -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#27 $
* $Id: //depot/aic7xxx/aic7xxx/aic7770.c#29 $
*
* $FreeBSD$
*/
......@@ -59,6 +59,9 @@
#define ID_OLV_274x 0x04907782 /* Olivetti OEM */
#define ID_OLV_274xD 0x04907783 /* Olivetti OEM (Differential) */
static int aic7770_chip_init(struct ahc_softc *ahc);
static int aic7770_suspend(struct ahc_softc *ahc);
static int aic7770_resume(struct ahc_softc *ahc);
static int aha2840_load_seeprom(struct ahc_softc *ahc);
static ahc_device_setup_t ahc_aic7770_VL_setup;
static ahc_device_setup_t ahc_aic7770_EISA_setup;;
......@@ -144,6 +147,12 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
ahc->description = entry->name;
error = ahc_softc_init(ahc);
if (error != 0)
return (error);
ahc->bus_chip_init = aic7770_chip_init;
ahc->bus_suspend = aic7770_suspend;
ahc->bus_resume = aic7770_resume;
error = ahc_reset(ahc);
if (error != 0)
......@@ -226,6 +235,9 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
ahc_outb(ahc, BUSSPD, hostconf & DFTHRSH);
ahc_outb(ahc, BUSTIME, (hostconf << 2) & BOFF);
ahc->bus_softc.aic7770_softc.busspd = hostconf & DFTHRSH;
ahc->bus_softc.aic7770_softc.bustime = (hostconf << 2) & BOFF;
/*
* Generic aic7xxx initialization.
*/
......@@ -253,6 +265,28 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
return (0);
}
static int
aic7770_chip_init(struct ahc_softc *ahc)
{
ahc_outb(ahc, BUSSPD, ahc->bus_softc.aic7770_softc.busspd);
ahc_outb(ahc, BUSTIME, ahc->bus_softc.aic7770_softc.bustime);
ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~AUTOFLUSHDIS);
ahc_outb(ahc, BCTL, ENABLE);
return (ahc_chip_init(ahc));
}
static int
aic7770_suspend(struct ahc_softc *ahc)
{
return (ahc_suspend(ahc));
}
static int
aic7770_resume(struct ahc_softc *ahc)
{
return (ahc_resume(ahc));
}
/*
* Read the 284x SEEPROM.
*/
......@@ -371,5 +405,6 @@ ahc_aic7770_setup(struct ahc_softc *ahc)
ahc->features = AHC_AIC7770_FE;
ahc->bugs |= AHC_TMODE_WIDEODD_BUG;
ahc->flags |= AHC_PAGESCBS;
ahc->instruction_ram_size = 448;
return (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.h#78 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#79 $
*
* $FreeBSD$
*/
......@@ -309,7 +309,17 @@ typedef enum {
* Controller write to INTSTAT will lose to a host
* write to CLRINT.
*/
AHD_INTCOLLISION_BUG = 0x100000
AHD_INTCOLLISION_BUG = 0x100000,
/*
* The GEM318 violates the SCSI spec by not waiting
* the mandated bus settle delay between phase changes
* in some situations. Some aic79xx chip revs. are more
* strict in this regard and will treat REQ assertions
* that fall within the bus settle delay window as
* glitches. This flag enables causes the firmware
* to tolerate early REQ assertions.
*/
AHD_EARLY_REQ_BUG = 0x200000
} ahd_bug;
/*
......
......@@ -40,7 +40,7 @@
* $FreeBSD$
*/
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#78 $"
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#86 $"
PATCH_ARG_LIST = "struct ahd_softc *ahd"
PREFIX = "ahd_"
......@@ -122,22 +122,24 @@ gsfifo_complete_normally:
/*
* Since this status did not consume a FIFO, we have to
* be a bit more dilligent in how we check for FIFOs pertaining
* to this transaction. There are three states that a FIFO still
* to this transaction. There are two states that a FIFO still
* transferring data may be in.
*
* 1) Configured and draining to the host, with a pending CLRCHN.
* 2) Configured and draining to the host, no pending CLRCHN.
* 3) Pending cfg4data, fifo not empty.
* 1) Configured and draining to the host, with a FIFO handler.
* 2) Pending cfg4data, fifo not empty.
*
* Cases 1 and 2 can be detected by noticing that a longjmp is
* active for the FIFO and LONGJMP_SCB matches our SCB. In this
* case, we allow the routine servicing the FIFO to complete the SCB.
* Case 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 3 implies either a pending or yet to occur save data
* 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 2, we will properly defer the post of the SCB
* 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;
/*
......@@ -519,7 +521,7 @@ BEGIN_CRITICAL;
/*
* For packetized, the LQO manager clears ENSELO on
* the assertion of SELDO. If we are non-packetized,
* LASTSCB and CURRSCB are acuate.
* LASTSCB and CURRSCB are accurate.
*/
test SCSISEQ0, ENSELO jnz use_lastscb;
......@@ -1030,14 +1032,6 @@ queue_arg1_scb_completion:
SET_MODE(M_SCSI, M_SCSI)
bmov SCBPTR, ARG_1, 2;
queue_scb_completion:
if ((ahd->bugs & AHD_ABORT_LQI_BUG) == 0) {
/*
* Set MK_MESSAGE to trigger an abort should this SCB
* be referenced by a target even though it is not currently
* active.
*/
or SCB_CONTROL, MK_MESSAGE;
}
test SCB_SCSI_STATUS,0xff jnz bad_status;
/*
* Check for residuals
......@@ -1163,7 +1157,28 @@ clear_target_state:
mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret;
phase_lock:
if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) {
/*
* Don't ignore persistent REQ assertions just because
* they were asserted within the bus settle delay window.
* This allows us to tolerate devices like the GEM318
* that violate the SCSI spec. We are careful not to
* count REQ while we are waiting for it to fall during
* an async phase due to our asserted ACK. Each
* sequencer instruction takes ~25ns, so the REQ must
* last at least 100ns in order to be counted as a true
* REQ.
*/
test SCSIPHASE, 0xFF jnz phase_locked;
test SCSISIGI, ACKI jnz phase_lock;
test SCSISIGI, REQI jz phase_lock;
test SCSIPHASE, 0xFF jnz phase_locked;
test SCSISIGI, ACKI jnz phase_lock;
test SCSISIGI, REQI jz phase_lock;
phase_locked:
} else {
test SCSIPHASE, 0xFF jz .;
}
test SSTAT1, SCSIPERR jnz phase_lock;
phase_lock_latch_phase:
and LASTPHASE, PHASE_MASK, SCSISIGI ret;
......@@ -1247,7 +1262,7 @@ service_fifo:
nop;
}
and SGHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR;
mvi CCSGCTL, CCSGEN|SG_CACHE_AVAIL|CCSGRESET;
mvi CCSGCTL, CCSGEN|CCSGRESET;
or SG_STATE, FETCH_INPROG ret;
idle_sgfetch_complete:
/*
......@@ -1261,6 +1276,15 @@ idle_sgfetch_complete:
idle_sg_avail:
/* Does the hardware have space for another SG entry? */
test DFSTATUS, PRELOAD_AVAIL jz return;
/*
* On the A, preloading a segment before HDMAENACK
* comes true can clobber the shaddow address of the
* first segment in the S/G FIFO. Wait until it is
* safe to proceed.
*/
if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0) {
test DFCNTRL, HDMAENACK jz return;
}
if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
bmov HADDR, CCSGRAM, 8;
} else {
......@@ -1290,22 +1314,12 @@ sg_advance:
or SINDEX, LAST_SEG;
clr SG_STATE;
mov SG_CACHE_PRE, SINDEX;
/*
* Load the segment. Or in HDMAEN here too
* just in case HDMAENACK has not come true
* by the time this segment is loaded. If
* HDMAENACK is not true, this or will disable
* HDMAEN mid-transfer. We do not want to simply
* mvi our original settings as SCSIEN automatically
* de-asserts and we don't want to accidentally
* re-enable it.
*/
if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {
/*
* Use SCSIENWRDIS so that SCSIEN is never
* modified by this operation.
*/
or DFCNTRL, PRELOADEN|SCSIENWRDIS|HDMAEN;
or DFCNTRL, PRELOADEN|HDMAEN|SCSIENWRDIS;
} else {
or DFCNTRL, PRELOADEN|HDMAEN;
}
......@@ -1510,12 +1524,6 @@ data_phase_done:
* the idle loop and there is no need to perform
* any fixups.
*/
calc_residual:
test SG_CACHE_SHADOW, LAST_SEG jz residual_before_last_seg;
/* Record if we've consumed all S/G entries */
test MDFFSTAT, SHVALID jz . + 2;
bmov SCB_RESIDUAL_DATACNT, SHCNT, 3 ret;
or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL ret;
residual_before_last_seg:
test MDFFSTAT, SHVALID jnz sgptr_fixup;
/*
......@@ -1525,7 +1533,13 @@ residual_before_last_seg:
*/
call idle_loop_service_fifos;
RESTORE_MODE(SAVED_MODE)
jmp calc_residual;
/* FALLTHROUGH */
calc_residual:
test SG_CACHE_SHADOW, LAST_SEG jz residual_before_last_seg;
/* Record if we've consumed all S/G entries */
test MDFFSTAT, SHVALID jz . + 2;
bmov SCB_RESIDUAL_DATACNT, SHCNT, 3 ret;
or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL ret;
sgptr_fixup:
/*
......@@ -1570,7 +1584,51 @@ export timer_isr:
}
export seq_isr:
nop; /* Jumps in the first ISR instruction fail on Rev A. */
if ((ahd->features & AHD_RTI) == 0) {
/*
* On RevA Silicon, if the target returns us to data-out
* after we have already trained for data-out, it is
* possible for us to transition the free running clock to
* data-valid before the required 100ns P1 setup time (8 P1
* assertions in fast-160 mode). This will only happen if
* this L-Q is a continuation of a data transfer for which
* we have already prefetched data into our FIFO (LQ/Data
* followed by LQ/Data for the same write transaction).
* This can cause some target implementations to miss the
* first few data transfers on the bus. We detect this
* situation by noticing that this is the first data transfer
* after an LQ (LQIWORKONLQ true), that the data transfer is
* a continuation of a transfer already setup in our FIFO
* (SAVEPTRS interrupt), and that the transaction is a write
* (DIRECTION set in DFCNTRL). The delay is performed by
* disabling SCSIEN until we see the first REQ from the
* target.
*
* First instruction in an ISR cannot be a branch on
* Rev A. Snapshot LQISTAT2 so the status is not missed
* 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 LONGJMP_ADDR[1], INVALID_ADDR jz saveptr_active_fifo;
/*
* Switch to the active FIFO.
*/
xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
test DFCNTRL, DIRECTION jz snapshot_other_fifo;
and DFCNTRL, ~SCSIEN;
test SSTAT1, REQINIT jz .;
or DFCNTRL, SCSIEN;
/* FALLTHROUGH */
snapshot_other_fifo:
xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
/* FALLTHROUGH */
snapshot_saveptr:
mvi DFFSXFRCTL, CLRCHN;
or SEQINTCTL, IRET ret;
data_valid:
}
test SEQINTSRC, CFG4DATA jnz cfg4data_intr;
test SEQINTSRC, CFG4ISTAT jnz cfg4istat_intr;
test SEQINTSRC, SAVEPTRS jnz saveptr_intr;
......@@ -1583,21 +1641,23 @@ export seq_isr:
* active and contains a snapshot of the current poniter information.
* This happens between packets in a stream for a single L_Q. Since we
* are not performing a pointer save, we can safely clear the channel
* so it can be used for other transactions.
* so it can be used for other transactions. On RTI capable controllers,
* where snapshots can, and are, disabled, the code to handle this type
* of snapshot is not active.
*
* The second case is a save pointers on an active FIFO which occurs
* if the target changes to a new L_Q or busfrees/QAS' and the transfer
* if the target changes to a new L_Q or busfrees/QASes and the transfer
* has a residual. This should occur coincident with a ctxtdone. We
* disable the interrupt and allow our active routine to handle the
* save.
*/
saveptr_intr:
test DFCNTRL, HDMAENACK jz snapshot_saveptr;
if ((ahd->features & AHD_RTI) == 0) {
test LONGJMP_ADDR[1], INVALID_ADDR jnz snapshot_saveptr;
}
saveptr_active_fifo:
and SEQIMODE, ~ENSAVEPTRS;
or SEQINTCTL, IRET ret;
snapshot_saveptr:
mvi DFFSXFRCTL, CLRCHN;
or SEQINTCTL, IRET ret;
cfg4data_intr:
test SCB_SGPTR[0], SG_LIST_NULL jnz pkt_handle_overrun;
......@@ -1672,7 +1732,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_done;
test SG_CACHE_SHADOW, LAST_SEG_DONE jnz last_pkt_xfer_done;
test SCSIPHASE, ~DATA_PHASE_MASK jz . + 2;
test SCSISIGO, ATNO jnz . + 2;
test SSTAT2, NONPACKREQ jz return;
......@@ -1716,7 +1776,7 @@ pkt_saveptrs_clrchn:
mvi DFFSXFRCTL, CLRCHN ret;
END_CRITICAL;
last_pkt_done:
last_pkt_xfer_done:
BEGIN_CRITICAL;
if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) {
or DFCNTRL, FIFOFLUSH;
......
......@@ -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#156 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#161 $
*
* $FreeBSD$
*/
......@@ -1249,6 +1249,14 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
ahd_outb(ahd, CLRSINT3, status3);
} else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) {
ahd_handle_lqiphase_error(ahd, lqistat1);
} else if ((lqistat1 & LQICRCI_NLQ) != 0) {
/*
* This status can be delayed during some
* streaming operations. The SCSIPHASE
* handler has already dealt with this case
* so just clear the error.
*/
ahd_outb(ahd, CLRLQIINT1, CLRLQICRCI_NLQ);
} else if ((status & BUSFREE) != 0) {
u_int lqostat1;
int restart;
......@@ -1626,14 +1634,6 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
scb = ahd_lookup_scb(ahd, scbid);
if (scb == NULL)
panic("SCB not valid during LQOBUSFREE");
/*
* Return the LQO manager to its idle loop. It will
* not do this automatically if the busfree occurs
* after the first REQ of either the LQ or command
* packet or between the LQ and command packet.
*/
ahd_outb(ahd, LQCTL2, ahd_inb(ahd, LQCTL2) | LQOTOIDLE);
/*
* Clear the status.
*/
......@@ -1641,8 +1641,17 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)
ahd_outb(ahd, CLRLQOINT1, 0);
ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
ahd_flush_device_writes(ahd);
ahd_outb(ahd, CLRSINT0, CLRSELDO);
/*
* Return the LQO manager to its idle loop. It will
* not do this automatically if the busfree occurs
* after the first REQ of either the LQ or command
* packet or between the LQ and command packet.
*/
ahd_outb(ahd, LQCTL2, ahd_inb(ahd, LQCTL2) | LQOTOIDLE);
/*
* Update the waiting for selection queue so
* we restart on the correct SCB.
......@@ -1653,9 +1662,9 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
ahd_outw(ahd, WAITING_TID_HEAD, scbid);
waiting_t = ahd_inw(ahd, WAITING_TID_TAIL);
next = SCB_LIST_NULL;
if (waiting_t == waiting_h) {
ahd_outw(ahd, WAITING_TID_TAIL, scbid);
next = SCB_LIST_NULL;
} else {
ahd_set_scbptr(ahd, waiting_h);
next = ahd_inw(ahd, SCB_NEXT2);
......@@ -1704,6 +1713,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
scb = ahd_lookup_scb(ahd, scbid);
ahd_print_path(ahd, scb);
printf("Unexpected PKT busfree condition\n");
ahd_dump_card_state(ahd);
ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), 'A',
SCB_GET_LUN(scb), SCB_GET_TAG(scb),
ROLE_INITIATOR, CAM_UNEXP_BUSFREE);
......@@ -5049,7 +5059,7 @@ ahd_reset(struct ahd_softc *ahd)
/*
* If a recovery action has forced a chip reset,
* re-initialize the chip to our likeing.
* re-initialize the chip to our liking.
*/
if (ahd->init_level > 0)
ahd_chip_init(ahd);
......@@ -6050,7 +6060,7 @@ ahd_chip_init(struct ahd_softc *ahd)
} else {
ahd_outb(ahd, OPTIONMODE, AUTOACKEN|BUSFREEREV|AUTO_MSGOUT_DE);
}
ahd_outb(ahd, SCSCHKN, CURRFIFODEF|WIDERESEN);
ahd_outb(ahd, SCSCHKN, CURRFIFODEF|WIDERESEN|SHVALIDSTDIS);
if ((ahd->chip & AHD_BUS_MASK) == AHD_PCIX)
/*
* Do not issue a target abort when a split completion
......@@ -6565,13 +6575,13 @@ 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;
maxloops = 1000;
ahd->flags |= AHD_ALL_INTERRUPTS;
intstat = 0;
paused = FALSE;
do {
struct scb *waiting_scb;
......@@ -6582,6 +6592,8 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
ahd_pause(ahd);
paused = TRUE;
ahd_clear_critical_section(ahd);
saved_modes = ahd_save_modes(ahd);
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
if ((ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)
ahd_outb(ahd, SCSISEQ0,
ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
......@@ -6598,10 +6610,10 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
ahd_outb(ahd, SCSISEQ0,
ahd_inb(ahd, SCSISEQ0) | ENSELO);
if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0)
break;
intstat = ahd_inb(ahd, INTSTAT);
} while (--maxloops
&& (((intstat = ahd_inb(ahd, INTSTAT)) & INT_PEND) != 0
&& (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0)
&& ((intstat & INT_PEND) != 0
|| (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO))));
if (maxloops == 0) {
printf("Infinite interrupt loop, INTSTAT = %x",
......@@ -6612,6 +6624,7 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
ahd_platform_flushwork(ahd);
ahd->flags &= ~AHD_ALL_INTERRUPTS;
ahd_restore_modes(ahd, saved_modes);
}
int
......
......@@ -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#41 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#42 $
*
* $FreeBSD$
*/
......
/*
* Adaptec AIC79xx device driver for Linux.
*
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#115 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#123 $
*
* --------------------------------------------------------------------------
* Copyright (c) 1994-2000 Justin T. Gibbs.
......@@ -992,9 +992,13 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
cmd->device->id, cmd->device->lun,
/*alloc*/TRUE);
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_midlayer_entrypoint_unlock(ahd, &flags);
printf("aic79xx_linux_queue: Unable to allocate device!\n");
return (-ENOMEM);
printf("%s: aic79xx_linux_queue - Unable to allocate device!\n",
ahd_name(ahd));
return (0);
}
if (cmd->cmd_len > MAX_CDB_LEN)
return (-EINVAL);
......@@ -1213,6 +1217,7 @@ ahd_linux_abort(Scsi_Cmnd *cmd)
u_int saved_scbptr;
u_int active_scbptr;
u_int last_phase;
u_int cdb_byte;
int retval;
int paused;
int wait;
......@@ -1225,9 +1230,12 @@ ahd_linux_abort(Scsi_Cmnd *cmd)
ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
acmd = (struct ahd_cmd *)cmd;
printf("%s:%d:%d:%d: Attempting to abort cmd %p\n",
printf("%s:%d:%d:%d: Attempting to abort cmd %p:",
ahd_name(ahd), cmd->device->channel, cmd->device->id,
cmd->device->lun, cmd);
for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
printf(" 0x%x", cmd->cmnd[cdb_byte]);
printf("\n");
/*
* In all versions of Linux, we have to work around
......@@ -2405,8 +2413,23 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
* negotiation will occur for the first command, and DV
* will comence should that first command be successful.
*/
for (target = 0; target < host->max_id; target++)
for (target = 0; target < host->max_id; target++) {
/*
* Skip our own ID. Some Compaq/HP storage devices
* have enclosure management devices that respond to
* single bit selection (i.e. selecting ourselves).
* It is expected that either an external application
* or a modified kernel will be used to probe this
* ID if it is appropriate. To accomodate these installations,
* ahc_linux_alloc_target() will allocate for our ID if
* asked to do so.
*/
if (target == ahd->our_id)
continue;
ahd_linux_alloc_target(ahd, 0, target);
}
ahd_intr_enable(ahd, TRUE);
ahd_linux_start_dv(ahd);
ahd_unlock(ahd, &s);
......@@ -2847,16 +2870,21 @@ ahd_linux_dv_thread(void *data)
printf("In DV Thread\n");
#endif
/*
* Complete thread creation.
*/
lock_kernel();
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60)
/*
* Don't care about any signals.
*/
siginitsetinv(&current->blocked, 0);
/*
* Complete thread creation.
*/
lock_kernel();
daemonize();
sprintf(current->comm, "ahd_dv_%d", ahd->unit);
#else
daemonize("ahd_dv_%d", ahd->unit);
#endif
unlock_kernel();
while (1) {
......@@ -4433,17 +4461,6 @@ static struct ahd_linux_target*
ahd_linux_alloc_target(struct ahd_softc *ahd, u_int channel, u_int target)
{
struct ahd_linux_target *targ;
u_int target_offset;
target_offset = target;
/*
* Never allow allocation of a target object for
* our own SCSIID.
*/
if (target == ahd->our_id) {
ahd->platform_data->targets[target_offset] = NULL;
return (NULL);
}
targ = malloc(sizeof(*targ), M_DEVBUF, M_NOWAIT);
if (targ == NULL)
......@@ -4453,7 +4470,7 @@ ahd_linux_alloc_target(struct ahd_softc *ahd, u_int channel, u_int target)
targ->target = target;
targ->ahd = ahd;
targ->flags = AHD_DV_REQUIRED;
ahd->platform_data->targets[target_offset] = targ;
ahd->platform_data->targets[target] = targ;
return (targ);
}
......@@ -4695,6 +4712,14 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
#endif
ahd_set_transaction_status(scb, CAM_UNCOR_PARITY);
} else if (amount_xferred < scb->io_ctx->underflow) {
u_int i;
ahd_print_path(ahd, scb);
printf("CDB:");
for (i = 0; i < scb->io_ctx->cmd_len; i++)
printf(" 0x%x", scb->io_ctx->cmnd[i]);
printf("\n");
ahd_print_path(ahd, scb);
printf("Saw underflow (%ld of %ld bytes). "
"Treated as error\n",
ahd_get_residual(scb),
......
......@@ -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#108 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#112 $
*
*/
#ifndef _AIC79XX_LINUX_H_
......@@ -286,7 +286,7 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec)
#include <linux/smp.h>
#endif
#define AIC79XX_DRIVER_VERSION "1.3.0"
#define AIC79XX_DRIVER_VERSION "1.3.2"
/**************************** Front End Queues ********************************/
/*
......
......@@ -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#61 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#65 $
*
* $FreeBSD$
*/
......@@ -80,6 +80,7 @@ ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
#define ID_AIC7902_B 0x801D9005FFFF9005ull
#define ID_AIC7902_B_IROC 0x809D9005FFFF9005ull
#define ID_AHA_39320 0x8010900500409005ull
#define ID_AHA_39320A 0x8016900500409005ull
#define ID_AHA_39320D 0x8011900500419005ull
#define ID_AHA_39320D_B 0x801C900500419005ull
#define ID_AHA_39320D_HP 0x8011900500AC0E11ull
......@@ -137,6 +138,12 @@ struct ahd_pci_identity ahd_pci_ident_table [] =
"Adaptec 39320 Ultra320 SCSI adapter",
ahd_aic7902_setup
},
{
ID_AHA_39320A,
ID_ALL_MASK,
"Adaptec 39320A Ultra320 SCSI adapter",
ahd_aic7902_setup
},
{
ID_AHA_39320D,
ID_ALL_MASK,
......@@ -698,7 +705,7 @@ static const char *split_status_strings[] =
"%s: Split completion data bucket in %s\n",
"%s: Split completion address error in %s\n",
"%s: Split completion byte count error in %s\n",
"%s: Signaled Target-abort to early terminate a split in %s\n",
"%s: Signaled Target-abort to early terminate a split in %s\n"
};
static const char *pci_status_strings[] =
......@@ -898,7 +905,7 @@ ahd_aic7902_setup(struct ahd_softc *ahd)
ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS
| AHD_NEW_DFCNTRL_OPTS;
ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_ABORT_LQI_BUG
| AHD_INTCOLLISION_BUG;
| AHD_INTCOLLISION_BUG|AHD_EARLY_REQ_BUG;
/*
* IO Cell paramter setup.
......
......@@ -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#11 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#12 $
*/
#include "aic79xx_osm.h"
#include "aic79xx_inline.h"
......@@ -311,6 +311,7 @@ ahd_linux_proc_info(char *buffer, char **start, off_t offset,
copy_info(&info, "Adaptec AIC79xx driver version: %s\n",
AIC79XX_DRIVER_VERSION);
copy_info(&info, "%s\n", ahd->description);
ahd_controller_info(ahd, ahd_info);
copy_info(&info, "%s\n\n", ahd_info);
......
......@@ -2,7 +2,7 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#78 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#86 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#60 $
*/
typedef int (ahd_reg_print_t)(u_int, u_int *, u_int);
......@@ -3774,5 +3774,5 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
/* Exported Labels */
#define LABEL_seq_isr 0x263
#define LABEL_timer_isr 0x25f
#define LABEL_seq_isr 0x268
#define LABEL_timer_isr 0x264
......@@ -2,7 +2,7 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#78 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#86 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#60 $
*/
......
......@@ -2,7 +2,7 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#78 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#86 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#60 $
*/
static uint8_t seqprog[] = {
......@@ -23,16 +23,16 @@ static uint8_t seqprog[] = {
0x20, 0x4b, 0x78, 0x69,
0xfc, 0x42, 0x24, 0x78,
0x10, 0x40, 0x24, 0x78,
0x00, 0xe2, 0xa4, 0x5d,
0x00, 0xe2, 0xc0, 0x5d,
0x20, 0x4d, 0x28, 0x78,
0x00, 0xe2, 0xa4, 0x5d,
0x00, 0xe2, 0xc0, 0x5d,
0x00, 0xe2, 0x34, 0x58,
0x00, 0xe2, 0x66, 0x58,
0x00, 0xe2, 0x76, 0x58,
0x00, 0xe2, 0x06, 0x40,
0x33, 0xea, 0x3a, 0x59,
0x33, 0xea, 0x00, 0x00,
0x01, 0x52, 0x66, 0x7d,
0x01, 0x52, 0x82, 0x7d,
0x02, 0x58, 0x50, 0x31,
0xff, 0xea, 0x10, 0x0b,
0xff, 0x93, 0x45, 0x78,
......@@ -42,18 +42,18 @@ static uint8_t seqprog[] = {
0x14, 0xea, 0x04, 0x00,
0x08, 0xa8, 0x51, 0x03,
0x01, 0xa4, 0x4d, 0x78,
0x00, 0xe2, 0x44, 0x5b,
0x00, 0xe2, 0x42, 0x5b,
0x00, 0xe2, 0x34, 0x40,
0xff, 0xea, 0xd4, 0x19,
0x02, 0xa8, 0x84, 0x32,
0x00, 0xea, 0x3a, 0x59,
0x01, 0xea, 0x00, 0x30,
0x00, 0xe2, 0x98, 0x5d,
0x00, 0xe2, 0x66, 0x4d,
0x00, 0xe2, 0xb4, 0x5d,
0x00, 0xe2, 0x82, 0x4d,
0x11, 0xea, 0x3a, 0x59,
0x11, 0xea, 0x00, 0x00,
0x00, 0xe2, 0x98, 0x5d,
0x00, 0xe2, 0x66, 0x4d,
0x00, 0xe2, 0xb4, 0x5d,
0x00, 0xe2, 0x82, 0x4d,
0x33, 0xea, 0x3a, 0x59,
0x33, 0xea, 0x00, 0x00,
0x00, 0xe2, 0x3a, 0x43,
......@@ -72,14 +72,14 @@ static uint8_t seqprog[] = {
0x10, 0x16, 0x2c, 0x00,
0x18, 0xad, 0xee, 0x78,
0x04, 0xad, 0xbc, 0x68,
0x80, 0xad, 0x66, 0x7d,
0x80, 0xad, 0x82, 0x7d,
0x10, 0xad, 0x8a, 0x78,
0xe7, 0xad, 0x5a, 0x0d,
0xe7, 0xad, 0x5a, 0x09,
0x00, 0xe2, 0x98, 0x58,
0xff, 0xea, 0x56, 0x02,
0x04, 0x7c, 0x78, 0x32,
0x20, 0x16, 0x66, 0x7d,
0x20, 0x16, 0x82, 0x7d,
0x04, 0x38, 0x79, 0x32,
0x80, 0x37, 0x6f, 0x16,
0xff, 0x2d, 0xa7, 0x60,
......@@ -92,7 +92,7 @@ static uint8_t seqprog[] = {
0x01, 0x4c, 0xc1, 0x31,
0x00, 0x50, 0xd5, 0x19,
0x00, 0xe2, 0xb6, 0x48,
0x80, 0x18, 0x66, 0x7d,
0x80, 0x18, 0x82, 0x7d,
0x02, 0x4a, 0x1d, 0x30,
0x10, 0xea, 0x18, 0x00,
0x60, 0x18, 0x30, 0x00,
......@@ -100,7 +100,7 @@ static uint8_t seqprog[] = {
0x02, 0xea, 0x02, 0x00,
0xff, 0xea, 0xa0, 0x0a,
0x80, 0x18, 0x30, 0x04,
0x40, 0xad, 0x66, 0x7d,
0x40, 0xad, 0x82, 0x7d,
0xe7, 0xad, 0x5a, 0x09,
0x02, 0xa8, 0x40, 0x31,
0xff, 0xea, 0xc0, 0x09,
......@@ -128,7 +128,7 @@ static uint8_t seqprog[] = {
0x04, 0x47, 0xf3, 0x68,
0x40, 0x16, 0x1e, 0x69,
0xff, 0x2d, 0x23, 0x61,
0xff, 0x29, 0x67, 0x75,
0xff, 0x29, 0x83, 0x75,
0x01, 0x37, 0xc1, 0x31,
0x02, 0x28, 0x55, 0x32,
0x01, 0xea, 0x5a, 0x01,
......@@ -236,8 +236,8 @@ static uint8_t seqprog[] = {
0xff, 0xea, 0x46, 0x02,
0x02, 0x5c, 0x50, 0x31,
0x40, 0xea, 0x96, 0x00,
0x02, 0x56, 0xac, 0x6d,
0x01, 0x55, 0xac, 0x6d,
0x02, 0x56, 0xc8, 0x6d,
0x01, 0x55, 0xc8, 0x6d,
0x10, 0xa8, 0xd5, 0x79,
0x10, 0x40, 0xde, 0x69,
0x01, 0x56, 0xde, 0x79,
......@@ -253,9 +253,9 @@ static uint8_t seqprog[] = {
0x40, 0xea, 0x66, 0x02,
0x08, 0x3c, 0x78, 0x00,
0x80, 0xea, 0x62, 0x02,
0x00, 0xe2, 0xa4, 0x5b,
0x00, 0xe2, 0xa2, 0x5b,
0x01, 0x36, 0xc1, 0x31,
0x9f, 0xe0, 0x38, 0x7c,
0x9f, 0xe0, 0x44, 0x7c,
0x80, 0xe0, 0x02, 0x72,
0xa0, 0xe0, 0x3a, 0x72,
0xc0, 0xe0, 0x30, 0x72,
......@@ -299,31 +299,31 @@ static uint8_t seqprog[] = {
0xbf, 0xe2, 0xc4, 0x09,
0x20, 0xa8, 0x5b, 0x7a,
0x01, 0xe2, 0x88, 0x30,
0x00, 0xe2, 0xa4, 0x5b,
0x00, 0xe2, 0xa2, 0x5b,
0xa0, 0x36, 0x63, 0x62,
0x23, 0xa8, 0x89, 0x08,
0x00, 0xe2, 0xa4, 0x5b,
0x00, 0xe2, 0xa2, 0x5b,
0xa0, 0x36, 0x63, 0x62,
0x00, 0xa8, 0x5a, 0x42,
0xff, 0xe2, 0x5a, 0x62,
0x00, 0xe2, 0x7a, 0x42,
0x40, 0xea, 0x98, 0x00,
0x01, 0xe2, 0x88, 0x30,
0x00, 0xe2, 0xa4, 0x5b,
0x00, 0xe2, 0xa2, 0x5b,
0xa0, 0x36, 0x39, 0x72,
0x40, 0xea, 0x98, 0x00,
0x01, 0x31, 0x89, 0x32,
0x08, 0xea, 0x62, 0x02,
0x00, 0xe2, 0xee, 0x41,
0xe0, 0xea, 0xb4, 0x5b,
0xe0, 0xea, 0xbe, 0x5b,
0x80, 0xe0, 0xb2, 0x6a,
0x04, 0xe0, 0x52, 0x73,
0x02, 0xe0, 0x82, 0x73,
0x04, 0xe0, 0x50, 0x73,
0x02, 0xe0, 0x80, 0x73,
0x00, 0xea, 0x10, 0x73,
0x03, 0xe0, 0x92, 0x73,
0x03, 0xe0, 0x90, 0x73,
0x23, 0xe0, 0x8c, 0x72,
0x08, 0xe0, 0xae, 0x72,
0x00, 0xe2, 0xa4, 0x5b,
0x00, 0xe2, 0xa2, 0x5b,
0x07, 0xea, 0x46, 0x59,
0x07, 0xea, 0x04, 0x00,
0x08, 0x42, 0xef, 0x71,
......@@ -340,7 +340,7 @@ static uint8_t seqprog[] = {
0x00, 0x30, 0x3b, 0x59,
0x01, 0x30, 0x01, 0x30,
0x01, 0xe0, 0xac, 0x7a,
0xa0, 0xea, 0xaa, 0x5b,
0xa0, 0xea, 0xb4, 0x5b,
0x01, 0xa0, 0xac, 0x62,
0x01, 0x84, 0xa5, 0x7a,
0x01, 0xa7, 0xae, 0x7a,
......@@ -348,7 +348,7 @@ static uint8_t seqprog[] = {
0x03, 0xea, 0x46, 0x59,
0x03, 0xea, 0x04, 0x00,
0x00, 0xe2, 0xae, 0x42,
0x07, 0xea, 0xbc, 0x5b,
0x07, 0xea, 0xc6, 0x5b,
0x01, 0x44, 0xd4, 0x31,
0x00, 0xe2, 0xee, 0x41,
0x3f, 0xe0, 0x6a, 0x0a,
......@@ -367,13 +367,13 @@ static uint8_t seqprog[] = {
0x00, 0xe2, 0xf0, 0x42,
0x80, 0x33, 0x67, 0x02,
0x01, 0x44, 0xd4, 0x31,
0x00, 0xe2, 0xa4, 0x5b,
0x00, 0xe2, 0xa2, 0x5b,
0x01, 0x33, 0x67, 0x02,
0xe0, 0x36, 0x0b, 0x63,
0x02, 0x33, 0x67, 0x02,
0x20, 0x46, 0x04, 0x63,
0xff, 0xea, 0x52, 0x09,
0xa8, 0xea, 0xaa, 0x5b,
0xa8, 0xea, 0xb4, 0x5b,
0x04, 0xa8, 0xeb, 0x7a,
0x01, 0x34, 0xc1, 0x31,
0x00, 0xa9, 0xeb, 0x62,
......@@ -390,7 +390,7 @@ static uint8_t seqprog[] = {
0x02, 0xa8, 0x90, 0x32,
0x00, 0xe2, 0x60, 0x59,
0x10, 0xa8, 0xaf, 0x7a,
0xff, 0xea, 0xbc, 0x5b,
0xff, 0xea, 0xc6, 0x5b,
0x00, 0xe2, 0xae, 0x42,
0x04, 0xea, 0x46, 0x59,
0x04, 0xea, 0x04, 0x00,
......@@ -407,7 +407,7 @@ static uint8_t seqprog[] = {
0x0a, 0xea, 0x46, 0x59,
0x0a, 0xea, 0x04, 0x00,
0x00, 0xe2, 0x3a, 0x5b,
0x00, 0xe2, 0x6e, 0x43,
0x00, 0xe2, 0x6c, 0x43,
0x50, 0x4b, 0x28, 0x6b,
0xbf, 0x3a, 0x74, 0x08,
0x01, 0xe0, 0xf8, 0x31,
......@@ -419,21 +419,20 @@ static uint8_t seqprog[] = {
0x33, 0xea, 0x3a, 0x59,
0x33, 0xea, 0x00, 0x00,
0x02, 0x42, 0x51, 0x31,
0x10, 0xa8, 0x51, 0x03,
0xff, 0x88, 0x49, 0x6b,
0x01, 0xa4, 0x45, 0x6b,
0x02, 0xa4, 0x4d, 0x6b,
0x01, 0x84, 0x4d, 0x7b,
0xff, 0x88, 0x47, 0x6b,
0x01, 0xa4, 0x43, 0x6b,
0x02, 0xa4, 0x4b, 0x6b,
0x01, 0x84, 0x4b, 0x7b,
0x02, 0x28, 0x19, 0x33,
0x02, 0xa8, 0x50, 0x36,
0xff, 0x88, 0x4d, 0x73,
0xff, 0x88, 0x4b, 0x73,
0x00, 0xe2, 0x24, 0x5b,
0x02, 0x2c, 0x19, 0x33,
0x02, 0xa8, 0x58, 0x32,
0x04, 0xa4, 0x49, 0x07,
0xc0, 0x33, 0xa7, 0x6a,
0x04, 0xa8, 0x51, 0x03,
0x20, 0xa8, 0x6f, 0x6b,
0x20, 0xa8, 0x6d, 0x6b,
0x02, 0xa8, 0x40, 0x31,
0xc0, 0x34, 0xc1, 0x09,
0x00, 0x35, 0x51, 0x01,
......@@ -448,23 +447,23 @@ static uint8_t seqprog[] = {
0xf7, 0x57, 0xae, 0x08,
0x08, 0xea, 0x98, 0x00,
0x01, 0x44, 0xd4, 0x31,
0xee, 0x00, 0x78, 0x6b,
0xee, 0x00, 0x76, 0x6b,
0x02, 0xea, 0xb4, 0x00,
0x00, 0xe2, 0xa0, 0x5b,
0x09, 0x4c, 0x7a, 0x7b,
0x00, 0xe2, 0x9e, 0x5b,
0x09, 0x4c, 0x78, 0x7b,
0x08, 0x4c, 0x06, 0x68,
0x0b, 0xea, 0x46, 0x59,
0x0b, 0xea, 0x04, 0x00,
0x01, 0x44, 0xd4, 0x31,
0x20, 0x33, 0xef, 0x79,
0x00, 0xe2, 0x8a, 0x5b,
0x00, 0xe2, 0x88, 0x5b,
0x00, 0xe2, 0xee, 0x41,
0x01, 0x84, 0x8f, 0x7b,
0x01, 0x84, 0x8d, 0x7b,
0x01, 0xa4, 0x49, 0x07,
0x08, 0x60, 0x30, 0x33,
0x08, 0x80, 0x41, 0x37,
0xdf, 0x33, 0x67, 0x0a,
0xee, 0x00, 0x9c, 0x6b,
0xee, 0x00, 0x9a, 0x6b,
0x05, 0xea, 0xb4, 0x00,
0x33, 0xea, 0x3a, 0x59,
0x33, 0xea, 0x00, 0x00,
......@@ -472,12 +471,18 @@ static uint8_t seqprog[] = {
0x00, 0xe2, 0xae, 0x42,
0x01, 0xea, 0x6c, 0x02,
0xc0, 0xea, 0x66, 0x06,
0xff, 0x42, 0xa4, 0x7b,
0x04, 0x4c, 0xa4, 0x6b,
0xff, 0x42, 0xae, 0x6b,
0x01, 0x41, 0xa2, 0x6b,
0x02, 0x41, 0xa2, 0x7b,
0xff, 0x42, 0xae, 0x6b,
0x01, 0x41, 0xa2, 0x6b,
0x02, 0x41, 0xa2, 0x7b,
0xff, 0x42, 0xae, 0x7b,
0x04, 0x4c, 0xa2, 0x6b,
0xe0, 0x41, 0x6c, 0x0e,
0x01, 0x44, 0xd4, 0x31,
0xff, 0x42, 0xac, 0x7b,
0x04, 0x4c, 0xac, 0x6b,
0xff, 0x42, 0xb6, 0x7b,
0x04, 0x4c, 0xb6, 0x6b,
0xe0, 0x41, 0x6c, 0x0a,
0xe0, 0x36, 0xef, 0x61,
0xff, 0xea, 0xca, 0x09,
......@@ -486,28 +491,29 @@ static uint8_t seqprog[] = {
0x01, 0x44, 0xd4, 0x35,
0x10, 0xea, 0x80, 0x00,
0x01, 0xe2, 0x62, 0x36,
0x04, 0xa6, 0xc4, 0x7b,
0x04, 0xa6, 0xce, 0x7b,
0xff, 0xea, 0x5a, 0x09,
0xff, 0xea, 0x4c, 0x0d,
0x01, 0xa6, 0xe2, 0x6b,
0x10, 0xad, 0x66, 0x7d,
0x80, 0xad, 0xda, 0x6b,
0x08, 0xad, 0x66, 0x6d,
0x01, 0xa6, 0xec, 0x6b,
0x10, 0xad, 0x82, 0x7d,
0x80, 0xad, 0xe4, 0x6b,
0x08, 0xad, 0x82, 0x6d,
0x04, 0x84, 0xf9, 0x30,
0x00, 0xea, 0x08, 0x81,
0xff, 0xea, 0xd4, 0x09,
0x02, 0x84, 0xf9, 0x88,
0x1d, 0xea, 0x5a, 0x01,
0x0d, 0xea, 0x5a, 0x01,
0x04, 0xa6, 0x4c, 0x05,
0x04, 0xa6, 0x66, 0x7d,
0x04, 0xa6, 0x82, 0x7d,
0xff, 0xea, 0x5a, 0x09,
0x03, 0x84, 0x59, 0x89,
0x03, 0xea, 0x4c, 0x01,
0x80, 0x1a, 0x66, 0x7d,
0x80, 0x1a, 0x82, 0x7d,
0x08, 0x19, 0x82, 0x7d,
0x08, 0xb0, 0xe0, 0x30,
0x04, 0xb0, 0xe0, 0x30,
0x03, 0xb0, 0xf0, 0x30,
0x01, 0x78, 0xee, 0x7b,
0x01, 0x78, 0xfa, 0x7b,
0x01, 0xa7, 0x4e, 0x11,
0x01, 0xb0, 0x06, 0x33,
0x7f, 0x83, 0xe9, 0x08,
......@@ -518,98 +524,97 @@ static uint8_t seqprog[] = {
0x00, 0x86, 0x0d, 0x23,
0x00, 0x87, 0x0f, 0x23,
0x01, 0x84, 0xc5, 0x31,
0x01, 0xa7, 0x04, 0x7c,
0x01, 0xa7, 0x10, 0x7c,
0x04, 0xe2, 0xc4, 0x01,
0x80, 0x83, 0x0b, 0x7c,
0x80, 0x83, 0x17, 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, 0x66, 0x55,
0x00, 0xe2, 0x82, 0x55,
0xfe, 0xa6, 0x4c, 0x0d,
0x0b, 0x98, 0xe1, 0x30,
0x01, 0xa0, 0x4f, 0x09,
0xfd, 0xa4, 0x49, 0x09,
0x80, 0xa3, 0x21, 0x7c,
0x80, 0xa3, 0x2d, 0x7c,
0x02, 0xa4, 0x48, 0x01,
0x01, 0xa7, 0x24, 0x7c,
0x01, 0xa7, 0x30, 0x7c,
0x04, 0xa4, 0x48, 0x01,
0x01, 0xa4, 0x36, 0x30,
0xa8, 0xea, 0x32, 0x00,
0xfd, 0xa4, 0x49, 0x0b,
0x05, 0xa3, 0x07, 0x33,
0x80, 0x83, 0x31, 0x6c,
0x80, 0x83, 0x3d, 0x6c,
0x02, 0xea, 0x4c, 0x05,
0xff, 0xea, 0x4c, 0x0d,
0x00, 0xe2, 0x32, 0x59,
0x02, 0xa6, 0xc6, 0x6b,
0x02, 0xa6, 0xd0, 0x6b,
0x80, 0xf9, 0xf2, 0x05,
0xc0, 0x33, 0x3f, 0x7c,
0xc0, 0x33, 0x4b, 0x7c,
0x03, 0xea, 0x46, 0x59,
0x03, 0xea, 0x04, 0x00,
0x20, 0x33, 0x63, 0x7c,
0x01, 0x84, 0x49, 0x6c,
0x20, 0x33, 0x6f, 0x7c,
0x01, 0x84, 0x55, 0x6c,
0x06, 0xea, 0x46, 0x59,
0x06, 0xea, 0x04, 0x00,
0x00, 0xe2, 0x66, 0x44,
0x00, 0xe2, 0x72, 0x44,
0x01, 0x00, 0x60, 0x32,
0xee, 0x00, 0x52, 0x6c,
0xee, 0x00, 0x5e, 0x6c,
0x05, 0xea, 0xb4, 0x00,
0x33, 0xea, 0x3a, 0x59,
0x33, 0xea, 0x00, 0x00,
0x80, 0x3d, 0x7a, 0x00,
0xfc, 0x42, 0x54, 0x7c,
0xfc, 0x42, 0x60, 0x7c,
0x7f, 0x3d, 0x7a, 0x08,
0x00, 0x30, 0x3b, 0x59,
0x01, 0x30, 0x01, 0x30,
0x09, 0xea, 0x46, 0x59,
0x09, 0xea, 0x04, 0x00,
0x00, 0xe2, 0xee, 0x41,
0x01, 0xa4, 0x49, 0x6c,
0x00, 0xe2, 0x16, 0x5c,
0x01, 0xa4, 0x55, 0x6c,
0x00, 0xe2, 0x22, 0x5c,
0x20, 0x33, 0x67, 0x02,
0x01, 0x00, 0x60, 0x32,
0x02, 0xa6, 0x6e, 0x7c,
0x00, 0xe2, 0x32, 0x5c,
0x02, 0xa6, 0x7a, 0x7c,
0x00, 0xe2, 0x3e, 0x5c,
0x00, 0xe2, 0x66, 0x58,
0x00, 0xe2, 0x76, 0x58,
0x00, 0xe2, 0x30, 0x58,
0x00, 0x30, 0x3b, 0x59,
0x01, 0x30, 0x01, 0x30,
0x20, 0x19, 0x6e, 0x6c,
0x00, 0xe2, 0x96, 0x5c,
0x04, 0x19, 0x88, 0x6c,
0x20, 0x19, 0x7a, 0x6c,
0x00, 0xe2, 0xaa, 0x5c,
0x04, 0x19, 0x94, 0x6c,
0x02, 0x19, 0x32, 0x00,
0x01, 0x84, 0x89, 0x7c,
0x01, 0x1b, 0x82, 0x7c,
0x01, 0x1a, 0x88, 0x6c,
0x00, 0xe2, 0x38, 0x44,
0x80, 0x4b, 0x8e, 0x6c,
0x01, 0x4c, 0x8a, 0x7c,
0x03, 0x42, 0x38, 0x6c,
0x00, 0xe2, 0xc0, 0x5b,
0x01, 0x84, 0x95, 0x7c,
0x01, 0x1b, 0x8e, 0x7c,
0x01, 0x1a, 0x94, 0x6c,
0x00, 0xe2, 0x44, 0x44,
0x80, 0x4b, 0x9a, 0x6c,
0x01, 0x4c, 0x96, 0x7c,
0x03, 0x42, 0x44, 0x6c,
0x00, 0xe2, 0xca, 0x5b,
0x80, 0xf9, 0xf2, 0x01,
0x04, 0x33, 0xef, 0x79,
0x00, 0xe2, 0xee, 0x41,
0x02, 0x1b, 0x9e, 0x7c,
0x08, 0x5d, 0x9c, 0x7c,
0x03, 0x68, 0x00, 0x37,
0x01, 0x84, 0x09, 0x07,
0x08, 0x5d, 0xa8, 0x6c,
0x08, 0x5d, 0xb2, 0x6c,
0x00, 0xe2, 0x66, 0x58,
0x00, 0x30, 0x3b, 0x59,
0x01, 0x30, 0x01, 0x30,
0x00, 0xe2, 0x96, 0x44,
0x80, 0x1b, 0xb2, 0x7c,
0x80, 0x84, 0xb3, 0x6c,
0x02, 0x1b, 0xa2, 0x7c,
0x08, 0x5d, 0xb0, 0x7c,
0x03, 0x68, 0x00, 0x37,
0x01, 0x84, 0x09, 0x07,
0x80, 0x1b, 0xbc, 0x7c,
0x80, 0x84, 0xbd, 0x6c,
0xff, 0x85, 0x0b, 0x1b,
0xff, 0x86, 0x0d, 0x23,
0xff, 0x87, 0x0f, 0x23,
0xf8, 0x1b, 0x08, 0x0b,
0xff, 0xea, 0x4e, 0x09,
0x04, 0x1b, 0xba, 0x7c,
0x04, 0x1b, 0xc4, 0x7c,
0x01, 0xa7, 0x4e, 0x01,
0xff, 0xea, 0x06, 0x0b,
0x03, 0x68, 0x00, 0x37,
......@@ -617,74 +622,83 @@ static uint8_t seqprog[] = {
0x10, 0xea, 0x18, 0x00,
0xf9, 0xd9, 0xb2, 0x0d,
0x01, 0xd9, 0xb2, 0x05,
0xff, 0xea, 0xd4, 0x09,
0x10, 0x5b, 0xde, 0x6c,
0x08, 0x5b, 0xe6, 0x6c,
0x20, 0x5b, 0xd4, 0x6c,
0x02, 0x5b, 0xfa, 0x6d,
0x01, 0x52, 0x48, 0x31,
0x20, 0xa4, 0xe8, 0x7c,
0x20, 0x5b, 0xe8, 0x7c,
0x80, 0xf9, 0xf6, 0x7c,
0x11, 0x00, 0x00, 0x10,
0x04, 0x19, 0xe2, 0x7c,
0xdf, 0x19, 0x32, 0x08,
0x01, 0x4c, 0xde, 0x7c,
0x20, 0x19, 0x32, 0x00,
0x11, 0x00, 0x00, 0x10,
0x02, 0xea, 0xb4, 0x00,
0x01, 0xd9, 0xb2, 0x05,
0x10, 0x5b, 0xfa, 0x6c,
0x08, 0x5b, 0x02, 0x6d,
0x20, 0x5b, 0xf4, 0x6c,
0x02, 0x5b, 0x16, 0x6e,
0x0e, 0xea, 0x46, 0x59,
0x0e, 0xea, 0x04, 0x00,
0x08, 0x19, 0xda, 0x7c,
0x80, 0xf9, 0xe4, 0x6c,
0xdf, 0x5c, 0xb8, 0x08,
0x01, 0xd9, 0xb2, 0x05,
0x02, 0xea, 0xb4, 0x00,
0x01, 0xd9, 0xb2, 0x05,
0x01, 0xa4, 0xc3, 0x6d,
0x00, 0xe2, 0x16, 0x5c,
0x00, 0xe2, 0x06, 0x5d,
0x01, 0xa4, 0xdf, 0x6d,
0x00, 0xe2, 0x22, 0x5c,
0x00, 0xe2, 0x22, 0x5d,
0x01, 0xd9, 0xb2, 0x05,
0x00, 0xe2, 0x24, 0x5b,
0xf3, 0x92, 0xd5, 0x19,
0x00, 0xe2, 0xf4, 0x54,
0x80, 0x92, 0xf5, 0x6c,
0x00, 0xe2, 0x10, 0x55,
0x80, 0x92, 0x11, 0x6d,
0x0f, 0xea, 0x46, 0x59,
0x0f, 0xea, 0x04, 0x00,
0x00, 0xe2, 0xfc, 0x44,
0x00, 0xe2, 0x18, 0x45,
0x04, 0x8c, 0xe1, 0x30,
0x01, 0xea, 0xf2, 0x00,
0x02, 0xea, 0x36, 0x00,
0xa8, 0xea, 0x32, 0x00,
0xff, 0x93, 0x03, 0x7d,
0xff, 0x93, 0x1f, 0x7d,
0x14, 0xea, 0x46, 0x59,
0x14, 0xea, 0x04, 0x00,
0x00, 0xe2, 0x88, 0x5d,
0x00, 0xe2, 0xa4, 0x5d,
0x01, 0xd9, 0xb2, 0x05,
0x02, 0xa8, 0xf4, 0x31,
0x02, 0xa6, 0x18, 0x7d,
0x02, 0xa6, 0x34, 0x7d,
0x00, 0xe2, 0x34, 0x59,
0x20, 0x5b, 0x26, 0x6d,
0xfc, 0x42, 0x12, 0x7d,
0x10, 0x40, 0x14, 0x6d,
0x20, 0x4d, 0x16, 0x7d,
0x08, 0x5d, 0x26, 0x6d,
0x02, 0xa6, 0xc6, 0x6b,
0x20, 0x5b, 0x42, 0x6d,
0xfc, 0x42, 0x2e, 0x7d,
0x10, 0x40, 0x30, 0x6d,
0x20, 0x4d, 0x32, 0x7d,
0x08, 0x5d, 0x42, 0x6d,
0x02, 0xa6, 0xd0, 0x6b,
0x00, 0xe2, 0x34, 0x59,
0x20, 0x5b, 0x26, 0x6d,
0x01, 0x1b, 0x46, 0x6d,
0xfc, 0x42, 0x22, 0x7d,
0x10, 0x40, 0x24, 0x6d,
0x20, 0x4d, 0x66, 0x7d,
0x08, 0x5d, 0x66, 0x7d,
0x20, 0x5b, 0x42, 0x6d,
0x01, 0x1b, 0x62, 0x6d,
0xfc, 0x42, 0x3e, 0x7d,
0x10, 0x40, 0x40, 0x6d,
0x20, 0x4d, 0x82, 0x7d,
0x08, 0x5d, 0x82, 0x7d,
0x02, 0x19, 0x32, 0x00,
0x01, 0x5b, 0x40, 0x31,
0x00, 0xe2, 0x96, 0x5c,
0x00, 0xe2, 0x8a, 0x5b,
0x00, 0xe2, 0xaa, 0x5c,
0x00, 0xe2, 0x88, 0x5b,
0x20, 0xea, 0xb6, 0x00,
0x00, 0xe2, 0xc0, 0x5b,
0x00, 0xe2, 0xca, 0x5b,
0x20, 0x5c, 0xb8, 0x00,
0x04, 0x19, 0x3c, 0x6d,
0x01, 0x1a, 0x3c, 0x6d,
0x04, 0x19, 0x58, 0x6d,
0x01, 0x1a, 0x58, 0x6d,
0x00, 0xe2, 0x34, 0x59,
0x01, 0x1a, 0x66, 0x7d,
0x01, 0x1a, 0x82, 0x7d,
0x80, 0xf9, 0xf2, 0x01,
0x20, 0xa0, 0xac, 0x7d,
0x08, 0xa8, 0x45, 0x7d,
0x00, 0xe2, 0x58, 0x45,
0x20, 0xa0, 0xc8, 0x7d,
0x08, 0xa8, 0x61, 0x7d,
0x00, 0xe2, 0x74, 0x45,
0x02, 0xea, 0xb4, 0x04,
0x02, 0x19, 0x32, 0x00,
0x08, 0xa8, 0x69, 0x7d,
0x04, 0x5d, 0xc2, 0x7d,
0x01, 0x1a, 0xc2, 0x7d,
0x08, 0xa8, 0x85, 0x7d,
0x04, 0x5d, 0xde, 0x7d,
0x01, 0x1a, 0xde, 0x7d,
0x01, 0xa4, 0x49, 0x03,
0x80, 0xf9, 0xf2, 0x01,
0x02, 0xa8, 0x84, 0x32,
......@@ -695,48 +709,48 @@ static uint8_t seqprog[] = {
0xff, 0xea, 0xd4, 0x19,
0x00, 0xe2, 0x40, 0x59,
0x11, 0x00, 0x00, 0x10,
0x00, 0xe2, 0x98, 0x5d,
0x00, 0xe2, 0xb4, 0x5d,
0x00, 0xe2, 0x34, 0x53,
0xff, 0xea, 0xd4, 0x0d,
0x00, 0xe2, 0x34, 0x59,
0x40, 0x5b, 0x74, 0x6d,
0x04, 0x5d, 0xc2, 0x7d,
0x01, 0x1a, 0xc2, 0x7d,
0x20, 0x4d, 0x66, 0x7d,
0x40, 0x5b, 0xac, 0x7d,
0x04, 0x5d, 0xc2, 0x7d,
0x01, 0x1a, 0xc2, 0x7d,
0x40, 0x5b, 0x90, 0x6d,
0x04, 0x5d, 0xde, 0x7d,
0x01, 0x1a, 0xde, 0x7d,
0x20, 0x4d, 0x82, 0x7d,
0x40, 0x5b, 0xc8, 0x7d,
0x04, 0x5d, 0xde, 0x7d,
0x01, 0x1a, 0xde, 0x7d,
0x80, 0xf9, 0xf2, 0x01,
0x01, 0xa4, 0x49, 0x03,
0x08, 0xa8, 0x59, 0x6d,
0x08, 0xa8, 0x75, 0x6d,
0x02, 0xea, 0xb4, 0x04,
0xff, 0x6a, 0x8e, 0x7d,
0xff, 0x6a, 0xaa, 0x7d,
0x10, 0xea, 0x46, 0x59,
0x10, 0xea, 0x04, 0x00,
0x00, 0xe2, 0x8e, 0x45,
0x00, 0xe2, 0xaa, 0x45,
0x00, 0xe2, 0x32, 0x59,
0x10, 0x5d, 0x80, 0x6d,
0x40, 0x5b, 0x66, 0x7d,
0x10, 0x5d, 0x9c, 0x6d,
0x40, 0x5b, 0x82, 0x7d,
0x02, 0x19, 0x32, 0x00,
0x80, 0xf9, 0xf2, 0x01,
0xff, 0xea, 0x10, 0x03,
0x08, 0xa8, 0x51, 0x03,
0x00, 0xe2, 0x58, 0x45,
0x80, 0xf9, 0x66, 0x6d,
0x00, 0xe2, 0x74, 0x45,
0x80, 0xf9, 0x82, 0x6d,
0x01, 0x43, 0xc1, 0x31,
0x00, 0xfb, 0x66, 0x65,
0x00, 0xfb, 0x82, 0x65,
0x01, 0x42, 0xc1, 0x31,
0x00, 0xfa, 0x66, 0x65,
0x00, 0xfa, 0x82, 0x65,
0x01, 0xe8, 0xd4, 0x1d,
0x30, 0x3f, 0xc0, 0x09,
0x30, 0xe0, 0x66, 0x65,
0x40, 0x4b, 0x66, 0x6d,
0x30, 0xe0, 0x82, 0x65,
0x40, 0x4b, 0x82, 0x6d,
0xff, 0xea, 0x52, 0x01,
0xee, 0x00, 0xb2, 0x6d,
0xee, 0x00, 0xce, 0x6d,
0x80, 0xf9, 0xf2, 0x01,
0x02, 0xea, 0xb4, 0x00,
0x20, 0xea, 0x9a, 0x00,
0xf3, 0x42, 0xbc, 0x6d,
0xf3, 0x42, 0xd8, 0x6d,
0x12, 0xea, 0x46, 0x59,
0x12, 0xea, 0x04, 0x00,
0x00, 0xe2, 0xee, 0x41,
......@@ -747,18 +761,18 @@ static uint8_t seqprog[] = {
0x11, 0xea, 0x04, 0x00,
0x00, 0xe2, 0x24, 0x5b,
0x08, 0x5a, 0xb4, 0x00,
0x00, 0xe2, 0xe4, 0x5d,
0x00, 0xe2, 0x00, 0x5e,
0xa8, 0xea, 0x32, 0x00,
0x00, 0xe2, 0x34, 0x59,
0x80, 0x1a, 0xd6, 0x7d,
0x00, 0xe2, 0xe4, 0x5d,
0x80, 0x1a, 0xf2, 0x7d,
0x00, 0xe2, 0x00, 0x5e,
0x80, 0x19, 0x32, 0x00,
0x40, 0x5b, 0xdc, 0x6d,
0x08, 0x5a, 0xdc, 0x7d,
0x20, 0x4d, 0x66, 0x7d,
0x40, 0x5b, 0xf8, 0x6d,
0x08, 0x5a, 0xf8, 0x7d,
0x20, 0x4d, 0x82, 0x7d,
0x02, 0x84, 0x09, 0x03,
0x40, 0x5b, 0xac, 0x7d,
0x08, 0xa8, 0x51, 0x6d,
0x40, 0x5b, 0xc8, 0x7d,
0x08, 0xa8, 0x6d, 0x6d,
0x02, 0xea, 0xb4, 0x04,
0x01, 0x38, 0xe1, 0x30,
0x05, 0x39, 0xe3, 0x98,
......@@ -774,12 +788,28 @@ static uint8_t seqprog[] = {
};
typedef int ahd_patch_func_t (struct ahd_softc *ahd);
static ahd_patch_func_t ahd_patch20_func;
static int
ahd_patch20_func(struct ahd_softc *ahd)
{
return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0);
}
static ahd_patch_func_t ahd_patch19_func;
static int
ahd_patch19_func(struct ahd_softc *ahd)
{
return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0);
}
static ahd_patch_func_t ahd_patch18_func;
static int
ahd_patch18_func(struct ahd_softc *ahd)
{
return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0);
return ((ahd->features & AHD_RTI) == 0);
}
static ahd_patch_func_t ahd_patch17_func;
......@@ -787,7 +817,7 @@ static ahd_patch_func_t ahd_patch17_func;
static int
ahd_patch17_func(struct ahd_softc *ahd)
{
return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0);
return ((ahd->flags & AHD_INITIATORROLE) != 0);
}
static ahd_patch_func_t ahd_patch16_func;
......@@ -795,7 +825,7 @@ static ahd_patch_func_t ahd_patch16_func;
static int
ahd_patch16_func(struct ahd_softc *ahd)
{
return ((ahd->flags & AHD_INITIATORROLE) != 0);
return ((ahd->flags & AHD_TARGETROLE) != 0);
}
static ahd_patch_func_t ahd_patch15_func;
......@@ -803,7 +833,7 @@ static ahd_patch_func_t ahd_patch15_func;
static int
ahd_patch15_func(struct ahd_softc *ahd)
{
return ((ahd->flags & AHD_TARGETROLE) != 0);
return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0);
}
static ahd_patch_func_t ahd_patch14_func;
......@@ -811,7 +841,7 @@ static ahd_patch_func_t ahd_patch14_func;
static int
ahd_patch14_func(struct ahd_softc *ahd)
{
return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0);
return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0);
}
static ahd_patch_func_t ahd_patch13_func;
......@@ -819,7 +849,7 @@ static ahd_patch_func_t ahd_patch13_func;
static int
ahd_patch13_func(struct ahd_softc *ahd)
{
return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0);
return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0);
}
static ahd_patch_func_t ahd_patch12_func;
......@@ -827,7 +857,7 @@ static ahd_patch_func_t ahd_patch12_func;
static int
ahd_patch12_func(struct ahd_softc *ahd)
{
return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0);
return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0);
}
static ahd_patch_func_t ahd_patch11_func;
......@@ -835,7 +865,7 @@ static ahd_patch_func_t ahd_patch11_func;
static int
ahd_patch11_func(struct ahd_softc *ahd)
{
return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0);
return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0);
}
static ahd_patch_func_t ahd_patch10_func;
......@@ -851,7 +881,7 @@ static ahd_patch_func_t ahd_patch9_func;
static int
ahd_patch9_func(struct ahd_softc *ahd)
{
return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0);
return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0);
}
static ahd_patch_func_t ahd_patch8_func;
......@@ -859,7 +889,7 @@ static ahd_patch_func_t ahd_patch8_func;
static int
ahd_patch8_func(struct ahd_softc *ahd)
{
return ((ahd->bugs & AHD_ABORT_LQI_BUG) == 0);
return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0);
}
static ahd_patch_func_t ahd_patch7_func;
......@@ -1000,64 +1030,68 @@ static struct patch {
{ ahd_patch0_func, 399, 1, 1 },
{ ahd_patch2_func, 410, 1, 2 },
{ ahd_patch0_func, 411, 1, 1 },
{ ahd_patch8_func, 413, 1, 1 },
{ ahd_patch9_func, 440, 1, 1 },
{ ahd_patch1_func, 447, 1, 2 },
{ ahd_patch0_func, 448, 1, 1 },
{ ahd_patch2_func, 460, 1, 2 },
{ ahd_patch0_func, 461, 1, 1 },
{ ahd_patch10_func, 489, 1, 1 },
{ ahd_patch11_func, 498, 1, 2 },
{ ahd_patch0_func, 499, 1, 1 },
{ ahd_patch12_func, 504, 1, 1 },
{ ahd_patch11_func, 505, 1, 1 },
{ ahd_patch13_func, 518, 1, 2 },
{ ahd_patch0_func, 519, 1, 1 },
{ ahd_patch1_func, 541, 1, 2 },
{ ahd_patch0_func, 542, 1, 1 },
{ ahd_patch1_func, 545, 1, 2 },
{ ahd_patch0_func, 546, 1, 1 },
{ ahd_patch2_func, 551, 1, 2 },
{ ahd_patch8_func, 439, 1, 1 },
{ ahd_patch1_func, 446, 1, 2 },
{ ahd_patch0_func, 447, 1, 1 },
{ ahd_patch2_func, 459, 1, 2 },
{ ahd_patch0_func, 460, 1, 1 },
{ ahd_patch9_func, 465, 6, 2 },
{ ahd_patch0_func, 471, 1, 1 },
{ ahd_patch10_func, 494, 1, 1 },
{ ahd_patch11_func, 503, 1, 1 },
{ ahd_patch12_func, 504, 1, 2 },
{ ahd_patch0_func, 505, 1, 1 },
{ ahd_patch13_func, 510, 1, 1 },
{ ahd_patch12_func, 511, 1, 1 },
{ ahd_patch14_func, 524, 1, 2 },
{ ahd_patch0_func, 525, 1, 1 },
{ ahd_patch1_func, 547, 1, 2 },
{ ahd_patch0_func, 548, 1, 1 },
{ ahd_patch1_func, 551, 1, 2 },
{ ahd_patch0_func, 552, 1, 1 },
{ ahd_patch2_func, 556, 1, 2 },
{ ahd_patch0_func, 557, 1, 1 },
{ ahd_patch1_func, 558, 1, 2 },
{ ahd_patch0_func, 559, 1, 1 },
{ ahd_patch2_func, 570, 1, 2 },
{ ahd_patch0_func, 571, 1, 1 },
{ ahd_patch14_func, 575, 1, 1 },
{ ahd_patch15_func, 580, 1, 1 },
{ ahd_patch16_func, 581, 2, 1 },
{ ahd_patch15_func, 585, 1, 2 },
{ ahd_patch0_func, 586, 1, 1 },
{ ahd_patch2_func, 593, 1, 2 },
{ ahd_patch0_func, 594, 1, 1 },
{ ahd_patch2_func, 609, 1, 2 },
{ ahd_patch0_func, 610, 1, 1 },
{ ahd_patch1_func, 616, 1, 2 },
{ ahd_patch0_func, 617, 1, 1 },
{ ahd_patch1_func, 631, 1, 2 },
{ ahd_patch0_func, 632, 1, 1 },
{ ahd_patch1_func, 639, 1, 2 },
{ ahd_patch0_func, 640, 1, 1 },
{ ahd_patch14_func, 659, 1, 1 },
{ ahd_patch14_func, 675, 1, 1 },
{ ahd_patch2_func, 687, 1, 2 },
{ ahd_patch0_func, 688, 1, 1 },
{ ahd_patch1_func, 705, 1, 2 },
{ ahd_patch0_func, 706, 1, 1 },
{ ahd_patch14_func, 711, 1, 1 },
{ ahd_patch1_func, 731, 1, 2 },
{ ahd_patch0_func, 732, 1, 1 },
{ ahd_patch1_func, 734, 1, 2 },
{ ahd_patch0_func, 735, 1, 1 },
{ ahd_patch1_func, 737, 1, 2 },
{ ahd_patch0_func, 738, 1, 1 },
{ ahd_patch17_func, 740, 1, 2 },
{ ahd_patch0_func, 741, 2, 1 },
{ ahd_patch18_func, 744, 4, 2 },
{ ahd_patch0_func, 748, 1, 1 },
{ ahd_patch18_func, 754, 11, 1 }
{ ahd_patch2_func, 557, 1, 2 },
{ ahd_patch0_func, 558, 1, 1 },
{ ahd_patch2_func, 562, 1, 2 },
{ ahd_patch0_func, 563, 1, 1 },
{ ahd_patch1_func, 564, 1, 2 },
{ ahd_patch0_func, 565, 1, 1 },
{ ahd_patch2_func, 576, 1, 2 },
{ ahd_patch0_func, 577, 1, 1 },
{ ahd_patch15_func, 581, 1, 1 },
{ ahd_patch16_func, 586, 1, 1 },
{ ahd_patch17_func, 587, 2, 1 },
{ ahd_patch16_func, 591, 1, 2 },
{ ahd_patch0_func, 592, 1, 1 },
{ ahd_patch2_func, 595, 1, 2 },
{ ahd_patch0_func, 596, 1, 1 },
{ ahd_patch2_func, 614, 1, 2 },
{ ahd_patch0_func, 615, 1, 1 },
{ ahd_patch18_func, 616, 12, 1 },
{ ahd_patch1_func, 632, 1, 2 },
{ ahd_patch0_func, 633, 1, 1 },
{ ahd_patch18_func, 634, 1, 1 },
{ ahd_patch1_func, 645, 1, 2 },
{ ahd_patch0_func, 646, 1, 1 },
{ ahd_patch1_func, 653, 1, 2 },
{ ahd_patch0_func, 654, 1, 1 },
{ ahd_patch15_func, 673, 1, 1 },
{ ahd_patch15_func, 689, 1, 1 },
{ ahd_patch2_func, 701, 1, 2 },
{ ahd_patch0_func, 702, 1, 1 },
{ ahd_patch1_func, 719, 1, 2 },
{ ahd_patch0_func, 720, 1, 1 },
{ ahd_patch15_func, 725, 1, 1 },
{ ahd_patch1_func, 745, 1, 2 },
{ ahd_patch0_func, 746, 1, 1 },
{ ahd_patch1_func, 748, 1, 2 },
{ ahd_patch0_func, 749, 1, 1 },
{ ahd_patch1_func, 751, 1, 2 },
{ ahd_patch0_func, 752, 1, 1 },
{ ahd_patch19_func, 754, 1, 2 },
{ ahd_patch0_func, 755, 2, 1 },
{ ahd_patch20_func, 758, 4, 2 },
{ ahd_patch0_func, 762, 1, 1 },
{ ahd_patch20_func, 768, 11, 1 }
};
static struct cs {
......@@ -1074,11 +1108,11 @@ static struct cs {
{ 153, 157 },
{ 165, 173 },
{ 196, 245 },
{ 659, 675 },
{ 675, 693 },
{ 698, 704 },
{ 711, 716 },
{ 716, 722 }
{ 673, 689 },
{ 689, 707 },
{ 712, 718 },
{ 725, 730 },
{ 730, 736 }
};
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#70 $
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#72 $
*
* $FreeBSD$
*/
......@@ -365,7 +365,8 @@ typedef enum {
AHC_LSCBS_ENABLED = 0x2000000, /* 64Byte SCBs enabled */
AHC_SCB_CONFIG_USED = 0x4000000, /* No SEEPROM but SCB2 had info. */
AHC_NO_BIOS_INIT = 0x8000000, /* No BIOS left over settings. */
AHC_DISABLE_PCI_PERR = 0x10000000
AHC_DISABLE_PCI_PERR = 0x10000000,
AHC_HAS_TERM_LOGIC = 0x20000000
} ahc_flag;
/************************* Hardware SCB Definition ***************************/
......@@ -877,31 +878,39 @@ typedef enum {
/*********************** Software Configuration Structure *********************/
TAILQ_HEAD(scb_tailq, scb);
struct ahc_suspend_channel_state {
uint8_t scsiseq;
uint8_t sxfrctl0;
uint8_t sxfrctl1;
uint8_t simode0;
uint8_t simode1;
uint8_t seltimer;
uint8_t seqctl;
struct ahc_aic7770_softc {
/*
* Saved register state used for chip_init().
*/
uint8_t busspd;
uint8_t bustime;
};
struct ahc_suspend_state {
struct ahc_suspend_channel_state channel[2];
struct ahc_pci_softc {
/*
* Saved register state used for chip_init().
*/
uint32_t devconfig;
uint16_t targcrccnt;
uint8_t command;
uint8_t csize_lattime;
uint8_t optionmode;
uint8_t crccontrol1;
uint8_t dscommand0;
uint8_t dspcistatus;
/* hsmailbox */
uint8_t crccontrol1;
uint8_t scbbaddr;
/* Host and sequencer SCB counts */
uint8_t dff_thrsh;
uint8_t *scratch_ram;
uint8_t *btt;
};
union ahc_bus_softc {
struct ahc_aic7770_softc aic7770_softc;
struct ahc_pci_softc pci_softc;
};
typedef void (*ahc_bus_intr_t)(struct ahc_softc *);
typedef int (*ahc_bus_chip_init_t)(struct ahc_softc *);
typedef int (*ahc_bus_suspend_t)(struct ahc_softc *);
typedef int (*ahc_bus_resume_t)(struct ahc_softc *);
typedef void ahc_callback_t (void *);
struct ahc_softc {
......@@ -936,6 +945,11 @@ struct ahc_softc {
*/
struct scb_tailq untagged_queues[AHC_NUM_TARGETS];
/*
* Bus attachment specific data.
*/
union ahc_bus_softc bus_softc;
/*
* Platform specific data.
*/
......@@ -951,6 +965,22 @@ struct ahc_softc {
*/
ahc_bus_intr_t bus_intr;
/*
* Bus specific initialization required
* after a chip reset.
*/
ahc_bus_chip_init_t bus_chip_init;
/*
* Bus specific suspend routine.
*/
ahc_bus_suspend_t bus_suspend;
/*
* Bus specific resume routine.
*/
ahc_bus_resume_t bus_resume;
/*
* Target mode related state kept on a per enabled lun basis.
* Targets that are not enabled will have null entries.
......@@ -1043,9 +1073,6 @@ struct ahc_softc {
*/
bus_addr_t dma_bug_buf;
/* Information saved through suspend/resume cycles */
struct ahc_suspend_state suspend_state;
/* Number of enabled target mode device on this card */
u_int enabled_luns;
......@@ -1055,7 +1082,8 @@ struct ahc_softc {
/* PCI cacheline size. */
u_int pci_cachesize;
u_int stack_size;
/* Maximum number of sequencer instructions supported. */
u_int instruction_ram_size;
/* Per-Unit descriptive information */
const char *description;
......@@ -1152,6 +1180,7 @@ int ahc_match_scb(struct ahc_softc *ahc, struct scb *scb,
struct ahc_softc *ahc_alloc(void *platform_arg, char *name);
int ahc_softc_init(struct ahc_softc *);
void ahc_controller_info(struct ahc_softc *ahc, char *buf);
int ahc_chip_init(struct ahc_softc *ahc);
int ahc_init(struct ahc_softc *ahc);
void ahc_intr_enable(struct ahc_softc *ahc, int enable);
void ahc_pause_and_flushwork(struct ahc_softc *ahc);
......@@ -1167,7 +1196,6 @@ int ahc_reset(struct ahc_softc *ahc);
void ahc_shutdown(void *arg);
/*************************** Interrupt Services *******************************/
void ahc_pci_intr(struct ahc_softc *ahc);
void ahc_clear_intstat(struct ahc_softc *ahc);
void ahc_run_qoutfifo(struct ahc_softc *ahc);
#ifdef AHC_TARGET_MODE
......
......@@ -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#112 $
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#116 $
*
* $FreeBSD$
*/
......@@ -144,7 +144,8 @@ static struct ahc_syncrate ahc_syncrates[] =
#include "aic7xxx_seq.h"
/**************************** Function Declarations ***************************/
static void ahc_force_renegotiation(struct ahc_softc *ahc);
static void ahc_force_renegotiation(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo);
static struct ahc_tmode_tstate*
ahc_alloc_tstate(struct ahc_softc *ahc,
u_int scsi_id, char channel);
......@@ -224,7 +225,7 @@ static void ahc_reset_current_bus(struct ahc_softc *ahc);
#ifdef AHC_DUMP_SEQ
static void ahc_dumpseq(struct ahc_softc *ahc);
#endif
static void ahc_loadseq(struct ahc_softc *ahc);
static int ahc_loadseq(struct ahc_softc *ahc);
static int ahc_check_patch(struct ahc_softc *ahc,
struct patch **start_patch,
u_int start_instr, u_int *skip_addr);
......@@ -1032,6 +1033,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
* we should look at the last phase the sequencer recorded,
* or the current phase presented on the bus.
*/
struct ahc_devinfo devinfo;
u_int mesg_out;
u_int curphase;
u_int errorphase;
......@@ -1128,7 +1130,9 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
* case we are out of sync for some external reason
* unknown (or unreported) by the target.
*/
ahc_force_renegotiation(ahc);
ahc_fetch_devinfo(ahc, &devinfo);
ahc_force_renegotiation(ahc, &devinfo);
ahc_outb(ahc, CLRINT, CLRSCSIINT);
ahc_unpause(ahc);
} else if ((status & SELTO) != 0) {
......@@ -1165,6 +1169,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
ahc_name(ahc), scbptr, scb_index);
ahc_dump_card_state(ahc);
} else {
struct ahc_devinfo devinfo;
#ifdef AHC_DEBUG
if ((ahc_debug & AHC_SHOW_SELTO) != 0) {
ahc_print_path(ahc, scb);
......@@ -1181,7 +1186,8 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
* a unit attention in this case, so we must always
* renegotiate.
*/
ahc_force_renegotiation(ahc);
ahc_scb_devinfo(ahc, &devinfo, scb);
ahc_force_renegotiation(ahc, &devinfo);
ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT);
ahc_freeze_devq(ahc, scb);
}
......@@ -1189,6 +1195,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
ahc_restart(ahc);
} else if ((status & BUSFREE) != 0
&& (ahc_inb(ahc, SIMODE1) & ENBUSFREE) != 0) {
struct ahc_devinfo devinfo;
u_int lastphase;
u_int saved_scsiid;
u_int saved_lun;
......@@ -1227,13 +1234,13 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
target = SCSIID_TARGET(ahc, saved_scsiid);
initiator_role_id = SCSIID_OUR_ID(saved_scsiid);
channel = SCSIID_CHANNEL(ahc, saved_scsiid);
ahc_compile_devinfo(&devinfo, initiator_role_id,
target, saved_lun, channel, ROLE_INITIATOR);
printerror = 1;
if (lastphase == P_MESGOUT) {
struct ahc_devinfo devinfo;
u_int tag;
ahc_fetch_devinfo(ahc, &devinfo);
tag = SCB_LIST_NULL;
if (ahc_sent_msg(ahc, AHCMSG_1B, MSG_ABORT_TAG, TRUE)
|| ahc_sent_msg(ahc, AHCMSG_1B, MSG_ABORT, TRUE)) {
......@@ -1344,13 +1351,15 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
if (lastphase == ahc_phase_table[i].phase)
break;
}
if (lastphase != P_BUSFREE) {
/*
* Renegotiate with this device at the
* next oportunity just in case this busfree
* is due to a negotiation mismatch with the
* device.
*/
ahc_force_renegotiation(ahc);
ahc_force_renegotiation(ahc, &devinfo);
}
printf("Unexpected busfree %s\n"
"SEQADDR == 0x%x\n",
ahc_phase_table[i].phasemsg,
......@@ -1371,19 +1380,17 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
* a command to the current device.
*/
static void
ahc_force_renegotiation(struct ahc_softc *ahc)
ahc_force_renegotiation(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
{
struct ahc_devinfo devinfo;
struct ahc_initiator_tinfo *targ_info;
struct ahc_tmode_tstate *tstate;
ahc_fetch_devinfo(ahc, &devinfo);
targ_info = ahc_fetch_transinfo(ahc,
devinfo.channel,
devinfo.our_scsiid,
devinfo.target,
devinfo->channel,
devinfo->our_scsiid,
devinfo->target,
&tstate);
ahc_update_neg_request(ahc, &devinfo, tstate,
ahc_update_neg_request(ahc, devinfo, tstate,
targ_info, AHC_NEG_IF_NON_ASYNC);
}
......@@ -4038,6 +4045,7 @@ ahc_reset(struct ahc_softc *ahc)
{
u_int sblkctl;
u_int sxfrctl1_a, sxfrctl1_b;
int error;
int wait;
/*
......@@ -4128,12 +4136,19 @@ ahc_reset(struct ahc_softc *ahc)
}
ahc_outb(ahc, SXFRCTL1, sxfrctl1_a);
error = 0;
if (ahc->init_level > 0)
/*
* If a recovery action has forced a chip reset,
* re-initialize the chip to our liking.
*/
error = ahc->bus_chip_init(ahc);
#ifdef AHC_DUMP_SEQ
if (ahc->init_level == 0)
else
ahc_dumpseq(ahc);
#endif
return (0);
return (error);
}
/*
......@@ -4203,6 +4218,14 @@ ahc_build_free_scb_list(struct ahc_softc *ahc)
ahc_outb(ahc, SCB_LUN, 0xFF);
}
if ((ahc->flags & AHC_PAGESCBS) != 0) {
/* SCB 0 heads the free list. */
ahc_outb(ahc, FREE_SCBH, 0);
} else {
/* No free list. */
ahc_outb(ahc, FREE_SCBH, SCB_LIST_NULL);
}
/* Make sure that the last SCB terminates the free list */
ahc_outb(ahc, SCBPTR, i-1);
ahc_outb(ahc, SCB_NEXT, SCB_LIST_NULL);
......@@ -4228,20 +4251,11 @@ ahc_init_scbdata(struct ahc_softc *ahc)
/* Determine the number of hardware SCBs and initialize them */
scb_data->maxhscbs = ahc_probe_scbs(ahc);
if ((ahc->flags & AHC_PAGESCBS) != 0) {
/* SCB 0 heads the free list */
ahc_outb(ahc, FREE_SCBH, 0);
} else {
ahc_outb(ahc, FREE_SCBH, SCB_LIST_NULL);
}
if (ahc->scb_data->maxhscbs == 0) {
printf("%s: No SCB space found\n", ahc_name(ahc));
return (ENXIO);
}
ahc_build_free_scb_list(ahc);
/*
* Create our DMA tags. These tags define the kinds of device
* accessible memory allocations and memory mappings we will
......@@ -4343,10 +4357,9 @@ ahc_init_scbdata(struct ahc_softc *ahc)
}
/*
* Tell the sequencer which SCB will be the next one it receives.
* Reserve the next queued SCB.
*/
ahc->next_queued_scb = ahc_get_scb(ahc);
ahc_outb(ahc, NEXT_QUEUED_SCB, ahc->next_queued_scb->hscb->tag);
/*
* Note that we were successfull
......@@ -4531,6 +4544,192 @@ ahc_controller_info(struct ahc_softc *ahc, char *buf)
sprintf(buf, "%d SCBs", ahc->scb_data->maxhscbs);
}
int
ahc_chip_init(struct ahc_softc *ahc)
{
int term;
int error;
u_int i;
u_int scsi_conf;
u_int scsiseq_template;
uint32_t physaddr;
ahc_outb(ahc, SEQ_FLAGS, 0);
ahc_outb(ahc, SEQ_FLAGS2, 0);
/* Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1, for both channels*/
if (ahc->features & AHC_TWIN) {
/*
* Setup Channel B first.
*/
ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) | SELBUSB);
term = (ahc->flags & AHC_TERM_ENB_B) != 0 ? STPWEN : 0;
ahc_outb(ahc, SCSIID, ahc->our_id_b);
scsi_conf = ahc_inb(ahc, SCSICONF + 1);
ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL))
|term|ahc->seltime_b|ENSTIMER|ACTNEGEN);
if ((ahc->features & AHC_ULTRA2) != 0)
ahc_outb(ahc, SIMODE0, ahc_inb(ahc, SIMODE0)|ENIOERR);
ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);
/* Select Channel A */
ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~SELBUSB);
}
term = (ahc->flags & AHC_TERM_ENB_A) != 0 ? STPWEN : 0;
if ((ahc->features & AHC_ULTRA2) != 0)
ahc_outb(ahc, SCSIID_ULTRA2, ahc->our_id);
else
ahc_outb(ahc, SCSIID, ahc->our_id);
scsi_conf = ahc_inb(ahc, SCSICONF);
ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL))
|term|ahc->seltime
|ENSTIMER|ACTNEGEN);
if ((ahc->features & AHC_ULTRA2) != 0)
ahc_outb(ahc, SIMODE0, ahc_inb(ahc, SIMODE0)|ENIOERR);
ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);
/* There are no untagged SCBs active yet. */
for (i = 0; i < 16; i++) {
ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, 0));
if ((ahc->flags & AHC_SCB_BTT) != 0) {
int lun;
/*
* The SCB based BTT allows an entry per
* target and lun pair.
*/
for (lun = 1; lun < AHC_NUM_LUNS; lun++)
ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, lun));
}
}
/* All of our queues are empty */
for (i = 0; i < 256; i++)
ahc->qoutfifo[i] = SCB_LIST_NULL;
ahc_sync_qoutfifo(ahc, BUS_DMASYNC_PREREAD);
for (i = 0; i < 256; i++)
ahc->qinfifo[i] = SCB_LIST_NULL;
if ((ahc->features & AHC_MULTI_TID) != 0) {
ahc_outb(ahc, TARGID, 0);
ahc_outb(ahc, TARGID + 1, 0);
}
/*
* Tell the sequencer where it can find our arrays in memory.
*/
physaddr = ahc->scb_data->hscb_busaddr;
ahc_outb(ahc, HSCB_ADDR, physaddr & 0xFF);
ahc_outb(ahc, HSCB_ADDR + 1, (physaddr >> 8) & 0xFF);
ahc_outb(ahc, HSCB_ADDR + 2, (physaddr >> 16) & 0xFF);
ahc_outb(ahc, HSCB_ADDR + 3, (physaddr >> 24) & 0xFF);
physaddr = ahc->shared_data_busaddr;
ahc_outb(ahc, SHARED_DATA_ADDR, physaddr & 0xFF);
ahc_outb(ahc, SHARED_DATA_ADDR + 1, (physaddr >> 8) & 0xFF);
ahc_outb(ahc, SHARED_DATA_ADDR + 2, (physaddr >> 16) & 0xFF);
ahc_outb(ahc, SHARED_DATA_ADDR + 3, (physaddr >> 24) & 0xFF);
/*
* Initialize the group code to command length table.
* This overrides the values in TARG_SCSIRATE, so only
* setup the table after we have processed that information.
*/
ahc_outb(ahc, CMDSIZE_TABLE, 5);
ahc_outb(ahc, CMDSIZE_TABLE + 1, 9);
ahc_outb(ahc, CMDSIZE_TABLE + 2, 9);
ahc_outb(ahc, CMDSIZE_TABLE + 3, 0);
ahc_outb(ahc, CMDSIZE_TABLE + 4, 15);
ahc_outb(ahc, CMDSIZE_TABLE + 5, 11);
ahc_outb(ahc, CMDSIZE_TABLE + 6, 0);
ahc_outb(ahc, CMDSIZE_TABLE + 7, 0);
if ((ahc->features & AHC_HS_MAILBOX) != 0)
ahc_outb(ahc, HS_MAILBOX, 0);
/* Tell the sequencer of our initial queue positions */
if ((ahc->features & AHC_TARGETMODE) != 0) {
ahc->tqinfifonext = 1;
ahc_outb(ahc, KERNEL_TQINPOS, ahc->tqinfifonext - 1);
ahc_outb(ahc, TQINPOS, ahc->tqinfifonext);
}
ahc->qinfifonext = 0;
ahc->qoutfifonext = 0;
if ((ahc->features & AHC_QUEUE_REGS) != 0) {
ahc_outb(ahc, QOFF_CTLSTA, SCB_QSIZE_256);
ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
ahc_outb(ahc, SNSCB_QOFF, ahc->qinfifonext);
ahc_outb(ahc, SDSCB_QOFF, 0);
} else {
ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext);
ahc_outb(ahc, QINPOS, ahc->qinfifonext);
ahc_outb(ahc, QOUTPOS, ahc->qoutfifonext);
}
/* We don't have any waiting selections */
ahc_outb(ahc, WAITING_SCBH, SCB_LIST_NULL);
/* Our disconnection list is empty too */
ahc_outb(ahc, DISCONNECTED_SCBH, SCB_LIST_NULL);
/* Message out buffer starts empty */
ahc_outb(ahc, MSG_OUT, MSG_NOOP);
/*
* Setup the allowed SCSI Sequences based on operational mode.
* If we are a target, we'll enalbe select in operations once
* we've had a lun enabled.
*/
scsiseq_template = ENSELO|ENAUTOATNO|ENAUTOATNP;
if ((ahc->flags & AHC_INITIATORROLE) != 0)
scsiseq_template |= ENRSELI;
ahc_outb(ahc, SCSISEQ_TEMPLATE, scsiseq_template);
/* Initialize our list of free SCBs. */
ahc_build_free_scb_list(ahc);
/*
* Tell the sequencer which SCB will be the next one it receives.
*/
ahc_outb(ahc, NEXT_QUEUED_SCB, ahc->next_queued_scb->hscb->tag);
/*
* Load the Sequencer program and Enable the adapter
* in "fast" mode.
*/
if (bootverbose)
printf("%s: Downloading Sequencer Program...",
ahc_name(ahc));
error = ahc_loadseq(ahc);
if (error != 0)
return (error);
if ((ahc->features & AHC_ULTRA2) != 0) {
int wait;
/*
* Wait for up to 500ms for our transceivers
* to settle. If the adapter does not have
* a cable attached, the tranceivers may
* never settle, so don't complain if we
* fail here.
*/
ahc_pause(ahc);
for (wait = 5000;
(ahc_inb(ahc, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait;
wait--)
ahc_delay(100);
ahc_unpause(ahc);
}
return (0);
}
/*
* Start the board, ready for normal operation
*/
......@@ -4538,15 +4737,12 @@ int
ahc_init(struct ahc_softc *ahc)
{
int max_targ;
int i;
int term;
u_int i;
u_int scsi_conf;
u_int scsiseq_template;
u_int ultraenb;
u_int discenable;
u_int tagenable;
size_t driver_data_size;
uint32_t physaddr;
#ifdef AHC_DEBUG
if ((ahc_debug & AHC_DEBUG_SEQUENCER) != 0)
......@@ -4664,9 +4860,6 @@ ahc_init(struct ahc_softc *ahc)
for (i = 0; i < AHC_TMODE_CMDS; i++)
ahc->targetcmds[i].cmd_valid = 0;
ahc_sync_tqinfifo(ahc, BUS_DMASYNC_PREREAD);
ahc->tqinfifonext = 1;
ahc_outb(ahc, KERNEL_TQINPOS, ahc->tqinfifonext - 1);
ahc_outb(ahc, TQINPOS, ahc->tqinfifonext);
ahc->qoutfifo = (uint8_t *)&ahc->targetcmds[256];
}
ahc->qinfifo = &ahc->qoutfifo[256];
......@@ -4697,9 +4890,6 @@ ahc_init(struct ahc_softc *ahc)
}
}
ahc_outb(ahc, SEQ_FLAGS, 0);
ahc_outb(ahc, SEQ_FLAGS2, 0);
if (ahc->scb_data->maxhscbs < AHC_SCB_MAX_ALLOC) {
ahc->flags |= AHC_PAGESCBS;
} else {
......@@ -4717,53 +4907,22 @@ ahc_init(struct ahc_softc *ahc)
}
#endif /* AHC_DEBUG */
/* Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1, for both channels*/
if (ahc->features & AHC_TWIN) {
/*
* The device is gated to channel B after a chip reset,
* so set those values first
* Look at the information that board initialization or
* the board bios has left us.
*/
ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) | SELBUSB);
term = (ahc->flags & AHC_TERM_ENB_B) != 0 ? STPWEN : 0;
ahc_outb(ahc, SCSIID, ahc->our_id_b);
if (ahc->features & AHC_TWIN) {
scsi_conf = ahc_inb(ahc, SCSICONF + 1);
ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL))
|term|ahc->seltime_b|ENSTIMER|ACTNEGEN);
if ((ahc->features & AHC_ULTRA2) != 0)
ahc_outb(ahc, SIMODE0, ahc_inb(ahc, SIMODE0)|ENIOERR);
ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);
if ((scsi_conf & RESET_SCSI) != 0
&& (ahc->flags & AHC_INITIATORROLE) != 0)
ahc->flags |= AHC_RESET_BUS_B;
/* Select Channel A */
ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~SELBUSB);
}
term = (ahc->flags & AHC_TERM_ENB_A) != 0 ? STPWEN : 0;
if ((ahc->features & AHC_ULTRA2) != 0)
ahc_outb(ahc, SCSIID_ULTRA2, ahc->our_id);
else
ahc_outb(ahc, SCSIID, ahc->our_id);
scsi_conf = ahc_inb(ahc, SCSICONF);
ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL))
|term|ahc->seltime
|ENSTIMER|ACTNEGEN);
if ((ahc->features & AHC_ULTRA2) != 0)
ahc_outb(ahc, SIMODE0, ahc_inb(ahc, SIMODE0)|ENIOERR);
ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);
scsi_conf = ahc_inb(ahc, SCSICONF);
if ((scsi_conf & RESET_SCSI) != 0
&& (ahc->flags & AHC_INITIATORROLE) != 0)
ahc->flags |= AHC_RESET_BUS_A;
/*
* Look at the information that board initialization or
* the board bios has left us.
*/
ultraenb = 0;
tagenable = ALL_TARGETS_MASK;
......@@ -4890,127 +5049,7 @@ ahc_init(struct ahc_softc *ahc)
ahc->user_discenable = discenable;
ahc->user_tagenable = tagenable;
/* There are no untagged SCBs active yet. */
for (i = 0; i < 16; i++) {
ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, 0));
if ((ahc->flags & AHC_SCB_BTT) != 0) {
int lun;
/*
* The SCB based BTT allows an entry per
* target and lun pair.
*/
for (lun = 1; lun < AHC_NUM_LUNS; lun++)
ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, lun));
}
}
/* All of our queues are empty */
for (i = 0; i < 256; i++)
ahc->qoutfifo[i] = SCB_LIST_NULL;
ahc_sync_qoutfifo(ahc, BUS_DMASYNC_PREREAD);
for (i = 0; i < 256; i++)
ahc->qinfifo[i] = SCB_LIST_NULL;
if ((ahc->features & AHC_MULTI_TID) != 0) {
ahc_outb(ahc, TARGID, 0);
ahc_outb(ahc, TARGID + 1, 0);
}
/*
* Tell the sequencer where it can find our arrays in memory.
*/
physaddr = ahc->scb_data->hscb_busaddr;
ahc_outb(ahc, HSCB_ADDR, physaddr & 0xFF);
ahc_outb(ahc, HSCB_ADDR + 1, (physaddr >> 8) & 0xFF);
ahc_outb(ahc, HSCB_ADDR + 2, (physaddr >> 16) & 0xFF);
ahc_outb(ahc, HSCB_ADDR + 3, (physaddr >> 24) & 0xFF);
physaddr = ahc->shared_data_busaddr;
ahc_outb(ahc, SHARED_DATA_ADDR, physaddr & 0xFF);
ahc_outb(ahc, SHARED_DATA_ADDR + 1, (physaddr >> 8) & 0xFF);
ahc_outb(ahc, SHARED_DATA_ADDR + 2, (physaddr >> 16) & 0xFF);
ahc_outb(ahc, SHARED_DATA_ADDR + 3, (physaddr >> 24) & 0xFF);
/*
* Initialize the group code to command length table.
* This overrides the values in TARG_SCSIRATE, so only
* setup the table after we have processed that information.
*/
ahc_outb(ahc, CMDSIZE_TABLE, 5);
ahc_outb(ahc, CMDSIZE_TABLE + 1, 9);
ahc_outb(ahc, CMDSIZE_TABLE + 2, 9);
ahc_outb(ahc, CMDSIZE_TABLE + 3, 0);
ahc_outb(ahc, CMDSIZE_TABLE + 4, 15);
ahc_outb(ahc, CMDSIZE_TABLE + 5, 11);
ahc_outb(ahc, CMDSIZE_TABLE + 6, 0);
ahc_outb(ahc, CMDSIZE_TABLE + 7, 0);
/* Tell the sequencer of our initial queue positions */
ahc_outb(ahc, KERNEL_QINPOS, 0);
ahc_outb(ahc, QINPOS, 0);
ahc_outb(ahc, QOUTPOS, 0);
/*
* Use the built in queue management registers
* if they are available.
*/
if ((ahc->features & AHC_QUEUE_REGS) != 0) {
ahc_outb(ahc, QOFF_CTLSTA, SCB_QSIZE_256);
ahc_outb(ahc, SDSCB_QOFF, 0);
ahc_outb(ahc, SNSCB_QOFF, 0);
ahc_outb(ahc, HNSCB_QOFF, 0);
}
/* We don't have any waiting selections */
ahc_outb(ahc, WAITING_SCBH, SCB_LIST_NULL);
/* Our disconnection list is empty too */
ahc_outb(ahc, DISCONNECTED_SCBH, SCB_LIST_NULL);
/* Message out buffer starts empty */
ahc_outb(ahc, MSG_OUT, MSG_NOOP);
/*
* Setup the allowed SCSI Sequences based on operational mode.
* If we are a target, we'll enalbe select in operations once
* we've had a lun enabled.
*/
scsiseq_template = ENSELO|ENAUTOATNO|ENAUTOATNP;
if ((ahc->flags & AHC_INITIATORROLE) != 0)
scsiseq_template |= ENRSELI;
ahc_outb(ahc, SCSISEQ_TEMPLATE, scsiseq_template);
/*
* Load the Sequencer program and Enable the adapter
* in "fast" mode.
*/
if (bootverbose)
printf("%s: Downloading Sequencer Program...",
ahc_name(ahc));
ahc_loadseq(ahc);
if ((ahc->features & AHC_ULTRA2) != 0) {
int wait;
/*
* Wait for up to 500ms for our transceivers
* to settle. If the adapter does not have
* a cable attached, the tranceivers may
* never settle, so don't complain if we
* fail here.
*/
ahc_pause(ahc);
for (wait = 5000;
(ahc_inb(ahc, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait;
wait--)
ahc_delay(100);
ahc_unpause(ahc);
}
return (0);
return (ahc->bus_chip_init(ahc));
}
void
......@@ -5046,7 +5085,6 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc)
maxloops = 1000;
ahc->flags |= AHC_ALL_INTERRUPTS;
intstat = 0;
paused = FALSE;
do {
if (paused)
......@@ -5056,10 +5094,10 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc)
paused = TRUE;
ahc_outb(ahc, SCSISEQ, ahc_inb(ahc, SCSISEQ) & ~ENSELO);
ahc_clear_critical_section(ahc);
if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0)
break;
intstat = ahc_inb(ahc, INTSTAT);
} while (--maxloops
&& (((intstat = ahc_inb(ahc, INTSTAT)) & INT_PEND) != 0
&& (intstat != 0xFF || (ahc->features & AHC_REMOVABLE) == 0)
&& ((intstat & INT_PEND) != 0
|| (ahc_inb(ahc, SSTAT0) & (SELDO|SELINGO))));
if (maxloops == 0) {
printf("Infinite interrupt loop, INTSTAT = %x",
......@@ -5072,13 +5110,13 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc)
int
ahc_suspend(struct ahc_softc *ahc)
{
uint8_t *ptr;
int i;
ahc_pause_and_flushwork(ahc);
if (LIST_FIRST(&ahc->pending_scbs) != NULL)
if (LIST_FIRST(&ahc->pending_scbs) != NULL) {
ahc_unpause(ahc);
return (EBUSY);
}
#if AHC_TARGET_MODE
/*
......@@ -5086,73 +5124,11 @@ ahc_suspend(struct ahc_softc *ahc)
* Perhaps we should just refuse to be suspended if we
* are acting in a target role.
*/
if (ahc->pending_device != NULL)
if (ahc->pending_device != NULL) {
ahc_unpause(ahc);
return (EBUSY);
#endif
/* Save volatile registers */
if ((ahc->features & AHC_TWIN) != 0) {
ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) | SELBUSB);
ahc->suspend_state.channel[1].scsiseq = ahc_inb(ahc, SCSISEQ);
ahc->suspend_state.channel[1].sxfrctl0 = ahc_inb(ahc, SXFRCTL0);
ahc->suspend_state.channel[1].sxfrctl1 = ahc_inb(ahc, SXFRCTL1);
ahc->suspend_state.channel[1].simode0 = ahc_inb(ahc, SIMODE0);
ahc->suspend_state.channel[1].simode1 = ahc_inb(ahc, SIMODE1);
ahc->suspend_state.channel[1].seltimer = ahc_inb(ahc, SELTIMER);
ahc->suspend_state.channel[1].seqctl = ahc_inb(ahc, SEQCTL);
ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~SELBUSB);
}
ahc->suspend_state.channel[0].scsiseq = ahc_inb(ahc, SCSISEQ);
ahc->suspend_state.channel[0].sxfrctl0 = ahc_inb(ahc, SXFRCTL0);
ahc->suspend_state.channel[0].sxfrctl1 = ahc_inb(ahc, SXFRCTL1);
ahc->suspend_state.channel[0].simode0 = ahc_inb(ahc, SIMODE0);
ahc->suspend_state.channel[0].simode1 = ahc_inb(ahc, SIMODE1);
ahc->suspend_state.channel[0].seltimer = ahc_inb(ahc, SELTIMER);
ahc->suspend_state.channel[0].seqctl = ahc_inb(ahc, SEQCTL);
if ((ahc->chip & AHC_PCI) != 0) {
ahc->suspend_state.dscommand0 = ahc_inb(ahc, DSCOMMAND0);
ahc->suspend_state.dspcistatus = ahc_inb(ahc, DSPCISTATUS);
}
if ((ahc->features & AHC_DT) != 0) {
u_int sfunct;
sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
ahc->suspend_state.optionmode = ahc_inb(ahc, OPTIONMODE);
ahc_outb(ahc, SFUNCT, sfunct);
ahc->suspend_state.crccontrol1 = ahc_inb(ahc, CRCCONTROL1);
}
if ((ahc->features & AHC_MULTI_FUNC) != 0)
ahc->suspend_state.scbbaddr = ahc_inb(ahc, SCBBADDR);
if ((ahc->features & AHC_ULTRA2) != 0)
ahc->suspend_state.dff_thrsh = ahc_inb(ahc, DFF_THRSH);
ptr = ahc->suspend_state.scratch_ram;
for (i = 0; i < 64; i++)
*ptr++ = ahc_inb(ahc, SRAM_BASE + i);
if ((ahc->features & AHC_MORE_SRAM) != 0) {
for (i = 0; i < 16; i++)
*ptr++ = ahc_inb(ahc, TARG_OFFSET + i);
}
ptr = ahc->suspend_state.btt;
if ((ahc->flags & AHC_SCB_BTT) != 0) {
for (i = 0;i < AHC_NUM_TARGETS; i++) {
int j;
for (j = 0;j < AHC_NUM_LUNS; j++) {
u_int tcl;
tcl = BUILD_TCL(i << 4, j);
*ptr = ahc_index_busy_tcl(ahc, tcl);
}
}
}
#endif
ahc_shutdown(ahc);
return (0);
}
......@@ -5160,81 +5136,8 @@ ahc_suspend(struct ahc_softc *ahc)
int
ahc_resume(struct ahc_softc *ahc)
{
uint8_t *ptr;
int i;
ahc_reset(ahc);
ahc_build_free_scb_list(ahc);
/* Restore volatile registers */
if ((ahc->features & AHC_TWIN) != 0) {
ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) | SELBUSB);
ahc_outb(ahc, SCSIID, ahc->our_id);
ahc_outb(ahc, SCSISEQ, ahc->suspend_state.channel[1].scsiseq);
ahc_outb(ahc, SXFRCTL0, ahc->suspend_state.channel[1].sxfrctl0);
ahc_outb(ahc, SXFRCTL1, ahc->suspend_state.channel[1].sxfrctl1);
ahc_outb(ahc, SIMODE0, ahc->suspend_state.channel[1].simode0);
ahc_outb(ahc, SIMODE1, ahc->suspend_state.channel[1].simode1);
ahc_outb(ahc, SELTIMER, ahc->suspend_state.channel[1].seltimer);
ahc_outb(ahc, SEQCTL, ahc->suspend_state.channel[1].seqctl);
ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~SELBUSB);
}
ahc_outb(ahc, SCSISEQ, ahc->suspend_state.channel[0].scsiseq);
ahc_outb(ahc, SXFRCTL0, ahc->suspend_state.channel[0].sxfrctl0);
ahc_outb(ahc, SXFRCTL1, ahc->suspend_state.channel[0].sxfrctl1);
ahc_outb(ahc, SIMODE0, ahc->suspend_state.channel[0].simode0);
ahc_outb(ahc, SIMODE1, ahc->suspend_state.channel[0].simode1);
ahc_outb(ahc, SELTIMER, ahc->suspend_state.channel[0].seltimer);
ahc_outb(ahc, SEQCTL, ahc->suspend_state.channel[0].seqctl);
if ((ahc->features & AHC_ULTRA2) != 0)
ahc_outb(ahc, SCSIID_ULTRA2, ahc->our_id);
else
ahc_outb(ahc, SCSIID, ahc->our_id);
if ((ahc->chip & AHC_PCI) != 0) {
ahc_outb(ahc, DSCOMMAND0, ahc->suspend_state.dscommand0);
ahc_outb(ahc, DSPCISTATUS, ahc->suspend_state.dspcistatus);
}
if ((ahc->features & AHC_DT) != 0) {
u_int sfunct;
sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
ahc_outb(ahc, OPTIONMODE, ahc->suspend_state.optionmode);
ahc_outb(ahc, SFUNCT, sfunct);
ahc_outb(ahc, CRCCONTROL1, ahc->suspend_state.crccontrol1);
}
if ((ahc->features & AHC_MULTI_FUNC) != 0)
ahc_outb(ahc, SCBBADDR, ahc->suspend_state.scbbaddr);
if ((ahc->features & AHC_ULTRA2) != 0)
ahc_outb(ahc, DFF_THRSH, ahc->suspend_state.dff_thrsh);
ptr = ahc->suspend_state.scratch_ram;
for (i = 0; i < 64; i++)
ahc_outb(ahc, SRAM_BASE + i, *ptr++);
if ((ahc->features & AHC_MORE_SRAM) != 0) {
for (i = 0; i < 16; i++)
ahc_outb(ahc, TARG_OFFSET + i, *ptr++);
}
ptr = ahc->suspend_state.btt;
if ((ahc->flags & AHC_SCB_BTT) != 0) {
for (i = 0;i < AHC_NUM_TARGETS; i++) {
int j;
for (j = 0;j < AHC_NUM_LUNS; j++) {
u_int tcl;
tcl = BUILD_TCL(i << 4, j);
ahc_busy_tcl(ahc, tcl, *ptr);
}
}
}
return (0);
}
......@@ -6379,19 +6282,11 @@ void
ahc_dumpseq(struct ahc_softc* ahc)
{
int i;
int max_prog;
if ((ahc->chip & AHC_BUS_MASK) < AHC_PCI)
max_prog = 448;
else if ((ahc->features & AHC_ULTRA2) != 0)
max_prog = 768;
else
max_prog = 512;
ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
ahc_outb(ahc, SEQADDR0, 0);
ahc_outb(ahc, SEQADDR1, 0);
for (i = 0; i < max_prog; i++) {
for (i = 0; i < ahc->instruction_ram_size; i++) {
uint8_t ins_bytes[4];
ahc_insb(ahc, SEQRAM, ins_bytes, 4);
......@@ -6403,19 +6298,19 @@ ahc_dumpseq(struct ahc_softc* ahc)
}
#endif
static void
static int
ahc_loadseq(struct ahc_softc *ahc)
{
struct cs cs_table[num_critical_sections];
struct patch *cur_patch;
u_int begin_set[num_critical_sections];
u_int end_set[num_critical_sections];
struct patch *cur_patch;
u_int cs_count;
u_int cur_cs;
u_int i;
int downloaded;
u_int skip_addr;
u_int sg_prefetch_cnt;
int downloaded;
uint8_t download_consts[7];
/*
......@@ -6456,6 +6351,19 @@ ahc_loadseq(struct ahc_softc *ahc)
*/
continue;
}
if (downloaded == ahc->instruction_ram_size) {
/*
* We're about to exceed the instruction
* storage capacity for this chip. Fail
* the load.
*/
printf("\n%s: Program too large for instruction memory "
"size of %d!\n", ahc_name(ahc),
ahc->instruction_ram_size);
return (ENOMEM);
}
/*
* Move through the CS table until we find a CS
* that might apply to this instruction.
......@@ -6498,6 +6406,7 @@ ahc_loadseq(struct ahc_softc *ahc)
printf("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n",
ahc_name(ahc), ahc->features, ahc->bugs, ahc->flags);
}
return (0);
}
static int
......@@ -6942,11 +6851,12 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
struct ahc_tmode_lstate *lstate;
struct ccb_en_lun *cel;
cam_status status;
u_long s;
u_int target;
u_int lun;
u_int target_mask;
u_int our_id;
u_long s;
int error;
char channel;
status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, &lstate,
......@@ -7024,6 +6934,7 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
if ((ahc->flags & AHC_TARGETROLE) == 0
&& ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
u_long s;
ahc_flag saved_flags;
printf("Configuring Target Mode\n");
ahc_lock(ahc, &s);
......@@ -7032,11 +6943,28 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
ahc_unlock(ahc, &s);
return;
}
saved_flags = ahc->flags;
ahc->flags |= AHC_TARGETROLE;
if ((ahc->features & AHC_MULTIROLE) == 0)
ahc->flags &= ~AHC_INITIATORROLE;
ahc_pause(ahc);
ahc_loadseq(ahc);
error = ahc_loadseq(ahc);
if (error != 0) {
/*
* Restore original configuration and notify
* the caller that we cannot support target mode.
* Since the adapter started out in this
* configuration, the firmware load will succeed,
* so there is no point in checking ahc_loadseq's
* return value.
*/
ahc->flags = saved_flags;
(void)ahc_loadseq(ahc);
ahc_unpause(ahc);
ahc_unlock(ahc, &s);
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
return;
}
ahc_unlock(ahc, &s);
}
cel = &ccb->cel;
......@@ -7272,7 +7200,11 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
ahc->flags &= ~AHC_TARGETROLE;
ahc->flags |= AHC_INITIATORROLE;
ahc_pause(ahc);
ahc_loadseq(ahc);
/*
* Returning to a configuration that
* fit previously will always succeed.
*/
(void)ahc_loadseq(ahc);
}
}
ahc_unpause(ahc);
......
......@@ -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#39 $
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#40 $
*
* $FreeBSD$
*/
......
/*
* Adaptec AIC7xxx device driver for Linux.
*
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#179 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#188 $
*
* Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science.
......@@ -995,9 +995,13 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,
cmd->device->lun, /*alloc*/TRUE);
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_midlayer_entrypoint_unlock(ahc, &flags);
printf("aic7xxx_linux_queue: Unable to allocate device!\n");
return (-ENOMEM);
printf("%s: aic7xxx_linux_queue - Unable to allocate device!\n",
ahc_name(ahc));
return (0);
}
cmd->result = CAM_REQ_INPROG << 16;
TAILQ_INSERT_TAIL(&dev->busyq, (struct ahc_cmd *)cmd, acmd_links.tqe);
......@@ -1892,6 +1896,20 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
if (target > 7
&& (ahc->features & AHC_TWIN) != 0)
channel = 1;
/*
* Skip our own ID. Some Compaq/HP storage devices
* have enclosure management devices that respond to
* single bit selection (i.e. selecting ourselves).
* It is expected that either an external application
* or a modified kernel will be used to probe this
* ID if it is appropriate. To accomodate these installations,
* ahc_linux_alloc_target() will allocate for our ID if
* asked to do so.
*/
if ((channel == 0 && target == ahc->our_id)
|| (channel == 1 && target == ahc->our_id_b))
continue;
ahc_linux_alloc_target(ahc, channel, target);
}
ahc_intr_enable(ahc, TRUE);
......@@ -2360,7 +2378,17 @@ ahc_linux_dv_thread(void *data)
* Complete thread creation.
*/
lock_kernel();
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
/*
* Don't care about any signals.
*/
siginitsetinv(&current->blocked, 0);
daemonize();
sprintf(current->comm, "ahc_dv_%d", ahc->unit);
#else
daemonize("ahc_dv_%d", ahc->unit);
#endif
unlock_kernel();
while (1) {
......@@ -3993,15 +4021,6 @@ ahc_linux_alloc_target(struct ahc_softc *ahc, u_int channel, u_int target)
target_offset = target;
if (channel != 0)
target_offset += 8;
/*
* Never allow allocation of a target object for
* our own SCSIID.
*/
if ((channel == 0 && target == ahc->our_id)
|| (channel == 1 && target == ahc->our_id_b)) {
ahc->platform_data->targets[target_offset] = NULL;
return (NULL);
}
targ = malloc(sizeof(*targ), M_DEVBUG, M_NOWAIT);
if (targ == NULL)
......@@ -4272,6 +4291,14 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
#endif
ahc_set_transaction_status(scb, CAM_UNCOR_PARITY);
} else if (amount_xferred < scb->io_ctx->underflow) {
u_int i;
ahc_print_path(ahc, scb);
printf("CDB:");
for (i = 0; i < scb->io_ctx->cmd_len; i++)
printf(" 0x%x", scb->io_ctx->cmnd[i]);
printf("\n");
ahc_print_path(ahc, scb);
printf("Saw underflow (%ld of %ld bytes). "
"Treated as error\n",
ahc_get_residual(scb),
......@@ -4813,6 +4840,7 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
u_int active_scb_index;
u_int last_phase;
u_int saved_scsiid;
u_int cdb_byte;
int retval;
int paused;
int wait;
......@@ -4829,6 +4857,11 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
cmd->device->id, cmd->device->lun,
flag == SCB_ABORT ? "n ABORT" : " TARGET RESET");
printf("CDB:");
for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
printf(" 0x%x", cmd->cmnd[cdb_byte]);
printf("\n");
/*
* In all versions of Linux, we have to work around
* a major flaw in how the mid-layer is locked down
......
......@@ -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#123 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#126 $
*
*/
#ifndef _AIC7XXX_LINUX_H_
......@@ -299,7 +299,7 @@ ahc_scb_timer_reset(struct scb *scb, u_int usec)
#include <linux/smp.h>
#endif
#define AIC7XXX_DRIVER_VERSION "6.2.28"
#define AIC7XXX_DRIVER_VERSION "6.2.29"
/**************************** Front End Queues ********************************/
/*
......
......@@ -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#57 $
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#60 $
*
* $FreeBSD$
*/
......@@ -698,6 +698,10 @@ static void aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
int *eeprom_present);
static void write_brdctl(struct ahc_softc *ahc, uint8_t value);
static uint8_t read_brdctl(struct ahc_softc *ahc);
static void ahc_pci_intr(struct ahc_softc *ahc);
static int ahc_pci_chip_init(struct ahc_softc *ahc);
static int ahc_pci_suspend(struct ahc_softc *ahc);
static int ahc_pci_resume(struct ahc_softc *ahc);
static int
ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,
......@@ -854,6 +858,9 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
return (error);
ahc->bus_intr = ahc_pci_intr;
ahc->bus_chip_init = ahc_pci_chip_init;
ahc->bus_suspend = ahc_pci_suspend;
ahc->bus_resume = ahc_pci_resume;
/* Remeber how the card was setup in case there is no SEEPROM */
if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) {
......@@ -993,6 +1000,35 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
if ((sxfrctl1 & STPWEN) != 0)
ahc->flags |= AHC_TERM_ENB_A;
/*
* Save chip register configuration data for chip resets
* that occur during runtime and resume events.
*/
ahc->bus_softc.pci_softc.devconfig =
ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
ahc->bus_softc.pci_softc.command =
ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1);
ahc->bus_softc.pci_softc.csize_lattime =
ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1);
ahc->bus_softc.pci_softc.dscommand0 = ahc_inb(ahc, DSCOMMAND0);
ahc->bus_softc.pci_softc.dspcistatus = ahc_inb(ahc, DSPCISTATUS);
if ((ahc->features & AHC_DT) != 0) {
u_int sfunct;
sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
ahc->bus_softc.pci_softc.optionmode = ahc_inb(ahc, OPTIONMODE);
ahc->bus_softc.pci_softc.targcrccnt = ahc_inw(ahc, TARGCRCCNT);
ahc_outb(ahc, SFUNCT, sfunct);
ahc->bus_softc.pci_softc.crccontrol1 =
ahc_inb(ahc, CRCCONTROL1);
}
if ((ahc->features & AHC_MULTI_FUNC) != 0)
ahc->bus_softc.pci_softc.scbbaddr = ahc_inb(ahc, SCBBADDR);
if ((ahc->features & AHC_ULTRA2) != 0)
ahc->bus_softc.pci_softc.dff_thrsh = ahc_inb(ahc, DFF_THRSH);
/* Core initialization */
error = ahc_init(ahc);
if (error != 0)
......@@ -1412,6 +1448,7 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
}
if (have_autoterm) {
ahc->flags |= AHC_HAS_TERM_LOGIC;
ahc_acquire_seeprom(ahc, &sd);
configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1);
ahc_release_seeprom(&sd);
......@@ -1845,11 +1882,14 @@ aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
spiocap |= EXT_BRDCTL;
ahc_outb(ahc, SPIOCAP, spiocap);
ahc_outb(ahc, BRDCTL, BRDRW|BRDCS);
ahc_flush_device_writes(ahc);
ahc_delay(500);
ahc_outb(ahc, BRDCTL, 0);
ahc_flush_device_writes(ahc);
ahc_delay(500);
brdctl = ahc_inb(ahc, BRDCTL);
*internal50_present = (brdctl & BRDDAT5) ? 0 : 1;
*externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
*eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0;
}
......@@ -1943,7 +1983,7 @@ read_brdctl(ahc)
return (value);
}
void
static void
ahc_pci_intr(struct ahc_softc *ahc)
{
u_int error;
......@@ -1995,6 +2035,73 @@ ahc_pci_intr(struct ahc_softc *ahc)
ahc_unpause(ahc);
}
static int
ahc_pci_chip_init(struct ahc_softc *ahc)
{
ahc_outb(ahc, DSCOMMAND0, ahc->bus_softc.pci_softc.dscommand0);
ahc_outb(ahc, DSPCISTATUS, ahc->bus_softc.pci_softc.dspcistatus);
if ((ahc->features & AHC_DT) != 0) {
u_int sfunct;
sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
ahc_outb(ahc, OPTIONMODE, ahc->bus_softc.pci_softc.optionmode);
ahc_outw(ahc, TARGCRCCNT, ahc->bus_softc.pci_softc.targcrccnt);
ahc_outb(ahc, SFUNCT, sfunct);
ahc_outb(ahc, CRCCONTROL1,
ahc->bus_softc.pci_softc.crccontrol1);
}
if ((ahc->features & AHC_MULTI_FUNC) != 0)
ahc_outb(ahc, SCBBADDR, ahc->bus_softc.pci_softc.scbbaddr);
if ((ahc->features & AHC_ULTRA2) != 0)
ahc_outb(ahc, DFF_THRSH, ahc->bus_softc.pci_softc.dff_thrsh);
return (ahc_chip_init(ahc));
}
static int
ahc_pci_suspend(struct ahc_softc *ahc)
{
return (ahc_suspend(ahc));
}
static int
ahc_pci_resume(struct ahc_softc *ahc)
{
ahc_power_state_change(ahc, AHC_POWER_STATE_D0);
/*
* We assume that the OS has restored our register
* mappings, etc. Just update the config space registers
* that the OS doesn't know about and rely on our chip
* reset handler to handle the rest.
*/
ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4,
ahc->bus_softc.pci_softc.devconfig);
ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1,
ahc->bus_softc.pci_softc.command);
ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1,
ahc->bus_softc.pci_softc.csize_lattime);
if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) {
struct seeprom_descriptor sd;
u_int sxfrctl1;
sd.sd_ahc = ahc;
sd.sd_control_offset = SEECTL;
sd.sd_status_offset = SEECTL;
sd.sd_dataout_offset = SEECTL;
ahc_acquire_seeprom(ahc, &sd);
configure_termination(ahc, &sd,
ahc->seep_config->adapter_control,
&sxfrctl1);
ahc_release_seeprom(&sd);
}
return (ahc_resume(ahc));
}
static int
ahc_aic785X_setup(struct ahc_softc *ahc)
{
......@@ -2009,6 +2116,7 @@ ahc_aic785X_setup(struct ahc_softc *ahc)
rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
if (rev >= 1)
ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
ahc->instruction_ram_size = 512;
return (0);
}
......@@ -2026,6 +2134,7 @@ ahc_aic7860_setup(struct ahc_softc *ahc)
rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
if (rev >= 1)
ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
ahc->instruction_ram_size = 512;
return (0);
}
......@@ -2049,6 +2158,7 @@ ahc_aic7870_setup(struct ahc_softc *ahc)
ahc->chip = AHC_AIC7870;
ahc->features = AHC_AIC7870_FE;
ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
ahc->instruction_ram_size = 512;
return (0);
}
......@@ -2102,6 +2212,7 @@ ahc_aic7880_setup(struct ahc_softc *ahc)
} else {
ahc->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
}
ahc->instruction_ram_size = 512;
return (0);
}
......@@ -2149,6 +2260,7 @@ ahc_aic7890_setup(struct ahc_softc *ahc)
rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
if (rev == 0)
ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG;
ahc->instruction_ram_size = 768;
return (0);
}
......@@ -2161,6 +2273,7 @@ ahc_aic7892_setup(struct ahc_softc *ahc)
ahc->features = AHC_AIC7892_FE;
ahc->flags |= AHC_NEWEEPROM_FMT;
ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG;
ahc->instruction_ram_size = 1024;
return (0);
}
......@@ -2216,6 +2329,7 @@ ahc_aic7895_setup(struct ahc_softc *ahc)
ahc_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1);
#endif
ahc->flags |= AHC_NEWEEPROM_FMT;
ahc->instruction_ram_size = 512;
return (0);
}
......@@ -2230,6 +2344,7 @@ ahc_aic7896_setup(struct ahc_softc *ahc)
ahc->features = AHC_AIC7896_FE;
ahc->flags |= AHC_NEWEEPROM_FMT;
ahc->bugs |= AHC_CACHETHEN_DIS_BUG;
ahc->instruction_ram_size = 768;
return (0);
}
......@@ -2244,6 +2359,7 @@ ahc_aic7899_setup(struct ahc_softc *ahc)
ahc->features = AHC_AIC7899_FE;
ahc->flags |= AHC_NEWEEPROM_FMT;
ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG;
ahc->instruction_ram_size = 1024;
return (0);
}
......
......@@ -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#23 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#24 $
*/
#include "aic7xxx_osm.h"
#include "aic7xxx_inline.h"
......@@ -325,6 +325,7 @@ ahc_linux_proc_info(char *buffer, char **start, off_t offset,
copy_info(&info, "Adaptec AIC7xxx driver version: %s\n",
AIC7XXX_DRIVER_VERSION);
copy_info(&info, "%s\n", ahc->description);
ahc_controller_info(ahc, ahc_info);
copy_info(&info, "%s\n\n", ahc_info);
......
......@@ -10,9 +10,10 @@ GENHDRS= aicdb.h $(YSRCS:.y=.h)
GENSRCS= $(YSRCS:.y=.c) $(LSRCS:.l=.c)
SRCS= ${CSRCS} ${GENSRCS}
CLEANFILES= ${GENSRCS} ${GENHDRS} $(YSRCS:.y=.output)
LIBS= -ldb
clean-files:= ${GENSRCS} ${GENHDRS} $(YSRCS:.y=.output) $(PROG)
# Override default kernel CFLAGS. This is a userland app.
AICASM_CFLAGS:= -I/usr/include -I. -ldb
AICASM_CFLAGS:= -I/usr/include -I.
YFLAGS= -d
NOMAN= noman
......@@ -30,7 +31,7 @@ LFLAGS= -d
endif
$(PROG): ${GENHDRS} $(SRCS)
$(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG)
$(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) $(LIBS)
aicdb.h:
@if [ -e "/usr/include/db3/db_185.h" ]; then \
......@@ -46,7 +47,7 @@ aicdb.h:
fi
clean:
rm -f $(CLEANFILES) $(PROG)
rm -f $(clean-files)
aicasm_gram.c aicasm_gram.h: aicasm_gram.y
$(YACC) $(YFLAGS) -b $(<:.y=) $<
......
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