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