//! Handles a monitor command. void flash_handle_fn( uint8_t const app, uint8_t const verb, uint32_t const len) { switch(verb) { case 0x21: eraseflash(cmddataword[0]); txdata(app,0,0); break; case 0x22: writeflash(cmddataword[0], cmddata[2]); txdata(app,0,0); break; case 0x23: cmddata[0] = readflash(cmddataword[0]); txdata(app,0,1); break; } }
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 */ }