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

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

2000/1211/sys/src/9/bitsy/devflash.c:68,742000/1213/sys/src/9/bitsy/devflash.c:68,73 (short | long | prev | next)
2000/1117    
	ulong		nr;		/* number of regions */ 
	uchar		bootprotect; 
	FlashRegion	r[32]; 
	ulong		*wb;		/* staging area for write buffer */ 
} flash; 
2000/1111    
 
2000/1209    
enum 
2000/1211/sys/src/9/bitsy/devflash.c:133,1392000/1213/sys/src/9/bitsy/devflash.c:132,137
2000/1117    
		addr += flash.r[q].size*flash.r[q].n; 
		flash.r[q].end = addr; 
	} 
2000/1209    
	flash.wb = malloc(flash.wbsize>1024 ? flash.wbsize : 1024); 
2000/1117    
} 
 
2000/1111    
/* 
2000/1211/sys/src/9/bitsy/devflash.c:145,1512000/1213/sys/src/9/bitsy/devflash.c:143,149
2000/1207    
	Qtopdir, 
	Q2nddir, 
	Qfctl, 
	Qfpart, 
2000/1213    
	Qfdata, 
2000/1207    
 
	Maxpart= 8, 
2000/1111    
}; 
2000/1211/sys/src/9/bitsy/devflash.c:154,1602000/1213/sys/src/9/bitsy/devflash.c:152,158
2000/1207    
typedef struct FPart FPart; 
struct FPart 
{ 
	char	name[NAMELEN]; 
2000/1213    
	char	name[NAMELEN-4]; 
2000/1207    
	ulong	start; 
	ulong	end; 
2000/1111    
}; 
2000/1211/sys/src/9/bitsy/devflash.c:168,1742000/1213/sys/src/9/bitsy/devflash.c:166,172
2000/1207    
gen(Chan *c, Dirtab*, int, int i, Dir *dp) 
{ 
	Qid q; 
	char buf[32]; 
2000/1213    
	char buf[NAMELEN]; 
2000/1207    
	FPart *fp; 
 
	q.vers = 0; 
2000/1211/sys/src/9/bitsy/devflash.c:191,2152000/1213/sys/src/9/bitsy/devflash.c:189,214
2000/1207    
		return 1; 
	} 
 
	/* second level contains ctl plus all partitions */ 
2000/1213    
	/* second level contains all partitions and their control files */ 
2000/1207    
	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) 
2000/1213    
		if(i >= 2*Maxpart) 
2000/1207    
			return -1; 
		fp = &part[i]; 
2000/1213    
		fp = &part[i>>1]; 
2000/1207    
		if(fp->name[0] == 0) 
			return 0; 
		q.path = FQID(i, Qfpart); 
		devdir(c, q, fp->name, fp->end-fp->start, eve, 0660, dp); 
2000/1213    
		if(i & 1){ 
			q.path = FQID(i>>1, Qfdata); 
			devdir(c, q, fp->name, fp->end-fp->start, eve, 0660, dp); 
		} else { 
			snprint(buf, sizeof(buf), "%sctl", fp->name); 
			q.path = FQID(i>>1, Qfctl); 
			devdir(c, q, buf, 0, eve, 0660, dp); 
		} 
2000/1207    
		break; 
	} 
	return 1; 
2000/1211/sys/src/9/bitsy/devflash.c:229,2452000/1213/sys/src/9/bitsy/devflash.c:228,253
2000/1207    
} 
 
static void 
addpart(char *name, ulong start, ulong end) 
2000/1213    
addpart(FPart *fp, char *name, ulong start, ulong end) 
2000/1207    
{ 
	int i; 
	FPart *fp; 
 
	if(start >= flash.size || end > flash.size) 
		error(Ebadarg); 
2000/1213    
	if(strlen(name) > NAMELEN-3) 
		error("name too long"); 
	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); 
	} 
2000/1207    
	if(blockstart(start) != start) 
		error("must start on erase boundary"); 
	if(blockstart(end) != end && end != flash.size) 
		error("must end on erase boundary"); 
2000/1213    
 
2000/1207    
	fp = findpart(name); 
	if(fp != nil) 
		error(Eexist); 
2000/1211/sys/src/9/bitsy/devflash.c:255,2682000/1213/sys/src/9/bitsy/devflash.c:263,271
2000/1207    
} 
 
static void 
rempart(char *name) 
2000/1213    
rempart(FPart *fp) 
2000/1207    
{ 
	FPart *fp; 
                 
	/* can't remove the total partition */ 
	fp = findpart(name); 
	if(fp != nil) 
		fp->name[0] = 0; 
2000/1213    
	fp->name[0] = 0; 
2000/1207    
} 
 
