1 #include "u.h" 2 #include "../port/lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "../port/error.h" 7 8 /* 9 * flash memory 10 */ 11 12 #include "../port/flashif.h" 13 14 typedef struct Flashtype Flashtype; 15 struct Flashtype { 16 char* name; 17 int (*reset)(Flash*); 18 Flashtype* next; 19 }; 20 21 enum { 22 Nbanks = 2, 23 }; 24 25 static struct 26 { 27 Flash* card[Nbanks]; /* actual card type, reset for access */ 28 Flashtype* types; /* possible card types */ 29 }flash; 30 31 enum{ 32 Qtopdir, 33 Qflashdir, 34 Qdata, 35 Qctl, 36 }; 37 38 #define TYPE(q) ((ulong)(q) & 0xFF) 39 #define PART(q) ((ulong)(q)>>8) 40 #define QID(p,t) (((p)<<8) | (t)) 41 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); 49 50 static char Eprotect[] = "flash region protected"; 51 52 static int 53 flash2gen(Chan *c, ulong p, Dir *dp) 54 { 55 Flashpart *fp; 56 Flash *f; 57 Qid q; 58 int mode; 59 60 f = flash.card[c->dev]; 61 fp = &f->part[PART(p)]; 62 if(fp->name == nil) 63 return 0; 64 mkqid(&q, p, 0, QTFILE); 65 switch(TYPE(p)){ 66 case Qdata: 67 mode = 0660; 68 if(f->write == nil) 69 mode = 0440; 70 devdir(c, q, fp->name, fp->end-fp->start, eve, mode, dp); 71 return 1; 72 case Qctl: 73 snprint(up->genbuf, sizeof(up->genbuf), "%sctl", fp->name); 74 devdir(c, q, up->genbuf, 0, eve, 0660, dp); 75 return 1; 76 default: 77 return -1; 78 } 79 } 80 81 static int 82 flashgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp) 83 { 84 Qid q; 85 char *n; 86 87 if(s == DEVDOTDOT){ 88 mkqid(&q, QID(0, Qtopdir), 0, QTDIR); 89 n = "#F"; 90 if(c->dev != 0){ 91 sprint(up->genbuf, "#F%ld", c->dev); 92 n = up->genbuf; 93 } 94 devdir(c, q, n, 0, eve, 0555, dp); 95 return 1; 96 } 97 switch(TYPE(c->qid.path)){ 98 case Qtopdir: 99 if(s != 0) 100 break; 101 mkqid(&q, QID(0, Qflashdir), 0, QTDIR); 102 n = "flash"; 103 if(c->dev != 0){ 104 sprint(up->genbuf, "flash%ld", c->dev); 105 n = up->genbuf; 106 } 107 devdir(c, q, n, 0, eve, 0555, dp); 108 return 1; 109 case Qflashdir: 110 if(s >= 2*nelem(flash.card[c->dev]->part)) 111 return -1; 112 return flash2gen(c, QID(s>>1, s&1?Qctl:Qdata), dp); 113 case Qctl: 114 case Qdata: 115 return flash2gen(c, (ulong)c->qid.path, dp); 116 } 117 return -1; 118 } 119 120 static void 121 flashreset(void) 122 { 123 Flash *f; 124 Flashtype *t; 125 char *e; 126 int bank; 127 128 for(bank = 0; bank < Nbanks; bank++){ 129 f = malloc(sizeof(*f)); 130 if(f == nil){ 131 print("#F%d: can't allocate Flash data\n", bank); 132 return; 133 } 134 f->cmask = ~(ulong)0; 135 if(archflashreset(bank, f) < 0 || f->type == nil || f->addr == nil){ 136 free(f); 137 return; 138 } 139 for(t = flash.types; t != nil; t = t->next) 140 if(strcmp(f->type, t->name) == 0) 141 break; 142 if(t == nil){ 143 iprint("#F%d: no flash driver for type %s (addr %p)\n", bank, f->type, f->addr); 144 free(f); 145 return; 146 } 147 f->reset = t->reset; 148 f->protect = 1; 149 if(f->reset(f) == 0){ 150 flash.card[bank] = f; 151 iprint("#F%d: %s addr 0x%lux len %lud width %d interleave %d\n", bank, f->type, PADDR(f->addr), f->size, f->width, f->interleave); 152 e = flashnewpart(f, "flash", 0, f->size); 153 if(e != nil) 154 panic("#F%d: couldn't init table: %s\n", bank, e); /* shouldn't happen */ 155 }else 156 iprint("#F%d: reset failed (%s)\n", bank, f->type); 157 } 158 } 159 160 static Chan* 161 flashattach(char *spec) 162 { 163 Flash *f; 164 int bank; 165 Chan *c; 166 167 bank = strtol(spec, nil, 0); 168 if(bank < 0 || bank >= Nbanks || 169 (f = flash.card[bank]) == nil || 170 f->attach != nil && f->attach(f) < 0) 171 error(Enodev); 172 c = devattach('F', spec); 173 c->dev = bank; 174 return c; 175 } 176 177 static Walkqid* 178 flashwalk(Chan *c, Chan *nc, char **name, int nname) 179 { 180 return devwalk(c, nc, name, nname, nil, 0, flashgen); 181 } 182 183 static int 184 flashstat(Chan *c, uchar *dp, int n) 185 { 186 return devstat(c, dp, n, nil, 0, flashgen); 187 } 188 189 static Chan* 190 flashopen(Chan *c, int omode) 191 { 192 omode = openmode(omode); 193 switch(TYPE(c->qid.path)){ 194 case Qdata: 195 case Qctl: 196 if(flash.card[c->dev] == nil) 197 error(Enodev); 198 break; 199 } 200 return devopen(c, omode, nil, 0, flashgen); 201 } 202 203 static void 204 flashclose(Chan*) 205 { 206 } 207 208 static long 209 flashread(Chan *c, void *buf, long n, vlong offset) 210 { 211 Flash *f; 212 char *s, *o; 213 Flashpart *fp; 214 Flashregion *r; 215 int i; 216 ulong start, end; 217 218 if(c->qid.type & QTDIR) 219 return devdirread(c, buf, n, nil, 0, flashgen); 220 221 f = flash.card[c->dev]; 222 fp = &f->part[PART(c->qid.path)]; 223 if(fp->name == nil) 224 error(Egreg); 225 switch(TYPE(c->qid.path)){ 226 case Qdata: 227 offset += fp->start; 228 if(offset >= fp->end) 229 return 0; 230 if(offset+n > fp->end) 231 n = fp->end - offset; 232 n = readflash(f, buf, offset, n); 233 if(n < 0) 234 error(Eio); 235 return n; 236 case Qctl: 237 s = malloc(READSTR); 238 if(waserror()){ 239 free(s); 240 nexterror(); 241 } 242 o = seprint(s, s+READSTR, "%#2.2ux %#4.4ux %d %q\n", 243 f->id, f->devid, f->width, f->sort!=nil? f->sort: "nor"); 244 for(i=0; i<f->nr; i++){ 245 r = &f->regions[i]; 246 if(r->start < fp->end && fp->start < r->end){ 247 start = r->start; 248 if(fp->start > start) 249 start = fp->start; 250 end = r->end; 251 if(fp->end < end) 252 end = fp->end; 253 o = seprint(o, s+READSTR, "%#8.8lux %#8.8lux %#8.8lux", start, end, r->erasesize); 254 if(r->pagesize) 255 o = seprint(o, s+READSTR, " %#8.8lux", r->pagesize); 256 o = seprint(o, s+READSTR, "\n"); 257 } 258 } 259 n = readstr(offset, buf, n, s); 260 poperror(); 261 free(s); 262 return n; 263 } 264 error(Egreg); 265 return 0; /* not reached */ 266 } 267 268 enum { 269 CMerase, 270 CMadd, 271 CMremove, 272 CMsync, 273 CMprotectboot, 274 }; 275 276 static Cmdtab flashcmds[] = { 277 {CMerase, "erase", 2}, 278 {CMadd, "add", 0}, 279 {CMremove, "remove", 2}, 280 {CMsync, "sync", 0}, 281 {CMprotectboot, "protectboot", 0}, 282 }; 283 284 static long 285 flashwrite(Chan *c, void *buf, long n, vlong offset) 286 { 287 Cmdbuf *cb; 288 Cmdtab *ct; 289 ulong addr, start, end; 290 char *e; 291 Flashpart *fp; 292 Flashregion *r; 293 Flash *f; 294 295 f = flash.card[c->dev]; 296 fp = &f->part[PART(c->qid.path)]; 297 if(fp->name == nil) 298 error(Egreg); 299 switch(TYPE(c->qid.path)){ 300 case Qdata: 301 if(f->write == nil) 302 error(Eperm); 303 offset += fp->start; 304 if(offset >= fp->end) 305 return 0; 306 if(offset+n > fp->end) 307 n = fp->end - offset; 308 n = writeflash(f, offset, buf, n); 309 if(n < 0) 310 error(Eio); 311 return n; 312 case Qctl: 313 cb = parsecmd(buf, n); 314 if(waserror()){ 315 free(cb); 316 nexterror(); 317 } 318 ct = lookupcmd(cb, flashcmds, nelem(flashcmds)); 319 switch(ct->index){ 320 case CMerase: 321 if(strcmp(cb->f[1], "all") != 0){ 322 addr = flashaddr(f, fp, cb->f[1]); 323 r = flashregion(f, addr); 324 if(r == nil) 325 error("nonexistent flash region"); 326 if(addr%r->erasesize != 0) 327 error("invalid erase block address"); 328 eraseflash(f, r, addr); 329 }else if(fp->start == 0 && fp->end == f->size && f->eraseall != nil){ 330 eraseflash(f, nil, 0); 331 }else{ 332 for(addr = fp->start; addr < fp->end; addr += r->erasesize){ 333 r = flashregion(f, addr); 334 if(r == nil) 335 error("nonexistent flash region"); 336 if(addr%r->erasesize != 0) 337 error("invalid erase block address"); 338 eraseflash(f, r, addr); 339 } 340 } 341 break; 342 case CMadd: 343 if(cb->nf < 3) 344 error(Ebadarg); 345 start = flashaddr(f, fp, cb->f[2]); 346 if(cb->nf > 3 && strcmp(cb->f[3], "end") != 0) 347 end = flashaddr(f, fp, cb->f[3]); 348 else 349 end = fp->end; 350 if(start > end || start >= fp->end || end > fp->end) 351 error(Ebadarg); 352 e = flashnewpart(f, cb->f[1], start, end); 353 if(e != nil) 354 error(e); 355 break; 356 case CMremove: 357 /* TO DO */ 358 break; 359 case CMprotectboot: 360 if(cb->nf > 1 && strcmp(cb->f[1], "off") == 0) 361 f->protect = 0; 362 else 363 f->protect = 1; 364 break; 365 case CMsync: 366 /* TO DO? */ 367 break; 368 default: 369 error(Ebadarg); 370 } 371 poperror(); 372 free(cb); 373 return n; 374 } 375 error(Egreg); 376 return 0; /* not reached */ 377 } 378 379 static char* 380 flashnewpart(Flash *f, char *name, ulong start, ulong end) 381 { 382 Flashpart *fp, *empty; 383 int i; 384 385 empty = nil; 386 for(i = 0; i < nelem(f->part); i++){ 387 fp = &f->part[i]; 388 if(fp->name == nil){ 389 if(empty == nil) 390 empty = fp; 391 }else if(strcmp(fp->name, name) == 0) 392 return Eexist; 393 } 394 if((fp = empty) == nil) 395 return "partition table full"; 396 fp->name = strdup(name); 397 if(fp->name == nil) 398 return Enomem; 399 fp->start = start; 400 fp->end = end; 401 return nil; 402 } 403 404 static ulong 405 flashaddr(Flash *f, Flashpart *fp, char *s) 406 { 407 Flashregion *r; 408 ulong addr; 409 410 addr = strtoul(s, &s, 0); 411 if(*s) 412 error(Ebadarg); 413 if(fp->name == nil) 414 error("partition removed"); 415 addr += fp->start; 416 r = flashregion(f, addr); 417 if(r != nil && addr%r->erasesize != 0) 418 error("invalid erase unit address"); 419 if(addr < fp->start || addr > fp->end || addr > f->size) 420 error(Ebadarg); 421 return addr; 422 } 423 424 static Flashregion* 425 flashregion(Flash *f, ulong a) 426 { 427 int i; 428 Flashregion *r; 429 430 for(i=0; i<f->nr; i++){ 431 r = &f->regions[i]; 432 if(r->start <= a && a < r->end) 433 return r; 434 } 435 return nil; 436 } 437 438 Dev flashdevtab = { 439 'F', 440 "flash", 441 442 flashreset, 443 devinit, 444 devshutdown, 445 flashattach, 446 flashwalk, 447 flashstat, 448 flashopen, 449 devcreate, 450 flashclose, 451 flashread, 452 devbread, 453 flashwrite, 454 devbwrite, 455 devremove, 456 devwstat, 457 }; 458 459 /* 460 * called by flash card types named in link section (eg, flashamd.c) 461 */ 462 void 463 addflashcard(char *name, int (*reset)(Flash*)) 464 { 465 Flashtype *f, **l; 466 467 f = (Flashtype*)malloc(sizeof(*f)); 468 f->name = name; 469 f->reset = reset; 470 f->next = nil; 471 for(l = &flash.types; *l != nil; l = &(*l)->next) 472 ; 473 *l = f; 474 } 475 476 static long 477 readflash(Flash *f, void *buf, long offset, int n) 478 { 479 int r, width, wmask; 480 uchar tmp[16]; 481 uchar *p; 482 ulong o; 483 484 if(offset < 0 || offset+n > f->size) 485 error(Ebadarg); 486 qlock(f); 487 if(waserror()){ 488 qunlock(f); 489 nexterror(); 490 } 491 if(f->read != nil){ 492 width = f->width; 493 wmask = width-1; 494 p = buf; 495 if(offset&wmask) { 496 o = offset & ~wmask; 497 if(f->read(f, o, (ulong*)tmp, width) < 0) 498 error(Eio); 499 memmove(tmp, (uchar*)f->addr+o, width); 500 for(; n > 0 && offset&wmask; n--) 501 *p++ = tmp[offset++&wmask]; 502 } 503 r = n&wmask; 504 n &= ~wmask; 505 if(n){ 506 if(f->read(f, offset, (ulong*)p, n) < 0) 507 error(Eio); 508 offset += n; 509 p += n; 510 } 511 if(r){ 512 if(f->read(f, offset, (ulong*)tmp, width)) 513 error(Eio); 514 memmove(p, tmp, r); 515 } 516 }else 517 memmove(buf, (uchar*)f->addr+offset, n); /* assumes hardware supports byte access */ 518 poperror(); 519 qunlock(f); 520 return n; 521 } 522 523 static long 524 writeflash(Flash *f, long offset, void *buf, int n) 525 { 526 uchar tmp[16]; 527 uchar *p; 528 ulong o; 529 int r, width, wmask; 530 Flashregion *rg; 531 532 if(f->write == nil || offset < 0 || offset+n > f->size) 533 error(Ebadarg); 534 rg = flashregion(f, offset); 535 if(f->protect && rg != nil && rg->start == 0 && offset < rg->erasesize) 536 error(Eprotect); 537 width = f->width; 538 wmask = width-1; 539 qlock(f); 540 archflashwp(f, 0); 541 if(waserror()){ 542 archflashwp(f, 1); 543 qunlock(f); 544 nexterror(); 545 } 546 p = buf; 547 if(offset&wmask){ 548 o = offset & ~wmask; 549 if(f->read != nil){ 550 if(f->read(f, o, tmp, width) < 0) 551 error(Eio); 552 }else 553 memmove(tmp, (uchar*)f->addr+o, width); 554 for(; n > 0 && offset&wmask; n--) 555 tmp[offset++&wmask] = *p++; 556 if(f->write(f, o, tmp, width) < 0) 557 error(Eio); 558 } 559 r = n&wmask; 560 n &= ~wmask; 561 if(n){ 562 if(f->write(f, offset, p, n) < 0) 563 error(Eio); 564 offset += n; 565 p += n; 566 } 567 if(r){ 568 if(f->read != nil){ 569 if(f->read(f, offset, tmp, width) < 0) 570 error(Eio); 571 }else 572 memmove(tmp, (uchar*)f->addr+offset, width); 573 memmove(tmp, p, r); 574 if(f->write(f, offset, tmp, width) < 0) 575 error(Eio); 576 } 577 poperror(); 578 archflashwp(f, 1); 579 qunlock(f); 580 return n; 581 } 582 583 static void 584 eraseflash(Flash *f, Flashregion *r, ulong addr) 585 { 586 int rv; 587 588 if(f->protect && r != nil && r->start == 0 && addr < r->erasesize) 589 error(Eprotect); 590 qlock(f); 591 archflashwp(f, 0); 592 if(waserror()){ 593 archflashwp(f, 1); 594 qunlock(f); 595 nexterror(); 596 } 597 if(r == nil){ 598 if(f->eraseall != nil) 599 rv = f->eraseall(f); 600 else 601 rv = -1; 602 }else 603 rv = f->erasezone(f, r, addr); 604 if(rv < 0) 605 error(Eio); 606 poperror(); 607 archflashwp(f, 1); 608 qunlock(f); 609 } 610 611 /* 612 * flash access taking width and interleave into account 613 */ 614 int 615 flashget(Flash *f, ulong a) 616 { 617 switch(f->width){ 618 default: 619 return ((uchar*)f->addr)[a<<f->bshift]; 620 case 2: 621 return ((ushort*)f->addr)[a]; 622 case 4: 623 return ((ulong*)f->addr)[a]; 624 } 625 } 626 627 void 628 flashput(Flash *f, ulong a, int v) 629 { 630 switch(f->width){ 631 default: 632 ((uchar*)f->addr)[a<<f->bshift] = v; 633 break; 634 case 2: 635 ((ushort*)f->addr)[a] = v; 636 break; 637 case 4: 638 ((ulong*)f->addr)[a] = v; 639 break; 640 } 641 } 642