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