Added disk cache
[reactos.git] / freeldr / freeldr / disk / disk.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1999, 2000, 2001 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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <freeldr.h>
21 #include <disk.h>
22 #include <fs.h>
23 #include <rtl.h>
24 #include <ui.h>
25 #include <asmcode.h>
26 #include <debug.h>
27
28
29 /////////////////////////////////////////////////////////////////////////////////////////////
30 // FUNCTIONS
31 /////////////////////////////////////////////////////////////////////////////////////////////
32
33 VOID DiskError(PUCHAR ErrorString)
34 {
35 DbgPrint((DPRINT_DISK, "%s\n", ErrorString));
36
37 if (UserInterfaceUp)
38 {
39 MessageBox(ErrorString);
40 }
41 else
42 {
43 printf("%s", ErrorString);
44 printf("\nPress any key\n");
45 getch();
46 }
47 }
48
49 BOOL DiskReadMultipleLogicalSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
50 {
51 ULONG PhysicalSector;
52 ULONG PhysicalHead;
53 ULONG PhysicalTrack;
54 GEOMETRY DriveGeometry;
55 ULONG NumberOfSectorsToRead;
56
57 DbgPrint((DPRINT_DISK, "ReadLogicalSector() DriveNumber: 0x%x SectorNumber: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, Buffer));
58
59 //
60 // Check to see if it is a fixed disk drive
61 // If so then check to see if Int13 extensions work
62 // If they do then use them, otherwise default back to BIOS calls
63 //
64 if ((DriveNumber >= 0x80) && (BiosInt13ExtensionsSupported(DriveNumber)))
65 {
66 DbgPrint((DPRINT_DISK, "Using Int 13 Extensions for read. BiosInt13ExtensionsSupported(%d) = %s\n", DriveNumber, BiosInt13ExtensionsSupported(DriveNumber) ? "TRUE" : "FALSE"));
67
68 //
69 // LBA is easy, nothing to calculate
70 // Just do the read
71 //
72 if (!BiosInt13ReadExtended(DriveNumber, SectorNumber, 1, Buffer))
73 {
74 DiskError("Disk read error.");
75 return FALSE;
76 }
77 }
78 else
79 {
80 //
81 // Get the drive geometry
82 //
83 if (!DiskGetDriveGeometry(DriveNumber, &DriveGeometry))
84 {
85 return FALSE;
86 }
87
88 while (SectorCount)
89 {
90
91 //
92 // Calculate the physical disk offsets
93 //
94 PhysicalSector = 1 + (SectorNumber % DriveGeometry.Sectors);
95 PhysicalHead = (SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads;
96 PhysicalTrack = (SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads;
97
98 //
99 // Calculate how many sectors we are supposed to read
100 //
101 if (PhysicalSector > 1)
102 {
103 if (SectorCount >= (DriveGeometry.Sectors - (PhysicalSector - 1)))
104 NumberOfSectorsToRead = (DriveGeometry.Sectors - (PhysicalSector - 1));
105 else
106 NumberOfSectorsToRead = SectorCount;
107 }
108 else
109 {
110 if (SectorCount >= DriveGeometry.Sectors)
111 NumberOfSectorsToRead = DriveGeometry.Sectors;
112 else
113 NumberOfSectorsToRead = SectorCount;
114 }
115
116 DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalHead: %d\n", PhysicalHead));
117 DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalTrack: %d\n", PhysicalTrack));
118 DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalSector: %d\n", PhysicalSector));
119 DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with NumberOfSectorsToRead: %d\n", NumberOfSectorsToRead));
120
121 //
122 // Make sure the read is within the geometry boundaries
123 //
124 if ((PhysicalHead >= DriveGeometry.Heads) ||
125 (PhysicalTrack >= DriveGeometry.Cylinders) ||
126 ((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.Sectors + 1)) ||
127 (PhysicalSector > DriveGeometry.Sectors))
128 {
129 DiskError("Disk read exceeds drive geometry limits.");
130 return FALSE;
131 }
132
133 //
134 // Perform the read
135 //
136 if (!BiosInt13Read(DriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, NumberOfSectorsToRead, Buffer))
137 {
138 DiskError("Disk read error.");
139 return FALSE;
140 }
141
142 Buffer += (NumberOfSectorsToRead * DriveGeometry.BytesPerSector);
143 SectorCount -= NumberOfSectorsToRead;
144 SectorNumber += NumberOfSectorsToRead;
145 }
146 }
147
148 return TRUE;
149 }
150
151 BOOL DiskReadLogicalSector(ULONG DriveNumber, ULONG SectorNumber, PVOID Buffer)
152 {
153 ULONG PhysicalSector;
154 ULONG PhysicalHead;
155 ULONG PhysicalTrack;
156 GEOMETRY DriveGeometry;
157
158 DbgPrint((DPRINT_DISK, "ReadLogicalSector() DriveNumber: 0x%x SectorNumber: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, Buffer));
159
160 //
161 // Check to see if it is a fixed disk drive
162 // If so then check to see if Int13 extensions work
163 // If they do then use them, otherwise default back to BIOS calls
164 //
165 if ((DriveNumber >= 0x80) && (BiosInt13ExtensionsSupported(DriveNumber)))
166 {
167 DbgPrint((DPRINT_DISK, "Using Int 13 Extensions for read. BiosInt13ExtensionsSupported(%d) = %s\n", DriveNumber, BiosInt13ExtensionsSupported(DriveNumber) ? "TRUE" : "FALSE"));
168
169 //
170 // LBA is easy, nothing to calculate
171 // Just do the read
172 //
173 if (!BiosInt13ReadExtended(DriveNumber, SectorNumber, 1, Buffer))
174 {
175 DiskError("Disk read error.");
176 return FALSE;
177 }
178 }
179 else
180 {
181 //
182 // Get the drive geometry
183 //
184 if (!DiskGetDriveGeometry(DriveNumber, &DriveGeometry))
185 {
186 return FALSE;
187 }
188
189 //
190 // Calculate the physical disk offsets
191 //
192 PhysicalSector = 1 + (SectorNumber % DriveGeometry.Sectors);
193 PhysicalHead = (SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads;
194 PhysicalTrack = (SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads;
195
196 DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalHead: %d\n", PhysicalHead));
197 DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalTrack: %d\n", PhysicalTrack));
198 DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalSector: %d\n", PhysicalSector));
199
200 //
201 // Make sure the read is within the geometry boundaries
202 //
203 if ((PhysicalHead >= DriveGeometry.Heads) ||
204 (PhysicalTrack >= DriveGeometry.Cylinders) ||
205 (PhysicalSector > DriveGeometry.Sectors))
206 {
207 DiskError("Disk read exceeds drive geometry limits.");
208 return FALSE;
209 }
210
211 //
212 // Perform the read
213 //
214 if (!BiosInt13Read(DriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, 1, Buffer))
215 {
216 DiskError("Disk read error.");
217 return FALSE;
218 }
219 }
220
221 return TRUE;
222 }