ReactOS 0.4.16-dev-2359-g4b75ec5
pc98disk.c File Reference
#include <freeldr.h>
#include <hwide.h>
#include <debug.h>
Include dependency graph for pc98disk.c:

Go to the source code of this file.

Macros

#define MAX_DRIVES   0x100
 

Functions

 DBG_DEFAULT_CHANNEL (DISK)
 
LONG DiskReportError (_In_ BOOLEAN bShowError)
 
static PCSTR DiskGetErrorCodeString (_In_ ULONG ErrorCode)
 
static VOID DiskError (_In_ PCSTR ErrorString, _In_ ULONG ErrorCode)
 
static BOOLEAN DiskResetController (_In_ PPC98_DISK_DRIVE DiskDrive)
 
PPC98_DISK_DRIVE Pc98DiskDriveNumberToDrive (_In_ UCHAR DriveNumber)
 
CONFIGURATION_TYPE DiskGetConfigType (_In_ UCHAR DriveNumber)
 
static UCHAR BytesPerSectorToSectorLengthCode (_In_ ULONG BytesPerSector)
 
static BOOLEAN Pc98DiskReadLogicalSectorsLBA (_In_ PPC98_DISK_DRIVE DiskDrive, _In_ ULONG64 SectorNumber, _In_ ULONG SectorCount, _Out_writes_bytes_all_(SectorCount *DiskDrive->Geometry.BytesPerSector) PVOID Buffer)
 
static BOOLEAN Pc98DiskReadLogicalSectorsCHS (_In_ PPC98_DISK_DRIVE DiskDrive, _In_ ULONG64 SectorNumber, _In_ ULONG SectorCount, _Out_writes_bytes_all_(SectorCount *DiskDrive->Geometry.BytesPerSector) PVOID Buffer)
 
static BOOLEAN InitScsiDrive (_Out_ PPC98_DISK_DRIVE DiskDrive, _In_ UCHAR DaUa)
 
static BOOLEAN InitFloppyDrive (_Out_ PPC98_DISK_DRIVE DiskDrive, _In_ UCHAR DaUa)
 
static BOOLEAN InitIdeDrive (_Out_ PPC98_DISK_DRIVE DiskDrive, _In_ UCHAR AtaUnitNumber)
 
BOOLEAN Pc98InitializeBootDevices (VOID)
 
BOOLEAN Pc98DiskReadLogicalSectors (_In_ UCHAR DriveNumber, _In_ ULONGLONG SectorNumber, _In_ ULONG SectorCount, _Out_ PVOID Buffer)
 
BOOLEAN Pc98DiskGetDriveGeometry (_In_ UCHAR DriveNumber, _Out_ PGEOMETRY Geometry)
 
ULONG Pc98DiskGetCacheableBlockCount (_In_ UCHAR DriveNumber)
 

Variables

static PC98_DISK_DRIVE Pc98DiskDrive [MAX_DRIVES]
 
static LONG lReportError = 0
 

Macro Definition Documentation

◆ MAX_DRIVES

#define MAX_DRIVES   0x100

Definition at line 19 of file pc98disk.c.

Function Documentation

◆ BytesPerSectorToSectorLengthCode()

static UCHAR BytesPerSectorToSectorLengthCode ( _In_ ULONG  BytesPerSector)
static

Definition at line 187 of file pc98disk.c.

189{
190 switch (BytesPerSector)
191 {
192 case 128:
193 return 0;
194 case 256:
195 return 1;
196 case 512:
197 return 2;
198 case 1024:
199 return 3;
200 case 2048:
201 return 4;
202 default:
203 return 0;
204 }
205}

Referenced by Pc98DiskReadLogicalSectorsCHS().

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( DISK  )

◆ DiskError()

static VOID DiskError ( _In_ PCSTR  ErrorString,
_In_ ULONG  ErrorCode 
)
static

Definition at line 78 of file pc98disk.c.

81{
82 CHAR ErrorCodeString[200];
83
84 if (lReportError < 0)
85 return;
86
87 RtlStringCbPrintfA(ErrorCodeString,
88 sizeof(ErrorCodeString),
89 "%s\n\nError Code: 0x%lx\nError: %s",
90 ErrorString,
93
94 ERR("%s\n", ErrorCodeString);
95
96 UiMessageBox(ErrorCodeString);
97}
#define ERR(fmt,...)
Definition: precomp.h:57
VOID UiMessageBox(_In_ PCSTR Format,...)
Definition: ui.c:359
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436
NTSTRSAFEVAPI RtlStringCbPrintfA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,...)
Definition: ntstrsafe.h:1148
static LONG lReportError
Definition: pc98disk.c:26
static PCSTR DiskGetErrorCodeString(_In_ ULONG ErrorCode)
Definition: pc98disk.c:42
char CHAR
Definition: xmlstorage.h:175

Referenced by Pc98DiskReadLogicalSectorsCHS(), and Pc98DiskReadLogicalSectorsLBA().

◆ DiskGetConfigType()

CONFIGURATION_TYPE DiskGetConfigType ( _In_ UCHAR  DriveNumber)

Definition at line 168 of file pc98disk.c.

