diff options
Diffstat (limited to 'contrib/syslinux-4.02/memdisk/dskprobe.c')
-rw-r--r-- | contrib/syslinux-4.02/memdisk/dskprobe.c | 114 |
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(®s, 0, sizeof regs); + + regs.eax.b[1] = probe; /* AH = probe */ + regs.edx.b[0] = drive; /* DL = drive number to probe */ + intcall(0x13, ®s, ®s); + + 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; +} |