diff mbox

[v7,3/3] i386: populate floppy drive information in DSDT

Message ID 1453816225-139685-4-git-send-email-imammedo@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Igor Mammedov Jan. 26, 2016, 1:50 p.m. UTC
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.

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

QEMU doesn't provide those objects in its ACPI tables
and as a result floppy drives aren't invisible to Windows
on UEFI/OVMF.

This patch adds those objects to the floppy controller
in DSDT, populating them with the information from
respective QEMU objects.

Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
fixup:
  - rebase on latest FDC refactoring
---
 hw/i386/acpi-build.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 58 insertions(+), 3 deletions(-)

Comments

Michael S. Tsirkin Feb. 7, 2016, 9:08 a.m. UTC | #1
On Tue, Jan 26, 2016 at 02:50:25PM +0100, Igor Mammedov wrote:
> 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.
> 
> However Windows doesn't do it. Instead, it requests
> this information from BIOS via int 0x13/0x08 or through
> ACPI objects _FDE (Floppy Drive Enumerate) and _FDI
> (Floppy Drive Information) of the floppy controller object.
> On UEFI systems only ACPI-based detection is supported.
> 
> QEMU doesn't provide those objects in its ACPI tables
> and as a result floppy drives aren't invisible

are invisible

> to Windows
> on UEFI/OVMF.
> 
> This patch adds those objects to the floppy controller
> in DSDT, populating them with the information from
> respective QEMU objects.
> 
> Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
> fixup:
>   - rebase on latest FDC refactoring
> ---
>  hw/i386/acpi-build.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 58 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 2f685fb..1d291d8 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 "hw/mem/nvdimm.h"
>  #include "sysemu/tpm.h"
> @@ -1227,10 +1228,47 @@ static void build_hpet_aml(Aml *table)
>      aml_append(table, scope);
>  }
>  
> -static Aml *build_fdc_device_aml(void)
> +static Aml *build_fdinfo_aml(int idx, uint8_t type, uint8_t cylinders,
> +                             uint8_t heads, uint8_t sectors)

acpi spec says these are WORD values. Are they really uint8_t?

