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

📄 devflash.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	ulong x;	r = flash.r;	for(e = &flash.r[flash.nr]; r < e; r++)		if(addr >= r->addr && addr < r->end){			x = addr - r->addr;			x /= r->size;			return r->addr + (x+1)*r->size;		}				return (ulong)-1;}static longflashctlwrite(FPart *fp, char *p, long n){	Cmdbuf *cmd;	ulong off;	if(fp == nil)		panic("flashctlwrite");	cmd = parsecmd(p, n);	wlock(&flash);	if(waserror()){		wunlock(&flash);		nexterror();	}	if(strcmp(cmd->f[0], "erase") == 0){		switch(cmd->nf){		case 2:			/* erase a single block in the partition */			off = atoi(cmd->f[1]);			off += fp->start;			if(off >= fp->end)				error("region not in partition");			if(off != blockstart(off))				error("erase must be a block boundary");			bootprotect(off);			(*flash.alg->erase)(off);			break;		case 1:			/* erase the whole partition */			bootprotect(fp->start);			for(off = fp->start; off < fp->end; off = blockend(off))				(*flash.alg->erase)(off);			break;		default:			error(Ebadarg);		}	} else if(strcmp(cmd->f[0], "add") == 0){		if(cmd->nf != 4)			error(Ebadarg);		addpart(fp, cmd->f[1], strtoul(cmd->f[2], nil, 0), strtoul(cmd->f[3], nil, 0));	} else if(strcmp(cmd->f[0], "remove") == 0){		rempart(fp);	} else if(strcmp(cmd->f[0], "protectboot") == 0){		if(cmd->nf == 0 || strcmp(cmd->f[1], "off") != 0)			flash.bootprotect = 1;		else			flash.bootprotect = 0;	} else		error(Ebadarg);	poperror();	wunlock(&flash);	free(cmd);	return n;}static longflashdatawrite(FPart *fp, uchar *p, long n, long off){	uchar *end;	int m;	int on;	long ooff;	uchar *buf;	if(fp == nil)		panic("flashctlwrite");	buf = nil;	wlock(&flash);	if(waserror()){		wunlock(&flash);		if(buf != nil)			free(buf);		nexterror();	}	if(fp->name == nil)		error("partition vanished");	if(!iseve())		error(Eperm);	/* can't cross partition boundaries */	off += fp->start;	if(off >= fp->end || off+n > fp->end || n <= 0)		error(Ebadarg);	/* make sure we're not writing the boot sector */	bootprotect(off);	on = n;	/*	 *  get the data into kernel memory to avoid faults during writing.	 *  if write is not on a quad boundary or not a multiple of 4 bytes,	 *  extend with data already in flash.	 */	buf = smalloc(n+8);	m = off & 3;	if(m){		*(ulong*)buf = flash.p[(off)>>2];		n += m;		off -= m;	}	if(n & 3){		n -= n & 3;		*(ulong*)(&buf[n]) = flash.p[(off+n)>>2];		n += 4;	}	memmove(&buf[m], p, on);	/* (*flash.alg->write) can't cross blocks */	ooff = off;	p = buf;	for(end = p + n; p < end; p += m){		m = blockend(off) - off;		if(m > end - p)			m = end - p;		if(m > Maxwchunk)			m = Maxwchunk;		(*flash.alg->write)(p, m, off);		off += m;	}	/* make sure write succeeded */	if(memcmp(buf, &flash.p[ooff>>2], n) != 0)		error("written bytes don't match");	wunlock(&flash);	free(buf);	poperror();	return on;}static long	 flashwrite(Chan* c, void* a, long n, vlong off){	int t;	if(c->qid.type == QTDIR)		error(Eperm);	if(!iseve())		error(Eperm);	t = FTYPE(c->qid.path);	switch(t){	default:		panic("flashwrite");	case Qfctl:		n = flashctlwrite(FPART(c->qid.path), a, n);		break;	case Qfdata:		n = flashdatawrite(FPART(c->qid.path), a, n, off);		break;	}	return n;}Dev flashdevtab = {	'F',	"flash",	devreset,	flashinit,	devshutdown,	flashattach,	flashwalk,	flashstat,	flashopen,	devcreate,	flashclose,	flashread,	devbread,	flashwrite,	devbwrite,	devremove,	devwstat,};enum{	/* status register */	ISEs_lockerr=		1<<1,	ISEs_powererr=		1<<3,	ISEs_progerr=		1<<4,	ISEs_eraseerr=		1<<5,	ISEs_ready=		1<<7,	ISEs_err= (ISEs_lockerr|ISEs_powererr|ISEs_progerr|ISEs_eraseerr),	/* extended status register */	ISExs_bufavail=		1<<7,};/* intel/sharp extended command set */static voidise_reset(void){	flash.p[0x55] = mirror(0xff);	/* reset */}static voidise_id(void){	ise_reset();	flash.p[0x555] = mirror(0x90);	/* uncover vendor info */	flash.manid = flash.p[00];	flash.devid = flash.p[01];	ise_reset();}static voidise_clearerror(void){	flash.p[0x100] = mirror(0x50);}static voidise_error(int bank, ulong status){	char err[64];	if(status & (ISEs_lockerr)){		sprint(err, "flash%d: block locked %lux", bank, status);		error(err);	}	if(status & (ISEs_powererr)){		sprint(err, "flash%d: low prog voltage %lux", bank, status);		error(err);	}	if(status & (ISEs_progerr|ISEs_eraseerr)){		sprint(err, "flash%d: i/o error %lux", bank, status);		error(err);	}}static voidise_erase(ulong addr){	ulong start;	ulong x;	addr >>= 2;	/* convert to ulong offset */	flashprogpower(1);	flash.p[addr] = mirror(0x20);	flash.p[addr] = mirror(0xd0);	start = m->ticks;	do {		x = flash.p[addr];		if((x & mirror(ISEs_ready)) == mirror(ISEs_ready))			break;	} while(TK2MS(m->ticks-start) < 1500);	flashprogpower(0);	ise_clearerror();	ise_error(0, x);	ise_error(1, x>>16);	ise_reset();}/* *  the flash spec claimes writing goes faster if we use *  the write buffer.  We fill the write buffer and then *  issue the write request.  After the write request, *  subsequent reads will yield the status register. * *  returns the status, even on timeouts. * *  NOTE: I tried starting back to back buffered writes *	without reading the status in between, as the *	flowchart in the intel data sheet suggests. *	However, it always responded with an illegal *	command sequence, so I must be missing something. *	If someone learns better, please email me, though *	I doubt it will be much faster. -  presotto@bell-labs.com */static intise_wbwrite(ulong *p, int n, ulong off, ulong baddr, ulong *status){	ulong x, start;	int i;	int s;	/* put flash into write buffer mode */	start = m->ticks;	for(;;) {		s = splhi();		/* request write buffer mode */		flash.p[baddr] = mirror(0xe8);		/* look at extended status reg for status */		if((flash.p[baddr] & mirror(1<<7)) == mirror(1<<7))			break;		splx(s);		/* didn't work, keep trying for 2 secs */		if(TK2MS(m->ticks-start) > 2000){			/* set up to read status */			flash.p[baddr] = mirror(0x70);			*status = flash.p[baddr];			pprint("write buffered cmd timed out\n");			return -1;		}	}	/* fill write buffer */	flash.p[baddr] = mirror(n-1);	for(i = 0; i < n; i++)		flash.p[off+i] = *p++;	/* program from buffer */	flash.p[baddr] = mirror(0xd0);	splx(s);	/* wait till the programming is done */	start = m->ticks;	for(;;) {		x = *status = flash.p[baddr];	/* read status register */		if((x & mirror(ISEs_ready)) == mirror(ISEs_ready))			break;		if(TK2MS(m->ticks-start) > 2000){			pprint("read status timed out\n");			return -1;		}	}	if(x & mirror(ISEs_err))		return -1;	return n;}static voidise_write(void *a, long n, ulong off){	ulong *p, *end;	int i, wbsize;	ulong x, baddr;	/* everything in terms of ulongs */	wbsize = flash.wbsize>>2;	baddr = blockstart(off);	off >>= 2;	n >>= 2;	p = a;	baddr >>= 2;	/* first see if write will succeed */	for(i = 0; i < n; i++)		if((p[i] & flash.p[off+i]) != p[i])			error("flash needs erase");	if(waserror()){		ise_reset();		flashprogpower(0);		nexterror();	}	flashprogpower(1);	/*	 *  use the first write to reach 	 *  a write buffer boundary.  the intel maunal	 *  says writes startng at wb boundaries	 *  maximize speed.	 */	i = wbsize - (off & (wbsize-1));	for(end = p + n; p < end;){		if(i > end - p)			i = end - p;		if(ise_wbwrite(p, i, off, baddr, &x) < 0)			break;		off += i;		p += i;		i = wbsize;	}	ise_clearerror();	ise_error(0, x);	ise_error(1, x>>16);	ise_reset();	flashprogpower(0);	poperror();}/* amd/fujitsu standard command set *	I don't have an amd chipset to work with *	so I'm loathe to write this yet.  If someone *	else does, please send it to me and I'll *	incorporate it -- presotto@bell-labs.com */static voidafs_reset(void){	flash.p[0x55] = mirror(0xf0);	/* reset */}static voidafs_id(void){	afs_reset();	flash.p[0x55] = mirror(0xf0);	/* reset */	flash.p[0x555] = mirror(0xaa);	/* query vendor block */	flash.p[0x2aa] = mirror(0x55);	flash.p[0x555] = mirror(0x90);	flash.manid = flash.p[00];	afs_reset();	flash.p[0x555] = mirror(0xaa);	/* query vendor block */	flash.p[0x2aa] = mirror(0x55);	flash.p[0x555] = mirror(0x90);	flash.devid = flash.p[01];	afs_reset();}static voidafs_erase(ulong){	error("amd/fujistsu erase not implemented");}static voidafs_write(void*, long, ulong){	error("amd/fujistsu write not implemented");}

⌨️ 快捷键说明

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