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

📄 sdata.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 5 页
字号:
ataenable(SDev* sdev){	Ctlr *ctlr;	char name[32];	ctlr = sdev->ctlr;	if(ctlr->bmiba){#define ALIGN	(4 * 1024)		if(ctlr->pcidev != nil)			pcisetbme(ctlr->pcidev);		// ctlr->prdt = xspanalloc(Nprd*sizeof(Prd), 4, 4*1024);		ctlr->prdtbase = xalloc(Nprd * sizeof(Prd) + ALIGN);		ctlr->prdt = (Prd *)(((ulong)ctlr->prdtbase + ALIGN) & ~(ALIGN - 1));	}	snprint(name, sizeof(name), "%s (%s)", sdev->name, sdev->ifc->name);	intrenable(ctlr->irq, atainterrupt, ctlr, ctlr->tbdf, name);	outb(ctlr->ctlport+Dc, 0);	if(ctlr->ienable)		ctlr->ienable(ctlr);	return 1;}static intatadisable(SDev *sdev){	Ctlr *ctlr;	char name[32];	ctlr = sdev->ctlr;	outb(ctlr->ctlport+Dc, Nien);		/* disable interrupts */	if (ctlr->idisable)		ctlr->idisable(ctlr);	snprint(name, sizeof(name), "%s (%s)", sdev->name, sdev->ifc->name);	intrdisable(ctlr->irq, atainterrupt, ctlr, ctlr->tbdf, name);	if (ctlr->bmiba) {		if (ctlr->pcidev)			pciclrbme(ctlr->pcidev);		xfree(ctlr->prdtbase);	}	return 0;}#ifndef FSstatic intatarctl(SDunit* unit, char* p, int l){	int n;	Ctlr *ctlr;	Drive *drive;	if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil)		return 0;	drive = ctlr->drive[unit->subno];	qlock(drive);	n = snprint(p, l, "config %4.4uX capabilities %4.4uX",		drive->info[Iconfig], drive->info[Icapabilities]);	if(drive->dma)		n += snprint(p+n, l-n, " dma %8.8uX dmactl %8.8uX",			drive->dma, drive->dmactl);	if(drive->rwm)		n += snprint(p+n, l-n, " rwm %ud rwmctl %ud",			drive->rwm, drive->rwmctl);	if(drive->flags&Lba48)		n += snprint(p+n, l-n, " lba48always %s",			(drive->flags&Lba48always) ? "on" : "off");	n += snprint(p+n, l-n, "\n");	if(drive->sectors){		n += snprint(p+n, l-n, "geometry %lld %d",			(Wideoff)drive->sectors, drive->secsize);		if(drive->pkt == 0)			n += snprint(p+n, l-n, " %d %d %d",				drive->c, drive->h, drive->s);		n += snprint(p+n, l-n, "\n");	}	qunlock(drive);	return n;}static intatawctl(SDunit* unit, Cmdbuf* cb){	int period;	Ctlr *ctlr;	Drive *drive;	if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil)		return 0;	drive = ctlr->drive[unit->subno];	qlock(drive);	if(waserror()){		qunlock(drive);		nexterror();	}	/*	 * Dma and rwm control is passive at the moment,	 * i.e. it is assumed that the hardware is set up	 * correctly already either by the BIOS or when	 * the drive was initially identified.	 */	if(strcmp(cb->f[0], "dma") == 0){		if(cb->nf != 2 || drive->dma == 0)			error(Ebadctl);		if(strcmp(cb->f[1], "on") == 0)			drive->dmactl = drive->dma;		else if(strcmp(cb->f[1], "off") == 0)			drive->dmactl = 0;		else			error(Ebadctl);	}	else if(strcmp(cb->f[0], "rwm") == 0){		if(cb->nf != 2 || drive->rwm == 0)			error(Ebadctl);		if(strcmp(cb->f[1], "on") == 0)			drive->rwmctl = drive->rwm;		else if(strcmp(cb->f[1], "off") == 0)			drive->rwmctl = 0;		else			error(Ebadctl);	}	else if(strcmp(cb->f[0], "standby") == 0){		switch(cb->nf){		default:			error(Ebadctl);		case 2:			period = strtol(cb->f[1], 0, 0);			if(period && (period < 30 || period > 240*5))				error(Ebadctl);			period /= 5;			break;		}		if(atastandby(drive, period) != SDok)			error(Ebadctl);	}	else if(strcmp(cb->f[0], "lba48always") == 0){		if(cb->nf != 2 || !(drive->flags&Lba48))			error(Ebadctl);		if(strcmp(cb->f[1], "on") == 0)			drive->flags |= Lba48always;		else if(strcmp(cb->f[1], "off") == 0)			drive->flags &= ~Lba48always;		else			error(Ebadctl);	}	else		error(Ebadctl);	qunlock(drive);	poperror();	return 0;}#endifSDifc sdataifc = {	"ata",				/* name */	atapnp,				/* pnp */	atalegacy,			/* legacy */	ataid,				/* id */	ataenable,			/* enable */	atadisable,			/* disable */	scsiverify,			/* verify */	scsionline,			/* online */	atario,				/* rio */	nil,	//atarctl,		/* rctl */	nil,	//atawctl,		/* wctl */	scsibio,			/* bio */#ifndef FS	nil,	//ataprobew,		/* probe */	ataclear,			/* clear */	atastat,			/* stat */#endif};/* * file-server-specific routines * * ata* routines below this point are used to access nvram file, * ide* routines implement the `h' device and call the ata* routines. */static Drive*atapart(Drive *dp){	return dp;}static Drive*atadriveprobe(int driveno){	Drive *drive;	drive = atadrive[driveno];	if (drive == nil)		return nil;	drive->driveno = driveno;	if(drive->online == 0){		if(drive->lba)			print("h%d: LBA %llud sectors\n",				drive->driveno, (Wideoff)drive->sectors);		else			print("h%d: CHS %d/%d/%d %llud sectors\n",				drive->driveno, drive->c, drive->h, drive->s,				(Wideoff)drive->sectors);		drive->online = 1;	}	return atapart(drive);}static voidcmd_stat(int, char*[]){	Ctlr *ctlr;	int ctlrno, targetno;	Target *tp;	for(ctlrno = 0; ctlrno < nelem(atactlr); ctlrno++){		ctlr = atactlr[ctlrno];		if(ctlr == nil || ctlr->sdev == nil)			continue;		for(targetno = 0; targetno < NTarget; targetno++){			tp = &ctlr->target[targetno];			if(tp->fflag == 0)				continue;			print("\t%d.%d work =%7W%7W%7W xfrs\n",				ctlrno, targetno,				tp->work+0, tp->work+1, tp->work+2);			print("\t    rate =%7W%7W%7W tBps\n",				tp->rate+0, tp->rate+1, tp->rate+2);		}	}}/* find all the controllers, enable interrupts, set up SDevs & SDunits */intatainit(void){	unsigned i;	SDev *sdp;	SDev **sdpp;	static int first = 1;	if (first)		first = 0;	else		return 0xFF;	atapnp();	for (sdpp = sdevs; sdpp < sdevs + nelem(sdevs); sdpp++) {		sdp = *sdpp;		if (sdp == nil)			continue;		i = sdpp - sdevs;		sdp->ifc = &sdataifc;		sdp->nunit = NCtlrdrv;		sdp->index = i;		sdp->idno = 'C' + i;		sdp->ctlr = atactlr[i];		if (sdp->ctlr != nil)			ataenable(sdp);	}	cmd_install("stati", "-- ide/ata stats", cmd_stat);	return 0xFF;}Devsizeataseek(int driveno, Devsize offset){	Drive *drive = atadrive[driveno];	if (drive == nil || !drive->online)		return -1;	drive->offset = offset;	return offset;}/* zero indicates failure; only otherinit() cares */intsetatapart(int driveno, char *){	/* atadriveprobe() sets drive->online */	if(atadriveprobe(driveno) == nil)		return 0;	return 1;}static voidkeepstats(Drive *dp, int dbytes){	Target *tp = &dp->ctlr->target[dp->driveno%NCtlrdrv];	qlock(tp);//	if(tp->ok == 0)//		scsiprobe(d);	if(tp->fflag == 0) {		dofilter(tp->work+0, C0a, C0b, 1);	/* was , 1000); */		dofilter(tp->work+1, C1a, C1b, 1);	/* was , 1000); */		dofilter(tp->work+2, C2a, C2b, 1);	/* was , 1000); */		dofilter(tp->rate+0, C0a, C0b, 1);		dofilter(tp->rate+1, C1a, C1b, 1);		dofilter(tp->rate+2, C2a, C2b, 1);		tp->fflag = 1;	}	tp->work[0].count++;	tp->work[1].count++;	tp->work[2].count++;	tp->rate[0].count += dbytes;	tp->rate[1].count += dbytes;	tp->rate[2].count += dbytes;	qunlock(tp);}static longataxfer(Drive *dp, int inout, Devsize start, long bytes){	unsigned driveno = dp->driveno;	ulong secsize = dp->secsize, sects;	SDunit *unit = sdgetunit(sdevs[driveno/NCtlrdrv], driveno%NCtlrdrv);	if (unit == nil) {		print("mvsataxfer: nil unit\n");		return -1;	}	if (dp->driveno == -1)		panic("ataxfer: dp->driveno unset");	/*	 * unit->dev will be nil if the controller is missing (e.g., h0 on a	 * machine with only sdD, not sdC), so make this a non-fatal error.	 */	if (unit->dev == nil) {		print("ataxfer: missing controller for h%d\n", driveno);		return -1;	}	if (unit->dev != sdevs[driveno/NCtlrdrv])		panic("ataxfer: sdunits[%d].dev=%p is wrong controller (want %p)",			driveno, unit->dev, sdevs + driveno/NCtlrdrv);	if (unit->subno != driveno%NCtlrdrv)		panic("ataxfer: sdunits[%d].subno is %d, not %d",			driveno, unit->subno, driveno%NCtlrdrv);	keepstats(dp, bytes);	if (unit->sectors == 0) {		unit->sectors = dp->sectors;		unit->secsize = secsize;	}	sects = (bytes + secsize - 1) / secsize;	/* round up */	if (start%secsize != 0)		print("ataxfer: start offset not on sector boundary\n");	return scsibio(unit, 0, inout, dp->buf, sects, start/secsize);}/* * ataread & atawrite do the real work; ideread & idewrite just call them. * ataread & atawrite are called by the nvram routines. * ideread & idewrite are called for normal file server I/O. */Offataread(int driveno, void *a, long n){	int skip;	Off rv, i;	uchar *aa = a;//	Ctlr *cp;	Drive *dp;	dp = atadrive[driveno];	if(dp == nil || !dp->online)		return 0;//	cp = dp->ctlr;	if (dp->secsize == 0)		panic("ataread: sector size of zero");	skip = dp->offset % dp->secsize;	for(rv = 0; rv < n; rv += i){		i = ataxfer(dp, Read, dp->offset+rv-skip, n-rv+skip);		if(i == 0)			break;		if(i < 0)			return -1;		i -= skip;		if(i > n - rv)			i = n - rv;		memmove(aa+rv, dp->buf + skip, i);		skip = 0;	}	dp->offset += rv;	return rv;}Offatawrite(int driveno, void *a, long n){	Off rv, i, partial;	uchar *aa = a;//	Ctlr *cp;	Drive *dp;	dp = atadrive[driveno];	if(dp == nil || !dp->online)		return 0;//	cp = dp->ctlr;	/*	 *  if not starting on a sector boundary,	 *  read in the first sector before writing it out.	 */	if (dp->secsize == 0)		panic("atawrite: sector size of zero");	partial = dp->offset % dp->secsize;	if(partial){		if (ataxfer(dp, Read, dp->offset-partial, dp->secsize) < 0)			return -1;		if(partial+n > dp->secsize)			rv = dp->secsize - partial;		else			rv = n;		memmove(dp->buf+partial, aa, rv);		if(ataxfer(dp, Write, dp->offset-partial, dp->secsize) < 0)			return -1;	} else		rv = 0;	/*	 *  write out the full sectors (common case)	 */	partial = (n - rv) % dp->secsize;	n -= partial;	for(; rv < n; rv += i){		i = n - rv;		if(i > Maxxfer)			i = Maxxfer;		memmove(dp->buf, aa+rv, i);		i = ataxfer(dp, Write, dp->offset+rv, i);		if(i == 0)			break;		if(i < 0)			return -1;	}	/*	 *  if not ending on a sector boundary,	 *  read in the last sector before writing it out.	 */	if(partial){		if(ataxfer(dp, Read, dp->offset+rv, dp->secsize) < 0)			return -1;		memmove(dp->buf, aa+rv, partial);		if(ataxfer(dp, Write, dp->offset+rv, dp->secsize) < 0)			return -1;		rv += partial;	}	dp->offset += rv;	return rv;}/* * normal I/O interface *//* result is size of d in blocks of RBUFSIZE bytes */Devsizeidesize(Device *d){	Drive *dp = d->private;	if (dp == nil)		return 0;	/*	 * dividing first is sloppy but reduces the range of intermediate	 * values, avoiding possible overflow.	 */	return (dp->sectors / RBUFSIZE) * dp->secsize;}voidideinit(Device *d){	int driveno;	Drive *dp;	atainit();	if (d->private)		return;	/* call setatapart() first in case we didn't boot off this drive */	driveno = d->wren.ctrl*NCtlrdrv + d->wren.targ;	setatapart(driveno, "disk");	dp = atadriveprobe(driveno);	if (dp) {		print("ideinit(ctrl %d targ %d) driveno %d\n",			d->wren.ctrl, d->wren.targ, dp->driveno);		if (dp->driveno != driveno)			panic("ideinit: dp->dev != driveno");		d->private = dp;		/* print the sizes now, not later */		print(	"  idesize(driveno %d):  %llud %d-byte sectors -> %llud blocks\n",			dp->driveno, (Wideoff)dp->sectors, dp->secsize,			(Wideoff)idesize(d));	}}intideread(Device *d, Devsize b, void *c){	int x, driveno;	Drive *dp;	Ctlr *cp;	if (d == nil || d->private == nil)		return 1;	dp = d->private;	cp = dp->ctlr;	if (cp == nil)		panic("ideread: no controller for drive");	qlock(&cp->idelock);	cp->idelock.name = "ideio";	driveno = dp->driveno;	if (driveno == -1)		panic("ideread: dp->driveno unset");	IDPRINT("ideread(dev %p, %lld, %p, %d): %p\n", d, (Wideoff)b, c,		driveno, dp);	ataseek(driveno, b * RBUFSIZE);	x = ataread(driveno, c, RBUFSIZE) != RBUFSIZE;	qunlock(&cp->idelock);	return x;}intidewrite(Device *d, Devsize b, void *c){	int x, driveno;	Drive *dp;	Ctlr *cp;	if (d == nil || d->private == nil)		return 1;	dp = d->private;	cp = dp->ctlr;	if (cp == nil)		panic("idewrite: no controller for drive");	qlock(&cp->idelock);	cp->idelock.name = "ideio";	driveno = dp->driveno;	if (driveno == -1)		panic("idewrite: dp->driveno unset");	IDPRINT("idewrite(%p, %lld, %p): driveno %d\n", d, (Wideoff)b, c,		driveno);	ataseek(driveno, b * RBUFSIZE);	x = atawrite(driveno, c, RBUFSIZE) != RBUFSIZE;	qunlock(&cp->idelock);	return x;}

⌨️ 快捷键说明

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