170{
171 PPC98_DISK_DRIVE DiskDrive;
172
173 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber);
174 if (!DiskDrive)
175 return -1; // MaximumType;
176
177 if (DiskDrive->Type == DRIVE_TYPE_CDROM)
178 return CdromController;
179 else if (DiskDrive->Type == DRIVE_TYPE_FDD)
181 else
182 return DiskPeripheral;
183}
#define DRIVE_TYPE_CDROM
Definition: machpc98.h:117
#define DRIVE_TYPE_FDD
Definition: machpc98.h:118
PPC98_DISK_DRIVE Pc98DiskDriveNumberToDrive(_In_ UCHAR DriveNumber)
Definition: pc98disk.c:150
@ DiskPeripheral
Definition: arc.h:138
@ FloppyDiskPeripheral
Definition: arc.h:139
@ CdromController
Definition: arc.h:128

◆ DiskGetErrorCodeString()

static PCSTR DiskGetErrorCodeString ( _In_ ULONG  ErrorCode)
static

Definition at line 42 of file pc98disk.c.

44{
45 switch (ErrorCode & 0xF0)
46 {
47 case 0x00: return "No error";
48 case 0x10: return "Drive write protection error";
49 case 0x20: return "DMA access across 64 kB boundary";
50 case 0x30: return "End of cylinder";
51 case 0x40: return "The drive name is invalid or the device have low health";
52 case 0x50: return "Time out, data not written";
53 case 0x60: return "Time out, drive not ready";
54 case 0x70:
55 if (ErrorCode == 0x78)
56 return "Illegal disk address";
57 else
58 return "Drive write protection error";
59 case 0x80: return "Undefined error";
60 case 0x90: return "Time out error";
61 case 0xA0: return "CRC error in the ID section";
62 case 0xB0: return "CRC error in the DATA section";
63 case 0xC0:
64 if (ErrorCode == 0xC8)
65 return "Seek failure";
66 else
67 return "No data (Sector not found)";
68 case 0xD0: return "Bad cylinder";
69 case 0xE0: return "No ID address mark was found";
70 case 0xF0: return "No DATA address mark was found";
71
72 default: return "Unknown error code";
73 }
74}

Referenced by DiskError(), Pc98DiskReadLogicalSectorsCHS(), and Pc98DiskReadLogicalSectorsLBA().

◆ DiskReportError()

LONG DiskReportError ( _In_ BOOLEAN  bShowError)

Definition at line 29 of file pc98disk.c.

31{
32 /* Set the reference count */
33 if (bShowError)
35 else
37 return lReportError;
38}

◆ DiskResetController()

static BOOLEAN DiskResetController ( _In_ PPC98_DISK_DRIVE  DiskDrive)
static

Definition at line 103 of file pc98disk.c.

105{
106 REGS Regs;
107
108 if (DiskDrive->Type == DRIVE_TYPE_FDD)
109 {
110 /* Int 1Bh AH=07h
111 * DISK BIOS - Recalibrate
112 *
113 * Call with:
114 * AL - drive number
115 *
116 * Return:
117 * CF - set on error, clear if successful
118 * AH - status
119 */
120 Regs.b.ah = 0x07;
121 }
122 else if (DiskDrive->Type == DRIVE_TYPE_HDD)
123 {
124 /* Int 1Bh AH=03h
125 * DISK BIOS - Initialize
126 *
127 * Call with:
128 * AL - drive number
129 *
130 * Return:
131 * CF - set on error, clear if successful
132 * AH - status
133 */
134 Regs.b.ah = 0x03;
135 }
136 else
137 {
138 return FALSE;
139 }
140
141 WARN("DiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n",
142 DiskDrive->DaUa);
143
144 Regs.b.al = DiskDrive->DaUa;
145 Int386(0x1B, &Regs, &Regs);
146 return INT386_SUCCESS(Regs);
147}
#define WARN(fmt,...)
Definition: precomp.h:61
#define FALSE
Definition: types.h:117
#define DRIVE_TYPE_HDD
Definition: machpc98.h:116
#define INT386_SUCCESS(regs)
Definition: pcbios.h:181
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char al
Definition: pcbios.h:133
unsigned char ah
Definition: pcbios.h:134
Definition: pcbios.h:161
BYTEREGS b
Definition: pcbios.h:165

Referenced by Pc98DiskReadLogicalSectorsCHS(), and Pc98DiskReadLogicalSectorsLBA().

◆ InitFloppyDrive()

static BOOLEAN InitFloppyDrive ( _Out_ PPC98_DISK_DRIVE  DiskDrive,
_In_ UCHAR  DaUa 
)
static

Definition at line 500 of file pc98disk.c.