2000/1111    
void 
2000/1211/sys/src/9/bitsy/devflash.c:280,2862000/1213/sys/src/9/bitsy/devflash.c:283,289
2000/1117    
		} 
	flash.bootprotect = 1; 
2000/1207    
 
	addpart("whole", 0, flash.size); 
2000/1213    
	addpart(nil, "flash", 0, flash.size); 
2000/1111    
} 
 
static Chan* 
2000/1211/sys/src/9/bitsy/devflash.c:315,3272000/1213/sys/src/9/bitsy/devflash.c:318,378
2000/1111    
{ 
} 
 
static long	  
flashread(Chan* c, void* a, long n, vlong off) 
2000/1213    
static long 
flashctlread(FPart *fp, void* a, long n, vlong off) 
2000/1111    
{ 
2000/1117    
	char *buf, *p, *e; 
	int i; 
2000/1207    
	FPart *fp; 
2000/1213    
	ulong addr, end; 
2000/1117    
 
2000/1213    
	buf = smalloc(1024); 
	e = buf + 1024; 
	p = seprint(buf, e, "0x%-9lux 0x%-9lux 0x%-9lux 0x%-9lux\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 long 
flashdataread(FPart *fp, void* a, long n, vlong off) 
{ 
	rlock(&flash); 
	if(waserror()){ 
		runlock(&flash); 
		nexterror(); 
	} 
	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); 
	runlock(&flash); 
	poperror(); 
 
	return n; 
} 
 
static long	  
flashread(Chan* c, void* a, long n, vlong off) 
{ 
2000/1117    
	if(c->qid.path&CHDIR) 
2000/1207    
		return devdirread(c, a, n, nil, 0, gen); 
	switch(FTYPE(c->qid.path)){ 
2000/1211/sys/src/9/bitsy/devflash.c:328,3632000/1213/sys/src/9/bitsy/devflash.c:379,388
2000/1117    
	default: 
		error(Eperm); 
	case Qfctl: 
		buf = smalloc(1024); 
		e = buf + 1024; 
		p = seprint(buf, e, "0x%-9lux 0x%-9lux 0x%-9lux 0x%-9lux\n", flash.size, 
			flash.wbsize, flash.manid, flash.devid); 
		for(i = 0; i < flash.nr; i++) 
			p = seprint(p, e, "0x%-9lux 0x%-9lux 0x%-9lux\n", flash.r[i].addr, 
				flash.r[i].n, flash.r[i].size); 
		n = readstr(off, a, n, buf); 
		free(buf); 
2000/1213    
		n = flashctlread(FPART(c->qid.path), a, n, off); 
2000/1117    
		break; 
2000/1207    
	case Qfpart: 
		fp = FPART(c->qid.path); 
2000/1117    
		rlock(&flash); 
		if(waserror()){ 
			runlock(&flash); 
			nexterror(); 
		} 
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(); 
2000/1213    
	case Qfdata: 
		n = flashdataread(FPART(c->qid.path), a, n, off); 
2000/1117    
		break; 
	} 
2000/1111    
	return n; 
2000/1211/sys/src/9/bitsy/devflash.c:412,4232000/1213/sys/src/9/bitsy/devflash.c:437,450
2000/1117    
} 
 
static long 
flashctlwrite(char *p, long n) 
2000/1213    
flashctlwrite(FPart *fp, char *p, long n) 
2000/1117    
{ 
	Cmdbuf *cmd; 
2000/1207    
	ulong off; 
	FPart *fp; 
2000/1117    
 
2000/1213    
	if(fp == nil) 
		panic("flashctlwrite"); 
 
2000/1117    
	cmd = parsecmd(p, n); 
	wlock(&flash); 
	if(waserror()){ 
2000/1211/sys/src/9/bitsy/devflash.c:425,4402000/1213/sys/src/9/bitsy/devflash.c:452,461
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]); 
2000/1213    
		case 2: 
			/* erase a single block in the partition */ 
			off = atoi(cmd->f[1]); 
2000/1207    
			off += fp->start; 
			if(off >= fp->end) 
				error("region not in partition"); 
2000/1211/sys/src/9/bitsy/devflash.c:443,4492000/1213/sys/src/9/bitsy/devflash.c:464,470
2000/1207    
			bootprotect(off); 
			(*flash.alg->erase)(off); 
			break; 
		case 2: 
2000/1213    
		case 1: 
2000/1207    
			/* erase the whole partition */ 
			bootprotect(fp->start); 
			for(off = fp->start; off < fp->end; off = blockend(off)) 
2000/1211/sys/src/9/bitsy/devflash.c:455,4652000/1213/sys/src/9/bitsy/devflash.c:476,484
2000/1207    
	} 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)); 
