⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 siop_common.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 2 页
字号:
	int target = siop_cmd->xs->sc_link->target;	int sync, offset, scf;	int send_msgout = 0;	struct siop_xfer_common *tables = &siop_cmd->siop_xfer->tables;	sync = tables->msg_in[3];	offset = tables->msg_in[4];	/* revert to async until told otherwise */	sc->targets[target]->id    &= 0x0fff0000; /* Keep SCNTL3.EWS, SCNTL3.CCF and id */	sc->targets[target]->flags &= ~(TARF_ISDT | TARF_ISQAS | TARF_ISIUS);	if (siop_target->status == TARST_SYNC_NEG) {		/* we initiated sync negotiation */#ifdef DEBUG		printf("%s: sdtr for target %d: sync %d offset %d\n",		    sc->sc_dev.dv_xname, target, sync, offset);#endif		scf = siop_period_factor_to_scf(sc, sync, sc->targets[target]->flags);		if (offset > sc->maxoff || scf == 0)			goto reject;		sc->targets[target]->id |= scf << (24 + SCNTL3_SCF_SHIFT);		if (((sc->features & SF_CHIP_C10) == 0) && (sync < 25))			sc->targets[target]->id |= SCNTL3_ULTRA << 24;		sc->targets[target]->id |= (offset & 0xff) << 8;		goto end;		/*		 * We didn't find it in our table, so stay async and send reject		 * msg.		 */reject:		send_msgout = 1;		tables->t_msgout.count= htole32(1);		tables->msg_out[0] = MSG_MESSAGE_REJECT;	} else { /* target initiated sync neg */#ifdef DEBUG		printf("%s: target initiated sdtr for target %d: sync %d offset %d\n",		    sc->sc_dev.dv_xname, target, sync, offset);		printf("sdtr (target): sync %d offset %d\n", sync, offset);#endif		if (sync < sc->min_st_sync)			sync = sc->min_st_sync;		scf = siop_period_factor_to_scf(sc, sync, sc->targets[target]->flags);		if ((sc->targets[target]->flags & TARF_SYNC) == 0		    || offset == 0		    || scf == 0) {			goto async;		}		if ((offset > 31) && ((sc->targets[target]->flags & TARF_ISDT) == 0))			offset = 31;		if (offset > sc->maxoff)			offset = sc->maxoff;		sc->targets[target]->id |= scf << (24 + SCNTL3_SCF_SHIFT);		if (((sc->features & SF_CHIP_C10) == 0) && (sync < 25))			sc->targets[target]->id |= SCNTL3_ULTRA << 24;		sc->targets[target]->id |= (offset & 0xff) << 8;		siop_sdtr_msg(siop_cmd, 0, sync, offset);		send_msgout = 1;		goto end;async:		siop_sdtr_msg(siop_cmd, 0, 0, 0);		send_msgout = 1;	}end:#ifdef DEBUG	printf("id now 0x%x\n", sc->targets[target]->id);#endif	tables->id = htole32(sc->targets[target]->id);	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3,	    (sc->targets[target]->id >> 24) & 0xff);	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SXFER,	    (sc->targets[target]->id >> 8) & 0xff);	if (siop_target->status != TARST_PROBING) {		siop_target->status = TARST_OK;		siop_print_info(sc, target);	}	if (send_msgout) {		return SIOP_NEG_MSGOUT;	} else {		return SIOP_NEG_ACK;	}}voidsiop_ppr_msg(siop_cmd, offset, ssync, soff)	struct siop_cmd *siop_cmd;	int offset, ssync, soff;{	struct siop_softc *sc = siop_cmd->siop_sc;	u_int8_t protocol;	siop_cmd->siop_tables.msg_out[offset + 0] = MSG_EXTENDED;	siop_cmd->siop_tables.msg_out[offset + 1] = MSG_EXT_PPR_LEN;	siop_cmd->siop_tables.msg_out[offset + 2] = MSG_EXT_PPR;	siop_cmd->siop_tables.msg_out[offset + 3] = ssync;	siop_cmd->siop_tables.msg_out[offset + 4] = 0; /* RESERVED */	siop_cmd->siop_tables.msg_out[offset + 5] = soff;	siop_cmd->siop_tables.msg_out[offset + 6] = MSG_EXT_WDTR_BUS_16_BIT;	protocol = 0;	if (sc->min_dt_sync != 0)		protocol |= MSG_EXT_PPR_PROT_DT;	/* XXX - need tests for chip's capability to do QAS & IUS	 *       	 * if (test for QAS support)	 *         protocol |= MSG_EXT_PPR_PROT_QAS;	 * if (test for IUS support)	 *         protocol |= MSG_EXT_PPR_PROT_IUS;	 */	siop_cmd->siop_tables.msg_out[offset + 7] = protocol;	siop_cmd->siop_tables.t_msgout.count =	    htole32(offset + MSG_EXT_PPR_LEN + 2);}voidsiop_sdtr_msg(siop_cmd, offset, ssync, soff)	struct siop_cmd *siop_cmd;	int offset;	int ssync, soff;{	siop_cmd->siop_tables.msg_out[offset + 0] = MSG_EXTENDED;	siop_cmd->siop_tables.msg_out[offset + 1] = MSG_EXT_SDTR_LEN;	siop_cmd->siop_tables.msg_out[offset + 2] = MSG_EXT_SDTR;	siop_cmd->siop_tables.msg_out[offset + 3] = ssync;	if ((soff > 31) && ((siop_cmd->siop_target->flags & TARF_ISDT) == 0))		soff = 31;	siop_cmd->siop_tables.msg_out[offset + 4] = soff;	siop_cmd->siop_tables.t_msgout.count =	    htole32(offset + MSG_EXT_SDTR_LEN + 2);}voidsiop_wdtr_msg(siop_cmd, offset, wide)	struct siop_cmd *siop_cmd;	int offset;{	siop_cmd->siop_tables.msg_out[offset + 0] = MSG_EXTENDED;	siop_cmd->siop_tables.msg_out[offset + 1] = MSG_EXT_WDTR_LEN;	siop_cmd->siop_tables.msg_out[offset + 2] = MSG_EXT_WDTR;	siop_cmd->siop_tables.msg_out[offset + 3] = wide;	siop_cmd->siop_tables.t_msgout.count =	    htole32(offset + MSG_EXT_WDTR_LEN + 2);}voidsiop_minphys(bp)	struct buf *bp;{	minphys(bp);}voidsiop_sdp(siop_cmd)	struct siop_cmd *siop_cmd;{	/* save data pointer. Handle async only for now */	int offset, dbc, sstat;	struct siop_softc *sc = siop_cmd->siop_sc;	struct scr_table *table; /* table to patch */	if ((siop_cmd->xs->flags & (SCSI_DATA_OUT | SCSI_DATA_IN))	    == 0)	    return; /* no data pointers to save */	offset = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SCRATCHA + 1);	if (offset >= SIOP_NSG) {		printf("%s: bad offset in siop_sdp (%d)\n",		    sc->sc_dev.dv_xname, offset);		return;	}	table = &siop_cmd->siop_xfer->tables.data[offset];#ifdef DEBUG_DR	printf("sdp: offset %d count=%d addr=0x%x ", offset,	    table->count, table->addr);#endif	dbc = bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DBC) & 0x00ffffff;	if (siop_cmd->xs->flags & SCSI_DATA_OUT) {		/* need to account for stale data in FIFO */		if (sc->features & SF_CHIP_C10)			dbc += bus_space_read_2(sc->sc_rt, sc->sc_rh, SIOP_DFBC);		else {			int dfifo = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DFIFO);			if (sc->features & SF_CHIP_FIFO) {				dfifo |= (bus_space_read_1(sc->sc_rt, sc->sc_rh,					      SIOP_CTEST5) & CTEST5_BOMASK) << 8;				dbc += (dfifo - (dbc & 0x3ff)) & 0x3ff;			} else {				dbc += (dfifo - (dbc & 0x7f)) & 0x7f;			}		}		sstat = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SSTAT0);		if (sstat & SSTAT0_OLF)			dbc++;		if ((sc->features & SF_CHIP_C10) == 0)			if (sstat & SSTAT0_ORF)				dbc++;		if (siop_cmd->siop_target->flags & TARF_ISWIDE) {			sstat = bus_space_read_1(sc->sc_rt, sc->sc_rh,			    SIOP_SSTAT2);			if (sstat & SSTAT2_OLF1)				dbc++;			if ((sc->features & SF_CHIP_C10) == 0)				if (sstat & SSTAT2_ORF1)					dbc++;		}		/* clear the FIFO */		bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3,		    bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3) |		    CTEST3_CLF);	}	table->addr =	    htole32(letoh32(table->addr) + letoh32(table->count) - dbc);	table->count = htole32(dbc);#ifdef DEBUG_DR	printf("now count=%d addr=0x%x\n", table->count, table->addr);#endif}voidsiop_clearfifo(sc)	struct siop_softc *sc;{	int timeout = 0;	int ctest3 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3);#ifdef SIOP_DEBUG_INTR	printf("DMA fifo not empty!\n");#endif	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3,	    ctest3 | CTEST3_CLF);	while ((bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3) &	    CTEST3_CLF) != 0) {		delay(1);		if (++timeout > 1000) {			printf("clear fifo failed\n");			bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3,			    bus_space_read_1(sc->sc_rt, sc->sc_rh,			    SIOP_CTEST3) & ~CTEST3_CLF);			return;		}	}}intsiop_modechange(sc)	struct siop_softc *sc;{	int retry;	int sist0, sist1, stest2, stest4;	for (retry = 0; retry < 5; retry++) {		/*		 * Datasheet says to wait 100ms and re-read SIST1,		 * to check that DIFFSENSE is stable.		 * We may delay() 5 times for 100ms at interrupt time;		 * hopefully this will not happen often.		 */		delay(100000);		sist0 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SIST0);		sist1 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SIST1);		if (sist1 & SIEN1_SBMC)			continue; /* we got an irq again */		stest4 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_STEST4) &		    STEST4_MODE_MASK;		stest2 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2);		switch(stest4) {		case STEST4_MODE_DIF:			if (sc->features & SF_CHIP_C10) {				printf("%s: invalid SCSI mode 0x%x\n",				    sc->sc_dev.dv_xname, stest4);				return 0;			} else {				printf("%s: switching to differential mode\n",				    sc->sc_dev.dv_xname);				bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2,				    stest2 | STEST2_DIF);			}			break;		case STEST4_MODE_SE:			printf("%s: switching to single-ended mode\n",			    sc->sc_dev.dv_xname);			bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2,			    stest2 & ~STEST2_DIF);			break;		case STEST4_MODE_LVD:			printf("%s: switching to LVD mode\n",			    sc->sc_dev.dv_xname);			bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2,			    stest2 & ~STEST2_DIF);			break;		default:			printf("%s: invalid SCSI mode 0x%x\n",			    sc->sc_dev.dv_xname, stest4);			return 0;		}		bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST0,		    stest4 >> 2);		return 1;	}	printf("%s: timeout waiting for DIFFSENSE to stabilise\n",	    sc->sc_dev.dv_xname);	return 0;}voidsiop_resetbus(sc)	struct siop_softc *sc;{	int scntl1;	scntl1 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1);	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1,	    scntl1 | SCNTL1_RST);	/* minimum 25 us, more time won't hurt */	delay(100);	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1, scntl1);}/* * siop_print_info: print the current negotiated wide/sync xfer values for *                  a particular target. This function is called whenever *		    a wide/sync negotiation completes, i.e. whenever *		    target->status is set to TARST_OK. */voidsiop_print_info(sc, target)        struct siop_softc *sc;        int target;{	struct siop_target *siop_target;	u_int8_t scf, offset;	int scf_index, factors, i;	siop_target = sc->targets[target];		printf("%s: target %d now using %s%s%s%s%d bit ",            sc->sc_dev.dv_xname, target,	    (siop_target->flags & TARF_TAG) ? "tagged " : "",	    (siop_target->flags & TARF_ISDT) ? "DT " : "",	    (siop_target->flags & TARF_ISQAS) ? "QAS " : "",	    (siop_target->flags & TARF_ISIUS) ? "IUS " : "",	    (siop_target->flags & TARF_ISWIDE) ? 16 : 8);	offset = ((siop_target->id >> 8) & 0xff) >> SXFER_MO_SHIFT;	if (offset == 0)		printf("async ");	else { 		factors = sizeof(period_factor) / sizeof(period_factor[0]);				scf = ((siop_target->id >> 24) & SCNTL3_SCF_MASK) >> SCNTL3_SCF_SHIFT;		scf_index = sc->scf_index;		for (i = 0; i < factors; i++)			if (siop_target->flags & TARF_ISDT) {				if (period_factor[i].scf[scf_index].dt_scf == scf)					break;			}			else if	(period_factor[i].scf[scf_index].st_scf == scf)				break;		if (i >= factors)			printf("?? ");		else			printf("%s ", period_factor[i].rate);		printf("MHz %d REQ/ACK offset ", offset);	}		printf("xfers\n");}intsiop_period_factor_to_scf(sc, pf, flags)	struct siop_softc *sc;	int pf, flags;{	const int scf_index = sc->scf_index;	int i;	const int factors = sizeof(period_factor) / sizeof(period_factor[0]);	for (i = 0; i < factors; i++)		if (period_factor[i].factor == pf) {			if (flags & TARF_ISDT)				return (period_factor[i].scf[scf_index].dt_scf);			else				return (period_factor[i].scf[scf_index].st_scf);		}	return (0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -