~kris/9p

9hist

ref: 673d2fe8805d24559336baf1fdd94d67d93174a5 9hist/bitsy/devflash.c -rw-r--r-- 3.0 KiB
673d2fe8 — David du Colombier Plan 9 from Bell Labs 2000-11-11 25 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"../port/error.h"

/* flash partitions */
typedef struct FlashPart FlashPart;
struct FlashPart
{
	QLock;
	char	name[NAMELEN];
	ulong	start;		/* byte offsets */
	ulong	end;
};

static ulong *flash = (ulong*)FLASHZERO;

/*
 *  on the bitsy, all 32 bit accesses to flash are mapped to two 16 bit
 *  accesses, one to the low half of the chip and the other to the high
 *  half.  Therefore for all command accesses, ushort indices in the
 *  manuals turn into ulong indices in our code.  Also, by copying all
 *  16 bit commands to both halves of a 32 bit command, we erase 2
 *  sectors for each request erase request.
 */

/*
 *  common flash memory interface
 */
struct CFIid
{
	ulong	q;
	ulong	r;
	ulong	y;
	ulong	cmd_set;
	ulong	vendor_alg;
	ulong	ext_alg_addr[2];
	ulong	alt_cmd_set;
	ulong	alt_vendor_alg;
	ulong	alt_ext_ald_addr[2];
	
};

struct CFIsys
{
	ulong 	vcc_min;	/* 100 mv */
	ulong	vcc_max;
	ulong	vpp_min;
	ulong	vpp_max;
	ulong	word_wr_to;		/* 2**n µs */
	ulong	buf_wr_to;		/* 2**n µs */
	ulong	block_erase_to;		/* 2**n ms */
	ulong	chip_erase_to;		/* 2**n ms */
	ulong	max_word_wr_to;		/* 2**n µs */
	ulong	max_buf_wr_to;		/* 2**n µs */
	ulong	max_block_erase_to;	/* 2**n ms */
	ulong	max_chip_erase_to;	/* 2**n ms */
};

struct CFIgeom
{
	ulong	size;		/* 2**n bytes */
	ulong	dev_code;	/* ??? */
	ulong	max_multi;	/* max bytes in a multibyte write */
	ulong	nregion;	/* number of erase regions */
	ulong	region[1];	/* erase region info */
};

#define mirror(x) (((x)<<16)|(x))

void
cfiquery(void)
{
	struct CFIid *id;

	flash[0x55] = mirror(0x98);
	id = (struct CFIid*)&flash[0x10];
	if(id.q != 'q' || id.r != 'r' || id.y != 'y')
		print("CFI not supported by flash\n");
	
	flash[0x55] = mirror(0xFF);
}

void
cfigeom(void)
{
}

/*
 *  flash device interface
 */

enum
{
	Qf0=1,
	Qf1,
	Qf2,
	Qf3,
};

Dirtab flashdir[]={
	"f0",		{ Qf0, 0 },	0,	0664,
	"f1",		{ Qf1, 0 },	0,	0664,
	"f2",		{ Qf2, 0 },	0,	0664,
	"f3",		{ Qf3, 0 },	0,	0664,
};

void
flashinit(void)
{
	cfiquery();
	cfigeom();
}

static Chan*
flashattach(char* spec)
{
	return devattach('r', spec);
}

static int	 
flashwalk(Chan* c, char* name)
{
	return devwalk(c, name, flashdir, nelem(flashdir), devgen);
}

static void	 
flashstat(Chan* c, char* dp)
{
	devstat(c, dp, flashdir, nelem(flashdir), devgen);
}

static Chan*
flashopen(Chan* c, int omode)
{
	omode = openmode(omode);
	if(strcmp(up->user, eve)!=0)
		error(Eperm);
	return devopen(c, omode, flashdir, nelem(flashdir), devgen);
}

static void	 
flashclose(Chan*)
{
}

static long	 
flashread(Chan* c, void* a, long n, vlong off)
{
	USED(c, a, off);
	error("UUO");
	return n;
}

static long	 
flashwrite(Chan* c, void* a, long n, vlong)
{
	USED(c, a, off);
	error("UUO");
	return n;
}

Dev flashdevtab = {
	'F',
	"flash",

	devreset,
	flashinit,
	flashattach,
	devclone,
	flashwalk,
	flashstat,
	flashopen,
	devcreate,
	flashclose,
	flashread,
	devbread,
	flashwrite,
	devbwrite,
	devremove,
	devwstat,
};