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); } }
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; }
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); }
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); }
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); } }