[SeaBIOS] [PATCH 1/8] Dynamically allocate each drive_g with malloc_fseg().

Kevin O'Connor kevin at koconnor.net
Thu Feb 18 05:39:51 CET 2010


This eliminates the limit on the number of available drives.  It also
allows for each driver to allocate additional custom fields.
---
 src/ata.c     |   14 ++++++++++----
 src/biosvar.h |    6 ++++--
 src/block.c   |   46 +++++++++++++---------------------------------
 src/boot.c    |    2 +-
 src/cdrom.c   |   10 ++++++----
 src/config.h  |    4 +---
 src/disk.h    |   11 +++--------
 src/floppy.c  |    7 +++++--
 8 files changed, 43 insertions(+), 57 deletions(-)

diff --git a/src/ata.c b/src/ata.c
index a27da56..f935e1f 100644
--- a/src/ata.c
+++ b/src/ata.c
@@ -775,9 +775,12 @@ init_drive_atapi(struct drive_s *dummy, u16 *buffer)
         return NULL;
 
     // Success - setup as ATAPI.
-    struct drive_s *drive_g = allocDrive();
-    if (! drive_g)
+    struct drive_s *drive_g = malloc_fseg(sizeof(*drive_g));
+    if (! drive_g) {
+        warn_noalloc();
         return NULL;
+    }
+    memset(drive_g, 0, sizeof(*drive_g));
     SET_GLOBAL(drive_g->cntl_id, dummy->cntl_id);
     extract_identify(drive_g, buffer);
     SET_GLOBAL(drive_g->type, DTYPE_ATAPI);
@@ -821,9 +824,12 @@ init_drive_ata(struct drive_s *dummy, u16 *buffer)
         return NULL;
 
     // Success - setup as ATA.
-    struct drive_s *drive_g = allocDrive();
-    if (! drive_g)
+    struct drive_s *drive_g = malloc_fseg(sizeof(*drive_g));
+    if (! drive_g) {
+        warn_noalloc();
         return NULL;
+    }
+    memset(drive_g, 0, sizeof(*drive_g));
     SET_GLOBAL(drive_g->cntl_id, dummy->cntl_id);
     extract_identify(drive_g, buffer);
     SET_GLOBAL(drive_g->type, DTYPE_ATA);
diff --git a/src/biosvar.h b/src/biosvar.h
index d011966..c67503c 100644
--- a/src/biosvar.h
+++ b/src/biosvar.h
@@ -329,9 +329,11 @@ static inline u16 get_global_seg(void) {
         (var) = (val);                          \
     } while (0)
 #if MODESEGMENT
-#define ADJUST_GLOBAL_PTR(var) (var)
+#define STORE_GLOBAL_PTR(var) (var)
+#define RETRIEVE_GLOBAL_PTR(var) (var)
 #else
-#define ADJUST_GLOBAL_PTR(var) ((typeof(var))((void*)var - BUILD_BIOS_ADDR))
+#define STORE_GLOBAL_PTR(var) ((typeof(var))((void*)var - BUILD_BIOS_ADDR))
+#define RETRIEVE_GLOBAL_PTR(var) ((typeof(var))((void*)var + BUILD_BIOS_ADDR))
 #endif
 
 
diff --git a/src/block.c b/src/block.c
index 3a9a68d..63aa368 100644
--- a/src/block.c
+++ b/src/block.c
@@ -16,30 +16,9 @@ struct drives_s Drives VAR16VISIBLE;
 struct drive_s *
 getDrive(u8 exttype, u8 extdriveoffset)
 {
-    // basic check : device has to be defined
     if (extdriveoffset >= ARRAY_SIZE(Drives.idmap[0]))
         return NULL;
-
-    // Get the ata channel
-    u8 driveid = GET_GLOBAL(Drives.idmap[exttype][extdriveoffset]);
-
-    // basic check : device has to be valid
-    if (driveid >= ARRAY_SIZE(Drives.drives))
-        return NULL;
-
-    return &Drives.drives[driveid];
-}
-
-struct drive_s *
-allocDrive(void)
-{
-    int driveid = Drives.drivecount;
-    if (driveid >= ARRAY_SIZE(Drives.drives))
-        return NULL;
-    Drives.drivecount++;
-    struct drive_s *drive_g = &Drives.drives[driveid];
-    memset(drive_g, 0, sizeof(*drive_g));
-    return drive_g;
+    return RETRIEVE_GLOBAL_PTR(GET_GLOBAL(Drives.idmap[exttype][extdriveoffset]));
 }
 
 