> +{
> +    Aml *dev, *fdi;
> +
> +    dev = aml_device("FLP%c", 'A' + idx);
> +
> +    aml_append(dev, aml_name_decl("_ADR", aml_int(idx)));
> +
> +    fdi = aml_package(0x10);

Why 0x10 and not 16?

> +    aml_append(fdi, aml_int(idx));  /* Drive Number */
> +    aml_append(fdi,
> +        aml_int(cmos_get_fd_drive_type(type)));  /* Device Type */
> +    aml_append(fdi,
> +        aml_int(cylinders - 1));  /* Maximum Cylinder Number */
> +    aml_append(fdi, aml_int(sectors));  /* Maximum Sector Number */
> +    aml_append(fdi, aml_int(heads - 1));  /* Maximum Head Number */

Doesn't above change on media change?
If so this must be created dynamically, not hard-coded at machine
done type.

> +    /* SeaBIOS returns the below values for int 0x13 func 0x08 regardless of
> +     * the drive type, so shall we */

    /*
     * Format comments
     * Like this please
     */

    /* Not
     * Like this */


> +    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 Aml *build_fdc_device_aml(ISADevice *fdc)
>  {
> +    int i;
>      Aml *dev;
>      Aml *crs;
> +    uint32_t fde_buf[5] = {0, 0, 0, 0, cpu_to_le32(0x2)};

Pls document values.

>  
>      dev = aml_device("FDC0");
>      aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0700")));
> @@ -1243,6 +1281,21 @@ static Aml *build_fdc_device_aml(void)
>          aml_dma(AML_COMPATIBILITY, AML_NOTBUSMASTER, AML_TRANSFER8, 2));
>      aml_append(dev, aml_name_decl("_CRS", crs));
>  
> +    for (i = 0; i < MAX_FD; i++) {
> +        uint8_t type = isa_fdc_get_drive_type(fdc, i);
> +
> +        if (type < FLOPPY_DRIVE_TYPE_NONE) {
> +            uint8_t cylinders, heads, sectors;
> +
> +            fde_buf[i] = cpu_to_le32(0x1);

Pls document values.

> +            isa_fdc_get_drive_geometry(fdc, i, &cylinders, &heads, &sectors);
> +            aml_append(dev,
> +                build_fdinfo_aml(i, type, cylinders, heads, sectors));
> +        }
> +    }
> +    aml_append(dev, aml_name_decl("_FDE",
> +               aml_buffer(sizeof(fde_buf), (uint8_t *) fde_buf)));

No space after cast please.

> +
>      return dev;
>  }
>  
> @@ -1387,13 +1440,15 @@ static Aml *build_com_device_aml(uint8_t uid)
>  
>  static void build_isa_devices_aml(Aml *table)
>  {
> +    ISADevice *fdc = pc_find_fdc0();
> +
>      Aml *scope = aml_scope("_SB.PCI0.ISA");
>  
>      aml_append(scope, build_rtc_device_aml());
>      aml_append(scope, build_kbd_device_aml());
>      aml_append(scope, build_mouse_device_aml());
> -    if (!!pc_find_fdc0()) {
> -        aml_append(scope, build_fdc_device_aml());
> +    if (!!fdc) {
> +        aml_append(scope, build_fdc_device_aml(fdc));
>      }
>      aml_append(scope, build_lpt_device_aml());
>      aml_append(scope, build_com_device_aml(1));
> -- 
> 1.8.3.1
Roman Kagan Feb. 8, 2016, 1 p.m. UTC | #2
On Sun, Feb 07, 2016 at 11:08:07AM +0200, Michael S. Tsirkin wrote:
> On Tue, Jan 26, 2016 at 02:50:25PM +0100, Igor Mammedov wrote:
> > From: Roman Kagan <rkagan@virtuozzo.com>
> > -static Aml *build_fdc_device_aml(void)
> > +static Aml *build_fdinfo_aml(int idx, uint8_t type, uint8_t cylinders,
> > +                             uint8_t heads, uint8_t sectors)
> 
> acpi spec says these are WORD values. Are they really uint8_t?

Yes, see struct FDrive.

> > +    fdi = aml_package(0x10);
> 
> Why 0x10 and not 16?

I'm unaware of the difference...  If you have any preference I'll
adjust.  (Originally I stuck with hex because so did iasl -d and the
then hand-written ASL).

> > +    aml_append(fdi, aml_int(idx));  /* Drive Number */
> > +    aml_append(fdi,
> > +        aml_int(cmos_get_fd_drive_type(type)));  /* Device Type */
> > +    aml_append(fdi,
> > +        aml_int(cylinders - 1));  /* Maximum Cylinder Number */
> > +    aml_append(fdi, aml_int(sectors));  /* Maximum Sector Number */
> > +    aml_append(fdi, aml_int(heads - 1));  /* Maximum Head Number */
> 
> Doesn't above change on media change?

I guess no, because this IMHO is supposed to describe the drive
properties, not the diskette properties.  But I'll double-check.

I'm confused about the status of this patchset: I saw you post a pull
request with this series last week, and now you review it.  What should
I do now in response to your comments: rework and resubmit it or post
incremental fixes on top of it?

Thanks,
Roman.
Michael S. Tsirkin Feb. 8, 2016, 1:16 p.m. UTC | #3
On Mon, Feb 08, 2016 at 04:00:37PM +0300, Roman Kagan wrote:
> On Sun, Feb 07, 2016 at 11:08:07AM +0200, Michael S. Tsirkin wrote:
> > On Tue, Jan 26, 2016 at 02:50:25PM +0100, Igor Mammedov wrote:
> > > From: Roman Kagan <rkagan@virtuozzo.com>
> > > -static Aml *build_fdc_device_aml(void)
> > > +static Aml *build_fdinfo_aml(int idx, uint8_t type, uint8_t cylinders,
> > > +                             uint8_t heads, uint8_t sectors)
> > 
> > acpi spec says these are WORD values. Are they really uint8_t?
> 
> Yes, see struct FDrive.
> 
> > > +    fdi = aml_package(0x10);
> > 
> > Why 0x10 and not 16?
> 
> I'm unaware of the difference...  If you have any preference I'll
> adjust.  (Originally I stuck with hex because so did iasl -d and the
> then hand-written ASL).

Decimal as other packages please.

> > > +    aml_append(fdi, aml_int(idx));  /* Drive Number */
> > > +    aml_append(fdi,
> > > +        aml_int(cmos_get_fd_drive_type(type)));  /* Device Type */
> > > +    aml_append(fdi,
> > > +        aml_int(cylinders - 1));  /* Maximum Cylinder Number */
> > > +    aml_append(fdi, aml_int(sectors));  /* Maximum Sector Number */
> > > +    aml_append(fdi, aml_int(heads - 1));  /* Maximum Head Number */
> > 
> > Doesn't above change on media change?
> 
> I guess no, because this IMHO is supposed to describe the drive
> properties, not the diskette properties.  But I'll double-check.

Where you take this from seems to be diskette properties though ...

> I'm confused about the status of this patchset: I saw you post a pull
> request with this series last week, and now you review it.  What should
> I do now in response to your comments: rework and resubmit it or post
> incremental fixes on top of it?
> 
> Thanks,
> Roman.

I dropped and re-did review because Igor reported XP crashing.
You should address comments and resubmit.

Thanks!
Igor Mammedov Feb. 8, 2016, 1:41 p.m. UTC | #4
On Tue, 26 Jan 2016 14:50:25 +0100
Igor Mammedov <imammedo@redhat.com> wrote:

> 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.
> 
> However Windows doesn't do it. Instead, it requests
> this information from BIOS via int 0x13/0x08 or through
> ACPI objects _FDE (Floppy Drive Enumerate) and _FDI
> (Floppy Drive Information) of the floppy controller object.
> On UEFI systems only ACPI-based detection is supported.
> 
> QEMU doesn't provide those objects in its ACPI tables
> and as a result floppy drives aren't invisible to Windows
> on UEFI/OVMF.
> 
> This patch adds those objects to the floppy controller
> in DSDT, populating them with the information from
> respective QEMU objects.
> 
> Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
pls also test with booting XP guest with default SeaBIOS firmware.

> ---
> fixup:
>   - rebase on latest FDC refactoring
> ---
>  hw/i386/acpi-build.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 58 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 2f685fb..1d291d8 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 "hw/mem/nvdimm.h"
>  #include "sysemu/tpm.h"
> @@ -1227,10 +1228,47 @@ static void build_hpet_aml(Aml *table)
>      aml_append(table, scope);
>  }
>  
> -static Aml *build_fdc_device_aml(void)
> +static Aml *build_fdinfo_aml(int idx, uint8_t type, uint8_t cylinders,
> +                             uint8_t heads, uint8_t sectors)
> +{
> +    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(type)));  /* Device Type */
> +    aml_append(fdi,
> +        aml_int(cylinders - 1));  /* Maximum Cylinder Number */
int overflow shouldn't happen here, XP crashes here
because overflows causes 64bit number here which has not
supported AML opcode per ACPI1.0b spec,
Also per ACPI spec it's uint16_t type max.


