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

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

2000/1207/sys/src/9/bitsy/devflash.c:71,762000/1209/sys/src/9/bitsy/devflash.c:71,81 (short | long | prev | next)
2000/1117    
	ulong		*wb;		/* staging area for write buffer */ 
} flash; 
2000/1111    
 
2000/1209    
enum 
{ 
	Maxwchunk=	1024,	/* maximum chunk written by one call to falg->write */ 
}; 
 
2000/1117    
/* 
 *  common flash interface 
 */ 
2000/1207/sys/src/9/bitsy/devflash.c:128,1342000/1209/sys/src/9/bitsy/devflash.c:133,139
2000/1117    
		addr += flash.r[q].size*flash.r[q].n; 
		flash.r[q].end = addr; 
	} 
	flash.wb = malloc(flash.wbsize); 
2000/1209    
	flash.wb = malloc(flash.wbsize>1024 ? flash.wbsize : 1024); 
2000/1117    
} 
 
2000/1111    
/* 
2000/1207/sys/src/9/bitsy/devflash.c:506,5122000/1209/sys/src/9/bitsy/devflash.c:511,520
2000/1117    
		m = blockend(off) - off; 
		if(m > end - p) 
			m = end - p; 
		(*flash.alg->write)(p, m, off); 
2000/1209    
		if(m > Maxwchunk) 
			m = Maxwchunk; 
		memmove(flash.wb, p, m); 
		(*flash.alg->write)(flash.wb, m, off); 
2000/1117    
		off += m; 
	} 
 
2000/1207/sys/src/9/bitsy/devflash.c:561,5672000/1209/sys/src/9/bitsy/devflash.c:569,590
2000/1111    
	devwstat, 
2000/1107    
}; 
2000/1117    
 
2000/1209    
enum 
{ 
	/* status register */ 
	ISEs_lockerr=		1<<1, 
	ISEs_powererr=		1<<3, 
	ISEs_progerr=		1<<4, 
	ISEs_eraseerr=		1<<5, 
	ISEs_ready=		1<<7, 
	ISEs_err= (ISEs_lockerr|ISEs_powererr|ISEs_progerr|ISEs_eraseerr), 
2000/1117    
 
2000/1209    
	/* extended status register */ 
	ISExs_bufavail=		1<<7, 
}; 
 
 
 
