devflash.c 20 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024
  1. /*
  2. * flash memory file system
  3. *
  4. * implements partitions
  5. */
  6. #include "u.h"
  7. #include "../port/lib.h"
  8. #include "mem.h"
  9. #include "dat.h"
  10. #include "fns.h"
  11. #include "../port/error.h"
  12. enum {
  13. Nflash = 2,
  14. Maxwchunk= 1024, /* max. chunk written by one call to falg->write */
  15. };
  16. /*
  17. * Flashes are either 8 or 16 bits wide. On some installations (e.g., the
  18. * bitsy, they are interleaved: address 0 is in the first chip, address 2
  19. * on the second, address 4 on the first, etc.
  20. * We define Funit as the unit that matches the width of a single flash chip,
  21. * so Funit is either `uchar' or `ushort' (I haven't seen 32-bit wide flashes),
  22. * and we define Fword as the unit that matches a set of interleaved Funits.
  23. * We access interleaved flashes simultaneously, by doing single reads and
  24. * writes to both. The macro `mirror' takes a command and replicates it for
  25. * this purpose.
  26. * The Blast board has a non-interleaved 16-bit wide flash. When doing
  27. * writes to it, we must swap bytes.
  28. */
  29. typedef struct FlashAlg FlashAlg;
  30. typedef struct Flash Flash;
  31. typedef struct FlashRegion FlashRegion;
  32. typedef ushort Funit;
  33. #define mirror(x) ((x)<<16|(x))
  34. #define reg(x) (x)
  35. typedef ushort Fword;
  36. #define Wshift 1
  37. #define fromendian(x) (x)
  38. /*
  39. * hardware info about a device
  40. */
  41. typedef struct {
  42. ulong port;
  43. int size;
  44. } Devport;
  45. #define NCONFOPT 8
  46. struct DevConf
  47. {
  48. RWlock; /* write: configure/unconfigure/suspend; read: normal access */
  49. ulong mem; /* mapped memory address */
  50. Devport *ports; /* ports[0]: mapped i/o regs, access size */
  51. int nports; /* always 1 for the bitsy */
  52. int size;
  53. int itype; /* type of interrupt */
  54. ulong intnum; /* interrupt number */
  55. char *type; /* card type, mallocated */
  56. int nopt; /* number of options */
  57. char *opt[NCONFOPT]; /* options */
  58. };
  59. /* this defines a contiguous set of erase blocks of one size */
  60. struct FlashRegion
  61. {
  62. ulong addr; /* start of region */
  63. ulong end; /* end of region + 1 */
  64. ulong n; /* number of blocks */
  65. ulong size; /* size of each block */
  66. };
  67. /* this defines a particular access algorithm */
  68. struct FlashAlg
  69. {
  70. int id;
  71. char *name;
  72. void (*identify)(Flash*); /* identify device */
  73. void (*erase)(Flash*, ulong); /* erase a region */
  74. void (*write)(Flash*, void*, long, ulong); /* write a region */
  75. };
  76. struct Flash
  77. {
  78. DevConf; /* contains size */
  79. RWlock;
  80. Fword *p;
  81. ushort algid; /* access algorithm */
  82. FlashAlg *alg;
  83. ushort manid; /* manufacturer id */
  84. ushort devid; /* device id */
  85. int wbsize; /* size of write buffer */
  86. ulong nr; /* number of regions */
  87. uchar bootprotect;
  88. ulong offset; /* beginning offset of this flash */
  89. FlashRegion r[32];
  90. };
  91. static void ise_id(Flash*);
  92. static void ise_erase(Flash*, ulong);
  93. static void ise_write(Flash*, void*, long, ulong);
  94. static void afs_id(Flash*);
  95. static void afs_erase(Flash*, ulong);
  96. static void afs_write(Flash*, void*, long, ulong);
  97. static ulong blockstart(Flash*, ulong);
  98. static ulong blockend(Flash*, ulong);
  99. FlashAlg falg[] =
  100. {
  101. { 1, "Intel/Sharp Extended", ise_id, ise_erase, ise_write },
  102. { 2, "AMD/Fujitsu Standard", afs_id, afs_erase, afs_write },
  103. };
  104. Flash flashes[Nflash];
  105. /*
  106. * common flash interface
  107. */
  108. static uchar
  109. cfigetc(Flash *flash, int off)
  110. {
  111. uchar rv;
  112. flash->p[reg(0x55)] = mirror(0x98);
  113. rv = flash->p[reg(off)];
  114. flash->p[reg(0x55)] = mirror(0xFF);
  115. return rv;
  116. }
  117. static ushort
  118. cfigets(Flash *flash, int off)
  119. {
  120. return (cfigetc(flash, off+1)<<8)|cfigetc(flash, off);
  121. }
  122. static ulong
  123. cfigetl(Flash *flash, int off)
  124. {
  125. return (cfigetc(flash, off+3)<<24)|(cfigetc(flash, off+2)<<16)|
  126. (cfigetc(flash, off+1)<<8)|cfigetc(flash, off);
  127. }
  128. static void
  129. cfiquery(Flash *flash)
  130. {
  131. uchar q, r, y;
  132. ulong x, addr;
  133. q = cfigetc(flash, 0x10);
  134. r = cfigetc(flash, 0x11);
  135. y = cfigetc(flash, 0x12);
  136. if(q != 'Q' || r != 'R' || y != 'Y'){
  137. print("cfi query failed: %ux %ux %ux\n", q, r, y);
  138. return;
  139. }
  140. flash->algid = cfigetc(flash, 0x13);
  141. flash->size = (sizeof(Fword)/sizeof(Funit)) * (1<<(cfigetc(flash, 0x27)));
  142. flash->wbsize = (sizeof(Fword)/sizeof(Funit)) * (1<<(cfigetc(flash, 0x2a)));
  143. flash->nr = cfigetc(flash, 0x2c);
  144. if(flash->nr > nelem(flash->r)){
  145. print("cfi reports > %d regions\n", nelem(flash->r));
  146. flash->nr = nelem(flash->r);
  147. }
  148. addr = 0;
  149. for(q = 0; q < flash->nr; q++){
  150. x = cfigetl(flash, q * 4 + 0x2d);
  151. flash->r[q].size = (sizeof(Fword)/sizeof(Funit)) * 256 * (x>>16);
  152. flash->r[q].n = (x&0xffff)+1;
  153. flash->r[q].addr = addr;
  154. addr += flash->r[q].size*flash->r[q].n;
  155. flash->r[q].end = addr;
  156. }
  157. }
  158. /*
  159. * flash device interface
  160. */
  161. enum
  162. {
  163. Qtopdir,
  164. Q2nddir,
  165. Qfctl,
  166. Qfdata,
  167. Maxpart= 8,
  168. };
  169. typedef struct FPart FPart;
  170. struct FPart
  171. {
  172. Flash *flash;
  173. char *name;
  174. char *ctlname;
  175. ulong start;
  176. ulong end;
  177. };
  178. static FPart part[Maxpart];
  179. #define FQID(p,q) ((p)<<8|(q))
  180. #define FTYPE(q) ((q) & 0xff)
  181. #define FPART(q) (&part[(q) >>8])
  182. static int
  183. gen(Chan *c, char*, Dirtab*, int, int i, Dir *dp)
  184. {
  185. Qid q;
  186. FPart *fp;
  187. q.vers = 0;
  188. /* top level directory contains the name of the network */
  189. if(c->qid.path == Qtopdir){
  190. switch(i){
  191. case DEVDOTDOT:
  192. q.path = Qtopdir;
  193. q.type = QTDIR;
  194. devdir(c, q, "#F", 0, eve, DMDIR|0555, dp);
  195. break;
  196. case 0:
  197. q.path = Q2nddir;
  198. q.type = QTDIR;
  199. devdir(c, q, "flash", 0, eve, DMDIR|0555, dp);
  200. break;
  201. default:
  202. return -1;
  203. }
  204. return 1;
  205. }
  206. /* second level contains all partitions and their control files */
  207. switch(i) {
  208. case DEVDOTDOT:
  209. q.path = Qtopdir;
  210. q.type = QTDIR;
  211. devdir(c, q, "#F", 0, eve, DMDIR|0555, dp);
  212. break;
  213. default:
  214. if(i >= 2*Maxpart)
  215. return -1;
  216. fp = &part[i>>1];
  217. if(fp->name == nil)
  218. return 0;
  219. if(i & 1){
  220. q.path = FQID(i>>1, Qfdata);
  221. q.type = QTFILE;
  222. devdir(c, q, fp->name, fp->end-fp->start, eve, 0660, dp);
  223. } else {
  224. q.path = FQID(i>>1, Qfctl);
  225. q.type = QTFILE;
  226. devdir(c, q, fp->ctlname, 0, eve, 0660, dp);
  227. }
  228. break;
  229. }
  230. return 1;
  231. }
  232. static Flash *
  233. findflash(ulong addr)
  234. {
  235. Flash *flash;
  236. for (flash = flashes; flash < flashes + Nflash; flash++)
  237. if(addr >= flash->offset && addr < flash->offset + flash->size)
  238. return flash;
  239. return nil;
  240. }
  241. static FPart*
  242. findpart(char *name)
  243. {
  244. int i;
  245. for(i = 0; i < Maxpart; i++)
  246. if(part[i].name != nil && strcmp(name, part[i].name) == 0)
  247. break;
  248. if(i >= Maxpart)
  249. return nil;
  250. return &part[i];
  251. }
  252. static void
  253. addpart(FPart *fp, char *name, ulong start, ulong end)
  254. {
  255. int i;
  256. char ctlname[64];
  257. Flash *flash;
  258. if (start > end)
  259. error(Ebadarg);
  260. if(fp == nil){
  261. flash = findflash(start);
  262. if (flash == nil || end > flash->offset + flash->size)
  263. error(Ebadarg);
  264. start -= flash->offset;
  265. end -= flash->offset;
  266. } else {
  267. start += fp->start;
  268. end += fp->start;
  269. if(start >= fp->end || end > fp->end){
  270. error(Ebadarg);
  271. }
  272. flash = fp->flash;
  273. }
  274. if(blockstart(flash, start) != start)
  275. error("must start on erase boundary");
  276. if(blockstart(flash, end) != end && end != flash->size)
  277. error("must end on erase boundary");
  278. fp = findpart(name);
  279. if(fp != nil)
  280. error(Eexist);
  281. for(i = 0; i < Maxpart; i++)
  282. if(part[i].name == nil)
  283. break;
  284. if(i == Maxpart)
  285. error("no more partitions");
  286. fp = &part[i];
  287. kstrdup(&fp->name, name);
  288. snprint(ctlname, sizeof ctlname, "%sctl", name);
  289. kstrdup(&fp->ctlname, ctlname);
  290. fp->flash = flash;
  291. fp->start = start;
  292. fp->end = end;
  293. }
  294. static void
  295. rempart(FPart *fp)
  296. {
  297. char *p, *cp;
  298. p = fp->name;
  299. fp->name = nil;
  300. cp = fp->ctlname;
  301. fp->ctlname = nil;
  302. free(p);
  303. free(cp);
  304. }
  305. void
  306. flashinit(void)
  307. {
  308. error("flash driver not ready for use yet");
  309. int i, ctlrno;
  310. char *fname;
  311. ulong offset;
  312. Flash *flash;
  313. offset = 0;
  314. for (ctlrno = 0; ctlrno < Nflash; ctlrno++){
  315. flash = flashes + ctlrno;
  316. // if(plan9config("flash", ctlrno, flash) == 0)
  317. // continue;
  318. flash->p = (Fword*)flash->mem;
  319. cfiquery(flash);
  320. for(i = 0; i < nelem(falg); i++)
  321. if(flash->algid == falg[i].id){
  322. flash->alg = &falg[i];
  323. (*flash->alg->identify)(flash);
  324. break;
  325. }
  326. flash->bootprotect = 1;
  327. flash->offset = offset;
  328. fname = malloc(8);
  329. sprint(fname, "flash%d", ctlrno);
  330. addpart(nil, fname, offset, offset + flash->size);
  331. offset += flash->size;
  332. }
  333. }
  334. static Chan*
  335. flashattach(char* spec)
  336. {
  337. return devattach('F', spec);
  338. }
  339. static Walkqid*
  340. flashwalk(Chan *c, Chan *nc, char **name, int nname)
  341. {
  342. return devwalk(c, nc, name, nname, nil, 0, gen);
  343. }
  344. static int
  345. flashstat(Chan *c, uchar *db, int n)
  346. {
  347. return devstat(c, db, n, nil, 0, gen);
  348. }
  349. static Chan*
  350. flashopen(Chan* c, int omode)
  351. {
  352. omode = openmode(omode);
  353. if(strcmp(up->user, eve)!=0)
  354. error(Eperm);
  355. return devopen(c, omode, nil, 0, gen);
  356. }
  357. static void
  358. flashclose(Chan*)
  359. {
  360. }
  361. static long
  362. flashctlread(FPart *fp, void* a, long n, vlong off)
  363. {
  364. char *buf, *p, *e;
  365. int i;
  366. ulong addr, end;
  367. Flash *flash;
  368. flash = fp->flash;
  369. buf = smalloc(READSTR);
  370. e = buf + READSTR;
  371. p = seprint(buf, e, "0x%-9lux 0x%-9lux 0x%-9lux 0x%-9x 0x%-9ux 0x%-9ux\n",
  372. flash->offset, fp->start, fp->end-fp->start, flash->wbsize,
  373. flash->manid, flash->devid);
  374. addr = fp->start;
  375. for(i = 0; i < flash->nr && addr < fp->end; i++)
  376. if(flash->r[i].addr <= addr && flash->r[i].end > addr){
  377. if(fp->end <= flash->r[i].end)
  378. end = fp->end;
  379. else
  380. end = flash->r[i].end;
  381. p = seprint(p, e, "0x%-9lux 0x%-9lux 0x%-9lux\n", addr,
  382. (end-addr)/flash->r[i].size, flash->r[i].size);
  383. addr = end;
  384. }
  385. n = readstr(off, a, n, buf);
  386. free(buf);
  387. return n;
  388. }
  389. static long
  390. flashdataread(FPart *fp, void* a, long n, vlong off)
  391. {
  392. Flash *flash;
  393. flash = fp->flash;
  394. rlock(flash);
  395. if(waserror()){
  396. runlock(flash);
  397. nexterror();
  398. }
  399. if(fp->name == nil)
  400. error("partition vanished");
  401. if(!iseve())
  402. error(Eperm);
  403. off += fp->start;
  404. if(off >= fp->end)
  405. n = 0;
  406. if(off+n >= fp->end)
  407. n = fp->end - off;
  408. if(n > 0)
  409. memmove(a, ((uchar*)flash->mem)+off, n);
  410. runlock(flash);
  411. poperror();
  412. return n;
  413. }
  414. static long
  415. flashread(Chan* c, void* a, long n, vlong off)
  416. {
  417. int t;
  418. if(c->qid.type == QTDIR)
  419. return devdirread(c, a, n, nil, 0, gen);
  420. t = FTYPE(c->qid.path);
  421. switch(t){
  422. default:
  423. error(Eperm);
  424. case Qfctl:
  425. n = flashctlread(FPART(c->qid.path), a, n, off);
  426. break;
  427. case Qfdata:
  428. n = flashdataread(FPART(c->qid.path), a, n, off);
  429. break;
  430. }
  431. return n;
  432. }
  433. static void
  434. bootprotect(ulong addr)
  435. {
  436. FlashRegion *r;
  437. Flash *flash;
  438. flash = findflash(addr);
  439. if (flash == nil)
  440. error(Ebadarg);
  441. if(flash->bootprotect == 0)
  442. return;
  443. if(flash->nr == 0)
  444. error("writing over boot loader disallowed");
  445. r = flash->r;
  446. if(addr >= r->addr && addr < r->addr + r->size)
  447. error("writing over boot loader disallowed");
  448. }
  449. static ulong
  450. blockstart(Flash *flash, ulong addr)
  451. {
  452. FlashRegion *r, *e;
  453. ulong x;
  454. r = flash->r;
  455. for(e = &flash->r[flash->nr]; r < e; r++)
  456. if(addr >= r->addr && addr < r->end){
  457. x = addr - r->addr;
  458. x /= r->size;
  459. return r->addr + x*r->size;
  460. }
  461. return -1;
  462. }
  463. static ulong
  464. blockend(Flash *flash, ulong addr)
  465. {
  466. FlashRegion *r, *e;
  467. ulong x;
  468. r = flash->r;
  469. for(e = &flash->r[flash->nr]; r < e; r++)
  470. if(addr >= r->addr && addr < r->end){
  471. x = addr - r->addr;
  472. x /= r->size;
  473. return r->addr + (x+1)*r->size;
  474. }
  475. return -1;
  476. }
  477. static long
  478. flashctlwrite(FPart *fp, char *p, long n)
  479. {
  480. Cmdbuf *cmd;
  481. ulong off;
  482. Flash *flash;
  483. if(fp == nil)
  484. panic("flashctlwrite");
  485. flash = fp->flash;
  486. cmd = parsecmd(p, n);
  487. wlock(flash);
  488. if(waserror()){
  489. wunlock(flash);
  490. nexterror();
  491. }
  492. if(strcmp(cmd->f[0], "erase") == 0){
  493. switch(cmd->nf){
  494. case 2:
  495. /* erase a single block in the partition */
  496. off = atoi(cmd->f[1]);
  497. off += fp->start;
  498. if(off >= fp->end)
  499. error("region not in partition");
  500. if(off != blockstart(flash, off))
  501. error("erase must be a block boundary");
  502. bootprotect(off);
  503. (*flash->alg->erase)(flash, off);
  504. break;
  505. case 1:
  506. /* erase the whole partition */
  507. bootprotect(fp->start);
  508. for(off = fp->start; off < fp->end; off = blockend(flash, off))
  509. (*flash->alg->erase)(flash, off);
  510. break;
  511. default:
  512. error(Ebadarg);
  513. }
  514. } else if(strcmp(cmd->f[0], "add") == 0){
  515. if(cmd->nf != 4)
  516. error(Ebadarg);
  517. addpart(fp, cmd->f[1], strtoul(cmd->f[2], nil, 0),
  518. strtoul(cmd->f[3], nil, 0));
  519. } else if(strcmp(cmd->f[0], "remove") == 0){
  520. rempart(fp);
  521. } else if(strcmp(cmd->f[0], "protectboot") == 0){
  522. if(cmd->nf == 1 || strcmp(cmd->f[1], "off") != 0)
  523. flash->bootprotect = 1;
  524. else
  525. flash->bootprotect = 0;
  526. } else
  527. error(Ebadarg);
  528. poperror();
  529. wunlock(flash);
  530. free(cmd);
  531. return n;
  532. }
  533. static long
  534. flashdatawrite(FPart *fp, uchar *p, long n, long off)
  535. {
  536. int m, on;
  537. long ooff;
  538. uchar *buf, *end;
  539. Flash *flash;
  540. if(fp == nil)
  541. panic("flashdatawrite");
  542. flash = fp->flash;
  543. buf = nil;
  544. wlock(flash);
  545. if(waserror()){
  546. wunlock(flash);
  547. if(buf != nil)
  548. free(buf);
  549. nexterror();
  550. }
  551. if(fp->name == nil)
  552. error("partition vanished");
  553. if(!iseve())
  554. error(Eperm);
  555. /* can't cross partition boundaries */
  556. off += fp->start;
  557. if(off >= fp->end || off+n > fp->end || n <= 0)
  558. error(Ebadarg);
  559. /* make sure we're not writing the boot sector */
  560. bootprotect(off);
  561. on = n;
  562. /*
  563. * get the data into kernel memory to avoid faults during writing.
  564. * if write is not on a quad boundary or not a multiple of 4 bytes,
  565. * extend with data already in flash.
  566. */
  567. buf = smalloc(n+8);
  568. m = off & 3;
  569. if(m){
  570. *(ulong*)buf = flash->p[off>>Wshift];
  571. n += m;
  572. off -= m;
  573. }
  574. if(n & 3){
  575. n -= n & 3;
  576. *(ulong*)(&buf[n]) = flash->p[(off+n)>>Wshift];
  577. n += 4;
  578. }
  579. memmove(&buf[m], p, on);
  580. /* (*flash->alg->write) can't cross blocks */
  581. ooff = off;
  582. p = buf;
  583. for(end = p + n; p < end; p += m){
  584. m = blockend(flash, off) - off;
  585. if(m > end - p)
  586. m = end - p;
  587. if(m > Maxwchunk)
  588. m = Maxwchunk;
  589. (*flash->alg->write)(flash, p, m, off);
  590. off += m;
  591. }
  592. /* make sure write succeeded */
  593. if(memcmp(buf, &flash->p[ooff>>Wshift], n) != 0)
  594. error("written bytes don't match");
  595. wunlock(flash);
  596. free(buf);
  597. poperror();
  598. return on;
  599. }
  600. static long
  601. flashwrite(Chan* c, void* a, long n, vlong off)
  602. {
  603. int t;
  604. if(c->qid.type == QTDIR)
  605. error(Eperm);
  606. if(!iseve())
  607. error(Eperm);
  608. t = FTYPE(c->qid.path);
  609. switch(t){
  610. default:
  611. panic("flashwrite");
  612. case Qfctl:
  613. n = flashctlwrite(FPART(c->qid.path), a, n);
  614. break;
  615. case Qfdata:
  616. n = flashdatawrite(FPART(c->qid.path), a, n, off);
  617. break;
  618. }
  619. return n;
  620. }
  621. Dev flashdevtab = {
  622. 'F',
  623. "flash",
  624. devreset,
  625. flashinit,
  626. devshutdown,
  627. flashattach,
  628. flashwalk,
  629. flashstat,
  630. flashopen,
  631. devcreate,
  632. flashclose,
  633. flashread,
  634. devbread,
  635. flashwrite,
  636. devbwrite,
  637. devremove,
  638. devwstat,
  639. };
  640. enum
  641. {
  642. /* status register */
  643. ISEs_lockerr= 1<<1,
  644. ISEs_powererr= 1<<3,
  645. ISEs_progerr= 1<<4,
  646. ISEs_eraseerr= 1<<5,
  647. ISEs_ready= 1<<7,
  648. ISEs_err= (ISEs_lockerr|ISEs_powererr|ISEs_progerr|ISEs_eraseerr),
  649. /* extended status register */
  650. ISExs_bufavail= 1<<7,
  651. AFSs_ready= 1<<7,
  652. };
  653. /* intel/sharp extended command set */
  654. static void
  655. ise_reset(Flash* flash)
  656. {
  657. flash->p[reg(0xaa)] = mirror(0xff); /* reset */
  658. }
  659. static void
  660. ise_id(Flash* flash)
  661. {
  662. ise_reset(flash);
  663. flash->p[reg(0xaaa)] = mirror(0x90); /* uncover vendor info */
  664. flash->manid = fromendian(flash->p[reg(0x0)]);
  665. flash->devid = fromendian(flash->p[reg(0x1)]);
  666. ise_reset(flash);
  667. }
  668. static void
  669. ise_clearerror(Flash* flash)
  670. {
  671. flash->p[reg(0x200)] = mirror(0x50);
  672. }
  673. static void
  674. ise_error(int bank, ulong status)
  675. {
  676. char err[64];
  677. if(status & (ISEs_lockerr)){
  678. sprint(err, "flash%d: block locked %lux", bank, status);
  679. error(err);
  680. }
  681. if(status & (ISEs_powererr)){
  682. sprint(err, "flash%d: low prog voltage %lux", bank, status);
  683. error(err);
  684. }
  685. if(status & (ISEs_progerr|ISEs_eraseerr)){
  686. sprint(err, "flash%d: i/o error %lux", bank, status);
  687. error(err);
  688. }
  689. }
  690. static void
  691. ise_erase(Flash *flash, ulong addr)
  692. {
  693. ulong start, x;
  694. addr >>= Wshift;
  695. flash->p[addr] = mirror(0x20);
  696. flash->p[addr] = mirror(0xd0);
  697. start = m->ticks;
  698. do {
  699. x = fromendian(flash->p[addr]);
  700. if((x & mirror(ISEs_ready)) == mirror(ISEs_ready))
  701. break;
  702. } while(TK2MS(m->ticks-start) < 1500);
  703. ise_clearerror(flash);
  704. ise_error(0, x);
  705. ise_error(1, x>>16);
  706. ise_reset(flash);
  707. }
  708. /*
  709. * the flash spec claimes writing goes faster if we use
  710. * the write buffer. We fill the write buffer and then
  711. * issue the write request. After the write request,
  712. * subsequent reads will yield the status register.
  713. *
  714. * returns the status, even on timeouts.
  715. *
  716. * NOTE: I tried starting back to back buffered writes
  717. * without reading the status in between, as the
  718. * flowchart in the intel data sheet suggests.
  719. * However, it always responded with an illegal
  720. * command sequence, so I must be missing something.
  721. * If someone learns better, please email me, though
  722. * I doubt it will be much faster. - presotto@bell-labs.com
  723. */
  724. static long
  725. ise_wbwrite(Flash *flash, Fword *p, int n, ulong off, ulong baddr, ulong *status)
  726. {
  727. Fword x;
  728. ulong start;
  729. int i, s;
  730. /* put flash into write buffer mode */
  731. start = m->ticks;
  732. for(;;) {
  733. s = splhi();
  734. /* request write buffer mode */
  735. flash->p[baddr] = mirror(0xe8);
  736. /* look at extended status reg for status */
  737. if((flash->p[baddr] & mirror(1<<7)) == mirror(1<<7))
  738. break;
  739. splx(s);
  740. /* didn't work, keep trying for 2 secs */
  741. if(TK2MS(m->ticks-start) > 2000){
  742. /* set up to read status */
  743. flash->p[baddr] = mirror(0x70);
  744. *status = fromendian(flash->p[baddr]);
  745. pprint("write buffered cmd timed out\n");
  746. return -1;
  747. }
  748. }
  749. /* fill write buffer */
  750. flash->p[baddr] = mirror(n-1);
  751. for(i = 0; i < n; i++)
  752. flash->p[off+i] = *p++;
  753. /* program from buffer */
  754. flash->p[baddr] = mirror(0xd0);
  755. splx(s);
  756. /* wait till the programming is done */
  757. start = m->ticks;
  758. for(;;) {
  759. x = flash->p[baddr]; /* read status register */
  760. *status = fromendian(x);
  761. if((x & mirror(ISEs_ready)) == mirror(ISEs_ready))
  762. break;
  763. if(TK2MS(m->ticks-start) > 2000){
  764. pprint("read status timed out\n");
  765. return -1;
  766. }
  767. }
  768. if(x & mirror(ISEs_err))
  769. return -1;
  770. return n;
  771. }
  772. static void
  773. ise_write(Flash *flash, void *a, long n, ulong off)
  774. {
  775. Fword *p, *end;
  776. int i, wbsize;
  777. ulong x, baddr;
  778. /* everything in terms of Fwords */
  779. wbsize = flash->wbsize >> Wshift;
  780. baddr = blockstart(flash, off) >> Wshift;
  781. off >>= Wshift;
  782. n >>= Wshift;
  783. p = a;
  784. /* first see if write will succeed */
  785. for(i = 0; i < n; i++)
  786. if((p[i] & flash->p[off+i]) != p[i])
  787. error("flash needs erase");
  788. if(waserror()){
  789. ise_reset(flash);
  790. nexterror();
  791. }
  792. /*
  793. * use the first write to reach
  794. * a write buffer boundary. the intel maunal
  795. * says writes starting at wb boundaries
  796. * maximize speed.
  797. */
  798. i = wbsize - (off & (wbsize-1));
  799. for(end = p + n; p < end;){
  800. if(i > end - p)
  801. i = end - p;
  802. if(ise_wbwrite(flash, p, i, off, baddr, &x) < 0)
  803. break;
  804. off += i;
  805. p += i;
  806. i = wbsize;
  807. }
  808. ise_clearerror(flash);
  809. ise_error(0, x);
  810. ise_error(1, x>>16);
  811. ise_reset(flash);
  812. poperror();
  813. }
  814. /*
  815. * amd/fujitsu standard command set
  816. * I don't have an amd chipset to work with
  817. * so I'm loathe to write this yet. If someone
  818. * else does, please send it to me and I'll
  819. * incorporate it -- presotto@bell-labs.com
  820. */
  821. static void
  822. afs_reset(Flash *flash)
  823. {
  824. flash->p[reg(0xaa)] = mirror(0xf0); /* reset */
  825. }
  826. static void
  827. afs_id(Flash *flash)
  828. {
  829. afs_reset(flash);
  830. flash->p[reg(0xaa)] = mirror(0xf0); /* reset */
  831. flash->p[reg(0xaaa)] = mirror(0xaa); /* query vendor block */
  832. flash->p[reg(0x554)] = mirror(0x55);
  833. flash->p[reg(0xaaa)] = mirror(0x90);
  834. flash->manid = fromendian(flash->p[reg(0x00)]);
  835. afs_reset(flash);
  836. flash->p[reg(0xaaa)] = mirror(0xaa); /* query vendor block */
  837. flash->p[reg(0x554)] = mirror(0x55);
  838. flash->p[reg(0xaaa)] = mirror(0x90);
  839. flash->devid = fromendian(flash->p[reg(0x02)]);
  840. afs_reset(flash);
  841. }
  842. static void
  843. afs_erase(Flash *flash, ulong addr)
  844. {
  845. ulong start, x;
  846. addr >>= Wshift;
  847. afs_reset(flash);
  848. flash->p[reg(0x555)] = mirror(0xaa);
  849. flash->p[reg(0x2aa)] = mirror(0x55);
  850. flash->p[reg(0x555)] = mirror(0x80);
  851. flash->p[reg(0x555)] = mirror(0xaa);
  852. flash->p[reg(0x2aa)] = mirror(0x55);
  853. flash->p[reg(addr)] = mirror(0x30);
  854. start = m->ticks;
  855. do {
  856. x = flash->p[reg(addr)];
  857. if((x & mirror(AFSs_ready)) == mirror(AFSs_ready))
  858. break;
  859. } while(TK2MS(m->ticks-start) < 1500);
  860. }
  861. static void
  862. afs_write(Flash *flash, void *a, long n, ulong offs)
  863. {
  864. Fword *p;
  865. int i;
  866. ulong x, start;
  867. /* everything in terms of Fwords */
  868. offs >>= Wshift;
  869. n >>= Wshift;
  870. p = a;
  871. /* first see if write will succeed */
  872. for(i = 0; i < n; i++)
  873. if((p[i] & flash->p[offs + i]) != p[i])
  874. error("flash needs erase");
  875. if(waserror()){
  876. afs_reset(flash);
  877. nexterror();
  878. }
  879. for(i = 0; i < n; i++){
  880. flash->p[reg(0x555)] = mirror(0xaa);
  881. flash->p[reg(0x2aa)] = mirror(0x55);
  882. flash->p[reg(0x555)] = mirror(0xa0);
  883. flash->p[reg(offs + i)] = mirror(p[i]);
  884. start = m->ticks;
  885. do {
  886. x = flash->p[reg(offs + i)];
  887. if(x == p[i])
  888. break;
  889. } while(TK2MS(m->ticks-start) < 1500);
  890. if(x != p[i])
  891. error("timed out");
  892. }
  893. poperror();
  894. }