| plan 9 kernel history: overview | file list | diff list |
2000/1207/bitsy/devflash.c (diff list | history)
| 2000/1117/sys/src/9/bitsy/devflash.c:46,51 – 2000/1207/sys/src/9/bitsy/devflash.c:46,54 (short | long | prev | next) | ||
| 2000/1117 | static void afs_erase(ulong); static void afs_write(void*, long, ulong); | |
| 2000/1207 | static ulong blockstart(ulong); static ulong blockend(ulong); | |
| 2000/1117 | FlashAlg falg[] = | |
| 2000/1107 | { | |
| 2000/1117 | { 1, "Intel/Sharp Extended", ise_id, ise_erase, ise_write }, | |
| 2000/1117/sys/src/9/bitsy/devflash.c:134,148 – 2000/1207/sys/src/9/bitsy/devflash.c:137,265 | ||
| 2000/1111 | enum { | |
| 2000/1117 |
| |
| 2000/1207 | Qtopdir, Q2nddir, Qfctl, Qfpart, Maxpart= 8, | |
| 2000/1111 | }; | |
| 2000/1117 |
| |
| 2000/1207 | typedef struct FPart FPart; struct FPart { char name[NAMELEN]; ulong start; ulong end; | |
| 2000/1111 | }; | |
| 2000/1207 | static FPart part[Maxpart]; | |
| 2000/1111 | ||
| 2000/1207 | #define FQID(p,q) ((p)<<8|(q)) #define FTYPE(q) ((q) & 0xff) #define FPART(q) (&part[(q) >>8]) static int gen(Chan *c, Dirtab*, int, int i, Dir *dp) { Qid q; char buf[32]; FPart *fp; q.vers = 0; /* top level directory contains the name of the network */ if(c->qid.path == CHDIR){ switch(i){ case DEVDOTDOT: q.path = CHDIR; devdir(c, q, ".", 0, eve, CHDIR|0555, dp); break; case 0: q.path = CHDIR | Q2nddir; strcpy(buf, "flash"); devdir(c, q, buf, 0, eve, CHDIR|0555, dp); break; default: return -1; } return 1; } /* second level contains ctl plus all partitions */ switch(i) { case DEVDOTDOT: q.path = CHDIR; devdir(c, q, "#F", 0, eve, CHDIR|0555, dp); break; case 0: q.path = Qfctl; devdir(c, q, "ctl", 0, eve, 0666, dp); break; default: i -= 1; if(i >= Maxpart) return -1; fp = &part[i]; if(fp->name[0] == 0) return 0; q.path = FQID(i, Qfpart); devdir(c, q, fp->name, fp->end-fp->start, eve, 0660, dp); break; } return 1; } static FPart* findpart(char *name) { int i; for(i = 0; i < Maxpart; i++) if(strcmp(name, part[i].name) == 0) break; if(i >= Maxpart) return nil; return &part[i]; } static void addpart(char *name, ulong start, ulong end) { int i; FPart *fp; if(start >= flash.size || end > flash.size) error(Ebadarg); if(blockstart(start) != start) error("must start on erase boundary"); if(blockstart(end) != end && end != flash.size) error("must end on erase boundary"); fp = findpart(name); if(fp != nil) error(Eexist); for(i = 0; i < Maxpart; i++) if(part[i].name[0] == 0) break; if(i == Maxpart) error("no more partitions"); fp = &part[i]; strncpy(fp->name, name, sizeof(fp->name)-1); fp->start = start; fp->end = end; } static void rempart(char *name) { FPart *fp; /* can't remove the total partition */ fp = findpart(name); if(fp != nil) fp->name[0] = 0; } | |
| 2000/1111 | void flashinit(void) { | |
| 2000/1117/sys/src/9/bitsy/devflash.c:157,162 – 2000/1207/sys/src/9/bitsy/devflash.c:274,281 | ||
| 2000/1117 | break; } flash.bootprotect = 1; | |
| 2000/1207 | addpart("whole", 0, flash.size); | |
| 2000/1111 | } static Chan* | |
| 2000/1117/sys/src/9/bitsy/devflash.c:168,180 – 2000/1207/sys/src/9/bitsy/devflash.c:287,299 | ||
| 2000/1111 | static int flashwalk(Chan* c, char* name) { | |
| 2000/1207 | return devwalk(c, name, nil, 0, gen); | |
| 2000/1111 | } static void flashstat(Chan* c, char* dp) { | |
| 2000/1207 | devstat(c, dp, nil, 0, gen); | |
| 2000/1111 | } static Chan* | |
| 2000/1117/sys/src/9/bitsy/devflash.c:183,189 – 2000/1207/sys/src/9/bitsy/devflash.c:302,308 | ||
| 2000/1111 | omode = openmode(omode); if(strcmp(up->user, eve)!=0) error(Eperm); | |
| 2000/1207 | return devopen(c, omode, nil, 0, gen); | |
| 2000/1111 | } static void | |
| 2000/1117/sys/src/9/bitsy/devflash.c:196,205 – 2000/1207/sys/src/9/bitsy/devflash.c:315,325 | ||
| 2000/1111 | { | |
| 2000/1117 | char *buf, *p, *e; int i; | |
| 2000/1207 | FPart *fp; | |
| 2000/1117 | if(c->qid.path&CHDIR) | |
| 2000/1207 | return devdirread(c, a, n, nil, 0, gen); switch(FTYPE(c->qid.path)){ | |
| 2000/1117 | default: error(Eperm); case Qfctl: | |
| 2000/1117/sys/src/9/bitsy/devflash.c:213,231 – 2000/1207/sys/src/9/bitsy/devflash.c:333,356 | ||
| 2000/1117 | n = readstr(off, a, n, buf); free(buf); break; | |
| 2000/1207 | case Qfpart: fp = FPART(c->qid.path); | |
| 2000/1117 | rlock(&flash); if(waserror()){ runlock(&flash); nexterror(); } | |
| 2000/1207 | 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); | |
| 2000/1117 | runlock(&flash); poperror(); break; | |
| 2000/1117/sys/src/9/bitsy/devflash.c:247,253 – 2000/1207/sys/src/9/bitsy/devflash.c:372,378 | ||
| 2000/1117 | error("writing over boot loader disallowed"); } | |
| 2000/1207 | static ulong | |
| 2000/1117 | blockstart(ulong addr) { FlashRegion *r, *e; | |
| 2000/1117/sys/src/9/bitsy/devflash.c:264,270 – 2000/1207/sys/src/9/bitsy/devflash.c:389,395 | ||
| 2000/1117 | return (ulong)-1; } | |
| 2000/1207 | static ulong | |
| 2000/1117 | blockend(ulong addr) { FlashRegion *r, *e; | |
| 2000/1117/sys/src/9/bitsy/devflash.c:285,291 – 2000/1207/sys/src/9/bitsy/devflash.c:410,417 | ||
| 2000/1117 | flashctlwrite(char *p, long n) { Cmdbuf *cmd; | |
| 2000/1207 | ulong off; FPart *fp; | |
| 2000/1117 | cmd = parsecmd(p, n); wlock(&flash); | |
| 2000/1117/sys/src/9/bitsy/devflash.c:294,306 – 2000/1207/sys/src/9/bitsy/devflash.c:420,460 | ||
| 2000/1117 | nexterror(); } if(strcmp(cmd->f[0], "erase") == 0){ | |
| 2000/1207 | if(cmd->nf < 2) error(Ebadarg); fp = findpart(cmd->f[1]); if(fp == nil) error("no such partition"); switch(cmd->nf){ case 3: /* erase a single block */ off = atoi(cmd->f[2]); off += fp->start; if(off >= fp->end) error("region not in partition"); if(off != blockstart(off)) error("erase must be a block boundary"); bootprotect(off); (*flash.alg->erase)(off); break; case 2: /* erase the whole partition */ bootprotect(fp->start); for(off = fp->start; off < fp->end; off = blockend(off)) (*flash.alg->erase)(off); break; default: error(Ebadarg); } } else if(strcmp(cmd->f[0], "add") == 0){ if(cmd->nf != 4) error(Ebadarg); addpart(cmd->f[1], strtoul(cmd->f[2], nil, 0), strtoul(cmd->f[3], nil, 0)); } else if(strcmp(cmd->f[0], "remove") == 0){ | |
| 2000/1117 | if(cmd->nf != 2) error(Ebadarg); | |
| 2000/1207 | rempart(cmd->f[1]); | |
| 2000/1117 | } else if(strcmp(cmd->f[0], "protectboot") == 0){ if(cmd->nf == 0 || strcmp(cmd->f[1], "off") != 0) flash.bootprotect = 1; | |
| 2000/1117/sys/src/9/bitsy/devflash.c:316,332 – 2000/1207/sys/src/9/bitsy/devflash.c:470,484 | ||
| 2000/1117 | } static long | |
| 2000/1207 | flashdatawrite(Chan *c, uchar *p, long n, long off) | |
| 2000/1117 | { uchar *end; int m; | |
| 2000/1207 | long ooff; | |
| 2000/1117 | uchar *op = p; | |
| 2000/1207 | FPart *fp; | |
| 2000/1117 |
| |
| 2000/1207 | fp = FPART(c->qid.path); | |
| 2000/1117 | wlock(&flash); if(waserror()){ | |
| 2000/1117/sys/src/9/bitsy/devflash.c:334,343 – 2000/1207/sys/src/9/bitsy/devflash.c:486,507 | ||
| 2000/1117 | nexterror(); } | |
| 2000/1207 | if(fp->name[0] == 0) error("partition vanished"); if(!iseve()) error(Eperm); if((off & 0x3) || (n & 0x3)) error("only quad writes"); off += fp->start; if(off >= fp->end || off+n > fp->end || n <= 0) error(Ebadarg); | |
| 2000/1117 | /* make sure we're not writing the boot sector */ bootprotect(off); /* (*flash.alg->write) can't cross blocks */ | |
| 2000/1207 | ooff = off; | |
| 2000/1117 | for(end = p + n; p < end; p += m){ m = blockend(off) - off; if(m > end - p) | |
| 2000/1117/sys/src/9/bitsy/devflash.c:365,377 – 2000/1207/sys/src/9/bitsy/devflash.c:529,541 | ||
| 2000/1117 | if(!iseve()) error(Eperm); | |
| 2000/1207 | switch(FTYPE(c->qid.path)){ | |
| 2000/1117 | default: panic("flashwrite"); case Qfctl: return flashctlwrite(a, n); | |
| 2000/1207 | case Qfpart: return flashdatawrite(c, a, n, off); | |
| 2000/1117 | } | |
| 2000/1111 | return n; } | |