summaryrefslogtreecommitdiff
path: root/src/VBox/Devices/PC/BIOS/ata.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/PC/BIOS/ata.c')
-rw-r--r--src/VBox/Devices/PC/BIOS/ata.c243
1 files changed, 136 insertions, 107 deletions
diff --git a/src/VBox/Devices/PC/BIOS/ata.c b/src/VBox/Devices/PC/BIOS/ata.c
index 5290edea..921433d2 100644
--- a/src/VBox/Devices/PC/BIOS/ata.c
+++ b/src/VBox/Devices/PC/BIOS/ata.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -82,9 +82,9 @@ void BIOSCALL ata_init(void)
{
uint8_t channel, device;
bio_dsk_t __far *bios_dsk;
-
+
bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
-
+
// Channels info init.
for (channel=0; channel<BX_MAX_ATA_INTERFACES; channel++) {
bios_dsk->channels[channel].iface = ATA_IFACE_NONE;
@@ -92,7 +92,7 @@ void BIOSCALL ata_init(void)
bios_dsk->channels[channel].iobase2 = 0x0;
bios_dsk->channels[channel].irq = 0;
}
-
+
// Devices info init.
for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
bios_dsk->devices[device].type = DSK_TYPE_NONE;
@@ -110,13 +110,13 @@ void BIOSCALL ata_init(void)
bios_dsk->devices[device].pchs.spt = 0;
bios_dsk->devices[device].sectors = 0;
}
-
+
// hdidmap and cdidmap init.
for (device=0; device<BX_MAX_STORAGE_DEVICES; device++) {
bios_dsk->hdidmap[device] = BX_MAX_STORAGE_DEVICES;
bios_dsk->cdidmap[device] = BX_MAX_STORAGE_DEVICES;
}
-
+
bios_dsk->hdcount = 0;
bios_dsk->cdcount = 0;
}
@@ -134,11 +134,11 @@ void ata_reset(uint16_t device)
uint16_t max;
uint16_t pdelay;
bio_dsk_t __far *bios_dsk;
-
+
bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
channel = device / 2;
slave = device % 2;
-
+
iobase1 = bios_dsk->channels[channel].iobase1;
iobase2 = bios_dsk->channels[channel].iobase2;
@@ -184,10 +184,10 @@ void ata_reset(uint16_t device)
max = 0x10; /* Speed up for virtual drives. Disks are immediately ready, CDs never */
while(--max>0) {
uint8_t status = inb(iobase1+ATA_CB_STAT);
- if ((status & ATA_CB_STAT_RDY) != 0)
+ if ((status & ATA_CB_STAT_RDY) != 0)
break;
}
-
+
// Enable interrupts
outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
}
@@ -235,7 +235,7 @@ uint16_t ata_cmd_data_in(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t c
else
blksize >>= 1;
}
-
+
status = inb(iobase1 + ATA_CB_STAT);
if (status & ATA_CB_STAT_BSY)
{
@@ -271,7 +271,7 @@ uint16_t ata_cmd_data_in(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t c
lba >>= 16;
head = ((uint16_t) (lba & 0x0000000fL)) | 0x40;
}
-
+
outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
outb(iobase1 + ATA_CB_FR, 0x00);
outb(iobase1 + ATA_CB_SC, count);
@@ -280,20 +280,20 @@ uint16_t ata_cmd_data_in(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t c
outb(iobase1 + ATA_CB_CH, cylinder >> 8);
outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (uint8_t) head );
outb(iobase1 + ATA_CB_CMD, command);
-
+
if (command == ATA_CMD_READ_MULTIPLE || command == ATA_CMD_READ_MULTIPLE_EXT) {
mult_blk_cnt = count;
count = 1;
} else {
mult_blk_cnt = 1;
}
-
+
while (1) {
status = inb(iobase1 + ATA_CB_STAT);
if ( !(status & ATA_CB_STAT_BSY) )
break;
}
-
+
if (status & ATA_CB_STAT_ERR) {
BX_DEBUG_ATA("%s: read error\n", __func__);
// Enable interrupts
@@ -305,17 +305,17 @@ uint16_t ata_cmd_data_in(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t c
outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
return 3;
}
-
+
// FIXME : move seg/off translation here
-
+
int_enable(); // enable higher priority interrupts
-
+
while (1) {
-
+
// adjust if there will be an overrun. 2K max sector size
if (FP_OFF(buffer) >= 0xF800)
buffer = MK_FP(FP_SEG(buffer) + 0x80, FP_OFF(buffer) - 0x800);
-
+
if (mode == ATA_MODE_PIO32) {
buffer = rep_insd(buffer, blksize, iobase1);
} else {
@@ -364,7 +364,7 @@ void BIOSCALL ata_detect(void)
uint8_t hdcount, cdcount, device, type;
uint8_t buffer[0x0200];
bio_dsk_t __far *bios_dsk;
-
+
bios_dsk = ebda_seg :> &EbdaData->bdisk;
#if BX_MAX_ATA_INTERFACES > 0
@@ -404,16 +404,16 @@ void BIOSCALL ata_detect(void)
uint16_t iobase1, iobase2;
uint8_t channel, slave;
uint8_t sc, sn, cl, ch, st;
-
+
channel = device / 2;
slave = device % 2;
-
+
iobase1 = bios_dsk->channels[channel].iobase1;
iobase2 = bios_dsk->channels[channel].iobase2;
-
+
// Disable interrupts
outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
-
+
// Look for device
outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
outb(iobase1+ATA_CB_SC, 0x55);
@@ -422,7 +422,7 @@ void BIOSCALL ata_detect(void)
outb(iobase1+ATA_CB_SN, 0x55);
outb(iobase1+ATA_CB_SC, 0x55);
outb(iobase1+ATA_CB_SN, 0xaa);
-
+
// If we found something
sc = inb(iobase1+ATA_CB_SC);
sn = inb(iobase1+ATA_CB_SN);
@@ -461,7 +461,7 @@ void BIOSCALL ata_detect(void)
if (type == DSK_TYPE_ATA) {
uint32_t sectors;
uint16_t cylinders, heads, spt, blksize;
- uint16_t lcylinders, lheads, lspt;
+ chs_t lgeo;
uint8_t chsgeo_base;
uint8_t removable, mode;
@@ -500,35 +500,20 @@ void BIOSCALL ata_detect(void)
case 3:
chsgeo_base = 0x70;
break;
- case 4:
- chsgeo_base = 0x40;
- break;
- case 5:
- chsgeo_base = 0x48;
- break;
- case 6:
- chsgeo_base = 0x50;
- break;
- case 7:
- chsgeo_base = 0x58;
- break;
default:
chsgeo_base = 0;
}
- if (chsgeo_base != 0)
+ if (chsgeo_base)
{
- lcylinders = inb_cmos(chsgeo_base) + (inb_cmos(chsgeo_base+1) << 8);
- lheads = inb_cmos(chsgeo_base+2);
- lspt = inb_cmos(chsgeo_base+7);
+ lgeo.cylinders = inb_cmos(chsgeo_base) + (inb_cmos(chsgeo_base + 1) << 8);
+ lgeo.heads = inb_cmos(chsgeo_base + 2);
+ lgeo.spt = inb_cmos(chsgeo_base + 7);
}
else
- {
- lcylinders = 0;
- lheads = 0;
- lspt = 0;
- }
+ set_geom_lba(&lgeo, sectors); /* Default EDD-style translated LBA geometry. */
+
BX_INFO("ata%d-%d: PCHS=%u/%d/%d LCHS=%u/%u/%u\n", channel, slave,
- cylinders,heads, spt, lcylinders, lheads, lspt);
+ cylinders,heads, spt, lgeo.cylinders, lgeo.heads, lgeo.spt);
bios_dsk->devices[device].device = DSK_DEVICE_HD;
bios_dsk->devices[device].removable = removable;
@@ -538,9 +523,7 @@ void BIOSCALL ata_detect(void)
bios_dsk->devices[device].pchs.cylinders = cylinders;
bios_dsk->devices[device].pchs.spt = spt;
bios_dsk->devices[device].sectors = sectors;
- bios_dsk->devices[device].lchs.heads = lheads;
- bios_dsk->devices[device].lchs.cylinders = lcylinders;
- bios_dsk->devices[device].lchs.spt = lspt;
+ bios_dsk->devices[device].lchs = lgeo;
if (device < 2)
{
uint8_t sum, i;
@@ -555,8 +538,8 @@ void BIOSCALL ata_detect(void)
* to be done at POST time with lots of ugly assembler code, which
* isn't worth the effort of converting from AMI to Award CMOS
* format. Just do it here. */
- fdpt->lcyl = lcylinders;
- fdpt->lhead = lheads;
+ fdpt->lcyl = lgeo.cylinders;
+ fdpt->lhead = lgeo.heads;
fdpt->sig = 0xa0;
fdpt->spt = spt;
fdpt->cyl = cylinders;
@@ -632,7 +615,7 @@ void BIOSCALL ata_detect(void)
for ( i = 39; i > 0; i-- ){
if (*(model+i) == 0x20)
*(model+i) = 0x00;
- else
+ else
break;
}
break;
@@ -708,11 +691,11 @@ uint16_t ata_cmd_data_out(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t
uint16_t device;
uint8_t channel, slave;
uint8_t status, mode;
-
+
device = bios_dsk->drqp.dev_id;
channel = device / 2;
slave = device % 2;
-
+
iobase1 = bios_dsk->channels[channel].iobase1;
iobase2 = bios_dsk->channels[channel].iobase2;
mode = bios_dsk->devices[device].mode;
@@ -721,7 +704,7 @@ uint16_t ata_cmd_data_out(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t
blksize >>= 2;
else
blksize >>= 1;
-
+
status = inb(iobase1 + ATA_CB_STAT);
if (status & ATA_CB_STAT_BSY)
{
@@ -756,7 +739,7 @@ uint16_t ata_cmd_data_out(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t
lba >>= 16;
head = ((uint16_t) (lba & 0x0000000fL)) | 0x40;
}
-
+
outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
outb(iobase1 + ATA_CB_FR, 0x00);
outb(iobase1 + ATA_CB_SC, count);
@@ -765,15 +748,15 @@ uint16_t ata_cmd_data_out(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t
outb(iobase1 + ATA_CB_CH, cylinder >> 8);
outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (uint8_t) head );
outb(iobase1 + ATA_CB_CMD, command);
-
+
while (1) {
status = inb(iobase1 + ATA_CB_STAT);
if ( !(status & ATA_CB_STAT_BSY) )
break;
}
-
+
if (status & ATA_CB_STAT_ERR) {
- BX_DEBUG_ATA("%s: read error\n", __func__);
+ BX_DEBUG_ATA("%s: write error\n", __func__);
// Enable interrupts
outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
return 2;
@@ -783,23 +766,23 @@ uint16_t ata_cmd_data_out(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t
outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
return 3;
}
-
+
// FIXME : move seg/off translation here
-
+
int_enable(); // enable higher priority interrupts
-
+
while (1) {
-
+
// adjust if there will be an overrun. 2K max sector size
if (FP_OFF(buffer) >= 0xF800)
buffer = MK_FP(FP_SEG(buffer) + 0x80, FP_OFF(buffer) - 0x800);
-
+
if (mode == ATA_MODE_PIO32) {
buffer = rep_outsd(buffer, blksize, iobase1);
} else {
buffer = rep_outsw(buffer, blksize, iobase1);
}
-
+
bios_dsk->drqp.trsfsectors++;
count--;
while (1) {
@@ -838,7 +821,7 @@ uint16_t ata_cmd_data_out(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t
* Read sectors from an attached ATA device.
*
* @returns status code.
- * @param bios_dsk Pointer to disk request packet (in the
+ * @param bios_dsk Pointer to disk request packet (in the
* EBDA).
*/
int ata_read_sectors(bio_dsk_t __far *bios_dsk)
@@ -872,7 +855,7 @@ int ata_read_sectors(bio_dsk_t __far *bios_dsk)
* Write sectors to an attached ATA device.
*
* @returns status code.
- * @param bios_dsk Pointer to disk request packet (in the
+ * @param bios_dsk Pointer to disk request packet (in the
* EBDA).
*/
int ata_write_sectors(bio_dsk_t __far *bios_dsk)
@@ -903,7 +886,7 @@ int ata_write_sectors(bio_dsk_t __far *bios_dsk)
// 2 : BUSY bit set
// 3 : error
// 4 : not ready
-uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
+uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
uint16_t header, uint32_t length, uint8_t inout, char __far *buffer)
{
uint16_t iobase1, iobase2;
@@ -923,33 +906,33 @@ uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
BX_INFO("%s: DATA_OUT not supported yet\n", __func__);
return 1;
}
-
+
// The header length must be even
if (header & 1) {
BX_DEBUG_ATA("%s: header must be even (%04x)\n", __func__, header);
return 1;
}
-
+
iobase1 = bios_dsk->channels[channel].iobase1;
iobase2 = bios_dsk->channels[channel].iobase2;
mode = bios_dsk->devices[device].mode;
transfer = 0L;
-
+
if (cmdlen < 12)
cmdlen = 12;
if (cmdlen > 12)
cmdlen = 16;
cmdlen >>= 1;
-
+
// Reset count of transferred data
// @todo: clear in calling code?
bios_dsk->drqp.trsfsectors = 0;
bios_dsk->drqp.trsfbytes = 0;
-
+
status = inb(iobase1 + ATA_CB_STAT);
if (status & ATA_CB_STAT_BSY)
return 2;
-
+
outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
// outb(iobase1 + ATA_CB_FR, 0x00);
// outb(iobase1 + ATA_CB_SC, 0x00);
@@ -958,14 +941,14 @@ uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
outb(iobase1 + ATA_CB_CH, 0xfff0 >> 8);
outb(iobase1 + ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
outb(iobase1 + ATA_CB_CMD, ATA_CMD_PACKET);
-
+
// Device should ok to receive command
while (1) {
status = inb(iobase1 + ATA_CB_STAT);
if ( !(status & ATA_CB_STAT_BSY) ) break;
}
-
- if (status & ATA_CB_STAT_ERR) {
+
+ if (status & ATA_CB_STAT_CHK) {
BX_DEBUG_ATA("%s: error, status is %02x\n", __func__, status);
// Enable interrupts
outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
@@ -976,59 +959,59 @@ uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
return 4;
}
-
+
int_enable(); // enable higher priority interrupts
-
+
// Normalize address
BX_DEBUG_ATA("acp1 buffer ptr: %04x:%04x wlen %04x\n", FP_SEG(cmdbuf), FP_OFF(cmdbuf), cmdlen);
cmdbuf = MK_FP(FP_SEG(cmdbuf) + FP_OFF(cmdbuf) / 16 , FP_OFF(cmdbuf) % 16);
// cmdseg += (cmdoff / 16);
// cmdoff %= 16;
-
+
// Send command to device
rep_outsw(cmdbuf, cmdlen, iobase1);
-
+
if (inout == ATA_DATA_NO) {
status = inb(iobase1 + ATA_CB_STAT);
}
else {
while (1) {
-
+
while (1) {
status = inb(iobase1 + ATA_CB_STAT);
- if ( !(status & ATA_CB_STAT_BSY) )
+ if ( !(status & ATA_CB_STAT_BSY) )
break;
}
-
+
// Check if command completed
if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ) ) ==0 )
break;
-
- if (status & ATA_CB_STAT_ERR) {
+
+ if (status & ATA_CB_STAT_CHK) {
BX_DEBUG_ATA("%s: error (status %02x)\n", __func__, status);
// Enable interrupts
outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
return 3;
}
-
+
// Device must be ready to send data
- if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
+ if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_CHK) )
!= (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
BX_DEBUG_ATA("%s: not ready (status %02x)\n", __func__, status);
// Enable interrupts
outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
return 4;
}
-
+
// Normalize address
BX_DEBUG_ATA("acp2 buffer ptr: %04x:%04x\n", FP_SEG(buffer), FP_OFF(buffer));
buffer = MK_FP(FP_SEG(buffer) + FP_OFF(buffer) / 16 , FP_OFF(buffer) % 16);
// bufseg += (bufoff / 16);
// bufoff %= 16;
-
+
// Get the byte count
lcount = ((uint16_t)(inb(iobase1 + ATA_CB_CH))<<8)+inb(iobase1 + ATA_CB_CL);
-
+
// adjust to read what we want
if (header>lcount) {
lbefore = lcount;
@@ -1040,7 +1023,7 @@ uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
header = 0;
lcount -= lbefore;
}
-
+
if (lcount>length) {
lafter = lcount - length;
lcount = length;
@@ -1050,13 +1033,13 @@ uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
lafter = 0;
length -= lcount;
}
-
+
// Save byte count
count = lcount;
-
+
BX_DEBUG_ATA("Trying to read %04x bytes (%04x %04x %04x) ",lbefore+lcount+lafter,lbefore,lcount,lafter);
BX_DEBUG_ATA("to 0x%04x:0x%04x\n",FP_SEG(buffer),FP_OFF(buffer));
-
+
// If counts not dividable by 4, use 16bits mode
lmode = mode;
if (lbefore & 0x03)
@@ -1065,7 +1048,7 @@ uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
lmode = ATA_MODE_PIO16;
if (lafter & 0x03)
lmode = ATA_MODE_PIO16;
-
+
// adds an extra byte if count are odd. before is always even
if (lcount & 0x01) {
lcount += 1;
@@ -1073,7 +1056,7 @@ uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
lafter -= 1;
}
}
-
+
if (lmode == ATA_MODE_PIO32) {
lcount >>= 2;
lbefore >>= 2;
@@ -1084,7 +1067,7 @@ uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
lbefore >>= 1;
lafter >>= 1;
}
-
+
if (lmode == ATA_MODE_PIO32) {
if (lbefore)
insd_discard(lbefore, iobase1);
@@ -1098,31 +1081,77 @@ uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
if (lafter)
insw_discard(lafter, iobase1);
}
-
-
+
+
// Compute new buffer address
buffer += count;
-
+
// Save transferred bytes count
transfer += count;
bios_dsk->drqp.trsfbytes = transfer;
}
}
-
+
// Final check, device must be ready
- if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
+ 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 ) {
BX_DEBUG_ATA("%s: not ready (status %02x)\n", __func__, (unsigned) status);
// Enable interrupts
outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
return 4;
}
-
+
// Enable interrupts
outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
return 0;
}
+// ---------------------------------------------------------------------------
+// ATA/ATAPI driver : reset device; intended for ATAPI devices
+// ---------------------------------------------------------------------------
+ // returns
+ // 0 : no error
+ // 1 : error
+uint16_t ata_soft_reset(uint16_t device)
+{
+ uint16_t iobase1, iobase2;
+ uint8_t channel, slave;
+ uint8_t status;
+ bio_dsk_t __far *bios_dsk;
+
+ bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
+
+ channel = device / 2;
+ slave = device % 2;
+
+ iobase1 = bios_dsk->channels[channel].iobase1;
+ iobase2 = bios_dsk->channels[channel].iobase2;
+
+ /* Send a reset command to the device. */
+ outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
+ outb(iobase1 + ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
+ outb(iobase1 + ATA_CB_CMD, ATA_CMD_DEVICE_RESET);
+
+ /* Wait for the device to clear BSY. */
+ while (1) {
+ status = inb(iobase1 + ATA_CB_STAT);
+ if ( !(status & ATA_CB_STAT_BSY) ) break;
+ }
+
+ /* Final check, device must be ready */
+ 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 ) {
+ BX_DEBUG_ATA("%s: not ready (status %02x)\n", __func__, (unsigned) status);
+ /* Enable interrupts */
+ outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15);
+ return 1;
+ }
+
+ /* Enable interrupts */
+ outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
+ return 0;
+}
+
// ---------------------------------------------------------------------------
// End of ATA/ATAPI Driver