503{
504 REGS RegsIn, RegsOut;
505 ULONG BytesPerSector;
507
508 /* Int 1Bh AH=4Ah
509 * DISK BIOS - Read ID
510 *
511 * Call with:
512 * AL - drive number
513 *
514 * Return:
515 * CH - sector size
516 * CL - cylinder
517 * DH - head
518 * DL - sector
519 * CF - set on error, clear if successful
520 * AH - status
521 */
522 RegsIn.b.ah = 0x4A;
523 RegsIn.b.al = DaUa;
524 Int386(0x1B, &RegsIn, &RegsOut);
525 if (!INT386_SUCCESS(RegsOut))
526 return FALSE;
527
528 /* There is no way to obtain floppy disk geometry in BIOS */
529 DeviceAddress = DaUa & 0xF0;
530 BytesPerSector = 128 << RegsOut.b.ch;
531 switch (BytesPerSector)
532 {
533 case 256:
534 if (DeviceAddress == 0x50)
535 {
536 /* 320 kB 2DD */
537 DiskDrive->Geometry.Cylinders = 80;
538 DiskDrive->Geometry.Heads = 2;
539 DiskDrive->Geometry.SectorsPerTrack = 16;
540 }
541 else
542 {
543 /* 1 MB 2HD */
544 DiskDrive->Geometry.Cylinders = 77;
545 DiskDrive->Geometry.Heads = 2;
546 DiskDrive->Geometry.SectorsPerTrack = 26;
547 }
548 break;
549
550 case 512:
551 if (DeviceAddress == 0x30 || DeviceAddress == 0xB0)
552 {
553 /* 1.44 MB 2HD */
554 DiskDrive->Geometry.Cylinders = 80;
555 DiskDrive->Geometry.Heads = 2;
556 DiskDrive->Geometry.SectorsPerTrack = 18;
557 }
558 else if (DeviceAddress == 0x70 || DeviceAddress == 0xF0)
559 {
560 /* 720/640 kB 2DD */
561 DiskDrive->Geometry.Cylinders = 80;
562 DiskDrive->Geometry.Heads = 2;
563 DiskDrive->Geometry.SectorsPerTrack = 8;
564 }
565 else
566 {
567 /* 1.2 MB 2HC */
568 DiskDrive->Geometry.Cylinders = 80;
569 DiskDrive->Geometry.Heads = 2;
570 DiskDrive->Geometry.SectorsPerTrack = 15;
571 }
572 break;
573
574 case 1024:
575 /* 1.25 MB 2HD */
576 DiskDrive->Geometry.Cylinders = 77;
577 DiskDrive->Geometry.Heads = 2;
578 DiskDrive->Geometry.SectorsPerTrack = 8;
579 break;
580
581 default:
582 return FALSE;
583 }
584
585 DiskDrive->Geometry.BytesPerSector = BytesPerSector;
586 DiskDrive->Geometry.Sectors = (ULONGLONG)DiskDrive->Geometry.Cylinders *
587 DiskDrive->Geometry.Heads *
588 DiskDrive->Geometry.SectorsPerTrack;
589
590 DiskDrive->DaUa = DaUa;
591 DiskDrive->Type = DRIVE_TYPE_FDD;
593
594 TRACE("InitFloppyDrive(0x%x) returned:\n"
595 "Cylinders : 0x%x\n"
596 "Heads : 0x%x\n"
597 "Sects/Track: 0x%x\n"
598 "Total Sects: 0x%llx\n"
599 "Bytes/Sect : 0x%x\n",
600 DaUa,
601 DiskDrive->Geometry.Cylinders,
602 DiskDrive->Geometry.Heads,
603 DiskDrive->Geometry.SectorsPerTrack,
604 DiskDrive->Geometry.Sectors,
605 DiskDrive->Geometry.BytesPerSector);
606
607 return TRUE;
608}
#define TRUE
Definition: types.h:120
_In_ PUSB_DEVICE_HANDLE _Out_ PUSHORT DeviceAddress
Definition: hubbusif.h:360
#define DRIVE_FLAGS_REMOVABLE
Definition: machpc98.h:124
#define DRIVE_FLAGS_INITIALIZED
Definition: machpc98.h:125
#define TRACE(s)
Definition: solgame.cpp:4
unsigned char ch
Definition: pcbios.h:140
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by Pc98InitializeBootDevices().

◆ InitIdeDrive()

static BOOLEAN InitIdeDrive ( _Out_ PPC98_DISK_DRIVE  DiskDrive,
_In_ UCHAR  AtaUnitNumber 
)
static

Definition at line 612 of file pc98disk.c.

615{
616 PDEVICE_UNIT DeviceUnit = AtaGetDevice(AtaUnitNumber);
617
618 if (!DeviceUnit)
619 return FALSE;
620
621 DiskDrive->Geometry.Cylinders = DeviceUnit->Cylinders;
622 DiskDrive->Geometry.Heads = DeviceUnit->Heads;
623 DiskDrive->Geometry.SectorsPerTrack = DeviceUnit->SectorsPerTrack;
624 DiskDrive->Geometry.BytesPerSector = DeviceUnit->SectorSize;
625 DiskDrive->Geometry.Sectors = DeviceUnit->TotalSectors;
626
627 DiskDrive->DaUa = 0xFF; // Invalid
628 DiskDrive->AtaUnitNumber = AtaUnitNumber;
629 DiskDrive->Flags = DRIVE_FLAGS_IDE | DRIVE_FLAGS_INITIALIZED;
630
631 if (DeviceUnit->Flags & ATA_DEVICE_LBA)
632 DiskDrive->Flags |= DRIVE_FLAGS_LBA;
633
634 if (DeviceUnit->Flags & ATA_DEVICE_ATAPI)
635 {
636 DiskDrive->Type = DRIVE_TYPE_CDROM;
637 DiskDrive->Flags |= DRIVE_FLAGS_REMOVABLE;
638 }
639 else
640 {
641 DiskDrive->Type = DRIVE_TYPE_HDD;
642 }
643
644 TRACE("InitIdeDrive(0x%x) returned:\n"
645 "Cylinders : 0x%x\n"
646 "Heads : 0x%x\n"
647 "Sects/Track: 0x%x\n"
648 "Total Sects: 0x%llx\n"
649 "Bytes/Sect : 0x%x\n",
650 AtaUnitNumber,
651 DiskDrive->Geometry.Cylinders,
652 DiskDrive->Geometry.Heads,
653 DiskDrive->Geometry.SectorsPerTrack,
654 DiskDrive->Geometry.Sectors,
655 DiskDrive->Geometry.BytesPerSector);
656 return TRUE;
657}
PDEVICE_UNIT AtaGetDevice(_In_ UCHAR UnitNumber)
Definition: hwide.c:1270
#define ATA_DEVICE_LBA
Definition: hwide.h:31
#define ATA_DEVICE_ATAPI
Definition: hwide.h:30
#define DRIVE_FLAGS_IDE
Definition: machpc98.h:122
#define DRIVE_FLAGS_LBA
Definition: machpc98.h:123
Data structure for the ATA device.
Definition: hwide.h:12
ULONG Cylinders
Definition: hwide.h:14
ULONG SectorSize
Definition: hwide.h:23
ULONG SectorsPerTrack
Definition: hwide.h:20
ULONG64 TotalSectors
Definition: hwide.h:26
ULONG Flags
Definition: hwide.h:29
ULONG Heads
Definition: hwide.h:17

