ReactOS 0.4.16-dev-1946-g52006dd
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 (BOOLEAN bShowError)
 
static PCSTR DiskGetErrorCodeString (ULONG ErrorCode)
 
static VOID DiskError (PCSTR ErrorString, ULONG ErrorCode)
 
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 ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
 
static BOOLEAN Pc98DiskReadLogicalSectorsCHS (IN PPC98_DISK_DRIVE DiskDrive, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
 
static BOOLEAN InitScsiDrive (IN UCHAR DaUa, IN OUT PPC98_DISK_DRIVE DiskDrive)
 
static BOOLEAN InitIdeDrive (IN UCHAR UnitNumber, IN OUT PPC98_DISK_DRIVE DiskDrive)
 
static BOOLEAN InitHardDrive (IN UCHAR DaUa, IN OUT PPC98_DISK_DRIVE DiskDrive)
 
static BOOLEAN InitFloppyDrive (IN UCHAR DaUa, IN OUT PPC98_DISK_DRIVE DiskDrive)
 
BOOLEAN Pc98InitializeBootDevices (VOID)
 
BOOLEAN Pc98DiskReadLogicalSectors (IN UCHAR DriveNumber, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
 
BOOLEAN Pc98DiskGetDriveGeometry (UCHAR DriveNumber, PGEOMETRY Geometry)
 
ULONG Pc98DiskGetCacheableBlockCount (UCHAR DriveNumber)
 

Variables

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)
inlinestatic

Definition at line 172 of file pc98disk.c.

173{
174 switch (BytesPerSector)
175 {
176 case 128:
177 return 0;
178 case 256:
179 return 1;
180 case 512:
181 return 2;
182 case 1024:
183 return 3;
184 case 2048:
185 return 4;
186 default:
187 return 0;
188 }
189}

Referenced by Pc98DiskReadLogicalSectorsCHS().

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( DISK  )

◆ DiskError()

static VOID DiskError ( PCSTR  ErrorString,
ULONG  ErrorCode 
)
static

Definition at line 74 of file pc98disk.c.

75{
76 CHAR ErrorCodeString[200];
77
78 if (lReportError < 0)
79 return;
80
81 RtlStringCbPrintfA(ErrorCodeString, sizeof(ErrorCodeString), "%s\n\nError Code: 0x%lx\nError: %s",
83
84 ERR("%s\n", ErrorCodeString);
85
86 UiMessageBox(ErrorCodeString);
87}
#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(ULONG ErrorCode)
Definition: pc98disk.c:40
char CHAR
Definition: xmlstorage.h:175

Referenced by Pc98DiskReadLogicalSectorsCHS(), and Pc98DiskReadLogicalSectorsLBA().

◆ DiskGetConfigType()

CONFIGURATION_TYPE DiskGetConfigType ( _In_ UCHAR  DriveNumber)

Definition at line 153 of file pc98disk.c.

155{
156 PPC98_DISK_DRIVE DiskDrive;
157
158 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber);
159 if (!DiskDrive)
160 return -1; // MaximumType;
161
162 if (DiskDrive->Type & DRIVE_CDROM || DiskDrive->Type & DRIVE_MO)
163 return CdromController;
164 else if (DiskDrive->Type & DRIVE_FDD)
166 else
167 return DiskPeripheral;
168}
#define DRIVE_MO
Definition: machpc98.h:121
#define DRIVE_CDROM
Definition: machpc98.h:119
#define DRIVE_FDD
Definition: machpc98.h:120
PPC98_DISK_DRIVE Pc98DiskDriveNumberToDrive(IN UCHAR DriveNumber)
Definition: pc98disk.c:136
@ DiskPeripheral
Definition: arc.h:138
@ FloppyDiskPeripheral
Definition: arc.h:139
@ CdromController
Definition: arc.h:128

◆ DiskGetErrorCodeString()

static PCSTR DiskGetErrorCodeString ( ULONG  ErrorCode)
static

Definition at line 40 of file pc98disk.c.

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

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

◆ DiskReportError()

LONG DiskReportError ( BOOLEAN  bShowError)

Definition at line 29 of file pc98disk.c.

30{
31 /* Set the reference count */
32 if (bShowError)
34 else
36 return lReportError;
37}

◆ DiskResetController()

BOOLEAN DiskResetController ( IN PPC98_DISK_DRIVE  DiskDrive)

Definition at line 91 of file pc98disk.c.

92{
93 REGS Regs;
94
95 if (DiskDrive->Type & DRIVE_FDD)
96 {
97 /* Int 1Bh AH=07h
98 * DISK BIOS - Recalibrate
99 *
100 * Call with:
101 * AL - drive number
102 *
103 * Return:
104 * CF - set on error, clear if successful
105 * AH - status
106 */
107 Regs.b.ah = 0x07;
108 }
109 else if (DiskDrive->Type != (DRIVE_IDE | DRIVE_CDROM))
110 {
111 /* Int 1Bh AH=03h
112 * DISK BIOS - Initialize
113 *
114 * Call with:
115 * AL - drive number
116 *
117 * Return:
118 * CF - set on error, clear if successful
119 * AH - status
120 */
121 Regs.b.ah = 0x03;
122 }
123 else
124 {
125 return FALSE;
126 }
127
128 WARN("DiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n", DiskDrive->DaUa);
129
130 Regs.b.al = DiskDrive->DaUa;
131 Int386(0x1B, &Regs, &Regs);
132 return INT386_SUCCESS(Regs);
133}
#define WARN(fmt,...)
Definition: precomp.h:61
#define FALSE
Definition: types.h:117
#define DRIVE_IDE
Definition: machpc98.h:117
#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 ( IN UCHAR  DaUa,
IN OUT PPC98_DISK_DRIVE  DiskDrive 
)
static

