ata.c revision 8a2c7cae7578acfb7c77a510f12fabee2670e31c
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Copyright (C) 2006-2012 Oracle Corporation
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * available from http://www.virtualbox.org. This file is free software;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * you can redistribute it and/or modify it under the terms of the GNU
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * General Public License (GPL) as published by the Free Software
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * --------------------------------------------------------------------
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * This code is based on:
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * Copyright (C) 2002 MandrakeSoft S.A.
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * MandrakeSoft S.A.
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * 43, rue d'Aboukir
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * 75002 Paris - France
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * This library is free software; you can redistribute it and/or
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * modify it under the terms of the GNU Lesser General Public
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * License as published by the Free Software Foundation; either
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * version 2 of the License, or (at your option) any later version.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * This library is distributed in the hope that it will be useful,
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * but WITHOUT ANY WARRANTY; without even the implied warranty of
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Lesser General Public License for more details.
032a52c5b2984e26e84c2961f8f7f98a3954c8f2vboxsync * You should have received a copy of the GNU Lesser General Public
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * License along with this library; if not, write to the Free Software
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync// ---------------------------------------------------------------------------
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync// Start of ATA/ATAPI Driver
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync// ---------------------------------------------------------------------------
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync "in ax,dx" \
044af0d1e6474076366759db86f101778c5f20ccvboxsync "loop again" \
044af0d1e6474076366759db86f101778c5f20ccvboxsync "push eax" \
044af0d1e6474076366759db86f101778c5f20ccvboxsync "in eax,dx" \
044af0d1e6474076366759db86f101778c5f20ccvboxsync "loop again" \
044af0d1e6474076366759db86f101778c5f20ccvboxsync "pop eax" \
044af0d1e6474076366759db86f101778c5f20ccvboxsync// ---------------------------------------------------------------------------
044af0d1e6474076366759db86f101778c5f20ccvboxsync// ATA/ATAPI driver : initialization
044af0d1e6474076366759db86f101778c5f20ccvboxsync// ---------------------------------------------------------------------------
044af0d1e6474076366759db86f101778c5f20ccvboxsync bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
044af0d1e6474076366759db86f101778c5f20ccvboxsync // Channels info init.
044af0d1e6474076366759db86f101778c5f20ccvboxsync for (channel=0; channel<BX_MAX_ATA_INTERFACES; channel++) {
044af0d1e6474076366759db86f101778c5f20ccvboxsync bios_dsk->channels[channel].iface = ATA_IFACE_NONE;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync // Devices info init.
044af0d1e6474076366759db86f101778c5f20ccvboxsync for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync bios_dsk->devices[device].device = DSK_DEVICE_NONE;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync bios_dsk->devices[device].translation = GEO_TRANSLATION_NONE;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync // hdidmap and cdidmap init.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync for (device=0; device<BX_MAX_STORAGE_DEVICES; device++) {
044af0d1e6474076366759db86f101778c5f20ccvboxsync bios_dsk->hdidmap[device] = BX_MAX_STORAGE_DEVICES;
044af0d1e6474076366759db86f101778c5f20ccvboxsync bios_dsk->cdidmap[device] = BX_MAX_STORAGE_DEVICES;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync// ---------------------------------------------------------------------------
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync// ATA/ATAPI driver : software reset
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync// ---------------------------------------------------------------------------
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync// 8.2.1 Software reset - Device 0
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync // 8.2.1 (a) -- set SRST in DC
a1df400bbe9d64aad400442e56eb637019300a5evboxsync outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync // 8.2.1 (b) -- wait for BSY
044af0d1e6474076366759db86f101778c5f20ccvboxsync while(--max>0) {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync // 8.2.1 (f) -- clear SRST
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (bios_dsk->devices[device].type != DSK_TYPE_NONE) {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync // 8.2.1 (g) -- check for sc==sn==0x01
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync // select device
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync outb(iobase1+ATA_CB_DH, slave?ATA_CB_DH_DEV1:ATA_CB_DH_DEV0);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync // 8.2.1 (h) -- wait for not BSY
044af0d1e6474076366759db86f101778c5f20ccvboxsync max=0xffff; /* The ATA specification says that the drive may be busy for up to 30 seconds. */
044af0d1e6474076366759db86f101778c5f20ccvboxsync while(--max>0) {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync while (--pdelay>0) {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync /* nothing */
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync // 8.2.1 (i) -- wait for DRDY
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync max = 0x10; /* Speed up for virtual drives. Disks are immediately ready, CDs never */
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync while(--max>0) {
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync // Enable interrupts
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync// ---------------------------------------------------------------------------
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync// ATA/ATAPI driver : execute a data-in command
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync// ---------------------------------------------------------------------------
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync // 0 : no error
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync // 1 : BUSY bit set
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync // 2 : read error
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync // 3 : expected DRQ=1
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync // 4 : no sectors left to read/verify
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync // 5 : more sectors to read/verify
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync // 6 : no sectors left to write
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync // 7 : more sectors to write
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncuint16_t ata_cmd_data_in(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t count)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (blksize == 0) { /* If transfer size is exactly 64K */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // Enable interrupts
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync // sector will be 0 only on lba access. Convert to lba-chs
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync cylinder = 0; /* The parameter lba is just a 32 bit value. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* Leave the bottom 24 bits as is, they are treated correctly by the
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * LBA28 code path. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (uint8_t) head );
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (command == ATA_CMD_READ_MULTIPLE || command == ATA_CMD_READ_MULTIPLE_EXT) {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync while (1) {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // Enable interrupts
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync BX_DEBUG_ATA("%s: DRQ not set (status %02x)\n", __func__, (unsigned) status);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // Enable interrupts
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // FIXME : move seg/off translation here
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync while (1) {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // adjust if there will be an overrun. 2K max sector size
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync buffer = MK_FP(FP_SEG(buffer) + 0x80, FP_OFF(buffer) - 0x800);
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync while (1) {
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync BX_DEBUG_ATA("%s: no sectors left (status %02x)\n", __func__, (unsigned) status);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // Enable interrupts
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync BX_DEBUG_ATA("%s: more sectors left (status %02x)\n", __func__, (unsigned) status);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // Enable interrupts
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // Enable interrupts
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync// ---------------------------------------------------------------------------
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync// ATA/ATAPI driver : device detection
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync// ---------------------------------------------------------------------------
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync#if 0 //@todo - temporarily removed to avoid conflict with AHCI
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // Device detection
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (device = 0; device < BX_MAX_ATA_DEVICES; device++) {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // Disable interrupts
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // Look for device
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // If we found something
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // reset the channel
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // check for ATA or ATAPI
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync } else if ((cl==0x00) && (ch==0x00) && (st!=0x00)) {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // Enable interrupts
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // Now we send a IDENTIFY command to ATA device
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync //Temporary values to do the transfer
a1df400bbe9d64aad400442e56eb637019300a5evboxsync if (ata_cmd_data_in(bios_dsk, ATA_CMD_IDENTIFY_DEVICE, 1) !=0 )
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync BX_PANIC("ata-detect: Failed to detect ATA device\n");
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync mode = *(buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync blksize = 512; /* There is no sector size field any more. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync sectors = *(uint32_t *)(buffer+(60*2)); // word 60 and word 61
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /** @todo update sectors to be a 64 bit number (also lba...). */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (sectors == 0x0FFFFFFF) /* For disks bigger than ~128GB */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync sectors = *(uint32_t *)(buffer+(100*2)); // words 100 to 103 (someday)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync lgeo.cylinders = inb_cmos(chsgeo_base) + (inb_cmos(chsgeo_base + 1) << 8);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync set_geom_lba(&lgeo, sectors); /* Default EDD-style translated LBA geometry. */
a1df400bbe9d64aad400442e56eb637019300a5evboxsync BX_INFO("ata%d-%d: PCHS=%u/%u/%u LCHS=%u/%u/%u\n", channel, slave,
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync cylinders, heads, spt, lgeo.cylinders, lgeo.heads, lgeo.spt);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync bios_dsk->devices[device].pchs.cylinders = cylinders;
044af0d1e6474076366759db86f101778c5f20ccvboxsync /* Update the DPT for drive 0/1 pointed to by Int41/46. This used
044af0d1e6474076366759db86f101778c5f20ccvboxsync * to be done at POST time with lots of ugly assembler code, which
044af0d1e6474076366759db86f101778c5f20ccvboxsync * isn't worth the effort of converting from AMI to Award CMOS
044af0d1e6474076366759db86f101778c5f20ccvboxsync * format. Just do it here. */
044af0d1e6474076366759db86f101778c5f20ccvboxsync for (i = 0; i < 0xf; i++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // fill hdidmap
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // Now we send an IDENTIFY command to ATAPI device
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync // Temporary values to do the transfer
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync bios_dsk->devices[device].device = DSK_DEVICE_CDROM;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync if (ata_cmd_data_in(bios_dsk, ATA_CMD_IDENTIFY_PACKET, 1) != 0)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync BX_PANIC("ata-detect: Failed to detect ATAPI device\n");
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync mode = *(buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // fill cdidmap
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // Read ATA/ATAPI version
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync ataversion = ((uint16_t)(*(buffer+161))<<8) | *(buffer+160);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // Read model name
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync for (i = 0; i < 20; i++ ) {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // Reformat
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync for ( i = 39; i > 0; i-- ){
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // we don't want any noisy output for now
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync#else /* !VBOX */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync printf("ata%d %s: ", channel, slave ? " slave" : "master");
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync while(c=*(model+i++))
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync printf(" ATA-%d Hard-Disk (%lu MBytes)\n", version, sizeinmb);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync printf("ata%d %s: ", channel, slave ? " slave" : "master");
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync while(c=*(model+i++))
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if (bios_dsk->devices[device].device == DSK_DEVICE_CDROM)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync printf("ata%d %s: Unknown device\n", channel , slave ? " slave" : "master");
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync#endif /* !VBOX */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // Store the devices counts
044af0d1e6474076366759db86f101778c5f20ccvboxsync // we don't want any noisy output for now
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync#else /* !VBOX */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync#endif /* !VBOX */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // FIXME : should use bios=cmos|auto|disable bits
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // FIXME : should know about translation bits
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // FIXME : move hard_drive_post here
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync// ---------------------------------------------------------------------------
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync// ATA/ATAPI driver : execute a data-out command
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync// ---------------------------------------------------------------------------
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // 0 : no error
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // 1 : BUSY bit set
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // 2 : read error
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // 3 : expected DRQ=1
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // 4 : no sectors left to read/verify
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // 5 : more sectors to read/verify
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // 6 : no sectors left to write
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // 7 : more sectors to write
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncuint16_t ata_cmd_data_out(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t count)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync blksize = 0x200; // was = bios_dsk->devices[device].blksize;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // Enable interrupts
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync // sector will be 0 only on lba access. Convert to lba-chs
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync cylinder = 0; /* The parameter lba is just a 32 bit value. */
a1df400bbe9d64aad400442e56eb637019300a5evboxsync /* Leave the bottom 24 bits as is, they are treated correctly by the
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * LBA28 code path. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (uint8_t) head );
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync while (1) {
a1df400bbe9d64aad400442e56eb637019300a5evboxsync // Enable interrupts
a1df400bbe9d64aad400442e56eb637019300a5evboxsync BX_DEBUG_ATA("%s: DRQ not set (status %02x)\n", __func__, (unsigned) status);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync // Enable interrupts
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync // FIXME : move seg/off translation here
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync while (1) {
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync // adjust if there will be an overrun. 2K max sector size
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync buffer = MK_FP(FP_SEG(buffer) + 0x80, FP_OFF(buffer) - 0x800);
count--;
if (count == 0) {
if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
!= ATA_CB_STAT_RDY ) {
int status;
return status;
transfer = 0L;
lcount = 0;
header = 0;
length = 0;
lafter = 0;
BX_DEBUG_ATA("Trying to read %04x bytes (%04x %04x %04x) ",lbefore+lcount+lafter,lbefore,lcount,lafter);
if (lbefore)
if (lafter)
if (lbefore)
if (lafter)
if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_CHK) )
!= ATA_CB_STAT_RDY ) {
if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_CHK) )
!= ATA_CB_STAT_RDY ) {