diff options
Diffstat (limited to 'hw')
| -rw-r--r-- | hw/alpha_dp264.c | 2 | ||||
| -rw-r--r-- | hw/alpha_sys.h | 3 | ||||
| -rw-r--r-- | hw/alpha_typhoon.c | 14 | ||||
| -rw-r--r-- | hw/an5206.c | 2 | ||||
| -rw-r--r-- | hw/apic.h | 2 | ||||
| -rw-r--r-- | hw/arm-misc.h | 8 | ||||
| -rw-r--r-- | hw/arm_boot.c | 10 | ||||
| -rw-r--r-- | hw/arm_pic.c | 4 | ||||
| -rw-r--r-- | hw/armv7m.c | 4 | ||||
| -rw-r--r-- | hw/axis_dev88.c | 2 | ||||
| -rw-r--r-- | hw/cris-boot.c | 6 | ||||
| -rw-r--r-- | hw/cris-boot.h | 2 | ||||
| -rw-r--r-- | hw/cris_pic_cpu.c | 4 | ||||
| -rw-r--r-- | hw/dummy_m68k.c | 2 | ||||
| -rw-r--r-- | hw/etraxfs.h | 2 | ||||
| -rw-r--r-- | hw/etraxfs_ser.c | 4 | ||||
| -rw-r--r-- | hw/exynos4210.h | 2 | ||||
| -rw-r--r-- | hw/grlib.h | 2 | ||||
| -rw-r--r-- | hw/highbank.c | 8 | ||||
| -rw-r--r-- | hw/integratorcp.c | 2 | ||||
| -rw-r--r-- | hw/kvm/apic.c | 2 | ||||
| -rw-r--r-- | hw/kvm/clock.c | 2 | ||||
| -rw-r--r-- | hw/kvmvapic.c | 26 | ||||
| -rw-r--r-- | hw/leon3.c | 10 | ||||
| -rw-r--r-- | hw/lm32_boards.c | 12 | ||||
| -rw-r--r-- | hw/mc146818rtc.c | 2 | ||||
| -rw-r--r-- | hw/mcf.h | 4 | ||||
| -rw-r--r-- | hw/mcf5206.c | 4 | ||||
| -rw-r--r-- | hw/mcf5208.c | 2 | ||||
| -rw-r--r-- | hw/mcf_intc.c | 4 | ||||
| -rw-r--r-- | hw/microblaze_boot.c | 10 | ||||
| -rw-r--r-- | hw/microblaze_boot.h | 4 | ||||
| -rw-r--r-- | hw/microblaze_pic_cpu.c | 4 | ||||
| -rw-r--r-- | hw/microblaze_pic_cpu.h | 2 | ||||
| -rw-r--r-- | hw/milkymist.c | 10 | ||||
| -rw-r--r-- | hw/mips_cpudevs.h | 4 | ||||
| -rw-r--r-- | hw/mips_fulong2e.c | 19 | ||||
| -rw-r--r-- | hw/mips_int.c | 6 | ||||
| -rw-r--r-- | hw/mips_jazz.c | 8 | ||||
| -rw-r--r-- | hw/mips_malta.c | 15 | ||||
| -rw-r--r-- | hw/mips_mipssim.c | 8 | ||||
| -rw-r--r-- | hw/mips_r4k.c | 8 | ||||
| -rw-r--r-- | hw/mips_timer.c | 20 | ||||
| -rw-r--r-- | hw/mpc8544_guts.c | 2 | ||||
| -rw-r--r-- | hw/musicpal.c | 2 | ||||
| -rw-r--r-- | hw/omap.h | 2 | ||||
| -rw-r--r-- | hw/omap1.c | 2 | ||||
| -rw-r--r-- | hw/omap2.c | 2 | ||||
| -rw-r--r-- | hw/pc.c | 22 | ||||
| -rw-r--r-- | hw/pc_piix.c | 4 | ||||
| -rw-r--r-- | hw/pci.c | 1 | ||||
| -rw-r--r-- | hw/petalogix_ml605_mmu.c | 4 | ||||
| -rw-r--r-- | hw/petalogix_s3adsp1800_mmu.c | 4 | ||||
| -rw-r--r-- | hw/ppc.c | 123 | ||||
| -rw-r--r-- | hw/ppc.h | 28 | ||||
| -rw-r--r-- | hw/ppc405.h | 8 | ||||
| -rw-r--r-- | hw/ppc405_uc.c | 50 | ||||
| -rw-r--r-- | hw/ppc440_bamboo.c | 8 | ||||
| -rw-r--r-- | hw/ppc4xx.h | 8 | ||||
| -rw-r--r-- | hw/ppc4xx_devs.c | 17 | ||||
| -rw-r--r-- | hw/ppc_booke.c | 20 | ||||
| -rw-r--r-- | hw/ppc_newworld.c | 14 | ||||
| -rw-r--r-- | hw/ppc_oldworld.c | 14 | ||||
| -rw-r--r-- | hw/ppc_prep.c | 16 | ||||
| -rw-r--r-- | hw/ppce500_mpc8544ds.c | 16 | ||||
| -rw-r--r-- | hw/ppce500_spin.c | 8 | ||||
| -rw-r--r-- | hw/pxa.h | 6 | ||||
| -rw-r--r-- | hw/pxa2xx.c | 2 | ||||
| -rw-r--r-- | hw/pxa2xx_gpio.c | 4 | ||||
| -rw-r--r-- | hw/pxa2xx_pic.c | 4 | ||||
| -rw-r--r-- | hw/qdev-properties.c | 4 | ||||
| -rw-r--r-- | hw/r2d.c | 8 | ||||
| -rw-r--r-- | hw/realview.c | 5 | ||||
| -rw-r--r-- | hw/s390-virtio-bus.c | 6 | ||||
| -rw-r--r-- | hw/s390-virtio.c | 16 | ||||
| -rw-r--r-- | hw/sh.h | 2 | ||||
| -rw-r--r-- | hw/shix.c | 2 | ||||
| -rw-r--r-- | hw/spapr.c | 17 | ||||
| -rw-r--r-- | hw/spapr.h | 4 | ||||
| -rw-r--r-- | hw/spapr_hcall.c | 42 | ||||
| -rw-r--r-- | hw/spapr_llan.c | 10 | ||||
| -rw-r--r-- | hw/spapr_rtas.c | 4 | ||||
| -rw-r--r-- | hw/spapr_vio.c | 12 | ||||
| -rw-r--r-- | hw/spapr_vty.c | 4 | ||||
| -rw-r--r-- | hw/strongarm.h | 2 | ||||
| -rw-r--r-- | hw/sun4m.c | 16 | ||||
| -rw-r--r-- | hw/sun4u.c | 26 | ||||
| -rw-r--r-- | hw/usb-ohci.h | 9 | ||||
| -rw-r--r-- | hw/usb-uhci.h | 10 | ||||
| -rw-r--r-- | hw/usb.h | 1 | ||||
| -rw-r--r-- | hw/usb/bus.c (renamed from hw/usb-bus.c) | 6 | ||||
| -rw-r--r-- | hw/usb/core.c (renamed from hw/usb.c) | 39 | ||||
| -rw-r--r-- | hw/usb/desc.c (renamed from hw/usb-desc.c) | 4 | ||||
| -rw-r--r-- | hw/usb/desc.h (renamed from hw/usb-desc.h) | 0 | ||||
| -rw-r--r-- | hw/usb/dev-audio.c (renamed from hw/usb-audio.c) | 8 | ||||
| -rw-r--r-- | hw/usb/dev-bluetooth.c (renamed from hw/usb-bt.c) | 6 | ||||
| -rw-r--r-- | hw/usb/dev-hid.c (renamed from hw/usb-hid.c) | 8 | ||||
| -rw-r--r-- | hw/usb/dev-hub.c (renamed from hw/usb-hub.c) | 4 | ||||
| -rw-r--r-- | hw/usb/dev-network.c (renamed from hw/usb-net.c) | 4 | ||||
| -rw-r--r-- | hw/usb/dev-serial.c (renamed from hw/usb-serial.c) | 4 | ||||
| -rw-r--r-- | hw/usb/dev-smartcard-reader.c (renamed from hw/usb-ccid.c) | 4 | ||||
| -rw-r--r-- | hw/usb/dev-storage.c (renamed from hw/usb-msd.c) | 12 | ||||
| -rw-r--r-- | hw/usb/dev-wacom.c (renamed from hw/usb-wacom.c) | 6 | ||||
| -rw-r--r-- | hw/usb/hcd-ehci.c (renamed from hw/usb-ehci.c) | 12 | ||||
| -rw-r--r-- | hw/usb/hcd-musb.c (renamed from hw/usb-musb.c) | 6 | ||||
| -rw-r--r-- | hw/usb/hcd-ohci.c (renamed from hw/usb-ohci.c) | 33 | ||||
| -rw-r--r-- | hw/usb/hcd-uhci.c (renamed from hw/usb-uhci.c) | 156 | ||||
| -rw-r--r-- | hw/usb/hcd-xhci.c (renamed from hw/usb-xhci.c) | 10 | ||||
| -rw-r--r-- | hw/usb/host-bsd.c | 647 | ||||
| -rw-r--r-- | hw/usb/host-linux.c | 1913 | ||||
| -rw-r--r-- | hw/usb/host-stub.c | 52 | ||||
| -rw-r--r-- | hw/usb/libhw.c (renamed from hw/usb-libhw.c) | 2 | ||||
| -rw-r--r-- | hw/usb/redirect.c | 1485 | ||||
| -rw-r--r-- | hw/versatilepb.c | 5 | ||||
| -rw-r--r-- | hw/vexpress.c | 4 | ||||
| -rw-r--r-- | hw/vga.c | 2 | ||||
| -rw-r--r-- | hw/virtex_ml507.c | 12 | ||||
| -rw-r--r-- | hw/vmport.c | 12 | ||||
| -rw-r--r-- | hw/xen_machine_pv.c | 2 | ||||
| -rw-r--r-- | hw/xics.c | 10 | ||||
| -rw-r--r-- | hw/xilinx_zynq.c | 2 | ||||
| -rw-r--r-- | hw/xtensa_lx60.c | 10 | ||||
| -rw-r--r-- | hw/xtensa_pic.c | 16 | ||||
| -rw-r--r-- | hw/xtensa_sim.c | 4 |
124 files changed, 4721 insertions, 641 deletions
diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c index ea0fd95f84..9eb939f383 100644 --- a/hw/alpha_dp264.c +++ b/hw/alpha_dp264.c @@ -49,7 +49,7 @@ static void clipper_init(ram_addr_t ram_size, const char *initrd_filename, const char *cpu_model) { - CPUState *cpus[4]; + CPUAlphaState *cpus[4]; PCIBus *pci_bus; ISABus *isa_bus; qemu_irq rtc_irq; diff --git a/hw/alpha_sys.h b/hw/alpha_sys.h index d54b18f8ed..de40f8b613 100644 --- a/hw/alpha_sys.h +++ b/hw/alpha_sys.h @@ -8,11 +8,10 @@ #include "ide.h" #include "net.h" #include "pc.h" -#include "usb-ohci.h" #include "irq.h" -PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, CPUState *[4], +PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, CPUAlphaState *[4], pci_map_irq_fn); /* alpha_pci.c. */ diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c index b539416589..872e1122e8 100644 --- a/hw/alpha_typhoon.c +++ b/hw/alpha_typhoon.c @@ -21,7 +21,7 @@ typedef struct TyphoonCchip { uint64_t drir; uint64_t dim[4]; uint32_t iic[4]; - CPUState *cpu[4]; + CPUAlphaState *cpu[4]; } TyphoonCchip; typedef struct TyphoonWindow { @@ -52,7 +52,7 @@ typedef struct TyphoonState { } TyphoonState; /* Called when one of DRIR or DIM changes. */ -static void cpu_irq_change(CPUState *env, uint64_t req) +static void cpu_irq_change(CPUAlphaState *env, uint64_t req) { /* If there are any non-masked interrupts, tell the cpu. */ if (env) { @@ -66,7 +66,7 @@ static void cpu_irq_change(CPUState *env, uint64_t req) static uint64_t cchip_read(void *opaque, target_phys_addr_t addr, unsigned size) { - CPUState *env = cpu_single_env; + CPUAlphaState *env = cpu_single_env; TyphoonState *s = opaque; uint64_t ret = 0; @@ -347,7 +347,7 @@ static void cchip_write(void *opaque, target_phys_addr_t addr, if ((newval ^ oldval) & 0xff0) { int i; for (i = 0; i < 4; ++i) { - CPUState *env = s->cchip.cpu[i]; + CPUAlphaState *env = s->cchip.cpu[i]; if (env) { /* IPI can be either cleared or set by the write. */ if (newval & (1 << (i + 8))) { @@ -655,7 +655,7 @@ static void typhoon_set_timer_irq(void *opaque, int irq, int level) /* Deliver the interrupt to each CPU, considering each CPU's IIC. */ for (i = 0; i < 4; ++i) { - CPUState *env = s->cchip.cpu[i]; + CPUAlphaState *env = s->cchip.cpu[i]; if (env) { uint32_t iic = s->cchip.iic[i]; @@ -693,7 +693,7 @@ static void typhoon_alarm_timer(void *opaque) PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, qemu_irq *p_rtc_irq, - CPUState *cpus[4], pci_map_irq_fn sys_map_irq) + CPUAlphaState *cpus[4], pci_map_irq_fn sys_map_irq) { const uint64_t MB = 1024 * 1024; const uint64_t GB = 1024 * MB; @@ -713,7 +713,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, /* Remember the CPUs so that we can deliver interrupts to them. */ for (i = 0; i < 4; i++) { - CPUState *env = cpus[i]; + CPUAlphaState *env = cpus[i]; s->cchip.cpu[i] = env; if (env) { env->alarm_timer = qemu_new_timer_ns(rtc_clock, diff --git a/hw/an5206.c b/hw/an5206.c index d57306d3ad..25407c0f50 100644 --- a/hw/an5206.c +++ b/hw/an5206.c @@ -24,7 +24,7 @@ static void an5206_init(ram_addr_t ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - CPUState *env; + CPUM68KState *env; int kernel_size; uint64_t elf_entry; target_phys_addr_t entry; diff --git a/hw/apic.h b/hw/apic.h index d6d6d440ee..62179cebee 100644 --- a/hw/apic.h +++ b/hw/apic.h @@ -22,7 +22,7 @@ void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip, TPRAccess access); /* pc.c */ -int cpu_is_bsp(CPUState *env); +int cpu_is_bsp(CPUX86State *env); DeviceState *cpu_get_current_apic(void); #endif diff --git a/hw/arm-misc.h b/hw/arm-misc.h index 734bd82428..2f46e214cf 100644 --- a/hw/arm-misc.h +++ b/hw/arm-misc.h @@ -16,7 +16,7 @@ /* The CPU is also modeled as an interrupt controller. */ #define ARM_PIC_CPU_IRQ 0 #define ARM_PIC_CPU_FIQ 1 -qemu_irq *arm_pic_init_cpu(CPUState *env); +qemu_irq *arm_pic_init_cpu(CPUARMState *env); /* armv7m.c */ qemu_irq *armv7m_init(MemoryRegion *address_space_mem, @@ -50,16 +50,16 @@ struct arm_boot_info { * perform any necessary CPU reset handling and set the PC for thei * secondary CPUs to point at this boot blob. */ - void (*write_secondary_boot)(CPUState *env, + void (*write_secondary_boot)(CPUARMState *env, const struct arm_boot_info *info); - void (*secondary_cpu_reset_hook)(CPUState *env, + void (*secondary_cpu_reset_hook)(CPUARMState *env, const struct arm_boot_info *info); /* Used internally by arm_boot.c */ int is_linux; target_phys_addr_t initrd_size; target_phys_addr_t entry; }; -void arm_load_kernel(CPUState *env, struct arm_boot_info *info); +void arm_load_kernel(CPUARMState *env, struct arm_boot_info *info); /* Multiplication factor to convert from system clock ticks to qemu timer ticks. */ diff --git a/hw/arm_boot.c b/hw/arm_boot.c index fc669100c5..7447f5c169 100644 --- a/hw/arm_boot.c +++ b/hw/arm_boot.c @@ -59,7 +59,7 @@ static uint32_t smpboot[] = { 0 /* bootreg: Boot register address is held here */ }; -static void default_write_secondary(CPUState *env, +static void default_write_secondary(CPUARMState *env, const struct arm_boot_info *info) { int n; @@ -72,7 +72,7 @@ static void default_write_secondary(CPUState *env, info->smp_loader_start); } -static void default_reset_secondary(CPUState *env, +static void default_reset_secondary(CPUARMState *env, const struct arm_boot_info *info) { stl_phys_notdirty(info->smp_bootreg_addr, 0); @@ -274,10 +274,10 @@ static int load_dtb(target_phys_addr_t addr, const struct arm_boot_info *binfo) static void do_cpu_reset(void *opaque) { - CPUState *env = opaque; + CPUARMState *env = opaque; const struct arm_boot_info *info = env->boot_info; - cpu_reset(env); + cpu_state_reset(env); if (info) { if (!info->is_linux) { /* Jump to the entry point. */ @@ -300,7 +300,7 @@ static void do_cpu_reset(void *opaque) } } -void arm_load_kernel(CPUState *env, struct arm_boot_info *info) +void arm_load_kernel(CPUARMState *env, struct arm_boot_info *info) { int kernel_size; int initrd_size; diff --git a/hw/arm_pic.c b/hw/arm_pic.c index a2e8a73301..109496528c 100644 --- a/hw/arm_pic.c +++ b/hw/arm_pic.c @@ -13,7 +13,7 @@ /* Input 0 is IRQ and input 1 is FIQ. */ static void arm_pic_cpu_handler(void *opaque, int irq, int level) { - CPUState *env = (CPUState *)opaque; + CPUARMState *env = (CPUARMState *)opaque; switch (irq) { case ARM_PIC_CPU_IRQ: if (level) @@ -32,7 +32,7 @@ static void arm_pic_cpu_handler(void *opaque, int irq, int level) } } -qemu_irq *arm_pic_init_cpu(CPUState *env) +qemu_irq *arm_pic_init_cpu(CPUARMState *env) { return qemu_allocate_irqs(arm_pic_cpu_handler, env, 2); } diff --git a/hw/armv7m.c b/hw/armv7m.c index 6b805798e6..4aac076e48 100644 --- a/hw/armv7m.c +++ b/hw/armv7m.c @@ -149,7 +149,7 @@ static void armv7m_bitband_init(void) static void armv7m_reset(void *opaque) { - cpu_reset((CPUState *)opaque); + cpu_state_reset((CPUARMState *)opaque); } /* Init CPU and memory for a v7-M based board. @@ -160,7 +160,7 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem, int flash_size, int sram_size, const char *kernel_filename, const char *cpu_model) { - CPUState *env; + CPUARMState *env; DeviceState *nvic; /* FIXME: make this local state. */ static qemu_irq pic[64]; diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c index c9301fda1d..2304e3533a 100644 --- a/hw/axis_dev88.c +++ b/hw/axis_dev88.c @@ -247,7 +247,7 @@ void axisdev88_init (ram_addr_t ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - CPUState *env; + CPUCRISState *env; DeviceState *dev; SysBusDevice *s; DriveInfo *nand; diff --git a/hw/cris-boot.c b/hw/cris-boot.c index 37894f8b53..ca6c52fa8e 100644 --- a/hw/cris-boot.c +++ b/hw/cris-boot.c @@ -29,12 +29,12 @@ static void main_cpu_reset(void *opaque) { - CPUState *env = opaque; + CPUCRISState *env = opaque; struct cris_load_info *li; li = env->load_info; - cpu_reset(env); + cpu_state_reset(env); if (!li) { /* nothing more to do. */ @@ -60,7 +60,7 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr) return addr - 0x80000000LL; } -void cris_load_image(CPUState *env, struct cris_load_info *li) +void cris_load_image(CPUCRISState *env, struct cris_load_info *li) { uint64_t entry, high; int kcmdline_len; diff --git a/hw/cris-boot.h b/hw/cris-boot.h index e9caf8dee8..ecb9779e49 100644 --- a/hw/cris-boot.h +++ b/hw/cris-boot.h @@ -8,4 +8,4 @@ struct cris_load_info target_phys_addr_t entry; }; -void cris_load_image(CPUState *env, struct cris_load_info *li); +void cris_load_image(CPUCRISState *env, struct cris_load_info *li); diff --git a/hw/cris_pic_cpu.c b/hw/cris_pic_cpu.c index 06ae484950..3da0e86536 100644 --- a/hw/cris_pic_cpu.c +++ b/hw/cris_pic_cpu.c @@ -30,7 +30,7 @@ static void cris_pic_cpu_handler(void *opaque, int irq, int level) { - CPUState *env = (CPUState *)opaque; + CPUCRISState *env = (CPUCRISState *)opaque; int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD; if (level) @@ -39,7 +39,7 @@ static void cris_pic_cpu_handler(void *opaque, int irq, int level) cpu_reset_interrupt(env, type); } -qemu_irq *cris_pic_init_cpu(CPUState *env) +qemu_irq *cris_pic_init_cpu(CPUCRISState *env) { return qemu_allocate_irqs(cris_pic_cpu_handler, env, 2); } diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c index e3c574008f..7cc7a99bfb 100644 --- a/hw/dummy_m68k.c +++ b/hw/dummy_m68k.c @@ -21,7 +21,7 @@ static void dummy_m68k_init(ram_addr_t ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - CPUState *env; + CPUM68KState *env; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); int kernel_size; diff --git a/hw/etraxfs.h b/hw/etraxfs.h index 24e8fd880b..c62f94b7b7 100644 --- a/hw/etraxfs.h +++ b/hw/etraxfs.h @@ -25,7 +25,7 @@ #include "net.h" #include "etraxfs_dma.h" -qemu_irq *cris_pic_init_cpu(CPUState *env); +qemu_irq *cris_pic_init_cpu(CPUCRISState *env); /* Instantiate an ETRAXFS Ethernet MAC. */ static inline DeviceState * diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c index cecd819584..5f16b17835 100644 --- a/hw/etraxfs_ser.c +++ b/hw/etraxfs_ser.c @@ -78,7 +78,7 @@ static uint64_t ser_read(void *opaque, target_phys_addr_t addr, unsigned int size) { struct etrax_serial *s = opaque; - D(CPUState *env = s->env); + D(CPUCRISState *env = s->env); uint32_t r = 0; addr >>= 2; @@ -116,7 +116,7 @@ ser_write(void *opaque, target_phys_addr_t addr, struct etrax_serial *s = opaque; uint32_t value = val64; unsigned char ch = val64; - D(CPUState *env = s->env); + D(CPUCRISState *env = s->env); D(qemu_log("%s " TARGET_FMT_plx "=%x\n", __func__, addr, value)); addr >>= 2; diff --git a/hw/exynos4210.h b/hw/exynos4210.h index e7522f851a..c112e03bfb 100644 --- a/hw/exynos4210.h +++ b/hw/exynos4210.h @@ -83,7 +83,7 @@ typedef struct Exynos4210Irq { } Exynos4210Irq; typedef struct Exynos4210State { - CPUState * env[EXYNOS4210_NCPUS]; + CPUARMState * env[EXYNOS4210_NCPUS]; Exynos4210Irq irqs; qemu_irq *irq_table; diff --git a/hw/grlib.h b/hw/grlib.h index fdf4b1190a..e1c41378d4 100644 --- a/hw/grlib.h +++ b/hw/grlib.h @@ -42,7 +42,7 @@ void grlib_irqmp_ack(DeviceState *dev, int intno); static inline DeviceState *grlib_irqmp_create(target_phys_addr_t base, - CPUState *env, + CPUSPARCState *env, qemu_irq **cpu_irqs, uint32_t nr_irqs, set_pil_in_fn set_pil_in) diff --git a/hw/highbank.c b/hw/highbank.c index 489c00e5b9..906eed5a47 100644 --- a/hw/highbank.c +++ b/hw/highbank.c @@ -37,12 +37,12 @@ /* Board init. */ static void highbank_cpu_reset(void *opaque) { - CPUState *env = opaque; + CPUARMState *env = opaque; env->cp15.c15_config_base_address = GIC_BASE_ADDR; } -static void hb_write_secondary(CPUState *env, const struct arm_boot_info *info) +static void hb_write_secondary(CPUARMState *env, const struct arm_boot_info *info) { int n; uint32_t smpboot[] = { @@ -66,7 +66,7 @@ static void hb_write_secondary(CPUState *env, const struct arm_boot_info *info) rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR); } -static void hb_reset_secondary(CPUState *env, const struct arm_boot_info *info) +static void hb_reset_secondary(CPUARMState *env, const struct arm_boot_info *info) { switch (info->nb_cpus) { case 4: @@ -196,7 +196,7 @@ static void highbank_init(ram_addr_t ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - CPUState *env = NULL; + CPUARMState *env = NULL; DeviceState *dev; SysBusDevice *busdev; qemu_irq *irqp; diff --git a/hw/integratorcp.c b/hw/integratorcp.c index 5b06c81c9b..9bdb9e62d6 100644 --- a/hw/integratorcp.c +++ b/hw/integratorcp.c @@ -443,7 +443,7 @@ static void integratorcp_init(ram_addr_t ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - CPUState *env; + CPUARMState *env; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *ram_alias = g_new(MemoryRegion, 1); diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c index 9ca68f81aa..ffe7a521b7 100644 --- a/hw/kvm/apic.c +++ b/hw/kvm/apic.c @@ -124,7 +124,7 @@ static void kvm_apic_vapic_base_update(APICCommonState *s) static void do_inject_external_nmi(void *data) { APICCommonState *s = data; - CPUState *env = s->cpu_env; + CPUX86State *env = s->cpu_env; uint32_t lvt; int ret; diff --git a/hw/kvm/clock.c b/hw/kvm/clock.c index 2157340326..446bd62176 100644 --- a/hw/kvm/clock.c +++ b/hw/kvm/clock.c @@ -121,9 +121,7 @@ void kvmclock_create(void) static void kvmclock_register_types(void) { - if (kvm_enabled()) { type_register_static(&kvmclock_info); - } } type_init(kvmclock_register_types) diff --git a/hw/kvmvapic.c b/hw/kvmvapic.c index 36ccfbcdbd..5d83625f4a 100644 --- a/hw/kvmvapic.c +++ b/hw/kvmvapic.c @@ -142,7 +142,7 @@ static void update_guest_rom_state(VAPICROMState *s) write_guest_rom_state(s); } -static int find_real_tpr_addr(VAPICROMState *s, CPUState *env) +static int find_real_tpr_addr(VAPICROMState *s, CPUX86State *env) { target_phys_addr_t paddr; target_ulong addr; @@ -185,7 +185,7 @@ static bool opcode_matches(uint8_t *opcode, const TPRInstruction *instr) modrm_reg(opcode[1]) == instr->modrm_reg); } -static int evaluate_tpr_instruction(VAPICROMState *s, CPUState *env, +static int evaluate_tpr_instruction(VAPICROMState *s, CPUX86State *env, target_ulong *pip, TPRAccess access) { const TPRInstruction *instr; @@ -267,7 +267,7 @@ instruction_ok: return 0; } -static int update_rom_mapping(VAPICROMState *s, CPUState *env, target_ulong ip) +static int update_rom_mapping(VAPICROMState *s, CPUX86State *env, target_ulong ip) { target_phys_addr_t paddr; uint32_t rom_state_vaddr; @@ -330,7 +330,7 @@ static int update_rom_mapping(VAPICROMState *s, CPUState *env, target_ulong ip) * cannot be accessed or is considered invalid. This also ensures that we are * not patching the wrong guest. */ -static int get_kpcr_number(CPUState *env) +static int get_kpcr_number(CPUX86State *env) { struct kpcr { uint8_t fill1[0x1c]; @@ -347,7 +347,7 @@ static int get_kpcr_number(CPUState *env) return kpcr.number; } -static int vapic_enable(VAPICROMState *s, CPUState *env) +static int vapic_enable(VAPICROMState *s, CPUX86State *env) { int cpu_number = get_kpcr_number(env); target_phys_addr_t vapic_paddr; @@ -367,12 +367,12 @@ static int vapic_enable(VAPICROMState *s, CPUState *env) return 0; } -static void patch_byte(CPUState *env, target_ulong addr, uint8_t byte) +static void patch_byte(CPUX86State *env, target_ulong addr, uint8_t byte) { cpu_memory_rw_debug(env, addr, &byte, 1, 1); } -static void patch_call(VAPICROMState *s, CPUState *env, target_ulong ip, +static void patch_call(VAPICROMState *s, CPUX86State *env, target_ulong ip, uint32_t target) { uint32_t offset; @@ -382,7 +382,7 @@ static void patch_call(VAPICROMState *s, CPUState *env, target_ulong ip, cpu_memory_rw_debug(env, ip + 1, (void *)&offset, sizeof(offset), 1); } -static void patch_instruction(VAPICROMState *s, CPUState *env, target_ulong ip) +static void patch_instruction(VAPICROMState *s, CPUX86State *env, target_ulong ip) { target_phys_addr_t paddr; VAPICHandlers *handlers; @@ -439,7 +439,7 @@ void vapic_report_tpr_access(DeviceState *dev, void *cpu, target_ulong ip, TPRAccess access) { VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev); - CPUState *env = cpu; + CPUX86State *env = cpu; cpu_synchronize_state(env); @@ -475,7 +475,7 @@ static void vapic_enable_tpr_reporting(bool enable) VAPICEnableTPRReporting info = { .enable = enable, }; - CPUState *env; + CPUX86State *env; for (env = first_cpu; env != NULL; env = env->next_cpu) { info.apic = env->apic_state; @@ -578,8 +578,10 @@ static void vapic_map_rom_writable(VAPICROMState *s) rom_size = ram[rom_paddr + 2] * ROM_BLOCK_SIZE; s->rom_size = rom_size; - /* We need to round up to avoid creating subpages + /* We need to round to avoid creating subpages * from which we cannot run code. */ + rom_size += rom_paddr & ~TARGET_PAGE_MASK; + rom_paddr &= TARGET_PAGE_MASK; rom_size = TARGET_PAGE_ALIGN(rom_size); memory_region_init_alias(&s->rom, "kvmvapic-rom", section.mr, rom_paddr, @@ -604,7 +606,7 @@ static int vapic_prepare(VAPICROMState *s) static void vapic_write(void *opaque, target_phys_addr_t addr, uint64_t data, unsigned int size) { - CPUState *env = cpu_single_env; + CPUX86State *env = cpu_single_env; target_phys_addr_t rom_paddr; VAPICROMState *s = opaque; diff --git a/hw/leon3.c b/hw/leon3.c index 71d79a65a7..0a5ff165a1 100644 --- a/hw/leon3.c +++ b/hw/leon3.c @@ -42,16 +42,16 @@ #define MAX_PILS 16 typedef struct ResetData { - CPUState *env; + CPUSPARCState *env; uint32_t entry; /* save kernel entry in case of reset */ } ResetData; static void main_cpu_reset(void *opaque) { ResetData *s = (ResetData *)opaque; - CPUState *env = s->env; + CPUSPARCState *env = s->env; - cpu_reset(env); + cpu_state_reset(env); env->halted = 0; env->pc = s->entry; @@ -65,7 +65,7 @@ void leon3_irq_ack(void *irq_manager, int intno) static void leon3_set_pil_in(void *opaque, uint32_t pil_in) { - CPUState *env = (CPUState *)opaque; + CPUSPARCState *env = (CPUSPARCState *)opaque; assert(env != NULL); @@ -101,7 +101,7 @@ static void leon3_generic_hw_init(ram_addr_t ram_size, const char *initrd_filename, const char *cpu_model) { - CPUState *env; + CPUSPARCState *env; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *prom = g_new(MemoryRegion, 1); diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c index 3cdf120a14..4dd4f0ab90 100644 --- a/hw/lm32_boards.c +++ b/hw/lm32_boards.c @@ -31,7 +31,7 @@ #include "exec-memory.h" typedef struct { - CPUState *env; + CPULM32State *env; target_phys_addr_t bootstrap_pc; target_phys_addr_t flash_base; target_phys_addr_t hwsetup_base; @@ -42,7 +42,7 @@ typedef struct { static void cpu_irq_handler(void *opaque, int irq, int level) { - CPUState *env = opaque; + CPULM32State *env = opaque; if (level) { cpu_interrupt(env, CPU_INTERRUPT_HARD); @@ -54,9 +54,9 @@ static void cpu_irq_handler(void *opaque, int irq, int level) static void main_cpu_reset(void *opaque) { ResetInfo *reset_info = opaque; - CPUState *env = reset_info->env; + CPULM32State *env = reset_info->env; - cpu_reset(env); + cpu_state_reset(env); /* init defaults */ env->pc = (uint32_t)reset_info->bootstrap_pc; @@ -75,7 +75,7 @@ static void lm32_evr_init(ram_addr_t ram_size_not_used, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - CPUState *env; + CPULM32State *env; DriveInfo *dinfo; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *phys_ram = g_new(MemoryRegion, 1); @@ -163,7 +163,7 @@ static void lm32_uclinux_init(ram_addr_t ram_size_not_used, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - CPUState *env; + CPULM32State *env; DriveInfo *dinfo; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *phys_ram = g_new(MemoryRegion, 1); diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index 8b5cf8c81f..2b59c36ee6 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -24,8 +24,6 @@ #include "hw.h" #include "qemu-timer.h" #include "sysemu.h" -#include "pc.h" -#include "isa.h" #include "mc146818rtc.h" #ifdef TARGET_I386 diff --git a/hw/mcf.h b/hw/mcf.h index baa790b0c5..19a8b54778 100644 --- a/hw/mcf.h +++ b/hw/mcf.h @@ -17,7 +17,7 @@ void mcf_uart_mm_init(struct MemoryRegion *sysmem, /* mcf_intc.c */ qemu_irq *mcf_intc_init(struct MemoryRegion *sysmem, target_phys_addr_t base, - CPUState *env); + CPUM68KState *env); /* mcf_fec.c */ void mcf_fec_init(struct MemoryRegion *sysmem, NICInfo *nd, @@ -25,6 +25,6 @@ void mcf_fec_init(struct MemoryRegion *sysmem, NICInfo *nd, /* mcf5206.c */ qemu_irq *mcf5206_init(struct MemoryRegion *sysmem, - uint32_t base, CPUState *env); + uint32_t base, CPUM68KState *env); #endif diff --git a/hw/mcf5206.c b/hw/mcf5206.c index 5110d833af..539b391338 100644 --- a/hw/mcf5206.c +++ b/hw/mcf5206.c @@ -145,7 +145,7 @@ static m5206_timer_state *m5206_timer_init(qemu_irq irq) /* System Integration Module. */ typedef struct { - CPUState *env; + CPUM68KState *env; MemoryRegion iomem; m5206_timer_state *timer[2]; void *uart[2]; @@ -525,7 +525,7 @@ static const MemoryRegionOps m5206_mbar_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -qemu_irq *mcf5206_init(MemoryRegion *sysmem, uint32_t base, CPUState *env) +qemu_irq *mcf5206_init(MemoryRegion *sysmem, uint32_t base, CPUM68KState *env) { m5206_mbar_state *s; qemu_irq *pic; diff --git a/hw/mcf5208.c b/hw/mcf5208.c index aa11a755cc..d3ebe8d9ad 100644 --- a/hw/mcf5208.c +++ b/hw/mcf5208.c @@ -192,7 +192,7 @@ static void mcf5208evb_init(ram_addr_t ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - CPUState *env; + CPUM68KState *env; int kernel_size; uint64_t elf_entry; target_phys_addr_t entry; diff --git a/hw/mcf_intc.c b/hw/mcf_intc.c index 0b498dd3ac..cc1a5f3763 100644 --- a/hw/mcf_intc.c +++ b/hw/mcf_intc.c @@ -16,7 +16,7 @@ typedef struct { uint64_t ifr; uint64_t enabled; uint8_t icr[64]; - CPUState *env; + CPUM68KState *env; int active_vector; } mcf_intc_state; @@ -139,7 +139,7 @@ static const MemoryRegionOps mcf_intc_ops = { qemu_irq *mcf_intc_init(MemoryRegion *sysmem, target_phys_addr_t base, - CPUState *env) + CPUM68KState *env) { mcf_intc_state *s; diff --git a/hw/microblaze_boot.c b/hw/microblaze_boot.c index b2f96df344..b4fbb10dd0 100644 --- a/hw/microblaze_boot.c +++ b/hw/microblaze_boot.c @@ -35,7 +35,7 @@ static struct { - void (*machine_cpu_reset)(CPUState *); + void (*machine_cpu_reset)(CPUMBState *); uint32_t bootstrap_pc; uint32_t cmdline; uint32_t fdt; @@ -43,9 +43,9 @@ static struct static void main_cpu_reset(void *opaque) { - CPUState *env = opaque; + CPUMBState *env = opaque; - cpu_reset(env); + cpu_state_reset(env); env->regs[5] = boot_info.cmdline; env->regs[7] = boot_info.fdt; env->sregs[SR_PC] = boot_info.bootstrap_pc; @@ -99,9 +99,9 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr) return addr - 0x30000000LL; } -void microblaze_load_kernel(CPUState *env, target_phys_addr_t ddr_base, +void microblaze_load_kernel(CPUMBState *env, target_phys_addr_t ddr_base, uint32_t ramsize, const char *dtb_filename, - void (*machine_cpu_reset)(CPUState *)) + void (*machine_cpu_reset)(CPUMBState *)) { QemuOpts *machine_opts; diff --git a/hw/microblaze_boot.h b/hw/microblaze_boot.h index 69d4ac635b..bf9d136f12 100644 --- a/hw/microblaze_boot.h +++ b/hw/microblaze_boot.h @@ -3,8 +3,8 @@ #include "hw.h" -void microblaze_load_kernel(CPUState *env, target_phys_addr_t ddr_base, +void microblaze_load_kernel(CPUMBState *env, target_phys_addr_t ddr_base, uint32_t ramsize, const char *dtb_filename, - void (*machine_cpu_reset)(CPUState *)); + void (*machine_cpu_reset)(CPUMBState *)); #endif /* __MICROBLAZE_BOOT __ */ diff --git a/hw/microblaze_pic_cpu.c b/hw/microblaze_pic_cpu.c index 8b5623ce28..ff36a526fc 100644 --- a/hw/microblaze_pic_cpu.c +++ b/hw/microblaze_pic_cpu.c @@ -29,7 +29,7 @@ static void microblaze_pic_cpu_handler(void *opaque, int irq, int level) { - CPUState *env = (CPUState *)opaque; + CPUMBState *env = (CPUMBState *)opaque; int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD; if (level) @@ -38,7 +38,7 @@ static void microblaze_pic_cpu_handler(void *opaque, int irq, int level) cpu_reset_interrupt(env, type); } -qemu_irq *microblaze_pic_init_cpu(CPUState *env) +qemu_irq *microblaze_pic_init_cpu(CPUMBState *env) { return qemu_allocate_irqs(microblaze_pic_cpu_handler, env, 2); } diff --git a/hw/microblaze_pic_cpu.h b/hw/microblaze_pic_cpu.h index 4c76275976..43090a48ef 100644 --- a/hw/microblaze_pic_cpu.h +++ b/hw/microblaze_pic_cpu.h @@ -3,6 +3,6 @@ #include "qemu-common.h" -qemu_irq *microblaze_pic_init_cpu(CPUState *env); +qemu_irq *microblaze_pic_init_cpu(CPUMBState *env); #endif /* MICROBLAZE_PIC_CPU_H */ diff --git a/hw/milkymist.c b/hw/milkymist.c index eaef0c24c3..8bb6a97b22 100644 --- a/hw/milkymist.c +++ b/hw/milkymist.c @@ -37,7 +37,7 @@ #define KERNEL_LOAD_ADDR 0x40000000 typedef struct { - CPUState *env; + CPULM32State *env; target_phys_addr_t bootstrap_pc; target_phys_addr_t flash_base; target_phys_addr_t initrd_base; @@ -47,7 +47,7 @@ typedef struct { static void cpu_irq_handler(void *opaque, int irq, int level) { - CPUState *env = opaque; + CPULM32State *env = opaque; if (level) { cpu_interrupt(env, CPU_INTERRUPT_HARD); @@ -59,9 +59,9 @@ static void cpu_irq_handler(void *opaque, int irq, int level) static void main_cpu_reset(void *opaque) { ResetInfo *reset_info = opaque; - CPUState *env = reset_info->env; + CPULM32State *env = reset_info->env; - cpu_reset(env); + cpu_state_reset(env); /* init defaults */ env->pc = reset_info->bootstrap_pc; @@ -79,7 +79,7 @@ milkymist_init(ram_addr_t ram_size_not_used, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - CPUState *env; + CPULM32State *env; int kernel_size; DriveInfo *dinfo; MemoryRegion *address_space_mem = get_system_memory(); diff --git a/hw/mips_cpudevs.h b/hw/mips_cpudevs.h index db82b4105c..6bea24bf10 100644 --- a/hw/mips_cpudevs.h +++ b/hw/mips_cpudevs.h @@ -7,9 +7,9 @@ uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr); uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr); /* mips_int.c */ -void cpu_mips_irq_init_cpu(CPUState *env); +void cpu_mips_irq_init_cpu(CPUMIPSState *env); /* mips_timer.c */ -void cpu_mips_clock_init(CPUState *); +void cpu_mips_clock_init(CPUMIPSState *); #endif diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c index e3ba9dd42d..37dc711e08 100644 --- a/hw/mips_fulong2e.c +++ b/hw/mips_fulong2e.c @@ -29,7 +29,6 @@ #include "mips.h" #include "mips_cpudevs.h" #include "pci.h" -#include "usb-uhci.h" #include "qemu-char.h" #include "sysemu.h" #include "audio/audio.h" @@ -103,7 +102,7 @@ static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index, va_end(ap); } -static int64_t load_kernel (CPUState *env) +static int64_t load_kernel (CPUMIPSState *env) { int64_t kernel_entry, kernel_low, kernel_high; int index = 0; @@ -169,7 +168,7 @@ static int64_t load_kernel (CPUState *env) return kernel_entry; } -static void write_bootloader (CPUState *env, uint8_t *base, int64_t kernel_addr) +static void write_bootloader (CPUMIPSState *env, uint8_t *base, int64_t kernel_addr) { uint32_t *p; @@ -199,9 +198,9 @@ static void write_bootloader (CPUState *env, uint8_t *base, int64_t kernel_addr) static void main_cpu_reset(void *opaque) { - CPUState *env = opaque; + CPUMIPSState *env = opaque; - cpu_reset(env); + cpu_state_reset(env); /* TODO: 2E reset stuff */ if (loaderparams.kernel_filename) { env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL)); @@ -249,7 +248,7 @@ static void network_init (void) static void cpu_request_exit(void *opaque, int irq, int level) { - CPUState *env = cpu_single_env; + CPUMIPSState *env = cpu_single_env; if (env && level) { cpu_exit(env); @@ -273,7 +272,7 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device, i2c_bus *smbus; int i; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; - CPUState *env; + CPUMIPSState *env; /* init CPUs */ if (cpu_model == NULL) { @@ -355,8 +354,10 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device, isa_bus_irqs(isa_bus, i8259); vt82c686b_ide_init(pci_bus, hd, PCI_DEVFN(FULONG2E_VIA_SLOT, 1)); - usb_uhci_vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 2)); - usb_uhci_vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 3)); + pci_create_simple(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 2), + "vt82c686b-usb-uhci"); + pci_create_simple(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 3), + "vt82c686b-usb-uhci"); smbus = vt82c686b_pm_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 4), 0xeee1, NULL); diff --git a/hw/mips_int.c b/hw/mips_int.c index 477f6abf95..6423fd0bd9 100644 --- a/hw/mips_int.c +++ b/hw/mips_int.c @@ -26,7 +26,7 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level) { - CPUState *env = (CPUState *)opaque; + CPUMIPSState *env = (CPUMIPSState *)opaque; if (irq < 0 || irq > 7) return; @@ -44,7 +44,7 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level) } } -void cpu_mips_irq_init_cpu(CPUState *env) +void cpu_mips_irq_init_cpu(CPUMIPSState *env) { qemu_irq *qi; int i; @@ -55,7 +55,7 @@ void cpu_mips_irq_init_cpu(CPUState *env) } } -void cpu_mips_soft_irq(CPUState *env, int irq, int level) +void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level) { if (irq < 0 || irq > 2) { return; diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c index 2b4678e170..a6bc7badff 100644 --- a/hw/mips_jazz.c +++ b/hw/mips_jazz.c @@ -50,8 +50,8 @@ enum jazz_model_e static void main_cpu_reset(void *opaque) { - CPUState *env = opaque; - cpu_reset(env); + CPUMIPSState *env = opaque; + cpu_state_reset(env); } static uint64_t rtc_read(void *opaque, target_phys_addr_t addr, unsigned size) @@ -97,7 +97,7 @@ static const MemoryRegionOps dma_dummy_ops = { static void cpu_request_exit(void *opaque, int irq, int level) { - CPUState *env = cpu_single_env; + CPUMIPSState *env = cpu_single_env; if (env && level) { cpu_exit(env); @@ -112,7 +112,7 @@ static void mips_jazz_init(MemoryRegion *address_space, { char *filename; int bios_size, n; - CPUState *env; + CPUMIPSState *env; qemu_irq *rc4030, *i8259; rc4030_dma *dmas; void* rc4030_opaque; diff --git a/hw/mips_malta.c b/hw/mips_malta.c index b1563ed2a7..5e26775e64 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -33,7 +33,6 @@ #include "mips.h" #include "mips_cpudevs.h" #include "pci.h" -#include "usb-uhci.h" #include "vmware_vga.h" #include "qemu-char.h" #include "sysemu.h" @@ -501,7 +500,7 @@ static void network_init(void) a3 - RAM size in bytes */ -static void write_bootloader (CPUState *env, uint8_t *base, +static void write_bootloader (CPUMIPSState *env, uint8_t *base, int64_t kernel_entry) { uint32_t *p; @@ -737,7 +736,7 @@ static int64_t load_kernel (void) return kernel_entry; } -static void malta_mips_config(CPUState *env) +static void malta_mips_config(CPUMIPSState *env) { env->mvp->CP0_MVPConf0 |= ((smp_cpus - 1) << CP0MVPC0_PVPE) | ((smp_cpus * env->nr_threads - 1) << CP0MVPC0_PTC); @@ -745,8 +744,8 @@ static void malta_mips_config(CPUState *env) static void main_cpu_reset(void *opaque) { - CPUState *env = opaque; - cpu_reset(env); + CPUMIPSState *env = opaque; + cpu_state_reset(env); /* The bootloader does not need to be rewritten as it is located in a read only location. The kernel location and the arguments table @@ -760,7 +759,7 @@ static void main_cpu_reset(void *opaque) static void cpu_request_exit(void *opaque, int irq, int level) { - CPUState *env = cpu_single_env; + CPUMIPSState *env = cpu_single_env; if (env && level) { cpu_exit(env); @@ -782,7 +781,7 @@ void mips_malta_init (ram_addr_t ram_size, int64_t kernel_entry; PCIBus *pci_bus; ISABus *isa_bus; - CPUState *env; + CPUMIPSState *env; qemu_irq *isa_irq; qemu_irq *cpu_exit_irq; int piix4_devfn; @@ -965,7 +964,7 @@ void mips_malta_init (ram_addr_t ram_size, isa_bus_irqs(isa_bus, s->i8259); pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1); - usb_uhci_piix4_init(pci_bus, piix4_devfn + 2); + pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci"); smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_get_irq(NULL, 9), NULL, 0); /* TODO: Populate SPD eeprom data. */ diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c index 76c95b2ec0..1ea7b58323 100644 --- a/hw/mips_mipssim.c +++ b/hw/mips_mipssim.c @@ -46,7 +46,7 @@ static struct _loaderparams { } loaderparams; typedef struct ResetData { - CPUState *env; + CPUMIPSState *env; uint64_t vector; } ResetData; @@ -105,9 +105,9 @@ static int64_t load_kernel(void) static void main_cpu_reset(void *opaque) { ResetData *s = (ResetData *)opaque; - CPUState *env = s->env; + CPUMIPSState *env = s->env; - cpu_reset(env); + cpu_state_reset(env); env->active_tc.PC = s->vector & ~(target_ulong)1; if (s->vector & 1) { env->hflags |= MIPS_HFLAG_M16; @@ -140,7 +140,7 @@ mips_mipssim_init (ram_addr_t ram_size, MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); - CPUState *env; + CPUMIPSState *env; ResetData *reset_info; int bios_size; diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index 83401f0648..e2da49c09d 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -65,7 +65,7 @@ static const MemoryRegionOps mips_qemu_ops = { }; typedef struct ResetData { - CPUState *env; + CPUMIPSState *env; uint64_t vector; } ResetData; @@ -143,9 +143,9 @@ static int64_t load_kernel(void) static void main_cpu_reset(void *opaque) { ResetData *s = (ResetData *)opaque; - CPUState *env = s->env; + CPUMIPSState *env = s->env; - cpu_reset(env); + cpu_state_reset(env); env->active_tc.PC = s->vector; } @@ -162,7 +162,7 @@ void mips_r4k_init (ram_addr_t ram_size, MemoryRegion *bios; MemoryRegion *iomem = g_new(MemoryRegion, 1); int bios_size; - CPUState *env; + CPUMIPSState *env; ResetData *reset_info; int i; qemu_irq *i8259; diff --git a/hw/mips_timer.c b/hw/mips_timer.c index cf6ac694e3..7aa9004a0e 100644 --- a/hw/mips_timer.c +++ b/hw/mips_timer.c @@ -27,7 +27,7 @@ #define TIMER_FREQ 100 * 1000 * 1000 /* XXX: do not use a global */ -uint32_t cpu_mips_get_random (CPUState *env) +uint32_t cpu_mips_get_random (CPUMIPSState *env) { static uint32_t lfsr = 1; static uint32_t prev_idx = 0; @@ -42,7 +42,7 @@ uint32_t cpu_mips_get_random (CPUState *env) } /* MIPS R4K timer */ -static void cpu_mips_timer_update(CPUState *env) +static void cpu_mips_timer_update(CPUMIPSState *env) { uint64_t now, next; uint32_t wait; @@ -55,7 +55,7 @@ static void cpu_mips_timer_update(CPUState *env) } /* Expire the timer. */ -static void cpu_mips_timer_expire(CPUState *env) +static void cpu_mips_timer_expire(CPUMIPSState *env) { cpu_mips_timer_update(env); if (env->insn_flags & ISA_MIPS32R2) { @@ -64,7 +64,7 @@ static void cpu_mips_timer_expire(CPUState *env) qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); } -uint32_t cpu_mips_get_count (CPUState *env) +uint32_t cpu_mips_get_count (CPUMIPSState *env) { if (env->CP0_Cause & (1 << CP0Ca_DC)) { return env->CP0_Count; @@ -83,7 +83,7 @@ uint32_t cpu_mips_get_count (CPUState *env) } } -void cpu_mips_store_count (CPUState *env, uint32_t count) +void cpu_mips_store_count (CPUMIPSState *env, uint32_t count) { if (env->CP0_Cause & (1 << CP0Ca_DC)) env->CP0_Count = count; @@ -97,7 +97,7 @@ void cpu_mips_store_count (CPUState *env, uint32_t count) } } -void cpu_mips_store_compare (CPUState *env, uint32_t value) +void cpu_mips_store_compare (CPUMIPSState *env, uint32_t value) { env->CP0_Compare = value; if (!(env->CP0_Cause & (1 << CP0Ca_DC))) @@ -107,12 +107,12 @@ void cpu_mips_store_compare (CPUState *env, uint32_t value) qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); } -void cpu_mips_start_count(CPUState *env) +void cpu_mips_start_count(CPUMIPSState *env) { cpu_mips_store_count(env, env->CP0_Count); } -void cpu_mips_stop_count(CPUState *env) +void cpu_mips_stop_count(CPUMIPSState *env) { /* Store the current value */ env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock_ns(vm_clock), @@ -121,7 +121,7 @@ void cpu_mips_stop_count(CPUState *env) static void mips_timer_cb (void *opaque) { - CPUState *env; + CPUMIPSState *env; env = opaque; #if 0 @@ -139,7 +139,7 @@ static void mips_timer_cb (void *opaque) env->CP0_Count--; } -void cpu_mips_clock_init (CPUState *env) +void cpu_mips_clock_init (CPUMIPSState *env) { env->timer = qemu_new_timer_ns(vm_clock, &mips_timer_cb, env); env->CP0_Compare = 0; diff --git a/hw/mpc8544_guts.c b/hw/mpc8544_guts.c index aeb2de7ccc..13b0dddc1e 100644 --- a/hw/mpc8544_guts.c +++ b/hw/mpc8544_guts.c @@ -62,7 +62,7 @@ static uint64_t mpc8544_guts_read(void *opaque, target_phys_addr_t addr, unsigned size) { uint32_t value = 0; - CPUState *env = cpu_single_env; + CPUPPCState *env = cpu_single_env; addr &= MPC8544_GUTS_MMIO_SIZE - 1; switch (addr) { diff --git a/hw/musicpal.c b/hw/musicpal.c index 187a1aef5e..c9f845a3f2 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -1513,7 +1513,7 @@ static void musicpal_init(ram_addr_t ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - CPUState *env; + CPUARMState *env; qemu_irq *cpu_pic; qemu_irq pic[32]; DeviceState *dev; diff --git a/hw/omap.h b/hw/omap.h index 60fa34cef2..63ef847ed0 100644 --- a/hw/omap.h +++ b/hw/omap.h @@ -813,7 +813,7 @@ struct omap_mpu_state_s { omap3630, } mpu_model; - CPUState *env; + CPUARMState *env; qemu_irq *drq; diff --git a/hw/omap1.c b/hw/omap1.c index 1aa5f2388b..5317b9be2b 100644 --- a/hw/omap1.c +++ b/hw/omap1.c @@ -3702,7 +3702,7 @@ static void omap1_mpu_reset(void *opaque) omap_lpg_reset(mpu->led[0]); omap_lpg_reset(mpu->led[1]); omap_clkm_reset(mpu); - cpu_reset(mpu->env); + cpu_state_reset(mpu->env); } static const struct omap_map_s { diff --git a/hw/omap2.c b/hw/omap2.c index a6851b0fb0..157defb393 100644 --- a/hw/omap2.c +++ b/hw/omap2.c @@ -2224,7 +2224,7 @@ static void omap2_mpu_reset(void *opaque) omap_mcspi_reset(mpu->mcspi[1]); omap_i2c_reset(mpu->i2c[0]); omap_i2c_reset(mpu->i2c[1]); - cpu_reset(mpu->env); + cpu_state_reset(mpu->env); } static int omap2_validate_addr(struct omap_mpu_state_s *s, diff --git a/hw/pc.c b/hw/pc.c index bb9867b070..83a1b5b32b 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -140,7 +140,7 @@ void cpu_smm_register(cpu_set_smm_t callback, void *arg) smm_arg = arg; } -void cpu_smm_update(CPUState *env) +void cpu_smm_update(CPUX86State *env) { if (smm_set && smm_arg && env == first_cpu) smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg); @@ -148,7 +148,7 @@ void cpu_smm_update(CPUState *env) /* IRQ handling */ -int cpu_get_pic_interrupt(CPUState *env) +int cpu_get_pic_interrupt(CPUX86State *env) { int intno; @@ -167,7 +167,7 @@ int cpu_get_pic_interrupt(CPUState *env) static void pic_irq_request(void *opaque, int irq, int level) { - CPUState *env = first_cpu; + CPUX86State *env = first_cpu; DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq); if (env->apic_state) { @@ -522,7 +522,7 @@ type_init(port92_register_types) static void handle_a20_line_change(void *opaque, int irq, int level) { - CPUState *cpu = opaque; + CPUX86State *cpu = opaque; /* XXX: send to all CPUs ? */ /* XXX: add logic to handle multiple A20 line sources */ @@ -869,7 +869,7 @@ void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd) nb_ne2k++; } -int cpu_is_bsp(CPUState *env) +int cpu_is_bsp(CPUX86State *env) { /* We hard-wire the BSP to the first CPU. */ return env->cpu_index == 0; @@ -917,7 +917,7 @@ static DeviceState *apic_init(void *env, uint8_t apic_id) void pc_acpi_smi_interrupt(void *opaque, int irq, int level) { - CPUState *s = opaque; + CPUX86State *s = opaque; if (level) { cpu_interrupt(s, CPU_INTERRUPT_SMI); @@ -926,15 +926,15 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) static void pc_cpu_reset(void *opaque) { - CPUState *env = opaque; + CPUX86State *env = opaque; - cpu_reset(env); + cpu_state_reset(env); env->halted = !cpu_is_bsp(env); } -static CPUState *pc_new_cpu(const char *cpu_model) +static CPUX86State *pc_new_cpu(const char *cpu_model) { - CPUState *env; + CPUX86State *env; env = cpu_init(cpu_model); if (!env) { @@ -1070,7 +1070,7 @@ DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus) static void cpu_request_exit(void *opaque, int irq, int level) { - CPUState *env = cpu_single_env; + CPUX86State *env = cpu_single_env; if (env && level) { cpu_exit(env); diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 6c5c40f5df..3f99f9a7c2 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -28,8 +28,6 @@ #include "pc.h" #include "apic.h" #include "pci.h" -#include "usb-uhci.h" -#include "usb-ohci.h" #include "net.h" #include "boards.h" #include "ide.h" @@ -284,7 +282,7 @@ static void pc_init1(MemoryRegion *system_memory, floppy, idebus[0], idebus[1], rtc_state); if (pci_enabled && usb_enabled) { - usb_uhci_piix3_init(pci_bus, piix3_devfn + 2); + pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci"); } if (pci_enabled && acpi_enabled) { diff --git a/hw/pci.c b/hw/pci.c index bf046bfcad..ed8ec99073 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -841,7 +841,6 @@ static int pci_unregister_device(DeviceState *dev) pci_unregister_io_regions(pci_dev); pci_del_option_rom(pci_dev); - g_free(pci_dev->romfile); do_pci_unregister_device(pci_dev); return 0; } diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c index c87fa1186c..31a434872d 100644 --- a/hw/petalogix_ml605_mmu.c +++ b/hw/petalogix_ml605_mmu.c @@ -54,7 +54,7 @@ #define AXIENET_BASEADDR 0x82780000 #define AXIDMA_BASEADDR 0x84600000 -static void machine_cpu_reset(CPUState *env) +static void machine_cpu_reset(CPUMBState *env) { env->pvr.regs[10] = 0x0e000000; /* virtex 6 */ /* setup pvr to match kernel setting */ @@ -75,7 +75,7 @@ petalogix_ml605_init(ram_addr_t ram_size, { MemoryRegion *address_space_mem = get_system_memory(); DeviceState *dev; - CPUState *env; + CPUMBState *env; DriveInfo *dinfo; int i; target_phys_addr_t ddr_base = MEMORY_BASEADDR; diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c index 2cb0b1f10a..ff154c7aa9 100644 --- a/hw/petalogix_s3adsp1800_mmu.c +++ b/hw/petalogix_s3adsp1800_mmu.c @@ -49,7 +49,7 @@ #define UARTLITE_BASEADDR 0x84000000 #define ETHLITE_BASEADDR 0x81000000 -static void machine_cpu_reset(CPUState *env) +static void machine_cpu_reset(CPUMBState *env) { /* FIXME: move to machine specfic cpu reset */ env->pvr.regs[10] = 0x0c000000; /* spartan 3a dsp family. */ @@ -63,7 +63,7 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size, const char *initrd_filename, const char *cpu_model) { DeviceState *dev; - CPUState *env; + CPUMBState *env; DriveInfo *dinfo; int i; target_phys_addr_t ddr_base = MEMORY_BASEADDR; diff --git a/hw/ppc.c b/hw/ppc.c index 59882e2ecd..98546de991 100644 --- a/hw/ppc.c +++ b/hw/ppc.c @@ -47,10 +47,10 @@ # define LOG_TB(...) do { } while (0) #endif -static void cpu_ppc_tb_stop (CPUState *env); -static void cpu_ppc_tb_start (CPUState *env); +static void cpu_ppc_tb_stop (CPUPPCState *env); +static void cpu_ppc_tb_start (CPUPPCState *env); -void ppc_set_irq(CPUState *env, int n_IRQ, int level) +void ppc_set_irq(CPUPPCState *env, int n_IRQ, int level) { unsigned int old_pending = env->pending_interrupts; @@ -77,7 +77,7 @@ void ppc_set_irq(CPUState *env, int n_IRQ, int level) /* PowerPC 6xx / 7xx internal IRQ controller */ static void ppc6xx_set_irq (void *opaque, int pin, int level) { - CPUState *env = opaque; + CPUPPCState *env = opaque; int cur_level; LOG_IRQ("%s: env %p pin %d level %d\n", __func__, @@ -131,13 +131,7 @@ static void ppc6xx_set_irq (void *opaque, int pin, int level) /* Level sensitive - active low */ if (level) { LOG_IRQ("%s: reset the CPU\n", __func__); - env->interrupt_request |= CPU_INTERRUPT_EXITTB; - /* XXX: TOFIX */ -#if 0 - cpu_reset(env); -#else - qemu_system_reset_request(); -#endif + cpu_interrupt(env, CPU_INTERRUPT_RESET); } break; case PPC6xx_INPUT_SRESET: @@ -157,7 +151,7 @@ static void ppc6xx_set_irq (void *opaque, int pin, int level) } } -void ppc6xx_irq_init (CPUState *env) +void ppc6xx_irq_init (CPUPPCState *env) { env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, PPC6xx_INPUT_NB); @@ -167,7 +161,7 @@ void ppc6xx_irq_init (CPUState *env) /* PowerPC 970 internal IRQ controller */ static void ppc970_set_irq (void *opaque, int pin, int level) { - CPUState *env = opaque; + CPUPPCState *env = opaque; int cur_level; LOG_IRQ("%s: env %p pin %d level %d\n", __func__, @@ -214,10 +208,7 @@ static void ppc970_set_irq (void *opaque, int pin, int level) case PPC970_INPUT_HRESET: /* Level sensitive - active low */ if (level) { -#if 0 // XXX: TOFIX - LOG_IRQ("%s: reset the CPU\n", __func__); - cpu_reset(env); -#endif + cpu_interrupt(env, CPU_INTERRUPT_RESET); } break; case PPC970_INPUT_SRESET: @@ -242,7 +233,7 @@ static void ppc970_set_irq (void *opaque, int pin, int level) } } -void ppc970_irq_init (CPUState *env) +void ppc970_irq_init (CPUPPCState *env) { env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env, PPC970_INPUT_NB); @@ -251,7 +242,7 @@ void ppc970_irq_init (CPUState *env) /* POWER7 internal IRQ controller */ static void power7_set_irq (void *opaque, int pin, int level) { - CPUState *env = opaque; + CPUPPCState *env = opaque; LOG_IRQ("%s: env %p pin %d level %d\n", __func__, env, pin, level); @@ -275,7 +266,7 @@ static void power7_set_irq (void *opaque, int pin, int level) } } -void ppcPOWER7_irq_init (CPUState *env) +void ppcPOWER7_irq_init (CPUPPCState *env) { env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, env, POWER7_INPUT_NB); @@ -285,7 +276,7 @@ void ppcPOWER7_irq_init (CPUState *env) /* PowerPC 40x internal IRQ controller */ static void ppc40x_set_irq (void *opaque, int pin, int level) { - CPUState *env = opaque; + CPUPPCState *env = opaque; int cur_level; LOG_IRQ("%s: env %p pin %d level %d\n", __func__, @@ -355,7 +346,7 @@ static void ppc40x_set_irq (void *opaque, int pin, int level) } } -void ppc40x_irq_init (CPUState *env) +void ppc40x_irq_init (CPUPPCState *env) { env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq, env, PPC40x_INPUT_NB); @@ -364,7 +355,7 @@ void ppc40x_irq_init (CPUState *env) /* PowerPC E500 internal IRQ controller */ static void ppce500_set_irq (void *opaque, int pin, int level) { - CPUState *env = opaque; + CPUPPCState *env = opaque; int cur_level; LOG_IRQ("%s: env %p pin %d level %d\n", __func__, @@ -416,7 +407,7 @@ static void ppce500_set_irq (void *opaque, int pin, int level) } } -void ppce500_irq_init (CPUState *env) +void ppce500_irq_init (CPUPPCState *env) { env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq, env, PPCE500_INPUT_NB); @@ -430,7 +421,7 @@ uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset) return muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec()) + tb_offset; } -uint64_t cpu_ppc_load_tbl (CPUState *env) +uint64_t cpu_ppc_load_tbl (CPUPPCState *env) { ppc_tb_t *tb_env = env->tb_env; uint64_t tb; @@ -445,7 +436,7 @@ uint64_t cpu_ppc_load_tbl (CPUState *env) return tb; } -static inline uint32_t _cpu_ppc_load_tbu(CPUState *env) +static inline uint32_t _cpu_ppc_load_tbu(CPUPPCState *env) { ppc_tb_t *tb_env = env->tb_env; uint64_t tb; @@ -456,7 +447,7 @@ static inline uint32_t _cpu_ppc_load_tbu(CPUState *env) return tb >> 32; } -uint32_t cpu_ppc_load_tbu (CPUState *env) +uint32_t cpu_ppc_load_tbu (CPUPPCState *env) { if (kvm_enabled()) { return env->spr[SPR_TBU]; @@ -473,7 +464,7 @@ static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk, __func__, value, *tb_offsetp); } -void cpu_ppc_store_tbl (CPUState *env, uint32_t value) +void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value) { ppc_tb_t *tb_env = env->tb_env; uint64_t tb; @@ -484,7 +475,7 @@ void cpu_ppc_store_tbl (CPUState *env, uint32_t value) &tb_env->tb_offset, tb | (uint64_t)value); } -static inline void _cpu_ppc_store_tbu(CPUState *env, uint32_t value) +static inline void _cpu_ppc_store_tbu(CPUPPCState *env, uint32_t value) { ppc_tb_t *tb_env = env->tb_env; uint64_t tb; @@ -495,12 +486,12 @@ static inline void _cpu_ppc_store_tbu(CPUState *env, uint32_t value) &tb_env->tb_offset, ((uint64_t)value << 32) | tb); } -void cpu_ppc_store_tbu (CPUState *env, uint32_t value) +void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value) { _cpu_ppc_store_tbu(env, value); } -uint64_t cpu_ppc_load_atbl (CPUState *env) +uint64_t cpu_ppc_load_atbl (CPUPPCState *env) { ppc_tb_t *tb_env = env->tb_env; uint64_t tb; @@ -511,7 +502,7 @@ uint64_t cpu_ppc_load_atbl (CPUState *env) return tb; } -uint32_t cpu_ppc_load_atbu (CPUState *env) +uint32_t cpu_ppc_load_atbu (CPUPPCState *env) { ppc_tb_t *tb_env = env->tb_env; uint64_t tb; @@ -522,7 +513,7 @@ uint32_t cpu_ppc_load_atbu (CPUState *env) return tb >> 32; } -void cpu_ppc_store_atbl (CPUState *env, uint32_t value) +void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value) { ppc_tb_t *tb_env = env->tb_env; uint64_t tb; @@ -533,7 +524,7 @@ void cpu_ppc_store_atbl (CPUState *env, uint32_t value) &tb_env->atb_offset, tb | (uint64_t)value); } -void cpu_ppc_store_atbu (CPUState *env, uint32_t value) +void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value) { ppc_tb_t *tb_env = env->tb_env; uint64_t tb; @@ -544,7 +535,7 @@ void cpu_ppc_store_atbu (CPUState *env, uint32_t value) &tb_env->atb_offset, ((uint64_t)value << 32) | tb); } -static void cpu_ppc_tb_stop (CPUState *env) +static void cpu_ppc_tb_stop (CPUPPCState *env) { ppc_tb_t *tb_env = env->tb_env; uint64_t tb, atb, vmclk; @@ -566,7 +557,7 @@ static void cpu_ppc_tb_stop (CPUState *env) } } -static void cpu_ppc_tb_start (CPUState *env) +static void cpu_ppc_tb_start (CPUPPCState *env) { ppc_tb_t *tb_env = env->tb_env; uint64_t tb, atb, vmclk; @@ -587,7 +578,7 @@ static void cpu_ppc_tb_start (CPUState *env) } } -static inline uint32_t _cpu_ppc_load_decr(CPUState *env, uint64_t next) +static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next) { ppc_tb_t *tb_env = env->tb_env; uint32_t decr; @@ -606,7 +597,7 @@ static inline uint32_t _cpu_ppc_load_decr(CPUState *env, uint64_t next) return decr; } -uint32_t cpu_ppc_load_decr (CPUState *env) +uint32_t cpu_ppc_load_decr (CPUPPCState *env) { ppc_tb_t *tb_env = env->tb_env; @@ -617,14 +608,14 @@ uint32_t cpu_ppc_load_decr (CPUState *env) return _cpu_ppc_load_decr(env, tb_env->decr_next); } -uint32_t cpu_ppc_load_hdecr (CPUState *env) +uint32_t cpu_ppc_load_hdecr (CPUPPCState *env) { ppc_tb_t *tb_env = env->tb_env; return _cpu_ppc_load_decr(env, tb_env->hdecr_next); } -uint64_t cpu_ppc_load_purr (CPUState *env) +uint64_t cpu_ppc_load_purr (CPUPPCState *env) { ppc_tb_t *tb_env = env->tb_env; uint64_t diff; @@ -637,23 +628,23 @@ uint64_t cpu_ppc_load_purr (CPUState *env) /* When decrementer expires, * all we need to do is generate or queue a CPU exception */ -static inline void cpu_ppc_decr_excp(CPUState *env) +static inline void cpu_ppc_decr_excp(CPUPPCState *env) { /* Raise it */ LOG_TB("raise decrementer exception\n"); ppc_set_irq(env, PPC_INTERRUPT_DECR, 1); } -static inline void cpu_ppc_hdecr_excp(CPUState *env) +static inline void cpu_ppc_hdecr_excp(CPUPPCState *env) { /* Raise it */ LOG_TB("raise decrementer exception\n"); ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1); } -static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp, +static void __cpu_ppc_store_decr (CPUPPCState *env, uint64_t *nextp, struct QEMUTimer *timer, - void (*raise_excp)(CPUState *), + void (*raise_excp)(CPUPPCState *), uint32_t decr, uint32_t value, int is_excp) { @@ -690,7 +681,7 @@ static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp, } } -static inline void _cpu_ppc_store_decr(CPUState *env, uint32_t decr, +static inline void _cpu_ppc_store_decr(CPUPPCState *env, uint32_t decr, uint32_t value, int is_excp) { ppc_tb_t *tb_env = env->tb_env; @@ -699,7 +690,7 @@ static inline void _cpu_ppc_store_decr(CPUState *env, uint32_t decr, &cpu_ppc_decr_excp, decr, value, is_excp); } -void cpu_ppc_store_decr (CPUState *env, uint32_t value) +void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value) { _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0); } @@ -709,7 +700,7 @@ static void cpu_ppc_decr_cb (void *opaque) _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1); } -static inline void _cpu_ppc_store_hdecr(CPUState *env, uint32_t hdecr, +static inline void _cpu_ppc_store_hdecr(CPUPPCState *env, uint32_t hdecr, uint32_t value, int is_excp) { ppc_tb_t *tb_env = env->tb_env; @@ -720,7 +711,7 @@ static inline void _cpu_ppc_store_hdecr(CPUState *env, uint32_t hdecr, } } -void cpu_ppc_store_hdecr (CPUState *env, uint32_t value) +void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value) { _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0); } @@ -730,7 +721,7 @@ static void cpu_ppc_hdecr_cb (void *opaque) _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1); } -void cpu_ppc_store_purr (CPUState *env, uint64_t value) +void cpu_ppc_store_purr (CPUPPCState *env, uint64_t value) { ppc_tb_t *tb_env = env->tb_env; @@ -740,7 +731,7 @@ void cpu_ppc_store_purr (CPUState *env, uint64_t value) static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq) { - CPUState *env = opaque; + CPUPPCState *env = opaque; ppc_tb_t *tb_env = env->tb_env; tb_env->tb_freq = freq; @@ -755,7 +746,7 @@ static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq) } /* Set up (once) timebase frequency (in Hz) */ -clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq) +clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq) { ppc_tb_t *tb_env; @@ -778,28 +769,28 @@ clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq) /* Specific helpers for POWER & PowerPC 601 RTC */ #if 0 -static clk_setup_cb cpu_ppc601_rtc_init (CPUState *env) +static clk_setup_cb cpu_ppc601_rtc_init (CPUPPCState *env) { return cpu_ppc_tb_init(env, 7812500); } #endif -void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value) +void cpu_ppc601_store_rtcu (CPUPPCState *env, uint32_t value) { _cpu_ppc_store_tbu(env, value); } -uint32_t cpu_ppc601_load_rtcu (CPUState *env) +uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env) { return _cpu_ppc_load_tbu(env); } -void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value) +void cpu_ppc601_store_rtcl (CPUPPCState *env, uint32_t value) { cpu_ppc_store_tbl(env, value & 0x3FFFFF80); } -uint32_t cpu_ppc601_load_rtcl (CPUState *env) +uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env) { return cpu_ppc_load_tbl(env) & 0x3FFFFF80; } @@ -823,7 +814,7 @@ struct ppc40x_timer_t { /* Fixed interval timer */ static void cpu_4xx_fit_cb (void *opaque) { - CPUState *env; + CPUPPCState *env; ppc_tb_t *tb_env; ppc40x_timer_t *ppc40x_timer; uint64_t now, next; @@ -862,7 +853,7 @@ static void cpu_4xx_fit_cb (void *opaque) } /* Programmable interval timer */ -static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp) +static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp) { ppc40x_timer_t *ppc40x_timer; uint64_t now, next; @@ -891,7 +882,7 @@ static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp) static void cpu_4xx_pit_cb (void *opaque) { - CPUState *env; + CPUPPCState *env; ppc_tb_t *tb_env; ppc40x_timer_t *ppc40x_timer; @@ -913,7 +904,7 @@ static void cpu_4xx_pit_cb (void *opaque) /* Watchdog timer */ static void cpu_4xx_wdt_cb (void *opaque) { - CPUState *env; + CPUPPCState *env; ppc_tb_t *tb_env; ppc40x_timer_t *ppc40x_timer; uint64_t now, next; @@ -978,7 +969,7 @@ static void cpu_4xx_wdt_cb (void *opaque) } } -void store_40x_pit (CPUState *env, target_ulong val) +void store_40x_pit (CPUPPCState *env, target_ulong val) { ppc_tb_t *tb_env; ppc40x_timer_t *ppc40x_timer; @@ -990,14 +981,14 @@ void store_40x_pit (CPUState *env, target_ulong val) start_stop_pit(env, tb_env, 0); } -target_ulong load_40x_pit (CPUState *env) +target_ulong load_40x_pit (CPUPPCState *env) { return cpu_ppc_load_decr(env); } static void ppc_40x_set_tb_clk (void *opaque, uint32_t freq) { - CPUState *env = opaque; + CPUPPCState *env = opaque; ppc_tb_t *tb_env = env->tb_env; LOG_TB("%s set new frequency to %" PRIu32 "\n", __func__, @@ -1007,7 +998,7 @@ static void ppc_40x_set_tb_clk (void *opaque, uint32_t freq) /* XXX: we should also update all timers */ } -clk_setup_cb ppc_40x_timers_init (CPUState *env, uint32_t freq, +clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq, unsigned int decr_excp) { ppc_tb_t *tb_env; @@ -1093,7 +1084,7 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val) return -1; } -int ppc_dcr_register (CPUState *env, int dcrn, void *opaque, +int ppc_dcr_register (CPUPPCState *env, int dcrn, void *opaque, dcr_read_cb dcr_read, dcr_write_cb dcr_write) { ppc_dcr_t *dcr_env; @@ -1116,7 +1107,7 @@ int ppc_dcr_register (CPUState *env, int dcrn, void *opaque, return 0; } -int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn), +int ppc_dcr_init (CPUPPCState *env, int (*read_error)(int dcrn), int (*write_error)(int dcrn)) { ppc_dcr_t *dcr_env; diff --git a/hw/ppc.h b/hw/ppc.h index 9f911704af..2f3ea277bc 100644 --- a/hw/ppc.h +++ b/hw/ppc.h @@ -1,4 +1,4 @@ -void ppc_set_irq (CPUState *env, int n_IRQ, int level); +void ppc_set_irq (CPUPPCState *env, int n_IRQ, int level); /* PowerPC hardware exceptions management helpers */ typedef void (*clk_setup_cb)(void *opaque, uint32_t freq); @@ -43,32 +43,32 @@ struct ppc_tb_t { */ uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset); -clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq); +clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq); /* Embedded PowerPC DCR management */ typedef uint32_t (*dcr_read_cb)(void *opaque, int dcrn); typedef void (*dcr_write_cb)(void *opaque, int dcrn, uint32_t val); -int ppc_dcr_init (CPUState *env, int (*dcr_read_error)(int dcrn), +int ppc_dcr_init (CPUPPCState *env, int (*dcr_read_error)(int dcrn), int (*dcr_write_error)(int dcrn)); -int ppc_dcr_register (CPUState *env, int dcrn, void *opaque, +int ppc_dcr_register (CPUPPCState *env, int dcrn, void *opaque, dcr_read_cb drc_read, dcr_write_cb dcr_write); -clk_setup_cb ppc_40x_timers_init (CPUState *env, uint32_t freq, +clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq, unsigned int decr_excp); /* Embedded PowerPC reset */ -void ppc40x_core_reset (CPUState *env); -void ppc40x_chip_reset (CPUState *env); -void ppc40x_system_reset (CPUState *env); +void ppc40x_core_reset (CPUPPCState *env); +void ppc40x_chip_reset (CPUPPCState *env); +void ppc40x_system_reset (CPUPPCState *env); void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val); extern CPUWriteMemoryFunc * const PPC_io_write[]; extern CPUReadMemoryFunc * const PPC_io_read[]; void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val); -void ppc40x_irq_init (CPUState *env); -void ppce500_irq_init (CPUState *env); -void ppc6xx_irq_init (CPUState *env); -void ppc970_irq_init (CPUState *env); -void ppcPOWER7_irq_init (CPUState *env); +void ppc40x_irq_init (CPUPPCState *env); +void ppce500_irq_init (CPUPPCState *env); +void ppc6xx_irq_init (CPUPPCState *env); +void ppc970_irq_init (CPUPPCState *env); +void ppcPOWER7_irq_init (CPUPPCState *env); /* PPC machines for OpenBIOS */ enum { @@ -89,4 +89,4 @@ enum { #define PPC_SERIAL_MM_BAUDBASE 399193 /* ppc_booke.c */ -void ppc_booke_timers_init(CPUState *env, uint32_t freq, uint32_t flags); +void ppc_booke_timers_init(CPUPPCState *env, uint32_t freq, uint32_t flags); diff --git a/hw/ppc405.h b/hw/ppc405.h index d8fdf0930a..1f5dc5fd36 100644 --- a/hw/ppc405.h +++ b/hw/ppc405.h @@ -56,23 +56,23 @@ struct ppc4xx_bd_info_t { }; /* PowerPC 405 core */ -ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd, +ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd, uint32_t flags); -CPUState *ppc405cr_init(MemoryRegion *address_space_mem, +CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem, MemoryRegion ram_memories[4], target_phys_addr_t ram_bases[4], target_phys_addr_t ram_sizes[4], uint32_t sysclk, qemu_irq **picp, int do_init); -CPUState *ppc405ep_init(MemoryRegion *address_space_mem, +CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem, MemoryRegion ram_memories[2], target_phys_addr_t ram_bases[2], target_phys_addr_t ram_sizes[2], uint32_t sysclk, qemu_irq **picp, int do_init); /* IBM STBxxx microcontrollers */ -CPUState *ppc_stb025_init (MemoryRegion ram_memories[2], +CPUPPCState *ppc_stb025_init (MemoryRegion ram_memories[2], target_phys_addr_t ram_bases[2], target_phys_addr_t ram_sizes[2], uint32_t sysclk, qemu_irq **picp, diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c index 98079fa23f..6f8342e0e7 100644 --- a/hw/ppc405_uc.c +++ b/hw/ppc405_uc.c @@ -41,7 +41,7 @@ #define DEBUG_CLOCKS //#define DEBUG_CLOCKS_LL -ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd, +ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd, uint32_t flags) { ram_addr_t bdloc; @@ -169,7 +169,7 @@ static void ppc4xx_plb_reset (void *opaque) plb->besr = 0x00000000; } -static void ppc4xx_plb_init(CPUState *env) +static void ppc4xx_plb_init(CPUPPCState *env) { ppc4xx_plb_t *plb; @@ -245,7 +245,7 @@ static void ppc4xx_pob_reset (void *opaque) pob->besr[1] = 0x0000000; } -static void ppc4xx_pob_init(CPUState *env) +static void ppc4xx_pob_init(CPUPPCState *env) { ppc4xx_pob_t *pob; @@ -574,7 +574,7 @@ static void ebc_reset (void *opaque) ebc->cfg = 0x80400000; } -static void ppc405_ebc_init(CPUState *env) +static void ppc405_ebc_init(CPUPPCState *env) { ppc4xx_ebc_t *ebc; @@ -657,7 +657,7 @@ static void ppc405_dma_reset (void *opaque) dma->pol = 0x00000000; } -static void ppc405_dma_init(CPUState *env, qemu_irq irqs[4]) +static void ppc405_dma_init(CPUPPCState *env, qemu_irq irqs[4]) { ppc405_dma_t *dma; @@ -960,7 +960,7 @@ static void ocm_reset (void *opaque) ocm->dsacntl = dsacntl; } -static void ppc405_ocm_init(CPUState *env) +static void ppc405_ocm_init(CPUPPCState *env) { ppc405_ocm_t *ocm; @@ -1713,7 +1713,7 @@ static void ppc40x_mal_reset (void *opaque) mal->txeobisr = 0x00000000; } -static void ppc405_mal_init(CPUState *env, qemu_irq irqs[4]) +static void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4]) { ppc40x_mal_t *mal; int i; @@ -1764,36 +1764,24 @@ static void ppc405_mal_init(CPUState *env, qemu_irq irqs[4]) /*****************************************************************************/ /* SPR */ -void ppc40x_core_reset (CPUState *env) +void ppc40x_core_reset (CPUPPCState *env) { target_ulong dbsr; printf("Reset PowerPC core\n"); - env->interrupt_request |= CPU_INTERRUPT_EXITTB; - /* XXX: TOFIX */ -#if 0 - cpu_reset(env); -#else - qemu_system_reset_request(); -#endif + cpu_interrupt(env, CPU_INTERRUPT_RESET); dbsr = env->spr[SPR_40x_DBSR]; dbsr &= ~0x00000300; dbsr |= 0x00000100; env->spr[SPR_40x_DBSR] = dbsr; } -void ppc40x_chip_reset (CPUState *env) +void ppc40x_chip_reset (CPUPPCState *env) { target_ulong dbsr; printf("Reset PowerPC chip\n"); - env->interrupt_request |= CPU_INTERRUPT_EXITTB; - /* XXX: TOFIX */ -#if 0 - cpu_reset(env); -#else - qemu_system_reset_request(); -#endif + cpu_interrupt(env, CPU_INTERRUPT_RESET); /* XXX: TODO reset all internal peripherals */ dbsr = env->spr[SPR_40x_DBSR]; dbsr &= ~0x00000300; @@ -1801,13 +1789,13 @@ void ppc40x_chip_reset (CPUState *env) env->spr[SPR_40x_DBSR] = dbsr; } -void ppc40x_system_reset (CPUState *env) +void ppc40x_system_reset (CPUPPCState *env) { printf("Reset PowerPC system\n"); qemu_system_reset_request(); } -void store_40x_dbcr0 (CPUState *env, uint32_t val) +void store_40x_dbcr0 (CPUPPCState *env, uint32_t val) { switch ((val >> 28) & 0x3) { case 0x0: @@ -2078,7 +2066,7 @@ static void ppc405cr_clk_init (ppc405cr_cpc_t *cpc) cpc->psr |= D << 17; } -static void ppc405cr_cpc_init (CPUState *env, clk_setup_t clk_setup[7], +static void ppc405cr_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[7], uint32_t sysclk) { ppc405cr_cpc_t *cpc; @@ -2108,7 +2096,7 @@ static void ppc405cr_cpc_init (CPUState *env, clk_setup_t clk_setup[7], qemu_register_reset(ppc405cr_cpc_reset, cpc); } -CPUState *ppc405cr_init(MemoryRegion *address_space_mem, +CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem, MemoryRegion ram_memories[4], target_phys_addr_t ram_bases[4], target_phys_addr_t ram_sizes[4], @@ -2117,7 +2105,7 @@ CPUState *ppc405cr_init(MemoryRegion *address_space_mem, { clk_setup_t clk_setup[PPC405CR_CLK_NB]; qemu_irq dma_irqs[4]; - CPUState *env; + CPUPPCState *env; qemu_irq *pic, *irqs; memset(clk_setup, 0, sizeof(clk_setup)); @@ -2420,7 +2408,7 @@ static void ppc405ep_cpc_reset (void *opaque) } /* XXX: sysclk should be between 25 and 100 MHz */ -static void ppc405ep_cpc_init (CPUState *env, clk_setup_t clk_setup[8], +static void ppc405ep_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[8], uint32_t sysclk) { ppc405ep_cpc_t *cpc; @@ -2457,7 +2445,7 @@ static void ppc405ep_cpc_init (CPUState *env, clk_setup_t clk_setup[8], #endif } -CPUState *ppc405ep_init(MemoryRegion *address_space_mem, +CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem, MemoryRegion ram_memories[2], target_phys_addr_t ram_bases[2], target_phys_addr_t ram_sizes[2], @@ -2466,7 +2454,7 @@ CPUState *ppc405ep_init(MemoryRegion *address_space_mem, { clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup; qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4]; - CPUState *env; + CPUPPCState *env; qemu_irq *pic, *irqs; memset(clk_setup, 0, sizeof(clk_setup)); diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c index f86b16838a..220c81d06e 100644 --- a/hw/ppc440_bamboo.c +++ b/hw/ppc440_bamboo.c @@ -121,7 +121,7 @@ out: } /* Create reset TLB entries for BookE, spanning the 32bit addr space. */ -static void mmubooke_create_initial_mapping(CPUState *env, +static void mmubooke_create_initial_mapping(CPUPPCState *env, target_ulong va, target_phys_addr_t pa) { @@ -145,9 +145,9 @@ static void mmubooke_create_initial_mapping(CPUState *env, static void main_cpu_reset(void *opaque) { - CPUState *env = opaque; + CPUPPCState *env = opaque; - cpu_reset(env); + cpu_state_reset(env); env->gpr[1] = (16<<20) - 8; env->gpr[3] = FDT_ADDR; env->nip = entry; @@ -172,7 +172,7 @@ static void bamboo_init(ram_addr_t ram_size, qemu_irq *pic; qemu_irq *irqs; PCIBus *pcibus; - CPUState *env; + CPUPPCState *env; uint64_t elf_entry; uint64_t elf_lowaddr; target_phys_addr_t loadaddr = 0; diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h index f969e44e1b..b511020aeb 100644 --- a/hw/ppc4xx.h +++ b/hw/ppc4xx.h @@ -28,7 +28,7 @@ #include "pci.h" /* PowerPC 4xx core initialization */ -CPUState *ppc4xx_init (const char *cpu_model, +CPUPPCState *ppc4xx_init (const char *cpu_model, clk_setup_t *cpu_clk, clk_setup_t *tb_clk, uint32_t sysclk); @@ -38,7 +38,7 @@ enum { PPCUIC_OUTPUT_CINT = 1, PPCUIC_OUTPUT_NB, }; -qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs, +qemu_irq *ppcuic_init (CPUPPCState *env, qemu_irq *irqs, uint32_t dcr_base, int has_ssr, int has_vr); ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks, @@ -47,13 +47,13 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks, target_phys_addr_t ram_sizes[], const unsigned int sdram_bank_sizes[]); -void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks, +void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks, MemoryRegion ram_memories[], target_phys_addr_t *ram_bases, target_phys_addr_t *ram_sizes, int do_init); -PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4], +PCIBus *ppc4xx_pci_init(CPUPPCState *env, qemu_irq pci_irqs[4], target_phys_addr_t config_space, target_phys_addr_t int_ack, target_phys_addr_t special_cycle, diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c index 26040ac3ad..00e36f4109 100644 --- a/hw/ppc4xx_devs.c +++ b/hw/ppc4xx_devs.c @@ -38,13 +38,20 @@ # define LOG_UIC(...) do { } while (0) #endif +static void ppc4xx_reset(void *opaque) +{ + CPUPPCState *env = opaque; + + cpu_state_reset(env); +} + /*****************************************************************************/ /* Generic PowerPC 4xx processor instantiation */ -CPUState *ppc4xx_init (const char *cpu_model, +CPUPPCState *ppc4xx_init (const char *cpu_model, clk_setup_t *cpu_clk, clk_setup_t *tb_clk, uint32_t sysclk) { - CPUState *env; + CPUPPCState *env; /* init CPUs */ env = cpu_init(cpu_model); @@ -60,7 +67,7 @@ CPUState *ppc4xx_init (const char *cpu_model, tb_clk->opaque = env; ppc_dcr_init(env, NULL, NULL); /* Register qemu callbacks */ - qemu_register_reset((QEMUResetHandler*)&cpu_reset, env); + qemu_register_reset(ppc4xx_reset, env); return env; } @@ -288,7 +295,7 @@ static void ppcuic_reset (void *opaque) } } -qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs, +qemu_irq *ppcuic_init (CPUPPCState *env, qemu_irq *irqs, uint32_t dcr_base, int has_ssr, int has_vr) { ppcuic_t *uic; @@ -634,7 +641,7 @@ static void sdram_reset (void *opaque) sdram->cfg = 0x00800000; } -void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks, +void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks, MemoryRegion *ram_memories, target_phys_addr_t *ram_bases, target_phys_addr_t *ram_sizes, diff --git a/hw/ppc_booke.c b/hw/ppc_booke.c index 88719458b0..d51e7fad67 100644 --- a/hw/ppc_booke.c +++ b/hw/ppc_booke.c @@ -71,7 +71,7 @@ struct booke_timer_t { uint32_t flags; }; -static void booke_update_irq(CPUState *env) +static void booke_update_irq(CPUPPCState *env) { ppc_set_irq(env, PPC_INTERRUPT_DECR, (env->spr[SPR_BOOKE_TSR] & TSR_DIS @@ -88,7 +88,7 @@ static void booke_update_irq(CPUState *env) /* Return the location of the bit of time base at which the FIT will raise an interrupt */ -static uint8_t booke_get_fit_target(CPUState *env, ppc_tb_t *tb_env) +static uint8_t booke_get_fit_target(CPUPPCState *env, ppc_tb_t *tb_env) { uint8_t fp = (env->spr[SPR_BOOKE_TCR] & TCR_FP_MASK) >> TCR_FP_SHIFT; @@ -106,7 +106,7 @@ static uint8_t booke_get_fit_target(CPUState *env, ppc_tb_t *tb_env) /* Return the location of the bit of time base at which the WDT will raise an interrupt */ -static uint8_t booke_get_wdt_target(CPUState *env, ppc_tb_t *tb_env) +static uint8_t booke_get_wdt_target(CPUPPCState *env, ppc_tb_t *tb_env) { uint8_t wp = (env->spr[SPR_BOOKE_TCR] & TCR_WP_MASK) >> TCR_WP_SHIFT; @@ -122,7 +122,7 @@ static uint8_t booke_get_wdt_target(CPUState *env, ppc_tb_t *tb_env) return wp; } -static void booke_update_fixed_timer(CPUState *env, +static void booke_update_fixed_timer(CPUPPCState *env, uint8_t target_bit, uint64_t *next, struct QEMUTimer *timer) @@ -153,7 +153,7 @@ static void booke_update_fixed_timer(CPUState *env, static void booke_decr_cb(void *opaque) { - CPUState *env = opaque; + CPUPPCState *env = opaque; env->spr[SPR_BOOKE_TSR] |= TSR_DIS; booke_update_irq(env); @@ -166,7 +166,7 @@ static void booke_decr_cb(void *opaque) static void booke_fit_cb(void *opaque) { - CPUState *env; + CPUPPCState *env; ppc_tb_t *tb_env; booke_timer_t *booke_timer; @@ -185,7 +185,7 @@ static void booke_fit_cb(void *opaque) static void booke_wdt_cb(void *opaque) { - CPUState *env; + CPUPPCState *env; ppc_tb_t *tb_env; booke_timer_t *booke_timer; @@ -203,13 +203,13 @@ static void booke_wdt_cb(void *opaque) booke_timer->wdt_timer); } -void store_booke_tsr(CPUState *env, target_ulong val) +void store_booke_tsr(CPUPPCState *env, target_ulong val) { env->spr[SPR_BOOKE_TSR] &= ~val; booke_update_irq(env); } -void store_booke_tcr(CPUState *env, target_ulong val) +void store_booke_tcr(CPUPPCState *env, target_ulong val) { ppc_tb_t *tb_env = env->tb_env; booke_timer_t *booke_timer = tb_env->opaque; @@ -231,7 +231,7 @@ void store_booke_tcr(CPUState *env, target_ulong val) } -void ppc_booke_timers_init(CPUState *env, uint32_t freq, uint32_t flags) +void ppc_booke_timers_init(CPUPPCState *env, uint32_t freq, uint32_t flags) { ppc_tb_t *tb_env; booke_timer_t *booke_timer; diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index 506187b182..879651018b 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -54,7 +54,6 @@ #include "nvram.h" #include "pc.h" #include "pci.h" -#include "usb-ohci.h" #include "net.h" #include "sysemu.h" #include "boards.h" @@ -122,6 +121,13 @@ static target_phys_addr_t round_page(target_phys_addr_t addr) return (addr + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK; } +static void ppc_core99_reset(void *opaque) +{ + CPUPPCState *env = opaque; + + cpu_state_reset(env); +} + /* PowerPC Mac99 hardware initialisation */ static void ppc_core99_init (ram_addr_t ram_size, const char *boot_device, @@ -130,7 +136,7 @@ static void ppc_core99_init (ram_addr_t ram_size, const char *initrd_filename, const char *cpu_model) { - CPUState *env = NULL; + CPUPPCState *env = NULL; char *filename; qemu_irq *pic, **openpic_irqs; MemoryRegion *unin_memory = g_new(MemoryRegion, 1); @@ -167,7 +173,7 @@ static void ppc_core99_init (ram_addr_t ram_size, } /* Set time-base frequency to 100 Mhz */ cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL); - qemu_register_reset((QEMUResetHandler*)&cpu_reset, env); + qemu_register_reset(ppc_core99_reset, env); } /* allocate RAM */ @@ -352,7 +358,7 @@ static void ppc_core99_init (ram_addr_t ram_size, dbdma_mem, cuda_mem, NULL, 3, ide_mem, escc_bar); if (usb_enabled) { - usb_ohci_init_pci(pci_bus, -1); + pci_create_simple(pci_bus, -1, "pci-ohci"); } /* U3 needs to use USB for input because Linux doesn't support via-cuda diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index 9295a34f59..7e73d37c34 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -34,7 +34,6 @@ #include "net.h" #include "isa.h" #include "pci.h" -#include "usb-ohci.h" #include "boards.h" #include "fw_cfg.h" #include "escc.h" @@ -66,6 +65,13 @@ static target_phys_addr_t round_page(target_phys_addr_t addr) return (addr + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK; } +static void ppc_heathrow_reset(void *opaque) +{ + CPUPPCState *env = opaque; + + cpu_state_reset(env); +} + static void ppc_heathrow_init (ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, @@ -74,7 +80,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size, const char *cpu_model) { MemoryRegion *sysmem = get_system_memory(); - CPUState *env = NULL; + CPUPPCState *env = NULL; char *filename; qemu_irq *pic, **heathrow_irqs; int linux_boot, i; @@ -105,7 +111,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size, } /* Set time-base frequency to 16.6 Mhz */ cpu_ppc_tb_init(env, 16600000UL); - qemu_register_reset((QEMUResetHandler*)&cpu_reset, env); + qemu_register_reset(ppc_heathrow_reset, env); } /* allocate RAM */ @@ -278,7 +284,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size, dbdma_mem, cuda_mem, nvr, 2, ide_mem, escc_bar); if (usb_enabled) { - usb_ohci_init_pci(pci_bus, -1); + pci_create_simple(pci_bus, -1, "pci-ohci"); } if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8) diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index eb43fb5849..06d589d97b 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -30,7 +30,6 @@ #include "isa.h" #include "pci.h" #include "pci_host.h" -#include "usb-ohci.h" #include "ppc.h" #include "boards.h" #include "qemu-log.h" @@ -464,13 +463,20 @@ static const MemoryRegionOps PPC_prep_io_ops = { static void cpu_request_exit(void *opaque, int irq, int level) { - CPUState *env = cpu_single_env; + CPUPPCState *env = cpu_single_env; if (env && level) { cpu_exit(env); } } +static void ppc_prep_reset(void *opaque) +{ + CPUPPCState *env = opaque; + + cpu_state_reset(env); +} + /* PowerPC PREP hardware initialisation */ static void ppc_prep_init (ram_addr_t ram_size, const char *boot_device, @@ -480,7 +486,7 @@ static void ppc_prep_init (ram_addr_t ram_size, const char *cpu_model) { MemoryRegion *sysmem = get_system_memory(); - CPUState *env = NULL; + CPUPPCState *env = NULL; char *filename; nvram_t nvram; M48t59State *m48t59; @@ -525,7 +531,7 @@ static void ppc_prep_init (ram_addr_t ram_size, /* Set time-base frequency to 100 Mhz */ cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL); } - qemu_register_reset((QEMUResetHandler*)&cpu_reset, env); + qemu_register_reset(ppc_prep_reset, env); } /* allocate RAM */ @@ -688,7 +694,7 @@ static void ppc_prep_init (ram_addr_t ram_size, #endif if (usb_enabled) { - usb_ohci_init_pci(pci_bus, -1); + pci_create_simple(pci_bus, -1, "pci-ohci"); } m48t59 = m48t59_init_isa(isa_bus, 0x0074, NVRAM_SIZE, 59); diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index d69f78cf33..5ee8cb34c1 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -58,7 +58,7 @@ struct boot_info uint32_t entry; }; -static int mpc8544_load_device_tree(CPUState *env, +static int mpc8544_load_device_tree(CPUPPCState *env, target_phys_addr_t addr, uint32_t ramsize, target_phys_addr_t initrd_base, @@ -178,7 +178,7 @@ static inline target_phys_addr_t booke206_page_size_to_tlb(uint64_t size) return ffs(size >> 10) - 1; } -static void mmubooke_create_initial_mapping(CPUState *env, +static void mmubooke_create_initial_mapping(CPUPPCState *env, target_ulong va, target_phys_addr_t pa) { @@ -196,9 +196,9 @@ static void mmubooke_create_initial_mapping(CPUState *env, static void mpc8544ds_cpu_reset_sec(void *opaque) { - CPUState *env = opaque; + CPUPPCState *env = opaque; - cpu_reset(env); + cpu_state_reset(env); /* Secondary CPU starts in halted state for now. Needs to change when implementing non-kernel boot. */ @@ -208,10 +208,10 @@ static void mpc8544ds_cpu_reset_sec(void *opaque) static void mpc8544ds_cpu_reset(void *opaque) { - CPUState *env = opaque; + CPUPPCState *env = opaque; struct boot_info *bi = env->load_info; - cpu_reset(env); + cpu_state_reset(env); /* Set initial guest state. */ env->halted = 0; @@ -231,7 +231,7 @@ static void mpc8544ds_init(ram_addr_t ram_size, MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); PCIBus *pci_bus; - CPUState *env = NULL; + CPUPPCState *env = NULL; uint64_t elf_entry; uint64_t elf_lowaddr; target_phys_addr_t entry=0; @@ -244,7 +244,7 @@ static void mpc8544ds_init(ram_addr_t ram_size, unsigned int pci_irq_nrs[4] = {1, 2, 3, 4}; qemu_irq **irqs, *mpic; DeviceState *dev; - CPUState *firstenv = NULL; + CPUPPCState *firstenv = NULL; /* Setup CPUs */ if (cpu_model == NULL) { diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c index 6b8a189c0e..268f5fdb9c 100644 --- a/hw/ppce500_spin.c +++ b/hw/ppce500_spin.c @@ -49,7 +49,7 @@ typedef struct spin_state { } SpinState; typedef struct spin_kick { - CPUState *env; + CPUPPCState *env; SpinInfo *spin; } SpinKick; @@ -73,7 +73,7 @@ static inline target_phys_addr_t booke206_page_size_to_tlb(uint64_t size) return (ffs(size >> 10) - 1) >> 1; } -static void mmubooke_create_initial_mapping(CPUState *env, +static void mmubooke_create_initial_mapping(CPUPPCState *env, target_ulong va, target_phys_addr_t pa, target_phys_addr_t len) @@ -91,7 +91,7 @@ static void mmubooke_create_initial_mapping(CPUState *env, static void spin_kick(void *data) { SpinKick *kick = data; - CPUState *env = kick->env; + CPUPPCState *env = kick->env; SpinInfo *curspin = kick->spin; target_phys_addr_t map_size = 64 * 1024 * 1024; target_phys_addr_t map_start; @@ -121,7 +121,7 @@ static void spin_write(void *opaque, target_phys_addr_t addr, uint64_t value, { SpinState *s = opaque; int env_idx = addr / sizeof(SpinInfo); - CPUState *env; + CPUPPCState *env; SpinInfo *curspin = &s->spin[env_idx]; uint8_t *curspin_p = (uint8_t*)curspin; diff --git a/hw/pxa.h b/hw/pxa.h index e7787393c7..025be34f86 100644 --- a/hw/pxa.h +++ b/hw/pxa.h @@ -65,11 +65,11 @@ # define PXA2XX_INTERNAL_SIZE 0x40000 /* pxa2xx_pic.c */ -DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env); +DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUARMState *env); /* pxa2xx_gpio.c */ DeviceState *pxa2xx_gpio_init(target_phys_addr_t base, - CPUState *env, DeviceState *pic, int lines); + CPUARMState *env, DeviceState *pic, int lines); void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler); /* pxa2xx_dma.c */ @@ -122,7 +122,7 @@ typedef struct PXA2xxI2SState PXA2xxI2SState; typedef struct PXA2xxFIrState PXA2xxFIrState; typedef struct { - CPUState *env; + CPUARMState *env; DeviceState *pic; qemu_irq reset; MemoryRegion sdram; diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c index 1ab27012c1..f55287774a 100644 --- a/hw/pxa2xx.c +++ b/hw/pxa2xx.c @@ -2045,7 +2045,7 @@ static void pxa2xx_reset(void *opaque, int line, int level) PXA2xxState *s = (PXA2xxState *) opaque; if (level && (s->pm_regs[PCFR >> 2] & 0x10)) { /* GPR_EN */ - cpu_reset(s->env); + cpu_state_reset(s->env); /* TODO: reset peripherals */ } } diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c index d5f57162ed..09a408b781 100644 --- a/hw/pxa2xx_gpio.c +++ b/hw/pxa2xx_gpio.c @@ -20,7 +20,7 @@ struct PXA2xxGPIOInfo { qemu_irq irq0, irq1, irqX; int lines; int ncpu; - CPUState *cpu_env; + CPUARMState *cpu_env; /* XXX: GNU C vectors are more suitable */ uint32_t ilevel[PXA2XX_GPIO_BANKS]; @@ -249,7 +249,7 @@ static const MemoryRegionOps pxa_gpio_ops = { }; DeviceState *pxa2xx_gpio_init(target_phys_addr_t base, - CPUState *env, DeviceState *pic, int lines) + CPUARMState *env, DeviceState *pic, int lines) { DeviceState *dev; diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c index 6b2bdb0df1..a806b80b0f 100644 --- a/hw/pxa2xx_pic.c +++ b/hw/pxa2xx_pic.c @@ -34,7 +34,7 @@ typedef struct { SysBusDevice busdev; MemoryRegion iomem; - CPUState *cpu_env; + CPUARMState *cpu_env; uint32_t int_enabled[2]; uint32_t int_pending[2]; uint32_t is_fiq[2]; @@ -245,7 +245,7 @@ static int pxa2xx_pic_post_load(void *opaque, int version_id) return 0; } -DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env) +DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUARMState *env) { DeviceState *dev = qdev_create(NULL, "pxa2xx_pic"); PXA2xxPICState *s = FROM_SYSBUS(PXA2xxPICState, sysbus_from_qdev(dev)); diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 0423af1c31..bff9152df5 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -421,10 +421,6 @@ static void set_string(Object *obj, Visitor *v, void *opaque, error_propagate(errp, local_err); return; } - if (!*str) { - g_free(str); - str = NULL; - } if (*ptr) { g_free(*ptr); } diff --git a/hw/r2d.c b/hw/r2d.c index c80f9e3a29..c55de0141b 100644 --- a/hw/r2d.c +++ b/hw/r2d.c @@ -192,16 +192,16 @@ static qemu_irq *r2d_fpga_init(MemoryRegion *sysmem, } typedef struct ResetData { - CPUState *env; + CPUSH4State *env; uint32_t vector; } ResetData; static void main_cpu_reset(void *opaque) { ResetData *s = (ResetData *)opaque; - CPUState *env = s->env; + CPUSH4State *env = s->env; - cpu_reset(env); + cpu_state_reset(env); env->pc = s->vector; } @@ -224,7 +224,7 @@ static void r2d_init(ram_addr_t ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - CPUState *env; + CPUSH4State *env; ResetData *reset_info; struct SH7750State *s; MemoryRegion *sdram = g_new(MemoryRegion, 1); diff --git a/hw/realview.c b/hw/realview.c index ae1bbcdac3..cf55204c96 100644 --- a/hw/realview.c +++ b/hw/realview.c @@ -12,7 +12,6 @@ #include "primecell.h" #include "devices.h" #include "pci.h" -#include "usb-ohci.h" #include "net.h" #include "sysemu.h" #include "boards.h" @@ -129,7 +128,7 @@ static void realview_init(ram_addr_t ram_size, const char *initrd_filename, const char *cpu_model, enum realview_board_type board_type) { - CPUState *env = NULL; + CPUARMState *env = NULL; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram_lo = g_new(MemoryRegion, 1); MemoryRegion *ram_hi = g_new(MemoryRegion, 1); @@ -305,7 +304,7 @@ static void realview_init(ram_addr_t ram_size, sysbus_connect_irq(busdev, 3, pic[51]); pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci"); if (usb_enabled) { - usb_ohci_init_pci(pci_bus, -1); + pci_create_simple(pci_bus, -1, "pci-ohci"); } n = drive_get_max_bus(IF_SCSI); while (n >= 0) { diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index c450e4bb5b..be1f5f1061 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -85,7 +85,7 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size) return bus; } -static void s390_virtio_irq(CPUState *env, int config_change, uint64_t token) +static void s390_virtio_irq(CPUS390XState *env, int config_change, uint64_t token) { if (kvm_enabled()) { kvm_s390_virtio_irq(env, config_change, token); @@ -116,7 +116,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev) s390_virtio_device_sync(dev); if (dev->qdev.hotplugged) { - CPUState *env = s390_cpu_addr2state(0); + CPUS390XState *env = s390_cpu_addr2state(0); s390_virtio_irq(env, VIRTIO_PARAM_DEV_ADD, dev->dev_offs); } @@ -331,7 +331,7 @@ static void virtio_s390_notify(void *opaque, uint16_t vector) { VirtIOS390Device *dev = (VirtIOS390Device*)opaque; uint64_t token = s390_virtio_device_vq_token(dev, vector); - CPUState *env = s390_cpu_addr2state(0); + CPUS390XState *env = s390_cpu_addr2state(0); s390_virtio_irq(env, 0, token); } diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index 15e3ef389a..1ebe70d0e3 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -61,9 +61,9 @@ #define MAX_BLK_DEVS 10 static VirtIOS390Bus *s390_bus; -static CPUState **ipi_states; +static CPUS390XState **ipi_states; -CPUState *s390_cpu_addr2state(uint16_t cpu_addr) +CPUS390XState *s390_cpu_addr2state(uint16_t cpu_addr) { if (cpu_addr >= smp_cpus) { return NULL; @@ -72,7 +72,7 @@ CPUState *s390_cpu_addr2state(uint16_t cpu_addr) return ipi_states[cpu_addr]; } -int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall) +int s390_virtio_hypercall(CPUS390XState *env, uint64_t mem, uint64_t hypercall) { int r = 0, i; @@ -129,7 +129,7 @@ int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall) */ static unsigned s390_running_cpus; -void s390_add_running_cpu(CPUState *env) +void s390_add_running_cpu(CPUS390XState *env) { if (env->halted) { s390_running_cpus++; @@ -138,7 +138,7 @@ void s390_add_running_cpu(CPUState *env) } } -unsigned s390_del_running_cpu(CPUState *env) +unsigned s390_del_running_cpu(CPUS390XState *env) { if (env->halted == 0) { assert(s390_running_cpus >= 1); @@ -157,7 +157,7 @@ static void s390_init(ram_addr_t my_ram_size, const char *initrd_filename, const char *cpu_model) { - CPUState *env = NULL; + CPUS390XState *env = NULL; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); ram_addr_t kernel_size = 0; @@ -205,10 +205,10 @@ static void s390_init(ram_addr_t my_ram_size, cpu_model = "host"; } - ipi_states = g_malloc(sizeof(CPUState *) * smp_cpus); + ipi_states = g_malloc(sizeof(CPUS390XState *) * smp_cpus); for (i = 0; i < smp_cpus; i++) { - CPUState *tmp_env; + CPUS390XState *tmp_env; tmp_env = cpu_init(cpu_model); if (!env) { diff --git a/hw/sh.h b/hw/sh.h index 6488db25c4..40df18c5dc 100644 --- a/hw/sh.h +++ b/hw/sh.h @@ -11,7 +11,7 @@ struct SH7750State; struct MemoryRegion; -struct SH7750State *sh7750_init(CPUState * cpu, struct MemoryRegion *sysmem); +struct SH7750State *sh7750_init(CPUSH4State * cpu, struct MemoryRegion *sysmem); typedef struct { /* The callback will be triggered if any of the designated lines change */ diff --git a/hw/shix.c b/hw/shix.c index e259c17c52..dd9ce174f9 100644 --- a/hw/shix.c +++ b/hw/shix.c @@ -43,7 +43,7 @@ static void shix_init(ram_addr_t ram_size, const char *initrd_filename, const char *cpu_model) { int ret; - CPUState *env; + CPUSH4State *env; struct SH7750State *s; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *rom = g_new(MemoryRegion, 1); diff --git a/hw/spapr.c b/hw/spapr.c index dffb6a2a50..3719e0e4a7 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -110,7 +110,7 @@ qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num) static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr) { int ret = 0, offset; - CPUState *env; + CPUPPCState *env; char cpu_model[32]; int smt = kvmppc_smt_threads(); @@ -155,7 +155,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model, long hash_shift) { void *fdt; - CPUState *env; + CPUPPCState *env; uint64_t mem_reg_property[2]; uint32_t start_prop = cpu_to_be32(initrd_base); uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size); @@ -476,7 +476,7 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr) return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR; } -static void emulate_spapr_hypercall(CPUState *env) +static void emulate_spapr_hypercall(CPUPPCState *env) { env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]); } @@ -502,6 +502,13 @@ static void spapr_reset(void *opaque) } +static void spapr_cpu_reset(void *opaque) +{ + CPUPPCState *env = opaque; + + cpu_state_reset(env); +} + /* pSeries LPAR / sPAPR hardware init */ static void ppc_spapr_init(ram_addr_t ram_size, const char *boot_device, @@ -510,7 +517,7 @@ static void ppc_spapr_init(ram_addr_t ram_size, const char *initrd_filename, const char *cpu_model) { - CPUState *env; + CPUPPCState *env; int i; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); @@ -560,7 +567,7 @@ static void ppc_spapr_init(ram_addr_t ram_size, } /* Set time-base frequency to 512 MHz */ cpu_ppc_tb_init(env, TIMEBASE_FREQ); - qemu_register_reset((QEMUResetHandler *)&cpu_reset, env); + qemu_register_reset(spapr_cpu_reset, env); env->hreset_vector = 0x60; env->hreset_excp_prefix = 0; diff --git a/hw/spapr.h b/hw/spapr.h index e946a3433e..a41641fdde 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -278,12 +278,12 @@ extern sPAPREnvironment *spapr; do { } while (0) #endif -typedef target_ulong (*spapr_hcall_fn)(CPUState *env, sPAPREnvironment *spapr, +typedef target_ulong (*spapr_hcall_fn)(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args); void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn); -target_ulong spapr_hypercall(CPUState *env, target_ulong opcode, +target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode, target_ulong *args); qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num); diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c index 6ac7384013..634763eefd 100644 --- a/hw/spapr_hcall.c +++ b/hw/spapr_hcall.c @@ -92,7 +92,7 @@ static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r, return rb; } -static target_ulong h_enter(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_enter(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong flags = args[0]; @@ -181,7 +181,7 @@ enum { REMOVE_HW = 3, }; -static target_ulong remove_hpte(CPUState *env, target_ulong ptex, +static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex, target_ulong avpn, target_ulong flags, target_ulong *vp, target_ulong *rp) @@ -219,7 +219,7 @@ static target_ulong remove_hpte(CPUState *env, target_ulong ptex, return REMOVE_SUCCESS; } -static target_ulong h_remove(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_remove(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong flags = args[0]; @@ -265,7 +265,7 @@ static target_ulong h_remove(CPUState *env, sPAPREnvironment *spapr, #define H_BULK_REMOVE_MAX_BATCH 4 -static target_ulong h_bulk_remove(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_bulk_remove(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { int i; @@ -311,7 +311,7 @@ static target_ulong h_bulk_remove(CPUState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -static target_ulong h_protect(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_protect(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong flags = args[0]; @@ -356,7 +356,7 @@ static target_ulong h_protect(CPUState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -static target_ulong h_set_dabr(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_set_dabr(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { /* FIXME: actually implement this */ @@ -375,7 +375,7 @@ static target_ulong h_set_dabr(CPUState *env, sPAPREnvironment *spapr, #define VPA_SHARED_PROC_OFFSET 0x9 #define VPA_SHARED_PROC_VAL 0x2 -static target_ulong register_vpa(CPUState *env, target_ulong vpa) +static target_ulong register_vpa(CPUPPCState *env, target_ulong vpa) { uint16_t size; uint8_t tmp; @@ -410,7 +410,7 @@ static target_ulong register_vpa(CPUState *env, target_ulong vpa) return H_SUCCESS; } -static target_ulong deregister_vpa(CPUState *env, target_ulong vpa) +static target_ulong deregister_vpa(CPUPPCState *env, target_ulong vpa) { if (env->slb_shadow) { return H_RESOURCE; @@ -424,7 +424,7 @@ static target_ulong deregister_vpa(CPUState *env, target_ulong vpa) return H_SUCCESS; } -static target_ulong register_slb_shadow(CPUState *env, target_ulong addr) +static target_ulong register_slb_shadow(CPUPPCState *env, target_ulong addr) { uint32_t size; @@ -451,13 +451,13 @@ static target_ulong register_slb_shadow(CPUState *env, target_ulong addr) return H_SUCCESS; } -static target_ulong deregister_slb_shadow(CPUState *env, target_ulong addr) +static target_ulong deregister_slb_shadow(CPUPPCState *env, target_ulong addr) { env->slb_shadow = 0; return H_SUCCESS; } -static target_ulong register_dtl(CPUState *env, target_ulong addr) +static target_ulong register_dtl(CPUPPCState *env, target_ulong addr) { uint32_t size; @@ -482,7 +482,7 @@ static target_ulong register_dtl(CPUState *env, target_ulong addr) return H_SUCCESS; } -static target_ulong deregister_dtl(CPUState *emv, target_ulong addr) +static target_ulong deregister_dtl(CPUPPCState *emv, target_ulong addr) { env->dispatch_trace_log = 0; env->dtl_size = 0; @@ -490,14 +490,14 @@ static target_ulong deregister_dtl(CPUState *emv, target_ulong addr) return H_SUCCESS; } -static target_ulong h_register_vpa(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_register_vpa(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong flags = args[0]; target_ulong procno = args[1]; target_ulong vpa = args[2]; target_ulong ret = H_PARAMETER; - CPUState *tenv; + CPUPPCState *tenv; for (tenv = first_cpu; tenv; tenv = tenv->next_cpu) { if (tenv->cpu_index == procno) { @@ -538,7 +538,7 @@ static target_ulong h_register_vpa(CPUState *env, sPAPREnvironment *spapr, return ret; } -static target_ulong h_cede(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_cede(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { env->msr |= (1ULL << MSR_EE); @@ -549,7 +549,7 @@ static target_ulong h_cede(CPUState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -static target_ulong h_rtas(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_rtas(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong rtas_r3 = args[0]; @@ -561,7 +561,7 @@ static target_ulong h_rtas(CPUState *env, sPAPREnvironment *spapr, nret, rtas_r3 + 12 + 4*nargs); } -static target_ulong h_logical_load(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_logical_load(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong size = args[0]; @@ -584,7 +584,7 @@ static target_ulong h_logical_load(CPUState *env, sPAPREnvironment *spapr, return H_PARAMETER; } -static target_ulong h_logical_store(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_logical_store(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong size = args[0]; @@ -608,14 +608,14 @@ static target_ulong h_logical_store(CPUState *env, sPAPREnvironment *spapr, return H_PARAMETER; } -static target_ulong h_logical_icbi(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_logical_icbi(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { /* Nothing to do on emulation, KVM will trap this in the kernel */ return H_SUCCESS; } -static target_ulong h_logical_dcbf(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_logical_dcbf(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { /* Nothing to do on emulation, KVM will trap this in the kernel */ @@ -644,7 +644,7 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn) *slot = fn; } -target_ulong spapr_hypercall(CPUState *env, target_ulong opcode, +target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode, target_ulong *args) { if (msr_pr) { diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c index 77d40479c8..cfc777804b 100644 --- a/hw/spapr_llan.c +++ b/hw/spapr_llan.c @@ -254,7 +254,7 @@ static int check_bd(VIOsPAPRVLANDevice *dev, vlan_bd_t bd, return 0; } -static target_ulong h_register_logical_lan(CPUState *env, +static target_ulong h_register_logical_lan(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) @@ -320,7 +320,7 @@ static target_ulong h_register_logical_lan(CPUState *env, } -static target_ulong h_free_logical_lan(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_free_logical_lan(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; @@ -343,7 +343,7 @@ static target_ulong h_free_logical_lan(CPUState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -static target_ulong h_add_logical_lan_buffer(CPUState *env, +static target_ulong h_add_logical_lan_buffer(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) @@ -392,7 +392,7 @@ static target_ulong h_add_logical_lan_buffer(CPUState *env, return H_SUCCESS; } -static target_ulong h_send_logical_lan(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_send_logical_lan(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; @@ -461,7 +461,7 @@ static target_ulong h_send_logical_lan(CPUState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -static target_ulong h_multicast_ctrl(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_multicast_ctrl(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c index c0723b3039..09465853ba 100644 --- a/hw/spapr_rtas.c +++ b/hw/spapr_rtas.c @@ -118,7 +118,7 @@ static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr, uint32_t nret, target_ulong rets) { target_ulong id; - CPUState *env; + CPUPPCState *env; if (nargs != 1 || nret != 2) { rtas_st(rets, 0, -3); @@ -151,7 +151,7 @@ static void rtas_start_cpu(sPAPREnvironment *spapr, uint32_t nret, target_ulong rets) { target_ulong id, start, r3; - CPUState *env; + CPUPPCState *env; if (nargs != 3 || nret != 1) { rtas_st(rets, 0, -3); diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index ea317efbe4..2fb3cee266 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -194,7 +194,7 @@ static void rtce_init(VIOsPAPRDevice *dev) } } -static target_ulong h_put_tce(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong liobn = args[0]; @@ -405,7 +405,7 @@ uint64_t ldq_tce(VIOsPAPRDevice *dev, uint64_t taddr) /* * CRQ handling */ -static target_ulong h_reg_crq(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; @@ -453,7 +453,7 @@ static target_ulong h_reg_crq(CPUState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -static target_ulong h_free_crq(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; @@ -474,7 +474,7 @@ static target_ulong h_free_crq(CPUState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -static target_ulong h_send_crq(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_send_crq(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; @@ -498,7 +498,7 @@ static target_ulong h_send_crq(CPUState *env, sPAPREnvironment *spapr, return H_HARDWARE; } -static target_ulong h_enable_crq(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_enable_crq(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; @@ -680,7 +680,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev) return pc->init(dev); } -static target_ulong h_vio_signal(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_vio_signal(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c index 3efe24211e..60e22b1600 100644 --- a/hw/spapr_vty.c +++ b/hw/spapr_vty.c @@ -72,7 +72,7 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev) /* Forward declaration */ static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg); -static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_put_term_char(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; @@ -99,7 +99,7 @@ static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -static target_ulong h_get_term_char(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_get_term_char(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong reg = args[0]; diff --git a/hw/strongarm.h b/hw/strongarm.h index 684f61bee3..02acac3db1 100644 --- a/hw/strongarm.h +++ b/hw/strongarm.h @@ -53,7 +53,7 @@ enum { }; typedef struct { - CPUState *env; + CPUARMState *env; MemoryRegion sdram; DeviceState *pic; DeviceState *gpio; diff --git a/hw/sun4m.c b/hw/sun4m.c index 99fb219b3a..7bcbf37e98 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -228,7 +228,7 @@ void sun4m_irq_info(Monitor *mon) slavio_irq_info(mon, slavio_intctl); } -void cpu_check_irqs(CPUState *env) +void cpu_check_irqs(CPUSPARCState *env) { if (env->pil_in && (env->interrupt_index == 0 || (env->interrupt_index & ~15) == TT_EXTINT)) { @@ -253,7 +253,7 @@ void cpu_check_irqs(CPUState *env) } } -static void cpu_kick_irq(CPUState *env) +static void cpu_kick_irq(CPUSPARCState *env) { env->halted = 0; cpu_check_irqs(env); @@ -262,7 +262,7 @@ static void cpu_kick_irq(CPUState *env) static void cpu_set_irq(void *opaque, int irq, int level) { - CPUState *env = opaque; + CPUSPARCState *env = opaque; if (level) { trace_sun4m_cpu_set_irq_raise(irq); @@ -281,17 +281,17 @@ static void dummy_cpu_set_irq(void *opaque, int irq, int level) static void main_cpu_reset(void *opaque) { - CPUState *env = opaque; + CPUSPARCState *env = opaque; - cpu_reset(env); + cpu_state_reset(env); env->halted = 0; } static void secondary_cpu_reset(void *opaque) { - CPUState *env = opaque; + CPUSPARCState *env = opaque; - cpu_reset(env); + cpu_state_reset(env); env->halted = 1; } @@ -809,7 +809,7 @@ static TypeInfo ram_info = { static void cpu_devinit(const char *cpu_model, unsigned int id, uint64_t prom_addr, qemu_irq **cpu_irqs) { - CPUState *env; + CPUSPARCState *env; env = cpu_init(cpu_model); if (!env) { diff --git a/hw/sun4u.c b/hw/sun4u.c index 423108f236..c32eddb31f 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -243,7 +243,7 @@ static unsigned long sun4u_load_kernel(const char *kernel_filename, return kernel_size; } -void cpu_check_irqs(CPUState *env) +void cpu_check_irqs(CPUSPARCState *env) { uint32_t pil = env->pil_in | (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER)); @@ -297,7 +297,7 @@ void cpu_check_irqs(CPUState *env) } } -static void cpu_kick_irq(CPUState *env) +static void cpu_kick_irq(CPUSPARCState *env) { env->halted = 0; cpu_check_irqs(env); @@ -306,7 +306,7 @@ static void cpu_kick_irq(CPUState *env) static void cpu_set_irq(void *opaque, int irq, int level) { - CPUState *env = opaque; + CPUSPARCState *env = opaque; if (level) { CPUIRQ_DPRINTF("Raise CPU IRQ %d\n", irq); @@ -320,7 +320,7 @@ static void cpu_set_irq(void *opaque, int irq, int level) } typedef struct ResetData { - CPUState *env; + CPUSPARCState *env; uint64_t prom_addr; } ResetData; @@ -344,7 +344,7 @@ void cpu_get_timer(QEMUFile *f, CPUTimer *s) qemu_get_timer(f, s->qtimer); } -static CPUTimer* cpu_timer_create(const char* name, CPUState *env, +static CPUTimer* cpu_timer_create(const char* name, CPUSPARCState *env, QEMUBHFunc *cb, uint32_t frequency, uint64_t disabled_mask) { @@ -373,10 +373,10 @@ static void cpu_timer_reset(CPUTimer *timer) static void main_cpu_reset(void *opaque) { ResetData *s = (ResetData *)opaque; - CPUState *env = s->env; + CPUSPARCState *env = s->env; static unsigned int nr_resets; - cpu_reset(env); + cpu_state_reset(env); cpu_timer_reset(env->tick); cpu_timer_reset(env->stick); @@ -396,7 +396,7 @@ static void main_cpu_reset(void *opaque) static void tick_irq(void *opaque) { - CPUState *env = opaque; + CPUSPARCState *env = opaque; CPUTimer* timer = env->tick; @@ -413,7 +413,7 @@ static void tick_irq(void *opaque) static void stick_irq(void *opaque) { - CPUState *env = opaque; + CPUSPARCState *env = opaque; CPUTimer* timer = env->stick; @@ -430,7 +430,7 @@ static void stick_irq(void *opaque) static void hstick_irq(void *opaque) { - CPUState *env = opaque; + CPUSPARCState *env = opaque; CPUTimer* timer = env->hstick; @@ -714,9 +714,9 @@ static TypeInfo ram_info = { .class_init = ram_class_init, }; -static CPUState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef) +static CPUSPARCState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef) { - CPUState *env; + CPUSPARCState *env; ResetData *reset_info; uint32_t tick_frequency = 100*1000000; @@ -755,7 +755,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, const char *initrd_filename, const char *cpu_model, const struct hwdef *hwdef) { - CPUState *env; + CPUSPARCState *env; M48t59State *nvram; unsigned int i; long initrd_size, kernel_size; diff --git a/hw/usb-ohci.h b/hw/usb-ohci.h deleted file mode 100644 index eefcef3602..0000000000 --- a/hw/usb-ohci.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef QEMU_USB_OHCI_H -#define QEMU_USB_OHCI_H - -#include "qemu-common.h" - -void usb_ohci_init_pci(struct PCIBus *bus, int devfn); - -#endif - diff --git a/hw/usb-uhci.h b/hw/usb-uhci.h deleted file mode 100644 index 3e4d3777d4..0000000000 --- a/hw/usb-uhci.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef QEMU_USB_UHCI_H -#define QEMU_USB_UHCI_H - -#include "qemu-common.h" - -void usb_uhci_piix3_init(PCIBus *bus, int devfn); -void usb_uhci_piix4_init(PCIBus *bus, int devfn); -void usb_uhci_vt82c686b_init(PCIBus *bus, int devfn); - -#endif diff --git a/hw/usb.h b/hw/usb.h index d60d03df9c..e95085f0b3 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -336,6 +336,7 @@ struct USBPacket { void usb_packet_init(USBPacket *p); void usb_packet_set_state(USBPacket *p, USBPacketState state); +void usb_packet_check_state(USBPacket *p, USBPacketState expected); void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep); void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len); int usb_packet_map(USBPacket *p, QEMUSGList *sgl); diff --git a/hw/usb-bus.c b/hw/usb/bus.c index 70b7ebc086..d3f835895d 100644 --- a/hw/usb-bus.c +++ b/hw/usb/bus.c @@ -1,6 +1,6 @@ -#include "hw.h" -#include "usb.h" -#include "qdev.h" +#include "hw/hw.h" +#include "hw/usb.h" +#include "hw/qdev.h" #include "sysemu.h" #include "monitor.h" #include "trace.h" diff --git a/hw/usb.c b/hw/usb/core.c index 1ec2e90ef7..a4048fe3e0 100644 --- a/hw/usb.c +++ b/hw/usb/core.c @@ -24,7 +24,7 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "usb.h" +#include "hw/usb.h" #include "iov.h" #include "trace.h" @@ -378,7 +378,7 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) } assert(dev == p->ep->dev); assert(dev->state == USB_STATE_DEFAULT); - assert(p->state == USB_PACKET_SETUP); + usb_packet_check_state(p, USB_PACKET_SETUP); assert(p->ep != NULL); if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) { @@ -406,7 +406,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p) USBEndpoint *ep = p->ep; int ret; - assert(p->state == USB_PACKET_ASYNC); + usb_packet_check_state(p, USB_PACKET_ASYNC); assert(QTAILQ_FIRST(&ep->queue) == p); usb_packet_set_state(p, USB_PACKET_COMPLETE); QTAILQ_REMOVE(&ep->queue, p, queue); @@ -417,7 +417,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p) if (p->state == USB_PACKET_ASYNC) { break; } - assert(p->state == USB_PACKET_QUEUED); + usb_packet_check_state(p, USB_PACKET_QUEUED); ret = usb_process_one(p); if (ret == USB_RET_ASYNC) { usb_packet_set_state(p, USB_PACKET_ASYNC); @@ -450,7 +450,7 @@ void usb_packet_init(USBPacket *p) qemu_iovec_init(&p->iov, 1); } -void usb_packet_set_state(USBPacket *p, USBPacketState state) +static const char *usb_packet_state_name(USBPacketState state) { static const char *name[] = { [USB_PACKET_UNDEFINED] = "undef", @@ -460,11 +460,36 @@ void usb_packet_set_state(USBPacket *p, USBPacketState state) [USB_PACKET_COMPLETE] = "complete", [USB_PACKET_CANCELED] = "canceled", }; + if (state < ARRAY_SIZE(name)) { + return name[state]; + } + return "INVALID"; +} + +void usb_packet_check_state(USBPacket *p, USBPacketState expected) +{ + USBDevice *dev; + USBBus *bus; + + if (p->state == expected) { + return; + } + dev = p->ep->dev; + bus = usb_bus_from_device(dev); + trace_usb_packet_state_fault(bus->busnr, dev->port->path, p->ep->nr, p, + usb_packet_state_name(p->state), + usb_packet_state_name(expected)); + assert(!"usb packet state check failed"); +} + +void usb_packet_set_state(USBPacket *p, USBPacketState state) +{ USBDevice *dev = p->ep->dev; USBBus *bus = usb_bus_from_device(dev); - trace_usb_packet_state_change(bus->busnr, dev->port->path, p->ep->nr, - p, name[p->state], name[state]); + trace_usb_packet_state_change(bus->busnr, dev->port->path, p->ep->nr, p, + usb_packet_state_name(p->state), + usb_packet_state_name(state)); p->state = state; } diff --git a/hw/usb-desc.c b/hw/usb/desc.c index ccf85ade9e..9847a75b83 100644 --- a/hw/usb-desc.c +++ b/hw/usb/desc.c @@ -1,5 +1,5 @@ -#include "usb.h" -#include "usb-desc.h" +#include "hw/usb.h" +#include "hw/usb/desc.h" #include "trace.h" /* ------------------------------------------------------------------ */ diff --git a/hw/usb-desc.h b/hw/usb/desc.h index d6e07ea5d2..d6e07ea5d2 100644 --- a/hw/usb-desc.h +++ b/hw/usb/desc.h diff --git a/hw/usb-audio.c b/hw/usb/dev-audio.c index fed136117b..426b95c82b 100644 --- a/hw/usb-audio.c +++ b/hw/usb/dev-audio.c @@ -30,10 +30,10 @@ */ #include "qemu-common.h" -#include "usb.h" -#include "usb-desc.h" -#include "hw.h" -#include "audiodev.h" +#include "hw/usb.h" +#include "hw/usb/desc.h" +#include "hw/hw.h" +#include "hw/audiodev.h" #include "audio/audio.h" #define USBAUDIO_VENDOR_NUM 0x46f4 /* CRC16() of "QEMU" */ diff --git a/hw/usb-bt.c b/hw/usb/dev-bluetooth.c index 23c39ecc23..195370c24a 100644 --- a/hw/usb-bt.c +++ b/hw/usb/dev-bluetooth.c @@ -19,10 +19,10 @@ */ #include "qemu-common.h" -#include "usb.h" -#include "usb-desc.h" +#include "hw/usb.h" +#include "hw/usb/desc.h" #include "net.h" -#include "bt.h" +#include "hw/bt.h" struct USBBtState { USBDevice dev; diff --git a/hw/usb-hid.c b/hw/usb/dev-hid.c index 37bca78eca..f29544d954 100644 --- a/hw/usb-hid.c +++ b/hw/usb/dev-hid.c @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "hw.h" +#include "hw/hw.h" #include "console.h" -#include "usb.h" -#include "usb-desc.h" +#include "hw/usb.h" +#include "hw/usb/desc.h" #include "qemu-timer.h" -#include "hid.h" +#include "hw/hid.h" /* HID interface requests */ #define GET_REPORT 0xa101 diff --git a/hw/usb-hub.c b/hw/usb/dev-hub.c index a12856e2e9..eb4e711207 100644 --- a/hw/usb-hub.c +++ b/hw/usb/dev-hub.c @@ -22,8 +22,8 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "usb.h" -#include "usb-desc.h" +#include "hw/usb.h" +#include "hw/usb/desc.h" //#define DEBUG diff --git a/hw/usb-net.c b/hw/usb/dev-network.c index 22b82017e3..cff55f223e 100644 --- a/hw/usb-net.c +++ b/hw/usb/dev-network.c @@ -24,8 +24,8 @@ */ #include "qemu-common.h" -#include "usb.h" -#include "usb-desc.h" +#include "hw/usb.h" +#include "hw/usb/desc.h" #include "net.h" #include "qemu-queue.h" #include "sysemu.h" diff --git a/hw/usb-serial.c b/hw/usb/dev-serial.c index 0aae379b20..8dcac8bc88 100644 --- a/hw/usb-serial.c +++ b/hw/usb/dev-serial.c @@ -10,8 +10,8 @@ #include "qemu-common.h" #include "qemu-error.h" -#include "usb.h" -#include "usb-desc.h" +#include "hw/usb.h" +#include "hw/usb/desc.h" #include "qemu-char.h" //#define DEBUG_Serial diff --git a/hw/usb-ccid.c b/hw/usb/dev-smartcard-reader.c index ced687f288..8e66675d86 100644 --- a/hw/usb-ccid.c +++ b/hw/usb/dev-smartcard-reader.c @@ -36,8 +36,8 @@ #include "qemu-common.h" #include "qemu-error.h" -#include "usb.h" -#include "usb-desc.h" +#include "hw/usb.h" +#include "hw/usb/desc.h" #include "monitor.h" #include "hw/ccid.h" diff --git a/hw/usb-msd.c b/hw/usb/dev-storage.c index c6f08a0313..bdbe7bdd11 100644 --- a/hw/usb-msd.c +++ b/hw/usb/dev-storage.c @@ -10,9 +10,9 @@ #include "qemu-common.h" #include "qemu-option.h" #include "qemu-config.h" -#include "usb.h" -#include "usb-desc.h" -#include "scsi.h" +#include "hw/usb.h" +#include "hw/usb/desc.h" +#include "hw/scsi.h" #include "console.h" #include "monitor.h" #include "sysemu.h" @@ -193,9 +193,9 @@ static void usb_msd_send_status(MSDState *s, USBPacket *p) int len; DPRINTF("Command status %d tag 0x%x, len %zd\n", - s->csw.status, s->csw.tag, p->iov.size); + s->csw.status, le32_to_cpu(s->csw.tag), p->iov.size); - assert(s->csw.sig == 0x53425355); + assert(s->csw.sig == cpu_to_le32(0x53425355)); len = MIN(sizeof(s->csw), p->iov.size); usb_packet_copy(p, &s->csw, len); memset(&s->csw, 0, sizeof(s->csw)); @@ -233,7 +233,7 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r s->csw.sig = cpu_to_le32(0x53425355); s->csw.tag = cpu_to_le32(req->tag); - s->csw.residue = s->residue; + s->csw.residue = cpu_to_le32(s->residue); s->csw.status = status != 0; if (s->packet) { diff --git a/hw/usb-wacom.c b/hw/usb/dev-wacom.c index 197e2dced5..c1cfd74403 100644 --- a/hw/usb-wacom.c +++ b/hw/usb/dev-wacom.c @@ -25,10 +25,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "hw.h" +#include "hw/hw.h" #include "console.h" -#include "usb.h" -#include "usb-desc.h" +#include "hw/usb.h" +#include "hw/usb/desc.h" /* Interface requests */ #define WACOM_GET_REPORT 0x2101 diff --git a/hw/usb-ehci.c b/hw/usb/hcd-ehci.c index df742f7f02..60f9f5bdb5 100644 --- a/hw/usb-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -22,10 +22,10 @@ * along with this program; if not, see <http://www.gnu.org/licenses/>. */ -#include "hw.h" +#include "hw/hw.h" #include "qemu-timer.h" -#include "usb.h" -#include "pci.h" +#include "hw/usb.h" +#include "hw/pci.h" #include "monitor.h" #include "trace.h" #include "dma.h" @@ -419,7 +419,6 @@ struct EHCIState { USBPacket ipacket; QEMUSGList isgl; - int isoch_pause; uint64_t last_run_ns; }; @@ -907,7 +906,6 @@ static void ehci_reset(void *opaque) s->astate = EST_INACTIVE; s->pstate = EST_INACTIVE; - s->isoch_pause = -1; s->attach_poll_counter = 0; for(i = 0; i < NB_PORTS; i++) { @@ -2150,9 +2148,7 @@ static void ehci_frame_timer(void *opaque) for (i = 0; i < frames; i++) { if ( !(ehci->usbsts & USBSTS_HALT)) { - if (ehci->isoch_pause <= 0) { - ehci->frindex += 8; - } + ehci->frindex += 8; if (ehci->frindex > 0x00001fff) { ehci->frindex = 0; diff --git a/hw/usb-musb.c b/hw/usb/hcd-musb.c index 820907a9a9..fa9385ee49 100644 --- a/hw/usb-musb.c +++ b/hw/usb/hcd-musb.c @@ -22,9 +22,9 @@ */ #include "qemu-common.h" #include "qemu-timer.h" -#include "usb.h" -#include "irq.h" -#include "hw.h" +#include "hw/usb.h" +#include "hw/irq.h" +#include "hw/hw.h" /* Common USB registers */ #define MUSB_HDRC_FADDR 0x00 /* 8-bit */ diff --git a/hw/usb-ohci.c b/hw/usb/hcd-ohci.c index 20aaa74250..1a1cc88b1f 100644 --- a/hw/usb-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -26,13 +26,12 @@ * o BIOS work to boot from USB storage */ -#include "hw.h" +#include "hw/hw.h" #include "qemu-timer.h" -#include "usb.h" -#include "pci.h" -#include "usb-ohci.h" -#include "sysbus.h" -#include "qdev-addr.h" +#include "hw/usb.h" +#include "hw/pci.h" +#include "hw/sysbus.h" +#include "hw/qdev-addr.h" //#define DEBUG_OHCI /* Dump packet contents. */ @@ -122,6 +121,11 @@ struct ohci_hcca { uint16_t frame, pad; uint32_t done; }; +#define HCCA_WRITEBACK_OFFSET offsetof(struct ohci_hcca, frame) +#define HCCA_WRITEBACK_SIZE 8 /* frame, pad, done */ + +#define ED_WBACK_OFFSET offsetof(struct ohci_ed, head) +#define ED_WBACK_SIZE 4 static void ohci_bus_stop(OHCIState *ohci); static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev); @@ -569,7 +573,13 @@ static inline int ohci_read_hcca(OHCIState *ohci, static inline int ohci_put_ed(OHCIState *ohci, uint32_t addr, struct ohci_ed *ed) { - return put_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2); + /* ed->tail is under control of the HCD. + * Since just ed->head is changed by HC, just write back this + */ + + return put_dwords(ohci, addr + ED_WBACK_OFFSET, + (uint32_t *)((char *)ed + ED_WBACK_OFFSET), + ED_WBACK_SIZE >> 2); } static inline int ohci_put_td(OHCIState *ohci, @@ -588,7 +598,9 @@ static inline int ohci_put_iso_td(OHCIState *ohci, static inline int ohci_put_hcca(OHCIState *ohci, uint32_t addr, struct ohci_hcca *hcca) { - cpu_physical_memory_write(addr + ohci->localmem_base, hcca, sizeof(*hcca)); + cpu_physical_memory_write(addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET, + (char *)hcca + HCCA_WRITEBACK_OFFSET, + HCCA_WRITEBACK_SIZE); return 1; } @@ -1815,11 +1827,6 @@ static int usb_ohci_initfn_pci(struct PCIDevice *dev) return 0; } -void usb_ohci_init_pci(struct PCIBus *bus, int devfn) -{ - pci_create_simple(bus, devfn, "pci-ohci"); -} - typedef struct { SysBusDevice busdev; OHCIState ohci; diff --git a/hw/usb-uhci.c b/hw/usb/hcd-uhci.c index 304b84b831..e55dad914c 100644 --- a/hw/usb-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -25,13 +25,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "hw.h" -#include "usb.h" -#include "pci.h" +#include "hw/hw.h" +#include "hw/usb.h" +#include "hw/pci.h" #include "qemu-timer.h" -#include "usb-uhci.h" #include "iov.h" #include "dma.h" +#include "trace.h" //#define DEBUG //#define DEBUG_DUMP_DATA @@ -77,22 +77,13 @@ #define NB_PORTS 2 -#ifdef DEBUG -#define DPRINTF printf - -static const char *pid2str(int pid) -{ - switch (pid) { - case USB_TOKEN_SETUP: return "SETUP"; - case USB_TOKEN_IN: return "IN"; - case USB_TOKEN_OUT: return "OUT"; - } - return "?"; -} - -#else -#define DPRINTF(...) -#endif +enum { + TD_RESULT_STOP_FRAME = 10, + TD_RESULT_COMPLETE, + TD_RESULT_NEXT_QH, + TD_RESULT_ASYNC_START, + TD_RESULT_ASYNC_CONT, +}; typedef struct UHCIState UHCIState; typedef struct UHCIAsync UHCIAsync; @@ -188,6 +179,7 @@ static UHCIQueue *uhci_queue_get(UHCIState *s, UHCI_TD *td) queue->token = token; QTAILQ_INIT(&queue->asyncs); QTAILQ_INSERT_HEAD(&s->queues, queue, next); + trace_usb_uhci_queue_add(queue->token); return queue; } @@ -195,23 +187,27 @@ static void uhci_queue_free(UHCIQueue *queue) { UHCIState *s = queue->uhci; + trace_usb_uhci_queue_del(queue->token); QTAILQ_REMOVE(&s->queues, queue, next); g_free(queue); } -static UHCIAsync *uhci_async_alloc(UHCIQueue *queue) +static UHCIAsync *uhci_async_alloc(UHCIQueue *queue, uint32_t addr) { UHCIAsync *async = g_new0(UHCIAsync, 1); async->queue = queue; + async->td = addr; usb_packet_init(&async->packet); pci_dma_sglist_init(&async->sgl, &queue->uhci->dev, 1); + trace_usb_uhci_packet_add(async->queue->token, async->td); return async; } static void uhci_async_free(UHCIAsync *async) { + trace_usb_uhci_packet_del(async->queue->token, async->td); usb_packet_cleanup(&async->packet); qemu_sglist_destroy(&async->sgl); g_free(async); @@ -221,19 +217,19 @@ static void uhci_async_link(UHCIAsync *async) { UHCIQueue *queue = async->queue; QTAILQ_INSERT_TAIL(&queue->asyncs, async, next); + trace_usb_uhci_packet_link_async(async->queue->token, async->td); } static void uhci_async_unlink(UHCIAsync *async) { UHCIQueue *queue = async->queue; QTAILQ_REMOVE(&queue->asyncs, async, next); + trace_usb_uhci_packet_unlink_async(async->queue->token, async->td); } static void uhci_async_cancel(UHCIAsync *async) { - DPRINTF("uhci: cancel td 0x%x token 0x%x done %u\n", - async->td, async->token, async->done); - + trace_usb_uhci_packet_cancel(async->queue->token, async->td, async->done); if (!async->done) usb_cancel_packet(&async->packet); uhci_async_free(async); @@ -300,6 +296,7 @@ static void uhci_async_cancel_all(UHCIState *s) uhci_async_unlink(curr); uhci_async_cancel(curr); } + uhci_queue_free(queue); } } @@ -350,7 +347,7 @@ static void uhci_reset(void *opaque) int i; UHCIPort *port; - DPRINTF("uhci: full reset\n"); + trace_usb_uhci_reset(); pci_conf = s->dev.config; @@ -450,12 +447,13 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val) UHCIState *s = opaque; addr &= 0x1f; - DPRINTF("uhci: writew port=0x%04x val=0x%04x\n", addr, val); + trace_usb_uhci_mmio_writew(addr, val); switch(addr) { case 0x00: if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) { /* start frame processing */ + trace_usb_uhci_schedule_start(); s->expire_time = qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() / FRAME_TIMER_FREQ); qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock)); @@ -560,7 +558,7 @@ static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr) break; } - DPRINTF("uhci: readw port=0x%04x val=0x%04x\n", addr, val); + trace_usb_uhci_mmio_readw(addr, val); return val; } @@ -570,7 +568,7 @@ static void uhci_ioport_writel(void *opaque, uint32_t addr, uint32_t val) UHCIState *s = opaque; addr &= 0x1f; - DPRINTF("uhci: writel port=0x%04x val=0x%08x\n", addr, val); + trace_usb_uhci_mmio_writel(addr, val); switch(addr) { case 0x08: @@ -593,6 +591,7 @@ static uint32_t uhci_ioport_readl(void *opaque, uint32_t addr) val = 0xffffffff; break; } + trace_usb_uhci_mmio_readl(addr, val); return val; } @@ -728,13 +727,15 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_ if ((td->ctrl & TD_CTRL_SPD) && len < max_len) { *int_mask |= 0x02; /* short packet: do not update QH */ - DPRINTF("uhci: short packet. td 0x%x token 0x%x\n", async->td, async->token); - return 1; + trace_usb_uhci_packet_complete_shortxfer(async->queue->token, + async->td); + return TD_RESULT_NEXT_QH; } } /* success */ - return 0; + trace_usb_uhci_packet_complete_success(async->queue->token, async->td); + return TD_RESULT_COMPLETE; out: switch(ret) { @@ -746,7 +747,8 @@ out: *int_mask |= 0x01; } uhci_update_irq(s); - return 1; + trace_usb_uhci_packet_complete_stall(async->queue->token, async->td); + return TD_RESULT_NEXT_QH; case USB_RET_BABBLE: td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL; @@ -757,13 +759,14 @@ out: } uhci_update_irq(s); /* frame interrupted */ - return -1; + trace_usb_uhci_packet_complete_babble(async->queue->token, async->td); + return TD_RESULT_STOP_FRAME; case USB_RET_NAK: td->ctrl |= TD_CTRL_NAK; if (pid == USB_TOKEN_SETUP) break; - return 1; + return TD_RESULT_NEXT_QH; case USB_RET_IOERROR: case USB_RET_NODEV: @@ -783,11 +786,13 @@ out: if (td->ctrl & TD_CTRL_IOC) *int_mask |= 0x01; uhci_update_irq(s); + trace_usb_uhci_packet_complete_error(async->queue->token, + async->td); } } td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) | (err << TD_CTRL_ERROR_SHIFT); - return 1; + return TD_RESULT_NEXT_QH; } static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *int_mask) @@ -800,7 +805,7 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in /* Is active ? */ if (!(td->ctrl & TD_CTRL_ACTIVE)) - return 1; + return TD_RESULT_NEXT_QH; async = uhci_async_find_td(s, addr, td); if (async) { @@ -808,22 +813,19 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in async->queue->valid = 32; if (!async->done) - return 1; + return TD_RESULT_ASYNC_CONT; uhci_async_unlink(async); goto done; } /* Allocate new packet */ - async = uhci_async_alloc(uhci_queue_get(s, td)); - if (!async) - return 1; + async = uhci_async_alloc(uhci_queue_get(s, td), addr); /* valid needs to be large enough to handle 10 frame delay * for initial isochronous requests */ async->queue->valid = 32; - async->td = addr; async->isoc = td->ctrl & TD_CTRL_IOS; max_len = ((td->token >> 21) + 1) & 0x7ff; @@ -852,12 +854,12 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in uhci_async_free(async); s->status |= UHCI_STS_HCPERR; uhci_update_irq(s); - return -1; + return TD_RESULT_STOP_FRAME; } if (len == USB_RET_ASYNC) { uhci_async_link(async); - return 2; + return TD_RESULT_ASYNC_START; } async->packet.result = len; @@ -874,8 +876,6 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet) UHCIAsync *async = container_of(packet, UHCIAsync, packet); UHCIState *s = async->queue->uhci; - DPRINTF("uhci: async complete. td 0x%x token 0x%x\n", async->td, async->token); - if (async->isoc) { UHCI_TD td; uint32_t link = async->td; @@ -963,8 +963,9 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td) if (uhci_queue_token(&ptd) != token) { break; } + trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token); ret = uhci_handle_td(s, plink, &ptd, &int_mask); - assert(ret == 2); /* got USB_RET_ASYNC */ + assert(ret == TD_RESULT_ASYNC_START); assert(int_mask == 0); plink = ptd.link; } @@ -981,8 +982,6 @@ static void uhci_process_frame(UHCIState *s) frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2); - DPRINTF("uhci: processing frame %d addr 0x%x\n" , s->frnum, frame_addr); - pci_dma_read(&s->dev, frame_addr, &link, 4); le32_to_cpus(&link); @@ -994,6 +993,7 @@ static void uhci_process_frame(UHCIState *s) for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) { if (is_qh(link)) { /* QH */ + trace_usb_uhci_qh_load(link & ~0xf); if (qhdb_insert(&qhdb, link)) { /* @@ -1006,14 +1006,14 @@ static void uhci_process_frame(UHCIState *s) * (b) we've reached the usb 1.1 bandwidth, which is * 1280 bytes/frame. */ - DPRINTF("uhci: detected loop. qh 0x%x\n", link); if (td_count == 0) { - DPRINTF("uhci: no transaction last round, stop\n"); + trace_usb_uhci_frame_loop_stop_idle(); break; } else if (bytes_count >= 1280) { - DPRINTF("uhci: bandwidth limit reached, stop\n"); + trace_usb_uhci_frame_loop_stop_bandwidth(); break; } else { + trace_usb_uhci_frame_loop_continue(); td_count = 0; qhdb_reset(&qhdb); qhdb_insert(&qhdb, link); @@ -1024,9 +1024,6 @@ static void uhci_process_frame(UHCIState *s) le32_to_cpus(&qh.link); le32_to_cpus(&qh.el_link); - DPRINTF("uhci: QH 0x%x load. link 0x%x elink 0x%x\n", - link, qh.link, qh.el_link); - if (!is_valid(qh.el_link)) { /* QH w/o elements */ curr_qh = 0; @@ -1045,9 +1042,7 @@ static void uhci_process_frame(UHCIState *s) le32_to_cpus(&td.ctrl); le32_to_cpus(&td.token); le32_to_cpus(&td.buffer); - - DPRINTF("uhci: TD 0x%x load. link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n", - link, td.link, td.ctrl, td.token, curr_qh); + trace_usb_uhci_td_load(curr_qh & ~0xf, link & ~0xf, td.ctrl, td.token); old_td_ctrl = td.ctrl; ret = uhci_handle_td(s, link, &td, &int_mask); @@ -1058,31 +1053,25 @@ static void uhci_process_frame(UHCIState *s) } switch (ret) { - case -1: /* interrupted frame */ + case TD_RESULT_STOP_FRAME: /* interrupted frame */ goto out; - case 1: /* goto next queue */ - DPRINTF("uhci: TD 0x%x skip. " - "link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n", - link, td.link, td.ctrl, td.token, curr_qh); + case TD_RESULT_NEXT_QH: + case TD_RESULT_ASYNC_CONT: + trace_usb_uhci_td_nextqh(curr_qh & ~0xf, link & ~0xf); link = curr_qh ? qh.link : td.link; continue; - case 2: /* got USB_RET_ASYNC */ - DPRINTF("uhci: TD 0x%x async. " - "link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n", - link, td.link, td.ctrl, td.token, curr_qh); + case TD_RESULT_ASYNC_START: + trace_usb_uhci_td_async(curr_qh & ~0xf, link & ~0xf); if (is_valid(td.link)) { uhci_fill_queue(s, &td); } link = curr_qh ? qh.link : td.link; continue; - case 0: /* completed TD */ - DPRINTF("uhci: TD 0x%x done. " - "link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n", - link, td.link, td.ctrl, td.token, curr_qh); - + case TD_RESULT_COMPLETE: + trace_usb_uhci_td_complete(curr_qh & ~0xf, link & ~0xf); link = td.link; td_count++; bytes_count += (td.ctrl & 0x7ff) + 1; @@ -1095,10 +1084,6 @@ static void uhci_process_frame(UHCIState *s) if (!depth_first(link)) { /* done with this QH */ - - DPRINTF("uhci: QH 0x%x done. link 0x%x elink 0x%x\n", - curr_qh, qh.link, qh.el_link); - curr_qh = 0; link = qh.link; } @@ -1125,11 +1110,11 @@ static void uhci_frame_timer(void *opaque) if (!(s->cmd & UHCI_CMD_RS)) { /* Full stop */ + trace_usb_uhci_schedule_stop(); qemu_del_timer(s->frame_timer); + uhci_async_cancel_all(s); /* set hchalted bit in status - UHCI11D 2.1.2 */ s->status |= UHCI_STS_HCHALTED; - - DPRINTF("uhci: halted\n"); return; } @@ -1144,7 +1129,7 @@ static void uhci_frame_timer(void *opaque) /* Start new frame */ s->frnum = (s->frnum + 1) & 0x7ff; - DPRINTF("uhci: new frame #%u\n" , s->frnum); + trace_usb_uhci_frame_start(s->frnum); uhci_async_validate_begin(s); @@ -1391,18 +1376,3 @@ static void uhci_register_types(void) } type_init(uhci_register_types) - -void usb_uhci_piix3_init(PCIBus *bus, int devfn) -{ - pci_create_simple(bus, devfn, "piix3-usb-uhci"); -} - -void usb_uhci_piix4_init(PCIBus *bus, int devfn) -{ - pci_create_simple(bus, devfn, "piix4-usb-uhci"); -} - -void usb_uhci_vt82c686b_init(PCIBus *bus, int devfn) -{ - pci_create_simple(bus, devfn, "vt82c686b-usb-uhci"); -} diff --git a/hw/usb-xhci.c b/hw/usb/hcd-xhci.c index e8f1b6e3a5..73b0c7f5e5 100644 --- a/hw/usb-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -18,12 +18,12 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ -#include "hw.h" +#include "hw/hw.h" #include "qemu-timer.h" -#include "usb.h" -#include "pci.h" -#include "qdev-addr.h" -#include "msi.h" +#include "hw/usb.h" +#include "hw/pci.h" +#include "hw/qdev-addr.h" +#include "hw/msi.h" //#define DEBUG_XHCI //#define DEBUG_DATA diff --git a/hw/usb/host-bsd.c b/hw/usb/host-bsd.c new file mode 100644 index 0000000000..ec26266620 --- /dev/null +++ b/hw/usb/host-bsd.c @@ -0,0 +1,647 @@ +/* + * BSD host USB redirector + * + * Copyright (c) 2006 Lonnie Mendez + * Portions of code and concepts borrowed from + * usb-linux.c and libusb's bsd.c and are copyright their respective owners. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu-common.h" +#include "monitor.h" +#include "hw/usb.h" + +/* usb.h declares these */ +#undef USB_SPEED_HIGH +#undef USB_SPEED_FULL +#undef USB_SPEED_LOW + +#include <sys/ioctl.h> +#ifndef __DragonFly__ +#include <dev/usb/usb.h> +#else +#include <bus/usb/usb.h> +#endif + +/* This value has maximum potential at 16. + * You should also set hw.usb.debug to gain + * more detailed view. + */ +//#define DEBUG +#define UGEN_DEBUG_LEVEL 0 + + +typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id, + int vendor_id, int product_id, + const char *product_name, int speed); +static int usb_host_find_device(int *pbus_num, int *paddr, + const char *devname); + +typedef struct USBHostDevice { + USBDevice dev; + int ep_fd[USB_MAX_ENDPOINTS]; + int devfd; + char devpath[32]; +} USBHostDevice; + + +static int ensure_ep_open(USBHostDevice *dev, int ep, int mode) +{ + char buf[32]; + int fd; + + /* Get the address for this endpoint */ + ep = UE_GET_ADDR(ep); + + if (dev->ep_fd[ep] < 0) { +#if defined(__FreeBSD__) || defined(__DragonFly__) + snprintf(buf, sizeof(buf) - 1, "%s.%d", dev->devpath, ep); +#else + snprintf(buf, sizeof(buf) - 1, "%s.%02d", dev->devpath, ep); +#endif + /* Try to open it O_RDWR first for those devices which have in and out + * endpoints with the same address (eg 0x02 and 0x82) + */ + fd = open(buf, O_RDWR); + if (fd < 0 && errno == ENXIO) + fd = open(buf, mode); + if (fd < 0) { +#ifdef DEBUG + printf("ensure_ep_open: failed to open device endpoint %s: %s\n", + buf, strerror(errno)); +#endif + } + dev->ep_fd[ep] = fd; + } + + return dev->ep_fd[ep]; +} + +static void ensure_eps_closed(USBHostDevice *dev) +{ + int epnum = 1; + + if (!dev) + return; + + while (epnum < USB_MAX_ENDPOINTS) { + if (dev->ep_fd[epnum] >= 0) { + close(dev->ep_fd[epnum]); + dev->ep_fd[epnum] = -1; + } + epnum++; + } +} + +static void usb_host_handle_reset(USBDevice *dev) +{ +#if 0 + USBHostDevice *s = (USBHostDevice *)dev; +#endif +} + +/* XXX: + * -check device states against transfer requests + * and return appropriate response + */ +static int usb_host_handle_control(USBDevice *dev, + USBPacket *p, + int request, + int value, + int index, + int length, + uint8_t *data) +{ + USBHostDevice *s = (USBHostDevice *)dev; + struct usb_ctl_request req; + struct usb_alt_interface aiface; + int ret, timeout = 50; + + if ((request >> 8) == UT_WRITE_DEVICE && + (request & 0xff) == UR_SET_ADDRESS) { + + /* specific SET_ADDRESS support */ + dev->addr = value; + return 0; + } else if ((request >> 8) == UT_WRITE_DEVICE && + (request & 0xff) == UR_SET_CONFIG) { + + ensure_eps_closed(s); /* can't do this without all eps closed */ + + ret = ioctl(s->devfd, USB_SET_CONFIG, &value); + if (ret < 0) { +#ifdef DEBUG + printf("handle_control: failed to set configuration - %s\n", + strerror(errno)); +#endif + return USB_RET_STALL; + } + + return 0; + } else if ((request >> 8) == UT_WRITE_INTERFACE && + (request & 0xff) == UR_SET_INTERFACE) { + + aiface.uai_interface_index = index; + aiface.uai_alt_no = value; + + ensure_eps_closed(s); /* can't do this without all eps closed */ + ret = ioctl(s->devfd, USB_SET_ALTINTERFACE, &aiface); + if (ret < 0) { +#ifdef DEBUG + printf("handle_control: failed to set alternate interface - %s\n", + strerror(errno)); +#endif + return USB_RET_STALL; + } + + return 0; + } else { + req.ucr_request.bmRequestType = request >> 8; + req.ucr_request.bRequest = request & 0xff; + USETW(req.ucr_request.wValue, value); + USETW(req.ucr_request.wIndex, index); + USETW(req.ucr_request.wLength, length); + req.ucr_data = data; + req.ucr_flags = USBD_SHORT_XFER_OK; + + ret = ioctl(s->devfd, USB_SET_TIMEOUT, &timeout); +#if defined(__NetBSD__) || defined(__OpenBSD__) + if (ret < 0 && errno != EINVAL) { +#else + if (ret < 0) { +#endif +#ifdef DEBUG + printf("handle_control: setting timeout failed - %s\n", + strerror(errno)); +#endif + } + + ret = ioctl(s->devfd, USB_DO_REQUEST, &req); + /* ugen returns EIO for usbd_do_request_ no matter what + * happens with the transfer */ + if (ret < 0) { +#ifdef DEBUG + printf("handle_control: error after request - %s\n", + strerror(errno)); +#endif + return USB_RET_NAK; // STALL + } else { + return req.ucr_actlen; + } + } +} + +static int usb_host_handle_data(USBDevice *dev, USBPacket *p) +{ + USBHostDevice *s = (USBHostDevice *)dev; + int ret, fd, mode; + int one = 1, shortpacket = 0, timeout = 50; + sigset_t new_mask, old_mask; + uint8_t devep = p->ep->nr; + + /* protect data transfers from SIGALRM signal */ + sigemptyset(&new_mask); + sigaddset(&new_mask, SIGALRM); + sigprocmask(SIG_BLOCK, &new_mask, &old_mask); + + if (p->pid == USB_TOKEN_IN) { + devep |= 0x80; + mode = O_RDONLY; + shortpacket = 1; + } else { + mode = O_WRONLY; + } + + fd = ensure_ep_open(s, devep, mode); + if (fd < 0) { + sigprocmask(SIG_SETMASK, &old_mask, NULL); + return USB_RET_NODEV; + } + + if (ioctl(fd, USB_SET_TIMEOUT, &timeout) < 0) { +#ifdef DEBUG + printf("handle_data: failed to set timeout - %s\n", + strerror(errno)); +#endif + } + + if (shortpacket) { + if (ioctl(fd, USB_SET_SHORT_XFER, &one) < 0) { +#ifdef DEBUG + printf("handle_data: failed to set short xfer mode - %s\n", + strerror(errno)); +#endif + sigprocmask(SIG_SETMASK, &old_mask, NULL); + } + } + + if (p->pid == USB_TOKEN_IN) + ret = readv(fd, p->iov.iov, p->iov.niov); + else + ret = writev(fd, p->iov.iov, p->iov.niov); + + sigprocmask(SIG_SETMASK, &old_mask, NULL); + + if (ret < 0) { +#ifdef DEBUG + printf("handle_data: error after %s data - %s\n", + pid == USB_TOKEN_IN ? "reading" : "writing", strerror(errno)); +#endif + switch(errno) { + case ETIMEDOUT: + case EINTR: + return USB_RET_NAK; + default: + return USB_RET_STALL; + } + } else { + return ret; + } +} + +static void usb_host_handle_destroy(USBDevice *opaque) +{ + USBHostDevice *s = (USBHostDevice *)opaque; + int i; + + for (i = 0; i < USB_MAX_ENDPOINTS; i++) + if (s->ep_fd[i] >= 0) + close(s->ep_fd[i]); + + if (s->devfd < 0) + return; + + close(s->devfd); + + g_free(s); +} + +static int usb_host_initfn(USBDevice *dev) +{ + return 0; +} + +USBDevice *usb_host_device_open(USBBus *guest_bus, const char *devname) +{ + struct usb_device_info bus_info, dev_info; + USBDevice *d = NULL, *ret = NULL; + USBHostDevice *dev; + char ctlpath[PATH_MAX + 1]; + char buspath[PATH_MAX + 1]; + int bfd, dfd, bus, address, i; + int ugendebug = UGEN_DEBUG_LEVEL; + + if (usb_host_find_device(&bus, &address, devname) < 0) { + goto fail; + } + + snprintf(buspath, PATH_MAX, "/dev/usb%d", bus); + + bfd = open(buspath, O_RDWR); + if (bfd < 0) { +#ifdef DEBUG + printf("usb_host_device_open: failed to open usb bus - %s\n", + strerror(errno)); +#endif + goto fail; + } + + bus_info.udi_addr = address; + if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0) { +#ifdef DEBUG + printf("usb_host_device_open: failed to grab bus information - %s\n", + strerror(errno)); +#endif + goto fail_bfd; + } + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) + snprintf(ctlpath, PATH_MAX, "/dev/%s", bus_info.udi_devnames[0]); +#else + snprintf(ctlpath, PATH_MAX, "/dev/%s.00", bus_info.udi_devnames[0]); +#endif + + dfd = open(ctlpath, O_RDWR); + if (dfd < 0) { + dfd = open(ctlpath, O_RDONLY); + if (dfd < 0) { +#ifdef DEBUG + printf("usb_host_device_open: failed to open usb device %s - %s\n", + ctlpath, strerror(errno)); +#endif + } + goto fail_dfd; + } + + if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) { +#ifdef DEBUG + printf("usb_host_device_open: failed to grab device info - %s\n", + strerror(errno)); +#endif + goto fail_dfd; + } + + d = usb_create(guest_bus, "usb-host"); + dev = DO_UPCAST(USBHostDevice, dev, d); + + if (dev_info.udi_speed == 1) { + dev->dev.speed = USB_SPEED_LOW - 1; + dev->dev.speedmask = USB_SPEED_MASK_LOW; + } else { + dev->dev.speed = USB_SPEED_FULL - 1; + dev->dev.speedmask = USB_SPEED_MASK_FULL; + } + + if (strncmp(dev_info.udi_product, "product", 7) != 0) { + pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc), + dev_info.udi_product); + } else { + snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc), + "host:%s", devname); + } + + pstrcpy(dev->devpath, sizeof(dev->devpath), "/dev/"); + pstrcat(dev->devpath, sizeof(dev->devpath), dev_info.udi_devnames[0]); + + /* Mark the endpoints as not yet open */ + for (i = 0; i < USB_MAX_ENDPOINTS; i++) { + dev->ep_fd[i] = -1; + } + + ioctl(dfd, USB_SETDEBUG, &ugendebug); + + ret = (USBDevice *)dev; + +fail_dfd: + close(dfd); +fail_bfd: + close(bfd); +fail: + return ret; +} + +static void usb_host_class_initfn(ObjectClass *klass, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->product_desc = "USB Host Device"; + uc->init = usb_host_initfn; + uc->handle_reset = usb_host_handle_reset; + uc->handle_control = usb_host_handle_control; + uc->handle_data = usb_host_handle_data; + uc->handle_destroy = usb_host_handle_destroy; +} + +static TypeInfo usb_host_dev_info = { + .name = "usb-host", + .parent = TYPE_USB_DEVICE, + .instance_size = sizeof(USBHostDevice), + .class_init = usb_host_class_initfn, +}; + +static void usb_host_register_types(void) +{ + type_register_static(&usb_host_dev_info); +} + +type_init(usb_host_register_types) + +static int usb_host_scan(void *opaque, USBScanFunc *func) +{ + struct usb_device_info bus_info; + struct usb_device_info dev_info; + uint16_t vendor_id, product_id, class_id, speed; + int bfd, dfd, bus, address; + char busbuf[20], devbuf[20], product_name[256]; + int ret = 0; + + for (bus = 0; bus < 10; bus++) { + + snprintf(busbuf, sizeof(busbuf) - 1, "/dev/usb%d", bus); + bfd = open(busbuf, O_RDWR); + if (bfd < 0) + continue; + + for (address = 1; address < 127; address++) { + + bus_info.udi_addr = address; + if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0) + continue; + + /* only list devices that can be used by generic layer */ + if (strncmp(bus_info.udi_devnames[0], "ugen", 4) != 0) + continue; + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) + snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s", bus_info.udi_devnames[0]); +#else + snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s.00", bus_info.udi_devnames[0]); +#endif + + dfd = open(devbuf, O_RDONLY); + if (dfd < 0) { +#ifdef DEBUG + printf("usb_host_scan: couldn't open device %s - %s\n", devbuf, + strerror(errno)); +#endif + continue; + } + + if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) + printf("usb_host_scan: couldn't get device information for %s - %s\n", + devbuf, strerror(errno)); + + /* XXX: might need to fixup endianness of word values before copying over */ + + vendor_id = dev_info.udi_vendorNo; + product_id = dev_info.udi_productNo; + class_id = dev_info.udi_class; + speed = dev_info.udi_speed; + + if (strncmp(dev_info.udi_product, "product", 7) != 0) + pstrcpy(product_name, sizeof(product_name), + dev_info.udi_product); + else + product_name[0] = '\0'; + + ret = func(opaque, bus, address, class_id, vendor_id, + product_id, product_name, speed); + + close(dfd); + + if (ret) + goto the_end; + } + + close(bfd); + } + +the_end: + return ret; +} + +typedef struct FindDeviceState { + int vendor_id; + int product_id; + int bus_num; + int addr; +} FindDeviceState; + +static int usb_host_find_device_scan(void *opaque, int bus_num, int addr, + int class_id, + int vendor_id, int product_id, + const char *product_name, int speed) +{ + FindDeviceState *s = opaque; + if (vendor_id == s->vendor_id && + product_id == s->product_id) { + s->bus_num = bus_num; + s->addr = addr; + return 1; + } else { + return 0; + } +} + + +/* the syntax is : + 'bus.addr' (decimal numbers) or + 'vendor_id:product_id' (hexa numbers) */ +static int usb_host_find_device(int *pbus_num, int *paddr, + const char *devname) +{ + const char *p; + int ret; + FindDeviceState fs; + + p = strchr(devname, '.'); + if (p) { + *pbus_num = strtoul(devname, NULL, 0); + *paddr = strtoul(p + 1, NULL, 0); + return 0; + } + p = strchr(devname, ':'); + if (p) { + fs.vendor_id = strtoul(devname, NULL, 16); + fs.product_id = strtoul(p + 1, NULL, 16); + ret = usb_host_scan(&fs, usb_host_find_device_scan); + if (ret) { + *pbus_num = fs.bus_num; + *paddr = fs.addr; + return 0; + } + } + return -1; +} + +/**********************/ +/* USB host device info */ + +struct usb_class_info { + int class; + const char *class_name; +}; + +static const struct usb_class_info usb_class_info[] = { + { USB_CLASS_AUDIO, "Audio"}, + { USB_CLASS_COMM, "Communication"}, + { USB_CLASS_HID, "HID"}, + { USB_CLASS_HUB, "Hub" }, + { USB_CLASS_PHYSICAL, "Physical" }, + { USB_CLASS_PRINTER, "Printer" }, + { USB_CLASS_MASS_STORAGE, "Storage" }, + { USB_CLASS_CDC_DATA, "Data" }, + { USB_CLASS_APP_SPEC, "Application Specific" }, + { USB_CLASS_VENDOR_SPEC, "Vendor Specific" }, + { USB_CLASS_STILL_IMAGE, "Still Image" }, + { USB_CLASS_CSCID, "Smart Card" }, + { USB_CLASS_CONTENT_SEC, "Content Security" }, + { -1, NULL } +}; + +static const char *usb_class_str(uint8_t class) +{ + const struct usb_class_info *p; + for (p = usb_class_info; p->class != -1; p++) { + if (p->class == class) + break; + } + return p->class_name; +} + +static void usb_info_device(Monitor *mon, int bus_num, int addr, int class_id, + int vendor_id, int product_id, + const char *product_name, + int speed) +{ + const char *class_str, *speed_str; + + switch(speed) { + case USB_SPEED_LOW: + speed_str = "1.5"; + break; + case USB_SPEED_FULL: + speed_str = "12"; + break; + case USB_SPEED_HIGH: + speed_str = "480"; + break; + default: + speed_str = "?"; + break; + } + + monitor_printf(mon, " Device %d.%d, speed %s Mb/s\n", + bus_num, addr, speed_str); + class_str = usb_class_str(class_id); + if (class_str) + monitor_printf(mon, " %s:", class_str); + else + monitor_printf(mon, " Class %02x:", class_id); + monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id); + if (product_name[0] != '\0') + monitor_printf(mon, ", %s", product_name); + monitor_printf(mon, "\n"); +} + +static int usb_host_info_device(void *opaque, + int bus_num, int addr, + int class_id, + int vendor_id, int product_id, + const char *product_name, + int speed) +{ + Monitor *mon = opaque; + + usb_info_device(mon, bus_num, addr, class_id, vendor_id, product_id, + product_name, speed); + return 0; +} + +void usb_host_info(Monitor *mon) +{ + usb_host_scan(mon, usb_host_info_device); +} + +/* XXX add this */ +int usb_host_device_close(const char *devname) +{ + return 0; +} diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c new file mode 100644 index 0000000000..90919c242a --- /dev/null +++ b/hw/usb/host-linux.c @@ -0,0 +1,1913 @@ +/* + * Linux host USB redirector + * + * Copyright (c) 2005 Fabrice Bellard + * + * Copyright (c) 2008 Max Krasnyansky + * Support for host device auto connect & disconnect + * Major rewrite to support fully async operation + * + * Copyright 2008 TJ <linux@tjworld.net> + * Added flexible support for /dev/bus/usb /sys/bus/usb/devices in addition + * to the legacy /proc/bus/usb USB device discovery and handling + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu-common.h" +#include "qemu-timer.h" +#include "monitor.h" +#include "sysemu.h" +#include "trace.h" + +#include <dirent.h> +#include <sys/ioctl.h> + +#include <linux/usbdevice_fs.h> +#include <linux/version.h> +#include "hw/usb.h" + +/* We redefine it to avoid version problems */ +struct usb_ctrltransfer { + uint8_t bRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; + uint32_t timeout; + void *data; +}; + +typedef int USBScanFunc(void *opaque, int bus_num, int addr, const char *port, + int class_id, int vendor_id, int product_id, + const char *product_name, int speed); + +//#define DEBUG + +#ifdef DEBUG +#define DPRINTF printf +#else +#define DPRINTF(...) +#endif + +#define PRODUCT_NAME_SZ 32 +#define MAX_PORTLEN 16 + +/* endpoint association data */ +#define ISO_FRAME_DESC_PER_URB 32 + +/* devio.c limits single requests to 16k */ +#define MAX_USBFS_BUFFER_SIZE 16384 + +typedef struct AsyncURB AsyncURB; + +struct endp_data { + uint8_t halted; + uint8_t iso_started; + AsyncURB *iso_urb; + int iso_urb_idx; + int iso_buffer_used; + int inflight; +}; + +struct USBAutoFilter { + uint32_t bus_num; + uint32_t addr; + char *port; + uint32_t vendor_id; + uint32_t product_id; +}; + +typedef struct USBHostDevice { + USBDevice dev; + int fd; + int hub_fd; + int hub_port; + + uint8_t descr[8192]; + int descr_len; + int closing; + uint32_t iso_urb_count; + Notifier exit; + + struct endp_data ep_in[USB_MAX_ENDPOINTS]; + struct endp_data ep_out[USB_MAX_ENDPOINTS]; + QLIST_HEAD(, AsyncURB) aurbs; + + /* Host side address */ + int bus_num; + int addr; + char port[MAX_PORTLEN]; + struct USBAutoFilter match; + int seen, errcount; + + QTAILQ_ENTRY(USBHostDevice) next; +} USBHostDevice; + +static QTAILQ_HEAD(, USBHostDevice) hostdevs = QTAILQ_HEAD_INITIALIZER(hostdevs); + +static int usb_host_close(USBHostDevice *dev); +static int parse_filter(const char *spec, struct USBAutoFilter *f); +static void usb_host_auto_check(void *unused); +static int usb_host_read_file(char *line, size_t line_size, + const char *device_file, const char *device_name); +static int usb_linux_update_endp_table(USBHostDevice *s); + +static int usb_host_usbfs_type(USBHostDevice *s, USBPacket *p) +{ + static const int usbfs[] = { + [USB_ENDPOINT_XFER_CONTROL] = USBDEVFS_URB_TYPE_CONTROL, + [USB_ENDPOINT_XFER_ISOC] = USBDEVFS_URB_TYPE_ISO, + [USB_ENDPOINT_XFER_BULK] = USBDEVFS_URB_TYPE_BULK, + [USB_ENDPOINT_XFER_INT] = USBDEVFS_URB_TYPE_INTERRUPT, + }; + uint8_t type = p->ep->type; + assert(type < ARRAY_SIZE(usbfs)); + return usbfs[type]; +} + +static int usb_host_do_reset(USBHostDevice *dev) +{ + struct timeval s, e; + uint32_t usecs; + int ret; + + gettimeofday(&s, NULL); + ret = ioctl(dev->fd, USBDEVFS_RESET); + gettimeofday(&e, NULL); + usecs = (e.tv_sec - s.tv_sec) * 1000000; + usecs += e.tv_usec - s.tv_usec; + if (usecs > 1000000) { + /* more than a second, something is fishy, broken usb device? */ + fprintf(stderr, "husb: device %d:%d reset took %d.%06d seconds\n", + dev->bus_num, dev->addr, usecs / 1000000, usecs % 1000000); + } + return ret; +} + +static struct endp_data *get_endp(USBHostDevice *s, int pid, int ep) +{ + struct endp_data *eps = pid == USB_TOKEN_IN ? s->ep_in : s->ep_out; + assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT); + assert(ep > 0 && ep <= USB_MAX_ENDPOINTS); + return eps + ep - 1; +} + +static int is_isoc(USBHostDevice *s, int pid, int ep) +{ + return usb_ep_get_type(&s->dev, pid, ep) == USB_ENDPOINT_XFER_ISOC; +} + +static int is_valid(USBHostDevice *s, int pid, int ep) +{ + return usb_ep_get_type(&s->dev, pid, ep) != USB_ENDPOINT_XFER_INVALID; +} + +static int is_halted(USBHostDevice *s, int pid, int ep) +{ + return get_endp(s, pid, ep)->halted; +} + +static void clear_halt(USBHostDevice *s, int pid, int ep) +{ + trace_usb_host_ep_clear_halt(s->bus_num, s->addr, ep); + get_endp(s, pid, ep)->halted = 0; +} + +static void set_halt(USBHostDevice *s, int pid, int ep) +{ + if (ep != 0) { + trace_usb_host_ep_set_halt(s->bus_num, s->addr, ep); + get_endp(s, pid, ep)->halted = 1; + } +} + +static int is_iso_started(USBHostDevice *s, int pid, int ep) +{ + return get_endp(s, pid, ep)->iso_started; +} + +static void clear_iso_started(USBHostDevice *s, int pid, int ep) +{ + trace_usb_host_ep_stop_iso(s->bus_num, s->addr, ep); + get_endp(s, pid, ep)->iso_started = 0; +} + +static void set_iso_started(USBHostDevice *s, int pid, int ep) +{ + struct endp_data *e = get_endp(s, pid, ep); + + trace_usb_host_ep_start_iso(s->bus_num, s->addr, ep); + if (!e->iso_started) { + e->iso_started = 1; + e->inflight = 0; + } +} + +static int change_iso_inflight(USBHostDevice *s, int pid, int ep, int value) +{ + struct endp_data *e = get_endp(s, pid, ep); + + e->inflight += value; + return e->inflight; +} + +static void set_iso_urb(USBHostDevice *s, int pid, int ep, AsyncURB *iso_urb) +{ + get_endp(s, pid, ep)->iso_urb = iso_urb; +} + +static AsyncURB *get_iso_urb(USBHostDevice *s, int pid, int ep) +{ + return get_endp(s, pid, ep)->iso_urb; +} + +static void set_iso_urb_idx(USBHostDevice *s, int pid, int ep, int i) +{ + get_endp(s, pid, ep)->iso_urb_idx = i; +} + +static int get_iso_urb_idx(USBHostDevice *s, int pid, int ep) +{ + return get_endp(s, pid, ep)->iso_urb_idx; +} + +static void set_iso_buffer_used(USBHostDevice *s, int pid, int ep, int i) +{ + get_endp(s, pid, ep)->iso_buffer_used = i; +} + +static int get_iso_buffer_used(USBHostDevice *s, int pid, int ep) +{ + return get_endp(s, pid, ep)->iso_buffer_used; +} + +/* + * Async URB state. + * We always allocate iso packet descriptors even for bulk transfers + * to simplify allocation and casts. + */ +struct AsyncURB +{ + struct usbdevfs_urb urb; + struct usbdevfs_iso_packet_desc isocpd[ISO_FRAME_DESC_PER_URB]; + USBHostDevice *hdev; + QLIST_ENTRY(AsyncURB) next; + + /* For regular async urbs */ + USBPacket *packet; + int more; /* large transfer, more urbs follow */ + + /* For buffered iso handling */ + int iso_frame_idx; /* -1 means in flight */ +}; + +static AsyncURB *async_alloc(USBHostDevice *s) +{ + AsyncURB *aurb = g_malloc0(sizeof(AsyncURB)); + aurb->hdev = s; + QLIST_INSERT_HEAD(&s->aurbs, aurb, next); + return aurb; +} + +static void async_free(AsyncURB *aurb) +{ + QLIST_REMOVE(aurb, next); + g_free(aurb); +} + +static void do_disconnect(USBHostDevice *s) +{ + usb_host_close(s); + usb_host_auto_check(NULL); +} + +static void async_complete(void *opaque) +{ + USBHostDevice *s = opaque; + AsyncURB *aurb; + int urbs = 0; + + while (1) { + USBPacket *p; + + int r = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &aurb); + if (r < 0) { + if (errno == EAGAIN) { + if (urbs > 2) { + fprintf(stderr, "husb: %d iso urbs finished at once\n", urbs); + } + return; + } + if (errno == ENODEV) { + if (!s->closing) { + trace_usb_host_disconnect(s->bus_num, s->addr); + do_disconnect(s); + } + return; + } + + perror("USBDEVFS_REAPURBNDELAY"); + return; + } + + DPRINTF("husb: async completed. aurb %p status %d alen %d\n", + aurb, aurb->urb.status, aurb->urb.actual_length); + + /* If this is a buffered iso urb mark it as complete and don't do + anything else (it is handled further in usb_host_handle_iso_data) */ + if (aurb->iso_frame_idx == -1) { + int inflight; + int pid = (aurb->urb.endpoint & USB_DIR_IN) ? + USB_TOKEN_IN : USB_TOKEN_OUT; + int ep = aurb->urb.endpoint & 0xf; + if (aurb->urb.status == -EPIPE) { + set_halt(s, pid, ep); + } + aurb->iso_frame_idx = 0; + urbs++; + inflight = change_iso_inflight(s, pid, ep, -1); + if (inflight == 0 && is_iso_started(s, pid, ep)) { + fprintf(stderr, "husb: out of buffers for iso stream\n"); + } + continue; + } + + p = aurb->packet; + trace_usb_host_urb_complete(s->bus_num, s->addr, aurb, aurb->urb.status, + aurb->urb.actual_length, aurb->more); + + if (p) { + switch (aurb->urb.status) { + case 0: + p->result += aurb->urb.actual_length; + break; + + case -EPIPE: + set_halt(s, p->pid, p->ep->nr); + p->result = USB_RET_STALL; + break; + + case -EOVERFLOW: + p->result = USB_RET_BABBLE; + break; + + default: + p->result = USB_RET_IOERROR; + break; + } + + if (aurb->urb.type == USBDEVFS_URB_TYPE_CONTROL) { + trace_usb_host_req_complete(s->bus_num, s->addr, p->result); + usb_generic_async_ctrl_complete(&s->dev, p); + } else if (!aurb->more) { + trace_usb_host_req_complete(s->bus_num, s->addr, p->result); + usb_packet_complete(&s->dev, p); + } + } + + async_free(aurb); + } +} + +static void usb_host_async_cancel(USBDevice *dev, USBPacket *p) +{ + USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev); + AsyncURB *aurb; + + QLIST_FOREACH(aurb, &s->aurbs, next) { + if (p != aurb->packet) { + continue; + } + + DPRINTF("husb: async cancel: packet %p, aurb %p\n", p, aurb); + + /* Mark it as dead (see async_complete above) */ + aurb->packet = NULL; + + int r = ioctl(s->fd, USBDEVFS_DISCARDURB, aurb); + if (r < 0) { + DPRINTF("husb: async. discard urb failed errno %d\n", errno); + } + } +} + +static int usb_host_open_device(int bus, int addr) +{ + const char *usbfs = NULL; + char filename[32]; + struct stat st; + int fd, rc; + + rc = stat("/dev/bus/usb", &st); + if (rc == 0 && S_ISDIR(st.st_mode)) { + /* udev-created device nodes available */ + usbfs = "/dev/bus/usb"; + } else { + /* fallback: usbfs mounted below /proc */ + usbfs = "/proc/bus/usb"; + } + + snprintf(filename, sizeof(filename), "%s/%03d/%03d", + usbfs, bus, addr); + fd = open(filename, O_RDWR | O_NONBLOCK); + if (fd < 0) { + fprintf(stderr, "husb: open %s: %s\n", filename, strerror(errno)); + } + return fd; +} + +static int usb_host_claim_port(USBHostDevice *s) +{ +#ifdef USBDEVFS_CLAIM_PORT + char *h, hub_name[64], line[1024]; + int hub_addr, ret; + + snprintf(hub_name, sizeof(hub_name), "%d-%s", + s->match.bus_num, s->match.port); + + /* try strip off last ".$portnr" to get hub */ + h = strrchr(hub_name, '.'); + if (h != NULL) { + s->hub_port = atoi(h+1); + *h = '\0'; + } else { + /* no dot in there -> it is the root hub */ + snprintf(hub_name, sizeof(hub_name), "usb%d", + s->match.bus_num); + s->hub_port = atoi(s->match.port); + } + + if (!usb_host_read_file(line, sizeof(line), "devnum", + hub_name)) { + return -1; + } + if (sscanf(line, "%d", &hub_addr) != 1) { + return -1; + } + + s->hub_fd = usb_host_open_device(s->match.bus_num, hub_addr); + if (s->hub_fd < 0) { + return -1; + } + + ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &s->hub_port); + if (ret < 0) { + close(s->hub_fd); + s->hub_fd = -1; + return -1; + } + + trace_usb_host_claim_port(s->match.bus_num, hub_addr, s->hub_port); + return 0; +#else + return -1; +#endif +} + +static void usb_host_release_port(USBHostDevice *s) +{ + if (s->hub_fd == -1) { + return; + } +#ifdef USBDEVFS_RELEASE_PORT + ioctl(s->hub_fd, USBDEVFS_RELEASE_PORT, &s->hub_port); +#endif + close(s->hub_fd); + s->hub_fd = -1; +} + +static int usb_host_disconnect_ifaces(USBHostDevice *dev, int nb_interfaces) +{ + /* earlier Linux 2.4 do not support that */ +#ifdef USBDEVFS_DISCONNECT + struct usbdevfs_ioctl ctrl; + int ret, interface; + + for (interface = 0; interface < nb_interfaces; interface++) { + ctrl.ioctl_code = USBDEVFS_DISCONNECT; + ctrl.ifno = interface; + ctrl.data = 0; + ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl); + if (ret < 0 && errno != ENODATA) { + perror("USBDEVFS_DISCONNECT"); + return -1; + } + } +#endif + return 0; +} + +static int usb_linux_get_num_interfaces(USBHostDevice *s) +{ + char device_name[64], line[1024]; + int num_interfaces = 0; + + sprintf(device_name, "%d-%s", s->bus_num, s->port); + if (!usb_host_read_file(line, sizeof(line), "bNumInterfaces", + device_name)) { + return -1; + } + if (sscanf(line, "%d", &num_interfaces) != 1) { + return -1; + } + return num_interfaces; +} + +static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration) +{ + const char *op = NULL; + int dev_descr_len, config_descr_len; + int interface, nb_interfaces; + int ret, i; + + for (i = 0; i < USB_MAX_INTERFACES; i++) { + dev->dev.altsetting[i] = 0; + } + + if (configuration == 0) { /* address state - ignore */ + dev->dev.ninterfaces = 0; + dev->dev.configuration = 0; + return 1; + } + + DPRINTF("husb: claiming interfaces. config %d\n", configuration); + + i = 0; + dev_descr_len = dev->descr[0]; + if (dev_descr_len > dev->descr_len) { + fprintf(stderr, "husb: update iface failed. descr too short\n"); + return 0; + } + + i += dev_descr_len; + while (i < dev->descr_len) { + DPRINTF("husb: i is %d, descr_len is %d, dl %d, dt %d\n", + i, dev->descr_len, + dev->descr[i], dev->descr[i+1]); + + if (dev->descr[i+1] != USB_DT_CONFIG) { + i += dev->descr[i]; + continue; + } + config_descr_len = dev->descr[i]; + + DPRINTF("husb: config #%d need %d\n", dev->descr[i + 5], configuration); + + if (configuration == dev->descr[i + 5]) { + configuration = dev->descr[i + 5]; + break; + } + + i += config_descr_len; + } + + if (i >= dev->descr_len) { + fprintf(stderr, + "husb: update iface failed. no matching configuration\n"); + return 0; + } + nb_interfaces = dev->descr[i + 4]; + + if (usb_host_disconnect_ifaces(dev, nb_interfaces) < 0) { + goto fail; + } + + /* XXX: only grab if all interfaces are free */ + for (interface = 0; interface < nb_interfaces; interface++) { + op = "USBDEVFS_CLAIMINTERFACE"; + ret = ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface); + if (ret < 0) { + goto fail; + } + } + + trace_usb_host_claim_interfaces(dev->bus_num, dev->addr, + nb_interfaces, configuration); + + dev->dev.ninterfaces = nb_interfaces; + dev->dev.configuration = configuration; + return 1; + +fail: + if (errno == ENODEV) { + do_disconnect(dev); + } + perror(op); + return 0; +} + +static int usb_host_release_interfaces(USBHostDevice *s) +{ + int ret, i; + + trace_usb_host_release_interfaces(s->bus_num, s->addr); + + for (i = 0; i < s->dev.ninterfaces; i++) { + ret = ioctl(s->fd, USBDEVFS_RELEASEINTERFACE, &i); + if (ret < 0) { + perror("USBDEVFS_RELEASEINTERFACE"); + return 0; + } + } + return 1; +} + +static void usb_host_handle_reset(USBDevice *dev) +{ + USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev); + + trace_usb_host_reset(s->bus_num, s->addr); + + usb_host_do_reset(s);; + + usb_host_claim_interfaces(s, 0); + usb_linux_update_endp_table(s); +} + +static void usb_host_handle_destroy(USBDevice *dev) +{ + USBHostDevice *s = (USBHostDevice *)dev; + + usb_host_release_port(s); + usb_host_close(s); + QTAILQ_REMOVE(&hostdevs, s, next); + qemu_remove_exit_notifier(&s->exit); +} + +/* iso data is special, we need to keep enough urbs in flight to make sure + that the controller never runs out of them, otherwise the device will + likely suffer a buffer underrun / overrun. */ +static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, int pid, uint8_t ep) +{ + AsyncURB *aurb; + int i, j, len = usb_ep_get_max_packet_size(&s->dev, pid, ep); + + aurb = g_malloc0(s->iso_urb_count * sizeof(*aurb)); + for (i = 0; i < s->iso_urb_count; i++) { + aurb[i].urb.endpoint = ep; + aurb[i].urb.buffer_length = ISO_FRAME_DESC_PER_URB * len; + aurb[i].urb.buffer = g_malloc(aurb[i].urb.buffer_length); + aurb[i].urb.type = USBDEVFS_URB_TYPE_ISO; + aurb[i].urb.flags = USBDEVFS_URB_ISO_ASAP; + aurb[i].urb.number_of_packets = ISO_FRAME_DESC_PER_URB; + for (j = 0 ; j < ISO_FRAME_DESC_PER_URB; j++) + aurb[i].urb.iso_frame_desc[j].length = len; + if (pid == USB_TOKEN_IN) { + aurb[i].urb.endpoint |= 0x80; + /* Mark as fully consumed (idle) */ + aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB; + } + } + set_iso_urb(s, pid, ep, aurb); + + return aurb; +} + +static void usb_host_stop_n_free_iso(USBHostDevice *s, int pid, uint8_t ep) +{ + AsyncURB *aurb; + int i, ret, killed = 0, free = 1; + + aurb = get_iso_urb(s, pid, ep); + if (!aurb) { + return; + } + + for (i = 0; i < s->iso_urb_count; i++) { + /* in flight? */ + if (aurb[i].iso_frame_idx == -1) { + ret = ioctl(s->fd, USBDEVFS_DISCARDURB, &aurb[i]); + if (ret < 0) { + perror("USBDEVFS_DISCARDURB"); + free = 0; + continue; + } + killed++; + } + } + + /* Make sure any urbs we've killed are reaped before we free them */ + if (killed) { + async_complete(s); + } + + for (i = 0; i < s->iso_urb_count; i++) { + g_free(aurb[i].urb.buffer); + } + + if (free) + g_free(aurb); + else + printf("husb: leaking iso urbs because of discard failure\n"); + set_iso_urb(s, pid, ep, NULL); + set_iso_urb_idx(s, pid, ep, 0); + clear_iso_started(s, pid, ep); +} + +static int urb_status_to_usb_ret(int status) +{ + switch (status) { + case -EPIPE: + return USB_RET_STALL; + case -EOVERFLOW: + return USB_RET_BABBLE; + default: + return USB_RET_IOERROR; + } +} + +static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in) +{ + AsyncURB *aurb; + int i, j, ret, max_packet_size, offset, len = 0; + uint8_t *buf; + + max_packet_size = p->ep->max_packet_size; + if (max_packet_size == 0) + return USB_RET_NAK; + + aurb = get_iso_urb(s, p->pid, p->ep->nr); + if (!aurb) { + aurb = usb_host_alloc_iso(s, p->pid, p->ep->nr); + } + + i = get_iso_urb_idx(s, p->pid, p->ep->nr); + j = aurb[i].iso_frame_idx; + if (j >= 0 && j < ISO_FRAME_DESC_PER_URB) { + if (in) { + /* Check urb status */ + if (aurb[i].urb.status) { + len = urb_status_to_usb_ret(aurb[i].urb.status); + /* Move to the next urb */ + aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB - 1; + /* Check frame status */ + } else if (aurb[i].urb.iso_frame_desc[j].status) { + len = urb_status_to_usb_ret( + aurb[i].urb.iso_frame_desc[j].status); + /* Check the frame fits */ + } else if (aurb[i].urb.iso_frame_desc[j].actual_length + > p->iov.size) { + printf("husb: received iso data is larger then packet\n"); + len = USB_RET_BABBLE; + /* All good copy data over */ + } else { + len = aurb[i].urb.iso_frame_desc[j].actual_length; + buf = aurb[i].urb.buffer + + j * aurb[i].urb.iso_frame_desc[0].length; + usb_packet_copy(p, buf, len); + } + } else { + len = p->iov.size; + offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->pid, p->ep->nr); + + /* Check the frame fits */ + if (len > max_packet_size) { + printf("husb: send iso data is larger then max packet size\n"); + return USB_RET_NAK; + } + + /* All good copy data over */ + usb_packet_copy(p, aurb[i].urb.buffer + offset, len); + aurb[i].urb.iso_frame_desc[j].length = len; + offset += len; + set_iso_buffer_used(s, p->pid, p->ep->nr, offset); + + /* Start the stream once we have buffered enough data */ + if (!is_iso_started(s, p->pid, p->ep->nr) && i == 1 && j == 8) { + set_iso_started(s, p->pid, p->ep->nr); + } + } + aurb[i].iso_frame_idx++; + if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) { + i = (i + 1) % s->iso_urb_count; + set_iso_urb_idx(s, p->pid, p->ep->nr, i); + } + } else { + if (in) { + set_iso_started(s, p->pid, p->ep->nr); + } else { + DPRINTF("hubs: iso out error no free buffer, dropping packet\n"); + } + } + + if (is_iso_started(s, p->pid, p->ep->nr)) { + /* (Re)-submit all fully consumed / filled urbs */ + for (i = 0; i < s->iso_urb_count; i++) { + if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) { + ret = ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]); + if (ret < 0) { + perror("USBDEVFS_SUBMITURB"); + if (!in || len == 0) { + switch(errno) { + case ETIMEDOUT: + len = USB_RET_NAK; + break; + case EPIPE: + default: + len = USB_RET_STALL; + } + } + break; + } + aurb[i].iso_frame_idx = -1; + change_iso_inflight(s, p->pid, p->ep->nr, 1); + } + } + } + + return len; +} + +static int usb_host_handle_data(USBDevice *dev, USBPacket *p) +{ + USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev); + struct usbdevfs_urb *urb; + AsyncURB *aurb; + int ret, rem, prem, v; + uint8_t *pbuf; + uint8_t ep; + + trace_usb_host_req_data(s->bus_num, s->addr, + p->pid == USB_TOKEN_IN, + p->ep->nr, p->iov.size); + + if (!is_valid(s, p->pid, p->ep->nr)) { + trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK); + return USB_RET_NAK; + } + + if (p->pid == USB_TOKEN_IN) { + ep = p->ep->nr | 0x80; + } else { + ep = p->ep->nr; + } + + if (is_halted(s, p->pid, p->ep->nr)) { + unsigned int arg = ep; + ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &arg); + if (ret < 0) { + perror("USBDEVFS_CLEAR_HALT"); + trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK); + return USB_RET_NAK; + } + clear_halt(s, p->pid, p->ep->nr); + } + + if (is_isoc(s, p->pid, p->ep->nr)) { + return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN); + } + + v = 0; + prem = p->iov.iov[v].iov_len; + pbuf = p->iov.iov[v].iov_base; + rem = p->iov.size; + while (rem) { + if (prem == 0) { + v++; + assert(v < p->iov.niov); + prem = p->iov.iov[v].iov_len; + pbuf = p->iov.iov[v].iov_base; + assert(prem <= rem); + } + aurb = async_alloc(s); + aurb->packet = p; + + urb = &aurb->urb; + urb->endpoint = ep; + urb->type = usb_host_usbfs_type(s, p); + urb->usercontext = s; + urb->buffer = pbuf; + urb->buffer_length = prem; + + if (urb->buffer_length > MAX_USBFS_BUFFER_SIZE) { + urb->buffer_length = MAX_USBFS_BUFFER_SIZE; + } + pbuf += urb->buffer_length; + prem -= urb->buffer_length; + rem -= urb->buffer_length; + if (rem) { + aurb->more = 1; + } + + trace_usb_host_urb_submit(s->bus_num, s->addr, aurb, + urb->buffer_length, aurb->more); + ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb); + + DPRINTF("husb: data submit: ep 0x%x, len %u, more %d, packet %p, aurb %p\n", + urb->endpoint, urb->buffer_length, aurb->more, p, aurb); + + if (ret < 0) { + perror("USBDEVFS_SUBMITURB"); + async_free(aurb); + + switch(errno) { + case ETIMEDOUT: + trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK); + return USB_RET_NAK; + case EPIPE: + default: + trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_STALL); + return USB_RET_STALL; + } + } + } + + return USB_RET_ASYNC; +} + +static int ctrl_error(void) +{ + if (errno == ETIMEDOUT) { + return USB_RET_NAK; + } else { + return USB_RET_STALL; + } +} + +static int usb_host_set_address(USBHostDevice *s, int addr) +{ + trace_usb_host_set_address(s->bus_num, s->addr, addr); + s->dev.addr = addr; + return 0; +} + +static int usb_host_set_config(USBHostDevice *s, int config) +{ + int ret, first = 1; + + trace_usb_host_set_config(s->bus_num, s->addr, config); + + usb_host_release_interfaces(s); + +again: + ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config); + + DPRINTF("husb: ctrl set config %d ret %d errno %d\n", config, ret, errno); + + if (ret < 0 && errno == EBUSY && first) { + /* happens if usb device is in use by host drivers */ + int count = usb_linux_get_num_interfaces(s); + if (count > 0) { + DPRINTF("husb: busy -> disconnecting %d interfaces\n", count); + usb_host_disconnect_ifaces(s, count); + first = 0; + goto again; + } + } + + if (ret < 0) { + return ctrl_error(); + } + usb_host_claim_interfaces(s, config); + usb_linux_update_endp_table(s); + return 0; +} + +static int usb_host_set_interface(USBHostDevice *s, int iface, int alt) +{ + struct usbdevfs_setinterface si; + int i, ret; + + trace_usb_host_set_interface(s->bus_num, s->addr, iface, alt); + + for (i = 1; i <= USB_MAX_ENDPOINTS; i++) { + if (is_isoc(s, USB_TOKEN_IN, i)) { + usb_host_stop_n_free_iso(s, USB_TOKEN_IN, i); + } + if (is_isoc(s, USB_TOKEN_OUT, i)) { + usb_host_stop_n_free_iso(s, USB_TOKEN_OUT, i); + } + } + + if (iface >= USB_MAX_INTERFACES) { + return USB_RET_STALL; + } + + si.interface = iface; + si.altsetting = alt; + ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si); + + DPRINTF("husb: ctrl set iface %d altset %d ret %d errno %d\n", + iface, alt, ret, errno); + + if (ret < 0) { + return ctrl_error(); + } + + s->dev.altsetting[iface] = alt; + usb_linux_update_endp_table(s); + return 0; +} + +static int usb_host_handle_control(USBDevice *dev, USBPacket *p, + int request, int value, int index, int length, uint8_t *data) +{ + USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev); + struct usbdevfs_urb *urb; + AsyncURB *aurb; + int ret; + + /* + * Process certain standard device requests. + * These are infrequent and are processed synchronously. + */ + + /* Note request is (bRequestType << 8) | bRequest */ + trace_usb_host_req_control(s->bus_num, s->addr, request, value, index); + + switch (request) { + case DeviceOutRequest | USB_REQ_SET_ADDRESS: + return usb_host_set_address(s, value); + + case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: + return usb_host_set_config(s, value & 0xff); + + case InterfaceOutRequest | USB_REQ_SET_INTERFACE: + return usb_host_set_interface(s, index, value); + } + + /* The rest are asynchronous */ + + if (length > sizeof(dev->data_buf)) { + fprintf(stderr, "husb: ctrl buffer too small (%d > %zu)\n", + length, sizeof(dev->data_buf)); + return USB_RET_STALL; + } + + aurb = async_alloc(s); + aurb->packet = p; + + /* + * Setup ctrl transfer. + * + * s->ctrl is laid out such that data buffer immediately follows + * 'req' struct which is exactly what usbdevfs expects. + */ + urb = &aurb->urb; + + urb->type = USBDEVFS_URB_TYPE_CONTROL; + urb->endpoint = p->ep->nr; + + urb->buffer = &dev->setup_buf; + urb->buffer_length = length + 8; + + urb->usercontext = s; + + trace_usb_host_urb_submit(s->bus_num, s->addr, aurb, + urb->buffer_length, aurb->more); + ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb); + + DPRINTF("husb: submit ctrl. len %u aurb %p\n", urb->buffer_length, aurb); + + if (ret < 0) { + DPRINTF("husb: submit failed. errno %d\n", errno); + async_free(aurb); + + switch(errno) { + case ETIMEDOUT: + return USB_RET_NAK; + case EPIPE: + default: + return USB_RET_STALL; + } + } + + return USB_RET_ASYNC; +} + +static uint8_t usb_linux_get_alt_setting(USBHostDevice *s, + uint8_t configuration, uint8_t interface) +{ + char device_name[64], line[1024]; + int alt_setting; + + sprintf(device_name, "%d-%s:%d.%d", s->bus_num, s->port, + (int)configuration, (int)interface); + + if (!usb_host_read_file(line, sizeof(line), "bAlternateSetting", + device_name)) { + /* Assume alt 0 on error */ + return 0; + } + if (sscanf(line, "%d", &alt_setting) != 1) { + /* Assume alt 0 on error */ + return 0; + } + return alt_setting; +} + +/* returns 1 on problem encountered or 0 for success */ +static int usb_linux_update_endp_table(USBHostDevice *s) +{ + uint8_t *descriptors; + uint8_t devep, type, alt_interface; + uint16_t raw; + int interface, length, i, ep, pid; + struct endp_data *epd; + + usb_ep_init(&s->dev); + + if (s->dev.configuration == 0) { + /* not configured yet -- leave all endpoints disabled */ + return 0; + } + + /* get the desired configuration, interface, and endpoint descriptors + * from device description */ + descriptors = &s->descr[18]; + length = s->descr_len - 18; + i = 0; + + while (i < length) { + if (descriptors[i + 1] != USB_DT_CONFIG) { + fprintf(stderr, "invalid descriptor data\n"); + return 1; + } else if (descriptors[i + 5] != s->dev.configuration) { + DPRINTF("not requested configuration %d\n", s->dev.configuration); + i += (descriptors[i + 3] << 8) + descriptors[i + 2]; + continue; + } + i += descriptors[i]; + + if (descriptors[i + 1] != USB_DT_INTERFACE || + (descriptors[i + 1] == USB_DT_INTERFACE && + descriptors[i + 4] == 0)) { + i += descriptors[i]; + continue; + } + + interface = descriptors[i + 2]; + alt_interface = usb_linux_get_alt_setting(s, s->dev.configuration, + interface); + + /* the current interface descriptor is the active interface + * and has endpoints */ + if (descriptors[i + 3] != alt_interface) { + i += descriptors[i]; + continue; + } + + /* advance to the endpoints */ + while (i < length && descriptors[i +1] != USB_DT_ENDPOINT) { + i += descriptors[i]; + } + + if (i >= length) + break; + + while (i < length) { + if (descriptors[i + 1] != USB_DT_ENDPOINT) { + break; + } + + devep = descriptors[i + 2]; + pid = (devep & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT; + ep = devep & 0xf; + if (ep == 0) { + fprintf(stderr, "usb-linux: invalid ep descriptor, ep == 0\n"); + return 1; + } + + type = descriptors[i + 3] & 0x3; + raw = descriptors[i + 4] + (descriptors[i + 5] << 8); + usb_ep_set_max_packet_size(&s->dev, pid, ep, raw); + assert(usb_ep_get_type(&s->dev, pid, ep) == + USB_ENDPOINT_XFER_INVALID); + usb_ep_set_type(&s->dev, pid, ep, type); + usb_ep_set_ifnum(&s->dev, pid, ep, interface); + if (type == USB_ENDPOINT_XFER_BULK) { + usb_ep_set_pipeline(&s->dev, pid, ep, true); + } + + epd = get_endp(s, pid, ep); + epd->halted = 0; + + i += descriptors[i]; + } + } +#ifdef DEBUG + usb_ep_dump(&s->dev); +#endif + return 0; +} + +/* + * Check if we can safely redirect a usb2 device to a usb1 virtual controller, + * this function assumes this is safe, if: + * 1) There are no isoc endpoints + * 2) There are no interrupt endpoints with a max_packet_size > 64 + * Note bulk endpoints with a max_packet_size > 64 in theory also are not + * usb1 compatible, but in practice this seems to work fine. + */ +static int usb_linux_full_speed_compat(USBHostDevice *dev) +{ + int i, packet_size; + + /* + * usb_linux_update_endp_table only registers info about ep in the current + * interface altsettings, so we need to parse the descriptors again. + */ + for (i = 0; (i + 5) < dev->descr_len; i += dev->descr[i]) { + if (dev->descr[i + 1] == USB_DT_ENDPOINT) { + switch (dev->descr[i + 3] & 0x3) { + case 0x00: /* CONTROL */ + break; + case 0x01: /* ISO */ + return 0; + case 0x02: /* BULK */ + break; + case 0x03: /* INTERRUPT */ + packet_size = dev->descr[i + 4] + (dev->descr[i + 5] << 8); + if (packet_size > 64) + return 0; + break; + } + } + } + return 1; +} + +static int usb_host_open(USBHostDevice *dev, int bus_num, + int addr, const char *port, + const char *prod_name, int speed) +{ + int fd = -1, ret; + + trace_usb_host_open_started(bus_num, addr); + + if (dev->fd != -1) { + goto fail; + } + + fd = usb_host_open_device(bus_num, addr); + if (fd < 0) { + goto fail; + } + DPRINTF("husb: opened %s\n", buf); + + dev->bus_num = bus_num; + dev->addr = addr; + strcpy(dev->port, port); + dev->fd = fd; + + /* read the device description */ + dev->descr_len = read(fd, dev->descr, sizeof(dev->descr)); + if (dev->descr_len <= 0) { + perror("husb: reading device data failed"); + goto fail; + } + +#ifdef DEBUG + { + int x; + printf("=== begin dumping device descriptor data ===\n"); + for (x = 0; x < dev->descr_len; x++) { + printf("%02x ", dev->descr[x]); + } + printf("\n=== end dumping device descriptor data ===\n"); + } +#endif + + + /* start unconfigured -- we'll wait for the guest to set a configuration */ + if (!usb_host_claim_interfaces(dev, 0)) { + goto fail; + } + + ret = usb_linux_update_endp_table(dev); + if (ret) { + goto fail; + } + + if (speed == -1) { + struct usbdevfs_connectinfo ci; + + ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci); + if (ret < 0) { + perror("usb_host_device_open: USBDEVFS_CONNECTINFO"); + goto fail; + } + + if (ci.slow) { + speed = USB_SPEED_LOW; + } else { + speed = USB_SPEED_HIGH; + } + } + dev->dev.speed = speed; + dev->dev.speedmask = (1 << speed); + if (dev->dev.speed == USB_SPEED_HIGH && usb_linux_full_speed_compat(dev)) { + dev->dev.speedmask |= USB_SPEED_MASK_FULL; + } + + trace_usb_host_open_success(bus_num, addr); + + if (!prod_name || prod_name[0] == '\0') { + snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc), + "host:%d.%d", bus_num, addr); + } else { + pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc), + prod_name); + } + + ret = usb_device_attach(&dev->dev); + if (ret) { + goto fail; + } + + /* USB devio uses 'write' flag to check for async completions */ + qemu_set_fd_handler(dev->fd, NULL, async_complete, dev); + + return 0; + +fail: + trace_usb_host_open_failure(bus_num, addr); + if (dev->fd != -1) { + close(dev->fd); + dev->fd = -1; + } + return -1; +} + +static int usb_host_close(USBHostDevice *dev) +{ + int i; + + if (dev->fd == -1) { + return -1; + } + + trace_usb_host_close(dev->bus_num, dev->addr); + + qemu_set_fd_handler(dev->fd, NULL, NULL, NULL); + dev->closing = 1; + for (i = 1; i <= USB_MAX_ENDPOINTS; i++) { + if (is_isoc(dev, USB_TOKEN_IN, i)) { + usb_host_stop_n_free_iso(dev, USB_TOKEN_IN, i); + } + if (is_isoc(dev, USB_TOKEN_OUT, i)) { + usb_host_stop_n_free_iso(dev, USB_TOKEN_OUT, i); + } + } + async_complete(dev); + dev->closing = 0; + if (dev->dev.attached) { + usb_device_detach(&dev->dev); + } + usb_host_do_reset(dev); + close(dev->fd); + dev->fd = -1; + return 0; +} + +static void usb_host_exit_notifier(struct Notifier *n, void *data) +{ + USBHostDevice *s = container_of(n, USBHostDevice, exit); + + usb_host_release_port(s); + if (s->fd != -1) { + usb_host_do_reset(s);; + } +} + +static int usb_host_initfn(USBDevice *dev) +{ + USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev); + + dev->auto_attach = 0; + s->fd = -1; + s->hub_fd = -1; + + QTAILQ_INSERT_TAIL(&hostdevs, s, next); + s->exit.notify = usb_host_exit_notifier; + qemu_add_exit_notifier(&s->exit); + usb_host_auto_check(NULL); + + if (s->match.bus_num != 0 && s->match.port != NULL) { + usb_host_claim_port(s); + } + return 0; +} + +static const VMStateDescription vmstate_usb_host = { + .name = "usb-host", + .unmigratable = 1, +}; + +static Property usb_host_dev_properties[] = { + DEFINE_PROP_UINT32("hostbus", USBHostDevice, match.bus_num, 0), + DEFINE_PROP_UINT32("hostaddr", USBHostDevice, match.addr, 0), + DEFINE_PROP_STRING("hostport", USBHostDevice, match.port), + DEFINE_PROP_HEX32("vendorid", USBHostDevice, match.vendor_id, 0), + DEFINE_PROP_HEX32("productid", USBHostDevice, match.product_id, 0), + DEFINE_PROP_UINT32("isobufs", USBHostDevice, iso_urb_count, 4), + DEFINE_PROP_END_OF_LIST(), +}; + +static void usb_host_class_initfn(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->init = usb_host_initfn; + uc->product_desc = "USB Host Device"; + uc->cancel_packet = usb_host_async_cancel; + uc->handle_data = usb_host_handle_data; + uc->handle_control = usb_host_handle_control; + uc->handle_reset = usb_host_handle_reset; + uc->handle_destroy = usb_host_handle_destroy; + dc->vmsd = &vmstate_usb_host; + dc->props = usb_host_dev_properties; +} + +static TypeInfo usb_host_dev_info = { + .name = "usb-host", + .parent = TYPE_USB_DEVICE, + .instance_size = sizeof(USBHostDevice), + .class_init = usb_host_class_initfn, +}; + +static void usb_host_register_types(void) +{ + type_register_static(&usb_host_dev_info); + usb_legacy_register("usb-host", "host", usb_host_device_open); +} + +type_init(usb_host_register_types) + +USBDevice *usb_host_device_open(USBBus *bus, const char *devname) +{ + struct USBAutoFilter filter; + USBDevice *dev; + char *p; + + dev = usb_create(bus, "usb-host"); + + if (strstr(devname, "auto:")) { + if (parse_filter(devname, &filter) < 0) { + goto fail; + } + } else { + if ((p = strchr(devname, '.'))) { + filter.bus_num = strtoul(devname, NULL, 0); + filter.addr = strtoul(p + 1, NULL, 0); + filter.vendor_id = 0; + filter.product_id = 0; + } else if ((p = strchr(devname, ':'))) { + filter.bus_num = 0; + filter.addr = 0; + filter.vendor_id = strtoul(devname, NULL, 16); + filter.product_id = strtoul(p + 1, NULL, 16); + } else { + goto fail; + } + } + + qdev_prop_set_uint32(&dev->qdev, "hostbus", filter.bus_num); + qdev_prop_set_uint32(&dev->qdev, "hostaddr", filter.addr); + qdev_prop_set_uint32(&dev->qdev, "vendorid", filter.vendor_id); + qdev_prop_set_uint32(&dev->qdev, "productid", filter.product_id); + qdev_init_nofail(&dev->qdev); + return dev; + +fail: + qdev_free(&dev->qdev); + return NULL; +} + +int usb_host_device_close(const char *devname) +{ +#if 0 + char product_name[PRODUCT_NAME_SZ]; + int bus_num, addr; + USBHostDevice *s; + + if (strstr(devname, "auto:")) { + return usb_host_auto_del(devname); + } + if (usb_host_find_device(&bus_num, &addr, product_name, + sizeof(product_name), devname) < 0) { + return -1; + } + s = hostdev_find(bus_num, addr); + if (s) { + usb_device_delete_addr(s->bus_num, s->dev.addr); + return 0; + } +#endif + + return -1; +} + +/* + * Read sys file-system device file + * + * @line address of buffer to put file contents in + * @line_size size of line + * @device_file path to device file (printf format string) + * @device_name device being opened (inserted into device_file) + * + * @return 0 failed, 1 succeeded ('line' contains data) + */ +static int usb_host_read_file(char *line, size_t line_size, + const char *device_file, const char *device_name) +{ + FILE *f; + int ret = 0; + char filename[PATH_MAX]; + + snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/%s", device_name, + device_file); + f = fopen(filename, "r"); + if (f) { + ret = fgets(line, line_size, f) != NULL; + fclose(f); + } + + return ret; +} + +/* + * Use /sys/bus/usb/devices/ directory to determine host's USB + * devices. + * + * This code is based on Robert Schiele's original patches posted to + * the Novell bug-tracker https://bugzilla.novell.com/show_bug.cgi?id=241950 + */ +static int usb_host_scan(void *opaque, USBScanFunc *func) +{ + DIR *dir = NULL; + char line[1024]; + int bus_num, addr, speed, class_id, product_id, vendor_id; + int ret = 0; + char port[MAX_PORTLEN]; + char product_name[512]; + struct dirent *de; + + dir = opendir("/sys/bus/usb/devices"); + if (!dir) { + perror("husb: opendir /sys/bus/usb/devices"); + fprintf(stderr, "husb: please make sure sysfs is mounted at /sys\n"); + goto the_end; + } + + while ((de = readdir(dir))) { + if (de->d_name[0] != '.' && !strchr(de->d_name, ':')) { + if (sscanf(de->d_name, "%d-%7[0-9.]", &bus_num, port) < 2) { + continue; + } + + if (!usb_host_read_file(line, sizeof(line), "devnum", de->d_name)) { + goto the_end; + } + if (sscanf(line, "%d", &addr) != 1) { + goto the_end; + } + if (!usb_host_read_file(line, sizeof(line), "bDeviceClass", + de->d_name)) { + goto the_end; + } + if (sscanf(line, "%x", &class_id) != 1) { + goto the_end; + } + + if (!usb_host_read_file(line, sizeof(line), "idVendor", + de->d_name)) { + goto the_end; + } + if (sscanf(line, "%x", &vendor_id) != 1) { + goto the_end; + } + if (!usb_host_read_file(line, sizeof(line), "idProduct", + de->d_name)) { + goto the_end; + } + if (sscanf(line, "%x", &product_id) != 1) { + goto the_end; + } + if (!usb_host_read_file(line, sizeof(line), "product", + de->d_name)) { + *product_name = 0; + } else { + if (strlen(line) > 0) { + line[strlen(line) - 1] = '\0'; + } + pstrcpy(product_name, sizeof(product_name), line); + } + + if (!usb_host_read_file(line, sizeof(line), "speed", de->d_name)) { + goto the_end; + } + if (!strcmp(line, "5000\n")) { + speed = USB_SPEED_SUPER; + } else if (!strcmp(line, "480\n")) { + speed = USB_SPEED_HIGH; + } else if (!strcmp(line, "1.5\n")) { + speed = USB_SPEED_LOW; + } else { + speed = USB_SPEED_FULL; + } + + ret = func(opaque, bus_num, addr, port, class_id, vendor_id, + product_id, product_name, speed); + if (ret) { + goto the_end; + } + } + } + the_end: + if (dir) { + closedir(dir); + } + return ret; +} + +static QEMUTimer *usb_auto_timer; + +static int usb_host_auto_scan(void *opaque, int bus_num, + int addr, const char *port, + int class_id, int vendor_id, int product_id, + const char *product_name, int speed) +{ + struct USBAutoFilter *f; + struct USBHostDevice *s; + + /* Ignore hubs */ + if (class_id == 9) + return 0; + + QTAILQ_FOREACH(s, &hostdevs, next) { + f = &s->match; + + if (f->bus_num > 0 && f->bus_num != bus_num) { + continue; + } + if (f->addr > 0 && f->addr != addr) { + continue; + } + if (f->port != NULL && (port == NULL || strcmp(f->port, port) != 0)) { + continue; + } + + if (f->vendor_id > 0 && f->vendor_id != vendor_id) { + continue; + } + + if (f->product_id > 0 && f->product_id != product_id) { + continue; + } + /* We got a match */ + s->seen++; + if (s->errcount >= 3) { + return 0; + } + + /* Already attached ? */ + if (s->fd != -1) { + return 0; + } + DPRINTF("husb: auto open: bus_num %d addr %d\n", bus_num, addr); + + if (usb_host_open(s, bus_num, addr, port, product_name, speed) < 0) { + s->errcount++; + } + break; + } + + return 0; +} + +static void usb_host_auto_check(void *unused) +{ + struct USBHostDevice *s; + int unconnected = 0; + + usb_host_scan(NULL, usb_host_auto_scan); + + QTAILQ_FOREACH(s, &hostdevs, next) { + if (s->fd == -1) { + unconnected++; + } + if (s->seen == 0) { + s->errcount = 0; + } + s->seen = 0; + } + + if (unconnected == 0) { + /* nothing to watch */ + if (usb_auto_timer) { + qemu_del_timer(usb_auto_timer); + trace_usb_host_auto_scan_disabled(); + } + return; + } + + if (!usb_auto_timer) { + usb_auto_timer = qemu_new_timer_ms(rt_clock, usb_host_auto_check, NULL); + if (!usb_auto_timer) { + return; + } + trace_usb_host_auto_scan_enabled(); + } + qemu_mod_timer(usb_auto_timer, qemu_get_clock_ms(rt_clock) + 2000); +} + +/* + * Autoconnect filter + * Format: + * auto:bus:dev[:vid:pid] + * auto:bus.dev[:vid:pid] + * + * bus - bus number (dec, * means any) + * dev - device number (dec, * means any) + * vid - vendor id (hex, * means any) + * pid - product id (hex, * means any) + * + * See 'lsusb' output. + */ +static int parse_filter(const char *spec, struct USBAutoFilter *f) +{ + enum { BUS, DEV, VID, PID, DONE }; + const char *p = spec; + int i; + + f->bus_num = 0; + f->addr = 0; + f->vendor_id = 0; + f->product_id = 0; + + for (i = BUS; i < DONE; i++) { + p = strpbrk(p, ":."); + if (!p) { + break; + } + p++; + + if (*p == '*') { + continue; + } + switch(i) { + case BUS: f->bus_num = strtol(p, NULL, 10); break; + case DEV: f->addr = strtol(p, NULL, 10); break; + case VID: f->vendor_id = strtol(p, NULL, 16); break; + case PID: f->product_id = strtol(p, NULL, 16); break; + } + } + + if (i < DEV) { + fprintf(stderr, "husb: invalid auto filter spec %s\n", spec); + return -1; + } + + return 0; +} + +/**********************/ +/* USB host device info */ + +struct usb_class_info { + int class; + const char *class_name; +}; + +static const struct usb_class_info usb_class_info[] = { + { USB_CLASS_AUDIO, "Audio"}, + { USB_CLASS_COMM, "Communication"}, + { USB_CLASS_HID, "HID"}, + { USB_CLASS_HUB, "Hub" }, + { USB_CLASS_PHYSICAL, "Physical" }, + { USB_CLASS_PRINTER, "Printer" }, + { USB_CLASS_MASS_STORAGE, "Storage" }, + { USB_CLASS_CDC_DATA, "Data" }, + { USB_CLASS_APP_SPEC, "Application Specific" }, + { USB_CLASS_VENDOR_SPEC, "Vendor Specific" }, + { USB_CLASS_STILL_IMAGE, "Still Image" }, + { USB_CLASS_CSCID, "Smart Card" }, + { USB_CLASS_CONTENT_SEC, "Content Security" }, + { -1, NULL } +}; + +static const char *usb_class_str(uint8_t class) +{ + const struct usb_class_info *p; + for(p = usb_class_info; p->class != -1; p++) { + if (p->class == class) { + break; + } + } + return p->class_name; +} + +static void usb_info_device(Monitor *mon, int bus_num, + int addr, const char *port, + int class_id, int vendor_id, int product_id, + const char *product_name, + int speed) +{ + const char *class_str, *speed_str; + + switch(speed) { + case USB_SPEED_LOW: + speed_str = "1.5"; + break; + case USB_SPEED_FULL: + speed_str = "12"; + break; + case USB_SPEED_HIGH: + speed_str = "480"; + break; + case USB_SPEED_SUPER: + speed_str = "5000"; + break; + default: + speed_str = "?"; + break; + } + + monitor_printf(mon, " Bus %d, Addr %d, Port %s, Speed %s Mb/s\n", + bus_num, addr, port, speed_str); + class_str = usb_class_str(class_id); + if (class_str) { + monitor_printf(mon, " %s:", class_str); + } else { + monitor_printf(mon, " Class %02x:", class_id); + } + monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id); + if (product_name[0] != '\0') { + monitor_printf(mon, ", %s", product_name); + } + monitor_printf(mon, "\n"); +} + +static int usb_host_info_device(void *opaque, int bus_num, int addr, + const char *path, int class_id, + int vendor_id, int product_id, + const char *product_name, + int speed) +{ + Monitor *mon = opaque; + + usb_info_device(mon, bus_num, addr, path, class_id, vendor_id, product_id, + product_name, speed); + return 0; +} + +static void dec2str(int val, char *str, size_t size) +{ + if (val == 0) { + snprintf(str, size, "*"); + } else { + snprintf(str, size, "%d", val); + } +} + +static void hex2str(int val, char *str, size_t size) +{ + if (val == 0) { + snprintf(str, size, "*"); + } else { + snprintf(str, size, "%04x", val); + } +} + +void usb_host_info(Monitor *mon) +{ + struct USBAutoFilter *f; + struct USBHostDevice *s; + + usb_host_scan(mon, usb_host_info_device); + + if (QTAILQ_EMPTY(&hostdevs)) { + return; + } + + monitor_printf(mon, " Auto filters:\n"); + QTAILQ_FOREACH(s, &hostdevs, next) { + char bus[10], addr[10], vid[10], pid[10]; + f = &s->match; + dec2str(f->bus_num, bus, sizeof(bus)); + dec2str(f->addr, addr, sizeof(addr)); + hex2str(f->vendor_id, vid, sizeof(vid)); + hex2str(f->product_id, pid, sizeof(pid)); + monitor_printf(mon, " Bus %s, Addr %s, Port %s, ID %s:%s\n", + bus, addr, f->port ? f->port : "*", vid, pid); + } +} diff --git a/hw/usb/host-stub.c b/hw/usb/host-stub.c new file mode 100644 index 0000000000..b4e10c12ca --- /dev/null +++ b/hw/usb/host-stub.c @@ -0,0 +1,52 @@ +/* + * Stub host USB redirector + * + * Copyright (c) 2005 Fabrice Bellard + * + * Copyright (c) 2008 Max Krasnyansky + * Support for host device auto connect & disconnect + * Major rewrite to support fully async operation + * + * Copyright 2008 TJ <linux@tjworld.net> + * Added flexible support for /dev/bus/usb /sys/bus/usb/devices in addition + * to the legacy /proc/bus/usb USB device discovery and handling + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu-common.h" +#include "console.h" +#include "hw/usb.h" +#include "monitor.h" + +void usb_host_info(Monitor *mon) +{ + monitor_printf(mon, "USB host devices not supported\n"); +} + +/* XXX: modify configure to compile the right host driver */ +USBDevice *usb_host_device_open(USBBus *bus, const char *devname) +{ + return NULL; +} + +int usb_host_device_close(const char *devname) +{ + return 0; +} diff --git a/hw/usb-libhw.c b/hw/usb/libhw.c index 162b42bd5b..2462351389 100644 --- a/hw/usb-libhw.c +++ b/hw/usb/libhw.c @@ -21,7 +21,7 @@ */ #include "qemu-common.h" #include "cpu-common.h" -#include "usb.h" +#include "hw/usb.h" #include "dma.h" int usb_packet_map(USBPacket *p, QEMUSGList *sgl) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c new file mode 100644 index 0000000000..8e9f175dbb --- /dev/null +++ b/hw/usb/redirect.c @@ -0,0 +1,1485 @@ +/* + * USB redirector usb-guest + * + * Copyright (c) 2011 Red Hat, Inc. + * + * Red Hat Authors: + * Hans de Goede <hdegoede@redhat.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu-common.h" +#include "qemu-timer.h" +#include "monitor.h" +#include "sysemu.h" + +#include <dirent.h> +#include <sys/ioctl.h> +#include <signal.h> +#include <usbredirparser.h> +#include <usbredirfilter.h> + +#include "hw/usb.h" + +#define MAX_ENDPOINTS 32 +#define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f)) +#define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f)) + +typedef struct AsyncURB AsyncURB; +typedef struct USBRedirDevice USBRedirDevice; + +/* Struct to hold buffered packets (iso or int input packets) */ +struct buf_packet { + uint8_t *data; + int len; + int status; + QTAILQ_ENTRY(buf_packet)next; +}; + +struct endp_data { + uint8_t type; + uint8_t interval; + uint8_t interface; /* bInterfaceNumber this ep belongs to */ + uint8_t iso_started; + uint8_t iso_error; /* For reporting iso errors to the HC */ + uint8_t interrupt_started; + uint8_t interrupt_error; + uint8_t bufpq_prefilled; + uint8_t bufpq_dropping_packets; + QTAILQ_HEAD(, buf_packet) bufpq; + int bufpq_size; + int bufpq_target_size; +}; + +struct USBRedirDevice { + USBDevice dev; + /* Properties */ + CharDriverState *cs; + uint8_t debug; + char *filter_str; + /* Data passed from chardev the fd_read cb to the usbredirparser read cb */ + const uint8_t *read_buf; + int read_buf_size; + /* For async handling of open/close */ + QEMUBH *open_close_bh; + /* To delay the usb attach in case of quick chardev close + open */ + QEMUTimer *attach_timer; + int64_t next_attach_time; + struct usbredirparser *parser; + struct endp_data endpoint[MAX_ENDPOINTS]; + uint32_t packet_id; + QTAILQ_HEAD(, AsyncURB) asyncq; + /* Data for device filtering */ + struct usb_redir_device_connect_header device_info; + struct usb_redir_interface_info_header interface_info; + struct usbredirfilter_rule *filter_rules; + int filter_rules_count; +}; + +struct AsyncURB { + USBRedirDevice *dev; + USBPacket *packet; + uint32_t packet_id; + int get; + union { + struct usb_redir_control_packet_header control_packet; + struct usb_redir_bulk_packet_header bulk_packet; + struct usb_redir_interrupt_packet_header interrupt_packet; + }; + QTAILQ_ENTRY(AsyncURB)next; +}; + +static void usbredir_hello(void *priv, struct usb_redir_hello_header *h); +static void usbredir_device_connect(void *priv, + struct usb_redir_device_connect_header *device_connect); +static void usbredir_device_disconnect(void *priv); +static void usbredir_interface_info(void *priv, + struct usb_redir_interface_info_header *interface_info); +static void usbredir_ep_info(void *priv, + struct usb_redir_ep_info_header *ep_info); +static void usbredir_configuration_status(void *priv, uint32_t id, + struct usb_redir_configuration_status_header *configuration_status); +static void usbredir_alt_setting_status(void *priv, uint32_t id, + struct usb_redir_alt_setting_status_header *alt_setting_status); +static void usbredir_iso_stream_status(void *priv, uint32_t id, + struct usb_redir_iso_stream_status_header *iso_stream_status); +static void usbredir_interrupt_receiving_status(void *priv, uint32_t id, + struct usb_redir_interrupt_receiving_status_header + *interrupt_receiving_status); +static void usbredir_bulk_streams_status(void *priv, uint32_t id, + struct usb_redir_bulk_streams_status_header *bulk_streams_status); +static void usbredir_control_packet(void *priv, uint32_t id, + struct usb_redir_control_packet_header *control_packet, + uint8_t *data, int data_len); +static void usbredir_bulk_packet(void *priv, uint32_t id, + struct usb_redir_bulk_packet_header *bulk_packet, + uint8_t *data, int data_len); +static void usbredir_iso_packet(void *priv, uint32_t id, + struct usb_redir_iso_packet_header *iso_packet, + uint8_t *data, int data_len); +static void usbredir_interrupt_packet(void *priv, uint32_t id, + struct usb_redir_interrupt_packet_header *interrupt_header, + uint8_t *data, int data_len); + +static int usbredir_handle_status(USBRedirDevice *dev, + int status, int actual_len); + +#define VERSION "qemu usb-redir guest " QEMU_VERSION + +/* + * Logging stuff + */ + +#define ERROR(...) \ + do { \ + if (dev->debug >= usbredirparser_error) { \ + error_report("usb-redir error: " __VA_ARGS__); \ + } \ + } while (0) +#define WARNING(...) \ + do { \ + if (dev->debug >= usbredirparser_warning) { \ + error_report("usb-redir warning: " __VA_ARGS__); \ + } \ + } while (0) +#define INFO(...) \ + do { \ + if (dev->debug >= usbredirparser_info) { \ + error_report("usb-redir: " __VA_ARGS__); \ + } \ + } while (0) +#define DPRINTF(...) \ + do { \ + if (dev->debug >= usbredirparser_debug) { \ + error_report("usb-redir: " __VA_ARGS__); \ + } \ + } while (0) +#define DPRINTF2(...) \ + do { \ + if (dev->debug >= usbredirparser_debug_data) { \ + error_report("usb-redir: " __VA_ARGS__); \ + } \ + } while (0) + +static void usbredir_log(void *priv, int level, const char *msg) +{ + USBRedirDevice *dev = priv; + + if (dev->debug < level) { + return; + } + + error_report("%s", msg); +} + +static void usbredir_log_data(USBRedirDevice *dev, const char *desc, + const uint8_t *data, int len) +{ + int i, j, n; + + if (dev->debug < usbredirparser_debug_data) { + return; + } + + for (i = 0; i < len; i += j) { + char buf[128]; + + n = sprintf(buf, "%s", desc); + for (j = 0; j < 8 && i + j < len; j++) { + n += sprintf(buf + n, " %02X", data[i + j]); + } + error_report("%s", buf); + } +} + +/* + * usbredirparser io functions + */ + +static int usbredir_read(void *priv, uint8_t *data, int count) +{ + USBRedirDevice *dev = priv; + + if (dev->read_buf_size < count) { + count = dev->read_buf_size; + } + + memcpy(data, dev->read_buf, count); + + dev->read_buf_size -= count; + if (dev->read_buf_size) { + dev->read_buf += count; + } else { + dev->read_buf = NULL; + } + + return count; +} + +static int usbredir_write(void *priv, uint8_t *data, int count) +{ + USBRedirDevice *dev = priv; + + if (!dev->cs->opened) { + return 0; + } + + return qemu_chr_fe_write(dev->cs, data, count); +} + +/* + * Async and buffered packets helpers + */ + +static AsyncURB *async_alloc(USBRedirDevice *dev, USBPacket *p) +{ + AsyncURB *aurb = (AsyncURB *) g_malloc0(sizeof(AsyncURB)); + aurb->dev = dev; + aurb->packet = p; + aurb->packet_id = dev->packet_id; + QTAILQ_INSERT_TAIL(&dev->asyncq, aurb, next); + dev->packet_id++; + + return aurb; +} + +static void async_free(USBRedirDevice *dev, AsyncURB *aurb) +{ + QTAILQ_REMOVE(&dev->asyncq, aurb, next); + g_free(aurb); +} + +static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id) +{ + AsyncURB *aurb; + + QTAILQ_FOREACH(aurb, &dev->asyncq, next) { + if (aurb->packet_id == packet_id) { + return aurb; + } + } + ERROR("could not find async urb for packet_id %u\n", packet_id); + return NULL; +} + +static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p) +{ + USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + AsyncURB *aurb; + + QTAILQ_FOREACH(aurb, &dev->asyncq, next) { + if (p != aurb->packet) { + continue; + } + + DPRINTF("async cancel id %u\n", aurb->packet_id); + usbredirparser_send_cancel_data_packet(dev->parser, aurb->packet_id); + usbredirparser_do_write(dev->parser); + + /* Mark it as dead */ + aurb->packet = NULL; + break; + } +} + +static void bufp_alloc(USBRedirDevice *dev, + uint8_t *data, int len, int status, uint8_t ep) +{ + struct buf_packet *bufp; + + if (!dev->endpoint[EP2I(ep)].bufpq_dropping_packets && + dev->endpoint[EP2I(ep)].bufpq_size > + 2 * dev->endpoint[EP2I(ep)].bufpq_target_size) { + DPRINTF("bufpq overflow, dropping packets ep %02X\n", ep); + dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 1; + } + /* Since we're interupting the stream anyways, drop enough packets to get + back to our target buffer size */ + if (dev->endpoint[EP2I(ep)].bufpq_dropping_packets) { + if (dev->endpoint[EP2I(ep)].bufpq_size > + dev->endpoint[EP2I(ep)].bufpq_target_size) { + free(data); + return; + } + dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0; + } + + bufp = g_malloc(sizeof(struct buf_packet)); + bufp->data = data; + bufp->len = len; + bufp->status = status; + QTAILQ_INSERT_TAIL(&dev->endpoint[EP2I(ep)].bufpq, bufp, next); + dev->endpoint[EP2I(ep)].bufpq_size++; +} + +static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp, + uint8_t ep) +{ + QTAILQ_REMOVE(&dev->endpoint[EP2I(ep)].bufpq, bufp, next); + dev->endpoint[EP2I(ep)].bufpq_size--; + free(bufp->data); + g_free(bufp); +} + +static void usbredir_free_bufpq(USBRedirDevice *dev, uint8_t ep) +{ + struct buf_packet *buf, *buf_next; + + QTAILQ_FOREACH_SAFE(buf, &dev->endpoint[EP2I(ep)].bufpq, next, buf_next) { + bufp_free(dev, buf, ep); + } +} + +/* + * USBDevice callbacks + */ + +static void usbredir_handle_reset(USBDevice *udev) +{ + USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + + DPRINTF("reset device\n"); + usbredirparser_send_reset(dev->parser); + usbredirparser_do_write(dev->parser); +} + +static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p, + uint8_t ep) +{ + int status, len; + if (!dev->endpoint[EP2I(ep)].iso_started && + !dev->endpoint[EP2I(ep)].iso_error) { + struct usb_redir_start_iso_stream_header start_iso = { + .endpoint = ep, + }; + int pkts_per_sec; + + if (dev->dev.speed == USB_SPEED_HIGH) { + pkts_per_sec = 8000 / dev->endpoint[EP2I(ep)].interval; + } else { + pkts_per_sec = 1000 / dev->endpoint[EP2I(ep)].interval; + } + /* Testing has shown that we need circa 60 ms buffer */ + dev->endpoint[EP2I(ep)].bufpq_target_size = (pkts_per_sec * 60) / 1000; + + /* Aim for approx 100 interrupts / second on the client to + balance latency and interrupt load */ + start_iso.pkts_per_urb = pkts_per_sec / 100; + if (start_iso.pkts_per_urb < 1) { + start_iso.pkts_per_urb = 1; + } else if (start_iso.pkts_per_urb > 32) { + start_iso.pkts_per_urb = 32; + } + + start_iso.no_urbs = (dev->endpoint[EP2I(ep)].bufpq_target_size + + start_iso.pkts_per_urb - 1) / + start_iso.pkts_per_urb; + /* Output endpoints pre-fill only 1/2 of the packets, keeping the rest + as overflow buffer. Also see the usbredir protocol documentation */ + if (!(ep & USB_DIR_IN)) { + start_iso.no_urbs *= 2; + } + if (start_iso.no_urbs > 16) { + start_iso.no_urbs = 16; + } + + /* No id, we look at the ep when receiving a status back */ + usbredirparser_send_start_iso_stream(dev->parser, 0, &start_iso); + usbredirparser_do_write(dev->parser); + DPRINTF("iso stream started pkts/sec %d pkts/urb %d urbs %d ep %02X\n", + pkts_per_sec, start_iso.pkts_per_urb, start_iso.no_urbs, ep); + dev->endpoint[EP2I(ep)].iso_started = 1; + dev->endpoint[EP2I(ep)].bufpq_prefilled = 0; + dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0; + } + + if (ep & USB_DIR_IN) { + struct buf_packet *isop; + + if (dev->endpoint[EP2I(ep)].iso_started && + !dev->endpoint[EP2I(ep)].bufpq_prefilled) { + if (dev->endpoint[EP2I(ep)].bufpq_size < + dev->endpoint[EP2I(ep)].bufpq_target_size) { + return usbredir_handle_status(dev, 0, 0); + } + dev->endpoint[EP2I(ep)].bufpq_prefilled = 1; + } + + isop = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq); + if (isop == NULL) { + DPRINTF("iso-token-in ep %02X, no isop, iso_error: %d\n", + ep, dev->endpoint[EP2I(ep)].iso_error); + /* Re-fill the buffer */ + dev->endpoint[EP2I(ep)].bufpq_prefilled = 0; + /* Check iso_error for stream errors, otherwise its an underrun */ + status = dev->endpoint[EP2I(ep)].iso_error; + dev->endpoint[EP2I(ep)].iso_error = 0; + return status ? USB_RET_IOERROR : 0; + } + DPRINTF2("iso-token-in ep %02X status %d len %d queue-size: %d\n", ep, + isop->status, isop->len, dev->endpoint[EP2I(ep)].bufpq_size); + + status = isop->status; + if (status != usb_redir_success) { + bufp_free(dev, isop, ep); + return USB_RET_IOERROR; + } + + len = isop->len; + if (len > p->iov.size) { + ERROR("received iso data is larger then packet ep %02X (%d > %d)\n", + ep, len, (int)p->iov.size); + bufp_free(dev, isop, ep); + return USB_RET_BABBLE; + } + usb_packet_copy(p, isop->data, len); + bufp_free(dev, isop, ep); + return len; + } else { + /* If the stream was not started because of a pending error don't + send the packet to the usb-host */ + if (dev->endpoint[EP2I(ep)].iso_started) { + struct usb_redir_iso_packet_header iso_packet = { + .endpoint = ep, + .length = p->iov.size + }; + uint8_t buf[p->iov.size]; + /* No id, we look at the ep when receiving a status back */ + usb_packet_copy(p, buf, p->iov.size); + usbredirparser_send_iso_packet(dev->parser, 0, &iso_packet, + buf, p->iov.size); + usbredirparser_do_write(dev->parser); + } + status = dev->endpoint[EP2I(ep)].iso_error; + dev->endpoint[EP2I(ep)].iso_error = 0; + DPRINTF2("iso-token-out ep %02X status %d len %zd\n", ep, status, + p->iov.size); + return usbredir_handle_status(dev, status, p->iov.size); + } +} + +static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep) +{ + struct usb_redir_stop_iso_stream_header stop_iso_stream = { + .endpoint = ep + }; + if (dev->endpoint[EP2I(ep)].iso_started) { + usbredirparser_send_stop_iso_stream(dev->parser, 0, &stop_iso_stream); + DPRINTF("iso stream stopped ep %02X\n", ep); + dev->endpoint[EP2I(ep)].iso_started = 0; + } + dev->endpoint[EP2I(ep)].iso_error = 0; + usbredir_free_bufpq(dev, ep); +} + +static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p, + uint8_t ep) +{ + AsyncURB *aurb = async_alloc(dev, p); + struct usb_redir_bulk_packet_header bulk_packet; + + DPRINTF("bulk-out ep %02X len %zd id %u\n", ep, + p->iov.size, aurb->packet_id); + + bulk_packet.endpoint = ep; + bulk_packet.length = p->iov.size; + bulk_packet.stream_id = 0; + aurb->bulk_packet = bulk_packet; + + if (ep & USB_DIR_IN) { + usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id, + &bulk_packet, NULL, 0); + } else { + uint8_t buf[p->iov.size]; + usb_packet_copy(p, buf, p->iov.size); + usbredir_log_data(dev, "bulk data out:", buf, p->iov.size); + usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id, + &bulk_packet, buf, p->iov.size); + } + usbredirparser_do_write(dev->parser); + return USB_RET_ASYNC; +} + +static int usbredir_handle_interrupt_data(USBRedirDevice *dev, + USBPacket *p, uint8_t ep) +{ + if (ep & USB_DIR_IN) { + /* Input interrupt endpoint, buffered packet input */ + struct buf_packet *intp; + int status, len; + + if (!dev->endpoint[EP2I(ep)].interrupt_started && + !dev->endpoint[EP2I(ep)].interrupt_error) { + struct usb_redir_start_interrupt_receiving_header start_int = { + .endpoint = ep, + }; + /* No id, we look at the ep when receiving a status back */ + usbredirparser_send_start_interrupt_receiving(dev->parser, 0, + &start_int); + usbredirparser_do_write(dev->parser); + DPRINTF("interrupt recv started ep %02X\n", ep); + dev->endpoint[EP2I(ep)].interrupt_started = 1; + /* We don't really want to drop interrupt packets ever, but + having some upper limit to how much we buffer is good. */ + dev->endpoint[EP2I(ep)].bufpq_target_size = 1000; + dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0; + } + + intp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq); + if (intp == NULL) { + DPRINTF2("interrupt-token-in ep %02X, no intp\n", ep); + /* Check interrupt_error for stream errors */ + status = dev->endpoint[EP2I(ep)].interrupt_error; + dev->endpoint[EP2I(ep)].interrupt_error = 0; + if (status) { + return usbredir_handle_status(dev, status, 0); + } + return USB_RET_NAK; + } + DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep, + intp->status, intp->len); + + status = intp->status; + if (status != usb_redir_success) { + bufp_free(dev, intp, ep); + return usbredir_handle_status(dev, status, 0); + } + + len = intp->len; + if (len > p->iov.size) { + ERROR("received int data is larger then packet ep %02X\n", ep); + bufp_free(dev, intp, ep); + return USB_RET_BABBLE; + } + usb_packet_copy(p, intp->data, len); + bufp_free(dev, intp, ep); + return len; + } else { + /* Output interrupt endpoint, normal async operation */ + AsyncURB *aurb = async_alloc(dev, p); + struct usb_redir_interrupt_packet_header interrupt_packet; + uint8_t buf[p->iov.size]; + + DPRINTF("interrupt-out ep %02X len %zd id %u\n", ep, p->iov.size, + aurb->packet_id); + + interrupt_packet.endpoint = ep; + interrupt_packet.length = p->iov.size; + aurb->interrupt_packet = interrupt_packet; + + usb_packet_copy(p, buf, p->iov.size); + usbredir_log_data(dev, "interrupt data out:", buf, p->iov.size); + usbredirparser_send_interrupt_packet(dev->parser, aurb->packet_id, + &interrupt_packet, buf, p->iov.size); + usbredirparser_do_write(dev->parser); + return USB_RET_ASYNC; + } +} + +static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev, + uint8_t ep) +{ + struct usb_redir_stop_interrupt_receiving_header stop_interrupt_recv = { + .endpoint = ep + }; + if (dev->endpoint[EP2I(ep)].interrupt_started) { + usbredirparser_send_stop_interrupt_receiving(dev->parser, 0, + &stop_interrupt_recv); + DPRINTF("interrupt recv stopped ep %02X\n", ep); + dev->endpoint[EP2I(ep)].interrupt_started = 0; + } + dev->endpoint[EP2I(ep)].interrupt_error = 0; + usbredir_free_bufpq(dev, ep); +} + +static int usbredir_handle_data(USBDevice *udev, USBPacket *p) +{ + USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + uint8_t ep; + + ep = p->ep->nr; + if (p->pid == USB_TOKEN_IN) { + ep |= USB_DIR_IN; + } + + switch (dev->endpoint[EP2I(ep)].type) { + case USB_ENDPOINT_XFER_CONTROL: + ERROR("handle_data called for control transfer on ep %02X\n", ep); + return USB_RET_NAK; + case USB_ENDPOINT_XFER_ISOC: + return usbredir_handle_iso_data(dev, p, ep); + case USB_ENDPOINT_XFER_BULK: + return usbredir_handle_bulk_data(dev, p, ep); + case USB_ENDPOINT_XFER_INT: + return usbredir_handle_interrupt_data(dev, p, ep); + default: + ERROR("handle_data ep %02X has unknown type %d\n", ep, + dev->endpoint[EP2I(ep)].type); + return USB_RET_NAK; + } +} + +static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p, + int config) +{ + struct usb_redir_set_configuration_header set_config; + AsyncURB *aurb = async_alloc(dev, p); + int i; + + DPRINTF("set config %d id %u\n", config, aurb->packet_id); + + for (i = 0; i < MAX_ENDPOINTS; i++) { + switch (dev->endpoint[i].type) { + case USB_ENDPOINT_XFER_ISOC: + usbredir_stop_iso_stream(dev, I2EP(i)); + break; + case USB_ENDPOINT_XFER_INT: + if (i & 0x10) { + usbredir_stop_interrupt_receiving(dev, I2EP(i)); + } + break; + } + usbredir_free_bufpq(dev, I2EP(i)); + } + + set_config.configuration = config; + usbredirparser_send_set_configuration(dev->parser, aurb->packet_id, + &set_config); + usbredirparser_do_write(dev->parser); + return USB_RET_ASYNC; +} + +static int usbredir_get_config(USBRedirDevice *dev, USBPacket *p) +{ + AsyncURB *aurb = async_alloc(dev, p); + + DPRINTF("get config id %u\n", aurb->packet_id); + + aurb->get = 1; + usbredirparser_send_get_configuration(dev->parser, aurb->packet_id); + usbredirparser_do_write(dev->parser); + return USB_RET_ASYNC; +} + +static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p, + int interface, int alt) +{ + struct usb_redir_set_alt_setting_header set_alt; + AsyncURB *aurb = async_alloc(dev, p); + int i; + + DPRINTF("set interface %d alt %d id %u\n", interface, alt, + aurb->packet_id); + + for (i = 0; i < MAX_ENDPOINTS; i++) { + if (dev->endpoint[i].interface == interface) { + switch (dev->endpoint[i].type) { + case USB_ENDPOINT_XFER_ISOC: + usbredir_stop_iso_stream(dev, I2EP(i)); + break; + case USB_ENDPOINT_XFER_INT: + if (i & 0x10) { + usbredir_stop_interrupt_receiving(dev, I2EP(i)); + } + break; + } + usbredir_free_bufpq(dev, I2EP(i)); + } + } + + set_alt.interface = interface; + set_alt.alt = alt; + usbredirparser_send_set_alt_setting(dev->parser, aurb->packet_id, + &set_alt); + usbredirparser_do_write(dev->parser); + return USB_RET_ASYNC; +} + +static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p, + int interface) +{ + struct usb_redir_get_alt_setting_header get_alt; + AsyncURB *aurb = async_alloc(dev, p); + + DPRINTF("get interface %d id %u\n", interface, aurb->packet_id); + + get_alt.interface = interface; + aurb->get = 1; + usbredirparser_send_get_alt_setting(dev->parser, aurb->packet_id, + &get_alt); + usbredirparser_do_write(dev->parser); + return USB_RET_ASYNC; +} + +static int usbredir_handle_control(USBDevice *udev, USBPacket *p, + int request, int value, int index, int length, uint8_t *data) +{ + USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + struct usb_redir_control_packet_header control_packet; + AsyncURB *aurb; + + /* Special cases for certain standard device requests */ + switch (request) { + case DeviceOutRequest | USB_REQ_SET_ADDRESS: + DPRINTF("set address %d\n", value); + dev->dev.addr = value; + return 0; + case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: + return usbredir_set_config(dev, p, value & 0xff); + case DeviceRequest | USB_REQ_GET_CONFIGURATION: + return usbredir_get_config(dev, p); + case InterfaceOutRequest | USB_REQ_SET_INTERFACE: + return usbredir_set_interface(dev, p, index, value); + case InterfaceRequest | USB_REQ_GET_INTERFACE: + return usbredir_get_interface(dev, p, index); + } + + /* "Normal" ctrl requests */ + aurb = async_alloc(dev, p); + + /* Note request is (bRequestType << 8) | bRequest */ + DPRINTF("ctrl-out type 0x%x req 0x%x val 0x%x index %d len %d id %u\n", + request >> 8, request & 0xff, value, index, length, + aurb->packet_id); + + control_packet.request = request & 0xFF; + control_packet.requesttype = request >> 8; + control_packet.endpoint = control_packet.requesttype & USB_DIR_IN; + control_packet.value = value; + control_packet.index = index; + control_packet.length = length; + aurb->control_packet = control_packet; + + if (control_packet.requesttype & USB_DIR_IN) { + usbredirparser_send_control_packet(dev->parser, aurb->packet_id, + &control_packet, NULL, 0); + } else { + usbredir_log_data(dev, "ctrl data out:", data, length); + usbredirparser_send_control_packet(dev->parser, aurb->packet_id, + &control_packet, data, length); + } + usbredirparser_do_write(dev->parser); + return USB_RET_ASYNC; +} + +/* + * Close events can be triggered by usbredirparser_do_write which gets called + * from within the USBDevice data / control packet callbacks and doing a + * usb_detach from within these callbacks is not a good idea. + * + * So we use a bh handler to take care of close events. We also handle + * open events from this callback to make sure that a close directly followed + * by an open gets handled in the right order. + */ +static void usbredir_open_close_bh(void *opaque) +{ + USBRedirDevice *dev = opaque; + uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, }; + + usbredir_device_disconnect(dev); + + if (dev->parser) { + usbredirparser_destroy(dev->parser); + dev->parser = NULL; + } + + if (dev->cs->opened) { + dev->parser = qemu_oom_check(usbredirparser_create()); + dev->parser->priv = dev; + dev->parser->log_func = usbredir_log; + dev->parser->read_func = usbredir_read; + dev->parser->write_func = usbredir_write; + dev->parser->hello_func = usbredir_hello; + dev->parser->device_connect_func = usbredir_device_connect; + dev->parser->device_disconnect_func = usbredir_device_disconnect; + dev->parser->interface_info_func = usbredir_interface_info; + dev->parser->ep_info_func = usbredir_ep_info; + dev->parser->configuration_status_func = usbredir_configuration_status; + dev->parser->alt_setting_status_func = usbredir_alt_setting_status; + dev->parser->iso_stream_status_func = usbredir_iso_stream_status; + dev->parser->interrupt_receiving_status_func = + usbredir_interrupt_receiving_status; + dev->parser->bulk_streams_status_func = usbredir_bulk_streams_status; + dev->parser->control_packet_func = usbredir_control_packet; + dev->parser->bulk_packet_func = usbredir_bulk_packet; + dev->parser->iso_packet_func = usbredir_iso_packet; + dev->parser->interrupt_packet_func = usbredir_interrupt_packet; + dev->read_buf = NULL; + dev->read_buf_size = 0; + + usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version); + usbredirparser_caps_set_cap(caps, usb_redir_cap_filter); + usbredirparser_init(dev->parser, VERSION, caps, USB_REDIR_CAPS_SIZE, 0); + usbredirparser_do_write(dev->parser); + } +} + +static void usbredir_do_attach(void *opaque) +{ + USBRedirDevice *dev = opaque; + + usb_device_attach(&dev->dev); +} + +/* + * chardev callbacks + */ + +static int usbredir_chardev_can_read(void *opaque) +{ + USBRedirDevice *dev = opaque; + + if (dev->parser) { + /* usbredir_parser_do_read will consume *all* data we give it */ + return 1024 * 1024; + } else { + /* usbredir_open_close_bh hasn't handled the open event yet */ + return 0; + } +} + +static void usbredir_chardev_read(void *opaque, const uint8_t *buf, int size) +{ + USBRedirDevice *dev = opaque; + + /* No recursion allowed! */ + assert(dev->read_buf == NULL); + + dev->read_buf = buf; + dev->read_buf_size = size; + + usbredirparser_do_read(dev->parser); + /* Send any acks, etc. which may be queued now */ + usbredirparser_do_write(dev->parser); +} + +static void usbredir_chardev_event(void *opaque, int event) +{ + USBRedirDevice *dev = opaque; + + switch (event) { + case CHR_EVENT_OPENED: + case CHR_EVENT_CLOSED: + qemu_bh_schedule(dev->open_close_bh); + break; + } +} + +/* + * init + destroy + */ + +static int usbredir_initfn(USBDevice *udev) +{ + USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + int i; + + if (dev->cs == NULL) { + qerror_report(QERR_MISSING_PARAMETER, "chardev"); + return -1; + } + + if (dev->filter_str) { + i = usbredirfilter_string_to_rules(dev->filter_str, ":", "|", + &dev->filter_rules, + &dev->filter_rules_count); + if (i) { + qerror_report(QERR_INVALID_PARAMETER_VALUE, "filter", + "a usb device filter string"); + return -1; + } + } + + dev->open_close_bh = qemu_bh_new(usbredir_open_close_bh, dev); + dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev); + + QTAILQ_INIT(&dev->asyncq); + for (i = 0; i < MAX_ENDPOINTS; i++) { + QTAILQ_INIT(&dev->endpoint[i].bufpq); + } + + /* We'll do the attach once we receive the speed from the usb-host */ + udev->auto_attach = 0; + + /* Let the backend know we are ready */ + qemu_chr_fe_open(dev->cs); + qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read, + usbredir_chardev_read, usbredir_chardev_event, dev); + + return 0; +} + +static void usbredir_cleanup_device_queues(USBRedirDevice *dev) +{ + AsyncURB *aurb, *next_aurb; + int i; + + QTAILQ_FOREACH_SAFE(aurb, &dev->asyncq, next, next_aurb) { + async_free(dev, aurb); + } + for (i = 0; i < MAX_ENDPOINTS; i++) { + usbredir_free_bufpq(dev, I2EP(i)); + } +} + +static void usbredir_handle_destroy(USBDevice *udev) +{ + USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + + qemu_chr_fe_close(dev->cs); + qemu_chr_delete(dev->cs); + /* Note must be done after qemu_chr_close, as that causes a close event */ + qemu_bh_delete(dev->open_close_bh); + + qemu_del_timer(dev->attach_timer); + qemu_free_timer(dev->attach_timer); + + usbredir_cleanup_device_queues(dev); + + if (dev->parser) { + usbredirparser_destroy(dev->parser); + } + + free(dev->filter_rules); +} + +static int usbredir_check_filter(USBRedirDevice *dev) +{ + if (dev->interface_info.interface_count == 0) { + ERROR("No interface info for device\n"); + goto error; + } + + if (dev->filter_rules) { + if (!usbredirparser_peer_has_cap(dev->parser, + usb_redir_cap_connect_device_version)) { + ERROR("Device filter specified and peer does not have the " + "connect_device_version capability\n"); + goto error; + } + + if (usbredirfilter_check( + dev->filter_rules, + dev->filter_rules_count, + dev->device_info.device_class, + dev->device_info.device_subclass, + dev->device_info.device_protocol, + dev->interface_info.interface_class, + dev->interface_info.interface_subclass, + dev->interface_info.interface_protocol, + dev->interface_info.interface_count, + dev->device_info.vendor_id, + dev->device_info.product_id, + dev->device_info.device_version_bcd, + 0) != 0) { + goto error; + } + } + + return 0; + +error: + usbredir_device_disconnect(dev); + if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter)) { + usbredirparser_send_filter_reject(dev->parser); + usbredirparser_do_write(dev->parser); + } + return -1; +} + +/* + * usbredirparser packet complete callbacks + */ + +static int usbredir_handle_status(USBRedirDevice *dev, + int status, int actual_len) +{ + switch (status) { + case usb_redir_success: + return actual_len; + case usb_redir_stall: + return USB_RET_STALL; + case usb_redir_cancelled: + WARNING("returning cancelled packet to HC?\n"); + return USB_RET_NAK; + case usb_redir_inval: + WARNING("got invalid param error from usb-host?\n"); + return USB_RET_NAK; + case usb_redir_ioerror: + case usb_redir_timeout: + default: + return USB_RET_IOERROR; + } +} + +static void usbredir_hello(void *priv, struct usb_redir_hello_header *h) +{ + USBRedirDevice *dev = priv; + + /* Try to send the filter info now that we've the usb-host's caps */ + if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter) && + dev->filter_rules) { + usbredirparser_send_filter_filter(dev->parser, dev->filter_rules, + dev->filter_rules_count); + usbredirparser_do_write(dev->parser); + } +} + +static void usbredir_device_connect(void *priv, + struct usb_redir_device_connect_header *device_connect) +{ + USBRedirDevice *dev = priv; + const char *speed; + + if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) { + ERROR("Received device connect while already connected\n"); + return; + } + + switch (device_connect->speed) { + case usb_redir_speed_low: + speed = "low speed"; + dev->dev.speed = USB_SPEED_LOW; + break; + case usb_redir_speed_full: + speed = "full speed"; + dev->dev.speed = USB_SPEED_FULL; + break; + case usb_redir_speed_high: + speed = "high speed"; + dev->dev.speed = USB_SPEED_HIGH; + break; + case usb_redir_speed_super: + speed = "super speed"; + dev->dev.speed = USB_SPEED_SUPER; + break; + default: + speed = "unknown speed"; + dev->dev.speed = USB_SPEED_FULL; + } + + if (usbredirparser_peer_has_cap(dev->parser, + usb_redir_cap_connect_device_version)) { + INFO("attaching %s device %04x:%04x version %d.%d class %02x\n", + speed, device_connect->vendor_id, device_connect->product_id, + ((device_connect->device_version_bcd & 0xf000) >> 12) * 10 + + ((device_connect->device_version_bcd & 0x0f00) >> 8), + ((device_connect->device_version_bcd & 0x00f0) >> 4) * 10 + + ((device_connect->device_version_bcd & 0x000f) >> 0), + device_connect->device_class); + } else { + INFO("attaching %s device %04x:%04x class %02x\n", speed, + device_connect->vendor_id, device_connect->product_id, + device_connect->device_class); + } + + dev->dev.speedmask = (1 << dev->dev.speed); + dev->device_info = *device_connect; + + if (usbredir_check_filter(dev)) { + WARNING("Device %04x:%04x rejected by device filter, not attaching\n", + device_connect->vendor_id, device_connect->product_id); + return; + } + + qemu_mod_timer(dev->attach_timer, dev->next_attach_time); +} + +static void usbredir_device_disconnect(void *priv) +{ + USBRedirDevice *dev = priv; + int i; + + /* Stop any pending attaches */ + qemu_del_timer(dev->attach_timer); + + if (dev->dev.attached) { + usb_device_detach(&dev->dev); + /* + * Delay next usb device attach to give the guest a chance to see + * see the detach / attach in case of quick close / open succession + */ + dev->next_attach_time = qemu_get_clock_ms(vm_clock) + 200; + } + + /* Reset state so that the next dev connected starts with a clean slate */ + usbredir_cleanup_device_queues(dev); + memset(dev->endpoint, 0, sizeof(dev->endpoint)); + for (i = 0; i < MAX_ENDPOINTS; i++) { + QTAILQ_INIT(&dev->endpoint[i].bufpq); + } + usb_ep_init(&dev->dev); + dev->interface_info.interface_count = 0; +} + +static void usbredir_interface_info(void *priv, + struct usb_redir_interface_info_header *interface_info) +{ + USBRedirDevice *dev = priv; + + dev->interface_info = *interface_info; + + /* + * If we receive interface info after the device has already been + * connected (ie on a set_config), re-check the filter. + */ + if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) { + if (usbredir_check_filter(dev)) { + ERROR("Device no longer matches filter after interface info " + "change, disconnecting!\n"); + } + } +} + +static void usbredir_ep_info(void *priv, + struct usb_redir_ep_info_header *ep_info) +{ + USBRedirDevice *dev = priv; + struct USBEndpoint *usb_ep; + int i; + + for (i = 0; i < MAX_ENDPOINTS; i++) { + dev->endpoint[i].type = ep_info->type[i]; + dev->endpoint[i].interval = ep_info->interval[i]; + dev->endpoint[i].interface = ep_info->interface[i]; + switch (dev->endpoint[i].type) { + case usb_redir_type_invalid: + break; + case usb_redir_type_iso: + case usb_redir_type_interrupt: + if (dev->endpoint[i].interval == 0) { + ERROR("Received 0 interval for isoc or irq endpoint\n"); + usbredir_device_disconnect(dev); + } + /* Fall through */ + case usb_redir_type_control: + case usb_redir_type_bulk: + DPRINTF("ep: %02X type: %d interface: %d\n", I2EP(i), + dev->endpoint[i].type, dev->endpoint[i].interface); + break; + default: + ERROR("Received invalid endpoint type\n"); + usbredir_device_disconnect(dev); + return; + } + usb_ep = usb_ep_get(&dev->dev, + (i & 0x10) ? USB_TOKEN_IN : USB_TOKEN_OUT, + i & 0x0f); + usb_ep->type = dev->endpoint[i].type; + usb_ep->ifnum = dev->endpoint[i].interface; + } +} + +static void usbredir_configuration_status(void *priv, uint32_t id, + struct usb_redir_configuration_status_header *config_status) +{ + USBRedirDevice *dev = priv; + AsyncURB *aurb; + int len = 0; + + DPRINTF("set config status %d config %d id %u\n", config_status->status, + config_status->configuration, id); + + aurb = async_find(dev, id); + if (!aurb) { + return; + } + if (aurb->packet) { + if (aurb->get) { + dev->dev.data_buf[0] = config_status->configuration; + len = 1; + } + aurb->packet->result = + usbredir_handle_status(dev, config_status->status, len); + usb_generic_async_ctrl_complete(&dev->dev, aurb->packet); + } + async_free(dev, aurb); +} + +static void usbredir_alt_setting_status(void *priv, uint32_t id, + struct usb_redir_alt_setting_status_header *alt_setting_status) +{ + USBRedirDevice *dev = priv; + AsyncURB *aurb; + int len = 0; + + DPRINTF("alt status %d intf %d alt %d id: %u\n", + alt_setting_status->status, + alt_setting_status->interface, + alt_setting_status->alt, id); + + aurb = async_find(dev, id); + if (!aurb) { + return; + } + if (aurb->packet) { + if (aurb->get) { + dev->dev.data_buf[0] = alt_setting_status->alt; + len = 1; + } + aurb->packet->result = + usbredir_handle_status(dev, alt_setting_status->status, len); + usb_generic_async_ctrl_complete(&dev->dev, aurb->packet); + } + async_free(dev, aurb); +} + +static void usbredir_iso_stream_status(void *priv, uint32_t id, + struct usb_redir_iso_stream_status_header *iso_stream_status) +{ + USBRedirDevice *dev = priv; + uint8_t ep = iso_stream_status->endpoint; + + DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status, + ep, id); + + if (!dev->dev.attached || !dev->endpoint[EP2I(ep)].iso_started) { + return; + } + + dev->endpoint[EP2I(ep)].iso_error = iso_stream_status->status; + if (iso_stream_status->status == usb_redir_stall) { + DPRINTF("iso stream stopped by peer ep %02X\n", ep); + dev->endpoint[EP2I(ep)].iso_started = 0; + } +} + +static void usbredir_interrupt_receiving_status(void *priv, uint32_t id, + struct usb_redir_interrupt_receiving_status_header + *interrupt_receiving_status) +{ + USBRedirDevice *dev = priv; + uint8_t ep = interrupt_receiving_status->endpoint; + + DPRINTF("interrupt recv status %d ep %02X id %u\n", + interrupt_receiving_status->status, ep, id); + + if (!dev->dev.attached || !dev->endpoint[EP2I(ep)].interrupt_started) { + return; + } + + dev->endpoint[EP2I(ep)].interrupt_error = + interrupt_receiving_status->status; + if (interrupt_receiving_status->status == usb_redir_stall) { + DPRINTF("interrupt receiving stopped by peer ep %02X\n", ep); + dev->endpoint[EP2I(ep)].interrupt_started = 0; + } +} + +static void usbredir_bulk_streams_status(void *priv, uint32_t id, + struct usb_redir_bulk_streams_status_header *bulk_streams_status) +{ +} + +static void usbredir_control_packet(void *priv, uint32_t id, + struct usb_redir_control_packet_header *control_packet, + uint8_t *data, int data_len) +{ + USBRedirDevice *dev = priv; + int len = control_packet->length; + AsyncURB *aurb; + + DPRINTF("ctrl-in status %d len %d id %u\n", control_packet->status, + len, id); + + aurb = async_find(dev, id); + if (!aurb) { + free(data); + return; + } + + aurb->control_packet.status = control_packet->status; + aurb->control_packet.length = control_packet->length; + if (memcmp(&aurb->control_packet, control_packet, + sizeof(*control_packet))) { + ERROR("return control packet mismatch, please report this!\n"); + len = USB_RET_NAK; + } + + if (aurb->packet) { + len = usbredir_handle_status(dev, control_packet->status, len); + if (len > 0) { + usbredir_log_data(dev, "ctrl data in:", data, data_len); + if (data_len <= sizeof(dev->dev.data_buf)) { + memcpy(dev->dev.data_buf, data, data_len); + } else { + ERROR("ctrl buffer too small (%d > %zu)\n", + data_len, sizeof(dev->dev.data_buf)); + len = USB_RET_STALL; + } + } + aurb->packet->result = len; + usb_generic_async_ctrl_complete(&dev->dev, aurb->packet); + } + async_free(dev, aurb); + free(data); +} + +static void usbredir_bulk_packet(void *priv, uint32_t id, + struct usb_redir_bulk_packet_header *bulk_packet, + uint8_t *data, int data_len) +{ + USBRedirDevice *dev = priv; + uint8_t ep = bulk_packet->endpoint; + int len = bulk_packet->length; + AsyncURB *aurb; + + DPRINTF("bulk-in status %d ep %02X len %d id %u\n", bulk_packet->status, + ep, len, id); + + aurb = async_find(dev, id); + if (!aurb) { + free(data); + return; + } + + if (aurb->bulk_packet.endpoint != bulk_packet->endpoint || + aurb->bulk_packet.stream_id != bulk_packet->stream_id) { + ERROR("return bulk packet mismatch, please report this!\n"); + len = USB_RET_NAK; + } + + if (aurb->packet) { + len = usbredir_handle_status(dev, bulk_packet->status, len); + if (len > 0) { + usbredir_log_data(dev, "bulk data in:", data, data_len); + if (data_len <= aurb->packet->iov.size) { + usb_packet_copy(aurb->packet, data, data_len); + } else { + ERROR("bulk buffer too small (%d > %zd)\n", data_len, + aurb->packet->iov.size); + len = USB_RET_STALL; + } + } + aurb->packet->result = len; + usb_packet_complete(&dev->dev, aurb->packet); + } + async_free(dev, aurb); + free(data); +} + +static void usbredir_iso_packet(void *priv, uint32_t id, + struct usb_redir_iso_packet_header *iso_packet, + uint8_t *data, int data_len) +{ + USBRedirDevice *dev = priv; + uint8_t ep = iso_packet->endpoint; + + DPRINTF2("iso-in status %d ep %02X len %d id %u\n", iso_packet->status, ep, + data_len, id); + + if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_ISOC) { + ERROR("received iso packet for non iso endpoint %02X\n", ep); + free(data); + return; + } + + if (dev->endpoint[EP2I(ep)].iso_started == 0) { + DPRINTF("received iso packet for non started stream ep %02X\n", ep); + free(data); + return; + } + + /* bufp_alloc also adds the packet to the ep queue */ + bufp_alloc(dev, data, data_len, iso_packet->status, ep); +} + +static void usbredir_interrupt_packet(void *priv, uint32_t id, + struct usb_redir_interrupt_packet_header *interrupt_packet, + uint8_t *data, int data_len) +{ + USBRedirDevice *dev = priv; + uint8_t ep = interrupt_packet->endpoint; + + DPRINTF("interrupt-in status %d ep %02X len %d id %u\n", + interrupt_packet->status, ep, data_len, id); + + if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_INT) { + ERROR("received int packet for non interrupt endpoint %02X\n", ep); + free(data); + return; + } + + if (ep & USB_DIR_IN) { + if (dev->endpoint[EP2I(ep)].interrupt_started == 0) { + DPRINTF("received int packet while not started ep %02X\n", ep); + free(data); + return; + } + + /* bufp_alloc also adds the packet to the ep queue */ + bufp_alloc(dev, data, data_len, interrupt_packet->status, ep); + } else { + int len = interrupt_packet->length; + + AsyncURB *aurb = async_find(dev, id); + if (!aurb) { + return; + } + + if (aurb->interrupt_packet.endpoint != interrupt_packet->endpoint) { + ERROR("return int packet mismatch, please report this!\n"); + len = USB_RET_NAK; + } + + if (aurb->packet) { + aurb->packet->result = usbredir_handle_status(dev, + interrupt_packet->status, len); + usb_packet_complete(&dev->dev, aurb->packet); + } + async_free(dev, aurb); + } +} + +static Property usbredir_properties[] = { + DEFINE_PROP_CHR("chardev", USBRedirDevice, cs), + DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0), + DEFINE_PROP_STRING("filter", USBRedirDevice, filter_str), + DEFINE_PROP_END_OF_LIST(), +}; + +static void usbredir_class_initfn(ObjectClass *klass, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + uc->init = usbredir_initfn; + uc->product_desc = "USB Redirection Device"; + uc->handle_destroy = usbredir_handle_destroy; + uc->cancel_packet = usbredir_cancel_packet; + uc->handle_reset = usbredir_handle_reset; + uc->handle_data = usbredir_handle_data; + uc->handle_control = usbredir_handle_control; + dc->props = usbredir_properties; +} + +static TypeInfo usbredir_dev_info = { + .name = "usb-redir", + .parent = TYPE_USB_DEVICE, + .instance_size = sizeof(USBRedirDevice), + .class_init = usbredir_class_initfn, +}; + +static void usbredir_register_types(void) +{ + type_register_static(&usbredir_dev_info); +} + +type_init(usbredir_register_types) diff --git a/hw/versatilepb.c b/hw/versatilepb.c index b9102f4a54..25afb1eb31 100644 --- a/hw/versatilepb.c +++ b/hw/versatilepb.c @@ -13,7 +13,6 @@ #include "net.h" #include "sysemu.h" #include "pci.h" -#include "usb-ohci.h" #include "boards.h" #include "blockdev.h" #include "exec-memory.h" @@ -168,7 +167,7 @@ static void versatile_init(ram_addr_t ram_size, const char *initrd_filename, const char *cpu_model, int board_id) { - CPUState *env; + CPUARMState *env; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); qemu_irq *cpu_pic; @@ -240,7 +239,7 @@ static void versatile_init(ram_addr_t ram_size, } } if (usb_enabled) { - usb_ohci_init_pci(pci_bus, -1); + pci_create_simple(pci_bus, -1, "pci-ohci"); } n = drive_get_max_bus(IF_SCSI); while (n >= 0) { diff --git a/hw/vexpress.c b/hw/vexpress.c index b9aafec4cc..18d87ac378 100644 --- a/hw/vexpress.c +++ b/hw/vexpress.c @@ -159,7 +159,7 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard, const char *cpu_model, qemu_irq *pic, uint32_t *proc_id) { - CPUState *env = NULL; + CPUARMState *env = NULL; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *lowram = g_new(MemoryRegion, 1); @@ -259,7 +259,7 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard, qemu_irq *pic, uint32_t *proc_id) { int n; - CPUState *env = NULL; + CPUARMState *env = NULL; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *sram = g_new(MemoryRegion, 1); diff --git a/hw/vga.c b/hw/vga.c index 5994f43b75..6dc98f6c2a 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -30,6 +30,7 @@ #include "pixel_ops.h" #include "qemu-timer.h" #include "xen.h" +#include "trace.h" //#define DEBUG_VGA //#define DEBUG_VGA_MEM @@ -2372,6 +2373,7 @@ int ppm_save(const char *filename, struct DisplaySurface *ds) int ret; char *linebuf, *pbuf; + trace_ppm_save(filename, ds); f = fopen(filename, "wb"); if (!f) return -1; diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c index f8d2b1be04..4a133b5d1e 100644 --- a/hw/virtex_ml507.c +++ b/hw/virtex_ml507.c @@ -56,7 +56,7 @@ static struct boot_info } boot_info; /* Create reset TLB entries for BookE, spanning the 32bit addr space. */ -static void mmubooke_create_initial_mapping(CPUState *env, +static void mmubooke_create_initial_mapping(CPUPPCState *env, target_ulong va, target_phys_addr_t pa) { @@ -78,12 +78,12 @@ static void mmubooke_create_initial_mapping(CPUState *env, tlb->PID = 0; } -static CPUState *ppc440_init_xilinx(ram_addr_t *ram_size, +static CPUPPCState *ppc440_init_xilinx(ram_addr_t *ram_size, int do_init, const char *cpu_model, uint32_t sysclk) { - CPUState *env; + CPUPPCState *env; qemu_irq *irqs; env = cpu_init(cpu_model); @@ -106,10 +106,10 @@ static CPUState *ppc440_init_xilinx(ram_addr_t *ram_size, static void main_cpu_reset(void *opaque) { - CPUState *env = opaque; + CPUPPCState *env = opaque; struct boot_info *bi = env->load_info; - cpu_reset(env); + cpu_state_reset(env); /* Linux Kernel Parameters (passing device tree): * r3: pointer to the fdt * r4: 0 @@ -188,7 +188,7 @@ static void virtex_init(ram_addr_t ram_size, { MemoryRegion *address_space_mem = get_system_memory(); DeviceState *dev; - CPUState *env; + CPUPPCState *env; target_phys_addr_t ram_base = 0; DriveInfo *dinfo; MemoryRegion *phys_ram = g_new(MemoryRegion, 1); diff --git a/hw/vmport.c b/hw/vmport.c index 9373be9775..a4f52ee5bb 100644 --- a/hw/vmport.c +++ b/hw/vmport.c @@ -57,7 +57,7 @@ void vmport_register(unsigned char command, IOPortReadFunc *func, void *opaque) static uint32_t vmport_ioport_read(void *opaque, uint32_t addr) { VMPortState *s = opaque; - CPUState *env = cpu_single_env; + CPUX86State *env = cpu_single_env; unsigned char command; uint32_t eax; @@ -83,21 +83,21 @@ static uint32_t vmport_ioport_read(void *opaque, uint32_t addr) static void vmport_ioport_write(void *opaque, uint32_t addr, uint32_t val) { - CPUState *env = cpu_single_env; + CPUX86State *env = cpu_single_env; env->regs[R_EAX] = vmport_ioport_read(opaque, addr); } static uint32_t vmport_cmd_get_version(void *opaque, uint32_t addr) { - CPUState *env = cpu_single_env; + CPUX86State *env = cpu_single_env; env->regs[R_EBX] = VMPORT_MAGIC; return 6; } static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr) { - CPUState *env = cpu_single_env; + CPUX86State *env = cpu_single_env; env->regs[R_EBX] = 0x1177; return ram_size; } @@ -105,7 +105,7 @@ static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr) /* vmmouse helpers */ void vmmouse_get_data(uint32_t *data) { - CPUState *env = cpu_single_env; + CPUX86State *env = cpu_single_env; data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX]; data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX]; @@ -114,7 +114,7 @@ void vmmouse_get_data(uint32_t *data) void vmmouse_set_data(const uint32_t *data) { - CPUState *env = cpu_single_env; + CPUX86State *env = cpu_single_env; env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1]; env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3]; diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c index 7985d11d5a..7eee770eea 100644 --- a/hw/xen_machine_pv.c +++ b/hw/xen_machine_pv.c @@ -36,7 +36,7 @@ static void xen_init_pv(ram_addr_t ram_size, const char *initrd_filename, const char *cpu_model) { - CPUState *env; + CPUX86State *env; DriveInfo *dinfo; int i; diff --git a/hw/xics.c b/hw/xics.c index 1c5eaa4135..f7963f3096 100644 --- a/hw/xics.c +++ b/hw/xics.c @@ -268,7 +268,7 @@ qemu_irq xics_find_qirq(struct icp_state *icp, int irq) return icp->ics->qirqs[irq - icp->ics->offset]; } -static target_ulong h_cppr(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_cppr(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong cppr = args[0]; @@ -277,7 +277,7 @@ static target_ulong h_cppr(CPUState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -static target_ulong h_ipi(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_ipi(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong server = args[0]; @@ -292,7 +292,7 @@ static target_ulong h_ipi(CPUState *env, sPAPREnvironment *spapr, } -static target_ulong h_xirr(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_xirr(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { uint32_t xirr = icp_accept(spapr->icp->ss + env->cpu_index); @@ -301,7 +301,7 @@ static target_ulong h_xirr(CPUState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -static target_ulong h_eoi(CPUState *env, sPAPREnvironment *spapr, +static target_ulong h_eoi(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { target_ulong xirr = args[0]; @@ -424,7 +424,7 @@ static void rtas_int_on(sPAPREnvironment *spapr, uint32_t token, struct icp_state *xics_system_init(int nr_irqs) { - CPUState *env; + CPUPPCState *env; int max_server_num; int i; struct icp_state *icp; diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c index ea13e8c844..7290c64a4c 100644 --- a/hw/xilinx_zynq.c +++ b/hw/xilinx_zynq.c @@ -50,7 +50,7 @@ static void zynq_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) { - CPUState *env = NULL; + CPUARMState *env = NULL; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ext_ram = g_new(MemoryRegion, 1); MemoryRegion *ocm_ram = g_new(MemoryRegion, 1); diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c index 26112c3eb0..afdef494b2 100644 --- a/hw/xtensa_lx60.c +++ b/hw/xtensa_lx60.c @@ -146,9 +146,11 @@ static uint64_t translate_phys_addr(void *env, uint64_t addr) return cpu_get_phys_page_debug(env, addr); } -static void lx60_reset(void *env) +static void lx60_reset(void *opaque) { - cpu_reset(env); + CPUXtensaState *env = opaque; + + cpu_state_reset(env); } static void lx_init(const LxBoardDesc *board, @@ -162,7 +164,7 @@ static void lx_init(const LxBoardDesc *board, int be = 0; #endif MemoryRegion *system_memory = get_system_memory(); - CPUState *env = NULL; + CPUXtensaState *env = NULL; MemoryRegion *ram, *rom, *system_io; DriveInfo *dinfo; pflash_t *flash = NULL; @@ -183,7 +185,7 @@ static void lx_init(const LxBoardDesc *board, /* Need MMU initialized prior to ELF loading, * so that ELF gets loaded into virtual addresses */ - cpu_reset(env); + cpu_state_reset(env); } ram = g_malloc(sizeof(*ram)); diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c index 71d5fc89d4..653ded6820 100644 --- a/hw/xtensa_pic.c +++ b/hw/xtensa_pic.c @@ -29,7 +29,7 @@ #include "qemu-log.h" #include "qemu-timer.h" -void xtensa_advance_ccount(CPUState *env, uint32_t d) +void xtensa_advance_ccount(CPUXtensaState *env, uint32_t d) { uint32_t old_ccount = env->sregs[CCOUNT]; @@ -45,7 +45,7 @@ void xtensa_advance_ccount(CPUState *env, uint32_t d) } } -void check_interrupts(CPUState *env) +void check_interrupts(CPUXtensaState *env) { int minlevel = xtensa_get_cintlevel(env); uint32_t int_set_enabled = env->sregs[INTSET] & env->sregs[INTENABLE]; @@ -84,7 +84,7 @@ void check_interrupts(CPUState *env) static void xtensa_set_irq(void *opaque, int irq, int active) { - CPUState *env = opaque; + CPUXtensaState *env = opaque; if (irq >= env->config->ninterrupt) { qemu_log("%s: bad IRQ %d\n", __func__, irq); @@ -101,12 +101,12 @@ static void xtensa_set_irq(void *opaque, int irq, int active) } } -void xtensa_timer_irq(CPUState *env, uint32_t id, uint32_t active) +void xtensa_timer_irq(CPUXtensaState *env, uint32_t id, uint32_t active) { qemu_set_irq(env->irq_inputs[env->config->timerint[id]], active); } -void xtensa_rearm_ccompare_timer(CPUState *env) +void xtensa_rearm_ccompare_timer(CPUXtensaState *env) { int i; uint32_t wake_ccount = env->sregs[CCOUNT] - 1; @@ -125,7 +125,7 @@ void xtensa_rearm_ccompare_timer(CPUState *env) static void xtensa_ccompare_cb(void *opaque) { - CPUState *env = opaque; + CPUXtensaState *env = opaque; if (env->halted) { env->halt_clock = qemu_get_clock_ns(vm_clock); @@ -137,7 +137,7 @@ static void xtensa_ccompare_cb(void *opaque) } } -void xtensa_irq_init(CPUState *env) +void xtensa_irq_init(CPUXtensaState *env) { env->irq_inputs = (void **)qemu_allocate_irqs( xtensa_set_irq, env, env->config->ninterrupt); @@ -148,7 +148,7 @@ void xtensa_irq_init(CPUState *env) } } -void *xtensa_get_extint(CPUState *env, unsigned extint) +void *xtensa_get_extint(CPUXtensaState *env, unsigned extint) { if (extint < env->config->nextint) { unsigned irq = env->config->extint[extint]; diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c index 104e5dc619..c7e05dcf4e 100644 --- a/hw/xtensa_sim.c +++ b/hw/xtensa_sim.c @@ -39,7 +39,7 @@ static uint64_t translate_phys_addr(void *env, uint64_t addr) static void sim_reset(void *env) { - cpu_reset(env); + cpu_state_reset(env); } static void sim_init(ram_addr_t ram_size, @@ -47,7 +47,7 @@ static void sim_init(ram_addr_t ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - CPUState *env = NULL; + CPUXtensaState *env = NULL; MemoryRegion *ram, *rom; int n; |