| /* ----------------------------------------------------------------------- * |
| * |
| * 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; |
| } |