3fb951de1a6517968f288882fbb6deaeb5f17c1b
[reactos.git] / boot / freeldr / freeldr / arch / i386 / 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
21 #include <debug.h>
22
23 DBG_DEFAULT_CHANNEL(HWDETECT);
24
25
26 BOOLEAN
27 XboxFindPciBios(PPCI_REGISTRY_INFO BusData)
28 {
29 /* We emulate PCI BIOS here, there are 2 known working PCI buses on an original Xbox */
30
31 BusData->NoBuses = 2;
32 BusData->MajorRevision = 1;
33 BusData->MinorRevision = 0;
34 BusData->HardwareMechanism = 1;
35 return TRUE;
36 }
37
38 extern
39 VOID
40 DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey, PUCHAR Base);
41
42 static
43 ULONG
44 XboxGetSerialPort(ULONG Index, PULONG Irq)
45 {
46 /*
47 * Xbox may have maximum two Serial COM ports
48 * if the Super I/O chip is connected via LPC
49 */
50 static const UCHAR Device[MAX_XBOX_COM_PORTS] = {LPC_DEVICE_SERIAL_PORT_1, LPC_DEVICE_SERIAL_PORT_2};
51 ULONG ComBase = 0;
52
53 // Enter Configuration
54 WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_ENTER_CONFIG_KEY);
55
56 // Select serial device
57 WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_NUMBER);
58 WRITE_PORT_UCHAR(LPC_IO_BASE + 1, Device[Index]);
59
60 // Check if selected device is active
61 WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_ACTIVATE);
62 if (READ_PORT_UCHAR(LPC_IO_BASE + 1) == 1)
63 {
64 // Read LSB
65 WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_BASE_ADDRESS_LOW);
66 ComBase = READ_PORT_UCHAR(LPC_IO_BASE + 1);
67 // Read MSB
68 WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_BASE_ADDRESS_HIGH);
69 ComBase |= (READ_PORT_UCHAR(LPC_IO_BASE + 1) << 8);
70 // Read IRQ
71 WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_INTERRUPT);
72 *Irq = READ_PORT_UCHAR(LPC_IO_BASE + 1);
73 }
74
75 // Exit Configuration
76 WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_EXIT_CONFIG_KEY);
77
78 return ComBase;
79 }
80
81 extern
82 VOID
83 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey, GET_SERIAL_PORT MachGetSerialPort, ULONG Count);
84
85 VOID
86 XboxGetExtendedBIOSData(PULONG ExtendedBIOSDataArea, PULONG ExtendedBIOSDataSize)
87 {
88 TRACE("XboxGetExtendedBIOSData(): UNIMPLEMENTED\n");
89 *ExtendedBIOSDataArea = 0;
90 *ExtendedBIOSDataSize = 0;
91 }
92
93 // NOTE: Similar to machpc.c!PcGetHarddiskConfigurationData(),
94 // but without extended geometry support.
95 static
96 PCM_PARTIAL_RESOURCE_LIST
97 XboxGetHarddiskConfigurationData(UCHAR DriveNumber, ULONG* pSize)
98 {
99 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
100 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
101 //EXTENDED_GEOMETRY ExtGeometry;
102 GEOMETRY Geometry;
103 ULONG Size;
104
105 //
106 // Initialize returned size
107 //
108 *pSize = 0;
109
110 /* Set 'Configuration Data' value */
111 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
112 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
113 PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
114 if (PartialResourceList == NULL)
115 {
116 ERR("Failed to allocate a full resource descriptor\n");
117 return NULL;
118 }
119
120 memset(PartialResourceList, 0, Size);
121 PartialResourceList->Version = 1;
122 PartialResourceList->Revision = 1;
123 PartialResourceList->Count = 1;
124 PartialResourceList->PartialDescriptors[0].Type =
125 CmResourceTypeDeviceSpecific;
126 // PartialResourceList->PartialDescriptors[0].ShareDisposition =
127 // PartialResourceList->PartialDescriptors[0].Flags =
128 PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
129 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
130
131 /* Get pointer to geometry data */
132 DiskGeometry = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
133
134 /* Get the disk geometry */
135 //ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
136
137 if (MachDiskGetDriveGeometry(DriveNumber, &Geometry))
138 {
139 DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
140 DiskGeometry->NumberOfCylinders = Geometry.Cylinders;
141 DiskGeometry->SectorsPerTrack = Geometry.Sectors;
142 DiskGeometry->NumberOfHeads = Geometry.Heads;
143 }
144 else
145 {
146 ERR("Reading disk geometry failed\n");
147 FrLdrHeapFree(PartialResourceList, TAG_HW_RESOURCE_LIST);
148 return NULL;
149 }
150 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
151 DriveNumber,
152 DiskGeometry->NumberOfCylinders,
153 DiskGeometry->NumberOfHeads,
154 DiskGeometry->SectorsPerTrack,
155 DiskGeometry->BytesPerSector);
156
157 //
158 // Return configuration data
159 //
160 *pSize = Size;
161 return PartialResourceList;
162 }
163
164 static
165 VOID
166 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
167 {
168 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
169 PCONFIGURATION_COMPONENT_DATA BusKey;
170 ULONG Size;
171
172 /* Set 'Configuration Data' value */
173 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) -
174 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
175 PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
176 if (PartialResourceList == NULL)
177 {
178 TRACE("Failed to allocate resource descriptor\n");
179 return;
180 }
181
182 /* Initialize resource descriptor */
183 memset(PartialResourceList, 0, Size);
184 PartialResourceList->Version = 1;
185 PartialResourceList->Revision = 1;
186 PartialResourceList->Count = 0;
187
188 /* Create new bus key */
189 FldrCreateComponentKey(SystemKey,
190 AdapterClass,
191 MultiFunctionAdapter,
192 0x0,
193 0x0,
194 0xFFFFFFFF,
195 "ISA",
196 PartialResourceList,
197 Size,
198 &BusKey);
199
200 /* Increment bus number */
201 (*BusNumber)++;
202
203 /* Detect ISA/BIOS devices */
204 DetectBiosDisks(SystemKey, BusKey);
205 DetectSerialPorts(BusKey, XboxGetSerialPort, MAX_XBOX_COM_PORTS);
206
207 /* FIXME: Detect more ISA devices */
208 }
209
210 static
211 UCHAR
212 XboxGetFloppyCount(VOID)
213 {
214 /* On a PC we use CMOS/RTC I/O ports 0x70 and 0x71 to detect floppies.
215 * However an Xbox CMOS memory range [0x10, 0x70) and [0x80, 0x100)
216 * is filled with 0x55 0xAA 0x55 0xAA ... byte pattern which is used
217 * to validate the date/time settings by Xbox OS.
218 *
219 * Technically it's possible to connect a floppy drive to Xbox, but
220 * CMOS detection method should not be used here. */
221
222 WARN("XboxGetFloppyCount() is UNIMPLEMENTED, returning 0\n");
223 return 0;
224 }
225
226 PCONFIGURATION_COMPONENT_DATA
227 XboxHwDetect(VOID)
228 {
229 PCONFIGURATION_COMPONENT_DATA SystemKey;
230 ULONG BusNumber = 0;
231
232 TRACE("DetectHardware()\n");
233
234 /* Create the 'System' key */
235 FldrCreateSystemKey(&SystemKey);
236
237 GetHarddiskConfigurationData = XboxGetHarddiskConfigurationData;
238 FindPciBios = XboxFindPciBios;
239
240 /* TODO: Build actual xbox's hardware configuration tree */
241 DetectPciBios(SystemKey, &BusNumber);
242 DetectIsaBios(SystemKey, &BusNumber);
243
244 TRACE("DetectHardware() Done\n");
245 return SystemKey;
246 }
247
248 VOID XboxHwIdle(VOID)
249 {
250 /* UNIMPLEMENTED */
251 }
252
253
254 /******************************************************************************/
255
256 VOID
257 XboxMachInit(const char *CmdLine)
258 {
259 /* Set LEDs to red before anything is initialized */
260 XboxSetLED("rrrr");
261
262 /* Initialize our stuff */
263 XboxMemInit();
264 XboxVideoInit();
265
266 /* Setup vtbl */
267 MachVtbl.ConsPutChar = XboxConsPutChar;
268 MachVtbl.ConsKbHit = XboxConsKbHit;
269 MachVtbl.ConsGetCh = XboxConsGetCh;
270 MachVtbl.VideoClearScreen = XboxVideoClearScreen;
271 MachVtbl.VideoSetDisplayMode = XboxVideoSetDisplayMode;
272 MachVtbl.VideoGetDisplaySize = XboxVideoGetDisplaySize;
273 MachVtbl.VideoGetBufferSize = XboxVideoGetBufferSize;
274 MachVtbl.VideoGetFontsFromFirmware = XboxVideoGetFontsFromFirmware;
275 MachVtbl.VideoSetTextCursorPosition = XboxVideoSetTextCursorPosition;
276 MachVtbl.VideoHideShowTextCursor = XboxVideoHideShowTextCursor;
277 MachVtbl.VideoPutChar = XboxVideoPutChar;
278 MachVtbl.VideoCopyOffScreenBufferToVRAM = XboxVideoCopyOffScreenBufferToVRAM;
279 MachVtbl.VideoIsPaletteFixed = XboxVideoIsPaletteFixed;
280 MachVtbl.VideoSetPaletteColor = XboxVideoSetPaletteColor;
281 MachVtbl.VideoGetPaletteColor = XboxVideoGetPaletteColor;
282 MachVtbl.VideoSync = XboxVideoSync;
283 MachVtbl.Beep = PcBeep;
284 MachVtbl.PrepareForReactOS = XboxPrepareForReactOS;
285 MachVtbl.GetMemoryMap = XboxMemGetMemoryMap;
286 MachVtbl.GetExtendedBIOSData = XboxGetExtendedBIOSData;
287 MachVtbl.GetFloppyCount = XboxGetFloppyCount;
288 MachVtbl.DiskGetBootPath = DiskGetBootPath;
289 MachVtbl.DiskReadLogicalSectors = XboxDiskReadLogicalSectors;
290 MachVtbl.DiskGetDriveGeometry = XboxDiskGetDriveGeometry;
291 MachVtbl.DiskGetCacheableBlockCount = XboxDiskGetCacheableBlockCount;
292 MachVtbl.GetTime = XboxGetTime;
293 MachVtbl.InitializeBootDevices = PcInitializeBootDevices;
294 MachVtbl.HwDetect = XboxHwDetect;
295 MachVtbl.HwIdle = XboxHwIdle;
296
297 /* Set LEDs to orange after init */
298 XboxSetLED("oooo");
299 }
300
301 VOID
302 XboxPrepareForReactOS(VOID)
303 {
304 /* On XBOX, prepare video and turn off the floppy motor */
305 XboxVideoPrepareForReactOS();
306 DiskStopFloppyMotor();
307 }
308
309 /* EOF */