~kris/9p

9hist

f85cc12c9777754a672ece9da01507770d424e96 — David du Colombier 25 years ago eed620f
Plan 9 from Bell Labs 2000-12-13
1 files changed, 134 insertions(+), 88 deletions(-)

M bitsy/devflash.c
M bitsy/devflash.c => bitsy/devflash.c +134 -88
@@ 68,7 68,6 @@ struct
	ulong		nr;		/* number of regions */
	uchar		bootprotect;
	FlashRegion	r[32];
	ulong		*wb;		/* staging area for write buffer */
} flash;

enum


@@ 133,7 132,6 @@ cfiquery(void)
		addr += flash.r[q].size*flash.r[q].n;
		flash.r[q].end = addr;
	}
	flash.wb = malloc(flash.wbsize>1024 ? flash.wbsize : 1024);
}

/*


@@ 145,7 143,7 @@ enum
	Qtopdir,
	Q2nddir,
	Qfctl,
	Qfpart,
	Qfdata,

	Maxpart= 8,
};


@@ 154,7 152,7 @@ enum
typedef struct FPart FPart;
struct FPart
{
	char	name[NAMELEN];
	char	name[NAMELEN-4];
	ulong	start;
	ulong	end;
};


@@ 168,7 166,7 @@ static int
gen(Chan *c, Dirtab*, int, int i, Dir *dp)
{
	Qid q;
	char buf[32];
	char buf[NAMELEN];
	FPart *fp;

	q.vers = 0;


@@ 191,25 189,26 @@ gen(Chan *c, Dirtab*, int, int i, Dir *dp)
		return 1;
	}

	/* second level contains ctl plus all partitions */
	/* second level contains all partitions and their control files */
	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)
		if(i >= 2*Maxpart)
			return -1;
		fp = &part[i];
		fp = &part[i>>1];
		if(fp->name[0] == 0)
			return 0;
		q.path = FQID(i, Qfpart);
		devdir(c, q, fp->name, fp->end-fp->start, eve, 0660, dp);
		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);
		}
		break;
	}
	return 1;


@@ 229,17 228,26 @@ findpart(char *name)
}

static void
addpart(char *name, ulong start, ulong end)
addpart(FPart *fp, char *name, ulong start, ulong end)
{
	int i;
	FPart *fp;

	if(start >= flash.size || end > flash.size)
		error(Ebadarg);
	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);
	}
	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);


@@ 255,14 263,9 @@ addpart(char *name, ulong start, ulong end)
}

static void
rempart(char *name)
rempart(FPart *fp)
{
	FPart *fp;

	/* can't remove the total partition */
	fp = findpart(name);
	if(fp != nil)
		fp->name[0] = 0;
	fp->name[0] = 0;
}

void


@@ 280,7 283,7 @@ flashinit(void)
		}
	flash.bootprotect = 1;

	addpart("whole", 0, flash.size);
	addpart(nil, "flash", 0, flash.size);
}

static Chan*


@@ 315,49 318,71 @@ flashclose(Chan*)
{
}

static long	 
flashread(Chan* c, void* a, long n, vlong off)
static long
flashctlread(FPart *fp, void* a, long n, vlong off)
{
	char *buf, *p, *e;
	int i;
	FPart *fp;
	ulong addr, end;

	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)
{
	if(c->qid.path&CHDIR)
		return devdirread(c, a, n, nil, 0, gen);
	switch(FTYPE(c->qid.path)){
	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);
		n = flashctlread(FPART(c->qid.path), a, n, off);
		break;
	case Qfpart:
		fp = FPART(c->qid.path);
		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();
	case Qfdata:
		n = flashdataread(FPART(c->qid.path), a, n, off);
		break;
	}
	return n;


@@ 412,11 437,13 @@ blockend(ulong addr)
}

static long
flashctlwrite(char *p, long n)
flashctlwrite(FPart *fp, char *p, long n)
{
	Cmdbuf *cmd;
	ulong off;
	FPart *fp;

	if(fp == nil)
		panic("flashctlwrite");

	cmd = parsecmd(p, n);
	wlock(&flash);


@@ 425,16 452,10 @@ flashctlwrite(char *p, long n)
		nexterror();
	}
	if(strcmp(cmd->f[0], "erase") == 0){
		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]);
		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");


@@ 443,7 464,7 @@ flashctlwrite(char *p, long n)
			bootprotect(off);
			(*flash.alg->erase)(off);
			break;
		case 2:
		case 1:
			/* erase the whole partition */
			bootprotect(fp->start);
			for(off = fp->start; off < fp->end; off = blockend(off))


@@ 455,11 476,9 @@ flashctlwrite(char *p, long n)
	} 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));
		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){
		if(cmd->nf != 2)
			error(Ebadarg);
		rempart(cmd->f[1]);
		rempart(fp);
	} else if(strcmp(cmd->f[0], "protectboot") == 0){
		if(cmd->nf == 0 || strcmp(cmd->f[1], "off") != 0)
			flash.bootprotect = 1;


@@ 475,19 494,23 @@ flashctlwrite(char *p, long n)
}

static long
flashdatawrite(Chan *c, uchar *p, long n, long off)
flashdatawrite(FPart *fp, uchar *p, long n, long off)
{
	uchar *end;
	int m;
	int on;
	long ooff;
	uchar *op = p;
	FPart *fp;
	uchar *buf;

	fp = FPART(c->qid.path);
	if(fp == nil)
		panic("flashctlwrite");

	buf = nil;
	wlock(&flash);
	if(waserror()){
		wunlock(&flash);
		if(buf != nil)
			free(buf);
		nexterror();
	}



@@ 496,8 519,7 @@ flashdatawrite(Chan *c, uchar *p, long n, long off)
	if(!iseve())
		error(Eperm);

	if((off & 0x3) || (n & 0x3))
		error("only quad writes");
	/* can't cross partition boundaries */
	off += fp->start;
	if(off >= fp->end || off+n > fp->end || n <= 0)
		error(Ebadarg);


@@ 505,27 527,49 @@ flashdatawrite(Chan *c, uchar *p, long n, long off)
	/* 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;
		memmove(flash.wb, p, m);
		(*flash.alg->write)(flash.wb, m, off);
		(*flash.alg->write)(p, m, off);
		off += m;
	}

	/* make sure write succeeded */
	if(memcmp(op, &flash.p[ooff>>2], n) != 0)
	if(memcmp(buf, &flash.p[ooff>>2], n) != 0)
		error("written bytes don't match");

	wunlock(&flash);
	free(buf);
	poperror();

	return n;
	return on;
}

static long	 


@@ 541,9 585,11 @@ flashwrite(Chan* c, void* a, long n, vlong off)
	default:
		panic("flashwrite");
	case Qfctl:
		return flashctlwrite(a, n);
	case Qfpart:
		return flashdatawrite(c, a, n, off);
		n = flashctlwrite(FPART(c->qid.path), a, n);
		break;
	case Qfdata:
		n = flashdatawrite(FPART(c->qid.path), a, n, off);
		break;
	}
	return n;
}