ReactOS 0.4.15-dev-5672-gf73ac17
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: debug.h:110
#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
VOID UiMessageBox(PCSTR Format,...)
Definition: ui.c:363
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", *(unsigned long long*)&Ptr[8]);
342 TRACE("bytes per sector: %u\n", Ptr[12]);
343 if (Ptr[0] >= 0x1e)
344 {
345 TRACE("EED configuration parameters: %x:%x\n", Ptr[13], Ptr[14]);
346 if (Ptr[13] != 0xffff && Ptr[14] != 0xffff)
347 {
348 PUCHAR SpecPtr = (PUCHAR)(ULONG_PTR)((Ptr[13] << 4) + Ptr[14]);
349 TRACE("SpecPtr: %x\n", SpecPtr);
350 TRACE("physical I/O port base address: %x\n", *(PUSHORT)&SpecPtr[0]);
351 TRACE("disk-drive control port address: %x\n", *(PUSHORT)&SpecPtr[2]);
352 TRACE("drive flags: %x\n", SpecPtr[4]);
353 TRACE("proprietary information: %x\n", SpecPtr[5]);
354 TRACE("IRQ for drive: %u\n", SpecPtr[6]);
355 TRACE("sector count for multi-sector transfers: %u\n", SpecPtr[7]);
356 TRACE("DMA control: %x\n", SpecPtr[8]);
357 TRACE("programmed I/O control: %x\n", SpecPtr[9]);
358 TRACE("drive options: %x\n", *(PUSHORT)&SpecPtr[10]);
359 }
360 }
361 if (Ptr[0] >= 0x42)
362 {
363 TRACE("signature: %x\n", Ptr[15]);
364 }
365#endif
366
367 return TRUE;
368}
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
#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(), and PcGetHarddiskConfigurationData().

◆ 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: debug.h:112
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 371 of file pcdisk.c.

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

Referenced by PcDiskDriveInit().

◆ PcDiskDriveInit()

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

Definition at line 463 of file pcdisk.c.

466{
467 DiskDrive->IsRemovable = DiskIsDriveRemovable(DriveNumber);
468
469 /*
470 * Check to see if it is a fixed disk drive.
471 * If so then check to see if INT 13h extensions work.
472 * If they do then use them, otherwise default back to BIOS calls.
473 */
474 DiskDrive->Int13ExtensionsSupported = DiskInt13ExtensionsSupported(DriveNumber);
475
476 if (!InitDriveGeometry(DriveNumber, DiskDrive))
477 return FALSE;
478
479 TRACE("\n"
480 "DriveNumber: 0x%x\n"
481 "IsRemovable = %s\n"
482 "Int13ExtensionsSupported = %s\n",
483 DriveNumber,
484 DiskDrive->IsRemovable ? "TRUE" : "FALSE",
485 DiskDrive->Int13ExtensionsSupported ? "TRUE" : "FALSE");
486
487 return TRUE;
488}
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:371

Referenced by PcDiskDriveNumberToDrive().

◆ PcDiskDriveNumberToDrive()

static PPC_DISK_DRIVE PcDiskDriveNumberToDrive ( IN UCHAR  DriveNumber)
inlinestatic

Definition at line 492 of file pcdisk.c.

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

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

◆ PcDiskGetCacheableBlockCount()

ULONG PcDiskGetCacheableBlockCount ( UCHAR  DriveNumber)

Definition at line 827 of file pcdisk.c.

828{
829 PPC_DISK_DRIVE DiskDrive;
830
831 DiskDrive = PcDiskDriveNumberToDrive(DriveNumber);
832 if (!DiskDrive)
833 return 1; // Unknown count.
834
835 /*
836 * If LBA is supported then the block size will be 64 sectors (32k).
837 * If not then the block size is the size of one track.
838 */
839 if (DiskDrive->Int13ExtensionsSupported)
840 return 64;
841 else
842 return DiskDrive->Geometry.Sectors;
843}
static PPC_DISK_DRIVE PcDiskDriveNumberToDrive(IN UCHAR DriveNumber)
Definition: pcdisk.c:492
ULONG Sectors
Definition: disk.h:28
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 798 of file pcdisk.c.

799{
800 PPC_DISK_DRIVE DiskDrive;
801
802 TRACE("PcDiskGetDriveGeometry(0x%x)\n", DriveNumber);
803
804 DiskDrive = PcDiskDriveNumberToDrive(DriveNumber);
805 if (!DiskDrive)
806 return FALSE;
807
808 /* Try to get the extended geometry first */
809 if (DiskDrive->ExtGeometry.Size == sizeof(DiskDrive->ExtGeometry))
810 {
811 /* Extended geometry has been initialized, return it */
812 Geometry->Cylinders = DiskDrive->ExtGeometry.Cylinders;
813 Geometry->Heads = DiskDrive->ExtGeometry.Heads;
814 Geometry->Sectors = DiskDrive->ExtGeometry.SectorsPerTrack;
815 Geometry->BytesPerSector = DiskDrive->ExtGeometry.BytesPerSector;
816 }
817 else
818 /* Fall back to legacy BIOS geometry */
819 {
820 *Geometry = DiskDrive->Geometry;
821 }
822
823 return TRUE;
824}
USHORT Size
Definition: disk.h:39
ULONG Heads
Definition: disk.h:42
USHORT BytesPerSector
Definition: disk.h:45
ULONG SectorsPerTrack
Definition: disk.h:43
ULONG Cylinders
Definition: disk.h:41
ULONG BytesPerSector
Definition: disk.h:29
ULONG Cylinders
Definition: disk.h:26
ULONG Heads
Definition: disk.h:27
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 758 of file pcdisk.c.

763{
764 PPC_DISK_DRIVE DiskDrive;
765
766 TRACE("PcDiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n",
767 DriveNumber, SectorNumber, SectorCount, Buffer);
768
769 /* 16-bit BIOS addressing limitation */
770 ASSERT(((ULONG_PTR)Buffer) <= 0xFFFFF);
771
772 DiskDrive = PcDiskDriveNumberToDrive(DriveNumber);
773 if (!DiskDrive)
774 return FALSE;
775
776 if ((DriveNumber >= 0x80) && DiskDrive->Int13ExtensionsSupported)
777 {
778 /* LBA is easy, nothing to calculate. Just do the read. */
779 TRACE("--> Using LBA\n");
780 return PcDiskReadLogicalSectorsLBA(DriveNumber, SectorNumber, SectorCount, Buffer);
781 }
782 else
783 {
784 /* LBA is not supported, default to CHS */
785 TRACE("--> Using CHS\n");
786 return PcDiskReadLogicalSectorsCHS(DriveNumber, DiskDrive, SectorNumber, SectorCount, Buffer);
787 }
788}
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:558
static BOOLEAN PcDiskReadLogicalSectorsCHS(IN UCHAR DriveNumber, IN PPC_DISK_DRIVE DiskDrive, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
Definition: pcdisk.c:626

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 626 of file pcdisk.c.

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

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