qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 1/1] i386: expose floppy-related objects in SSDT
@ 2015-12-16  7:45 Denis V. Lunev
  2015-12-16 16:46 ` John Snow
                   ` (2 more replies)
  0 siblings, 3 replies; 31+ messages in thread
From: Denis V. Lunev @ 2015-12-16  7:45 UTC (permalink / raw)
  Cc: Kevin Wolf, Eduardo Habkost, Michael S. Tsirkin, qemu-devel,
	qemu-stable, Paolo Bonzini, Roman Kagan, Igor Mammedov,
	Denis V. Lunev, John Snow, Richard Henderson

From: Roman Kagan <rkagan@virtuozzo.com>

On x86-based systems Linux determines the presence and the type of
floppy drives via a query of a CMOS field.  So does SeaBIOS when
populating the return data for int 0x13 function 0x08.

Windows doesn't; instead, it requests this information from BIOS via int
0x13/0x08 or through ACPI objects _FDE (Floppy Drive Enumerate) and _FDI
(Floppy Drive Information).  On UEFI systems only ACPI-based detection
is supported.

QEMU used not to provide those objects in its ACPI tables; as a result
floppy drives were invisible to Windows on UEFI/OVMF.

This patch implements those objects in SSDT, populating them via AML
API.  For that, a couple of functions are extern-ified to facilitate
populating those objects in acpi-build.c.

Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Michael S. Tsirkin <mst@redhat.com>
CC: Igor Mammedov <imammedo@redhat.com>
CC: Paolo Bonzini <pbonzini@redhat.com>
CC: Richard Henderson <rth@twiddle.net>
CC: Eduardo Habkost <ehabkost@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
---
- The patch is made against QEMU upstream

 hw/block/fdc.c         | 11 +++++++
 hw/i386/acpi-build.c   | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/i386/pc.c           | 46 +++++++++++++++++------------
 include/hw/block/fdc.h |  2 ++
 include/hw/i386/pc.h   |  3 ++
 5 files changed, 121 insertions(+), 19 deletions(-)

diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index 4292ece..c858c5f 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -2408,6 +2408,17 @@ FDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i)
     return isa->state.drives[i].drive;
 }
 
