示例#1
0
static int
stg_expect_signal(struct stg_softc *sc, u_int8_t phase, u_int8_t mask)
{
	struct scsi_low_softc *slp = &sc->sc_sclow;
	bus_space_tag_t bst = sc->sc_iot;
	bus_space_handle_t bsh = sc->sc_ioh;
	int wc;
	u_int8_t ph;

	phase &= PHASE_MASK;
	for (wc = 0; wc < STG_DELAY_MAX / STG_DELAY_INTERVAL; wc ++)
	{
		ph = bus_space_read_1(bst, bsh, tmc_bstat);
		if (ph == (u_int8_t) -1)
			return -1;
		if ((ph & PHASE_MASK) != phase)
			return 0;
		if ((ph & mask) != 0)
			return 1;

		SCSI_LOW_DELAY(STG_DELAY_INTERVAL);
	}

	kprintf("%s: stg_expect_signal timeout\n", slp->sl_xname);
	return -1;
}
示例#2
0
/****************************************************
 * scsi low interface
 ****************************************************/
static void
stghw_attention(struct stg_softc *sc)
{

	sc->sc_busc |= BCTL_ATN;
	sc->sc_busimg |= BCTL_ATN;
	bus_space_write_1(sc->sc_iot, sc->sc_ioh, tmc_bctl, sc->sc_busimg);
	SCSI_LOW_DELAY(10);
}
示例#3
0
static void
stghw_bus_reset(struct stg_softc *sc)
{
	bus_space_tag_t iot = sc->sc_iot;
	bus_space_handle_t ioh = sc->sc_ioh;

	bus_space_write_1(iot, ioh, tmc_ictl, 0);
	bus_space_write_1(iot, ioh, tmc_fctl, 0);
	stghw_bcr_write_1(sc, BCTL_RST);
	SCSI_LOW_DELAY(100000);
	stghw_bcr_write_1(sc, BCTL_BUSFREE);
}
示例#4
0
static int
stghw_select_targ_wait(struct stg_softc *sc, int mu)
{
	bus_space_tag_t iot = sc->sc_iot;
	bus_space_handle_t ioh = sc->sc_ioh;

	mu = mu / STGHW_SELECT_INTERVAL;
	while (mu -- > 0)
	{
		if ((bus_space_read_1(iot, ioh, tmc_bstat) & BSTAT_BSY) == 0)
		{
			SCSI_LOW_DELAY(STGHW_SELECT_INTERVAL);
			continue;
		}
		SCSI_LOW_DELAY(1);
		if ((bus_space_read_1(iot, ioh, tmc_bstat) & BSTAT_BSY) != 0)
		{
			return 0;
		}
	}
	return ENXIO;
}
示例#5
0
void
bshw_bus_reset(struct ct_softc *ct)
{
    struct scsi_low_softc *slp = &ct->sc_sclow;
    struct ct_bus_access_handle *chp = &ct->sc_ch;
    struct bshw_softc *bs = ct->ct_hw;
    struct bshw *hw = bs->sc_hw;
    bus_addr_t offs;
    u_int8_t regv;
    int i;

    /* open hardware busmaster mode */
    if (hw->hw_dma_init != NULL && ((*hw->hw_dma_init)(ct)) != 0)
    {
        printf("%s: change mode using external DMA (%x)\n",
               slp->sl_xname, (u_int)ct_cr_read_1(chp, 0x37));
    }

    /* clear hardware synch registers */
    offs = hw->hw_sregaddr;
    if (offs != 0)
    {
        for (i = 0; i < 8; i ++, offs ++)
        {
            ct_cr_write_1(chp, offs, 0);
            if ((hw->hw_flags & BSHW_DOUBLE_DMACHAN) != 0)
                ct_cr_write_1(chp, offs + 8, 0);
        }
    }

    /* disable interrupt & assert reset */
    regv = ct_cr_read_1(chp, wd3s_mbank);
    regv |= MBR_RST;
    regv &= ~MBR_IEN;
    ct_cr_write_1(chp, wd3s_mbank, regv);

    SCSI_LOW_DELAY(500000);

    /* reset signal off */
    regv &= ~MBR_RST;
    ct_cr_write_1(chp, wd3s_mbank, regv);

    /* interrupt enable */
    regv |= MBR_IEN;
    ct_cr_write_1(chp, wd3s_mbank, regv);
}
示例#6
0
static int
stg_negate_signal(struct stg_softc *sc, u_int8_t mask, u_char *s)
{
	struct scsi_low_softc *slp = &sc->sc_sclow;
	bus_space_tag_t bst = sc->sc_iot;
	bus_space_handle_t bsh = sc->sc_ioh;
	int wc;
	u_int8_t regv;

	for (wc = 0; wc < STG_DELAY_MAX / STG_DELAY_INTERVAL; wc ++)
	{
		regv = bus_space_read_1(bst, bsh, tmc_bstat);
		if (regv == (u_int8_t) -1)
			return -1;
		if ((regv & mask) == 0)
			return 1;

		SCSI_LOW_DELAY(STG_DELAY_INTERVAL);
	}

	kprintf("%s: %s stg_negate_signal timeout\n", slp->sl_xname, s);
	return -1;
}
示例#7
0
/**************************************************************
 * 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;
}
示例#8
0
static void
stg_pio_write(struct stg_softc *sc, struct targ_info *ti, u_int thold)
{
	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 sc_p *sp = &slp->sl_scp;
	u_int res;
	int tout;
	u_int8_t stat;

	if ((slp->sl_flags & HW_PDMASTART) == 0)
	{
		stat = sc->sc_fcWinit | FCTL_FIFOEN | FCTL_FIFOW;
		bus_space_write_1(iot, ioh, tmc_fctl, stat | FCTL_CLRFIFO);
		bus_space_write_1(iot, ioh, tmc_fctl, stat);
		slp->sl_flags |= HW_PDMASTART;
	}

	tout = sc->sc_tmaxcnt;
	while (tout -- > 0)
	{
		stat = bus_space_read_1(iot, ioh, tmc_bstat);
		if ((stat & PHASE_MASK) != DATA_OUT_PHASE)
			break;

		if (sp->scp_datalen <= 0)
		{
			if (sc->sc_dataout_timeout == 0)
				sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ;
			break;
		}

		if (thold > 0)
		{
			crit_enter();
			res = bus_space_read_2(iot, ioh, tmc_fdcnt);
			if (res > thold)
			{
				bus_space_write_1(iot, ioh, tmc_ictl,
						  sc->sc_icinit);
				crit_exit();
				break;
			}
			crit_exit();
		}
		else
		{
			res = bus_space_read_2(iot, ioh, tmc_fdcnt);
			if (res > sc->sc_maxwsize / 2)
			{
				SCSI_LOW_DELAY(1);
				continue;
			}
		}
			
		if (res == (u_int) -1)
			break;
		res = sc->sc_maxwsize - res;
		if (res > sp->scp_datalen)
			res = sp->scp_datalen;

		sp->scp_datalen -= res;
		if ((res & 0x1) != 0)
		{
			bus_space_write_1(iot, ioh, tmc_wfifo, *sp->scp_data);
			sp->scp_data ++;
			res --;
		}

		bus_space_write_multi_2(iot, ioh, tmc_wfifo, 
					(u_int16_t *) sp->scp_data, res >> 1);
		sp->scp_data += res;
	}

	if (tout <= 0)
		kprintf("%s: pio write timeout\n", slp->sl_xname);
}
示例#9
0
static void
stg_pio_read(struct stg_softc *sc, struct targ_info *ti, u_int thold)
{
	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 sc_p *sp = &slp->sl_scp;
	int tout;
	u_int res;
	u_int8_t stat;

	if ((slp->sl_flags & HW_PDMASTART) == 0)
	{
		bus_space_write_1(iot, ioh, tmc_fctl,
				  sc->sc_fcRinit | FCTL_FIFOEN);
		slp->sl_flags |= HW_PDMASTART;
	}

	tout = sc->sc_tmaxcnt;
	while (tout -- > 0)
	{
		if (thold > 0)
		{
			crit_enter();
			res = bus_space_read_2(iot, ioh, tmc_fdcnt);
			if (res < thold)
			{
				bus_space_write_1(iot, ioh, tmc_ictl,
						  sc->sc_icinit);
				crit_exit();
				break;
			}
			crit_exit();
		}
		else
		{
			stat = bus_space_read_1(iot, ioh, tmc_bstat);
			res = bus_space_read_2(iot, ioh, tmc_fdcnt);
			if (res == 0)
			{
				if ((stat & PHASE_MASK) != DATA_IN_PHASE)
					break;
				if (sp->scp_datalen <= 0)
					break;
				SCSI_LOW_DELAY(1);
				continue;
			}
		}

		/* The assumtion res != 0 is valid here */
		if (res > sp->scp_datalen)
		{
			if (res == (u_int) -1)
				break;

			slp->sl_error |= PDMAERR;
			if ((slp->sl_flags & HW_READ_PADDING) == 0)
			{
				kprintf("%s: read padding required\n",
					slp->sl_xname);
				break;
			}

			sp->scp_datalen = 0;
			if (res > STG_MAX_DATA_SIZE)
				res = STG_MAX_DATA_SIZE;
			while (res -- > 0)
			{
				(void) bus_space_read_1(iot, ioh, tmc_rfifo);
			}
			continue;
		}

		sp->scp_datalen -= res;
		if (res & 1)
		{
			*sp->scp_data = bus_space_read_1(iot, ioh, tmc_rfifo);
			sp->scp_data ++;
			res --;
		}

		bus_space_read_multi_2(iot, ioh, tmc_rfifo,
				       (u_int16_t *) sp->scp_data, res >> 1);
		sp->scp_data += res;
	}

	if (tout <= 0)
		kprintf("%s: pio read timeout\n", slp->sl_xname);
}
示例#10
0
static int
stg_timeout(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, count;
	u_int8_t status;

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

	status = bus_space_read_1(iot, ioh, tmc_bstat);
	if ((status & PHASE_MASK) == 0)
	{
		if (sc->sc_ubf_timeout ++ == 0)
			return 0;

		kprintf("%s: unexpected bus free detected\n", slp->sl_xname);
		slp->sl_error |= FATALIO;
		scsi_low_print(slp, slp->sl_Tnexus);
		stg_disconnected(sc, slp->sl_Tnexus);
		return 0;
	}

	switch (status & PHASE_MASK)
	{
	case DATA_OUT_PHASE:
		if (sc->sc_dataout_timeout == 0)
			break;
		if ((status & BSTAT_REQ) == 0)
			break;
		if (bus_space_read_2(iot, ioh, tmc_fdcnt) != 0)
			break;
		if ((-- sc->sc_dataout_timeout) > 0)
			break;	

	        slp->sl_error |= PDMAERR;
		if ((slp->sl_flags & HW_WRITE_PADDING) == 0)
		{
			kprintf("%s: write padding required\n",
				slp->sl_xname);
			break;
		}	

		bus_space_write_1(iot, ioh, tmc_ictl, 0);

		tout = STG_DELAY_MAX;
		while (tout --)
		{
			status = bus_space_read_1(iot, ioh, tmc_bstat);
			if ((status & PHASE_MASK) != DATA_OUT_PHASE)
				break;

			if (bus_space_read_2(iot, ioh, tmc_fdcnt) != 0)
			{
				SCSI_LOW_DELAY(1);
				continue;
			}

			for (count = sc->sc_maxwsize; count > 0; count --)
				bus_space_write_1(iot, ioh, tmc_wfifo, 0);
		}

		status = bus_space_read_1(iot, ioh, tmc_bstat);
		if ((status & PHASE_MASK) == DATA_OUT_PHASE)
			sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ;

		bus_space_write_1(iot, ioh, tmc_ictl, sc->sc_icinit);
		break;

	default:
		break;
	}
	return 0;
}