floppy.c revision 2b114c590cf5a19f8047cd7bde9c7e5ae00aa22b
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Copyright (C) 2006-2012 Oracle Corporation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * available from http://www.virtualbox.org. This file is free software;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * you can redistribute it and/or modify it under the terms of the GNU
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * General Public License (GPL) as published by the Free Software
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * --------------------------------------------------------------------
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This code is based on:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Copyright (C) 2002 MandrakeSoft S.A.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * MandrakeSoft S.A.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * 43, rue d'Aboukir
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * 75002 Paris - France
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This library is free software; you can redistribute it and/or
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * modify it under the terms of the GNU Lesser General Public
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * License as published by the Free Software Foundation; either
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * version 2 of the License, or (at your option) any later version.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This library is distributed in the hope that it will be useful,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * but WITHOUT ANY WARRANTY; without even the implied warranty of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Lesser General Public License for more details.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * You should have received a copy of the GNU Lesser General Public
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * License along with this library; if not, write to the Free Software
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//////////////////////
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// FLOPPY functions //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//////////////////////
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncvoid set_diskette_current_cyl(uint8_t drive, uint8_t cyl)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync# define BX_DEBUG_INT13_FL(...) BX_DEBUG(__VA_ARGS__)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncextern int diskette_param_table; /* At a fixed location. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Wait for the 7th bit of 0040:003e to be set by int0e_handler.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns first 7 bits of byte 0040:003e, interrupts disabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Wait for the 7th bit of 0040:003e to be set by int0e_handler or 0040:0040 to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * be cleared by the timer, clearing the interrupt flag on success.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns 0 on timeout with interrupts enabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * All 8 bits at 0040:003e on interrupt with interrupts disabled (i.e.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * non-zero), after first clearing the 7th bit at 0040:003e.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (val8 == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif /* !VBOX_WITH_FLOPPY_IRQ_POLLING */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Reset controller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Wait for controller to come out of reset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // set 40:3e bit 7 to 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // turn on motor of selected drive, DMA & int enabled, normal operation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // reset the disk motor timeout value of INT 08
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // program data rate
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // wait for drive readiness
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // turn on interrupts
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // wait on 40:3e bit 7 to become 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync val8 = floppy_wait_for_interrupt(); /* (7th bit cleared in ret val) */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync val8 = read_byte(0x0040, 0x003e); // diskette recal status
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // checks passed, return KNOWN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // send Read ID command (2 bytes) to controller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync outb(0x03f5, drive); // 0=drive0, 1=drive1, head always 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // turn on interrupts
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // wait on 40:3e bit 7 to become 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while ( val8 == 0 );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // turn off interrupts
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // read 7 return status bytes from controller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < 7; ++i) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // send Recalibrate command (2 bytes) to controller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // turn on interrupts
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // wait on 40:3e bit 7 to become 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while ( val8 == 0 );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // turn off interrupts
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // set 40:3e bit 7 to 0, and calibrated bit
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync val8 = floppy_wait_for_interrupt(); /* (7th bit cleared in ret val) */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // set 40:3e bit 7 to 0, and calibrated bit
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync write_byte(0x0040, curr_cyl_offset, 0); // current cylinder is 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Try the diskette data rates in the following order:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 1 Mbps -> 500 Kbps -> 300 Kbps -> 250 Kbps
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The 1 Mbps rate is only tried for 2.88M drives.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ** config_data **
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Bitfields for diskette media control:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Bit(s) Description (Table M0028)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 7-6 last data rate set by controller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 5-4 last diskette drive step rate selected
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 00=0Ch, 01=0Dh, 10=0Eh, 11=0Ah
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 3-2 {data rate at start of operation}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 1-0 reserved
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ** media_state **
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Bitfields for diskette drive media state:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Bit(s) Description (Table M0030)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 7-6 data rate
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 5 double stepping required (e.g. 360kB in 1.2MB)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 4 media type established
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 3 drive capable of supporting 4MB media
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 2-0 on exit from BIOS, contains
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 000 trying 360kB in 360kB
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 001 trying 360kB in 1.2MB
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 010 trying 1.2MB in 1.2MB
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 011 360kB in 360kB established
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 100 360kB in 1.2MB established
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 101 1.2MB in 1.2MB established
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 110 reserved
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 111 all other formats/drives
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // @todo: break out drive type determination
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 360K 5.25" drive
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 1.2 MB 5.25" drive
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync media_state = 0x35; // 0011 0101 // need double stepping??? (bit 5)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 720K 3.5" drive
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 1.44 MB 3.5" drive
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 2.88 MB 3.5" drive
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Extended floppy size uses special cmos setting
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 15.6 MB 3.5" (fake) || 63.5 MB 3.5" (fake) - report same as 2.88 MB.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // not recognized
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If even 250 Kbps failed, we can't do much
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync write_byte(0x0040, media_state_offset, media_state);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // check CMOS to see if drive exists
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // @todo: break out drive type determination
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//@todo: put in a header
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncvoid BIOSCALL int13_diskette_function(disk_regs_t r)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BX_DEBUG_INT13_FL("%s: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", __func__, AX, BX, CX, DX, ES);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch ( ah ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // @todo: break out drive type determination
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // force re-calibration etc.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync set_diskette_current_cyl(drive, 0); // current cylinder
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // see if drive exists
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // see if media in drive, and type is known
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read Diskette Sectors
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //-----------------------------------
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // set up DMA controller for transfer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //-----------------------------------
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // es:bx = pointer to where to place information from diskette
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // port 04: DMA-1 base and current address, channel 2
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // port 05: DMA-1 base and current count, channel 2
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // @todo: merge/factor out pointer normalization
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync base_es = (ES << 4); // lower 16bits contributed by ES
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync base_address = base_es + BX; // lower 16 bits of address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // contributed by ES:BX
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // in case of carry, adjust page by 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // check for 64K boundary overrun
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // port 0b: DMA-1 Mode Register
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync mode_register = 0x46; // single mode, increment, autoinit disable,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // transfer type=write, channel 2
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // port 81: DMA-1 Page Register, channel 2
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //--------------------------------------
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // set up floppy controller for transfer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //--------------------------------------
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // send read-normal-data command (9 bytes) to controller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync outb(0x03f5, sector + num_sectors - 1); // last sector to read on track
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // turn on interrupts
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // wait on 40:3e bit 7 to become 1 or timeout (latter isn't armed so it won't happen)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (val8 == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while ( val8 == 0 );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // turn off interrupts
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // set 40:3e bit 7 to 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (val8 == 0) { /* Note! Interrupts enabled in this branch. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // check port 3f4 for accessibility to status bytes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // read 7 return status bytes from controller and store in BDA
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < 7; ++i) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rep_movsw(ES :> BX, ES :> BX, num_sectors * 512 / 2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ??? should track be new val from return_status[3] ?
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // AL = number of sectors read (same value as passed)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Write Diskette Sectors
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //-----------------------------------
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // set up DMA controller for transfer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //-----------------------------------
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // es:bx = pointer to where to place information from diskette
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // port 04: DMA-1 base and current address, channel 2
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // port 05: DMA-1 base and current count, channel 2
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // @todo: merge/factor out pointer normalization
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync base_es = (ES << 4); // lower 16bits contributed by ES
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync base_address = base_es + BX; // lower 16 bits of address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // contributed by ES:BX
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // in case of carry, adjust page by 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // check for 64K boundary overrun
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // port 0b: DMA-1 Mode Register
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync mode_register = 0x4a; // single mode, increment, autoinit disable,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // transfer type=read, channel 2
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // port 81: DMA-1 Page Register, channel 2
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //--------------------------------------
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // set up floppy controller for transfer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //--------------------------------------
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // send write-normal-data command (9 bytes) to controller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync outb(0x03f5, sector + num_sectors - 1); // last sector to write on track
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // turn on interrupts
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // wait on 40:3e bit 7 to become 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (val8 == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while ( val8 == 0 );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync val8 = 0; // separate asm from while() loop @todo: why??
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // turn off interrupts
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // set 40:3e bit 7 to 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (val8 == 0) { /* Note! Interrupts enabled in this branch. */
SET_CF();
page++;
#ifdef VBOX_WITH_FLOPPY_IRQ_POLLING
int_enable();
if (val8 == 0) {
} while ( val8 == 0 );
int_disable();
SET_CF();
SET_AH(0);
AX = 0;
BX = 0;
CX = 0;
DX = 0;
ES = 0;
DI = 0;
SET_CF();
num_floppies = 0;
num_floppies++;
num_floppies++;
if (drive == 0)
SET_BH(0);
SET_AH(0);
SET_AL(0);
switch (drive_type) {
CX = 0;
SET_CF();
if (drive == 0)
if (drive_type==0) {
SET_CF();
SET_CF();
SET_CF();
SET_CF();
SET_CF();
switch ( GET_AH() ) {
CLEAR_CF();
if (val8) {
SET_CF();
SET_CF();
if (drive == 0) {