6 #include "../port/lib.h"
10 #include "../port/error.h"
12 #include "../port/flashif.h"
14 typedef struct Flashtype Flashtype;
27 Flash* card[Nbanks]; /* actual card type, reset for access */
28 Flashtype* types; /* possible card types */
38 #define TYPE(q) ((ulong)(q) & 0xFF)
39 #define PART(q) ((ulong)(q)>>8)
40 #define QID(p,t) (((p)<<8) | (t))
42 static Flashregion* flashregion(Flash*, ulong);
43 static char* flashnewpart(Flash*, char*, ulong, ulong);
44 static ulong flashaddr(Flash*, Flashpart*, char*);
45 static void protect(Flash*, ulong);
46 static void eraseflash(Flash*, Flashregion*, ulong);
47 static long readflash(Flash*, void*, long, int);
48 static long writeflash(Flash*, long, void*,int);
50 static char Eprotect[] = "flash region protected";
53 flash2gen(Chan *c, ulong p, Dir *dp)
60 f = flash.card[c->dev];
61 fp = &f->part[PART(p)];
64 mkqid(&q, p, 0, QTFILE);
70 devdir(c, q, fp->name, fp->end-fp->start, eve, mode, dp);
73 snprint(up->genbuf, sizeof(up->genbuf), "%sctl", fp->name);
74 devdir(c, q, up->genbuf, 0, eve, 0660, dp);
82 flashgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
88 mkqid(&q, QID(0, Qtopdir), 0, QTDIR);
91 sprint(up->genbuf, "#F%ld", c->dev);
94 devdir(c, q, n, 0, eve, 0555, dp);
97 switch(TYPE(c->qid.path)){
101 mkqid(&q, QID(0, Qflashdir), 0, QTDIR);
104 sprint(up->genbuf, "flash%ld", c->dev);
107 devdir(c, q, n, 0, eve, 0555, dp);
110 if(s >= 2*nelem(flash.card[c->dev]->part))
112 return flash2gen(c, QID(s>>1, s&1?Qctl:Qdata), dp);
115 return flash2gen(c, (ulong)c->qid.path, dp);
128 for(bank = 0; bank < Nbanks; bank++){
129 f = malloc(sizeof(*f));
131 print("#F%d: can't allocate Flash data\n", bank);
134 f->cmask = ~(ulong)0;
135 if(archflashreset(bank, f) < 0 || f->type == nil ||
140 for(t = flash.types; t != nil; t = t->next)
141 if(strcmp(f->type, t->name) == 0)
144 iprint("#F%d: no flash driver for type %s (addr %p)\n",
145 bank, f->type, f->addr);
151 if(f->reset(f) == 0){
152 flash.card[bank] = f;
153 iprint("#F%d: %s addr %#p len %lud width %d interleave %d\n",
154 // bank, f->type, PADDR(f->addr), f->size,
155 bank, f->type, f->addr, f->size,
156 f->width, f->interleave);
157 e = flashnewpart(f, "flash", 0, f->size);
159 panic("#F%d: couldn't init table: %s", bank, e);
161 iprint("#F%d: %#p: reset failed (%s)\n",
162 bank, f->addr, f->type);
167 flashattach(char *spec)
173 bank = strtol(spec, nil, 0);
174 if(bank < 0 || bank >= Nbanks ||
175 (f = flash.card[bank]) == nil ||
176 f->attach != nil && f->attach(f) < 0)
178 c = devattach('F', spec);
184 flashwalk(Chan *c, Chan *nc, char **name, int nname)
186 return devwalk(c, nc, name, nname, nil, 0, flashgen);
190 flashstat(Chan *c, uchar *dp, int n)
192 return devstat(c, dp, n, nil, 0, flashgen);
196 flashopen(Chan *c, int omode)
198 omode = openmode(omode);
199 switch(TYPE(c->qid.path)){
202 if(flash.card[c->dev] == nil)
206 return devopen(c, omode, nil, 0, flashgen);
215 flashread(Chan *c, void *buf, long n, vlong offset)
224 if(c->qid.type & QTDIR)
225 return devdirread(c, buf, n, nil, 0, flashgen);
227 f = flash.card[c->dev];
228 fp = &f->part[PART(c->qid.path)];
231 switch(TYPE(c->qid.path)){
234 if(offset >= fp->end)
236 if(offset+n > fp->end)
237 n = fp->end - offset;
238 n = readflash(f, buf, offset, n);
248 o = seprint(s, s+READSTR, "%#2.2ux %#4.4ux %d %q\n",
249 f->id, f->devid, f->width, f->sort!=nil? f->sort: "nor");
250 for(i=0; i<f->nr; i++){
252 if(r->start < fp->end && fp->start < r->end){
254 if(fp->start > start)
259 o = seprint(o, s+READSTR, "%#8.8lux %#8.8lux %#8.8lux",
260 start, end, r->erasesize);
262 o = seprint(o, s+READSTR, " %#8.8lux",
264 o = seprint(o, s+READSTR, "\n");
267 n = readstr(offset, buf, n, s);
273 return 0; /* not reached */
284 static Cmdtab flashcmds[] = {
285 {CMerase, "erase", 2},
287 {CMremove, "remove", 2},
289 {CMprotectboot, "protectboot", 0},
293 flashwrite(Chan *c, void *buf, long n, vlong offset)
297 ulong addr, start, end;
303 f = flash.card[c->dev];
304 fp = &f->part[PART(c->qid.path)];
307 switch(TYPE(c->qid.path)){
312 if(offset >= fp->end)
314 if(offset+n > fp->end)
315 n = fp->end - offset;
316 n = writeflash(f, offset, buf, n);
321 cb = parsecmd(buf, n);
326 ct = lookupcmd(cb, flashcmds, nelem(flashcmds));
329 if(strcmp(cb->f[1], "all") != 0){
330 addr = flashaddr(f, fp, cb->f[1]);
331 r = flashregion(f, addr);
333 error("nonexistent flash region");
334 if(addr%r->erasesize != 0)
335 error("invalid erase block address");
336 eraseflash(f, r, addr);
337 }else if(fp->start == 0 && fp->end == f->size &&
339 eraseflash(f, nil, 0);
341 for(addr = fp->start; addr < fp->end;
342 addr += r->erasesize){
343 r = flashregion(f, addr);
345 error("nonexistent flash region");
346 if(addr%r->erasesize != 0)
347 error("invalid erase block address");
348 eraseflash(f, r, addr);
355 start = flashaddr(f, fp, cb->f[2]);
356 if(cb->nf > 3 && strcmp(cb->f[3], "end") != 0)
357 end = flashaddr(f, fp, cb->f[3]);
360 if(start > end || start >= fp->end || end > fp->end)
362 e = flashnewpart(f, cb->f[1], start, end);
370 if(cb->nf > 1 && strcmp(cb->f[1], "off") == 0)
386 return 0; /* not reached */
390 flashnewpart(Flash *f, char *name, ulong start, ulong end)
392 Flashpart *fp, *empty;
396 for(i = 0; i < nelem(f->part); i++){
401 }else if(strcmp(fp->name, name) == 0)
404 if((fp = empty) == nil)
405 return "partition table full";
407 kstrdup(&fp->name, name);
416 flashaddr(Flash *f, Flashpart *fp, char *s)
421 addr = strtoul(s, &s, 0);
425 error("partition removed");
427 r = flashregion(f, addr);
428 if(r != nil && addr%r->erasesize != 0)
429 error("invalid erase unit address");
430 if(addr < fp->start || addr > fp->end || addr > f->size)
436 flashregion(Flash *f, ulong a)
441 for(i=0; i<f->nr; i++){
443 if(r->start <= a && a < r->end)
471 * called by flash card types named in link section (eg, flashamd.c)
474 addflashcard(char *name, int (*reset)(Flash*))
478 f = (Flashtype*)malloc(sizeof(*f));
482 for(l = &flash.types; *l != nil; l = &(*l)->next)
488 readflash(Flash *f, void *buf, long offset, int n)
495 if(offset < 0 || offset+n > f->size)
508 if(f->read(f, o, (ulong*)tmp, width) < 0)
510 memmove(tmp, (uchar*)f->addr + o, width);
511 for(; n > 0 && offset & wmask; n--)
512 *p++ = tmp[offset++ & wmask];
517 if(f->read(f, offset, (ulong*)p, n) < 0)
523 if(f->read(f, offset, (ulong*)tmp, width))
528 /* assumes hardware supports byte access */
529 memmove(buf, (uchar*)f->addr+offset, n);
536 writeflash(Flash *f, long offset, void *buf, int n)
544 if(f->write == nil || offset < 0 || offset+n > f->size)
546 rg = flashregion(f, offset);
547 if(f->protect && rg != nil && rg->start == 0 && offset < rg->erasesize)
562 if(f->read(f, o, tmp, width) < 0)
565 memmove(tmp, (uchar*)f->addr+o, width);
566 for(; n > 0 && offset&wmask; n--)
567 tmp[offset++&wmask] = *p++;
568 if(f->write(f, o, tmp, width) < 0)
574 if(f->write(f, offset, p, n) < 0)
581 if(f->read(f, offset, tmp, width) < 0)
584 memmove(tmp, (uchar*)f->addr+offset, width);
586 if(f->write(f, offset, tmp, width) < 0)
596 eraseflash(Flash *f, Flashregion *r, ulong addr)
600 if(f->protect && r != nil && r->start == 0 && addr < r->erasesize)
610 if(f->eraseall != nil)
615 rv = f->erasezone(f, r, addr);
624 * flash access taking width and interleave into account
627 flashget(Flash *f, ulong a)
631 return ((uchar*)f->addr)[a<<f->bshift];
633 return ((ushort*)f->addr)[a];
635 return ((ulong*)f->addr)[a];
640 flashput(Flash *f, ulong a, int v)
644 ((uchar*)f->addr)[a<<f->bshift] = v;
647 ((ushort*)f->addr)[a] = v;
650 ((ulong*)f->addr)[a] = v;