Revision cfe5f011 hw/pflash_cfi02.c

b/hw/pflash_cfi02.c
39 39
#include "flash.h"
40 40
#include "qemu-timer.h"
41 41
#include "block.h"
42
#include "exec-memory.h"
42 43

  
43 44
//#define PFLASH_DEBUG
44 45
#ifdef PFLASH_DEBUG
......
69 70
    uint8_t cfi_len;
70 71
    uint8_t cfi_table[0x52];
71 72
    QEMUTimer *timer;
72
    ram_addr_t off;
73
    int fl_mem;
73
    /* The device replicates the flash memory across its memory space.  Emulate
74
     * that by having a container (.mem) filled with an array of aliases
75
     * (.mem_mappings) pointing to the flash memory (.orig_mem).
76
     */
77
    MemoryRegion mem;
78
    MemoryRegion *mem_mappings;    /* array; one per mapping */
79
    MemoryRegion orig_mem;
74 80
    int rom_mode;
75 81
    int read_counter; /* used for lazy switch-back to rom mode */
76 82
    void *storage;
77 83
};
78 84

  
79
static void pflash_register_memory(pflash_t *pfl, int rom_mode)
85
/*
86
 * Set up replicated mappings of the same region.
87
 */
88
static void pflash_setup_mappings(pflash_t *pfl)
80 89
{
81
    unsigned long phys_offset = pfl->fl_mem;
82
    int i;
83

  
84
    if (rom_mode)
85
        phys_offset |= pfl->off | IO_MEM_ROMD;
86
    pfl->rom_mode = rom_mode;
90
    unsigned i;
91
    target_phys_addr_t size = memory_region_size(&pfl->orig_mem);
92

  
93
    memory_region_init(&pfl->mem, "pflash", pfl->mappings * size);
94
    pfl->mem_mappings = g_new(MemoryRegion, pfl->mappings);
95
    for (i = 0; i < pfl->mappings; ++i) {
96
        memory_region_init_alias(&pfl->mem_mappings[i], "pflash-alias",
97
                                 &pfl->orig_mem, 0, size);
98
        memory_region_add_subregion(&pfl->mem, i * size, &pfl->mem_mappings[i]);
99
    }
100
}
87 101

  
88
    for (i = 0; i < pfl->mappings; i++)
89
        cpu_register_physical_memory(pfl->base + i * pfl->chip_len,
90
                                     pfl->chip_len, phys_offset);
102
static void pflash_register_memory(pflash_t *pfl, int rom_mode)
103
{
104
    memory_region_rom_device_set_readable(&pfl->orig_mem, rom_mode);
91 105
}
92 106

  
93 107
static void pflash_timer (void *opaque)
......
538 552
    pflash_write(pfl, addr, value, 4, 0);
539 553
}
540 554

  
541
static CPUWriteMemoryFunc * const pflash_write_ops_be[] = {
542
    &pflash_writeb_be,
543
    &pflash_writew_be,
544
    &pflash_writel_be,
545
};
546

  
547
static CPUReadMemoryFunc * const pflash_read_ops_be[] = {
548
    &pflash_readb_be,
549
    &pflash_readw_be,
550
    &pflash_readl_be,
555
static const MemoryRegionOps pflash_cfi02_ops_be = {
556
    .old_mmio = {
557
        .read = { pflash_readb_be, pflash_readw_be, pflash_readl_be, },
558
        .write = { pflash_writeb_be, pflash_writew_be, pflash_writel_be, },
559
    },
560
    .endianness = DEVICE_NATIVE_ENDIAN,
551 561
};
552 562

  
553
static CPUWriteMemoryFunc * const pflash_write_ops_le[] = {
554
    &pflash_writeb_le,
555
    &pflash_writew_le,
556
    &pflash_writel_le,
557
};
558

  
559
static CPUReadMemoryFunc * const pflash_read_ops_le[] = {
560
    &pflash_readb_le,
561
    &pflash_readw_le,
562
    &pflash_readl_le,
563
static const MemoryRegionOps pflash_cfi02_ops_le = {
564
    .old_mmio = {
565
        .read = { pflash_readb_le, pflash_readw_le, pflash_readl_le, },
566
        .write = { pflash_writeb_le, pflash_writew_le, pflash_writel_le, },
567
    },
568
    .endianness = DEVICE_NATIVE_ENDIAN,
563 569
};
564 570

  
565 571
/* Count trailing zeroes of a 32 bits quantity */
......
598 604
    return ret;
599 605
}
600 606

  
601
pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
607
pflash_t *pflash_cfi02_register(target_phys_addr_t base,
608
                                DeviceState *qdev, const char *name,
609
                                target_phys_addr_t size,
602 610
                                BlockDriverState *bs, uint32_t sector_len,
603 611
                                int nb_blocs, int nb_mappings, int width,
604 612
                                uint16_t id0, uint16_t id1,
......
618 626
        return NULL;
619 627
#endif
620 628
    pfl = g_malloc0(sizeof(pflash_t));
621
    /* FIXME: Allocate ram ourselves.  */
622
    pfl->storage = qemu_get_ram_ptr(off);
623
    if (be) {
624
        pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_be,
625
                                             pflash_write_ops_be,
626
                                             pfl, DEVICE_NATIVE_ENDIAN);
627
    } else {
628
        pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_le,
629
                                             pflash_write_ops_le,
630
                                             pfl, DEVICE_NATIVE_ENDIAN);
631
    }
632
    pfl->off = off;
629
    memory_region_init_rom_device(
630
        &pfl->orig_mem, be ? &pflash_cfi02_ops_be : &pflash_cfi02_ops_le, pfl,
631
        qdev, name, size);
632
    pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem);
633 633
    pfl->base = base;
634 634
    pfl->chip_len = chip_len;
635 635
    pfl->mappings = nb_mappings;
636
    pflash_register_memory(pfl, 1);
637 636
    pfl->bs = bs;
638 637
    if (pfl->bs) {
639 638
        /* read the initial flash content */
640 639
        ret = bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9);
641 640
        if (ret < 0) {
642
            cpu_unregister_io_memory(pfl->fl_mem);
643 641
            g_free(pfl);
644 642
            return NULL;
645 643
        }
646 644
    }
645
    pflash_setup_mappings(pfl);
646
    pfl->rom_mode = 1;
647
    memory_region_add_subregion(get_system_memory(), pfl->base, &pfl->mem);
647 648
#if 0 /* XXX: there should be a bit to set up read-only,
648 649
       *      the same way the hardware does (with WP pin).
649 650
       */

Also available in: Unified diff