Definition at line 615 of file pc98disk.c.

618{
619 REGS RegsIn, RegsOut;
620 USHORT BytesPerSector;
621 UCHAR DeviceAddress = DaUa & 0xF0;
622
623 /* There's no way to obtain floppy disk geometry in BIOS */
624
625 /* Int 1Bh AH=4Ah
626 * DISK BIOS - Read ID
627 *
628 * Call with:
629 * AL - drive number
630 *
631 * Return:
632 * CH - sector size
633 * CL - cylinder
634 * DH - head
635 * DL - sector
636 * CF - set on error, clear if successful
637 * AH - status
638 */
639 RegsIn.b.ah = 0x4A;
640 RegsIn.b.al = DaUa;
641 Int386(0x1B, &RegsIn, &RegsOut);
642 if (!INT386_SUCCESS(RegsOut))
643 {
644 DiskDrive->Initialized = FALSE;
645 return FALSE;
646 }
647
648 BytesPerSector = 128 << RegsOut.b.ch;
649 switch (BytesPerSector)
650 {
651 case 256:
652 if (DeviceAddress == 0x50)
653 {
654 /* 320 kB 2DD */
655 DiskDrive->Geometry.Cylinders = 80;
656 DiskDrive->Geometry.Heads = 2;
657 DiskDrive->Geometry.SectorsPerTrack = 16;
658 }
659 else
660 {
661 /* 1 MB 2HD */
662 DiskDrive->Geometry.Cylinders = 77;
663 DiskDrive->Geometry.Heads = 2;
664 DiskDrive->Geometry.SectorsPerTrack = 26;
665 }
666 break;
667
668 case 512:
669 if (DeviceAddress == 0x30 || DeviceAddress == 0xB0)
670 {
671 /* 1.44 MB 2HD */
672 DiskDrive->Geometry.Cylinders = 80;
673 DiskDrive->Geometry.Heads = 2;
674 DiskDrive->Geometry.SectorsPerTrack = 18;
675 }
676 else if (DeviceAddress == 0x70 || DeviceAddress == 0xF0)
677 {
678 /* 720/640 kB 2DD */
679 DiskDrive->Geometry.Cylinders = 80;
680 DiskDrive->Geometry.Heads = 2;
681 DiskDrive->Geometry.SectorsPerTrack = 8;
682 }
683 else
684 {
685 /* 1.2 MB 2HC */
686 DiskDrive->Geometry.Cylinders = 80;
687 DiskDrive->Geometry.Heads = 2;
688 DiskDrive->Geometry.SectorsPerTrack = 15;
689 }
690 break;
691
692 case 1024:
693 /* 1.25 MB 2HD */
694 DiskDrive->Geometry.Cylinders = 77;
695 DiskDrive->Geometry.Heads = 2;
696 DiskDrive->Geometry.SectorsPerTrack = 8;
697 break;
698
699 default:
700 DiskDrive->Initialized = FALSE;
701 return FALSE;
702 }
703
704 DiskDrive->Geometry.BytesPerSector = BytesPerSector;
705 DiskDrive->Geometry.Sectors = (ULONGLONG)DiskDrive->Geometry.Cylinders *
706 DiskDrive->Geometry.Heads *
707 DiskDrive->Geometry.SectorsPerTrack;
708
709 DiskDrive->DaUa = DaUa;
710 DiskDrive->Type = DRIVE_FDD;
711 DiskDrive->LBASupported = FALSE;
712 DiskDrive->IsRemovable = TRUE;
713 DiskDrive->Initialized = TRUE;
714
715 TRACE("InitFloppyDrive(0x%x) returned:\n"
716 "Cylinders : 0x%x\n"
717 "Heads : 0x%x\n"
718 "Sects/Track: 0x%x\n"
719 "Total Sects: 0x%llx\n"
720 "Bytes/Sect : 0x%x\n",
721 DaUa,
722 DiskDrive->Geometry.Cylinders,
723 DiskDrive->Geometry.Heads,
724 DiskDrive->Geometry.SectorsPerTrack,
725 DiskDrive->Geometry.Sectors,
726 DiskDrive->Geometry.BytesPerSector);
727
728 return TRUE;
729}
#define TRUE
Definition: types.h:120
_In_ PUSB_DEVICE_HANDLE _Out_ PUSHORT DeviceAddress
Definition: hubbusif.h:360
unsigned short USHORT
Definition: pedump.c:61
#define TRACE(s)
Definition: solgame.cpp:4
unsigned char ch
Definition: pcbios.h:140
uint64_t ULONGLONG
Definition: typedefs.h:67
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by Pc98InitializeBootDevices().

