static void flashreset(void) { Flash *f; Flashtype *t; char *e; int bank; for(bank = 0; bank < Nbanks; bank++){ f = malloc(sizeof(*f)); if(f == nil){ print("#F%d: can't allocate Flash data\n", bank); return; } f->cmask = ~(ulong)0; if(archflashreset(bank, f) < 0 || f->type == nil || f->addr == nil){ free(f); return; } for(t = flash.types; t != nil; t = t->next) if(strcmp(f->type, t->name) == 0) break; if(t == nil){ iprint("#F%d: no flash driver for type %s (addr %p)\n", bank, f->type, f->addr); free(f); return; } f->reset = t->reset; f->protect = 1; if(f->reset(f) == 0){ flash.card[bank] = f; iprint("#F%d: %s addr %#p len %lud width %d interleave %d\n", // bank, f->type, PADDR(f->addr), f->size, bank, f->type, f->addr, f->size, f->width, f->interleave); e = flashnewpart(f, "flash", 0, f->size); if(e != nil) panic("#F%d: couldn't init table: %s", bank, e); }else iprint("#F%d: %#p: reset failed (%s)\n", bank, f->addr, f->type); } }
static long flashwrite(Chan *c, void *buf, long n, vlong offset) { Cmdbuf *cb; Cmdtab *ct; ulong addr, start, end; char *e; Flashpart *fp; Flashregion *r; Flash *f; f = flash.card[c->dev]; fp = &f->part[PART(c->qid.path)]; if(fp->name == nil) error(Egreg); switch(TYPE(c->qid.path)){ case Qdata: if(f->write == nil) error(Eperm); offset += fp->start; if(offset >= fp->end) return 0; if(offset+n > fp->end) n = fp->end - offset; n = writeflash(f, offset, buf, n); if(n < 0) error(Eio); return n; case Qctl: cb = parsecmd(buf, n); if(waserror()){ free(cb); nexterror(); } ct = lookupcmd(cb, flashcmds, nelem(flashcmds)); switch(ct->index){ case CMerase: if(strcmp(cb->f[1], "all") != 0){ addr = flashaddr(f, fp, cb->f[1]); r = flashregion(f, addr); if(r == nil) error("nonexistent flash region"); if(addr%r->erasesize != 0) error("invalid erase block address"); eraseflash(f, r, addr); }else if(fp->start == 0 && fp->end == f->size && f->eraseall != nil){ eraseflash(f, nil, 0); }else{ for(addr = fp->start; addr < fp->end; addr += r->erasesize){ r = flashregion(f, addr); if(r == nil) error("nonexistent flash region"); if(addr%r->erasesize != 0) error("invalid erase block address"); eraseflash(f, r, addr); } } break; case CMadd: if(cb->nf < 3) error(Ebadarg); start = flashaddr(f, fp, cb->f[2]); if(cb->nf > 3 && strcmp(cb->f[3], "end") != 0) end = flashaddr(f, fp, cb->f[3]); else end = fp->end; if(start > end || start >= fp->end || end > fp->end) error(Ebadarg); e = flashnewpart(f, cb->f[1], start, end); if(e != nil) error(e); break; case CMremove: /* TO DO */ break; case CMprotectboot: if(cb->nf > 1 && strcmp(cb->f[1], "off") == 0) f->protect = 0; else f->protect = 1; break; case CMsync: /* TO DO? */ break; default: error(Ebadarg); } poperror(); free(cb); return n; } error(Egreg); return 0; /* not reached */ }