grml...
[seabios.git] / src / block.c
index 818c9f9dc3b54c23114f19ca6ece1968a828cfbf..eeebd83b82091881d6ab65d59f90b4f5167c9886 100644 (file)
 #include "util.h" // dprintf
 #include "ata.h" // process_ata_op
 #include "ahci.h" // process_ahci_op
-#include "usb-msc.h" // process_usb_op
-#include "virtio-blk.h" // process_virtio_op
+#include "virtio-blk.h" // process_virtio_blk_op
+#include "blockcmd.h" // cdb_*
 
-struct drives_s Drives VAR16VISIBLE;
+u8 FloppyCount VAR16VISIBLE;
+u8 CDCount;
+struct drive_s *IDMap[3][CONFIG_MAX_EXTDRIVE] VAR16VISIBLE;
+u8 *bounce_buf_fl VAR16VISIBLE;
 
 struct drive_s *
 getDrive(u8 exttype, u8 extdriveoffset)
 {
-    if (extdriveoffset >= ARRAY_SIZE(Drives.idmap[0]))
+    if (extdriveoffset >= ARRAY_SIZE(IDMap[0]))
         return NULL;
-    struct drive_s *drive_gf = GET_GLOBAL(Drives.idmap[exttype][extdriveoffset]);
+    struct drive_s *drive_gf = GET_GLOBAL(IDMap[exttype][extdriveoffset]);
     if (!drive_gf)
         return NULL;
     return GLOBALFLAT2GLOBAL(drive_gf);
 }
 