◆ InitHardDrive()

static BOOLEAN InitHardDrive ( IN UCHAR  DaUa,
IN OUT PPC98_DISK_DRIVE  DiskDrive 
)
static

Definition at line 544 of file pc98disk.c.

547{
548 REGS RegsIn, RegsOut;
549
550 /* Int 1Bh AH=8Eh
551 * DISK BIOS - Set half-height operation mode
552 *
553 * Call with:
554 * AL - drive number
555 */
556 RegsIn.b.al = DaUa;
557 RegsIn.b.ah = 0x8E;
558 Int386(0x1B, &RegsIn, &RegsOut);
559
560 /* Int 1Bh AH=84h
561 * DISK BIOS - Sense
562 *
563 * Call with:
564 * AL - drive number
565 *
566 * Return:
567 * BX - bytes per sector
568 * CX - cylinders number
569 * DH - heads number
570 * DL - sectors number
571 * CF - set on error, clear if successful
572 * AH - status
573 */
574 RegsIn.b.al = DaUa;
575 RegsIn.b.ah = 0x84;
576 Int386(0x1B, &RegsIn, &RegsOut);
577 if (!INT386_SUCCESS(RegsOut) || RegsOut.w.cx == 0)
578 {
579 DiskDrive->Initialized = FALSE;
580 return FALSE;
581 }
582
583 DiskDrive->Geometry.Cylinders = RegsOut.w.cx;
584 DiskDrive->Geometry.Heads = RegsOut.b.dh;
585 DiskDrive->Geometry.SectorsPerTrack = RegsOut.b.dl;
586 DiskDrive->Geometry.BytesPerSector = RegsOut.w.bx;
587
588 DiskDrive->Geometry.Sectors = (ULONGLONG)DiskDrive->Geometry.Cylinders *
589 DiskDrive->Geometry.Heads *
590 DiskDrive->Geometry.SectorsPerTrack;
591
592 DiskDrive->DaUa = DaUa;
593 DiskDrive->Type = DRIVE_IDE;
594 DiskDrive->LBASupported = FALSE;
595 DiskDrive->IsRemovable = FALSE;
596 DiskDrive->Initialized = TRUE;
597
598 TRACE("InitHardDrive(0x%x) returned:\n"
599 "Cylinders : 0x%x\n"
600 "Heads : 0x%x\n"
601 "Sects/Track: 0x%x\n"
602 "Total Sects: 0x%llx\n"
603 "Bytes/Sect : 0x%x\n",
604 DaUa,
605 DiskDrive->Geometry.Cylinders,
606 DiskDrive->Geometry.Heads,
607 DiskDrive->Geometry.SectorsPerTrack,
608 DiskDrive->Geometry.Sectors,
609 DiskDrive->Geometry.BytesPerSector);
610
611 return TRUE;
612}
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
WORDREGS w
Definition: pcbios.h:164

