NEWS: wrapping
[syslinux.git] / memdisk / dskprobe.c
blob84400a83dc94d303bf976cb6e6233c056fb2588d
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 * ----------------------------------------------------------------------- */
14 * dskprobe.c
16 * Routines for probing BIOS disk drives
19 /* Change to 1 for debugging */
20 #define DBG_DSKPROBE 0
22 #include <stdint.h>
23 #include "memdisk.h"
24 #include "bda.h"
25 #include "conio.h"
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);
48 return;
51 /**
52 * INT 0x13, AH == 0x08: Get drive parameters.
54 static int probe_int13h_08h(uint8_t drive, com32sys_t * regs)
56 int present;
58 memset(regs, 0, sizeof *regs);
59 probe_any(0x08, drive, regs);
60 present = !(regs->eflags.l & 1);
61 dskprobe_printf(" AH08: CF%d BL%02x DL%02x\n", regs->eflags.l & 1,
62 regs->ebx.b[0], regs->edx.b[0]);
63 return present;
66 /**
67 * INT 0x13, AH == 0x15: Get disk type.
69 static int probe_int13h_15h(uint8_t drive, com32sys_t * regs)
71 int present;
73 memset(regs, 0, sizeof *regs);
74 probe_any(0x15, drive, regs);
75 present = !(regs->eflags.l & 1) && regs->eax.b[1];
76 dskprobe_printf(" AH15: CF%d AH%02x\n", regs->eflags.l & 1,
77 regs->eax.b[1]);
78 return present;
81 /**
82 * INT 0x13, AH == 0x41: INT 0x13 extensions installation check.
84 static int probe_int13h_41h(uint8_t drive, com32sys_t * regs)
86 int present;
88 memset(regs, 0, sizeof *regs);
89 regs->ebx.w[0] = 0x55AA; /* BX == 0x55AA */
90 probe_any(0x41, drive, regs);
91 present = !(regs->eflags.l & 1);
92 dskprobe_printf(" AH41: CF%d BX%04x AH%02x DH%02x\n", regs->eflags.l & 1,
93 regs->ebx.w[0], regs->eax.b[1], regs->edx.b[1]);
94 return present;
98 * We will probe the BIOS Data Area and count the drives found there.
99 * This heuristic then assumes that all drives of 'drive's type are
100 * found in a contiguous range, and returns 1 if the probed drive
101 * is less than or equal to the BDA count.
102 * This particular function's code is derived from code in setup.c by
103 * H. Peter Anvin. Please respect that file's copyright for this function
105 int probe_bda_drive(uint8_t drive)
107 int bios_drives;
108 int err;
110 if (drive & 0x80) {
111 bios_drives = rdz_8(BIOS_HD_COUNT); /* HDD count */
112 } else {
113 uint8_t equip = rdz_8(BIOS_EQUIP);
114 if (equip & 1)
115 bios_drives = (equip >> 6) + 1; /* Floppy count */
116 else
117 bios_drives = 0;
119 err = (drive - (drive & 0x80)) >= bios_drives ? 0 : 1;
120 dskprobe_printf("BDA drive %02x? %d, total count: %d\n", drive, err,
121 bios_drives);
122 return err;
126 * We will probe a drive with a few different methods, returning
127 * the count of succesful probes
129 int multi_probe_drive(uint8_t drive)
131 int c = 0;
132 com32sys_t regs;
134 dskprobe_printf("INT 13 DL%02x:\n", drive);
135 /* Only probe the BDA for floppies */
136 if (drive & 0x80) {
138 c += probe_int13h_08h(drive, &regs);
139 c += probe_int13h_15h(drive, &regs);
140 c += probe_int13h_41h(drive, &regs);
142 c += probe_bda_drive(drive);
143 dskprobe_pause(&regs);
144 return c;
148 * We will probe a contiguous range of BIOS drive, starting with drive
149 * number 'start'. We probe with a few different methods, and return
150 * the first drive which doesn't respond to any of the probes.
152 uint8_t probe_drive_range(uint8_t start)
154 uint8_t drive = start;
155 while (multi_probe_drive(drive)) {
156 drive++;
157 /* Check for passing the floppy/HDD boundary */
158 if ((drive & 0x7F) == 0)
159 break;
161 return drive;
164 /* Dummy printf() that does nothing */
165 static int no_printf(const char *ignored, ...)
167 (void)ignored;
168 return 0;
171 /* Pause if we are in debug-mode */
172 static void dskprobe_pause(com32sys_t * regs)
174 if (!DBG_DSKPROBE)
175 return;
176 dskprobe_printf("Press a key to continue...\n");
177 memset(regs, 0, sizeof *regs);
178 regs->eax.w[0] = 0;
179 intcall(0x16, regs, NULL);
180 return;