~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to hw/pflash_cfi01.c

  • Committer: Blue Swirl
  • Date: 2009-08-31 15:14:40 UTC
  • Revision ID: git-v1:528e93a9787ccfc59582a44035f5f342caf5b84f
Fix breakage due to __thread

Thread-local storage is not supported on all hosts.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 * Lesser General Public License for more details.
16
16
 *
17
17
 * You should have received a copy of the GNU Lesser General Public
18
 
 * License along with this library; if not, write to the Free Software
19
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20
19
 */
21
20
 
22
21
/*
42
41
#include "block.h"
43
42
#include "qemu-timer.h"
44
43
 
45
 
#define PFLASH_BUG(fmt, args...) \
 
44
#define PFLASH_BUG(fmt, ...) \
46
45
do { \
47
 
    printf("PFLASH: Possible BUG - " fmt, ##args); \
 
46
    printf("PFLASH: Possible BUG - " fmt, ## __VA_ARGS__); \
48
47
    exit(1); \
49
48
} while(0)
50
49
 
51
50
/* #define PFLASH_DEBUG */
52
51
#ifdef PFLASH_DEBUG
53
 
#define DPRINTF(fmt, args...)                      \
 
52
#define DPRINTF(fmt, ...)                          \
54
53
do {                                               \
55
 
        printf("PFLASH: " fmt , ##args);           \
 
54
    printf("PFLASH: " fmt , ## __VA_ARGS__);       \
56
55
} while (0)
57
56
#else
58
 
#define DPRINTF(fmt, args...) do { } while (0)
 
57
#define DPRINTF(fmt, ...) do { } while (0)
59
58
#endif
60
59
 
61
60
struct pflash_t {
62
61
    BlockDriverState *bs;
63
 
    target_ulong base;
64
 
    target_ulong sector_len;
65
 
    target_ulong total_len;
 
62
    target_phys_addr_t base;
 
63
    target_phys_addr_t sector_len;
 
64
    target_phys_addr_t total_len;
66
65
    int width;
67
66
    int wcycle; /* if 0, the flash is read normally */
68
67
    int bypass;
72
71
    uint16_t ident[4];
73
72
    uint8_t cfi_len;
74
73
    uint8_t cfi_table[0x52];
75
 
    target_ulong counter;
 
74
    target_phys_addr_t counter;
76
75
    QEMUTimer *timer;
77
76
    ram_addr_t off;
78
77
    int fl_mem;
96
95
    pfl->cmd = 0;
97
96
}
98
97
 
99
 
static uint32_t pflash_read (pflash_t *pfl, target_ulong offset, int width)
 
98
static uint32_t pflash_read (pflash_t *pfl, target_phys_addr_t offset,
 
99
                             int width)
100
100
{
101
 
    target_ulong boff;
 
101
    target_phys_addr_t boff;
102
102
    uint32_t ret;
103
103
    uint8_t *p;
104
104
 
105
105
    ret = -1;
106
 
    offset -= pfl->base;
107
106
    boff = offset & 0xFF; /* why this here ?? */
108
107
 
109
108
    if (pfl->width == 2)
111
110
    else if (pfl->width == 4)
112
111
        boff = boff >> 2;
113
112
 
114
 
    DPRINTF("%s: reading offset " TARGET_FMT_lx " under cmd %02x\n",
115
 
            __func__, boff, pfl->cmd);
 
113
    DPRINTF("%s: reading offset " TARGET_FMT_lx " under cmd %02x width %d\n",
 
114
            __func__, offset, pfl->cmd, width);
116
115
 
117
116
    switch (pfl->cmd) {
118
117
    case 0x00:
195
194
    }
196
195
}
197
196
 
198
 
static void pflash_write (pflash_t *pfl, target_ulong offset, uint32_t value,
199
 
                          int width)
200
 
{
201
 
    target_ulong boff;
 
197
static void inline pflash_data_write(pflash_t *pfl, target_phys_addr_t offset,
 
198
                          uint32_t value, int width)
 
199
{
 
200
    uint8_t *p = pfl->storage;
 
201
 
 
202
    DPRINTF("%s: block write offset " TARGET_FMT_lx
 
203
            " value %x counter " TARGET_FMT_lx "\n",
 
204
            __func__, offset, value, pfl->counter);
 
205
    switch (width) {
 
206
    case 1:
 
207
        p[offset] = value;
 
208
        pflash_update(pfl, offset, 1);
 
209
        break;
 
210
    case 2:
 
211
#if defined(TARGET_WORDS_BIGENDIAN)
 
212
        p[offset] = value >> 8;
 
213
        p[offset + 1] = value;
 
214
#else
 
215
        p[offset] = value;
 
216
        p[offset + 1] = value >> 8;
 
217
#endif
 
218
        pflash_update(pfl, offset, 2);
 
219
        break;
 
220
    case 4:
 
221
#if defined(TARGET_WORDS_BIGENDIAN)
 
222
        p[offset] = value >> 24;
 
223
        p[offset + 1] = value >> 16;
 
224
        p[offset + 2] = value >> 8;
 
225
        p[offset + 3] = value;
 
226
#else
 
227
        p[offset] = value;
 
228
        p[offset + 1] = value >> 8;
 
229
        p[offset + 2] = value >> 16;
 
230
        p[offset + 3] = value >> 24;
 
231
#endif
 
232
        pflash_update(pfl, offset, 4);
 
233
        break;
 
234
    }
 
235
 
 
236
}
 
237
 
 
238
static void pflash_write(pflash_t *pfl, target_phys_addr_t offset,
 
239
                         uint32_t value, int width)
 
240
{
 
241
    target_phys_addr_t boff;
202
242
    uint8_t *p;
203
243
    uint8_t cmd;
204
244
 
205
 
    /* WARNING: when the memory area is in ROMD mode, the offset is a
206
 
       ram offset, not a physical address */
207
245
    cmd = value;
208
246
 
209
 
    if (pfl->wcycle == 0)
210
 
        offset -= (target_ulong)(long)pfl->storage;
211
 
    else
212
 
        offset -= pfl->base;
213
 
 
214
 
    DPRINTF("%s: offset " TARGET_FMT_lx " %08x %d wcycle 0x%x\n",
 
247
    DPRINTF("%s: writing offset " TARGET_FMT_lx " value %08x width %d wcycle 0x%x\n",
215
248
            __func__, offset, value, width, pfl->wcycle);
216
249
 
217
250
    /* Set the device in I/O access mode */
229
262
        switch (cmd) {
230
263
        case 0x00: /* ??? */
231
264
            goto reset_flash;
 
265
        case 0x10: /* Single Byte Program */
 
266
        case 0x40: /* Single Byte Program */
 
267
            DPRINTF(stderr, "%s: Single Byte Program\n", __func__);
 
268
            break;
232
269
        case 0x20: /* Block erase */
233
270
            p = pfl->storage;
234
271
            offset &= ~(pfl->sector_len - 1);
270
307
        return;
271
308
    case 1:
272
309
        switch (pfl->cmd) {
 
310
        case 0x10: /* Single Byte Program */
 
311
        case 0x40: /* Single Byte Program */
 
312
            DPRINTF("%s: Single Byte Program\n", __func__);
 
313
            pflash_data_write(pfl, offset, value, width);
 
314
            pfl->status |= 0x80; /* Ready! */
 
315
            pfl->wcycle = 0;
 
316
        break;
273
317
        case 0x20: /* Block erase */
274
318
        case 0x28:
275
319
            if (cmd == 0xd0) { /* confirm */
276
 
                pfl->wcycle = 1;
 
320
                pfl->wcycle = 0;
277
321
                pfl->status |= 0x80;
278
322
            } else if (cmd == 0xff) { /* read array mode */
279
323
                goto reset_flash;
282
326
 
283
327
            break;
284
328
        case 0xe8:
285
 
            DPRINTF("%s: block write of %x bytes\n", __func__, cmd);
286
 
            pfl->counter = cmd;
 
329
            DPRINTF("%s: block write of %x bytes\n", __func__, value);
 
330
            pfl->counter = value;
287
331
            pfl->wcycle++;
288
332
            break;
289
333
        case 0x60:
314
358
    case 2:
315
359
        switch (pfl->cmd) {
316
360
        case 0xe8: /* Block write */
317
 
            p = pfl->storage;
318
 
            DPRINTF("%s: block write offset " TARGET_FMT_lx
319
 
                    " value %x counter " TARGET_FMT_lx "\n",
320
 
                    __func__, offset, value, pfl->counter);
321
 
            switch (width) {
322
 
            case 1:
323
 
                p[offset] = value;
324
 
                pflash_update(pfl, offset, 1);
325
 
                break;
326
 
            case 2:
327
 
#if defined(TARGET_WORDS_BIGENDIAN)
328
 
                p[offset] = value >> 8;
329
 
                p[offset + 1] = value;
330
 
#else
331
 
                p[offset] = value;
332
 
                p[offset + 1] = value >> 8;
333
 
#endif
334
 
                pflash_update(pfl, offset, 2);
335
 
                break;
336
 
            case 4:
337
 
#if defined(TARGET_WORDS_BIGENDIAN)
338
 
                p[offset] = value >> 24;
339
 
                p[offset + 1] = value >> 16;
340
 
                p[offset + 2] = value >> 8;
341
 
                p[offset + 3] = value;
342
 
#else
343
 
                p[offset] = value;
344
 
                p[offset + 1] = value >> 8;
345
 
                p[offset + 2] = value >> 16;
346
 
                p[offset + 3] = value >> 24;
347
 
#endif
348
 
                pflash_update(pfl, offset, 4);
349
 
                break;
350
 
            }
 
361
            pflash_data_write(pfl, offset, value, width);
351
362
 
352
363
            pfl->status |= 0x80;
353
364
 
387
398
 
388
399
 error_flash:
389
400
    printf("%s: Unimplemented flash cmd sequence "
390
 
           "(offset " TARGET_FMT_lx ", wcycle 0x%x cmd 0x%x value 0x%x\n",
 
401
           "(offset " TARGET_FMT_plx ", wcycle 0x%x cmd 0x%x value 0x%x)\n",
391
402
           __func__, offset, pfl->wcycle, pfl->cmd, value);
392
403
 
393
404
 reset_flash:
442
453
    pflash_write(pfl, addr, value, 4);
443
454
}
444
455
 
445
 
static CPUWriteMemoryFunc *pflash_write_ops[] = {
 
456
static CPUWriteMemoryFunc * const pflash_write_ops[] = {
446
457
    &pflash_writeb,
447
458
    &pflash_writew,
448
459
    &pflash_writel,
449
460
};
450
461
 
451
 
static CPUReadMemoryFunc *pflash_read_ops[] = {
 
462
static CPUReadMemoryFunc * const pflash_read_ops[] = {
452
463
    &pflash_readb,
453
464
    &pflash_readw,
454
465
    &pflash_readl,
495
506
                                uint16_t id2, uint16_t id3)
496
507
{
497
508
    pflash_t *pfl;
498
 
    target_long total_len;
 
509
    target_phys_addr_t total_len;
 
510
    int ret;
499
511
 
500
512
    total_len = sector_len * nb_blocs;
501
513
 
508
520
 
509
521
    pfl = qemu_mallocz(sizeof(pflash_t));
510
522
 
511
 
    if (pfl == NULL)
512
 
        return NULL;
513
 
    pfl->storage = phys_ram_base + off;
514
 
    pfl->fl_mem = cpu_register_io_memory(0,
 
523
    /* FIXME: Allocate ram ourselves.  */
 
524
    pfl->storage = qemu_get_ram_ptr(off);
 
525
    pfl->fl_mem = cpu_register_io_memory(
515
526
                    pflash_read_ops, pflash_write_ops, pfl);
516
527
    pfl->off = off;
517
528
    cpu_register_physical_memory(base, total_len,
520
531
    pfl->bs = bs;
521
532
    if (pfl->bs) {
522
533
        /* read the initial flash content */
523
 
        bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9);
 
534
        ret = bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9);
 
535
        if (ret < 0) {
 
536
            cpu_unregister_io_memory(pfl->fl_mem);
 
537
            qemu_free(pfl);
 
538
            return NULL;
 
539
        }
524
540
    }
525
541
#if 0 /* XXX: there should be a bit to set up read-only,
526
542
       *      the same way the hardware does (with WP pin).
589
605
    pfl->cfi_table[0x28] = 0x02;
590
606
    pfl->cfi_table[0x29] = 0x00;
591
607
    /* Max number of bytes in multi-bytes write */
592
 
    pfl->cfi_table[0x2A] = 0x04;
 
608
    pfl->cfi_table[0x2A] = 0x0B;
593
609
    pfl->cfi_table[0x2B] = 0x00;
594
610
    /* Number of erase block regions (uniform) */
595
611
    pfl->cfi_table[0x2C] = 0x01;