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

📄 scsincr53c8xx.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
#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 voidinterrupt(Ureg *ur, void *a){	int wakeme = 0, cont = -1;	uchar istat, dstat;	ushort sist;	Controller *c = a;	Ncr *n = c->n;	Dsa *dsa;	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; d = KPTR(legetl(d->next))) {			if (d->stateb == A_STATE_DONE) {				d->p9status = STATUS_COMPLETE | 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;	dsa = (Dsa *)DMASEG_TO_KADDR(legetl(n->dsa));	c->running = 0;	if (dsa == nil || dsa == (Dsa *)-1)		panic("53c8xx: dsa == %ld in interrupt; bad controller", (long)dsa);	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) {				dbc = read_mismatch_recover(c, n, dsa);				tbc = legetl(dsa->data_buf.dbc) - dbc;				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_to_decisions;			}			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;				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_to_decisions;			}			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 = STATUS_FAIL;	/* chf */				wakeme = 1;			}		}		/*else*/ if (sist & 0x400) {			if (DEBUG(0))				IPRINT(PRINTPREFIX "%d/%d Sto\n", dsa->target, dsa->lun);			dsa->p9status = STATUS_SELECTION_TIMEOUT;			dsa->stateb = A_STATE_DONE;			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 = STATUS_FAIL;		}	}	if (istat & Dip) {		if (DEBUG(1))			IPRINT("dstat = %.2x\n", dstat);		/*else*/ if (dstat & Ssi) {			ulong *p = DMASEG_TO_KADDR(legetl(n->dsp));			ulong w = (uchar *)p - (uchar *)c->script;			IPRINT("[%lux]", w);			USED(w);			cont = -2;	/* restart */		}		if (dstat & Sir) {			switch (legetl(n->dsps)) {			case A_SIR_MSG_IO_COMPLETE:				dsa->p9status = STATUS_COMPLETE | 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->dmablks == 0 && dsa->flag)					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_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->target, dsa->lun);			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 = DMASEG_TO_KADDR(legetl(n->dsp));				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:				IPRINT(PRINTPREFIX "%d/%d: reselected during select\n",				    dsa->target, dsa->lun);				cont = -2;				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) {			ulong addr = legetl(n->dsp);			ulong dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];			IPRINT(PRINTPREFIX "%d/%d: Iid pa=%.8lux sa=%.8lux dbc=%lux\n",			    dsa->target, dsa->lun,			    addr, addr - c->scriptpa, dbc);			addr = (ulong)DMASEG_TO_KADDR(addr);			IPRINT("%.8lux %.8lux %.8lux\n",			    *(ulong *)(addr - 12), *(ulong *)(addr - 8), *(ulong *)(addr - 4));			USED(addr, dbc);			if (dsa)				dsa->p9status = STATUS_FAIL;			wakeme = 1;		}		/*else*/ if (dstat & Bf) {			if (dsa == nil)				print(PRINTPREFIX "Bus Fault with dsa==0\n");			else {				print(PRINTPREFIX "%d/%d: Bus Fault\n", dsa->target, dsa->lun);				dsa->p9status = STATUS_FAIL;			}			dumpncrregs(c, 1);			wakeme = 1;		}	}	if (cont == -2)		ncrcontinue(c);	else if (cont >= 0)		start(c, cont);	if (wakeme && dsa){		if(dsa->p9status == 0xffff)			dsa->p9status = STATUS_FAIL;		wakeup(dsa);	}	iunlock(c);	if (DEBUG(1)) {		IPRINT(PRINTPREFIX "int end 1\n");	}}static intdone(void *arg){	return ((Dsa *)arg)->p9status != 0xffff;}static intxfunc(Controller *c, enum na_external x, unsigned long *v){	switch (x) {	default:		print("xfunc: can't find external %d\n", x);		return 0;	case X_scsi_id_buf:		*v = offsetof(Dsa, scsi_id_buf[0]);		break;	case X_msg_out_buf:		*v = offsetof(Dsa, msg_out_buf);		break;	case X_cmd_buf:		*v = offsetof(Dsa, cmd_buf);		break;	case X_data_buf:		*v = offsetof(Dsa, data_buf);		break;	case X_status_buf:		*v = offsetof(Dsa, status_buf);		break;	case X_dsa_head:		*v = DMASEG(&c->dsalist.head[0]);		break;	case X_ssid_mask:		*v = SSIDMASK(c);		break;	}	return 1;}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);		if (i < datalen) {			KPRINT("...");		}		KPRINT("\n");	}}static voidbusreset(Controller *c){	int x, ntarget;	/* bus reset */	c->n->scntl1 |= (1 << 3);	delay(500);	c->n->scntl1 &= ~(1 << 3);	if(!(c->v->feature & Wide))		ntarget = 8;	else		ntarget = MAXTARGET;	for (x = 0; x < ntarget; x++) {		setwide(0, c, x, 0);#ifndef ASYNC_ONLY		c->s[x] = NeitherDone;#endif	}	c->capvalid = 0;}static voidreset(Controller *c){	/* should wakeup all pending tasks */	softreset(c);	busreset(c);}static intio(Controller *c, uchar target, uchar lun, int rw, uchar *cmd, int cmdlen, uchar *data, int datalen,

⌨️ 快捷键说明

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