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

📄 devflash.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h"enum {	Nflash = 2,	Maxwchunk=	1024,	/* maximum chunk written by one call to falg->write */};/* *  Flashes are either 8 or 16 bits wide.  On some installations (e.g., the *  bitsy, they are interleaved: address 0 is in the first chip, address 2 *  on the second, address 4 on the first, etc. *  We define Funit as the unit that matches the width of a single flash chip, *  so Funit is either `uchar' or `ushort' (I haven't seen 32-bit wide flashes), *  and we define Fword as the unit that matches a set of interleaved Funits. *  We access interleaved flashes simultaneously, by doing single reads and *  writes to both.  The macro `mirror' takes a command and replicates it for *  this purpose. *  The Blast board has a non-interleaved 16-bit wide flash.  When doing *  writes to it, we must swap bytes. */typedef struct FlashAlg FlashAlg;typedef struct Flash Flash;typedef struct FlashRegion FlashRegion;#ifdef WIDTH8	typedef		uchar		Funit;		/* Width of the flash (uchar or ushort) */#	define		toendian(x)	(x)			/* Little or big endianness */#	define		fromendian(x)	(x)#	define		reg(x)		((x)<<1)#	ifdef INTERLEAVED#		define	mirror(x)		((x)<<8|(x))	/* Double query for interleaved flashes */		typedef	ushort		Fword;		/* Width after interleaving */#		define	Wshift		1#	else#		define 	mirror(x)		(x)		typedef	uchar		Fword;#		define	Wshift		0#	endif#else	typedef		ushort		Funit;#	define		toendian(x)	((x)<<8)#	define		fromendian(x)	((x)>>8)#	define		reg(x)		(x)#	ifdef INTERLEAVED#		define	mirror(x)		(toendian(x)<<16|toendian(x))		typedef	ulong		Fword;#		define	Wshift		2#	else#		define mirror(x)		toendian(x)		typedef	ushort		Fword;#		define	Wshift		1#	endif#endif/* this defines a contiguous set of erase blocks of one size */struct FlashRegion{	ulong	addr;	/* start of region */	ulong	end;		/* end of region + 1 */	ulong	n;		/* number of blocks */	ulong	size;		/* size of each block */};struct Flash{	ISAConf;					/* contains size */	RWlock;	Fword		*p;	ushort		algid;		/* access algorithm */	FlashAlg		*alg;	ushort		manid;		/* manufacturer id */	ushort		devid;		/* device id */	int			wbsize;		/* size of write buffer */ 	ulong		nr;			/* number of regions */	uchar		bootprotect;	ulong		offset;		/* beginning offset of this flash */	FlashRegion	r[32];};/* this defines a particular access algorithm */struct FlashAlg{	int	id;	char	*name;	void	(*identify)(Flash*);	/* identify device */	void	(*erase)(Flash*, ulong);	/* erase a region */	void	(*write)(Flash*, void*, long, ulong);	/* write a region */};static void	ise_id(Flash*);static void	ise_erase(Flash*, ulong);static void	ise_write(Flash*, void*, long, ulong);static void	afs_id(Flash*);static void	afs_erase(Flash*, ulong);static void	afs_write(Flash*, void*, long, ulong);static ulong	blockstart(Flash*, ulong);static ulong	blockend(Flash*, ulong);FlashAlg falg[] ={	{ 1,	"Intel/Sharp Extended",	ise_id, ise_erase, ise_write	},	{ 2,	"AMD/Fujitsu Standard",	afs_id, afs_erase, afs_write	},};Flash flashes[Nflash];/* *  common flash interface */static ucharcfigetc(Flash *flash, int off){	uchar rv;	flash->p[reg(0x55)] = mirror(0x98);	rv = fromendian(flash->p[reg(off)]);	flash->p[reg(0x55)] = mirror(0xFF);	return rv;}static ushortcfigets(Flash *flash, int off){	return (cfigetc(flash, off+1)<<8)|cfigetc(flash, off);}static ulongcfigetl(Flash *flash, int off){	return (cfigetc(flash, off+3)<<24)|(cfigetc(flash, off+2)<<16)|		(cfigetc(flash, off+1)<<8)|cfigetc(flash, off);}static voidcfiquery(Flash *flash){	uchar q, r, y;	ulong x, addr;	q = cfigetc(flash, 0x10);	r = cfigetc(flash, 0x11);	y = cfigetc(flash, 0x12);	if(q != 'Q' || r != 'R' || y != 'Y'){		print("cfi query failed: %ux %ux %ux\n", q, r, y);		return;	}	flash->algid = cfigetc(flash, 0x13);	flash->size = (sizeof(Fword)/sizeof(Funit)) * (1<<(cfigetc(flash, 0x27)));	flash->wbsize = (sizeof(Fword)/sizeof(Funit)) * (1<<(cfigetc(flash, 0x2a)));	flash->nr = cfigetc(flash, 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(flash, q+0x2d);		flash->r[q].size = (sizeof(Fword)/sizeof(Funit)) * 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{	Flash	*flash;	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 Flash *findflash(ulong addr){	Flash *flash;	for (flash = flashes; flash < flashes + Nflash; flash++)		if(addr >= flash->offset && addr < flash->offset + flash->size)			return flash;	return nil;}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];	Flash *flash;	if (start > end)		error(Ebadarg);	if(fp == nil){		flash = findflash(start);		if (flash == nil || end > flash->offset + flash->size)			error(Ebadarg);		start -= flash->offset;		end -= flash->offset;	} else {		start += fp->start;		end += fp->start;		if(start >= fp->end || end > fp->end){			error(Ebadarg);		}		flash = fp->flash;	}	if(blockstart(flash, start) != start)		error("must start on erase boundary");	if(blockstart(flash, 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->flash = flash;	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, ctlrno;	char *fname;	ulong offset;	Flash *flash;	offset = 0;	for (ctlrno = 0; ctlrno < Nflash; ctlrno++){		flash = flashes + ctlrno;		if(isaconfig("flash", ctlrno, flash) == 0)			continue;		flash->p = (Fword*)flash->mem;		cfiquery(flash);		for(i = 0; i < nelem(falg); i++)			if(flash->algid == falg[i].id){				flash->alg = &falg[i];				(*flash->alg->identify)(flash);				break;			}		flash->bootprotect = 1;		flash->offset = offset;		fname = malloc(8);		sprint(fname, "flash%d", ctlrno);		addpart(nil, fname, offset, offset + flash->size);		offset += 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;	Flash *flash;	flash = fp->flash;	buf = smalloc(1024);	e = buf + 1024;	p = seprint(buf, e, "0x%-9lux 0x%-9lux 0x%-9lux 0x%-9x 0x%-9ux 0x%-9ux\n",		flash->offset, fp->start, 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){	Flash *flash;	flash = fp->flash;	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*)flash->mem)+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){

⌨️ 快捷键说明

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