Annotation of sys/arch/zaurus/dev/zaurus_flash.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: zaurus_flash.c,v 1.4 2007/06/20 18:15:46 deraadt Exp $ */
2:
3: /*
4: * Copyright (c) 2005 Uwe Stuehler <uwe@openbsd.org>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: /*
20: * Samsung NAND flash controlled by some unspecified CPLD device.
21: */
22:
23: #include <sys/param.h>
24: #include <sys/buf.h>
25: #include <sys/device.h>
26: #include <sys/disk.h>
27: #include <sys/disklabel.h>
28: #include <sys/kernel.h>
29: #include <sys/malloc.h>
30: #include <sys/systm.h>
31:
32: #include <dev/flashvar.h>
33: #include <dev/rndvar.h>
34:
35: #include <machine/zaurus_var.h>
36:
37: #include <arch/arm/xscale/pxa2x0var.h>
38:
39: #define DEBUG
40: #ifdef DEBUG
41: #define DPRINTF(x) printf x
42: #else
43: #define DPRINTF(x)
44: #endif
45:
46: /* CPLD register definitions */
47: #define CPLD_REG_ECCLPLB 0x00
48: #define CPLD_REG_ECCLPUB 0x04
49: #define CPLD_REG_ECCCP 0x08
50: #define CPLD_REG_ECCCNTR 0x0c
51: #define CPLD_REG_ECCCLRR 0x10
52: #define CPLD_REG_FLASHIO 0x14
53: #define CPLD_REG_FLASHCTL 0x18
54: #define FLASHCTL_NCE0 (1<<0)
55: #define FLASHCTL_CLE (1<<1)
56: #define FLASHCTL_ALE (1<<2)
57: #define FLASHCTL_NWP (1<<3)
58: #define FLASHCTL_NCE1 (1<<4)
59: #define FLASHCTL_RYBY (1<<5)
60: #define FLASHCTL_NCE (FLASHCTL_NCE0|FLASHCTL_NCE1)
61:
62: /* CPLD register accesses */
63: #define CPLD_READ(sc, r) \
64: bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (r))
65: #define CPLD_WRITE(sc, r, v) \
66: bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (r), (v))
67: #define CPLD_SET(sc, r, v) \
68: CPLD_WRITE((sc), (r), CPLD_READ((sc), (r)) | (v))
69: #define CPLD_CLR(sc, r, v) \
70: CPLD_WRITE((sc), (r), CPLD_READ((sc), (r)) & ~(v))
71: #define CPLD_SETORCLR(sc, r, m, v) \
72: ((v) ? CPLD_SET((sc), (r), (m)) : CPLD_CLR((sc), (r), (m)))
73:
74: /* Offsets into OOB data. */
75: #define OOB_JFFS2_ECC0 0
76: #define OOB_JFFS2_ECC1 1
77: #define OOB_JFFS2_ECC2 2
78: #define OOB_JFFS2_ECC3 3
79: #define OOB_JFFS2_ECC4 6
80: #define OOB_JFFS2_ECC5 7
81: #define OOB_LOGADDR_0_LO 8
82: #define OOB_LOGADDR_0_HI 9
83: #define OOB_LOGADDR_1_LO 10
84: #define OOB_LOGADDR_1_HI 11
85: #define OOB_LOGADDR_2_LO 12
86: #define OOB_LOGADDR_2_HI 13
87:
88: /*
89: * Structure for managing logical blocks in a partition; allocated on
90: * first use of each partition on a "safe" flash device.
91: */
92: struct zflash_safe {
93: dev_t sp_dev;
94: u_long sp_pblks; /* physical block count */
95: u_long sp_lblks; /* logical block count */
96: u_int16_t *sp_phyuse; /* physical block usage */
97: u_int *sp_logmap; /* logical to physical */
98: u_int sp_pnext; /* next physical block */
99: };
100:
101: struct zflash_softc {
102: struct flash_softc sc_flash;
103: bus_space_tag_t sc_iot;
104: bus_space_handle_t sc_ioh;
105: int sc_ioobbadblk;
106: int sc_ioobpostbadblk;
107: struct zflash_safe *sc_safe[MAXPARTITIONS];
108: };
109:
110: int zflashmatch(struct device *, void *, void *);
111: void zflashattach(struct device *, struct device *, void *);
112: int zflashdetach(struct device *, int);
113:
114: u_int8_t zflash_reg8_read(void *, int);
115: int zflash_regx_read_page(void *, caddr_t, caddr_t);
116: void zflash_reg8_write(void *, int, u_int8_t);
117: int zflash_regx_write_page(void *, caddr_t, caddr_t);
118: void zflash_default_disklabel(void *, dev_t, struct disklabel *);
119: int zflash_safe_strategy(void *, struct buf *);
120:
121: int zflash_safe_start(struct zflash_softc *, dev_t);
122: void zflash_safe_stop(struct zflash_softc *, dev_t);
123:
124: struct cfattach flash_pxaip_ca = {
125: sizeof(struct zflash_softc), zflashmatch, zflashattach,
126: zflashdetach, flashactivate
127: };
128:
129: struct flash_ctl_tag zflash_ctl_tag = {
130: zflash_reg8_read,
131: zflash_regx_read_page,
132: zflash_reg8_write,
133: zflash_regx_write_page,
134: zflash_default_disklabel,
135: zflash_safe_strategy
136: };
137:
138: int
139: zflashmatch(struct device *parent, void *match, void *aux)
140: {
141: /* XXX call flashprobe(), yet to be implemented */
142: return ZAURUS_ISC3000;
143: }
144:
145: void
146: zflashattach(struct device *parent, struct device *self, void *aux)
147: {
148: struct zflash_softc *sc = (struct zflash_softc *)self;
149: struct pxaip_attach_args *pxa = aux;
150: bus_addr_t addr = pxa->pxa_addr;
151: bus_size_t size = pxa->pxa_size;
152:
153: sc->sc_iot = pxa->pxa_iot;
154:
155: if ((int)addr == -1 || (int)size == 0) {
156: addr = 0x0c000000;
157: size = 0x00001000;
158: }
159:
160: if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh) != 0) {
161: printf(": failed to map controller\n");
162: return;
163: }
164:
165: /* Disable and write-protect the chip. */
166: CPLD_WRITE(sc, CPLD_REG_FLASHCTL, FLASHCTL_NCE);
167:
168: flashattach(&sc->sc_flash, &zflash_ctl_tag, sc);
169:
170: switch (sc->sc_flash.sc_flashdev->id) {
171: case FLASH_DEVICE_SAMSUNG_K9F2808U0C: /* C3000 */
172: sc->sc_ioobpostbadblk = 4;
173: sc->sc_ioobbadblk = 5;
174: break;
175: case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: /* C3100 */
176: sc->sc_ioobpostbadblk = 4;
177: sc->sc_ioobbadblk = 0;
178: break;
179: }
180: }
181:
182: int
183: zflashdetach(struct device *self, int flags)
184: {
185: struct zflash_softc *sc = (struct zflash_softc *)self;
186: int part;
187:
188: for (part = 0; part < MAXPARTITIONS; part++)
189: zflash_safe_stop(sc, part);
190:
191: return (flashdetach(self, flags));
192: }
193:
194: u_int8_t
195: zflash_reg8_read(void *arg, int reg)
196: {
197: struct zflash_softc *sc = arg;
198: u_int8_t value;
199:
200: switch (reg) {
201: case FLASH_REG_DATA:
202: value = CPLD_READ(sc, CPLD_REG_FLASHIO);
203: break;
204: case FLASH_REG_READY:
205: value = (CPLD_READ(sc, CPLD_REG_FLASHCTL) &
206: FLASHCTL_RYBY) != 0;
207: break;
208: default:
209: #ifdef DIAGNOSTIC
210: printf("%s: read from pseudo-register %02x\n",
211: sc->sc_flash.sc_dev.dv_xname, reg);
212: #endif
213: value = 0;
214: break;
215: }
216: return value;
217: }
218:
219: void
220: zflash_reg8_write(void *arg, int reg, u_int8_t value)
221: {
222: struct zflash_softc *sc = arg;
223:
224: switch (reg) {
225: case FLASH_REG_DATA:
226: case FLASH_REG_COL:
227: case FLASH_REG_ROW:
228: case FLASH_REG_CMD:
229: CPLD_WRITE(sc, CPLD_REG_FLASHIO, value);
230: break;
231: case FLASH_REG_ALE:
232: CPLD_SETORCLR(sc, CPLD_REG_FLASHCTL, FLASHCTL_ALE, value);
233: break;
234: case FLASH_REG_CLE:
235: CPLD_SETORCLR(sc, CPLD_REG_FLASHCTL, FLASHCTL_CLE, value);
236: break;
237: case FLASH_REG_CE:
238: CPLD_SETORCLR(sc, CPLD_REG_FLASHCTL, FLASHCTL_NCE, !value);
239: break;
240: case FLASH_REG_WP:
241: CPLD_SETORCLR(sc, CPLD_REG_FLASHCTL, FLASHCTL_NWP, !value);
242: break;
243: #ifdef DIAGNOSTIC
244: default:
245: printf("%s: write to pseudo-register %02x\n",
246: sc->sc_flash.sc_dev.dv_xname, reg);
247: #endif
248: }
249: }
250:
251: int
252: zflash_regx_read_page(void *arg, caddr_t data, caddr_t oob)
253: {
254: struct zflash_softc *sc = arg;
255:
256: if (oob == NULL || sc->sc_flash.sc_flashdev->pagesize != 512) {
257: flash_reg8_read_page(&sc->sc_flash, data, oob);
258: return 0;
259: }
260:
261: flash_reg8_read_page(&sc->sc_flash, data, oob);
262:
263: oob[OOB_JFFS2_ECC0] = 0xff;
264: oob[OOB_JFFS2_ECC1] = 0xff;
265: oob[OOB_JFFS2_ECC2] = 0xff;
266: oob[OOB_JFFS2_ECC3] = 0xff;
267: oob[OOB_JFFS2_ECC4] = 0xff;
268: oob[OOB_JFFS2_ECC5] = 0xff;
269: return 0;
270: }
271:
272: int
273: zflash_regx_write_page(void *arg, caddr_t data, caddr_t oob)
274: {
275: struct zflash_softc *sc = arg;
276: int i;
277:
278: if (oob == NULL || sc->sc_flash.sc_flashdev->pagesize != 512) {
279: flash_reg8_write_page(&sc->sc_flash, data, oob);
280: return 0;
281: }
282:
283: if (oob[OOB_JFFS2_ECC0] != 0xff || oob[OOB_JFFS2_ECC1] != 0xff ||
284: oob[OOB_JFFS2_ECC2] != 0xff || oob[OOB_JFFS2_ECC3] != 0xff ||
285: oob[OOB_JFFS2_ECC4] != 0xff || oob[OOB_JFFS2_ECC5] != 0xff) {
286: #ifdef DIAGNOSTIC
287: printf("%s: non-FF ECC bytes in OOB data\n",
288: sc->sc_flash.sc_dev.dv_xname);
289: #endif
290: return EINVAL;
291: }
292:
293: CPLD_WRITE(sc, CPLD_REG_ECCCLRR, 0x00);
294: for (i = 0; i < sc->sc_flash.sc_flashdev->pagesize / 2; i++)
295: flash_reg8_write(&sc->sc_flash, FLASH_REG_DATA, data[i]);
296:
297: oob[OOB_JFFS2_ECC0] = ~CPLD_READ(sc, CPLD_REG_ECCLPUB);
298: oob[OOB_JFFS2_ECC1] = ~CPLD_READ(sc, CPLD_REG_ECCLPLB);
299: oob[OOB_JFFS2_ECC2] = (~CPLD_READ(sc, CPLD_REG_ECCCP) << 2) | 0x03;
300:
301: if (CPLD_READ(sc, CPLD_REG_ECCCNTR) != 0) {
302: printf("%s: ECC failed\n", sc->sc_flash.sc_dev.dv_xname);
303: oob[OOB_JFFS2_ECC0] = 0xff;
304: oob[OOB_JFFS2_ECC1] = 0xff;
305: oob[OOB_JFFS2_ECC2] = 0xff;
306: return EIO;
307: }
308:
309: CPLD_WRITE(sc, CPLD_REG_ECCCLRR, 0x00);
310: for (; i < sc->sc_flash.sc_flashdev->pagesize; i++)
311: flash_reg8_write(&sc->sc_flash, FLASH_REG_DATA, data[i]);
312:
313: oob[OOB_JFFS2_ECC3] = ~CPLD_READ(sc, CPLD_REG_ECCLPUB);
314: oob[OOB_JFFS2_ECC4] = ~CPLD_READ(sc, CPLD_REG_ECCLPLB);
315: oob[OOB_JFFS2_ECC5] = (~CPLD_READ(sc, CPLD_REG_ECCCP) << 2) | 0x03;
316:
317: if (CPLD_READ(sc, CPLD_REG_ECCCNTR) != 0) {
318: printf("%s: ECC failed\n", sc->sc_flash.sc_dev.dv_xname);
319: oob[OOB_JFFS2_ECC0] = 0xff;
320: oob[OOB_JFFS2_ECC1] = 0xff;
321: oob[OOB_JFFS2_ECC2] = 0xff;
322: oob[OOB_JFFS2_ECC3] = 0xff;
323: oob[OOB_JFFS2_ECC4] = 0xff;
324: oob[OOB_JFFS2_ECC5] = 0xff;
325: return EIO;
326: }
327:
328: for (i = 0; i < sc->sc_flash.sc_flashdev->oobsize; i++)
329: flash_reg8_write(&sc->sc_flash, FLASH_REG_DATA, oob[i]);
330:
331: oob[OOB_JFFS2_ECC0] = 0xff;
332: oob[OOB_JFFS2_ECC1] = 0xff;
333: oob[OOB_JFFS2_ECC2] = 0xff;
334: oob[OOB_JFFS2_ECC3] = 0xff;
335: oob[OOB_JFFS2_ECC4] = 0xff;
336: oob[OOB_JFFS2_ECC5] = 0xff;
337: return 0;
338: }
339:
340: /*
341: * A default disklabel with only one RAW_PART spanning the whole
342: * device is passed to us. We add the partitions besides RAW_PART.
343: */
344: void
345: zflash_default_disklabel(void *arg, dev_t dev, struct disklabel *lp)
346: {
347: struct zflash_softc *sc = arg;
348: long bsize = sc->sc_flash.sc_flashdev->pagesize;
349:
350: switch (sc->sc_flash.sc_flashdev->id) {
351: case FLASH_DEVICE_SAMSUNG_K9F2808U0C:
352: DL_SETPSIZE(&lp->d_partitions[8], 7*1024*1024 / bsize);
353: DL_SETPSIZE(&lp->d_partitions[9], 5*1024*1024 / bsize);
354: DL_SETPSIZE(&lp->d_partitions[10], 4*1024*1024 / bsize);
355: break;
356: case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
357: DL_SETPSIZE(&lp->d_partitions[8], 7*1024*1024 / bsize);
358: DL_SETPSIZE(&lp->d_partitions[9], 32*1024*1024 / bsize);
359: DL_SETPSIZE(&lp->d_partitions[10], 89*1024*1024 / bsize);
360: break;
361: default:
362: return;
363: }
364:
365: /* The "smf" partition uses logical addressing. */
366: DL_SETPOFFSET(&lp->d_partitions[8], 0);
367: lp->d_partitions[8].p_fstype = FS_OTHER;
368:
369: /* The "root" partition uses physical addressing. */
370: DL_SETPSIZE(&lp->d_partitions[9], DL_GETPSIZE(&lp->d_partitions[8]));
371: lp->d_partitions[9].p_fstype = FS_OTHER;
372:
373: /* The "home" partition uses physical addressing. */
374: DL_SETPOFFSET(&lp->d_partitions[10],
375: DL_GETPOFFSET(&lp->d_partitions[9]) + DL_GETPSIZE(&lp->d_partitions[9]));
376: lp->d_partitions[10].p_fstype = FS_OTHER;
377: lp->d_npartitions = 11;
378:
379: lp->d_version = 1;
380: /* Re-calculate the checksum. */
381: lp->d_checksum = dkcksum(lp);
382: }
383:
384: /*
385: * Sharp's access strategy for bad blocks management and wear-leveling.
386: */
387:
388: #define PHYUSE_STATUS(v) ((v) & 0x00ff)
389: #define P_BADBLOCK 0x0000
390: #define P_POSTBADBLOCK 0x00f0
391: #define P_NORMALBLOCK 0x00ff
392: #define PHYUSE_WRITTEN(v) ((v) & 0xff00)
393: #define P_DUST 0x0000
394: #define P_LOGICAL 0x0100
395: #define P_JFFS2 0x0300
396:
397: void zflash_write_strategy(struct zflash_softc *, struct buf *,
398: struct zflash_safe *, u_int, u_int);
399: u_int zflash_safe_next_block(struct zflash_safe *);
400:
401: u_char zflash_oob_status_decode(u_char);
402: u_int16_t zflash_oob_status(struct zflash_softc *, u_char *);
403: u_int zflash_oob_logno(struct zflash_softc *, u_char *);
404: void zflash_oob_set_status(struct zflash_softc *, u_char *, u_int16_t);
405: void zflash_oob_set_logno(struct zflash_softc *, u_char *, u_int);
406:
407: int
408: zflash_safe_strategy(void *arg, struct buf *bp)
409: {
410: struct zflash_softc *sc = arg;
411: struct zflash_safe *sp;
412: u_int logno;
413: u_int blkofs;
414: u_int blkno;
415: int error;
416: int part;
417: int i;
418:
419: /* Initialize logical blocks management on the fly. */
420: /* XXX toss everything when the disklabel has changed. */
421: if ((error = zflash_safe_start(sc, bp->b_dev)) != 0) {
422: bp->b_error = error;
423: bp->b_flags |= B_ERROR;
424: return 0;
425: }
426:
427: part = flashpart(bp->b_dev);
428: sp = sc->sc_safe[part];
429:
430: logno = bp->b_blkno / (sc->sc_flash.sc_flashdev->blkpages *
431: sc->sc_flash.sc_flashdev->pagesize / DEV_BSIZE);
432: blkofs = bp->b_blkno % (sc->sc_flash.sc_flashdev->blkpages *
433: sc->sc_flash.sc_flashdev->pagesize / DEV_BSIZE);
434:
435: /* If exactly at end of logical flash, return EOF, else error. */
436: if (logno == sp->sp_lblks && blkofs == 0) {
437: bp->b_resid = bp->b_bcount;
438: return 0;
439: } else if (logno >= sp->sp_lblks) {
440: bp->b_error = EINVAL;
441: bp->b_flags |= B_ERROR;
442: return 0;
443: }
444:
445: /* Writing is more complicated, so handle it separately. */
446: if ((bp->b_flags & B_READ) == 0) {
447: flash_chip_enable(&sc->sc_flash);
448: zflash_write_strategy(sc, bp, sp, logno, blkofs);
449: flash_chip_disable(&sc->sc_flash);
450: return 0;
451: }
452:
453: /* Get the physical flash block number for this logical one. */
454: blkno = sp->sp_logmap[logno];
455:
456: /* Unused logical blocks read as all 0xff. */
457: if ((bp->b_flags & B_READ) != 0 && blkno == UINT_MAX) {
458: for (i = 0; i < sc->sc_flash.sc_flashdev->pagesize; i++)
459: ((u_char *)bp->b_data)[i] = 0xff;
460: bp->b_resid = bp->b_bcount -
461: sc->sc_flash.sc_flashdev->pagesize;
462: return 0;
463: }
464:
465: /* Update the block number in the buffer with the physical one. */
466: bp->b_blkno = blkno * (sc->sc_flash.sc_flashdev->blkpages *
467: sc->sc_flash.sc_flashdev->pagesize / DEV_BSIZE) + blkofs;
468:
469: /* Process the modified transfer buffer normally. */
470: return 1;
471: }
472:
473: void
474: zflash_write_strategy(struct zflash_softc *sc, struct buf *bp,
475: struct zflash_safe *sp, u_int logno, u_int logofs)
476: {
477: size_t bufsize;
478: u_char *buf = NULL;
479: size_t oobsize;
480: u_char *oob = NULL;
481: u_int oblkno;
482: u_int nblkno;
483: int error;
484:
485: /* Not efficient, but we always transfer one page for now. */
486: if (bp->b_bcount < sc->sc_flash.sc_flashdev->pagesize) {
487: bp->b_error = EINVAL;
488: goto bad;
489: }
490:
491: /* Allocate a temporary buffer for one flash block. */
492: bufsize = sc->sc_flash.sc_flashdev->blkpages *
493: sc->sc_flash.sc_flashdev->pagesize;
494: buf = (u_char *)malloc(bufsize, M_DEVBUF, M_NOWAIT);
495: if (buf == NULL) {
496: bp->b_error = ENOMEM;
497: goto bad;
498: }
499:
500: /* Allocate a temporary buffer for one spare area. */
501: oobsize = sc->sc_flash.sc_flashdev->oobsize;
502: oob = (u_char *)malloc(oobsize, M_DEVBUF, M_NOWAIT);
503: if (oob == NULL) {
504: bp->b_error = ENOMEM;
505: goto bad;
506: }
507:
508: /* Read the old logical block into the temporary buffer. */
509: oblkno = sp->sp_logmap[logno];
510: if (oblkno != UINT_MAX) {
511: error = flash_chip_read_block(&sc->sc_flash, oblkno, buf);
512: if (error != 0) {
513: bp->b_error = error;
514: goto bad;
515: }
516: } else
517: /* Unused logical blocks read as all 0xff. */
518: memset(buf, 0xff, bufsize);
519:
520: /* Transfer the page into the logical block buffer. */
521: bcopy(bp->b_data, buf + logofs * sc->sc_flash.sc_flashdev->pagesize,
522: sc->sc_flash.sc_flashdev->pagesize);
523:
524: /* Generate OOB data for the spare area of this logical block. */
525: memset(oob, 0xff, oobsize);
526: zflash_oob_set_status(sc, oob, P_NORMALBLOCK);
527: zflash_oob_set_logno(sc, oob, logno);
528:
529: while (1) {
530: /* Search for a free physical block. */
531: nblkno = zflash_safe_next_block(sp);
532: if (nblkno == UINT_MAX) {
533: printf("%s: no spare block, giving up on logical"
534: " block %u\n", sc->sc_flash.sc_dev.dv_xname,
535: logno);
536: bp->b_error = ENOSPC;
537: goto bad;
538: }
539:
540: #if 0
541: DPRINTF(("%s: moving logical block %u from physical %u to %u\n",
542: sc->sc_flash.sc_dev.dv_xname, logno, oblkno, nblkno));
543: #endif
544:
545: /* Erase the free physical block. */
546: if (flash_chip_erase_block(&sc->sc_flash, nblkno) != 0) {
547: printf("%s: can't erase block %u, retrying\n",
548: sc->sc_flash.sc_dev.dv_xname, nblkno);
549: sp->sp_phyuse[nblkno] = P_POSTBADBLOCK | P_DUST;
550: continue;
551: }
552:
553: /* Write the logical block to the free physical block. */
554: if (flash_chip_write_block(&sc->sc_flash, nblkno, buf, oob)) {
555: printf("%s: can't write block %u, retrying\n",
556: sc->sc_flash.sc_dev.dv_xname, nblkno);
557: goto trynext;
558: }
559:
560: /* Yeah, we re-wrote that logical block! */
561: break;
562: trynext:
563: sp->sp_phyuse[nblkno] = P_POSTBADBLOCK | P_DUST;
564: (void)flash_chip_erase_block(&sc->sc_flash, nblkno);
565: }
566:
567: /* Map the new physical block. */
568: sp->sp_logmap[logno] = nblkno;
569: sp->sp_phyuse[nblkno] = PHYUSE_STATUS(sp->sp_phyuse[nblkno])
570: | P_LOGICAL;
571:
572: /* Erase the old physical block. */
573: if (oblkno != UINT_MAX) {
574: sp->sp_phyuse[oblkno] = PHYUSE_STATUS(sp->sp_phyuse[oblkno])
575: | P_DUST;
576: error = flash_chip_erase_block(&sc->sc_flash, oblkno);
577: if (error != 0) {
578: printf("%s: can't erase old block %u\n",
579: sc->sc_flash.sc_dev.dv_xname, oblkno);
580: bp->b_error = error;
581: goto bad;
582: }
583: }
584:
585: bp->b_resid = bp->b_bcount - sc->sc_flash.sc_flashdev->pagesize;
586: free(oob, M_DEVBUF);
587: free(buf, M_DEVBUF);
588: return;
589: bad:
590: bp->b_flags |= B_ERROR;
591: if (oob != NULL)
592: free(oob, M_DEVBUF);
593: if (buf != NULL)
594: free(buf, M_DEVBUF);
595: }
596:
597: int
598: zflash_safe_start(struct zflash_softc *sc, dev_t dev)
599: {
600: u_char oob[FLASH_MAXOOBSIZE];
601: struct disklabel *lp = sc->sc_flash.sc_dk.dk_label;
602: struct zflash_safe *sp;
603: u_int16_t *phyuse;
604: u_int *logmap;
605: u_int blksect;
606: u_int blkno;
607: u_int logno;
608: u_int unusable;
609: int part;
610:
611: part = flashpart(dev);
612: if (sc->sc_safe[part] != NULL)
613: return 0;
614:
615: /* We can only handle so much OOB data here. */
616: if (sc->sc_flash.sc_flashdev->oobsize > FLASH_MAXOOBSIZE)
617: return EIO;
618:
619: /* Safe partitions must start on a flash block boundary. */
620: blksect = (sc->sc_flash.sc_flashdev->blkpages *
621: sc->sc_flash.sc_flashdev->pagesize) / lp->d_secsize;
622: if (DL_GETPOFFSET(&lp->d_partitions[part]) % blksect)
623: return EIO;
624:
625: MALLOC(sp, struct zflash_safe *, sizeof(struct zflash_safe),
626: M_DEVBUF, M_NOWAIT);
627: if (sp == NULL)
628: return ENOMEM;
629:
630: bzero(sp, sizeof(struct zflash_safe));
631: sp->sp_dev = dev;
632:
633: sp->sp_pblks = DL_GETPSIZE(&lp->d_partitions[part]) / blksect;
634: sp->sp_lblks = sp->sp_pblks;
635:
636: /* Try to reserve a number of spare physical blocks. */
637: switch (sc->sc_flash.sc_flashdev->id) {
638: case FLASH_DEVICE_SAMSUNG_K9F2808U0C:
639: sp->sp_lblks -= 24; /* C3000 */
640: break;
641: case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
642: sp->sp_lblks -= 4; /* C3100 */
643: break;
644: }
645:
646: DPRINTF(("pblks %u lblks %u\n", sp->sp_pblks, sp->sp_lblks));
647:
648: /* Next physical block to use; randomize for wear-leveling. */
649: sp->sp_pnext = arc4random() % sp->sp_pblks;
650:
651: /* Allocate physical block usage map. */
652: phyuse = (u_int16_t *)malloc(sp->sp_pblks * sizeof(u_int16_t),
653: M_DEVBUF, M_NOWAIT);
654: if (phyuse == NULL) {
655: FREE(sp, M_DEVBUF);
656: return ENOMEM;
657: }
658: sp->sp_phyuse = phyuse;
659:
660: /* Allocate logical to physical block map. */
661: logmap = (u_int *)malloc(sp->sp_lblks * sizeof(u_int),
662: M_DEVBUF, M_NOWAIT);
663: if (logmap == NULL) {
664: FREE(phyuse, M_DEVBUF);
665: FREE(sp, M_DEVBUF);
666: return ENOMEM;
667: }
668: sp->sp_logmap = logmap;
669:
670: /* Initialize the physical and logical block maps. */
671: for (blkno = 0; blkno < sp->sp_pblks; blkno++)
672: phyuse[blkno] = P_BADBLOCK | P_DUST;
673: for (blkno = 0; blkno < sp->sp_lblks; blkno++)
674: logmap[blkno] = UINT_MAX;
675:
676: /* Update physical block usage map with real data. */
677: unusable = 0;
678: flash_chip_enable(&sc->sc_flash);
679: for (blkno = 0; blkno < sp->sp_pblks; blkno++) {
680: long pageno;
681:
682: pageno = blkno * sc->sc_flash.sc_flashdev->blkpages;
683: if (flash_chip_read_oob(&sc->sc_flash, pageno, oob) != 0) {
684: DPRINTF(("blkno %u: can't read oob data\n", blkno));
685: phyuse[blkno] = P_POSTBADBLOCK | P_DUST;
686: unusable++;
687: continue;
688: }
689:
690: phyuse[blkno] = zflash_oob_status(sc, oob);
691: if (PHYUSE_STATUS(phyuse[blkno]) != P_NORMALBLOCK) {
692: DPRINTF(("blkno %u: badblock status %x\n", blkno,
693: PHYUSE_STATUS(phyuse[blkno])));
694: phyuse[blkno] |= P_DUST;
695: unusable++;
696: continue;
697: }
698:
699: logno = zflash_oob_logno(sc, oob);
700: if (logno == UINT_MAX) {
701: DPRINTF(("blkno %u: can't read logno\n", blkno));
702: phyuse[blkno] |= P_JFFS2;
703: unusable++;
704: continue;
705: }
706:
707: if (logno == USHRT_MAX) {
708: phyuse[blkno] |= P_DUST;
709: /* Block is usable and available. */
710: continue;
711: }
712:
713: if (logno >= sp->sp_lblks) {
714: DPRINTF(("blkno %u: logno %u too big\n", blkno,
715: logno));
716: phyuse[blkno] |= P_JFFS2;
717: unusable++;
718: continue;
719: }
720:
721: if (logmap[logno] == UINT_MAX) {
722: phyuse[blkno] |= P_LOGICAL;
723: logmap[logno] = blkno;
724: } else {
725: /* Duplicate logical block! */
726: DPRINTF(("blkno %u: duplicate logno %u\n", blkno,
727: logno));
728: phyuse[blkno] |= P_DUST;
729: }
730: }
731: flash_chip_disable(&sc->sc_flash);
732:
733: if (unusable > 0)
734: printf("%s: %u unusable blocks\n",
735: sc->sc_flash.sc_dev.dv_xname, unusable);
736:
737: sc->sc_safe[part] = sp;
738: return 0;
739: }
740:
741: void
742: zflash_safe_stop(struct zflash_softc *sc, dev_t dev)
743: {
744: struct zflash_safe *sp;
745: int part;
746:
747: part = flashpart(dev);
748: if (sc->sc_safe[part] == NULL)
749: return;
750:
751: sp = sc->sc_safe[part];
752: free(sp->sp_phyuse, M_DEVBUF);
753: free(sp->sp_logmap, M_DEVBUF);
754: FREE(sp, M_DEVBUF);
755: sc->sc_safe[part] = NULL;
756: }
757:
758: u_int
759: zflash_safe_next_block(struct zflash_safe *sp)
760: {
761: u_int blkno;
762:
763: for (blkno = sp->sp_pnext; blkno < sp->sp_pblks; blkno++)
764: if (sp->sp_phyuse[blkno] == (P_NORMALBLOCK|P_DUST)) {
765: sp->sp_pnext = blkno + 1;
766: return blkno;
767: }
768:
769: for (blkno = 0; blkno < sp->sp_pnext; blkno++)
770: if (sp->sp_phyuse[blkno] == (P_NORMALBLOCK|P_DUST)) {
771: sp->sp_pnext = blkno + 1;
772: return blkno;
773: }
774:
775: return UINT_MAX;
776: }
777:
778: /*
779: * Correct single bit errors in the block's status byte.
780: */
781: u_char
782: zflash_oob_status_decode(u_char status)
783: {
784: u_char bit;
785: int count;
786:
787: /* Speed-up. */
788: if (status == 0xff)
789: return 0xff;
790:
791: /* Count the number of bits set in the byte. */
792: for (count = 0, bit = 0x01; bit != 0x00; bit <<= 1)
793: if ((status & bit) != 0)
794: count++;
795:
796: return (count > 6) ? 0xff : 0x00;
797: }
798:
799: /*
800: * Decode the block's status byte into a value for the phyuse map.
801: */
802: u_int16_t
803: zflash_oob_status(struct zflash_softc *sc, u_char *oob)
804: {
805: u_char status;
806:
807: status = zflash_oob_status_decode(oob[sc->sc_ioobbadblk]);
808: if (status != 0xff)
809: return P_BADBLOCK;
810:
811: status = zflash_oob_status_decode(oob[sc->sc_ioobpostbadblk]);
812: if (status != 0xff)
813: return P_POSTBADBLOCK;
814:
815: return P_NORMALBLOCK;
816: }
817:
818: /*
819: * Extract the 16-bit logical block number corresponding to a physical
820: * block from the physical block's OOB data.
821: */
822: u_int
823: zflash_oob_logno(struct zflash_softc *sc, u_char *oob)
824: {
825: int idx_lo, idx_hi;
826: u_int16_t word;
827: u_int16_t bit;
828: int parity;
829:
830: /* Find a matching pair of high and low bytes. */
831: if (oob[OOB_LOGADDR_0_LO] == oob[OOB_LOGADDR_1_LO] &&
832: oob[OOB_LOGADDR_0_HI] == oob[OOB_LOGADDR_1_HI]) {
833: idx_lo = OOB_LOGADDR_0_LO;
834: idx_hi = OOB_LOGADDR_0_HI;
835: } else if (oob[OOB_LOGADDR_1_LO] == oob[OOB_LOGADDR_2_LO] &&
836: oob[OOB_LOGADDR_1_HI] == oob[OOB_LOGADDR_2_HI]) {
837: idx_lo = OOB_LOGADDR_1_LO;
838: idx_hi = OOB_LOGADDR_1_HI;
839: } else if (oob[OOB_LOGADDR_2_LO] == oob[OOB_LOGADDR_0_LO] &&
840: oob[OOB_LOGADDR_2_HI] == oob[OOB_LOGADDR_0_HI]) {
841: idx_lo = OOB_LOGADDR_2_LO;
842: idx_hi = OOB_LOGADDR_2_HI;
843: } else
844: /* Block's OOB data may be invalid. */
845: return UINT_MAX;
846:
847: word = ((u_int16_t)oob[idx_lo] << 0) |
848: ((u_int16_t)oob[idx_hi] << 8);
849:
850: /* Check for parity error in the logical block number. */
851: for (parity = 0, bit = 0x0001; bit != 0x0000; bit <<= 1)
852: if ((word & bit) != 0)
853: parity++;
854: if ((parity & 1) != 0)
855: return UINT_MAX;
856:
857: /* No logical block number assigned to this block? */
858: if (word == USHRT_MAX)
859: return word;
860:
861: /* Return the validated logical block number. */
862: return (word & 0x07fe) >> 1;
863: }
864:
865: void
866: zflash_oob_set_status(struct zflash_softc *sc, u_char *oob, u_int16_t phyuse)
867: {
868: switch (PHYUSE_STATUS(phyuse)) {
869: case P_NORMALBLOCK:
870: oob[sc->sc_ioobbadblk] = 0xff;
871: oob[sc->sc_ioobpostbadblk] = 0xff;
872: break;
873: case P_BADBLOCK:
874: oob[sc->sc_ioobbadblk] = 0x00;
875: oob[sc->sc_ioobpostbadblk] = 0x00;
876: break;
877: case P_POSTBADBLOCK:
878: oob[sc->sc_ioobbadblk] = 0xff;
879: oob[sc->sc_ioobpostbadblk] = 0x00;
880: break;
881: }
882: }
883:
884: void
885: zflash_oob_set_logno(struct zflash_softc *sc, u_char *oob, u_int logno)
886: {
887: u_int16_t word;
888: u_int16_t bit;
889: u_char lo;
890: u_char hi;
891: int parity;
892:
893: /* Why do we set the most significant bit? */
894: word = ((logno & 0x03ff) << 1) | 0x1000;
895:
896: /* Calculate the parity. */
897: for (bit = 0x0001; bit != 0x0000; bit <<= 1)
898: if ((word & bit) != 0)
899: parity++;
900: if ((parity & 1) != 0)
901: word |= 0x0001;
902:
903: lo = word & 0x00ff;
904: hi = (word & 0xff00) >> 8;
905:
906: oob[OOB_LOGADDR_0_LO] = lo;
907: oob[OOB_LOGADDR_0_HI] = hi;
908: oob[OOB_LOGADDR_1_LO] = lo;
909: oob[OOB_LOGADDR_1_HI] = hi;
910: oob[OOB_LOGADDR_2_LO] = lo;
911: oob[OOB_LOGADDR_2_HI] = hi;
912: }
CVSweb