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

📄 sd53c8xx.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
		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 intsd53c8xxrio(SDreq* r){	Dsa *d;	uchar *bp;	Controller *c;	uchar target_expo, my_expo;	int bc, check, i, status, target;	if((target = r->unit->subno) == 0x07)		return r->status = SDtimeout;	/* assign */	c = r->unit->dev->ctlr;	check = 0;	d = dsaalloc(c, target, r->lun);	qlock(&c->q[target]);			/* obtain access to target */docheck:	/* 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 | r->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(r->cmd), r->clen);	calcblockdma(d, r->data ? DMASEG(r->data) : 0, r->dlen);	if (DEBUG(0)) {		KPRINT(PRINTPREFIX "%d/%d: exec: ", target, r->lun);		for (bp = r->cmd; bp < &r->cmd[r->clen]; bp++) {			KPRINT("%.2ux", *bp);		}		KPRINT("\n");		if (!r->write) {			KPRINT(PRINTPREFIX "%d/%d: exec: limit=(%d)%ld\n",			  target, r->lun, d->dmablks, legetl(d->data_buf.dbc));		}		else			dumpwritedata(r->data, r->dlen);	}	setmovedata(&d->status_buf, DMASEG(&d->status), 1);		d->p9status = SDnostatus;	d->parityerror = 0;	coherence();	d->stateb = A_STATE_ISSUE;		/* start operation */	coherence();	ilock(c);	if (c->ssm)		c->n->dcntl |= 0x10;		/* single step */	if (c->running) {		c->n->istat = Sigp;	}	else {		start(c, E_issue_check);	}	iunlock(c);	while(waserror())		;	tsleep(d, done, d, 600 * 1000);	poperror();	if (!done(d)) {		KPRINT(PRINTPREFIX "%d/%d: exec: Timed out\n", target, r->lun);		dumpncrregs(c, 0);		dsafree(c, d);		reset(c);		qunlock(&c->q[target]);		r->status = SDtimeout;		return r->status = SDtimeout;	/* assign */	}	if((status = d->p9status) == SDeio)		c->s[target] = NeitherDone;	if (d->parityerror) {		status = SDeio;	}	/*	 * adjust datalen	 */	r->rlen = r->dlen;	if (DEBUG(0)) {		KPRINT(PRINTPREFIX "%d/%d: exec: before rlen adjust: dmablks %d flag %d dbc %lud\n",		    target, r->lun, d->dmablks, d->flag, legetl(d->data_buf.dbc));	}	r->rlen = r->dlen;	if (d->flag != 2) {		r->rlen -= d->dmablks * A_BSIZE;		r->rlen -= legetl(d->data_buf.dbc);	}	if(!r->write)		dumpreaddata(r->data, r->rlen);	if (DEBUG(0)) {		KPRINT(PRINTPREFIX "%d/%d: exec: p9status=%d status %d rlen %ld\n",		    target, r->lun, d->p9status, status, r->rlen);	}	/*	 * spot the identify	 */	if ((c->capvalid & (1 << target)) == 0	 && (status == SDok || status == SDcheck)	 && r->cmd[0] == 0x12 && r->dlen >= 8) {		c->capvalid |= 1 << target;		bp = r->data;		c->cap[target] = bp[7];		KPRINT(PRINTPREFIX "%d: capabilities %.2x\n", target, bp[7]);	}	if(!check && status == SDcheck && !(r->flags & SDnosense)){		check = 1;		r->write = 0;		memset(r->cmd, 0, sizeof(r->cmd));		r->cmd[0] = 0x03;		r->cmd[1] = r->lun<<5;		r->cmd[4] = sizeof(r->sense)-1;		r->clen = 6;		r->data = r->sense;		r->dlen = sizeof(r->sense)-1;		/*		 * Clear out the microcode state		 * so the Dsa can be re-used.		 */		lesetl(&d->stateb, A_STATE_ALLOCATED);		coherence();		goto docheck;	}	qunlock(&c->q[target]);	dsafree(c, d);	if(status == SDok && check){		status = SDcheck;		r->flags |= SDvalidsense;	}	if(DEBUG(0))		KPRINT(PRINTPREFIX "%d: r flags %8.8uX status %d rlen %ld\n",			target, r->flags, status, r->rlen);	if(r->flags & SDvalidsense){		if(!DEBUG(0))			KPRINT(PRINTPREFIX "%d: r flags %8.8uX status %d rlen %ld\n",				target, r->flags, status, r->rlen);		for(i = 0; i < r->rlen; i++)			KPRINT(" %2.2uX", r->sense[i]);		KPRINT("\n");	}	return r->status = status;}#define	vpt ((ulong*)VPT)#define	VPTX(va)		(((ulong)(va))>>12)static voidcribbios(Controller *c){	c->bios.scntl3 = c->n->scntl3;	c->bios.stest2 = c->n->stest2;	print(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_1011_DID	0x0021#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 },{ SYM_1011_DID,   0xff, "SYM53C1010",	Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },};static intxfunc(Controller *c, enum na_external x, unsigned long *v){	switch (x)	{	case X_scsi_id_buf:		*v = offsetof(Dsa, scsi_id_buf[0]); return 1;	case X_msg_out_buf:		*v = offsetof(Dsa, msg_out_buf); return 1;	case X_cmd_buf:		*v = offsetof(Dsa, cmd_buf); return 1;	case X_data_buf:		*v = offsetof(Dsa, data_buf); return 1;	case X_status_buf:		*v = offsetof(Dsa, status_buf); return 1;	case X_dsa_head:		*v = DMASEG(&c->dsalist.head[0]); return 1;	case X_ssid_mask:		*v = SSIDMASK(c); return 1;	default:		print("xfunc: can't find external %d\n", x);		return 0;	}	return 1;}static 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;}static SDev*sd53c8xxpnp(void){	char *cp;	Pcidev *p;	Variant *v;	int ba, nctlr;	void *scriptma;	Controller *ctlr;	SDev *sdev, *head, *tail;	ulong regpa, *script, scriptpa;	void *regva, *scriptva;	if(cp = getconf("*maxsd53c8xx"))		nctlr = strtoul(cp, 0, 0);	else		nctlr = 32;	p = nil;	head = tail = nil;	while((p = pcimatch(p, NCR_VID, 0)) != nil && nctlr > 0){		for(v = variant; v < &variant[nelem(variant)]; v++){			if(p->did == v->did && p->rid <= v->maxrid)				break;		}		if(v >= &variant[nelem(variant)]) {			print("no match\n");			continue;		}		print(PRINTPREFIX "%s rev. 0x%2.2x intr=%d command=%4.4uX\n",			v->name, p->rid, p->intl, p->pcr);		regpa = p->mem[1].bar;		ba = 2;		if(regpa & 0x04){			if(p->mem[2].bar)				continue;			ba++;		}		if(regpa == 0)			print("regpa 0\n");		regpa &= ~0xF;		regva = vmap(regpa, p->mem[1].size);		if(regva == 0)			continue;		script = nil;		scriptpa = 0;		scriptva = nil;		scriptma = nil;		if((v->feature & LocalRAM) && sizeof(na_script) <= 4096){			scriptpa = p->mem[ba].bar;			if((scriptpa & 0x04) && p->mem[ba+1].bar){				vunmap(regva, p->mem[1].size);				continue;			}			scriptpa &= ~0x0F;			scriptva = vmap(scriptpa, p->mem[ba].size);			if(scriptva)				script = scriptva;		}		if(scriptpa == 0){			/*			 * Either the map failed, or this chip does not have			 * local RAM. It will need a copy of the microcode.			 */			scriptma = malloc(sizeof(na_script));			if(scriptma == nil){				vunmap(regva, p->mem[1].size);				continue;			}			scriptpa = DMASEG(scriptma);			script = scriptma;		}		ctlr = malloc(sizeof(Controller));		sdev = malloc(sizeof(SDev));		if(ctlr == nil || sdev == nil){buggery:			if(ctlr)				free(ctlr);			if(sdev)				free(sdev);			if(scriptma)				free(scriptma);			else if(scriptva)				vunmap(scriptva, p->mem[ba].size);			if(regva)				vunmap(regva, p->mem[1].size);			continue;		}		if(dsaend == nil)			dsaend = xalloc(sizeof *dsaend);		lesetl(&dsaend->stateb, A_STATE_END);	//	lesetl(dsaend->next, DMASEG(dsaend));		coherence();		lesetl(ctlr->dsalist.head, DMASEG(dsaend));		coherence();		ctlr->dsalist.freechain = 0;		ctlr->n = regva;		ctlr->v = v;		ctlr->script = script;		memmove(ctlr->script, na_script, sizeof(na_script));		/*		 * Because we don't yet have an abstraction for the		 * addresses as seen from the controller side (and on		 * the 386 it doesn't matter), the following three lines		 * are different between the 386 and alpha copies of		 * this driver.		 */		USED(scriptpa);		ctlr->scriptpa = p->mem[ba].bar & ~0x0F;		if(!na_fixup(ctlr, p->mem[1].bar & ~0x0F, na_patches, NA_PATCHES, xfunc)){			print("script fixup failed\n");			goto buggery;		}		swabl(ctlr->script, ctlr->script, sizeof(na_script));		ctlr->pcidev = p;		sdev->ifc = &sd53c8xxifc;		sdev->ctlr = ctlr;		sdev->idno = '0';		if(!(v->feature & Wide))			sdev->nunit = 8;		else			sdev->nunit = MAXTARGET;		ctlr->sdev = sdev;				if(head != nil)			tail->next = sdev;		else			head = sdev;		tail = sdev;		nctlr--;	}	return head;}static intsd53c8xxenable(SDev* sdev){	Pcidev *pcidev;	Controller *ctlr;	char name[32];	ctlr = sdev->ctlr;	pcidev = ctlr->pcidev;	pcisetbme(pcidev);	ilock(ctlr);	synctabinit(ctlr);	cribbios(ctlr);	reset(ctlr);	snprint(name, sizeof(name), "%s (%s)", sdev->name, sdev->ifc->name);	intrenable(pcidev->intl, sd53c8xxinterrupt, ctlr, pcidev->tbdf, name);	iunlock(ctlr);	return 1;}SDifc sd53c8xxifc = {	"53c8xx",			/* name */	sd53c8xxpnp,			/* pnp */	nil,				/* legacy */	sd53c8xxenable,			/* enable */	nil,				/* disable */	scsiverify,			/* verify */	scsionline,			/* online */	sd53c8xxrio,			/* rio */	nil,				/* rctl */	nil,				/* wctl */	scsibio,			/* bio */	nil,				/* probe */	nil,				/* clear */	nil,				/* stat */};

⌨️ 快捷键说明

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