plan 9 kernel history: overview | file list | diff list

2000/1207/bitsy/devflash.c (diff list | history)

2000/1117/sys/src/9/bitsy/devflash.c:46,512000/1207/sys/src/9/bitsy/devflash.c:46,54 (short | long | prev | next)
2000/1117    
static void	afs_erase(ulong); 
static void	afs_write(void*, long, ulong); 
 
2000/1207    
static ulong	blockstart(ulong); 
static ulong	blockend(ulong); 
 
2000/1117    
FlashAlg falg[] = 
2000/1107    
{ 
2000/1117    
	{ 1,	"Intel/Sharp Extended",	ise_id, ise_erase, ise_write	}, 
2000/1117/sys/src/9/bitsy/devflash.c:134,1482000/1207/sys/src/9/bitsy/devflash.c:137,265
2000/1111    
 
enum 
{ 
2000/1117    
	Qfctl=1, 
	Qfdata, 
2000/1207    
	Qtopdir, 
	Q2nddir, 
	Qfctl, 
	Qfpart, 
 
	Maxpart= 8, 
2000/1111    
}; 
 
Dirtab flashdir[]={ 
2000/1117    
	"flashctl",		{ Qfctl, 0 },	0,	0664, 
	"flashdata",		{ Qfdata, 0 },	0,	0660, 
2000/1207    
 
typedef struct FPart FPart; 
struct FPart 
{ 
	char	name[NAMELEN]; 
	ulong	start; 
	ulong	end; 
2000/1111    
}; 
2000/1207    
static FPart	part[Maxpart]; 
2000/1111    
 
2000/1207    
#define FQID(p,q)	((p)<<8|(q)) 
#define FTYPE(q)	((q) & 0xff) 
#define FPART(q)	(&part[(q) >>8]) 
 
static int 
gen(Chan *c, Dirtab*, int, int i, Dir *dp) 
{ 
	Qid q; 
	char buf[32]; 
	FPart *fp; 
 
	q.vers = 0; 
 
	/* top level directory contains the name of the network */ 
	if(c->qid.path == CHDIR){ 
		switch(i){ 
		case DEVDOTDOT: 
			q.path = CHDIR; 
			devdir(c, q, ".", 0, eve, CHDIR|0555, dp); 
			break; 
		case 0: 
			q.path = CHDIR | Q2nddir; 
			strcpy(buf, "flash"); 
			devdir(c, q, buf, 0, eve, CHDIR|0555, dp); 
			break; 
		default: 
			return -1; 
		} 
		return 1; 
	} 
 
	/* second level contains ctl plus all partitions */ 
	switch(i) { 
	case DEVDOTDOT: 
		q.path = CHDIR; 
		devdir(c, q, "#F", 0, eve, CHDIR|0555, dp); 
		break; 
	case 0: 
		q.path = Qfctl; 
		devdir(c, q, "ctl", 0, eve, 0666, dp); 
		break; 
	default: 
		i -= 1; 
		if(i >= Maxpart) 
			return -1; 
		fp = &part[i]; 
		if(fp->name[0] == 0) 
			return 0; 
		q.path = FQID(i, Qfpart); 
		devdir(c, q, fp->name, fp->end-fp->start, eve, 0660, dp); 
		break; 
	} 
	return 1; 
} 
 
static FPart* 
findpart(char *name) 
{ 
	int i; 
 
	for(i = 0; i < Maxpart; i++) 
		if(strcmp(name, part[i].name) == 0) 
			break; 
	if(i >= Maxpart) 
		return nil; 
	return &part[i]; 
} 
 
static void 
addpart(char *name, ulong start, ulong end) 
{ 
	int i; 
	FPart *fp; 
 
	if(start >= flash.size || end > flash.size) 
		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[0] == 0) 
			break; 
	if(i == Maxpart) 
		error("no more partitions"); 
	fp = &part[i]; 
	strncpy(fp->name, name, sizeof(fp->name)-1); 
	fp->start = start; 
	fp->end = end; 
} 
 
static void 
rempart(char *name) 
{ 
	FPart *fp; 
 
	/* can't remove the total partition */ 
	fp = findpart(name); 
	if(fp != nil) 
		fp->name[0] = 0; 
} 
 
2000/1111    
void 
flashinit(void) 
{ 
2000/1117/sys/src/9/bitsy/devflash.c:157,1622000/1207/sys/src/9/bitsy/devflash.c:274,281
2000/1117    
			break; 
		} 
	flash.bootprotect = 1; 
2000/1207    
 
	addpart("whole", 0, flash.size); 
2000/1111    
} 
 