2000/1117    
/* intel/sharp extended command set */ 
static void 
ise_reset(void) 
2000/1207/sys/src/9/bitsy/devflash.c:588,6032000/1209/sys/src/9/bitsy/devflash.c:611,626
2000/1117    
{ 
	char err[ERRLEN]; 
 
	if(status & (1<<3)){ 
		sprint(err, "flash%d: low prog voltage", bank); 
2000/1209    
	if(status & (ISEs_lockerr)){ 
		sprint(err, "flash%d: block locked %lux", bank, status); 
2000/1117    
		error(err); 
	} 
	if(status & (1<<1)){ 
		sprint(err, "flash%d: block locked", bank); 
2000/1209    
	if(status & (ISEs_powererr)){ 
		sprint(err, "flash%d: low prog voltage %lux", bank, status); 
2000/1117    
		error(err); 
	} 
	if(status & (1<<5)){ 
		sprint(err, "flash%d: i/o error", bank); 
2000/1209    
	if(status & (ISEs_progerr|ISEs_eraseerr)){ 
		sprint(err, "flash%d: i/o error %lux", bank, status); 
2000/1117    
		error(err); 
	} 
} 
2000/1207/sys/src/9/bitsy/devflash.c:615,6212000/1209/sys/src/9/bitsy/devflash.c:638,644
2000/1117    
	start = m->ticks; 
	do { 
		x = flash.p[addr]; 
		if((x & mirror(1<<7)) == mirror(1<<7)) 
2000/1209    
		if((x & mirror(ISEs_ready)) == mirror(ISEs_ready)) 
2000/1117    
			break; 
	} while(TK2MS(m->ticks-start) < 1500); 
	flashprogpower(0); 
2000/1207/sys/src/9/bitsy/devflash.c:627,6332000/1209/sys/src/9/bitsy/devflash.c:650,656
2000/1117    
	ise_reset(); 
} 
/* 
 *  flash writing goes about 16 times faster if we use 
2000/1209    
 *  the flash spec claimes writing goes faster if we use 
2000/1117    
 *  the write buffer.  We fill the write buffer and then 
 *  issue the write request.  After the write request, 
 *  subsequent reads will yield the status register or, 
2000/1207/sys/src/9/bitsy/devflash.c:637,6802000/1209/sys/src/9/bitsy/devflash.c:660,719
2000/1117    
 *  On timeout, we issue a read status register request so 
 *  that the status register can be read no matter how we 
 *  exit. 
2000/1209    
 * 
 *  returns the status. 
2000/1117    
 */ 
static int 
ise_wbwrite(ulong *p, int n, ulong off) 
2000/1209    
static ulong 
ise_wbwrite(ulong *p, int n, ulong off, ulong baddr, ulong *status) 
2000/1117    
{ 
	ulong start; 
2000/1209    
	ulong x, start; 
2000/1117    
	int i; 
2000/1209    
	int s; 
2000/1117    
 
	/* copy out of user space to avoid faults later */ 
	memmove(flash.wb, p, n*4); 
	p = flash.wb; 
                 
	/* put flash into write buffer mode */ 
	start = m->ticks; 
	for(;;) { 
2000/1209    
		s = splhi(); 
2000/1117    
		/* request write buffer mode */ 
		flash.p[off] = mirror(0xe8); 
2000/1209    
		flash.p[baddr] = mirror(0xe8); 
2000/1117    
 
		/* look at extended status reg for status */ 
		if((flash.p[off] & mirror(1<<7)) == mirror(1<<7)) 
2000/1209    
		if((flash.p[baddr] & mirror(1<<7)) == mirror(1<<7)) 
2000/1117    
			break; 
2000/1209    
		splx(s); 
2000/1117    
 
		/* didn't work, keep trying for 2 secs */ 
		if(TK2MS(m->ticks-start) > 2000){ 
			/* set up to read status */ 
			flash.p[off] = mirror(0x70); 
2000/1209    
			flash.p[baddr] = mirror(0x70); 
			*status = flash.p[baddr]; 
			pprint("write buffered cmd timed out\n"); 
2000/1117    
			return -1; 
		} 
	} 
 
	/* fill write buffer */ 
	flash.p[off] = mirror(n-1); 
2000/1209    
	flash.p[baddr] = mirror(n-1); 
2000/1117    
	for(i = 0; i < n; i++) 
		flash.p[off+i] = *p++; 
 
	/* program from buffer */ 
	flash.p[off] = mirror(0xd0); 
2000/1209    
	flash.p[baddr] = mirror(0xd0); 
	splx(s); 
2000/1117    
 
	/* subsequent reads will return status about the write */ 
2000/1209    
	/* wait till the programming is done */ 
	start = m->ticks; 
	for(;;) { 
		x = *status = flash.p[baddr];	/* read status register */ 
		if((x & mirror(ISEs_ready)) == mirror(ISEs_ready)) 
			break; 
		if(TK2MS(m->ticks-start) > 2000){ 
			pprint("read status timed out\n"); 
			return -1; 
		} 
	} 
	if(x & mirror(ISEs_err)) 
		return -1; 
2000/1117    
 
	return n; 
} 
2000/1207/sys/src/9/bitsy/devflash.c:683,6962000/1209/sys/src/9/bitsy/devflash.c:722,736
2000/1117    
{ 
	ulong *p, *end; 
	int i, wbsize; 
	ulong x, start, ooff; 
2000/1209    
	ulong x, baddr; 
2000/1117    
 
	/* everything in terms of ulongs */ 
	wbsize = flash.wbsize>>2; 
2000/1209    
	baddr = blockstart(off); 
2000/1117    
	off >>= 2; 
	n >>= 2; 
	p = a; 
	ooff = off; 
2000/1209    
	baddr >>= 2; 
2000/1117    
 
	/* first see if write will succeed */ 
	for(i = 0; i < n; i++) 
2000/1207/sys/src/9/bitsy/devflash.c:715,7212000/1209/sys/src/9/bitsy/devflash.c:755,761
2000/1117    
		if(i > end - p) 
			i = end - p; 
 
		if(ise_wbwrite(p, i, off) != i) 
2000/1209    
		if(ise_wbwrite(p, i, off, baddr, &x) < 0) 
2000/1117    
			break; 
 
		off += i; 
2000/1207/sys/src/9/bitsy/devflash.c:722,7352000/1209/sys/src/9/bitsy/devflash.c:762,767
2000/1117    
		p += i; 
		i = wbsize; 
	} 
                 
	/* wait till the programming is done */ 
	start = m->ticks; 
	do { 
		x = flash.p[ooff]; 
		if((x & mirror(1<<7)) == mirror(1<<7)) 
			break; 
	} while(TK2MS(m->ticks-start) < 1000); 
 
	ise_clearerror(); 
	ise_error(0, x); 


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