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

📄 sd53c8xx.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
	else		inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;#ifdef WMR_DEBUG	if (inchip) {		IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: DMA FIFO = %d\n",		    dsa->target, dsa->lun, inchip);	}#endif	if (n->sstat0 & (1 << 5)) {		inchip++;#ifdef WMR_DEBUG		IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODL full\n", dsa->target, dsa->lun);#endif	}	if (n->sstat2 & (1 << 5)) {		inchip++;#ifdef WMR_DEBUG		IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODL msb full\n", dsa->target, dsa->lun);#endif	}	if (n->sxfer & SYNCOFFMASK(c)) {		/* synchronous SODR */		if (n->sstat0 & (1 << 6)) {			inchip++;#ifdef WMR_DEBUG			IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODR full\n",			    dsa->target, dsa->lun);#endif		}		if (n->sstat2 & (1 << 6)) {			inchip++;#ifdef WMR_DEBUG			IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODR msb full\n",			    dsa->target, dsa->lun);#endif		}	}	/* clear the dma fifo */	n->ctest3 |= (1 << 2);	/* wait till done */	while ((n->dstat & Dfe) == 0)		;	return dbc + inchip;}static voidsd53c8xxinterrupt(Ureg *ur, void *a){	uchar istat;	ushort sist;	uchar dstat;	int wakeme = 0;	int cont = -1;	Dsa *dsa;	ulong dsapa;	Controller *c = a;	Ncr *n = c->n;	USED(ur);	if (DEBUG(1)) {		IPRINT(PRINTPREFIX "int\n");	}	ilock(c);	istat = n->istat;	if (istat & Intf) {		Dsa *d;		int wokesomething = 0;		if (DEBUG(1)) {			IPRINT(PRINTPREFIX "Intfly\n");		}		n->istat = Intf;		/* search for structures in A_STATE_DONE */		for (d = KPTR(legetl(c->dsalist.head)); d != dsaend; d = KPTR(legetl(d->next))) {			if (d->stateb == A_STATE_DONE) {				d->p9status = d->status;				if (DEBUG(1)) {					IPRINT(PRINTPREFIX "waking up dsa %lux\n", (ulong)d);				}				wakeup(d);				wokesomething = 1;			}		}		if (!wokesomething) {			IPRINT(PRINTPREFIX "nothing to wake up\n");		}	}	if ((istat & (Sip | Dip)) == 0) {		if (DEBUG(1)) {			IPRINT(PRINTPREFIX "int end %x\n", istat);		}		iunlock(c);		return;	}	sist = (n->sist1<<8)|n->sist0;	/* BUG? can two-byte read be inconsistent? */	dstat = n->dstat;	dsapa = legetl(n->dsa);	/*	 * Can't compute dsa until we know that dsapa is valid.	 */	if(dsapa < -KZERO)		dsa = (Dsa*)DMASEG_TO_KADDR(dsapa);	else{		dsa = nil;		/*		 * happens at startup on some cards but we 		 * don't actually deref dsa because none of the		 * flags we are about are set.		 * still, print in case that changes and we're		 * about to dereference nil.		 */		iprint("sd53c8xxinterrupt: dsa=%.8lux istat=%ux sist=%ux dstat=%ux\n", dsapa, istat, sist, dstat);	}	c->running = 0;	if (istat & Sip) {		if (DEBUG(1)) {			IPRINT("sist = %.4x\n", sist);		}		if (sist & 0x80) {			ulong addr;			ulong sa;			ulong dbc;			ulong tbc;			int dmablks;			ulong dmaaddr;			addr = legetl(n->dsp);			sa = addr - c->scriptpa;			if (DEBUG(1) || DEBUG(2)) {				IPRINT(PRINTPREFIX "%d/%d: Phase Mismatch sa=%.8lux\n",				    dsa->target, dsa->lun, sa);			}			/*			 * now recover			 */			if (sa == E_data_in_mismatch) {				/*				 * though this is a failure in the residue, there may have been blocks				 * as well. if so, dmablks will not have been zeroed, since the state				 * was not saved by the microcode. 				 */				dbc = read_mismatch_recover(c, n, dsa);				tbc = legetl(dsa->data_buf.dbc) - dbc;				dsa->dmablks = 0;				n->scratcha[2] = 0;				advancedata(&dsa->data_buf, tbc);				if (DEBUG(1) || DEBUG(2)) {					IPRINT(PRINTPREFIX "%d/%d: transferred = %ld residue = %ld\n",					    dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc));				}				cont = E_data_mismatch_recover;			}			else if (sa == E_data_in_block_mismatch) {				dbc = read_mismatch_recover(c, n, dsa);				tbc = A_BSIZE - dbc;				/* recover current state from registers */				dmablks = n->scratcha[2];				dmaaddr = legetl(n->scratchb);				/* we have got to dmaaddr + tbc */				/* we have dmablks * A_BSIZE - tbc + residue left to do */				/* so remaining transfer is */				IPRINT("in_block_mismatch: dmaaddr = 0x%lux tbc=%lud dmablks=%d\n",				    dmaaddr, tbc, dmablks);				calcblockdma(dsa, dmaaddr + tbc,				    dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc));				/* copy changes into scratch registers */				IPRINT("recalc: dmablks %d dmaaddr 0x%lx pa 0x%lx dbc %ld\n",				    dsa->dmablks, legetl(dsa->dmaaddr),				    legetl(dsa->data_buf.pa), legetl(dsa->data_buf.dbc));				n->scratcha[2] = dsa->dmablks;				lesetl(n->scratchb, dsa->dmancr);				cont = E_data_block_mismatch_recover;			}			else if (sa == E_data_out_mismatch) {				dbc = write_mismatch_recover(c, n, dsa);				tbc = legetl(dsa->data_buf.dbc) - dbc;				dsa->dmablks = 0;				n->scratcha[2] = 0;				advancedata(&dsa->data_buf, tbc);				if (DEBUG(1) || DEBUG(2)) {					IPRINT(PRINTPREFIX "%d/%d: transferred = %ld residue = %ld\n",					    dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc));				}				cont = E_data_mismatch_recover;			}			else if (sa == E_data_out_block_mismatch) {				dbc = write_mismatch_recover(c, n, dsa);				tbc = legetl(dsa->data_buf.dbc) - dbc;				/* recover current state from registers */				dmablks = n->scratcha[2];				dmaaddr = legetl(n->scratchb);				/* we have got to dmaaddr + tbc */				/* we have dmablks blocks - tbc + residue left to do */				/* so remaining transfer is */				IPRINT("out_block_mismatch: dmaaddr = %lux tbc=%lud dmablks=%d\n",				    dmaaddr, tbc, dmablks);				calcblockdma(dsa, dmaaddr + tbc,				    dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc));				/* copy changes into scratch registers */				n->scratcha[2] = dsa->dmablks;				lesetl(n->scratchb, dsa->dmancr);				cont = E_data_block_mismatch_recover;			}			else if (sa == E_id_out_mismatch) {				/*				 * target switched phases while attention held during				 * message out. The possibilities are:				 * 1. It didn't like the last message. This is indicated				 *    by the new phase being message_in. Use script to recover				 *				 * 2. It's not SCSI-II compliant. The new phase will be other				 *    than message_in. We should also indicate that the device				 *    is asynchronous, if it's the SDTR that got ignored				 * 				 * For now, if the phase switch is not to message_in, and				 * and it happens after IDENTIFY and before SDTR, we				 * notify the negotiation state machine.				 */				ulong lim = legetl(dsa->msg_out_buf.dbc);				uchar p = n->sstat1 & 7;				dbc = write_mismatch_recover(c, n, dsa);				tbc = lim - dbc;				IPRINT(PRINTPREFIX "%d/%d: msg_out_mismatch: %lud/%lud sent, phase %s\n",				    dsa->target, dsa->lun, tbc, lim, phase[p]);				if (p != MessageIn && tbc == 1) {					msgsm(dsa, c, A_SIR_EV_PHASE_SWITCH_AFTER_ID, &cont, &wakeme);				}				else					cont = E_id_out_mismatch_recover;			}			else if (sa == E_cmd_out_mismatch) {				/*				 * probably the command count is longer than the device wants ...				 */				ulong lim = legetl(dsa->cmd_buf.dbc);				uchar p = n->sstat1 & 7;				dbc = write_mismatch_recover(c, n, dsa);				tbc = lim - dbc;				IPRINT(PRINTPREFIX "%d/%d: cmd_out_mismatch: %lud/%lud sent, phase %s\n",				    dsa->target, dsa->lun, tbc, lim, phase[p]);				USED(p, tbc);				cont = E_to_decisions;			}			else {				IPRINT(PRINTPREFIX "%d/%d: ma sa=%.8lux wanted=%s got=%s\n",				    dsa->target, dsa->lun, sa,				    phase[n->dcmd & 7],				    phase[n->sstat1 & 7]);				dumpncrregs(c, 1);				dsa->p9status = SDeio;	/* chf */				wakeme = 1;			}		}		/*else*/ if (sist & 0x400) {			if (DEBUG(0)) {				IPRINT(PRINTPREFIX "%d/%d Sto\n", dsa->target, dsa->lun);			}			dsa->p9status = SDtimeout;			dsa->stateb = A_STATE_DONE;			coherence();			softreset(c);			cont = E_issue_check;			wakeme = 1;		}		if (sist & 0x1) {			IPRINT(PRINTPREFIX "%d/%d: parity error\n", dsa->target, dsa->lun);			dsa->parityerror = 1;		}		if (sist & 0x4) {			IPRINT(PRINTPREFIX "%d/%d: unexpected disconnect\n",			    dsa->target, dsa->lun);			dumpncrregs(c, 1);			//wakeme = 1;			dsa->p9status = SDeio;		}	}	if (istat & Dip) {		if (DEBUG(1)) {			IPRINT("dstat = %.2x\n", dstat);		}		/*else*/ if (dstat & Ssi) {			ulong w = legetl(n->dsp) - c->scriptpa;			IPRINT("[%lux]", w);			USED(w);			cont = -2;	/* restart */		}		if (dstat & Sir) {			switch (legetl(n->dsps)) {			case A_SIR_MSG_IO_COMPLETE:				dsa->p9status = dsa->status;				wakeme = 1;				break;			case A_SIR_MSG_SDTR:			case A_SIR_MSG_WDTR:			case A_SIR_MSG_REJECT:			case A_SIR_EV_RESPONSE_OK:				msgsm(dsa, c, legetl(n->dsps), &cont, &wakeme);				break;			case A_SIR_MSG_IGNORE_WIDE_RESIDUE:				/* back up one in the data transfer */				IPRINT(PRINTPREFIX "%d/%d: ignore wide residue %d, WSR = %d\n",				    dsa->target, dsa->lun, n->scratcha[1], n->scntl2 & 1);				if (dsa->flag == 2) {					IPRINT(PRINTPREFIX "%d/%d: transfer over; residue ignored\n",					    dsa->target, dsa->lun);				}				else {					calcblockdma(dsa, legetl(dsa->dmaaddr) - 1,					    dsa->dmablks * A_BSIZE + legetl(dsa->data_buf.dbc) + 1);				}				cont = -2;				break;			case A_SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT:				IPRINT(PRINTPREFIX "%d: not msg_in after reselect (%s)",				    n->ssid & SSIDMASK(c), phase[n->sstat1 & 7]);				dsa = dsafind(c, n->ssid & SSIDMASK(c), -1, A_STATE_DISCONNECTED);				dumpncrregs(c, 1);				wakeme = 1;				break;			case A_SIR_NOTIFY_LOAD_STATE:				IPRINT(PRINTPREFIX ": load_state dsa=%p\n", dsa);				if (dsa == (void*)KZERO || dsa == (void*)-1) {					dsadump(c);					dumpncrregs(c, 1);					panic("bad dsa in load_state");				}				cont = -2;				break;			case A_SIR_NOTIFY_MSG_IN:				IPRINT(PRINTPREFIX "%d/%d: msg_in %d\n",				    dsa->target, dsa->lun, n->sfbr);				cont = -2;				break;			case A_SIR_NOTIFY_DISC:				IPRINT(PRINTPREFIX "%d/%d: disconnect:", dsa->target, dsa->lun);				goto dsadump;			case A_SIR_NOTIFY_STATUS:				IPRINT(PRINTPREFIX "%d/%d: status\n", dsa->target, dsa->lun);				cont = -2;				break;			case A_SIR_NOTIFY_COMMAND:				IPRINT(PRINTPREFIX "%d/%d: commands\n", dsa->target, dsa->lun);				cont = -2;				break;			case A_SIR_NOTIFY_DATA_IN:				IPRINT(PRINTPREFIX "%d/%d: data in a %lx b %lx\n",				    dsa->target, dsa->lun, legetl(n->scratcha), legetl(n->scratchb));				cont = -2;				break;			case A_SIR_NOTIFY_BLOCK_DATA_IN:				IPRINT(PRINTPREFIX "%d/%d: block data in: a2 %x b %lx\n",				    dsa->target, dsa->lun, n->scratcha[2], legetl(n->scratchb));				cont = -2;				break;			case A_SIR_NOTIFY_DATA_OUT:				IPRINT(PRINTPREFIX "%d/%d: data out\n", dsa->target, dsa->lun);				cont = -2;				break;			case A_SIR_NOTIFY_DUMP:				IPRINT(PRINTPREFIX "%d/%d: dump\n", dsa->target, dsa->lun);				dumpncrregs(c, 1);				cont = -2;				break;			case A_SIR_NOTIFY_DUMP2:				IPRINT(PRINTPREFIX "%d/%d: dump2:", dsa->target, dsa->lun);				IPRINT(" sa %lux", legetl(n->dsp) - c->scriptpa);				IPRINT(" dsa %lux", legetl(n->dsa));				IPRINT(" sfbr %ux", n->sfbr);				IPRINT(" a %lux", legetl(n->scratcha));				IPRINT(" b %lux", legetl(n->scratchb));				IPRINT(" ssid %ux", n->ssid);				IPRINT("\n");				cont = -2;				break;			case A_SIR_NOTIFY_WAIT_RESELECT:				IPRINT(PRINTPREFIX "wait reselect\n");				cont = -2;				break;			case A_SIR_NOTIFY_RESELECT:				IPRINT(PRINTPREFIX "reselect: ssid %.2x sfbr %.2x at %ld\n",				    n->ssid, n->sfbr, TK2MS(m->ticks));				cont = -2;				break;			case A_SIR_NOTIFY_ISSUE:				IPRINT(PRINTPREFIX "%d/%d: issue dsa=%p end=%p:", dsa->target, dsa->lun, dsa, dsaend);			dsadump:				IPRINT(" tgt=%d", dsa->target);				IPRINT(" time=%ld", TK2MS(m->ticks));				IPRINT("\n");				cont = -2;				break;			case A_SIR_NOTIFY_ISSUE_CHECK:				IPRINT(PRINTPREFIX "issue check\n");				cont = -2;				break;			case A_SIR_NOTIFY_SIGP:				IPRINT(PRINTPREFIX "responded to SIGP\n");				cont = -2;				break;			case A_SIR_NOTIFY_DUMP_NEXT_CODE: {				ulong *dsp = c->script + (legetl(n->dsp)-c->scriptpa)/4;				int x;				IPRINT(PRINTPREFIX "code at %lux", dsp - c->script);				for (x = 0; x < 6; x++) {					IPRINT(" %.8lux", dsp[x]);				}				IPRINT("\n");				USED(dsp);				cont = -2;				break;			}			case A_SIR_NOTIFY_WSR:				IPRINT(PRINTPREFIX "%d/%d: WSR set\n", dsa->target, dsa->lun);				cont = -2;				break;			case A_SIR_NOTIFY_LOAD_SYNC:				IPRINT(PRINTPREFIX "%d/%d: scntl=%.2x sxfer=%.2x\n",				    dsa->target, dsa->lun, n->scntl3, n->sxfer);				cont = -2;				break;			case A_SIR_NOTIFY_RESELECTED_ON_SELECT:				if (DEBUG(2)) {					IPRINT(PRINTPREFIX "%d/%d: reselected during select\n", 					    dsa->target, dsa->lun);				}				cont = -2;				break;			case A_error_reselected:		/* dsa isn't valid here */				iprint(PRINTPREFIX "reselection error\n");				dumpncrregs(c, 1);				for (dsa = KPTR(legetl(c->dsalist.head)); dsa != dsaend; dsa = KPTR(legetl(dsa->next))) {					IPRINT(PRINTPREFIX "dsa target %d lun %d state %d\n", dsa->target, dsa->lun, dsa->stateb);				}				break;			default:				IPRINT(PRINTPREFIX "%d/%d: script error %ld\n",					dsa->target, dsa->lun, legetl(n->dsps));				dumpncrregs(c, 1);				wakeme = 1;			}		}		/*else*/ if (dstat & Iid) {			int i, target, lun;			ulong addr, dbc, *v;						addr = legetl(n->dsp);			if(dsa){				target = dsa->target;				lun = dsa->lun;			}else{				target = -1;				lun = -1;			}			dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];		//	if(dsa == nil)				idebug++;			IPRINT(PRINTPREFIX "%d/%d: Iid pa=%.8lux sa=%.8lux dbc=%lux\n",			    target, lun,			    addr, addr - c->scriptpa, dbc);			addr = (ulong)c->script + addr - c->scriptpa;			addr -= 64;			addr &= ~63;			v = (ulong*)addr;			for(i=0; i<8; i++){				IPRINT("%.8lux: %.8lux %.8lux %.8lux %.8lux\n", 					addr, v[0], v[1], v[2], v[3]);				addr += 4*4;				v += 4;			}			USED(addr, dbc);			if(dsa == nil){				dsadump(c);				dumpncrregs(c, 1);				panic("bad dsa");			}			dsa->p9status = SDeio;			wakeme = 1;		}		/*else*/ if (dstat & Bf) {			IPRINT(PRINTPREFIX "%d/%d: Bus Fault\n", dsa->target, dsa->lun);			dumpncrregs(c, 1);			dsa->p9status = SDeio;			wakeme = 1;		}	}	if (cont == -2)		ncrcontinue(c);	else if (cont >= 0)		start(c, cont);	if (wakeme){		if(dsa->p9status == SDnostatus)			dsa->p9status = SDeio;		wakeup(dsa);	}	iunlock(c);	if (DEBUG(1)) {		IPRINT(PRINTPREFIX "int end 1\n");	}}static intdone(void *arg){	return ((Dsa *)arg)->p9status != SDnostatus;}static voidsetmovedata(Movedata *d, ulong pa, ulong bc){	d->pa[0] = pa;	d->pa[1] = pa>>8;	d->pa[2] = pa>>16;	d->pa[3] = pa>>24;	d->dbc[0] = bc;	d->dbc[1] = bc>>8;	d->dbc[2] = bc>>16;	d->dbc[3] = bc>>24;}static voidadvancedata(Movedata *d, long v){	lesetl(d->pa, legetl(d->pa) + v);	lesetl(d->dbc, legetl(d->dbc) - v);}static voiddumpwritedata(uchar *data, int datalen){	int i;	uchar *bp;	if (!DEBUG(0)){		USED(data, datalen);		return;	}	if (datalen) {		KPRINT(PRINTPREFIX "write:");		for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++) {			KPRINT("%.2ux", *bp);		}		if (i < datalen) {			KPRINT("...");		}		KPRINT("\n");	}}static voiddumpreaddata(uchar *data, int datalen){	int i;	uchar *bp;	if (!DEBUG(0)){		USED(data, datalen);		return;	}	if (datalen) {		KPRINT(PRINTPREFIX "read:");		for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++) {			KPRINT("%.2ux", *bp);		}

⌨️ 快捷键说明

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