summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c133
-rw-r--r--sys/dev/aic7xxx/aic7xxx.h39
-rw-r--r--sys/dev/aic7xxx/aic7xxx_freebsd.h19
-rw-r--r--sys/dev/aic7xxx/aic7xxx_osm.h19
-rw-r--r--sys/dev/aic7xxx/aic7xxx_pci.c58
5 files changed, 186 insertions, 82 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c
index 8e15223aebc3..5f8540a936ee 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#20 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.c#21 $
*
* $FreeBSD$
*/
@@ -492,6 +492,10 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
sg->len = ahc_get_sense_bufsize(ahc, scb);
sg->len |= AHC_DMA_LAST_SEG;
+ /* Fixup byte order */
+ sg->addr = ahc_htole32(sg->addr);
+ sg->len = ahc_htole32(sg->len);
+
sc->opcode = REQUEST_SENSE;
sc->byte2 = 0;
if (tinfo->protocol_version <= SCSI_REV_2
@@ -530,6 +534,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
hscb->dataptr = sg->addr;
hscb->datacnt = sg->len;
hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID;
+ hscb->sgptr = ahc_htole32(hscb->sgptr);
scb->sg_count = 1;
scb->flags |= SCB_SENSE;
ahc_qinfifo_requeue_tail(ahc, scb);
@@ -770,8 +775,9 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
for (i = 0; i < scb->sg_count; i++) {
printf("sg[%d] - Addr 0x%x : Length %d\n",
i,
- scb->sg_list[i].addr,
- scb->sg_list[i].len & AHC_SG_LEN_MASK);
+ ahc_le32toh(scb->sg_list[i].addr),
+ ahc_le32toh(scb->sg_list[i].len)
+ & AHC_SG_LEN_MASK);
}
}
/*
@@ -1326,16 +1332,16 @@ ahc_print_scb(struct scb *scb)
hscb->shared_data.cdb[i++],
hscb->shared_data.cdb[i++]);
printf(" dataptr:%#x datacnt:%#x sgptr:%#x tag:%#x\n",
- hscb->dataptr,
- hscb->datacnt,
- hscb->sgptr,
+ ahc_le32toh(hscb->dataptr),
+ ahc_le32toh(hscb->datacnt),
+ ahc_le32toh(hscb->sgptr),
hscb->tag);
if (scb->sg_count > 0) {
for (i = 0; i < scb->sg_count; i++) {
printf("sg[%d] - Addr 0x%x : Length %d\n",
i,
- scb->sg_list[i].addr,
- scb->sg_list[i].len);
+ ahc_le32toh(scb->sg_list[i].addr),
+ ahc_le32toh(scb->sg_list[i].len));
}
}
}
@@ -4121,7 +4127,7 @@ ahc_init(struct ahc_softc *ahc)
ahc_outb(ahc, SCSIID, ahc->our_id_b);
scsi_conf = ahc_inb(ahc, SCSICONF + 1);
ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL))
- |term|ENSTIMER|ACTNEGEN);
+ |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);
@@ -4141,7 +4147,7 @@ ahc_init(struct ahc_softc *ahc)
ahc_outb(ahc, SCSIID, ahc->our_id);
scsi_conf = ahc_inb(ahc, SCSICONF);
ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL))
- |term
+ |term|ahc->seltime
|ENSTIMER|ACTNEGEN);
if ((ahc->features & AHC_ULTRA2) != 0)
ahc_outb(ahc, SIMODE0, ahc_inb(ahc, SIMODE0)|ENIOERR);
@@ -4447,13 +4453,24 @@ ahc_suspend(struct ahc_softc *ahc)
#endif
/* Save volatile registers */
- ahc->suspend_state.scsiseq = ahc_inb(ahc, SCSISEQ);
- ahc->suspend_state.sxfrctl0 = ahc_inb(ahc, SXFRCTL0);
- ahc->suspend_state.sxfrctl1 = ahc_inb(ahc, SXFRCTL1);
- ahc->suspend_state.simode0 = ahc_inb(ahc, SIMODE0);
- ahc->suspend_state.simode1 = ahc_inb(ahc, SIMODE1);
- ahc->suspend_state.seltimer = ahc_inb(ahc, SELTIMER);
- ahc->suspend_state.seqctl = ahc_inb(ahc, SEQCTL);
+ 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);
@@ -4513,13 +4530,29 @@ ahc_resume(struct ahc_softc *ahc)
ahc_build_free_scb_list(ahc);
/* Restore volatile registers */
- ahc_outb(ahc, SCSISEQ, ahc->suspend_state.scsiseq);
- ahc_outb(ahc, SXFRCTL0, ahc->suspend_state.sxfrctl0);
- ahc_outb(ahc, SXFRCTL1, ahc->suspend_state.sxfrctl1);
- ahc_outb(ahc, SIMODE0, ahc->suspend_state.simode0);
- ahc_outb(ahc, SIMODE1, ahc->suspend_state.simode1);
- ahc_outb(ahc, SELTIMER, ahc->suspend_state.seltimer);
- ahc_outb(ahc, SEQCTL, ahc->suspend_state.seqctl);
+ 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);
@@ -5425,6 +5458,8 @@ ahc_calc_residual(struct scb *scb)
{
struct hardware_scb *hscb;
struct status_pkt *spkt;
+ uint32_t sgptr;
+ uint32_t resid_sgptr;
uint32_t resid;
/*
@@ -5444,24 +5479,26 @@ ahc_calc_residual(struct scb *scb)
*/
hscb = scb->hscb;
- if ((hscb->sgptr & SG_RESID_VALID) == 0)
+ sgptr = ahc_le32toh(hscb->sgptr);
+ if ((sgptr & SG_RESID_VALID) == 0)
/* Case 1 */
return;
- hscb->sgptr &= ~SG_RESID_VALID;
+ sgptr &= ~SG_RESID_VALID;
- if ((hscb->sgptr & SG_LIST_NULL) != 0)
+ if ((sgptr & SG_LIST_NULL) != 0)
/* Case 2 */
return;
spkt = &hscb->shared_data.status;
- if ((hscb->sgptr & SG_FULL_RESID) != 0) {
+ resid_sgptr = ahc_le32toh(spkt->residual_sg_ptr);
+ if ((sgptr & SG_FULL_RESID) != 0) {
/* Case 3 */
resid = ahc_get_transfer_length(scb);
- } else if ((spkt->residual_sg_ptr & SG_LIST_NULL) != 0) {
+ } else if ((resid_sgptr & SG_LIST_NULL) != 0) {
/* Case 4 */
return;
- } else if ((spkt->residual_sg_ptr & ~SG_PTR_MASK) != 0) {
- panic("Bogus resid sgptr value 0x%x\n", spkt->residual_sg_ptr);
+ } else if ((resid_sgptr & ~SG_PTR_MASK) != 0) {
+ panic("Bogus resid sgptr value 0x%x\n", resid_sgptr);
} else {
struct ahc_dma_seg *sg;
@@ -5469,9 +5506,8 @@ ahc_calc_residual(struct scb *scb)
* Remainder of the SG where the transfer
* stopped.
*/
- resid = spkt->residual_datacnt & AHC_SG_LEN_MASK;
- sg = ahc_sg_bus_to_virt(scb,
- spkt->residual_sg_ptr & SG_PTR_MASK);
+ resid = ahc_le32toh(spkt->residual_datacnt) & AHC_SG_LEN_MASK;
+ sg = ahc_sg_bus_to_virt(scb, resid_sgptr & SG_PTR_MASK);
/* The residual sg_ptr always points to the next sg */
sg--;
@@ -5481,9 +5517,9 @@ ahc_calc_residual(struct scb *scb)
* SG segments that are after the SG where
* the transfer stopped.
*/
- while ((sg->len & AHC_DMA_LAST_SEG) == 0) {
+ while ((ahc_le32toh(sg->len) & AHC_DMA_LAST_SEG) == 0) {
sg++;
- resid += sg->len & AHC_SG_LEN_MASK;
+ resid += ahc_le32toh(sg->len) & AHC_SG_LEN_MASK;
}
}
if ((scb->flags & SCB_SENSE) == 0)
@@ -5757,17 +5793,10 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts)
struct ins_format3 *fmt3_ins;
u_int opcode;
- /* Structure copy */
- instr = *(union ins_formats*)&seqprog[instrptr * 4];
-
-#if BYTE_ORDER == BIG_ENDIAN
- opcode = instr.format.bytes[0];
- instr.format.bytes[0] = instr.format.bytes[3];
- instr.format.bytes[3] = opcode;
- opcode = instr.format.bytes[1];
- instr.format.bytes[1] = instr.format.bytes[2];
- instr.format.bytes[2] = opcode;
-#endif
+ /*
+ * The firmware is always compiled into a little endian format.
+ */
+ instr.integer = ahc_le32toh(*(uint32_t*)&seqprog[instrptr * 4]);
fmt1_ins = &instr.format1;
fmt3_ins = NULL;
@@ -5871,14 +5900,8 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts)
| (fmt1_ins->opcode << 25);
}
}
-#if BYTE_ORDER == BIG_ENDIAN
- opcode = instr.format.bytes[0];
- instr.format.bytes[0] = instr.format.bytes[3];
- instr.format.bytes[3] = opcode;
- opcode = instr.format.bytes[1];
- instr.format.bytes[1] = instr.format.bytes[2];
- instr.format.bytes[2] = opcode;
-#endif
+ /* The sequencer is a little endian cpu */
+ instr.integer = ahc_htole32(instr.integer);
ahc_outsb(ahc, SEQRAM, instr.bytes, 4);
break;
default:
diff --git a/sys/dev/aic7xxx/aic7xxx.h b/sys/dev/aic7xxx/aic7xxx.h
index 8d1c83cdd9a3..12bfdb297d98 100644
--- a/sys/dev/aic7xxx/aic7xxx.h
+++ b/sys/dev/aic7xxx/aic7xxx.h
@@ -809,25 +809,28 @@ 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_suspend_state {
- uint8_t scsiseq;
- uint8_t sxfrctl0;
- uint8_t sxfrctl1;
- /* scsiid */
- uint8_t optionmode;
- uint8_t simode0;
- uint8_t simode1;
- uint8_t seltimer;
- uint8_t seqctl;
- uint8_t dscommand0;
- uint8_t dspcistatus;
+ struct ahc_suspend_channel_state channel[2];
+ uint8_t optionmode;
+ uint8_t dscommand0;
+ uint8_t dspcistatus;
/* hsmailbox */
- uint8_t crccontrol1;
- uint8_t scbbaddr;
+ uint8_t crccontrol1;
+ uint8_t scbbaddr;
/* Host and sequencer SCB counts */
- uint8_t dff_thrsh;
- uint8_t *scratch_ram;
- uint8_t *btt;
+ uint8_t dff_thrsh;
+ uint8_t *scratch_ram;
+ uint8_t *btt;
};
struct ahc_softc {
@@ -983,6 +986,10 @@ struct ahc_softc {
char *name;
int unit;
+ /* Selection Timer settings */
+ int seltime;
+ int seltime_b;
+
uint16_t user_discenable;/* Disconnection allowed */
uint16_t user_tagenable;/* Tagged Queuing allowed */
};
diff --git a/sys/dev/aic7xxx/aic7xxx_freebsd.h b/sys/dev/aic7xxx/aic7xxx_freebsd.h
index ee07b9e27dd1..f57fd9c5422d 100644
--- a/sys/dev/aic7xxx/aic7xxx_freebsd.h
+++ b/sys/dev/aic7xxx/aic7xxx_freebsd.h
@@ -172,6 +172,25 @@ struct ahc_platform_data {
struct scb_platform_data {
};
+/********************************* Byte Order *********************************/
+/*
+ * XXX Waiting for FreeBSD byte swapping functions.
+ * For now assume host is Little Endian.
+ */
+#define ahc_htobe16(x) x
+#define ahc_htobe32(x) x
+#define ahc_htobe64(x) x
+#define ahc_htole16(x) x
+#define ahc_htole32(x) x
+#define ahc_htole64(x) x
+
+#define ahc_be16toh(x) x
+#define ahc_be32toh(x) x
+#define ahc_be64toh(x) x
+#define ahc_le16toh(x) x
+#define ahc_le32toh(x) x
+#define ahc_le64toh(x) x
+
/***************************** Core Includes **********************************/
#include <dev/aic7xxx/aic7xxx.h>
diff --git a/sys/dev/aic7xxx/aic7xxx_osm.h b/sys/dev/aic7xxx/aic7xxx_osm.h
index ee07b9e27dd1..f57fd9c5422d 100644
--- a/sys/dev/aic7xxx/aic7xxx_osm.h
+++ b/sys/dev/aic7xxx/aic7xxx_osm.h
@@ -172,6 +172,25 @@ struct ahc_platform_data {
struct scb_platform_data {
};
+/********************************* Byte Order *********************************/
+/*
+ * XXX Waiting for FreeBSD byte swapping functions.
+ * For now assume host is Little Endian.
+ */
+#define ahc_htobe16(x) x
+#define ahc_htobe32(x) x
+#define ahc_htobe64(x) x
+#define ahc_htole16(x) x
+#define ahc_htole32(x) x
+#define ahc_htole64(x) x
+
+#define ahc_be16toh(x) x
+#define ahc_be32toh(x) x
+#define ahc_be64toh(x) x
+#define ahc_le16toh(x) x
+#define ahc_le32toh(x) x
+#define ahc_le64toh(x) x
+
/***************************** Core Includes **********************************/
#include <dev/aic7xxx/aic7xxx.h>
diff --git a/sys/dev/aic7xxx/aic7xxx_pci.c b/sys/dev/aic7xxx/aic7xxx_pci.c
index 6231b28752b1..07f53abe2c28 100644
--- a/sys/dev/aic7xxx/aic7xxx_pci.c
+++ b/sys/dev/aic7xxx/aic7xxx_pci.c
@@ -134,16 +134,52 @@ ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
#define ID_AIC7810 0x1078900400000000ull
#define ID_AIC7815 0x7815900400000000ull
-#define SUBID_9005_TYPE 0x000F
-#define SUBID_9005_MAXRATE 0x0030
-#define SUBID_9005_DISAUTOTERM 0x0040
-#define SUBID_9005_LEGACYCONN 0x0080
-#define SUBID_9005_SEEPTYPE 0x0300
-#define SUBID_9005_NUMCHAN 0x0C00
-#define SUBID_9005_MFUNCENB 0x1000
-#define SUBID_9005_SCSIWIDTH 0x2000
-#define SUBID_9005_PCIWIDTH 0x4000
-#define SUBID_9005_SEDIFF 0x8000
+#define SUBID_9005_TYPE(id) ((id) & 0xF)
+#define SUBID_9005_TYPE_MB 0xF /* On Motherboard */
+#define SUBID_9005_TYPE_CARD 0x0 /* Standard Card */
+#define SUBID_9005_TYPE_LCCARD 0x1 /* Low Cost Card */
+#define SUBID_9005_TYPE_RAID 0x3 /* Combined with Raid */
+
+#define SUBID_9005_MAXRATE(id) (((id) & 0x30) >> 4)
+#define SUBID_9005_MAXRATE_ULTRA2 0x0
+#define SUBID_9005_MAXRATE_ULTRA 0x1
+#define SUBID_9005_MAXRATE_U160 0x2
+#define SUBID_9005_MAXRATE_RESERVED 0x3
+
+#define SUBID_9005_SEEPTYPE(id) \
+ ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \
+ ? ((id) & 0xC0) >> 6 \
+ : ((id) & 0x300) >> 8)
+#define SUBID_9005_SEEPTYPE_NONE 0x0
+#define SUBID_9005_SEEPTYPE_1K 0x1
+#define SUBID_9005_SEEPTYPE_2K_4K 0x2
+#define SUBID_9005_SEEPTYPE_RESERVED 0x3
+#define SUBID_9005_AUTOTERM(id) \
+ ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \
+ ? (((id) & 0x400) >> 10) == 0 \
+ : (((id) & 0x40) >> 6) == 0)
+
+#define SUBID_9005_NUMCHAN(id) \
+ ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \
+ ? ((id) & 0x300) >> 8 \
+ : ((id) & 0xC00) >> 10)
+
+#define SUBID_9005_LEGACYCONN(id) \
+ ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \
+ ? 0 \
+ : ((id) & 0x80) >> 7)
+
+#define SUBID_9005_MFUNCENB(id) \
+ ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \
+ ? ((id) & 0x800) >> 11 \
+ : ((id) & 0x1000) >> 12)
+/*
+ * Informational only. Should use chip register to be
+ * ceratian, but may be use in identification strings.
+ */
+#define SUBID_9005_CARD_SCSIWIDTH_MASK 0x2000
+#define SUBID_9005_CARD_PCIWIDTH_MASK 0x4000
+#define SUBID_9005_CARD_SEDIFF_MASK 0x8000
static ahc_device_setup_t ahc_aic7850_setup;
static ahc_device_setup_t ahc_aic7855_setup;
@@ -614,7 +650,7 @@ ahc_find_pci_device(ahc_dev_softc_t pci)
/* If the second function is not hooked up, ignore it. */
if (ahc_get_pci_function(pci) > 0
&& subvendor == 0x9005
- && (subdevice & SUBID_9005_MFUNCENB) == 0)
+ && SUBID_9005_MFUNCENB(subdevice) == 0)
return (NULL);
for (i = 0; i < ahc_num_pci_devs; i++) {