> +    aml_append(fdi, aml_int(sectors));  /* Maximum Sector Number */
> +    aml_append(fdi, aml_int(heads - 1));  /* Maximum Head Number */
isa_fdc_get_drive_geometry() returns number of 'heads' either 1 or 2,
so are you sure that (heads - 1) is correct here?
The same question applies to 'cylinders'.


> +    /* 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 Aml *build_fdc_device_aml(ISADevice *fdc)
>  {
> +    int i;
>      Aml *dev;
>      Aml *crs;
> +    uint32_t fde_buf[5] = {0, 0, 0, 0, cpu_to_le32(0x2)};
>  
>      dev = aml_device("FDC0");
>      aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0700")));
> @@ -1243,6 +1281,21 @@ static Aml *build_fdc_device_aml(void)
>          aml_dma(AML_COMPATIBILITY, AML_NOTBUSMASTER, AML_TRANSFER8, 2));
>      aml_append(dev, aml_name_decl("_CRS", crs));
>  
> +    for (i = 0; i < MAX_FD; i++) {
> +        uint8_t type = isa_fdc_get_drive_type(fdc, i);
> +
> +        if (type < FLOPPY_DRIVE_TYPE_NONE) {
> +            uint8_t cylinders, heads, sectors;
> +
> +            fde_buf[i] = cpu_to_le32(0x1);
> +            isa_fdc_get_drive_geometry(fdc, i, &cylinders, &heads, &sectors);
> +            aml_append(dev,
> +                build_fdinfo_aml(i, type, cylinders, heads, sectors));
> +        }
> +    }
> +    aml_append(dev, aml_name_decl("_FDE",
> +               aml_buffer(sizeof(fde_buf), (uint8_t *) fde_buf)));
> +
>      return dev;
>  }
>  
> @@ -1387,13 +1440,15 @@ static Aml *build_com_device_aml(uint8_t uid)
>  
>  static void build_isa_devices_aml(Aml *table)
>  {
> +    ISADevice *fdc = pc_find_fdc0();
> +
>      Aml *scope = aml_scope("_SB.PCI0.ISA");
>  
>      aml_append(scope, build_rtc_device_aml());
>      aml_append(scope, build_kbd_device_aml());
>      aml_append(scope, build_mouse_device_aml());
> -    if (!!pc_find_fdc0()) {
> -        aml_append(scope, build_fdc_device_aml());
> +    if (!!fdc) {
> +        aml_append(scope, build_fdc_device_aml(fdc));
>      }
>      aml_append(scope, build_lpt_device_aml());
>      aml_append(scope, build_com_device_aml(1));
diff mbox

Patch

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 2f685fb..1d291d8 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 "hw/mem/nvdimm.h"
 #include "sysemu/tpm.h"
@@ -1227,10 +1228,47 @@  static void build_hpet_aml(Aml *table)
     aml_append(table, scope);
 }
 
-static Aml *build_fdc_device_aml(void)
+static Aml *build_fdinfo_aml(int idx, uint8_t type, uint8_t cylinders,
+                             uint8_t heads, uint8_t sectors)
+{
+    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(type)));  /* Device Type */
+    aml_append(fdi,
+        aml_int(cylinders - 1));  /* Maximum Cylinder Number */
+    aml_append(fdi, aml_int(sectors));  /* Maximum Sector Number */
+    aml_append(fdi, aml_int(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 Aml *build_fdc_device_aml(ISADevice *fdc)
 {
+    int i;
     Aml *dev;
     Aml *crs;
+    uint32_t fde_buf[5] = {0, 0, 0, 0, cpu_to_le32(0x2)};
 
     dev = aml_device("FDC0");
     aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0700")));
@@ -1243,6 +1281,21 @@  static Aml *build_fdc_device_aml(void)
         aml_dma(AML_COMPATIBILITY, AML_NOTBUSMASTER, AML_TRANSFER8, 2));
     aml_append(dev, aml_name_decl("_CRS", crs));
 
+    for (i = 0; i < MAX_FD; i++) {
+        uint8_t type = isa_fdc_get_drive_type(fdc, i);
+
+        if (type < FLOPPY_DRIVE_TYPE_NONE) {
+            uint8_t cylinders, heads, sectors;
+
+            fde_buf[i] = cpu_to_le32(0x1);
+            isa_fdc_get_drive_geometry(fdc, i, &cylinders, &heads, &sectors);
+            aml_append(dev,
+                build_fdinfo_aml(i, type, cylinders, heads, sectors));
+        }
+    }
+    aml_append(dev, aml_name_decl("_FDE",
+               aml_buffer(sizeof(fde_buf), (uint8_t *) fde_buf)));
+
     return dev;
 }
 
@@ -1387,13 +1440,15 @@  static Aml *build_com_device_aml(uint8_t uid)
 
 static void build_isa_devices_aml(Aml *table)
 {
+    ISADevice *fdc = pc_find_fdc0();
+
     Aml *scope = aml_scope("_SB.PCI0.ISA");
 
     aml_append(scope, build_rtc_device_aml());
     aml_append(scope, build_kbd_device_aml());
     aml_append(scope, build_mouse_device_aml());
-    if (!!pc_find_fdc0()) {
-        aml_append(scope, build_fdc_device_aml());
+    if (!!fdc) {
+        aml_append(scope, build_fdc_device_aml(fdc));
     }
     aml_append(scope, build_lpt_device_aml());
     aml_append(scope, build_com_device_aml(1));