コード例 #1
0
ファイル: ct.c プロジェクト: 2asoft/freebsd
static void
ct_phase_error(struct ct_softc *ct, u_int8_t scsi_status)
{
	struct scsi_low_softc *slp = &ct->sc_sclow;
	struct targ_info *ti = slp->sl_Tnexus;
	struct ct_err *pep;
	u_int msg = 0;

	if ((scsi_status & BSR_CM) == BSR_CMDERR &&
	    (scsi_status & BSR_PHVALID) == 0)
	{
		pep = &ct_cmderr[scsi_status & BSR_PM];
		slp->sl_error |= pep->pe_err;
		if ((pep->pe_err & PARITYERR) != 0)
		{
			if (ti->ti_phase == PH_MSGIN)
				msg = SCSI_LOW_MSG_PARITY;
			else
				msg = SCSI_LOW_MSG_ERROR;
		}
		else
			msg = pep->pe_errmsg;	

		if (msg != 0)
			scsi_low_assert_msg(slp, slp->sl_Tnexus, msg, 1);

		if (pep->pe_msg != NULL)
		{
			device_printf(slp->sl_dev, "phase error: %s",
			    pep->pe_msg);
			scsi_low_print(slp, slp->sl_Tnexus);
		}

		if (pep->pe_done != 0)
			scsi_low_disconnected(slp, ti);
	}
	else
	{
		slp->sl_error |= FATALIO;
		scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "phase error");
	}
}
コード例 #2
0
ファイル: tmc18c30.c プロジェクト: Gwenio/DragonFlyBSD
int
stgintr(void *arg)
{
	struct stg_softc *sc = arg;
	struct scsi_low_softc *slp = &sc->sc_sclow;
	bus_space_tag_t iot = sc->sc_iot;
	bus_space_handle_t ioh = sc->sc_ioh;
	struct targ_info *ti;
	struct buf *bp;
	u_int derror, flags;
	int len;
	u_int8_t status, astatus, regv;

	/*******************************************
	 * interrupt check
	 *******************************************/
	if (slp->sl_flags & HW_INACTIVE)
		return 0;

	astatus = bus_space_read_1(iot, ioh, tmc_astat);
	status = bus_space_read_1(iot, ioh, tmc_bstat);

	if ((astatus & ASTAT_STATMASK) == 0 || astatus == (u_int8_t) -1)
		return 0;

	bus_space_write_1(iot, ioh, tmc_ictl, 0);
	if (astatus & ASTAT_SCSIRST)
	{
		bus_space_write_1(iot, ioh, tmc_fctl,
				  sc->sc_fcRinit | FCTL_CLRFIFO);
		bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit);
		bus_space_write_1(iot, ioh, tmc_ictl, 0);

		scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT, 
				 "bus reset (power off?)");
		return 1;
	}

	/*******************************************
	 * debug section
	 *******************************************/
#ifdef	STG_DEBUG
	if (stg_debug)
	{
		scsi_low_print(slp, NULL);
		kprintf("%s: st %x ist %x\n\n", slp->sl_xname,
		       status, astatus);
#ifdef	DDB
		if (stg_debug > 1)
			SCSI_LOW_DEBUGGER("stg");
#endif	/* DDB */
	}