static Chan* 
2000/1117/sys/src/9/bitsy/devflash.c:168,1802000/1207/sys/src/9/bitsy/devflash.c:287,299
2000/1111    
static int	  
flashwalk(Chan* c, char* name) 
{ 
	return devwalk(c, name, flashdir, nelem(flashdir), devgen); 
2000/1207    
	return devwalk(c, name, nil, 0, gen); 
2000/1111    
} 
 
static void	  
flashstat(Chan* c, char* dp) 
{ 
	devstat(c, dp, flashdir, nelem(flashdir), devgen); 
2000/1207    
	devstat(c, dp, nil, 0, gen); 
2000/1111    
} 
 
static Chan* 
2000/1117/sys/src/9/bitsy/devflash.c:183,1892000/1207/sys/src/9/bitsy/devflash.c:302,308
2000/1111    
	omode = openmode(omode); 
	if(strcmp(up->user, eve)!=0) 
		error(Eperm); 
	return devopen(c, omode, flashdir, nelem(flashdir), devgen); 
2000/1207    
	return devopen(c, omode, nil, 0, gen); 
2000/1111    
} 
 
static void	  
2000/1117/sys/src/9/bitsy/devflash.c:196,2052000/1207/sys/src/9/bitsy/devflash.c:315,325
2000/1111    
{ 
2000/1117    
	char *buf, *p, *e; 
	int i; 
2000/1207    
	FPart *fp; 
2000/1117    
 
	if(c->qid.path&CHDIR) 
		return devdirread(c, a, n, flashdir, nelem(flashdir), devgen); 
	switch(c->qid.path){ 
2000/1207    
		return devdirread(c, a, n, nil, 0, gen); 
	switch(FTYPE(c->qid.path)){ 
2000/1117    
	default: 
		error(Eperm); 
	case Qfctl: 
2000/1117/sys/src/9/bitsy/devflash.c:213,2312000/1207/sys/src/9/bitsy/devflash.c:333,356
2000/1117    
		n = readstr(off, a, n, buf); 
		free(buf); 
		break; 
	case Qfdata: 
		if(!iseve()) 
			error(Eperm); 
		if(off >= flash.size) 
			return 0; 
		if(off + n > flash.size) 
			n = flash.size - off; 
2000/1207    
	case Qfpart: 
		fp = FPART(c->qid.path); 
2000/1117    
		rlock(&flash); 
		if(waserror()){ 
			runlock(&flash); 
			nexterror(); 
		} 
		memmove(a, ((uchar*)FLASHZERO)+off, n); 
2000/1207    
		if(fp->name[0] == 0) 
			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); 
2000/1117    
		runlock(&flash); 
		poperror(); 
		break; 
2000/1117/sys/src/9/bitsy/devflash.c:247,2532000/1207/sys/src/9/bitsy/devflash.c:372,378
2000/1117    
		error("writing over boot loader disallowed"); 
} 
 
ulong 
2000/1207    
static ulong 
2000/1117    
blockstart(ulong addr) 
{ 
	FlashRegion *r, *e; 
2000/1117/sys/src/9/bitsy/devflash.c:264,2702000/1207/sys/src/9/bitsy/devflash.c:389,395
2000/1117    
	return (ulong)-1; 
} 
 
ulong 
2000/1207    
static ulong 
2000/1117    
blockend(ulong addr) 
{ 
	FlashRegion *r, *e; 
2000/1117/sys/src/9/bitsy/devflash.c:285,2912000/1207/sys/src/9/bitsy/devflash.c:410,417
2000/1117    
flashctlwrite(char *p, long n) 
{ 
	Cmdbuf *cmd; 
	ulong addr; 
2000/1207    
	ulong off; 
	FPart *fp; 
2000/1117    
 
	cmd = parsecmd(p, n); 
	wlock(&flash); 
2000/1117/sys/src/9/bitsy/devflash.c:294,3062000/1207/sys/src/9/bitsy/devflash.c:420,460
2000/1117    
		nexterror(); 
	} 
	if(strcmp(cmd->f[0], "erase") == 0){ 
2000/1207    
		if(cmd->nf < 2) 
			error(Ebadarg); 
		fp = findpart(cmd->f[1]); 
		if(fp == nil) 
			error("no such partition"); 
 
		switch(cmd->nf){ 
		case 3: 
			/* erase a single block */ 
			off = atoi(cmd->f[2]); 
			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 2: 
			/* 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(cmd->f[1], strtoul(cmd->f[2], nil, 0), strtoul(cmd->f[3], nil, 0)); 
	} else if(strcmp(cmd->f[0], "remove") == 0){ 
2000/1117    
		if(cmd->nf != 2) 
			error(Ebadarg); 
		addr = atoi(cmd->f[1]); 
		if(addr != blockstart(addr)) 
			error("erase must be a block boundary"); 
		bootprotect(addr); 
		(*flash.alg->erase)(addr); 
2000/1207    
		rempart(cmd->f[1]); 
2000/1117    
	} else if(strcmp(cmd->f[0], "protectboot") == 0){ 
		if(cmd->nf == 0 || strcmp(cmd->f[1], "off") != 0) 
			flash.bootprotect = 1; 
2000/1117/sys/src/9/bitsy/devflash.c:316,3322000/1207/sys/src/9/bitsy/devflash.c:470,484
2000/1117    
} 
 
static long 
flashdatawrite(uchar *p, long n, long off) 
2000/1207    
flashdatawrite(Chan *c, uchar *p, long n, long off) 
2000/1117    
{ 
	uchar *end; 
	int m; 
	long ooff = off; 
2000/1207    
	long ooff; 
2000/1117    
	uchar *op = p; 
2000/1207    
	FPart *fp; 
2000/1117    
 
	if((off & 0x3) || (n & 0x3)) 
		error("only quad writes"); 
	if(off >= flash.size || off+n > flash.size || n <= 0) 
		error(Ebadarg); 
2000/1207    
	fp = FPART(c->qid.path); 
2000/1117    
 
	wlock(&flash); 
	if(waserror()){ 
2000/1117/sys/src/9/bitsy/devflash.c:334,3432000/1207/sys/src/9/bitsy/devflash.c:486,507
2000/1117    
		nexterror(); 
	} 
 
2000/1207    
	if(fp->name[0] == 0) 
		error("partition vanished"); 
	if(!iseve()) 
		error(Eperm); 
 
	if((off & 0x3) || (n & 0x3)) 
		error("only quad writes"); 
	off += fp->start; 
	if(off >= fp->end || off+n > fp->end || n <= 0) 
		error(Ebadarg); 
 
2000/1117    
	/* make sure we're not writing the boot sector */ 
	bootprotect(off); 
 
	/* (*flash.alg->write) can't cross blocks */ 
2000/1207    
	ooff = off; 
2000/1117    
	for(end = p + n; p < end; p += m){ 
		m = blockend(off) - off; 
		if(m > end - p) 
2000/1117/sys/src/9/bitsy/devflash.c:365,3772000/1207/sys/src/9/bitsy/devflash.c:529,541
2000/1117    
	if(!iseve()) 
		error(Eperm); 
 
	switch(c->qid.path){ 
2000/1207    
	switch(FTYPE(c->qid.path)){ 
2000/1117    
	default: 
		panic("flashwrite"); 
	case Qfctl: 
		return flashctlwrite(a, n); 
	case Qfdata: 
		return flashdatawrite(a, n, off); 
2000/1207    
	case Qfpart: 
		return flashdatawrite(c, a, n, off); 
2000/1117    
	} 
2000/1111    
	return n; 
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)