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

📄 scsincr53c8xx.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
    int *transferred){	uchar *bp;	int bc;	Dsa *d;	Ncr *n = c->n;	uchar target_expo, my_expo;	ushort status;	d = dsaalloc(c, target, lun);	qlock(&c->q[target]);			/* obtain access to target */	/* load the transfer control stuff */	d->scsi_id_buf[0] = 0;	d->scsi_id_buf[1] = c->sxfer[target];	d->scsi_id_buf[2] = target;	d->scsi_id_buf[3] = c->scntl3[target];	synctodsa(d, c);	bc = 0;	d->msg_out[bc] = 0x80 | lun;#ifndef NO_DISCONNECT	d->msg_out[bc] |= (1 << 6);#endif	bc++;	/* work out what to do about negotiation */	switch (c->s[target]) {	default:		KPRINT(PRINTPREFIX "%d: strange nego state %d\n", target, c->s[target]);		c->s[target] = NeitherDone;		/* fall through */	case NeitherDone:		if ((c->capvalid & (1 << target)) == 0)			break;		target_expo = (c->cap[target] >> 5) & 3;		my_expo = (c->v->feature & Wide) != 0;		if (target_expo < my_expo)			my_expo = target_expo;#ifdef ALWAYS_DO_WDTR		bc += buildwdtrmsg(d->msg_out + bc, my_expo);		KPRINT(PRINTPREFIX "%d: WDTN: initiating expo %d\n", target, my_expo);		c->s[target] = WideInit;		break;#else		if (my_expo) {			bc += buildwdtrmsg(d->msg_out + bc, (c->v->feature & Wide) ? 1 : 0);			KPRINT(PRINTPREFIX "%d: WDTN: initiating expo %d\n", target, my_expo);			c->s[target] = WideInit;			break;		}		KPRINT(PRINTPREFIX "%d: WDTN: narrow\n", target);		/* fall through */#endif	case WideDone:		if (c->cap[target] & (1 << 4)) {			KPRINT(PRINTPREFIX "%d: SDTN: initiating %d %d\n", target, c->tpf, c->v->maxsyncoff);			bc += buildsdtrmsg(d->msg_out + bc, c->tpf, c->v->maxsyncoff);			c->s[target] = SyncInit;			break;		}		KPRINT(PRINTPREFIX "%d: SDTN: async only\n", target);		c->s[target] = BothDone;		break;	case BothDone:		break;	}	setmovedata(&d->msg_out_buf, DMASEG(d->msg_out), bc);	setmovedata(&d->cmd_buf, DMASEG(cmd), cmdlen);	calcblockdma(d, DMASEG(data), datalen);	if (DEBUG(0)) {		KPRINT(PRINTPREFIX "%d/%d: exec: ", target, lun);		for (bp = cmd; bp < &cmd[cmdlen]; bp++)			KPRINT("%.2ux", *bp);		KPRINT("\n");		if (rw)			KPRINT(PRINTPREFIX "%d/%d: exec: limit=(%d)%ld\n",			    target, lun, d->dmablks, legetl(d->data_buf.dbc));		else			dumpwritedata(data, datalen);	}	setmovedata(&d->status_buf, DMASEG(&d->status), 1);	d->p9status = 0xffff;	d->parityerror = 0;	d->stateb = A_STATE_ISSUE;		/* start operation */	ilock(c);	if (c->ssm)		c->n->dcntl |= 0x10;		/* SSI */	if (c->running) {		n->istat |= Sigp;	}	else {		start(c, E_issue_check);	}	iunlock(c);#ifdef CPU	while(waserror())		;#ifdef QUICK_TIMEOUT	tsleep(d, done, d, 30 * 1000);#else	tsleep(d, done, d, 60 * 60 * 1000);#endif	poperror();	if (!done(d)) {		KPRINT(PRINTPREFIX "%d/%d: exec: Timed out\n", target, lun);		dumpncrregs(c, 0);		dsafree(c, d);		reset(c);		qunlock(&c->q[target]);		error(Eio);	}#endif#ifdef FS	sleep(d, done, d);#endif	if (d->p9status == STATUS_SELECTION_TIMEOUT)		c->s[target] = NeitherDone;	if (d->parityerror) {		d->p9status = STATUS_FAIL;	}	/*	 * adjust datalen	 */	if (d->dmablks > 0)		datalen -= d->dmablks * A_BSIZE;	else if (d->flag == 0)		datalen -= legetl(d->data_buf.dbc);	if (transferred)		*transferred = datalen;	if (rw)		dumpreaddata(data, datalen);	if (DEBUG(0))		KPRINT(PRINTPREFIX "%d/%d: exec: p9status=%d status %d rlen %d\n",		    target, lun, d->p9status, status, datalen);	/*	 * spot the identify	 */	if ((c->capvalid & (1 << target)) == 0 &&	    d->p9status == STATUS_COMPLETE && cmd[0] == 0x12 && datalen >= 8) {		c->capvalid |= 1 << target;		c->cap[target] = data[7];		KPRINT(PRINTPREFIX "%d: capabilities %.2x\n", target, data[7]);	}	status = d->p9status;	dsafree(c, d);	qunlock(&c->q[target]);	return status;}#ifdef CPUstatic intexec(Scsi *p, int rw){	int transferred;	Controller *c = &controller;		/* MULTIPLE - map from scsi bus to controller instance */	p->status = io(c, p->target, p->lun, rw,	    p->cmd.base, p->cmd.lim - p->cmd.base,	    p->data.base, p->data.lim - p->data.base, &transferred);	p->data.ptr = p->data.base + transferred;	return p->status;}#endif#ifdef Plan9fsstatic intexec(Device d, int rw, uchar *cmd, int clen, void *data, int dlen){	Controller *c = &controller;		/* MULTIPLE - map from scsi bus to controller instance */	return io(c, d.unit, (cmd[1] >> 5) & 7, rw, cmd, clen, data, dlen, 0);}#endif /* Plan9fs#ifdef FSstatic intexec(Target* t, int rw, uchar* cmd, int cbytes, void* data, int* dbytes){	int n, s;	Controller *ctlr;	if((ctlr = ctlrxx[t->ctlrno]) == nil || ctlr->n == nil)		return STharderr;	if(t->targetno == 0x07)		return STownid;	if(dbytes)		n = *dbytes;	else		n = 0;	s = io(ctlr, t->targetno, (cmd[1] >> 5) & 7, rw, cmd, cbytes, data, n, dbytes);	switch(s){	case STATUS_COMPLETE:		return STok;	case STATUS_FAIL:		return STharderr;	case STATUS_SELECTION_TIMEOUT:		return STtimeout;	case 0x6002:		return STcheck;	default:		print("scsi#%d: exec status 0x%ux\n", ctlr->ctlrno, s);		return STharderr;	}}#endifstatic voidcribbios(Controller *c){	c->bios.scntl3 = c->n->scntl3;	c->bios.stest2 = c->n->stest2;	KPRINT(PRINTPREFIX "bios scntl3(%.2x) stest2(%.2x)\n", c->bios.scntl3, c->bios.stest2);}static intbios_set_differential(Controller *c){	/* Concept lifted from FreeBSD - thanks Gerard */	/* basically, if clock conversion factors are set, then there is 	 * evidence the bios had a go at the chip, and if so, it would	 * have set the differential enable bit in stest2	 */	return (c->bios.scntl3 & 7) != 0 && (c->bios.stest2 & 0x20) != 0;}#define NCR_VID 	0x1000#define NCR_810_DID 	0x0001#define NCR_820_DID	0x0002	/* don't know enough about this one to support it */#define NCR_825_DID	0x0003#define NCR_815_DID	0x0004#define SYM_810AP_DID	0x0005#define SYM_860_DID	0x0006#define SYM_896_DID	0x000b#define SYM_895_DID	0x000c#define SYM_885_DID	0x000d	/* ditto */#define SYM_875_DID	0x000f	/* ditto */#define SYM_1010_DID	0x0020#define SYM_875J_DID	0x008fstatic Variant variant[] = {{ NCR_810_DID,   0x0f, "NCR53C810",	Burst16,   8, 24, 0 },{ NCR_810_DID,   0x1f, "SYM53C810ALV",	Burst16,   8, 24, Prefetch },{ NCR_810_DID,   0xff, "SYM53C810A",	Burst16,   8, 24, Prefetch },{ SYM_810AP_DID, 0xff, "SYM53C810AP",	Burst16,   8, 24, Prefetch },{ NCR_815_DID,   0xff, "NCR53C815",	Burst16,   8, 24, BurstOpCodeFetch },{ NCR_825_DID,   0x0f, "NCR53C825",	Burst16,   8, 24, Wide|BurstOpCodeFetch|Differential },{ NCR_825_DID,   0xff, "SYM53C825A",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide },{ SYM_860_DID,   0x0f, "SYM53C860",	Burst16,   8, 24, Prefetch|Ultra },{ SYM_860_DID,   0xff, "SYM53C860LV",	Burst16,   8, 24, Prefetch|Ultra },{ SYM_875_DID,   0x01, "SYM53C875r1",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra },{ SYM_875_DID,   0xff, "SYM53C875",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },{ SYM_875J_DID,   0xff, "SYM53C875j",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },{ SYM_885_DID,   0xff, "SYM53C885",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|ClockDouble },{ SYM_895_DID,   0xff, "SYM53C895",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },{ SYM_896_DID,   0xff, "SYM53C896",	Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },{ SYM_1010_DID,  0xff, "SYM53C1010",	Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },};#define MAXVAR (sizeof(variant)/sizeof(variant[0]))#ifndef NAINCLUDEstatic intna_fixup(Controller *c, ulong pa_reg,    struct na_patch *patch, int patches,    int (*externval)(Controller*, int, ulong*)){	int p;	int v;	ulong *script, pa_script;	unsigned long lw, lv;	script = c->script;	pa_script = c->scriptpa;	for (p = 0; p < patches; p++) {		switch (patch[p].type) {		case 1:			/* script relative */			script[patch[p].lwoff] += pa_script;			break;		case 2:			/* register i/o relative */			script[patch[p].lwoff] += pa_reg;			break;		case 3:			/* data external */			lw = script[patch[p].lwoff];			v = (lw >> 8) & 0xff;			if (!(*externval)(c, v, &lv))				return 0;			v = lv & 0xff;			script[patch[p].lwoff] = (lw & 0xffff00ffL) | (v << 8);			break;		case 4:			/* 32 bit external */			lw = script[patch[p].lwoff];			if (!(*externval)(c, lw, &lv))				return 0;			script[patch[p].lwoff] = lv;			break;		case 5:			/* 24 bit external */			lw = script[patch[p].lwoff];			if (!(*externval)(c, lw & 0xffffff, &lv))				return 0;			script[patch[p].lwoff] = (lw & 0xff000000L) | (lv & 0xffffffL);			break;		}	}	return 1;}#endif /* NAINCLUDE */typedef struct Adapter {	Pcidev*	pcidev;	int	port;	int	irq;	int	rid;} Adapter;static Msgbuf* adapter;static voidscanpci(void){	Pcidev *p;	Msgbuf *mb, *last;	Adapter *ap;	p = nil;	last = nil;	while(p = pcimatch(p, NCR_VID, 0)){		mb = mballoc(sizeof(Adapter), 0, Mxxx);		ap = (Adapter*)mb->data;		ap->pcidev = p;		ap->port = p->mem[0].bar & ~0x01;		if(adapter == nil)			adapter = mb;		else			last->next = mb;		last = mb;	}}static intinit(Controller* ctlr, ISAConf* isa, int differential){	int is64, var, rid;	ulong regpa, scriptpa;	Pcidev *pcidev;	Msgbuf *mb, **mbb;	Adapter *ap;	extern ulong upamalloc(ulong, int, int);	/*	 * Any adapter matches if no isa->port is supplied,	 * otherwise the ports must match.	 */	pcidev = nil;	mbb = &adapter;	for(mb = *mbb; mb; mb = mb->next){		ap = (Adapter*)mb->data;		if(isa->port == 0 || isa->port == ap->port){			pcidev = ap->pcidev;			*mbb = mb->next;			mbfree(mb);			break;		}		mbb = &mb->next;	}	if(pcidev == nil)		return 0;	rid = pcicfgr8(pcidev, PciRID);	for (var = 0; var < MAXVAR; var++) {		if (pcidev->did == variant[var].did && rid <= variant[var].maxrid)			break;	}	if (var >= MAXVAR)		return 0;	print("scsi#%d: %s rev. 0x%.2x intr=%d command=%.4x\n",		ctlr->ctlrno, variant[var].name, rid,		pcidev->intl, pcicfgr16(pcidev, PciPCR));	is64 = pcidev->mem[1].bar & 0x04;	if(is64 && pcidev->mem[2].bar){		print("scsi#%d: registers in 64-bit space\n",			ctlr->ctlrno);		return 0;	}	regpa = upamalloc(pcidev->mem[1].bar & ~0x0F, pcidev->mem[1].size, 0);	if (regpa == 0) {		print("scsi#%d: failed to map registers\n", ctlr->ctlrno);		return 0;	}	ctlr->n = KADDR(regpa);	ctlr->v = &variant[var];	scriptpa = 0;	if ((ctlr->v->feature & LocalRAM) && sizeof(na_script) <= 4096) {		if(is64){			if((pcidev->mem[3].bar & 0x04) && pcidev->mem[4].bar){				print("scsi#%d: RAM in 64-bit space\n",					ctlr->ctlrno);				scriptpa = 0;			}			else				scriptpa = upamalloc(pcidev->mem[3].bar & ~0x0F,					pcidev->mem[3].size, 0);		}		else			scriptpa = upamalloc(pcidev->mem[2].bar & ~0x0F,					pcidev->mem[2].size, 0);		if (scriptpa == 0)			print("scsi#%d: failed to map onboard RAM\n", ctlr->ctlrno);		else {			ctlr->script = KADDR(scriptpa);			ctlr->scriptpa = scriptpa;			memmove(ctlr->script, na_script, sizeof(na_script));			print("scsi#%d: local SCRIPT ram enabled\n", ctlr->ctlrno);		}	}	if (scriptpa == 0) {		/* either the map failed, or this chip does not have local RAM		 * it will need a copy of the microcode		 */		/*		 * should allocate memory and copy na_script into it for		 * multiple controllers here		 * single controller version uses the microcode in place		 */		ctlr->script = na_script;		ctlr->scriptpa = DMASEG(na_script);	}	/* fixup script */	if (!na_fixup(ctlr, regpa, na_patches, NA_PATCHES, xfunc)) {		print("script fixup failed\n");		return 0;	}	if (differential)		ctlr->feature |= Differential;	swabl(ctlr->script, ctlr->script, sizeof(na_script));	ctlr->dsalist.freechain = 0;	lesetl(ctlr->dsalist.head, 0);	isa->port = (ulong)KADDR(regpa);	isa->irq = pcidev->intl;	synctabinit(ctlr);	cribbios(ctlr);	/*	intrenable(isa->irq, interrupt, ctlr, pcidev->tbdf);	 */	setvec(IRQBASE + isa->irq, interrupt, ctlr);	reset(ctlr);	return 1;}#ifdef CPUint (*ncr53c8xxreset(void))(Scsi*, int){	ISAConf isaconf;	int ic;	int differential = 0;	int o;	Controller *c;	memset(&isaconf, 0, sizeof(isaconf));	strcpy(isaconf.type, DEVICENAME);	ic = isaconfig("scsi", 0, &isaconf);	/* search any ISA opts */	if (ic) {		for (o = 0; o < isaconf.nopt; o++) {			if (strcmp(isaconf.opt[o], "diff") == 0)				differential = 1;		}	}	c = &controller; 			/* MULTIPLE - map from scsi bus to controller instance */	if (init(c, differential))		return exec;	return 0;}#endif#ifdef Plan9fsint (*ncr53c8xxreset(int /*ctlrno*/, ISAConf */*isa*/))(Device, int, uchar*, int, void*, int){	Controller *c = &controller;		/* MULTIPLE - map from scsi bus to controller instance */	if (init(c, 0))		return exec;	return 0;}#endif /* Plan9fs */#ifdef FSScsiioncr53c8xxreset(int ctlrno, ISAConf* isa){	int differential, o;	Controller *ctlr;	static int scandone;	if(scandone == 0){		scanpci();		scandone = 1;	}	differential = 0;	for (o = 0; o < isa->nopt; o++) {		if (strcmp(isa->opt[o], "diff") == 0)			differential = 1;	}	if((ctlr = xalloc(sizeof(Controller))) == 0){		print("scsi#%d: %s: controller allocation failed\n",			ctlrno, isa->type);		return 0;	}	ctlrxx[ctlrno] = ctlr;	ctlr->ctlrno = ctlrno;	if (init(ctlr, isa, differential))		return exec;	return 0;}#endif /* FS */

⌨️ 快捷键说明

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