@@ -208,11 +187,12 @@ map_hd_drive(struct drive_s *drive_g)
 {
     // fill hdidmap
     u8 hdcount = GET_BDA(hdcount);
-    if (hdcount >= ARRAY_SIZE(Drives.idmap[0]))
+    if (hdcount >= ARRAY_SIZE(Drives.idmap[0])) {
+        warn_noalloc();
         return;
+    }
     dprintf(3, "Mapping hd drive %p to %d\n", drive_g, hdcount);
-    int driveid = drive_g - Drives.drives;
-    SET_GLOBAL(Drives.idmap[EXTTYPE_HD][hdcount], driveid);
+    Drives.idmap[EXTTYPE_HD][hdcount] = STORE_GLOBAL_PTR(drive_g);
     SET_BDA(hdcount, hdcount + 1);
 
     // Fill "fdpt" structure.
@@ -221,22 +201,22 @@ map_hd_drive(struct drive_s *drive_g)
 
 // Find spot to add a drive
 static void
-add_ordered_drive(u8 *idmap, u8 *count, struct drive_s *drive_g)
+add_ordered_drive(struct drive_s **idmap, u8 *count, struct drive_s *drive_g)
 {
     if (*count >= ARRAY_SIZE(Drives.idmap[0])) {
         warn_noalloc();
         return;
     }
-    u8 *pos = &idmap[*count];
+    struct drive_s **pos = &idmap[*count];
     *count = *count + 1;
     if (CONFIG_THREADS) {
         // Add to idmap with assured drive order.
-        u8 *end = pos;
+        struct drive_s **end = pos;
         for (;;) {
-            u8 *prev = pos - 1;
+            struct drive_s **prev = pos - 1;
             if (prev < idmap)
                 break;
-            struct drive_s *prevdrive = &Drives.drives[*prev];
+            struct drive_s *prevdrive = *prev;
             if (prevdrive->type < drive_g->type
                 || (prevdrive->type == drive_g->type
                     && prevdrive->cntl_id < drive_g->cntl_id))
@@ -246,7 +226,7 @@ add_ordered_drive(u8 *idmap, u8 *count, struct drive_s *drive_g)
         if (pos != end)
             memmove(pos+1, pos, (void*)end-(void*)pos);
     }
-    *pos = drive_g - Drives.drives;
+    *pos = STORE_GLOBAL_PTR(drive_g);
 }
 
 // Map a cd
@@ -312,6 +292,7 @@ describe_drive(struct drive_s *drive_g)
 int
 process_op(struct disk_op_s *op)
 {
+    ASSERT16();
     u8 type = GET_GLOBAL(op->drive_g->type);
     switch (type) {
     case DTYPE_FLOPPY:
@@ -355,9 +336,9 @@ __send_disk_op(struct disk_op_s *op_far, u16 op_seg)
 int
 send_disk_op(struct disk_op_s *op)
 {
+    ASSERT16();
     if (! CONFIG_DRIVES)
         return -1;
-    ASSERT16();
 
     return stack_hop((u32)op, GET_SEG(SS), 0, __send_disk_op);
 }
@@ -371,5 +352,4 @@ void
 drive_setup(void)
 {
     memset(&Drives, 0, sizeof(Drives));
-    memset(&Drives.idmap, 0xff, sizeof(Drives.idmap));
 }
diff --git a/src/boot.c b/src/boot.c
index 151b0d3..6b69dc2 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -321,7 +321,7 @@ boot_prep(void)
 
     // Setup floppy boot order
     int override = IPL.bev[0].subchoice;
-    int tmp = Drives.idmap[EXTTYPE_FLOPPY][0];
+    struct drive_s *tmp = Drives.idmap[EXTTYPE_FLOPPY][0];
     Drives.idmap[EXTTYPE_FLOPPY][0] = Drives.idmap[EXTTYPE_FLOPPY][override];
     Drives.idmap[EXTTYPE_FLOPPY][override] = tmp;
 
diff --git a/src/cdrom.c b/src/cdrom.c
index 4e70729..06adefa 100644
--- a/src/cdrom.c
+++ b/src/cdrom.c
@@ -113,12 +113,14 @@ cdemu_setup(void)
     if (!CONFIG_CDROM_EMU)
         return;
 
-    struct drive_s *drive_g = allocDrive();
-    if (!drive_g) {
+    struct drive_s *drive_g = malloc_fseg(sizeof(*drive_g));
+    if (! drive_g) {
+        warn_noalloc();
         cdemu_drive = NULL;
         return;
     }
-    cdemu_drive = ADJUST_GLOBAL_PTR(drive_g);
+    memset(drive_g, 0, sizeof(*drive_g));
+    cdemu_drive = STORE_GLOBAL_PTR(drive_g);
     drive_g->type = DTYPE_CDEMU;
     drive_g->blksize = DISK_SECTOR_SIZE;
     drive_g->sectors = (u64)-1;
@@ -327,7 +329,7 @@ cdrom_boot(int cdid)
     u8 media = buffer[0x21];
     SET_EBDA2(ebda_seg, cdemu.media, media);
 
-    SET_EBDA2(ebda_seg, cdemu.emulated_drive, ADJUST_GLOBAL_PTR(dop.drive_g));
+    SET_EBDA2(ebda_seg, cdemu.emulated_drive, STORE_GLOBAL_PTR(dop.drive_g));
 
     u16 boot_segment = *(u16*)&buffer[0x22];
     if (!boot_segment)
diff --git a/src/config.h b/src/config.h
index c02d496..e359652 100644
--- a/src/config.h
+++ b/src/config.h
@@ -119,15 +119,13 @@
 #define CONFIG_USE_SMM 1
 // Maximum number of map entries in the e820 map
 #define CONFIG_MAX_E820 32
-// Space to reserve in f-segment for run-time built bios tables.
+// Space to reserve in f-segment for dynamic allocations
 #define CONFIG_MAX_BIOSTABLE 2048
 // Space to reserve in high-memory for tables
 #define CONFIG_MAX_HIGHTABLE (64*1024)
 
 // Maximum number of ATA controllers to support
 #define CONFIG_MAX_ATA_INTERFACES 4
-// Maximum number of internal drives supported
-#define CONFIG_MAX_DRIVES 8
 // Largest supported externaly facing drive id
 #define CONFIG_MAX_EXTDRIVE 16
 
diff --git a/src/disk.h b/src/disk.h
index ac5748e..635d511 100644
--- a/src/disk.h
+++ b/src/disk.h
@@ -173,7 +173,7 @@ struct chs_s {
 };
 
 struct drive_s {
-    u8  type;         // Detected type of drive (ata/atapi/none)
+    u8  type;         // Driver type (DTYPE_*)
     u8  removable;    // Removable device flag
     u16 blksize;      // block size
     u32 cntl_id;
@@ -205,14 +205,10 @@ struct drive_s {
 #define TRANSLATION_RECHS 3
 
 struct drives_s {
-    // info on each internally handled drive
-    struct drive_s drives[CONFIG_MAX_DRIVES];
-    u8 drivecount;
-    //
-    // map between bios floppy/hd/cd id and driveid index into drives[]
+    // map between bios floppy/hd/cd id and drive_s struct
     u8 floppycount;
     u8 cdcount;
-    u8 idmap[3][CONFIG_MAX_EXTDRIVE];
+    struct drive_s *idmap[3][CONFIG_MAX_EXTDRIVE];
 };
 
 #define EXTTYPE_FLOPPY 0
@@ -230,7 +226,6 @@ struct drives_s {
 // block.c
 extern struct drives_s Drives;
 struct drive_s *getDrive(u8 exttype, u8 extdriveoffset);
-struct drive_s *allocDrive(void);
 void setup_translation(struct drive_s *drive_g);
 void map_floppy_drive(struct drive_s *drive_g);
 void map_hd_drive(struct drive_s *drive_g);
diff --git a/src/floppy.c b/src/floppy.c
index dba3e00..d2e689c 100644
--- a/src/floppy.c
+++ b/src/floppy.c
@@ -96,9 +96,12 @@ addFloppy(int floppyid, int ftype, int driver)
         return NULL;
     }
 
-    struct drive_s *drive_g = allocDrive();
-    if (!drive_g)
+    struct drive_s *drive_g = malloc_fseg(sizeof(*drive_g));
+    if (!drive_g) {
+        warn_noalloc();
         return NULL;
+    }
+    memset(drive_g, 0, sizeof(*drive_g));
     drive_g->cntl_id = floppyid;
     drive_g->type = driver;
     drive_g->blksize = DISK_SECTOR_SIZE;
-- 
1.6.6




More information about the SeaBIOS mailing list