[FREELDR] Cache INT13h drive data in pcdisk.c (#2097)
[reactos.git] / boot / freeldr / freeldr / arch / i386 / xboxdisk.c
1 /*
2 * PROJECT: FreeLoader
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Xbox specific disk access routines
5 * COPYRIGHT: Copyright 2004 Gé van Geldorp (gvg@reactos.com)
6 * Copyright 2019 Dmitry Borisov (di.sean@protonmail.com)
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <freeldr.h>
12 #include <hwide.h>
13
14 #include <debug.h>
15 DBG_DEFAULT_CHANNEL(DISK);
16
17 /* GLOBALS ********************************************************************/
18
19 static PDEVICE_UNIT HardDrive = NULL;
20 static PDEVICE_UNIT CdDrive = NULL;
21 static BOOLEAN AtaInitialized = FALSE;
22
23 /* FUNCTIONS ******************************************************************/
24
25 VOID
26 XboxDiskInit(BOOLEAN Init)
27 {
28 UCHAR DetectedCount;
29 UCHAR UnitNumber;
30 PDEVICE_UNIT DeviceUnit = NULL;
31
32 if (Init & !AtaInitialized)
33 {
34 /* Find first HDD and CD */
35 AtaInit(&DetectedCount);
36 for (UnitNumber = 0; UnitNumber <= DetectedCount; UnitNumber++)
37 {
38 DeviceUnit = AtaGetDevice(UnitNumber);
39 if (DeviceUnit)
40 {
41 if (DeviceUnit->Flags & ATA_DEVICE_ATAPI)
42 {
43 if (!CdDrive)
44 CdDrive = DeviceUnit;
45 }
46 else
47 {
48 if (!HardDrive)
49 HardDrive = DeviceUnit;
50 }
51 }
52 }
53 AtaInitialized = TRUE;
54 }
55 else
56 {
57 AtaFree();
58 }
59 }
60
61 static inline
62 PDEVICE_UNIT
63 XboxDiskDriveNumberToDeviceUnit(UCHAR DriveNumber)
64 {
65 /* Xbox has only 1 IDE controller and no floppy */
66 if (DriveNumber < 0x80 || (DriveNumber & 0x0F) >= 2)
67 return NULL;
68
69 if (!AtaInitialized)
70 XboxDiskInit(TRUE);
71
72 /* HDD */
73 if ((DriveNumber == 0x80) && HardDrive)
74 return HardDrive;
75
76 /* CD */
77 if (((DriveNumber & 0xF0) > 0x80) && CdDrive)
78 return CdDrive;
79
80 return NULL;
81 }
82
83 BOOLEAN
84 XboxDiskReadLogicalSectors(
85 IN UCHAR DriveNumber,
86 IN ULONGLONG SectorNumber,
87 IN ULONG SectorCount,
88 OUT PVOID Buffer)
89 {
90 PDEVICE_UNIT DeviceUnit;
91
92 TRACE("XboxDiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n",
93 DriveNumber, SectorNumber, SectorCount, Buffer);
94
95 DeviceUnit = XboxDiskDriveNumberToDeviceUnit(DriveNumber);
96 if (!DeviceUnit)
97 return FALSE;
98
99 return AtaAtapiReadLogicalSectorsLBA(DeviceUnit, SectorNumber, SectorCount, Buffer);
100 }
101
102 BOOLEAN
103 XboxDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
104 {
105 PDEVICE_UNIT DeviceUnit;
106
107 TRACE("XboxDiskGetDriveGeometry(0x%x)\n", DriveNumber);
108
109 DeviceUnit = XboxDiskDriveNumberToDeviceUnit(DriveNumber);
110 if (!DeviceUnit)
111 return FALSE;
112
113 Geometry->Cylinders = DeviceUnit->Cylinders;
114 Geometry->Heads = DeviceUnit->Heads;
115 Geometry->Sectors = DeviceUnit->Sectors;
116 Geometry->BytesPerSector = DeviceUnit->SectorSize;
117
118 return TRUE;
119 }
120
121 ULONG
122 XboxDiskGetCacheableBlockCount(UCHAR DriveNumber)
123 {
124 PDEVICE_UNIT DeviceUnit;
125
126 DeviceUnit = XboxDiskDriveNumberToDeviceUnit(DriveNumber);
127 if (!DeviceUnit)
128 return 1; // Unknown count.
129
130 /*
131 * If LBA is supported then the block size will be 64 sectors (32k).
132 * If not then the block size is the size of one track.
133 */
134 if (DeviceUnit->Flags & ATA_DEVICE_LBA)
135 return 64;
136 else
137 return DeviceUnit->Sectors;
138 }
139
140 /* EOF */