| plan 9 kernel history: overview | file list | diff list |
2000/1213/bitsy/devflash.c (diff list | history)
| 2000/1211/sys/src/9/bitsy/devflash.c:68,74 – 2000/1213/sys/src/9/bitsy/devflash.c:68,73 (short | long | prev | next) | ||
| 2000/1117 | ulong nr; /* number of regions */ uchar bootprotect; FlashRegion r[32]; | |
| 2000/1111 | ||
| 2000/1209 | enum | |
| 2000/1211/sys/src/9/bitsy/devflash.c:133,139 – 2000/1213/sys/src/9/bitsy/devflash.c:132,137 | ||
| 2000/1117 | addr += flash.r[q].size*flash.r[q].n; flash.r[q].end = addr; } | |
| 2000/1209 |
| |
| 2000/1117 | } | |
| 2000/1111 | /* | |
| 2000/1211/sys/src/9/bitsy/devflash.c:145,151 – 2000/1213/sys/src/9/bitsy/devflash.c:143,149 | ||
| 2000/1207 | Qtopdir, Q2nddir, Qfctl, | |
| 2000/1213 | Qfdata, | |
| 2000/1207 | Maxpart= 8, | |
| 2000/1111 | }; | |
| 2000/1211/sys/src/9/bitsy/devflash.c:154,160 – 2000/1213/sys/src/9/bitsy/devflash.c:152,158 | ||
| 2000/1207 | typedef struct FPart FPart; struct FPart { | |
| 2000/1213 | char name[NAMELEN-4]; | |
| 2000/1207 | ulong start; ulong end; | |
| 2000/1111 | }; | |
| 2000/1211/sys/src/9/bitsy/devflash.c:168,174 – 2000/1213/sys/src/9/bitsy/devflash.c:166,172 | ||
| 2000/1207 | gen(Chan *c, Dirtab*, int, int i, Dir *dp) { Qid q; | |
| 2000/1213 | char buf[NAMELEN]; | |
| 2000/1207 | FPart *fp; q.vers = 0; | |
| 2000/1211/sys/src/9/bitsy/devflash.c:191,215 – 2000/1213/sys/src/9/bitsy/devflash.c:189,214 | ||
| 2000/1207 | return 1; } | |
| 2000/1213 | /* second level contains all partitions and their control files */ | |
| 2000/1207 | switch(i) { case DEVDOTDOT: q.path = CHDIR; devdir(c, q, "#F", 0, eve, CHDIR|0555, dp); break; | |
| 2000/1213 | if(i >= 2*Maxpart) | |
| 2000/1207 | return -1; | |
| 2000/1213 | fp = &part[i>>1]; | |
| 2000/1207 | if(fp->name[0] == 0) return 0; | |
| 2000/1213 | if(i & 1){ q.path = FQID(i>>1, Qfdata); devdir(c, q, fp->name, fp->end-fp->start, eve, 0660, dp); } else { snprint(buf, sizeof(buf), "%sctl", fp->name); q.path = FQID(i>>1, Qfctl); devdir(c, q, buf, 0, eve, 0660, dp); } | |
| 2000/1207 | break; } return 1; | |
| 2000/1211/sys/src/9/bitsy/devflash.c:229,245 – 2000/1213/sys/src/9/bitsy/devflash.c:228,253 | ||
| 2000/1207 | } static void | |
| 2000/1213 | addpart(FPart *fp, char *name, ulong start, ulong end) | |
| 2000/1207 | { int i; | |
| 2000/1213 | if(strlen(name) > NAMELEN-3) error("name too long"); if(fp == nil){ if(start >= flash.size || end > flash.size) error(Ebadarg); } else { start += fp->start; end += fp->start; if(start >= fp->end || end > fp->end) error(Ebadarg); } | |
| 2000/1207 | if(blockstart(start) != start) error("must start on erase boundary"); if(blockstart(end) != end && end != flash.size) error("must end on erase boundary"); | |
| 2000/1213 | ||
| 2000/1207 | fp = findpart(name); if(fp != nil) error(Eexist); | |
| 2000/1211/sys/src/9/bitsy/devflash.c:255,268 – 2000/1213/sys/src/9/bitsy/devflash.c:263,271 | ||
| 2000/1207 | } static void | |
| 2000/1213 | rempart(FPart *fp) | |
| 2000/1207 | { | |
| 2000/1213 | fp->name[0] = 0; | |
| 2000/1207 | } | |
| 2000/1111 | void | |
| 2000/1211/sys/src/9/bitsy/devflash.c:280,286 – 2000/1213/sys/src/9/bitsy/devflash.c:283,289 | ||
| 2000/1117 | } flash.bootprotect = 1; | |
| 2000/1207 |
| |
| 2000/1213 | addpart(nil, "flash", 0, flash.size); | |
| 2000/1111 | } static Chan* | |
| 2000/1211/sys/src/9/bitsy/devflash.c:315,327 – 2000/1213/sys/src/9/bitsy/devflash.c:318,378 | ||
| 2000/1111 | { } | |
| 2000/1213 | static long flashctlread(FPart *fp, void* a, long n, vlong off) | |
| 2000/1111 | { | |
| 2000/1117 | char *buf, *p, *e; int i; | |
| 2000/1207 |
| |
| 2000/1213 | ulong addr, end; | |
| 2000/1117 | ||
| 2000/1213 | buf = smalloc(1024); e = buf + 1024; p = seprint(buf, e, "0x%-9lux 0x%-9lux 0x%-9lux 0x%-9lux\n", fp->end-fp->start, flash.wbsize, flash.manid, flash.devid); addr = fp->start; for(i = 0; i < flash.nr && addr < fp->end; i++) if(flash.r[i].addr <= addr && flash.r[i].end > addr){ if(fp->end <= flash.r[i].end) end = fp->end; else end = flash.r[i].end; p = seprint(p, e, "0x%-9lux 0x%-9lux 0x%-9lux\n", addr, (end-addr)/flash.r[i].size, flash.r[i].size); addr = end; } n = readstr(off, a, n, buf); free(buf); return n; } static long flashdataread(FPart *fp, void* a, long n, vlong off) { rlock(&flash); if(waserror()){ runlock(&flash); nexterror(); } if(fp->name[0] == 0) error("partition vanished"); if(!iseve()) error(Eperm); off += fp->start; if(off >= fp->end) n = 0; if(off+n >= fp->end) n = fp->end - off; if(n > 0) memmove(a, ((uchar*)FLASHZERO)+off, n); runlock(&flash); poperror(); return n; } static long flashread(Chan* c, void* a, long n, vlong off) { | |
| 2000/1117 | if(c->qid.path&CHDIR) | |
| 2000/1207 | return devdirread(c, a, n, nil, 0, gen); switch(FTYPE(c->qid.path)){ | |
| 2000/1211/sys/src/9/bitsy/devflash.c:328,363 – 2000/1213/sys/src/9/bitsy/devflash.c:379,388 | ||
| 2000/1117 | default: error(Eperm); case Qfctl: | |
| 2000/1213 | n = flashctlread(FPART(c->qid.path), a, n, off); | |
| 2000/1117 | break; | |
| 2000/1207 |
| |
| 2000/1117 |
| |
| 2000/1207 |
| |
| 2000/1117 |
| |
| 2000/1213 | case Qfdata: n = flashdataread(FPART(c->qid.path), a, n, off); | |
| 2000/1117 | break; } | |
| 2000/1111 | return n; | |
| 2000/1211/sys/src/9/bitsy/devflash.c:412,423 – 2000/1213/sys/src/9/bitsy/devflash.c:437,450 | ||
| 2000/1117 | } static long | |
| 2000/1213 | flashctlwrite(FPart *fp, char *p, long n) | |
| 2000/1117 | { Cmdbuf *cmd; | |
| 2000/1207 | ulong off; | |
| 2000/1117 | ||
| 2000/1213 | if(fp == nil) panic("flashctlwrite"); | |
| 2000/1117 | cmd = parsecmd(p, n); wlock(&flash); if(waserror()){ | |
| 2000/1211/sys/src/9/bitsy/devflash.c:425,440 – 2000/1213/sys/src/9/bitsy/devflash.c:452,461 | ||
| 2000/1117 | nexterror(); } if(strcmp(cmd->f[0], "erase") == 0){ | |
| 2000/1207 |
| |
| 2000/1213 | case 2: /* erase a single block in the partition */ off = atoi(cmd->f[1]); | |
| 2000/1207 | off += fp->start; if(off >= fp->end) error("region not in partition"); | |
| 2000/1211/sys/src/9/bitsy/devflash.c:443,449 – 2000/1213/sys/src/9/bitsy/devflash.c:464,470 | ||
| 2000/1207 | bootprotect(off); (*flash.alg->erase)(off); break; | |
| 2000/1213 | case 1: | |
| 2000/1207 | /* erase the whole partition */ bootprotect(fp->start); for(off = fp->start; off < fp->end; off = blockend(off)) | |
| 2000/1211/sys/src/9/bitsy/devflash.c:455,465 – 2000/1213/sys/src/9/bitsy/devflash.c:476,484 | ||
| 2000/1207 | } else if(strcmp(cmd->f[0], "add") == 0){ if(cmd->nf != 4) error(Ebadarg); | |
| 2000/1213 | addpart(fp, cmd->f[1], strtoul(cmd->f[2], nil, 0), strtoul(cmd->f[3], nil, 0)); | |
| 2000/1207 | } else if(strcmp(cmd->f[0], "remove") == 0){ | |
| 2000/1117 |
| |
| 2000/1207 |
| |
| 2000/1213 | rempart(fp); | |
| 2000/1117 | } else if(strcmp(cmd->f[0], "protectboot") == 0){ if(cmd->nf == 0 || strcmp(cmd->f[1], "off") != 0) flash.bootprotect = 1; | |
| 2000/1211/sys/src/9/bitsy/devflash.c:475,493 – 2000/1213/sys/src/9/bitsy/devflash.c:494,516 | ||
| 2000/1117 | } static long | |
| 2000/1207 |
| |
| 2000/1213 | flashdatawrite(FPart *fp, uchar *p, long n, long off) | |
| 2000/1117 | { uchar *end; int m; | |
| 2000/1213 | int on; | |
| 2000/1207 | long ooff; | |
| 2000/1117 |
| |
| 2000/1207 |
| |
| 2000/1213 | uchar *buf; | |
| 2000/1117 | ||
| 2000/1207 |
| |
| 2000/1213 | if(fp == nil) panic("flashctlwrite"); | |
| 2000/1117 | ||
| 2000/1213 | buf = nil; | |
| 2000/1117 | wlock(&flash); if(waserror()){ wunlock(&flash); | |
| 2000/1213 | if(buf != nil) free(buf); | |
| 2000/1117 | nexterror(); } | |
| 2000/1211/sys/src/9/bitsy/devflash.c:496,503 – 2000/1213/sys/src/9/bitsy/devflash.c:519,525 | ||
| 2000/1207 | if(!iseve()) error(Eperm); | |
| 2000/1213 | /* can't cross partition boundaries */ | |
| 2000/1207 | off += fp->start; if(off >= fp->end || off+n > fp->end || n <= 0) error(Ebadarg); | |
| 2000/1211/sys/src/9/bitsy/devflash.c:505,512 – 2000/1213/sys/src/9/bitsy/devflash.c:527,556 | ||
| 2000/1117 | /* make sure we're not writing the boot sector */ bootprotect(off); | |
| 2000/1213 | on = n; /* * get the data into kernel memory to avoid faults during writing. * if write is not on a quad boundary or not a multiple of 4 bytes, * extend with data already in flash. */ buf = smalloc(n+8); m = off & 3; if(m){ *(ulong*)buf = flash.p[(off)>>2]; n += m; off -= m; } if(n & 3){ n -= n & 3; *(ulong*)(&buf[n]) = flash.p[(off+n)>>2]; n += 4; } memmove(&buf[m], p, on); | |
| 2000/1117 | /* (*flash.alg->write) can't cross blocks */ | |
| 2000/1207 | ooff = off; | |
| 2000/1213 | p = buf; | |
| 2000/1117 | for(end = p + n; p < end; p += m){ m = blockend(off) - off; if(m > end - p) | |
| 2000/1211/sys/src/9/bitsy/devflash.c:513,531 – 2000/1213/sys/src/9/bitsy/devflash.c:557,575 | ||
| 2000/1117 | m = end - p; | |
| 2000/1209 | if(m > Maxwchunk) m = Maxwchunk; | |
| 2000/1213 | (*flash.alg->write)(p, m, off); | |
| 2000/1117 | off += m; } /* make sure write succeeded */ | |
| 2000/1213 | if(memcmp(buf, &flash.p[ooff>>2], n) != 0) | |
| 2000/1117 | error("written bytes don't match"); wunlock(&flash); | |
| 2000/1213 | free(buf); | |
| 2000/1117 | poperror(); | |
| 2000/1213 | return on; | |
| 2000/1117 | } | |
| 2000/1111 | static long | |
| 2000/1211/sys/src/9/bitsy/devflash.c:541,549 – 2000/1213/sys/src/9/bitsy/devflash.c:585,595 | ||
| 2000/1117 | default: panic("flashwrite"); case Qfctl: | |
| 2000/1207 |
| |
| 2000/1213 | n = flashctlwrite(FPART(c->qid.path), a, n); break; case Qfdata: n = flashdatawrite(FPART(c->qid.path), a, n, off); break; | |
| 2000/1117 | } | |
| 2000/1111 | return n; } | |