1 /* ----------------------------------------------------------------------- *
3 * Copyright 2009 Shao Miller - All Rights Reserved
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 * Boston MA 02111-1307, USA; either version 2 of the License, or
9 * (at your option) any later version; incorporated herein by reference.
11 * ----------------------------------------------------------------------- */
16 * Routines for probing BIOS disk drives
19 /* Change to 1 for debugging */
20 #define DBG_DSKPROBE 0
27 /* Function type for printf() */
28 typedef int (f_printf
) (const char *, ...);
30 /* Dummy printf() that does nothing */
31 static f_printf no_printf
;
32 static f_printf
*dskprobe_printfs
[] = { no_printf
, printf
};
34 #define dskprobe_printf (dskprobe_printfs[DBG_DSKPROBE])
36 static void dskprobe_pause(com32sys_t
*);
38 /* Probe routine function type */
39 typedef int (f_probe
) (uint8_t, com32sys_t
*);
40 static f_probe probe_int13h_08h
, probe_int13h_15h
, probe_int13h_41h
;
42 /* We will probe a BIOS drive number using INT 0x13, AH == func */
43 static void probe_any(uint8_t func
, uint8_t drive
, com32sys_t
* regs
)
45 regs
->eax
.b
[1] = func
; /* AH == sub-function for probe */
46 regs
->edx
.b
[0] = drive
; /* DL == drive number to probe */
47 intcall(0x13, regs
, regs
);
52 * Determine if the return from probe_int13h_01h indicates a failure; a
53 * return of zero indicates no known failure.
55 static int probe_int13h_01h_fail(int istatus
)
63 case 1: status
= istatus
;
69 * INT 0x13, AH == 0x01: Get status of last command.
71 static int probe_int13h_01h(uint8_t drive
)
76 memset(®s
, 0, sizeof regs
);
77 probe_any(0x01, drive
, ®s
);
78 status
= (regs
.eflags
.l
& 1) * 256 + regs
.eax
.b
[1];
79 dskprobe_printf(" AH01: CF%d AH%02x", regs
.eflags
.l
& 1, regs
.eax
.b
[1]);
84 * INT 0x13, AH == 0x08: Get drive parameters.
86 static int probe_int13h_08h(uint8_t drive
, com32sys_t
* regs
)
90 memset(regs
, 0, sizeof *regs
);
91 probe_any(0x08, drive
, regs
);
92 dskprobe_printf(" AH08: CF%d AH%02x AL%02x BL%02x DL%02x",
93 regs
->eflags
.l
& 1, regs
->eax
.b
[1], regs
->eax
.b
[0],
94 regs
->ebx
.b
[0], regs
->edx
.b
[0]);
95 present
= !(regs
->eflags
.l
& 1) && !regs
->eax
.b
[1];
96 dskprobe_printf(" P%d\n", present
);
101 * INT 0x13, AH == 0x15: Get disk type.
103 static int probe_int13h_15h(uint8_t drive
, com32sys_t
* regs
)
108 memset(regs
, 0, sizeof *regs
);
109 probe_any(0x15, drive
, regs
);
110 dskprobe_printf(" AH15: CF%d AH%02x AL%02x CX%04x DX%04x",
111 regs
->eflags
.l
& 1, regs
->eax
.b
[1], regs
->eax
.b
[0],
112 regs
->ecx
.w
[0], regs
->edx
.w
[0]);
113 present
= !(regs
->eflags
.l
& 1) && regs
->eax
.b
[1];
114 status
= probe_int13h_01h(drive
);
115 present
= present
&& !(probe_int13h_01h_fail(status
));
116 dskprobe_printf(" P%d\n", present
);
121 * INT 0x13, AH == 0x41: INT 0x13 extensions installation check.
123 static int probe_int13h_41h(uint8_t drive
, com32sys_t
* regs
)
127 memset(regs
, 0, sizeof *regs
);
128 regs
->ebx
.w
[0] = 0x55AA; /* BX == 0x55AA */
129 probe_any(0x41, drive
, regs
);
130 dskprobe_printf(" AH41: CF%d BX%04x AH%02x DH%02x",
131 regs
->eflags
.l
& 1, regs
->ebx
.w
[0], regs
->eax
.b
[1],
133 present
= !(regs
->eflags
.l
& 1) && (regs
->ebx
.w
[0] == 0xAA55);
134 dskprobe_printf(" P%d\n", present
);
139 * We will probe the BIOS Data Area and count the drives found there.
140 * This heuristic then assumes that all drives of 'drive's type are
141 * found in a contiguous range, and returns 1 if the probed drive
142 * is less than or equal to the BDA count.
143 * This particular function's code is derived from code in setup.c by
144 * H. Peter Anvin. Please respect that file's copyright for this function
146 int probe_bda_drive(uint8_t drive
)
152 bios_drives
= rdz_8(BIOS_HD_COUNT
); /* HDD count */
154 uint8_t equip
= rdz_8(BIOS_EQUIP
);
156 bios_drives
= (equip
>> 6) + 1; /* Floppy count */
160 err
= (drive
- (drive
& 0x80)) >= bios_drives
? 0 : 1;
161 dskprobe_printf("BDA drive %02x? %d, total count: %d\n", drive
, err
,
167 * We will probe a drive with a few different methods, returning
168 * the count of succesful probes
170 int multi_probe_drive(uint8_t drive
)
175 dskprobe_printf("INT 13 DL%02x:\n", drive
);
176 /* Only probe the BDA for floppies */
179 c
+= probe_int13h_08h(drive
, ®s
);
180 c
+= probe_int13h_15h(drive
, ®s
);
181 c
+= probe_int13h_41h(drive
, ®s
);
183 c
+= probe_bda_drive(drive
);
184 dskprobe_pause(®s
);
189 * We will probe a contiguous range of BIOS drive, starting with drive
190 * number 'start'. We probe with a few different methods, and return
191 * the first drive which doesn't respond to any of the probes.
193 uint8_t probe_drive_range(uint8_t start
)
195 uint8_t drive
= start
;
196 while (multi_probe_drive(drive
)) {
198 /* Check for passing the floppy/HDD boundary */
199 if ((drive
& 0x7F) == 0)
205 /* Dummy printf() that does nothing */
206 static int no_printf(const char *ignored
, ...)
212 /* Pause if we are in debug-mode */
213 static void dskprobe_pause(com32sys_t
* regs
)
217 dskprobe_printf("Press a key to continue...\n");
218 memset(regs
, 0, sizeof *regs
);
220 intcall(0x16, regs
, NULL
);