diff options
Diffstat (limited to 'sys/dev/aic7xxx/aic7xxx.c')
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.c | 264 |
1 files changed, 199 insertions, 65 deletions
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 |