From nobody Mon Sep 21 03:46:36 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of seabios.org designates 78.46.105.101 as permitted sender) client-ip=78.46.105.101; envelope-from=seabios-bounces@seabios.org; helo=coreboot.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of seabios.org designates 78.46.105.101 as permitted sender) smtp.mailfrom=seabios-bounces@seabios.org Return-Path: Received: from coreboot.org (mail.coreboot.org [78.46.105.101]) by mx.zohomail.com with SMTPS id 17839715183581.3404915824106638; Mon, 13 Jul 2026 12:38:38 -0700 (PDT) Received: from authenticated-user (PRIMARY_HOSTNAME [PUBLIC_IP]) by coreboot.org (Postfix) with ESMTPA id 504A254EB61; Mon, 13 Jul 2026 19:38:36 +0000 (UTC) Received: from authenticated-user (PRIMARY_HOSTNAME [PUBLIC_IP]) (nx103.node02.secure-mailgate.com [192.162.87.103]) by coreboot.org (Postfix) with ESMTP id 7DD3054E4EF for ; Mon, 13 Jul 2026 19:37:59 +0000 (UTC) Received: from authenticated-user (PRIMARY_HOSTNAME [PUBLIC_IP]) by node02.secure-mailgate.com with esmtps (TLS1.2) tls TLS_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1wjMTT-007eA8-ME; Mon, 13 Jul 2026 21:37:56 +0200 Received: from authenticated-user (PRIMARY_HOSTNAME [PUBLIC_IP]) (Authenticated sender: christian@quante.one) by web279.dogado.net (Postfix) with ESMTPSA id 11A6A282A6B; Mon, 13 Jul 2026 21:37:55 +0200 (CEST) X-SecureMailgate-Identity: christian@quante.one;web279.dogado.net DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quante.one; s=cloudpit; t=1783971475; bh=ho9HizgE2AMuglfrW7Tf1rA6mzMpSIrbVs4LDgtrED0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OU1OWeCUkQSjrQjiRRIYXsF3OzrHgnPlGM/bDK0XYE5HAURxChu7PgI7i9/TKsSl9 +O0g4kllFaLm9qEoHSoEpiS/XDV3OrSyBvkWr4v3Hlp5uZXmMWgTDIA/z6kSyBGnPh d5Xe0OBoYwZHNZtkXKmmPpOHAQ0uVmTz/TYUFy3s= X-SecureMailgate-Identity: christian@quante.one;web279.dogado.net From: Christian Quante To: seabios@seabios.org Date: Mon, 13 Jul 2026 21:35:28 +0200 Message-ID: <20260713193529.13004-3-christian@quante.one> In-Reply-To: <20260713193529.13004-1-christian@quante.one> References: <20260710131853.59862-1-christian@quante.one> <20260713193529.13004-1-christian@quante.one> MIME-Version: 1.0 X-PPP-Message-ID: <178397147550.1149888.9500339901143447190@web279.dogado.net> X-PPP-Vhost: quante.one X-SecureMailgate-Domain: web279.dogado.net X-SecureMailgate-Username: 31.47.255.59 X-SecureMailgate-Outgoing-Class: ham X-SecureMailgate-Outgoing-Evidence: SB/global_tokens (0.0012513856958) X-Recommended-Action: accept X-Filter-ID: 9kzQTOBWQUFZTohSKvQbgI7ZDo5ubYELi59AwcWUnuVu4t7jIdYrPz0JwzgVSLVzqp67aYsyCkiU AIO2E1258iu2SmbhJN1U9FKs8X3+Nt1HOctZ5X+40a9IXddeG3M38JQYgcgjsac3uQcQdCX4ROfH zJ6mVE7ewsipSVIfs4ah3WCVN5shuB3NfXF1c2z5S5+h1uiHzk/Rfxfh461YLyu3RZI1CD15pCOE 1vk99RPdEorPfEdXy94XZtjluxSTdOtYechJ/ikE1WgRg4cS6A6B6pTstltS07kaQJ8I9sYal0h7 43VOpKNY+4MjijihZK0EMmf3P50Ajf/tIX00Fuu2beRqilmjgQ6jA3UwYgm3QTha208ypFqQwBFb xm4JX7semJdl8Weuy8+tlMSTQwhoy9D5QZ6a84vJal7pM1XhlAOd290vPXa7Loma0jth7qAXzi6H u+vd1PUHqD56sKVpCSy8DvYjml2C5x08HjVOdbycUIjxTi/oScdKqdkqU23mck4kYaL7W/YjuX9F gtaPrsMji/nLJj58tIE9bJtlIqecxOBP1yJf91UNzkSEUDq6mKQ/XAiI42Mzh38yXz3dKxLhoxcm aInYbR5vlqHlDhVAB/0EYD/jnz2OZJv6szlVwj1n2JAvHUSGQgae904HZe+Npbm5PA9zxaDCuu7n enbrzWUw2X62ZQfetBN+Wd6yNxOSUIsmGCJDuSiGSNdj68Lf4FNI5GmjYNknO4X1WwpSOxYAbinP WCPuFtl/VoXnJtsWNsYVIIkn7QRyQSC01dGS582vdIGGJfCYvwM9tQrhDVxWCGj1JArKPJWkG7EB ouE/Lp65oEK6Kr4PFISAzVaFNHfkjGyFyiRzr7YOhfiboNBv0POUVLQJNXGP/GGMrN0VgEP1fddi hPZrzx1Lw2yMf4vpvhlM+vErQ1gn6IjLLbcvolUaG2pSKCEkiWrFfcvTzpdI3AEG059XQZZCz9LK 39KzUylJRvNoHDV3OnKG9eRDP2/Ogb+c8D2oSvdcBJ1869L2y5ERFHC8NPIK4B7OUVSn0kbL6D23 dfd3aH2fATPqEIe+zbt2NwyT7DYzFfTn4NXnBjEun9DvZ0n9a1rfFCnSMsc+vEwrNstTbe4wBw6S kC2jAENWaINDgXBbKTIlqNpRK89muFbKwBsa9A+nmEd7cRVfyxrpZ1WT35ix5VehBc2cUR742vO7 eUcOGCmJTaorUhtlNRknxw== X-Report-Abuse-To: spam@node04.secure-mailgate.com X-Complaints-To: abuse@node01.secure-mailgate.com Message-ID-Hash: EFKONU76IE7CQWIN3YC3OU66I6OJHYJD X-Message-ID-Hash: EFKONU76IE7CQWIN3YC3OU66I6OJHYJD X-MailFrom: christian@quante.one X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-seabios.seabios.org-0; header-match-seabios.seabios.org-1; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header Cc: Gerd Hoffmann , Christian Quante X-Mailman-Version: 3.3.11b1 Precedence: list Subject: [SeaBIOS] [PATCH v2 2/3] floppy: detect an empty drive via the disk change line List-Id: SeaBIOS mailing list Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Content-Transfer-Encoding: quoted-printable Authentication-Results: coreboot.org; auth=pass smtp.auth=mailman@coreboot.org smtp.mailfrom=seabios-bounces@seabios.org X-Spamd-Bar: --- X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1783971521471158500 Content-Type: text/plain; charset="utf-8" floppy_prep() recalibrates and then calls floppy_media_sense(), which issues READ ID once per data rate. A drive with no medium spins no diskette and therefore produces no index pulses, so a real controller never completes READ ID and every attempt waits out FLOPPY_IRQ_TIMEOUT. Booting with an empty drive, or an INT 13h read of an empty A:, costs about ten seconds. The disk change line answers the same question immediately. It latches when the medium is removed and is cleared only by a step pulse with a diskette in the drive. A recalibrate leaves the head on cylinder 0 and need not step at all, so seek to cylinder 1 and read DIR again. Linux's floppy driver has done exactly this since 2.0 and never issues READ ID. Only the 1.2MB 5.25" drive and the 3.5" drives have the change line (CMOS types 2..5); on the older 5.25" types the pin is not driven and reads back as a permanent "changed". Restrict the probe to those types, and report any uncertainty as success, so that the code can only ever fall back to the current behaviour. The error code is unchanged: floppy_media_sense() already reports DISK_RET_EMEDIA once it has exhausted the data rates, so an empty drive still answers DISK_RET_EMEDIA -- just without the wait. Measured with qemu-system-x86_64, "-machine pc -device floppy, drive-type=3D144" and no medium, INT 13h AH=3D02h on drive A: before 0.11 s, AH =3D 0x20 (controller failure) after 0.11 s, AH =3D 0xC0 (no media) QEMU completes READ ID successfully on an empty drive, which hides the timeout; a fix for that is on qemu-devel [1]. With it applied, so that READ ID never completes as on real hardware, the same read takes 10.12 s before this change and 0.11 s after it. Booting from a diskette is unaffected, including the cold start where the change line is set for a freshly inserted medium. [1] https://lore.kernel.org/qemu-devel/20260710113134.43012-1-christian@qua= nte.one/ Signed-off-by: Christian Quante --- src/hw/floppy.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/hw/floppy.c b/src/hw/floppy.c index 8f053fe3..20033fa3 100644 --- a/src/hw/floppy.c +++ b/src/hw/floppy.c @@ -27,6 +27,9 @@ #define PORT_FD_DATA 0x03f5 #define PORT_FD_DIR 0x03f7 =20 +// Digital Input Register (read) +#define FLOPPY_DIR_DSKCHG 0x80 + #define FLOPPY_SIZE_CODE 0x02 // 512 byte sectors #define FLOPPY_DATALEN 0xff // Not used - because size code is 0x02 #define FLOPPY_MOTOR_TICKS 37 // ~2 seconds @@ -457,6 +460,47 @@ floppy_drive_readid(u8 floppyid, u8 data_rate, u8 head) return 0; } =20 +// Only the 1.2MB 5.25" drive and the 3.5" drives have a disk change line.= On +// the older 5.25" types the pin is not driven and reads back as a permane= nt +// "changed". +static int +floppy_has_changeline(u8 ftype) +{ + return ftype >=3D 2 && ftype <=3D 5; +} + +// Determine whether a diskette is present, without waiting for a command = to +// time out. The disk change line latches when the medium is removed and = is +// cleared only by a step pulse with a diskette in the drive. The caller = has +// just recalibrated, which leaves the head on cylinder 0 and need not ste= p at +// all, so step to cylinder 1 and look again. The head is left there; the +// caller seeks to the cylinder it wants anyway. +// +// Report DISK_RET_EMEDIA only when the drive is known to be empty -- any +// uncertainty is reported as success, so this can only ever fall back to = the +// previous behaviour. +static int +floppy_check_media(struct drive_s *drive_gf, u8 floppyid) +{ + if (!floppy_has_changeline(GET_GLOBALFLAT(drive_gf->floppy_type))) + return DISK_RET_SUCCESS; + + // The caller has just recalibrated this drive, so it is selected in t= he + // DOR and the DIR reflects its change line. + if (!(inb(PORT_FD_DIR) & FLOPPY_DIR_DSKCHG)) + return DISK_RET_SUCCESS; + + int ret =3D floppy_drive_seek(floppyid, 1); + if (ret) + return DISK_RET_SUCCESS; + + if (!(inb(PORT_FD_DIR) & FLOPPY_DIR_DSKCHG)) + return DISK_RET_SUCCESS; + + dprintf(2, "Floppy_check_media %d: no medium\n", floppyid); + return DISK_RET_EMEDIA; +} + static int floppy_media_sense(struct drive_s *drive_gf) { @@ -513,6 +557,13 @@ floppy_prep(struct drive_s *drive_gf, u8 cylinder) if (ret) return ret; =20 + // An empty drive gives no index pulses, so the READ ID that + // floppy_media_sense() issues would never complete and would wait= out + // its timeout once per data rate. Ask the disk change line inste= ad. + ret =3D floppy_check_media(drive_gf, floppyid); + if (ret) + return ret; + // Sense media. ret =3D floppy_media_sense(drive_gf); if (ret) --=20 2.53.0 _______________________________________________ SeaBIOS mailing list -- seabios@seabios.org To unsubscribe send an email to seabios-leave@seabios.org