diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/char/serial.c | 58 | ||||
-rw-r--r-- | hw/i386/kvm/apic.c | 10 | ||||
-rw-r--r-- | hw/i386/kvm/clock.c | 3 | ||||
-rw-r--r-- | hw/i386/kvm/i8254.c | 2 | ||||
-rw-r--r-- | hw/i386/multiboot.c | 32 | ||||
-rw-r--r-- | hw/i386/pc.c | 3 | ||||
-rw-r--r-- | hw/i386/pc_piix.c | 47 | ||||
-rw-r--r-- | hw/i386/pc_q35.c | 44 | ||||
-rw-r--r-- | hw/i386/pc_sysfw.c | 4 | ||||
-rw-r--r-- | hw/intc/apic_common.c | 5 | ||||
-rw-r--r-- | hw/intc/openpic_kvm.c | 1 | ||||
-rw-r--r-- | hw/intc/xics_kvm.c | 1 | ||||
-rw-r--r-- | hw/misc/vfio.c | 5 | ||||
-rw-r--r-- | hw/scsi/lsi53c895a.c | 2 | ||||
-rw-r--r-- | hw/scsi/megasas.c | 6 | ||||
-rw-r--r-- | hw/scsi/scsi-disk.c | 27 | ||||
-rw-r--r-- | hw/scsi/scsi-generic.c | 6 | ||||
-rw-r--r-- | hw/scsi/virtio-scsi.c | 2 | ||||
-rw-r--r-- | hw/sd/sdhci.c | 209 | ||||
-rw-r--r-- | hw/sd/sdhci.h | 39 |
20 files changed, 323 insertions, 183 deletions
diff --git a/hw/char/serial.c b/hw/char/serial.c index ebcacdc872..6d522ff4f3 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -224,21 +224,23 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque) SerialState *s = opaque; do { + assert(!(s->lsr & UART_LSR_TEMT)); if (s->tsr_retry <= 0) { + assert(!(s->lsr & UART_LSR_THRE)); + if (s->fcr & UART_FCR_FE) { - if (fifo8_is_empty(&s->xmit_fifo)) { - return FALSE; - } + assert(!fifo8_is_empty(&s->xmit_fifo)); s->tsr = fifo8_pop(&s->xmit_fifo); if (!s->xmit_fifo.num) { s->lsr |= UART_LSR_THRE; } - } else if ((s->lsr & UART_LSR_THRE)) { - return FALSE; } else { s->tsr = s->thr; s->lsr |= UART_LSR_THRE; - s->lsr &= ~UART_LSR_TEMT; + } + if ((s->lsr & UART_LSR_THRE) && !s->thr_ipending) { + s->thr_ipending = 1; + serial_update_irq(s); } } @@ -256,17 +258,13 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque) } else { s->tsr_retry = 0; } + /* Transmit another byte if it is already available. It is only possible when FIFO is enabled and not empty. */ - } while ((s->fcr & UART_FCR_FE) && !fifo8_is_empty(&s->xmit_fifo)); + } while (!(s->lsr & UART_LSR_THRE)); s->last_xmit_ts = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - - if (s->lsr & UART_LSR_THRE) { - s->lsr |= UART_LSR_TEMT; - s->thr_ipending = 1; - serial_update_irq(s); - } + s->lsr |= UART_LSR_TEMT; return FALSE; } @@ -323,10 +321,10 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, fifo8_pop(&s->xmit_fifo); } fifo8_push(&s->xmit_fifo, s->thr); - s->lsr &= ~UART_LSR_TEMT; } s->thr_ipending = 0; s->lsr &= ~UART_LSR_THRE; + s->lsr &= ~UART_LSR_TEMT; serial_update_irq(s); if (s->tsr_retry <= 0) { serial_xmit(NULL, G_IO_OUT, s); @@ -338,10 +336,12 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, s->divider = (s->divider & 0x00ff) | (val << 8); serial_update_parameters(s); } else { + uint8_t changed = (s->ier ^ val) & 0x0f; s->ier = val & 0x0f; /* If the backend device is a real serial port, turn polling of the modem - status lines on physical port on or off depending on UART_IER_MSI state */ - if (s->poll_msl >= 0) { + * status lines on physical port on or off depending on UART_IER_MSI state. + */ + if ((changed & UART_IER_MSI) && s->poll_msl >= 0) { if (s->ier & UART_IER_MSI) { s->poll_msl = 1; serial_update_msl(s); @@ -350,8 +350,27 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, s->poll_msl = 0; } } - if (s->lsr & UART_LSR_THRE) { - s->thr_ipending = 1; + + /* Turning on the THRE interrupt on IER can trigger the interrupt + * if LSR.THRE=1, even if it had been masked before by reading IIR. + * This is not in the datasheet, but Windows relies on it. It is + * unclear if THRE has to be resampled every time THRI becomes + * 1, or only on the rising edge. Bochs does the latter, and Windows + * always toggles IER to all zeroes and back to all ones, so do the + * same. + * + * If IER.THRI is zero, thr_ipending is not used. Set it to zero + * so that the thr_ipending subsection is not migrated. + */ + if (changed & UART_IER_THRI) { + if ((s->ier & UART_IER_THRI) && (s->lsr & UART_LSR_THRE)) { + s->thr_ipending = 1; + } else { + s->thr_ipending = 0; + } + } + + if (changed) { serial_update_irq(s); } } @@ -365,12 +384,15 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, /* FIFO clear */ if (val & UART_FCR_RFR) { + s->lsr &= ~(UART_LSR_DR | UART_LSR_BI); timer_del(s->fifo_timeout_timer); s->timeout_ipending = 0; fifo8_reset(&s->recv_fifo); } if (val & UART_FCR_XFR) { + s->lsr |= UART_LSR_THRE; + s->thr_ipending = 1; fifo8_reset(&s->xmit_fifo); } diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c index 271e97f86f..5b470562a6 100644 --- a/hw/i386/kvm/apic.c +++ b/hw/i386/kvm/apic.c @@ -171,12 +171,15 @@ static const MemoryRegionOps kvm_apic_io_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void kvm_apic_realize(DeviceState *dev, Error **errp) +static void kvm_apic_reset(APICCommonState *s) { - APICCommonState *s = APIC_COMMON(dev); - /* Not used by KVM, which uses the CPU mp_state instead. */ s->wait_for_sipi = 0; +} + +static void kvm_apic_realize(DeviceState *dev, Error **errp) +{ + APICCommonState *s = APIC_COMMON(dev); memory_region_init_io(&s->io_memory, NULL, &kvm_apic_io_ops, s, "kvm-apic-msi", APIC_SPACE_SIZE); @@ -191,6 +194,7 @@ static void kvm_apic_class_init(ObjectClass *klass, void *data) APICCommonClass *k = APIC_COMMON_CLASS(klass); k->realize = kvm_apic_realize; + k->reset = kvm_apic_reset; k->set_base = kvm_apic_set_base; k->set_tpr = kvm_apic_set_tpr; k->get_tpr = kvm_apic_get_tpr; diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c index 58be2bda27..efdf165848 100644 --- a/hw/i386/kvm/clock.c +++ b/hw/i386/kvm/clock.c @@ -88,7 +88,7 @@ static void kvmclock_vm_state_change(void *opaque, int running, int ret; if (running) { - struct kvm_clock_data data; + struct kvm_clock_data data = {}; uint64_t time_at_migration = kvmclock_current_nsec(s); s->clock_valid = false; @@ -99,7 +99,6 @@ static void kvmclock_vm_state_change(void *opaque, int running, } data.clock = s->clock; - data.flags = 0; ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data); if (ret < 0) { fprintf(stderr, "KVM_SET_CLOCK failed: %s\n", strerror(ret)); diff --git a/hw/i386/kvm/i8254.c b/hw/i386/kvm/i8254.c index 472af811cd..90eea10df7 100644 --- a/hw/i386/kvm/i8254.c +++ b/hw/i386/kvm/i8254.c @@ -138,7 +138,7 @@ static void kvm_pit_get(PITCommonState *pit) static void kvm_pit_put(PITCommonState *pit) { KVMPITState *s = KVM_PIT(pit); - struct kvm_pit_state2 kpit; + struct kvm_pit_state2 kpit = {}; struct kvm_pit_channel_state *kchan; struct PITChannelState *sc; int i, ret; diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c index 985ca1ed84..f86d351b3e 100644 --- a/hw/i386/multiboot.c +++ b/hw/i386/multiboot.c @@ -54,6 +54,7 @@ enum { MBI_MODS_COUNT = 20, MBI_MODS_ADDR = 24, MBI_MMAP_ADDR = 48, + MBI_BOOTLOADER = 64, MBI_SIZE = 88, @@ -74,6 +75,7 @@ enum { MULTIBOOT_FLAGS_CMDLINE = 1 << 2, MULTIBOOT_FLAGS_MODULES = 1 << 3, MULTIBOOT_FLAGS_MMAP = 1 << 6, + MULTIBOOT_FLAGS_BOOTLOADER = 1 << 9, }; typedef struct { @@ -87,6 +89,8 @@ typedef struct { hwaddr offset_mbinfo; /* offset in buffer for cmdlines in bytes */ hwaddr offset_cmdlines; + /* offset in buffer for bootloader name in bytes */ + hwaddr offset_bootloader; /* offset of modules in bytes */ hwaddr offset_mods; /* available slots for mb modules infos */ @@ -95,6 +99,8 @@ typedef struct { int mb_mods_count; } MultibootState; +const char *bootloader_name = "qemu"; + static uint32_t mb_add_cmdline(MultibootState *s, const char *cmdline) { hwaddr p = s->offset_cmdlines; @@ -105,6 +111,16 @@ static uint32_t mb_add_cmdline(MultibootState *s, const char *cmdline) return s->mb_buf_phys + p; } +static uint32_t mb_add_bootloader(MultibootState *s, const char *bootloader) +{ + hwaddr p = s->offset_bootloader; + char *b = (char *)s->mb_buf + p; + + memcpy(b, bootloader, strlen(bootloader) + 1); + s->offset_bootloader += strlen(b) + 1; + return s->mb_buf_phys + p; +} + static void mb_add_mod(MultibootState *s, hwaddr start, hwaddr end, hwaddr cmdline_phys) @@ -241,9 +257,10 @@ int load_multiboot(FWCfgState *fw_cfg, mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_kernel_size); mbs.offset_mbinfo = mbs.mb_buf_size; - /* Calculate space for cmdlines and mb_mods */ + /* Calculate space for cmdlines, bootloader name, and mb_mods */ mbs.mb_buf_size += strlen(kernel_filename) + 1; mbs.mb_buf_size += strlen(kernel_cmdline) + 1; + mbs.mb_buf_size += strlen(bootloader_name) + 1; if (initrd_filename) { const char *r = initrd_filename; mbs.mb_buf_size += strlen(r) + 1; @@ -257,9 +274,11 @@ int load_multiboot(FWCfgState *fw_cfg, mbs.mb_buf_size = TARGET_PAGE_ALIGN(mbs.mb_buf_size); - /* enlarge mb_buf to hold cmdlines and mb-info structs */ - mbs.mb_buf = g_realloc(mbs.mb_buf, mbs.mb_buf_size); - mbs.offset_cmdlines = mbs.offset_mbinfo + mbs.mb_mods_avail * MB_MOD_SIZE; + /* enlarge mb_buf to hold cmdlines, bootloader, mb-info structs */ + mbs.mb_buf = g_realloc(mbs.mb_buf, mbs.mb_buf_size); + mbs.offset_cmdlines = mbs.offset_mbinfo + mbs.mb_mods_avail * MB_MOD_SIZE; + mbs.offset_bootloader = mbs.offset_cmdlines + strlen(kernel_filename) + 1 + + strlen(kernel_cmdline) + 1; if (initrd_filename) { char *next_initrd, not_last; @@ -306,6 +325,8 @@ int load_multiboot(FWCfgState *fw_cfg, kernel_filename, kernel_cmdline); stl_p(bootinfo + MBI_CMDLINE, mb_add_cmdline(&mbs, kcmdline)); + stl_p(bootinfo + MBI_BOOTLOADER, mb_add_bootloader(&mbs, bootloader_name)); + stl_p(bootinfo + MBI_MODS_ADDR, mbs.mb_buf_phys + mbs.offset_mbinfo); stl_p(bootinfo + MBI_MODS_COUNT, mbs.mb_mods_count); /* mods_count */ @@ -314,7 +335,8 @@ int load_multiboot(FWCfgState *fw_cfg, | MULTIBOOT_FLAGS_BOOT_DEVICE | MULTIBOOT_FLAGS_CMDLINE | MULTIBOOT_FLAGS_MODULES - | MULTIBOOT_FLAGS_MMAP); + | MULTIBOOT_FLAGS_MMAP + | MULTIBOOT_FLAGS_BOOTLOADER); stl_p(bootinfo + MBI_BOOT_DEVICE, 0x8000ffff); /* XXX: use the -boot switch? */ stl_p(bootinfo + MBI_MMAP_ADDR, ADDR_E820_MAP); diff --git a/hw/i386/pc.c b/hw/i386/pc.c index f31d55e7ea..c0e55a6446 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -602,8 +602,7 @@ int e820_add_entry(uint64_t address, uint64_t length, uint32_t type) } /* new "etc/e820" file -- include ram too */ - e820_table = g_realloc(e820_table, - sizeof(struct e820_entry) * (e820_entries+1)); + e820_table = g_renew(struct e820_entry, e820_table, e820_entries + 1); e820_table[e820_entries].address = cpu_to_le64(address); e820_table[e820_entries].length = cpu_to_le64(length); e820_table[e820_entries].type = cpu_to_le32(type); diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 85ed3c8785..220f7415fa 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -308,9 +308,33 @@ static void pc_init_pci(MachineState *machine) pc_init1(machine, 1, 1); } +static void pc_compat_2_2(MachineState *machine) +{ + x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Conroe", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Penryn", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Nehalem", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Westmere", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("SandyBridge", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Haswell", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Broadwell", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Opteron_G1", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Opteron_G2", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Opteron_G3", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Opteron_G4", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Opteron_G5", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Haswell", FEAT_1_ECX, 0, CPUID_EXT_F16C); + x86_cpu_compat_set_features("Haswell", FEAT_1_ECX, 0, CPUID_EXT_RDRAND); + x86_cpu_compat_set_features("Broadwell", FEAT_1_ECX, 0, CPUID_EXT_F16C); + x86_cpu_compat_set_features("Broadwell", FEAT_1_ECX, 0, CPUID_EXT_RDRAND); +} + static void pc_compat_2_1(MachineState *machine) { PCMachineState *pcms = PC_MACHINE(machine); + + pc_compat_2_2(machine); smbios_uuid_encoded = false; x86_cpu_compat_set_features("coreduo", FEAT_1_ECX, CPUID_EXT_VMX, 0); x86_cpu_compat_set_features("core2duo", FEAT_1_ECX, CPUID_EXT_VMX, 0); @@ -385,6 +409,12 @@ static void pc_compat_1_2(MachineState *machine) x86_cpu_compat_kvm_no_autoenable(FEAT_KVM, KVM_FEATURE_PV_EOI); } +static void pc_init_pci_2_2(MachineState *machine) +{ + pc_compat_2_2(machine); + pc_init_pci(machine); +} + static void pc_init_pci_2_1(MachineState *machine) { pc_compat_2_1(machine); @@ -478,19 +508,27 @@ static void pc_xen_hvm_init(MachineState *machine) .desc = "Standard PC (i440FX + PIIX, 1996)", \ .hot_add_cpu = pc_hot_add_cpu -#define PC_I440FX_2_2_MACHINE_OPTIONS \ +#define PC_I440FX_2_3_MACHINE_OPTIONS \ PC_I440FX_MACHINE_OPTIONS, \ .default_machine_opts = "firmware=bios-256k.bin", \ .default_display = "std" -static QEMUMachine pc_i440fx_machine_v2_2 = { - PC_I440FX_2_2_MACHINE_OPTIONS, - .name = "pc-i440fx-2.2", +static QEMUMachine pc_i440fx_machine_v2_3 = { + PC_I440FX_2_3_MACHINE_OPTIONS, + .name = "pc-i440fx-2.3", .alias = "pc", .init = pc_init_pci, .is_default = 1, }; +#define PC_I440FX_2_2_MACHINE_OPTIONS PC_I440FX_2_3_MACHINE_OPTIONS + +static QEMUMachine pc_i440fx_machine_v2_2 = { + PC_I440FX_2_2_MACHINE_OPTIONS, + .name = "pc-i440fx-2.2", + .init = pc_init_pci_2_2, +}; + #define PC_I440FX_2_1_MACHINE_OPTIONS \ PC_I440FX_MACHINE_OPTIONS, \ .default_machine_opts = "firmware=bios-256k.bin" @@ -928,6 +966,7 @@ static QEMUMachine xenfv_machine = { static void pc_machine_init(void) { + qemu_register_pc_machine(&pc_i440fx_machine_v2_3); qemu_register_pc_machine(&pc_i440fx_machine_v2_2); qemu_register_pc_machine(&pc_i440fx_machine_v2_1); qemu_register_pc_machine(&pc_i440fx_machine_v2_0); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 0262b5ef19..7ba05353aa 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -287,10 +287,33 @@ static void pc_q35_init(MachineState *machine) } } +static void pc_compat_2_2(MachineState *machine) +{ + x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Conroe", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Penryn", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Nehalem", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Westmere", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("SandyBridge", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Haswell", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Broadwell", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Opteron_G1", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Opteron_G2", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Opteron_G3", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Opteron_G4", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Opteron_G5", FEAT_1_EDX, 0, CPUID_VME); + x86_cpu_compat_set_features("Haswell", FEAT_1_ECX, 0, CPUID_EXT_F16C); + x86_cpu_compat_set_features("Haswell", FEAT_1_ECX, 0, CPUID_EXT_RDRAND); + x86_cpu_compat_set_features("Broadwell", FEAT_1_ECX, 0, CPUID_EXT_F16C); + x86_cpu_compat_set_features("Broadwell", FEAT_1_ECX, 0, CPUID_EXT_RDRAND); +} + static void pc_compat_2_1(MachineState *machine) { PCMachineState *pcms = PC_MACHINE(machine); + pc_compat_2_2(machine); pcms->enforce_aligned_dimm = false; smbios_uuid_encoded = false; x86_cpu_compat_set_features("coreduo", FEAT_1_ECX, CPUID_EXT_VMX, 0); @@ -334,6 +357,12 @@ static void pc_compat_1_4(MachineState *machine) x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); } +static void pc_q35_init_2_2(MachineState *machine) +{ + pc_compat_2_2(machine); + pc_q35_init(machine); +} + static void pc_q35_init_2_1(MachineState *machine) { pc_compat_2_1(machine); @@ -377,16 +406,24 @@ static void pc_q35_init_1_4(MachineState *machine) .hot_add_cpu = pc_hot_add_cpu, \ .units_per_default_bus = 1 -#define PC_Q35_2_2_MACHINE_OPTIONS \ +#define PC_Q35_2_3_MACHINE_OPTIONS \ PC_Q35_MACHINE_OPTIONS, \ .default_machine_opts = "firmware=bios-256k.bin", \ .default_display = "std" +static QEMUMachine pc_q35_machine_v2_3 = { + PC_Q35_2_3_MACHINE_OPTIONS, + .name = "pc-q35-2.3", + .alias = "q35", + .init = pc_q35_init, +}; + +#define PC_Q35_2_2_MACHINE_OPTIONS PC_Q35_2_3_MACHINE_OPTIONS + static QEMUMachine pc_q35_machine_v2_2 = { PC_Q35_2_2_MACHINE_OPTIONS, .name = "pc-q35-2.2", - .alias = "q35", - .init = pc_q35_init, + .init = pc_q35_init_2_2, }; #define PC_Q35_2_1_MACHINE_OPTIONS \ @@ -465,6 +502,7 @@ static QEMUMachine pc_q35_machine_v1_4 = { static void pc_q35_machine_init(void) { + qemu_register_pc_machine(&pc_q35_machine_v2_3); qemu_register_pc_machine(&pc_q35_machine_v2_2); qemu_register_pc_machine(&pc_q35_machine_v2_1); qemu_register_pc_machine(&pc_q35_machine_v2_0); diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c index 75913c5b2f..662d99768e 100644 --- a/hw/i386/pc_sysfw.c +++ b/hw/i386/pc_sysfw.c @@ -204,9 +204,7 @@ static void old_pc_system_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw) fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name); exit(1); } - if (filename) { - g_free(filename); - } + g_free(filename); /* map the last 128KB of the BIOS in ISA space */ isa_bios_size = bios_size; diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index 4e62f25edb..d9bb188c15 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -178,6 +178,7 @@ bool apic_next_timer(APICCommonState *s, int64_t current_time) void apic_init_reset(DeviceState *dev) { APICCommonState *s = APIC_COMMON(dev); + APICCommonClass *info = APIC_COMMON_GET_CLASS(s); int i; if (!s) { @@ -206,6 +207,10 @@ void apic_init_reset(DeviceState *dev) timer_del(s->timer); } s->timer_expiry = -1; + + if (info->reset) { + info->reset(s); + } } void apic_designate_bsp(DeviceState *dev) diff --git a/hw/intc/openpic_kvm.c b/hw/intc/openpic_kvm.c index 3e2cd189ff..f7cac585a9 100644 --- a/hw/intc/openpic_kvm.c +++ b/hw/intc/openpic_kvm.c @@ -248,7 +248,6 @@ static void kvm_openpic_realize(DeviceState *dev, Error **errp) kvm_irqchip_add_irq_route(kvm_state, i, 0, i); } - kvm_irqfds_allowed = true; kvm_msi_via_irqfd_allowed = true; kvm_gsi_routing_allowed = true; diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c index 20b19e9d4f..c15453f26f 100644 --- a/hw/intc/xics_kvm.c +++ b/hw/intc/xics_kvm.c @@ -448,7 +448,6 @@ static void xics_kvm_realize(DeviceState *dev, Error **errp) } kvm_kernel_irqchip = true; - kvm_irqfds_allowed = true; kvm_msi_via_irqfd_allowed = true; kvm_gsi_direct_mapping = true; diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index fd318a122d..a315c3acdc 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -406,7 +406,7 @@ static void vfio_enable_intx_kvm(VFIODevice *vdev) if (!VFIO_ALLOW_KVM_INTX || !kvm_irqfds_enabled() || vdev->intx.route.mode != PCI_INTX_ENABLED || - !kvm_check_extension(kvm_state, KVM_CAP_IRQFD_RESAMPLE)) { + !kvm_resamplefds_enabled()) { return; } @@ -568,8 +568,7 @@ static int vfio_enable_intx(VFIODevice *vdev) * Only conditional to avoid generating error messages on platforms * where we won't actually use the result anyway. */ - if (kvm_irqfds_enabled() && - kvm_check_extension(kvm_state, KVM_CAP_IRQFD_RESAMPLE)) { + if (kvm_irqfds_enabled() && kvm_resamplefds_enabled()) { vdev->intx.route = pci_device_route_intx_to_irq(&vdev->pdev, vdev->intx.pin); } diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index d9b4c7ea3c..ec920488d6 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -781,7 +781,7 @@ static void lsi_do_command(LSIState *s) } assert(s->current == NULL); - s->current = g_malloc0(sizeof(lsi_request)); + s->current = g_new0(lsi_request, 1); s->current->tag = s->select_tag; s->current->req = scsi_req_new(dev, s->current->tag, s->current_lun, buf, s->current); diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 604252a198..4852237a79 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -1018,8 +1018,7 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun, size_t len, resid; if (!cmd->iov_buf) { - cmd->iov_buf = g_malloc(dcmd_size); - memset(cmd->iov_buf, 0, dcmd_size); + cmd->iov_buf = g_malloc0(dcmd_size); info = cmd->iov_buf; info->inquiry_data[0] = 0x7f; /* Force PQual 0x3, PType 0x1f */ info->vpd_page83[0] = 0x7f; @@ -1221,8 +1220,7 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun, uint64_t ld_size; if (!cmd->iov_buf) { - cmd->iov_buf = g_malloc(dcmd_size); - memset(cmd->iov_buf, 0x0, dcmd_size); + cmd->iov_buf = g_malloc0(dcmd_size); info = cmd->iov_buf; megasas_setup_inquiry(cdb, 0x83, sizeof(info->vpd_page83)); req = scsi_req_new(sdev, cmd->index, lun, cdb, cmd); diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 2f75d7d51c..f65618d802 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -49,6 +49,7 @@ do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0) #define DEFAULT_DISCARD_GRANULARITY 4096 #define DEFAULT_MAX_UNMAP_SIZE (1 << 30) /* 1 GB */ +#define DEFAULT_MAX_IO_SIZE INT_MAX /* 2 GB - 1 block */ typedef struct SCSIDiskState SCSIDiskState; @@ -79,6 +80,7 @@ struct SCSIDiskState uint64_t port_wwn; uint16_t port_index; uint64_t max_unmap_size; + uint64_t max_io_size; QEMUBH *bh; char *version; char *serial; @@ -635,6 +637,8 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) s->qdev.conf.opt_io_size / s->qdev.blocksize; unsigned int max_unmap_sectors = s->max_unmap_size / s->qdev.blocksize; + unsigned int max_io_sectors = + s->max_io_size / s->qdev.blocksize; if (s->qdev.type == TYPE_ROM) { DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n", @@ -651,6 +655,12 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) outbuf[6] = (min_io_size >> 8) & 0xff; outbuf[7] = min_io_size & 0xff; + /* maximum transfer length */ + outbuf[8] = (max_io_sectors >> 24) & 0xff; + outbuf[9] = (max_io_sectors >> 16) & 0xff; + outbuf[10] = (max_io_sectors >> 8) & 0xff; + outbuf[11] = max_io_sectors & 0xff; + /* optimal transfer length */ outbuf[12] = (opt_io_size >> 24) & 0xff; outbuf[13] = (opt_io_size >> 16) & 0xff; @@ -674,6 +684,17 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) outbuf[29] = (unmap_sectors >> 16) & 0xff; outbuf[30] = (unmap_sectors >> 8) & 0xff; outbuf[31] = unmap_sectors & 0xff; + + /* max write same size */ + outbuf[36] = 0; + outbuf[37] = 0; + outbuf[38] = 0; + outbuf[39] = 0; + + outbuf[40] = (max_io_sectors >> 24) & 0xff; + outbuf[41] = (max_io_sectors >> 16) & 0xff; + outbuf[42] = (max_io_sectors >> 8) & 0xff; + outbuf[43] = max_io_sectors & 0xff; break; } case 0xb2: /* thin provisioning */ @@ -2579,6 +2600,8 @@ static Property scsi_hd_properties[] = { DEFINE_PROP_UINT16("port_index", SCSIDiskState, port_index, 0), DEFINE_PROP_UINT64("max_unmap_size", SCSIDiskState, max_unmap_size, DEFAULT_MAX_UNMAP_SIZE), + DEFINE_PROP_UINT64("max_io_size", SCSIDiskState, max_io_size, + DEFAULT_MAX_IO_SIZE), DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf), DEFINE_PROP_END_OF_LIST(), }; @@ -2625,6 +2648,8 @@ static Property scsi_cd_properties[] = { DEFINE_PROP_UINT64("wwn", SCSIDiskState, wwn, 0), DEFINE_PROP_UINT64("port_wwn", SCSIDiskState, port_wwn, 0), DEFINE_PROP_UINT16("port_index", SCSIDiskState, port_index, 0), + DEFINE_PROP_UINT64("max_io_size", SCSIDiskState, max_io_size, + DEFAULT_MAX_IO_SIZE), DEFINE_PROP_END_OF_LIST(), }; @@ -2690,6 +2715,8 @@ static Property scsi_disk_properties[] = { DEFINE_PROP_UINT16("port_index", SCSIDiskState, port_index, 0), DEFINE_PROP_UINT64("max_unmap_size", SCSIDiskState, max_unmap_size, DEFAULT_MAX_UNMAP_SIZE), + DEFINE_PROP_UINT64("max_io_size", SCSIDiskState, max_io_size, + DEFAULT_MAX_IO_SIZE), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 6b9e4e1ef9..e53470f85e 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -298,8 +298,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd) #endif if (r->req.cmd.xfer == 0) { - if (r->buf != NULL) - g_free(r->buf); + g_free(r->buf); r->buflen = 0; r->buf = NULL; /* The request is used as the AIO opaque value, so add a ref. */ @@ -314,8 +313,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd) } if (r->buflen != r->req.cmd.xfer) { - if (r->buf != NULL) - g_free(r->buf); + g_free(r->buf); r->buf = g_malloc(r->req.cmd.xfer); r->buflen = r->req.cmd.xfer; } diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index ef485508b1..b06dd390d2 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -829,7 +829,7 @@ void virtio_scsi_common_realize(DeviceState *dev, Error **errp, virtio_cleanup(vdev); return; } - s->cmd_vqs = g_malloc0(s->conf.num_queues * sizeof(VirtQueue *)); + s->cmd_vqs = g_new0(VirtQueue *, s->conf.num_queues); s->sense_size = VIRTIO_SCSI_SENSE_SIZE; s->cdb_size = VIRTIO_SCSI_CDB_SIZE; diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index b38005003c..15064d3ec2 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -74,10 +74,10 @@ #define SDHC_CAPAB_MAXBLOCKLENGTH 512ul /* Maximum clock frequency for SDclock in MHz * value in range 10-63 MHz, 0 - not defined */ -#define SDHC_CAPAB_BASECLKFREQ 0ul +#define SDHC_CAPAB_BASECLKFREQ 52ul #define SDHC_CAPAB_TOUNIT 1ul /* Timeout clock unit 0 - kHz, 1 - MHz */ /* Timeout clock frequency 1-63, 0 - not defined */ -#define SDHC_CAPAB_TOCLKFREQ 0ul +#define SDHC_CAPAB_TOCLKFREQ 52ul /* Now check all parameters and calculate CAPABILITIES REGISTER value */ #if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_18V > 1 || SDHC_CAPAB_30V > 1 || \ @@ -198,12 +198,7 @@ static void sdhci_reset(SDHCIState *s) s->stopped_state = sdhc_not_stopped; } -static void sdhci_do_data_transfer(void *opaque) -{ - SDHCIState *s = (SDHCIState *)opaque; - - SDHCI_GET_CLASS(s)->data_transfer(s); -} +static void sdhci_data_transfer(void *opaque); static void sdhci_send_command(SDHCIState *s) { @@ -261,7 +256,7 @@ static void sdhci_send_command(SDHCIState *s) if (s->blksize && (s->cmdreg & SDHC_CMD_DATA_PRESENT)) { s->data_count = 0; - sdhci_do_data_transfer(s); + sdhci_data_transfer(s); } } @@ -367,9 +362,9 @@ static uint32_t sdhci_read_dataport(SDHCIState *s, unsigned size) /* stop at gap request */ (s->stopped_state == sdhc_gap_read && !(s->prnsts & SDHC_DAT_LINE_ACTIVE))) { - SDHCI_GET_CLASS(s)->end_data_transfer(s); + sdhci_end_transfer(s); } else { /* if there are more data, read next block from card */ - SDHCI_GET_CLASS(s)->read_block_from_card(s); + sdhci_read_block_from_card(s); } break; } @@ -410,7 +405,7 @@ static void sdhci_write_block_to_card(SDHCIState *s) if ((s->trnmod & SDHC_TRNS_MULTI) == 0 || ((s->trnmod & SDHC_TRNS_MULTI) && (s->trnmod & SDHC_TRNS_BLK_CNT_EN) && (s->blkcnt == 0))) { - SDHCI_GET_CLASS(s)->end_data_transfer(s); + sdhci_end_transfer(s); } else if (s->norintstsen & SDHC_NISEN_WBUFRDY) { s->norintsts |= SDHC_NIS_WBUFRDY; } @@ -422,7 +417,7 @@ static void sdhci_write_block_to_card(SDHCIState *s) if (s->norintstsen & SDHC_EISEN_BLKGAP) { s->norintsts |= SDHC_EIS_BLKGAP; } - SDHCI_GET_CLASS(s)->end_data_transfer(s); + sdhci_end_transfer(s); } sdhci_update_irq(s); @@ -450,7 +445,7 @@ static void sdhci_write_dataport(SDHCIState *s, uint32_t value, unsigned size) s->data_count = 0; s->prnsts &= ~SDHC_SPACE_AVAILABLE; if (s->prnsts & SDHC_DOING_WRITE) { - SDHCI_GET_CLASS(s)->write_block_to_card(s); + sdhci_write_block_to_card(s); } } } @@ -537,7 +532,7 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s) } if (s->blkcnt == 0) { - SDHCI_GET_CLASS(s)->end_data_transfer(s); + sdhci_end_transfer(s); } else { if (s->norintstsen & SDHC_NISEN_DMA) { s->norintsts |= SDHC_NIS_DMA; @@ -571,7 +566,7 @@ static void sdhci_sdma_transfer_single_block(SDHCIState *s) s->blkcnt--; } - SDHCI_GET_CLASS(s)->end_data_transfer(s); + sdhci_end_transfer(s); } typedef struct ADMADescr { @@ -758,7 +753,7 @@ static void sdhci_do_adma(SDHCIState *s) sdhci_update_irq(s); } - SDHCI_GET_CLASS(s)->end_data_transfer(s); + sdhci_end_transfer(s); return; } @@ -771,9 +766,9 @@ static void sdhci_do_adma(SDHCIState *s) /* Perform data transfer according to controller configuration */ -static void sdhci_data_transfer(SDHCIState *s) +static void sdhci_data_transfer(void *opaque) { - SDHCIClass *k = SDHCI_GET_CLASS(s); + SDHCIState *s = (SDHCIState *)opaque; if (s->trnmod & SDHC_TRNS_DMA) { switch (SDHC_DMA_TYPE(s->hostctl)) { @@ -784,9 +779,9 @@ static void sdhci_data_transfer(SDHCIState *s) } if ((s->blkcnt == 1) || !(s->trnmod & SDHC_TRNS_MULTI)) { - k->do_sdma_single(s); + sdhci_sdma_transfer_single_block(s); } else { - k->do_sdma_multi(s); + sdhci_sdma_transfer_multi_blocks(s); } break; @@ -796,7 +791,7 @@ static void sdhci_data_transfer(SDHCIState *s) break; } - k->do_adma(s); + sdhci_do_adma(s); break; case SDHC_CTRL_ADMA2_32: if (!(s->capareg & SDHC_CAN_DO_ADMA2)) { @@ -804,7 +799,7 @@ static void sdhci_data_transfer(SDHCIState *s) break; } - k->do_adma(s); + sdhci_do_adma(s); break; case SDHC_CTRL_ADMA2_64: if (!(s->capareg & SDHC_CAN_DO_ADMA2) || @@ -813,7 +808,7 @@ static void sdhci_data_transfer(SDHCIState *s) break; } - k->do_adma(s); + sdhci_do_adma(s); break; default: ERRPRINT("Unsupported DMA type\n"); @@ -823,11 +818,11 @@ static void sdhci_data_transfer(SDHCIState *s) if ((s->trnmod & SDHC_TRNS_READ) && sd_data_ready(s->card)) { s->prnsts |= SDHC_DOING_READ | SDHC_DATA_INHIBIT | SDHC_DAT_LINE_ACTIVE; - SDHCI_GET_CLASS(s)->read_block_from_card(s); + sdhci_read_block_from_card(s); } else { s->prnsts |= SDHC_DOING_WRITE | SDHC_DAT_LINE_ACTIVE | SDHC_SPACE_AVAILABLE | SDHC_DATA_INHIBIT; - SDHCI_GET_CLASS(s)->write_block_to_card(s); + sdhci_write_block_to_card(s); } } } @@ -858,8 +853,9 @@ sdhci_buff_access_is_sequential(SDHCIState *s, unsigned byte_num) return true; } -static uint32_t sdhci_read(SDHCIState *s, unsigned int offset, unsigned size) +static uint64_t sdhci_read(void *opaque, hwaddr offset, unsigned size) { + SDHCIState *s = (SDHCIState *)opaque; uint32_t ret = 0; switch (offset & ~0x3) { @@ -880,8 +876,8 @@ static uint32_t sdhci_read(SDHCIState *s, unsigned int offset, unsigned size) break; case SDHC_BDATA: if (sdhci_buff_access_is_sequential(s, offset - SDHC_BDATA)) { - ret = SDHCI_GET_CLASS(s)->bdata_read(s, size); - DPRINT_L2("read %ub: addr[0x%04x] -> %u(0x%x)\n", size, offset, + ret = sdhci_read_dataport(s, size); + DPRINT_L2("read %ub: addr[0x%04x] -> %u(0x%x)\n", size, (int)offset, ret, ret); return ret; } @@ -927,13 +923,13 @@ static uint32_t sdhci_read(SDHCIState *s, unsigned int offset, unsigned size) ret = (SD_HOST_SPECv2_VERS << 16) | sdhci_slotint(s); break; default: - ERRPRINT("bad %ub read: addr[0x%04x]\n", size, offset); + ERRPRINT("bad %ub read: addr[0x%04x]\n", size, (int)offset); break; } ret >>= (offset & 0x3) * 8; ret &= (1ULL << (size * 8)) - 1; - DPRINT_L2("read %ub: addr[0x%04x] -> %u(0x%x)\n", size, offset, ret, ret); + DPRINT_L2("read %ub: addr[0x%04x] -> %u(0x%x)\n", size, (int)offset, ret, ret); return ret; } @@ -948,10 +944,10 @@ static inline void sdhci_blkgap_write(SDHCIState *s, uint8_t value) (s->blkgap & SDHC_STOP_AT_GAP_REQ) == 0) { if (s->stopped_state == sdhc_gap_read) { s->prnsts |= SDHC_DAT_LINE_ACTIVE | SDHC_DOING_READ; - SDHCI_GET_CLASS(s)->read_block_from_card(s); + sdhci_read_block_from_card(s); } else { s->prnsts |= SDHC_DAT_LINE_ACTIVE | SDHC_DOING_WRITE; - SDHCI_GET_CLASS(s)->write_block_to_card(s); + sdhci_write_block_to_card(s); } s->stopped_state = sdhc_not_stopped; } else if (!s->stopped_state && (value & SDHC_STOP_AT_GAP_REQ)) { @@ -967,7 +963,7 @@ static inline void sdhci_reset_write(SDHCIState *s, uint8_t value) { switch (value) { case SDHC_RESET_ALL: - DEVICE_GET_CLASS(s)->reset(DEVICE(s)); + sdhci_reset(s); break; case SDHC_RESET_CMD: s->prnsts &= ~SDHC_CMD_INHIBIT; @@ -987,10 +983,12 @@ static inline void sdhci_reset_write(SDHCIState *s, uint8_t value) } static void -sdhci_write(SDHCIState *s, unsigned int offset, uint32_t value, unsigned size) +sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { + SDHCIState *s = (SDHCIState *)opaque; unsigned shift = 8 * (offset & 0x3); uint32_t mask = ~(((1ULL << (size * 8)) - 1) << shift); + uint32_t value = val; value <<= shift; switch (offset & ~0x3) { @@ -1000,7 +998,7 @@ sdhci_write(SDHCIState *s, unsigned int offset, uint32_t value, unsigned size) /* Writing to last byte of sdmasysad might trigger transfer */ if (!(mask & 0xFF000000) && TRANSFERRING_DATA(s->prnsts) && s->blkcnt && s->blksize && SDHC_DMA_TYPE(s->hostctl) == SDHC_CTRL_SDMA) { - SDHCI_GET_CLASS(s)->do_sdma_multi(s); + sdhci_sdma_transfer_multi_blocks(s); } break; case SDHC_BLKSIZE: @@ -1022,15 +1020,15 @@ sdhci_write(SDHCIState *s, unsigned int offset, uint32_t value, unsigned size) MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16); /* Writing to the upper byte of CMDREG triggers SD command generation */ - if ((mask & 0xFF000000) || !SDHCI_GET_CLASS(s)->can_issue_command(s)) { + if ((mask & 0xFF000000) || !sdhci_can_issue_command(s)) { break; } - SDHCI_GET_CLASS(s)->send_command(s); + sdhci_send_command(s); break; case SDHC_BDATA: if (sdhci_buff_access_is_sequential(s, offset - SDHC_BDATA)) { - SDHCI_GET_CLASS(s)->bdata_write(s, value >> shift, size); + sdhci_write_dataport(s, value >> shift, size); } break; case SDHC_HOSTCTL: @@ -1111,32 +1109,16 @@ sdhci_write(SDHCIState *s, unsigned int offset, uint32_t value, unsigned size) break; default: ERRPRINT("bad %ub write offset: addr[0x%04x] <- %u(0x%x)\n", - size, offset, value >> shift, value >> shift); + size, (int)offset, value >> shift, value >> shift); break; } DPRINT_L2("write %ub: addr[0x%04x] <- %u(0x%x)\n", - size, offset, value >> shift, value >> shift); -} - -static uint64_t -sdhci_readfn(void *opaque, hwaddr offset, unsigned size) -{ - SDHCIState *s = (SDHCIState *)opaque; - - return SDHCI_GET_CLASS(s)->mem_read(s, offset, size); -} - -static void -sdhci_writefn(void *opaque, hwaddr off, uint64_t val, unsigned sz) -{ - SDHCIState *s = (SDHCIState *)opaque; - - SDHCI_GET_CLASS(s)->mem_write(s, off, val, sz); + size, (int)offset, value >> shift, value >> shift); } static const MemoryRegionOps sdhci_mmio_ops = { - .read = sdhci_readfn, - .write = sdhci_writefn, + .read = sdhci_read, + .write = sdhci_write, .valid = { .min_access_size = 1, .max_access_size = 4, @@ -1160,9 +1142,8 @@ static inline unsigned int sdhci_get_fifolen(SDHCIState *s) } } -static void sdhci_initfn(Object *obj) +static void sdhci_initfn(SDHCIState *s) { - SDHCIState *s = SDHCI(obj); DriveInfo *di; di = drive_get_next(IF_SD); @@ -1175,13 +1156,11 @@ static void sdhci_initfn(Object *obj) sd_set_cb(s->card, s->ro_cb, s->eject_cb); s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_raise_insertion_irq, s); - s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_do_data_transfer, s); + s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_data_transfer, s); } -static void sdhci_uninitfn(Object *obj) +static void sdhci_uninitfn(SDHCIState *s) { - SDHCIState *s = SDHCI(obj); - timer_del(s->insert_timer); timer_free(s->insert_timer); timer_del(s->transfer_timer); @@ -1241,9 +1220,64 @@ static Property sdhci_properties[] = { DEFINE_PROP_END_OF_LIST(), }; -static void sdhci_realize(DeviceState *dev, Error ** errp) +static int sdhci_pci_init(PCIDevice *dev) { - SDHCIState *s = SDHCI(dev); + SDHCIState *s = PCI_SDHCI(dev); + dev->config[PCI_CLASS_PROG] = 0x01; /* Standard Host supported DMA */ + dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */ + sdhci_initfn(s); + s->buf_maxsz = sdhci_get_fifolen(s); + s->fifo_buffer = g_malloc0(s->buf_maxsz); + s->irq = pci_allocate_irq(dev); + memory_region_init_io(&s->iomem, OBJECT(s), &sdhci_mmio_ops, s, "sdhci", + SDHC_REGISTERS_MAP_SIZE); + pci_register_bar(dev, 0, 0, &s->iomem); + return 0; +} + +static void sdhci_pci_exit(PCIDevice *dev) +{ + SDHCIState *s = PCI_SDHCI(dev); + sdhci_uninitfn(s); +} + +static void sdhci_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->init = sdhci_pci_init; + k->exit = sdhci_pci_exit; + k->vendor_id = PCI_VENDOR_ID_REDHAT; + k->device_id = PCI_DEVICE_ID_REDHAT_SDHCI; + k->class_id = PCI_CLASS_SYSTEM_SDHCI; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->vmsd = &sdhci_vmstate; + dc->props = sdhci_properties; +} + +static const TypeInfo sdhci_pci_info = { + .name = TYPE_PCI_SDHCI, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(SDHCIState), + .class_init = sdhci_pci_class_init, +}; + +static void sdhci_sysbus_init(Object *obj) +{ + SDHCIState *s = SYSBUS_SDHCI(obj); + sdhci_initfn(s); +} + +static void sdhci_sysbus_finalize(Object *obj) +{ + SDHCIState *s = SYSBUS_SDHCI(obj); + sdhci_uninitfn(s); +} + +static void sdhci_sysbus_realize(DeviceState *dev, Error ** errp) +{ + SDHCIState *s = SYSBUS_SDHCI(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); s->buf_maxsz = sdhci_get_fifolen(s); @@ -1254,51 +1288,28 @@ static void sdhci_realize(DeviceState *dev, Error ** errp) sysbus_init_mmio(sbd, &s->iomem); } -static void sdhci_generic_reset(DeviceState *ds) -{ - SDHCIState *s = SDHCI(ds); - SDHCI_GET_CLASS(s)->reset(s); -} - -static void sdhci_class_init(ObjectClass *klass, void *data) +static void sdhci_sysbus_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SDHCIClass *k = SDHCI_CLASS(klass); dc->vmsd = &sdhci_vmstate; dc->props = sdhci_properties; - dc->reset = sdhci_generic_reset; - dc->realize = sdhci_realize; - - k->reset = sdhci_reset; - k->mem_read = sdhci_read; - k->mem_write = sdhci_write; - k->send_command = sdhci_send_command; - k->can_issue_command = sdhci_can_issue_command; - k->data_transfer = sdhci_data_transfer; - k->end_data_transfer = sdhci_end_transfer; - k->do_sdma_single = sdhci_sdma_transfer_single_block; - k->do_sdma_multi = sdhci_sdma_transfer_multi_blocks; - k->do_adma = sdhci_do_adma; - k->read_block_from_card = sdhci_read_block_from_card; - k->write_block_to_card = sdhci_write_block_to_card; - k->bdata_read = sdhci_read_dataport; - k->bdata_write = sdhci_write_dataport; + dc->realize = sdhci_sysbus_realize; } -static const TypeInfo sdhci_type_info = { - .name = TYPE_SDHCI, +static const TypeInfo sdhci_sysbus_info = { + .name = TYPE_SYSBUS_SDHCI, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(SDHCIState), - .instance_init = sdhci_initfn, - .instance_finalize = sdhci_uninitfn, - .class_init = sdhci_class_init, - .class_size = sizeof(SDHCIClass) + .instance_init = sdhci_sysbus_init, + .instance_finalize = sdhci_sysbus_finalize, + .class_init = sdhci_sysbus_class_init, }; static void sdhci_register_types(void) { - type_register_static(&sdhci_type_info); + type_register_static(&sdhci_pci_info); + type_register_static(&sdhci_sysbus_info); } type_init(sdhci_register_types) diff --git a/hw/sd/sdhci.h b/hw/sd/sdhci.h index a560c3c93f..3352d23d68 100644 --- a/hw/sd/sdhci.h +++ b/hw/sd/sdhci.h @@ -26,6 +26,7 @@ #define SDHCI_H #include "qemu-common.h" +#include "hw/pci/pci.h" #include "hw/sysbus.h" #include "hw/sd.h" @@ -232,7 +233,10 @@ enum { /* SD/MMC host controller state */ typedef struct SDHCIState { - SysBusDevice busdev; + union { + PCIDevice pcidev; + SysBusDevice busdev; + }; SDState *card; MemoryRegion iomem; @@ -279,34 +283,13 @@ typedef struct SDHCIState { /* RO Host Controller Version Register always reads as 0x2401 */ } SDHCIState; -typedef struct SDHCIClass { - SysBusDeviceClass busdev_class; - - void (*reset)(SDHCIState *s); - uint32_t (*mem_read)(SDHCIState *s, unsigned int offset, unsigned size); - void (*mem_write)(SDHCIState *s, unsigned int offset, uint32_t value, - unsigned size); - void (*send_command)(SDHCIState *s); - bool (*can_issue_command)(SDHCIState *s); - void (*data_transfer)(SDHCIState *s); - void (*end_data_transfer)(SDHCIState *s); - void (*do_sdma_single)(SDHCIState *s); - void (*do_sdma_multi)(SDHCIState *s); - void (*do_adma)(SDHCIState *s); - void (*read_block_from_card)(SDHCIState *s); - void (*write_block_to_card)(SDHCIState *s); - uint32_t (*bdata_read)(SDHCIState *s, unsigned size); - void (*bdata_write)(SDHCIState *s, uint32_t value, unsigned size); -} SDHCIClass; - extern const VMStateDescription sdhci_vmstate; -#define TYPE_SDHCI "generic-sdhci" -#define SDHCI(obj) \ - OBJECT_CHECK(SDHCIState, (obj), TYPE_SDHCI) -#define SDHCI_CLASS(klass) \ - OBJECT_CLASS_CHECK(SDHCIClass, (klass), TYPE_SDHCI) -#define SDHCI_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SDHCIClass, (obj), TYPE_SDHCI) +#define TYPE_PCI_SDHCI "sdhci-pci" +#define PCI_SDHCI(obj) OBJECT_CHECK(SDHCIState, (obj), TYPE_PCI_SDHCI) + +#define TYPE_SYSBUS_SDHCI "generic-sdhci" +#define SYSBUS_SDHCI(obj) \ + OBJECT_CHECK(SDHCIState, (obj), TYPE_SYSBUS_SDHCI) #endif /* SDHCI_H */ |