diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/aic7xxx/ahc_pci.c | 20 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7770.c | 39 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.c | 264 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.h | 44 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.reg | 21 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.seq | 175 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_93cx6.c | 2 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_freebsd.c | 19 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_freebsd.h | 5 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_inline.h | 147 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_osm.c | 19 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_osm.h | 5 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_pci.c | 296 |
13 files changed, 696 insertions, 360 deletions
diff --git a/sys/dev/aic7xxx/ahc_pci.c b/sys/dev/aic7xxx/ahc_pci.c index 01772a0..b76d232 100644 --- a/sys/dev/aic7xxx/ahc_pci.c +++ b/sys/dev/aic7xxx/ahc_pci.c @@ -102,11 +102,20 @@ ahc_pci_attach(device_t dev) ahc_set_unit(ahc, device_get_unit(dev)); + /* + * Should we bother disabling 39Bit addressing + * based on installed memory? + */ + if (sizeof(bus_addr_t) > 4) + ahc->flags |= AHC_39BIT_ADDRESSING; + /* Allocate a dmatag for our SCB DMA maps */ /* XXX Should be a child of the PCI bus dma tag */ error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, + (ahc->flags & AHC_39BIT_ADDRESSING) + ? 0x7FFFFFFFFF + : BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/MAXBSIZE, /*nsegments*/AHC_NSEG, @@ -182,7 +191,7 @@ ahc_pci_map_registers(struct ahc_softc *ahc) regs_id = AHC_PCI_IOADDR; regs = bus_alloc_resource(ahc->dev_softc, regs_type, ®s_id, 0, ~0, 1, RF_ACTIVE); - if (regs) { + if (regs != NULL) { ahc->tag = rman_get_bustag(regs); ahc->bsh = rman_get_bushandle(regs); command &= ~PCIM_CMD_MEMEN; @@ -190,15 +199,14 @@ ahc_pci_map_registers(struct ahc_softc *ahc) command, /*bytes*/1); } } - ahc->platform_data->regs_res_type = regs_type; - ahc->platform_data->regs_res_id = regs_id; - ahc->platform_data->regs = regs; - if (regs == NULL) { device_printf(ahc->dev_softc, "can't allocate register resources\n"); return (ENOMEM); } + ahc->platform_data->regs_res_type = regs_type; + ahc->platform_data->regs_res_id = regs_id; + ahc->platform_data->regs = regs; return (0); } diff --git a/sys/dev/aic7xxx/aic7770.c b/sys/dev/aic7xxx/aic7770.c index d717882..8383762 100644 --- a/sys/dev/aic7xxx/aic7770.c +++ b/sys/dev/aic7xxx/aic7770.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: //depot/src/aic7xxx/aic7770.c#11 $ + * $Id: //depot/src/aic7xxx/aic7770.c#12 $ * * $FreeBSD$ */ @@ -90,14 +90,12 @@ aic7770_find_device(uint32_t id) int aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry) { - struct ahc_probe_config probe_config; int error; u_int hostconf; u_int irq; u_int intdef; - ahc_init_probe_config(&probe_config); - error = entry->setup(ahc->dev_softc, &probe_config); + error = entry->setup(ahc); if (error != 0) return (error); @@ -105,8 +103,8 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry) if (error != 0) return (error); - probe_config.description = entry->name; - error = ahc_softc_init(ahc, &probe_config); + ahc->description = entry->name; + error = ahc_softc_init(ahc); error = ahc_reset(ahc); if (error != 0) @@ -131,7 +129,7 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry) if ((intdef & EDGE_TRIG) != 0) ahc->flags |= AHC_EDGE_INTERRUPT; - switch (probe_config.chip & (AHC_EISA|AHC_VL)) { + switch (ahc->chip & (AHC_EISA|AHC_VL)) { case AHC_EISA: { u_int biosctrl; @@ -312,34 +310,33 @@ aha2840_load_seeprom(struct ahc_softc *ahc) } static int -ahc_aic7770_VL_setup(ahc_dev_softc_t dev, struct ahc_probe_config *probe_config) +ahc_aic7770_VL_setup(struct ahc_softc *ahc) { int error; - error = ahc_aic7770_setup(dev, probe_config); - probe_config->chip |= AHC_VL; + error = ahc_aic7770_setup(ahc); + ahc->chip |= AHC_VL; return (error); } static int -ahc_aic7770_EISA_setup(ahc_dev_softc_t dev, - struct ahc_probe_config *probe_config) +ahc_aic7770_EISA_setup(struct ahc_softc *ahc) { int error; - error = ahc_aic7770_setup(dev, probe_config); - probe_config->chip |= AHC_EISA; + error = ahc_aic7770_setup(ahc); + ahc->chip |= AHC_EISA; return (error); } static int -ahc_aic7770_setup(ahc_dev_softc_t dev, struct ahc_probe_config *probe_config) +ahc_aic7770_setup(struct ahc_softc *ahc) { - probe_config->channel = 'A'; - probe_config->channel_b = 'B'; - probe_config->chip = AHC_AIC7770; - probe_config->features = AHC_AIC7770_FE; - probe_config->bugs |= AHC_TMODE_WIDEODD_BUG; - probe_config->flags |= AHC_PAGESCBS; + ahc->channel = 'A'; + ahc->channel_b = 'B'; + ahc->chip = AHC_AIC7770; + ahc->features = AHC_AIC7770_FE; + ahc->bugs |= AHC_TMODE_WIDEODD_BUG; + ahc->flags |= AHC_PAGESCBS; return (0); } diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c index 829f609..4f0ac4f 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#39 $ + * $Id: //depot/src/aic7xxx/aic7xxx.c#43 $ * * $FreeBSD$ */ @@ -179,6 +179,7 @@ static int ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo); static void ahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo); +static void ahc_reinitialize_dataptrs(struct ahc_softc *ahc); static void ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, cam_status status, char *message, @@ -282,6 +283,7 @@ ahc_run_qoutfifo(struct ahc_softc *ahc) struct scb *scb; u_int scb_index; + ahc_sync_qoutfifo(ahc, BUS_DMASYNC_POSTREAD); while (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL) { scb_index = ahc->qoutfifo[ahc->qoutfifonext]; @@ -297,6 +299,10 @@ ahc_run_qoutfifo(struct ahc_softc *ahc) */ modnext = ahc->qoutfifonext & ~0x3; *((uint32_t *)(&ahc->qoutfifo[modnext])) = 0xFFFFFFFFUL; + ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + ahc->shared_data_dmamap, + /*offset*/modnext, /*len*/4, + BUS_DMASYNC_PREREAD); } ahc->qoutfifonext++; @@ -624,6 +630,9 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) case IGN_WIDE_RES: ahc_handle_ign_wide_residue(ahc, &devinfo); break; + case PDATA_REINIT: + ahc_reinitialize_dataptrs(ahc); + break; case BAD_PHASE: { u_int lastphase; @@ -777,8 +786,11 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) ahc_get_transfer_length(scb), scb->sg_count); if (scb->sg_count > 0) { for (i = 0; i < scb->sg_count; i++) { - printf("sg[%d] - Addr 0x%x : Length %d\n", + + printf("sg[%d] - Addr 0x%x%x : Length %d\n", i, + (ahc_le32toh(scb->sg_list[i].len) >> 24 + & SG_HIGH_ADDR_BITS), ahc_le32toh(scb->sg_list[i].addr), ahc_le32toh(scb->sg_list[i].len) & AHC_SG_LEN_MASK); @@ -791,6 +803,26 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) ahc_freeze_devq(ahc, scb); ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR); ahc_freeze_scb(scb); + + if ((ahc->features & AHC_ULTRA2) != 0) { + /* + * Clear the channel in case we return + * to data phase later. + */ + ahc_outb(ahc, SXFRCTL0, + ahc_inb(ahc, SXFRCTL0) | CLRSTCNT|CLRCHN); + ahc_outb(ahc, SXFRCTL0, + ahc_inb(ahc, SXFRCTL0) | CLRSTCNT|CLRCHN); + } + if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { + u_int dscommand1; + + /* Ensure HHADDR is 0 for future DMA operations. */ + dscommand1 = ahc_inb(ahc, DSCOMMAND1); + ahc_outb(ahc, DSCOMMAND1, dscommand1 | HADDLDSEL0); + ahc_outb(ahc, HADDR, 0); + ahc_outb(ahc, DSCOMMAND1, dscommand1); + } break; } case MKMSG_FAILED: @@ -1338,7 +1370,7 @@ ahc_print_scb(struct scb *scb) struct hardware_scb *hscb = scb->hscb; printf("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n", - scb, + (void *)scb, hscb->control, hscb->scsiid, hscb->lun, @@ -1366,8 +1398,10 @@ ahc_print_scb(struct scb *scb) hscb->tag); if (scb->sg_count > 0) { for (i = 0; i < scb->sg_count; i++) { - printf("sg[%d] - Addr 0x%x : Length %d\n", + printf("sg[%d] - Addr 0x%x%x : Length %d\n", i, + (ahc_le32toh(scb->sg_list[i].len) >> 24 + & SG_HIGH_ADDR_BITS), ahc_le32toh(scb->sg_list[i].addr), ahc_le32toh(scb->sg_list[i].len)); } @@ -1911,7 +1945,7 @@ ahc_update_pending_scbs(struct ahc_softc *ahc) struct hardware_scb *pending_hscb; struct ahc_initiator_tinfo *tinfo; struct ahc_tmode_tstate *tstate; - + ahc_scb_devinfo(ahc, &devinfo, pending_scb); tinfo = ahc_fetch_transinfo(ahc, devinfo.channel, devinfo.our_scsiid, @@ -1927,6 +1961,8 @@ ahc_update_pending_scbs(struct ahc_softc *ahc) pending_scb->flags &= ~SCB_AUTO_NEGOTIATE; pending_hscb->control &= ~MK_MESSAGE; } + ahc_sync_scb(ahc, pending_scb, + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); pending_scb_count++; } @@ -2181,6 +2217,9 @@ ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) */ period = tinfo->goal.period; ppr_options = tinfo->goal.ppr_options; + /* Target initiated PPR is not allowed in the SCSI spec */ + if (devinfo->role == ROLE_TARGET) + ppr_options = 0; rate = ahc_devlimited_syncrate(ahc, tinfo, &period, &ppr_options, devinfo->role); dowide = tinfo->curr.width != tinfo->goal.width; @@ -3208,13 +3247,15 @@ ahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) struct ahc_dma_seg *sg; uint32_t data_cnt; uint32_t data_addr; + uint32_t sglen; /* Pull in the rest of the sgptr */ sgptr |= (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 3) << 24) | (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 2) << 16) | (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 1) << 8); sgptr &= SG_PTR_MASK; - data_cnt = (ahc_inb(ahc, SCB_RESIDUAL_DATACNT+2) << 16) + data_cnt = (ahc_inb(ahc, SCB_RESIDUAL_DATACNT+3) << 24) + | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT+2) << 16) | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT+1) << 8) | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT)); @@ -3232,13 +3273,19 @@ ahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) * to load so we must go back one. */ sg--; + sglen = ahc_le32toh(sg->len) & AHC_SG_LEN_MASK; if (sg != scb->sg_list - && (sg->len & AHC_SG_LEN_MASK) < data_cnt) { + && sglen < (data_cnt & AHC_SG_LEN_MASK)) { sg--; - data_cnt = 1 | (sg->len & AHC_DMA_LAST_SEG); - data_addr = sg->addr - + (sg->len & AHC_SG_LEN_MASK) - 1; + sglen = ahc_le32toh(sg->len); + /* + * Preserve High Address and SG_LIST bits + * while setting the count to 1. + */ + data_cnt = 1 | (sglen & (~AHC_SG_LEN_MASK)); + data_addr = ahc_le32toh(sg->addr) + + (sglen & AHC_SG_LEN_MASK) - 1; /* * Increment sg so it points to the @@ -3255,31 +3302,72 @@ ahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) ahc_outb(ahc, SCB_RESIDUAL_SGPTR, sgptr); } -/* XXX What about high address byte??? */ ahc_outb(ahc, SCB_RESIDUAL_DATACNT + 3, data_cnt >> 24); ahc_outb(ahc, SCB_RESIDUAL_DATACNT + 2, data_cnt >> 16); ahc_outb(ahc, SCB_RESIDUAL_DATACNT + 1, data_cnt >> 8); ahc_outb(ahc, SCB_RESIDUAL_DATACNT, data_cnt); - -/* XXX Perhaps better to just keep the saved address in sram */ - if ((ahc->features & AHC_ULTRA2) != 0) { - ahc_outb(ahc, HADDR + 3, data_addr >> 24); - ahc_outb(ahc, HADDR + 2, data_addr >> 16); - ahc_outb(ahc, HADDR + 1, data_addr >> 8); - ahc_outb(ahc, HADDR, data_addr); - ahc_outb(ahc, DFCNTRL, PRELOADEN); - ahc_outb(ahc, SXFRCTL0, - ahc_inb(ahc, SXFRCTL0) | CLRCHN); - } else { - ahc_outb(ahc, HADDR + 3, data_addr >> 24); - ahc_outb(ahc, HADDR + 2, data_addr >> 16); - ahc_outb(ahc, HADDR + 1, data_addr >> 8); - ahc_outb(ahc, HADDR, data_addr); - } } } } + +/* + * Reinitialize the data pointers for the active transfer + * based on its current residual. + */ +static void +ahc_reinitialize_dataptrs(struct ahc_softc *ahc) +{ + struct scb *scb; + struct ahc_dma_seg *sg; + u_int scb_index; + uint32_t sgptr; + uint32_t resid; + uint32_t dataptr; + + scb_index = ahc_inb(ahc, SCB_TAG); + scb = ahc_lookup_scb(ahc, scb_index); + sgptr = (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 3) << 24) + | (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 2) << 16) + | (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 1) << 8) + | ahc_inb(ahc, SCB_RESIDUAL_SGPTR); + + sgptr &= SG_PTR_MASK; + sg = ahc_sg_bus_to_virt(scb, sgptr); + + /* The residual sg_ptr always points to the next sg */ + sg--; + + resid = (ahc_inb(ahc, SCB_RESIDUAL_DATACNT + 2) << 16) + | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT + 1) << 8) + | ahc_inb(ahc, SCB_RESIDUAL_DATACNT); + + dataptr = ahc_le32toh(sg->addr) + + (ahc_le32toh(sg->len) & AHC_SG_LEN_MASK) + - resid; + if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { + u_int dscommand1; + + dscommand1 = ahc_inb(ahc, DSCOMMAND1); + ahc_outb(ahc, DSCOMMAND1, dscommand1 | HADDLDSEL0); + ahc_outb(ahc, HADDR, + (ahc_le32toh(sg->len) >> 24) & SG_HIGH_ADDR_BITS); + ahc_outb(ahc, DSCOMMAND1, dscommand1); + } + ahc_outb(ahc, HADDR + 3, dataptr >> 24); + ahc_outb(ahc, HADDR + 2, dataptr >> 16); + ahc_outb(ahc, HADDR + 1, dataptr >> 8); + ahc_outb(ahc, HADDR, dataptr); + ahc_outb(ahc, HCNT + 2, resid >> 16); + ahc_outb(ahc, HCNT + 1, resid >> 8); + ahc_outb(ahc, HCNT, resid); + if ((ahc->features & AHC_ULTRA2) == 0) { + ahc_outb(ahc, STCNT + 2, resid >> 16); + ahc_outb(ahc, STCNT + 1, resid >> 8); + ahc_outb(ahc, STCNT, resid); + } +} + /* * Handle the effects of issuing a bus device reset message. */ @@ -3385,6 +3473,14 @@ ahc_alloc(void *platform_arg, char *name) /* We don't know our unit number until the OSM sets it */ ahc->name = name; ahc->unit = -1; + ahc->description = NULL; + ahc->channel = 'A'; + ahc->channel_b = 'B'; + ahc->chip = AHC_NONE; + ahc->features = AHC_FENONE; + ahc->bugs = AHC_BUGNONE; + ahc->flags = AHC_FNONE; + for (i = 0; i < 16; i++) TAILQ_INIT(&ahc->untagged_queues[i]); if (ahc_platform_alloc(ahc, platform_arg) != 0) { @@ -3395,16 +3491,9 @@ ahc_alloc(void *platform_arg, char *name) } int -ahc_softc_init(struct ahc_softc *ahc, struct ahc_probe_config *config) +ahc_softc_init(struct ahc_softc *ahc) { - ahc->chip = config->chip; - ahc->features = config->features; - ahc->bugs = config->bugs; - ahc->flags = config->flags; - ahc->channel = config->channel; - ahc->unpause = (ahc_inb(ahc, HCNTRL) & IRQMS); - ahc->description = config->description; /* The IRQMS bit is only valid on VL and EISA chips */ if ((ahc->chip & AHC_PCI) != 0) ahc->unpause &= ~IRQMS; @@ -3697,18 +3786,6 @@ ahc_probe_scbs(struct ahc_softc *ahc) { return (i); } -void -ahc_init_probe_config(struct ahc_probe_config *probe_config) -{ - probe_config->description = NULL; - probe_config->channel = 'A'; - probe_config->channel_b = 'B'; - probe_config->chip = AHC_NONE; - probe_config->features = AHC_FENONE; - probe_config->bugs = AHC_BUGNONE; - probe_config->flags = AHC_FNONE; -} - static void ahc_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) { @@ -3794,7 +3871,8 @@ ahc_init_scbdata(struct ahc_softc *ahc) /* DMA tag for our hardware scb structures */ if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, - /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR, + /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, + /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, AHC_SCB_MAX * sizeof(struct hardware_scb), @@ -3806,7 +3884,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) scb_data->init_level++; - /* Allocation for our ccbs */ + /* Allocation for our hscbs */ if (ahc_dmamem_alloc(ahc, scb_data->hscb_dmat, (void **)&scb_data->hscbs, BUS_DMA_NOWAIT, &scb_data->hscb_dmamap) != 0) { @@ -3825,7 +3903,8 @@ ahc_init_scbdata(struct ahc_softc *ahc) /* DMA tag for our sense buffers */ if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, - /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR, + /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, + /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, AHC_SCB_MAX * sizeof(struct scsi_sense_data), @@ -3856,7 +3935,8 @@ ahc_init_scbdata(struct ahc_softc *ahc) /* DMA tag for our S/G structures. We allocate in page sized chunks */ if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, - /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR, + /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, + /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, PAGE_SIZE, /*nsegments*/1, @@ -3999,6 +4079,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc) if (pdata == NULL) break; next_scb->platform_data = pdata; + next_scb->sg_map = sg_map; next_scb->sg_list = segs; /* * The sequencer always starts with the second entry. @@ -4126,7 +4207,8 @@ ahc_init(struct ahc_softc *ahc) #ifndef __linux__ /* DMA tag for mapping buffers into device visible space. */ if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, - /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR, + /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, + /*lowaddr*/BUS_SPACE_MAXADDR, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/MAXBSIZE, /*nsegments*/AHC_NSEG, @@ -4153,7 +4235,8 @@ ahc_init(struct ahc_softc *ahc) driver_data_size += AHC_TMODE_CMDS * sizeof(struct target_cmd) + /*DMA WideOdd Bug Buffer*/1; if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, - /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR, + /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, + /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, driver_data_size, @@ -4187,6 +4270,7 @@ ahc_init(struct ahc_softc *ahc) /* All target command blocks start out invalid. */ for (i = 0; i < AHC_TMODE_CMDS; i++) ahc->targetcmds[i].cmd_valid = 0; + ahc_sync_tqinfifo(ahc, BUS_DMASYNC_PREREAD); ahc->tqinfifonext = 1; ahc_outb(ahc, KERNEL_TQINPOS, ahc->tqinfifonext - 1); ahc_outb(ahc, TQINPOS, ahc->tqinfifonext); @@ -4431,6 +4515,7 @@ ahc_init(struct ahc_softc *ahc) /* All of our queues are empty */ for (i = 0; i < 256; i++) ahc->qoutfifo[i] = SCB_LIST_NULL; + ahc_sync_qoutfifo(ahc, BUS_DMASYNC_PREREAD); for (i = 0; i < 256; i++) ahc->qinfifo[i] = SCB_LIST_NULL; @@ -4896,12 +4981,16 @@ static void ahc_qinfifo_requeue(struct ahc_softc *ahc, struct scb *prev_scb, struct scb *scb) { - if (prev_scb == NULL) + if (prev_scb == NULL) { ahc_outb(ahc, NEXT_QUEUED_SCB, scb->hscb->tag); - else + } else { prev_scb->hscb->next = scb->hscb->tag; + ahc_sync_scb(ahc, prev_scb, + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + } ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag; scb->hscb->next = ahc->next_queued_scb->hscb->tag; + ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); } static int @@ -4948,6 +5037,9 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, found = 0; prev_scb = NULL; + if (bootverbose) + printf("qinpos = %d, qintail = %d\n", qinpos, qintail); + if (action == SEARCH_COMPLETE) { /* * Don't attempt to run any queued untagged transactions @@ -4965,6 +5057,12 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, while (qinpos != qintail) { scb = ahc_lookup_scb(ahc, ahc->qinfifo[qinpos]); + if (scb == NULL) { + printf("qinpos = %d, SCB index = %d\n", + qinpos, ahc->qinfifo[qinpos]); + panic("Loop 1\n"); + } + if (ahc_match_scb(ahc, scb, target, channel, lun, tag, role)) { /* * We found an scb that needs to be acted on. @@ -5026,6 +5124,11 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, */ scb = ahc_lookup_scb(ahc, ahc->qinfifo[qinstart]); + if (scb == NULL) { + printf("found = %d, qinstart = %d, qinfifionext = %d\n", + found, qinstart, ahc->qinfifonext); + panic("First/Second Qinfifo fixup\n"); + } /* * ahc_swap_with_next_hscb forces our next pointer to * point to the reserved SCB for future commands. Save @@ -5067,6 +5170,11 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, panic("for safety"); } scb = ahc_lookup_scb(ahc, scb_index); + if (scb == NULL) { + printf("scb_index = %d, next = %d\n", + scb_index, next); + panic("Waiting List traversal\n"); + } if (ahc_match_scb(ahc, scb, target, channel, lun, SCB_LIST_NULL, role)) { /* @@ -5490,6 +5598,8 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset) struct ahc_devinfo devinfo; u_int initiator, target, max_scsiid; u_int sblkctl; + u_int scsiseq; + u_int simode1; int found; int restart_needed; char cur_channel; @@ -5526,31 +5636,48 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset) if ((ahc->features & AHC_TWIN) != 0 && ((sblkctl & SELBUSB) != 0)) cur_channel = 'B'; + scsiseq = ahc_inb(ahc, SCSISEQ_TEMPLATE); if (cur_channel != channel) { /* Case 1: Command for another bus is active * Stealthily reset the other bus without * upsetting the current bus. */ ahc_outb(ahc, SBLKCTL, sblkctl ^ SELBUSB); - ahc_outb(ahc, SIMODE1, - ahc_inb(ahc, SIMODE1) & ~(ENBUSFREE|ENSCSIRST)); - ahc_outb(ahc, SCSISEQ, - ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP)); + simode1 = ahc_inb(ahc, SIMODE1) & ~(ENBUSFREE|ENSCSIRST); + ahc_outb(ahc, SIMODE1, simode1); if (initiate_reset) ahc_reset_current_bus(ahc); ahc_clear_intstat(ahc); +#if AHC_TARGET_MODE + /* + * Bus resets clear ENSELI, so we cannot + * defer re-enabling bus reset interrupts + * if we are in target mode. + */ + if ((ahc->flags & AHC_TARGETROLE) != 0) + ahc_outb(ahc, SIMODE1, simode1 | ENSCSIRST); +#endif + ahc_outb(ahc, SCSISEQ, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP)); ahc_outb(ahc, SBLKCTL, sblkctl); restart_needed = FALSE; } else { /* Case 2: A command from this bus is active or we're idle */ ahc_clear_msg_state(ahc); - ahc_outb(ahc, SIMODE1, - ahc_inb(ahc, SIMODE1) & ~(ENBUSFREE|ENSCSIRST)); - ahc_outb(ahc, SCSISEQ, - ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP)); + simode1 = ahc_inb(ahc, SIMODE1) & ~(ENBUSFREE|ENSCSIRST); + ahc_outb(ahc, SIMODE1, simode1); if (initiate_reset) ahc_reset_current_bus(ahc); ahc_clear_intstat(ahc); +#if AHC_TARGET_MODE + /* + * Bus resets clear ENSELI, so we cannot + * defer re-enabling bus reset interrupts + * if we are in target mode. + */ + if ((ahc->flags & AHC_TARGETROLE) != 0) + ahc_outb(ahc, SIMODE1, simode1 | ENSCSIRST); +#endif + ahc_outb(ahc, SCSISEQ, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP)); restart_needed = TRUE; } @@ -5702,7 +5829,7 @@ ahc_calc_residual(struct scb *scb) ahc_set_sense_residual(scb, resid); #ifdef AHC_DEBUG - if (ahc_debug & AHC_SHOWMISC) { + if ((ahc_debug & AHC_SHOWMISC) != 0) { ahc_print_path(ahc, scb); printf("Handled Residual of %d bytes\n", resid); } @@ -6157,6 +6284,7 @@ ahc_dump_card_state(struct ahc_softc *ahc) } printf("\n"); + ahc_sync_qoutfifo(ahc, BUS_DMASYNC_POSTREAD); printf("QOUTFIFO entries: "); qoutpos = ahc->qoutfifonext; i = 0; @@ -6629,6 +6757,7 @@ ahc_run_tqinfifo(struct ahc_softc *ahc, int paused) if ((ahc->features & AHC_AUTOPAUSE) != 0) paused = TRUE; + ahc_sync_tqinfifo(ahc, BUS_DMASYNC_POSTREAD); while ((cmd = &ahc->targetcmds[ahc->tqinfifonext])->cmd_valid != 0) { /* @@ -6638,8 +6767,13 @@ ahc_run_tqinfifo(struct ahc_softc *ahc, int paused) if (ahc_handle_target_cmd(ahc, cmd) != 0) break; - ahc->tqinfifonext++; cmd->cmd_valid = 0; + ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + ahc->shared_data_dmamap, + ahc_targetcmd_offset(ahc, ahc->tqinfifonext), + sizeof(struct target_cmd), + BUS_DMASYNC_PREREAD); + ahc->tqinfifonext++; /* * Lazily update our position in the target mode incoming diff --git a/sys/dev/aic7xxx/aic7xxx.h b/sys/dev/aic7xxx/aic7xxx.h index 4eded92..cc5bf76 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#27 $ + * $Id: //depot/src/aic7xxx/aic7xxx.h#29 $ * * $FreeBSD$ */ @@ -335,22 +335,10 @@ typedef enum { AHC_BIOS_ENABLED = 0x80000, AHC_ALL_INTERRUPTS = 0x100000, AHC_PAGESCBS = 0x400000, /* Enable SCB paging */ - AHC_EDGE_INTERRUPT = 0x800000 /* Device uses edge triggered ints */ + AHC_EDGE_INTERRUPT = 0x800000, /* Device uses edge triggered ints */ + AHC_39BIT_ADDRESSING = 0x1000000 /* Use 39 bit addressing scheme. */ } ahc_flag; -/* - * Controller Information composed at probe time. - */ -struct ahc_probe_config { - const char *description; - char channel; - char channel_b; - ahc_chip chip; - ahc_feature features; - ahc_bug bugs; - ahc_flag flags; -}; - /************************* Hardware SCB Definition ***************************/ /* @@ -499,6 +487,13 @@ struct ahc_dma_seg { #define AHC_SG_LEN_MASK 0x00FFFFFF }; +struct sg_map_node { + bus_dmamap_t sg_dmamap; + bus_addr_t sg_physaddr; + struct ahc_dma_seg* sg_vaddr; + SLIST_ENTRY(sg_map_node) links; +}; + /* * The current state of this SCB. */ @@ -538,18 +533,12 @@ struct scb { bus_dmamap_t dmamap; #endif struct scb_platform_data *platform_data; - struct ahc_dma_seg *sg_list; + struct sg_map_node *sg_map; + struct ahc_dma_seg *sg_list; bus_addr_t sg_list_phys; u_int sg_count;/* How full ahc_dma_seg is */ }; -struct sg_map_node { - bus_dmamap_t sg_dmamap; - bus_addr_t sg_physaddr; - struct ahc_dma_seg* sg_vaddr; - SLIST_ENTRY(sg_map_node) links; -}; - struct scb_data { SLIST_HEAD(, scb) free_scbs; /* * Pool of SCBs ready to be assigned @@ -865,7 +854,7 @@ struct ahc_softc { /* * SCBs that have been sent to the controller */ - LIST_HEAD(, scb) pending_scbs; + LIST_HEAD(, scb) pending_scbs; /* * Counting lock for deferring the release of additional @@ -1039,8 +1028,7 @@ struct ahc_devinfo { }; /****************************** PCI Structures ********************************/ -typedef int (ahc_device_setup_t)(ahc_dev_softc_t, - struct ahc_probe_config *); +typedef int (ahc_device_setup_t)(struct ahc_softc *); struct ahc_pci_identity { uint64_t full_id; @@ -1093,10 +1081,8 @@ int ahc_match_scb(struct ahc_softc *ahc, struct scb *scb, u_int tag, role_t role); /****************************** Initialization ********************************/ -void ahc_init_probe_config(struct ahc_probe_config *); struct ahc_softc *ahc_alloc(void *platform_arg, char *name); -int ahc_softc_init(struct ahc_softc *, - struct ahc_probe_config*); +int ahc_softc_init(struct ahc_softc *); void ahc_controller_info(struct ahc_softc *ahc, char *buf); int ahc_init(struct ahc_softc *ahc); void ahc_intr_enable(struct ahc_softc *ahc, int enable); diff --git a/sys/dev/aic7xxx/aic7xxx.reg b/sys/dev/aic7xxx/aic7xxx.reg index 91c6b8a..6d44293 100644 --- a/sys/dev/aic7xxx/aic7xxx.reg +++ b/sys/dev/aic7xxx/aic7xxx.reg @@ -28,10 +28,9 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: //depot/src/aic7xxx/aic7xxx.reg#17 $ - * * $FreeBSD$ */ +VERSION = "$Id: //depot/src/aic7xxx/aic7xxx.reg#19 $" /* * This file is processed by the aic7xxx_asm utility for use in assembling @@ -683,8 +682,16 @@ register DSCOMMAND0 { bit CIOPARCKEN 0x01 /* Internal bus parity error enable */ } +register DSCOMMAND1 { + address 0x085 + access_mode RW + mask DSLATT 0xfc /* PCI latency timer (non-ultra2) */ + bit HADDLDSEL1 0x02 /* Host Address Load Select Bits */ + bit HADDLDSEL0 0x01 +} + /* - * Bus On/Off Time (p. 3-44) + * Bus On/Off Time (p. 3-44) aic7770 only */ register BUSTIME { address 0x085 @@ -781,7 +788,13 @@ register INTSTAT { mask NO_IDENT 0x20|SEQINT /* no IDENTIFY after reconnect*/ mask NO_MATCH 0x30|SEQINT /* no cmd match for reconnect */ mask IGN_WIDE_RES 0x40|SEQINT /* Complex IGN Wide Res Msg */ - mask RESIDUAL 0x50|SEQINT /* Residual byte count != 0 */ + mask PDATA_REINIT 0x50|SEQINT /* + * Returned to data phase + * that requires data + * transfer pointers to be + * recalculated from the + * transfer residual. + */ mask HOST_MSG_LOOP 0x60|SEQINT /* * The bus is ready for the * host to perform another diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq index c50a99c..179445c 100644 --- a/sys/dev/aic7xxx/aic7xxx.seq +++ b/sys/dev/aic7xxx/aic7xxx.seq @@ -28,11 +28,11 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: //depot/src/aic7xxx/aic7xxx.seq#27 $ - * * $FreeBSD$ */ +VERSION = "$Id: //depot/src/aic7xxx/aic7xxx.seq#32 $" + #include "aic7xxx.reg" #include "scsi_message.h" @@ -175,16 +175,7 @@ select_in: * We've just been selected. Assert BSY and * setup the phase for receiving messages * from the target. - * - * If bus reset interrupts have been disabled (from a - * previous reset), re-enable them now. Resets are only - * of interest when we have outstanding transactions, so - * we can safely defer re-enabling the interrupt until, - * as a target, we start receiving transactions again. */ - test SIMODE1, ENSCSIRST jnz . + 3; - mvi CLRSINT1, CLRSCSIRSTI; - or SIMODE1, ENSCSIRST; mvi SCSISIGO, P_MESGOUT|BSYO; /* @@ -749,13 +740,13 @@ idle_sg_avail: if ((ahc->features & AHC_ULTRA2) != 0) { /* Does the hardware have space for another SG entry? */ test DFSTATUS, PRELOAD_AVAIL jz return; - bmov HADDR, CCSGRAM, 4; - bmov SINDEX, CCSGRAM, 1; - test SINDEX, 0x1 jz . + 2; + bmov HADDR, CCSGRAM, 7; + test HCNT[0], 0x1 jz . + 2; xor DATA_COUNT_ODD, 0x1; - bmov HCNT[0], SINDEX, 1; - bmov HCNT[1], CCSGRAM, 2; bmov SCB_RESIDUAL_DATACNT[3], CCSGRAM, 1; + if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { + mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr; + } call sg_advance; mov SINDEX, SCB_RESIDUAL_SGPTR[0]; test DATA_COUNT_ODD, 0x1 jz . + 2; @@ -803,29 +794,10 @@ calc_mwi_residual_final: adc HCNT[2], -1 ret; } -/* - * If we re-enter the data phase after going through another phase, the - * STCNT may have been cleared, so restore it from the residual field. - */ -data_phase_reinit: - if ((ahc->features & AHC_ULTRA2) != 0) { - /* - * The preload circuitry requires us to - * reload the address too, so pull it from - * the shaddow address. - */ - bmov HADDR, SHADDR, 4; - bmov HCNT, SCB_RESIDUAL_DATACNT, 3; - } else if ((ahc->features & AHC_CMD_CHAN) != 0) { - bmov STCNT, SCB_RESIDUAL_DATACNT, 3; - } else { - mvi DINDEX, STCNT; - mvi SCB_RESIDUAL_DATACNT call bcopy_3; - } - and DATA_COUNT_ODD, 0x1, SCB_RESIDUAL_DATACNT[0]; - jmp data_phase_loop; - p_data: + test SEQ_FLAGS,IDENTIFY_SEEN jnz p_data_okay; + mvi NO_IDENT jmp set_seqint; +p_data_okay: if ((ahc->features & AHC_ULTRA2) != 0) { mvi DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN; } else { @@ -833,17 +805,23 @@ p_data: } test LASTPHASE, IOI jnz . + 2; or DMAPARAMS, DIRECTION; - call assert; /* - * Ensure entering a data - * phase is okay - seen identify, etc. - */ if ((ahc->features & AHC_CMD_CHAN) != 0) { /* We don't have any valid S/G elements */ mvi CCSGADDR, SG_PREFETCH_CNT; } - test SEQ_FLAGS, DPHASE jnz data_phase_reinit; + test SEQ_FLAGS, DPHASE jz data_phase_initialize; - /* We have seen a data phase */ + /* + * If we re-enter the data phase after going through another + * phase, our transfer location has almost certainly been + * corrupted by the interveining, non-data, transfers. Ask + * the host driver to fix us up based on the transfer residual. + */ + mvi PDATA_REINIT call set_seqint; + jmp data_phase_loop; + +data_phase_initialize: + /* We have seen a data phase for the first time */ or SEQ_FLAGS, DPHASE; /* @@ -853,6 +831,10 @@ p_data: * modify the saved values in the SCB until we see a save * data pointers message. */ + if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { + /* The lowest address byte must be loaded last. */ + mov SCB_DATACNT[3] call set_hhaddr; + } if ((ahc->features & AHC_CMD_CHAN) != 0) { bmov HADDR, SCB_DATAPTR, 7; bmov SCB_RESIDUAL_DATACNT[3], SCB_DATACNT[3], 5; @@ -1057,6 +1039,29 @@ ultra2_fifoempty: ultra2_dmahalt: and DFCNTRL, ~(SCSIEN|HDMAEN); test DFCNTRL, SCSIEN|HDMAEN jnz .; + if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { + /* + * Keep HHADDR cleared for future, 32bit addressed + * only, DMA operations. + * + * Due to bayonette style S/G handling, our residual + * data must be "fixed up" once the transfer is halted. + * Here we fixup the HSHADDR stored in the high byte + * of the residual data cnt. By postponing the fixup, + * we can batch the clearing of HADDR with the fixup. + * If we halted on the last segment, the residual is + * already correct. If we are not on the last + * segment, copy the high address directly from HSHADDR. + * We don't need to worry about maintaining the + * SG_LAST_SEG flag as it will always be false in the + * case where an update is required. + */ + or DSCOMMAND1, HADDLDSEL0; + test SG_CACHE_SHADOW, LAST_SEG jnz . + 2; + mov SCB_RESIDUAL_DATACNT[3], SHADDR; + clr HADDR; + and DSCOMMAND1, ~HADDLDSEL0; + } } else { /* If we are the last SG block, tell the hardware. */ if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 @@ -1163,9 +1168,18 @@ sg_load: call idle_loop; test CCSGCTL, CCSGEN jnz . - 1; bmov HADDR, CCSGRAM, 7; - test CCSGRAM, SG_LAST_SEG jz . + 2; - or SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG; + /* + * Workaround for flaky external SCB RAM + * on certain aic7895 setups. It seems + * unable to handle direct transfers from + * S/G ram to certain SCB locations. + */ + mov SINDEX, CCSGRAM; + mov SCB_RESIDUAL_DATACNT[3], SINDEX; } else { + if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { + mov ALLZEROS call set_hhaddr; + } mvi DINDEX, HADDR; mvi SCB_RESIDUAL_SGPTR call bcopy_4; @@ -1180,6 +1194,17 @@ sg_load: mov SCB_RESIDUAL_DATACNT[3], DFDAT; } + if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { + mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr; + + /* + * The lowest address byte must be loaded + * last as it triggers the computation of + * some items in the PCI block. The ULTRA2 + * chips do this on PRELOAD. + */ + mov HADDR, HADDR; + } if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) { call calc_mwi_residual; @@ -1234,6 +1259,24 @@ data_phase_done: call disable_ccsgen; } + if ((ahc->features & AHC_ULTRA2) == 0) { + /* + * Clear the high address byte so that all other DMA + * operations, which use 32bit addressing, can assume + * HHADDR is 0. + */ + if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { + mov ALLZEROS call set_hhaddr; + } + } + + /* + * Update our residual information before the information is + * lost by some other type of SCSI I/O (e.g. PIO). If we have + * transferred all data, no update is needed. + * + */ + test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jnz residual_update_done; if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) { if ((ahc->features & AHC_CMD_CHAN) != 0) { @@ -1257,7 +1300,7 @@ bmov_resid: mov SCB_RESIDUAL_DATACNT[1], STCNT[1]; mov SCB_RESIDUAL_DATACNT[2], STCNT[2]; } - +residual_update_done: /* * Since we've been through a data phase, the SCB_RESID* fields * are now initialized. Clear the full residual flag. @@ -1289,7 +1332,9 @@ if ((ahc->flags & AHC_INITIATORROLE) != 0) { * Command phase. Set up the DMA registers and let 'er rip. */ p_command: - call assert; + test SEQ_FLAGS,IDENTIFY_SEEN jnz p_command_okay; + mvi NO_IDENT jmp set_seqint; +p_command_okay: if ((ahc->features & AHC_ULTRA2) != 0) { bmov HCNT[0], SCB_CDB_LEN, 1; @@ -1383,8 +1428,9 @@ p_command_loop: * and store it into the SCB. */ p_status: - call assert; - + test SEQ_FLAGS,IDENTIFY_SEEN jnz p_status_okay; + mvi NO_IDENT jmp set_seqint; +p_status_okay: mov SCB_SCSI_STATUS, SCSIDATL; jmp ITloop; @@ -1626,6 +1672,18 @@ mesgin_sdptrs: } else { test SEQ_FLAGS, DPHASE jz mesgin_done; } + + /* + * If we are asked to save our position at the end of the + * transfer, just mark us at the end rather than perform a + * full save. + */ + test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz mesgin_sdptrs_full; + or SCB_SGPTR, SG_LIST_NULL; + jmp mesgin_done; + +mesgin_sdptrs_full: + /* * The SCB_SGPTR becomes the next one we'll download, * and the SCB_DATAPTR becomes the current SHADDR. @@ -1907,16 +1965,6 @@ target_outb: and SXFRCTL0, ~SPIOEN ret; } - -/* - * Assert that if we've been reselected, then we've seen an IDENTIFY - * message. - */ -assert: - test SEQ_FLAGS,IDENTIFY_SEEN jnz return; /* seen IDENTIFY? */ - - mvi NO_IDENT jmp set_seqint; /* no - tell the kernel */ - /* * Locate a disconnected SCB by SCBID. Upon return, SCBPTR and SINDEX will * be set to the position of the SCB. If the SCB cannot be found locally, @@ -2250,6 +2298,13 @@ END_CRITICAL mvi SCB_TAG, SCB_LIST_NULL ret; } +if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { +set_hhaddr: + or DSCOMMAND1, HADDLDSEL0; + and HADDR, SG_HIGH_ADDR_BITS, SINDEX; + and DSCOMMAND1, ~HADDLDSEL0 ret; +} + if ((ahc->flags & AHC_PAGESCBS) != 0) { get_free_or_disc_scb: BEGIN_CRITICAL diff --git a/sys/dev/aic7xxx/aic7xxx_93cx6.c b/sys/dev/aic7xxx/aic7xxx_93cx6.c index e3eaedd..c2a216d 100644 --- a/sys/dev/aic7xxx/aic7xxx_93cx6.c +++ b/sys/dev/aic7xxx/aic7xxx_93cx6.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_93cx6.c#7 $ + * $Id: //depot/src/aic7xxx/aic7xxx_93cx6.c#8 $ * * $FreeBSD$ */ diff --git a/sys/dev/aic7xxx/aic7xxx_freebsd.c b/sys/dev/aic7xxx/aic7xxx_freebsd.c index e06a1d6..6582f8c 100644 --- a/sys/dev/aic7xxx/aic7xxx_freebsd.c +++ b/sys/dev/aic7xxx/aic7xxx_freebsd.c @@ -1106,9 +1106,12 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, /* Copy the segments into our SG list */ sg = scb->sg_list; while (dm_segs < end_seg) { - sg->addr = dm_segs->ds_addr; -/* XXX Add in the 5th byte of the address later. */ - sg->len = dm_segs->ds_len; + uint32_t len; + + sg->addr = ahc_htole32(dm_segs->ds_addr); + len = dm_segs->ds_len + | ((dm_segs->ds_addr >> 8) & 0x7F000000); + sg->len = ahc_htole32(len); sg++; dm_segs++; } @@ -1119,7 +1122,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, * sequencer will clear as soon as a data transfer * occurs. */ - scb->hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID; + scb->hscb->sgptr = ahc_htole32(scb->sg_list_phys|SG_FULL_RESID); if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) op = BUS_DMASYNC_PREREAD; @@ -1165,13 +1168,13 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, xpt_done(ccb); return; } - sg->addr = ahc->dma_bug_buf; - sg->len = 1; + sg->addr = ahc_htole32(ahc->dma_bug_buf); + sg->len = ahc_htole32(1); sg++; } } sg--; - sg->len |= AHC_DMA_LAST_SEG; + sg->len |= ahc_htole32(AHC_DMA_LAST_SEG); /* Copy the first SG into the "current" data pointer area */ scb->hscb->dataptr = scb->sg_list->addr; @@ -1297,6 +1300,8 @@ ahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim, hscb = scb->hscb; ccb_h = &csio->ccb_h; + csio->resid = 0; + csio->sense_resid = 0; if (ccb_h->func_code == XPT_SCSI_IO) { hscb->cdb_len = csio->cdb_len; if ((ccb_h->flags & CAM_CDB_POINTER) != 0) { diff --git a/sys/dev/aic7xxx/aic7xxx_freebsd.h b/sys/dev/aic7xxx/aic7xxx_freebsd.h index f90caba..b12a2d6 100644 --- a/sys/dev/aic7xxx/aic7xxx_freebsd.h +++ b/sys/dev/aic7xxx/aic7xxx_freebsd.h @@ -138,8 +138,9 @@ typedef union ccb *ahc_io_ctx_t; #define ahc_dmamap_unload(ahc, tag, map) \ bus_dmamap_unload(tag, map) -#define ahc_dmamap_sync(ahc, dma_tag, dmamap, op) \ - bus_dmamap_sync(dma_tag_dmamap, op) +/* XXX Need to update Bus DMA for partial map syncs */ +#define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op) \ + bus_dmamap_sync(dma_tag, dmamap, op) /************************ Tunable Driver Parameters **************************/ /* diff --git a/sys/dev/aic7xxx/aic7xxx_inline.h b/sys/dev/aic7xxx/aic7xxx_inline.h index ddf1bb5..c5db614 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#21 $ + * $Id: //depot/src/aic7xxx/aic7xxx_inline.h#27 $ * * $FreeBSD$ */ @@ -37,8 +37,8 @@ #define _AIC7XXX_INLINE_H_ /************************* Sequencer Execution Control ************************/ -static __inline int ahc_is_paused(struct ahc_softc *ahc); static __inline void ahc_pause_bug_fix(struct ahc_softc *ahc); +static __inline int ahc_is_paused(struct ahc_softc *ahc); static __inline void ahc_pause(struct ahc_softc *ahc); static __inline void ahc_unpause(struct ahc_softc *ahc); @@ -146,6 +146,13 @@ static __inline uint32_t struct ahc_dma_seg *sg); static __inline uint32_t ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index); +static __inline void ahc_sync_scb(struct ahc_softc *ahc, + struct scb *scb, int op); +static __inline void ahc_sync_sglist(struct ahc_softc *ahc, + struct scb *scb, int op); +static __inline uint32_t + ahc_targetcmd_offset(struct ahc_softc *ahc, + u_int index); static __inline struct ahc_dma_seg * ahc_sg_bus_to_virt(struct scb *scb, uint32_t sg_busaddr) @@ -177,6 +184,33 @@ ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index) + (sizeof(struct hardware_scb) * index)); } +static __inline void +ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op) +{ + ahc_dmamap_sync(ahc, ahc->scb_data->hscb_dmat, + ahc->scb_data->hscb_dmamap, + /*offset*/(scb->hscb - ahc->hscbs) * sizeof(*scb->hscb), + /*len*/sizeof(*scb->hscb), op); +} + +static __inline void +ahc_sync_sglist(struct ahc_softc *ahc, struct scb *scb, int op) +{ + if (scb->sg_count == 0) + return; + + ahc_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap, + /*offset*/(scb->sg_list - scb->sg_map->sg_vaddr) + * sizeof(struct ahc_dma_seg), + /*len*/sizeof(struct ahc_dma_seg) * scb->sg_count, op); +} + +static __inline uint32_t +ahc_targetcmd_offset(struct ahc_softc *ahc, u_int index) +{ + return (((uint8_t *)&ahc->targetcmds[index]) - ahc->qoutfifo); +} + /******************************** Debugging ***********************************/ static __inline char *ahc_name(struct ahc_softc *ahc); @@ -219,8 +253,6 @@ ahc_update_residual(struct scb *scb) sgptr = ahc_le32toh(scb->hscb->sgptr); if ((sgptr & SG_RESID_VALID) != 0) ahc_calc_residual(scb); - else - ahc_set_residual(scb, 0); } /* @@ -284,8 +316,13 @@ ahc_free_scb(struct ahc_softc *ahc, struct scb *scb) static __inline struct scb * ahc_lookup_scb(struct ahc_softc *ahc, u_int tag) { - return (ahc->scb_data->scbindex[tag]); + struct scb* scb; + scb = ahc->scb_data->scbindex[tag]; + if (scb != NULL) + ahc_sync_scb(ahc, scb, + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + return (scb); } static __inline void @@ -342,6 +379,14 @@ ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb) * Keep a history of SCBs we've downloaded in the qinfifo. */ ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag; + + /* + * Make sure our data is consistant from the + * perspective of the adapter. + */ + ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + + /* Tell the adapter about the newly queued SCB */ if ((ahc->features & AHC_QUEUE_REGS) != 0) { ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext); } else { @@ -373,8 +418,31 @@ ahc_get_sense_bufaddr(struct ahc_softc *ahc, struct scb *scb) } /************************** Interrupt Processing ******************************/ -static __inline u_int ahc_check_cmdcmpltqueues(struct ahc_softc *ahc); -static __inline void ahc_intr(struct ahc_softc *ahc); +static __inline void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op); +static __inline void ahc_sync_tqinfifo(struct ahc_softc *ahc, int op); +static __inline u_int ahc_check_cmdcmpltqueues(struct ahc_softc *ahc); +static __inline void ahc_intr(struct ahc_softc *ahc); + +static __inline void +ahc_sync_qoutfifo(struct ahc_softc *ahc, int op) +{ + ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, + /*offset*/0, /*len*/256, op); +} + +static __inline void +ahc_sync_tqinfifo(struct ahc_softc *ahc, int op) +{ +#ifdef AHC_TARGET_MODE + if ((ahc->flags & AHC_TARGETROLE) != 0) { + ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + ahc->shared_data_dmamap, + ahc_targetcmd_offset(ahc, 0), + sizeof(struct target_cmd) * AHC_TMODE_CMDS, + op); + } +#endif +} /* * See if the firmware has posted any completed commands @@ -388,12 +456,21 @@ ahc_check_cmdcmpltqueues(struct ahc_softc *ahc) u_int retval; retval = 0; + ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, + /*offset*/ahc->qoutfifonext, /*len*/1, + BUS_DMASYNC_POSTREAD); if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL) retval |= AHC_RUN_QOUTFIFO; #ifdef AHC_TARGET_MODE - if ((ahc->flags & AHC_TARGETROLE) != 0 - && ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0) - retval |= AHC_RUN_TQINFIFO; + if ((ahc->flags & AHC_TARGETROLE) != 0) { + ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + ahc->shared_data_dmamap, + ahc_targetcmd_offset(ahc, ahc->tqinfifofnext), + /*len*/sizeof(struct target_cmd), + BUS_DMASYNC_POSTREAD); + if (ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0) + retval |= AHC_RUN_TQINFIFO; + } #endif return (retval); } @@ -418,36 +495,13 @@ ahc_intr(struct ahc_softc *ahc) intstat = CMDCMPLT; else { intstat = ahc_inb(ahc, INTSTAT); - /* - * We can't generate queuestat once above - * or we are exposed to a race when our - * interrupt is shared with another device. - * if instat showed a command complete interrupt, - * but our first generation of queue stat - * "just missed" the delivery of this transaction, - * we would clear the command complete interrupt - * below without ever servicing the completed - * command. - */ - queuestat = ahc_check_cmdcmpltqueues(ahc); -#if AHC_PCI_CONFIG > 0 - if (ahc->unsolicited_ints > 500 - && (ahc->chip & AHC_PCI) != 0 - && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0) - ahc->bus_intr(ahc); + queuestat = AHC_RUN_QOUTFIFO; +#ifdef AHC_TARGET_MODE + if ((ahc->flags & AHC_TARGETROLE) != 0) + queuestat |= AHC_RUN_TQINFIFO; #endif } - if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0) - /* Hot eject */ - return; - - if ((intstat & INT_PEND) == 0) { - ahc->unsolicited_ints++; - return; - } - ahc->unsolicited_ints = 0; - if (intstat & CMDCMPLT) { ahc_outb(ahc, CLRINT, CLRCMDINT); @@ -469,6 +523,25 @@ ahc_intr(struct ahc_softc *ahc) ahc_run_tqinfifo(ahc, /*paused*/FALSE); #endif } + + if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0) + /* Hot eject */ + return; + + if ((intstat & INT_PEND) == 0) { +#if AHC_PCI_CONFIG > 0 + if (ahc->unsolicited_ints > 500) { + ahc->unsolicited_ints = 0; + if ((ahc->chip & AHC_PCI) != 0 + && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0) + ahc->bus_intr(ahc); + } +#endif + ahc->unsolicited_ints++; + return; + } + ahc->unsolicited_ints = 0; + if (intstat & BRKADRINT) { ahc_handle_brkadrint(ahc); /* Fatal error, no more interrupts to handle. */ diff --git a/sys/dev/aic7xxx/aic7xxx_osm.c b/sys/dev/aic7xxx/aic7xxx_osm.c index e06a1d6..6582f8c 100644 --- a/sys/dev/aic7xxx/aic7xxx_osm.c +++ b/sys/dev/aic7xxx/aic7xxx_osm.c @@ -1106,9 +1106,12 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, /* Copy the segments into our SG list */ sg = scb->sg_list; while (dm_segs < end_seg) { - sg->addr = dm_segs->ds_addr; -/* XXX Add in the 5th byte of the address later. */ - sg->len = dm_segs->ds_len; + uint32_t len; + + sg->addr = ahc_htole32(dm_segs->ds_addr); + len = dm_segs->ds_len + | ((dm_segs->ds_addr >> 8) & 0x7F000000); + sg->len = ahc_htole32(len); sg++; dm_segs++; } @@ -1119,7 +1122,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, * sequencer will clear as soon as a data transfer * occurs. */ - scb->hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID; + scb->hscb->sgptr = ahc_htole32(scb->sg_list_phys|SG_FULL_RESID); if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) op = BUS_DMASYNC_PREREAD; @@ -1165,13 +1168,13 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, xpt_done(ccb); return; } - sg->addr = ahc->dma_bug_buf; - sg->len = 1; + sg->addr = ahc_htole32(ahc->dma_bug_buf); + sg->len = ahc_htole32(1); sg++; } } sg--; - sg->len |= AHC_DMA_LAST_SEG; + sg->len |= ahc_htole32(AHC_DMA_LAST_SEG); /* Copy the first SG into the "current" data pointer area */ scb->hscb->dataptr = scb->sg_list->addr; @@ -1297,6 +1300,8 @@ ahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim, hscb = scb->hscb; ccb_h = &csio->ccb_h; + csio->resid = 0; + csio->sense_resid = 0; if (ccb_h->func_code == XPT_SCSI_IO) { hscb->cdb_len = csio->cdb_len; if ((ccb_h->flags & CAM_CDB_POINTER) != 0) { diff --git a/sys/dev/aic7xxx/aic7xxx_osm.h b/sys/dev/aic7xxx/aic7xxx_osm.h index f90caba..b12a2d6 100644 --- a/sys/dev/aic7xxx/aic7xxx_osm.h +++ b/sys/dev/aic7xxx/aic7xxx_osm.h @@ -138,8 +138,9 @@ typedef union ccb *ahc_io_ctx_t; #define ahc_dmamap_unload(ahc, tag, map) \ bus_dmamap_unload(tag, map) -#define ahc_dmamap_sync(ahc, dma_tag, dmamap, op) \ - bus_dmamap_sync(dma_tag_dmamap, op) +/* XXX Need to update Bus DMA for partial map syncs */ +#define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op) \ + bus_dmamap_sync(dma_tag, dmamap, op) /************************ Tunable Driver Parameters **************************/ /* diff --git a/sys/dev/aic7xxx/aic7xxx_pci.c b/sys/dev/aic7xxx/aic7xxx_pci.c index 0a7b4f3..bee6caf 100644 --- a/sys/dev/aic7xxx/aic7xxx_pci.c +++ b/sys/dev/aic7xxx/aic7xxx_pci.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: //depot/src/aic7xxx/aic7xxx_pci.c#24 $ + * $Id: //depot/src/aic7xxx/aic7xxx_pci.c#27 $ * * $FreeBSD$ */ @@ -628,9 +628,10 @@ const u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table); #define DEVCONFIG 0x40 #define SCBSIZE32 0x00010000ul /* aic789X only */ #define REXTVALID 0x00001000ul /* ultra cards only */ -#define MPORTMODE 0x00000400ul /* aic7870 only */ -#define RAMPSM 0x00000200ul /* aic7870 only */ +#define MPORTMODE 0x00000400ul /* aic7870+ only */ +#define RAMPSM 0x00000200ul /* aic7870+ only */ #define VOLSENSE 0x00000100ul +#define PCI64BIT 0x00000080ul /* 64Bit PCI bus (Ultra2 Only)*/ #define SCBRAMSEL 0x00000080ul #define MRDCEN 0x00000040ul #define EXTSCBTIME 0x00000020ul /* aic7870 only */ @@ -693,9 +694,16 @@ ahc_find_pci_device(ahc_dev_softc_t pci) subdevice, subvendor); - /* If the second function is not hooked up, ignore it. */ + /* + * If the second function is not hooked up, ignore it. + * Unfortunately, not all MB vendors implement the + * subdevice ID as per the Adaptec spec, so do our best + * to sanity check it prior to accepting the subdevice + * ID as valid. + */ if (ahc_get_pci_function(pci) > 0 && subvendor == 0x9005 + && subdevice != device && SUBID_9005_TYPE_KNOWN(subdevice) != 0 && SUBID_9005_MFUNCENB(subdevice) == 0) return (NULL); @@ -715,7 +723,6 @@ ahc_find_pci_device(ahc_dev_softc_t pci) int ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) { - struct ahc_probe_config probe_config; struct scb_data *shared_scb_data; u_int command; u_int our_id = 0; @@ -726,12 +733,11 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) uint8_t sblkctl; shared_scb_data = NULL; - ahc_init_probe_config(&probe_config); - error = entry->setup(ahc->dev_softc, &probe_config); + error = entry->setup(ahc); if (error != 0) return (error); - probe_config.chip |= AHC_PCI; - probe_config.description = entry->name; + ahc->chip |= AHC_PCI; + ahc->description = entry->name; error = ahc_pci_map_registers(ahc); if (error != 0) @@ -739,15 +745,34 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) ahc_power_state_change(ahc, AHC_POWER_STATE_D0); + /* + * If we need to support high memory, enable dual + * address cycles. This bit must be set to enable + * high address bit generation even if we are on a + * 64bit bus (PCI64BIT set in devconfig). + */ + if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { + uint32_t devconfig; + + if (bootverbose) + printf("%s: Enabling 39Bit Addressing\n", + ahc_name(ahc)); + devconfig = ahc_pci_read_config(ahc->dev_softc, + DEVCONFIG, /*bytes*/4); + devconfig |= DACEN; + ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, + devconfig, /*bytes*/4); + } + /* Ensure busmastering is enabled */ command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); command |= PCIM_CMD_BUSMASTEREN; ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/1); /* On all PCI adapters, we allow SCB paging */ - probe_config.flags |= AHC_PAGESCBS; + ahc->flags |= AHC_PAGESCBS; - error = ahc_softc_init(ahc, &probe_config); + error = ahc_softc_init(ahc); if (error != 0) return (error); @@ -1764,14 +1789,15 @@ ahc_pci_intr(struct ahc_softc *ahc) printf("%s: Data Parity Error has been reported via PERR#\n", ahc_name(ahc)); } - if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) { - printf("%s: Latched PCIERR interrupt with " - "no status bits set\n", ahc_name(ahc)); - } + + /* Clear latched errors. */ ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, status1, /*bytes*/1); - if (status1 & (DPR|RMA|RTA)) { + if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) { + printf("%s: Latched PCIERR interrupt with " + "no status bits set\n", ahc_name(ahc)); + } else { ahc_outb(ahc, CLRINT, CLRPARERR); } @@ -1779,187 +1805,204 @@ ahc_pci_intr(struct ahc_softc *ahc) } static int -ahc_aic785X_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aic785X_setup(struct ahc_softc *ahc) { + ahc_dev_softc_t pci; uint8_t rev; - probe_config->channel = 'A'; - probe_config->chip = AHC_AIC7850; - probe_config->features = AHC_AIC7850_FE; - probe_config->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG - | AHC_PCI_MWI_BUG; + pci = ahc->dev_softc; + ahc->channel = 'A'; + ahc->chip = AHC_AIC7850; + ahc->features = AHC_AIC7850_FE; + ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 1) - probe_config->bugs |= AHC_PCI_2_1_RETRY_BUG; + ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; return (0); } static int -ahc_aic7860_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aic7860_setup(struct ahc_softc *ahc) { + ahc_dev_softc_t pci; uint8_t rev; - probe_config->channel = 'A'; - probe_config->chip = AHC_AIC7860; - probe_config->features = AHC_AIC7860_FE; - probe_config->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG - | AHC_PCI_MWI_BUG; + pci = ahc->dev_softc; + ahc->channel = 'A'; + ahc->chip = AHC_AIC7860; + ahc->features = AHC_AIC7860_FE; + ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 1) - probe_config->bugs |= AHC_PCI_2_1_RETRY_BUG; + ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; return (0); } static int -ahc_apa1480_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_apa1480_setup(struct ahc_softc *ahc) { + ahc_dev_softc_t pci; int error; - error = ahc_aic7860_setup(pci, probe_config); + pci = ahc->dev_softc; + error = ahc_aic7860_setup(ahc); if (error != 0) return (error); - probe_config->features |= AHC_REMOVABLE; + ahc->features |= AHC_REMOVABLE; return (0); } static int -ahc_aic7870_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aic7870_setup(struct ahc_softc *ahc) { - probe_config->channel = 'A'; - probe_config->chip = AHC_AIC7870; - probe_config->features = AHC_AIC7870_FE; - probe_config->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG - | AHC_PCI_MWI_BUG; + ahc_dev_softc_t pci; + + pci = ahc->dev_softc; + ahc->channel = 'A'; + ahc->chip = AHC_AIC7870; + ahc->features = AHC_AIC7870_FE; + ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; return (0); } static int -ahc_aha394X_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aha394X_setup(struct ahc_softc *ahc) { int error; - error = ahc_aic7870_setup(pci, probe_config); + error = ahc_aic7870_setup(ahc); if (error == 0) - error = ahc_aha394XX_setup(pci, probe_config); + error = ahc_aha394XX_setup(ahc); return (error); } static int -ahc_aha398X_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aha398X_setup(struct ahc_softc *ahc) { int error; - error = ahc_aic7870_setup(pci, probe_config); + error = ahc_aic7870_setup(ahc); if (error == 0) - error = ahc_aha398XX_setup(pci, probe_config); + error = ahc_aha398XX_setup(ahc); return (error); } static int -ahc_aha494X_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aha494X_setup(struct ahc_softc *ahc) { int error; - error = ahc_aic7870_setup(pci, probe_config); + error = ahc_aic7870_setup(ahc); if (error == 0) - error = ahc_aha494XX_setup(pci, probe_config); + error = ahc_aha494XX_setup(ahc); return (error); } static int -ahc_aic7880_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aic7880_setup(struct ahc_softc *ahc) { + ahc_dev_softc_t pci; uint8_t rev; - probe_config->channel = 'A'; - probe_config->chip = AHC_AIC7880; - probe_config->features = AHC_AIC7880_FE; - probe_config->bugs |= AHC_TMODE_WIDEODD_BUG; + pci = ahc->dev_softc; + ahc->channel = 'A'; + ahc->chip = AHC_AIC7880; + ahc->features = AHC_AIC7880_FE; + ahc->bugs |= AHC_TMODE_WIDEODD_BUG; rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 1) { - probe_config->bugs |= AHC_PCI_2_1_RETRY_BUG; + ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; } else { - probe_config->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; + ahc->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; } return (0); } static int -ahc_aha2940Pro_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aha2940Pro_setup(struct ahc_softc *ahc) { + ahc_dev_softc_t pci; int error; - probe_config->flags |= AHC_INT50_SPEEDFLEX; - error = ahc_aic7880_setup(pci, probe_config); + pci = ahc->dev_softc; + ahc->flags |= AHC_INT50_SPEEDFLEX; + error = ahc_aic7880_setup(ahc); return (0); } static int -ahc_aha394XU_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aha394XU_setup(struct ahc_softc *ahc) { int error; - error = ahc_aic7880_setup(pci, probe_config); + error = ahc_aic7880_setup(ahc); if (error == 0) - error = ahc_aha394XX_setup(pci, probe_config); + error = ahc_aha394XX_setup(ahc); return (error); } static int -ahc_aha398XU_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aha398XU_setup(struct ahc_softc *ahc) { int error; - error = ahc_aic7880_setup(pci, probe_config); + error = ahc_aic7880_setup(ahc); if (error == 0) - error = ahc_aha398XX_setup(pci, probe_config); + error = ahc_aha398XX_setup(ahc); return (error); } static int -ahc_aic7890_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aic7890_setup(struct ahc_softc *ahc) { + ahc_dev_softc_t pci; uint8_t rev; - probe_config->channel = 'A'; - probe_config->chip = AHC_AIC7890; - probe_config->features = AHC_AIC7890_FE; - probe_config->flags |= AHC_NEWEEPROM_FMT; + pci = ahc->dev_softc; + ahc->channel = 'A'; + ahc->chip = AHC_AIC7890; + ahc->features = AHC_AIC7890_FE; + ahc->flags |= AHC_NEWEEPROM_FMT; rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev == 0) - probe_config->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG; + ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG; return (0); } static int -ahc_aic7892_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aic7892_setup(struct ahc_softc *ahc) { - probe_config->channel = 'A'; - probe_config->chip = AHC_AIC7892; - probe_config->features = AHC_AIC7892_FE; - probe_config->flags |= AHC_NEWEEPROM_FMT; - probe_config->bugs |= AHC_SCBCHAN_UPLOAD_BUG; + ahc_dev_softc_t pci; + + pci = ahc->dev_softc; + ahc->channel = 'A'; + ahc->chip = AHC_AIC7892; + ahc->features = AHC_AIC7892_FE; + ahc->flags |= AHC_NEWEEPROM_FMT; + ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG; return (0); } static int -ahc_aic7895_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aic7895_setup(struct ahc_softc *ahc) { + ahc_dev_softc_t pci; uint8_t rev; - probe_config->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; + pci = ahc->dev_softc; + ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; /* * The 'C' revision of the aic7895 has a few additional features. */ rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 4) { - probe_config->chip = AHC_AIC7895C; - probe_config->features = AHC_AIC7895C_FE; + ahc->chip = AHC_AIC7895C; + ahc->features = AHC_AIC7895C_FE; } else { u_int command; - probe_config->chip = AHC_AIC7895; - probe_config->features = AHC_AIC7895_FE; + ahc->chip = AHC_AIC7895; + ahc->features = AHC_AIC7895_FE; /* * The BIOS disables the use of MWI transactions @@ -1970,14 +2013,14 @@ ahc_aic7895_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) command = ahc_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1); command |= PCIM_CMD_MWRICEN; ahc_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1); - probe_config->bugs |= AHC_PCI_MWI_BUG; + ahc->bugs |= AHC_PCI_MWI_BUG; } /* * XXX Does CACHETHEN really not work??? What about PCI retry? * on C level chips. Need to test, but for now, play it safe. */ - probe_config->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG - | AHC_CACHETHEN_BUG; + ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG + | AHC_CACHETHEN_BUG; #if 0 uint32_t devconfig; @@ -1991,116 +2034,131 @@ ahc_aic7895_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) devconfig |= MRDCEN; ahc_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1); #endif - probe_config->flags |= AHC_NEWEEPROM_FMT; + ahc->flags |= AHC_NEWEEPROM_FMT; return (0); } static int -ahc_aic7896_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aic7896_setup(struct ahc_softc *ahc) { - probe_config->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; - probe_config->chip = AHC_AIC7896; - probe_config->features = AHC_AIC7896_FE; - probe_config->flags |= AHC_NEWEEPROM_FMT; - probe_config->bugs |= AHC_CACHETHEN_DIS_BUG; + ahc_dev_softc_t pci; + + pci = ahc->dev_softc; + ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; + ahc->chip = AHC_AIC7896; + ahc->features = AHC_AIC7896_FE; + ahc->flags |= AHC_NEWEEPROM_FMT; + ahc->bugs |= AHC_CACHETHEN_DIS_BUG; return (0); } static int -ahc_aic7899_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aic7899_setup(struct ahc_softc *ahc) { - probe_config->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; - probe_config->chip = AHC_AIC7899; - probe_config->features = AHC_AIC7899_FE; - probe_config->flags |= AHC_NEWEEPROM_FMT; - probe_config->bugs |= AHC_SCBCHAN_UPLOAD_BUG; + ahc_dev_softc_t pci; + + pci = ahc->dev_softc; + ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; + ahc->chip = AHC_AIC7899; + ahc->features = AHC_AIC7899_FE; + ahc->flags |= AHC_NEWEEPROM_FMT; + ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG; return (0); } static int -ahc_aha29160C_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aha29160C_setup(struct ahc_softc *ahc) { int error; - error = ahc_aic7899_setup(pci, probe_config); + error = ahc_aic7899_setup(ahc); if (error != 0) return (error); - probe_config->features |= AHC_REMOVABLE; + ahc->features |= AHC_REMOVABLE; return (0); } static int -ahc_raid_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_raid_setup(struct ahc_softc *ahc) { printf("RAID functionality unsupported\n"); return (ENXIO); } static int -ahc_aha394XX_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aha394XX_setup(struct ahc_softc *ahc) { + ahc_dev_softc_t pci; + + pci = ahc->dev_softc; switch (ahc_get_pci_slot(pci)) { case AHC_394X_SLOT_CHANNEL_A: - probe_config->channel = 'A'; + ahc->channel = 'A'; break; case AHC_394X_SLOT_CHANNEL_B: - probe_config->channel = 'B'; + ahc->channel = 'B'; break; default: printf("adapter at unexpected slot %d\n" "unable to map to a channel\n", ahc_get_pci_slot(pci)); - probe_config->channel = 'A'; + ahc->channel = 'A'; } return (0); } static int -ahc_aha398XX_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aha398XX_setup(struct ahc_softc *ahc) { + ahc_dev_softc_t pci; + + pci = ahc->dev_softc; switch (ahc_get_pci_slot(pci)) { case AHC_398X_SLOT_CHANNEL_A: - probe_config->channel = 'A'; + ahc->channel = 'A'; break; case AHC_398X_SLOT_CHANNEL_B: - probe_config->channel = 'B'; + ahc->channel = 'B'; break; case AHC_398X_SLOT_CHANNEL_C: - probe_config->channel = 'C'; + ahc->channel = 'C'; break; default: printf("adapter at unexpected slot %d\n" "unable to map to a channel\n", ahc_get_pci_slot(pci)); - probe_config->channel = 'A'; + ahc->channel = 'A'; break; } - probe_config->flags |= AHC_LARGE_SEEPROM; + ahc->flags |= AHC_LARGE_SEEPROM; return (0); } static int -ahc_aha494XX_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) +ahc_aha494XX_setup(struct ahc_softc *ahc) { + ahc_dev_softc_t pci; + + pci = ahc->dev_softc; switch (ahc_get_pci_slot(pci)) { case AHC_494X_SLOT_CHANNEL_A: - probe_config->channel = 'A'; + ahc->channel = 'A'; break; case AHC_494X_SLOT_CHANNEL_B: - probe_config->channel = 'B'; + ahc->channel = 'B'; break; case AHC_494X_SLOT_CHANNEL_C: - probe_config->channel = 'C'; + ahc->channel = 'C'; break; case AHC_494X_SLOT_CHANNEL_D: - probe_config->channel = 'D'; + ahc->channel = 'D'; break; default: printf("adapter at unexpected slot %d\n" "unable to map to a channel\n", ahc_get_pci_slot(pci)); - probe_config->channel = 'A'; + ahc->channel = 'A'; } - probe_config->flags |= AHC_LARGE_SEEPROM; + ahc->flags |= AHC_LARGE_SEEPROM; return (0); } |