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

📄 scsincr53c8xx.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
static voidsynctabinit(Controller *c){	int scf;	unsigned long scsilimit;	int xferp;	unsigned long cr, sr;	int tpf;	int fast;	int maxscf;	if (c->v->feature & Ultra2)		maxscf = NULTRA2SCF;	else if (c->v->feature & Ultra)		maxscf = NULTRASCF;	else		maxscf = NSCF;	/*	 * for chips with no clock doubler, but Ultra capable (e.g. 860, or interestingly the	 * first spin of the 875), assume 80MHz	 * otherwise use the internal (33 Mhz) or external (40MHz) default	 */	if ((c->v->feature & Ultra) != 0 && (c->v->feature & (ClockDouble | ClockQuad)) == 0)		c->sclk = ULTRA_NOCLOCKDOUBLE_SCLK;	else		c->sclk = SCLK;	/*	 * otherwise, if the chip is Ultra capable, but has a slow(ish) clock,	 * invoke the doubler	 */	if (SCLK <= 40000000) {		if (c->v->feature & ClockDouble) {			c->sclk *= 2;			c->clockmult = 1;		}		else if (c->v->feature & ClockQuad) {			c->sclk *= 4;			c->clockmult = 1;		}		else			c->clockmult = 0;	}	else		c->clockmult = 0;	/* derive CCF from sclk */	/* woebetide anyone with SCLK < 16.7 or > 80MHz */	if (c->sclk <= 25 * MEGA)		c->ccf = 1;	else if (c->sclk <= 3750000)		c->ccf = 2;	else if (c->sclk <= 50 * MEGA)		c->ccf = 3;	else if (c->sclk <= 75 * MEGA)		c->ccf = 4;	else if ((c->v->feature & ClockDouble) && c->sclk <= 80 * MEGA)		c->ccf = 5;	else if ((c->v->feature & ClockQuad) && c->sclk <= 120 * MEGA)		c->ccf = 6;	else if ((c->v->feature & ClockQuad) && c->sclk <= 160 * MEGA)		c->ccf = 7;	for (scf = 1; scf < maxscf; scf++) {		/* check for legal core rate */		/* round up so we run slower for safety */	   	cr = (c->sclk * 2 + cf2[scf] - 1) / cf2[scf];		if (cr <= MAXSYNCCORERATE) {			scsilimit = MAXSYNCSCSIRATE;			fast = 0;		}		else if (cr <= MAXFASTSYNCCORERATE) {			scsilimit = MAXFASTSYNCSCSIRATE;			fast = 1;		}		else if ((c->v->feature & Ultra) && cr <= MAXULTRASYNCCORERATE) {			scsilimit = MAXULTRASYNCSCSIRATE;			fast = 2;		}		else if ((c->v->feature & Ultra2) && cr <= MAXULTRA2SYNCCORERATE) {			scsilimit = MAXULTRA2SYNCSCSIRATE;			fast = 3;		}		else			continue;		for (xferp = 11; xferp >= 4; xferp--) {			int ok;			int tp;			/* calculate scsi rate - round up again */			/* start from sclk for accuracy */			int totaldivide = xferp * cf2[scf];			sr = (c->sclk * 2 + totaldivide - 1) / totaldivide;			if (sr > scsilimit)				break;			/*			 * now work out transfer period			 * round down now so that period is pessimistic			 */			tp = (MEGA * 1000) / sr;			/*			 * bounds check it			 */			if (tp < 25 || tp > 255 * 4)				continue;			/*			 * spot stupid special case for Ultra or Ultra2			 * while working out factor			 */			if (tp == 25)				tpf = 10;			else if (tp == 50)				tpf = 12;			else if (tp < 52)				continue;			else				tpf = tp / 4;			/*			 * now check tpf looks sensible			 * given core rate			 */			switch (fast) {			case 0:				/* scf must be ccf for SCSI 1 */				ok = tpf >= 50 && scf == c->ccf;				break;			case 1:				ok = tpf >= 25 && tpf < 50;				break;			case 2:				/*				 * must use xferp of 4, or 5 at a pinch				 * for an Ultra transfer				 */				ok = xferp <= 5 && tpf >= 12 && tpf < 25;				break;			case 3:				ok = xferp == 4 && (tpf == 10 || tpf == 11);				break;			default:				ok = 0;			}			if (!ok)				continue;			c->synctab[scf - 1][xferp - 4] = tpf;		}	}#ifndef NO_ULTRA2	if (c->v->feature & Ultra2)		tpf = 10;	else#endif	if (c->v->feature & Ultra)		tpf = 12;	else		tpf = 25;	for (; tpf < 256; tpf++) {		if (chooserate(c, tpf, &scf, &xferp) == tpf) {			unsigned tp = tpf == 10 ? 25 : (tpf == 12 ? 50 : tpf * 4);			unsigned long khz = (MEGA + tp - 1) / (tp);			KPRINT(PRINTPREFIX "tpf=%d scf=%d.%.1d xferp=%d mhz=%ld.%.3ld\n",			    tpf, cf2[scf] / 2, (cf2[scf] & 1) ? 5 : 0,			    xferp + 4, khz / 1000, khz % 1000);			USED(khz);			if (c->tpf == 0)				c->tpf = tpf;	/* note lowest value for controller */		}	}}static voidsynctodsa(Dsa *dsa, Controller *c){/*	KPRINT("synctodsa(dsa=%lux, target=%d, scntl3=%.2lx sxfer=%.2x)\n",	    dsa, dsa->target, c->scntl3[dsa->target], c->sxfer[dsa->target]);*/	dsa->scntl3 = c->scntl3[dsa->target];	dsa->sxfer = c->sxfer[dsa->target];}static voidsetsync(Dsa *dsa, Controller *c, int target, uchar ultra, uchar scf, uchar xferp, uchar reqack){	c->scntl3[target] =	    (c->scntl3[target] & 0x08) | (((scf << 4) | c->ccf | (ultra << 7)) & ~0x08);	c->sxfer[target] = (xferp << 5) | reqack;	c->s[target] = BothDone;	if (dsa) {		synctodsa(dsa, c);		c->n->scntl3 = c->scntl3[target];		c->n->sxfer = c->sxfer[target];	}}static voidsetasync(Dsa *dsa, Controller *c, int target){	setsync(dsa, c, target, 0, c->ccf, 0, 0);}static voidsetwide(Dsa *dsa, Controller *c, int target, uchar wide){	c->scntl3[target] = wide ? (1 << 3) : 0;	setasync(dsa, c, target);	c->s[target] = WideDone;}static intbuildsdtrmsg(uchar *buf, uchar tpf, uchar offset){	*buf++ = X_MSG;	*buf++ = 3;	*buf++ = X_MSG_SDTR;	*buf++ = tpf;	*buf = offset;	return 5;}static intbuildwdtrmsg(uchar *buf, uchar expo){	*buf++ = X_MSG;	*buf++ = 2;	*buf++ = X_MSG_WDTR;	*buf = expo;	return 4;}static voidstart(Controller *c, long entry){	ulong p;	if (c->running)		panic(PRINTPREFIX "start called while running");	c->running = 1;	p = c->scriptpa + entry;	lesetl(c->n->dsp, p);	if (c->ssm)		c->n->dcntl |= 0x4;		/* start DMA in SSI mode */}static voidncrcontinue(Controller *c){	if (c->running)		panic(PRINTPREFIX "ncrcontinue called while running");	/* set the start DMA bit to continue execution */	c->running = 1;	c->n->dcntl |= 0x4;}static voidsoftreset(Controller *c){	Ncr *n = c->n;	n->istat = Srst;		/* software reset */	n->istat = 0;	/* general initialisation */	n->scid = (1 << 6) | 7;		/* respond to reselect, ID 7 */	n->respid = 1 << 7;		/* response ID = 7 */#ifdef INTERNAL_SCLK	n->stest1 = 0x80;		/* disable external scsi clock */#else	n->stest1 = 0x00;#endif	n->stime0 = 0xdd;		/* about 0.5 second timeout on each device */	n->scntl0 |= 0x8;		/* Enable parity checking */	/* continued setup */	n->sien0 = 0x8f;	n->sien1 = 0x04;	n->dien = 0x7d;	n->stest3 = 0x80;		/* TolerANT enable */	c->running = 0;	if (c->v->feature & BigFifo)		n->ctest5 = (1 << 5);	n->dmode = c->v->burst << 6;	/* set burst length bits */	if (c->v->burst & 4)		n->ctest5 |= (1 << 2);	/* including overflow into ctest5 bit 2 */	if (c->v->feature & Prefetch)		n->dcntl |= (1 << 5);	/* prefetch enable */	else if (c->v->feature & BurstOpCodeFetch)		n->dmode |= (1 << 1);	/* burst opcode fetch */	if (c->v->feature & Differential) {		/* chip capable */		if ((c->feature & Differential) || bios_set_differential(c)) {			/* user enabled, or some evidence bios set differential */			if (n->sstat2 & (1 << 2))				print(PRINTPREFIX "can't go differential; wrong cable\n");			else {				n->stest2 = (1 << 5);				print(PRINTPREFIX "differential mode set\n");			}		}	}	if (c->clockmult) {		n->stest1 |= (1 << 3);	/* power up doubler */		delay(2);		n->stest3 |= (1 << 5);	/* stop clock */		n->stest1 |= (1 << 2);	/* enable doubler */		n->stest3 &= ~(1 << 5);	/* start clock */		/* pray */	}}static voidmsgsm(Dsa *dsa, Controller *c, int msg, int *cont, int *wakeme){	uchar histpf, hisreqack;	int tpf;	int scf, xferp;	int len;	Ncr *n = c->n;	switch (c->s[dsa->target]) {	case SyncInit:		switch (msg) {		case A_SIR_MSG_SDTR:			/* reply to my SDTR */			histpf = n->scratcha[2];			hisreqack = n->scratcha[3];			KPRINT(PRINTPREFIX "%d: SDTN response %d %d\n",			    dsa->target, histpf, hisreqack);			if (hisreqack == 0)				setasync(dsa, c, dsa->target);			else {				/* hisreqack should be <= c->v->maxsyncoff */				tpf = chooserate(c, histpf, &scf, &xferp);				KPRINT(PRINTPREFIX "%d: SDTN: using %d %d\n",				    dsa->target, tpf, hisreqack);				setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack);			}			*cont = -2;			return;		case A_SIR_EV_PHASE_SWITCH_AFTER_ID:			/* target ignored ATN for message after IDENTIFY - not SCSI-II */			KPRINT(PRINTPREFIX "%d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target);			KPRINT(PRINTPREFIX "%d: SDTN: async\n", dsa->target);			setasync(dsa, c, dsa->target);			*cont = E_to_decisions;			return;		case A_SIR_MSG_REJECT:			/* rejection of my SDTR */			KPRINT(PRINTPREFIX "%d: SDTN: rejected SDTR\n", dsa->target);		//async:			KPRINT(PRINTPREFIX "%d: SDTN: async\n", dsa->target);			setasync(dsa, c, dsa->target);			*cont = -2;			return;		}		break;	case WideInit:		switch (msg) {		case A_SIR_MSG_WDTR:			/* reply to my WDTR */			KPRINT(PRINTPREFIX "%d: WDTN: response %d\n",			    dsa->target, n->scratcha[2]);			setwide(dsa, c, dsa->target, n->scratcha[2]);			*cont = -2;			return;		case A_SIR_EV_PHASE_SWITCH_AFTER_ID:			/* target ignored ATN for message after IDENTIFY - not SCSI-II */			KPRINT(PRINTPREFIX "%d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target);			setwide(dsa, c, dsa->target, 0);			*cont = E_to_decisions;			return;		case A_SIR_MSG_REJECT:			/* rejection of my SDTR */			KPRINT(PRINTPREFIX "%d: WDTN: rejected WDTR\n", dsa->target);			setwide(dsa, c, dsa->target, 0);			*cont = -2;			return;		}		break;	case NeitherDone:	case WideDone:	case BothDone:		switch (msg) {		case A_SIR_MSG_WDTR: {			uchar hiswide, mywide;			hiswide = n->scratcha[2];			mywide = (c->v->feature & Wide) != 0;			KPRINT(PRINTPREFIX "%d: WDTN: target init %d\n",			    dsa->target, hiswide);			if (hiswide < mywide)				mywide = hiswide;			KPRINT(PRINTPREFIX "%d: WDTN: responding %d\n",			    dsa->target, mywide);			setwide(dsa, c, dsa->target, mywide);			len = buildwdtrmsg(dsa->msg_out, mywide);			setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len);			*cont = E_response;			c->s[dsa->target] = WideResponse;			return;		}		case A_SIR_MSG_SDTR:#ifdef ASYNC_ONLY			*cont = E_reject;			return;#else			/* target decides to renegotiate */			histpf = n->scratcha[2];			hisreqack = n->scratcha[3];			KPRINT(PRINTPREFIX "%d: SDTN: target init %d %d\n",			    dsa->target, histpf, hisreqack);			if (hisreqack == 0) {				/* he wants asynchronous */				setasync(dsa, c, dsa->target);				tpf = 0;			}			else {				/* he wants synchronous */				tpf = chooserate(c, histpf, &scf, &xferp);				if (hisreqack > c->v->maxsyncoff)					hisreqack = c->v->maxsyncoff;				KPRINT(PRINTPREFIX "%d: using %d %d\n",				    dsa->target, tpf, hisreqack);				setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack);			}			/* build my SDTR message */			len = buildsdtrmsg(dsa->msg_out, tpf, hisreqack);			setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len);			*cont = E_response;			c->s[dsa->target] = SyncResponse;			return;#endif		}		break;	case WideResponse:		switch (msg) {		case A_SIR_EV_RESPONSE_OK:			c->s[dsa->target] = WideDone;			KPRINT(PRINTPREFIX "%d: WDTN: response accepted\n", dsa->target);			*cont = -2;			return;		case A_SIR_MSG_REJECT:			setwide(dsa, c, dsa->target, 0);			KPRINT(PRINTPREFIX "%d: WDTN: response REJECTed\n", dsa->target);			*cont = -2;			return;		}		break;	case SyncResponse:		switch (msg) {		case A_SIR_EV_RESPONSE_OK:			c->s[dsa->target] = BothDone;			KPRINT(PRINTPREFIX "%d: SDTN: response accepted (%s)\n",			    dsa->target, phase[n->sstat1 & 7]);			*cont = -2;			return;	/* chf */		case A_SIR_MSG_REJECT:			setasync(dsa, c, dsa->target);			KPRINT(PRINTPREFIX "%d: SDTN: response REJECTed\n", dsa->target);			*cont = -2;			return;		}		break;	}	KPRINT(PRINTPREFIX "%d: msgsm: state %d msg %d\n",	    dsa->target, c->s[dsa->target], msg);	*wakeme = 1;	return;}static voidcalcblockdma(Dsa *d, ulong base, ulong count){	ulong blocks;	if (DEBUG(3))		blocks = 0;	else {		blocks = count / A_BSIZE;		if (blocks > 255)			blocks = 255;	}	d->dmablks = blocks;	d->dmaaddr[0] = base;	d->dmaaddr[1] = base >> 8;	d->dmaaddr[2] = base >> 16;	d->dmaaddr[3] = base >> 24;	setmovedata(&d->data_buf, base + blocks * A_BSIZE, count - blocks * A_BSIZE);	if (legetl(d->data_buf.dbc) == 0)		d->flag = 1;}static ulongread_mismatch_recover(Controller *c, Ncr *n, Dsa *dsa){	ulong dbc;	uchar dfifo = n->dfifo;	int inchip;	dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];	if (n->ctest5 & (1 << 5))		inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff;	else		inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;	if (inchip) {		IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: DMA FIFO = %d\n",		    dsa->target, dsa->lun, inchip);	}	if (n->sxfer & SYNCOFFMASK(c)) {		/* SCSI FIFO */		uchar fifo = n->sstat1 >> 4;		if (c->v->maxsyncoff > 8)			fifo |= (n->sstat2 & (1 << 4));		if (fifo) {			inchip += fifo;			IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SCSI FIFO = %d\n",			    dsa->target, dsa->lun, fifo);		}	}	else {		if (n->sstat0 & (1 << 7)) {			inchip++;			IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SIDL full\n",			    dsa->target, dsa->lun);		}		if (n->sstat2 & (1 << 7)) {			inchip++;			IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SIDL msb full\n",			    dsa->target, dsa->lun);		}	}	USED(inchip);	return dbc;}static ulongwrite_mismatch_recover(Controller *c, Ncr *n, Dsa *dsa){	ulong dbc;	uchar dfifo = n->dfifo;	int inchip;	dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];	USED(dsa);	if (n->ctest5 & (1 << 5))		inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff;	else		inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;

⌨️ 快捷键说明

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