summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/char/serial.c58
-rw-r--r--hw/i386/kvm/apic.c10
-rw-r--r--hw/i386/kvm/clock.c3
-rw-r--r--hw/i386/kvm/i8254.c2
-rw-r--r--hw/i386/multiboot.c32
-rw-r--r--hw/i386/pc.c3
-rw-r--r--hw/i386/pc_piix.c47
-rw-r--r--hw/i386/pc_q35.c44
-rw-r--r--hw/i386/pc_sysfw.c4
-rw-r--r--hw/intc/apic_common.c5
-rw-r--r--hw/intc/openpic_kvm.c1
-rw-r--r--hw/intc/xics_kvm.c1
-rw-r--r--hw/misc/vfio.c5
-rw-r--r--hw/scsi/lsi53c895a.c2
-rw-r--r--hw/scsi/megasas.c6
-rw-r--r--hw/scsi/scsi-disk.c27
-rw-r--r--hw/scsi/scsi-generic.c6
-rw-r--r--hw/scsi/virtio-scsi.c2
-rw-r--r--hw/sd/sdhci.c209
-rw-r--r--hw/sd/sdhci.h39
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 */