Last active
January 5, 2026 13:52
-
-
Save bbaranoff/1d3420074c8207ff919e5c6ce83b3fe1 to your computer and use it in GitHub Desktop.
Adding Calypso machine to qemu
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "qemu/osdep.h" | |
| #include "qemu/units.h" | |
| #include "qemu/log.h" | |
| #include "hw/boards.h" | |
| #include "hw/loader.h" | |
| #include "hw/misc/unimp.h" | |
| #include "hw/char/serial.h" | |
| #include "hw/block/flash.h" | |
| #include "sysemu/sysemu.h" | |
| #include "sysemu/block-backend.h" | |
| #include "exec/address-spaces.h" | |
| #include "target/arm/cpu.h" | |
| #include "elf.h" | |
| #define TYPE_CALYPSO_MIN_MACHINE MACHINE_TYPE_NAME("calypso-min") | |
| OBJECT_DECLARE_SIMPLE_TYPE(CalypsoMinState, CALYPSO_MIN_MACHINE) | |
| #define CALYPSO_FLASH_BASE 0x02000000u | |
| #define CALYPSO_FLASH_SIZE (4 * MiB) | |
| #define FLASH_SECTOR_SIZE (64 * KiB) | |
| #define CALYPSO_RAM_BASE 0x00800000u | |
| #define CALYPSO_RAM_ALIAS0_BASE 0x00000000u | |
| #define CALYPSO_RAM_ALIAS0_SIZE (128 * KiB) | |
| #define CALYPSO_UART_BASE 0xFFFF5800u | |
| #define CALYPSO_SPI_BASE 0xFFFE3000u | |
| #define CALYPSO_SPI_SIZE 0x00000100u | |
| #define SPI_OFF_STATUS 0x06 | |
| #define SPI_OFF_DATA 0x0A | |
| #define ST_TX_READY (1u << 0) | |
| #define ST_RX_READY (1u << 1) | |
| #define CALYPSO_UART_SIZE 0x00000100u | |
| #define UART_OFF_TXRX 0x00 | |
| #define UART_OFF_STATUS 0x11 | |
| #define UART_ST_TX_READY 0x60 /* valeur “OK” pour éviter polling infini */ | |
| #define CALYPSO_SYSFB_BASE 0xFFFFFB00u | |
| #define CALYPSO_SYSFB_SIZE 0x00000100u | |
| #define CALYPSO_SYSFD_BASE 0xFFFFFD00u | |
| #define CALYPSO_SYSFD_SIZE 0x00000100u | |
| #define CALYPSO_48XX_BASE 0xFFFE4800u | |
| #define CALYPSO_48XX_SIZE 0x00000100u | |
| #define CALYPSO_28XX_BASE 0xFFFE2800u | |
| #define CALYPSO_28XX_SIZE 0x00000100u | |
| #define CALYPSO_18XX_BASE 0xFFFE1800u | |
| #define CALYPSO_18XX_SIZE 0x00000100u | |
| #define CALYPSO_68XX_BASE 0xFFFE6800u | |
| #define CALYPSO_68XX_SIZE 0x00000100u | |
| #define CALYPSO_FAXX_BASE 0xFFFFFA00u | |
| #define CALYPSO_FAXX_SIZE 0x00000100u | |
| #define CALYPSO_50XX_BASE 0xFFFF5000u | |
| #define CALYPSO_50XX_SIZE 0x00000100u | |
| #define CALYPSO_FCXX_BASE 0xFFFFFC00u | |
| #define CALYPSO_FCXX_SIZE 0x00000100u | |
| #define CALYPSO_TMR1_BASE 0xFFFE3800u | |
| #define CALYPSO_TMR1_SIZE 0x00000100u /* prends large, le firmware touche au moins +0x00 */ | |
| #define CALYPSO_98XX_BASE 0xFFFF9800u | |
| #define CALYPSO_98XX_SIZE 0x00000100u | |
| #define CALYPSO_F9XX_BASE 0xFFFFF900u | |
| #define CALYPSO_F9XX_SIZE 0x00000100u | |
| #define CALYPSO_F0XX_BASE 0xFFFEF000u | |
| #define CALYPSO_F0XX_SIZE 0x00000100u | |
| #define CALYPSO_VECTORS_HI_BASE 0xFFFF0000u | |
| #define CALYPSO_VECTORS_HI_SIZE 0x00010000u | |
| #define CALYPSO_FFXX_BASE 0xFFFFFF00u | |
| #define CALYPSO_FFXX_SIZE 0x00000100u | |
| #define CALYPSO_80XX_BASE 0xFFFE8000u | |
| #define CALYPSO_80XX_SIZE 0x00000100u | |
| typedef struct CalypsoMinState { | |
| MachineState parent_obj; | |
| ARMCPU *cpu; | |
| MemoryRegion ram; | |
| MemoryRegion ram_alias0; | |
| MemoryRegion stub_mmio; /* Pour utiliser la structure ops */ | |
| MemoryRegion spi_mmio; | |
| uint16_t spi_status; | |
| uint16_t spi_rx; | |
| MemoryRegion uart_mmio; | |
| MemoryRegion uart_alias0; | |
| uint8_t uart_last; | |
| MemoryRegion sysfb_mmio; | |
| MemoryRegion sysfd_mmio; | |
| MemoryRegion mmio_48xx; | |
| uint16_t sysfb_regs[0x80]; /* 0x100 bytes / 2 */ | |
| uint16_t sysfd_regs[0x80]; | |
| uint16_t regs_48xx[0x80]; | |
| MemoryRegion mmio_28xx; | |
| uint8_t regs_28xx[CALYPSO_28XX_SIZE]; | |
| MemoryRegion mmio_18xx; | |
| uint8_t regs_18xx[CALYPSO_18XX_SIZE]; | |
| MemoryRegion mmio_68xx; | |
| uint8_t regs_68xx[CALYPSO_68XX_SIZE]; | |
| MemoryRegion mmio_faxx; | |
| uint16_t regs_faxx[0x80]; | |
| MemoryRegion mmio_faxx_alias0; | |
| MemoryRegion mmio_50xx; | |
| uint8_t regs_50xx[CALYPSO_50XX_SIZE]; | |
| MemoryRegion mmio_fcxx; | |
| MemoryRegion mmio_fcxx_alias0; | |
| uint16_t regs_fcxx[0x80]; | |
| /* Timer @ 0xFFFE3800 */ | |
| MemoryRegion tmr_mmio; | |
| uint16_t tmr_cnt; | |
| MemoryRegion mmio_98xx; | |
| uint16_t regs_98xx[0x80]; | |
| MemoryRegion mmio_f9xx; | |
| MemoryRegion mmio_f9xx_alias0100; | |
| uint16_t regs_f9xx[0x80]; | |
| MemoryRegion mmio_f0xx; | |
| uint16_t regs_f0xx[0x80]; | |
| MemoryRegion ram_alias_hi; | |
| MemoryRegion ffxx_mmio; | |
| uint8_t regs_ffxx[CALYPSO_FFXX_SIZE]; | |
| MemoryRegion mmio_80xx; | |
| uint8_t regs_80xx[CALYPSO_80XX_SIZE]; | |
| } CalypsoMinState; | |
| static uint64_t calypso_stub_read(void *opaque, hwaddr off, unsigned size) { | |
| return (off == 0x06) ? 0x0003 : 0; | |
| } | |
| static void calypso_stub_write(void *opaque, hwaddr off, uint64_t val, unsigned size) { | |
| /* Stub write */ | |
| } | |
| static const MemoryRegionOps calypso_stub_ops = { | |
| .read = calypso_stub_read, | |
| .write = calypso_stub_write, | |
| .endianness = DEVICE_LITTLE_ENDIAN, | |
| }; | |
| static uint64_t calypso_spi_read(void *opaque, hwaddr off, unsigned size) | |
| { | |
| CalypsoMinState *s = (CalypsoMinState *)opaque; | |
| if (size == 2 && off == SPI_OFF_STATUS) { | |
| return s->spi_status; | |
| } | |
| if (size == 2 && off == SPI_OFF_DATA) { | |
| return s->spi_rx; | |
| } | |
| return 0; | |
| } | |
| static void calypso_spi_write(void *opaque, hwaddr off, uint64_t val, unsigned size) | |
| { | |
| CalypsoMinState *s = (CalypsoMinState *)opaque; | |
| if (size == 2 && off == SPI_OFF_DATA) { | |
| /* répond quelque chose et signale "ready" */ | |
| s->spi_rx = 0xFFFF; | |
| s->spi_status = (ST_TX_READY | ST_RX_READY); | |
| } | |
| } | |
| static uint64_t calypso_uart_read(void *opaque, hwaddr off, unsigned size) | |
| { | |
| CalypsoMinState *s = (CalypsoMinState *)opaque; | |
| if (size != 1) { | |
| return 0; | |
| } | |
| if (off == UART_OFF_STATUS) { | |
| return UART_ST_TX_READY; | |
| } | |
| if (off == UART_OFF_TXRX) { | |
| return s->uart_last; | |
| } | |
| return 0; | |
| } | |
| static void calypso_uart_write(void *opaque, hwaddr off, uint64_t val, unsigned size) | |
| { | |
| CalypsoMinState *s = (CalypsoMinState *)opaque; | |
| if (size != 1) { | |
| return; | |
| } | |
| if (off == UART_OFF_TXRX) { | |
| s->uart_last = (uint8_t)val; | |
| /* log minimal */ | |
| qemu_log_mask(LOG_GUEST_ERROR, "[calypso-uart] '%c' (0x%02x)\n", | |
| (val >= 32 && val < 127) ? (char)val : '.', (unsigned)val); | |
| } | |
| } | |
| static const MemoryRegionOps calypso_uart_ops = { | |
| .read = calypso_uart_read, | |
| .write = calypso_uart_write, | |
| .endianness = DEVICE_LITTLE_ENDIAN, | |
| }; | |
| static uint64_t calypso_reg16_read(void *opaque, hwaddr off, unsigned size) | |
| { | |
| uint16_t *regs = (uint16_t *)opaque; | |
| if (size != 2) { | |
| return 0; | |
| } | |
| off &= 0xFE; /* aligne 16-bit */ | |
| uint32_t idx = (uint32_t)(off >> 1); | |
| return regs[idx]; | |
| } | |
| static void calypso_reg16_write(void *opaque, hwaddr off, uint64_t val, unsigned size) | |
| { | |
| uint16_t *regs = (uint16_t *)opaque; | |
| if (size != 2) { | |
| return; | |
| } | |
| off &= 0xFE; | |
| uint32_t idx = (uint32_t)(off >> 1); | |
| regs[idx] = (uint16_t)val; | |
| } | |
| /* Variante “always ready” pour casser les polls */ | |
| static uint64_t calypso_ready16_read(void *opaque, hwaddr off, unsigned size) | |
| { | |
| uint16_t *regs = (uint16_t *)opaque; | |
| if (size != 2) { | |
| return 0; | |
| } | |
| off &= 0xFE; | |
| uint32_t idx = (uint32_t)(off >> 1); | |
| /* Force un bit “ready” (0xFFFF = prêt pour beaucoup de drivers crades) */ | |
| if (off == 0x0A) { /* ton log lit 0x...480A */ | |
| return 0xFFFF; | |
| } | |
| return regs[idx]; | |
| } | |
| static const MemoryRegionOps calypso_reg16_ops = { | |
| .read = calypso_reg16_read, | |
| .write = calypso_reg16_write, | |
| .endianness = DEVICE_LITTLE_ENDIAN, | |
| }; | |
| static const MemoryRegionOps calypso_ready16_ops = { | |
| .read = calypso_ready16_read, | |
| .write = calypso_reg16_write, | |
| .endianness = DEVICE_LITTLE_ENDIAN, | |
| }; | |
| static uint64_t calypso_reg8_read(void *opaque, hwaddr off, unsigned size) | |
| { | |
| uint8_t *regs = (uint8_t *)opaque; | |
| if (size != 1) { | |
| return 0; | |
| } | |
| /* Pour casser le polling: offsets vus dans ton log */ | |
| if (off == 0x04 || off == 0x09) { | |
| return 0xFF; | |
| } | |
| return regs[off & 0xFF]; | |
| if (off == 0x03) { | |
| /* “power key pressed” + “no pending irq” style: renvoie un truc non-bloquant */ | |
| return 0x01; | |
| } | |
| } | |
| static void calypso_reg8_write(void *opaque, hwaddr off, uint64_t val, unsigned size) | |
| { | |
| uint8_t *regs = (uint8_t *)opaque; | |
| if (size != 1) { | |
| return; | |
| } | |
| regs[off & 0xFF] = (uint8_t)val; | |
| } | |
| static uint64_t calypso_80xx_read(void *opaque, hwaddr off, unsigned size) | |
| { | |
| CalypsoMinState *s = opaque; | |
| if (size != 1) { | |
| return 0; | |
| } | |
| return s->regs_80xx[off & 0xFF]; | |
| } | |
| static inline void calypso_log_mmio(const char *op, hwaddr addr, | |
| unsigned size, uint64_t val, bool has_val) | |
| { | |
| if (has_val) { | |
| qemu_log_mask(LOG_GUEST_ERROR, | |
| "[calypso-mmio] %s addr=0x%08" HWADDR_PRIx " size=%u val=0x%08" PRIx64 "\n", | |
| op, addr, size, val); | |
| } else { | |
| qemu_log_mask(LOG_GUEST_ERROR, | |
| "[calypso-mmio] %s addr=0x%08" HWADDR_PRIx " size=%u\n", | |
| op, addr, size); | |
| } | |
| } | |
| static void calypso_80xx_write(void *opaque, hwaddr off, uint64_t val, unsigned size) | |
| { | |
| CalypsoMinState *s = opaque; | |
| if (size != 1) { | |
| return; | |
| } | |
| s->regs_80xx[off & 0xFF] = (uint8_t)val; | |
| calypso_log_mmio("80XX-WRITE", CALYPSO_80XX_BASE + off, size, val, true); | |
| } | |
| static const MemoryRegionOps calypso_80xx_ops = { | |
| .read = calypso_80xx_read, | |
| .write = calypso_80xx_write, | |
| .endianness = DEVICE_LITTLE_ENDIAN, | |
| }; | |
| static const MemoryRegionOps calypso_reg8_ops = { | |
| .read = calypso_reg8_read, | |
| .write = calypso_reg8_write, | |
| .endianness = DEVICE_LITTLE_ENDIAN, | |
| }; | |
| static uint64_t calypso_reg8_16_read(void *opaque, hwaddr off, unsigned size) | |
| { | |
| uint8_t *r = (uint8_t *)opaque; | |
| off &= 0xFF; | |
| if (size == 1) { | |
| /* casse les polls éventuels */ | |
| if (off == 0x00) return 0xFF; | |
| return r[off]; | |
| } | |
| if (size == 2) { | |
| uint16_t lo = r[off]; | |
| uint16_t hi = r[(off + 1) & 0xFF]; | |
| return (hi << 8) | lo; /* little-endian */ | |
| } | |
| return 0; | |
| } | |
| static void calypso_reg8_16_write(void *opaque, hwaddr off, uint64_t val, unsigned size) | |
| { | |
| uint8_t *r = (uint8_t *)opaque; | |
| off &= 0xFF; | |
| if (size == 1) { | |
| r[off] = (uint8_t)val; | |
| return; | |
| } | |
| if (size == 2) { | |
| r[off] = (uint8_t)(val & 0xFF); | |
| r[(off + 1) & 0xFF] = (uint8_t)((val >> 8) & 0xFF); | |
| return; | |
| } | |
| } | |
| static uint64_t calypso_tmr_read(void *opaque, hwaddr off, unsigned size) | |
| { | |
| CalypsoMinState *s = (CalypsoMinState *)opaque; | |
| if (size == 1) { | |
| /* renvoie qqchose de stable pour éviter le blocage */ | |
| if ((off & 0xFF) == 0x02) { | |
| return (uint8_t)(s->tmr_cnt++ & 0xFF); | |
| } | |
| return 0; | |
| } | |
| if (size == 2) { | |
| if ((off & 0xFF) == 0x02) { | |
| return s->tmr_cnt++; | |
| } | |
| return 0; | |
| } | |
| return 0; | |
| } | |
| static void calypso_tmr_write(void *opaque, hwaddr off, uint64_t val, unsigned size) | |
| { | |
| (void)opaque; (void)val; | |
| /* accepter size 1 / 2 */ | |
| calypso_log_mmio("TMR-WRITE", CALYPSO_TMR1_BASE + off, size, val, true); | |
| } | |
| static const MemoryRegionOps calypso_reg8_16_ops = { | |
| .read = calypso_reg8_16_read, | |
| .write = calypso_reg8_16_write, | |
| .endianness = DEVICE_LITTLE_ENDIAN, | |
| }; | |
| static const MemoryRegionOps calypso_tmr_ops = { | |
| .read = calypso_tmr_read, | |
| .write = calypso_tmr_write, | |
| .endianness = DEVICE_LITTLE_ENDIAN, | |
| }; | |
| static uint64_t calypso_ffxx_read(void *opaque, hwaddr off, unsigned size) | |
| { | |
| CalypsoMinState *s = opaque; | |
| if (size != 1) { | |
| return 0; | |
| } | |
| /* Valeur par défaut "safe" */ | |
| uint8_t v = s->regs_ffxx[off & 0xFF]; | |
| /* Option anti-blocage : si ça poll un status, on pourra ajuster ici */ | |
| return v; | |
| } | |
| static void calypso_ffxx_write(void *opaque, hwaddr off, uint64_t val, unsigned size) | |
| { | |
| CalypsoMinState *s = opaque; | |
| if (size != 1) { | |
| return; | |
| } | |
| s->regs_ffxx[off & 0xFF] = (uint8_t)val; | |
| calypso_log_mmio("FFXX-WRITE", CALYPSO_FFXX_BASE + off, size, val, true); | |
| } | |
| static const MemoryRegionOps calypso_ffxx_ops = { | |
| .read = calypso_ffxx_read, | |
| .write = calypso_ffxx_write, | |
| .endianness = DEVICE_LITTLE_ENDIAN, | |
| }; | |
| static void calypso_min_init(MachineState *ms) | |
| { | |
| CalypsoMinState *s = CALYPSO_MIN_MACHINE(ms); | |
| MemoryRegion *sysmem = get_system_memory(); | |
| s->cpu = ARM_CPU(cpu_create(ms->cpu_type ? ms->cpu_type : ARM_CPU_TYPE_NAME("arm946"))); | |
| /* 1. RAM principale */ | |
| memory_region_init_ram(&s->ram, NULL, "calypso.ram", ms->ram_size, &error_fatal); | |
| memory_region_add_subregion(sysmem, CALYPSO_RAM_BASE, &s->ram); | |
| /* 2. Alias RAM @ 0x0 (Priorité 1) - Garantit l'affichage */ | |
| memory_region_init_alias(&s->ram_alias0, NULL, "calypso.ram.alias0", | |
| &s->ram, 0, CALYPSO_RAM_ALIAS0_SIZE); | |
| memory_region_add_subregion_overlap(sysmem, CALYPSO_RAM_ALIAS0_BASE, &s->ram_alias0, 1); | |
| s->spi_status = (ST_TX_READY | ST_RX_READY); | |
| s->spi_rx = 0xFFFF; | |
| /* Alias vecteurs HIGH @ 0xFFFF0000 (certains firmwares/CPU le veulent) */ | |
| memory_region_init_alias(&s->ram_alias_hi, NULL, "calypso.ram.aliashi", | |
| &s->ram, 0, CALYPSO_VECTORS_HI_SIZE); | |
| memory_region_add_subregion_overlap(get_system_memory(), CALYPSO_VECTORS_HI_BASE, | |
| &s->ram_alias_hi, -1); | |
| static const MemoryRegionOps calypso_spi_ops = { | |
| .read = calypso_spi_read, | |
| .write = calypso_spi_write, | |
| .endianness = DEVICE_LITTLE_ENDIAN, | |
| }; | |
| memset(s->regs_ffxx, 0x00, sizeof(s->regs_ffxx)); | |
| memory_region_init_io(&s->ffxx_mmio, NULL, &calypso_ffxx_ops, s, | |
| "calypso.ffxx", CALYPSO_FFXX_SIZE); | |
| memory_region_add_subregion(get_system_memory(), CALYPSO_FFXX_BASE, &s->ffxx_mmio); | |
| /* UART stub @ 0xFFFF5800 */ | |
| memory_region_init_io(&s->uart_mmio, NULL, &calypso_uart_ops, s, | |
| "calypso.uart", CALYPSO_UART_SIZE); | |
| memory_region_add_subregion(get_system_memory(), CALYPSO_UART_BASE, &s->uart_mmio); | |
| /* Alias UART @ 0x00000000 pour couvrir les reads à 0x11 */ | |
| memory_region_init_alias(&s->uart_alias0, NULL, "calypso.uart.alias0", | |
| &s->uart_mmio, 0, CALYPSO_UART_SIZE); | |
| memory_region_add_subregion_overlap(get_system_memory(), 0x00000000u, | |
| &s->uart_alias0, -2); | |
| memory_region_init_io(&s->spi_mmio, NULL, &calypso_spi_ops, s, "calypso.spi", CALYPSO_SPI_SIZE); | |
| memory_region_add_subregion(sysmem, CALYPSO_SPI_BASE, &s->spi_mmio); | |
| /* 3. NOR Flash @ 0x02000000 (Miroir pour éviter le conflit avec la RAM) */ | |
| DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); | |
| pflash_cfi01_register(CALYPSO_FLASH_BASE, "calypso.flash", CALYPSO_FLASH_SIZE, | |
| dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, | |
| FLASH_SECTOR_SIZE, 4, | |
| 0x0089, 0x8871, 0x0089, 0x8871, 0); | |
| /* 4. Utilisation des ops pour éviter l'erreur de compilation */ | |
| memory_region_init_io(&s->stub_mmio, NULL, &calypso_stub_ops, s, "calypso.stub", 0x100); | |
| memory_region_add_subregion(sysmem, 0xFFFE4000, &s->stub_mmio); | |
| /* 5. UART */ | |
| if (serial_hd(0)) { | |
| serial_mm_init(sysmem, CALYPSO_UART_BASE, 0, NULL, 115200, serial_hd(0), DEVICE_LITTLE_ENDIAN); | |
| } | |
| /* 0xFFFFFB00 block */ | |
| memory_region_init_io(&s->sysfb_mmio, NULL, &calypso_reg16_ops, | |
| s->sysfb_regs, "calypso.sysfb", CALYPSO_SYSFB_SIZE); | |
| memory_region_add_subregion(get_system_memory(), CALYPSO_SYSFB_BASE, &s->sysfb_mmio); | |
| /* 0xFFFFFD00 block */ | |
| memory_region_init_io(&s->sysfd_mmio, NULL, &calypso_reg16_ops, | |
| s->sysfd_regs, "calypso.sysfd", CALYPSO_SYSFD_SIZE); | |
| memory_region_add_subregion(get_system_memory(), CALYPSO_SYSFD_BASE, &s->sysfd_mmio); | |
| /* 0xFFFE4800 block: status “ready” à +0x0A */ | |
| memory_region_init_io(&s->mmio_48xx, NULL, &calypso_ready16_ops, | |
| s->regs_48xx, "calypso.48xx", CALYPSO_48XX_SIZE); | |
| memory_region_add_subregion(get_system_memory(), CALYPSO_48XX_BASE, &s->mmio_48xx); | |
| memory_region_init_io(&s->mmio_28xx, NULL, &calypso_reg8_ops, | |
| s->regs_28xx, "calypso.28xx", CALYPSO_28XX_SIZE); | |
| memory_region_add_subregion(get_system_memory(), CALYPSO_28XX_BASE, &s->mmio_28xx); | |
| memory_region_init_io(&s->mmio_18xx, NULL, &calypso_reg8_ops, | |
| s->regs_18xx, "calypso.18xx", CALYPSO_18XX_SIZE); | |
| memory_region_add_subregion(get_system_memory(), CALYPSO_18XX_BASE, &s->mmio_18xx); | |
| memory_region_init_io(&s->mmio_68xx, NULL, &calypso_reg8_16_ops, | |
| s->regs_68xx, "calypso.68xx", CALYPSO_68XX_SIZE); | |
| memory_region_add_subregion(get_system_memory(), CALYPSO_68XX_BASE, &s->mmio_68xx); | |
| memory_region_init_io(&s->mmio_faxx, NULL, &calypso_reg16_ops, | |
| s->regs_faxx, "calypso.faxx", CALYPSO_FAXX_SIZE); | |
| memory_region_add_subregion(get_system_memory(), CALYPSO_FAXX_BASE, &s->mmio_faxx); | |
| memory_region_init_alias(&s->mmio_faxx_alias0, NULL, "calypso.faxx.alias0", | |
| &s->mmio_faxx, 0, CALYPSO_FAXX_SIZE); | |
| memory_region_add_subregion_overlap(get_system_memory(), 0x00000000u, | |
| &s->mmio_faxx_alias0, -3); | |
| memory_region_init_io(&s->mmio_50xx, NULL, &calypso_reg8_ops, | |
| s->regs_50xx, "calypso.50xx", CALYPSO_50XX_SIZE); | |
| memory_region_add_subregion(get_system_memory(), CALYPSO_50XX_BASE, &s->mmio_50xx); | |
| memory_region_init_io(&s->mmio_fcxx, NULL, &calypso_reg16_ops, | |
| s->regs_fcxx, "calypso.fcxx", CALYPSO_FCXX_SIZE); | |
| memory_region_add_subregion(get_system_memory(), CALYPSO_FCXX_BASE, &s->mmio_fcxx); | |
| /* Alias bas pour capter 0x00000002 */ | |
| memory_region_init_alias(&s->mmio_fcxx_alias0, NULL, "calypso.fcxx.alias0", | |
| &s->mmio_fcxx, 0, CALYPSO_FCXX_SIZE); | |
| memory_region_add_subregion_overlap(get_system_memory(), 0x00000000u, | |
| &s->mmio_fcxx_alias0, -4); | |
| /* Stub Timer (Priorité 1) */ | |
| s->tmr_cnt = 0; | |
| memory_region_init_io(&s->tmr_mmio, NULL, &calypso_tmr_ops, s, | |
| "calypso.tmr1", CALYPSO_TMR1_SIZE); | |
| memory_region_add_subregion_overlap(get_system_memory(), CALYPSO_TMR1_BASE, | |
| &s->tmr_mmio, 1); | |
| memory_region_init_io(&s->mmio_98xx, NULL, &calypso_reg16_ops, | |
| s->regs_98xx, "calypso.98xx", CALYPSO_98XX_SIZE); | |
| memory_region_add_subregion(get_system_memory(), CALYPSO_98XX_BASE, &s->mmio_98xx); | |
| memory_region_init_io(&s->mmio_f9xx, NULL, &calypso_reg16_ops, | |
| s->regs_f9xx, "calypso.f9xx", CALYPSO_F9XX_SIZE); | |
| memory_region_add_subregion(get_system_memory(), CALYPSO_F9XX_BASE, &s->mmio_f9xx); | |
| /* Alias bas à 0x00000100 pour capter 0x100/0x102/0x104 */ | |
| memory_region_init_alias(&s->mmio_f9xx_alias0100, NULL, "calypso.f9xx.alias0100", | |
| &s->mmio_f9xx, 0, 0x100); | |
| memory_region_add_subregion_overlap(get_system_memory(), 0x00000100u, | |
| &s->mmio_f9xx_alias0100, -5); | |
| memory_region_init_io(&s->mmio_f0xx, NULL, &calypso_reg16_ops, | |
| s->regs_f0xx, "calypso.f0xx", CALYPSO_F0XX_SIZE); | |
| memory_region_add_subregion(get_system_memory(), CALYPSO_F0XX_BASE, &s->mmio_f0xx); | |
| memset(s->regs_80xx, 0x00, sizeof(s->regs_80xx)); | |
| memory_region_init_io(&s->mmio_80xx, NULL, &calypso_80xx_ops, s, | |
| "calypso.80xx", CALYPSO_80XX_SIZE); | |
| memory_region_add_subregion(get_system_memory(), CALYPSO_80XX_BASE, &s->mmio_80xx); | |
| /* 6. Chargement ELF et Patch de la variable 'the_flash' */ | |
| if (ms->kernel_filename) { | |
| uint64_t entry = 0; | |
| if (load_elf(ms->kernel_filename, NULL, NULL, &entry, NULL, NULL, NULL, NULL, 0, EM_ARM, 1, 0) >= 0) { | |
| /* Patch de la variable 'the_flash' (0x008147e8) pour pointer sur 0x02000000 */ | |
| uint32_t flash_addr = tswap32(CALYPSO_FLASH_BASE); | |
| cpu_physical_memory_write(0x008147e8, &flash_addr, 4); | |
| cpu_set_pc(CPU(s->cpu), entry); | |
| } | |
| } | |
| } | |
| static void calypso_min_class_init(ObjectClass *oc, void *data) { | |
| MachineClass *mc = MACHINE_CLASS(oc); | |
| mc->init = calypso_min_init; | |
| mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm946"); | |
| mc->ignore_memory_transaction_failures = true; | |
| } | |
| static const TypeInfo calypso_min_typeinfo = { | |
| .name = TYPE_CALYPSO_MIN_MACHINE, .parent = TYPE_MACHINE, | |
| .instance_size = sizeof(CalypsoMinState), .class_init = calypso_min_class_init, | |
| }; | |
| static void calypso_min_register_types(void) { type_register_static(&calypso_min_typeinfo); } | |
| type_init(calypso_min_register_types); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment