Provide full EDD 3.0 info for virtio disk
authorGleb Natapov <gleb@redhat.com>
Thu, 23 Dec 2010 09:29:35 +0000 (11:29 +0200)
committerKevin O'Connor <kevin@koconnor.net>
Fri, 24 Dec 2010 15:33:17 +0000 (10:33 -0500)
Fill out entire EDD 3.0 structure for virtio disk. Currently only EDD 1.0
part is filled which is missing such important info as device path. Use
SCSI device type since virtio is not defined by EDD spec and virtio disk pci
device uses SCSI class.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
src/disk.c

index 242c74235f4cbc4a670d647f91e19c4b6594d31a..56c369ae2112c3302250922254a3a8af9753732f 100644 (file)
@@ -544,64 +544,78 @@ disk_1348(struct bregs *regs, struct drive_s *drive_g)
     }
     SET_INT13DPT(regs, blksize, blksize);
 
-    if (size < 30 || (type != DTYPE_ATA && type != DTYPE_ATAPI)) {
+    if (size < 30 ||
+        (type != DTYPE_ATA && type != DTYPE_ATAPI && type != DTYPE_VIRTIO)) {
         disk_ret(regs, DISK_RET_SUCCESS);
         return;
     }
 
     // EDD 2.x
 
-    u16 ebda_seg = get_ebda_seg();
+    int bdf;
+    u16 iobase1;
+    u64 device_path;
     SET_INT13DPT(regs, size, 30);
+    if (type == DTYPE_ATA || type == DTYPE_ATAPI) {
+        u16 ebda_seg = get_ebda_seg();
 
-    SET_INT13DPT(regs, dpte_segment, ebda_seg);
-    SET_INT13DPT(regs, dpte_offset
-                 , offsetof(struct extended_bios_data_area_s, dpte));
-
-    // Fill in dpte
-    struct atadrive_s *adrive_g = container_of(
-        drive_g, struct atadrive_s, drive);
-    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
-    u8 slave = GET_GLOBAL(adrive_g->slave);
-    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
-    u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);
-    u8 irq = GET_GLOBALFLAT(chan_gf->irq);
-
-    u16 options = 0;
-    if (type == DTYPE_ATA) {
-        u8 translation = GET_GLOBAL(drive_g->translation);
-        if (translation != TRANSLATION_NONE) {
-            options |= 1<<3; // CHS translation
-            if (translation == TRANSLATION_LBA)
-                options |= 1<<9;
-            if (translation == TRANSLATION_RECHS)
-                options |= 3<<9;
+        SET_INT13DPT(regs, dpte_segment, ebda_seg);
+        SET_INT13DPT(regs, dpte_offset
+                     , offsetof(struct extended_bios_data_area_s, dpte));
+
+        // Fill in dpte
+        struct atadrive_s *adrive_g = container_of(
+            drive_g, struct atadrive_s, drive);
+        struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
+        u8 slave = GET_GLOBAL(adrive_g->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;
+
+        u16 options = 0;
+        if (type == DTYPE_ATA) {
+            u8 translation = GET_GLOBAL(drive_g->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_EBDA2(ebda_seg, dpte.iobase1, iobase1);
+        SET_EBDA2(ebda_seg, dpte.iobase2, iobase2 + ATA_CB_DC);
+        SET_EBDA2(ebda_seg, dpte.prefix, ((slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0)
+                                          | ATA_CB_DH_LBA));
+        SET_EBDA2(ebda_seg, dpte.unused, 0xcb);
+        SET_EBDA2(ebda_seg, dpte.irq, irq);
+        SET_EBDA2(ebda_seg, dpte.blkcount, 1);
+        SET_EBDA2(ebda_seg, dpte.dma, 0);
+        SET_EBDA2(ebda_seg, dpte.pio, 0);
+        SET_EBDA2(ebda_seg, dpte.options, options);
+        SET_EBDA2(ebda_seg, dpte.reserved, 0);
+        SET_EBDA2(ebda_seg, dpte.revision, 0x11);
+
+        u8 sum = checksum_far(
+            ebda_seg, (void*)offsetof(struct extended_bios_data_area_s, dpte), 15);
+        SET_EBDA2(ebda_seg, dpte.checksum, -sum);
     } else {
-        // ATAPI
-        options |= 1<<5; // removable device
-        options |= 1<<6; // atapi device
+        SET_INT13DPT(regs, dpte_segment, 0);
+        SET_INT13DPT(regs, dpte_offset, 0);
+        bdf = GET_GLOBAL(drive_g->cntl_id);
+        device_path = 0;
+        iobase1 = 0;
     }
-    options |= 1<<4; // lba translation
-    if (CONFIG_ATA_PIO32)
-        options |= 1<<7;
-
-    SET_EBDA2(ebda_seg, dpte.iobase1, iobase1);
-    SET_EBDA2(ebda_seg, dpte.iobase2, iobase2 + ATA_CB_DC);
-    SET_EBDA2(ebda_seg, dpte.prefix, ((slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0)
-                                      | ATA_CB_DH_LBA));
-    SET_EBDA2(ebda_seg, dpte.unused, 0xcb);
-    SET_EBDA2(ebda_seg, dpte.irq, irq);
-    SET_EBDA2(ebda_seg, dpte.blkcount, 1);
-    SET_EBDA2(ebda_seg, dpte.dma, 0);
-    SET_EBDA2(ebda_seg, dpte.pio, 0);
-    SET_EBDA2(ebda_seg, dpte.options, options);
-    SET_EBDA2(ebda_seg, dpte.reserved, 0);
-    SET_EBDA2(ebda_seg, dpte.revision, 0x11);
-
-    u8 sum = checksum_far(
-        ebda_seg, (void*)offsetof(struct extended_bios_data_area_s, dpte), 15);
-    SET_EBDA2(ebda_seg, dpte.checksum, -sum);
 
     if (size < 66) {
         disk_ret(regs, DISK_RET_SUCCESS);
@@ -614,7 +628,6 @@ disk_1348(struct bregs *regs, struct drive_s *drive_g)
     SET_INT13DPT(regs, reserved1, 0);
     SET_INT13DPT(regs, reserved2, 0);
 
-    int bdf = GET_GLOBALFLAT(chan_gf->pci_bdf);
     if (bdf != -1) {
         SET_INT13DPT(regs, host_bus[0], 'P');
         SET_INT13DPT(regs, host_bus[1], 'C');
@@ -634,16 +647,23 @@ disk_1348(struct bregs *regs, struct drive_s *drive_g)
         SET_INT13DPT(regs, iface_path, iobase1);
     }
 
-    SET_INT13DPT(regs, iface_type[0], 'A');
-    SET_INT13DPT(regs, iface_type[1], 'T');
-    SET_INT13DPT(regs, iface_type[2], 'A');
-    SET_INT13DPT(regs, iface_type[3], 0);
+    if (type != DTYPE_VIRTIO) {
+        SET_INT13DPT(regs, iface_type[0], 'A');
+        SET_INT13DPT(regs, iface_type[1], 'T');
+        SET_INT13DPT(regs, iface_type[2], 'A');
+        SET_INT13DPT(regs, iface_type[3], 0);
+    } else {
+        SET_INT13DPT(regs, iface_type[0], 'S');
+        SET_INT13DPT(regs, iface_type[1], 'C');
+        SET_INT13DPT(regs, iface_type[2], 'S');
+        SET_INT13DPT(regs, iface_type[3], 'I');
+    }
     SET_INT13DPT(regs, iface_type[4], 0);
     SET_INT13DPT(regs, iface_type[5], 0);
     SET_INT13DPT(regs, iface_type[6], 0);
     SET_INT13DPT(regs, iface_type[7], 0);
 
-    SET_INT13DPT(regs, device_path, slave);
+    SET_INT13DPT(regs, device_path, device_path);
 
     SET_INT13DPT(regs, checksum
                  , -checksum_far(regs->ds, (void*)(regs->si+30), 35));