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

📄 devflash.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"../port/error.h"/* *  on the bitsy, all 32 bit accesses to flash are mapped to two 16 bit *  accesses, one to the low half of the chip and the other to the high *  half.  Therefore for all command accesses, ushort indices in the *  manuals turn into ulong indices in our code.  Also, by copying all *  16 bit commands to both halves of a 32 bit command, we erase 2 *  sectors for each request erase request. */#define mirror(x) (((x)<<16)|(x))/* this defines a contiguous set of erase blocks of one size */typedef struct FlashRegion FlashRegion;struct FlashRegion{	ulong	addr;		/* start of region */	ulong	end;		/* end of region + 1 */	ulong	n;		/* number of blocks */	ulong	size;		/* size of each block */};/* this defines a particular access algorithm */typedef struct FlashAlg FlashAlg;struct FlashAlg{	int	id;	char	*name;	void	(*identify)(void);	/* identify device */	void	(*erase)(ulong);	/* erase a region */	void	(*write)(void*, long, ulong);	/* write a region */};static void	ise_id(void);static void	ise_erase(ulong);static void	ise_write(void*, long, ulong);static void	afs_id(void);static void	afs_erase(ulong);static void	afs_write(void*, long, ulong);static ulong	blockstart(ulong);static ulong	blockend(ulong);FlashAlg falg[] ={	{ 1,	"Intel/Sharp Extended",	ise_id, ise_erase, ise_write	},	{ 2,	"AMD/Fujitsu Standard",	afs_id, afs_erase, afs_write	},};struct{	RWlock;	ulong		*p;	ushort		algid;		/* access algorithm */	FlashAlg	*alg;	ushort		manid;		/* manufacturer id */	ushort		devid;		/* device id */	ulong		size;		/* size in bytes */	int		wbsize;		/* size of write buffer */ 	ulong		nr;		/* number of regions */	uchar		bootprotect;	FlashRegion	r[32];} flash;enum{	Maxwchunk=	1024,	/* maximum chunk written by one call to falg->write */};/* *  common flash interface */static ucharcfigetc(int off){	uchar rv;	flash.p[0x55] = mirror(0x98);	rv = flash.p[off];	flash.p[0x55] = mirror(0xFF);	return rv;}static ushortcfigets(int off){	return (cfigetc(off+1)<<8)|cfigetc(off);}static ulongcfigetl(int off){	return (cfigetc(off+3)<<24)|(cfigetc(off+2)<<16)|		(cfigetc(off+1)<<8)|cfigetc(off);}static voidcfiquery(void){	uchar q, r, y;	ulong x, addr;	q = cfigetc(0x10);	r = cfigetc(0x11);	y = cfigetc(0x12);	if(q != 'Q' || r != 'R' || y != 'Y'){		print("cfi query failed: %ux %ux %ux\n", q, r, y);		return;	}	flash.algid = cfigetc(0x13);	flash.size = 1<<(cfigetc(0x27)+1);	flash.wbsize = 1<<(cfigetc(0x2a)+1);	flash.nr = cfigetc(0x2c);	if(flash.nr > nelem(flash.r)){		print("cfi reports > %d regions\n", nelem(flash.r));		flash.nr = nelem(flash.r);	}	addr = 0;	for(q = 0; q < flash.nr; q++){		x = cfigetl(q+0x2d);		flash.r[q].size = 2*256*(x>>16);		flash.r[q].n = (x&0xffff)+1;		flash.r[q].addr = addr;		addr += flash.r[q].size*flash.r[q].n;		flash.r[q].end = addr;	}}/* *  flash device interface */enum{	Qtopdir,	Q2nddir,	Qfctl,	Qfdata,	Maxpart= 8,};typedef struct FPart FPart;struct FPart{	char	*name;	char	*ctlname;	ulong	start;	ulong	end;};static FPart	part[Maxpart];#define FQID(p,q)	((p)<<8|(q))#define FTYPE(q)	((q) & 0xff)#define FPART(q)	(&part[(q) >>8])static intgen(Chan *c, char*, Dirtab*, int, int i, Dir *dp){	Qid q;	FPart *fp;	q.vers = 0;	/* top level directory contains the name of the network */	if(c->qid.path == Qtopdir){		switch(i){		case DEVDOTDOT:			q.path = Qtopdir;			q.type = QTDIR;			devdir(c, q, "#F", 0, eve, DMDIR|0555, dp);			break;		case 0:			q.path = Q2nddir;			q.type = QTDIR;			devdir(c, q, "flash", 0, eve, DMDIR|0555, dp);			break;		default:			return -1;		}		return 1;	}	/* second level contains all partitions and their control files */	switch(i) {	case DEVDOTDOT:		q.path = Qtopdir;		q.type = QTDIR;		devdir(c, q, "#F", 0, eve, DMDIR|0555, dp);		break;	default:		if(i >= 2*Maxpart)			return -1;		fp = &part[i>>1];		if(fp->name == nil)			return 0;		if(i & 1){			q.path = FQID(i>>1, Qfdata);			q.type = QTFILE;			devdir(c, q, fp->name, fp->end-fp->start, eve, 0660, dp);		} else {			q.path = FQID(i>>1, Qfctl);			q.type = QTFILE;			devdir(c, q, fp->ctlname, 0, eve, 0660, dp);		}		break;	}	return 1;}static FPart*findpart(char *name){	int i;	for(i = 0; i < Maxpart; i++)		if(part[i].name != nil && strcmp(name, part[i].name) == 0)			break;	if(i >= Maxpart)		return nil;	return &part[i];}static voidaddpart(FPart *fp, char *name, ulong start, ulong end){	int i;	char ctlname[64];	if(fp == nil){		if(start >= flash.size || end > flash.size)			error(Ebadarg);	} else {		start += fp->start;		end += fp->start;		if(start >= fp->end || end > fp->end)			error(Ebadarg);	}	if(blockstart(start) != start)		error("must start on erase boundary");	if(blockstart(end) != end && end != flash.size)		error("must end on erase boundary");	fp = findpart(name);	if(fp != nil)		error(Eexist);	for(i = 0; i < Maxpart; i++)		if(part[i].name == nil)			break;	if(i == Maxpart)		error("no more partitions");	fp = &part[i];	kstrdup(&fp->name, name);	snprint(ctlname, sizeof ctlname, "%sctl", name);	kstrdup(&fp->ctlname, ctlname);	fp->start = start;	fp->end = end;}static voidrempart(FPart *fp){	char *p, *cp;	p = fp->name;	fp->name = nil;	cp = fp->ctlname;	fp->ctlname = nil;	free(p);	free(cp);}voidflashinit(void){	int i;	flash.p = (ulong*)FLASHZERO;	cfiquery();	for(i = 0; i < nelem(falg); i++)		if(flash.algid == falg[i].id){			flash.alg = &falg[i];			(*flash.alg->identify)();			break;		}	flash.bootprotect = 1;	addpart(nil, "flash", 0, flash.size);}static Chan*flashattach(char* spec){	return devattach('F', spec);}static Walkqid*flashwalk(Chan *c, Chan *nc, char **name, int nname){	return devwalk(c, nc, name, nname, nil, 0, gen);}static int	 flashstat(Chan *c, uchar *db, int n){	return devstat(c, db, n, nil, 0, gen);}static Chan*flashopen(Chan* c, int omode){	omode = openmode(omode);	if(strcmp(up->user, eve)!=0)		error(Eperm);	return devopen(c, omode, nil, 0, gen);}static void	 flashclose(Chan*){}static longflashctlread(FPart *fp, void* a, long n, vlong off){	char *buf, *p, *e;	int i;	ulong addr, end;	buf = smalloc(1024);	e = buf + 1024;	p = seprint(buf, e, "0x%-9lux 0x%-9x 0x%-9ux 0x%-9ux\n", fp->end-fp->start,		flash.wbsize, flash.manid, flash.devid);	addr = fp->start;	for(i = 0; i < flash.nr && addr < fp->end; i++)		if(flash.r[i].addr <= addr && flash.r[i].end > addr){			if(fp->end <= flash.r[i].end)				end = fp->end;			else				end = flash.r[i].end;			p = seprint(p, e, "0x%-9lux 0x%-9lux 0x%-9lux\n", addr,				(end-addr)/flash.r[i].size, flash.r[i].size);			addr = end;		}	n = readstr(off, a, n, buf);	free(buf);	return n;}static longflashdataread(FPart *fp, void* a, long n, vlong off){	rlock(&flash);	if(waserror()){		runlock(&flash);		nexterror();	}	if(fp->name == nil)		error("partition vanished");	if(!iseve())		error(Eperm);	off += fp->start;	if(off >= fp->end)		n = 0;	if(off+n >= fp->end)		n = fp->end - off;	if(n > 0)		memmove(a, ((uchar*)FLASHZERO)+off, n);	runlock(&flash);	poperror();	return n;}static long	 flashread(Chan* c, void* a, long n, vlong off){	int t;	if(c->qid.type == QTDIR)		return devdirread(c, a, n, nil, 0, gen);	t = FTYPE(c->qid.path);	switch(t){	default:		error(Eperm);	case Qfctl:		n = flashctlread(FPART(c->qid.path), a, n, off);		break;	case Qfdata:		n = flashdataread(FPART(c->qid.path), a, n, off);		break;	}	return n;}static voidbootprotect(ulong addr){	FlashRegion *r;	if(flash.bootprotect == 0)		return;	if(flash.nr == 0)		error("writing over boot loader disallowed");	r = flash.r;	if(addr >= r->addr && addr < r->addr + r->size)		error("writing over boot loader disallowed");}static ulongblockstart(ulong addr){	FlashRegion *r, *e;	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*r->size;		}				return (ulong)-1;}static ulongblockend(ulong addr){	FlashRegion *r, *e;

⌨️ 快捷键说明

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