[SETUPLIB] Add two hacks in partlist.c for temporarily setting consistently the disk...
[reactos.git] / boot / freeldr / freeldr / arch / i386 / xbox / machxbox.c
1 /*
2 * FreeLoader
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include <freeldr.h>
20 #include <drivers/xbox/superio.h>
21
22 #include <debug.h>
23 DBG_DEFAULT_CHANNEL(HWDETECT);
24
25 #define MAX_XBOX_COM_PORTS 2
26
27 extern PVOID FrameBuffer;
28 extern ULONG FrameBufferSize;
29
30 BOOLEAN
31 XboxFindPciBios(PPCI_REGISTRY_INFO BusData)
32 {
33 /* We emulate PCI BIOS here, there are 2 known working PCI buses on an original Xbox */
34
35 BusData->NoBuses = 2;
36 BusData->MajorRevision = 1;
37 BusData->MinorRevision = 0;
38 BusData->HardwareMechanism = 1;
39 return TRUE;
40 }
41
42 extern
43 VOID
44 DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey, PUCHAR Base);
45
46 static
47 ULONG
48 XboxGetSerialPort(ULONG Index, PULONG Irq)
49 {
50 /*
51 * Xbox may have maximum two Serial COM ports
52 * if the Super I/O chip is connected via LPC
53 */
54 static const UCHAR Device[MAX_XBOX_COM_PORTS] = {LPC_DEVICE_SERIAL_PORT_1, LPC_DEVICE_SERIAL_PORT_2};
55 ULONG ComBase = 0;
56
57 LpcEnterConfig();
58
59 // Select serial device
60 LpcWriteRegister(LPC_CONFIG_DEVICE_NUMBER, Device[Index]);
61
62 // Check if selected device is active
63 if (LpcReadRegister(LPC_CONFIG_DEVICE_ACTIVATE) == 1)
64 {
65 ComBase = LpcGetIoBase();
66 *Irq = LpcGetIrqPrimary();
67 }
68
69 LpcExitConfig();
70
71 return ComBase;
72 }
73
74 extern
75 VOID
76 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey, GET_SERIAL_PORT MachGetSerialPort, ULONG Count);
77
78 VOID
79 XboxGetExtendedBIOSData(PULONG ExtendedBIOSDataArea, PULONG ExtendedBIOSDataSize)
80 {
81 TRACE("XboxGetExtendedBIOSData(): UNIMPLEMENTED\n");
82 *ExtendedBIOSDataArea = 0;
83 *ExtendedBIOSDataSize = 0;
84 }
85
86 // NOTE: Similar to machpc.c!PcGetHarddiskConfigurationData(),
87 // but without extended geometry support.
88 static
89 PCM_PARTIAL_RESOURCE_LIST
90 XboxGetHarddiskConfigurationData(UCHAR DriveNumber, ULONG* pSize)
91 {
92 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
93 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
94 //EXTENDED_GEOMETRY ExtGeometry;
95 GEOMETRY Geometry;
96 ULONG Size;
97
98 //
99 // Initialize returned size
100 //
101 *pSize = 0;
102
103 /* Set 'Configuration Data' value */
104 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
105 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
106 PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
107 if (PartialResourceList == NULL)
108 {
109 ERR("Failed to allocate a full resource descriptor\n");
110 return NULL;
111 }
112
113 memset(PartialResourceList, 0, Size);
114 PartialResourceList->Version = 1;
115 PartialResourceList->Revision = 1;
116 PartialResourceList->Count = 1;
117 PartialResourceList->PartialDescriptors[0].Type =
118 CmResourceTypeDeviceSpecific;
119 // PartialResourceList->PartialDescriptors[0].ShareDisposition =
120 // PartialResourceList->PartialDescriptors[0].Flags =
121 PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
122 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
123
124 /* Get pointer to geometry data */
125 DiskGeometry = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
126
127 /* Get the disk geometry */
128 //ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
129
130 if (XboxDiskGetDriveGeometry(DriveNumber, &Geometry))
131 {
132 DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
133 DiskGeometry->NumberOfCylinders = Geometry.Cylinders;
134 DiskGeometry->SectorsPerTrack = Geometry.Sectors;
135 DiskGeometry->NumberOfHeads = Geometry.Heads;
136 }
137 else
138 {
139 ERR("Reading disk geometry failed\n");
140 FrLdrHeapFree(PartialResourceList, TAG_HW_RESOURCE_LIST);
141 return NULL;
142 }
143 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
144 DriveNumber,
145 DiskGeometry->NumberOfCylinders,
146 DiskGeometry->NumberOfHeads,
147 DiskGeometry->SectorsPerTrack,
148 DiskGeometry->BytesPerSector);
149
150 //
151 // Return configuration data
152 //
153 *pSize = Size;
154 return PartialResourceList;
155 }
156
157 static VOID
158 DetectDisplayController(PCONFIGURATION_COMPONENT_DATA BusKey)
159 {
160 CHAR Buffer[80];
161 PCONFIGURATION_COMPONENT_DATA ControllerKey;
162 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
163 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
164 ULONG Size;
165
166 if (FrameBufferSize == 0)
167 return;
168
169 strcpy(Buffer, "NV2A Framebuffer");
170
171 Size = sizeof(CM_PARTIAL_RESOURCE_LIST);
172 PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
173 if (PartialResourceList == NULL)
174 {
175 ERR("Failed to allocate resource descriptor\n");
176 return;
177 }
178 memset(PartialResourceList, 0, Size);
179
180 /* Initialize resource descriptor */
181 PartialResourceList->Version = 1;
182 PartialResourceList->Revision = 1;
183 PartialResourceList->Count = 1;
184
185 /* Set Memory */
186 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
187 PartialDescriptor->Type = CmResourceTypeMemory;
188 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
189 PartialDescriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
190 PartialDescriptor->u.Memory.Start.LowPart = (ULONG_PTR)FrameBuffer & 0x0FFFFFFF;
191 PartialDescriptor->u.Memory.Length = FrameBufferSize;
192
193 FldrCreateComponentKey(BusKey,
194 ControllerClass,
195 DisplayController,
196 0x0,
197 0x0,
198 0xFFFFFFFF,
199 Buffer,
200 PartialResourceList,
201 Size,
202 &ControllerKey);
203
204 TRACE("Created key: DisplayController\\0\n");
205 }
206
207 static
208 VOID
209 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
210 {
211 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
212 PCONFIGURATION_COMPONENT_DATA BusKey;
213 ULONG Size;
214
215 /* Set 'Configuration Data' value */
216 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) -
217 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
218 PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
219 if (PartialResourceList == NULL)
220 {
221 TRACE("Failed to allocate resource descriptor\n");
222 return;
223 }
224
225 /* Initialize resource descriptor */
226 memset(PartialResourceList, 0, Size);
227 PartialResourceList->Version = 1;
228 PartialResourceList->Revision = 1;
229 PartialResourceList->Count = 0;
230
231 /* Create new bus key */
232 FldrCreateComponentKey(SystemKey,
233 AdapterClass,
234 MultiFunctionAdapter,
235 0x0,
236 0x0,
237 0xFFFFFFFF,
238 "ISA",
239 PartialResourceList,
240 Size,
241 &BusKey);
242
243 /* Increment bus number */
244 (*BusNumber)++;
245
246 /* Detect ISA/BIOS devices */
247 DetectBiosDisks(SystemKey, BusKey);
248 DetectSerialPorts(BusKey, XboxGetSerialPort, MAX_XBOX_COM_PORTS);
249 DetectDisplayController(BusKey);
250
251 /* FIXME: Detect more ISA devices */
252 }
253
254 static
255 UCHAR
256 XboxGetFloppyCount(VOID)
257 {
258 /* On a PC we use CMOS/RTC I/O ports 0x70 and 0x71 to detect floppies.
259 * However an Xbox CMOS memory range [0x10, 0x70) and [0x80, 0x100)
260 * is filled with 0x55 0xAA 0x55 0xAA ... byte pattern which is used
261 * to validate the date/time settings by Xbox OS.
262 *
263 * Technically it's possible to connect a floppy drive to Xbox, but
264 * CMOS detection method should not be used here. */
265
266 WARN("XboxGetFloppyCount() is UNIMPLEMENTED, returning 0\n");
267 return 0;
268 }
269
270 PCONFIGURATION_COMPONENT_DATA
271 XboxHwDetect(VOID)
272 {
273 PCONFIGURATION_COMPONENT_DATA SystemKey;
274 ULONG BusNumber = 0;
275
276 TRACE("DetectHardware()\n");
277
278 /* Create the 'System' key */
279 FldrCreateSystemKey(&SystemKey);
280 FldrSetIdentifier(SystemKey, "Original Xbox (PC/AT like)");
281
282 GetHarddiskConfigurationData = XboxGetHarddiskConfigurationData;
283 FindPciBios = XboxFindPciBios;
284
285 /* TODO: Build actual xbox's hardware configuration tree */
286 DetectPciBios(SystemKey, &BusNumber);
287 DetectIsaBios(SystemKey, &BusNumber);
288
289 TRACE("DetectHardware() Done\n");
290 return SystemKey;
291 }
292
293 VOID XboxHwIdle(VOID)
294 {
295 /* UNIMPLEMENTED */
296 }
297
298
299 /******************************************************************************/
300
301 VOID
302 MachInit(const char *CmdLine)
303 {
304 ULONG PciId;
305
306 memset(&MachVtbl, 0, sizeof(MACHVTBL));
307
308 /* Check for Xbox by identifying device at PCI 0:0:0, if it's
309 * 0x10DE/0x02A5 then we're running on an Xbox */
310 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(0, 0, 0));
311 PciId = READ_PORT_ULONG((PULONG)0xCFC);
312 if (PciId != 0x02A510DE)
313 {
314 ERR("This is not original Xbox!\n");
315
316 /* Disable and halt the CPU */
317 _disable();
318 __halt();
319
320 while (TRUE);
321 }
322
323 /* Set LEDs to red before anything is initialized */
324 XboxSetLED("rrrr");
325
326 /* Setup vtbl */
327 MachVtbl.ConsPutChar = XboxConsPutChar;
328 MachVtbl.ConsKbHit = XboxConsKbHit;
329 MachVtbl.ConsGetCh = XboxConsGetCh;
330 MachVtbl.VideoClearScreen = XboxVideoClearScreen;
331 MachVtbl.VideoSetDisplayMode = XboxVideoSetDisplayMode;
332 MachVtbl.VideoGetDisplaySize = XboxVideoGetDisplaySize;
333 MachVtbl.VideoGetBufferSize = XboxVideoGetBufferSize;
334 MachVtbl.VideoGetFontsFromFirmware = XboxVideoGetFontsFromFirmware;
335 MachVtbl.VideoSetTextCursorPosition = XboxVideoSetTextCursorPosition;
336 MachVtbl.VideoHideShowTextCursor = XboxVideoHideShowTextCursor;
337 MachVtbl.VideoPutChar = XboxVideoPutChar;
338 MachVtbl.VideoCopyOffScreenBufferToVRAM = XboxVideoCopyOffScreenBufferToVRAM;
339 MachVtbl.VideoIsPaletteFixed = XboxVideoIsPaletteFixed;
340 MachVtbl.VideoSetPaletteColor = XboxVideoSetPaletteColor;
341 MachVtbl.VideoGetPaletteColor = XboxVideoGetPaletteColor;
342 MachVtbl.VideoSync = XboxVideoSync;
343 MachVtbl.Beep = PcBeep;
344 MachVtbl.PrepareForReactOS = XboxPrepareForReactOS;
345 MachVtbl.GetMemoryMap = XboxMemGetMemoryMap;
346 MachVtbl.GetExtendedBIOSData = XboxGetExtendedBIOSData;
347 MachVtbl.GetFloppyCount = XboxGetFloppyCount;
348 MachVtbl.DiskReadLogicalSectors = XboxDiskReadLogicalSectors;
349 MachVtbl.DiskGetDriveGeometry = XboxDiskGetDriveGeometry;
350 MachVtbl.DiskGetCacheableBlockCount = XboxDiskGetCacheableBlockCount;
351 MachVtbl.GetTime = XboxGetTime;
352 MachVtbl.InitializeBootDevices = PcInitializeBootDevices;
353 MachVtbl.HwDetect = XboxHwDetect;
354 MachVtbl.HwIdle = XboxHwIdle;
355
356 /* Initialize our stuff */
357 XboxMemInit();
358 XboxVideoInit();
359
360 /* Set LEDs to orange after init */
361 XboxSetLED("oooo");
362
363 HalpCalibrateStallExecution();
364 }
365
366 VOID
367 XboxPrepareForReactOS(VOID)
368 {
369 /* On Xbox, prepare video and disk support */
370 XboxVideoPrepareForReactOS();
371 XboxDiskInit(FALSE);
372 DiskStopFloppyMotor();
373
374 /* Turn off debug messages to screen */
375 DebugDisableScreenPort();
376 }
377
378 /* EOF */