/************************************************** * ### SCSI PHASE SEQUENCER ### **************************************************/ static int ct_reselected(struct ct_softc *ct, u_int8_t scsi_status) { struct scsi_low_softc *slp = &ct->sc_sclow; struct ct_bus_access_handle *chp = &ct->sc_ch; struct targ_info *ti; u_int sid; u_int8_t regv; ct->sc_atten = 0; ct->sc_satgo &= ~CT_SAT_GOING; regv = ct_cr_read_1(chp, wd3s_sid); if ((regv & SIDR_VALID) == 0) return EJUSTRETURN; sid = regv & SIDR_IDM; if ((ti = scsi_low_reselected(slp, sid)) == NULL) return EJUSTRETURN; ct_target_nexus_establish(ct, 0, SCSI_LOW_READ); if (scsi_status != BSR_AFM_RESEL) return EJUSTRETURN; SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN); regv = ct_cr_read_1(chp, wd3s_data); if (scsi_low_msgin(slp, ti, (u_int) regv) == 0) { if (scsi_low_is_msgout_continue(ti, 0) != 0) { /* XXX: scsi_low_attetion */ scsi_low_attention(slp); } } if (ct->sc_atten != 0) { ct_attention(ct); } ct_cr_write_1(chp, wd3s_cmd, WD3S_NEGATE_ACK); return EJUSTRETURN; }
/************************************************************** * disconnect & reselect (HW low) **************************************************************/ static int stg_reselected(struct stg_softc *sc) { struct scsi_low_softc *slp = &sc->sc_sclow; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; int tout; u_int sid; u_int8_t regv; if (slp->sl_selid != NULL) { /* XXX: * Selection vs Reselection conflicts. */ bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit); stghw_bcr_write_1(sc, BCTL_BUSFREE); } else if (slp->sl_Tnexus != NULL) { kprintf("%s: unexpected termination\n", slp->sl_xname); stg_disconnected(sc, slp->sl_Tnexus); } /* XXX: * We should ack the reselection as soon as possible, * because the target would abort the current reselection seq * due to reselection timeout. */ tout = STG_DELAY_SELECT_POLLING_MAX; while (tout -- > 0) { regv = bus_space_read_1(iot, ioh, tmc_bstat); if ((regv & (BSTAT_IO | BSTAT_SEL | BSTAT_BSY)) == (BSTAT_IO | BSTAT_SEL)) { SCSI_LOW_DELAY(1); regv = bus_space_read_1(iot, ioh, tmc_bstat); if ((regv & (BSTAT_IO | BSTAT_SEL | BSTAT_BSY)) == (BSTAT_IO | BSTAT_SEL)) goto reselect_start; } SCSI_LOW_DELAY(1); } kprintf("%s: reselction timeout I\n", slp->sl_xname); return EJUSTRETURN; reselect_start: sid = (u_int) bus_space_read_1(iot, ioh, tmc_scsiid); if ((sid & sc->sc_idbit) == 0) { /* not us */ return EJUSTRETURN; } bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit | FCTL_CLRFIFO | FCTL_CLRINT); bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit); stghw_bcr_write_1(sc, sc->sc_busc | BCTL_BSY); while (tout -- > 0) { regv = bus_space_read_1(iot, ioh, tmc_bstat); if ((regv & (BSTAT_SEL | BSTAT_BSY)) == BSTAT_BSY) goto reselected; SCSI_LOW_DELAY(1); } kprintf("%s: reselction timeout II\n", slp->sl_xname); return EJUSTRETURN; reselected: sid &= ~sc->sc_idbit; sid = ffs(sid) - 1; if (scsi_low_reselected(slp, sid) == NULL) return EJUSTRETURN; #ifdef STG_STATICS stg_statics.reselect ++; #endif /* STG_STATICS */ return EJUSTRETURN; }