ReactOS 0.4.16-dev-455-g37b0646
pcdisk.c File Reference
#include <freeldr.h>
#include <debug.h>
#include <pshpack2.h>
#include <poppack.h>
Include dependency graph for pcdisk.c:

Go to the source code of this file.

Classes

struct  I386_DISK_ADDRESS_PACKET
 
struct  I386_CDROM_SPEC_PACKET
 
struct  _PC_DISK_DRIVE
 

Typedefs

typedef struct I386_DISK_ADDRESS_PACKETPI386_DISK_ADDRESS_PACKET
 
typedef struct I386_CDROM_SPEC_PACKETPI386_CDROM_SPEC_PACKET
 
typedef struct _PC_DISK_DRIVE PC_DISK_DRIVE
 
typedef struct _PC_DISK_DRIVEPPC_DISK_DRIVE
 

Functions

 DBG_DEFAULT_CHANNEL (DISK)
 
LONG DiskReportError (BOOLEAN bShowError)
 
static PCSTR DiskGetErrorCodeString (ULONG ErrorCode)
 
static VOID DiskError (PCSTR ErrorString, ULONG ErrorCode)
 
BOOLEAN DiskResetController (UCHAR DriveNumber)
 
static BOOLEAN DiskIsDriveRemovable (UCHAR DriveNumber)
 
static BOOLEAN DiskInt13ExtensionsSupported (IN UCHAR DriveNumber)
 
static BOOLEAN DiskGetExtendedDriveParameters (IN UCHAR DriveNumber, IN PPC_DISK_DRIVE DiskDrive, OUT PVOID Buffer, IN USHORT BufferSize)
 
static BOOLEAN InitDriveGeometry (IN UCHAR DriveNumber, IN PPC_DISK_DRIVE DiskDrive)
 
static BOOLEAN PcDiskDriveInit (IN UCHAR DriveNumber, IN OUT PPC_DISK_DRIVE DiskDrive)
 
static PPC_DISK_DRIVE PcDiskDriveNumberToDrive (IN UCHAR DriveNumber)
 
