static uint64_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset, unsigned size) { PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque; int tm = 0; switch (offset) { case OSMR3: tm ++; case OSMR2: tm ++; case OSMR1: tm ++; case OSMR0: return s->timer[tm].value; case OSMR11: tm ++; case OSMR10: tm ++; case OSMR9: tm ++; case OSMR8: tm ++; case OSMR7: tm ++; case OSMR6: tm ++; case OSMR5: tm ++; case OSMR4: if (!pxa2xx_timer_has_tm4(s)) goto badreg; return s->tm4[tm].tm.value; case OSCR: return s->clock + muldiv64(qemu_get_clock_ns(vm_clock) - s->lastload, s->freq, get_ticks_per_sec()); case OSCR11: tm ++; case OSCR10: tm ++; case OSCR9: tm ++; case OSCR8: tm ++; case OSCR7: tm ++; case OSCR6: tm ++; case OSCR5: tm ++; case OSCR4: if (!pxa2xx_timer_has_tm4(s)) goto badreg; if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) { if (s->tm4[tm - 1].freq) s->snapshot = s->tm4[tm - 1].clock + muldiv64( qemu_get_clock_ns(vm_clock) - s->tm4[tm - 1].lastload, s->tm4[tm - 1].freq, get_ticks_per_sec()); else s->snapshot = s->tm4[tm - 1].clock; } if (!s->tm4[tm].freq) return s->tm4[tm].clock; return s->tm4[tm].clock + muldiv64(qemu_get_clock_ns(vm_clock) - s->tm4[tm].lastload, s->tm4[tm].freq, get_ticks_per_sec()); case OIER: return s->irq_enabled; case OSSR: /* Status register */ return s->events; case OWER: return s->reset3; case OMCR11: tm ++; case OMCR10: tm ++; case OMCR9: tm ++; case OMCR8: tm ++; case OMCR7: tm ++; case OMCR6: tm ++; case OMCR5: tm ++; case OMCR4: if (!pxa2xx_timer_has_tm4(s)) goto badreg; return s->tm4[tm].control; case OSNR: return s->snapshot; default: badreg: hw_error("pxa2xx_timer_read: Bad offset " REG_FMT "\n", offset); } return 0; }
static uint64_t pxa2xx_lcdc_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxLCDState *s = (PXA2xxLCDState *) opaque; int ch; switch (offset) { case LCCR0: return s->control[0]; case LCCR1: return s->control[1]; case LCCR2: return s->control[2]; case LCCR3: return s->control[3]; case LCCR4: return s->control[4]; case LCCR5: return s->control[5]; case OVL1C1: return s->ovl1c[0]; case OVL1C2: return s->ovl1c[1]; case OVL2C1: return s->ovl2c[0]; case OVL2C2: return s->ovl2c[1]; case CCR: return s->ccr; case CMDCR: return s->cmdcr; case TRGBR: return s->trgbr; case TCR: return s->tcr; case 0x200 ... 0x1000: /* DMA per-channel registers */ ch = (offset - 0x200) >> 4; if (!(ch >= 0 && ch < PXA_LCDDMA_CHANS)) goto fail; switch (offset & 0xf) { case DMA_FDADR: return s->dma_ch[ch].descriptor; case DMA_FSADR: return s->dma_ch[ch].source; case DMA_FIDR: return s->dma_ch[ch].id; case DMA_LDCMD: return s->dma_ch[ch].command; default: goto fail; } case FBR0: return s->dma_ch[0].branch; case FBR1: return s->dma_ch[1].branch; case FBR2: return s->dma_ch[2].branch; case FBR3: return s->dma_ch[3].branch; case FBR4: return s->dma_ch[4].branch; case FBR5: return s->dma_ch[5].branch; case FBR6: return s->dma_ch[6].branch; case BSCNTR: return s->bscntr; case PRSR: return 0; case LCSR0: return s->status[0]; case LCSR1: return s->status[1]; case LIIDR: return s->liidr; default: fail: hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset); } return 0; }
static void ppc_heathrow_init (ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { MemoryRegion *sysmem = get_system_memory(); CPUPPCState *env = NULL; char *filename; qemu_irq *pic, **heathrow_irqs; int linux_boot, i; MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); uint32_t kernel_base, initrd_base, cmdline_base = 0; int32_t kernel_size, initrd_size; PCIBus *pci_bus; MacIONVRAMState *nvr; int bios_size; MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem; MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1), *ide_mem[2]; uint16_t ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; void *dbdma; linux_boot = (kernel_filename != NULL); /* init CPUs */ if (cpu_model == NULL) cpu_model = "G3"; for (i = 0; i < smp_cpus; i++) { env = cpu_init(cpu_model); if (!env) { fprintf(stderr, "Unable to find PowerPC CPU definition\n"); exit(1); } /* Set time-base frequency to 16.6 Mhz */ cpu_ppc_tb_init(env, 16600000UL); qemu_register_reset(ppc_heathrow_reset, env); } /* allocate RAM */ if (ram_size > (2047 << 20)) { fprintf(stderr, "qemu: Too much memory for this machine: %d MB, maximum 2047 MB\n", ((unsigned int)ram_size / (1 << 20))); exit(1); } memory_region_init_ram(ram, "ppc_heathrow.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(sysmem, 0, ram); /* allocate and load BIOS */ memory_region_init_ram(bios, "ppc_heathrow.bios", BIOS_SIZE); vmstate_register_ram_global(bios); if (bios_name == NULL) bios_name = PROM_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); memory_region_set_readonly(bios, true); memory_region_add_subregion(sysmem, PROM_ADDR, bios); /* Load OpenBIOS (ELF) */ if (filename) { bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL, 1, ELF_MACHINE, 0); g_free(filename); } else { bios_size = -1; } if (bios_size < 0 || bios_size > BIOS_SIZE) { hw_error("qemu: could not load PowerPC bios '%s'\n", bios_name); exit(1); } if (linux_boot) { uint64_t lowaddr = 0; int bswap_needed; #ifdef BSWAP_NEEDED bswap_needed = 1; #else bswap_needed = 0; #endif kernel_base = KERNEL_LOAD_ADDR; kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0); if (kernel_size < 0) kernel_size = load_aout(kernel_filename, kernel_base, ram_size - kernel_base, bswap_needed, TARGET_PAGE_SIZE); if (kernel_size < 0) kernel_size = load_image_targphys(kernel_filename, kernel_base, ram_size - kernel_base); if (kernel_size < 0) { hw_error("qemu: could not load kernel '%s'\n", kernel_filename); exit(1); } /* load initrd */ if (initrd_filename) { initrd_base = round_page(kernel_base + kernel_size + KERNEL_GAP); initrd_size = load_image_targphys(initrd_filename, initrd_base, ram_size - initrd_base); if (initrd_size < 0) { hw_error("qemu: could not load initial ram disk '%s'\n", initrd_filename); exit(1); } cmdline_base = round_page(initrd_base + initrd_size); } else { initrd_base = 0; initrd_size = 0; cmdline_base = round_page(kernel_base + kernel_size + KERNEL_GAP); } ppc_boot_device = 'm'; } else { kernel_base = 0; kernel_size = 0; initrd_base = 0; initrd_size = 0; ppc_boot_device = '\0'; for (i = 0; boot_device[i] != '\0'; i++) { /* TOFIX: for now, the second IDE channel is not properly * used by OHW. The Mac floppy disk are not emulated. * For now, OHW cannot boot from the network. */ #if 0 if (boot_device[i] >= 'a' && boot_device[i] <= 'f') { ppc_boot_device = boot_device[i]; break; } #else if (boot_device[i] >= 'c' && boot_device[i] <= 'd') { ppc_boot_device = boot_device[i]; break; } #endif } if (ppc_boot_device == '\0') { fprintf(stderr, "No valid boot device for G3 Beige machine\n"); exit(1); } } /* Register 2 MB of ISA IO space */ isa_mmio_init(0xfe000000, 0x00200000); /* XXX: we register only 1 output pin for heathrow PIC */ heathrow_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); heathrow_irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * 1); /* Connect the heathrow PIC outputs to the 6xx bus */ for (i = 0; i < smp_cpus; i++) { switch (PPC_INPUT(env)) { case PPC_FLAGS_INPUT_6xx: heathrow_irqs[i] = heathrow_irqs[0] + (i * 1); heathrow_irqs[i][0] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT]; break; default: hw_error("Bus model not supported on OldWorld Mac machine\n"); } } /* init basic PC hardware */ if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) { hw_error("Only 6xx bus is supported on heathrow machine\n"); } pic = heathrow_pic_init(&pic_mem, 1, heathrow_irqs); pci_bus = pci_grackle_init(0xfec00000, pic, get_system_memory(), get_system_io()); pci_vga_init(pci_bus); escc_mem = escc_init(0, pic[0x0f], pic[0x10], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); memory_region_init_alias(escc_bar, "escc-bar", escc_mem, 0, memory_region_size(escc_mem)); for(i = 0; i < nb_nics; i++) pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL); ide_drive_get(hd, MAX_IDE_BUS); /* First IDE channel is a MAC IDE on the MacIO bus */ dbdma = DBDMA_init(&dbdma_mem); ide_mem[0] = NULL; ide_mem[1] = pmac_ide_init(hd, pic[0x0D], dbdma, 0x16, pic[0x02]); /* Second IDE channel is a CMD646 on the PCI bus */ hd[0] = hd[MAX_IDE_DEVS]; hd[1] = hd[MAX_IDE_DEVS + 1]; hd[3] = hd[2] = NULL; pci_cmd646_ide_init(pci_bus, hd, 0); /* cuda also initialize ADB */ cuda_init(&cuda_mem, pic[0x12]); adb_kbd_init(&adb_bus); adb_mouse_init(&adb_bus); nvr = macio_nvram_init(0x2000, 4); pmac_format_nvram_partition(nvr, 0x2000); macio_init(pci_bus, PCI_DEVICE_ID_APPLE_343S1201, 1, pic_mem, dbdma_mem, cuda_mem, nvr, 2, ide_mem, escc_bar); if (usb_enabled) { pci_create_simple(pci_bus, -1, "pci-ohci"); } if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8) graphic_depth = 15; /* No PCI init: the BIOS will do it */ fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2); fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_HEATHROW); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); if (kernel_cmdline) { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base); pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline); } else { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0); } fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_base); fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ppc_boot_device); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_WIDTH, graphic_width); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled()); if (kvm_enabled()) { #ifdef CONFIG_KVM uint8_t *hypercall; fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq()); hypercall = g_malloc(16); kvmppc_get_hypercall(env, hypercall, 16); fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); #endif } else { fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec()); } qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); }
static void sh_timer_write(void *opaque, hwaddr offset, uint32_t value) { sh_timer_state *s = (sh_timer_state *)opaque; int freq; switch (offset >> 2) { case OFFSET_TCOR: s->tcor = value; ptimer_set_limit(s->timer, s->tcor, 0); break; case OFFSET_TCNT: s->tcnt = value; ptimer_set_count(s->timer, s->tcnt); break; case OFFSET_TCR: if (s->enabled) { /* Pause the timer if it is running. This may cause some inaccuracy dure to rounding, but avoids a whole lot of other messyness. */ ptimer_stop(s->timer); } freq = s->freq; /* ??? Need to recalculate expiry time after changing divisor. */ switch (value & TIMER_TCR_TPSC) { case 0: freq >>= 2; break; case 1: freq >>= 4; break; case 2: freq >>= 6; break; case 3: freq >>= 8; break; case 4: freq >>= 10; break; case 6: case 7: if (s->feat & TIMER_FEAT_EXTCLK) break; default: hw_error("sh_timer_write: Reserved TPSC value\n"); break; } switch ((value & TIMER_TCR_CKEG) >> 3) { case 0: break; case 1: case 2: case 3: if (s->feat & TIMER_FEAT_EXTCLK) break; default: hw_error("sh_timer_write: Reserved CKEG value\n"); break; } switch ((value & TIMER_TCR_ICPE) >> 6) { case 0: break; case 2: case 3: if (s->feat & TIMER_FEAT_CAPT) break; default: hw_error("sh_timer_write: Reserved ICPE value\n"); break; } if ((value & TIMER_TCR_UNF) == 0) s->int_level = 0; value &= ~TIMER_TCR_UNF; if ((value & TIMER_TCR_ICPF) && (!(s->feat & TIMER_FEAT_CAPT))) hw_error("sh_timer_write: Reserved ICPF value\n"); value &= ~TIMER_TCR_ICPF; /* capture not supported */ if (value & TIMER_TCR_RESERVED) hw_error("sh_timer_write: Reserved TCR bits set\n"); s->tcr = value; ptimer_set_limit(s->timer, s->tcor, 0); ptimer_set_freq(s->timer, freq); if (s->enabled) { /* Restart the timer if still enabled. */ ptimer_run(s->timer, 0); } break; case OFFSET_TCPR: if (s->feat & TIMER_FEAT_CAPT) { s->tcpr = value; break; } default: hw_error("sh_timer_write: Bad offset %x\n", (int)offset); } sh_timer_update(s); }
static uint64_t stellaris_enet_read(void *opaque, hwaddr offset, unsigned size) { stellaris_enet_state *s = (stellaris_enet_state *)opaque; uint32_t val; switch (offset) { case 0x00: /* RIS */ DPRINTF("IRQ status %02x\n", s->ris); return s->ris; case 0x04: /* IM */ return s->im; case 0x08: /* RCTL */ return s->rctl; case 0x0c: /* TCTL */ return s->tctl; case 0x10: /* DATA */ { uint8_t *rx_fifo; if (s->np == 0) { BADF("RX underflow\n"); return 0; } rx_fifo = s->rx[s->next_packet].data + s->rx_fifo_offset; val = rx_fifo[0] | (rx_fifo[1] << 8) | (rx_fifo[2] << 16) | (rx_fifo[3] << 24); s->rx_fifo_offset += 4; if (s->rx_fifo_offset >= s->rx[s->next_packet].len) { s->rx_fifo_offset = 0; s->next_packet++; if (s->next_packet >= 31) s->next_packet = 0; s->np--; DPRINTF("RX done np=%d\n", s->np); } return val; } case 0x14: /* IA0 */ return s->conf.macaddr.a[0] | (s->conf.macaddr.a[1] << 8) | (s->conf.macaddr.a[2] << 16) | ((uint32_t)s->conf.macaddr.a[3] << 24); case 0x18: /* IA1 */ return s->conf.macaddr.a[4] | (s->conf.macaddr.a[5] << 8); case 0x1c: /* THR */ return s->thr; case 0x20: /* MCTL */ return s->mctl; case 0x24: /* MDV */ return s->mdv; case 0x28: /* MADD */ return 0; case 0x2c: /* MTXD */ return s->mtxd; case 0x30: /* MRXD */ return s->mrxd; case 0x34: /* NP */ return s->np; case 0x38: /* TR */ return 0; case 0x3c: /* Undocuented: Timestamp? */ return 0; default: hw_error("stellaris_enet_read: Bad offset %x\n", (int)offset); return 0; } }
static void dma_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value) { hw_error("Unsupported short waccess. reg=" TARGET_FMT_plx "\n", addr); }
static void tusb_async_writew(void *opaque, hwaddr addr, uint32_t value) { TUSBState *s = (TUSBState *) opaque; int offset = addr & 0xfff; int epnum; switch (offset) { case TUSB_VLYNQ_CTRL: break; case TUSB_BASE_OFFSET ... (TUSB_BASE_OFFSET | 0x1ff): musb_write[2](s->musb, offset & 0x1ff, value); break; case TUSB_FIFO_BASE ... (TUSB_FIFO_BASE | 0x1ff): musb_write[2](s->musb, 0x20 + ((addr >> 3) & 0x3c), value); break; case TUSB_DEV_CONF: s->dev_config = value; s->host_mode = (value & TUSB_DEV_CONF_USB_HOST_MODE); if (value & TUSB_DEV_CONF_PROD_TEST_MODE) hw_error("%s: Product Test mode not allowed\n", __FUNCTION__); break; case TUSB_PHY_OTG_CTRL_ENABLE: case TUSB_PHY_OTG_CTRL: return; /* TODO */ case TUSB_DEV_OTG_TIMER: s->otg_timer_val = value; if (value & TUSB_DEV_OTG_TIMER_ENABLE) qemu_mod_timer(s->otg_timer, qemu_get_clock_ns(vm_clock) + muldiv64(TUSB_DEV_OTG_TIMER_VAL(value), get_ticks_per_sec(), TUSB_DEVCLOCK)); else qemu_del_timer(s->otg_timer); break; case TUSB_PRCM_CONF: s->prcm_config = value; break; case TUSB_PRCM_MNGMT: s->prcm_mngmt = value; break; case TUSB_PRCM_WAKEUP_CLEAR: break; case TUSB_PRCM_WAKEUP_MASK: s->wkup_mask = value; break; case TUSB_PULLUP_1_CTRL: s->pullup[0] = value; break; case TUSB_PULLUP_2_CTRL: s->pullup[1] = value; break; case TUSB_INT_CTRL_CONF: s->control_config = value; tusb_intr_update(s); break; case TUSB_USBIP_INT_SET: s->usbip_intr |= value; tusb_usbip_intr_update(s); break; case TUSB_USBIP_INT_CLEAR: s->usbip_intr &= ~value; tusb_usbip_intr_update(s); musb_core_intr_clear(s->musb, ~value); break; case TUSB_USBIP_INT_MASK: s->usbip_mask = value; tusb_usbip_intr_update(s); break; case TUSB_DMA_INT_SET: s->dma_intr |= value; tusb_dma_intr_update(s); break; case TUSB_DMA_INT_CLEAR: s->dma_intr &= ~value; tusb_dma_intr_update(s); break; case TUSB_DMA_INT_MASK: s->dma_mask = value; tusb_dma_intr_update(s); break; case TUSB_GPIO_INT_SET: s->gpio_intr |= value; tusb_gpio_intr_update(s); break; case TUSB_GPIO_INT_CLEAR: s->gpio_intr &= ~value; tusb_gpio_intr_update(s); break; case TUSB_GPIO_INT_MASK: s->gpio_mask = value; tusb_gpio_intr_update(s); break; case TUSB_INT_SRC_SET: s->intr |= value; tusb_intr_update(s); break; case TUSB_INT_SRC_CLEAR: s->intr &= ~value; tusb_intr_update(s); break; case TUSB_INT_MASK: s->mask = value; tusb_intr_update(s); break; case TUSB_GPIO_CONF: s->gpio_config = value; break; case TUSB_DMA_REQ_CONF: s->dma_config = value; break; case TUSB_EP0_CONF: s->ep0_config = value & 0x1ff; musb_set_size(s->musb, 0, TUSB_EP0_CONFIG_XFR_SIZE(value), value & TUSB_EP0_CONFIG_DIR_TX); break; case TUSB_EP_IN_SIZE ... (TUSB_EP_IN_SIZE + 0x3b): epnum = (offset - TUSB_EP_IN_SIZE) >> 2; s->tx_config[epnum] = value; musb_set_size(s->musb, epnum + 1, TUSB_EP_CONFIG_XFR_SIZE(value), 1); break; case TUSB_DMA_EP_MAP: s->dma_map = value; break; case TUSB_EP_OUT_SIZE ... (TUSB_EP_OUT_SIZE + 0x3b): epnum = (offset - TUSB_EP_OUT_SIZE) >> 2; s->rx_config[epnum] = value; musb_set_size(s->musb, epnum + 1, TUSB_EP_CONFIG_XFR_SIZE(value), 0); break; case TUSB_EP_MAX_PACKET_SIZE_OFFSET ... (TUSB_EP_MAX_PACKET_SIZE_OFFSET + 0x3b): return; /* TODO */ case TUSB_WAIT_COUNT: return; /* TODO */ case TUSB_SCRATCH_PAD: s->scratch = value; break; case TUSB_PROD_TEST_RESET: s->test_reset = value; break; default: printf("%s: unknown register at %03x\n", __FUNCTION__, offset); return; } }
static uint64_t pl181_read(void *opaque, target_phys_addr_t offset, unsigned size) { pl181_state *s = (pl181_state *)opaque; uint32_t tmp; if (offset >= 0xfe0 && offset < 0x1000) { return pl181_id[(offset - 0xfe0) >> 2]; } switch (offset) { case 0x00: /* Power */ return s->power; case 0x04: /* Clock */ return s->clock; case 0x08: /* Argument */ return s->cmdarg; case 0x0c: /* Command */ return s->cmd; case 0x10: /* RespCmd */ return s->respcmd; case 0x14: /* Response0 */ return s->response[0]; case 0x18: /* Response1 */ return s->response[1]; case 0x1c: /* Response2 */ return s->response[2]; case 0x20: /* Response3 */ return s->response[3]; case 0x24: /* DataTimer */ return s->datatimer; case 0x28: /* DataLength */ return s->datalength; case 0x2c: /* DataCtrl */ return s->datactrl; case 0x30: /* DataCnt */ return s->datacnt; case 0x34: /* Status */ tmp = s->status; if (s->linux_hack) { s->linux_hack = 0; pl181_fifo_run(s); pl181_update(s); } return tmp; case 0x3c: /* Mask0 */ return s->mask[0]; case 0x40: /* Mask1 */ return s->mask[1]; case 0x48: /* FifoCnt */ /* The documentation is somewhat vague about exactly what FifoCnt does. On real hardware it appears to be when decrememnted when a word is transferred between the FIFO and the serial data engine. DataCnt is decremented after each byte is transferred between the serial engine and the card. We don't emulate this level of detail, so both can be the same. */ tmp = (s->datacnt + 3) >> 2; if (s->linux_hack) { s->linux_hack = 0; pl181_fifo_run(s); pl181_update(s); } return tmp; case 0x80: case 0x84: case 0x88: case 0x8c: /* FifoData */ case 0x90: case 0x94: case 0x98: case 0x9c: case 0xa0: case 0xa4: case 0xa8: case 0xac: case 0xb0: case 0xb4: case 0xb8: case 0xbc: if (s->fifo_len == 0) { fprintf(stderr, "pl181: Unexpected FIFO read\n"); return 0; } else { uint32_t value; value = pl181_fifo_pop(s); s->linux_hack = 1; pl181_fifo_run(s); pl181_update(s); return value; } default: hw_error("pl181_read: Bad offset %x\n", (int)offset); return 0; } }
static void pl181_write(void *opaque, target_phys_addr_t offset, uint64_t value, unsigned size) { pl181_state *s = (pl181_state *)opaque; switch (offset) { case 0x00: /* Power */ s->power = value & 0xff; break; case 0x04: /* Clock */ s->clock = value & 0xff; break; case 0x08: /* Argument */ s->cmdarg = value; break; case 0x0c: /* Command */ s->cmd = value; if (s->cmd & PL181_CMD_ENABLE) { if (s->cmd & PL181_CMD_INTERRUPT) { fprintf(stderr, "pl181: Interrupt mode not implemented\n"); abort(); } if (s->cmd & PL181_CMD_PENDING) { fprintf(stderr, "pl181: Pending commands not implemented\n"); abort(); } else { pl181_send_command(s); pl181_fifo_run(s); } /* The command has completed one way or the other. */ s->cmd &= ~PL181_CMD_ENABLE; } break; case 0x24: /* DataTimer */ s->datatimer = value; break; case 0x28: /* DataLength */ s->datalength = value & 0xffff; break; case 0x2c: /* DataCtrl */ s->datactrl = value & 0xff; if (value & PL181_DATA_ENABLE) { s->datacnt = s->datalength; pl181_fifo_run(s); } break; case 0x38: /* Clear */ s->status &= ~(value & 0x7ff); break; case 0x3c: /* Mask0 */ s->mask[0] = value; break; case 0x40: /* Mask1 */ s->mask[1] = value; break; case 0x80: case 0x84: case 0x88: case 0x8c: /* FifoData */ case 0x90: case 0x94: case 0x98: case 0x9c: case 0xa0: case 0xa4: case 0xa8: case 0xac: case 0xb0: case 0xb4: case 0xb8: case 0xbc: if (s->datacnt == 0) { fprintf(stderr, "pl181: Unexpected FIFO write\n"); } else { pl181_fifo_push(s, value); pl181_fifo_run(s); } break; default: hw_error("pl181_write: Bad offset %x\n", (int)offset); } pl181_update(s); }
static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val) { PicState *s = opaque; int priority, cmd, irq; DPRINTF("write: addr=0x%02x val=0x%02x\n", addr, val); addr &= 1; if (addr == 0) { if (val & 0x10) { /* init */ pic_reset(s); /* deassert a pending interrupt */ qemu_irq_lower(s->pics_state->parent_irq); s->init_state = 1; s->init4 = val & 1; s->single_mode = val & 2; if (val & 0x08) hw_error("level sensitive irq not supported"); } else if (val & 0x08) { if (val & 0x04) s->poll = 1; if (val & 0x02) s->read_reg_select = val & 1; if (val & 0x40) s->special_mask = (val >> 5) & 1; } else { cmd = val >> 5; switch(cmd) { case 0: case 4: s->rotate_on_auto_eoi = cmd >> 2; break; case 1: /* end of interrupt */ case 5: priority = get_priority(s, s->isr); if (priority != 8) { irq = (priority + s->priority_add) & 7; s->isr &= ~(1 << irq); if (cmd == 5) s->priority_add = (irq + 1) & 7; pic_update_irq(s->pics_state); } break; case 3: irq = val & 7; s->isr &= ~(1 << irq); pic_update_irq(s->pics_state); break; case 6: s->priority_add = (val + 1) & 7; pic_update_irq(s->pics_state); break; case 7: irq = val & 7; s->isr &= ~(1 << irq); s->priority_add = (irq + 1) & 7; pic_update_irq(s->pics_state); break; default: /* no operation */ break; } } } else {
void pc_memory_init(ram_addr_t ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, ram_addr_t *below_4g_mem_size_p, ram_addr_t *above_4g_mem_size_p) { char *filename; int ret, linux_boot, i; ram_addr_t ram_addr, bios_offset, option_rom_offset; ram_addr_t below_4g_mem_size, above_4g_mem_size = 0; int bios_size, isa_bios_size; void *fw_cfg; if (ram_size >= 0xe0000000 ) { above_4g_mem_size = ram_size - 0xe0000000; below_4g_mem_size = 0xe0000000; } else { below_4g_mem_size = ram_size; } *above_4g_mem_size_p = above_4g_mem_size; *below_4g_mem_size_p = below_4g_mem_size; #if TARGET_PHYS_ADDR_BITS == 32 if (above_4g_mem_size > 0) { hw_error("To much RAM for 32-bit physical address"); } #endif linux_boot = (kernel_filename != NULL); /* allocate RAM */ ram_addr = qemu_ram_alloc(NULL, "pc.ram", below_4g_mem_size + above_4g_mem_size); cpu_register_physical_memory(0, 0xa0000, ram_addr); cpu_register_physical_memory(0x100000, below_4g_mem_size - 0x100000, ram_addr + 0x100000); #if TARGET_PHYS_ADDR_BITS > 32 if (above_4g_mem_size > 0) { cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size, ram_addr + below_4g_mem_size); } #endif /* BIOS load */ if (bios_name == NULL) bios_name = BIOS_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { bios_size = get_image_size(filename); } else { bios_size = -1; } if (bios_size <= 0 || (bios_size % 65536) != 0) { goto bios_error; } bios_offset = qemu_ram_alloc(NULL, "pc.bios", bios_size); ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size)); if (ret != 0) { bios_error: fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name); exit(1); } if (filename) { qemu_free(filename); } /* map the last 128KB of the BIOS in ISA space */ isa_bios_size = bios_size; if (isa_bios_size > (128 * 1024)) isa_bios_size = 128 * 1024; cpu_register_physical_memory(0x100000 - isa_bios_size, isa_bios_size, (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM); option_rom_offset = qemu_ram_alloc(NULL, "pc.rom", PC_ROM_SIZE); cpu_register_physical_memory(PC_ROM_MIN_VGA, PC_ROM_SIZE, option_rom_offset); /* map all the bios at the top of memory */ cpu_register_physical_memory((uint32_t)(-bios_size), bios_size, bios_offset | IO_MEM_ROM); fw_cfg = bochs_bios_init(); rom_set_fw(fw_cfg); if (linux_boot) { load_linux(fw_cfg, kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size); } for (i = 0; i < nb_option_roms; i++) { rom_add_option(option_rom[i]); } }
static void reptar_init(MachineState *machine) { MemoryRegion *sysmem = get_system_memory(); struct reptar_s *s = (struct reptar_s *)g_malloc0(sizeof(*s)); DriveInfo *dmtd = NULL, *dsd = NULL, *pflash = NULL; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; /* (DRE) */ uint32_t pflash_size = 16 << 10; /* 16 KB */ if (ram_size > 1024 * 1024 * 1024) { fprintf(stderr, "reptar: maximum permitted RAM size 1024MB\n"); exit(1); } /* Check if we are in -kernel u-boot.bin mode */ if (kernel_filename) { /* (DRE) We do the following in order to retrieve the kernel filename during the boot process. * For example, if qemu was launched with -kernel u-boot.bin */ reptar_binfo.ram_size = ram_size; reptar_binfo.kernel_filename = kernel_filename; reptar_binfo.kernel_cmdline = kernel_cmdline; reptar_binfo.initrd_filename = initrd_filename; reptar_binfo.loader_start = 0x40014100; /* Start of small bootloader*/ reptar_binfo.board_id = 0; } else reptar_binfo.kernel_filename = NULL; s->cpu = omap3_mpu_init(sysmem, omap3430, ram_size, NULL, NULL, serial_hds[0], NULL); pflash = drive_get(IF_PFLASH, 0, 0); if (pflash) { if (!pflash_cfi02_register(0x30000000, NULL, "reptar.nand_flash", pflash_size, blk_by_legacy_dinfo(pflash), sector_len, pflash_size / sector_len, 1, 2, 0, 0, 0, 0, 0x555, 0x2AA, 0)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); exit(1); } } else { dmtd = drive_get(IF_MTD, 0, 0); s->nand = nand_init(dmtd ? blk_by_legacy_dinfo(dmtd) : NULL, NAND_MFR_MICRON, 0xba); nand_setpins(s->nand, 0, 0, 0, 1, 0); /* no write-protect */ omap_gpmc_attach_nand(s->cpu->gpmc, REPTAR_NAND_CS, s->nand); } /* * (DRE) Define MMC if any */ dsd = drive_get(IF_SD, 0, 0); if (dsd) omap3_mmc_attach(s->cpu->omap3_mmc[0], blk_by_legacy_dinfo(dsd), 0, 0); if (!pflash && !dmtd && !dsd) hw_error("%s: SD or NAND image required", __FUNCTION__); /* FAB revs >= 2516: 4030 interrupt is GPIO 0 (earlier ones were 112) */ s->twl4030 = twl4030_init(omap_i2c_bus(s->cpu->i2c[0]), qdev_get_gpio_in(s->cpu->gpio, 0), NULL, NULL); /* Wire up an I2C slave which returns EDID monitor information; * newer Linux kernels won't turn on the display unless they * detect a monitor over DDC. */ s->ddc = i2c_create_slave(omap_i2c_bus(s->cpu->i2c[2]), "i2c-ddc", 0x50); omap_lcd_panel_attach(s->cpu->dss); /* Strictly this should be a LAN9221 */ #if 0 if (nd_table[0].vlan) { #endif /* 0 */ /* The ethernet chip hangs off the GPMC */ NICInfo *nd = &nd_table[0]; qemu_check_nic_model(nd, "lan9118"); s->eth = qdev_create(NULL, "lan9118"); qdev_set_nic_properties(s->eth, nd); qdev_init_nofail(s->eth); omap_gpmc_attach(s->cpu->gpmc, REPTAR_NET_CS, sysbus_mmio_get_region(SYS_BUS_DEVICE(s->eth), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(s->eth), 0, qdev_get_gpio_in(s->cpu->gpio, 29)); #if 0 } #endif /* 0 */ // Addd the Spartan 6 to the SYS BUS printf("sysbus_create_simple()\n"); s->sp6 = sysbus_create_simple("reptar_sp6", 0x18000000, NULL); sysbus_connect_irq(SYS_BUS_DEVICE(s->sp6), 0, qdev_get_gpio_in(s->cpu->gpio, 10)); }
void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3) { uint64_t addr = env->regs[r1]; uint64_t subcode = env->regs[r3]; IplParameterBlock *iplb; if (env->psw.mask & PSW_MASK_PSTATE) { program_interrupt(env, PGM_PRIVILEGED, ILEN_LATER_INC); return; } if ((subcode & ~0x0ffffULL) || (subcode > 6)) { program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); return; } switch (subcode) { case 0: modified_clear_reset(s390_env_get_cpu(env)); break; case 1: load_normal_reset(s390_env_get_cpu(env)); break; case 5: if ((r1 & 1) || (addr & 0x0fffULL)) { program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); return; } if (!address_space_access_valid(&address_space_memory, addr, sizeof(IplParameterBlock), false)) { program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC); return; } iplb = g_malloc0(sizeof(struct IplParameterBlock)); cpu_physical_memory_read(addr, iplb, sizeof(struct IplParameterBlock)); if (!s390_ipl_update_diag308(iplb)) { env->regs[r1 + 1] = DIAG_308_RC_OK; } else { env->regs[r1 + 1] = DIAG_308_RC_INVALID; } g_free(iplb); return; case 6: if ((r1 & 1) || (addr & 0x0fffULL)) { program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); return; } if (!address_space_access_valid(&address_space_memory, addr, sizeof(IplParameterBlock), true)) { program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC); return; } iplb = s390_ipl_get_iplb(); if (iplb) { cpu_physical_memory_write(addr, iplb, sizeof(struct IplParameterBlock)); env->regs[r1 + 1] = DIAG_308_RC_OK; } else { env->regs[r1 + 1] = DIAG_308_RC_NO_CONF; } return; default: hw_error("Unhandled diag308 subcode %" PRIx64, subcode); break; } }
static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset, uint64_t value, unsigned size) { int i, tm = 0; PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque; switch (offset) { case OSMR3: tm ++; case OSMR2: tm ++; case OSMR1: tm ++; case OSMR0: s->timer[tm].value = value; pxa2xx_timer_update(s, qemu_get_clock_ns(vm_clock)); break; case OSMR11: tm ++; case OSMR10: tm ++; case OSMR9: tm ++; case OSMR8: tm ++; case OSMR7: tm ++; case OSMR6: tm ++; case OSMR5: tm ++; case OSMR4: if (!pxa2xx_timer_has_tm4(s)) goto badreg; s->tm4[tm].tm.value = value; pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm); break; case OSCR: s->oldclock = s->clock; s->lastload = qemu_get_clock_ns(vm_clock); s->clock = value; pxa2xx_timer_update(s, s->lastload); break; case OSCR11: tm ++; case OSCR10: tm ++; case OSCR9: tm ++; case OSCR8: tm ++; case OSCR7: tm ++; case OSCR6: tm ++; case OSCR5: tm ++; case OSCR4: if (!pxa2xx_timer_has_tm4(s)) goto badreg; s->tm4[tm].oldclock = s->tm4[tm].clock; s->tm4[tm].lastload = qemu_get_clock_ns(vm_clock); s->tm4[tm].clock = value; pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm); break; case OIER: s->irq_enabled = value & 0xfff; break; case OSSR: /* Status register */ value &= s->events; s->events &= ~value; for (i = 0; i < 4; i ++, value >>= 1) if (value & 1) qemu_irq_lower(s->timer[i].irq); if (pxa2xx_timer_has_tm4(s) && !(s->events & 0xff0) && value) qemu_irq_lower(s->irq4); break; case OWER: /* XXX: Reset on OSMR3 match? */ s->reset3 = value; break; case OMCR7: tm ++; case OMCR6: tm ++; case OMCR5: tm ++; case OMCR4: if (!pxa2xx_timer_has_tm4(s)) goto badreg; s->tm4[tm].control = value & 0x0ff; /* XXX Stop if running (shouldn't happen) */ if ((value & (1 << 7)) || tm == 0) s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7]; else { s->tm4[tm].freq = 0; pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm); } break; case OMCR11: tm ++; case OMCR10: tm ++; case OMCR9: tm ++; case OMCR8: tm += 4; if (!pxa2xx_timer_has_tm4(s)) goto badreg; s->tm4[tm].control = value & 0x3ff; /* XXX Stop if running (shouldn't happen) */ if ((value & (1 << 7)) || !(tm & 1)) s->tm4[tm].freq = pxa2xx_timer4_freq[(value & (1 << 8)) ? 0 : (value & 7)]; else { s->tm4[tm].freq = 0; pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm); } break; default: badreg: hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset); } }
/* PowerPC Mac99 hardware initialisation */ static void ppc_core99_init(QEMUMachineInitArgs *args) { ram_addr_t ram_size = args->ram_size; const char *cpu_model = args->cpu_model; const char *kernel_filename = args->kernel_filename; const char *kernel_cmdline = args->kernel_cmdline; const char *initrd_filename = args->initrd_filename; const char *boot_device = args->boot_device; PowerPCCPU *cpu = NULL; CPUPPCState *env = NULL; char *filename; qemu_irq *pic, **openpic_irqs; MemoryRegion *unin_memory = g_new(MemoryRegion, 1); int linux_boot, i; MemoryRegion *ram = g_new(MemoryRegion, 1), *bios = g_new(MemoryRegion, 1); hwaddr kernel_base, initrd_base, cmdline_base = 0; long kernel_size, initrd_size; PCIBus *pci_bus; MacIONVRAMState *nvr; int bios_size; MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem, *escc_mem; MemoryRegion *escc_bar = g_new(MemoryRegion, 1); MemoryRegion *ide_mem[3]; int ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; void *dbdma; int machine_arch; linux_boot = (kernel_filename != NULL); /* init CPUs */ if (cpu_model == NULL) #ifdef TARGET_PPC64 cpu_model = "970fx"; #else cpu_model = "G4"; #endif for (i = 0; i < smp_cpus; i++) { cpu = cpu_ppc_init(cpu_model); if (cpu == NULL) { fprintf(stderr, "Unable to find PowerPC CPU definition\n"); exit(1); } env = &cpu->env; /* Set time-base frequency to 100 Mhz */ cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL); qemu_register_reset(ppc_core99_reset, cpu); } /* allocate RAM */ memory_region_init_ram(ram, "ppc_core99.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(get_system_memory(), 0, ram); /* allocate and load BIOS */ memory_region_init_ram(bios, "ppc_core99.bios", BIOS_SIZE); vmstate_register_ram_global(bios); if (bios_name == NULL) bios_name = PROM_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); memory_region_set_readonly(bios, true); memory_region_add_subregion(get_system_memory(), PROM_ADDR, bios); /* Load OpenBIOS (ELF) */ if (filename) { bios_size = load_elf(filename, NULL, NULL, NULL, NULL, NULL, 1, ELF_MACHINE, 0); g_free(filename); } else { bios_size = -1; } if (bios_size < 0 || bios_size > BIOS_SIZE) { hw_error("qemu: could not load PowerPC bios '%s'\n", bios_name); exit(1); } if (linux_boot) { uint64_t lowaddr = 0; int bswap_needed; #ifdef BSWAP_NEEDED bswap_needed = 1; #else bswap_needed = 0; #endif kernel_base = KERNEL_LOAD_ADDR; kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0); if (kernel_size < 0) kernel_size = load_aout(kernel_filename, kernel_base, ram_size - kernel_base, bswap_needed, TARGET_PAGE_SIZE); if (kernel_size < 0) kernel_size = load_image_targphys(kernel_filename, kernel_base, ram_size - kernel_base); if (kernel_size < 0) { hw_error("qemu: could not load kernel '%s'\n", kernel_filename); exit(1); } /* load initrd */ if (initrd_filename) { initrd_base = round_page(kernel_base + kernel_size + KERNEL_GAP); initrd_size = load_image_targphys(initrd_filename, initrd_base, ram_size - initrd_base); if (initrd_size < 0) { hw_error("qemu: could not load initial ram disk '%s'\n", initrd_filename); exit(1); } cmdline_base = round_page(initrd_base + initrd_size); } else { initrd_base = 0; initrd_size = 0; cmdline_base = round_page(kernel_base + kernel_size + KERNEL_GAP); } ppc_boot_device = 'm'; } else { kernel_base = 0; kernel_size = 0; initrd_base = 0; initrd_size = 0; ppc_boot_device = '\0'; /* We consider that NewWorld PowerMac never have any floppy drive * For now, OHW cannot boot from the network. */ for (i = 0; boot_device[i] != '\0'; i++) { if (boot_device[i] >= 'c' && boot_device[i] <= 'f') { ppc_boot_device = boot_device[i]; break; } } if (ppc_boot_device == '\0') { fprintf(stderr, "No valid boot device for Mac99 machine\n"); exit(1); } } /* Register 8 MB of ISA IO space */ isa_mmio_init(0xf2000000, 0x00800000); /* UniN init */ memory_region_init_io(unin_memory, &unin_ops, NULL, "unin", 0x1000); memory_region_add_subregion(get_system_memory(), 0xf8000000, unin_memory); openpic_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); openpic_irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB); for (i = 0; i < smp_cpus; i++) { /* Mac99 IRQ connection between OpenPIC outputs pins * and PowerPC input pins */ switch (PPC_INPUT(env)) { case PPC_FLAGS_INPUT_6xx: openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB); openpic_irqs[i][OPENPIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT]; openpic_irqs[i][OPENPIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT]; openpic_irqs[i][OPENPIC_OUTPUT_MCK] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP]; /* Not connected ? */ openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL; /* Check this */ openpic_irqs[i][OPENPIC_OUTPUT_RESET] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET]; break; #if defined(TARGET_PPC64) case PPC_FLAGS_INPUT_970: openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB); openpic_irqs[i][OPENPIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT]; openpic_irqs[i][OPENPIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT]; openpic_irqs[i][OPENPIC_OUTPUT_MCK] = ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_MCP]; /* Not connected ? */ openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL; /* Check this */ openpic_irqs[i][OPENPIC_OUTPUT_RESET] = ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_HRESET]; break; #endif /* defined(TARGET_PPC64) */ default: hw_error("Bus model not supported on mac99 machine\n"); exit(1); } } pic = openpic_init(&pic_mem, smp_cpus, openpic_irqs, NULL); if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) { /* 970 gets a U3 bus */ pci_bus = pci_pmac_u3_init(pic, get_system_memory(), get_system_io()); machine_arch = ARCH_MAC99_U3; } else { pci_bus = pci_pmac_init(pic, get_system_memory(), get_system_io()); machine_arch = ARCH_MAC99; } /* init basic PC hardware */ pci_vga_init(pci_bus); escc_mem = escc_init(0, pic[0x25], pic[0x24], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); memory_region_init_alias(escc_bar, "escc-bar", escc_mem, 0, memory_region_size(escc_mem)); for(i = 0; i < nb_nics; i++) pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL); ide_drive_get(hd, MAX_IDE_BUS); dbdma = DBDMA_init(&dbdma_mem); /* We only emulate 2 out of 3 IDE controllers for now */ ide_mem[0] = NULL; ide_mem[1] = pmac_ide_init(hd, pic[0x0d], dbdma, 0x16, pic[0x02]); ide_mem[2] = pmac_ide_init(&hd[MAX_IDE_DEVS], pic[0x0e], dbdma, 0x1a, pic[0x02]); /* cuda also initialize ADB */ if (machine_arch == ARCH_MAC99_U3) { usb_enabled = 1; } cuda_init(&cuda_mem, pic[0x19]); adb_kbd_init(&adb_bus); adb_mouse_init(&adb_bus); macio_init(pci_bus, PCI_DEVICE_ID_APPLE_UNI_N_KEYL, 0, pic_mem, dbdma_mem, cuda_mem, NULL, 3, ide_mem, escc_bar); if (usb_enabled) { pci_create_simple(pci_bus, -1, "pci-ohci"); } /* U3 needs to use USB for input because Linux doesn't support via-cuda on PPC64 */ if (machine_arch == ARCH_MAC99_U3) { usbdevice_create("keyboard"); usbdevice_create("mouse"); } if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8) graphic_depth = 15; /* The NewWorld NVRAM is not located in the MacIO device */ nvr = macio_nvram_init(0x2000, 1); pmac_format_nvram_partition(nvr, 0x2000); macio_nvram_setup_bar(nvr, get_system_memory(), 0xFFF04000); /* No PCI init: the BIOS will do it */ fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2); fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, machine_arch); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); if (kernel_cmdline) { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base); pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline); } else { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0); } fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_base); fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ppc_boot_device); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_WIDTH, graphic_width); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled()); if (kvm_enabled()) { #ifdef CONFIG_KVM uint8_t *hypercall; fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq()); hypercall = g_malloc(16); kvmppc_get_hypercall(env, hypercall, 16); fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); #endif } else { fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec()); } qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); }
/* ram_size must be set to match the upper bound of memory in the * device tree (linux/arch/arm/boot/dts/highbank.dts), which is * normally 0xff900000 or -m 4089. When running this board on a * 32-bit host, set the reg value of memory to 0xf7ff00000 in the * device tree and pass -m 2047 to QEMU. */ static void highbank_init(ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { DeviceState *dev; SysBusDevice *busdev; qemu_irq *irqp; qemu_irq pic[128]; int n; qemu_irq cpu_irq[4]; MemoryRegion *sysram; MemoryRegion *dram; MemoryRegion *sysmem; char *sysboot_filename; if (!cpu_model) { cpu_model = "cortex-a9"; } for (n = 0; n < smp_cpus; n++) { ARMCPU *cpu; cpu = cpu_arm_init(cpu_model); if (cpu == NULL) { fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } /* This will become a QOM property eventually */ cpu->reset_cbar = GIC_BASE_ADDR; irqp = arm_pic_init_cpu(cpu); cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ]; } sysmem = get_system_memory(); dram = g_new(MemoryRegion, 1); memory_region_init_ram(dram, "highbank.dram", ram_size); /* SDRAM at address zero. */ memory_region_add_subregion(sysmem, 0, dram); sysram = g_new(MemoryRegion, 1); memory_region_init_ram(sysram, "highbank.sysram", 0x8000); memory_region_add_subregion(sysmem, 0xfff88000, sysram); if (bios_name != NULL) { sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (sysboot_filename != NULL) { uint32_t filesize = get_image_size(sysboot_filename); if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) { hw_error("Unable to load %s\n", bios_name); } } else { hw_error("Unable to find %s\n", bios_name); } } dev = qdev_create(NULL, "a9mpcore_priv"); qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC); qdev_init_nofail(dev); busdev = sysbus_from_qdev(dev); sysbus_mmio_map(busdev, 0, GIC_BASE_ADDR); for (n = 0; n < smp_cpus; n++) { sysbus_connect_irq(busdev, n, cpu_irq[n]); } for (n = 0; n < 128; n++) { pic[n] = qdev_get_gpio_in(dev, n); } dev = qdev_create(NULL, "l2x0"); qdev_init_nofail(dev); busdev = sysbus_from_qdev(dev); sysbus_mmio_map(busdev, 0, 0xfff12000); dev = qdev_create(NULL, "sp804"); qdev_prop_set_uint32(dev, "freq0", 150000000); qdev_prop_set_uint32(dev, "freq1", 150000000); qdev_init_nofail(dev); busdev = sysbus_from_qdev(dev); sysbus_mmio_map(busdev, 0, 0xfff34000); sysbus_connect_irq(busdev, 0, pic[18]); sysbus_create_simple("pl011", 0xfff36000, pic[20]); dev = qdev_create(NULL, "highbank-regs"); qdev_init_nofail(dev); busdev = sysbus_from_qdev(dev); sysbus_mmio_map(busdev, 0, 0xfff3c000); sysbus_create_simple("pl061", 0xfff30000, pic[14]); sysbus_create_simple("pl061", 0xfff31000, pic[15]); sysbus_create_simple("pl061", 0xfff32000, pic[16]); sysbus_create_simple("pl061", 0xfff33000, pic[17]); sysbus_create_simple("pl031", 0xfff35000, pic[19]); sysbus_create_simple("pl022", 0xfff39000, pic[23]); sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]); if (nd_table[0].used) { qemu_check_nic_model(&nd_table[0], "xgmac"); dev = qdev_create(NULL, "xgmac"); qdev_set_nic_properties(dev, &nd_table[0]); qdev_init_nofail(dev); sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff50000); sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[77]); sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[78]); sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[79]); qemu_check_nic_model(&nd_table[1], "xgmac"); dev = qdev_create(NULL, "xgmac"); qdev_set_nic_properties(dev, &nd_table[1]); qdev_init_nofail(dev); sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff51000); sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[80]); sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[81]); sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[82]); } highbank_binfo.ram_size = ram_size; highbank_binfo.kernel_filename = kernel_filename; highbank_binfo.kernel_cmdline = kernel_cmdline; highbank_binfo.initrd_filename = initrd_filename; /* highbank requires a dtb in order to boot, and the dtb will override * the board ID. The following value is ignored, so set it to -1 to be * clear that the value is meaningless. */ highbank_binfo.board_id = -1; highbank_binfo.nb_cpus = smp_cpus; highbank_binfo.loader_start = 0; highbank_binfo.write_secondary_boot = hb_write_secondary; highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary; arm_load_kernel(arm_env_get_cpu(first_cpu), &highbank_binfo); }
static uint32_t dma_rinvalid (void *opaque, target_phys_addr_t addr) { hw_error("Unsupported short raccess. reg=" TARGET_FMT_plx "\n", addr); return 0; }
static int s390_ipl_init(SysBusDevice *dev) { S390IPLState *ipl = S390_IPL(dev); int kernel_size; if (!ipl->kernel) { int bios_size; char *bios_filename; /* Load zipl bootloader */ if (bios_name == NULL) { bios_name = ipl->firmware; } bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (bios_filename == NULL) { hw_error("could not find stage1 bootloader\n"); } bios_size = load_elf(bios_filename, NULL, NULL, &ipl->start_addr, NULL, NULL, 1, ELF_MACHINE, 0); if (bios_size == -1) { bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START, 4096); ipl->start_addr = ZIPL_IMAGE_START; if (bios_size > 4096) { hw_error("stage1 bootloader is > 4k\n"); } } g_free(bios_filename); if (bios_size == -1) { hw_error("could not load bootloader '%s'\n", bios_name); } return 0; } else { uint64_t pentry = KERN_IMAGE_START; kernel_size = load_elf(ipl->kernel, NULL, NULL, &pentry, NULL, NULL, 1, ELF_MACHINE, 0); if (kernel_size == -1) { kernel_size = load_image_targphys(ipl->kernel, 0, ram_size); } if (kernel_size == -1) { fprintf(stderr, "could not load kernel '%s'\n", ipl->kernel); return -1; } /* * Is it a Linux kernel (starting at 0x10000)? If yes, we fill in the * kernel parameters here as well. Note: For old kernels (up to 3.2) * we can not rely on the ELF entry point - it was 0x800 (the SALIPL * loader) and it won't work. For this case we force it to 0x10000, too. */ if (pentry == KERN_IMAGE_START || pentry == 0x800) { ipl->start_addr = KERN_IMAGE_START; /* Overwrite parameters in the kernel image, which are "rom" */ strcpy(rom_ptr(KERN_PARM_AREA), ipl->cmdline); } else { ipl->start_addr = pentry; } } if (ipl->initrd) { ram_addr_t initrd_offset; int initrd_size; initrd_offset = INITRD_START; while (kernel_size + 0x100000 > initrd_offset) { initrd_offset += 0x100000; } initrd_size = load_image_targphys(ipl->initrd, initrd_offset, ram_size - initrd_offset); if (initrd_size == -1) { fprintf(stderr, "qemu: could not load initrd '%s'\n", ipl->initrd); exit(1); } /* we have to overwrite values in the kernel image, which are "rom" */ stq_p(rom_ptr(INITRD_PARM_START), initrd_offset); stq_p(rom_ptr(INITRD_PARM_SIZE), initrd_size); } return 0; }
static uint64_t pxa2xx_keypad_read(void *opaque, target_phys_addr_t offset, unsigned size) { PXA2xxKeyPadState *s = (PXA2xxKeyPadState *) opaque; uint32_t tmp; switch (offset) { case KPC: tmp = s->kpc; if(tmp & KPC_MI) s->kpc &= ~(KPC_MI); if(tmp & KPC_DI) s->kpc &= ~(KPC_DI); qemu_irq_lower(s->irq); return tmp; break; case KPDK: return s->kpdk; break; case KPREC: tmp = s->kprec; if(tmp & KPREC_OF1) s->kprec &= ~(KPREC_OF1); if(tmp & KPREC_UF1) s->kprec &= ~(KPREC_UF1); if(tmp & KPREC_OF0) s->kprec &= ~(KPREC_OF0); if(tmp & KPREC_UF0) s->kprec &= ~(KPREC_UF0); return tmp; break; case KPMK: tmp = s->kpmk; if(tmp & KPMK_MKP) s->kpmk &= ~(KPMK_MKP); return tmp; break; case KPAS: return s->kpas; break; case KPASMKP0: return s->kpasmkp[0]; break; case KPASMKP1: return s->kpasmkp[1]; break; case KPASMKP2: return s->kpasmkp[2]; break; case KPASMKP3: return s->kpasmkp[3]; break; case KPKDI: return s->kpkdi; break; default: hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset); } return 0; }
static void vfio_prereg_listener_region_add(MemoryListener *listener, MemoryRegionSection *section) { VFIOContainer *container = container_of(listener, VFIOContainer, prereg_listener); const hwaddr gpa = section->offset_within_address_space; hwaddr end; int ret; hwaddr page_mask = qemu_real_host_page_mask; struct vfio_iommu_spapr_register_memory reg = { .argsz = sizeof(reg), .flags = 0, }; if (vfio_prereg_listener_skipped_section(section)) { trace_vfio_prereg_listener_region_add_skip( section->offset_within_address_space, section->offset_within_address_space + int128_get64(int128_sub(section->size, int128_one()))); return; } if (unlikely((section->offset_within_address_space & ~page_mask) || (section->offset_within_region & ~page_mask) || (int128_get64(section->size) & ~page_mask))) { error_report("%s received unaligned region", __func__); return; } end = section->offset_within_address_space + int128_get64(section->size); if (gpa >= end) { return; } memory_region_ref(section->mr); reg.vaddr = (uintptr_t) vfio_prereg_gpa_to_vaddr(section, gpa); reg.size = end - gpa; ret = ioctl(container->fd, VFIO_IOMMU_SPAPR_REGISTER_MEMORY, ®); trace_vfio_prereg_register(reg.vaddr, reg.size, ret ? -errno : 0); if (ret) { /* * On the initfn path, store the first error in the container so we * can gracefully fail. Runtime, there's not much we can do other * than throw a hardware error. */ if (!container->initialized) { if (!container->error) { container->error = ret; } } else { hw_error("vfio: Memory registering failed, unable to continue"); } } } static void vfio_prereg_listener_region_del(MemoryListener *listener, MemoryRegionSection *section) { VFIOContainer *container = container_of(listener, VFIOContainer, prereg_listener); const hwaddr gpa = section->offset_within_address_space; hwaddr end; int ret; hwaddr page_mask = qemu_real_host_page_mask; struct vfio_iommu_spapr_register_memory reg = { .argsz = sizeof(reg), .flags = 0, }; if (vfio_prereg_listener_skipped_section(section)) { trace_vfio_prereg_listener_region_del_skip( section->offset_within_address_space, section->offset_within_address_space + int128_get64(int128_sub(section->size, int128_one()))); return; } if (unlikely((section->offset_within_address_space & ~page_mask) || (section->offset_within_region & ~page_mask) || (int128_get64(section->size) & ~page_mask))) { error_report("%s received unaligned region", __func__); return; } end = section->offset_within_address_space + int128_get64(section->size); if (gpa >= end) { return; } reg.vaddr = (uintptr_t) vfio_prereg_gpa_to_vaddr(section, gpa); reg.size = end - gpa; ret = ioctl(container->fd, VFIO_IOMMU_SPAPR_UNREGISTER_MEMORY, ®); trace_vfio_prereg_unregister(reg.vaddr, reg.size, ret ? -errno : 0); } const MemoryListener vfio_prereg_listener = { .region_add = vfio_prereg_listener_region_add, .region_del = vfio_prereg_listener_region_del, }; int vfio_spapr_create_window(VFIOContainer *container, MemoryRegionSection *section, hwaddr *pgsize) { int ret; unsigned pagesize = memory_region_iommu_get_min_page_size(section->mr); unsigned entries, pages; struct vfio_iommu_spapr_tce_create create = { .argsz = sizeof(create) }; /* * FIXME: For VFIO iommu types which have KVM acceleration to * avoid bouncing all map/unmaps through qemu this way, this * would be the right place to wire that up (tell the KVM * device emulation the VFIO iommu handles to use). */ create.window_size = int128_get64(section->size); create.page_shift = ctz64(pagesize); /* * SPAPR host supports multilevel TCE tables, there is some * heuristic to decide how many levels we want for our table: * 0..64 = 1; 65..4096 = 2; 4097..262144 = 3; 262145.. = 4 */ entries = create.window_size >> create.page_shift; pages = MAX((entries * sizeof(uint64_t)) / getpagesize(), 1); pages = MAX(pow2ceil(pages) - 1, 1); /* Round up */ create.levels = ctz64(pages) / 6 + 1; ret = ioctl(container->fd, VFIO_IOMMU_SPAPR_TCE_CREATE, &create); if (ret) { error_report("Failed to create a window, ret = %d (%m)", ret); return -errno; } if (create.start_addr != section->offset_within_address_space) { vfio_spapr_remove_window(container, create.start_addr); error_report("Host doesn't support DMA window at %"HWADDR_PRIx", must be %"PRIx64, section->offset_within_address_space, (uint64_t)create.start_addr); ioctl(container->fd, VFIO_IOMMU_SPAPR_TCE_REMOVE, &remove); return -EINVAL; } trace_vfio_spapr_create_window(create.page_shift, create.window_size, create.start_addr); *pgsize = pagesize; return 0; } int vfio_spapr_remove_window(VFIOContainer *container, hwaddr offset_within_address_space) { struct vfio_iommu_spapr_tce_remove remove = { .argsz = sizeof(remove), .start_addr = offset_within_address_space, }; int ret; ret = ioctl(container->fd, VFIO_IOMMU_SPAPR_TCE_REMOVE, &remove); if (ret) { error_report("Failed to remove window at %"PRIx64, (uint64_t)remove.start_addr); return -errno; } trace_vfio_spapr_remove_window(offset_within_address_space); return 0; }
static void pxa2xx_mmci_write(void *opaque, target_phys_addr_t offset, uint32_t value) { PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque; switch (offset) { case MMC_STRPCL: if (value & STRPCL_STRT_CLK) { s->status |= STAT_CLK_EN; s->intreq &= ~INT_CLK_OFF; if (s->cmdreq && !(s->cmdat & CMDAT_STOP_TRAN)) { s->status &= STAT_CLK_EN; pxa2xx_mmci_wakequeues(s); } } if (value & STRPCL_STOP_CLK) { s->status &= ~STAT_CLK_EN; s->intreq |= INT_CLK_OFF; s->active = 0; } pxa2xx_mmci_int_update(s); break; case MMC_CLKRT: s->clkrt = value & 7; break; case MMC_SPI: s->spi = value & 0xf; if (value & SPI_SPI_MODE) printf("%s: attempted to use card in SPI mode\n", __FUNCTION__); break; case MMC_CMDAT: s->cmdat = value & 0x3dff; s->active = 0; s->cmdreq = 1; if (!(value & CMDAT_STOP_TRAN)) { s->status &= STAT_CLK_EN; if (s->status & STAT_CLK_EN) pxa2xx_mmci_wakequeues(s); } pxa2xx_mmci_int_update(s); break; case MMC_RESTO: s->resp_tout = value & 0x7f; break; case MMC_RDTO: s->read_tout = value & 0xffff; break; case MMC_BLKLEN: s->blklen = value & 0xfff; break; case MMC_NUMBLK: s->numblk = value & 0xffff; break; case MMC_PRTBUF: if (value & PRTBUF_PRT_BUF) { s->tx_start ^= 32; s->tx_len = 0; } pxa2xx_mmci_fifo_update(s); break; case MMC_I_MASK: s->intmask = value & 0x1fff; pxa2xx_mmci_int_update(s); break; case MMC_CMD: s->cmd = value & 0x3f; break; case MMC_ARGH: s->arg &= 0x0000ffff; s->arg |= value << 16; break; case MMC_ARGL: s->arg &= 0xffff0000; s->arg |= value & 0x0000ffff; break; case MMC_TXFIFO: while (s->ac_width -- && s->tx_len < 0x20) s->tx_fifo[(s->tx_start + (s->tx_len ++)) & 0x1f] = (value >> (s->ac_width << 3)) & 0xff; s->intreq &= ~INT_TXFIFO_REQ; pxa2xx_mmci_fifo_update(s); break; case MMC_RDWAIT: case MMC_BLKS_REM: break; default: hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset); } }
static void smc91c111_writeb(void *opaque, hwaddr offset, uint32_t value) { smc91c111_state *s = (smc91c111_state *)opaque; offset = offset & 0xf; if (offset == 14) { s->bank = value; return; } if (offset == 15) return; switch (s->bank) { case 0: switch (offset) { case 0: /* TCR */ SET_LOW(tcr, value); return; case 1: SET_HIGH(tcr, value); return; case 4: /* RCR */ SET_LOW(rcr, value); return; case 5: SET_HIGH(rcr, value); if (s->rcr & RCR_SOFT_RST) { smc91c111_reset(DEVICE(s)); } return; case 10: case 11: /* RPCR */ /* Ignored */ return; case 12: case 13: /* Reserved */ return; } break; case 1: switch (offset) { case 0: /* CONFIG */ SET_LOW(cr, value); return; case 1: SET_HIGH(cr,value); return; case 2: case 3: /* BASE */ case 4: case 5: case 6: case 7: case 8: case 9: /* IA */ /* Not implemented. */ return; case 10: /* Genral Purpose */ SET_LOW(gpr, value); return; case 11: SET_HIGH(gpr, value); return; case 12: /* Control */ if (value & 1) fprintf(stderr, "smc91c111:EEPROM store not implemented\n"); if (value & 2) fprintf(stderr, "smc91c111:EEPROM reload not implemented\n"); value &= ~3; SET_LOW(ctr, value); return; case 13: SET_HIGH(ctr, value); return; } break; case 2: switch (offset) { case 0: /* MMU Command */ switch (value >> 5) { case 0: /* no-op */ break; case 1: /* Allocate for TX. */ s->tx_alloc = 0x80; s->int_level &= ~INT_ALLOC; smc91c111_update(s); smc91c111_tx_alloc(s); break; case 2: /* Reset MMU. */ s->allocated = 0; s->tx_fifo_len = 0; s->tx_fifo_done_len = 0; s->rx_fifo_len = 0; s->tx_alloc = 0; break; case 3: /* Remove from RX FIFO. */ smc91c111_pop_rx_fifo(s); break; case 4: /* Remove from RX FIFO and release. */ if (s->rx_fifo_len > 0) { smc91c111_release_packet(s, s->rx_fifo[0]); } smc91c111_pop_rx_fifo(s); break; case 5: /* Release. */ smc91c111_release_packet(s, s->packet_num); break; case 6: /* Add to TX FIFO. */ smc91c111_queue_tx(s, s->packet_num); break; case 7: /* Reset TX FIFO. */ s->tx_fifo_len = 0; s->tx_fifo_done_len = 0; break; } return; case 1: /* Ignore. */ return; case 2: /* Packet Number Register */ s->packet_num = value; return; case 3: case 4: case 5: /* Should be readonly, but linux writes to them anyway. Ignore. */ return; case 6: /* Pointer */ SET_LOW(ptr, value); return; case 7: SET_HIGH(ptr, value); return; case 8: case 9: case 10: case 11: /* Data */ { int p; int n; if (s->ptr & 0x8000) n = s->rx_fifo[0]; else n = s->packet_num; p = s->ptr & 0x07ff; if (s->ptr & 0x4000) { s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x7ff); } else { p += (offset & 3); } s->data[n][p] = value; } return; case 12: /* Interrupt ACK. */ s->int_level &= ~(value & 0xd6); if (value & INT_TX) smc91c111_pop_tx_fifo_done(s); smc91c111_update(s); return; case 13: /* Interrupt mask. */ s->int_mask = value; smc91c111_update(s); return; } break; case 3: switch (offset) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: /* Multicast table. */ /* Not implemented. */ return; case 8: case 9: /* Management Interface. */ /* Not implemented. */ return; case 12: /* Early receive. */ s->ercv = value & 0x1f; return; case 13: /* Ignore. */ return; } break; } hw_error("smc91c111_write: Bad reg %d:%x\n", s->bank, (int)offset); }
static void ppc_heathrow_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; const char *boot_device = machine->boot_order; MemoryRegion *sysmem = get_system_memory(); PowerPCCPU *cpu = NULL; CPUPPCState *env = NULL; char *filename; qemu_irq *pic, **heathrow_irqs; int linux_boot, i; MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); MemoryRegion *isa = g_new(MemoryRegion, 1); uint32_t kernel_base, initrd_base, cmdline_base = 0; int32_t kernel_size, initrd_size; PCIBus *pci_bus; PCIDevice *macio; MACIOIDEState *macio_ide; DeviceState *dev; BusState *adb_bus; int bios_size; MemoryRegion *pic_mem; MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1); uint16_t ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; uint64_t tbfreq; linux_boot = (kernel_filename != NULL); /* init CPUs */ if (machine->cpu_model == NULL) machine->cpu_model = "G3"; for (i = 0; i < smp_cpus; i++) { cpu = cpu_ppc_init(machine->cpu_model); if (cpu == NULL) { fprintf(stderr, "Unable to find PowerPC CPU definition\n"); exit(1); } env = &cpu->env; /* Set time-base frequency to 16.6 Mhz */ cpu_ppc_tb_init(env, TBFREQ); qemu_register_reset(ppc_heathrow_reset, cpu); } /* allocate RAM */ if (ram_size > (2047 << 20)) { fprintf(stderr, "qemu: Too much memory for this machine: %d MB, maximum 2047 MB\n", ((unsigned int)ram_size / (1 << 20))); exit(1); } memory_region_allocate_system_memory(ram, NULL, "ppc_heathrow.ram", ram_size); memory_region_add_subregion(sysmem, 0, ram); /* allocate and load BIOS */ memory_region_init_ram(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE, &error_fatal); vmstate_register_ram_global(bios); if (bios_name == NULL) bios_name = PROM_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); memory_region_set_readonly(bios, true); memory_region_add_subregion(sysmem, PROM_ADDR, bios); /* Load OpenBIOS (ELF) */ if (filename) { bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL, 1, ELF_MACHINE, 0); g_free(filename); } else { bios_size = -1; } if (bios_size < 0 || bios_size > BIOS_SIZE) { hw_error("qemu: could not load PowerPC bios '%s'\n", bios_name); exit(1); } if (linux_boot) { uint64_t lowaddr = 0; int bswap_needed; #ifdef BSWAP_NEEDED bswap_needed = 1; #else bswap_needed = 0; #endif kernel_base = KERNEL_LOAD_ADDR; kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0); if (kernel_size < 0) kernel_size = load_aout(kernel_filename, kernel_base, ram_size - kernel_base, bswap_needed, TARGET_PAGE_SIZE); if (kernel_size < 0) kernel_size = load_image_targphys(kernel_filename, kernel_base, ram_size - kernel_base); if (kernel_size < 0) { hw_error("qemu: could not load kernel '%s'\n", kernel_filename); exit(1); } /* load initrd */ if (initrd_filename) { initrd_base = round_page(kernel_base + kernel_size + KERNEL_GAP); initrd_size = load_image_targphys(initrd_filename, initrd_base, ram_size - initrd_base); if (initrd_size < 0) { hw_error("qemu: could not load initial ram disk '%s'\n", initrd_filename); exit(1); } cmdline_base = round_page(initrd_base + initrd_size); } else { initrd_base = 0; initrd_size = 0; cmdline_base = round_page(kernel_base + kernel_size + KERNEL_GAP); } ppc_boot_device = 'm'; } else { kernel_base = 0; kernel_size = 0; initrd_base = 0; initrd_size = 0; ppc_boot_device = '\0'; for (i = 0; boot_device[i] != '\0'; i++) { /* TOFIX: for now, the second IDE channel is not properly * used by OHW. The Mac floppy disk are not emulated. * For now, OHW cannot boot from the network. */ #if 0 if (boot_device[i] >= 'a' && boot_device[i] <= 'f') { ppc_boot_device = boot_device[i]; break; } #else if (boot_device[i] >= 'c' && boot_device[i] <= 'd') { ppc_boot_device = boot_device[i]; break; } #endif } if (ppc_boot_device == '\0') { fprintf(stderr, "No valid boot device for G3 Beige machine\n"); exit(1); } } /* Register 2 MB of ISA IO space */ memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(), 0, 0x00200000); memory_region_add_subregion(sysmem, 0xfe000000, isa); /* XXX: we register only 1 output pin for heathrow PIC */ heathrow_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); heathrow_irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * 1); /* Connect the heathrow PIC outputs to the 6xx bus */ for (i = 0; i < smp_cpus; i++) { switch (PPC_INPUT(env)) { case PPC_FLAGS_INPUT_6xx: heathrow_irqs[i] = heathrow_irqs[0] + (i * 1); heathrow_irqs[i][0] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT]; break; default: hw_error("Bus model not supported on OldWorld Mac machine\n"); } } /* Timebase Frequency */ if (kvm_enabled()) { tbfreq = kvmppc_get_tbfreq(); } else { tbfreq = TBFREQ; } /* init basic PC hardware */ if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) { hw_error("Only 6xx bus is supported on heathrow machine\n"); } pic = heathrow_pic_init(&pic_mem, 1, heathrow_irqs); pci_bus = pci_grackle_init(0xfec00000, pic, get_system_memory(), get_system_io()); pci_vga_init(pci_bus); escc_mem = escc_init(0, pic[0x0f], pic[0x10], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); memory_region_init_alias(escc_bar, NULL, "escc-bar", escc_mem, 0, memory_region_size(escc_mem)); for(i = 0; i < nb_nics; i++) pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL); ide_drive_get(hd, ARRAY_SIZE(hd)); macio = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO); dev = DEVICE(macio); qdev_connect_gpio_out(dev, 0, pic[0x12]); /* CUDA */ qdev_connect_gpio_out(dev, 1, pic[0x0D]); /* IDE-0 */ qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE-0 DMA */ qdev_connect_gpio_out(dev, 3, pic[0x0E]); /* IDE-1 */ qdev_connect_gpio_out(dev, 4, pic[0x03]); /* IDE-1 DMA */ qdev_prop_set_uint64(dev, "frequency", tbfreq); macio_init(macio, pic_mem, escc_bar); macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), "ide[0]")); macio_ide_init_drives(macio_ide, hd); macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), "ide[1]")); macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]); dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda")); adb_bus = qdev_get_child_bus(dev, "adb.0"); dev = qdev_create(adb_bus, TYPE_ADB_KEYBOARD); qdev_init_nofail(dev); dev = qdev_create(adb_bus, TYPE_ADB_MOUSE); qdev_init_nofail(dev); if (usb_enabled()) { pci_create_simple(pci_bus, -1, "pci-ohci"); } if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8) graphic_depth = 15; /* No PCI init: the BIOS will do it */ fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_HEATHROW); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); if (kernel_cmdline) { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base); pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline); } else { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0); } fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_base); fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ppc_boot_device); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_WIDTH, graphic_width); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled()); if (kvm_enabled()) { #ifdef CONFIG_KVM uint8_t *hypercall; hypercall = g_malloc(16); kvmppc_get_hypercall(env, hypercall, 16); fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); #endif } fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, tbfreq); /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, CLOCKFREQ); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_BUSFREQ, BUSFREQ); qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); }
static uint32_t smc91c111_readb(void *opaque, hwaddr offset) { smc91c111_state *s = (smc91c111_state *)opaque; offset = offset & 0xf; if (offset == 14) { return s->bank; } if (offset == 15) return 0x33; switch (s->bank) { case 0: switch (offset) { case 0: /* TCR */ return s->tcr & 0xff; case 1: return s->tcr >> 8; case 2: /* EPH Status */ return 0; case 3: return 0x40; case 4: /* RCR */ return s->rcr & 0xff; case 5: return s->rcr >> 8; case 6: /* Counter */ case 7: /* Not implemented. */ return 0; case 8: /* Memory size. */ return NUM_PACKETS; case 9: /* Free memory available. */ { int i; int n; n = 0; for (i = 0; i < NUM_PACKETS; i++) { if (s->allocated & (1 << i)) n++; } return n; } case 10: case 11: /* RPCR */ /* Not implemented. */ return 0; case 12: case 13: /* Reserved */ return 0; } break; case 1: switch (offset) { case 0: /* CONFIG */ return s->cr & 0xff; case 1: return s->cr >> 8; case 2: case 3: /* BASE */ /* Not implemented. */ return 0; case 4: case 5: case 6: case 7: case 8: case 9: /* IA */ return s->conf.macaddr.a[offset - 4]; case 10: /* General Purpose */ return s->gpr & 0xff; case 11: return s->gpr >> 8; case 12: /* Control */ return s->ctr & 0xff; case 13: return s->ctr >> 8; } break; case 2: switch (offset) { case 0: case 1: /* MMUCR Busy bit. */ return 0; case 2: /* Packet Number. */ return s->packet_num; case 3: /* Allocation Result. */ return s->tx_alloc; case 4: /* TX FIFO */ if (s->tx_fifo_done_len == 0) return 0x80; else return s->tx_fifo_done[0]; case 5: /* RX FIFO */ if (s->rx_fifo_len == 0) return 0x80; else return s->rx_fifo[0]; case 6: /* Pointer */ return s->ptr & 0xff; case 7: return (s->ptr >> 8) & 0xf7; case 8: case 9: case 10: case 11: /* Data */ { int p; int n; if (s->ptr & 0x8000) n = s->rx_fifo[0]; else n = s->packet_num; p = s->ptr & 0x07ff; if (s->ptr & 0x4000) { s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x07ff); } else { p += (offset & 3); } return s->data[n][p]; } case 12: /* Interrupt status. */ return s->int_level; case 13: /* Interrupt mask. */ return s->int_mask; } break; case 3: switch (offset) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: /* Multicast table. */ /* Not implemented. */ return 0; case 8: /* Management Interface. */ /* Not implemented. */ return 0x30; case 9: return 0x33; case 10: /* Revision. */ return 0x91; case 11: return 0x33; case 12: return s->ercv; case 13: return 0; } break; } hw_error("smc91c111_read: Bad reg %d:%x\n", s->bank, (int)offset); return 0; }
static void stellaris_enet_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { stellaris_enet_state *s = (stellaris_enet_state *)opaque; switch (offset) { case 0x00: /* IACK */ s->ris &= ~value; DPRINTF("IRQ ack %02" PRIx64 "/%02x\n", value, s->ris); stellaris_enet_update(s); /* Clearing TXER also resets the TX fifo. */ if (value & SE_INT_TXER) { s->tx_fifo_len = 0; } break; case 0x04: /* IM */ DPRINTF("IRQ mask %02" PRIx64 "/%02x\n", value, s->ris); s->im = value; stellaris_enet_update(s); break; case 0x08: /* RCTL */ s->rctl = value; if (value & SE_RCTL_RSTFIFO) { s->np = 0; s->rx_fifo_offset = 0; stellaris_enet_update(s); } break; case 0x0c: /* TCTL */ s->tctl = value; break; case 0x10: /* DATA */ if (s->tx_fifo_len == 0) { /* The first word is special, it contains the data length */ int framelen = value & 0xffff; if (framelen > 2032) { DPRINTF("TX frame too long (%d)\n", framelen); s->ris |= SE_INT_TXER; stellaris_enet_update(s); break; } } if (s->tx_fifo_len + 4 <= ARRAY_SIZE(s->tx_fifo)) { s->tx_fifo[s->tx_fifo_len++] = value; s->tx_fifo[s->tx_fifo_len++] = value >> 8; s->tx_fifo[s->tx_fifo_len++] = value >> 16; s->tx_fifo[s->tx_fifo_len++] = value >> 24; } if (stellaris_tx_thr_reached(s) && stellaris_txpacket_complete(s)) { stellaris_enet_send(s); } break; case 0x14: /* IA0 */ s->conf.macaddr.a[0] = value; s->conf.macaddr.a[1] = value >> 8; s->conf.macaddr.a[2] = value >> 16; s->conf.macaddr.a[3] = value >> 24; break; case 0x18: /* IA1 */ s->conf.macaddr.a[4] = value; s->conf.macaddr.a[5] = value >> 8; break; case 0x1c: /* THR */ s->thr = value; break; case 0x20: /* MCTL */ s->mctl = value; break; case 0x24: /* MDV */ s->mdv = value; break; case 0x28: /* MADD */ /* ignored. */ break; case 0x2c: /* MTXD */ s->mtxd = value & 0xff; break; case 0x38: /* TR */ if (value & 1) { stellaris_enet_send(s); } break; case 0x30: /* MRXD */ case 0x34: /* NP */ /* Ignored. */ case 0x3c: /* Undocuented: Timestamp? */ /* Ignored. */ break; default: hw_error("stellaris_enet_write: Bad offset %x\n", (int)offset); }
static void smc91c111_writeb(void *opaque, target_phys_addr_t offset, uint32_t value) { smc91c111_state *s = (smc91c111_state *)opaque; if (offset == 14) { s->bank = value; return; } if (offset == 15) return; switch (s->bank) { case 0: switch (offset) { case 0: SET_LOW(tcr, value); return; case 1: SET_HIGH(tcr, value); return; case 4: SET_LOW(rcr, value); return; case 5: SET_HIGH(rcr, value); if (s->rcr & RCR_SOFT_RST) smc91c111_reset(s); return; case 10: case 11: return; } break; case 1: switch (offset) { case 0: SET_LOW(cr, value); return; case 1: SET_HIGH(cr,value); return; case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: return; case 10: SET_LOW(gpr, value); return; case 11: SET_HIGH(gpr, value); return; case 12: if (value & 1) fprintf(stderr, "smc91c111:EEPROM store not implemented\n"); if (value & 2) fprintf(stderr, "smc91c111:EEPROM reload not implemented\n"); value &= ~3; SET_LOW(ctr, value); return; case 13: SET_HIGH(ctr, value); return; } break; case 2: switch (offset) { case 0: switch (value >> 5) { case 0: break; case 1: s->tx_alloc = 0x80; s->int_level &= ~INT_ALLOC; smc91c111_update(s); smc91c111_tx_alloc(s); break; case 2: s->allocated = 0; s->tx_fifo_len = 0; s->tx_fifo_done_len = 0; s->rx_fifo_len = 0; s->tx_alloc = 0; break; case 3: smc91c111_pop_rx_fifo(s); break; case 4: if (s->rx_fifo_len > 0) { smc91c111_release_packet(s, s->rx_fifo[0]); } smc91c111_pop_rx_fifo(s); break; case 5: smc91c111_release_packet(s, s->packet_num); break; case 6: smc91c111_queue_tx(s, s->packet_num); break; case 7: s->tx_fifo_len = 0; s->tx_fifo_done_len = 0; break; } return; case 1: return; case 2: s->packet_num = value; return; case 3: case 4: case 5: return; case 6: SET_LOW(ptr, value); return; case 7: SET_HIGH(ptr, value); return; case 8: case 9: case 10: case 11: { int p; int n; if (s->ptr & 0x8000) n = s->rx_fifo[0]; else n = s->packet_num; p = s->ptr & 0x07ff; if (s->ptr & 0x4000) { s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x7ff); } else { p += (offset & 3); } s->data[n][p] = value; } return; case 12: s->int_level &= ~(value & 0xd6); if (value & INT_TX) smc91c111_pop_tx_fifo_done(s); smc91c111_update(s); return; case 13: s->int_mask = value; smc91c111_update(s); return; } break;; case 3: switch (offset) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: return; case 8: case 9: return; case 12: s->ercv = value & 0x1f; case 13: return; } break; } hw_error("smc91c111_write: Bad reg %d:%x\n", s->bank, (int)offset); }
static void pxa2xx_lcdc_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PXA2xxLCDState *s = (PXA2xxLCDState *) opaque; int ch; switch (offset) { case LCCR0: /* ACK Quick Disable done */ if ((s->control[0] & LCCR0_ENB) && !(value & LCCR0_ENB)) s->status[0] |= LCSR0_QD; if (!(s->control[0] & LCCR0_LCDT) && (value & LCCR0_LCDT)) printf("%s: internal frame buffer unsupported\n", __FUNCTION__); if ((s->control[3] & LCCR3_API) && (value & LCCR0_ENB) && !(value & LCCR0_LCDT)) s->status[0] |= LCSR0_ABC; s->control[0] = value & 0x07ffffff; pxa2xx_lcdc_int_update(s); s->dma_ch[0].up = !!(value & LCCR0_ENB); s->dma_ch[1].up = (s->ovl1c[0] & OVLC1_EN) || (value & LCCR0_SDS); break; case LCCR1: s->control[1] = value; break; case LCCR2: s->control[2] = value; break; case LCCR3: s->control[3] = value & 0xefffffff; s->bpp = LCCR3_BPP(value); break; case LCCR4: s->control[4] = value & 0x83ff81ff; break; case LCCR5: s->control[5] = value & 0x3f3f3f3f; break; case OVL1C1: if (!(s->ovl1c[0] & OVLC1_EN) && (value & OVLC1_EN)) printf("%s: Overlay 1 not supported\n", __FUNCTION__); s->ovl1c[0] = value & 0x80ffffff; s->dma_ch[1].up = (value & OVLC1_EN) || (s->control[0] & LCCR0_SDS); break; case OVL1C2: s->ovl1c[1] = value & 0x000fffff; break; case OVL2C1: if (!(s->ovl2c[0] & OVLC1_EN) && (value & OVLC1_EN)) printf("%s: Overlay 2 not supported\n", __FUNCTION__); s->ovl2c[0] = value & 0x80ffffff; s->dma_ch[2].up = !!(value & OVLC1_EN); s->dma_ch[3].up = !!(value & OVLC1_EN); s->dma_ch[4].up = !!(value & OVLC1_EN); break; case OVL2C2: s->ovl2c[1] = value & 0x007fffff; break; case CCR: if (!(s->ccr & CCR_CEN) && (value & CCR_CEN)) printf("%s: Hardware cursor unimplemented\n", __FUNCTION__); s->ccr = value & 0x81ffffe7; s->dma_ch[5].up = !!(value & CCR_CEN); break; case CMDCR: s->cmdcr = value & 0xff; break; case TRGBR: s->trgbr = value & 0x00ffffff; break; case TCR: s->tcr = value & 0x7fff; break; case 0x200 ... 0x1000: /* DMA per-channel registers */ ch = (offset - 0x200) >> 4; if (!(ch >= 0 && ch < PXA_LCDDMA_CHANS)) goto fail; switch (offset & 0xf) { case DMA_FDADR: s->dma_ch[ch].descriptor = value & 0xfffffff0; break; default: goto fail; } break; case FBR0: s->dma_ch[0].branch = value & 0xfffffff3; break; case FBR1: s->dma_ch[1].branch = value & 0xfffffff3; break; case FBR2: s->dma_ch[2].branch = value & 0xfffffff3; break; case FBR3: s->dma_ch[3].branch = value & 0xfffffff3; break; case FBR4: s->dma_ch[4].branch = value & 0xfffffff3; break; case FBR5: s->dma_ch[5].branch = value & 0xfffffff3; break; case FBR6: s->dma_ch[6].branch = value & 0xfffffff3; break; case BSCNTR: s->bscntr = value & 0xf; break; case PRSR: break; case LCSR0: s->status[0] &= ~(value & 0xfff); if (value & LCSR0_BER) s->status[0] &= ~LCSR0_BERCH(7); break; case LCSR1: s->status[1] &= ~(value & 0x3e3f3f); break; default: fail: hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset); } }
static uint32_t smc91c111_readb(void *opaque, target_phys_addr_t offset) { smc91c111_state *s = (smc91c111_state *)opaque; if (offset == 14) { return s->bank; } if (offset == 15) return 0x33; switch (s->bank) { case 0: switch (offset) { case 0: return s->tcr & 0xff; case 1: return s->tcr >> 8; case 2: return 0; case 3: return 0x40; case 4: return s->rcr & 0xff; case 5: return s->rcr >> 8; case 6: case 7: return 0; case 8: return NUM_PACKETS; case 9: { int i; int n; n = 0; for (i = 0; i < NUM_PACKETS; i++) { if (s->allocated & (1 << i)) n++; } return n; } case 10: case 11: return 0; } break; case 1: switch (offset) { case 0: return s->cr & 0xff; case 1: return s->cr >> 8; case 2: case 3: return 0; case 4: case 5: case 6: case 7: case 8: case 9: return s->macaddr[offset - 4]; case 10: return s->gpr & 0xff; case 11: return s->gpr >> 8; case 12: return s->ctr & 0xff; case 13: return s->ctr >> 8; } break; case 2: switch (offset) { case 0: case 1: return 0; case 2: return s->packet_num; case 3: return s->tx_alloc; case 4: if (s->tx_fifo_done_len == 0) return 0x80; else return s->tx_fifo_done[0]; case 5: if (s->rx_fifo_len == 0) return 0x80; else return s->rx_fifo[0]; case 6: return s->ptr & 0xff; case 7: return (s->ptr >> 8) & 0xf7; case 8: case 9: case 10: case 11: { int p; int n; if (s->ptr & 0x8000) n = s->rx_fifo[0]; else n = s->packet_num; p = s->ptr & 0x07ff; if (s->ptr & 0x4000) { s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x07ff); } else { p += (offset & 3); } return s->data[n][p]; } case 12: return s->int_level; case 13: return s->int_mask; } break; case 3: switch (offset) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: return 0; case 8: return 0x30; case 9: return 0x33; case 10: return 0x91; case 11: return 0x33; case 12: return s->ercv; case 13: return 0; } break; } hw_error("smc91c111_read: Bad reg %d:%x\n", s->bank, (int)offset); return 0; }
/* PowerPC Mac99 hardware initialisation */ static void ppc_core99_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; const char *cpu_model = machine->cpu_model; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; const char *boot_device = machine->boot_order; PowerPCCPU *cpu = NULL; CPUPPCState *env = NULL; char *filename; qemu_irq *pic, **openpic_irqs; MemoryRegion *isa = g_new(MemoryRegion, 1); MemoryRegion *unin_memory = g_new(MemoryRegion, 1); MemoryRegion *unin2_memory = g_new(MemoryRegion, 1); int linux_boot, i, j, k; MemoryRegion *ram = g_new(MemoryRegion, 1), *bios = g_new(MemoryRegion, 1); hwaddr kernel_base, initrd_base, cmdline_base = 0; long kernel_size, initrd_size; PCIBus *pci_bus; PCIDevice *macio; MACIOIDEState *macio_ide; BusState *adb_bus; MacIONVRAMState *nvr; int bios_size; MemoryRegion *pic_mem, *escc_mem; MemoryRegion *escc_bar = g_new(MemoryRegion, 1); int ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; int machine_arch; SysBusDevice *s; DeviceState *dev; int *token = g_new(int, 1); linux_boot = (kernel_filename != NULL); /* init CPUs */ if (cpu_model == NULL) #ifdef TARGET_PPC64 cpu_model = "970fx"; #else cpu_model = "G4"; #endif for (i = 0; i < smp_cpus; i++) { cpu = cpu_ppc_init(cpu_model); if (cpu == NULL) { fprintf(stderr, "Unable to find PowerPC CPU definition\n"); exit(1); } env = &cpu->env; /* Set time-base frequency to 100 Mhz */ cpu_ppc_tb_init(env, TBFREQ); qemu_register_reset(ppc_core99_reset, cpu); } /* allocate RAM */ memory_region_allocate_system_memory(ram, NULL, "ppc_core99.ram", ram_size); memory_region_add_subregion(get_system_memory(), 0, ram); /* allocate and load BIOS */ memory_region_init_ram(bios, NULL, "ppc_core99.bios", BIOS_SIZE); vmstate_register_ram_global(bios); if (bios_name == NULL) bios_name = PROM_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); memory_region_set_readonly(bios, true); memory_region_add_subregion(get_system_memory(), PROM_ADDR, bios); /* Load OpenBIOS (ELF) */ if (filename) { bios_size = load_elf(filename, NULL, NULL, NULL, NULL, NULL, 1, ELF_MACHINE, 0); g_free(filename); } else { bios_size = -1; } if (bios_size < 0 || bios_size > BIOS_SIZE) { hw_error("qemu: could not load PowerPC bios '%s'\n", bios_name); exit(1); } if (linux_boot) { uint64_t lowaddr = 0; int bswap_needed; #ifdef BSWAP_NEEDED bswap_needed = 1; #else bswap_needed = 0; #endif kernel_base = KERNEL_LOAD_ADDR; kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0); if (kernel_size < 0) kernel_size = load_aout(kernel_filename, kernel_base, ram_size - kernel_base, bswap_needed, TARGET_PAGE_SIZE); if (kernel_size < 0) kernel_size = load_image_targphys(kernel_filename, kernel_base, ram_size - kernel_base); if (kernel_size < 0) { hw_error("qemu: could not load kernel '%s'\n", kernel_filename); exit(1); } /* load initrd */ if (initrd_filename) { initrd_base = round_page(kernel_base + kernel_size + KERNEL_GAP); initrd_size = load_image_targphys(initrd_filename, initrd_base, ram_size - initrd_base); if (initrd_size < 0) { hw_error("qemu: could not load initial ram disk '%s'\n", initrd_filename); exit(1); } cmdline_base = round_page(initrd_base + initrd_size); } else { initrd_base = 0; initrd_size = 0; cmdline_base = round_page(kernel_base + kernel_size + KERNEL_GAP); } ppc_boot_device = 'm'; } else { kernel_base = 0; kernel_size = 0; initrd_base = 0; initrd_size = 0; ppc_boot_device = '\0'; /* We consider that NewWorld PowerMac never have any floppy drive * For now, OHW cannot boot from the network. */ for (i = 0; boot_device[i] != '\0'; i++) { if (boot_device[i] >= 'c' && boot_device[i] <= 'f') { ppc_boot_device = boot_device[i]; break; } } if (ppc_boot_device == '\0') { fprintf(stderr, "No valid boot device for Mac99 machine\n"); exit(1); } } /* Register 8 MB of ISA IO space */ memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(), 0, 0x00800000); memory_region_add_subregion(get_system_memory(), 0xf2000000, isa); /* UniN init: XXX should be a real device */ memory_region_init_io(unin_memory, NULL, &unin_ops, token, "unin", 0x1000); memory_region_add_subregion(get_system_memory(), 0xf8000000, unin_memory); memory_region_init_io(unin2_memory, NULL, &unin_ops, token, "unin", 0x1000); memory_region_add_subregion(get_system_memory(), 0xf3000000, unin2_memory); openpic_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); openpic_irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB); for (i = 0; i < smp_cpus; i++) { /* Mac99 IRQ connection between OpenPIC outputs pins * and PowerPC input pins */ switch (PPC_INPUT(env)) { case PPC_FLAGS_INPUT_6xx: openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB); openpic_irqs[i][OPENPIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT]; openpic_irqs[i][OPENPIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT]; openpic_irqs[i][OPENPIC_OUTPUT_MCK] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP]; /* Not connected ? */ openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL; /* Check this */ openpic_irqs[i][OPENPIC_OUTPUT_RESET] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET]; break; #if defined(TARGET_PPC64) case PPC_FLAGS_INPUT_970: openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB); openpic_irqs[i][OPENPIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT]; openpic_irqs[i][OPENPIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT]; openpic_irqs[i][OPENPIC_OUTPUT_MCK] = ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_MCP]; /* Not connected ? */ openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL; /* Check this */ openpic_irqs[i][OPENPIC_OUTPUT_RESET] = ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_HRESET]; break; #endif /* defined(TARGET_PPC64) */ default: hw_error("Bus model not supported on mac99 machine\n"); exit(1); } } pic = g_new(qemu_irq, 64); dev = qdev_create(NULL, TYPE_OPENPIC); qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_RAVEN); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); pic_mem = s->mmio[0].memory; k = 0; for (i = 0; i < smp_cpus; i++) { for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { sysbus_connect_irq(s, k++, openpic_irqs[i][j]); } } for (i = 0; i < 64; i++) { pic[i] = qdev_get_gpio_in(dev, i); } if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) { /* 970 gets a U3 bus */ pci_bus = pci_pmac_u3_init(pic, get_system_memory(), get_system_io()); machine_arch = ARCH_MAC99_U3; } else { pci_bus = pci_pmac_init(pic, get_system_memory(), get_system_io()); machine_arch = ARCH_MAC99; } /* init basic PC hardware */ escc_mem = escc_init(0, pic[0x25], pic[0x24], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); memory_region_init_alias(escc_bar, NULL, "escc-bar", escc_mem, 0, memory_region_size(escc_mem)); macio = pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO); dev = DEVICE(macio); qdev_connect_gpio_out(dev, 0, pic[0x19]); /* CUDA */ qdev_connect_gpio_out(dev, 1, pic[0x0d]); /* IDE */ qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE DMA */ qdev_connect_gpio_out(dev, 3, pic[0x0e]); /* IDE */ qdev_connect_gpio_out(dev, 4, pic[0x03]); /* IDE DMA */ macio_init(macio, pic_mem, escc_bar); /* We only emulate 2 out of 3 IDE controllers for now */ ide_drive_get(hd, MAX_IDE_BUS); macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), "ide[0]")); macio_ide_init_drives(macio_ide, hd); macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), "ide[1]")); macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]); dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda")); adb_bus = qdev_get_child_bus(dev, "adb.0"); dev = qdev_create(adb_bus, TYPE_ADB_KEYBOARD); qdev_init_nofail(dev); dev = qdev_create(adb_bus, TYPE_ADB_MOUSE); qdev_init_nofail(dev); if (usb_enabled(machine_arch == ARCH_MAC99_U3)) { pci_create_simple(pci_bus, -1, "pci-ohci"); /* U3 needs to use USB for input because Linux doesn't support via-cuda on PPC64 */ if (machine_arch == ARCH_MAC99_U3) { usbdevice_create("keyboard"); usbdevice_create("mouse"); } } pci_vga_init(pci_bus); if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8) { graphic_depth = 15; } for (i = 0; i < nb_nics; i++) { pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL); } /* The NewWorld NVRAM is not located in the MacIO device */ dev = qdev_create(NULL, TYPE_MACIO_NVRAM); qdev_prop_set_uint32(dev, "size", 0x2000); qdev_prop_set_uint32(dev, "it_shift", 1); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xFFF04000); nvr = MACIO_NVRAM(dev); pmac_format_nvram_partition(nvr, 0x2000); /* No PCI init: the BIOS will do it */ fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, machine_arch); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); if (kernel_cmdline) { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base); pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline); } else { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0); } fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_base); fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ppc_boot_device); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_WIDTH, graphic_width); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled()); if (kvm_enabled()) { #ifdef CONFIG_KVM uint8_t *hypercall; fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq()); hypercall = g_malloc(16); kvmppc_get_hypercall(env, hypercall, 16); fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); #endif } else { fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, TBFREQ); } /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, CLOCKFREQ); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_BUSFREQ, BUSFREQ); qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); }
static void e1000e_pci_realize(PCIDevice *pci_dev, Error **errp) { static const uint16_t e1000e_pmrb_offset = 0x0C8; static const uint16_t e1000e_pcie_offset = 0x0E0; static const uint16_t e1000e_aer_offset = 0x100; static const uint16_t e1000e_dsn_offset = 0x140; E1000EState *s = E1000E(pci_dev); uint8_t *macaddr; trace_e1000e_cb_pci_realize(); pci_dev->config_write = e1000e_write_config; pci_dev->config[PCI_CACHE_LINE_SIZE] = 0x10; pci_dev->config[PCI_INTERRUPT_PIN] = 1; pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID, s->subsys_ven); pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID, s->subsys); s->subsys_ven_used = s->subsys_ven; s->subsys_used = s->subsys; /* Define IO/MMIO regions */ memory_region_init_io(&s->mmio, OBJECT(s), &mmio_ops, s, "e1000e-mmio", E1000E_MMIO_SIZE); pci_register_bar(pci_dev, E1000E_MMIO_IDX, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio); /* * We provide a dummy implementation for the flash BAR * for drivers that may theoretically probe for its presence. */ memory_region_init(&s->flash, OBJECT(s), "e1000e-flash", E1000E_FLASH_SIZE); pci_register_bar(pci_dev, E1000E_FLASH_IDX, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->flash); memory_region_init_io(&s->io, OBJECT(s), &io_ops, s, "e1000e-io", E1000E_IO_SIZE); pci_register_bar(pci_dev, E1000E_IO_IDX, PCI_BASE_ADDRESS_SPACE_IO, &s->io); memory_region_init(&s->msix, OBJECT(s), "e1000e-msix", E1000E_MSIX_SIZE); pci_register_bar(pci_dev, E1000E_MSIX_IDX, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->msix); /* Create networking backend */ qemu_macaddr_default_if_unset(&s->conf.macaddr); macaddr = s->conf.macaddr.a; e1000e_init_msix(s); if (pcie_endpoint_cap_v1_init(pci_dev, e1000e_pcie_offset) < 0) { hw_error("Failed to initialize PCIe capability"); } e1000e_init_msi(s); if (e1000e_add_pm_capability(pci_dev, e1000e_pmrb_offset, PCI_PM_CAP_DSI) < 0) { hw_error("Failed to initialize PM capability"); } if (pcie_aer_init(pci_dev, e1000e_aer_offset, PCI_ERR_SIZEOF) < 0) { hw_error("Failed to initialize AER capability"); } pcie_dev_ser_num_init(pci_dev, e1000e_dsn_offset, e1000e_gen_dsn(macaddr)); e1000e_init_net_peer(s, pci_dev, macaddr); /* Initialize core */ e1000e_core_realize(s); e1000e_core_pci_realize(&s->core, e1000e_eeprom_template, sizeof(e1000e_eeprom_template), macaddr); }