From: Roman Kagan <rka...@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 DSDT; as a result floppy drives were invisible to Windows on UEFI/OVMF. This patch implements those objects in ASL, making the ACPI interpreter query the CMOS field and populate the objects. The data values used for _FDI (which, per ACPI spec, is supposed to be equivalent to BIOS int 0x13/0x08) are taken from SeaBIOS. Signed-off-by: Roman Kagan <rka...@virtuozzo.com> Signed-off-by: Denis V. Lunev <d...@openvz.org> CC: Michael S. Tsirkin <m...@redhat.com> CC: Igor Mammedov <imamm...@redhat.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Richard Henderson <r...@twiddle.net> CC: Eduardo Habkost <ehabk...@redhat.com> --- hw/i386/acpi-dsdt-isa.dsl | 109 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/hw/i386/acpi-dsdt-isa.dsl b/hw/i386/acpi-dsdt-isa.dsl index 89caa16..8b03e2b 100644 --- a/hw/i386/acpi-dsdt-isa.dsl +++ b/hw/i386/acpi-dsdt-isa.dsl @@ -23,6 +23,8 @@ Scope(\_SB.PCI0.ISA) { IRQNoFlags() { 8 } IO(Decode16, 0x0072, 0x0072, 0x02, 0x06) }) + + OperationRegion(CMS0, SystemCMOS, Zero, 0x40) } Device(KBD) { @@ -63,6 +65,113 @@ Scope(\_SB.PCI0.ISA) { IRQNoFlags() { 6 } DMA(Compatibility, NotBusMaster, Transfer8) { 2 } }) + + Field(^RTC.CMS0, ByteAcc, NoLock, Preserve) { + Offset(0x10), + FDTS, 8 + } + + Method(FDTY, 1, NotSerialized) { + If (LEqual(Arg0, 0x00)) { + Return (And(ShiftRight(FDTS, 0x04), 0x0F)) + } ElseIf (LEqual(Arg0, 0x01)) { + Return (And(FDTS, 0x0F)) + } Else { + Return (0x00) + } + } + + Method(_FDE, 0, NotSerialized) { + Store(Buffer(0x14) {}, Local0) + CreateDWordField(Local0, 0x00, FDAE) + CreateDWordField(Local0, 0x04, FDBE) + CreateDWordField(Local0, 0x10, TAPE) + + If (LNotEqual(FDTY(0x00), 0)) { + Store(0x01, FDAE) + } + If (LNotEqual(FDTY(0x01), 0)) { + Store(0x01, FDBE) + } + Store(0x02, TAPE) + + Return (Local0) + } + + Method(FSTA, 1, NotSerialized) { + If (LEqual(FDTY(Arg0), 0x00)) { + Return (0x00) + } Else { + Return (0x0F) + } + } + + Method(XFDI, 1, NotSerialized) { + Store(FDTY(Arg0), Local0) + + Store(Package (0x10) { + 0x00, // Drive Number + 0x00, // Device Type + 0x00, // Maximum Cylinder Number + 0x00, // Maximum Sector Number + 0x00, // Maximum Head Number + /* SeaBIOS uses the below values regardless of the drive + * type, so shall we */ + 0xAF, // disk_specify_1 + 0x02, // disk_specify_2 + 0x25, // disk_motor_wait + 0x02, // disk_sector_siz + 0x12, // disk_eot + 0x1B, // disk_rw_gap + 0xFF, // disk_dtl + 0x6C, // disk_formt_gap + 0xF6, // disk_fill + 0x0F, // disk_head_sttl + 0x08, // disk_motor_strt + }, Local1) + + Store(Arg0, Index(Local1, 0x00)) + Store(Local0, Index(Local1, 0x01)) + + If (LEqual(Local0, 4)) { + /* 1.44 Mb 3"5 drive */ + Store(0x4F, Index(Local1, 0x02)) + Store(0x12, Index(Local1, 0x03)) + Store(0x01, Index(Local1, 0x04)) + } ElseIf (LEqual(Local0, 5)) { + /* 2.88 Mb 3"5 drive */ + Store(0x4F, Index(Local1, 0x02)) + Store(0x24, Index(Local1, 0x03)) + Store(0x01, Index(Local1, 0x04)) + } ElseIf (LEqual(Local0, 2)) { + /* 1.2 Mb 5"5 drive */ + Store(0x4F, Index(Local1, 0x02)) + Store(0x0F, Index(Local1, 0x03)) + Store(0x01, Index(Local1, 0x04)) + } + + Return (Local1) + } + + Device(FLPA) { + Name(_ADR, 0x00) + Method(_STA, 0, NotSerialized) { + Return (FSTA(_ADR)) + } + Method(_FDI, 0, NotSerialized) { + Return (XFDI(_ADR)) + } + } + + Device(FLPB) { + Name(_ADR, 0x01) + Method(_STA, 0, NotSerialized) { + Return (FSTA(_ADR)) + } + Method(_FDI, 0, NotSerialized) { + Return (XFDI(_ADR)) + } + } } Device(LPT) { -- 2.1.4