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

📄 siop.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 5 页
字号:
			    siop_cmd->siop_tables.msg_in[0]);			siop_cmd->siop_tables.msg_out[0] = MSG_MESSAGE_REJECT;			siop_cmd->siop_tables.t_msgout.count= htole32(1);			siop_table_sync(siop_cmd,			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);			CALL_SCRIPT(Ent_send_msgout);			return 1;		}		case A_int_extmsgin:#ifdef SIOP_DEBUG_INTR			printf("extended message: msg 0x%x len %d\n",			    siop_cmd->siop_tables.msg_in[2], 			    siop_cmd->siop_tables.msg_in[1]);#endif			if (siop_cmd->siop_tables.msg_in[1] > 6)				printf("%s: extended message too big (%d)\n",				    sc->sc_dev.dv_xname,				    siop_cmd->siop_tables.msg_in[1]);			siop_cmd->siop_tables.t_extmsgdata.count =			    htole32(siop_cmd->siop_tables.msg_in[1] - 1);			siop_table_sync(siop_cmd,			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);			CALL_SCRIPT(Ent_get_extmsgdata);			return 1;		case A_int_extmsgdata:		{			int neg_action = SIOP_NEG_NOP;			const char *neg_name = "";#ifdef SIOP_DEBUG_INTR			{			int i;			printf("extended message: 0x%x, data:",			    siop_cmd->siop_tables.msg_in[2]);			for (i = 3; i < 2 + siop_cmd->siop_tables.msg_in[1];			    i++)				printf(" 0x%x",				    siop_cmd->siop_tables.msg_in[i]);			printf("\n");			}#endif			switch (siop_cmd->siop_tables.msg_in[2]) {			case MSG_EXT_WDTR:				neg_action = siop_wdtr_neg(siop_cmd);				neg_name = "wdtr";				break;			case MSG_EXT_SDTR:				neg_action = siop_sdtr_neg(siop_cmd);				neg_name = "sdtr";				break;			case MSG_EXT_PPR:				neg_action = siop_ppr_neg(siop_cmd);				neg_name = "ppr";				break;			default:				neg_action = SIOP_NEG_MSGREJ;				break;			}			switch (neg_action) {			case SIOP_NEG_NOP:				break;			case SIOP_NEG_MSGOUT:				siop_update_scntl3(sc, siop_cmd->siop_target);				siop_table_sync(siop_cmd,				    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);				CALL_SCRIPT(Ent_send_msgout);				break;			case SIOP_NEG_ACK:				siop_update_scntl3(sc, siop_cmd->siop_target);				siop_table_sync(siop_cmd,				    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);				CALL_SCRIPT(Ent_msgin_ack);				break;			case SIOP_NEG_MSGREJ:				siop_cmd->siop_tables.msg_out[0] = MSG_MESSAGE_REJECT;				siop_cmd->siop_tables.t_msgout.count = htole32(1);				siop_table_sync(siop_cmd,				    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);				CALL_SCRIPT(Ent_send_msgout);				break;			default:				panic("invalid return value from siop_%s_neg(): 0x%x", neg_name, neg_action);			}						return (1);		}		case A_int_disc:			INCSTAT(siop_stat_intr_sdp);			offset = bus_space_read_1(sc->sc_rt, sc->sc_rh,			    SIOP_SCRATCHA + 1);#ifdef SIOP_DEBUG_DR			printf("disconnect offset %d\n", offset);#endif			if (offset > SIOP_NSG) {				printf("%s: bad offset for disconnect (%d)\n",				    sc->sc_dev.dv_xname, offset);				goto reset;			}			/* 			 * offset == SIOP_NSG may be a valid condition if			 * we get a sdp when the xfer is done.			 * Don't call memmove in this case.			 */			if (offset < SIOP_NSG) {				bcopy(&siop_cmd->siop_tables.data[offset],				    &siop_cmd->siop_tables.data[0],				    (SIOP_NSG - offset) * sizeof(struct scr_table));				siop_table_sync(siop_cmd,				    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);			}			CALL_SCRIPT(Ent_script_sched);			/* check if we can put some command in scheduler */			siop_start(sc);			return 1;		case A_int_resfail:			printf("reselect failed\n");			CALL_SCRIPT(Ent_script_sched);			return  1;		case A_int_done:			if (xs == NULL) {				printf("%s: done without command, DSA=0x%lx\n",				    sc->sc_dev.dv_xname, (u_long)siop_cmd->dsa);				siop_cmd->status = CMDST_FREE;				siop_start(sc);				CALL_SCRIPT(Ent_script_sched);				return 1;			}#ifdef SIOP_DEBUG_INTR			printf("done, DSA=0x%lx target id 0x%x last msg "			    "in=0x%x status=0x%x\n", (u_long)siop_cmd->dsa,			    letoh32(siop_cmd->siop_tables.id),			    siop_cmd->siop_tables.msg_in[0],			    letoh32(siop_cmd->siop_tables.status));#endif			INCSTAT(siop_stat_intr_done);			if (siop_cmd->status == CMDST_SENSE_ACTIVE)				siop_cmd->status = CMDST_SENSE_DONE;			else				siop_cmd->status = CMDST_DONE;			goto end;		default:			printf("unknown irqcode %x\n", irqcode);			if (xs) {				xs->error = XS_SELTIMEOUT;				goto end;			}			goto reset;		}		return 1;	}	/* We can get here if ISTAT_DIP and DSTAT_DFE are the only bits set. */	/* But that *SHOULDN'T* happen. It does on powerpc (at least).	     */	printf("%s: siop_intr() - we should not be here!\n"	    "   istat = 0x%x, dstat = 0x%x, sist = 0x%x, sstat1 = 0x%x\n"	    "   need_reset = %x, irqcode = %x, siop_cmd %s\n",	    sc->sc_dev.dv_xname,	    istat, dstat, sist, sstat1, need_reset, irqcode,	    (siop_cmd == NULL) ? "== NULL" : "!= NULL");	goto reset; /* Where we should have gone in the first place! */end:	/*	 * Restart the script now if command completed properly.	 * Otherwise wait for siop_scsicmd_end(), it may need to put	 * a cmd at the front of the queue.	 */	if (letoh32(siop_cmd->siop_tables.status) == SCSI_OK &&	    TAILQ_FIRST(&sc->urgent_list) != NULL)		CALL_SCRIPT(Ent_script_sched);	else		restart = 1;	siop_scsicmd_end(siop_cmd);	siop_lun->siop_tag[tag].active = NULL;	if (siop_cmd->status == CMDST_FREE) {		TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);		siop_lun->lun_flags &= ~SIOP_LUNF_FULL;		if (freetarget && siop_target->status == TARST_PROBING)			siop_del_dev(sc, target, lun);	}	siop_start(sc);	if (restart)		CALL_SCRIPT(Ent_script_sched);	return 1;}voidsiop_scsicmd_end(siop_cmd)	struct siop_cmd *siop_cmd;{	struct scsi_xfer *xs = siop_cmd->xs;	struct siop_softc *sc = siop_cmd->siop_sc;	switch(letoh32(siop_cmd->siop_tables.status)) {	case SCSI_OK:		xs->error = (siop_cmd->status == CMDST_DONE) ?		    XS_NOERROR : XS_SENSE;		break;	case SCSI_BUSY:		xs->error = XS_BUSY;		break;	case SCSI_CHECK:		if (siop_cmd->status == CMDST_SENSE_DONE) {			/* request sense on a request sense ? */			printf("request sense failed\n");			xs->error = XS_DRIVER_STUFFUP;		} else {			siop_cmd->status = CMDST_SENSE;		}		break;	case SCSI_QUEUE_FULL:		{		struct siop_lun *siop_lun = siop_cmd->siop_target->siop_lun[		    xs->sc_link->lun];		/*		 * Device didn't queue the command. We have to retry		 * it.  We insert it into the urgent list, hoping to		 * preserve order.  But unfortunately, commands already		 * in the scheduler may be accepted before this one.		 * Also remember the condition, to avoid starting new		 * commands for this device before one is done.		 */		INCSTAT(siop_stat_intr_qfull);#ifdef SIOP_DEBUG		printf("%s:%d:%d: queue full (tag %d)\n", sc->sc_dev.dv_xname,		    xs->sc_link->target,		    xs->sc_link->lun, siop_cmd->tag);#endif#ifndef PMON		timeout_del(&xs->stimeout);#endif		siop_lun->lun_flags |= SIOP_LUNF_FULL;		siop_cmd->status = CMDST_READY;		siop_setuptables(siop_cmd);		TAILQ_INSERT_TAIL(&sc->urgent_list, siop_cmd, next);		return;		}	case SCSI_SIOP_NOCHECK:		/*		 * don't check status, xs->error is already valid		 */		break;	case SCSI_SIOP_NOSTATUS:		/*		 * the status byte was not updated, cmd was		 * aborted		 */		xs->error = XS_SELTIMEOUT;		break;	default:		xs->error = XS_DRIVER_STUFFUP;	}	if (siop_cmd->status != CMDST_SENSE_DONE &&	    xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {		bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data,		    0, siop_cmd->dmamap_data->dm_mapsize,		    (xs->flags & SCSI_DATA_IN) ?		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);		bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_data);	}	bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_cmd);	if (siop_cmd->status == CMDST_SENSE) {		/* issue a request sense for this target */		int error;		siop_cmd->rs_cmd.opcode = REQUEST_SENSE;		siop_cmd->rs_cmd.byte2 = xs->sc_link->lun << 5;		siop_cmd->rs_cmd.unused[0] = siop_cmd->rs_cmd.unused[1] = 0;		siop_cmd->rs_cmd.length = sizeof(struct scsi_sense_data);		siop_cmd->rs_cmd.control = 0;		siop_cmd->flags &= ~CMDFL_TAG;		error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_cmd,		    &siop_cmd->rs_cmd, sizeof(struct scsi_sense),		    NULL, BUS_DMA_NOWAIT);		if (error) {			printf("%s: unable to load cmd DMA map "			    "(for SENSE): %d\n",			    sc->sc_dev.dv_xname, error);			xs->error = XS_DRIVER_STUFFUP;			goto out;		}		error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_data,		    &xs->sense, sizeof(struct scsi_sense_data),		    NULL, BUS_DMA_NOWAIT);		if (error) {			printf("%s: unable to load data DMA map "			    "(for SENSE): %d\n",			    sc->sc_dev.dv_xname, error);			xs->error = XS_DRIVER_STUFFUP;			bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_cmd);			goto out;		}		bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data,		    0, siop_cmd->dmamap_data->dm_mapsize,		    BUS_DMASYNC_PREREAD);		bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_cmd,		    0, siop_cmd->dmamap_cmd->dm_mapsize,		    BUS_DMASYNC_PREWRITE);		siop_setuptables(siop_cmd);		/* arrange for the cmd to be handled now */		TAILQ_INSERT_HEAD(&sc->urgent_list, siop_cmd, next);		return;	} else if (siop_cmd->status == CMDST_SENSE_DONE) {		bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data,		    0, siop_cmd->dmamap_data->dm_mapsize,		    BUS_DMASYNC_POSTREAD);		bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_data);	}out:#ifndef PMON	timeout_del(&siop_cmd->xs->stimeout);#endif	siop_cmd->status = CMDST_FREE;	xs->flags |= ITSDONE;	xs->resid = 0;	scsi_done(xs);}/* * handle a rejected queue tag message: the command will run untagged, * has to adjust the reselect script. */intsiop_handle_qtag_reject(siop_cmd)	struct siop_cmd *siop_cmd;{	struct siop_softc *sc = siop_cmd->siop_sc;	int target = siop_cmd->xs->sc_link->target;	int lun = siop_cmd->xs->sc_link->lun;	int tag = siop_cmd->siop_tables.msg_out[2];	struct siop_lun *siop_lun = sc->targets[target]->siop_lun[lun];#ifdef SIOP_DEBUG	printf("%s:%d:%d: tag message %d (%d) rejected (status %d)\n",	    sc->sc_dev.dv_xname, target, lun, tag, siop_cmd->tag,	    siop_cmd->status);#endif	if (siop_lun->siop_tag[0].active != NULL) {		printf("%s: untagged command already running for target %d "		    "lun %d (status %d)\n", sc->sc_dev.dv_xname, target, lun,		    siop_lun->siop_tag[0].active->status);		return -1;	}	/* clear tag slot */	siop_lun->siop_tag[tag].active = NULL;	/* add command to non-tagged slot */	siop_lun->siop_tag[0].active = siop_cmd;	siop_cmd->tag = 0;	/* adjust reselect script if there is one */	if (siop_lun->siop_tag[0].reseloff > 0) {		siop_script_write(sc,		    siop_lun->siop_tag[0].reseloff + 1,		    siop_cmd->dsa + sizeof(struct siop_xfer_common) +		    Ent_ldsa_reload_dsa);		siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);	}	return 0;}/* * Handle a bus reset: reset chip, unqueue all active commands, free all * target structs and report losage to upper layer. * As the upper layer may requeue immediately we have to first store * all active commands in a temporary queue. */voidsiop_handle_reset(sc)	struct siop_softc *sc;{	struct cmd_list reset_list;	struct siop_cmd *siop_cmd, *next_siop_cmd;	struct siop_lun *siop_lun;	int target, lun, tag;	/*	 * SCSI bus reset. Reset the chip and restart	 * the queue. Need to clean up all active commands.	 */	printf("%s: scsi bus reset\n", sc->sc_dev.dv_xname);	/* stop, reset and restart the chip */	siop_reset(sc);	TAILQ_INIT(&reset_list);	/*	 * Process all commands: first commmands being executed	 */	for (target = 0; target < sc->sc_link.adapter_buswidth;	    target++) {		if (sc->targets[target] == NULL)			continue;		for (lun = 0; lun < 8; lun++) {			siop_lun = sc->targets[target]->siop_lun[lun];			if (siop_lun == NULL)				continue;			siop_lun->lun_flags &= ~SIOP_LUNF_FULL;			for (tag = 0; tag <			    ((sc->targets[target]->flags & TARF_TAG) ?			    SIOP_NTAG : 1);			    tag++) {				siop_cmd = siop_lun->siop_tag[tag].active;				if (siop_cmd == NULL)					continue;				printf("cmd %p (target %d:%d) in reset list\n",				    siop_cmd, target, lun);				TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);				siop_lun->siop_tag[tag].active = NULL;			}		}		sc->targets[target]->status = TARST_ASYNC;		sc->targets[target]->flags  = 0;	}	/* Next commands from the urgent list */	for (siop_cmd = TAILQ_FIRST(&sc->urgent_list); siop_cmd != NULL;	    siop_cmd = next_siop_cmd) {		next_siop_cmd = TAILQ_NEXT(siop_cmd, next);		siop_cmd->flags &= ~CMDFL_TAG;		printf("cmd %p (target %d:%d) in reset list (wait)\n",		    siop_cmd, siop_cmd->xs->sc_link->target,		    siop_cmd->xs->sc_link->lun);		TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next);		TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);	}	/* Then command waiting in the input list */	for (siop_cmd = TAILQ_FIRST(&sc->ready_list); siop_cmd != NULL;	    siop_cmd = next_siop_cmd) {		next_siop_cmd = TAILQ_NEXT(siop_cmd, next);		siop_cmd->flags &= ~CMDFL_TAG;		printf("cmd %p (target %d:%d) in reset list (wait)\n",		    siop_cmd, siop_cmd->xs->sc_link->target,		    siop_cmd->xs->sc_link->lun);

⌨️ 快捷键说明

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