+void isa_fdc_get_drive_geometry(ISADevice *fdc, int i, uint8_t *cylinders,
+                                uint8_t *heads, uint8_t *sectors)
+{
+    FDCtrlISABus *isa = ISA_FDC(fdc);
+    FDrive *drv = &isa->state.drives[i];
+
+    *cylinders = drv->max_track;
+    *heads = (drv->flags & FDISK_DBL_SIDES) ? 2 : 1;
+    *sectors = drv->last_sect;
+}
+
 static const VMStateDescription vmstate_isa_fdc ={
     .name = "fdc",
     .version_id = 2,
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 95e0c65..7f902b1 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -38,6 +38,7 @@
 #include "hw/acpi/bios-linker-loader.h"
 #include "hw/loader.h"
 #include "hw/isa/isa.h"
+#include "hw/block/fdc.h"
 #include "hw/acpi/memory_hotplug.h"
 #include "sysemu/tpm.h"
 #include "hw/acpi/tpm.h"
@@ -105,6 +106,13 @@ typedef struct AcpiPmInfo {
     uint16_t pcihp_io_len;
 } AcpiPmInfo;
 
+typedef struct AcpiFDInfo {
+    uint8_t type;
+    uint8_t cylinders;
+    uint8_t heads;
+    uint8_t sectors;
+} AcpiFDInfo;
+
 typedef struct AcpiMiscInfo {
     bool has_hpet;
     TPMVersion tpm_version;
@@ -112,6 +120,7 @@ typedef struct AcpiMiscInfo {
     unsigned dsdt_size;
     uint16_t pvpanic_port;
     uint16_t applesmc_io_base;
+    AcpiFDInfo fdinfo[2];
 } AcpiMiscInfo;
 
 typedef struct AcpiBuildPciBusHotplugState {
@@ -235,10 +244,25 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
 
 static void acpi_get_misc_info(AcpiMiscInfo *info)
 {
+    int i;
+    ISADevice *fdc;
+
     info->has_hpet = hpet_find();
     info->tpm_version = tpm_get_version();
     info->pvpanic_port = pvpanic_port();
     info->applesmc_io_base = applesmc_port();
+
+    fdc = pc_find_fdc0();
+    if (fdc != NULL) {
+        for (i = 0; i < ARRAY_SIZE(info->fdinfo); i++) {
+            AcpiFDInfo *fdinfo = &info->fdinfo[i];
+            fdinfo->type = isa_fdc_get_drive_type(fdc, i);
+            if (fdinfo->type < FDRIVE_DRV_NONE) {
+                isa_fdc_get_drive_geometry(fdc, i, &fdinfo->cylinders,
+                                           &fdinfo->heads, &fdinfo->sectors);
+            }
+        }
+    }
 }
 
 /*
@@ -900,6 +924,40 @@ static Aml *build_crs(PCIHostState *host,
     return crs;
 }
 
+static Aml *build_fdinfo_aml(int idx, AcpiFDInfo *fdinfo)
+{
+    Aml *dev, *fdi;
+
+    dev = aml_device("FLP%c", 'A' + idx);
+
+    aml_append(dev, aml_name_decl("_ADR", aml_int(idx)));
+
+    fdi = aml_package(0x10);
+    aml_append(fdi, aml_int(idx));  /* Drive Number */
+    aml_append(fdi,
+        aml_int(cmos_get_fd_drive_type(fdinfo->type)));  /* Device Type */
+    aml_append(fdi,
+        aml_int(fdinfo->cylinders - 1));  /* Maximum Cylinder Number */
+    aml_append(fdi, aml_int(fdinfo->sectors));  /* Maximum Sector Number */
+    aml_append(fdi, aml_int(fdinfo->heads - 1));  /* Maximum Head Number */
+    /* SeaBIOS returns the below values for int 0x13 func 0x08 regardless of
+     * the drive type, so shall we */
+    aml_append(fdi, aml_int(0xAF));  /* disk_specify_1 */
+    aml_append(fdi, aml_int(0x02));  /* disk_specify_2 */
+    aml_append(fdi, aml_int(0x25));  /* disk_motor_wait */
+    aml_append(fdi, aml_int(0x02));  /* disk_sector_siz */
+    aml_append(fdi, aml_int(0x12));  /* disk_eot */
+    aml_append(fdi, aml_int(0x1B));  /* disk_rw_gap */
+    aml_append(fdi, aml_int(0xFF));  /* disk_dtl */
+    aml_append(fdi, aml_int(0x6C));  /* disk_formt_gap */
+    aml_append(fdi, aml_int(0xF6));  /* disk_fill */
+    aml_append(fdi, aml_int(0x0F));  /* disk_head_sttl */
+    aml_append(fdi, aml_int(0x08));  /* disk_motor_strt */
+
+    aml_append(dev, aml_name_decl("_FDI", fdi));
+    return dev;
+}
+
 static void
 build_ssdt(GArray *table_data, GArray *linker,
            AcpiCpuInfo *cpu, AcpiPmInfo *pm, AcpiMiscInfo *misc,
@@ -1125,6 +1183,26 @@ build_ssdt(GArray *table_data, GArray *linker,
         aml_append(ssdt, scope);
     }
 
+    {
+        uint32_t fde_buf[5] = {0, 0, 0, 0, 0x2};
+
+        scope = aml_scope("\\_SB.PCI0.ISA.FDC0");
+
+        for (i = 0; i < ARRAY_SIZE(misc->fdinfo); i++) {
+            AcpiFDInfo *fdinfo = &misc->fdinfo[i];
+            if (fdinfo->type != FDRIVE_DRV_NONE) {
+                fde_buf[i] = 0x1;
+                aml_append(scope, build_fdinfo_aml(i, fdinfo));
+            }
+        }
+
+        aml_append(scope,
+            aml_name_decl("_FDE",
+                aml_buffer(sizeof(fde_buf), (uint8_t *) fde_buf)));
+
+        aml_append(ssdt, scope);
+    }
+
     sb_scope = aml_scope("\\_SB");
     {
         /* create PCI0.PRES device and its _CRS to reserve CPU hotplug MMIO */
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 5e20e07..b7b8774 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -207,7 +207,7 @@ static void pic_irq_request(void *opaque, int irq, int level)
 
 #define REG_EQUIPMENT_BYTE          0x14
 
-static int cmos_get_fd_drive_type(FDriveType fd0)
+int cmos_get_fd_drive_type(FDriveType fd0)
 {
     int val;
 
@@ -368,6 +368,31 @@ static const char * const fdc_container_path[] = {
     "/unattached", "/peripheral", "/peripheral-anon"
 };
 
+/*
+ * Locate the FDC at IO address 0x3f0, in order to configure the CMOS registers
+ * and ACPI objects.
+ */
+ISADevice *pc_find_fdc0(void)
+{
+    int i;
+    Object *container;
+    CheckFdcState state = { 0 };
+
+    for (i = 0; i < ARRAY_SIZE(fdc_container_path); i++) {
+        container = container_get(qdev_get_machine(), fdc_container_path[i]);
+        object_child_foreach(container, check_fdc, &state);
+    }
+
+    if (state.multiple) {
+        error_report("warning: multiple floppy disk controllers with "
+                     "iobase=0x3f0 have been found;\n"
+                     "the one being picked for CMOS setup might not reflect "
+                     "your intent");
+    }
+
+    return state.floppy;
+}
+
 static void pc_cmos_init_late(void *opaque)
 {
     pc_cmos_init_late_arg *arg = opaque;
@@ -376,8 +401,6 @@ static void pc_cmos_init_late(void *opaque)
     int8_t heads, sectors;
     int val;
     int i, trans;
-    Object *container;
-    CheckFdcState state = { 0 };
 
     val = 0;
     if (ide_get_geometry(arg->idebus[0], 0,
@@ -407,22 +430,7 @@ static void pc_cmos_init_late(void *opaque)
     }
     rtc_set_memory(s, 0x39, val);
 
-    /*
-     * Locate the FDC at IO address 0x3f0, and configure the CMOS registers
-     * accordingly.
-     */
-    for (i = 0; i < ARRAY_SIZE(fdc_container_path); i++) {
-        container = container_get(qdev_get_machine(), fdc_container_path[i]);
-        object_child_foreach(container, check_fdc, &state);
-    }
-
-    if (state.multiple) {
-        error_report("warning: multiple floppy disk controllers with "
-                     "iobase=0x3f0 have been found;\n"
-                     "the one being picked for CMOS setup might not reflect "
-                     "your intent");
-    }
-    pc_cmos_init_floppy(s, state.floppy);
+    pc_cmos_init_floppy(s, pc_find_fdc0());
 
     qemu_unregister_reset(pc_cmos_init_late, opaque);
 }
diff --git a/include/hw/block/fdc.h b/include/hw/block/fdc.h
index d48b2f8..adaf3dc 100644
--- a/include/hw/block/fdc.h
+++ b/include/hw/block/fdc.h
@@ -22,5 +22,7 @@ void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base,
                        DriveInfo **fds, qemu_irq *fdc_tc);
 
 FDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i);
+void isa_fdc_get_drive_geometry(ISADevice *fdc, int i, uint8_t *cylinders,
+                                uint8_t *heads, uint8_t *sectors);
 
 #endif
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 854c330..32ceb2f 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -211,6 +211,9 @@ typedef void (*cpu_set_smm_t)(int smm, void *arg);
 
 void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name);
 
+ISADevice *pc_find_fdc0(void);
+int cmos_get_fd_drive_type(FDriveType fd0);
+
 /* acpi_piix.c */
 
 I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v4 0/4] i386: expose floppy-related objects in SSDT
@ 2015-12-25 15:04 Roman Kagan
  2015-12-25 15:04 ` [Qemu-devel] [PATCH v4 1/4] i386/pc: expose identifying the floppy controller Roman Kagan
                   ` (4 more replies)
  0 siblings, 5 replies; 31+ messages in thread
From: Roman Kagan @ 2015-12-25 15:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Eduardo Habkost, qemu-block, Michael S. Tsirkin,
	qemu-stable, Roman Kagan, Paolo Bonzini, Igor Mammedov, John Snow,
	Richard Henderson

Windows on UEFI systems is only capable of detecting the presence and
the type of floppy drives via corresponding ACPI objects.

Those objects are added in the last patch of the series; the three
preceding ones pave the way to it, by making the necessary data
public and by moving the whole floppy drive controller description into
runtime-generated SSDT.

Note that the series conflicts with Igor's patchset for dynamic DSDT, in
particular, with "[PATCH 50/74] pc: acpi: move FDC0 device from DSDT
to SSDT"; I haven't managed to avoid that while trying to meet
maintainer's comments.

Roman Kagan (4):
  i386/pc: expose identifying the floppy controller
  i386/acpi: make floppy controller object dynamic
  expose floppy drive geometry and CMOS type
  i386: populate floppy drive information in SSDT

Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: John Snow <jsnow@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: qemu-block@nongnu.org
Cc: qemu-stable@nongnu.org
---
changes since v3:
 - make FDC object fully dynamic in a separate patch
 - split out support patches
 - include test data updates with the respective patches to maintain
   bisectability

changes since v2:
 - explicit endianness for buffer data
 - reorder code to reduce conflicts with dynamic DSDT patchset
 - update test data


 hw/block/fdc.c                      |  11 +++++
 hw/i386/acpi-build.c                |  92 ++++++++++++++++++++++++++++++++++++
 hw/i386/acpi-dsdt-isa.dsl           |  18 -------
 hw/i386/acpi-dsdt.dsl               |   1 -
 hw/i386/pc.c                        |  46 ++++++++++--------
 hw/i386/q35-acpi-dsdt.dsl           |   7 +--
 include/hw/block/fdc.h              |   2 +
 include/hw/i386/pc.h                |   3 ++
 tests/acpi-test-data/pc/DSDT        | Bin 3028 -> 2946 bytes
 tests/acpi-test-data/pc/SSDT        | Bin 2486 -> 2635 bytes
 tests/acpi-test-data/pc/SSDT.bridge | Bin 4345 -> 4494 bytes
 tests/acpi-test-data/q35/DSDT       | Bin 7666 -> 7578 bytes
 12 files changed, 137 insertions(+), 43 deletions(-)

-- 
2.5.0

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2015-12-29 16:42 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-12-16  7:45 [Qemu-devel] [PATCH v2 1/1] i386: expose floppy-related objects in SSDT Denis V. Lunev
2015-12-16 16:46 ` John Snow
2015-12-16 16:46 ` Igor Mammedov
2015-12-16 17:34   ` Roman Kagan
2015-12-16 22:15     ` Igor Mammedov
2015-12-17 13:26       ` Roman Kagan
2015-12-17 17:08         ` Igor Mammedov
2015-12-18 19:32 ` [Qemu-devel] [PATCH v3 0/2] " Roman Kagan
2015-12-18 19:32   ` [Qemu-devel] [PATCH v3 1/2] " Roman Kagan
2015-12-22 15:07     ` Michael S. Tsirkin
2015-12-22 15:13       ` Roman Kagan
2015-12-22 15:56     ` Igor Mammedov
2015-12-18 19:32   ` [Qemu-devel] [PATCH v3 2/2] tests: update expected SSDT for floppy changes Roman Kagan
2015-12-22 16:41     ` Michael S. Tsirkin
2015-12-23 13:08       ` Roman Kagan
2015-12-23 13:45         ` Michael S. Tsirkin
2015-12-23 15:06           ` Roman Kagan
2015-12-23 17:20             ` Roman Kagan
2015-12-23 17:47               ` Igor Mammedov
2015-12-23 17:51                 ` Roman Kagan
2015-12-24  6:17                   ` Michael S. Tsirkin
2015-12-25 15:25                     ` Roman Kagan
  -- strict thread matches above, loose matches on Subject: below --
2015-12-25 15:04 [Qemu-devel] [PATCH v4 0/4] i386: expose floppy-related objects in SSDT Roman Kagan
2015-12-25 15:04 ` [Qemu-devel] [PATCH v4 1/4] i386/pc: expose identifying the floppy controller Roman Kagan
2015-12-25 15:04 ` [Qemu-devel] [PATCH v4 2/4] i386/acpi: make floppy controller object dynamic Roman Kagan
2015-12-25 15:04 ` [Qemu-devel] [PATCH v4 3/4] expose floppy drive geometry and CMOS type Roman Kagan
2015-12-25 15:04 ` [Qemu-devel] [PATCH v4 4/4] i386: populate floppy drive information in SSDT Roman Kagan
2015-12-29 14:09 ` [Qemu-devel] [PATCH v4 0/4] i386: expose floppy-related objects " Igor Mammedov
2015-12-29 16:17   ` Roman Kagan
2015-12-29 16:27     ` Igor Mammedov
2015-12-29 16:42     ` Michael S. Tsirkin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).