+int getDriveId(u8 exttype, struct drive_s *drive_g)
+{
+    int i;
+    for (i = 0; i < ARRAY_SIZE(IDMap[0]); i++)
+        if (getDrive(exttype, i) == drive_g)
+            return i;
+    return -1;
+}
+
+int bounce_buf_init(void)
+{
+    if (bounce_buf_fl)
+        return 0;
+
+    u8 *buf = malloc_low(CDROM_SECTOR_SIZE);
+    if (!buf) {
+        warn_noalloc();
+        return -1;
+    }
+    bounce_buf_fl = buf;
+    return 0;
+}
 
 /****************************************************************
  * Disk geometry translation
@@ -63,7 +88,7 @@ get_translation(struct drive_s *drive_g)
     return TRANSLATION_LBA;
 }
 
-void
+static void
 setup_translation(struct drive_s *drive_g)
 {
     u8 translation = get_translation(drive_g);
@@ -190,52 +215,33 @@ fill_fdpt(struct drive_s *drive_g, int hdid)
                                  struct extended_bios_data_area_s, fdpt[1])));
 }
 
-// Map a drive (that was registered via add_bcv_hd)
-void
-map_hd_drive(struct drive_s *drive_g)
-{
-    // fill hdidmap
-    u8 hdcount = GET_BDA(hdcount);
-    if (hdcount >= ARRAY_SIZE(Drives.idmap[0])) {
-        warn_noalloc();
-        return;
-    }
-    dprintf(3, "Mapping hd drive %p to %d\n", drive_g, hdcount);
-    Drives.idmap[EXTTYPE_HD][hdcount] = drive_g;
-    SET_BDA(hdcount, hdcount + 1);
-
-    // Fill "fdpt" structure.
-    fill_fdpt(drive_g, hdcount);
-}
-
 // Find spot to add a drive
 static void
-add_ordered_drive(struct drive_s **idmap, u8 *count, struct drive_s *drive_g)
+add_drive(struct drive_s **idmap, u8 *count, struct drive_s *drive_g)
 {
-    if (*count >= ARRAY_SIZE(Drives.idmap[0])) {
+    if (*count >= ARRAY_SIZE(IDMap[0])) {
         warn_noalloc();
         return;
     }
-    struct drive_s **pos = &idmap[*count];
+    idmap[*count] = drive_g;
     *count = *count + 1;
-    if (CONFIG_THREADS) {
-        // Add to idmap with assured drive order.
-        struct drive_s **end = pos;
-        for (;;) {
-            struct drive_s **prev = pos - 1;
-            if (prev < idmap)
-                break;
-            struct drive_s *prevdrive = *prev;
-            if (prevdrive->type < drive_g->type
-                || (prevdrive->type == drive_g->type
-                    && prevdrive->cntl_id < drive_g->cntl_id))
-                break;
-            pos--;
-        }
-        if (pos != end)
-            memmove(pos+1, pos, (void*)end-(void*)pos);
-    }
-    *pos = drive_g;
+}
+
+// Map a hard drive
+void
+map_hd_drive(struct drive_s *drive_g)
+{
+    ASSERT32FLAT();
+    struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0);
+    int hdid = bda->hdcount;
+    dprintf(3, "Mapping hd drive %p to %d\n", drive_g, hdid);
+    add_drive(IDMap[EXTTYPE_HD], &bda->hdcount, drive_g);
+
+    // Setup disk geometry translation.
+    setup_translation(drive_g);
+
+    // Fill "fdpt" structure.
+    fill_fdpt(drive_g, hdid);
 }
 
 // Map a cd
@@ -243,24 +249,22 @@ void
 map_cd_drive(struct drive_s *drive_g)
 {
     dprintf(3, "Mapping cd drive %p\n", drive_g);
-    add_ordered_drive(Drives.idmap[EXTTYPE_CD], &Drives.cdcount, drive_g);
+    add_drive(IDMap[EXTTYPE_CD], &CDCount, drive_g);
 }
 
 // Map a floppy
 void
 map_floppy_drive(struct drive_s *drive_g)
 {
-    // fill idmap
     dprintf(3, "Mapping floppy drive %p\n", drive_g);
-    add_ordered_drive(Drives.idmap[EXTTYPE_FLOPPY], &Drives.floppycount
-                      , drive_g);
+    add_drive(IDMap[EXTTYPE_FLOPPY], &FloppyCount, drive_g);
 
     // Update equipment word bits for floppy
-    if (Drives.floppycount == 1) {
+    if (FloppyCount == 1) {
         // 1 drive, ready for boot
         SETBITS_BDA(equipment_list_flags, 0x01);
         SET_BDA(floppy_harddisk_info, 0x07);
-    } else if (Drives.floppycount >= 2) {
+    } else if (FloppyCount >= 2) {
         // 2 drives, ready for boot
         SETBITS_BDA(equipment_list_flags, 0x41);
         SET_BDA(floppy_harddisk_info, 0x77);
@@ -272,6 +276,28 @@ map_floppy_drive(struct drive_s *drive_g)
  * 16bit calling interface
  ****************************************************************/
 
+int
+process_scsi_op(struct disk_op_s *op)
+{
+    if (!CONFIG_USB_MSC)
+        return 0;
+    switch (op->command) {
+    case CMD_READ:
+        return cdb_read(op);
+    case CMD_WRITE:
+        return cdb_write(op);
+    case CMD_FORMAT:
+    case CMD_RESET:
+    case CMD_ISREADY:
+    case CMD_VERIFY:
+    case CMD_SEEK:
+        return DISK_RET_SUCCESS;
+    default:
+        op->count = 0;
+        return DISK_RET_EPARAM;
+    }
+}
+
 // Execute a disk_op request.
 int
 process_op(struct disk_op_s *op)
@@ -289,12 +315,12 @@ process_op(struct disk_op_s *op)
         return process_ramdisk_op(op);
     case DTYPE_CDEMU:
         return process_cdemu_op(op);
-    case DTYPE_USB:
-        return process_usb_op(op);
-    case DTYPE_VIRTIO:
-       return process_virtio_op(op);
+    case DTYPE_VIRTIO_BLK:
+        return process_virtio_blk_op(op);
     case DTYPE_AHCI:
        return process_ahci_op(op);
+    case DTYPE_USB:
+        return process_scsi_op(op);
     default:
         op->count = 0;
         return DISK_RET_EPARAM;