#endif	/* STG_DEBUG */

	/*******************************************
	 * reselection & nexus
	 *******************************************/
	if ((status & RESEL_PHASE_MASK)== PHASE_RESELECTED)
	{
		if (stg_reselected(sc) == EJUSTRETURN)
			goto out;
	}

	if ((ti = slp->sl_Tnexus) == NULL)
		return 0;

	derror = 0;
	if ((astatus & ASTAT_PARERR) != 0 && ti->ti_phase != PH_ARBSTART &&
	    (sc->sc_fcRinit & FCTL_PARENB) != 0)
	{
		slp->sl_error |= PARITYERR;
		derror = SCSI_LOW_DATA_PE;
		if ((status & PHASE_MASK) == MESSAGE_IN_PHASE)
			scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_PARITY, 0);
		else
			scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ERROR, 1);
	}

	/*******************************************
	 * aribitration & selection
	 *******************************************/
	switch (ti->ti_phase)
	{
	case PH_ARBSTART:
		if ((astatus & ASTAT_ARBIT) == 0)
		{
#ifdef	STG_STATICS
			stg_statics.arbit_fail_0 ++;
#endif	/* STG_STATICS */
			goto arb_fail;
		}

		status = bus_space_read_1(iot, ioh, tmc_bstat);
		if ((status & BSTAT_IO) != 0)
		{
			/* XXX:
			 * Selection vs Reselection conflicts.
			 */
#ifdef	STG_STATICS
			stg_statics.arbit_fail_1 ++;
#endif	/* STG_STATICS */
arb_fail:
			bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit);
			stghw_bcr_write_1(sc, BCTL_BUSFREE);
			scsi_low_arbit_fail(slp, slp->sl_Qnexus);
			goto out;
		}

		/*
		 * selection assert start.
		 */
		SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART);
		scsi_low_arbit_win(slp);

		crit_enter();
		bus_space_write_1(iot, ioh, tmc_scsiid,
				  sc->sc_idbit | (1 << ti->ti_id));
		stghw_bcr_write_1(sc, sc->sc_imsg | sc->sc_busc | BCTL_SEL);
		bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcWinit);
		if ((stg_io_control & STG_WAIT_FOR_SELECT) != 0)
		{
			/* selection abort delay 200 + 100 micro sec */
			if (stghw_select_targ_wait(sc, 300) == 0)
			{
				SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
				stg_selection_done_and_expect_msgout(sc);
			}	
		}
		crit_exit();
		goto out;

	case PH_SELSTART:
		if ((status & BSTAT_BSY) == 0)
		{
			/* selection timeout delay 250 ms */
			if (stghw_select_targ_wait(sc, 250 * 1000) != 0)
			{
				stg_disconnected(sc, ti);
				goto out;
			}
		}

		SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
		stg_selection_done_and_expect_msgout(sc);
		goto out;

	case PH_SELECTED:
		if ((status & BSTAT_REQ) == 0)
			goto out;
		stg_target_nexus_establish(sc);
		break;

	case PH_RESEL:
		if ((status & BSTAT_REQ) == 0)
			goto out;

		/* clear a busy line */
		bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit);
		stghw_bcr_write_1(sc, sc->sc_busc);
		stg_target_nexus_establish(sc);
		if ((status & PHASE_MASK) != MESSAGE_IN_PHASE)
		{
			kprintf("%s: unexpected phase after reselect\n",
			       slp->sl_xname);
			slp->sl_error |= FATALIO;
			scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
			goto out;
		}
		break;
	}

	/*******************************************
	 * data phase
	 *******************************************/
	if ((slp->sl_flags & HW_PDMASTART) && STG_IS_PHASE_DATA(status) == 0)
	{
		if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
			stg_pio_read(sc, ti, 0);

		stg_pdma_end(sc, ti);
	}

	/*******************************************
	 * scsi seq
	 *******************************************/
	switch (status & PHASE_MASK)
	{
	case COMMAND_PHASE:
		if (stg_expect_signal(sc, COMMAND_PHASE, BSTAT_REQ) <= 0)
			break;

		SCSI_LOW_SETUP_PHASE(ti, PH_CMD);
		if (scsi_low_cmd(slp, ti) != 0)
		{
			scsi_low_attention(slp);
		}

		if (stg_xfer(sc, slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen,
			     COMMAND_PHASE, 0) != 0)
		{
			kprintf("%s: CMDOUT short\n", slp->sl_xname);
		}
		break;

	case DATA_OUT_PHASE:
		SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
		if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0)
		{
			scsi_low_attention(slp);
		}

		if ((sc->sc_icinit & ICTL_FIFO) != 0)
			stg_pio_write(sc, ti, sc->sc_wthold);
		else
			stg_pio_write(sc, ti, 0);
		break;

	case DATA_IN_PHASE:
		SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
		if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0)
		{
			scsi_low_attention(slp);
		}

		if ((sc->sc_icinit & ICTL_FIFO) != 0)
			stg_pio_read(sc, ti, sc->sc_rthold);
		else
			stg_pio_read(sc, ti, 0);
		break;

	case STATUS_PHASE:
		regv = stg_expect_signal(sc, STATUS_PHASE, BSTAT_REQ);
		if (regv <= 0)
			break;

		SCSI_LOW_SETUP_PHASE(ti, PH_STAT);
		regv = bus_space_read_1(iot, ioh, tmc_sdna);
		if (scsi_low_statusin(slp, ti, regv | derror) != 0)
		{
			scsi_low_attention(slp);
		}
		if (regv != bus_space_read_1(iot, ioh, tmc_rdata))
		{
			kprintf("%s: STATIN: data mismatch\n", slp->sl_xname);
		}
		stg_negate_signal(sc, BSTAT_ACK, "statin<ACK>");
		break;

	case MESSAGE_OUT_PHASE:
		if (stg_expect_signal(sc, MESSAGE_OUT_PHASE, BSTAT_REQ) <= 0)
			break;

		SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
		flags = (ti->ti_ophase != ti->ti_phase) ? 
				SCSI_LOW_MSGOUT_INIT : 0;
		len = scsi_low_msgout(slp, ti, flags);

		if (len > 1 && slp->sl_atten == 0)
		{
			scsi_low_attention(slp);
		}

		if (stg_xfer(sc, ti->ti_msgoutstr, len, MESSAGE_OUT_PHASE,
			     slp->sl_clear_atten) != 0)
		{
			kprintf("%s: MSGOUT short\n", slp->sl_xname);
		}
		else
		{
			if (slp->sl_msgphase >= MSGPH_ABORT) 
			{
				stg_disconnected(sc, ti);
			}
		}
		break;

	case MESSAGE_IN_PHASE:
		/* confirm phase and req signal */
		if (stg_expect_signal(sc, MESSAGE_IN_PHASE, BSTAT_REQ) <= 0)
			break;

		SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN);

		/* read data with NOACK */
		regv = bus_space_read_1(iot, ioh, tmc_sdna);

		if (scsi_low_msgin(slp, ti, derror | regv) == 0)
		{
			if (scsi_low_is_msgout_continue(ti, 0) != 0)
			{
				scsi_low_attention(slp);
			}
		}

		/* read data with ACK */
		if (regv != bus_space_read_1(iot, ioh, tmc_rdata))
		{
			kprintf("%s: MSGIN: data mismatch\n", slp->sl_xname);
		}

		/* wait for the ack negated */
		stg_negate_signal(sc, BSTAT_ACK, "msgin<ACK>");

		if (slp->sl_msgphase != 0 && slp->sl_msgphase < MSGPH_ABORT)
		{
			stg_disconnected(sc, ti);
		}
		break;

	case BUSFREE_PHASE:
		kprintf("%s: unexpected disconnect\n", slp->sl_xname);
		stg_disconnected(sc, ti);
		break;

	default:
		slp->sl_error |= FATALIO;
		kprintf("%s: unknown phase bus %x intr %x\n",
			slp->sl_xname, status, astatus);
		break;
	}

out:
	bus_space_write_1(iot, ioh, tmc_ictl, sc->sc_icinit);
	return 1;
}