[memdisk] Add disk probing code to support a drive shifting limit
authorShao Miller <shao.miller@yrdsb.edu.on.ca>
Sat, 1 Aug 2009 05:07:50 +0000 (01:07 -0400)
committerShao Miller <shao.miller@yrdsb.edu.on.ca>
Tue, 4 Aug 2009 02:09:37 +0000 (22:09 -0400)
Our INT 13h hook will now only shift BIOS drive numbers up to a limit.
This limit is found by probing for a contiguous range of BIOS drives.  Anything
above this range of contiguous drive numbers is not shifted, and will thus be
available to callers at the same drive number.

memdisk/Makefile
memdisk/dskprobe.c [new file with mode: 0644]
memdisk/dskprobe.h [new file with mode: 0644]
memdisk/setup.c

index e1a8935..06413b6 100644 (file)
@@ -38,9 +38,9 @@ endif
 # Important: init.o16 must be first!!
 OBJS16   = init.o16 init32.o
 OBJS32   = start32.o setup.o msetup.o e820func.o conio.o memcpy.o memset.o \
-          memmove.o unzip.o memdisk_chs.o memdisk_edd.o
+          memmove.o unzip.o memdisk_chs.o memdisk_edd.o dskprobe.o
 
-CSRC     = setup.c msetup.c e820func.c conio.c unzip.c
+CSRC     = setup.c msetup.c e820func.c conio.c unzip.c dskprobe.c
 SSRC     = start32.S memcpy.S memset.S memmove.S
 NASMSRC  = memdisk_chs.asm memdisk_edd.asm memdisk16.asm
 
diff --git a/memdisk/dskprobe.c b/memdisk/dskprobe.c
new file mode 100644 (file)
index 0000000..de858bb
--- /dev/null
@@ -0,0 +1,114 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Shao Miller - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * dskprobe.c
+ *
+ * Routines for probing BIOS disk drives
+ */
+
+/*
+ * Uncomment for debugging
+ *
+ * #define DBG_DSKPROBE 1
+ */
+
+#include <stdint.h>
+#include "memdisk.h"
+#include "bda.h"
+#include "conio.h"
+
+/*
+ * We will probe a BIOS drive numer using INT 13h, AH=probe
+ * and will pass along that call's success or failure
+ */
+int probe_int13_ah(uint8_t drive, uint8_t probe)
+{
+    int err;
+    com32sys_t regs;
+
+    memset(&regs, 0, sizeof regs);
+
+    regs.eax.b[1] = probe;     /* AH = probe                 */
+    regs.edx.b[0] = drive;     /* DL = drive number to probe */
+    intcall(0x13, &regs, &regs);
+
+    err = !(regs.eflags.l & 1);
+#ifdef DBG_DSKPROBE
+    printf("probe_int13_ah(0x%02x, 0x%02x) == %d\n", drive, probe, err);
+#endif
+    return err;
+}
+
+/*
+ * We will probe the BIOS Data Area and count the drives found there.
+ * This heuristic then assumes that all drives of 'drive's type are
+ * found in a contiguous range, and returns 1 if the probed drive
+ * is less than or equal to the BDA count.
+ * This particular function's code is derived from code in setup.c by
+ * H. Peter Anvin.  Please respect that file's copyright for this function
+ */
+int probe_bda_drive(uint8_t drive)
+{
+    int bios_drives;
+    int err;
+
+    if (drive & 0x80) {
+       bios_drives = rdz_8(BIOS_HD_COUNT);     /* HDD count */
+    } else {
+       uint8_t equip = rdz_8(BIOS_EQUIP);
+       if (equip & 1)
+           bios_drives = (equip >> 6) + 1;     /* Floppy count */
+       else
+           bios_drives = 0;
+    }
+    err = (drive - (drive & 0x80)) >= bios_drives ? 0 : 1;
+#ifdef DBG_DSKPROBE
+    printf("probe_bda_drive(0x%02x) == %d, count: %d\n",
+          drive, err, bios_drives);
+#endif
+    return err;
+}
+
+/*
+ * We will probe a drive with a few different methods, returning
+ * the count of succesful probes
+ */
+int probe_drive(uint8_t drive)
+{
+    int c = 0;
+    /* Only probe the BDA for floppies */
+    if (drive & 0x80) {
+       c += probe_int13_ah(drive, 0x08);
+       c += probe_int13_ah(drive, 0x15);
+       c += probe_int13_ah(drive, 0x41);
+    }
+    c += probe_bda_drive(drive);
+    return c;
+}
+
+/*
+ * We will probe a contiguous range of BIOS drive, starting with drive
+ * number 'start'.  We probe with a few different methods, and return
+ * the first drive which doesn't respond to any of the probes.
+ */
+uint8_t probe_drive_range(uint8_t start)
+{
+    uint8_t drive = start;
+    while (probe_drive(drive)) {
+       drive++;
+       /* Check for passing the floppy/HDD boundary */
+       if ((drive & 0x7F) == 0)
+           break;
+    }
+    return drive;
+}
diff --git a/memdisk/dskprobe.h b/memdisk/dskprobe.h
new file mode 100644 (file)
index 0000000..99bfa66
--- /dev/null
@@ -0,0 +1,21 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2009 Shao Miller - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * dskprobe.h
+ *
+ * Routines for probing BIOS disk drives
+ */
+
+#include <stdint.h>
+
+extern uint8_t probe_drive_range(uint8_t);
index b2444f6..e3b9d31 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <stdint.h>
 #include "bda.h"
+#include "dskprobe.h"
 #include "e820.h"
 #include "conio.h"
 #include "version.h"
@@ -999,6 +1000,13 @@ void setup(const struct real_mode_args *rm_args_ptr)
     if (pptr->drivecnt <= (geometry->driveno & 0x7f))
        pptr->drivecnt = (geometry->driveno & 0x7f) + 1;
 
+    /* Probe for contiguous range of BIOS drives starting with driveno */
+    pptr->driveshiftlimit = probe_drive_range(geometry->driveno) + 1;
+    if ((pptr->driveshiftlimit & 0x80) != (geometry->driveno & 0x80))
+       printf("We lost the last drive in our class of drives.\n");
+    printf("Drive probing gives drive shift limit: 0x%02x\n",
+       pptr->driveshiftlimit);
+
     /* Pointer to the command line */
     pptr->cmdline_off = bin_size + (nranges + 1) * sizeof(ranges[0]);
     pptr->cmdline_seg = driverseg;