[FREELDR]
[reactos.git] / reactos / boot / freeldr / freeldr / arch / i386 / i386disk.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4 *
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; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <freeldr.h>
21
22 #define NDEBUG
23 #include <debug.h>
24
25 /////////////////////////////////////////////////////////////////////////////////////////////
26 // FUNCTIONS
27 /////////////////////////////////////////////////////////////////////////////////////////////
28
29 BOOLEAN DiskResetController(ULONG DriveNumber)
30 {
31 REGS RegsIn;
32 REGS RegsOut;
33
34 DPRINTM(DPRINT_DISK, "DiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n", DriveNumber);
35
36 // BIOS Int 13h, function 0 - Reset disk system
37 // AH = 00h
38 // DL = drive (if bit 7 is set both hard disks and floppy disks reset)
39 // Return:
40 // AH = status
41 // CF clear if successful
42 // CF set on error
43 RegsIn.b.ah = 0x00;
44 RegsIn.b.dl = DriveNumber;
45
46 // Reset the disk controller
47 Int386(0x13, &RegsIn, &RegsOut);
48
49 return INT386_SUCCESS(RegsOut);
50 }
51
52 BOOLEAN DiskInt13ExtensionsSupported(ULONG DriveNumber)
53 {
54 REGS RegsIn;
55 REGS RegsOut;
56
57 DPRINTM(DPRINT_DISK, "DiskInt13ExtensionsSupported()\n");
58
59 // IBM/MS INT 13 Extensions - INSTALLATION CHECK
60 // AH = 41h
61 // BX = 55AAh
62 // DL = drive (80h-FFh)
63 // Return:
64 // CF set on error (extensions not supported)
65 // AH = 01h (invalid function)
66 // CF clear if successful
67 // BX = AA55h if installed
68 // AH = major version of extensions
69 // 01h = 1.x
70 // 20h = 2.0 / EDD-1.0
71 // 21h = 2.1 / EDD-1.1
72 // 30h = EDD-3.0
73 // AL = internal use
74 // CX = API subset support bitmap
75 // DH = extension version (v2.0+ ??? -- not present in 1.x)
76 //
77 // Bitfields for IBM/MS INT 13 Extensions API support bitmap
78 // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
79 // Bit 1, removable drive controller functions (AH=45h,46h,48h,49h,INT 15/AH=52h) supported
80 // Bit 2, enhanced disk drive (EDD) functions (AH=48h,AH=4Eh) supported
81 // extended drive parameter table is valid
82 // Bits 3-15 reserved
83 RegsIn.b.ah = 0x41;
84 RegsIn.w.bx = 0x55AA;
85 RegsIn.b.dl = DriveNumber;
86
87 // Reset the disk controller
88 Int386(0x13, &RegsIn, &RegsOut);
89
90 if (!INT386_SUCCESS(RegsOut))
91 {
92 // CF set on error (extensions not supported)
93 return FALSE;
94 }
95
96 if (RegsOut.w.bx != 0xAA55)
97 {
98 // BX = AA55h if installed
99 return FALSE;
100 }
101
102 // Note:
103 // The original check is too strict because some BIOSes report that
104 // extended disk access functions are not suported when booting
105 // from a CD (e.g. Phoenix BIOS v6.00PG). Argh!
106 #if 0
107 if (!(RegsOut.w.cx & 0x0001))
108 {
109 // CX = API subset support bitmap
110 // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
111 return FALSE;
112 }
113 #endif
114
115 // Use this relaxed check instead
116 if (RegsOut.w.cx == 0x0000)
117 {
118 // CX = API subset support bitmap
119 return FALSE;
120 }
121
122 return TRUE;
123 }
124
125 VOID DiskStopFloppyMotor(VOID)
126 {
127 WRITE_PORT_UCHAR((PUCHAR)0x3F2, 0);
128 }
129
130 BOOLEAN DiskGetExtendedDriveParameters(ULONG DriveNumber, PVOID Buffer, USHORT BufferSize)
131 {
132 REGS RegsIn;
133 REGS RegsOut;
134 PUSHORT Ptr = (PUSHORT)(BIOSCALLBUFFER);
135
136 DPRINTM(DPRINT_DISK, "DiskGetExtendedDriveParameters()\n");
137
138 if (!DiskInt13ExtensionsSupported(DriveNumber))
139 return FALSE;
140
141 // Initialize transfer buffer
142 *Ptr = BufferSize;
143
144 // BIOS Int 13h, function 48h - Get drive parameters
145 // AH = 48h
146 // DL = drive (bit 7 set for hard disk)
147 // DS:SI = result buffer
148 // Return:
149 // CF set on error
150 // AH = status (07h)
151 // CF clear if successful
152 // AH = 00h
153 // DS:SI -> result buffer
154 RegsIn.b.ah = 0x48;
155 RegsIn.b.dl = DriveNumber;
156 RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> result buffer
157 RegsIn.w.si = BIOSCALLBUFOFFSET;
158
159 // Get drive parameters
160 Int386(0x13, &RegsIn, &RegsOut);
161
162 if (!INT386_SUCCESS(RegsOut))
163 {
164 return FALSE;
165 }
166
167 memcpy(Buffer, Ptr, BufferSize);
168
169 #if DBG
170 DPRINTM(DPRINT_DISK, "size of buffer: %x\n", Ptr[0]);
171 DPRINTM(DPRINT_DISK, "information flags: %x\n", Ptr[1]);
172 DPRINTM(DPRINT_DISK, "number of physical cylinders on drive: %u\n", *(PULONG)&Ptr[2]);
173 DPRINTM(DPRINT_DISK, "number of physical heads on drive: %u\n", *(PULONG)&Ptr[4]);
174 DPRINTM(DPRINT_DISK, "number of physical sectors per track: %u\n", *(PULONG)&Ptr[6]);
175 DPRINTM(DPRINT_DISK, "total number of sectors on drive: %I64u\n", *(unsigned long long*)&Ptr[8]);
176 DPRINTM(DPRINT_DISK, "bytes per sector: %u\n", Ptr[12]);
177 if (Ptr[0] >= 0x1e)
178 {
179 DPRINTM(DPRINT_DISK, "EED configuration parameters: %x:%x\n", Ptr[13], Ptr[14]);
180 if (Ptr[13] != 0xffff && Ptr[14] != 0xffff)
181 {
182 PUCHAR SpecPtr = (PUCHAR)(ULONG_PTR)((Ptr[13] << 4) + Ptr[14]);
183 DPRINTM(DPRINT_DISK, "SpecPtr: %x\n", SpecPtr);
184 DPRINTM(DPRINT_DISK, "physical I/O port base address: %x\n", *(PUSHORT)&SpecPtr[0]);
185 DPRINTM(DPRINT_DISK, "disk-drive control port address: %x\n", *(PUSHORT)&SpecPtr[2]);
186 DPRINTM(DPRINT_DISK, "drive flags: %x\n", SpecPtr[4]);
187 DPRINTM(DPRINT_DISK, "proprietary information: %x\n", SpecPtr[5]);
188 DPRINTM(DPRINT_DISK, "IRQ for drive: %u\n", SpecPtr[6]);
189 DPRINTM(DPRINT_DISK, "sector count for multi-sector transfers: %u\n", SpecPtr[7]);
190 DPRINTM(DPRINT_DISK, "DMA control: %x\n", SpecPtr[8]);
191 DPRINTM(DPRINT_DISK, "programmed I/O control: %x\n", SpecPtr[9]);
192 DPRINTM(DPRINT_DISK, "drive options: %x\n", *(PUSHORT)&SpecPtr[10]);
193 }
194 }
195 if (Ptr[0] >= 0x42)
196 {
197 DPRINTM(DPRINT_DISK, "signature: %x\n", Ptr[15]);
198 }
199 #endif
200
201 return TRUE;
202 }
203
204 /* EOF */