2000/1213    
		addpart(fp, cmd->f[1], strtoul(cmd->f[2], nil, 0), strtoul(cmd->f[3], nil, 0)); 
2000/1207    
	} else if(strcmp(cmd->f[0], "remove") == 0){ 
2000/1117    
		if(cmd->nf != 2) 
			error(Ebadarg); 
2000/1207    
		rempart(cmd->f[1]); 
2000/1213    
		rempart(fp); 
2000/1117    
	} else if(strcmp(cmd->f[0], "protectboot") == 0){ 
		if(cmd->nf == 0 || strcmp(cmd->f[1], "off") != 0) 
			flash.bootprotect = 1; 
2000/1211/sys/src/9/bitsy/devflash.c:475,4932000/1213/sys/src/9/bitsy/devflash.c:494,516
2000/1117    
} 
 
static long 
2000/1207    
flashdatawrite(Chan *c, uchar *p, long n, long off) 
2000/1213    
flashdatawrite(FPart *fp, uchar *p, long n, long off) 
2000/1117    
{ 
	uchar *end; 
	int m; 
2000/1213    
	int on; 
2000/1207    
	long ooff; 
2000/1117    
	uchar *op = p; 
2000/1207    
	FPart *fp; 
2000/1213    
	uchar *buf; 
2000/1117    
 
2000/1207    
	fp = FPART(c->qid.path); 
2000/1213    
	if(fp == nil) 
		panic("flashctlwrite"); 
2000/1117    
 
2000/1213    
	buf = nil; 
2000/1117    
	wlock(&flash); 
	if(waserror()){ 
		wunlock(&flash); 
2000/1213    
		if(buf != nil) 
			free(buf); 
2000/1117    
		nexterror(); 
	} 
 
2000/1211/sys/src/9/bitsy/devflash.c:496,5032000/1213/sys/src/9/bitsy/devflash.c:519,525
2000/1207    
	if(!iseve()) 
		error(Eperm); 
 
	if((off & 0x3) || (n & 0x3)) 
		error("only quad writes"); 
2000/1213    
	/* can't cross partition boundaries */ 
2000/1207    
	off += fp->start; 
	if(off >= fp->end || off+n > fp->end || n <= 0) 
		error(Ebadarg); 
2000/1211/sys/src/9/bitsy/devflash.c:505,5122000/1213/sys/src/9/bitsy/devflash.c:527,556
2000/1117    
	/* make sure we're not writing the boot sector */ 
	bootprotect(off); 
 
2000/1213    
	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); 
 
2000/1117    
	/* (*flash.alg->write) can't cross blocks */ 
2000/1207    
	ooff = off; 
2000/1213    
	p = buf; 
2000/1117    
	for(end = p + n; p < end; p += m){ 
		m = blockend(off) - off; 
		if(m > end - p) 
2000/1211/sys/src/9/bitsy/devflash.c:513,5312000/1213/sys/src/9/bitsy/devflash.c:557,575
2000/1117    
			m = end - p; 
2000/1209    
		if(m > Maxwchunk) 
			m = Maxwchunk; 
		memmove(flash.wb, p, m); 
		(*flash.alg->write)(flash.wb, m, off); 
2000/1213    
		(*flash.alg->write)(p, m, off); 
2000/1117    
		off += m; 
	} 
 
	/* make sure write succeeded */ 
	if(memcmp(op, &flash.p[ooff>>2], n) != 0) 
2000/1213    
	if(memcmp(buf, &flash.p[ooff>>2], n) != 0) 
2000/1117    
		error("written bytes don't match"); 
 
	wunlock(&flash); 
2000/1213    
	free(buf); 
2000/1117    
	poperror(); 
 
	return n; 
2000/1213    
	return on; 
2000/1117    
} 
 
2000/1111    
static long	  
2000/1211/sys/src/9/bitsy/devflash.c:541,5492000/1213/sys/src/9/bitsy/devflash.c:585,595
2000/1117    
	default: 
		panic("flashwrite"); 
	case Qfctl: 
		return flashctlwrite(a, n); 
2000/1207    
	case Qfpart: 
		return flashdatawrite(c, a, n, off); 
2000/1213    
		n = flashctlwrite(FPART(c->qid.path), a, n); 
		break; 
	case Qfdata: 
		n = flashdatawrite(FPART(c->qid.path), a, n, off); 
		break; 
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)