diff options
-rw-r--r-- | sys/dev/aic7xxx/aic7770.c | 7 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.c | 406 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.h | 56 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.reg | 11 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.seq | 21 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_freebsd.c | 81 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_inline.h | 8 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_osm.c | 81 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_pci.c | 10 |
9 files changed, 371 insertions, 310 deletions
diff --git a/sys/dev/aic7xxx/aic7770.c b/sys/dev/aic7xxx/aic7770.c index c493da2..ac23d19 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#8 $ + * $Id: //depot/src/aic7xxx/aic7770.c#9 $ * * $FreeBSD$ */ @@ -217,6 +217,11 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry) */ ahc_outb(ahc, BCTL, ENABLE); + /* + * Allow interrupts. + */ + ahc_intr_enable(ahc, TRUE); + return (0); } diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c index c0192a5..1e5a8b3 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#34 $ + * $Id: //depot/src/aic7xxx/aic7xxx.c#35 $ * * $FreeBSD$ */ @@ -137,7 +137,7 @@ static struct ahc_syncrate ahc_syncrates[] = #include "aic7xxx_seq.h" /**************************** Function Declarations ***************************/ -static struct tmode_tstate* +static struct ahc_tmode_tstate* ahc_alloc_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel); #ifdef AHC_TARGET_MODE @@ -150,7 +150,7 @@ static struct ahc_syncrate* u_int *period, u_int *ppr_options, role_t role); -static void ahc_update_pending_syncrates(struct ahc_softc *ahc); +static void ahc_update_pending_scbs(struct ahc_softc *ahc); static void ahc_fetch_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo); static void ahc_scb_devinfo(struct ahc_softc *ahc, @@ -190,6 +190,9 @@ static void ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, cam_status status, char *message, int verbose_level); +static void ahc_setup_target_msgin(struct ahc_softc *ahc, + struct ahc_devinfo *devinfo, + struct scb *scb); static bus_dmamap_callback_t ahc_dmamap_cb; static void ahc_build_free_scb_list(struct ahc_softc *ahc); @@ -220,7 +223,7 @@ static void ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts); #ifdef AHC_TARGET_MODE static void ahc_queue_lstate_event(struct ahc_softc *ahc, - struct tmode_lstate *lstate, + struct ahc_tmode_lstate *lstate, u_int initiator_id, u_int event_type, u_int event_arg); @@ -452,6 +455,12 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) break; case SCSI_STATUS_CMD_TERMINATED: case SCSI_STATUS_CHECK_COND: + { + struct ahc_dma_seg *sg; + struct scsi_sense *sc; + struct ahc_initiator_tinfo *targ_info; + struct ahc_tmode_tstate *tstate; + struct ahc_transinfo *tinfo; #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOWSENSE) { ahc_print_path(ahc, scb); @@ -460,99 +469,97 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) } #endif - if (ahc_perform_autosense(scb)) { - struct ahc_dma_seg *sg; - struct scsi_sense *sc; - struct ahc_initiator_tinfo *targ_info; - struct tmode_tstate *tstate; - struct ahc_transinfo *tinfo; + if (ahc_perform_autosense(scb) == 0) + break; - targ_info = - ahc_fetch_transinfo(ahc, + targ_info = ahc_fetch_transinfo(ahc, devinfo.channel, devinfo.our_scsiid, devinfo.target, &tstate); - tinfo = &targ_info->current; - sg = scb->sg_list; - sc = (struct scsi_sense *) - (&hscb->shared_data.cdb); - /* - * Save off the residual if there is one. - */ - if (ahc_check_residual(scb)) - ahc_calc_residual(scb); - else - ahc_set_residual(scb, 0); + tinfo = &targ_info->current; + sg = scb->sg_list; + sc = (struct scsi_sense *)(&hscb->shared_data.cdb); + /* + * Save off the residual if there is one. + */ + if (ahc_check_residual(scb)) + ahc_calc_residual(scb); + else + ahc_set_residual(scb, 0); #ifdef AHC_DEBUG - if (ahc_debug & AHC_SHOWSENSE) { - ahc_print_path(ahc, scb); - printf("Sending Sense\n"); - } + if (ahc_debug & AHC_SHOWSENSE) { + ahc_print_path(ahc, scb); + printf("Sending Sense\n"); + } #endif - sg->addr = ahc_get_sense_bufaddr(ahc, scb); - 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 - && SCB_GET_LUN(scb) < 8) - sc->byte2 = SCB_GET_LUN(scb) << 5; - sc->unused[0] = 0; - sc->unused[1] = 0; - sc->length = sg->len; - sc->control = 0; + sg->addr = ahc_get_sense_bufaddr(ahc, scb); + 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 + && SCB_GET_LUN(scb) < 8) + sc->byte2 = SCB_GET_LUN(scb) << 5; + sc->unused[0] = 0; + sc->unused[1] = 0; + sc->length = sg->len; + sc->control = 0; - /* - * XXX Still true??? - * Would be nice to preserve DISCENB here, - * but due to the way we manage busy targets, - * we can't. - */ - hscb->control = 0; + /* + * We can't allow the target to disconnect. + * This will be an untagged transaction and + * having the target disconnect will make this + * transaction indestinguishable from outstanding + * tagged transactions. + */ + hscb->control = 0; - /* - * This request sense could be because the - * the device lost power or in some other - * way has lost our transfer negotiations. - * Renegotiate if appropriate. Unit attention - * errors will be reported before any data - * phases occur. - */ - if (ahc_get_residual(scb) - == ahc_get_transfer_length(scb)) { - ahc_update_target_msg_request(ahc, - &devinfo, - targ_info, - /*force*/TRUE, - /*paused*/TRUE); - } - hscb->cdb_len = sizeof(*sc); - 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); - ahc_outb(ahc, RETURN_1, SEND_SENSE); + /* + * This request sense could be because the + * the device lost power or in some other + * way has lost our transfer negotiations. + * Renegotiate if appropriate. Unit attention + * errors will be reported before any data + * phases occur. + */ + if (ahc_get_residual(scb) + == ahc_get_transfer_length(scb)) { + ahc_update_neg_request(ahc, &devinfo, + tstate, targ_info, + /*force*/TRUE); + } + if (tstate->auto_negotiate & devinfo.target_mask) { + hscb->control |= MK_MESSAGE; + scb->flags &= ~SCB_NEGOTIATE; + scb->flags |= SCB_AUTO_NEGOTIATE; + } + hscb->cdb_len = sizeof(*sc); + 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); + ahc_outb(ahc, RETURN_1, SEND_SENSE); #ifdef __FreeBSD__ - /* - * Ensure we have enough time to actually - * retrieve the sense. - */ - untimeout(ahc_timeout, (caddr_t)scb, - scb->io_ctx->ccb_h.timeout_ch); - scb->io_ctx->ccb_h.timeout_ch = - timeout(ahc_timeout, (caddr_t)scb, 5 * hz); + /* + * Ensure we have enough time to actually + * retrieve the sense. + */ + untimeout(ahc_timeout, (caddr_t)scb, + scb->io_ctx->ccb_h.timeout_ch); + scb->io_ctx->ccb_h.timeout_ch = + timeout(ahc_timeout, (caddr_t)scb, 5 * hz); #endif - } break; + } default: break; } @@ -666,6 +673,8 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) * loop. */ if (ahc->msg_type == MSG_TYPE_NONE) { + struct scb *scb; + u_int scb_index; u_int bus_phase; bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; @@ -683,13 +692,9 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) return; } + scb_index = ahc_inb(ahc, SCB_TAG); + scb = ahc_lookup_scb(ahc, scb_index); if (devinfo.role == ROLE_INITIATOR) { - struct scb *scb; - u_int scb_index; - - scb_index = ahc_inb(ahc, SCB_TAG); - scb = ahc_lookup_scb(ahc, scb_index); - if (scb == NULL) panic("HOST_MSG_LOOP with " "invalid SCB %x\n", scb_index); @@ -711,7 +716,9 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) } #if AHC_TARGET_MODE else - ahc_setup_target_msgin(ahc, &devinfo); + ahc_setup_target_msgin(ahc, + &devinfo, + scb); #endif } } @@ -1129,7 +1136,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) } else if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_PPR, FALSE)) { struct ahc_initiator_tinfo *tinfo; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; /* * PPR Rejected. Try non-ppr negotiation @@ -1380,11 +1387,11 @@ ahc_print_scb(struct scb *scb) * Allocate per target mode instance (ID we respond to as a target) * transfer negotiation data structures. */ -static struct tmode_tstate * +static struct ahc_tmode_tstate * ahc_alloc_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel) { - struct tmode_tstate *master_tstate; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *master_tstate; + struct ahc_tmode_tstate *tstate; int i; master_tstate = ahc->enabled_targets[ahc->our_id]; @@ -1430,11 +1437,13 @@ ahc_alloc_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel) static void ahc_free_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel, int force) { - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; - /* Don't clean up the entry for our initiator role */ - if ((ahc->flags & AHC_INITIATORROLE) != 0 - && ((channel == 'B' && scsi_id == ahc->our_id_b) + /* + * Don't clean up our "master" tstate. + * It has our default user settings. + */ + if (((channel == 'B' && scsi_id == ahc->our_id_b) || (channel == 'A' && scsi_id == ahc->our_id)) && force == FALSE) return; @@ -1664,15 +1673,14 @@ ahc_validate_width(struct ahc_softc *ahc, struct ahc_initiator_tinfo *tinfo, * means the next time we send the initial identify messages for * a new transaction. */ -void -ahc_update_target_msg_request(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo, - struct ahc_initiator_tinfo *tinfo, - int force, int paused) +int +ahc_update_neg_request(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, + struct ahc_tmode_tstate *tstate, + struct ahc_initiator_tinfo *tinfo, int force) { - u_int targ_msg_req_orig; + u_int auto_negotiate_orig; - targ_msg_req_orig = ahc->targ_msg_req; + auto_negotiate_orig = tstate->auto_negotiate; if (tinfo->current.period != tinfo->goal.period || tinfo->current.width != tinfo->goal.width || tinfo->current.offset != tinfo->goal.offset @@ -1681,23 +1689,11 @@ ahc_update_target_msg_request(struct ahc_softc *ahc, && (tinfo->goal.period != 0 || tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT || tinfo->goal.ppr_options != 0))) - ahc->targ_msg_req |= devinfo->target_mask; + tstate->auto_negotiate |= devinfo->target_mask; else - ahc->targ_msg_req &= ~devinfo->target_mask; + tstate->auto_negotiate &= ~devinfo->target_mask; - if (ahc->targ_msg_req != targ_msg_req_orig) { - /* Update the message request bit for this target */ - if (!paused) - ahc_pause(ahc); - - ahc_outb(ahc, TARGET_MSG_REQUEST, - ahc->targ_msg_req & 0xFF); - ahc_outb(ahc, TARGET_MSG_REQUEST + 1, - (ahc->targ_msg_req >> 8) & 0xFF); - - if (!paused) - ahc_unpause(ahc); - } + return (auto_negotiate_orig != tstate->auto_negotiate); } /* @@ -1714,11 +1710,15 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, u_int offset, u_int ppr_options, u_int type, int paused) { struct ahc_initiator_tinfo *tinfo; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; u_int old_period; u_int old_offset; u_int old_ppr; - int active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE; + int active; + int update_needed; + + active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE; + update_needed = 0; if (syncrate == NULL) { period = 0; @@ -1750,6 +1750,7 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, || old_ppr != ppr_options)) { u_int scsirate; + update_needed++; scsirate = tinfo->scsirate; if ((ahc->features & AHC_ULTRA2) != 0) { @@ -1798,9 +1799,6 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, tinfo->current.offset = offset; tinfo->current.ppr_options = ppr_options; - /* Update the syncrates in any pending scbs */ - ahc_update_pending_syncrates(ahc); - ahc_send_async(ahc, devinfo->channel, devinfo->target, CAM_LUN_WILDCARD, AC_TRANSFER_NEG); if (bootverbose) { @@ -1818,9 +1816,11 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, } } - ahc_update_target_msg_request(ahc, devinfo, tinfo, - /*force*/FALSE, - paused); + update_needed += ahc_update_neg_request(ahc, devinfo, tstate, + tinfo, /*force*/FALSE); + + if (update_needed) + ahc_update_pending_scbs(ahc); } /* @@ -1835,11 +1835,14 @@ void ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, u_int width, u_int type, int paused) { - struct ahc_initiator_tinfo *tinfo; - struct tmode_tstate *tstate; - u_int oldwidth; - int active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE; + struct ahc_initiator_tinfo *tinfo; + struct ahc_tmode_tstate *tstate; + u_int oldwidth; + int active; + int update_needed; + active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE; + update_needed = 0; tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, devinfo->target, &tstate); @@ -1853,6 +1856,7 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, if ((type & AHC_TRANS_CUR) != 0 && oldwidth != width) { u_int scsirate; + update_needed++; scsirate = tinfo->scsirate; scsirate &= ~WIDEXFER; if (width == MSG_EXT_WDTR_BUS_16_BIT) @@ -1874,8 +1878,10 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, } } - ahc_update_target_msg_request(ahc, devinfo, tinfo, - /*force*/FALSE, paused); + update_needed += ahc_update_neg_request(ahc, devinfo, tstate, + tinfo, /*force*/FALSE); + if (update_needed) + ahc_update_pending_scbs(ahc); } /* @@ -1885,7 +1891,7 @@ void ahc_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, int enable) { struct ahc_initiator_tinfo *tinfo; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; uint16_t orig_tagenable; tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, @@ -1911,7 +1917,7 @@ ahc_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, int enable) * be set correctly during future (re)selections. */ static void -ahc_update_pending_syncrates(struct ahc_softc *ahc) +ahc_update_pending_scbs(struct ahc_softc *ahc) { struct scb *pending_scb; int pending_scb_count; @@ -1927,7 +1933,7 @@ ahc_update_pending_syncrates(struct ahc_softc *ahc) struct ahc_devinfo devinfo; struct hardware_scb *pending_hscb; struct ahc_initiator_tinfo *tinfo; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; ahc_scb_devinfo(ahc, &devinfo, pending_scb); tinfo = ahc_fetch_transinfo(ahc, devinfo.channel, @@ -1939,6 +1945,11 @@ ahc_update_pending_syncrates(struct ahc_softc *ahc) pending_hscb->control |= ULTRAENB; pending_hscb->scsirate = tinfo->scsirate; pending_hscb->scsioffset = tinfo->current.offset; + if ((tstate->auto_negotiate & devinfo.target_mask) == 0 + && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) { + pending_scb->flags &= ~SCB_AUTO_NEGOTIATE; + pending_hscb->control &= ~MK_MESSAGE; + } pending_scb_count++; } @@ -1960,9 +1971,8 @@ ahc_update_pending_syncrates(struct ahc_softc *ahc) pending_hscb = pending_scb->hscb; control = ahc_inb(ahc, SCB_CONTROL); - control &= ~ULTRAENB; - if ((pending_hscb->control & ULTRAENB) != 0) - control |= ULTRAENB; + control &= ~(ULTRAENB|MK_MESSAGE); + control |= pending_hscb->control & (ULTRAENB|MK_MESSAGE); ahc_outb(ahc, SCB_CONTROL, control); ahc_outb(ahc, SCB_SCSIRATE, pending_hscb->scsirate); ahc_outb(ahc, SCB_SCSIOFFSET, pending_hscb->scsioffset); @@ -2118,8 +2128,7 @@ ahc_setup_initiator_msgout(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, * away. */ ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO)); - } else if ((ahc->targ_msg_req & devinfo->target_mask) != 0 - || (scb->flags & SCB_NEGOTIATE) != 0) { + } else if ((scb->flags & (SCB_AUTO_NEGOTIATE|SCB_NEGOTIATE)) != 0) { ahc_build_transfer_msg(ahc, devinfo); } else { printf("ahc_intr: AWAITING_MSG for an SCB that " @@ -2136,6 +2145,7 @@ ahc_setup_initiator_msgout(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, * asked to send this message again. */ ahc_outb(ahc, SCB_CONTROL, ahc_inb(ahc, SCB_CONTROL) & ~MK_MESSAGE); + scb->hscb->control &= ~MK_MESSAGE; ahc->msgout_index = 0; ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT; } @@ -2153,7 +2163,7 @@ ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) * we want to renegotiate due to a check condition. */ struct ahc_initiator_tinfo *tinfo; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; struct ahc_syncrate *rate; int dowide; int dosync; @@ -2610,7 +2620,7 @@ static int ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) { struct ahc_initiator_tinfo *tinfo; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; int reject; int done; int response; @@ -2709,7 +2719,8 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) /* * Send our own SDTR in reply */ - if (bootverbose) { + if (bootverbose + && devinfo->role == ROLE_INITIATOR) { printf("(%s:%c:%d:%d): Target " "Initiated SDTR\n", ahc_name(ahc), devinfo->channel, @@ -2779,7 +2790,8 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) /* * Send our own WDTR in reply */ - if (bootverbose) { + if (bootverbose + && devinfo->role == ROLE_INITIATOR) { printf("(%s:%c:%d:%d): Target " "Initiated WDTR\n", ahc_name(ahc), devinfo->channel, @@ -2962,7 +2974,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) tstate = ahc->enabled_targets[devinfo->our_scsiid]; if (tstate != NULL) { - struct tmode_lstate* lstate; + struct ahc_tmode_lstate* lstate; lstate = tstate->enabled_luns[devinfo->lun]; if (lstate != NULL) { @@ -3014,7 +3026,7 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) */ struct scb *scb; struct ahc_initiator_tinfo *tinfo; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; u_int scb_index; u_int last_msg; int response = 0; @@ -3260,7 +3272,7 @@ ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, cam_status status, char *message, int verbose_level) { #ifdef AHC_TARGET_MODE - struct tmode_tstate* tstate; + struct ahc_tmode_tstate* tstate; u_int lun; #endif int found; @@ -3277,7 +3289,7 @@ ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, tstate = ahc->enabled_targets[devinfo->our_scsiid]; if (tstate != NULL) { for (lun = 0; lun < AHC_NUM_LUNS; lun++) { - struct tmode_lstate* lstate; + struct ahc_tmode_lstate* lstate; lstate = tstate->enabled_luns[lun]; if (lstate == NULL) @@ -3309,9 +3321,11 @@ ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, } #ifdef AHC_TARGET_MODE -void -ahc_setup_target_msgin(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) +static void +ahc_setup_target_msgin(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, + struct scb *scb) { + /* * To facilitate adding multiple messages together, * each routine should increment the index and len @@ -3320,7 +3334,7 @@ ahc_setup_target_msgin(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) ahc->msgout_index = 0; ahc->msgout_len = 0; - if ((ahc->targ_msg_req & devinfo->target_mask) != 0) + if (scb != NULL && (scb->flags & SCB_AUTO_NEGOTIATE) != 0) ahc_build_transfer_msg(ahc, devinfo); else panic("ahc_intr: AWAITING target message with no message"); @@ -3354,6 +3368,7 @@ ahc_alloc(void *platform_arg, char *name) LIST_INIT(&ahc->pending_scbs); /* We don't know our unit number until the OSM sets it */ ahc->name = name; + ahc->unit = -1; for (i = 0; i < 16; i++) TAILQ_INIT(&ahc->untagged_queues[i]); if (ahc_platform_alloc(ahc, platform_arg) != 0) { @@ -3372,7 +3387,7 @@ ahc_softc_init(struct ahc_softc *ahc, struct ahc_probe_config *config) ahc->bugs = config->bugs; ahc->flags = config->flags; ahc->channel = config->channel; - ahc->unpause = (ahc_inb(ahc, HCNTRL) & IRQMS) | INTEN; + 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) @@ -3498,7 +3513,7 @@ ahc_free(struct ahc_softc *ahc) #endif ahc_platform_free(ahc); for (i = 0; i < AHC_NUM_TARGETS; i++) { - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; tstate = ahc->enabled_targets[i]; if (tstate != NULL) { @@ -3506,7 +3521,7 @@ ahc_free(struct ahc_softc *ahc) int j; for (j = 0; j < AHC_NUM_LUNS; j++) { - struct tmode_lstate *lstate; + struct ahc_tmode_lstate *lstate; lstate = tstate->enabled_luns[j]; if (lstate != NULL) { @@ -4167,16 +4182,16 @@ ahc_init(struct ahc_softc *ahc) * data for any target mode initiator. */ if (ahc_alloc_tstate(ahc, ahc->our_id, 'A') == NULL) { - printf("%s: unable to allocate tmode_tstate. " + printf("%s: unable to allocate ahc_tmode_tstate. " "Failing attach\n", ahc_name(ahc)); - return (-1); + return (ENOMEM); } if ((ahc->features & AHC_TWIN) != 0) { if (ahc_alloc_tstate(ahc, ahc->our_id_b, 'B') == NULL) { - printf("%s: unable to allocate tmode_tstate. " + printf("%s: unable to allocate ahc_tmode_tstate. " "Failing attach\n", ahc_name(ahc)); - return (-1); + return (ENOMEM); } } @@ -4274,7 +4289,7 @@ ahc_init(struct ahc_softc *ahc) for (i = 0; i <= max_targ; i++) { struct ahc_initiator_tinfo *tinfo; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; u_int our_id; u_int target_id; char channel; @@ -4438,10 +4453,6 @@ ahc_init(struct ahc_softc *ahc) ahc_outb(ahc, QINPOS, 0); ahc_outb(ahc, QOUTPOS, 0); - /* Don't have any special messages to send to targets */ - ahc_outb(ahc, TARGET_MSG_REQUEST, 0); - ahc_outb(ahc, TARGET_MSG_REQUEST + 1, 0); - /* * Use the built in queue management registers * if they are available. @@ -4503,6 +4514,23 @@ ahc_init(struct ahc_softc *ahc) return (0); } +void +ahc_intr_enable(struct ahc_softc *ahc, int enable) +{ + u_int hcntrl; + + hcntrl = ahc_inb(ahc, HCNTRL); + hcntrl &= ~INTEN; + ahc->pause &= ~INTEN; + ahc->unpause &= ~INTEN; + if (enable) { + hcntrl |= INTEN; + ahc->pause |= INTEN; + ahc->unpause |= INTEN; + } + ahc_outb(ahc, HCNTRL, hcntrl); +} + /* * Ensure that the card is paused in a location * outside of all critical sections and that all @@ -5521,14 +5549,14 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset) * drivers affected by this action. */ for (target = 0; target <= max_scsiid; target++) { - struct tmode_tstate* tstate; + struct ahc_tmode_tstate* tstate; u_int lun; tstate = ahc->enabled_targets[target]; if (tstate == NULL) continue; for (lun = 0; lun < AHC_NUM_LUNS; lun++) { - struct tmode_lstate* lstate; + struct ahc_tmode_lstate* lstate; lstate = tstate->enabled_luns[lun]; if (lstate == NULL) @@ -5666,7 +5694,7 @@ ahc_calc_residual(struct scb *scb) * Add a target mode event to this lun's queue */ static void -ahc_queue_lstate_event(struct ahc_softc *ahc, struct tmode_lstate *lstate, +ahc_queue_lstate_event(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate, u_int initiator_id, u_int event_type, u_int event_arg) { struct ahc_tmode_event *event; @@ -5717,7 +5745,7 @@ ahc_queue_lstate_event(struct ahc_softc *ahc, struct tmode_lstate *lstate, * for immediate notify resources. */ void -ahc_send_lstate_events(struct ahc_softc *ahc, struct tmode_lstate *lstate) +ahc_send_lstate_events(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate) { struct ccb_hdr *ccbh; struct ccb_immed_notify *inot; @@ -6043,6 +6071,7 @@ ahc_dump_card_state(struct ahc_softc *ahc) int target; int maxtarget; int i; + uint8_t last_phase; uint8_t qinpos; uint8_t qintail; uint8_t qoutpos; @@ -6051,13 +6080,25 @@ ahc_dump_card_state(struct ahc_softc *ahc) saved_scbptr = ahc_inb(ahc, SCBPTR); - printf("%s: Dumping Card State at SEQADDR 0x%x\n", - ahc_name(ahc), + last_phase = ahc_inb(ahc, LASTPHASE); + printf("%s: Dumping Card State %s, at SEQADDR 0x%x\n", + ahc_name(ahc), ahc_lookup_phase_entry(last_phase)->phasemsg, ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); - - printf("SCSISEQ = 0x%x, SBLKCTL = 0x%x, SSTAT0 0x%x\n", - ahc_inb(ahc, SCSISEQ), ahc_inb(ahc, SBLKCTL), - ahc_inb(ahc, SSTAT0)); + printf("SCSISEQ = 0x%x, SBLKCTL = 0x%x\n", + ahc_inb(ahc, SCSISEQ), ahc_inb(ahc, SBLKCTL)); + printf(" DFCNTRL = 0x%x, DFSTATUS = 0x%x\n", + ahc_inb(ahc, DFCNTRL), ahc_inb(ahc, DFSTATUS)); + printf("LASTPHASE = 0x%x, SCSISIGI = 0x%x, SXFRCTL0 = 0x%x\n", + last_phase, ahc_inb(ahc, SCSISIGI), ahc_inb(ahc, SXFRCTL0)); + printf("SSTAT0 = 0x%x, SSTAT1 = 0x%x\n", + ahc_inb(ahc, SSTAT0), ahc_inb(ahc, SSTAT1)); + if ((ahc->features & AHC_DT) != 0) + printf("SCSIPHASE = 0x%x\n", ahc_inb(ahc, SCSIPHASE)); + printf("STACK == 0x%x, 0x%x, 0x%x, 0x%x\n", + ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), + ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), + ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), + ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8)); printf("SCB count = %d\n", ahc->scb_data->numscbs); printf("Kernel NEXTQSCB = %d\n", ahc->next_queued_scb->hscb->tag); printf("Card NEXTQSCB = %d\n", ahc_inb(ahc, NEXT_QUEUED_SCB)); @@ -6155,7 +6196,8 @@ ahc_dump_card_state(struct ahc_softc *ahc) #ifdef AHC_TARGET_MODE cam_status ahc_find_tmode_devs(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb, - struct tmode_tstate **tstate, struct tmode_lstate **lstate, + struct ahc_tmode_tstate **tstate, + struct ahc_tmode_lstate **lstate, int notfound_failure) { @@ -6196,8 +6238,8 @@ ahc_find_tmode_devs(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb, void ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) { - struct tmode_tstate *tstate; - struct tmode_lstate *lstate; + struct ahc_tmode_tstate *tstate; + struct ahc_tmode_lstate *lstate; struct ccb_en_lun *cel; cam_status status; u_int target; @@ -6605,8 +6647,8 @@ ahc_run_tqinfifo(struct ahc_softc *ahc, int paused) static int ahc_handle_target_cmd(struct ahc_softc *ahc, struct target_cmd *cmd) { - struct tmode_tstate *tstate; - struct tmode_lstate *lstate; + struct ahc_tmode_tstate *tstate; + struct ahc_tmode_lstate *lstate; struct ccb_accept_tio *atio; uint8_t *byte; int initiator; diff --git a/sys/dev/aic7xxx/aic7xxx.h b/sys/dev/aic7xxx/aic7xxx.h index 329a58d..eada9ad 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#22 $ + * $Id: //depot/src/aic7xxx/aic7xxx.h#24 $ * * $FreeBSD$ */ @@ -515,8 +515,9 @@ typedef enum { SCB_DEVICE_RESET = 0x0004, SCB_SENSE = 0x0008, SCB_CDB32_PTR = 0x0010, - SCB_RECOVERY_SCB = 0x0040, - SCB_NEGOTIATE = 0x0080, + SCB_RECOVERY_SCB = 0x0020, + SCB_AUTO_NEGOTIATE = 0x0040,/* Negotiate to achieve goal. */ + SCB_NEGOTIATE = 0x0080,/* Negotiation forced for command. */ SCB_ABORT = 0x1000, SCB_UNTAGGEDQ = 0x2000, SCB_ACTIVE = 0x4000, @@ -625,7 +626,7 @@ struct ahc_tmode_event { * data structures. */ #ifdef AHC_TARGET_MODE -struct tmode_lstate { +struct ahc_tmode_lstate { struct cam_path *path; struct ccb_hdr_slist accept_tios; struct ccb_hdr_slist immed_notifies; @@ -634,7 +635,7 @@ struct tmode_lstate { uint8_t event_w_idx; }; #else -struct tmode_lstate; +struct ahc_tmode_lstate; #endif /******************** Transfer Negotiation Datastructures *********************/ @@ -671,16 +672,17 @@ struct ahc_initiator_tinfo { * that we are the target and the targets are the initiators since the * negotiation is the same regardless of role. */ -struct tmode_tstate { - struct tmode_lstate* enabled_luns[AHC_NUM_LUNS]; +struct ahc_tmode_tstate { + struct ahc_tmode_lstate* enabled_luns[AHC_NUM_LUNS]; struct ahc_initiator_tinfo transinfo[AHC_NUM_TARGETS]; /* * Per initiator state bitmasks. */ - uint16_t ultraenb; /* Using ultra sync rate */ - uint16_t discenable; /* Disconnection allowed */ - uint16_t tagenable; /* Tagged Queuing allowed */ + uint16_t auto_negotiate;/* Auto Negotiation Required */ + uint16_t ultraenb; /* Using ultra sync rate */ + uint16_t discenable; /* Disconnection allowed */ + uint16_t tagenable; /* Tagged Queuing allowed */ }; /* @@ -841,6 +843,8 @@ struct ahc_suspend_state { uint8_t *btt; }; +typedef void (*ahc_bus_intr_t)(struct ahc_softc *); + struct ahc_softc { bus_space_tag_t tag; bus_space_handle_t bsh; @@ -884,24 +888,29 @@ struct ahc_softc { ahc_dev_softc_t dev_softc; /* + * Bus specific device information. + */ + ahc_bus_intr_t bus_intr; + + /* * Target mode related state kept on a per enabled lun basis. * Targets that are not enabled will have null entries. * As an initiator, we keep one target entry for our initiator * ID to store our sync/wide transfer settings. */ - struct tmode_tstate* enabled_targets[AHC_NUM_TARGETS]; + struct ahc_tmode_tstate *enabled_targets[AHC_NUM_TARGETS]; /* * The black hole device responsible for handling requests for * disabled luns on enabled targets. */ - struct tmode_lstate* black_hole; + struct ahc_tmode_lstate *black_hole; /* * Device instance currently on the bus awaiting a continue TIO * for a command that was not given the disconnect priveledge. */ - struct tmode_lstate* pending_device; + struct ahc_tmode_lstate *pending_device; /* * Card characteristics @@ -936,9 +945,6 @@ struct ahc_softc { uint8_t our_id; uint8_t our_id_b; - /* Targets that need negotiation messages */ - uint16_t targ_msg_req; - /* * PCI error detection. */ @@ -1086,6 +1092,7 @@ int ahc_softc_init(struct ahc_softc *, struct ahc_probe_config*); 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); void ahc_pause_and_flushwork(struct ahc_softc *ahc); int ahc_suspend(struct ahc_softc *ahc); int ahc_resume(struct ahc_softc *ahc); @@ -1149,10 +1156,11 @@ void ahc_validate_width(struct ahc_softc *ahc, struct ahc_initiator_tinfo *tinfo, u_int *bus_width, role_t role); -void ahc_update_target_msg_request(struct ahc_softc *ahc, - struct ahc_devinfo *dinfo, - struct ahc_initiator_tinfo *tinfo, - int force, int paused); +int ahc_update_neg_request(struct ahc_softc*, + struct ahc_devinfo*, + struct ahc_tmode_tstate*, + struct ahc_initiator_tinfo*, + int /*force*/); void ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, u_int width, u_int type, int paused); @@ -1168,16 +1176,14 @@ void ahc_set_tags(struct ahc_softc *ahc, /**************************** Target Mode *************************************/ #ifdef AHC_TARGET_MODE void ahc_send_lstate_events(struct ahc_softc *, - struct tmode_lstate *); + struct ahc_tmode_lstate *); void ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb); cam_status ahc_find_tmode_devs(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb, - struct tmode_tstate **tstate, - struct tmode_lstate **lstate, + struct ahc_tmode_tstate **tstate, + struct ahc_tmode_lstate **lstate, int notfound_failure); -void ahc_setup_target_msgin(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo); #ifndef AHC_TMODE_ENABLE #define AHC_TMODE_ENABLE 0 #endif diff --git a/sys/dev/aic7xxx/aic7xxx.reg b/sys/dev/aic7xxx/aic7xxx.reg index ac966f0..c1f342f 100644 --- a/sys/dev/aic7xxx/aic7xxx.reg +++ b/sys/dev/aic7xxx/aic7xxx.reg @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: //depot/src/aic7xxx/aic7xxx.reg#14 $ + * $Id: //depot/src/aic7xxx/aic7xxx.reg#15 $ * * $FreeBSD$ */ @@ -1419,15 +1419,6 @@ scratch_ram { } /* - * Interrupt kernel for a message to this target on - * the next transaction. This is usually used for - * negotiation requests. - */ - TARGET_MSG_REQUEST { - size 2 - } - - /* * Sequences the kernel driver has okayed for us. This allows * the driver to do things like prevent initiator or target * operations. diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq index 8788e60..bd4342a 100644 --- a/sys/dev/aic7xxx/aic7xxx.seq +++ b/sys/dev/aic7xxx/aic7xxx.seq @@ -479,6 +479,9 @@ target_synccmd: */ mov SEQ_FLAGS, SCB_TARGET_INFO[SCB_TARGET_PHASES]; + test SCB_CONTROL, MK_MESSAGE jz target_ITloop; + mvi P_MESGIN|BSYO call change_phase; + jmp host_target_message_loop; target_ITloop: /* * Start honoring ATN signals now that @@ -494,12 +497,12 @@ target_ITloop: * on the state of NO_DISCONNECT. */ test SEQ_FLAGS, NO_DISCONNECT jz target_disconnect; - if ((ahc->flags & AHC_PAGESCBS) != 0) { - mov ALLZEROS call get_free_or_disc_scb; - } mov RETURN_1, ALLZEROS; call complete_target_cmd; cmp RETURN_1, CONT_MSG_LOOP jne .; + if ((ahc->flags & AHC_PAGESCBS) != 0) { + mov ALLZEROS call get_free_or_disc_scb; + } mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET; mov SCB_TAG call dma_scb; jmp target_synccmd; @@ -1351,18 +1354,6 @@ p_mesgout: mov SINDEX, MSG_OUT; cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host; test SCB_CONTROL,MK_MESSAGE jnz host_message_loop; - mov FUNCTION1, SCB_SCSIID; - mov A, FUNCTION1; - mov SINDEX, TARGET_MSG_REQUEST[0]; - if ((ahc->features & AHC_TWIN) != 0) { - /* Second Channel uses high byte bits */ - test SCB_SCSIID, TWIN_CHNLB jz . + 2; - mov SINDEX, TARGET_MSG_REQUEST[1]; - } else if ((ahc->features & AHC_WIDE) != 0) { - test SCB_SCSIID, 0x80 jz . + 2; /* target > 7 */ - mov SINDEX, TARGET_MSG_REQUEST[1]; - } - test SINDEX, A jnz host_message_loop; p_mesgout_identify: or SINDEX, MSG_IDENTIFYFLAG|DISCENB, SCB_LUN; test SCB_CONTROL, DISCENB jnz . + 2; diff --git a/sys/dev/aic7xxx/aic7xxx_freebsd.c b/sys/dev/aic7xxx/aic7xxx_freebsd.c index 8d9fb21..f61c8da 100644 --- a/sys/dev/aic7xxx/aic7xxx_freebsd.c +++ b/sys/dev/aic7xxx/aic7xxx_freebsd.c @@ -288,6 +288,27 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) } if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { + struct cam_path *ccb_path; + + /* + * If we have finally disconnected, clean up our + * pending device state. + * XXX - There may be error states that cause where + * we will remain connected. + */ + ccb_path = ccb->ccb_h.path; + if (ahc->pending_device != NULL + && xpt_path_comp(ahc->pending_device->path, ccb_path) == 0) { + + if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) { + ahc->pending_device = NULL; + } else { + xpt_print_path(ccb->ccb_h.path); + printf("Still disconnected\n"); + ahc_freeze_ccb(ccb); + } + } + if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) ccb->ccb_h.status |= CAM_REQ_CMP; ccb->ccb_h.status &= ~CAM_SIM_QUEUED; @@ -361,7 +382,7 @@ static void ahc_action(struct cam_sim *sim, union ccb *ccb) { struct ahc_softc *ahc; - struct tmode_lstate *lstate; + struct ahc_tmode_lstate *lstate; u_int target_id; u_int our_id; long s; @@ -378,7 +399,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ case XPT_CONT_TARGET_IO:/* Continue Host Target I/O Connection*/ { - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; cam_status status; status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, @@ -427,6 +448,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) || ccb->ccb_h.func_code == XPT_RESET_DEV)) { ccb->ccb_h.status = CAM_PROVIDE_FAIL; xpt_done(ccb); + return; } /* @@ -470,10 +492,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) struct target_data *tdata; tdata = &hscb->shared_data.tdata; - if (ahc->pending_device == lstate) { + if (ahc->pending_device == lstate) scb->flags |= SCB_TARGET_IMMEDIATE; - ahc->pending_device = NULL; - } hscb->control |= TARGET_SCB; tdata->target_phases = IDENTIFY_SEEN; if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) { @@ -481,6 +501,9 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) tdata->scsi_status = ccb->csio.scsi_status; } + if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) + tdata->target_phases |= NO_DISCONNECT; + tdata->initiator_tag = ccb->csio.tag_id; } if (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) @@ -493,8 +516,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) case XPT_NOTIFY_ACK: case XPT_IMMED_NOTIFY: { - struct tmode_tstate *tstate; - struct tmode_lstate *lstate; + struct ahc_tmode_tstate *tstate; + struct ahc_tmode_lstate *lstate; cam_status status; status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, @@ -528,7 +551,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) struct ccb_trans_settings_scsi *scsi; struct ccb_trans_settings_spi *spi; struct ahc_initiator_tinfo *tinfo; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; uint16_t *discenable; uint16_t *tagenable; u_int update_type; @@ -652,7 +675,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) struct ahc_devinfo devinfo; struct ccb_trans_settings *cts; struct ahc_initiator_tinfo *tinfo; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; uint16_t *discenable; uint16_t *tagenable; u_int update_type; @@ -895,7 +918,7 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel, struct ccb_trans_settings_scsi *scsi; struct ccb_trans_settings_spi *spi; struct ahc_initiator_tinfo *targ_info; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; struct ahc_transinfo *tinfo; scsi = &cts->proto_specific.scsi; @@ -954,7 +977,7 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel, #else struct ahc_devinfo devinfo; struct ahc_initiator_tinfo *targ_info; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; struct ahc_transinfo *tinfo; long s; @@ -1051,7 +1074,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, union ccb *ccb; struct ahc_softc *ahc; struct ahc_initiator_tinfo *tinfo; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; u_int mask; long s; @@ -1186,7 +1209,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, scb->hscb->scsioffset = tinfo->current.offset; if ((tstate->ultraenb & mask) != 0) scb->hscb->control |= ULTRAENB; - + if ((tstate->discenable & mask) != 0 && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0) scb->hscb->control |= DISCENB; @@ -1197,6 +1220,9 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, || tinfo->goal.ppr_options != 0)) { scb->flags |= SCB_NEGOTIATE; scb->hscb->control |= MK_MESSAGE; + } else if ((tstate->auto_negotiate & mask) != 0) { + scb->flags |= SCB_AUTO_NEGOTIATE; + scb->hscb->control |= MK_MESSAGE; } LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links); @@ -1239,6 +1265,8 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, scb->flags |= SCB_ACTIVE; if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) { + /* Define a mapping from our tag to the SCB. */ + ahc->scb_data->scbindex[scb->hscb->tag] = scb; ahc_pause(ahc); if ((ahc->flags & AHC_PAGESCBS) == 0) ahc_outb(ahc, SCBPTR, scb->hscb->tag); @@ -1433,27 +1461,9 @@ ahc_timeout(void *arg) lun = SCB_GET_LUN(scb); ahc_print_path(ahc, scb); - printf("SCB 0x%x - timed out ", scb->hscb->tag); - /* - * Take a snapshot of the bus state and print out - * some information so we can track down driver bugs. - */ - last_phase = ahc_inb(ahc, LASTPHASE); - - printf("%s", ahc_lookup_phase_entry(last_phase)->phasemsg); - - printf(", SEQADDR == 0x%x\n", - ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); - - printf("STACK == 0x%x, 0x%x, 0x%x, 0x%x\n", - ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), - ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), - ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), - ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8)); - - printf("SXFRCTL0 == 0x%x\n", ahc_inb(ahc, SXFRCTL0)); - + printf("SCB 0x%x - timed out\n", scb->hscb->tag); ahc_dump_card_state(ahc); + last_phase = ahc_inb(ahc, LASTPHASE); if (scb->sg_count > 0) { for (i = 0; i < scb->sg_count; i++) { printf("sg[%d] - Addr 0x%x : Length %d\n", @@ -1683,8 +1693,8 @@ ahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) case XPT_IMMED_NOTIFY: case XPT_CONT_TARGET_IO: { - struct tmode_tstate *tstate; - struct tmode_lstate *lstate; + struct ahc_tmode_tstate *tstate; + struct ahc_tmode_lstate *lstate; struct ccb_hdr_slist *list; cam_status status; @@ -1818,7 +1828,6 @@ ahc_platform_free(struct ahc_softc *ahc) pdata = ahc->platform_data; if (pdata != NULL) { - device_printf(ahc->dev_softc, "Platform free\n"); if (pdata->regs != NULL) bus_release_resource(ahc->dev_softc, pdata->regs_res_type, diff --git a/sys/dev/aic7xxx/aic7xxx_inline.h b/sys/dev/aic7xxx/aic7xxx_inline.h index 16edaba..446b104 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#17 $ + * $Id: //depot/src/aic7xxx/aic7xxx_inline.h#19 $ * * $FreeBSD$ */ @@ -193,7 +193,7 @@ static __inline struct ahc_initiator_tinfo * ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id, u_int remote_id, - struct tmode_tstate **tstate); + struct ahc_tmode_tstate **tstate); static __inline struct scb* ahc_get_scb(struct ahc_softc *ahc); static __inline void ahc_free_scb(struct ahc_softc *ahc, struct scb *scb); @@ -228,7 +228,7 @@ ahc_check_residual(struct scb *scb) */ static __inline struct ahc_initiator_tinfo * ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id, - u_int remote_id, struct tmode_tstate **tstate) + u_int remote_id, struct ahc_tmode_tstate **tstate) { /* * Transfer data structures are stored from the perspective @@ -433,7 +433,7 @@ ahc_intr(struct ahc_softc *ahc) if (ahc->unsolicited_ints > 500 && (ahc->chip & AHC_PCI) != 0 && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0) - ahc_pci_intr(ahc); + ahc->bus_intr(ahc); #endif } diff --git a/sys/dev/aic7xxx/aic7xxx_osm.c b/sys/dev/aic7xxx/aic7xxx_osm.c index 8d9fb21..f61c8da 100644 --- a/sys/dev/aic7xxx/aic7xxx_osm.c +++ b/sys/dev/aic7xxx/aic7xxx_osm.c @@ -288,6 +288,27 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) } if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { + struct cam_path *ccb_path; + + /* + * If we have finally disconnected, clean up our + * pending device state. + * XXX - There may be error states that cause where + * we will remain connected. + */ + ccb_path = ccb->ccb_h.path; + if (ahc->pending_device != NULL + && xpt_path_comp(ahc->pending_device->path, ccb_path) == 0) { + + if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) { + ahc->pending_device = NULL; + } else { + xpt_print_path(ccb->ccb_h.path); + printf("Still disconnected\n"); + ahc_freeze_ccb(ccb); + } + } + if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) ccb->ccb_h.status |= CAM_REQ_CMP; ccb->ccb_h.status &= ~CAM_SIM_QUEUED; @@ -361,7 +382,7 @@ static void ahc_action(struct cam_sim *sim, union ccb *ccb) { struct ahc_softc *ahc; - struct tmode_lstate *lstate; + struct ahc_tmode_lstate *lstate; u_int target_id; u_int our_id; long s; @@ -378,7 +399,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ case XPT_CONT_TARGET_IO:/* Continue Host Target I/O Connection*/ { - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; cam_status status; status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, @@ -427,6 +448,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) || ccb->ccb_h.func_code == XPT_RESET_DEV)) { ccb->ccb_h.status = CAM_PROVIDE_FAIL; xpt_done(ccb); + return; } /* @@ -470,10 +492,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) struct target_data *tdata; tdata = &hscb->shared_data.tdata; - if (ahc->pending_device == lstate) { + if (ahc->pending_device == lstate) scb->flags |= SCB_TARGET_IMMEDIATE; - ahc->pending_device = NULL; - } hscb->control |= TARGET_SCB; tdata->target_phases = IDENTIFY_SEEN; if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) { @@ -481,6 +501,9 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) tdata->scsi_status = ccb->csio.scsi_status; } + if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) + tdata->target_phases |= NO_DISCONNECT; + tdata->initiator_tag = ccb->csio.tag_id; } if (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) @@ -493,8 +516,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) case XPT_NOTIFY_ACK: case XPT_IMMED_NOTIFY: { - struct tmode_tstate *tstate; - struct tmode_lstate *lstate; + struct ahc_tmode_tstate *tstate; + struct ahc_tmode_lstate *lstate; cam_status status; status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, @@ -528,7 +551,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) struct ccb_trans_settings_scsi *scsi; struct ccb_trans_settings_spi *spi; struct ahc_initiator_tinfo *tinfo; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; uint16_t *discenable; uint16_t *tagenable; u_int update_type; @@ -652,7 +675,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb) struct ahc_devinfo devinfo; struct ccb_trans_settings *cts; struct ahc_initiator_tinfo *tinfo; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; uint16_t *discenable; uint16_t *tagenable; u_int update_type; @@ -895,7 +918,7 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel, struct ccb_trans_settings_scsi *scsi; struct ccb_trans_settings_spi *spi; struct ahc_initiator_tinfo *targ_info; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; struct ahc_transinfo *tinfo; scsi = &cts->proto_specific.scsi; @@ -954,7 +977,7 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel, #else struct ahc_devinfo devinfo; struct ahc_initiator_tinfo *targ_info; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; struct ahc_transinfo *tinfo; long s; @@ -1051,7 +1074,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, union ccb *ccb; struct ahc_softc *ahc; struct ahc_initiator_tinfo *tinfo; - struct tmode_tstate *tstate; + struct ahc_tmode_tstate *tstate; u_int mask; long s; @@ -1186,7 +1209,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, scb->hscb->scsioffset = tinfo->current.offset; if ((tstate->ultraenb & mask) != 0) scb->hscb->control |= ULTRAENB; - + if ((tstate->discenable & mask) != 0 && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0) scb->hscb->control |= DISCENB; @@ -1197,6 +1220,9 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, || tinfo->goal.ppr_options != 0)) { scb->flags |= SCB_NEGOTIATE; scb->hscb->control |= MK_MESSAGE; + } else if ((tstate->auto_negotiate & mask) != 0) { + scb->flags |= SCB_AUTO_NEGOTIATE; + scb->hscb->control |= MK_MESSAGE; } LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links); @@ -1239,6 +1265,8 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, scb->flags |= SCB_ACTIVE; if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) { + /* Define a mapping from our tag to the SCB. */ + ahc->scb_data->scbindex[scb->hscb->tag] = scb; ahc_pause(ahc); if ((ahc->flags & AHC_PAGESCBS) == 0) ahc_outb(ahc, SCBPTR, scb->hscb->tag); @@ -1433,27 +1461,9 @@ ahc_timeout(void *arg) lun = SCB_GET_LUN(scb); ahc_print_path(ahc, scb); - printf("SCB 0x%x - timed out ", scb->hscb->tag); - /* - * Take a snapshot of the bus state and print out - * some information so we can track down driver bugs. - */ - last_phase = ahc_inb(ahc, LASTPHASE); - - printf("%s", ahc_lookup_phase_entry(last_phase)->phasemsg); - - printf(", SEQADDR == 0x%x\n", - ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); - - printf("STACK == 0x%x, 0x%x, 0x%x, 0x%x\n", - ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), - ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), - ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8), - ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8)); - - printf("SXFRCTL0 == 0x%x\n", ahc_inb(ahc, SXFRCTL0)); - + printf("SCB 0x%x - timed out\n", scb->hscb->tag); ahc_dump_card_state(ahc); + last_phase = ahc_inb(ahc, LASTPHASE); if (scb->sg_count > 0) { for (i = 0; i < scb->sg_count; i++) { printf("sg[%d] - Addr 0x%x : Length %d\n", @@ -1683,8 +1693,8 @@ ahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) case XPT_IMMED_NOTIFY: case XPT_CONT_TARGET_IO: { - struct tmode_tstate *tstate; - struct tmode_lstate *lstate; + struct ahc_tmode_tstate *tstate; + struct ahc_tmode_lstate *lstate; struct ccb_hdr_slist *list; cam_status status; @@ -1818,7 +1828,6 @@ ahc_platform_free(struct ahc_softc *ahc) pdata = ahc->platform_data; if (pdata != NULL) { - device_printf(ahc->dev_softc, "Platform free\n"); if (pdata->regs != NULL) bus_release_resource(ahc->dev_softc, pdata->regs_res_type, diff --git a/sys/dev/aic7xxx/aic7xxx_pci.c b/sys/dev/aic7xxx/aic7xxx_pci.c index 02a73d4..5102c5b 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#19 $ + * $Id: //depot/src/aic7xxx/aic7xxx_pci.c#21 $ * * $FreeBSD$ */ @@ -759,6 +759,8 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) if (error != 0) return (error); + ahc->bus_intr = ahc_pci_intr; + /* Remeber how the card was setup in case there is no SEEPROM */ if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) { ahc_pause(ahc); @@ -795,6 +797,7 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) error = ahc_pci_map_int(ahc); if (error != 0) return (error); + dscommand0 = ahc_inb(ahc, DSCOMMAND0); dscommand0 |= MPARCKEN|CACHETHEN; if ((ahc->features & AHC_ULTRA2) != 0) { @@ -901,6 +904,11 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) */ ahc_softc_insert(ahc); + /* + * Allow interrupts now that we are completely setup. + */ + ahc_intr_enable(ahc, TRUE); + return (0); } |