summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/aic7xxx/ahc_eisa.c2
-rw-r--r--sys/dev/aic7xxx/ahc_pci.c2
-rw-r--r--sys/dev/aic7xxx/aic7770.c18
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c320
-rw-r--r--sys/dev/aic7xxx/aic7xxx.h45
-rw-r--r--sys/dev/aic7xxx/aic7xxx.reg3
-rw-r--r--sys/dev/aic7xxx/aic7xxx.seq218
-rw-r--r--sys/dev/aic7xxx/aic7xxx_93cx6.c8
-rw-r--r--sys/dev/aic7xxx/aic7xxx_freebsd.c54
-rw-r--r--sys/dev/aic7xxx/aic7xxx_freebsd.h15
-rw-r--r--sys/dev/aic7xxx/aic7xxx_inline.h19
-rw-r--r--sys/dev/aic7xxx/aic7xxx_osm.c54
-rw-r--r--sys/dev/aic7xxx/aic7xxx_osm.h15
-rw-r--r--sys/dev/aic7xxx/aic7xxx_pci.c56
14 files changed, 506 insertions, 323 deletions
diff --git a/sys/dev/aic7xxx/ahc_eisa.c b/sys/dev/aic7xxx/ahc_eisa.c
index 79db102..f7552d4 100644
--- a/sys/dev/aic7xxx/ahc_eisa.c
+++ b/sys/dev/aic7xxx/ahc_eisa.c
@@ -211,3 +211,5 @@ static driver_t ahc_eisa_driver = {
static devclass_t ahc_devclass;
DRIVER_MODULE(ahc, eisa, ahc_eisa_driver, ahc_devclass, 0, 0);
+MODULE_DEPEND(ahc_eisa, ahc, 1, 1, 1);
+MODULE_VERSION(ahc_eisa, 1);
diff --git a/sys/dev/aic7xxx/ahc_pci.c b/sys/dev/aic7xxx/ahc_pci.c
index 3519dce..9968570 100644
--- a/sys/dev/aic7xxx/ahc_pci.c
+++ b/sys/dev/aic7xxx/ahc_pci.c
@@ -59,6 +59,8 @@ static devclass_t ahc_devclass;
DRIVER_MODULE(ahc, pci, ahc_pci_driver, ahc_devclass, 0, 0);
DRIVER_MODULE(ahc, cardbus, ahc_pci_driver, ahc_devclass, 0, 0);
+MODULE_DEPEND(ahc_pci, ahc, 1, 1, 1);
+MODULE_VERSION(ahc_pci, 1);
static int
ahc_pci_probe(device_t dev)
diff --git a/sys/dev/aic7xxx/aic7770.c b/sys/dev/aic7xxx/aic7770.c
index ac23d19..d717882 100644
--- a/sys/dev/aic7xxx/aic7770.c
+++ b/sys/dev/aic7xxx/aic7770.c
@@ -29,22 +29,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7770.c#9 $
+ * $Id: //depot/src/aic7xxx/aic7770.c#11 $
*
* $FreeBSD$
*/
-#ifdef __linux__
-#include "aic7xxx_linux.h"
-#include "aic7xxx_inline.h"
-#include "aic7xxx_93cx6.h"
-#endif
-
-#ifdef __FreeBSD__
#include <dev/aic7xxx/aic7xxx_freebsd.h>
#include <dev/aic7xxx/aic7xxx_inline.h>
#include <dev/aic7xxx/aic7xxx_93cx6.h>
-#endif
#define ID_AIC7770 0x04907770
#define ID_AHA_274x 0x04907771
@@ -139,10 +131,6 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry)
if ((intdef & EDGE_TRIG) != 0)
ahc->flags |= AHC_EDGE_INTERRUPT;
- error = aic7770_map_int(ahc, irq);
- if (error != 0)
- return (error);
-
switch (probe_config.chip & (AHC_EISA|AHC_VL)) {
case AHC_EISA:
{
@@ -212,6 +200,10 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry)
*/
ahc_softc_insert(ahc);
+ error = aic7770_map_int(ahc, irq);
+ if (error != 0)
+ return (error);
+
/*
* Enable the board's BUS drivers
*/
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c
index 0e4fa18..829f609 100644
--- a/sys/dev/aic7xxx/aic7xxx.c
+++ b/sys/dev/aic7xxx/aic7xxx.c
@@ -28,22 +28,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx.c#35 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.c#39 $
*
* $FreeBSD$
*/
-#ifdef __linux__
-#include "aic7xxx_linux.h"
-#include "aic7xxx_inline.h"
-#include "aicasm/aicasm_insformat.h"
-#endif
-
-#ifdef __FreeBSD__
#include <dev/aic7xxx/aic7xxx_freebsd.h>
#include <dev/aic7xxx/aic7xxx_inline.h>
#include <dev/aic7xxx/aicasm/aicasm_insformat.h>
-#endif
/****************************** Softc Data ************************************/
struct ahc_softc_tailq ahc_tailq = TAILQ_HEAD_INITIALIZER(ahc_tailq);
@@ -156,6 +148,7 @@ static void ahc_fetch_devinfo(struct ahc_softc *ahc,
static void ahc_scb_devinfo(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo,
struct scb *scb);
+static void ahc_assert_atn(struct ahc_softc *ahc);
static void ahc_setup_initiator_msgout(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo,
struct scb *scb);
@@ -190,9 +183,11 @@ static void ahc_handle_devreset(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo,
cam_status status, char *message,
int verbose_level);
+#if AHC_TARGET_MODE
static void ahc_setup_target_msgin(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo,
struct scb *scb);
+#endif
static bus_dmamap_callback_t ahc_dmamap_cb;
static void ahc_build_free_scb_list(struct ahc_softc *ahc);
@@ -211,7 +206,6 @@ static int ahc_abort_scbs(struct ahc_softc *ahc, int target,
char channel, int lun, u_int tag,
role_t role, uint32_t status);
static void ahc_reset_current_bus(struct ahc_softc *ahc);
-static void ahc_calc_residual(struct scb *scb);
#ifdef AHC_DUMP_SEQ
static void ahc_dumpseq(struct ahc_softc *ahc);
#endif
@@ -296,7 +290,7 @@ ahc_run_qoutfifo(struct ahc_softc *ahc)
/*
* Clear 32bits of QOUTFIFO at a time
- * so that we don't clobber an incomming
+ * so that we don't clobber an incoming
* byte DMA to the array on architectures
* that only support 32bit load and store
* operations.
@@ -319,10 +313,7 @@ ahc_run_qoutfifo(struct ahc_softc *ahc)
* Save off the residual
* if there is one.
*/
- if (ahc_check_residual(scb) != 0)
- ahc_calc_residual(scb);
- else
- ahc_set_residual(scb, 0);
+ ahc_update_residual(scb);
ahc_done(ahc, scb);
}
}
@@ -477,16 +468,13 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
devinfo.our_scsiid,
devinfo.target,
&tstate);
- tinfo = &targ_info->current;
+ tinfo = &targ_info->curr;
sg = scb->sg_list;
sc = (struct scsi_sense *)(&hscb->shared_data.cdb);
/*
* Save off the residual if there is one.
*/
- if (ahc_check_residual(scb))
- ahc_calc_residual(scb);
- else
- ahc_set_residual(scb, 0);
+ ahc_update_residual(scb);
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOWSENSE) {
ahc_print_path(ahc, scb);
@@ -600,7 +588,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
ahc->msgout_index = 0;
ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
ahc_outb(ahc, MSG_OUT, HOST_MSG);
- ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, LASTPHASE) | ATNO);
+ ahc_assert_atn(ahc);
break;
}
case SEND_REJECT:
@@ -741,17 +729,20 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
*/
if ((intstat & SCSIINT) == 0
&& (ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0) {
- u_int curphase;
- /*
- * The hardware will only let you ack bytes
- * if the expected phase in SCSISIGO matches
- * the current phase. Make sure this is
- * currently the case.
- */
- curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
- ahc_outb(ahc, LASTPHASE, curphase);
- ahc_outb(ahc, SCSISIGO, curphase);
+ if ((ahc->features & AHC_DT) == 0) {
+ u_int curphase;
+
+ /*
+ * The hardware will only let you ack bytes
+ * if the expected phase in SCSISIGO matches
+ * the current phase. Make sure this is
+ * currently the case.
+ */
+ curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
+ ahc_outb(ahc, LASTPHASE, curphase);
+ ahc_outb(ahc, SCSISIGO, curphase);
+ }
ahc_inb(ahc, SCSIDATL);
}
break;
@@ -1042,6 +1033,44 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
}
ahc_outb(ahc, CLRINT, CLRSCSIINT);
ahc_unpause(ahc);
+ } else if ((status & SELTO) != 0) {
+ u_int scbptr;
+
+ /* Stop the selection */
+ ahc_outb(ahc, SCSISEQ, 0);
+
+ /* No more pending messages */
+ ahc_clear_msg_state(ahc);
+
+ /* Clear interrupt state */
+ ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
+ ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR);
+
+ /*
+ * Although the driver does not care about the
+ * 'Selection in Progress' status bit, the busy
+ * LED does. SELINGO is only cleared by a sucessfull
+ * selection, so we must manually clear it to insure
+ * the LED turns off just incase no future successful
+ * selections occur (e.g. no devices on the bus).
+ */
+ ahc_outb(ahc, CLRSINT0, CLRSELINGO);
+
+ scbptr = ahc_inb(ahc, WAITING_SCBH);
+ ahc_outb(ahc, SCBPTR, scbptr);
+ scb_index = ahc_inb(ahc, SCB_TAG);
+
+ scb = ahc_lookup_scb(ahc, scb_index);
+ if (scb == NULL) {
+ printf("%s: ahc_intr - referenced scb not "
+ "valid during SELTO scb(%d, %d)\n",
+ ahc_name(ahc), scbptr, scb_index);
+ } else {
+ ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT);
+ ahc_freeze_devq(ahc, scb);
+ }
+ ahc_outb(ahc, CLRINT, CLRSCSIINT);
+ ahc_restart(ahc);
} else if ((status & BUSFREE) != 0
&& (ahc_inb(ahc, SIMODE1) & ENBUSFREE) != 0) {
u_int lastphase;
@@ -1147,7 +1176,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
devinfo.our_scsiid,
devinfo.target,
&tstate);
- tinfo->current.transport_version = 2;
+ tinfo->curr.transport_version = 2;
tinfo->goal.transport_version = 2;
tinfo->goal.ppr_options = 0;
ahc_qinfifo_requeue_tail(ahc, scb);
@@ -1209,43 +1238,6 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
ahc_clear_msg_state(ahc);
ahc_outb(ahc, CLRINT, CLRSCSIINT);
ahc_restart(ahc);
- } else if ((status & SELTO) != 0) {
- u_int scbptr;
-
- /* Stop the selection */
- ahc_outb(ahc, SCSISEQ, 0);
-
- /* No more pending messages */
- ahc_clear_msg_state(ahc);
-
- /* Clear interrupt state */
- ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR);
-
- /*
- * Although the driver does not care about the
- * 'Selection in Progress' status bit, the busy
- * LED does. SELINGO is only cleared by a sucessful
- * selection, so we must manually clear it to insure
- * the LED turns off just incase no future successful
- * selections occur (e.g. no devices on the bus).
- */
- ahc_outb(ahc, CLRSINT0, CLRSELINGO);
-
- scbptr = ahc_inb(ahc, WAITING_SCBH);
- ahc_outb(ahc, SCBPTR, scbptr);
- scb_index = ahc_inb(ahc, SCB_TAG);
-
- scb = ahc_lookup_scb(ahc, scb_index);
- if (scb == NULL) {
- printf("%s: ahc_intr - referenced scb not "
- "valid during SELTO scb(%d, %d)\n",
- ahc_name(ahc), scbptr, scb_index);
- } else {
- ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT);
- ahc_freeze_devq(ahc, scb);
- }
- ahc_outb(ahc, CLRINT, CLRSCSIINT);
- ahc_restart(ahc);
} else {
printf("%s: Missing case in ahc_handle_scsiint. status = %x\n",
ahc_name(ahc), status);
@@ -1418,8 +1410,8 @@ ahc_alloc_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel)
memset(tstate->enabled_luns, 0, sizeof(tstate->enabled_luns));
tstate->ultraenb = 0;
for (i = 0; i < 16; i++) {
- memset(&tstate->transinfo[i].current, 0,
- sizeof(tstate->transinfo[i].current));
+ memset(&tstate->transinfo[i].curr, 0,
+ sizeof(tstate->transinfo[i].curr));
memset(&tstate->transinfo[i].goal, 0,
sizeof(tstate->transinfo[i].goal));
}
@@ -1479,8 +1471,7 @@ ahc_devlimited_syncrate(struct ahc_softc *ahc,
/* Can't do DT on an SE bus */
*ppr_options &= ~MSG_EXT_PPR_DT_REQ;
}
- } else if ((ahc->features & AHC_ULTRA) != 0
- && (ahc->flags & AHC_ULTRA_DISABLED) == 0) {
+ } else if ((ahc->features & AHC_ULTRA) != 0) {
maxsync = AHC_SYNCRATE_ULTRA;
} else {
maxsync = AHC_SYNCRATE_FAST;
@@ -1522,6 +1513,11 @@ ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,
if ((ahc->features & AHC_DT) == 0)
*ppr_options &= ~MSG_EXT_PPR_DT_REQ;
+
+ /* Skip all DT only entries if DT is not available */
+ if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0
+ && maxsync < AHC_SYNCRATE_ULTRA2)
+ maxsync = AHC_SYNCRATE_ULTRA2;
for (syncrate = &ahc_syncrates[maxsync];
syncrate->rate != NULL;
@@ -1535,11 +1531,6 @@ ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,
&& (syncrate->sxfr_u2 == 0))
break;
- /* Skip any DT entries if DT is not available */
- if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0
- && (syncrate->sxfr_u2 & DT_SXFR) != 0)
- continue;
-
if (*period <= syncrate->period) {
/*
* When responding to a target that requests
@@ -1681,10 +1672,10 @@ ahc_update_neg_request(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
u_int auto_negotiate_orig;
auto_negotiate_orig = tstate->auto_negotiate;
- if (tinfo->current.period != tinfo->goal.period
- || tinfo->current.width != tinfo->goal.width
- || tinfo->current.offset != tinfo->goal.offset
- || tinfo->current.ppr_options != tinfo->goal.ppr_options
+ if (tinfo->curr.period != tinfo->goal.period
+ || tinfo->curr.width != tinfo->goal.width
+ || tinfo->curr.offset != tinfo->goal.offset
+ || tinfo->curr.ppr_options != tinfo->goal.ppr_options
|| (force
&& (tinfo->goal.period != 0
|| tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT
@@ -1697,7 +1688,7 @@ ahc_update_neg_request(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
}
/*
- * Update the user/goal/current tables of synchronous negotiation
+ * Update the user/goal/curr tables of synchronous negotiation
* parameters as well as, in the case of a current or active update,
* any data structures on the host controller. In the case of an
* active update, the specified target is currently talking to us on
@@ -1740,9 +1731,9 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
tinfo->goal.ppr_options = ppr_options;
}
- old_period = tinfo->current.period;
- old_offset = tinfo->current.offset;
- old_ppr = tinfo->current.ppr_options;
+ old_period = tinfo->curr.period;
+ old_offset = tinfo->curr.offset;
+ old_ppr = tinfo->curr.ppr_options;
if ((type & AHC_TRANS_CUR) != 0
&& (old_period != period
@@ -1795,12 +1786,12 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
}
tinfo->scsirate = scsirate;
- tinfo->current.period = period;
- tinfo->current.offset = offset;
- tinfo->current.ppr_options = ppr_options;
+ tinfo->curr.period = period;
+ tinfo->curr.offset = offset;
+ tinfo->curr.ppr_options = ppr_options;
ahc_send_async(ahc, devinfo->channel, devinfo->target,
- CAM_LUN_WILDCARD, AC_TRANSFER_NEG);
+ CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
if (bootverbose) {
if (offset != 0) {
printf("%s: target %d synchronous at %sMHz%s, "
@@ -1824,7 +1815,7 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
}
/*
- * Update the user/goal/current tables of wide negotiation
+ * Update the user/goal/curr tables of wide negotiation
* parameters as well as, in the case of a current or active update,
* any data structures on the host controller. In the case of an
* active update, the specified target is currently talking to us on
@@ -1852,7 +1843,7 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
if ((type & AHC_TRANS_GOAL) != 0)
tinfo->goal.width = width;
- oldwidth = tinfo->current.width;
+ oldwidth = tinfo->curr.width;
if ((type & AHC_TRANS_CUR) != 0 && oldwidth != width) {
u_int scsirate;
@@ -1867,10 +1858,10 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
if (active)
ahc_outb(ahc, SCSIRATE, scsirate);
- tinfo->current.width = width;
+ tinfo->curr.width = width;
ahc_send_async(ahc, devinfo->channel, devinfo->target,
- CAM_LUN_WILDCARD, AC_TRANSFER_NEG);
+ CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
if (bootverbose) {
printf("%s: target %d using %dbit transfers\n",
ahc_name(ahc), devinfo->target,
@@ -1888,27 +1879,12 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
* Update the current state of tagged queuing for a given target.
*/
void
-ahc_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, int enable)
+ahc_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
+ ahc_queue_alg alg)
{
- struct ahc_initiator_tinfo *tinfo;
- struct ahc_tmode_tstate *tstate;
- uint16_t orig_tagenable;
-
- tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
- devinfo->target, &tstate);
-
- orig_tagenable = tstate->tagenable;
- if (enable)
- tstate->tagenable |= devinfo->target_mask;
- else
- tstate->tagenable &= ~devinfo->target_mask;
-
- if (orig_tagenable != tstate->tagenable) {
- ahc_platform_set_tags(ahc, devinfo, enable);
- ahc_send_async(ahc, devinfo->channel, devinfo->target,
- devinfo->lun, AC_TRANSFER_NEG);
- }
-
+ ahc_platform_set_tags(ahc, devinfo, alg);
+ ahc_send_async(ahc, devinfo->channel, devinfo->target,
+ devinfo->lun, AC_TRANSFER_NEG, &alg);
}
/*
@@ -1945,7 +1921,7 @@ ahc_update_pending_scbs(struct ahc_softc *ahc)
if ((tstate->ultraenb & devinfo.target_mask) != 0)
pending_hscb->control |= ULTRAENB;
pending_hscb->scsirate = tinfo->scsirate;
- pending_hscb->scsioffset = tinfo->current.offset;
+ pending_hscb->scsioffset = tinfo->curr.offset;
if ((tstate->auto_negotiate & devinfo.target_mask) == 0
&& (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) {
pending_scb->flags &= ~SCB_AUTO_NEGOTIATE;
@@ -2073,6 +2049,17 @@ ahc_scb_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
/************************ Message Phase Processing ****************************/
+static void
+ahc_assert_atn(struct ahc_softc *ahc)
+{
+ u_int scsisigo;
+
+ scsisigo = ATNO;
+ if ((ahc->features & AHC_DT) == 0)
+ scsisigo |= ahc_inb(ahc, SCSISIGI);
+ ahc_outb(ahc, SCSISIGO, scsisigo);
+}
+
/*
* When an initiator transaction with the MK_MESSAGE flag either reconnects
* or enters the initial message out phase, we are interrupted. Fill our
@@ -2186,9 +2173,19 @@ ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
devinfo->target, &tstate);
- dowide = tinfo->current.width != tinfo->goal.width;
- dosync = tinfo->current.period != tinfo->goal.period;
- doppr = tinfo->current.ppr_options != tinfo->goal.ppr_options;
+ /*
+ * Filter our period based on the current connection.
+ * If we can't perform DT transfers on this segment (not in LVD
+ * mode for instance), then our decision to issue a PPR message
+ * may change.
+ */
+ period = tinfo->goal.period;
+ ppr_options = tinfo->goal.ppr_options;
+ rate = ahc_devlimited_syncrate(ahc, tinfo, &period,
+ &ppr_options, devinfo->role);
+ dowide = tinfo->curr.width != tinfo->goal.width;
+ dosync = tinfo->curr.period != period;
+ doppr = tinfo->curr.ppr_options != ppr_options;
if (!dowide && !dosync && !doppr) {
dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT;
@@ -2201,7 +2198,7 @@ ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
"but no negotiation needed\n");
}
- use_ppr = (tinfo->current.transport_version >= 3) || doppr;
+ use_ppr = (tinfo->curr.transport_version >= 3) || doppr;
/* Target initiated PPR is not allowed in the SCSI spec */
if (devinfo->role == ROLE_TARGET)
use_ppr = 0;
@@ -2216,16 +2213,10 @@ ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
*/
if (use_ppr || (dosync && !dowide)) {
- period = tinfo->goal.period;
- ppr_options = tinfo->goal.ppr_options;
- if (use_ppr == 0)
- ppr_options = 0;
- rate = ahc_devlimited_syncrate(ahc, tinfo, &period,
- &ppr_options, devinfo->role);
offset = tinfo->goal.offset;
ahc_validate_offset(ahc, tinfo, rate, &offset,
use_ppr ? tinfo->goal.width
- : tinfo->current.width,
+ : tinfo->curr.width,
devinfo->role);
if (use_ppr) {
ahc_construct_ppr(ahc, devinfo, period, offset,
@@ -2383,7 +2374,7 @@ reswitch:
* 0, and try again.
*/
ahc->msgout_index = 0;
- ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, SCSISIGO) | ATNO);
+ ahc_assert_atn(ahc);
}
lastbyte = ahc->msgout_index == (ahc->msgout_len - 1);
@@ -2438,8 +2429,7 @@ reswitch:
* message out phase.
*/
if (ahc->msgout_len != 0)
- ahc_outb(ahc, SCSISIGO,
- ahc_inb(ahc, SCSISIGO) | ATNO);
+ ahc_assert_atn(ahc);
} else
ahc->msgin_index++;
@@ -2604,7 +2594,7 @@ ahc_sent_msg(struct ahc_softc *ahc, ahc_msgtype type, u_int msgval, int full)
found = TRUE;
}
index = end_index;
- } else if (ahc->msgout_buf[index] >= MSG_SIMPLE_Q_TAG
+ } else if (ahc->msgout_buf[index] >= MSG_SIMPLE_TASK
&& ahc->msgout_buf[index] <= MSG_IGN_WIDE_RESIDUE) {
/* Skip tag type and tag id or residue param*/
@@ -2625,7 +2615,7 @@ ahc_sent_msg(struct ahc_softc *ahc, ahc_msgtype type, u_int msgval, int full)
}
/*
- * Wait for a complete incomming message, parse it, and respond accordingly.
+ * Wait for a complete incoming message, parse it, and respond accordingly.
*/
static int
ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
@@ -3062,7 +3052,7 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
devinfo->target, devinfo->lun);
}
tinfo->goal.ppr_options = 0;
- tinfo->current.transport_version = 2;
+ tinfo->curr.transport_version = 2;
tinfo->goal.transport_version = 2;
ahc->msgout_index = 0;
ahc->msgout_len = 0;
@@ -3104,24 +3094,39 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
"Using asynchronous transfers\n",
ahc_name(ahc), devinfo->channel,
devinfo->target, devinfo->lun);
- } else if ((scb->hscb->control & MSG_SIMPLE_Q_TAG) != 0) {
-
- printf("(%s:%c:%d:%d): refuses tagged commands. Performing "
- "non-tagged I/O\n", ahc_name(ahc),
- devinfo->channel, devinfo->target, devinfo->lun);
- ahc_set_tags(ahc, devinfo, FALSE);
+ } else if ((scb->hscb->control & MSG_SIMPLE_TASK) != 0) {
+ int tag_type;
+ int mask;
+
+ tag_type = (scb->hscb->control & MSG_SIMPLE_TASK);
+
+ if (tag_type == MSG_SIMPLE_TASK) {
+ printf("(%s:%c:%d:%d): refuses tagged commands. "
+ "Performing non-tagged I/O\n", ahc_name(ahc),
+ devinfo->channel, devinfo->target, devinfo->lun);
+ ahc_set_tags(ahc, devinfo, AHC_QUEUE_NONE);
+ mask = ~0x23;
+ } else {
+ printf("(%s:%c:%d:%d): refuses %s tagged commands. "
+ "Performing simple queue tagged I/O only\n",
+ ahc_name(ahc), devinfo->channel, devinfo->target,
+ devinfo->lun, tag_type == MSG_ORDERED_TASK
+ ? "ordered" : "head of queue");
+ ahc_set_tags(ahc, devinfo, AHC_QUEUE_BASIC);
+ mask = ~0x03;
+ }
/*
* Resend the identify for this CCB as the target
* may believe that the selection is invalid otherwise.
*/
ahc_outb(ahc, SCB_CONTROL,
- ahc_inb(ahc, SCB_CONTROL) & ~MSG_SIMPLE_Q_TAG);
- scb->hscb->control &= ~MSG_SIMPLE_Q_TAG;
+ ahc_inb(ahc, SCB_CONTROL) & mask);
+ scb->hscb->control &= mask;
ahc_set_transaction_tag(scb, /*enabled*/FALSE,
- /*type*/MSG_SIMPLE_Q_TAG);
+ /*type*/MSG_SIMPLE_TASK);
ahc_outb(ahc, MSG_OUT, MSG_IDENTIFYFLAG);
- ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, SCSISIGO) | ATNO);
+ ahc_assert_atn(ahc);
/*
* This transaction is now at the head of
@@ -3323,7 +3328,7 @@ ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
AHC_TRANS_CUR, /*paused*/TRUE);
ahc_send_async(ahc, devinfo->channel, devinfo->target,
- CAM_LUN_WILDCARD, AC_SENT_BDR);
+ CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
if (message != NULL
&& (verbose_level <= bootverbose))
@@ -4032,15 +4037,24 @@ ahc_controller_info(struct ahc_softc *ahc, char *buf)
ahc->our_id, ahc->our_id_b,
(ahc->flags & AHC_PRIMARY_CHANNEL) + 'A');
else {
+ const char *speed;
const char *type;
+ speed = "";
+ if ((ahc->features & AHC_ULTRA) != 0) {
+ speed = "Ultra ";
+ } else if ((ahc->features & AHC_DT) != 0) {
+ speed = "Ultra160 ";
+ } else if ((ahc->features & AHC_ULTRA2) != 0) {
+ speed = "Ultra2 ";
+ }
if ((ahc->features & AHC_WIDE) != 0) {
type = "Wide";
} else {
type = "Single";
}
- len = sprintf(buf, "%s Channel %c, SCSI Id=%d, ",
- type, ahc->channel, ahc->our_id);
+ len = sprintf(buf, "%s%s Channel %c, SCSI Id=%d, ",
+ speed, type, ahc->channel, ahc->our_id);
}
buf += len;
@@ -4292,8 +4306,6 @@ ahc_init(struct ahc_softc *ahc)
ultraenb = (ahc_inb(ahc, ULTRA_ENB + 1) << 8)
| ahc_inb(ahc, ULTRA_ENB);
}
- if ((ahc->flags & AHC_ULTRA_DISABLED) != 0)
- ultraenb = 0;
if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0)
max_targ = 7;
@@ -4393,12 +4405,10 @@ ahc_init(struct ahc_softc *ahc)
tinfo->user.transport_version = 2;
tinfo->goal.protocol_version = 2;
tinfo->goal.transport_version = 2;
- tinfo->current.protocol_version = 2;
- tinfo->current.transport_version = 2;
+ tinfo->curr.protocol_version = 2;
+ tinfo->curr.transport_version = 2;
}
tstate->ultraenb = ultraenb;
- tstate->discenable = discenable;
- tstate->tagenable = 0; /* Wait until the XPT says its okay */
}
ahc->user_discenable = discenable;
ahc->user_tagenable = tagenable;
@@ -5430,7 +5440,7 @@ ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel,
* Go through the pending CCB list and look for
* commands for this target that are still active.
* These are other tagged commands that were
- * disconnected when the reset occured.
+ * disconnected when the reset occurred.
*/
scbp_next = LIST_FIRST(&ahc->pending_scbs);
while (scbp_next != NULL) {
@@ -5581,7 +5591,7 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
#endif
/* Notify the XPT that a bus reset occurred */
ahc_send_async(ahc, devinfo.channel, CAM_TARGET_WILDCARD,
- CAM_LUN_WILDCARD, AC_BUS_RESET);
+ CAM_LUN_WILDCARD, AC_BUS_RESET, NULL);
/*
* Revert to async/narrow transfers until we renegotiate.
@@ -5617,7 +5627,7 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
/*
* Calculate the residual for a just completed SCB.
*/
-static void
+void
ahc_calc_residual(struct scb *scb)
{
struct hardware_scb *hscb;
@@ -6632,7 +6642,7 @@ ahc_run_tqinfifo(struct ahc_softc *ahc, int paused)
cmd->cmd_valid = 0;
/*
- * Lazily update our position in the target mode incomming
+ * Lazily update our position in the target mode incoming
* command queue as seen by the sequencer.
*/
if ((ahc->tqinfifonext & (HOST_TQINPOS - 1)) == 1) {
diff --git a/sys/dev/aic7xxx/aic7xxx.h b/sys/dev/aic7xxx/aic7xxx.h
index eada9ad..4eded92 100644
--- a/sys/dev/aic7xxx/aic7xxx.h
+++ b/sys/dev/aic7xxx/aic7xxx.h
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx.h#24 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.h#27 $
*
* $FreeBSD$
*/
@@ -209,9 +209,15 @@ typedef enum {
AHC_MULTIROLE = 0x40000, /* Space for two roles at a time */
AHC_REMOVABLE = 0x80000, /* Hot-Swap supported */
AHC_AIC7770_FE = AHC_FENONE,
- AHC_AIC7850_FE = AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE,
- AHC_AIC7855_FE = AHC_AIC7850_FE,
- AHC_AIC7860_FE = AHC_AIC7850_FE|AHC_ULTRA,
+ /*
+ * The real 7850 does not support Ultra modes, but there are
+ * several cards that use the generic 7850 PCI ID even though
+ * they are using an Ultra capable chip (7859/7860). We start
+ * out with the AHC_ULTRA feature set and then check the DEVSTATUS
+ * register to determine if the capability is really present.
+ */
+ AHC_AIC7850_FE = AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE|AHC_ULTRA,
+ AHC_AIC7860_FE = AHC_AIC7850_FE,
AHC_AIC7870_FE = AHC_TARGETMODE,
AHC_AIC7880_FE = AHC_AIC7870_FE|AHC_ULTRA,
/*
@@ -328,12 +334,6 @@ typedef enum {
*/
AHC_BIOS_ENABLED = 0x80000,
AHC_ALL_INTERRUPTS = 0x100000,
- AHC_ULTRA_DISABLED = 0x200000, /*
- * The precision resistor for
- * ultra transmission speeds is
- * missing, so we must limit
- * ourselves to fast SCSI.
- */
AHC_PAGESCBS = 0x400000, /* Enable SCB paging */
AHC_EDGE_INTERRUPT = 0x800000 /* Device uses edge triggered ints */
} ahc_flag;
@@ -660,7 +660,7 @@ struct ahc_transinfo {
* Per-initiator current, goal and user transfer negotiation information. */
struct ahc_initiator_tinfo {
uint8_t scsirate; /* Computed value for SCSIRATE reg */
- struct ahc_transinfo current;
+ struct ahc_transinfo curr;
struct ahc_transinfo goal;
struct ahc_transinfo user;
};
@@ -749,12 +749,19 @@ struct seeprom_config {
#define CFSUPREM 0x0001 /* support all removeable drives */
#define CFSUPREMB 0x0002 /* support removeable boot drives */
#define CFBIOSEN 0x0004 /* BIOS enabled */
-/* UNUSED 0x0008 */
+#define CFBIOS_BUSSCAN 0x0008 /* Have the BIOS Scan the Bus */
#define CFSM2DRV 0x0010 /* support more than two drives */
-#define CF284XEXTEND 0x0020 /* extended translation (284x cards) */
#define CFSTPWLEVEL 0x0010 /* Termination level control */
+#define CF284XEXTEND 0x0020 /* extended translation (284x cards) */
+#define CFCTRL_A 0x0020 /* BIOS displays Ctrl-A message */
+#define CFTERM_MENU 0x0040 /* BIOS displays termination menu */
#define CFEXTEND 0x0080 /* extended translation enabled */
#define CFSCAMEN 0x0100 /* SCAM enable */
+#define CFMSG_LEVEL 0x0600 /* BIOS Message Level */
+#define CFMSG_VERBOSE 0x0000
+#define CFMSG_SILENT 0x0200
+#define CFMSG_DIAG 0x0400
+#define CFBOOTCD 0x0800 /* Support Bootable CD-ROM */
/* UNUSED 0xff00 */
/*
@@ -769,7 +776,7 @@ struct seeprom_config {
#define CFWSTERM 0x0008 /* SCSI high byte termination */
#define CFSPARITY 0x0010 /* SCSI parity */
#define CF284XSTERM 0x0020 /* SCSI low byte term (284x cards) */
-#define CFMULTILUN 0x0020 /* SCSI low byte term (284x cards) */
+#define CFMULTILUN 0x0020
#define CFRESETB 0x0040 /* reset SCSI bus at boot */
#define CFCLUSTERENB 0x0080 /* Cluster Enable */
#define CFBOOTCHAN 0x0300 /* probe this channel first */
@@ -1135,6 +1142,7 @@ void ahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb);
int ahc_reset_channel(struct ahc_softc *ahc, char channel,
int initiate_reset);
void ahc_restart(struct ahc_softc *ahc);
+void ahc_calc_residual(struct scb *scb);
/*************************** Utility Functions ********************************/
struct ahc_phase_table_entry*
ahc_lookup_phase_entry(int phase);
@@ -1170,8 +1178,15 @@ void ahc_set_syncrate(struct ahc_softc *ahc,
u_int period, u_int offset,
u_int ppr_options,
u_int type, int paused);
+typedef enum {
+ AHC_QUEUE_NONE,
+ AHC_QUEUE_BASIC,
+ AHC_QUEUE_TAGGED
+} ahc_queue_alg;
+
void ahc_set_tags(struct ahc_softc *ahc,
- struct ahc_devinfo *devinfo, int enable);
+ struct ahc_devinfo *devinfo,
+ ahc_queue_alg alg);
/**************************** Target Mode *************************************/
#ifdef AHC_TARGET_MODE
diff --git a/sys/dev/aic7xxx/aic7xxx.reg b/sys/dev/aic7xxx/aic7xxx.reg
index c1f342f..91c6b8a 100644
--- a/sys/dev/aic7xxx/aic7xxx.reg
+++ b/sys/dev/aic7xxx/aic7xxx.reg
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx.reg#15 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.reg#17 $
*
* $FreeBSD$
*/
@@ -970,6 +970,7 @@ register SCSIPHASE {
bit MSG_OUT_PHASE 0x04
bit DATA_IN_PHASE 0x02
bit DATA_OUT_PHASE 0x01
+ mask DATA_PHASE_MASK 0x03
}
/*
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq
index bd4342a..c50a99c 100644
--- a/sys/dev/aic7xxx/aic7xxx.seq
+++ b/sys/dev/aic7xxx/aic7xxx.seq
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx.seq#24 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.seq#27 $
*
* $FreeBSD$
*/
@@ -153,7 +153,9 @@ selection:
* the kernel driver if it happens.
*/
mvi CLRSINT1,CLRBUSFREE;
- or SIMODE1, ENBUSFREE;
+ if ((ahc->features & AHC_DT) == 0) {
+ or SIMODE1, ENBUSFREE;
+ }
/*
* Guard against a bus free after (re)selection
@@ -706,6 +708,11 @@ disable_ccsgen_fetch_done:
test CCSGCTL, CCSGEN jnz .;
ret;
idle_loop:
+ /*
+ * Do we need any more segments for this transfer?
+ */
+ test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz return;
+
/* Did we just finish fetching segs? */
cmp CCSGCTL, CCSGEN|CCSGDONE je idle_sgfetch_complete;
@@ -713,11 +720,6 @@ idle_loop:
test CCSGCTL, CCSGEN jnz return;
/*
- * Do we need any more segments?
- */
- test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz return;
-
- /*
* Do we have any prefetch left???
*/
cmp CCSGADDR, SG_PREFETCH_CNT jne idle_sg_avail;
@@ -885,7 +887,11 @@ data_phase_loop:
and DMAPARAMS, DIRECTION;
mov DFCNTRL, DMAPARAMS;
or SXFRCTL1,BITBUCKET;
- test SSTAT1,PHASEMIS jz .;
+ if ((ahc->features & AHC_DT) == 0) {
+ test SSTAT1,PHASEMIS jz .;
+ } else {
+ test SCSIPHASE, DATA_PHASE_MASK jnz .;
+ }
and SXFRCTL1, ~BITBUCKET;
mvi DATA_OVERRUN call set_seqint;
jmp ITloop;
@@ -906,54 +912,48 @@ ultra2_dma_loop:
* completes or the target changes phase.
*/
test SG_CACHE_SHADOW, LAST_SEG_DONE jnz ultra2_dmafinish;
- if ((ahc->flags & AHC_TARGETROLE) != 0) {
- /*
- * As a target, we control the phases,
- * so ignore PHASEMIS.
- */
- test SSTAT0, TARGET jnz ultra2_dma_loop;
- }
- if ((ahc->flags & AHC_INITIATORROLE) != 0) {
- test SSTAT1,PHASEMIS jz ultra2_dma_loop;
+ if ((ahc->features & AHC_DT) == 0) {
+ if ((ahc->flags & AHC_TARGETROLE) != 0) {
+ /*
+ * As a target, we control the phases,
+ * so ignore PHASEMIS.
+ */
+ test SSTAT0, TARGET jnz ultra2_dma_loop;
+ }
+ if ((ahc->flags & AHC_INITIATORROLE) != 0) {
+ test SSTAT1,PHASEMIS jz ultra2_dma_loop;
+ }
+ } else {
+ test DFCNTRL, SCSIEN jnz ultra2_dma_loop;
}
ultra2_dmafinish:
- test DFCNTRL, DIRECTION jnz ultra2_dmafifoempty;
- if ((ahc->features & AHC_DT) == 0) {
- and DFCNTRL, ~SCSIEN;
- test DFCNTRL, SCSIEN jnz .;
- }
-ultra2_dmafifoflush:
+ /*
+ * The transfer has terminated either due to a phase
+ * change, and/or the completion of the last segment.
+ * We have two goals here. Do as much other work
+ * as possible while the data fifo drains on a read
+ * and respond as quickly as possible to the standard
+ * messages (save data pointers/disconnect and command
+ * complete) that usually follow a data phase.
+ */
if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
/*
- * On Rev A of the aic7890, the autoflush
- * features doesn't function correctly.
- * Perform an explicit manual flush. During
- * a manual flush, the FIFOEMP bit becomes
- * true every time the PCI FIFO empties
- * regardless of the state of the SCSI FIFO.
- * It can take up to 4 clock cycles for the
- * SCSI FIFO to get data into the PCI FIFO
- * and for FIFOEMP to de-assert. Here we
- * guard against this condition by making
- * sure the FIFOEMP bit stays on for 5 full
- * clock cycles.
+ * On chips with broken auto-flush, start
+ * the flushing process now. We'll poke
+ * the chip from time to time to keep the
+ * flush process going as we complete the
+ * data phase.
*/
or DFCNTRL, FIFOFLUSH;
- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
}
- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
-ultra2_dmafifoempty:
- /* Don't clobber an inprogress host data transfer */
- test DFSTATUS, MREQPEND jnz ultra2_dmafifoempty;
-ultra2_dmahalt:
- and DFCNTRL, ~(SCSIEN|HDMAEN);
- test DFCNTRL, SCSIEN|HDMAEN jnz .;
-
/*
+ * We assume that, even though data may still be
+ * transferring to the host, that the SCSI side of
+ * the DMA engine is now in a static state. This
+ * allows us to update our notion of where we are
+ * in this transfer.
+ *
* If, by chance, we stopped before being able
* to fetch additional segments for this transfer,
* yet the last S/G was completely exhausted,
@@ -964,14 +964,14 @@ ultra2_dmahalt:
* If we happened to stop on the last segment, then
* our residual information is still correct from
* the idle loop and there is no need to perform
- * any fixups. Just jump to data_phase_finish.
+ * any fixups.
*/
ultra2_ensure_sg:
test SG_CACHE_SHADOW, LAST_SEG jz ultra2_shvalid;
/* Record if we've consumed all S/G entries */
- test SG_CACHE_SHADOW, LAST_SEG_DONE jz data_phase_finish;
+ test SSTAT2, SHVALID jnz residuals_correct;
or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;
- jmp data_phase_finish;
+ jmp residuals_correct;
ultra2_shvalid:
test SSTAT2, SHVALID jnz sgptr_fixup;
@@ -1001,6 +1001,62 @@ sgptr_fixup_done:
test SG_CACHE_SHADOW, ODD_SEG jz . + 2;
or DATA_COUNT_ODD, 0x1;
clr SCB_RESIDUAL_DATACNT[3]; /* We are not the last seg */
+residuals_correct:
+ /*
+ * Go ahead and shut down the DMA engine now.
+ * In the future, we'll want to handle end of
+ * transfer messages prior to doing this, but this
+ * requires similar restructuring for pre-ULTRA2
+ * controllers.
+ */
+ test DMAPARAMS, DIRECTION jnz ultra2_fifoempty;
+ultra2_fifoflush:
+ if ((ahc->features & AHC_DT) == 0) {
+ if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
+ /*
+ * On Rev A of the aic7890, the autoflush
+ * feature doesn't function correctly.
+ * Perform an explicit manual flush. During
+ * a manual flush, the FIFOEMP bit becomes
+ * true every time the PCI FIFO empties
+ * regardless of the state of the SCSI FIFO.
+ * It can take up to 4 clock cycles for the
+ * SCSI FIFO to get data into the PCI FIFO
+ * and for FIFOEMP to de-assert. Here we
+ * guard against this condition by making
+ * sure the FIFOEMP bit stays on for 5 full
+ * clock cycles.
+ */
+ or DFCNTRL, FIFOFLUSH;
+ test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+ test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+ test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+ test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+ }
+ test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+ } else {
+ /*
+ * We enable the auto-ack feature on DT capable
+ * controllers. This means that the controller may
+ * have already transferred some overrun bytes into
+ * the data FIFO and acked them on the bus. The only
+ * way to detect this situation is to wait for
+ * LAST_SEG_DONE to come true on a completed transfer
+ * and then test to see if the data FIFO is non-empty.
+ */
+ test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 4;
+ test SG_CACHE_SHADOW, LAST_SEG_DONE jz .;
+ test DFSTATUS, FIFOEMP jnz ultra2_fifoempty;
+ /* Overrun */
+ jmp data_phase_loop;
+ test DFSTATUS, FIFOEMP jz .;
+ }
+ultra2_fifoempty:
+ /* Don't clobber an inprogress host data transfer */
+ test DFSTATUS, MREQPEND jnz ultra2_fifoempty;
+ultra2_dmahalt:
+ and DFCNTRL, ~(SCSIEN|HDMAEN);
+ test DFCNTRL, SCSIEN|HDMAEN jnz .;
} else {
/* If we are the last SG block, tell the hardware. */
if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
@@ -1159,7 +1215,11 @@ data_phase_finish:
}
if ((ahc->flags & AHC_INITIATORROLE) != 0) {
test SSTAT1, REQINIT jz .;
- test SSTAT1,PHASEMIS jz data_phase_loop;
+ if ((ahc->features & AHC_DT) == 0) {
+ test SSTAT1,PHASEMIS jz data_phase_loop;
+ } else {
+ test SCSIPHASE, DATA_PHASE_MASK jnz data_phase_loop;
+ }
}
data_phase_done:
@@ -1263,7 +1323,7 @@ p_command_from_host:
jmp p_command_loop;
p_command_embedded:
/*
- * The data fifo seems to require 4 byte alligned
+ * The data fifo seems to require 4 byte aligned
* transfers from the sequencer. Force this to
* be the case by clearing HADDR[0] even though
* we aren't going to touch host memeory.
@@ -1299,13 +1359,17 @@ p_command_embedded:
or DFCNTRL, FIFOFLUSH;
}
p_command_loop:
- test SSTAT0, SDONE jnz . + 2;
- test SSTAT1, PHASEMIS jz p_command_loop;
- /*
- * Wait for our ACK to go-away on it's own
- * instead of being killed by SCSIEN getting cleared.
- */
- test SCSISIGI, ACKI jnz .;
+ if ((ahc->features & AHC_DT) == 0) {
+ test SSTAT0, SDONE jnz . + 2;
+ test SSTAT1, PHASEMIS jz p_command_loop;
+ /*
+ * Wait for our ACK to go-away on it's own
+ * instead of being killed by SCSIEN getting cleared.
+ */
+ test SCSISIGI, ACKI jnz .;
+ } else {
+ test DFCNTRL, SCSIEN jnz p_command_loop;
+ }
and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz .;
if ((ahc->features & AHC_ULTRA2) != 0) {
@@ -1349,7 +1413,12 @@ p_status:
* reason.
*/
p_mesgout_retry:
- or SCSISIGO,ATNO,LASTPHASE;/* turn on ATN for the retry */
+ /* Turn on ATN for the retry */
+ if ((ahc->features & AHC_DT) == 0) {
+ or SCSISIGO, ATNO, LASTPHASE;
+ } else {
+ mvi SCSISIGO, ATNO;
+ }
p_mesgout:
mov SINDEX, MSG_OUT;
cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;
@@ -1546,10 +1615,17 @@ mesgin_disconnect:
* only if we've actually been into a data phase to change them. This
* protects against bogus data in scratch ram and the residual counts
* since they are only initialized when we go into data_in or data_out.
+ * Ack the message as soon as possible. For chips without S/G pipelining,
+ * we can only ack the message after SHADDR has been saved. On these
+ * chips, SHADDR increments with every bus transaction, even PIO.
*/
mesgin_sdptrs:
- test SEQ_FLAGS, DPHASE jz mesgin_done;
-
+ if ((ahc->features & AHC_ULTRA2) != 0) {
+ mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
+ test SEQ_FLAGS, DPHASE jz ITloop;
+ } else {
+ test SEQ_FLAGS, DPHASE jz mesgin_done;
+ }
/*
* The SCB_SGPTR becomes the next one we'll download,
* and the SCB_DATAPTR becomes the current SHADDR.
@@ -1558,13 +1634,17 @@ mesgin_sdptrs:
*/
if ((ahc->features & AHC_CMD_CHAN) != 0) {
bmov SCB_DATAPTR, SHADDR, 4;
+ if ((ahc->features & AHC_ULTRA2) == 0) {
+ mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
+ }
bmov SCB_DATACNT, SCB_RESIDUAL_DATACNT, 8;
} else {
mvi DINDEX, SCB_DATAPTR;
mvi SHADDR call bcopy_4;
+ mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
mvi SCB_RESIDUAL_DATACNT call bcopy_8;
}
- jmp mesgin_done;
+ jmp ITloop;
/*
* Restore pointers message? Data pointers are recopied from the
@@ -1742,7 +1822,11 @@ not_found:
jmp mesgin_done;
mk_mesg:
- or SCSISIGO,ATNO,LASTPHASE;/* turn on ATNO */
+ if ((ahc->features & AHC_DT) == 0) {
+ or SCSISIGO, ATNO, LASTPHASE;
+ } else {
+ mvi SCSISIGO, ATNO;
+ }
mov MSG_OUT,SINDEX ret;
/*
@@ -1789,7 +1873,7 @@ if ((ahc->flags & AHC_TARGETROLE) != 0) {
* from out to in, wait an additional data release delay before continuing.
*/
change_phase:
- /* Wait for preceding I/O session to complete. */
+ /* Wait for preceeding I/O session to complete. */
test SCSISIGI, ACKI jnz .;
/* Change the phase */
@@ -1915,7 +1999,9 @@ phase_lock:
test SSTAT1, REQINIT jz phase_lock;
test SSTAT1, SCSIPERR jnz phase_lock_perr;
phase_lock_latch_phase:
- and SCSISIGO, PHASE_MASK, SCSISIGI;
+ if ((ahc->features & AHC_DT) == 0) {
+ and SCSISIGO, PHASE_MASK, SCSISIGI;
+ }
and LASTPHASE, PHASE_MASK, SCSISIGI ret;
if ((ahc->features & AHC_CMD_CHAN) == 0) {
diff --git a/sys/dev/aic7xxx/aic7xxx_93cx6.c b/sys/dev/aic7xxx/aic7xxx_93cx6.c
index 684c608..e3eaedd 100644
--- a/sys/dev/aic7xxx/aic7xxx_93cx6.c
+++ b/sys/dev/aic7xxx/aic7xxx_93cx6.c
@@ -67,17 +67,9 @@
*
*/
-#ifdef __linux__
-#include "aic7xxx_linux.h"
-#include "aic7xxx_inline.h"
-#include "aic7xxx_93cx6.h"
-#endif
-
-#ifdef __FreeBSD__
#include <dev/aic7xxx/aic7xxx_freebsd.h>
#include <dev/aic7xxx/aic7xxx_inline.h>
#include <dev/aic7xxx/aic7xxx_93cx6.h>
-#endif
/*
* Right now, we only have to read the SEEPROM. But we make it easier to
diff --git a/sys/dev/aic7xxx/aic7xxx_freebsd.c b/sys/dev/aic7xxx/aic7xxx_freebsd.c
index f61c8da..e06a1d6 100644
--- a/sys/dev/aic7xxx/aic7xxx_freebsd.c
+++ b/sys/dev/aic7xxx/aic7xxx_freebsd.c
@@ -49,6 +49,7 @@ static int ahc_debug = AHC_DEBUG;
#if UNUSED
static void ahc_dump_targcmd(struct target_cmd *cmd);
#endif
+static int ahc_modevent(module_t mod, int type, void *data);
static void ahc_action(struct cam_sim *sim, union ccb *ccb);
static void ahc_get_tran_settings(struct ahc_softc *ahc,
int our_id, char channel,
@@ -572,9 +573,9 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
update_type |= AHC_TRANS_GOAL;
discenable = &tstate->discenable;
tagenable = &tstate->tagenable;
- tinfo->current.protocol_version =
+ tinfo->curr.protocol_version =
cts->protocol_version;
- tinfo->current.transport_version =
+ tinfo->curr.transport_version =
cts->transport_version;
tinfo->goal.protocol_version =
cts->protocol_version;
@@ -777,7 +778,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
&& tinfo->user.transport_version >= 3) {
tinfo->goal.transport_version =
tinfo->user.transport_version;
- tinfo->current.transport_version =
+ tinfo->curr.transport_version =
tinfo->user.transport_version;
}
@@ -932,7 +933,7 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
devinfo.target, &tstate);
if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
- tinfo = &targ_info->current;
+ tinfo = &targ_info->curr;
else
tinfo = &targ_info->user;
@@ -990,7 +991,7 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
devinfo.target, &tstate);
if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0)
- tinfo = &targ_info->current;
+ tinfo = &targ_info->curr;
else
tinfo = &targ_info->user;
@@ -1206,7 +1207,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
mask = SCB_GET_TARGET_MASK(ahc, scb);
scb->hscb->scsirate = tinfo->scsirate;
- scb->hscb->scsioffset = tinfo->current.offset;
+ scb->hscb->scsioffset = tinfo->curr.offset;
if ((tstate->ultraenb & mask) != 0)
scb->hscb->control |= ULTRAENB;
@@ -1767,7 +1768,7 @@ ahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
void
ahc_send_async(struct ahc_softc *ahc, char channel, u_int target,
- u_int lun, ac_code code)
+ u_int lun, ac_code code, void *opt_arg)
{
struct ccb_trans_settings cts;
struct cam_path *path;
@@ -1782,8 +1783,12 @@ ahc_send_async(struct ahc_softc *ahc, char channel, u_int target,
switch (code) {
case AC_TRANSFER_NEG:
+ {
#ifdef AHC_NEW_TRAN_SETTINGS
+ struct ccb_trans_settings_scsi *scsi;
+
cts.type = CTS_TYPE_CURRENT_SETTINGS;
+ scsi = &cts.proto_specific.scsi;
#else
cts.flags = CCB_TRANS_CURRENT_SETTINGS;
#endif
@@ -1794,7 +1799,25 @@ ahc_send_async(struct ahc_softc *ahc, char channel, u_int target,
: ahc->our_id_b,
channel, &cts);
arg = &cts;
+#ifdef AHC_NEW_TRAN_SETTINGS
+ scsi->valid &= ~CTS_SCSI_VALID_TQ;
+ scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
+#else
+ cts.valid &= ~CCB_TRANS_TQ_VALID;
+ cts.flags &= ~CCB_TRANS_TAG_ENB;
+#endif
+ if (opt_arg == NULL)
+ break;
+ if (*((ahc_queue_alg *)opt_arg) == AHC_QUEUE_TAGGED)
+#ifdef AHC_NEW_TRAN_SETTINGS
+ scsi->flags |= ~CTS_SCSI_FLAGS_TAG_ENB;
+ scsi->valid |= CTS_SCSI_VALID_TQ;
+#else
+ cts.flags |= CCB_TRANS_TAG_ENB;
+ cts.valid |= CCB_TRANS_TQ_VALID;
+#endif
break;
+ }
case AC_SENT_BDR:
case AC_BUS_RESET:
break;
@@ -1906,3 +1929,20 @@ ahc_dump_targcmd(struct target_cmd *cmd)
}
}
#endif
+
+static int
+ahc_modevent(module_t mod, int type, void *data)
+{
+ /* XXX Deal with busy status on unload. */
+ return 0;
+}
+
+static moduledata_t ahc_mod = {
+ "ahc",
+ ahc_modevent,
+ NULL
+};
+
+DECLARE_MODULE(ahc, ahc_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
+MODULE_DEPEND(ahc, cam, 1, 1, 1);
+MODULE_VERSION(ahc, 1);
diff --git a/sys/dev/aic7xxx/aic7xxx_freebsd.h b/sys/dev/aic7xxx/aic7xxx_freebsd.h
index 9e5c8f1..b2bf917 100644
--- a/sys/dev/aic7xxx/aic7xxx_freebsd.h
+++ b/sys/dev/aic7xxx/aic7xxx_freebsd.h
@@ -41,7 +41,9 @@
#define AHC_NEW_TRAN_SETTINGS
#endif /* CAM_NEW_TRAN_CODE */
#include <opt_aic7xxx.h> /* for config options */
-#include <pci.h> /* for NPCI */
+#ifndef NPCI
+#include <pci.h>
+#endif
#include <sys/param.h>
#include <sys/systm.h>
@@ -96,6 +98,9 @@
(SCB_GET_CHANNEL(ahc, scb) == 'A' ? (ahc)->platform_data->sim \
: (ahc)->platform_data->sim_b)
+#ifndef offsetof
+#define offsetof(type, member) ((size_t)(&((type *)0)->member))
+#endif
/************************* Forward Declarations *******************************/
typedef device_t ahc_dev_softc_t;
typedef union ccb *ahc_io_ctx_t;
@@ -144,10 +149,10 @@ typedef union ccb *ahc_io_ctx_t;
* transfer is as fragmented as possible and unaligned, this turns out to
* be the number of paged sized transfers in MAXPHYS plus an extra element
* to handle any unaligned residual. The sequencer fetches SG elements
- * in 128 byte chucks, so make the number per-transaction a nice multiple
- * of 16 (8 byte S/G elements).
+ * in cacheline sized chucks, so make the number per-transaction an even
+ * multiple of 16 which should align us on even the largest of cacheline
+ * boundaries.
*/
-/* XXX Worth the space??? */
#define AHC_NSEG (roundup(btoc(MAXPHYS) + 1, 16))
/* This driver supports target mode */
@@ -505,5 +510,5 @@ ahc_platform_flushwork(struct ahc_softc *ahc)
timeout_t ahc_timeout;
void ahc_done(struct ahc_softc *ahc, struct scb *scb);
void ahc_send_async(struct ahc_softc *, char /*channel*/,
- u_int /*target*/, u_int /*lun*/, ac_code);
+ u_int /*target*/, u_int /*lun*/, ac_code, void *arg);
#endif /* _AIC7XXX_FREEBSD_H_ */
diff --git a/sys/dev/aic7xxx/aic7xxx_inline.h b/sys/dev/aic7xxx/aic7xxx_inline.h
index 446b104..ddf1bb5 100644
--- a/sys/dev/aic7xxx/aic7xxx_inline.h
+++ b/sys/dev/aic7xxx/aic7xxx_inline.h
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx_inline.h#19 $
+ * $Id: //depot/src/aic7xxx/aic7xxx_inline.h#21 $
*
* $FreeBSD$
*/
@@ -188,7 +188,7 @@ ahc_name(struct ahc_softc *ahc)
/*********************** Miscelaneous Support Functions ***********************/
-static __inline int ahc_check_residual(struct scb *scb);
+static __inline void ahc_update_residual(struct scb *scb);
static __inline struct ahc_initiator_tinfo *
ahc_fetch_transinfo(struct ahc_softc *ahc,
char channel, u_int our_id,
@@ -211,15 +211,16 @@ static __inline uint32_t
* Determine whether the sequencer reported a residual
* for this SCB/transaction.
*/
-static __inline int
-ahc_check_residual(struct scb *scb)
+static __inline void
+ahc_update_residual(struct scb *scb)
{
- struct status_pkt *sp;
+ uint32_t sgptr;
- sp = &scb->hscb->shared_data.status;
- if ((scb->hscb->sgptr & SG_RESID_VALID) != 0)
- return (1);
- return (0);
+ sgptr = ahc_le32toh(scb->hscb->sgptr);
+ if ((sgptr & SG_RESID_VALID) != 0)
+ ahc_calc_residual(scb);
+ else
+ ahc_set_residual(scb, 0);
}
/*
diff --git a/sys/dev/aic7xxx/aic7xxx_osm.c b/sys/dev/aic7xxx/aic7xxx_osm.c
index f61c8da..e06a1d6 100644
--- a/sys/dev/aic7xxx/aic7xxx_osm.c
+++ b/sys/dev/aic7xxx/aic7xxx_osm.c
@@ -49,6 +49,7 @@ static int ahc_debug = AHC_DEBUG;
#if UNUSED
static void ahc_dump_targcmd(struct target_cmd *cmd);
#endif
+static int ahc_modevent(module_t mod, int type, void *data);
static void ahc_action(struct cam_sim *sim, union ccb *ccb);
static void ahc_get_tran_settings(struct ahc_softc *ahc,
int our_id, char channel,
@@ -572,9 +573,9 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
update_type |= AHC_TRANS_GOAL;
discenable = &tstate->discenable;
tagenable = &tstate->tagenable;
- tinfo->current.protocol_version =
+ tinfo->curr.protocol_version =
cts->protocol_version;
- tinfo->current.transport_version =
+ tinfo->curr.transport_version =
cts->transport_version;
tinfo->goal.protocol_version =
cts->protocol_version;
@@ -777,7 +778,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
&& tinfo->user.transport_version >= 3) {
tinfo->goal.transport_version =
tinfo->user.transport_version;
- tinfo->current.transport_version =
+ tinfo->curr.transport_version =
tinfo->user.transport_version;
}
@@ -932,7 +933,7 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
devinfo.target, &tstate);
if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
- tinfo = &targ_info->current;
+ tinfo = &targ_info->curr;
else
tinfo = &targ_info->user;
@@ -990,7 +991,7 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
devinfo.target, &tstate);
if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0)
- tinfo = &targ_info->current;
+ tinfo = &targ_info->curr;
else
tinfo = &targ_info->user;
@@ -1206,7 +1207,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
mask = SCB_GET_TARGET_MASK(ahc, scb);
scb->hscb->scsirate = tinfo->scsirate;
- scb->hscb->scsioffset = tinfo->current.offset;
+ scb->hscb->scsioffset = tinfo->curr.offset;
if ((tstate->ultraenb & mask) != 0)
scb->hscb->control |= ULTRAENB;
@@ -1767,7 +1768,7 @@ ahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
void
ahc_send_async(struct ahc_softc *ahc, char channel, u_int target,
- u_int lun, ac_code code)
+ u_int lun, ac_code code, void *opt_arg)
{
struct ccb_trans_settings cts;
struct cam_path *path;
@@ -1782,8 +1783,12 @@ ahc_send_async(struct ahc_softc *ahc, char channel, u_int target,
switch (code) {
case AC_TRANSFER_NEG:
+ {
#ifdef AHC_NEW_TRAN_SETTINGS
+ struct ccb_trans_settings_scsi *scsi;
+
cts.type = CTS_TYPE_CURRENT_SETTINGS;
+ scsi = &cts.proto_specific.scsi;
#else
cts.flags = CCB_TRANS_CURRENT_SETTINGS;
#endif
@@ -1794,7 +1799,25 @@ ahc_send_async(struct ahc_softc *ahc, char channel, u_int target,
: ahc->our_id_b,
channel, &cts);
arg = &cts;
+#ifdef AHC_NEW_TRAN_SETTINGS
+ scsi->valid &= ~CTS_SCSI_VALID_TQ;
+ scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
+#else
+ cts.valid &= ~CCB_TRANS_TQ_VALID;
+ cts.flags &= ~CCB_TRANS_TAG_ENB;
+#endif
+ if (opt_arg == NULL)
+ break;
+ if (*((ahc_queue_alg *)opt_arg) == AHC_QUEUE_TAGGED)
+#ifdef AHC_NEW_TRAN_SETTINGS
+ scsi->flags |= ~CTS_SCSI_FLAGS_TAG_ENB;
+ scsi->valid |= CTS_SCSI_VALID_TQ;
+#else
+ cts.flags |= CCB_TRANS_TAG_ENB;
+ cts.valid |= CCB_TRANS_TQ_VALID;
+#endif
break;
+ }
case AC_SENT_BDR:
case AC_BUS_RESET:
break;
@@ -1906,3 +1929,20 @@ ahc_dump_targcmd(struct target_cmd *cmd)
}
}
#endif
+
+static int
+ahc_modevent(module_t mod, int type, void *data)
+{
+ /* XXX Deal with busy status on unload. */
+ return 0;
+}
+
+static moduledata_t ahc_mod = {
+ "ahc",
+ ahc_modevent,
+ NULL
+};
+
+DECLARE_MODULE(ahc, ahc_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
+MODULE_DEPEND(ahc, cam, 1, 1, 1);
+MODULE_VERSION(ahc, 1);
diff --git a/sys/dev/aic7xxx/aic7xxx_osm.h b/sys/dev/aic7xxx/aic7xxx_osm.h
index 9e5c8f1..b2bf917 100644
--- a/sys/dev/aic7xxx/aic7xxx_osm.h
+++ b/sys/dev/aic7xxx/aic7xxx_osm.h
@@ -41,7 +41,9 @@
#define AHC_NEW_TRAN_SETTINGS
#endif /* CAM_NEW_TRAN_CODE */
#include <opt_aic7xxx.h> /* for config options */
-#include <pci.h> /* for NPCI */
+#ifndef NPCI
+#include <pci.h>
+#endif
#include <sys/param.h>
#include <sys/systm.h>
@@ -96,6 +98,9 @@
(SCB_GET_CHANNEL(ahc, scb) == 'A' ? (ahc)->platform_data->sim \
: (ahc)->platform_data->sim_b)
+#ifndef offsetof
+#define offsetof(type, member) ((size_t)(&((type *)0)->member))
+#endif
/************************* Forward Declarations *******************************/
typedef device_t ahc_dev_softc_t;
typedef union ccb *ahc_io_ctx_t;
@@ -144,10 +149,10 @@ typedef union ccb *ahc_io_ctx_t;
* transfer is as fragmented as possible and unaligned, this turns out to
* be the number of paged sized transfers in MAXPHYS plus an extra element
* to handle any unaligned residual. The sequencer fetches SG elements
- * in 128 byte chucks, so make the number per-transaction a nice multiple
- * of 16 (8 byte S/G elements).
+ * in cacheline sized chucks, so make the number per-transaction an even
+ * multiple of 16 which should align us on even the largest of cacheline
+ * boundaries.
*/
-/* XXX Worth the space??? */
#define AHC_NSEG (roundup(btoc(MAXPHYS) + 1, 16))
/* This driver supports target mode */
@@ -505,5 +510,5 @@ ahc_platform_flushwork(struct ahc_softc *ahc)
timeout_t ahc_timeout;
void ahc_done(struct ahc_softc *ahc, struct scb *scb);
void ahc_send_async(struct ahc_softc *, char /*channel*/,
- u_int /*target*/, u_int /*lun*/, ac_code);
+ u_int /*target*/, u_int /*lun*/, ac_code, void *arg);
#endif /* _AIC7XXX_FREEBSD_H_ */
diff --git a/sys/dev/aic7xxx/aic7xxx_pci.c b/sys/dev/aic7xxx/aic7xxx_pci.c
index 5102c5b..0a7b4f3 100644
--- a/sys/dev/aic7xxx/aic7xxx_pci.c
+++ b/sys/dev/aic7xxx/aic7xxx_pci.c
@@ -30,22 +30,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx_pci.c#21 $
+ * $Id: //depot/src/aic7xxx/aic7xxx_pci.c#24 $
*
* $FreeBSD$
*/
-#ifdef __linux__
-#include "aic7xxx_linux.h"
-#include "aic7xxx_inline.h"
-#include "aic7xxx_93cx6.h"
-#endif
-
-#ifdef __FreeBSD__
#include <dev/aic7xxx/aic7xxx_freebsd.h>
#include <dev/aic7xxx/aic7xxx_inline.h>
#include <dev/aic7xxx/aic7xxx_93cx6.h>
-#endif
#define AHC_PCI_IOADDR PCIR_MAPS /* I/O Address */
#define AHC_PCI_MEMADDR (PCIR_MAPS + 4) /* Mem I/O Address */
@@ -271,7 +263,7 @@ struct ahc_pci_identity ahc_pci_ident_table [] =
{
ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK,
ID_DEV_VENDOR_MASK,
- "Adaptec 2930C SCSI adapter (VAR)",
+ "Adaptec 2930C Ultra SCSI adapter (VAR)",
ahc_aic7860_setup
},
/* aic7870 based controllers */
@@ -460,7 +452,7 @@ struct ahc_pci_identity ahc_pci_ident_table [] =
{
ID_AIC7892_ARO,
ID_ALL_MASK,
- "Adaptec aic7892 Ultra2 SCSI adapter (ARO)",
+ "Adaptec aic7892 Ultra160 SCSI adapter (ARO)",
ahc_aic7892_setup
},
/* aic7895 based controllers */
@@ -554,13 +546,13 @@ struct ahc_pci_identity ahc_pci_ident_table [] =
{
ID_AIC7859 & ID_DEV_VENDOR_MASK,
ID_DEV_VENDOR_MASK,
- "Adaptec aic7859 Ultra SCSI adapter",
+ "Adaptec aic7859 SCSI adapter",
ahc_aic7860_setup
},
{
ID_AIC7860 & ID_DEV_VENDOR_MASK,
ID_DEV_VENDOR_MASK,
- "Adaptec aic7860 SCSI adapter",
+ "Adaptec aic7860 Ultra SCSI adapter",
ahc_aic7860_setup
},
{
@@ -786,7 +778,8 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
/* Perform ALT-Mode Setup */
sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
- ahc_outb(ahc, OPTIONMODE, OPTIONMODE_DEFAULTS);
+ ahc_outb(ahc, OPTIONMODE,
+ OPTIONMODE_DEFAULTS|AUTOACKEN|BUSFREEREV|EXPPHASEDIS);
ahc_outb(ahc, SFUNCT, sfunct);
/* Normal mode setup */
@@ -794,10 +787,6 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
|TARGCRCENDEN);
}
- error = ahc_pci_map_int(ahc);
- if (error != 0)
- return (error);
-
dscommand0 = ahc_inb(ahc, DSCOMMAND0);
dscommand0 |= MPARCKEN|CACHETHEN;
if ((ahc->features & AHC_ULTRA2) != 0) {
@@ -826,6 +815,19 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
/*bytes*/1) & CACHESIZE;
ahc->pci_cachesize *= 4;
+ /*
+ * We cannot perform ULTRA speeds without the presense
+ * of the external precision resistor.
+ */
+ if ((ahc->features & AHC_ULTRA) != 0) {
+ uint32_t devconfig;
+
+ devconfig = ahc_pci_read_config(ahc->dev_softc,
+ DEVCONFIG, /*bytes*/4);
+ if ((devconfig & REXTVALID) == 0)
+ ahc->features &= ~AHC_ULTRA;
+ }
+
/* See if we have a SEEPROM and perform auto-term */
check_extport(ahc, &sxfrctl1);
@@ -880,20 +882,6 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
if ((sxfrctl1 & STPWEN) != 0)
ahc->flags |= AHC_TERM_ENB_A;
- /*
- * We cannot perform ULTRA speeds without
- * the presense of the external precision
- * resistor.
- */
- if ((ahc->features & AHC_ULTRA) != 0) {
- uint32_t devconfig;
-
- devconfig = ahc_pci_read_config(ahc->dev_softc,
- DEVCONFIG, /*bytes*/4);
- if ((devconfig & REXTVALID) == 0)
- ahc->flags |= AHC_ULTRA_DISABLED;
- }
-
/* Core initialization */
error = ahc_init(ahc);
if (error != 0)
@@ -907,6 +895,10 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
/*
* Allow interrupts now that we are completely setup.
*/
+ error = ahc_pci_map_int(ahc);
+ if (error != 0)
+ return (error);
+
ahc_intr_enable(ahc, TRUE);
return (0);
OpenPOWER on IntegriCloud