summaryrefslogtreecommitdiffstats
path: root/contrib/syslinux-4.02/memdisk/dskprobe.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/syslinux-4.02/memdisk/dskprobe.c')
-rw-r--r--contrib/syslinux-4.02/memdisk/dskprobe.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/memdisk/dskprobe.c b/contrib/syslinux-4.02/memdisk/dskprobe.c
new file mode 100644
index 0000000..de858bb
--- /dev/null
+++ b/contrib/syslinux-4.02/memdisk/dskprobe.c
@@ -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;
+}