Referenced by Pc98InitializeBootDevices().

◆ InitScsiDrive()

static BOOLEAN InitScsiDrive ( _Out_ PPC98_DISK_DRIVE  DiskDrive,
_In_ UCHAR  DaUa 
)
static

Definition at line 401 of file pc98disk.c.

404{
405 REGS RegsIn, RegsOut;
406 UCHAR UnitAddress = DaUa & 0x0F;
407 USHORT DiskEquipment = *(PUCHAR)MEM_DISK_EQUIPS;
408 ULONG ScsiParameters = *(PULONG)(MEM_SCSI_TABLE + UnitAddress * sizeof(ULONG));
409
410 /* Hard drives */
411 if (DiskEquipment & (1 << UnitAddress))
412 {
413 /* Int 1Bh AH=84h
414 * DISK BIOS - Sense
415 *
416 * Call with:
417 * AL - drive number
418 *
419 * Return:
420 * BX - bytes per sector
421 * CX - cylinders number
422 * DH - heads number
423 * DL - sectors number
424 * CF - set on error, clear if successful
425 * AH - status
426 */
427 RegsIn.b.al = DaUa;
428 RegsIn.b.ah = 0x84;
429 Int386(0x1B, &RegsIn, &RegsOut);
430 if (!INT386_SUCCESS(RegsOut) || RegsOut.w.cx == 0)
431 return FALSE;
432
433 DiskDrive->Geometry.Cylinders = RegsOut.w.cx;
434 DiskDrive->Geometry.Heads = RegsOut.b.dh;
435 DiskDrive->Geometry.SectorsPerTrack = RegsOut.b.dl;
436 DiskDrive->Geometry.BytesPerSector = RegsOut.w.bx;
437 }
438 /* Other devices */
439 else if (ScsiParameters != 0)
440 {
441 UCHAR DeviceType = ScsiParameters & 0x1F;
442 switch (DeviceType)
443 {
444 case 0x05:
445 /* CD-ROM */
446 DiskDrive->Geometry.Cylinders = 0xFFFF;
447 DiskDrive->Geometry.Heads = 0xFFFF;
448 DiskDrive->Geometry.SectorsPerTrack = 0xFFFF;
449 DiskDrive->Geometry.BytesPerSector = 2048;
450
451 DiskDrive->Type = DRIVE_TYPE_CDROM;
452 DiskDrive->Flags = DRIVE_FLAGS_LBA | DRIVE_FLAGS_REMOVABLE;
453 break;
454
455 case 0x07:
456 /* Magneto-optical drive */
457 DiskDrive->Geometry.Cylinders = 0xFFFF;
458 DiskDrive->Geometry.Heads = 8;
459 DiskDrive->Geometry.SectorsPerTrack = 32;
460 DiskDrive->Geometry.BytesPerSector = 512;
461
462 DiskDrive->Type = DRIVE_TYPE_CDROM;
463 DiskDrive->Flags = DRIVE_FLAGS_LBA | DRIVE_FLAGS_REMOVABLE;
464 break;
465
466 default:
467 return FALSE;
468 }
469 }
470 else
471 {
472 return FALSE;
473 }
474
475 DiskDrive->Flags |= DRIVE_FLAGS_INITIALIZED;
476 DiskDrive->DaUa = DaUa;
477
478 DiskDrive->Geometry.Sectors = (ULONGLONG)DiskDrive->Geometry.Cylinders *
479 DiskDrive->Geometry.Heads *
480 DiskDrive->Geometry.SectorsPerTrack;
481
482 TRACE("InitScsiDrive(0x%x) returned:\n"
483 "Cylinders : 0x%x\n"
484 "Heads : 0x%x\n"
485 "Sects/Track: 0x%x\n"
486 "Total Sects: 0x%llx\n"
487 "Bytes/Sect : 0x%x\n",
488 DaUa,
489 DiskDrive->Geometry.Cylinders,
490 DiskDrive->Geometry.Heads,
491 DiskDrive->Geometry.SectorsPerTrack,
492 DiskDrive->Geometry.Sectors,
493 DiskDrive->Geometry.BytesPerSector);
494
495 return TRUE;
496}
#define MEM_SCSI_TABLE
Definition: machpc98.h:24
#define MEM_DISK_EQUIPS
Definition: machpc98.h:30
DeviceType
Definition: mmdrv.h:42
unsigned short USHORT
Definition: pedump.c:61
unsigned char dl
Definition: pcbios.h:142
unsigned char dh
Definition: pcbios.h:143
unsigned short cx
Definition: pcbios.h:115
unsigned short bx
Definition: pcbios.h:114
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char * PUCHAR
Definition: typedefs.h:53
WORDREGS w
Definition: pcbios.h:164

