diff options
| author | Justin T. Gibbs <gibbs@FreeBSD.org> | 2001-01-05 19:15:37 +0000 |
|---|---|---|
| committer | Justin T. Gibbs <gibbs@FreeBSD.org> | 2001-01-05 19:15:37 +0000 |
| commit | f8838555e87f543e09d714d0e2669fe1e1ad5cb7 (patch) | |
| tree | 7e37ad3a478ac2183b0db7c75b690237cf2cdde1 | |
| parent | f69734803487dd14ded1a80b7344707248a84227 (diff) | |
Notes
| -rw-r--r-- | sys/dev/aic7xxx/aic7xxx.c | 133 | ||||
| -rw-r--r-- | sys/dev/aic7xxx/aic7xxx.h | 39 | ||||
| -rw-r--r-- | sys/dev/aic7xxx/aic7xxx_freebsd.h | 19 | ||||
| -rw-r--r-- | sys/dev/aic7xxx/aic7xxx_osm.h | 19 | ||||
| -rw-r--r-- | sys/dev/aic7xxx/aic7xxx_pci.c | 58 |
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++) { |
