summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2014-05-10 12:46:57 -0400
committerKevin O'Connor <kevin@koconnor.net>2014-06-04 11:06:58 -0400
commit9e735bbd1d45b41319bb27358c3d2e8079c9786a (patch)
tree42dcfe04372c03356d982af2f03f9b5a26262911
parentf8387e2a9953b760d6d02d8f682d48616eb7f165 (diff)
downloadqemu-seabios-9e735bbd1d45b41319bb27358c3d2e8079c9786a.tar.gz
edd: Separate out ATA and virtio specific parts of fill_edd().
This also changes DTYPE_VIRTIO_SCSI drives to report that they are using a "SCSI" bus instead of an "ATA" bus - it was obviously incorrect before. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
-rw-r--r--src/block.c169
1 files changed, 88 insertions, 81 deletions
diff --git a/src/block.c b/src/block.c
index 4bec603..aff263c 100644
--- a/src/block.c
+++ b/src/block.c
@@ -25,7 +25,6 @@ u8 FloppyCount VARFSEG;
u8 CDCount;
struct drive_s *IDMap[3][BUILD_MAX_EXTDRIVE] VARFSEG;
u8 *bounce_buf_fl VARFSEG;
-struct dpte_s DefaultDPTE VARLOW;
struct drive_s *
getDrive(u8 exttype, u8 extdriveoffset)
@@ -314,8 +313,10 @@ __disk_ret_unimplemented(struct bregs *regs, u32 linecode, const char *fname)
* Extended Disk Drive (EDD) get drive parameters
****************************************************************/
-int noinline
-fill_edd(u16 seg, struct int13dpt_s *param_far, struct drive_s *drive_gf)
+static int
+fill_generic_edd(u16 seg, struct int13dpt_s *param_far, struct drive_s *drive_gf
+ , u32 dpte_so, char *iface_type
+ , int bdf, u8 channel, u16 iobase, u64 device_path)
{
u16 size = GET_FARVAR(seg, param_far->size);
u16 t13 = size == 74;
@@ -357,73 +358,15 @@ fill_edd(u16 seg, struct int13dpt_s *param_far, struct drive_s *drive_gf)
SET_FARVAR(seg, param_far->sector_count, lba);
SET_FARVAR(seg, param_far->blksize, blksize);
- if (size < 30 ||
- (type != DTYPE_ATA && type != DTYPE_ATA_ATAPI &&
- type != DTYPE_VIRTIO_BLK && type != DTYPE_VIRTIO_SCSI))
+ if (size < 30 || !dpte_so)
return DISK_RET_SUCCESS;
// EDD 2.x
- int bdf;
- u16 iobase1 = 0;
- u64 device_path = 0;
- u8 channel = 0;
SET_FARVAR(seg, param_far->size, 30);
- if (type == DTYPE_ATA || type == DTYPE_ATA_ATAPI) {
- SET_FARVAR(seg, param_far->dpte, SEGOFF(SEG_LOW, (u32)&DefaultDPTE));
-
- // Fill in dpte
- struct atadrive_s *adrive_gf = container_of(
- drive_gf, struct atadrive_s, drive);
- struct ata_channel_s *chan_gf = GET_GLOBALFLAT(adrive_gf->chan_gf);
- u8 slave = GET_GLOBALFLAT(adrive_gf->slave);
- u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);
- u8 irq = GET_GLOBALFLAT(chan_gf->irq);
- iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
- bdf = GET_GLOBALFLAT(chan_gf->pci_bdf);
- device_path = slave;
- channel = GET_GLOBALFLAT(chan_gf->chanid);
-
- u16 options = 0;
- if (type == DTYPE_ATA) {
- u8 translation = GET_GLOBALFLAT(drive_gf->translation);
- if (translation != TRANSLATION_NONE) {
- options |= 1<<3; // CHS translation
- if (translation == TRANSLATION_LBA)
- options |= 1<<9;
- if (translation == TRANSLATION_RECHS)
- options |= 3<<9;
- }
- } else {
- // ATAPI
- options |= 1<<5; // removable device
- options |= 1<<6; // atapi device
- }
- options |= 1<<4; // lba translation
- if (CONFIG_ATA_PIO32)
- options |= 1<<7;
-
- SET_LOW(DefaultDPTE.iobase1, iobase1);
- SET_LOW(DefaultDPTE.iobase2, iobase2 + ATA_CB_DC);
- SET_LOW(DefaultDPTE.prefix, ((slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0)
- | ATA_CB_DH_LBA));
- SET_LOW(DefaultDPTE.unused, 0xcb);
- SET_LOW(DefaultDPTE.irq, irq);
- SET_LOW(DefaultDPTE.blkcount, 1);
- SET_LOW(DefaultDPTE.dma, 0);
- SET_LOW(DefaultDPTE.pio, 0);
- SET_LOW(DefaultDPTE.options, options);
- SET_LOW(DefaultDPTE.reserved, 0);
- SET_LOW(DefaultDPTE.revision, 0x11);
-
- u8 sum = checksum_far(SEG_LOW, &DefaultDPTE, 15);
- SET_LOW(DefaultDPTE.checksum, -sum);
- } else {
- SET_FARVAR(seg, param_far->dpte.segoff, 0xffffffff);
- bdf = GET_GLOBALFLAT(drive_gf->cntl_id);
- }
+ SET_FARVAR(seg, param_far->dpte.segoff, dpte_so);
- if (size < 66)
+ if (size < 66 || !iface_type)
return DISK_RET_SUCCESS;
// EDD 3.x
@@ -432,6 +375,10 @@ fill_edd(u16 seg, struct int13dpt_s *param_far, struct drive_s *drive_gf)
SET_FARVAR(seg, param_far->reserved1, 0);
SET_FARVAR(seg, param_far->reserved2, 0);
+ int i;
+ for (i=0; i<sizeof(param_far->iface_type); i++)
+ SET_FARVAR(seg, param_far->iface_type[i], GET_GLOBAL(iface_type[i]));
+
if (bdf != -1) {
SET_FARVAR(seg, param_far->host_bus[0], 'P');
SET_FARVAR(seg, param_far->host_bus[1], 'C');
@@ -451,25 +398,9 @@ fill_edd(u16 seg, struct int13dpt_s *param_far, struct drive_s *drive_gf)
SET_FARVAR(seg, param_far->host_bus[2], 'A');
SET_FARVAR(seg, param_far->host_bus[3], ' ');
- SET_FARVAR(seg, param_far->iface_path, iobase1);
+ SET_FARVAR(seg, param_far->iface_path, iobase);
}
- if (type != DTYPE_VIRTIO_BLK) {
- SET_FARVAR(seg, param_far->iface_type[0], 'A');
- SET_FARVAR(seg, param_far->iface_type[1], 'T');
- SET_FARVAR(seg, param_far->iface_type[2], 'A');
- SET_FARVAR(seg, param_far->iface_type[3], ' ');
- } else {
- SET_FARVAR(seg, param_far->iface_type[0], 'S');
- SET_FARVAR(seg, param_far->iface_type[1], 'C');
- SET_FARVAR(seg, param_far->iface_type[2], 'S');
- SET_FARVAR(seg, param_far->iface_type[3], 'I');
- }
- SET_FARVAR(seg, param_far->iface_type[4], ' ');
- SET_FARVAR(seg, param_far->iface_type[5], ' ');
- SET_FARVAR(seg, param_far->iface_type[6], ' ');
- SET_FARVAR(seg, param_far->iface_type[7], ' ');
-
if (t13) {
SET_FARVAR(seg, param_far->t13.device_path[0], device_path);
SET_FARVAR(seg, param_far->t13.device_path[1], 0);
@@ -486,6 +417,82 @@ fill_edd(u16 seg, struct int13dpt_s *param_far, struct drive_s *drive_gf)
return DISK_RET_SUCCESS;
}
+struct dpte_s DefaultDPTE VARLOW;
+
+static int
+fill_ata_edd(u16 seg, struct int13dpt_s *param_far, struct drive_s *drive_gf)
+{
+ if (!CONFIG_ATA)
+ return DISK_RET_EPARAM;
+
+ // Fill in dpte
+ struct atadrive_s *adrive_gf = container_of(
+ drive_gf, struct atadrive_s, drive);
+ struct ata_channel_s *chan_gf = GET_GLOBALFLAT(adrive_gf->chan_gf);
+ u8 slave = GET_GLOBALFLAT(adrive_gf->slave);
+ u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);
+ u8 irq = GET_GLOBALFLAT(chan_gf->irq);
+ u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
+ int bdf = GET_GLOBALFLAT(chan_gf->pci_bdf);
+ u8 channel = GET_GLOBALFLAT(chan_gf->chanid);
+
+ u16 options = 0;
+ if (GET_GLOBALFLAT(drive_gf->type) == DTYPE_ATA) {
+ u8 translation = GET_GLOBALFLAT(drive_gf->translation);
+ if (translation != TRANSLATION_NONE) {
+ options |= 1<<3; // CHS translation
+ if (translation == TRANSLATION_LBA)
+ options |= 1<<9;
+ if (translation == TRANSLATION_RECHS)
+ options |= 3<<9;
+ }
+ } else {
+ // ATAPI
+ options |= 1<<5; // removable device
+ options |= 1<<6; // atapi device
+ }
+ options |= 1<<4; // lba translation
+ if (CONFIG_ATA_PIO32)
+ options |= 1<<7;
+
+ SET_LOW(DefaultDPTE.iobase1, iobase1);
+ SET_LOW(DefaultDPTE.iobase2, iobase2 + ATA_CB_DC);
+ SET_LOW(DefaultDPTE.prefix, ((slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0)
+ | ATA_CB_DH_LBA));
+ SET_LOW(DefaultDPTE.unused, 0xcb);
+ SET_LOW(DefaultDPTE.irq, irq);
+ SET_LOW(DefaultDPTE.blkcount, 1);
+ SET_LOW(DefaultDPTE.dma, 0);
+ SET_LOW(DefaultDPTE.pio, 0);
+ SET_LOW(DefaultDPTE.options, options);
+ SET_LOW(DefaultDPTE.reserved, 0);
+ SET_LOW(DefaultDPTE.revision, 0x11);
+
+ u8 sum = checksum_far(SEG_LOW, &DefaultDPTE, 15);
+ SET_LOW(DefaultDPTE.checksum, -sum);
+
+ return fill_generic_edd(
+ seg, param_far, drive_gf, SEGOFF(SEG_LOW, (u32)&DefaultDPTE).segoff
+ , "ATA ", bdf, channel, iobase1, slave);
+}
+
+int noinline
+fill_edd(u16 seg, struct int13dpt_s *param_far, struct drive_s *drive_gf)
+{
+ switch (GET_GLOBALFLAT(drive_gf->type)) {
+ case DTYPE_ATA:
+ case DTYPE_ATA_ATAPI:
+ return fill_ata_edd(seg, param_far, drive_gf);
+ case DTYPE_VIRTIO_BLK:
+ case DTYPE_VIRTIO_SCSI:
+ return fill_generic_edd(
+ seg, param_far, drive_gf, 0xffffffff
+ , "SCSI ", GET_GLOBALFLAT(drive_gf->cntl_id), 0, 0, 0);
+ default:
+ return fill_generic_edd(seg, param_far, drive_gf, 0, NULL, 0, 0, 0, 0);
+ }
+}
+
/****************************************************************
* 16bit calling interface