Referenced by Pc98InitializeBootDevices().

◆ Pc98DiskDriveNumberToDrive()

PPC98_DISK_DRIVE Pc98DiskDriveNumberToDrive ( _In_ UCHAR  DriveNumber)

Definition at line 150 of file pc98disk.c.

152{
153 PPC98_DISK_DRIVE DiskDrive;
154
155 ASSERT(DriveNumber < RTL_NUMBER_OF(Pc98DiskDrive));
156
157 /* Retrieve a slot */
158 DiskDrive = &Pc98DiskDrive[DriveNumber];
159
160 /* The pre-initialization of the BIOS disks was already done in Pc98InitializeBootDevices() */
161 if (DiskDrive->Flags & DRIVE_FLAGS_INITIALIZED)
162 return DiskDrive;
163 else
164 return NULL;
165}
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define NULL
Definition: types.h:112
#define ASSERT(a)
Definition: mode.c:44
static PC98_DISK_DRIVE Pc98DiskDrive[MAX_DRIVES]
Definition: pc98disk.c:22

Referenced by ChainLoadBiosBootSectorCode(), DiskGetConfigType(), Pc98DiskGetCacheableBlockCount(), Pc98DiskGetDriveGeometry(), Pc98DiskReadLogicalSectors(), and Pc98GetBootSectorLoadAddress().

◆ Pc98DiskGetCacheableBlockCount()

ULONG Pc98DiskGetCacheableBlockCount ( _In_ UCHAR  DriveNumber)

Definition at line 810 of file pc98disk.c.

812{
813 PPC98_DISK_DRIVE DiskDrive;
814
815 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber);
816 if (!DiskDrive)
817 return 1; // Unknown count.
818
819 /*
820 * If LBA is supported then the block size will be 64 sectors (32k).
821 * If not then the block size is the size of one track.
822 */
823 if (DiskDrive->Flags & DRIVE_FLAGS_LBA)
824 return 64;
825 else
826 return DiskDrive->Geometry.SectorsPerTrack;
827}
ULONG SectorsPerTrack
Number of sectors per track.
Definition: disk.h:29
GEOMETRY Geometry
Definition: machpc98.h:106

Referenced by MachInit().

◆ Pc98DiskGetDriveGeometry()

BOOLEAN Pc98DiskGetDriveGeometry ( _In_ UCHAR  DriveNumber,
_Out_ PGEOMETRY  Geometry 
)

Definition at line 792 of file pc98disk.c.

795{
796 PPC98_DISK_DRIVE DiskDrive;
797
798 TRACE("Pc98DiskGetDriveGeometry(0x%x)\n", DriveNumber);
799
800 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber);
801 if (!DiskDrive)
802 return FALSE;
803
804 *Geometry = DiskDrive->Geometry;
805
806 return TRUE;
807}

Referenced by DetectBiosDisks(), MachInit(), and Pc98GetHarddiskConfigurationData().

◆ Pc98DiskReadLogicalSectors()

BOOLEAN Pc98DiskReadLogicalSectors ( _In_ UCHAR  DriveNumber,
_In_ ULONGLONG  SectorNumber,
_In_ ULONG  SectorCount,
_Out_ PVOID  Buffer 
)

Definition at line 752 of file pc98disk.c.

757{
758 PPC98_DISK_DRIVE DiskDrive;
759
760 TRACE("Pc98DiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %I64u SectorCount: %u Buffer: 0x%x\n",
761 DriveNumber, SectorNumber, SectorCount, Buffer);
762
763 /* 16-bit BIOS addressing limitation */
764 ASSERT(((ULONG_PTR)Buffer) <= 0xFFFFF);
765
766 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber);
767 if (!DiskDrive)
768 return FALSE;
769
770 if (DiskDrive->Flags & DRIVE_FLAGS_IDE)
771 {
773 SectorNumber,
775 Buffer);
776 }
777 else if (DiskDrive->Flags & DRIVE_FLAGS_LBA)
778 {
779 /* LBA is easy, nothing to calculate. Just do the read. */
780 TRACE("--> Using LBA\n");
781 return Pc98DiskReadLogicalSectorsLBA(DiskDrive, SectorNumber, SectorCount, Buffer);
782 }
783 else
784 {
785 /* LBA is not supported, default to CHS */
786 TRACE("--> Using CHS\n");
787 return Pc98DiskReadLogicalSectorsCHS(DiskDrive, SectorNumber, SectorCount, Buffer);
788 }
789}
Definition: bufpool.h:45
BOOLEAN AtaReadLogicalSectors(_In_ PDEVICE_UNIT DeviceUnit, _In_ ULONG64 SectorNumber, _In_ ULONG SectorCount, _Out_writes_bytes_all_(SectorCount *DeviceUnit->SectorSize) PVOID Buffer)
Definition: hwide.c:1230
ULONG SectorCount
Definition: part_xbox.c:31
static BOOLEAN Pc98DiskReadLogicalSectorsCHS(_In_ PPC98_DISK_DRIVE DiskDrive, _In_ ULONG64 SectorNumber, _In_ ULONG SectorCount, _Out_writes_bytes_all_(SectorCount *DiskDrive->Geometry.BytesPerSector) PVOID Buffer)
Definition: pc98disk.c:266
static BOOLEAN Pc98DiskReadLogicalSectorsLBA(_In_ PPC98_DISK_DRIVE DiskDrive, _In_ ULONG64 SectorNumber, _In_ ULONG SectorCount, _Out_writes_bytes_all_(SectorCount *DiskDrive->Geometry.BytesPerSector) PVOID Buffer)
Definition: pc98disk.c:209
UCHAR AtaUnitNumber
Definition: machpc98.h:112
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by MachInit().