static BOOLEAN PcDiskReadLogicalSectorsLBA (IN UCHAR DriveNumber, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
 
static BOOLEAN PcDiskReadLogicalSectorsCHS (IN UCHAR DriveNumber, IN PPC_DISK_DRIVE DiskDrive, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
 
BOOLEAN PcDiskReadLogicalSectors (IN UCHAR DriveNumber, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
 
BOOLEAN PcDiskGetDriveGeometry (UCHAR DriveNumber, PGEOMETRY Geometry)
 
ULONG PcDiskGetCacheableBlockCount (UCHAR DriveNumber)
 

Variables

static USHORT LastDriveNumber = 0xFFFF
 
static PC_DISK_DRIVE PcDiskDrive
 
static LONG lReportError = 0
 

Typedef Documentation

◆ PC_DISK_DRIVE

◆ PI386_CDROM_SPEC_PACKET

◆ PI386_DISK_ADDRESS_PACKET

◆ PPC_DISK_DRIVE

Function Documentation

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( DISK  )

◆ DiskError()

static VOID DiskError ( PCSTR  ErrorString,
ULONG  ErrorCode 
)
static

Definition at line 163 of file pcdisk.c.

164{
165 CHAR ErrorCodeString[200];
166
167 if (lReportError < 0)
168 return;
169
170 sprintf(ErrorCodeString, "%s\n\nError Code: 0x%lx\nError: %s",
172
173 ERR("%s\n", ErrorCodeString);
174
175 UiMessageBox(ErrorCodeString);
176}
#define ERR(fmt,...)
Definition: precomp.h:57
VOID UiMessageBox(_In_ PCSTR Format,...)
Definition: ui.c:359
#define sprintf(buf, format,...)
Definition: sprintf.c:55
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436
static LONG lReportError
Definition: pcdisk.c:118
static PCSTR DiskGetErrorCodeString(ULONG ErrorCode)
Definition: pcdisk.c:128
char CHAR
Definition: xmlstorage.h:175

Referenced by PcDiskReadLogicalSectorsCHS(), and PcDiskReadLogicalSectorsLBA().

◆ DiskGetErrorCodeString()

static PCSTR DiskGetErrorCodeString ( ULONG  ErrorCode)
static

Definition at line 128 of file pcdisk.c.

129{
130 switch (ErrorCode)
131 {
132 case 0x00: return "no error";
133 case 0x01: return "bad command passed to driver";
134 case 0x02: return "address mark not found or bad sector";
135 case 0x03: return "diskette write protect error";
136 case 0x04: return "sector not found";
137 case 0x05: return "fixed disk reset failed";
138 case 0x06: return "diskette changed or removed";
139 case 0x07: return "bad fixed disk parameter table";
140 case 0x08: return "DMA overrun";
141 case 0x09: return "DMA access across 64k boundary";
142 case 0x0A: return "bad fixed disk sector flag";
143 case 0x0B: return "bad fixed disk cylinder";
144 case 0x0C: return "unsupported track/invalid media";
145 case 0x0D: return "invalid number of sectors on fixed disk format";
146 case 0x0E: return "fixed disk controlled data address mark detected";
147 case 0x0F: return "fixed disk DMA arbitration level out of range";
148 case 0x10: return "ECC/CRC error on disk read";
149 case 0x11: return "recoverable fixed disk data error, data fixed by ECC";
150 case 0x20: return "controller error (NEC for floppies)";
151 case 0x40: return "seek failure";
152 case 0x80: return "time out, drive not ready";
153 case 0xAA: return "fixed disk drive not ready";
154 case 0xBB: return "fixed disk undefined error";
155 case 0xCC: return "fixed disk write fault on selected drive";
156 case 0xE0: return "fixed disk status error/Error reg = 0";
157 case 0xFF: return "sense operation failed";
158
159 default: return "unknown error code";
160 }
161}

Referenced by DiskError(), PcDiskReadLogicalSectorsCHS(), and PcDiskReadLogicalSectorsLBA().

◆ DiskGetExtendedDriveParameters()

static BOOLEAN DiskGetExtendedDriveParameters ( IN UCHAR  DriveNumber,
IN PPC_DISK_DRIVE  DiskDrive,
OUT PVOID  Buffer,
IN USHORT  BufferSize 
)
static

Definition at line 294 of file pcdisk.c.

299{
300 REGS RegsIn, RegsOut;
302
303 TRACE("DiskGetExtendedDriveParameters(0x%x)\n", DriveNumber);
304
305 if (!DiskDrive->Int13ExtensionsSupported)
306 return FALSE;
307
308 /* Initialize transfer buffer */
309 *Ptr = BufferSize;
310
311 /*
312 * BIOS Int 13h, function 48h - Get drive parameters
313 * AH = 48h
314 * DL = drive (bit 7 set for hard disk)
315 * DS:SI = result buffer
316 * Return:
317 * CF set on error
318 * AH = status (07h)
319 * CF clear if successful
320 * AH = 00h
321 * DS:SI -> result buffer
322 */
323 RegsIn.b.ah = 0x48;
324 RegsIn.b.dl = DriveNumber;
325 RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> result buffer
326 RegsIn.w.si = BIOSCALLBUFOFFSET;
327
328 /* Get drive parameters */
329 Int386(0x13, &RegsIn, &RegsOut);
330 if (!INT386_SUCCESS(RegsOut))
331 return FALSE;
332
334
335#if DBG
336 TRACE("size of buffer: %x\n", Ptr[0]);
337 TRACE("information flags: %x\n", Ptr[1]);
338 TRACE("number of physical cylinders on drive: %u\n", *(PULONG)&Ptr[2]);
339 TRACE("number of physical heads on drive: %u\n", *(PULONG)&Ptr[4]);
340 TRACE("number of physical sectors per track: %u\n", *(PULONG)&Ptr[6]);
341 TRACE("total number of sectors on drive: %I64u\n", *(PULONGLONG)&Ptr[8]);
342 TRACE("bytes per sector: %u\n", Ptr[12]);
343 if (Ptr[0] >= 0x1e)
344 {
345 // Ptr[13]: offset, Ptr[14]: segment
346 TRACE("EDD configuration parameters: %x:%x\n", Ptr[14], Ptr[13]);
347 if (Ptr[13] != 0xffff && Ptr[14] != 0xffff)
348 {
349 PUCHAR SpecPtr = (PUCHAR)(ULONG_PTR)((Ptr[14] << 4) + Ptr[13]);
350 TRACE("SpecPtr: %x\n", SpecPtr);
351 TRACE("physical I/O port base address: %x\n", *(PUSHORT)&SpecPtr[0]);
352 TRACE("disk-drive control port address: %x\n", *(PUSHORT)&SpecPtr[2]);
353 TRACE("drive flags: %x\n", SpecPtr[4]);
354 TRACE("proprietary information: %x\n", SpecPtr[5]);
355 TRACE("IRQ for drive: %u\n", SpecPtr[6]);
356 TRACE("sector count for multi-sector transfers: %u\n", SpecPtr[7]);
357 TRACE("DMA control: %x\n", SpecPtr[8]);
358 TRACE("programmed I/O control: %x\n", SpecPtr[9]);
359 TRACE("drive options: %x\n", *(PUSHORT)&SpecPtr[10]);
360 }
361 }
362 if (Ptr[0] >= 0x42)
363 {
364 TRACE("signature: %x\n", Ptr[15]);
365 }
366#endif
367
368 return TRUE;
369}
Definition: bufpool.h:45
#define BufferSize
Definition: mmc.h:75
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:391
#define INT386_SUCCESS(regs)
Definition: pcbios.h:179
int __cdecl Int386(int ivec, REGS *in, REGS *out)
#define TRACE(s)
Definition: solgame.cpp:4
unsigned char dl
Definition: pcbios.h:140
unsigned char ah
Definition: pcbios.h:132
unsigned short ds
Definition: pcbios.h:100
unsigned short si
Definition: pcbios.h:116
uint32_t * PULONG
Definition: typedefs.h:59
uint16_t * PUSHORT
Definition: typedefs.h:56
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
Definition: pcbios.h:159
DWORDREGS x
Definition: pcbios.h:160
BYTEREGS b
Definition: pcbios.h:163
WORDREGS w
Definition: pcbios.h:162
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
#define BIOSCALLBUFSEGMENT
Definition: x86common.h:21
#define BIOSCALLBUFOFFSET
Definition: x86common.h:22
#define BIOSCALLBUFFER
Definition: x86common.h:12

Referenced by InitDriveGeometry().

◆ DiskInt13ExtensionsSupported()

static BOOLEAN DiskInt13ExtensionsSupported ( IN UCHAR  DriveNumber)
static

Definition at line 220 of file pcdisk.c.

221{
222 REGS RegsIn, RegsOut;
223
224 /*
225 * Some BIOSes report that extended disk access functions are not supported
226 * when booting from a CD (e.g. Phoenix BIOS v6.00PG and Insyde BIOS shipping
227 * with Intel Macs). Therefore we just return TRUE if we're booting from a CD
228 * - we can assume that all El Torito capable BIOSes support INT 13 extensions.
229 * We simply detect whether we're booting from CD by checking whether the drive
230 * number is >= 0x8A. It's 0x90 on the Insyde BIOS, and 0x9F on most other BIOSes.
231 */
232 if (DriveNumber >= 0x8A)
233 return TRUE;
234
235 /*
236 * IBM/MS INT 13 Extensions - INSTALLATION CHECK
237 * AH = 41h
238 * BX = 55AAh
239 * DL = drive (80h-FFh)
240 * Return:
241 * CF set on error (extensions not supported)
242 * AH = 01h (invalid function)
243 * CF clear if successful
244 * BX = AA55h if installed
245 * AH = major version of extensions
246 * 01h = 1.x
247 * 20h = 2.0 / EDD-1.0
248 * 21h = 2.1 / EDD-1.1
249 * 30h = EDD-3.0
250 * AL = internal use
251 * CX = API subset support bitmap
252 * DH = extension version (v2.0+ ??? -- not present in 1.x)
253 *
254 * Bitfields for IBM/MS INT 13 Extensions API support bitmap
255 * Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
256 * Bit 1, removable drive controller functions (AH=45h,46h,48h,49h,INT 15/AH=52h) supported
257 * Bit 2, enhanced disk drive (EDD) functions (AH=48h,AH=4Eh) supported
258 * extended drive parameter table is valid
259 * Bits 3-15 reserved
260 */
261 RegsIn.b.ah = 0x41;
262 RegsIn.w.bx = 0x55AA;
263 RegsIn.b.dl = DriveNumber;
264
265 /* Reset the disk controller */
266 Int386(0x13, &RegsIn, &RegsOut);
267 if (!INT386_SUCCESS(RegsOut))
268 {
269 /* CF set on error (extensions not supported) */
270 return FALSE;
271 }
272
273 if (RegsOut.w.bx != 0xAA55)
274 {
275 /* BX = AA55h if installed */
276 return FALSE;
277 }
278
279 if (!(RegsOut.w.cx & 0x0001))
280 {
281 /*
282 * CX = API subset support bitmap.
283 * Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported.
284 */
285 WARN("Suspicious API subset support bitmap 0x%x on device 0x%lx\n",
286 RegsOut.w.cx, DriveNumber);
287 return FALSE;
288 }
289
290 return TRUE;
291}
#define WARN(fmt,...)
Definition: precomp.h:61
unsigned short cx
Definition: pcbios.h:113
unsigned short bx
Definition: pcbios.h:112

Referenced by PcDiskDriveInit().

◆ DiskIsDriveRemovable()

static BOOLEAN DiskIsDriveRemovable ( UCHAR  DriveNumber)
static

Definition at line 205 of file pcdisk.c.

206{
207 /*
208 * Hard disks use drive numbers >= 0x80 . So if the drive number
209 * indicates a hard disk then return FALSE.
210 * 0x49 is our magic ramdisk drive, so return FALSE for that too.
211 */
212 if ((DriveNumber >= 0x80) || (DriveNumber == 0x49))
213 return FALSE;
214
215 /* The drive is a floppy diskette so return TRUE */
216 return TRUE;
217}

Referenced by PcDiskDriveInit().

◆ DiskReportError()

LONG DiskReportError ( BOOLEAN  bShowError)

Definition at line 120 of file pcdisk.c.

121{
122 /* Set the reference count */
123 if (bShowError) ++lReportError;
124 else --lReportError;
125 return lReportError;
126}

Referenced by EnumerateHarddisks(), and GetHarddiskInformation().

◆ DiskResetController()

BOOLEAN DiskResetController ( UCHAR  DriveNumber)

Definition at line 180 of file pcdisk.c.

181{
182 REGS RegsIn, RegsOut;
183
184 WARN("DiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n", DriveNumber);
185
186 /*
187 * BIOS Int 13h, function 0 - Reset disk system
188 * AH = 00h
189 * DL = drive (if bit 7 is set both hard disks and floppy disks reset)
190 * Return:
191 * AH = status
192 * CF clear if successful
193 * CF set on error
194 */
195 RegsIn.b.ah = 0x00;
196 RegsIn.b.dl = DriveNumber;
197
198 /* Reset the disk controller */
199 Int386(0x13, &RegsIn, &RegsOut);
200
201 return INT386_SUCCESS(RegsOut);
202}

Referenced by DetectBiosFloppyPeripheral(), PcDiskReadLogicalSectorsCHS(), and PcDiskReadLogicalSectorsLBA().

◆ InitDriveGeometry()

static BOOLEAN InitDriveGeometry ( IN UCHAR  DriveNumber,
IN PPC_DISK_DRIVE  DiskDrive 
)
static

Definition at line 372 of file pcdisk.c.

375{
377 REGS RegsIn, RegsOut;
378 ULONG Cylinders;
379
380 /* Get the extended geometry first */
381 DiskDrive->ExtGeometry.Size = sizeof(DiskDrive->ExtGeometry);
382 Success = DiskGetExtendedDriveParameters(DriveNumber, DiskDrive,
383 &DiskDrive->ExtGeometry,
384 DiskDrive->ExtGeometry.Size);
385 if (!Success)
386 {
387 /* Failed, zero it out */
388 RtlZeroMemory(&DiskDrive->ExtGeometry, sizeof(DiskDrive->ExtGeometry));
389 }
390 else
391 {
392 TRACE("DiskGetExtendedDriveParameters(0x%x) returned:\n"
393 "Cylinders : 0x%x\n"
394 "Heads : 0x%x\n"
395 "Sects/Track: 0x%x\n"
396 "Bytes/Sect : 0x%x\n",
397 DriveNumber,
398 DiskDrive->ExtGeometry.Cylinders,
399 DiskDrive->ExtGeometry.Heads,
400 DiskDrive->ExtGeometry.SectorsPerTrack,
401 DiskDrive->ExtGeometry.BytesPerSector);
402 }
403
404 /* Now try the legacy geometry */
405 RtlZeroMemory(&DiskDrive->Geometry, sizeof(DiskDrive->Geometry));
406
407 /*
408 * BIOS Int 13h, function 08h - Get drive parameters
409 * AH = 08h
410 * DL = drive (bit 7 set for hard disk)
411 * ES:DI = 0000h:0000h to guard against BIOS bugs
412 * Return:
413 * CF set on error
414 * AH = status (07h)
415 * CF clear if successful
416 * AH = 00h
417 * AL = 00h on at least some BIOSes
418 * BL = drive type (AT/PS2 floppies only)
419 * CH = low eight bits of maximum cylinder number
420 * CL = maximum sector number (bits 5-0)
421 * high two bits of maximum cylinder number (bits 7-6)
422 * DH = maximum head number
423 * DL = number of drives
424 * ES:DI -> drive parameter table (floppies only)
425 */
426 RegsIn.b.ah = 0x08;
427 RegsIn.b.dl = DriveNumber;
428 RegsIn.w.es = 0x0000;
429 RegsIn.w.di = 0x0000;
430
431 /* Get drive parameters */
432 Int386(0x13, &RegsIn, &RegsOut);
433 if (!INT386_SUCCESS(RegsOut))
434 {
435 /* We failed, return the result of the previous call (extended geometry) */
436 return Success;
437 }
438 /* OR it with the old result, so that we return TRUE whenever either call succeeded */
439 Success |= TRUE;
440
441 Cylinders = (RegsOut.b.cl & 0xC0) << 2;
442 Cylinders += RegsOut.b.ch;
443 Cylinders++;
444 DiskDrive->Geometry.Cylinders = Cylinders;
445 DiskDrive->Geometry.Heads = RegsOut.b.dh + 1;
446 DiskDrive->Geometry.SectorsPerTrack = RegsOut.b.cl & 0x3F;
447 DiskDrive->Geometry.BytesPerSector = 512; /* Just assume 512 bytes per sector */
448
449 DiskDrive->Geometry.Sectors = (ULONGLONG)DiskDrive->Geometry.Cylinders *
450 DiskDrive->Geometry.Heads *
451 DiskDrive->Geometry.SectorsPerTrack;
452
453 TRACE("Regular Int13h(0x%x) returned:\n"
454 "Cylinders : 0x%x\n"
455 "Heads : 0x%x\n"
456 "Sects/Track: 0x%x (original 0x%x)\n"
457 "Bytes/Sect : 0x%x\n",
458 DriveNumber,
459 DiskDrive->Geometry.Cylinders,
460 DiskDrive->Geometry.Heads,
461 DiskDrive->Geometry.SectorsPerTrack, RegsOut.b.cl,
462 DiskDrive->Geometry.BytesPerSector);
463
464 return Success;
465}
unsigned char BOOLEAN
@ Success
Definition: eventcreate.c:712
static BOOLEAN DiskGetExtendedDriveParameters(IN UCHAR DriveNumber, IN PPC_DISK_DRIVE DiskDrive, OUT PVOID Buffer, IN USHORT BufferSize)
Definition: pcdisk.c:294
unsigned char ch
Definition: pcbios.h:138
unsigned char cl
Definition: pcbios.h:137
unsigned char dh
Definition: pcbios.h:141
unsigned short es
Definition: pcbios.h:121
unsigned short di
Definition: pcbios.h:117
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67

Referenced by PcDiskDriveInit().

◆ PcDiskDriveInit()

static BOOLEAN PcDiskDriveInit ( IN UCHAR  DriveNumber,
IN OUT PPC_DISK_DRIVE  DiskDrive 
)
static

Definition at line 468 of file pcdisk.c.

471{
472 DiskDrive->IsRemovable = DiskIsDriveRemovable(DriveNumber);
473
474 /*
475 * Check to see if it is a fixed disk drive.
476 * If so then check to see if INT 13h extensions work.
477 * If they do then use them, otherwise default back to BIOS calls.
478 */
479 DiskDrive->Int13ExtensionsSupported = DiskInt13ExtensionsSupported(DriveNumber);
480
481 if (!InitDriveGeometry(DriveNumber, DiskDrive))
482 return FALSE;
483
484 TRACE("\n"
485 "DriveNumber: 0x%x\n"
486 "IsRemovable = %s\n"
487 "Int13ExtensionsSupported = %s\n",
488 DriveNumber,
489 DiskDrive->IsRemovable ? "TRUE" : "FALSE",
490 DiskDrive->Int13ExtensionsSupported ? "TRUE" : "FALSE");
491
492 return TRUE;
493}
static BOOLEAN DiskInt13ExtensionsSupported(IN UCHAR DriveNumber)
Definition: pcdisk.c:220
static BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber)
Definition: pcdisk.c:205
static BOOLEAN InitDriveGeometry(IN UCHAR DriveNumber, IN PPC_DISK_DRIVE DiskDrive)
Definition: pcdisk.c:372

Referenced by PcDiskDriveNumberToDrive().

◆ PcDiskDriveNumberToDrive()

static PPC_DISK_DRIVE PcDiskDriveNumberToDrive ( IN UCHAR  DriveNumber)
inlinestatic

Definition at line 497 of file pcdisk.c.

498{
499#ifdef CACHE_MULTI_DRIVES
500 PPC_DISK_DRIVE DiskDrive;
501
502 ASSERT((0 <= DriveNumber) && (DriveNumber < RTL_NUMBER_OF(PcDiskDrive)));
503
504 /* Retrieve a slot */
505 DiskDrive = &PcDiskDrive[DriveNumber];
506
507 /* If the drive has not been initialized before... */
508 if (!DiskDrive->Initialized)
509 {
510 /* ... try to initialize it now. */
511 if (!PcDiskDriveInit(DriveNumber, DiskDrive))
512 {
513 /*
514 * If we failed, there is no drive at this number
515 * and flag it as such (set its high bit).
516 */
517 DiskDrive->Initialized |= 0x80;
518 return NULL;
519 }
520 DiskDrive->Initialized = TRUE;
521 }
522 else if (DiskDrive->Initialized & 0x80)
523 {
524 /*
525 * The disk failed to be initialized previously, reset its flag to give
526 * it chance to be initialized again later, but just fail for the moment.
527 */
528 DiskDrive->Initialized = FALSE;
529 return NULL;
530 }
531
532 return DiskDrive;
533#else
534 static PC_DISK_DRIVE NewDiskDrive;
535
536 ASSERT((0 <= DriveNumber) && (DriveNumber <= 0xFF));
537
538 /* Update cached information */
539
540 /* If the drive has not been accessed last before... */
541 if ((USHORT)DriveNumber != LastDriveNumber)
542 {
543 /* ... try to (re-)initialize and cache it now. */
544 RtlZeroMemory(&NewDiskDrive, sizeof(NewDiskDrive));
545 if (!PcDiskDriveInit(DriveNumber, &NewDiskDrive))
546 {
547 /*
548 * If we failed, there is no drive at this number.
549 * Keep the last-accessed valid drive cached.
550 */
551 return NULL;
552 }
553 /* We succeeded, cache the drive data */
554 PcDiskDrive = NewDiskDrive;
555 LastDriveNumber = (USHORT)DriveNumber;
556 }
557
558 return &PcDiskDrive;
559#endif /* CACHE_MULTI_DRIVES */
560}
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define NULL
Definition: types.h:112
#define ASSERT(a)
Definition: mode.c:44
static USHORT LastDriveNumber
Definition: pcdisk.c:112
static PC_DISK_DRIVE PcDiskDrive
Definition: pcdisk.c:113
static BOOLEAN PcDiskDriveInit(IN UCHAR DriveNumber, IN OUT PPC_DISK_DRIVE DiskDrive)
Definition: pcdisk.c:468
unsigned short USHORT
Definition: pedump.c:61

Referenced by PcDiskGetCacheableBlockCount(), PcDiskGetDriveGeometry(), and PcDiskReadLogicalSectors().

◆ PcDiskGetCacheableBlockCount()

ULONG PcDiskGetCacheableBlockCount ( UCHAR  DriveNumber)

Definition at line 815 of file pcdisk.c.

816{
817 PPC_DISK_DRIVE DiskDrive;
818
819 DiskDrive = PcDiskDriveNumberToDrive(DriveNumber);
820 if (!DiskDrive)
821 return 1; // Unknown count.
822
823 /*
824 * If LBA is supported then the block size will be 64 sectors (32k).
825 * If not then the block size is the size of one track.
826 */
827 if (DiskDrive->Int13ExtensionsSupported)
828 return 64;
829 else
830 return DiskDrive->Geometry.SectorsPerTrack;
831}
static PPC_DISK_DRIVE PcDiskDriveNumberToDrive(IN UCHAR DriveNumber)
Definition: pcdisk.c:497
ULONG SectorsPerTrack
Number of sectors per track.
Definition: disk.h:29
BOOLEAN Int13ExtensionsSupported
Definition: pcdisk.c:86
GEOMETRY Geometry
Definition: pcdisk.c:82

Referenced by MachInit().

◆ PcDiskGetDriveGeometry()

BOOLEAN PcDiskGetDriveGeometry ( UCHAR  DriveNumber,
PGEOMETRY  Geometry 
)

Definition at line 785 of file pcdisk.c.

786{
787 PPC_DISK_DRIVE DiskDrive;
788
789 TRACE("PcDiskGetDriveGeometry(0x%x)\n", DriveNumber);
790
791 DiskDrive = PcDiskDriveNumberToDrive(DriveNumber);
792 if (!DiskDrive)
793 return FALSE;
794
795 /* Try to get the extended geometry first */
796 if (DiskDrive->ExtGeometry.Size == sizeof(DiskDrive->ExtGeometry))
797 {
798 /* Extended geometry has been initialized, return it */
799 Geometry->Cylinders = DiskDrive->ExtGeometry.Cylinders;
800 Geometry->Heads = DiskDrive->ExtGeometry.Heads;
801 Geometry->SectorsPerTrack = DiskDrive->ExtGeometry.SectorsPerTrack;
802 Geometry->BytesPerSector = DiskDrive->ExtGeometry.BytesPerSector;
803 Geometry->Sectors = DiskDrive->ExtGeometry.Sectors;
804 }
805 else
806 /* Fall back to legacy BIOS geometry */
807 {
808 *Geometry = DiskDrive->Geometry;
809 }
810
811 return TRUE;
812}
ULONGLONG Sectors
Definition: disk.h:47
USHORT Size
Definition: disk.h:42
ULONG Heads
Definition: disk.h:45
USHORT BytesPerSector
Definition: disk.h:48
ULONG SectorsPerTrack
Definition: disk.h:46
ULONG Cylinders
Definition: disk.h:44
ULONG BytesPerSector
Number of bytes per sector.
Definition: disk.h:30
ULONG Cylinders
Number of cylinders on the disk.
Definition: disk.h:27
ULONGLONG Sectors
Total number of disk sectors/LBA blocks.
Definition: disk.h:31
ULONG Heads
Number of heads on the disk.
Definition: disk.h:28
EXTENDED_GEOMETRY ExtGeometry
Definition: pcdisk.c:83

Referenced by MachInit(), and PcGetHarddiskConfigurationData().

◆ PcDiskReadLogicalSectors()

BOOLEAN PcDiskReadLogicalSectors ( IN UCHAR  DriveNumber,
IN ULONGLONG  SectorNumber,
IN ULONG  SectorCount,
OUT PVOID  Buffer 
)

Definition at line 745 of file pcdisk.c.

750{
751 PPC_DISK_DRIVE DiskDrive;
752
753 TRACE("PcDiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n",
754 DriveNumber, SectorNumber, SectorCount, Buffer);
755
756 /* 16-bit BIOS addressing limitation */
757 ASSERT(((ULONG_PTR)Buffer) <= 0xFFFFF);
758
759 DiskDrive = PcDiskDriveNumberToDrive(DriveNumber);
760 if (!DiskDrive)
761 return FALSE;
762
763 if ((DriveNumber >= 0x80) && DiskDrive->Int13ExtensionsSupported)
764 {
765 /* LBA is easy, nothing to calculate. Just do the read. */
766 TRACE("--> Using LBA\n");
767 return PcDiskReadLogicalSectorsLBA(DriveNumber, SectorNumber, SectorCount, Buffer);
768 }
769 else
770 {
771 /* LBA is not supported, default to CHS */
772 TRACE("--> Using CHS\n");
773 return PcDiskReadLogicalSectorsCHS(DriveNumber, DiskDrive, SectorNumber, SectorCount, Buffer);
774 }
775}
ULONG SectorCount
Definition: part_xbox.c:31
static BOOLEAN PcDiskReadLogicalSectorsLBA(IN UCHAR DriveNumber, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
Definition: pcdisk.c:563
static BOOLEAN PcDiskReadLogicalSectorsCHS(IN UCHAR DriveNumber, IN PPC_DISK_DRIVE DiskDrive, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
Definition: pcdisk.c:627

Referenced by MachInit().

◆ PcDiskReadLogicalSectorsCHS()

static BOOLEAN PcDiskReadLogicalSectorsCHS ( IN UCHAR  DriveNumber,
IN PPC_DISK_DRIVE  DiskDrive,
IN ULONGLONG  SectorNumber,
IN ULONG  SectorCount,
OUT PVOID  Buffer 
)
static

Definition at line 627 of file pcdisk.c.

633{
634 UCHAR PhysicalSector;
635 UCHAR PhysicalHead;
636 ULONG PhysicalTrack;
637 GEOMETRY DriveGeometry;
638 ULONG NumberOfSectorsToRead;
639 REGS RegsIn, RegsOut;
640 ULONG RetryCount;
641
642 DriveGeometry = DiskDrive->Geometry;
643 if (DriveGeometry.SectorsPerTrack == 0 || DriveGeometry.Heads == 0)
644 return FALSE;
645
646 while (SectorCount > 0)
647 {
648 /*
649 * Calculate the physical disk offsets.
650 * Note: DriveGeometry.SectorsPerTrack < 64
651 */
652 PhysicalSector = 1 + (UCHAR)(SectorNumber % DriveGeometry.SectorsPerTrack);
653 PhysicalHead = (UCHAR)((SectorNumber / DriveGeometry.SectorsPerTrack) % DriveGeometry.Heads);
654 PhysicalTrack = (ULONG)((SectorNumber / DriveGeometry.SectorsPerTrack) / DriveGeometry.Heads);
655
656 /* Calculate how many sectors we need to read this round */
657 if (PhysicalSector > 1)
658 {
659 NumberOfSectorsToRead = min(SectorCount,
660 (DriveGeometry.SectorsPerTrack - (PhysicalSector - 1)));
661 }
662 else
663 {
664 NumberOfSectorsToRead = min(SectorCount, DriveGeometry.SectorsPerTrack);
665 }
666
667 /* Make sure the read is within the geometry boundaries */
668 if ((PhysicalHead >= DriveGeometry.Heads) ||
669 (PhysicalTrack >= DriveGeometry.Cylinders) ||
670 ((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.SectorsPerTrack + 1)) ||
671 (PhysicalSector > DriveGeometry.SectorsPerTrack))
672 {
673 DiskError("Disk read exceeds drive geometry limits.", 0);
674 return FALSE;
675 }
676
677 /*
678 * BIOS Int 13h, function 2 - Read Disk Sectors
679 * AH = 02h
680 * AL = number of sectors to read (must be nonzero)
681 * CH = low eight bits of cylinder number
682 * CL = sector number 1-63 (bits 0-5)
683 * high two bits of cylinder (bits 6-7, hard disk only)
684 * DH = head number
685 * DL = drive number (bit 7 set for hard disk)
686 * ES:BX -> data buffer
687 * Return:
688 * CF set on error
689 * if AH = 11h (corrected ECC error), AL = burst length
690 * CF clear if successful
691 * AH = status
692 * AL = number of sectors transferred
693 * (only valid if CF set for some BIOSes)
694 */
695 RegsIn.b.ah = 0x02;
696 RegsIn.b.al = (UCHAR)NumberOfSectorsToRead;
697 RegsIn.b.ch = (PhysicalTrack & 0xFF);
698 RegsIn.b.cl = (UCHAR)(PhysicalSector + ((PhysicalTrack & 0x300) >> 2));
699 RegsIn.b.dh = PhysicalHead;
700 RegsIn.b.dl = DriveNumber;
701 RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4);
702 RegsIn.w.bx = ((ULONG_PTR)Buffer) & 0x0F;
703
704 /* Perform the read. Retry 3 times. */
705 for (RetryCount = 0; RetryCount < 3; ++RetryCount)
706 {
707 Int386(0x13, &RegsIn, &RegsOut);
708
709 /* If it worked, or if it was a corrected ECC error
710 * and the data is still good, break out */
711 if (INT386_SUCCESS(RegsOut) || (RegsOut.b.ah == 0x11))
712 break;
713
714 /* It failed, do the next retry */
715 DiskResetController(DriveNumber);
716 }
717
718 /* If we retried 3 times then fail */
719 if (RetryCount >= 3)
720 {
721 DiskError("Disk Read Failed in CHS mode, after retrying 3 times", RegsOut.b.ah);
722 ERR("Disk Read Failed in CHS mode, after retrying 3 times: %x (%s) (DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d)\n",
723 RegsOut.b.ah, DiskGetErrorCodeString(RegsOut.b.ah),
724 DriveNumber, SectorNumber, SectorCount);
725 return FALSE;
726 }
727
728 /*
729 * I have learned that not all BIOSes return
730 * the sector read count in the AL register (at least mine doesn't)
731 * even if the sectors were read correctly. So instead
732 * of checking the sector read count we will rely solely
733 * on the carry flag being set on error.
734 */
735
736 Buffer = (PVOID)((ULONG_PTR)Buffer + (NumberOfSectorsToRead * DriveGeometry.BytesPerSector));
737 SectorCount -= NumberOfSectorsToRead;
738 SectorNumber += NumberOfSectorsToRead;
739 }
740
741 return TRUE;
742}
#define ULONG_PTR
Definition: config.h:101
#define min(a, b)
Definition: monoChain.cc:55
BOOLEAN DiskResetController(UCHAR DriveNumber)
Definition: pcdisk.c:180
static VOID DiskError(PCSTR ErrorString, ULONG ErrorCode)
Definition: pcdisk.c:163
unsigned char al
Definition: pcbios.h:131
Definition: disk.h:26
void * PVOID
Definition: typedefs.h:50
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by PcDiskReadLogicalSectors().

◆ PcDiskReadLogicalSectorsLBA()

static BOOLEAN PcDiskReadLogicalSectorsLBA ( IN UCHAR  DriveNumber,
IN ULONGLONG  SectorNumber,
IN ULONG  SectorCount,
OUT PVOID  Buffer 
)
static

Definition at line 563 of file pcdisk.c.

568{
569 REGS RegsIn, RegsOut;
570 ULONG RetryCount;
572
573 /* Setup disk address packet */
574 RtlZeroMemory(Packet, sizeof(*Packet));
575 Packet->PacketSize = sizeof(*Packet);
576 Packet->Reserved = 0;
577 // Packet->LBABlockCount set in the loop.
578 Packet->TransferBufferOffset = ((ULONG_PTR)Buffer) & 0x0F;
579 Packet->TransferBufferSegment = (USHORT)(((ULONG_PTR)Buffer) >> 4);
580 Packet->LBAStartBlock = SectorNumber;
581
582 /*
583 * BIOS Int 13h, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
584 * Return:
585 * CF clear if successful
586 * AH = 00h
587 * CF set on error
588 * AH = error code
589 * Disk address packet's block count field set to the
590 * number of blocks successfully transferred.
591 */
592 RegsIn.b.ah = 0x42;
593 RegsIn.b.dl = DriveNumber; // Drive number in DL (0 - floppy, 0x80 - harddisk)
594 RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> disk address packet
595 RegsIn.w.si = BIOSCALLBUFOFFSET;
596
597 /* Retry 3 times */
598 for (RetryCount = 0; RetryCount < 3; ++RetryCount)
599 {
600 /* Restore the number of blocks to transfer, since it gets reset
601 * on failure with the number of blocks that were successfully
602 * transferred (and which could be zero). */
603 Packet->LBABlockCount = (USHORT)SectorCount;
604 ASSERT(Packet->LBABlockCount == SectorCount);
605
606 Int386(0x13, &RegsIn, &RegsOut);
607
608 /* If it worked, or if it was a corrected ECC error
609 * and the data is still good, return success */
610 if (INT386_SUCCESS(RegsOut) || (RegsOut.b.ah == 0x11))
611 return TRUE;
612
613 /* It failed, do the next retry */
614 DiskResetController(DriveNumber);
615 }
616
617 /* If we get here then the read failed */
618 DiskError("Disk Read Failed in LBA mode", RegsOut.b.ah);
619 ERR("Disk Read Failed in LBA mode: %x (%s) (DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d)\n",
620 RegsOut.b.ah, DiskGetErrorCodeString(RegsOut.b.ah),
621 DriveNumber, SectorNumber, SectorCount);
622
623 return FALSE;
624}
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1549
struct I386_DISK_ADDRESS_PACKET * PI386_DISK_ADDRESS_PACKET

Referenced by PcDiskReadLogicalSectors().

Variable Documentation

◆ LastDriveNumber

USHORT LastDriveNumber = 0xFFFF
static

Definition at line 112 of file pcdisk.c.

Referenced by PcDiskDriveNumberToDrive().

◆ lReportError

LONG lReportError = 0
static

Definition at line 118 of file pcdisk.c.

Referenced by DiskError(), and DiskReportError().

◆ PcDiskDrive

PC_DISK_DRIVE PcDiskDrive
static

Definition at line 113 of file pcdisk.c.

Referenced by PcDiskDriveNumberToDrive().