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

📄 siop.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 5 页
字号:
		TAILQ_REMOVE(&sc->ready_list, siop_cmd, next);		TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);	}	for (siop_cmd = TAILQ_FIRST(&reset_list); siop_cmd != NULL;	    siop_cmd = next_siop_cmd) {		next_siop_cmd = TAILQ_NEXT(siop_cmd, next);		siop_cmd->xs->error = (siop_cmd->flags & CMDFL_TIMEOUT) ?		    XS_TIMEOUT : XS_RESET;		siop_cmd->siop_tables.status = htole32(SCSI_SIOP_NOCHECK);		printf("cmd %p (status %d) about to be processed\n", siop_cmd,		    siop_cmd->status);		if (siop_cmd->status == CMDST_SENSE ||		    siop_cmd->status == CMDST_SENSE_ACTIVE) 			siop_cmd->status = CMDST_SENSE_DONE;		else			siop_cmd->status = CMDST_DONE;		TAILQ_REMOVE(&reset_list, siop_cmd, next);		siop_scsicmd_end(siop_cmd);		TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);	}}intsiop_scsicmd(xs)	struct scsi_xfer *xs;{	struct siop_softc *sc = (struct siop_softc *)xs->sc_link->adapter_softc;	struct siop_cmd *siop_cmd;	int s, error, i, j;	const int target = xs->sc_link->target;	const int lun = xs->sc_link->lun;	s = splbio();#ifdef SIOP_DEBUG_SCHED	printf("starting cmd 0x%02x for %d:%d\n", xs->cmd->opcode, target, lun);#endif	siop_cmd = TAILQ_FIRST(&sc->free_list);	if (siop_cmd != NULL) {		TAILQ_REMOVE(&sc->free_list, siop_cmd, next);	} else {		xs->error = XS_DRIVER_STUFFUP;		splx(s);		return(TRY_AGAIN_LATER);	}#ifndef PMON	/* Always reset xs->stimeout, lest we timeout_del() with trash */	timeout_set(&xs->stimeout, siop_timeout, siop_cmd);#endif#ifdef DIAGNOSTIC	if (siop_cmd->status != CMDST_FREE)		panic("siop_scsicmd: new cmd not free");#endif	if (sc->targets[target] == NULL) {#ifdef SIOP_DEBUG		printf("%s: alloc siop_target for target %d\n",			sc->sc_dev.dv_xname, target);#endif		sc->targets[target] =		    malloc(sizeof(struct siop_target), M_DEVBUF, M_NOWAIT);		if (sc->targets[target] == NULL) {			printf("%s: can't malloc memory for target %d\n",			    sc->sc_dev.dv_xname, target);			xs->error = XS_DRIVER_STUFFUP;			splx(s);			return(TRY_AGAIN_LATER);		}		sc->targets[target]->status = TARST_PROBING;		sc->targets[target]->flags  = 0;		sc->targets[target]->id = sc->clock_div << 24; /* scntl3 */		sc->targets[target]->id |=  target << 16; /* id */		/* sc->targets[target]->id |= 0x0 << 8; scxfer is 0 */		/* get a lun switch script */		sc->targets[target]->lunsw = siop_get_lunsw(sc);		if (sc->targets[target]->lunsw == NULL) {			printf("%s: can't alloc lunsw for target %d\n",			    sc->sc_dev.dv_xname, target);			xs->error = XS_DRIVER_STUFFUP;			splx(s);			return(TRY_AGAIN_LATER);		}		for (i=0; i < 8; i++)			sc->targets[target]->siop_lun[i] = NULL;		siop_add_reselsw(sc, target);	}	if (sc->targets[target]->siop_lun[lun] == NULL) {		sc->targets[target]->siop_lun[lun] =		    malloc(sizeof(struct siop_lun), M_DEVBUF, M_NOWAIT);		if (sc->targets[target]->siop_lun[lun] == NULL) {			printf("%s: can't alloc siop_lun for target %d "			    "lun %d\n", sc->sc_dev.dv_xname, target, lun);			xs->error = XS_DRIVER_STUFFUP;			splx(s);			return(TRY_AGAIN_LATER);		}		memset(sc->targets[target]->siop_lun[lun], 0,		    sizeof(struct siop_lun));	}	siop_cmd->siop_target = sc->targets[target];	siop_cmd->xs = xs;	siop_cmd->flags = 0;	siop_cmd->status = CMDST_READY;	/* load the DMA maps */	error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_cmd,	    xs->cmd, xs->cmdlen, NULL, BUS_DMA_NOWAIT);	if (error) {		printf("%s: unable to load cmd DMA map: %d\n",		    sc->sc_dev.dv_xname, error);		xs->error = XS_DRIVER_STUFFUP;		splx(s);		return(TRY_AGAIN_LATER);	}	if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {		error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_data,		    xs->data, xs->datalen, NULL, BUS_DMA_NOWAIT);		if (error) {			printf("%s: unable to load cmd DMA map: %d\n",			    sc->sc_dev.dv_xname, error);			xs->error = XS_DRIVER_STUFFUP;			bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_cmd);			splx(s);			return(TRY_AGAIN_LATER);		}		bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data,		    0, siop_cmd->dmamap_data->dm_mapsize,		    (xs->flags & SCSI_DATA_IN) ?		    BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);	}	bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_cmd,	    0, siop_cmd->dmamap_cmd->dm_mapsize,	    BUS_DMASYNC_PREWRITE);	siop_setuptables(siop_cmd);	TAILQ_INSERT_TAIL(&sc->ready_list, siop_cmd, next);	siop_start(sc);	if (xs->flags & SCSI_POLL) {		/* poll for command completion */		for(i = xs->timeout; i > 0; i--) {			siop_intr(sc);			if (xs->flags & ITSDONE) {				if ((xs->cmd->opcode == INQUIRY)				    && (xs->error == XS_NOERROR)) {					error = ((struct scsi_inquiry_data *)xs->data)->device & SID_QUAL;					if (error != SID_QUAL_BAD_LU) {						/* 						 * Allocate enough commands to hold at least max openings						 * worth of commands. Do this statically now 'cuz 						 * a) We can't rely on the upper layers to ask for more						 * b) Doing it dynamically in siop_startcmd may cause 						 *    calls to bus_dma* functions in interrupt context						 */						for (j = 0; j < SIOP_NTAG; j += SIOP_NCMDPB)							siop_morecbd(sc);						if (sc->targets[target]->status == TARST_PROBING)							sc->targets[target]->status = TARST_ASYNC;						/* Can't do lun 0 here, because flags not set yet */						if (lun > 0)							siop_add_dev(sc, target, lun);					}				}				break;			}			delay(1000);		}		splx(s);		if (i == 0) {			siop_timeout(siop_cmd);			while ((xs->flags & ITSDONE) == 0)				siop_intr(sc);		}		return (COMPLETE);	}	splx(s);	return (SUCCESSFULLY_QUEUED);}voidsiop_start(sc)	struct siop_softc *sc;{	struct siop_cmd *siop_cmd, *next_siop_cmd;	struct siop_lun *siop_lun;	u_int32_t dsa;#ifndef PMON	int timeout;#endif	int target, lun, tag, slot;	int newcmd = 0; 	int doingready = 0;	/*	 * first make sure to read valid data	 */	siop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);	/*	 * The queue management here is a bit tricky: the script always looks	 * at the slots from first to last, so if we always use the first 	 * free slot commands can stay at the tail of the queue ~forever.	 * The algorithm used here is to restart from the head when we know	 * that the queue is empty, and only add commands after the last one.	 * When we're at the end of the queue wait for the script to clear it.	 * The best thing to do here would be to implement a circular queue,	 * but using only 53c720 features this can be "interesting".	 * A mid-way solution could be to implement 2 queues and swap orders.	 */	slot = sc->sc_currschedslot;	/*	 * If the instruction is 0x80000000 (JUMP foo, IF FALSE) the slot is	 * free. As this is the last used slot, all previous slots are free,	 * we can restart from 1.	 * slot 0 is reserved for request sense commands.	 */	if (siop_script_read(sc, (Ent_script_sched_slot0 / 4) + slot * 2) ==	    0x80000000) {		slot = sc->sc_currschedslot = 1;	} else {		slot++;	}	/* first handle commands from the urgent list */	siop_cmd = TAILQ_FIRST(&sc->urgent_list);again:	for (; siop_cmd != NULL; siop_cmd = next_siop_cmd) {		next_siop_cmd = TAILQ_NEXT(siop_cmd, next);#ifdef DIAGNOSTIC		if (siop_cmd->status != CMDST_READY &&		    siop_cmd->status != CMDST_SENSE)			panic("siop: non-ready cmd in ready list");#endif			target = siop_cmd->xs->sc_link->target;		lun = siop_cmd->xs->sc_link->lun;		siop_lun = sc->targets[target]->siop_lun[lun];		/* if non-tagged command active, wait */		if (siop_lun->siop_tag[0].active != NULL)			continue;		/*		 * if we're in a queue full condition don't start a new		 * command, unless it's a request sense		 */		if ((siop_lun->lun_flags & SIOP_LUNF_FULL) &&		    siop_cmd->status == CMDST_READY)			continue;		/* find a free tag if needed */		if (siop_cmd->flags & CMDFL_TAG) {			for (tag = 1; tag < SIOP_NTAG; tag++) {				if (siop_lun->siop_tag[tag].active == NULL)					break;			}			if (tag == SIOP_NTAG) /* no free tag */				continue;		} else {			tag = 0;		}		siop_cmd->tag = tag;		/*		 * find a free scheduler slot and load it. If it's a request		 * sense we need to use slot 0.		 */		if (siop_cmd->status != CMDST_SENSE) {			for (; slot < SIOP_NSLOTS; slot++) {				/*				 * If cmd if 0x80000000 the slot is free				 */				if (siop_script_read(sc,				    (Ent_script_sched_slot0 / 4) + slot * 2) ==				    0x80000000)					break;			}			/* no more free slots, no need to continue */			if (slot == SIOP_NSLOTS) {				goto end;			}		} else {			slot = 0;			if (siop_script_read(sc, Ent_script_sched_slot0 / 4)			    != 0x80000000) 				goto end;		}#ifdef SIOP_DEBUG_SCHED		printf("using slot %d for DSA 0x%lx\n", slot,		    (u_long)siop_cmd->dsa);#endif		/* Ok, we can add the tag message */		if (tag > 0) {#ifdef DIAGNOSTIC			int msgcount =			    letoh32(siop_cmd->siop_tables.t_msgout.count);			if (msgcount != 1)				printf("%s:%d:%d: tag %d with msgcount %d\n",				    sc->sc_dev.dv_xname, target, lun, tag,				    msgcount);#endif			if (siop_cmd->xs->bp != NULL &&			    (siop_cmd->xs->bp->b_flags & B_ASYNC))				siop_cmd->siop_tables.msg_out[1] =				    MSG_SIMPLE_Q_TAG;			else				siop_cmd->siop_tables.msg_out[1] =				    MSG_ORDERED_Q_TAG;			siop_cmd->siop_tables.msg_out[2] = tag;			siop_cmd->siop_tables.t_msgout.count = htole32(3);		}		/* note that we started a new command */		newcmd = 1;		/* mark command as active */		if (siop_cmd->status == CMDST_READY) {			siop_cmd->status = CMDST_ACTIVE;		} else if (siop_cmd->status == CMDST_SENSE) {			siop_cmd->status = CMDST_SENSE_ACTIVE;		} else			panic("siop_start: bad status");		if (doingready)			TAILQ_REMOVE(&sc->ready_list, siop_cmd, next);		else			TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next);		siop_lun->siop_tag[tag].active = siop_cmd;		/* patch scripts with DSA addr */		dsa = siop_cmd->dsa;		/* first reselect switch, if we have an entry */		if (siop_lun->siop_tag[tag].reseloff > 0)			siop_script_write(sc,			    siop_lun->siop_tag[tag].reseloff + 1,			    dsa + sizeof(struct siop_xfer_common) +			    Ent_ldsa_reload_dsa);		/* CMD script: MOVE MEMORY addr */		siop_cmd->siop_xfer->resel[E_ldsa_abs_slot_Used[0]] = 		   htole32(sc->sc_scriptaddr + Ent_script_sched_slot0 +		   slot * 8);		siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);		/* scheduler slot: JUMP ldsa_select */		siop_script_write(sc,		    (Ent_script_sched_slot0 / 4) + slot * 2 + 1,		    dsa + sizeof(struct siop_xfer_common) + Ent_ldsa_select);#ifndef PMON		/* handle timeout */		if (siop_cmd->status == CMDST_ACTIVE) {			if ((siop_cmd->xs->flags & SCSI_POLL) == 0) {				/* start expire timer */				timeout = (u_int64_t) siop_cmd->xs->timeout *				    (u_int64_t)hz / 1000;				if (timeout == 0)					timeout = 1;				timeout_add(&siop_cmd->xs->stimeout, timeout);			}		}#endif		/*		 * Change JUMP cmd so that this slot will be handled		 */		siop_script_write(sc, (Ent_script_sched_slot0 / 4) + slot * 2,		    0x80080000);		/* if we're using the request sense slot, stop here */		if (slot == 0)			goto end;		sc->sc_currschedslot = slot;		slot++;	}	if (doingready == 0) {		/* now process ready list */		doingready = 1;		siop_cmd = TAILQ_FIRST(&sc->ready_list);		goto again;	}end:	/* if nothing changed no need to flush cache and wakeup script */	if (newcmd == 0)		return;	/* make sure SCRIPT processor will read valid data */	siop_script_sync(sc,BUS_DMASYNC_PREREAD |  BUS_DMASYNC_PREWRITE);	/* Signal script it has some work to do */	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT, ISTAT_SIGP);	/* and wait for IRQ */	return;}voidsiop_timeout(v)	void *v;{	struct siop_cmd *siop_cmd = v;	struct siop_softc *sc = siop_cmd->siop_sc;	int s;	sc_print_addr(siop_cmd->xs->sc_link);	printf("timeout on SCSI command 0x%x\n", siop_cmd->xs->cmd->opcode);	s = splbio();	/* reset the scsi bus */	siop_resetbus(sc);#ifndef PMON	/* deactivate callout */	timeout_del(&siop_cmd->xs->stimeout);#endif	/*	 * Mark command as being timed out and just return. The bus	 * reset will generate an interrupt, which will be handled	 * in siop_intr().	 */	siop_cmd->flags |= CMDFL_TIMEOUT;	splx(s);	return;}voidsiop_dump_script(sc)	struct siop_softc *sc;{ 	int i;	printf("Dumping script @ 0x%08x:\n", sc->sc_script);	for (i = 0; i < PAGE_SIZE / 4; i += 2) {		printf("0x%04x: 0x%08x 0x%08x", i * 4,		    siop_script_read(sc, i), siop_script_read(sc, i+1));		if ((siop_script_read(sc, i) & 0xe0000000) == 0xc0000000) {			i++;			printf(" 0x%08x", siop_script_read(sc, i+1));		}		printf("\n");

⌨️ 快捷键说明

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