◆ Pc98DiskReadLogicalSectorsCHS()

static BOOLEAN Pc98DiskReadLogicalSectorsCHS ( _In_ PPC98_DISK_DRIVE  DiskDrive,
_In_ ULONG64  SectorNumber,
_In_ ULONG  SectorCount,
_Out_writes_bytes_all_(SectorCount *DiskDrive->Geometry.BytesPerSector) PVOID  Buffer 
)
static

Definition at line 266 of file pc98disk.c.

271{
272 UCHAR PhysicalSector;
273 UCHAR PhysicalHead;
274 ULONG PhysicalTrack;
275 GEOMETRY DriveGeometry;
276 ULONG NumberOfSectorsToRead;
277 REGS RegsIn, RegsOut;
278 ULONG RetryCount;
279
280 DriveGeometry = DiskDrive->Geometry;
281
282 while (SectorCount > 0)
283 {
284 /*
285 * Calculate the physical disk offsets.
286 * Note: DriveGeometry.SectorsPerTrack < 64
287 */
288 PhysicalSector = (UCHAR)(SectorNumber % DriveGeometry.SectorsPerTrack);
289 PhysicalHead = (UCHAR)((SectorNumber / DriveGeometry.SectorsPerTrack) % DriveGeometry.Heads);
290 PhysicalTrack = (ULONG)((SectorNumber / DriveGeometry.SectorsPerTrack) / DriveGeometry.Heads);
291
292 /* Floppy sectors value always start at 1 */
293 if (DiskDrive->Type == DRIVE_TYPE_FDD)
294 ++PhysicalSector;
295
296 /* Calculate how many sectors we need to read this round */
297 if (PhysicalSector > 1)
298 {
299 NumberOfSectorsToRead = min(SectorCount,
300 (DriveGeometry.SectorsPerTrack - (PhysicalSector - 1)));
301 }
302 else
303 {
304 NumberOfSectorsToRead = min(SectorCount, DriveGeometry.SectorsPerTrack);
305 }
306
307 /* Make sure the read is within the geometry boundaries */
308 if ((PhysicalHead >= DriveGeometry.Heads) ||
309 (PhysicalTrack >= DriveGeometry.Cylinders) ||
310 ((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.SectorsPerTrack + 1)) ||
311 (PhysicalSector > DriveGeometry.SectorsPerTrack))
312 {
313 DiskError("Disk read exceeds drive geometry limits.", 0);
314 return FALSE;
315 }
316
317 if (DiskDrive->Type == DRIVE_TYPE_FDD)
318 {
319 /* Int 1Bh AH=x6h
320 * DISK BIOS - Read data
321 *
322 * Call with:
323 * AL - drive number
324 * BX - bytes to read
325 * CH - sector length code
326 * CL - cylinder number
327 * DH - head number
328 * DL - sector number
329 * ES:BP -> buffer to read data into
330 *
331 * Return:
332 * CF - set on error, clear if successful
333 * AH - status
334 */
335 RegsIn.b.ah = 0x56; /* With SEEK, and use double-density format (MFM) */
336 RegsIn.w.bx = DriveGeometry.BytesPerSector * (UCHAR)NumberOfSectorsToRead;
337 RegsIn.b.cl = PhysicalTrack & 0xFFFF;
338 RegsIn.b.ch = BytesPerSectorToSectorLengthCode(DriveGeometry.BytesPerSector);
339 }
340 else
341 {
342 /* Int 1Bh AH=06h
343 * DISK BIOS - Read data
344 *
345 * Call with:
346 * AL - drive number
347 * BX - bytes to read
348 * CX - cylinder number
349 * DH - head number
350 * DL - sector number
351 * ES:BP -> buffer to read data into
352 *
353 * Return:
354 * CF - set on error, clear if successful
355 * AH - status
356 */
357 RegsIn.b.ah = 0x06;
358 RegsIn.w.bx = DriveGeometry.BytesPerSector * (UCHAR)NumberOfSectorsToRead;
359 RegsIn.w.cx = PhysicalTrack & 0xFFFF;
360 }
361 RegsIn.b.al = DiskDrive->DaUa;
362 RegsIn.b.dl = PhysicalSector;
363 RegsIn.b.dh = PhysicalHead;
364 RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4);
365 RegsIn.w.bp = ((ULONG_PTR)Buffer) & 0x0F;
366
367 /* Perform the read. Retry 3 times. */
368 for (RetryCount = 0; RetryCount < 3; ++RetryCount)
369 {
370 Int386(0x1B, &RegsIn, &RegsOut);
371
372 /* If it worked, or if it was a corrected ECC error
373 * and the data is still good, return success */
374 if (INT386_SUCCESS(RegsOut) || (RegsOut.b.ah == 0x08))
375 break;
376
377 /* It failed, do the next retry */
378 DiskResetController(DiskDrive);
379 }
380
381 /* If we retried 3 times then fail */
382 if (RetryCount >= 3)
383 {
384 DiskError("Disk Read Failed in CHS mode, after retrying 3 times", RegsOut.b.ah);
385 ERR("Disk Read Failed in CHS mode, after retrying 3 times: %x (%s) (DriveNumber: 0x%x SectorNumber: %I64u SectorCount: %u)\n",
386 RegsOut.b.ah, DiskGetErrorCodeString(RegsOut.b.ah),
387 DiskDrive->DaUa, SectorNumber, SectorCount);
388 return FALSE;
389 }
390
391 Buffer = (PVOID)((ULONG_PTR)Buffer + (NumberOfSectorsToRead * DriveGeometry.BytesPerSector));
392 SectorCount -= NumberOfSectorsToRead;
393 SectorNumber += NumberOfSectorsToRead;
394 }
395
396 return TRUE;
397}
#define ULONG_PTR
Definition: config.h:101
#define min(a, b)
Definition: monoChain.cc:55
static VOID DiskError(_In_ PCSTR ErrorString, _In_ ULONG ErrorCode)
Definition: pc98disk.c:78
static UCHAR BytesPerSectorToSectorLengthCode(_In_ ULONG BytesPerSector)
Definition: pc98disk.c:187
static BOOLEAN DiskResetController(_In_ PPC98_DISK_DRIVE DiskDrive)
Definition: pc98disk.c:103
unsigned char cl
Definition: pcbios.h:139
unsigned short bp
Definition: pcbios.h:120
unsigned short es
Definition: pcbios.h:123
Definition: disk.h:26
ULONG BytesPerSector
Number of bytes per sector.
Definition: disk.h:30
ULONG Cylinders
Number of cylinders on the disk.
Definition: disk.h:27
ULONG Heads
Number of heads on the disk.
Definition: disk.h:28
void * PVOID
Definition: typedefs.h:50