Referenced by Pc98InitializeBootDevices().

◆ InitIdeDrive()

static BOOLEAN InitIdeDrive ( IN UCHAR  UnitNumber,
IN OUT PPC98_DISK_DRIVE  DiskDrive 
)
static

Definition at line 501 of file pc98disk.c.

504{
505 PDEVICE_UNIT DeviceUnit = AtaGetDevice(UnitNumber);
506
507 /* We work directly only with ATAPI drives because BIOS has ATA support */
508 if (DeviceUnit && DeviceUnit->Flags & ATA_DEVICE_ATAPI)
509 {
510 DiskDrive->Geometry.Cylinders = DeviceUnit->Cylinders;
511 DiskDrive->Geometry.Heads = DeviceUnit->Heads;
512 DiskDrive->Geometry.SectorsPerTrack = DeviceUnit->SectorsPerTrack;
513 DiskDrive->Geometry.BytesPerSector = DeviceUnit->SectorSize;
514 DiskDrive->Geometry.Sectors = DeviceUnit->TotalSectors;
515
516 DiskDrive->DaUa = 0xFF;
517 DiskDrive->IdeUnitNumber = UnitNumber;
518 DiskDrive->Type = DRIVE_IDE | DRIVE_CDROM;
519 DiskDrive->LBASupported = TRUE;
520 DiskDrive->IsRemovable = TRUE;
521 DiskDrive->Initialized = TRUE;
522
523 TRACE("InitIdeDrive(0x%x) returned:\n"
524 "Cylinders : 0x%x\n"
525 "Heads : 0x%x\n"
526 "Sects/Track: 0x%x\n"
527 "Total Sects: 0x%llx\n"
528 "Bytes/Sect : 0x%x\n",
529 UnitNumber,
530 DiskDrive->Geometry.Cylinders,
531 DiskDrive->Geometry.Heads,
532 DiskDrive->Geometry.SectorsPerTrack,
533 DiskDrive->Geometry.Sectors,
534 DiskDrive->Geometry.BytesPerSector);
535
536 return TRUE;
537 }
538
539 DiskDrive->Initialized = FALSE;
540 return FALSE;
541}
PDEVICE_UNIT AtaGetDevice(_In_ UCHAR UnitNumber)
Definition: hwide.c:1254
#define ATA_DEVICE_ATAPI
Definition: hwide.h:30
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 ( IN UCHAR  DaUa,
IN OUT PPC98_DISK_DRIVE  DiskDrive 
)
static

Definition at line 394 of file pc98disk.c.

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

Referenced by Pc98InitializeBootDevices().

◆ Pc98DiskDriveNumberToDrive()

PPC98_DISK_DRIVE Pc98DiskDriveNumberToDrive ( IN UCHAR  DriveNumber)

Definition at line 136 of file pc98disk.c.

137{
138 PPC98_DISK_DRIVE DiskDrive;
139
140 ASSERT((0 <= DriveNumber) && (DriveNumber < RTL_NUMBER_OF(Pc98DiskDrive)));
141
142 /* Retrieve a slot */
143 DiskDrive = &Pc98DiskDrive[DriveNumber];
144
145 /* The pre-initialization of the BIOS disks was already done in Pc98InitializeBootDevices() */
146 if (DiskDrive->Initialized)
147 return DiskDrive;
148 else
149 return NULL;
150}
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define NULL
Definition: types.h:112
#define ASSERT(a)
Definition: mode.c:44
PC98_DISK_DRIVE Pc98DiskDrive[MAX_DRIVES]
Definition: pc98disk.c:22
BOOLEAN Initialized
Definition: machpc98.h:137

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

◆ Pc98DiskGetCacheableBlockCount()

ULONG Pc98DiskGetCacheableBlockCount ( UCHAR  DriveNumber)

Definition at line 899 of file pc98disk.c.

900{
901 PPC98_DISK_DRIVE DiskDrive;
902
903 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber);
904 if (!DiskDrive)
905 return 1; // Unknown count.
906
907 /*
908 * If LBA is supported then the block size will be 64 sectors (32k).
909 * If not then the block size is the size of one track.
910 */
911 if (DiskDrive->LBASupported)
912 return 64;
913 else
914 return DiskDrive->Geometry.SectorsPerTrack;
915}
ULONG SectorsPerTrack
Number of sectors per track.
Definition: disk.h:29
BOOLEAN LBASupported
Definition: machpc98.h:125
GEOMETRY Geometry
Definition: machpc98.h:106

