summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>2001-02-10 18:04:27 +0000
committergibbs <gibbs@FreeBSD.org>2001-02-10 18:04:27 +0000
commitd06bf490d31b8fb1079c44b4e9594bcf1960014a (patch)
tree80ce7dafd202d94010c0ebfcd5675b29d340120a /sys/dev
parent078570308c3e8c99cd0cef923b983e532fe2484b (diff)
downloadFreeBSD-src-d06bf490d31b8fb1079c44b4e9594bcf1960014a.zip
FreeBSD-src-d06bf490d31b8fb1079c44b4e9594bcf1960014a.tar.gz
aic7xxx.c:
Style nits. Make sure that our selection hardware is disabled as soon as possible after detecting a busfree and even go so far as to disable the selection hardware in advance of an event that will cause a busfree (ABORT or BUS DEVICE RESET message). The concern is that the selection hardware will select a target for which, after processing the bus free, there will be no commands pending. The sequencer idle loop will re-enable the selection should it still be necessary. In ahc_handle_scsiint(), clear SSTAT0 events several PCI transactions (most notably reads) prior to clearing SCSIINT. The newer chips seem to take a bit of time to see the change which can make the clearing of SCSIINT ineffective. Don't bother panicing at the end of ahc_handle_scsiint(). Getting to the final else just means we lost the race with clearing SCSIINT. In ahc_free(), handle init-level 0. This can happen when we fail the attach for RAID devices. While I'm here, also kill the parent dma tag. In ahc_match_scb(), consider initiator ccbs to be any that are not from the target mode group. This fixes a bug where an external target reset CCB was not getting cleaned up by the reset code. Don't bother freezing a ccb in any of our "abort" routines when the status is set to CAM_REQ_CMP. This can happen for a target reset ccb. aic7xxx.reg: Reserve space for a completion queue. This will be used to enhance performance in the near future. aic7xxx.seq: Remove an optimization for the 7890 autoflush bug that turned out to allow, in rare cases, some data to get lost. Implement a simpler, faster, fix for the PCI_2_1 retry bug that hangs the sequencer on an SCB dma for certain chips. Test against SAVED_SCSIID rather than SELID during target reselections. This is how we always did it in the past, but the code was modified while trying to work around an issue with the 7895. SAVED_SCSIID takes into account twin channel adapters such as the 2742T, whereas SELID does not have the channel bit. This caused invalid selection warnings and other strangeness on these cards. aic7xxx_pci.c Use the correct mask for checking the generic aic7892 entry.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c134
-rw-r--r--sys/dev/aic7xxx/aic7xxx.h2
-rw-r--r--sys/dev/aic7xxx/aic7xxx.reg10
-rw-r--r--sys/dev/aic7xxx/aic7xxx.seq65
-rw-r--r--sys/dev/aic7xxx/aic7xxx_pci.c42
5 files changed, 175 insertions, 78 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c
index 0cb3df4..c7a9d95 100644
--- a/sys/dev/aic7xxx/aic7xxx.c
+++ b/sys/dev/aic7xxx/aic7xxx.c
@@ -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.c#26 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.c#28 $
*
* $FreeBSD$
*/
@@ -906,7 +906,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
scb = NULL;
if ((ahc->features & AHC_ULTRA2) != 0
- && (status0 & IOERR) != 0) {
+ && (status0 & IOERR) != 0) {
int now_lvd;
now_lvd = ahc_inb(ahc, SBLKCTL) & ENAB40;
@@ -977,8 +977,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
if (scb != NULL)
ahc_print_path(ahc, scb);
else
- printf("%s:%c:%d: ", ahc_name(ahc),
- intr_channel,
+ printf("%s:%c:%d: ", ahc_name(ahc), intr_channel,
SCSIID_TARGET(ahc, ahc_inb(ahc, SAVED_SCSIID)));
scsirate = ahc_inb(ahc, SCSIRATE);
printf("parity error detected %s. "
@@ -1017,22 +1016,46 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
unpause_sequencer(ahc);
} else if ((status & BUSFREE) != 0
&& (ahc_inb(ahc, SIMODE1) & ENBUSFREE) != 0) {
+ u_int lastphase;
+ u_int saved_scsiid;
+ u_int saved_lun;
+ u_int target;
+ u_int initiator_role_id;
+ char channel;
+ int printerror;
+
+ /*
+ * Clear our selection hardware as soon as possible.
+ * We may have an entry in the waiting Q for this target,
+ * that is affected by this busfree and we don't want to
+ * go about selecting the target while we handle the event.
+ */
+ ahc_outb(ahc, SCSISEQ,
+ ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP));
+
/*
- * First look at what phase we were last in.
+ * Disable busfree interrupts and clear the busfree
+ * interrupt status. We do this here so that several
+ * bus transactions occur prior to clearing the SCSIINT
+ * latch. It can take a bit for the clearing to take effect.
+ */
+ ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
+ ahc_outb(ahc, CLRSINT1, CLRBUSFREE|CLRSCSIPERR);
+
+ /*
+ * Look at what phase we were last in.
* If its message out, chances are pretty good
* that the busfree was in response to one of
* our abort requests.
*/
- u_int lastphase = ahc_inb(ahc, LASTPHASE);
- u_int saved_scsiid = ahc_inb(ahc, SAVED_SCSIID);
- u_int saved_lun = ahc_inb(ahc, SAVED_LUN);
- u_int target = SCSIID_TARGET(ahc, saved_scsiid);
- u_int initiator_role_id = SCSIID_OUR_ID(saved_scsiid);
- char channel = SCSIID_CHANNEL(ahc, saved_scsiid);
- int printerror = 1;
+ lastphase = ahc_inb(ahc, LASTPHASE);
+ saved_scsiid = ahc_inb(ahc, SAVED_SCSIID);
+ saved_lun = ahc_inb(ahc, SAVED_LUN);
+ target = SCSIID_TARGET(ahc, saved_scsiid);
+ initiator_role_id = SCSIID_OUR_ID(saved_scsiid);
+ channel = SCSIID_CHANNEL(ahc, saved_scsiid);
+ printerror = 1;
- ahc_outb(ahc, SCSISEQ,
- ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP));
if (lastphase == P_MESGOUT) {
struct ahc_devinfo devinfo;
u_int tag;
@@ -1045,9 +1068,9 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
== MSG_ABORT_TAG)
tag = scb->hscb->tag;
ahc_print_path(ahc, scb);
- printf("SCB %d - Abort %s Completed.\n",
+ printf("SCB %d - Abort%s Completed.\n",
scb->hscb->tag, tag == SCB_LIST_NULL ?
- "" : "Tag");
+ "" : " Tag");
ahc_abort_scbs(ahc, target, channel,
saved_lun, tag,
ROLE_INITIATOR,
@@ -1155,26 +1178,11 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
| (ahc_inb(ahc, SEQADDR1) << 8));
}
ahc_clear_msg_state(ahc);
- ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
- ahc_outb(ahc, CLRSINT1, CLRBUSFREE|CLRSCSIPERR);
ahc_outb(ahc, CLRINT, CLRSCSIINT);
restart_sequencer(ahc);
} else if ((status & SELTO) != 0) {
u_int scbptr;
- 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);
- }
/* Stop the selection */
ahc_outb(ahc, SCSISEQ, 0);
@@ -1194,11 +1202,25 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
*/
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);
restart_sequencer(ahc);
} else {
- panic("%s: Missing case in ahc_handle_scsiint. status = %x\n",
- ahc_name(ahc), status);
+ printf("%s: Missing case in ahc_handle_scsiint. status = %x\n",
+ ahc_name(ahc), status);
+ ahc_outb(ahc, CLRINT, CLRSCSIINT);
}
}
@@ -2027,6 +2049,14 @@ ahc_setup_initiator_msgout(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
ahc->msgout_len++;
ahc_print_path(ahc, scb);
printf("Bus Device Reset Message Sent\n");
+ /*
+ * Clear our selection hardware in advance of
+ * the busfree. We may have an entry in the waiting
+ * Q for this target, and we don't want to go about
+ * selecting while we handle the busfree and blow it
+ * away.
+ */
+ ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO));
} else if ((scb->flags & SCB_ABORT) != 0) {
if ((scb->hscb->control & TAG_ENB) != 0)
ahc->msgout_buf[ahc->msgout_index++] = MSG_ABORT_TAG;
@@ -2034,7 +2064,16 @@ ahc_setup_initiator_msgout(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
ahc->msgout_buf[ahc->msgout_index++] = MSG_ABORT;
ahc->msgout_len++;
ahc_print_path(ahc, scb);
- printf("Abort Message Sent\n");
+ printf("Abort%s Message Sent\n",
+ (scb->hscb->control & TAG_ENB) != 0 ? " Tag" : "");
+ /*
+ * Clear our selection hardware in advance of
+ * the busfree. We may have an entry in the waiting
+ * Q for this target, and we don't want to go about
+ * selecting while we handle the busfree and blow it
+ * away.
+ */
+ ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO));
} else if ((ahc->targ_msg_req & devinfo->target_mask) != 0
|| (scb->flags & SCB_NEGOTIATE) != 0) {
ahc_build_transfer_msg(ahc, devinfo);
@@ -3268,7 +3307,7 @@ ahc_alloc(void *platform_arg, char *name)
#endif
memset(ahc, 0, sizeof(*ahc));
LIST_INIT(&ahc->pending_scbs);
- /* We don't know or unit number until the OSM sets it */
+ /* We don't know our unit number until the OSM sets it */
ahc->name = name;
for (i = 0; i < 16; i++)
TAILQ_INIT(&ahc->untagged_queues[i]);
@@ -3397,8 +3436,13 @@ ahc_free(struct ahc_softc *ahc)
ahc_dma_tag_destroy(ahc, ahc->buffer_dmat);
#endif
break;
+ case 0:
+ break;
}
+#ifndef __linux__
+ ahc_dma_tag_destroy(ahc, ahc->parent_dmat);
+#endif
ahc_platform_free(ahc);
for (i = 0; i < AHC_NUM_TARGETS; i++) {
struct tmode_tstate *tstate;
@@ -4682,7 +4726,7 @@ ahc_match_scb(struct ahc_softc *ahc, struct scb *scb, int target,
group = XPT_FC_GROUP(scb->io_ctx->ccb_h.func_code);
if (role == ROLE_INITIATOR) {
- match = (group == XPT_FC_GROUP_COMMON)
+ match = (group != XPT_FC_GROUP_TMODE)
&& ((tag == scb->hscb->tag)
|| (tag == SCB_LIST_NULL));
} else if (role == ROLE_TARGET) {
@@ -4820,12 +4864,15 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
case SEARCH_COMPLETE:
{
cam_status ostat;
+ cam_status cstat;
ostat = ahc_get_transaction_status(scb);
if (ostat == CAM_REQ_INPROG)
ahc_set_transaction_status(scb,
status);
- ahc_freeze_scb(scb);
+ cstat = ahc_get_transaction_status(scb);
+ if (cstat != CAM_REQ_CMP)
+ ahc_freeze_scb(scb);
if ((scb->flags & SCB_ACTIVE) == 0)
printf("Inactive SCB in qinfifo\n");
ahc_done(ahc, scb);
@@ -4920,12 +4967,15 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
case SEARCH_COMPLETE:
{
cam_status ostat;
+ cam_status cstat;
ostat = ahc_get_transaction_status(scb);
if (ostat == CAM_REQ_INPROG)
ahc_set_transaction_status(scb,
status);
- ahc_freeze_scb(scb);
+ cstat = ahc_get_transaction_status(scb);
+ if (cstat != CAM_REQ_CMP)
+ ahc_freeze_scb(scb);
if ((scb->flags & SCB_ACTIVE) == 0)
printf("Inactive SCB in Waiting List\n");
ahc_done(ahc, scb);
@@ -4998,12 +5048,15 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
case SEARCH_COMPLETE:
{
cam_status ostat;
+ cam_status cstat;
ostat = ahc_get_transaction_status(scb);
if (ostat == CAM_REQ_INPROG)
ahc_set_transaction_status(scb,
status);
- ahc_freeze_scb(scb);
+ cstat = ahc_get_transaction_status(scb);
+ if (cstat != CAM_REQ_CMP)
+ ahc_freeze_scb(scb);
if ((scb->flags & SCB_ACTIVE) == 0)
printf("Inactive SCB in untaggedQ\n");
ahc_done(ahc, scb);
@@ -5289,7 +5342,8 @@ ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel,
ostat = ahc_get_transaction_status(scbp);
if (ostat == CAM_REQ_INPROG)
ahc_set_transaction_status(scbp, status);
- ahc_freeze_scb(scbp);
+ if (ahc_get_transaction_status(scbp) != CAM_REQ_CMP)
+ ahc_freeze_scb(scbp);
if ((scbp->flags & SCB_ACTIVE) == 0)
printf("Inactive SCB on pending list\n");
ahc_done(ahc, scbp);
diff --git a/sys/dev/aic7xxx/aic7xxx.h b/sys/dev/aic7xxx/aic7xxx.h
index cc073a2..ecfe1ea 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#17 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.h#18 $
*
* $FreeBSD$
*/
diff --git a/sys/dev/aic7xxx/aic7xxx.reg b/sys/dev/aic7xxx/aic7xxx.reg
index e249a83..9dabe15 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#10 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.reg#12 $
*
* $FreeBSD$
*/
@@ -1353,6 +1353,14 @@ scratch_ram {
size 1
}
/*
+ * head of list of SCBs that have
+ * completed but have not been
+ * put into the qoutfifo.
+ */
+ COMPLETE_SCBH {
+ size 1
+ }
+ /*
* Address of the hardware scb array in the host.
*/
HSCB_ADDR {
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq
index b43bfe2..bcb6dcc 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#16 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.seq#19 $
*
* $FreeBSD$
*/
@@ -902,10 +902,9 @@ ultra2_dma_loop:
ultra2_dmafinish:
test DFCNTRL, DIRECTION jnz ultra2_dmafifoempty;
- and DFCNTRL, ~SCSIEN;
- test DFCNTRL, SCSIEN jnz .;
- if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
- test DFSTATUS, FIFOEMP jnz ultra2_dmafifoempty;
+ if ((ahc->features & AHC_DT) == 0) {
+ and DFCNTRL, ~SCSIEN;
+ test DFCNTRL, SCSIEN jnz .;
}
ultra2_dmafifoflush:
if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
@@ -1464,9 +1463,10 @@ mesgin_complete:
* If ATN is raised, we still want to give the target a message.
* Perhaps there was a parity error on this last message byte.
* Either way, the target should take us to message out phase
- * and then attempt to complete the command again.
- * XXX - Need a critical section to do this corrctly. Wait until
- * we queue completions.
+ * and then attempt to complete the command again. We should use a
+ * critical section here to guard against a timeout triggering
+ * for this command and setting ATN while we are still processing
+ * the completion.
test SCSISIGI, ATNI jnz mesgin_done;
*/
@@ -1609,7 +1609,7 @@ mesgin_identify:
* for this target or the transaction is for a different lun, then
* this must be an untagged transaction.
*/
- shr SINDEX, 4, SELID;
+ shr SINDEX, 4, SAVED_SCSIID;
and SAVED_LUN, MSG_IDENTIFY_LUNMASK, A;
if ((ahc->flags & AHC_SCB_BTT) != 0) {
add SINDEX, SCB_64_BTT;
@@ -2035,13 +2035,13 @@ dma_scb_fromhost:
* continue the transfer. This does not
* happen for SCSI transfers as the SCSI module
* will drain the FIFO as data is made available.
- * When the hang occurs, we know that at least
- * 8 bytes are in the FIFO because the PCI
+ * When the hang occurs, we know that a multiple
+ * of 8 bytes are in the FIFO because the PCI
* module has an 8 byte input latch that only
* dumps to the FIFO when HCNT == 0 or the
* latch is full.
*/
- mvi A, -24;
+ clr A;
/* Wait for some data to arrive. */
dma_scb_hang_fifo:
test DFSTATUS, FIFOEMP jnz dma_scb_hang_fifo;
@@ -2051,34 +2051,43 @@ dma_scb_hang_wait:
test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
/*
- * The PCI no longer intends to perform a PCI
- * transaction and HDONE has not come true.
+ * The PCI module no longer intends to perform
+ * a PCI transaction and HDONE has not come true.
* We are hung. Drain the fifo.
*/
dma_scb_hang_empty_fifo:
- call dfdat_in_8;
- add A, 8;
- add SINDEX, A, HCNT;
/*
- * The result will be <= 0 (carry set) if at
- * least 8 bytes of data have been placed
- * into the fifo.
+ * Skip lines not yet transfered into the FIFO.
+ */
+ add SINDEX, 7, HCNT;
+ shr SINDEX, 3;
+
+ /*
+ * Skip lines already copied out of the FIFO.
+ */
+ add A, A, SINDEX;
+
+ call dma_scb_hang_dma_drain_fifo;
+
+ /*
+ * Set the lines transferred to all but
+ * those yet to reach the FIFO.
*/
- jc dma_scb_hang_empty_fifo;
+ not SINDEX;
+ add A, 5, SINDEX;
jmp dma_scb_hang_fifo;
dma_scb_hang_dma_done:
and DFCNTRL, ~HDMAEN;
test DFCNTRL, HDMAEN jnz .;
- call dfdat_in_8;
- add A, 8;
- cmp A, 8 jne . - 2;
+dma_scb_hang_dma_drain_fifo:
+ add SEQADDR0, A;
} else {
call dma_finish;
- /* If we were putting the SCB, we are done */
- call dfdat_in_8;
- call dfdat_in_8;
- call dfdat_in_8;
}
+ /* If we were putting the SCB, we are done */
+ call dfdat_in_8;
+ call dfdat_in_8;
+ call dfdat_in_8;
dfdat_in_8:
mov DINDIR,DFDAT;
dfdat_in_7:
diff --git a/sys/dev/aic7xxx/aic7xxx_pci.c b/sys/dev/aic7xxx/aic7xxx_pci.c
index 3e2f3dd..9ac27f8 100644
--- a/sys/dev/aic7xxx/aic7xxx_pci.c
+++ b/sys/dev/aic7xxx/aic7xxx_pci.c
@@ -65,6 +65,7 @@ ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
#define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull
#define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull
+#define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull
#define ID_AIC7850 0x5078900400000000ull
#define ID_AHA_2910_15_20_30C 0x5078900478509004ull
#define ID_AIC7855 0x5578900400000000ull
@@ -134,6 +135,23 @@ ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
#define ID_AIC7810 0x1078900400000000ull
#define ID_AIC7815 0x7815900400000000ull
+#define DEVID_9005_TYPE(id) ((id) & 0xF)
+#define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */
+#define DEVID_9005_TYPE_AAA 0x3 /* RAID Card */
+#define DEVID_9005_TYPE_SISL 0x5 /* Low Cost Card */
+#define DEVID_9005_TYPE_MB 0xF /* On Motherboard */
+
+#define DEVID_9005_MAXRATE(id) (((id) & 0x30) >> 4)
+#define DEVID_9005_MAXRATE_U160 0x0
+#define DEVID_9005_MAXRATE_ULTRA2 0x1
+#define DEVID_9005_MAXRATE_ULTRA 0x2
+#define DEVID_9005_MAXRATE_FAST 0x3
+
+#define DEVID_9005_MFUNC(id) (((id) & 0x40) >> 6)
+
+#define DEVID_9005_CLASS(id) (((id) & 0xFF00) >> 8)
+#define DEVID_9005_CLASS_SPI 0x0 /* Parallel SCSI */
+
#define SUBID_9005_TYPE(id) ((id) & 0xF)
#define SUBID_9005_TYPE_MB 0xF /* On Motherboard */
#define SUBID_9005_TYPE_CARD 0x0 /* Standard Card */
@@ -509,14 +527,14 @@ struct ahc_pci_identity ahc_pci_ident_table [] =
ahc_aic7880_setup
},
{
- ID_AIC7890 & ID_DEV_VENDOR_MASK,
- ID_DEV_VENDOR_MASK,
+ ID_AIC7890 & ID_9005_GENERIC_MASK,
+ ID_9005_GENERIC_MASK,
"Adaptec aic7890/91 Ultra2 SCSI adapter",
ahc_aic7890_setup
},
{
- ID_AIC7892 & ID_DEV_VENDOR_MASK,
- ID_DEV_VENDOR_MASK,
+ ID_AIC7892 & ID_9005_GENERIC_MASK,
+ ID_9005_GENERIC_MASK,
"Adaptec aic7892 Ultra160 SCSI adapter",
ahc_aic7892_setup
},
@@ -533,14 +551,14 @@ struct ahc_pci_identity ahc_pci_ident_table [] =
ahc_aic7895_setup
},
{
- ID_AIC7896 & ID_DEV_VENDOR_MASK,
- ID_DEV_VENDOR_MASK,
+ ID_AIC7896 & ID_9005_GENERIC_MASK,
+ ID_9005_GENERIC_MASK,
"Adaptec aic7896/97 Ultra2 SCSI adapter",
ahc_aic7896_setup
},
{
- ID_AIC7899 & ID_DEV_VENDOR_MASK,
- ID_DEV_VENDOR_MASK,
+ ID_AIC7899 & ID_9005_GENERIC_MASK,
+ ID_9005_GENERIC_MASK,
"Adaptec aic7899 Ultra160 SCSI adapter",
ahc_aic7899_setup
},
@@ -792,6 +810,7 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
printf("%s: Using left over BIOS settings\n",
ahc_name(ahc));
ahc->flags &= ~AHC_USEDEFAULTS;
+ ahc->flags |= AHC_BIOS_ENABLED;
} else {
/*
* Assume only one connector and always turn
@@ -1227,8 +1246,15 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
if (sc.adapter_control & CFRESETB)
scsi_conf |= RESET_SCSI;
+ if ((sc.adapter_control & CFCHNLBPRIMARY) != 0
+ && (ahc->features & AHC_MULTI_FUNC) != 0)
+ ahc->flags |= AHC_CHANNEL_B_PRIMARY;
+
if (sc.bios_control & CFEXTEND)
ahc->flags |= AHC_EXTENDED_TRANS_A;
+
+ if (sc.bios_control & CFBIOSEN)
+ ahc->flags |= AHC_BIOS_ENABLED;
if (ahc->features & AHC_ULTRA
&& (ahc->flags & AHC_NEWEEPROM_FMT) == 0) {
/* Should we enable Ultra mode? */
OpenPOWER on IntegriCloud