Referenced by Pc98DiskReadLogicalSectors().

◆ Pc98DiskReadLogicalSectorsLBA()

static BOOLEAN Pc98DiskReadLogicalSectorsLBA ( _In_ PPC98_DISK_DRIVE  DiskDrive,
_In_ ULONG64  SectorNumber,
_In_ ULONG  SectorCount,
_Out_writes_bytes_all_(SectorCount *DiskDrive->Geometry.BytesPerSector) PVOID  Buffer 
)
static

Definition at line 209 of file pc98disk.c.

214{
215 REGS RegsIn, RegsOut;
216 ULONG RetryCount;
217
218 /* Int 1Bh AH=06h
219 * DISK BIOS - Read data
220 *
221 * Call with:
222 * AL - drive number
223 * BX - bytes to read
224 * CX - cylinder number
225 * DH - head number
226 * DL - sector number
227 * ES:BP -> buffer to read data into
228 *
229 * Return:
230 * CF - set on error, clear if successful
231 * AH - status
232 */
233 RegsIn.b.al = DiskDrive->DaUa;
234 RegsIn.b.ah = 0x06;
235 RegsIn.w.bx = DiskDrive->Geometry.BytesPerSector * SectorCount;
236 RegsIn.w.cx = SectorNumber & 0xFFFF;
237 RegsIn.w.dx = (SectorNumber >> 16) & 0xFFFF;
238 RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4);
239 RegsIn.w.bp = ((ULONG_PTR)Buffer) & 0x0F;
240
241 /* Retry 3 times */
242 for (RetryCount = 0; RetryCount < 3; ++RetryCount)
243 {
244 Int386(0x1B, &RegsIn, &RegsOut);
245
246 /* If it worked, or if it was a corrected ECC error
247 * and the data is still good, return success */
248 if (INT386_SUCCESS(RegsOut) || (RegsOut.b.ah == 0x08))
249 return TRUE;
250
251 /* It failed, do the next retry */
252 DiskResetController(DiskDrive);
253 }
254
255 /* If we get here then the read failed */
256 DiskError("Disk Read Failed in LBA mode", RegsOut.b.ah);
257 ERR("Disk Read Failed in LBA mode: %x (%s) (DriveNumber: 0x%x SectorNumber: %I64u SectorCount: %u)\n",
258 RegsOut.b.ah, DiskGetErrorCodeString(RegsOut.b.ah),
259 DiskDrive->DaUa, SectorNumber, SectorCount);
260
261 return FALSE;
262}
unsigned short dx
Definition: pcbios.h:116

Referenced by Pc98DiskReadLogicalSectors().

◆ Pc98InitializeBootDevices()

BOOLEAN Pc98InitializeBootDevices ( VOID  )

Definition at line 660 of file pc98disk.c.