Referenced by MachInit().

◆ Pc98DiskGetDriveGeometry()

BOOLEAN Pc98DiskGetDriveGeometry ( UCHAR  DriveNumber,
PGEOMETRY  Geometry 
)

Definition at line 883 of file pc98disk.c.

884{
885 PPC98_DISK_DRIVE DiskDrive;
886
887 TRACE("Pc98DiskGetDriveGeometry(0x%x)\n", DriveNumber);
888
889 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber);
890 if (!DiskDrive)
891 return FALSE;
892
893 *Geometry = DiskDrive->Geometry;
894
895 return TRUE;
896}

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

◆ Pc98DiskReadLogicalSectors()

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

Definition at line 850 of file pc98disk.c.

855{
856 PPC98_DISK_DRIVE DiskDrive;
857
858 TRACE("Pc98DiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %I64u SectorCount: %u Buffer: 0x%x\n",
859 DriveNumber, SectorNumber, SectorCount, Buffer);
860
861 /* 16-bit BIOS addressing limitation */
862 ASSERT(((ULONG_PTR)Buffer) <= 0xFFFFF);
863
864 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber);
865 if (!DiskDrive)
866 return FALSE;
867
868 if (DiskDrive->LBASupported)
869 {
870 /* LBA is easy, nothing to calculate. Just do the read. */
871 TRACE("--> Using LBA\n");
872 return Pc98DiskReadLogicalSectorsLBA(DiskDrive, SectorNumber, SectorCount, Buffer);
873 }
874 else
875 {
876 /* LBA is not supported, default to CHS */
877 TRACE("--> Using CHS\n");
878 return Pc98DiskReadLogicalSectorsCHS(DiskDrive, SectorNumber, SectorCount, Buffer);
879 }
880}
Definition: bufpool.h:45
ULONG SectorCount
Definition: part_xbox.c:31
static BOOLEAN Pc98DiskReadLogicalSectorsLBA(IN PPC98_DISK_DRIVE DiskDrive, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
Definition: pc98disk.c:192
static BOOLEAN Pc98DiskReadLogicalSectorsCHS(IN PPC98_DISK_DRIVE DiskDrive, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
Definition: pc98disk.c:255
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by MachInit().

◆ Pc98DiskReadLogicalSectorsCHS()

static BOOLEAN Pc98DiskReadLogicalSectorsCHS ( IN PPC98_DISK_DRIVE  DiskDrive,
IN ULONGLONG  SectorNumber,
IN ULONG  SectorCount,
OUT PVOID  Buffer 
)
static

Definition at line 255 of file pc98disk.c.

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

Definition at line 192 of file pc98disk.c.

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

Referenced by Pc98DiskReadLogicalSectors().

◆ Pc98InitializeBootDevices()

BOOLEAN Pc98InitializeBootDevices ( VOID  )

Definition at line 733 of file pc98disk.c.

734{
735 PPC98_DISK_DRIVE DiskDrive;
736 UCHAR FakeFloppyDriveNumber = 0x30;
737 UCHAR FakeHardDriveDriveNumber = 0x80;
738 UCHAR FakeCdRomDriveNumber = 0xE0;
739 USHORT DiskEquipment = *(PUSHORT)MEM_DISK_EQUIP & ~(*(PUCHAR)MEM_RDISK_EQUIP);
740 UCHAR IdeDetectedCount;
741 UCHAR i;
742
743 TRACE("Pc98InitializeBootDevices()\n");
744
746
747 /*
748 * Map DA/UA to drive number, i.e.
749 * 0x90 -> 0x30
750 * 0x80 -> 0x80
751 * 0xA0 -> 0x81, etc.
752 */
753
754 /* Map floppies */
755
756 for (i = 0; i < 4; i++)
757 {
758 DiskDrive = &Pc98DiskDrive[FakeFloppyDriveNumber];
759 if (FIRSTBYTE(DiskEquipment) & (1 << i))
760 {
761 if (InitFloppyDrive(0x30 + i, DiskDrive) || InitFloppyDrive(0xB0 + i, DiskDrive) ||
762 InitFloppyDrive(0x90 + i, DiskDrive) || InitFloppyDrive(0x10 + i, DiskDrive))
763 ++FakeFloppyDriveNumber;
764 }
765 }
766
767 for (i = 0; i < 4; i++)
768 {
769 DiskDrive = &Pc98DiskDrive[FakeFloppyDriveNumber];
770 if (FIRSTBYTE(DiskEquipment) & (16 << i))
771 {
772 if (InitFloppyDrive(0x50 + i, DiskDrive))
773 ++FakeFloppyDriveNumber;
774 }
775 }
776
777 for (i = 0; i < 4; i++)
778 {
779 DiskDrive = &Pc98DiskDrive[FakeFloppyDriveNumber];
780 if (SECONDBYTE(DiskEquipment) & (16 << i))
781 {
782 if (InitFloppyDrive(0x70 + i, DiskDrive) || InitFloppyDrive(0xF0 + i, DiskDrive))
783 ++FakeFloppyDriveNumber;
784 }
785 }
786
787 /* Map IDE/SASI drives */
788
789 for (i = 0; i < 4; i++)
790 {
791 DiskDrive = &Pc98DiskDrive[FakeHardDriveDriveNumber];
792 if (InitHardDrive(0x80 + i, DiskDrive) || InitHardDrive(0x00 + i, DiskDrive))
793 ++FakeHardDriveDriveNumber;
794 }
795
796 AtaInit(&IdeDetectedCount);
797 for (i = 0; i <= IdeDetectedCount; i++)
798 {
799 DiskDrive = &Pc98DiskDrive[FakeCdRomDriveNumber];
800 if (InitIdeDrive(i, DiskDrive))
801 ++FakeCdRomDriveNumber;
802 }
803
804 /* Map SCSI drives */
805
806 for (i = 0; i < 7; i++)
807 {
808 DiskDrive = &Pc98DiskDrive[FakeHardDriveDriveNumber];
809 if (InitScsiDrive(0xA0 + i, DiskDrive) || InitScsiDrive(0x20 + i, DiskDrive))
810 {
811 if (DiskDrive->Type & DRIVE_CDROM || DiskDrive->Type & DRIVE_MO)
812 {
813 /* Move to CD-ROM area */
814 Pc98DiskDrive[FakeCdRomDriveNumber] = *DiskDrive;
815 RtlZeroMemory(DiskDrive, sizeof(PC98_DISK_DRIVE));
816 ++FakeCdRomDriveNumber;
817 }
818 else
819 {
820 ++FakeHardDriveDriveNumber;
821 }
822 }
823 }
824
825#if 1
826 // Ugly HACK: Force ISO boot
827 // FIXME: Fill ARC disk blocks completely
828 // to allow usage of CD-ROM root path (See floppy_pc98.ini).
829 FrldrBootDrive = 0xE0;
830 FrldrBootPartition = 0xFF;
831#else
832 /* Reassign boot drive */
833 for (i = 0; i < MAX_DRIVES - 1; i++)
834 {
835 DiskDrive = &Pc98DiskDrive[i];
836 if (DiskDrive->Initialized && DiskDrive->DaUa == FrldrBootDrive)
837 {
838 TRACE("Boot drive: old 0x%x, new 0x%x\n", FrldrBootDrive, i);
840 break;
841 }
842 }
843#endif
844
845 /* Call PC version */
847}
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:1264
#define MEM_RDISK_EQUIP
Definition: machpc98.h:33
#define MEM_DISK_EQUIP
Definition: machpc98.h:41
static BOOLEAN InitHardDrive(IN UCHAR DaUa, IN OUT PPC98_DISK_DRIVE DiskDrive)
Definition: pc98disk.c:544
static BOOLEAN InitFloppyDrive(IN UCHAR DaUa, IN OUT PPC98_DISK_DRIVE DiskDrive)
Definition: pc98disk.c:615
#define MAX_DRIVES
Definition: pc98disk.c:19
static BOOLEAN InitIdeDrive(IN UCHAR UnitNumber, IN OUT PPC98_DISK_DRIVE DiskDrive)
Definition: pc98disk.c:501
static BOOLEAN InitScsiDrive(IN UCHAR DaUa, IN OUT PPC98_DISK_DRIVE DiskDrive)
Definition: pc98disk.c:394
uint16_t * PUSHORT
Definition: typedefs.h:56
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
UCHAR FrldrBootDrive
Definition: uefidisk.c:47
ULONG FrldrBootPartition
Definition: uefidisk.c:48
#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]

Definition at line 22 of file pc98disk.c.

Referenced by Pc98DiskDriveNumberToDrive(), and Pc98InitializeBootDevices().