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

📄 siop.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 5 页
字号:
	for (cbdp = TAILQ_FIRST(&sc->cmds); cbdp != NULL;	    cbdp = TAILQ_NEXT(cbdp, next)) {		if (dsa >= cbdp->xferdma->dm_segs[0].ds_addr &&	    	    dsa < cbdp->xferdma->dm_segs[0].ds_addr + PAGE_SIZE) {			dsa -= cbdp->xferdma->dm_segs[0].ds_addr;			siop_cmd = &cbdp->cmds[dsa / sizeof(struct siop_xfer)];			siop_table_sync(siop_cmd,			    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);			break;		}	} 	if (cbdp == NULL) {		siop_cmd = NULL;	}	if (siop_cmd) {		xs = siop_cmd->xs;		siop_target = siop_cmd->siop_target;		target = siop_cmd->xs->sc_link->target;		lun = siop_cmd->xs->sc_link->lun;		tag = siop_cmd->tag;		siop_lun = siop_target->siop_lun[lun];#ifdef DIAGNOSTIC		if (siop_cmd->status != CMDST_ACTIVE &&		    siop_cmd->status != CMDST_SENSE_ACTIVE) {			printf("siop_cmd (lun %d) not active (%d)\n",				lun, siop_cmd->status);			xs = NULL;			siop_target = NULL;			target = -1;			lun = -1;			tag = -1;			siop_lun = NULL;			siop_cmd = NULL;		} else if (siop_lun->siop_tag[tag].active != siop_cmd) {			printf("siop_cmd (lun %d tag %d) not in siop_lun "			    "active (%p != %p)\n", lun, tag, siop_cmd,			    siop_lun->siop_tag[tag].active);		}#endif	} else {		xs = NULL;		siop_target = NULL;		target = -1;		lun = -1;		tag = -1;		siop_lun = NULL;	}	if (istat & ISTAT_DIP) {		dstat = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DSTAT);#ifdef DIAGNOSTIC		printf("DSTAT: 0x%02x\n", dstat);#endif		if (dstat & DSTAT_SSI) {			printf("single step dsp 0x%08x dsa 0x%08x\n",			    bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP),			    bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA));			if ( bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) < 0xc0000000) {				printf("* uncached inst 0x%08x 0x%08x\n",					*(uint32_t*)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) + 0xa0000000),					*(uint32_t*)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) + 0xa0000004));				printf("* cached inst 0x%08x 0x%08x\n",					*(uint32_t*)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) + 0x80000000),					*(uint32_t*)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) + 0x80000004));			} else {				printf("* inst 0x%08x 0x%08x\n",					siop_script_read(sc,					(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) - sc->sc_scriptaddr) / 4),			    		siop_script_read(sc,					(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) - sc->sc_scriptaddr) / 4 + 1));			}			if ((dstat & ~(DSTAT_DFE | DSTAT_SSI)) == 0 &&			    (istat & ISTAT_SIP) == 0) {				bus_space_write_1(sc->sc_rt, sc->sc_rh,				    SIOP_DCNTL, bus_space_read_1(sc->sc_rt,				    sc->sc_rh, SIOP_DCNTL) | DCNTL_STD);			}			return 1;		}		if (dstat & ~(DSTAT_SIR | DSTAT_DFE | DSTAT_SSI)) {			printf("DMA IRQ:");			if (dstat & DSTAT_IID)				printf("Illegal instruction");			if (dstat & DSTAT_ABRT)				printf(" abort");			if (dstat & DSTAT_BF)				printf(" bus fault");			if (dstat & DSTAT_MDPE)				printf(" parity");			if (dstat & DSTAT_DFE)				printf(" dma fifo empty");			printf(", DSP=0x%x DSA=0x%x: ",			    bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP),			    bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA));			if (siop_cmd)				printf("last msg_in=0x%x status=0x%x\n",				    siop_cmd->siop_tables.msg_in[0],				    letoh32(siop_cmd->siop_tables.status));			else 				printf("%s: current DSA invalid\n",				    sc->sc_dev.dv_xname);			need_reset = 1;		}	}	if (istat & ISTAT_SIP) {		if (istat & ISTAT_DIP)			delay(10);		/*		 * Can't read sist0 & sist1 independantly, or we have to		 * insert delay		 */		sist = bus_space_read_2(sc->sc_rt, sc->sc_rh, SIOP_SIST0);		sstat1 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SSTAT1);#ifdef SIOP_DEBUG_INTR		printf("scsi interrupt, sist=0x%x sstat1=0x%x "		    "DSA=0x%x DSP=0x%lx\n", sist,		    bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SSTAT1),		    bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA),		    bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP));#endif		if (sist & SIST0_RST) {			siop_handle_reset(sc);			siop_start(sc);			/* no table to flush here */			return 1;		}		if (sist & SIST0_SGE) {			if (siop_cmd)				sc_print_addr(xs->sc_link);			else				printf("%s:", sc->sc_dev.dv_xname);			printf("scsi gross error\n");			goto reset;		}		if ((sist & SIST0_MA) && need_reset == 0) {			if (siop_cmd) { 				int scratcha0;				dstat = bus_space_read_1(sc->sc_rt, sc->sc_rh,				    SIOP_DSTAT);				/*				 * first restore DSA, in case we were in a S/G				 * operation.				 */				bus_space_write_4(sc->sc_rt, sc->sc_rh,				    SIOP_DSA, siop_cmd->dsa);				scratcha0 = bus_space_read_1(sc->sc_rt,				    sc->sc_rh, SIOP_SCRATCHA);				switch (sstat1 & SSTAT1_PHASE_MASK) {				case SSTAT1_PHASE_STATUS:				/*				 * Previous phase may have aborted for any reason				 * (for example, the target has less data to				 * transfer than requested). Just go to status				 * and the command should terminate.				 */					INCSTAT(siop_stat_intr_shortxfer);					if ((dstat & DSTAT_DFE) == 0)						siop_clearfifo(sc);					/* no table to flush here */					CALL_SCRIPT(Ent_status);					return 1;				case SSTAT1_PHASE_MSGIN:					/*					 * Target may be ready to disconnect.					 * Save data pointers just in case.					 */					INCSTAT(siop_stat_intr_xferdisc);					if (scratcha0 & A_flag_data)						siop_sdp(siop_cmd);					else if ((dstat & DSTAT_DFE) == 0)						siop_clearfifo(sc);					bus_space_write_1(sc->sc_rt, sc->sc_rh,					    SIOP_SCRATCHA,					    scratcha0 & ~A_flag_data);					siop_table_sync(siop_cmd,					    BUS_DMASYNC_PREREAD |					    BUS_DMASYNC_PREWRITE);					CALL_SCRIPT(Ent_msgin);					return 1;				}				printf("%s: unexpected phase mismatch %d\n",				    sc->sc_dev.dv_xname,				    sstat1 & SSTAT1_PHASE_MASK);			} else {				printf("%s: phase mismatch without command\n",				    sc->sc_dev.dv_xname);			}			need_reset = 1;		}		if (sist & SIST0_PAR) {			/* parity error, reset */			if (siop_cmd)				sc_print_addr(xs->sc_link);			else				printf("%s:", sc->sc_dev.dv_xname);			printf("parity error\n");			goto reset;		}		if ((sist & (SIST1_STO << 8)) && need_reset == 0) {			/* selection time out, assume there's no device here */			if (siop_cmd) {				siop_cmd->status = CMDST_DONE;				xs->error = XS_SELTIMEOUT;				freetarget = 1;				goto end;			} else {				printf("%s: selection timeout without "				    "command\n", sc->sc_dev.dv_xname);				need_reset = 1;			}		}		if (sist & SIST0_UDC) {			/*			 * unexpected disconnect. Usually the target signals			 * a fatal condition this way. Attempt to get sense.			 */			 if (siop_cmd) {				siop_cmd->siop_tables.status =				    htole32(SCSI_CHECK);				goto end;			}			printf("%s: unexpected disconnect without "			    "command\n", sc->sc_dev.dv_xname);			goto reset;		}		if (sist & (SIST1_SBMC << 8)) {			/* SCSI bus mode change */			if (siop_modechange(sc) == 0 || need_reset == 1)				goto reset;			if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) {				/*				 * We have a script interrupt. It will				 * restart the script.				 */				goto scintr;			}			/*			 * Else we have to restart the script ourself, at the			 * interrupted instruction.			 */			bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP,			    bus_space_read_4(sc->sc_rt, sc->sc_rh,			    SIOP_DSP) - 8);			return 1;		}		/* Else it's an unhandled exception (for now). */		printf("%s: unhandled scsi interrupt, sist=0x%x sstat1=0x%x "		    "DSA=0x%x DSP=0x%x\n", sc->sc_dev.dv_xname, sist,		    bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SSTAT1),		    bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA),		    bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP));		if (siop_cmd) {			siop_cmd->status = CMDST_DONE;			xs->error = XS_SELTIMEOUT;			goto end;		}		need_reset = 1;	}	if (need_reset) {reset:		/* fatal error, reset the bus */		siop_resetbus(sc);		/* no table to flush here */		return 1;	}scintr:	if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */		irqcode = bus_space_read_4(sc->sc_rt, sc->sc_rh,		    SIOP_DSPS);#ifdef SIOP_DEBUG_INTR		printf("script interrupt 0x%x\n", irqcode);#endif		/*		 * no command, or an inactive command is only valid for a		 * reselect interrupt		 */		if ((irqcode & 0x80) == 0) {			if (siop_cmd == NULL) {				printf("%s: script interrupt (0x%x) with "				    "invalid DSA !!!\n", sc->sc_dev.dv_xname,				    irqcode);				goto reset;			}			if (siop_cmd->status != CMDST_ACTIVE &&			    siop_cmd->status != CMDST_SENSE_ACTIVE) {				printf("%s: command with invalid status "				    "(IRQ code 0x%x current status %d) !\n",				    sc->sc_dev.dv_xname,				    irqcode, siop_cmd->status);				xs = NULL;			}		}		switch(irqcode) {		case A_int_err:			printf("error, DSP=0x%x\n",			    (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh,			    SIOP_DSP) - sc->sc_scriptaddr));			if (xs) {				xs->error = XS_SELTIMEOUT;				goto end;			} else {				goto reset;			}		case A_int_reseltarg:			printf("%s: reselect with invalid target\n",				    sc->sc_dev.dv_xname);			goto reset;		case A_int_resellun: 			INCSTAT(siop_stat_intr_lunresel);			target = bus_space_read_1(sc->sc_rt, sc->sc_rh,			    SIOP_SCRATCHA) & 0xf;			lun = bus_space_read_1(sc->sc_rt, sc->sc_rh,			    SIOP_SCRATCHA + 1);			tag = bus_space_read_1(sc->sc_rt, sc->sc_rh,			    SIOP_SCRATCHA + 2);			siop_target = sc->targets[target];			if (siop_target == NULL) {				printf("%s: reselect with invalid "				    "target %d\n", sc->sc_dev.dv_xname, target);				goto reset;			}			siop_lun = siop_target->siop_lun[lun];			if (siop_lun == NULL) {				printf("%s: target %d reselect with invalid "				    "lun %d\n", sc->sc_dev.dv_xname,				    target, lun);				goto reset;			}			if (siop_lun->siop_tag[tag].active == NULL) {				printf("%s: target %d lun %d tag %d reselect "				    "without command\n", sc->sc_dev.dv_xname,				    target, lun, tag);				goto reset;			}			siop_cmd = siop_lun->siop_tag[tag].active;			bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP,			    siop_cmd->dsa + sizeof(struct siop_xfer_common) +			    Ent_ldsa_reload_dsa);			siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);			return 1;		case A_int_reseltag:			printf("%s: reselect with invalid tag\n",				    sc->sc_dev.dv_xname);			goto reset;		case A_int_msgin:		{			int msgin = bus_space_read_1(sc->sc_rt, sc->sc_rh,			    SIOP_SFBR);			if (msgin == MSG_MESSAGE_REJECT) {				int msg, extmsg;				if (siop_cmd->siop_tables.msg_out[0] & 0x80) {					/*					 * Message was part of an identify +					 * something else. Identify shouldn't					 * have been rejected.					 */					msg = siop_cmd->siop_tables.msg_out[1];					extmsg =					    siop_cmd->siop_tables.msg_out[3];				} else {					msg = siop_cmd->siop_tables.msg_out[0];					extmsg =					    siop_cmd->siop_tables.msg_out[2];				}				if (msg == MSG_MESSAGE_REJECT) {					/* MSG_REJECT for a MSG_REJECT! */					if (xs)						sc_print_addr(xs->sc_link);					else						printf("%s: ",						   sc->sc_dev.dv_xname);					printf("our reject message was "					    "rejected\n");					goto reset;				}				if (msg == MSG_EXTENDED &&				    extmsg == MSG_EXT_WDTR) {					if ((siop_target->flags & TARF_SYNC)					    == 0) {						siop_target->status = TARST_OK;						siop_print_info(sc, target);						/* no table to flush here */						CALL_SCRIPT(Ent_msgin_ack);						return 1;					}					siop_target->status = TARST_SYNC_NEG;					siop_sdtr_msg(siop_cmd, 0,					    sc->min_st_sync, sc->maxoff);					siop_table_sync(siop_cmd,					    BUS_DMASYNC_PREREAD |					    BUS_DMASYNC_PREWRITE);					CALL_SCRIPT(Ent_send_msgout);					return 1;				} else if (msg == MSG_EXTENDED &&				    extmsg == MSG_EXT_SDTR) {					siop_target->status = TARST_OK;					siop_print_info(sc, target);					/* no table to flush here */					CALL_SCRIPT(Ent_msgin_ack);					return 1;				} else if (msg == MSG_SIMPLE_Q_TAG || 				    msg == MSG_HEAD_OF_Q_TAG ||				    msg == MSG_ORDERED_Q_TAG) {					if (siop_handle_qtag_reject(					    siop_cmd) == -1)						goto reset;					CALL_SCRIPT(Ent_msgin_ack);					return 1;				}				if (xs)					sc_print_addr(xs->sc_link);				else					printf("%s: ", sc->sc_dev.dv_xname);				if (msg == MSG_EXTENDED) {					printf("scsi message reject, extended "					    "message sent was 0x%x\n", extmsg);				} else {					printf("scsi message reject, message "					    "sent was 0x%x\n", msg);				}				/* no table to flush here */				CALL_SCRIPT(Ent_msgin_ack);				return 1;			}			if (xs)				sc_print_addr(xs->sc_link);			else				printf("%s: ", sc->sc_dev.dv_xname);			printf("unhandled message 0x%x\n",

⌨️ 快捷键说明

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