661{
662 USHORT DiskEquipment = *(PUSHORT)MEM_DISK_EQUIP & ~(*(PUCHAR)MEM_RDISK_EQUIP);
663 PPC98_DISK_DRIVE DiskDrive;
664 UCHAR BiosFloppyDriveNumber, BiosHardDriveDriveNumber, IdeDetectedCount;
665 ULONG i;
666
667 TRACE("Pc98InitializeBootDevices()\n");
668
670
671 /*
672 * We emulate the standard PC BIOS drive numbers here. Map DA/UA to a drive number, i.e.
673 * 0x90 -> 0x30
674 * 0x80 -> 0x80
675 * 0xA0 -> 0x81, etc.
676 */
677 BiosFloppyDriveNumber = 0x30;
678 BiosHardDriveDriveNumber = 0x80;
679
680 /* Map floppies */
681 for (i = 0; i < 4; i++)
682 {
683 DiskDrive = &Pc98DiskDrive[BiosFloppyDriveNumber];
684 if (FIRSTBYTE(DiskEquipment) & (1 << i))
685 {
686 if (InitFloppyDrive(DiskDrive, 0x30 + i) || InitFloppyDrive(DiskDrive, 0xB0 + i) ||
687 InitFloppyDrive(DiskDrive, 0x90 + i) || InitFloppyDrive(DiskDrive, 0x10 + i))
688 ++BiosFloppyDriveNumber;
689 }
690 }
691 for (i = 0; i < 4; i++)
692 {
693 DiskDrive = &Pc98DiskDrive[BiosFloppyDriveNumber];
694 if (FIRSTBYTE(DiskEquipment) & (16 << i))
695 {
696 if (InitFloppyDrive(DiskDrive, 0x50 + i))
697 ++BiosFloppyDriveNumber;
698 }
699 }
700 for (i = 0; i < 4; i++)
701 {
702 DiskDrive = &Pc98DiskDrive[BiosFloppyDriveNumber];
703 if (SECONDBYTE(DiskEquipment) & (16 << i))
704 {
705 if (InitFloppyDrive(DiskDrive, 0x70 + i) || InitFloppyDrive(DiskDrive, 0xF0 + i))
706 ++BiosFloppyDriveNumber;
707 }
708 }
709
710 /*
711 * Map IDE drives. We provide our own IDE boot support because of IDE BIOS
712 * that cannot boot from a CD-ROM and has LBA limitations.
713 */
714 AtaInit(&IdeDetectedCount);
715 for (i = 0; i <= IdeDetectedCount; i++)
716 {
717 DiskDrive = &Pc98DiskDrive[BiosHardDriveDriveNumber];
718 if (InitIdeDrive(DiskDrive, i))
719 ++BiosHardDriveDriveNumber;
720 }
721
722 /* Map SCSI drives */
723 for (i = 0; i < 7; i++)
724 {
725 DiskDrive = &Pc98DiskDrive[BiosHardDriveDriveNumber];
726 if (InitScsiDrive(DiskDrive, 0xA0 + i) || InitScsiDrive(DiskDrive, 0x20 + i))
727 ++BiosHardDriveDriveNumber;
728 }
729
730 // Ugly HACK: Force ISO boot
731 // FIXME: Fill ARC disk blocks completely
732 // to allow usage of CD-ROM root path (See floppy_pc98.ini).
733 for (i = 0x80; i < RTL_NUMBER_OF(Pc98DiskDrive); i++)
734 {
735 DiskDrive = &Pc98DiskDrive[i];
736
737 if ((DiskDrive->Flags & DRIVE_FLAGS_INITIALIZED) &&
738 (DiskDrive->Flags & DRIVE_FLAGS_IDE) &&
739 (DiskDrive->Type == DRIVE_TYPE_CDROM))
740 {
742 FrldrBootPartition = 0xFF;
743 break;
744 }
745 }
746
747 /* Call PC version */
749}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
BOOLEAN PcInitializeBootDevices(VOID)
Definition: hwdisk.c:458
BOOLEAN AtaInit(_Out_ PUCHAR DetectedCount)
Definition: hwide.c:1280
#define MEM_RDISK_EQUIP
Definition: machpc98.h:33
#define MEM_DISK_EQUIP
Definition: machpc98.h:41
static BOOLEAN InitScsiDrive(_Out_ PPC98_DISK_DRIVE DiskDrive, _In_ UCHAR DaUa)
Definition: pc98disk.c:401
static BOOLEAN InitFloppyDrive(_Out_ PPC98_DISK_DRIVE DiskDrive, _In_ UCHAR DaUa)
Definition: pc98disk.c:500
static BOOLEAN InitIdeDrive(_Out_ PPC98_DISK_DRIVE DiskDrive, _In_ UCHAR AtaUnitNumber)
Definition: pc98disk.c:612
uint16_t * PUSHORT
Definition: typedefs.h:56
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
UCHAR FrldrBootDrive
Definition: uefidisk.c:105
ULONG FrldrBootPartition
Definition: uefidisk.c:106
#define SECONDBYTE(VALUE)
Definition: rtlfuncs.h:807
#define FIRSTBYTE(VALUE)
Definition: rtlfuncs.h:806

Referenced by MachInit().

Variable Documentation

◆ lReportError

LONG lReportError = 0
static

Definition at line 26 of file pc98disk.c.

Referenced by DiskError(), and DiskReportError().

◆ Pc98DiskDrive

PC98_DISK_DRIVE Pc98DiskDrive[MAX_DRIVES]
static

Definition at line 22 of file pc98disk.c.

Referenced by Pc98DiskDriveNumberToDrive(), and Pc98InitializeBootDevices().