]> Git Repo - qemu.git/blob - hw/nand.c
console: Avoid dereferencing NULL active_console
[qemu.git] / hw / nand.c
1 /*
2  * Flash NAND memory emulation.  Based on "16M x 8 Bit NAND Flash
3  * Memory" datasheet for the KM29U128AT / K9F2808U0A chips from
4  * Samsung Electronic.
5  *
6  * Copyright (c) 2006 Openedhand Ltd.
7  * Written by Andrzej Zaborowski <[email protected]>
8  *
9  * This code is licensed under the GNU GPL v2.
10  */
11
12 #ifndef NAND_IO
13
14 # include "hw.h"
15 # include "flash.h"
16 # include "blockdev.h"
17 /* FIXME: Pass block device as an argument.  */
18
19 # define NAND_CMD_READ0         0x00
20 # define NAND_CMD_READ1         0x01
21 # define NAND_CMD_READ2         0x50
22 # define NAND_CMD_LPREAD2       0x30
23 # define NAND_CMD_NOSERIALREAD2 0x35
24 # define NAND_CMD_RANDOMREAD1   0x05
25 # define NAND_CMD_RANDOMREAD2   0xe0
26 # define NAND_CMD_READID        0x90
27 # define NAND_CMD_RESET         0xff
28 # define NAND_CMD_PAGEPROGRAM1  0x80
29 # define NAND_CMD_PAGEPROGRAM2  0x10
30 # define NAND_CMD_CACHEPROGRAM2 0x15
31 # define NAND_CMD_BLOCKERASE1   0x60
32 # define NAND_CMD_BLOCKERASE2   0xd0
33 # define NAND_CMD_READSTATUS    0x70
34 # define NAND_CMD_COPYBACKPRG1  0x85
35
36 # define NAND_IOSTATUS_ERROR    (1 << 0)
37 # define NAND_IOSTATUS_PLANE0   (1 << 1)
38 # define NAND_IOSTATUS_PLANE1   (1 << 2)
39 # define NAND_IOSTATUS_PLANE2   (1 << 3)
40 # define NAND_IOSTATUS_PLANE3   (1 << 4)
41 # define NAND_IOSTATUS_BUSY     (1 << 6)
42 # define NAND_IOSTATUS_UNPROTCT (1 << 7)
43
44 # define MAX_PAGE               0x800
45 # define MAX_OOB                0x40
46
47 struct NANDFlashState {
48     uint8_t manf_id, chip_id;
49     int size, pages;
50     int page_shift, oob_shift, erase_shift, addr_shift;
51     uint8_t *storage;
52     BlockDriverState *bdrv;
53     int mem_oob;
54
55     int cle, ale, ce, wp, gnd;
56
57     uint8_t io[MAX_PAGE + MAX_OOB + 0x400];
58     uint8_t *ioaddr;
59     int iolen;
60
61     uint32_t cmd, addr;
62     int addrlen;
63     int status;
64     int offset;
65
66     void (*blk_write)(NANDFlashState *s);
67     void (*blk_erase)(NANDFlashState *s);
68     void (*blk_load)(NANDFlashState *s, uint32_t addr, int offset);
69 };
70
71 # define NAND_NO_AUTOINCR       0x00000001
72 # define NAND_BUSWIDTH_16       0x00000002
73 # define NAND_NO_PADDING        0x00000004
74 # define NAND_CACHEPRG          0x00000008
75 # define NAND_COPYBACK          0x00000010
76 # define NAND_IS_AND            0x00000020
77 # define NAND_4PAGE_ARRAY       0x00000040
78 # define NAND_NO_READRDY        0x00000100
79 # define NAND_SAMSUNG_LP        (NAND_NO_PADDING | NAND_COPYBACK)
80
81 # define NAND_IO
82
83 # define PAGE(addr)             ((addr) >> ADDR_SHIFT)
84 # define PAGE_START(page)       (PAGE(page) * (PAGE_SIZE + OOB_SIZE))
85 # define PAGE_MASK              ((1 << ADDR_SHIFT) - 1)
86 # define OOB_SHIFT              (PAGE_SHIFT - 5)
87 # define OOB_SIZE               (1 << OOB_SHIFT)
88 # define SECTOR(addr)           ((addr) >> (9 + ADDR_SHIFT - PAGE_SHIFT))
89 # define SECTOR_OFFSET(addr)    ((addr) & ((511 >> PAGE_SHIFT) << 8))
90
91 # define PAGE_SIZE              256
92 # define PAGE_SHIFT             8
93 # define PAGE_SECTORS           1
94 # define ADDR_SHIFT             8
95 # include "nand.c"
96 # define PAGE_SIZE              512
97 # define PAGE_SHIFT             9
98 # define PAGE_SECTORS           1
99 # define ADDR_SHIFT             8
100 # include "nand.c"
101 # define PAGE_SIZE              2048
102 # define PAGE_SHIFT             11
103 # define PAGE_SECTORS           4
104 # define ADDR_SHIFT             16
105 # include "nand.c"
106
107 /* Information based on Linux drivers/mtd/nand/nand_ids.c */
108 static const struct {
109     int size;
110     int width;
111     int page_shift;
112     int erase_shift;
113     uint32_t options;
114 } nand_flash_ids[0x100] = {
115     [0 ... 0xff] = { 0 },
116
117     [0x6e] = { 1,       8,      8, 4, 0 },
118     [0x64] = { 2,       8,      8, 4, 0 },
119     [0x6b] = { 4,       8,      9, 4, 0 },
120     [0xe8] = { 1,       8,      8, 4, 0 },
121     [0xec] = { 1,       8,      8, 4, 0 },
122     [0xea] = { 2,       8,      8, 4, 0 },
123     [0xd5] = { 4,       8,      9, 4, 0 },
124     [0xe3] = { 4,       8,      9, 4, 0 },
125     [0xe5] = { 4,       8,      9, 4, 0 },
126     [0xd6] = { 8,       8,      9, 4, 0 },
127
128     [0x39] = { 8,       8,      9, 4, 0 },
129     [0xe6] = { 8,       8,      9, 4, 0 },
130     [0x49] = { 8,       16,     9, 4, NAND_BUSWIDTH_16 },
131     [0x59] = { 8,       16,     9, 4, NAND_BUSWIDTH_16 },
132
133     [0x33] = { 16,      8,      9, 5, 0 },
134     [0x73] = { 16,      8,      9, 5, 0 },
135     [0x43] = { 16,      16,     9, 5, NAND_BUSWIDTH_16 },
136     [0x53] = { 16,      16,     9, 5, NAND_BUSWIDTH_16 },
137
138     [0x35] = { 32,      8,      9, 5, 0 },
139     [0x75] = { 32,      8,      9, 5, 0 },
140     [0x45] = { 32,      16,     9, 5, NAND_BUSWIDTH_16 },
141     [0x55] = { 32,      16,     9, 5, NAND_BUSWIDTH_16 },
142
143     [0x36] = { 64,      8,      9, 5, 0 },
144     [0x76] = { 64,      8,      9, 5, 0 },
145     [0x46] = { 64,      16,     9, 5, NAND_BUSWIDTH_16 },
146     [0x56] = { 64,      16,     9, 5, NAND_BUSWIDTH_16 },
147
148     [0x78] = { 128,     8,      9, 5, 0 },
149     [0x39] = { 128,     8,      9, 5, 0 },
150     [0x79] = { 128,     8,      9, 5, 0 },
151     [0x72] = { 128,     16,     9, 5, NAND_BUSWIDTH_16 },
152     [0x49] = { 128,     16,     9, 5, NAND_BUSWIDTH_16 },
153     [0x74] = { 128,     16,     9, 5, NAND_BUSWIDTH_16 },
154     [0x59] = { 128,     16,     9, 5, NAND_BUSWIDTH_16 },
155
156     [0x71] = { 256,     8,      9, 5, 0 },
157
158     /*
159      * These are the new chips with large page size. The pagesize and the
160      * erasesize is determined from the extended id bytes
161      */
162 # define LP_OPTIONS     (NAND_SAMSUNG_LP | NAND_NO_READRDY | NAND_NO_AUTOINCR)
163 # define LP_OPTIONS16   (LP_OPTIONS | NAND_BUSWIDTH_16)
164
165     /* 512 Megabit */
166     [0xa2] = { 64,      8,      0, 0, LP_OPTIONS },
167     [0xf2] = { 64,      8,      0, 0, LP_OPTIONS },
168     [0xb2] = { 64,      16,     0, 0, LP_OPTIONS16 },
169     [0xc2] = { 64,      16,     0, 0, LP_OPTIONS16 },
170
171     /* 1 Gigabit */
172     [0xa1] = { 128,     8,      0, 0, LP_OPTIONS },
173     [0xf1] = { 128,     8,      0, 0, LP_OPTIONS },
174     [0xb1] = { 128,     16,     0, 0, LP_OPTIONS16 },
175     [0xc1] = { 128,     16,     0, 0, LP_OPTIONS16 },
176
177     /* 2 Gigabit */
178     [0xaa] = { 256,     8,      0, 0, LP_OPTIONS },
179     [0xda] = { 256,     8,      0, 0, LP_OPTIONS },
180     [0xba] = { 256,     16,     0, 0, LP_OPTIONS16 },
181     [0xca] = { 256,     16,     0, 0, LP_OPTIONS16 },
182
183     /* 4 Gigabit */
184     [0xac] = { 512,     8,      0, 0, LP_OPTIONS },
185     [0xdc] = { 512,     8,      0, 0, LP_OPTIONS },
186     [0xbc] = { 512,     16,     0, 0, LP_OPTIONS16 },
187     [0xcc] = { 512,     16,     0, 0, LP_OPTIONS16 },
188
189     /* 8 Gigabit */
190     [0xa3] = { 1024,    8,      0, 0, LP_OPTIONS },
191     [0xd3] = { 1024,    8,      0, 0, LP_OPTIONS },
192     [0xb3] = { 1024,    16,     0, 0, LP_OPTIONS16 },
193     [0xc3] = { 1024,    16,     0, 0, LP_OPTIONS16 },
194
195     /* 16 Gigabit */
196     [0xa5] = { 2048,    8,      0, 0, LP_OPTIONS },
197     [0xd5] = { 2048,    8,      0, 0, LP_OPTIONS },
198     [0xb5] = { 2048,    16,     0, 0, LP_OPTIONS16 },
199     [0xc5] = { 2048,    16,     0, 0, LP_OPTIONS16 },
200 };
201
202 static void nand_reset(NANDFlashState *s)
203 {
204     s->cmd = NAND_CMD_READ0;
205     s->addr = 0;
206     s->addrlen = 0;
207     s->iolen = 0;
208     s->offset = 0;
209     s->status &= NAND_IOSTATUS_UNPROTCT;
210 }
211
212 static void nand_command(NANDFlashState *s)
213 {
214     unsigned int offset;
215     switch (s->cmd) {
216     case NAND_CMD_READ0:
217         s->iolen = 0;
218         break;
219
220     case NAND_CMD_READID:
221         s->io[0] = s->manf_id;
222         s->io[1] = s->chip_id;
223         s->io[2] = 'Q';         /* Don't-care byte (often 0xa5) */
224         if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP)
225             s->io[3] = 0x15;    /* Page Size, Block Size, Spare Size.. */
226         else
227             s->io[3] = 0xc0;    /* Multi-plane */
228         s->ioaddr = s->io;
229         s->iolen = 4;
230         break;
231
232     case NAND_CMD_RANDOMREAD2:
233     case NAND_CMD_NOSERIALREAD2:
234         if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP))
235             break;
236         offset = s->addr & ((1 << s->addr_shift) - 1);
237         s->blk_load(s, s->addr, offset);
238         if (s->gnd)
239             s->iolen = (1 << s->page_shift) - offset;
240         else
241             s->iolen = (1 << s->page_shift) + (1 << s->oob_shift) - offset;
242         break;
243
244     case NAND_CMD_RESET:
245         nand_reset(s);
246         break;
247
248     case NAND_CMD_PAGEPROGRAM1:
249         s->ioaddr = s->io;
250         s->iolen = 0;
251         break;
252
253     case NAND_CMD_PAGEPROGRAM2:
254         if (s->wp) {
255             s->blk_write(s);
256         }
257         break;
258
259     case NAND_CMD_BLOCKERASE1:
260         break;
261
262     case NAND_CMD_BLOCKERASE2:
263         if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP)
264             s->addr <<= 16;
265         else
266             s->addr <<= 8;
267
268         if (s->wp) {
269             s->blk_erase(s);
270         }
271         break;
272
273     case NAND_CMD_READSTATUS:
274         s->io[0] = s->status;
275         s->ioaddr = s->io;
276         s->iolen = 1;
277         break;
278
279     default:
280         printf("%s: Unknown NAND command 0x%02x\n", __FUNCTION__, s->cmd);
281     }
282 }
283
284 static void nand_save(QEMUFile *f, void *opaque)
285 {
286     NANDFlashState *s = (NANDFlashState *) opaque;
287     qemu_put_byte(f, s->cle);
288     qemu_put_byte(f, s->ale);
289     qemu_put_byte(f, s->ce);
290     qemu_put_byte(f, s->wp);
291     qemu_put_byte(f, s->gnd);
292     qemu_put_buffer(f, s->io, sizeof(s->io));
293     qemu_put_be32(f, s->ioaddr - s->io);
294     qemu_put_be32(f, s->iolen);
295
296     qemu_put_be32s(f, &s->cmd);
297     qemu_put_be32s(f, &s->addr);
298     qemu_put_be32(f, s->addrlen);
299     qemu_put_be32(f, s->status);
300     qemu_put_be32(f, s->offset);
301     /* XXX: do we want to save s->storage too? */
302 }
303
304 static int nand_load(QEMUFile *f, void *opaque, int version_id)
305 {
306     NANDFlashState *s = (NANDFlashState *) opaque;
307     s->cle = qemu_get_byte(f);
308     s->ale = qemu_get_byte(f);
309     s->ce = qemu_get_byte(f);
310     s->wp = qemu_get_byte(f);
311     s->gnd = qemu_get_byte(f);
312     qemu_get_buffer(f, s->io, sizeof(s->io));
313     s->ioaddr = s->io + qemu_get_be32(f);
314     s->iolen = qemu_get_be32(f);
315     if (s->ioaddr >= s->io + sizeof(s->io) || s->ioaddr < s->io)
316         return -EINVAL;
317
318     qemu_get_be32s(f, &s->cmd);
319     qemu_get_be32s(f, &s->addr);
320     s->addrlen = qemu_get_be32(f);
321     s->status = qemu_get_be32(f);
322     s->offset = qemu_get_be32(f);
323     return 0;
324 }
325
326 /*
327  * Chip inputs are CLE, ALE, CE, WP, GND and eight I/O pins.  Chip
328  * outputs are R/B and eight I/O pins.
329  *
330  * CE, WP and R/B are active low.
331  */
332 void nand_setpins(NANDFlashState *s,
333                 int cle, int ale, int ce, int wp, int gnd)
334 {
335     s->cle = cle;
336     s->ale = ale;
337     s->ce = ce;
338     s->wp = wp;
339     s->gnd = gnd;
340     if (wp)
341         s->status |= NAND_IOSTATUS_UNPROTCT;
342     else
343         s->status &= ~NAND_IOSTATUS_UNPROTCT;
344 }
345
346 void nand_getpins(NANDFlashState *s, int *rb)
347 {
348     *rb = 1;
349 }
350
351 void nand_setio(NANDFlashState *s, uint8_t value)
352 {
353     if (!s->ce && s->cle) {
354         if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
355             if (s->cmd == NAND_CMD_READ0 && value == NAND_CMD_LPREAD2)
356                 return;
357             if (value == NAND_CMD_RANDOMREAD1) {
358                 s->addr &= ~((1 << s->addr_shift) - 1);
359                 s->addrlen = 0;
360                 return;
361             }
362         }
363         if (value == NAND_CMD_READ0)
364             s->offset = 0;
365         else if (value == NAND_CMD_READ1) {
366             s->offset = 0x100;
367             value = NAND_CMD_READ0;
368         }
369         else if (value == NAND_CMD_READ2) {
370             s->offset = 1 << s->page_shift;
371             value = NAND_CMD_READ0;
372         }
373
374         s->cmd = value;
375
376         if (s->cmd == NAND_CMD_READSTATUS ||
377                 s->cmd == NAND_CMD_PAGEPROGRAM2 ||
378                 s->cmd == NAND_CMD_BLOCKERASE1 ||
379                 s->cmd == NAND_CMD_BLOCKERASE2 ||
380                 s->cmd == NAND_CMD_NOSERIALREAD2 ||
381                 s->cmd == NAND_CMD_RANDOMREAD2 ||
382                 s->cmd == NAND_CMD_RESET)
383             nand_command(s);
384
385         if (s->cmd != NAND_CMD_RANDOMREAD2) {
386             s->addrlen = 0;
387         }
388     }
389
390     if (s->ale) {
391         unsigned int shift = s->addrlen * 8;
392         unsigned int mask = ~(0xff << shift);
393         unsigned int v = value << shift;
394
395         s->addr = (s->addr & mask) | v;
396         s->addrlen ++;
397
398         if (s->addrlen == 1 && s->cmd == NAND_CMD_READID)
399             nand_command(s);
400
401         if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
402                 s->addrlen == 3 && (
403                     s->cmd == NAND_CMD_READ0 ||
404                     s->cmd == NAND_CMD_PAGEPROGRAM1))
405             nand_command(s);
406         if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
407                s->addrlen == 4 && (
408                     s->cmd == NAND_CMD_READ0 ||
409                     s->cmd == NAND_CMD_PAGEPROGRAM1))
410             nand_command(s);
411     }
412
413     if (!s->cle && !s->ale && s->cmd == NAND_CMD_PAGEPROGRAM1) {
414         if (s->iolen < (1 << s->page_shift) + (1 << s->oob_shift))
415             s->io[s->iolen ++] = value;
416     } else if (!s->cle && !s->ale && s->cmd == NAND_CMD_COPYBACKPRG1) {
417         if ((s->addr & ((1 << s->addr_shift) - 1)) <
418                 (1 << s->page_shift) + (1 << s->oob_shift)) {
419             s->io[s->iolen + (s->addr & ((1 << s->addr_shift) - 1))] = value;
420             s->addr ++;
421         }
422     }
423 }
424
425 uint8_t nand_getio(NANDFlashState *s)
426 {
427     int offset;
428
429     /* Allow sequential reading */
430     if (!s->iolen && s->cmd == NAND_CMD_READ0) {
431         offset = (s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
432         s->offset = 0;
433
434         s->blk_load(s, s->addr, offset);
435         if (s->gnd)
436             s->iolen = (1 << s->page_shift) - offset;
437         else
438             s->iolen = (1 << s->page_shift) + (1 << s->oob_shift) - offset;
439     }
440
441     if (s->ce || s->iolen <= 0)
442         return 0;
443
444     s->iolen --;
445     s->addr++;
446     return *(s->ioaddr ++);
447 }
448
449 NANDFlashState *nand_init(int manf_id, int chip_id)
450 {
451     int pagesize;
452     NANDFlashState *s;
453     DriveInfo *dinfo;
454
455     if (nand_flash_ids[chip_id].size == 0) {
456         hw_error("%s: Unsupported NAND chip ID.\n", __FUNCTION__);
457     }
458
459     s = (NANDFlashState *) qemu_mallocz(sizeof(NANDFlashState));
460     dinfo = drive_get(IF_MTD, 0, 0);
461     if (dinfo)
462         s->bdrv = dinfo->bdrv;
463     s->manf_id = manf_id;
464     s->chip_id = chip_id;
465     s->size = nand_flash_ids[s->chip_id].size << 20;
466     if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
467         s->page_shift = 11;
468         s->erase_shift = 6;
469     } else {
470         s->page_shift = nand_flash_ids[s->chip_id].page_shift;
471         s->erase_shift = nand_flash_ids[s->chip_id].erase_shift;
472     }
473
474     switch (1 << s->page_shift) {
475     case 256:
476         nand_init_256(s);
477         break;
478     case 512:
479         nand_init_512(s);
480         break;
481     case 2048:
482         nand_init_2048(s);
483         break;
484     default:
485         hw_error("%s: Unsupported NAND block size.\n", __FUNCTION__);
486     }
487
488     pagesize = 1 << s->oob_shift;
489     s->mem_oob = 1;
490     if (s->bdrv && bdrv_getlength(s->bdrv) >=
491                     (s->pages << s->page_shift) + (s->pages << s->oob_shift)) {
492         pagesize = 0;
493         s->mem_oob = 0;
494     }
495
496     if (!s->bdrv)
497         pagesize += 1 << s->page_shift;
498     if (pagesize)
499         s->storage = (uint8_t *) memset(qemu_malloc(s->pages * pagesize),
500                         0xff, s->pages * pagesize);
501     /* Give s->ioaddr a sane value in case we save state before it
502        is used.  */
503     s->ioaddr = s->io;
504
505     register_savevm(NULL, "nand", -1, 0, nand_save, nand_load, s);
506
507     return s;
508 }
509
510 void nand_done(NANDFlashState *s)
511 {
512     if (s->bdrv) {
513         bdrv_close(s->bdrv);
514         bdrv_delete(s->bdrv);
515     }
516
517     if (!s->bdrv || s->mem_oob)
518         qemu_free(s->storage);
519
520     qemu_free(s);
521 }
522
523 #else
524
525 /* Program a single page */
526 static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
527 {
528     uint32_t off, page, sector, soff;
529     uint8_t iobuf[(PAGE_SECTORS + 2) * 0x200];
530     if (PAGE(s->addr) >= s->pages)
531         return;
532
533     if (!s->bdrv) {
534         memcpy(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) +
535                         s->offset, s->io, s->iolen);
536     } else if (s->mem_oob) {
537         sector = SECTOR(s->addr);
538         off = (s->addr & PAGE_MASK) + s->offset;
539         soff = SECTOR_OFFSET(s->addr);
540         if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1) {
541             printf("%s: read error in sector %i\n", __FUNCTION__, sector);
542             return;
543         }
544
545         memcpy(iobuf + (soff | off), s->io, MIN(s->iolen, PAGE_SIZE - off));
546         if (off + s->iolen > PAGE_SIZE) {
547             page = PAGE(s->addr);
548             memcpy(s->storage + (page << OOB_SHIFT), s->io + PAGE_SIZE - off,
549                             MIN(OOB_SIZE, off + s->iolen - PAGE_SIZE));
550         }
551
552         if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1)
553             printf("%s: write error in sector %i\n", __FUNCTION__, sector);
554     } else {
555         off = PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset;
556         sector = off >> 9;
557         soff = off & 0x1ff;
558         if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1) {
559             printf("%s: read error in sector %i\n", __FUNCTION__, sector);
560             return;
561         }
562
563         memcpy(iobuf + soff, s->io, s->iolen);
564
565         if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1)
566             printf("%s: write error in sector %i\n", __FUNCTION__, sector);
567     }
568     s->offset = 0;
569 }
570
571 /* Erase a single block */
572 static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
573 {
574     uint32_t i, page, addr;
575     uint8_t iobuf[0x200] = { [0 ... 0x1ff] = 0xff, };
576     addr = s->addr & ~((1 << (ADDR_SHIFT + s->erase_shift)) - 1);
577
578     if (PAGE(addr) >= s->pages)
579         return;
580
581     if (!s->bdrv) {
582         memset(s->storage + PAGE_START(addr),
583                         0xff, (PAGE_SIZE + OOB_SIZE) << s->erase_shift);
584     } else if (s->mem_oob) {
585         memset(s->storage + (PAGE(addr) << OOB_SHIFT),
586                         0xff, OOB_SIZE << s->erase_shift);
587         i = SECTOR(addr);
588         page = SECTOR(addr + (ADDR_SHIFT + s->erase_shift));
589         for (; i < page; i ++)
590             if (bdrv_write(s->bdrv, i, iobuf, 1) == -1)
591                 printf("%s: write error in sector %i\n", __FUNCTION__, i);
592     } else {
593         addr = PAGE_START(addr);
594         page = addr >> 9;
595         if (bdrv_read(s->bdrv, page, iobuf, 1) == -1)
596             printf("%s: read error in sector %i\n", __FUNCTION__, page);
597         memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1);
598         if (bdrv_write(s->bdrv, page, iobuf, 1) == -1)
599             printf("%s: write error in sector %i\n", __FUNCTION__, page);
600
601         memset(iobuf, 0xff, 0x200);
602         i = (addr & ~0x1ff) + 0x200;
603         for (addr += ((PAGE_SIZE + OOB_SIZE) << s->erase_shift) - 0x200;
604                         i < addr; i += 0x200)
605             if (bdrv_write(s->bdrv, i >> 9, iobuf, 1) == -1)
606                 printf("%s: write error in sector %i\n", __FUNCTION__, i >> 9);
607
608         page = i >> 9;
609         if (bdrv_read(s->bdrv, page, iobuf, 1) == -1)
610             printf("%s: read error in sector %i\n", __FUNCTION__, page);
611         memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1);
612         if (bdrv_write(s->bdrv, page, iobuf, 1) == -1)
613             printf("%s: write error in sector %i\n", __FUNCTION__, page);
614     }
615 }
616
617 static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
618                 uint32_t addr, int offset)
619 {
620     if (PAGE(addr) >= s->pages)
621         return;
622
623     if (s->bdrv) {
624         if (s->mem_oob) {
625             if (bdrv_read(s->bdrv, SECTOR(addr), s->io, PAGE_SECTORS) == -1)
626                 printf("%s: read error in sector %i\n",
627                                 __FUNCTION__, SECTOR(addr));
628             memcpy(s->io + SECTOR_OFFSET(s->addr) + PAGE_SIZE,
629                             s->storage + (PAGE(s->addr) << OOB_SHIFT),
630                             OOB_SIZE);
631             s->ioaddr = s->io + SECTOR_OFFSET(s->addr) + offset;
632         } else {
633             if (bdrv_read(s->bdrv, PAGE_START(addr) >> 9,
634                                     s->io, (PAGE_SECTORS + 2)) == -1)
635                 printf("%s: read error in sector %i\n",
636                                 __FUNCTION__, PAGE_START(addr) >> 9);
637             s->ioaddr = s->io + (PAGE_START(addr) & 0x1ff) + offset;
638         }
639     } else {
640         memcpy(s->io, s->storage + PAGE_START(s->addr) +
641                         offset, PAGE_SIZE + OOB_SIZE - offset);
642         s->ioaddr = s->io;
643     }
644 }
645
646 static void glue(nand_init_, PAGE_SIZE)(NANDFlashState *s)
647 {
648     s->oob_shift = PAGE_SHIFT - 5;
649     s->pages = s->size >> PAGE_SHIFT;
650     s->addr_shift = ADDR_SHIFT;
651
652     s->blk_erase = glue(nand_blk_erase_, PAGE_SIZE);
653     s->blk_write = glue(nand_blk_write_, PAGE_SIZE);
654     s->blk_load = glue(nand_blk_load_, PAGE_SIZE);
655 }
656
657 # undef PAGE_SIZE
658 # undef PAGE_SHIFT
659 # undef PAGE_SECTORS
660 # undef ADDR_SHIFT
661 #endif  /* NAND_IO */
This page took 0.059762 seconds and 4 git commands to generate.