static void
ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
		      u_int our_id, char channel, u_int target_id)
{
	struct  scsi_target *starget;
	struct	ahd_initiator_tinfo *tinfo;
	struct	ahd_tmode_tstate *tstate;
	int	lun;

	tinfo = ahd_fetch_transinfo(ahd, channel, our_id,
				    target_id, &tstate);
	copy_info(info, "Target %d Negotiation Settings\n", target_id);
	copy_info(info, "\tUser: "******"\tGoal: ");
	ahd_format_transinfo(info, &tinfo->goal);
	copy_info(info, "\tCurr: ");
	ahd_format_transinfo(info, &tinfo->curr);

	for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
		struct scsi_device *dev;

		dev = scsi_device_lookup_by_target(starget, lun);

		if (dev == NULL)
			continue;

		ahd_dump_device_state(info, dev);
	}
}
Esempio n. 2
0
void
ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
                      ahd_queue_alg alg)
{
    struct ahd_tmode_tstate *tstate;

    ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
                        devinfo->target, &tstate);

    if (alg != AHD_QUEUE_NONE)
        tstate->tagenable |= devinfo->target_mask;
    else
        tstate->tagenable &= ~devinfo->target_mask;
}
Esempio n. 3
0
void
ahd_adapter_req_set_xfer_mode(struct ahd_softc *ahd, struct scb *scb)
{
    struct ahd_initiator_tinfo *tinfo;
    struct ahd_tmode_tstate *tstate;
    int target_id, our_id;
    struct ahd_devinfo devinfo;
    u_int16_t quirks;
    u_int width, ppr_options, period, offset;
    int s;

    target_id = scb->xs->sc_link->target;
    our_id = SCSI_SCSI_ID(ahd, scb->xs->sc_link);

    s = splbio();

    quirks = scb->xs->sc_link->quirks;
    tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, target_id, &tstate);
    ahd_compile_devinfo(&devinfo, our_id, target_id, 0, 'A',
                        ROLE_INITIATOR);

    tstate->discenable |= (ahd->user_discenable & devinfo.target_mask);

    if (quirks & SDEV_NOTAGS)
        tstate->tagenable &= ~devinfo.target_mask;
    else if (ahd->user_tagenable & devinfo.target_mask)
        tstate->tagenable |= devinfo.target_mask;

    if (quirks & SDEV_NOWIDE)
        width = MSG_EXT_WDTR_BUS_8_BIT;
    else
        width = MSG_EXT_WDTR_BUS_16_BIT;

    ahd_validate_width(ahd, NULL, &width, ROLE_UNKNOWN);
    if (width > tinfo->user.width)
        width = tinfo->user.width;
    ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);

    if (quirks & SDEV_NOSYNC) {
        period = 0;
        offset = 0;
    } else {
        period = tinfo->user.period;
        offset = tinfo->user.offset;
    }

    /* XXX Look at saved INQUIRY flags for PPR capabilities XXX */
    ppr_options = tinfo->user.ppr_options;
    /* XXX Other reasons to avoid ppr? XXX */
    if (width < MSG_EXT_WDTR_BUS_16_BIT)
        ppr_options = 0;

    if ((tstate->discenable & devinfo.target_mask) == 0 ||
            (tstate->tagenable & devinfo.target_mask) == 0)
        ppr_options &= ~MSG_EXT_PPR_PROT_IUS;

    ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX);
    ahd_validate_offset(ahd, NULL, period, &offset, width, ROLE_UNKNOWN);

    if (offset == 0) {
        period = 0;
        ppr_options = 0;
    }

    if (ppr_options != 0 && tinfo->user.transport_version >= 3) {
        tinfo->goal.transport_version = tinfo->user.transport_version;
        tinfo->curr.transport_version = tinfo->user.transport_version;
    }

    ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options,
                     AHD_TRANS_GOAL, FALSE);

    splx(s);
}
Esempio n. 4
0
void
ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
{
    struct	scb *scb;
    struct	scsi_xfer *xs;
    struct	ahd_softc *ahd;
    struct	ahd_initiator_tinfo *tinfo;
    struct	ahd_tmode_tstate *tstate;
    u_int	mask;
    int	s;

    scb = (struct scb *)arg;
    xs = scb->xs;
    xs->error = CAM_REQ_INPROG;
    xs->status = 0;
    ahd = (struct ahd_softc *)xs->sc_link->adapter_softc;

    if (nsegments != 0) {
        void *sg;
        int op;
        u_int i;

        ahd_setup_data_scb(ahd, scb);

        /* Copy the segments into our SG list */
        for (i = nsegments, sg = scb->sg_list; i > 0; i--) {

            sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr,
                              dm_segs->ds_len,
                              /*last*/i == 1);
            dm_segs++;
        }

        if ((xs->flags & SCSI_DATA_IN) != 0)
            op = BUS_DMASYNC_PREREAD;
        else
            op = BUS_DMASYNC_PREWRITE;

        bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
                        scb->dmamap->dm_mapsize, op);

    }

    ahd_lock(ahd, &s);

    /*
     * Last time we need to check if this SCB needs to
     * be aborted.
     */
    if (xs->flags & ITSDONE) {
        if (nsegments != 0)
            bus_dmamap_unload(ahd->parent_dmat,
                              scb->dmamap);
        ahd_free_scb(ahd, scb);
        ahd_unlock(ahd, &s);
        return;
    }

    tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid),
                                SCSIID_OUR_ID(scb->hscb->scsiid),
                                SCSIID_TARGET(ahd, scb->hscb->scsiid),
                                &tstate);

    mask = SCB_GET_TARGET_MASK(ahd, scb);

    if ((tstate->discenable & mask) != 0)
        scb->hscb->control |= DISCENB;

    if ((tstate->tagenable & mask) != 0)
        scb->hscb->control |= TAG_ENB;

    if ((tinfo->curr.ppr_options & MSG_EXT_PPR_PROT_IUS) != 0) {
        scb->flags |= SCB_PACKETIZED;
        if (scb->hscb->task_management != 0)
            scb->hscb->control &= ~MK_MESSAGE;
    }

    if ((tstate->auto_negotiate & mask) != 0) {
        scb->flags |= SCB_AUTO_NEGOTIATE;
        scb->hscb->control |= MK_MESSAGE;
    }

    /* XXX with ahc there was some bus_dmamap_sync(PREREAD|PREWRITE); */

    LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);

    if (!(xs->flags & SCSI_POLL))
        timeout_add_msec(&xs->stimeout, xs->timeout);

    scb->flags |= SCB_ACTIVE;

    if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
        /* Define a mapping from our tag to the SCB. */
        ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
        ahd_pause(ahd);
        ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
        ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
        ahd_unpause(ahd);
    } else {
        ahd_queue_scb(ahd, scb);
    }

    if (!(xs->flags & SCSI_POLL)) {
        int target = xs->sc_link->target;
        int lun = SCB_GET_LUN(scb);

        if (ahd->inited_target[target] == 0) {
            struct  ahd_devinfo devinfo;

            ahd_adapter_req_set_xfer_mode(ahd, scb);
            ahd_compile_devinfo(&devinfo, ahd->our_id, target, lun,
                                'A', /*XXX milos*/ROLE_UNKNOWN);
            ahd_scb_devinfo(ahd, &devinfo, scb);
            ahd_update_neg_request(ahd, &devinfo, tstate, tinfo,
                                   AHD_NEG_IF_NON_ASYNC);
            ahd->inited_target[target] = 1;
        }

        ahd_unlock(ahd, &s);
        return;
    }

    /*
     * If we can't use interrupts, poll for completion
     */
    SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_poll\n"));

    do {
        if (ahd_poll(ahd, xs->timeout)) {
            if (!(xs->flags & SCSI_SILENT))
                printf("cmd fail\n");
            ahd_timeout(scb);
            break;
        }
    } while (!(xs->flags & ITSDONE));

    ahd_unlock(ahd, &s);
}
Esempio n. 5
0
void
ahd_action(struct scsi_xfer *xs)
{
    struct	ahd_softc *ahd;
    struct scb *scb;
    struct hardware_scb *hscb;
    u_int	target_id;
    u_int	our_id;
    int	s;
    struct	ahd_initiator_tinfo *tinfo;
    struct	ahd_tmode_tstate *tstate;
    u_int	col_idx;
    u_int16_t quirks;

    SC_DEBUG(xs->sc_link, SDEV_DB3, ("ahd_action\n"));
    ahd = (struct ahd_softc *)xs->sc_link->adapter_softc;

    target_id = xs->sc_link->target;
    our_id = SCSI_SCSI_ID(ahd, xs->sc_link);

    ahd_lock(ahd, &s);
    if ((ahd->flags & AHD_INITIATORROLE) == 0) {
        xs->error = XS_DRIVER_STUFFUP;
        scsi_done(xs);
        ahd_unlock(ahd, &s);
        return;
    }
    /*
     * get an scb to use.
     */
    tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, target_id, &tstate);

    quirks = xs->sc_link->quirks;

    if ((quirks & SDEV_NOTAGS) != 0 ||
            (tinfo->curr.ppr_options & MSG_EXT_PPR_PROT_IUS) != 0)
        col_idx = AHD_NEVER_COL_IDX;
    else
        col_idx = AHD_BUILD_COL_IDX(target_id, xs->sc_link->lun);

    if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
        ahd->flags |= AHD_RESOURCE_SHORTAGE;
        xs->error = XS_NO_CCB;
        scsi_done(xs);
        ahd_unlock(ahd, &s);
        return;
    }
    ahd_unlock(ahd, &s);

    hscb = scb->hscb;

    SC_DEBUG(xs->sc_link, SDEV_DB3, ("start scb(%p)\n", scb));

    scb->xs = xs;
    timeout_set(&xs->stimeout, ahd_timeout, scb);

    /*
     * Put all the arguments for the xfer in the scb
     */
    hscb->control = 0;
    hscb->scsiid = BUILD_SCSIID(ahd, xs->sc_link, target_id, our_id);
    hscb->lun = xs->sc_link->lun;
    if (xs->xs_control & XS_CTL_RESET) {
        hscb->cdb_len = 0;
        scb->flags |= SCB_DEVICE_RESET;
        hscb->control |= MK_MESSAGE;
        hscb->task_management = SIU_TASKMGMT_LUN_RESET;
        ahd_execute_scb(scb, NULL, 0);
    } else {
        hscb->task_management = 0;
        ahd_setup_data(ahd, xs, scb);
    }
}