[FREELDR]
[reactos.git] / reactos / boot / freeldr / freeldr / arch / i386 / machpc.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 <cportlib/cportlib.h>
21
22 #define NDEBUG
23 #include <debug.h>
24
25 DBG_DEFAULT_CHANNEL(HWDETECT);
26
27
28 /* Maximum number of COM and LPT ports */
29 #define MAX_COM_PORTS 4
30 #define MAX_LPT_PORTS 3
31
32 /* No Mouse */
33 #define MOUSE_TYPE_NONE 0
34 /* Microsoft Mouse with 2 buttons */
35 #define MOUSE_TYPE_MICROSOFT 1
36 /* Logitech Mouse with 3 buttons */
37 #define MOUSE_TYPE_LOGITECH 2
38 /* Microsoft Wheel Mouse (aka Z Mouse) */
39 #define MOUSE_TYPE_WHEELZ 3
40 /* Mouse Systems Mouse */
41 #define MOUSE_TYPE_MOUSESYSTEMS 4
42
43
44 /* PS2 stuff */
45
46 /* Controller registers. */
47 #define CONTROLLER_REGISTER_STATUS 0x64
48 #define CONTROLLER_REGISTER_CONTROL 0x64
49 #define CONTROLLER_REGISTER_DATA 0x60
50
51 /* Controller commands. */
52 #define CONTROLLER_COMMAND_READ_MODE 0x20
53 #define CONTROLLER_COMMAND_WRITE_MODE 0x60
54 #define CONTROLLER_COMMAND_GET_VERSION 0xA1
55 #define CONTROLLER_COMMAND_MOUSE_DISABLE 0xA7
56 #define CONTROLLER_COMMAND_MOUSE_ENABLE 0xA8
57 #define CONTROLLER_COMMAND_TEST_MOUSE 0xA9
58 #define CONTROLLER_COMMAND_SELF_TEST 0xAA
59 #define CONTROLLER_COMMAND_KEYBOARD_TEST 0xAB
60 #define CONTROLLER_COMMAND_KEYBOARD_DISABLE 0xAD
61 #define CONTROLLER_COMMAND_KEYBOARD_ENABLE 0xAE
62 #define CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER 0xD3
63 #define CONTROLLER_COMMAND_WRITE_MOUSE 0xD4
64
65 /* Controller status */
66 #define CONTROLLER_STATUS_OUTPUT_BUFFER_FULL 0x01
67 #define CONTROLLER_STATUS_INPUT_BUFFER_FULL 0x02
68 #define CONTROLLER_STATUS_SELF_TEST 0x04
69 #define CONTROLLER_STATUS_COMMAND 0x08
70 #define CONTROLLER_STATUS_UNLOCKED 0x10
71 #define CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL 0x20
72 #define CONTROLLER_STATUS_GENERAL_TIMEOUT 0x40
73 #define CONTROLLER_STATUS_PARITY_ERROR 0x80
74 #define AUX_STATUS_OUTPUT_BUFFER_FULL (CONTROLLER_STATUS_OUTPUT_BUFFER_FULL | \
75 CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL)
76
77 /* Timeout in ms for sending to keyboard controller. */
78 #define CONTROLLER_TIMEOUT 250
79
80
81 // NOTE: Similar to xboxhw.c!XboxGetHarddiskConfigurationData(),
82 // but with extended geometry support.
83 // static
84 PCM_PARTIAL_RESOURCE_LIST
85 PcGetHarddiskConfigurationData(UCHAR DriveNumber, ULONG* pSize)
86 {
87 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
88 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
89 EXTENDED_GEOMETRY ExtGeometry;
90 GEOMETRY Geometry;
91 ULONG Size;
92
93 //
94 // Initialize returned size
95 //
96 *pSize = 0;
97
98 /* Set 'Configuration Data' value */
99 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
100 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
101 PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
102 if (PartialResourceList == NULL)
103 {
104 ERR("Failed to allocate resource descriptor\n");
105 return NULL;
106 }
107
108 memset(PartialResourceList, 0, Size);
109 PartialResourceList->Version = 1;
110 PartialResourceList->Revision = 1;
111 PartialResourceList->Count = 1;
112 PartialResourceList->PartialDescriptors[0].Type =
113 CmResourceTypeDeviceSpecific;
114 // PartialResourceList->PartialDescriptors[0].ShareDisposition =
115 // PartialResourceList->PartialDescriptors[0].Flags =
116 PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
117 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
118
119 /* Get pointer to geometry data */
120 DiskGeometry = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
121
122 /* Get the disk geometry */
123 ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
124 if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size))
125 {
126 DiskGeometry->BytesPerSector = ExtGeometry.BytesPerSector;
127 DiskGeometry->NumberOfCylinders = ExtGeometry.Cylinders;
128 DiskGeometry->SectorsPerTrack = ExtGeometry.SectorsPerTrack;
129 DiskGeometry->NumberOfHeads = ExtGeometry.Heads;
130 }
131 else if (MachDiskGetDriveGeometry(DriveNumber, &Geometry))
132 {
133 DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
134 DiskGeometry->NumberOfCylinders = Geometry.Cylinders;
135 DiskGeometry->SectorsPerTrack = Geometry.Sectors;
136 DiskGeometry->NumberOfHeads = Geometry.Heads;
137 }
138 else
139 {
140 TRACE("Reading disk geometry failed\n");
141 FrLdrHeapFree(PartialResourceList, TAG_HW_RESOURCE_LIST);
142 return NULL;
143 }
144 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
145 DriveNumber,
146 DiskGeometry->NumberOfCylinders,
147 DiskGeometry->NumberOfHeads,
148 DiskGeometry->SectorsPerTrack,
149 DiskGeometry->BytesPerSector);
150
151 //
152 // Return configuration data
153 //
154 *pSize = Size;
155 return PartialResourceList;
156 }
157
158 static
159 VOID
160 DetectPnpBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
161 {
162 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
163 PCM_PNP_BIOS_DEVICE_NODE DeviceNode;
164 PCM_PNP_BIOS_INSTALLATION_CHECK InstData;
165 PCONFIGURATION_COMPONENT_DATA BusKey;
166 ULONG x;
167 ULONG NodeSize = 0;
168 ULONG NodeCount = 0;
169 UCHAR NodeNumber;
170 ULONG FoundNodeCount;
171 int i;
172 ULONG PnpBufferSize;
173 ULONG PnpBufferSizeLimit;
174 ULONG Size;
175 char *Ptr;
176
177 InstData = (PCM_PNP_BIOS_INSTALLATION_CHECK)PnpBiosSupported();
178 if (InstData == NULL || strncmp((CHAR*)InstData->Signature, "$PnP", 4))
179 {
180 TRACE("PnP-BIOS not supported\n");
181 return;
182 }
183
184 TRACE("PnP-BIOS supported\n");
185 TRACE("Signature '%c%c%c%c'\n",
186 InstData->Signature[0], InstData->Signature[1],
187 InstData->Signature[2], InstData->Signature[3]);
188
189 x = PnpBiosGetDeviceNodeCount(&NodeSize, &NodeCount);
190 if (x == 0x82)
191 {
192 TRACE("PnP-BIOS function 'Get Number of System Device Nodes' not supported\n");
193 return;
194 }
195
196 NodeCount &= 0xFF; // needed since some fscked up BIOSes return
197 // wrong info (e.g. Mac Virtual PC)
198 // e.g. look: http://my.execpc.com/~geezer/osd/pnp/pnp16.c
199 if (x != 0 || NodeSize == 0 || NodeCount == 0)
200 {
201 ERR("PnP-BIOS failed to enumerate device nodes\n");
202 return;
203 }
204 TRACE("MaxNodeSize %u NodeCount %u\n", NodeSize, NodeCount);
205 TRACE("Estimated buffer size %u\n", NodeSize * NodeCount);
206
207 /* Set 'Configuration Data' value */
208 PnpBufferSizeLimit = sizeof(CM_PNP_BIOS_INSTALLATION_CHECK)
209 + (NodeSize * NodeCount);
210 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + PnpBufferSizeLimit;
211 PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
212 if (PartialResourceList == NULL)
213 {
214 ERR("Failed to allocate resource descriptor\n");
215 return;
216 }
217 memset(PartialResourceList, 0, Size);
218
219 /* Initialize resource descriptor */
220 PartialResourceList->Version = 1;
221 PartialResourceList->Revision = 1;
222 PartialResourceList->Count = 1;
223 PartialResourceList->PartialDescriptors[0].Type =
224 CmResourceTypeDeviceSpecific;
225 PartialResourceList->PartialDescriptors[0].ShareDisposition =
226 CmResourceShareUndetermined;
227
228 /* The buffer starts after PartialResourceList->PartialDescriptors[0] */
229 Ptr = (char *)(PartialResourceList + 1);
230
231 /* Set installation check data */
232 memcpy (Ptr, InstData, sizeof(CM_PNP_BIOS_INSTALLATION_CHECK));
233 Ptr += sizeof(CM_PNP_BIOS_INSTALLATION_CHECK);
234 PnpBufferSize = sizeof(CM_PNP_BIOS_INSTALLATION_CHECK);
235
236 /* Copy device nodes */
237 FoundNodeCount = 0;
238 for (i = 0; i < 0xFF; i++)
239 {
240 NodeNumber = (UCHAR)i;
241
242 x = PnpBiosGetDeviceNode(&NodeNumber, DiskReadBuffer);
243 if (x == 0)
244 {
245 DeviceNode = (PCM_PNP_BIOS_DEVICE_NODE)DiskReadBuffer;
246
247 TRACE("Node: %u Size %u (0x%x)\n",
248 DeviceNode->Node,
249 DeviceNode->Size,
250 DeviceNode->Size);
251
252 if (PnpBufferSize + DeviceNode->Size > PnpBufferSizeLimit)
253 {
254 ERR("Buffer too small! Ignoring remaining device nodes.\n");
255 break;
256 }
257
258 memcpy(Ptr, DeviceNode, DeviceNode->Size);
259
260 Ptr += DeviceNode->Size;
261 PnpBufferSize += DeviceNode->Size;
262
263 FoundNodeCount++;
264 if (FoundNodeCount >= NodeCount)
265 break;
266 }
267 }
268
269 /* Set real data size */
270 PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
271 PnpBufferSize;
272 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + PnpBufferSize;
273
274 TRACE("Real buffer size: %u\n", PnpBufferSize);
275 TRACE("Resource size: %u\n", Size);
276
277 /* Create component key */
278 FldrCreateComponentKey(SystemKey,
279 AdapterClass,
280 MultiFunctionAdapter,
281 0x0,
282 0x0,
283 0xFFFFFFFF,
284 "PNP BIOS",
285 PartialResourceList,
286 Size,
287 &BusKey);
288
289 (*BusNumber)++;
290 }
291
292 static
293 VOID
294 InitializeSerialPort(PUCHAR Port,
295 UCHAR LineControl)
296 {
297 WRITE_PORT_UCHAR(Port + 3, 0x80); /* set DLAB on */
298 WRITE_PORT_UCHAR(Port, 0x60); /* speed LO byte */
299 WRITE_PORT_UCHAR(Port + 1, 0); /* speed HI byte */
300 WRITE_PORT_UCHAR(Port + 3, LineControl);
301 WRITE_PORT_UCHAR(Port + 1, 0); /* set comm and DLAB to 0 */
302 WRITE_PORT_UCHAR(Port + 4, 0x09); /* DR int enable */
303 READ_PORT_UCHAR(Port + 5); /* clear error bits */
304 }
305
306 static
307 ULONG
308 DetectSerialMouse(PUCHAR Port)
309 {
310 CHAR Buffer[4];
311 ULONG i;
312 ULONG TimeOut;
313 UCHAR LineControl;
314
315 /* Shutdown mouse or something like that */
316 LineControl = READ_PORT_UCHAR(Port + 4);
317 WRITE_PORT_UCHAR(Port + 4, (LineControl & ~0x02) | 0x01);
318 StallExecutionProcessor(100000);
319
320 /*
321 * Clear buffer
322 * Maybe there is no serial port although BIOS reported one (this
323 * is the case on Apple hardware), or the serial port is misbehaving,
324 * therefore we must give up after some time.
325 */
326 TimeOut = 200;
327 while (READ_PORT_UCHAR(Port + 5) & 0x01)
328 {
329 if (--TimeOut == 0)
330 return MOUSE_TYPE_NONE;
331 READ_PORT_UCHAR(Port);
332 }
333
334 /*
335 * Send modem control with 'Data Terminal Ready', 'Request To Send' and
336 * 'Output Line 2' message. This enables mouse to identify.
337 */
338 WRITE_PORT_UCHAR(Port + 4, 0x0b);
339
340 /* Wait 10 milliseconds for the mouse getting ready */
341 StallExecutionProcessor(10000);
342
343 /* Read first four bytes, which contains Microsoft Mouse signs */
344 TimeOut = 200;
345 for (i = 0; i < 4; i++)
346 {
347 while (((READ_PORT_UCHAR(Port + 5) & 1) == 0) && (TimeOut > 0))
348 {
349 StallExecutionProcessor(1000);
350 --TimeOut;
351 if (TimeOut == 0)
352 return MOUSE_TYPE_NONE;
353 }
354 Buffer[i] = READ_PORT_UCHAR(Port);
355 }
356
357 TRACE("Mouse data: %x %x %x %x\n",
358 Buffer[0], Buffer[1], Buffer[2], Buffer[3]);
359
360 /* Check that four bytes for signs */
361 for (i = 0; i < 4; ++i)
362 {
363 if (Buffer[i] == 'B')
364 {
365 /* Sign for Microsoft Ballpoint */
366 // DbgPrint("Microsoft Ballpoint device detected\n");
367 // DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET\n");
368 return MOUSE_TYPE_NONE;
369 }
370 else if (Buffer[i] == 'M')
371 {
372 /* Sign for Microsoft Mouse protocol followed by button specifier */
373 if (i == 3)
374 {
375 /* Overflow Error */
376 return MOUSE_TYPE_NONE;
377 }
378
379 switch (Buffer[i + 1])
380 {
381 case '3':
382 TRACE("Microsoft Mouse with 3-buttons detected\n");
383 return MOUSE_TYPE_LOGITECH;
384
385 case 'Z':
386 TRACE("Microsoft Wheel Mouse detected\n");
387 return MOUSE_TYPE_WHEELZ;
388
389 /* case '2': */
390 default:
391 TRACE("Microsoft Mouse with 2-buttons detected\n");
392 return MOUSE_TYPE_MICROSOFT;
393 }
394 }
395 }
396
397 return MOUSE_TYPE_NONE;
398 }
399
400 static ULONG
401 GetSerialMousePnpId(PUCHAR Port, char *Buffer)
402 {
403 ULONG TimeOut;
404 ULONG i = 0;
405 char c;
406 char x;
407
408 WRITE_PORT_UCHAR(Port + 4, 0x09);
409
410 /* Wait 10 milliseconds for the mouse getting ready */
411 StallExecutionProcessor(10000);
412
413 WRITE_PORT_UCHAR(Port + 4, 0x0b);
414
415 StallExecutionProcessor(10000);
416
417 for (;;)
418 {
419 TimeOut = 200;
420 while (((READ_PORT_UCHAR(Port + 5) & 1) == 0) && (TimeOut > 0))
421 {
422 StallExecutionProcessor(1000);
423 --TimeOut;
424 if (TimeOut == 0)
425 {
426 return 0;
427 }
428 }
429
430 c = READ_PORT_UCHAR(Port);
431 if (c == 0x08 || c == 0x28)
432 break;
433 }
434
435 Buffer[i++] = c;
436 x = c + 1;
437
438 for (;;)
439 {
440 TimeOut = 200;
441 while (((READ_PORT_UCHAR(Port + 5) & 1) == 0) && (TimeOut > 0))
442 {
443 StallExecutionProcessor(1000);
444 --TimeOut;
445 if (TimeOut == 0)
446 return 0;
447 }
448 c = READ_PORT_UCHAR(Port);
449 Buffer[i++] = c;
450 if (c == x)
451 break;
452 if (i >= 256)
453 break;
454 }
455
456 return i;
457 }
458
459 static
460 VOID
461 DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey,
462 PUCHAR Base)
463 {
464 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
465 char Buffer[256];
466 CHAR Identifier[256];
467 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
468 ULONG MouseType;
469 ULONG Size, Length;
470 ULONG i;
471 ULONG j;
472 ULONG k;
473
474 TRACE("DetectSerialPointerPeripheral()\n");
475
476 Identifier[0] = 0;
477
478 InitializeSerialPort(Base, 2);
479 MouseType = DetectSerialMouse(Base);
480
481 if (MouseType != MOUSE_TYPE_NONE)
482 {
483 Length = GetSerialMousePnpId(Base, Buffer);
484 TRACE( "PnP ID length: %u\n", Length);
485
486 if (Length != 0)
487 {
488 /* Convert PnP sting to ASCII */
489 if (Buffer[0] == 0x08)
490 {
491 for (i = 0; i < Length; i++)
492 Buffer[i] += 0x20;
493 }
494 Buffer[Length] = 0;
495
496 TRACE("PnP ID string: %s\n", Buffer);
497
498 /* Copy PnpId string */
499 for (i = 0; i < 7; i++)
500 {
501 Identifier[i] = Buffer[3 + i];
502 }
503 memcpy(&Identifier[7],
504 L" - ",
505 3 * sizeof(WCHAR));
506
507 /* Skip device serial number */
508 i = 10;
509 if (Buffer[i] == '\\')
510 {
511 for (j = ++i; i < Length; ++i)
512 {
513 if (Buffer[i] == '\\')
514 break;
515 }
516 if (i >= Length)
517 i -= 3;
518 }
519
520 /* Skip PnP class */
521 if (Buffer[i] == '\\')
522 {
523 for (j = ++i; i < Length; ++i)
524 {
525 if (Buffer[i] == '\\')
526 break;
527 }
528
529 if (i >= Length)
530 i -= 3;
531 }
532
533 /* Skip compatible PnP Id */
534 if (Buffer[i] == '\\')
535 {
536 for (j = ++i; i < Length; ++i)
537 {
538 if (Buffer[i] == '\\')
539 break;
540 }
541 if (Buffer[j] == '*')
542 ++j;
543 if (i >= Length)
544 i -= 3;
545 }
546
547 /* Get product description */
548 if (Buffer[i] == '\\')
549 {
550 for (j = ++i; i < Length; ++i)
551 {
552 if (Buffer[i] == ';')
553 break;
554 }
555 if (i >= Length)
556 i -= 3;
557 if (i > j + 1)
558 {
559 for (k = 0; k < i - j; k++)
560 {
561 Identifier[k + 10] = Buffer[k + j];
562 }
563 Identifier[10 + (i - j)] = 0;
564 }
565 }
566
567 TRACE("Identifier string: %s\n", Identifier);
568 }
569
570 if (Length == 0 || strlen(Identifier) < 11)
571 {
572 switch (MouseType)
573 {
574 case MOUSE_TYPE_LOGITECH:
575 strcpy(Identifier, "LOGITECH SERIAL MOUSE");
576 break;
577
578 case MOUSE_TYPE_WHEELZ:
579 strcpy(Identifier, "MICROSOFT SERIAL MOUSE WITH WHEEL");
580 break;
581
582 case MOUSE_TYPE_MICROSOFT:
583 default:
584 strcpy(Identifier, "MICROSOFT SERIAL MOUSE");
585 break;
586 }
587 }
588
589 /* Set 'Configuration Data' value */
590 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) -
591 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
592 PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
593 if (PartialResourceList == NULL)
594 {
595 ERR("Failed to allocate resource descriptor\n");
596 return;
597 }
598 memset(PartialResourceList, 0, Size);
599 PartialResourceList->Version = 1;
600 PartialResourceList->Revision = 1;
601 PartialResourceList->Count = 0;
602
603 /* Create 'PointerPeripheral' key */
604 FldrCreateComponentKey(ControllerKey,
605 PeripheralClass,
606 PointerPeripheral,
607 Input,
608 0x0,
609 0xFFFFFFFF,
610 Identifier,
611 PartialResourceList,
612 Size,
613 &PeripheralKey);
614
615 TRACE("Created key: PointerPeripheral\\0\n");
616 }
617 }
618
619 static
620 VOID
621 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey)
622 {
623 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
624 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
625 PCM_SERIAL_DEVICE_DATA SerialDeviceData;
626 ULONG Irq[MAX_COM_PORTS] = {4, 3, 4, 3};
627 ULONG Base;
628 CHAR Buffer[80];
629 PUSHORT BasePtr;
630 ULONG ControllerNumber = 0;
631 PCONFIGURATION_COMPONENT_DATA ControllerKey;
632 ULONG i;
633 ULONG Size;
634
635 TRACE("DetectSerialPorts()\n");
636
637 /*
638 * The BIOS data area 0x400 holds the address of the first valid COM port.
639 * Each COM port address is stored in a 2-byte field.
640 * Infos at: http://www.bioscentral.com/misc/bda.htm
641 */
642 BasePtr = (PUSHORT)0x400;
643
644 for (i = 0; i < MAX_COM_PORTS; i++, BasePtr++)
645 {
646 Base = (ULONG) * BasePtr;
647 if (Base == 0 || !CpDoesPortExist((PUCHAR)Base))
648 continue;
649
650 TRACE("Found COM%u port at 0x%x\n", i + 1, Base);
651
652 /* Set 'Identifier' value */
653 sprintf(Buffer, "COM%ld", i + 1);
654
655 /* Build full device descriptor */
656 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
657 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) +
658 sizeof(CM_SERIAL_DEVICE_DATA);
659 PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
660 if (PartialResourceList == NULL)
661 {
662 ERR("Failed to allocate resource descriptor\n");
663 continue;
664 }
665 memset(PartialResourceList, 0, Size);
666
667 /* Initialize resource descriptor */
668 PartialResourceList->Version = 1;
669 PartialResourceList->Revision = 1;
670 PartialResourceList->Count = 3;
671
672 /* Set IO Port */
673 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
674 PartialDescriptor->Type = CmResourceTypePort;
675 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
676 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
677 PartialDescriptor->u.Port.Start.LowPart = Base;
678 PartialDescriptor->u.Port.Start.HighPart = 0x0;
679 PartialDescriptor->u.Port.Length = 7;
680
681 /* Set Interrupt */
682 PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
683 PartialDescriptor->Type = CmResourceTypeInterrupt;
684 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
685 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
686 PartialDescriptor->u.Interrupt.Level = Irq[i];
687 PartialDescriptor->u.Interrupt.Vector = Irq[i];
688 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
689
690 /* Set serial data (device specific) */
691 PartialDescriptor = &PartialResourceList->PartialDescriptors[2];
692 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
693 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
694 PartialDescriptor->Flags = 0;
695 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_SERIAL_DEVICE_DATA);
696
697 SerialDeviceData =
698 (PCM_SERIAL_DEVICE_DATA)&PartialResourceList->PartialDescriptors[3];
699 SerialDeviceData->BaudClock = 1843200; /* UART Clock frequency (Hertz) */
700
701 /* Create controller key */
702 FldrCreateComponentKey(BusKey,
703 ControllerClass,
704 SerialController,
705 Output | Input | ConsoleIn | ConsoleOut,
706 ControllerNumber,
707 0xFFFFFFFF,
708 Buffer,
709 PartialResourceList,
710 Size,
711 &ControllerKey);
712
713 if (!Rs232PortInUse(UlongToPtr(Base)))
714 {
715 /* Detect serial mouse */
716 DetectSerialPointerPeripheral(ControllerKey, UlongToPtr(Base));
717 }
718
719 ControllerNumber++;
720 }
721 }
722
723 static VOID
724 DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey)
725 {
726 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
727 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
728 ULONG Irq[MAX_LPT_PORTS] = {7, 5, (ULONG) - 1};
729 CHAR Buffer[80];
730 PCONFIGURATION_COMPONENT_DATA ControllerKey;
731 PUSHORT BasePtr;
732 ULONG Base;
733 ULONG ControllerNumber = 0;
734 ULONG i;
735 ULONG Size;
736
737 TRACE("DetectParallelPorts() called\n");
738
739 /*
740 * The BIOS data area 0x408 holds the address of the first valid LPT port.
741 * Each LPT port address is stored in a 2-byte field.
742 * Infos at: http://www.bioscentral.com/misc/bda.htm
743 */
744 BasePtr = (PUSHORT)0x408;
745
746 for (i = 0; i < MAX_LPT_PORTS; i++, BasePtr++)
747 {
748 Base = (ULONG) * BasePtr;
749 if (Base == 0)
750 continue;
751
752 TRACE("Parallel port %u: %x\n", ControllerNumber, Base);
753
754 /* Set 'Identifier' value */
755 sprintf(Buffer, "PARALLEL%ld", i + 1);
756
757 /* Build full device descriptor */
758 Size = sizeof(CM_PARTIAL_RESOURCE_LIST);
759 if (Irq[i] != (ULONG) - 1)
760 Size += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
761
762 PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
763 if (PartialResourceList == NULL)
764 {
765 ERR("Failed to allocate resource descriptor\n");
766 continue;
767 }
768 memset(PartialResourceList, 0, Size);
769
770 /* Initialize resource descriptor */
771 PartialResourceList->Version = 1;
772 PartialResourceList->Revision = 1;
773 PartialResourceList->Count = (Irq[i] != (ULONG) - 1) ? 2 : 1;
774
775 /* Set IO Port */
776 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
777 PartialDescriptor->Type = CmResourceTypePort;
778 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
779 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
780 PartialDescriptor->u.Port.Start.LowPart = Base;
781 PartialDescriptor->u.Port.Start.HighPart = 0x0;
782 PartialDescriptor->u.Port.Length = 3;
783
784 /* Set Interrupt */
785 if (Irq[i] != (ULONG) - 1)
786 {
787 PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
788 PartialDescriptor->Type = CmResourceTypeInterrupt;
789 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
790 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
791 PartialDescriptor->u.Interrupt.Level = Irq[i];
792 PartialDescriptor->u.Interrupt.Vector = Irq[i];
793 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
794 }
795
796 /* Create controller key */
797 FldrCreateComponentKey(BusKey,
798 ControllerClass,
799 ParallelController,
800 Output,
801 ControllerNumber,
802 0xFFFFFFFF,
803 Buffer,
804 PartialResourceList,
805 Size,
806 &ControllerKey);
807
808 ControllerNumber++;
809 }
810
811 TRACE("DetectParallelPorts() done\n");
812 }
813
814 //static
815 BOOLEAN
816 DetectKeyboardDevice(VOID)
817 {
818 UCHAR Status;
819 UCHAR Scancode;
820 ULONG Loops;
821 BOOLEAN Result = TRUE;
822
823 /* Identify device */
824 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA, 0xF2);
825
826 /* Wait for reply */
827 for (Loops = 0; Loops < 100; Loops++)
828 {
829 StallExecutionProcessor(10000);
830 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
831 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
832 break;
833 }
834
835 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) == 0)
836 {
837 /* PC/XT keyboard or no keyboard */
838 Result = FALSE;
839 }
840
841 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
842 if (Scancode != 0xFA)
843 {
844 /* No ACK received */
845 Result = FALSE;
846 }
847
848 StallExecutionProcessor(10000);
849
850 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
851 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) == 0)
852 {
853 /* Found AT keyboard */
854 return Result;
855 }
856
857 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
858 if (Scancode != 0xAB)
859 {
860 /* No 0xAB received */
861 Result = FALSE;
862 }
863
864 StallExecutionProcessor(10000);
865
866 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
867 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) == 0)
868 {
869 /* No byte in buffer */
870 Result = FALSE;
871 }
872
873 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
874 if (Scancode != 0x41)
875 {
876 /* No 0x41 received */
877 Result = FALSE;
878 }
879
880 /* Found MF-II keyboard */
881 return Result;
882 }
883
884 static VOID
885 DetectKeyboardPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey)
886 {
887 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
888 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
889 PCM_KEYBOARD_DEVICE_DATA KeyboardData;
890 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
891 ULONG Size;
892
893 /* HACK: don't call DetectKeyboardDevice() as it fails in Qemu 0.8.2
894 if (DetectKeyboardDevice()) */
895 {
896 /* Set 'Configuration Data' value */
897 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
898 sizeof(CM_KEYBOARD_DEVICE_DATA);
899 PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
900 if (PartialResourceList == NULL)
901 {
902 ERR("Failed to allocate resource descriptor\n");
903 return;
904 }
905
906 /* Initialize resource descriptor */
907 memset(PartialResourceList, 0, Size);
908 PartialResourceList->Version = 1;
909 PartialResourceList->Revision = 1;
910 PartialResourceList->Count = 1;
911
912 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
913 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
914 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
915 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_KEYBOARD_DEVICE_DATA);
916
917 KeyboardData = (PCM_KEYBOARD_DEVICE_DATA)(PartialDescriptor + 1);
918 KeyboardData->Version = 1;
919 KeyboardData->Revision = 1;
920 KeyboardData->Type = 4;
921 KeyboardData->Subtype = 0;
922 KeyboardData->KeyboardFlags = 0x20;
923
924 /* Create controller key */
925 FldrCreateComponentKey(ControllerKey,
926 PeripheralClass,
927 KeyboardPeripheral,
928 Input | ConsoleIn,
929 0x0,
930 0xFFFFFFFF,
931 "PCAT_ENHANCED",
932 PartialResourceList,
933 Size,
934 &PeripheralKey);
935 TRACE("Created key: KeyboardPeripheral\\0\n");
936 }
937 }
938
939 static
940 VOID
941 DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey)
942 {
943 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
944 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
945 PCONFIGURATION_COMPONENT_DATA ControllerKey;
946 ULONG Size;
947
948 /* Set 'Configuration Data' value */
949 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
950 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
951 PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
952 if (PartialResourceList == NULL)
953 {
954 ERR("Failed to allocate resource descriptor\n");
955 return;
956 }
957
958 /* Initialize resource descriptor */
959 memset(PartialResourceList, 0, Size);
960 PartialResourceList->Version = 1;
961 PartialResourceList->Revision = 1;
962 PartialResourceList->Count = 3;
963
964 /* Set Interrupt */
965 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
966 PartialDescriptor->Type = CmResourceTypeInterrupt;
967 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
968 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
969 PartialDescriptor->u.Interrupt.Level = 1;
970 PartialDescriptor->u.Interrupt.Vector = 1;
971 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
972
973 /* Set IO Port 0x60 */
974 PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
975 PartialDescriptor->Type = CmResourceTypePort;
976 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
977 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
978 PartialDescriptor->u.Port.Start.LowPart = 0x60;
979 PartialDescriptor->u.Port.Start.HighPart = 0x0;
980 PartialDescriptor->u.Port.Length = 1;
981
982 /* Set IO Port 0x64 */
983 PartialDescriptor = &PartialResourceList->PartialDescriptors[2];
984 PartialDescriptor->Type = CmResourceTypePort;
985 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
986 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
987 PartialDescriptor->u.Port.Start.LowPart = 0x64;
988 PartialDescriptor->u.Port.Start.HighPart = 0x0;
989 PartialDescriptor->u.Port.Length = 1;
990
991 /* Create controller key */
992 FldrCreateComponentKey(BusKey,
993 ControllerClass,
994 KeyboardController,
995 Input | ConsoleIn,
996 0x0,
997 0xFFFFFFFF,
998 NULL,
999 PartialResourceList,
1000 Size,
1001 &ControllerKey);
1002 TRACE("Created key: KeyboardController\\0\n");
1003
1004 DetectKeyboardPeripheral(ControllerKey);
1005 }
1006
1007 static
1008 VOID
1009 PS2ControllerWait(VOID)
1010 {
1011 ULONG Timeout;
1012 UCHAR Status;
1013
1014 for (Timeout = 0; Timeout < CONTROLLER_TIMEOUT; Timeout++)
1015 {
1016 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1017 if ((Status & CONTROLLER_STATUS_INPUT_BUFFER_FULL) == 0)
1018 return;
1019
1020 /* Sleep for one millisecond */
1021 StallExecutionProcessor(1000);
1022 }
1023 }
1024
1025 static
1026 BOOLEAN
1027 DetectPS2AuxPort(VOID)
1028 {
1029 #if 1
1030 /* Current detection is too unreliable. Just do as if
1031 * the PS/2 aux port is always present
1032 */
1033 return TRUE;
1034 #else
1035 ULONG Loops;
1036 UCHAR Status;
1037
1038 /* Put the value 0x5A in the output buffer using the
1039 * "WriteAuxiliary Device Output Buffer" command (0xD3).
1040 * Poll the Status Register for a while to see if the value really turns up
1041 * in the Data Register. If the KEYBOARD_STATUS_MOUSE_OBF bit is also set
1042 * to 1 in the Status Register, we assume this controller has an
1043 * Auxiliary Port (a.k.a. Mouse Port).
1044 */
1045 PS2ControllerWait();
1046 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL,
1047 CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER);
1048 PS2ControllerWait();
1049
1050 /* 0x5A is a random dummy value */
1051 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
1052 0x5A);
1053
1054 for (Loops = 0; Loops < 10; Loops++)
1055 {
1056 StallExecutionProcessor(10000);
1057 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1058 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
1059 break;
1060 }
1061
1062 READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1063
1064 return (Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL);
1065 #endif
1066 }
1067
1068 static
1069 BOOLEAN
1070 DetectPS2AuxDevice(VOID)
1071 {
1072 UCHAR Scancode;
1073 UCHAR Status;
1074 ULONG Loops;
1075 BOOLEAN Result = TRUE;
1076
1077 PS2ControllerWait();
1078 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL,
1079 CONTROLLER_COMMAND_WRITE_MOUSE);
1080 PS2ControllerWait();
1081
1082 /* Identify device */
1083 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA, 0xF2);
1084
1085 /* Wait for reply */
1086 for (Loops = 0; Loops < 100; Loops++)
1087 {
1088 StallExecutionProcessor(10000);
1089 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1090 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
1091 break;
1092 }
1093
1094 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1095 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
1096 Result = FALSE;
1097
1098 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1099 if (Scancode != 0xFA)
1100 Result = FALSE;
1101
1102 StallExecutionProcessor(10000);
1103
1104 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
1105 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
1106 Result = FALSE;
1107
1108 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
1109 if (Scancode != 0x00)
1110 Result = FALSE;
1111
1112 return Result;
1113 }
1114
1115 // FIXME: Missing: DetectPS2Peripheral!! (for corresponding 'PointerPeripheral')
1116
1117 static
1118 VOID
1119 DetectPS2Mouse(PCONFIGURATION_COMPONENT_DATA BusKey)
1120 {
1121 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1122 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1123 PCONFIGURATION_COMPONENT_DATA PeripheralKey;
1124 ULONG Size;
1125
1126 if (DetectPS2AuxPort())
1127 {
1128 TRACE("Detected PS2 port\n");
1129
1130 PartialResourceList = FrLdrHeapAlloc(sizeof(CM_PARTIAL_RESOURCE_LIST), TAG_HW_RESOURCE_LIST);
1131 if (PartialResourceList == NULL)
1132 {
1133 ERR("Failed to allocate resource descriptor\n");
1134 return;
1135 }
1136 memset(PartialResourceList, 0, sizeof(CM_PARTIAL_RESOURCE_LIST));
1137
1138 /* Initialize resource descriptor */
1139 PartialResourceList->Version = 1;
1140 PartialResourceList->Revision = 1;
1141 PartialResourceList->Count = 1;
1142
1143 /* Set Interrupt */
1144 PartialResourceList->PartialDescriptors[0].Type = CmResourceTypeInterrupt;
1145 PartialResourceList->PartialDescriptors[0].ShareDisposition = CmResourceShareUndetermined;
1146 PartialResourceList->PartialDescriptors[0].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1147 PartialResourceList->PartialDescriptors[0].u.Interrupt.Level = 12;
1148 PartialResourceList->PartialDescriptors[0].u.Interrupt.Vector = 12;
1149 PartialResourceList->PartialDescriptors[0].u.Interrupt.Affinity = 0xFFFFFFFF;
1150
1151 /* Create controller key */
1152 FldrCreateComponentKey(BusKey,
1153 ControllerClass,
1154 PointerController,
1155 Input,
1156 0x0,
1157 0xFFFFFFFF,
1158 NULL,
1159 PartialResourceList,
1160 sizeof(CM_PARTIAL_RESOURCE_LIST),
1161 &ControllerKey);
1162 TRACE("Created key: PointerController\\0\n");
1163
1164 if (DetectPS2AuxDevice())
1165 {
1166 TRACE("Detected PS2 mouse\n");
1167
1168 /* Initialize resource descriptor */
1169 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) -
1170 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1171 PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
1172 if (PartialResourceList == NULL)
1173 {
1174 ERR("Failed to allocate resource descriptor\n");
1175 return;
1176 }
1177 memset(PartialResourceList, 0, Size);
1178 PartialResourceList->Version = 1;
1179 PartialResourceList->Revision = 1;
1180 PartialResourceList->Count = 0;
1181
1182 /* Create peripheral key */
1183 FldrCreateComponentKey(ControllerKey,
1184 ControllerClass,
1185 PointerPeripheral,
1186 Input,
1187 0x0,
1188 0xFFFFFFFF,
1189 "MICROSOFT PS2 MOUSE",
1190 PartialResourceList,
1191 Size,
1192 &PeripheralKey);
1193 TRACE("Created key: PointerPeripheral\\0\n");
1194 }
1195 }
1196 }
1197
1198 static VOID
1199 DetectDisplayController(PCONFIGURATION_COMPONENT_DATA BusKey)
1200 {
1201 CHAR Buffer[80];
1202 PCONFIGURATION_COMPONENT_DATA ControllerKey;
1203 USHORT VesaVersion;
1204
1205 /* FIXME: Set 'ComponentInformation' value */
1206
1207 VesaVersion = BiosIsVesaSupported();
1208 if (VesaVersion != 0)
1209 {
1210 TRACE("VESA version %c.%c\n",
1211 (VesaVersion >> 8) + '0',
1212 (VesaVersion & 0xFF) + '0');
1213 }
1214 else
1215 {
1216 TRACE("VESA not supported\n");
1217 }
1218
1219 if (VesaVersion >= 0x0200)
1220 {
1221 strcpy(Buffer, "VBE Display");
1222 }
1223 else
1224 {
1225 strcpy(Buffer, "VGA Display");
1226 }
1227
1228 FldrCreateComponentKey(BusKey,
1229 ControllerClass,
1230 DisplayController,
1231 0x0,
1232 0x0,
1233 0xFFFFFFFF,
1234 Buffer,
1235 NULL,
1236 0,
1237 &ControllerKey);
1238 TRACE("Created key: DisplayController\\0\n");
1239
1240 /* FIXME: Add display peripheral (monitor) data */
1241 if (VesaVersion != 0)
1242 {
1243 if (BiosIsVesaDdcSupported())
1244 {
1245 TRACE("VESA/DDC supported!\n");
1246 if (BiosVesaReadEdid())
1247 {
1248 TRACE("EDID data read successfully!\n");
1249
1250 }
1251 }
1252 }
1253 }
1254
1255 extern VOID
1256 DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA BusKey);
1257
1258 static
1259 VOID
1260 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
1261 {
1262 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
1263 PCONFIGURATION_COMPONENT_DATA BusKey;
1264 ULONG Size;
1265
1266 /* Set 'Configuration Data' value */
1267 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) -
1268 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1269 PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
1270 if (PartialResourceList == NULL)
1271 {
1272 ERR("Failed to allocate resource descriptor\n");
1273 return;
1274 }
1275
1276 /* Initialize resource descriptor */
1277 memset(PartialResourceList, 0, Size);
1278 PartialResourceList->Version = 1;
1279 PartialResourceList->Revision = 1;
1280 PartialResourceList->Count = 0;
1281
1282 /* Create new bus key */
1283 FldrCreateComponentKey(SystemKey,
1284 AdapterClass,
1285 MultiFunctionAdapter,
1286 0x0,
1287 0x0,
1288 0xFFFFFFFF,
1289 "ISA",
1290 PartialResourceList,
1291 Size,
1292 &BusKey);
1293
1294 /* Increment bus number */
1295 (*BusNumber)++;
1296
1297 /* Detect ISA/BIOS devices */
1298 DetectBiosDisks(BusKey);
1299 DetectSerialPorts(BusKey);
1300 DetectParallelPorts(BusKey);
1301 DetectKeyboardController(BusKey);
1302 DetectPS2Mouse(BusKey);
1303 DetectDisplayController(BusKey);
1304
1305 /* FIXME: Detect more ISA devices */
1306 }
1307
1308 extern PCONFIGURATION_COMPONENT_DATA
1309 DetectSystem(VOID);
1310
1311 PCONFIGURATION_COMPONENT_DATA
1312 PcHwDetect(VOID)
1313 {
1314 PCONFIGURATION_COMPONENT_DATA SystemKey;
1315 ULONG BusNumber = 0;
1316
1317 TRACE("DetectHardware()\n");
1318
1319 /* Create the 'System' key */
1320 SystemKey = DetectSystem();
1321
1322 /* Detect buses */
1323 DetectPciBios(SystemKey, &BusNumber);
1324 DetectApmBios(SystemKey, &BusNumber);
1325 DetectPnpBios(SystemKey, &BusNumber);
1326 DetectIsaBios(SystemKey, &BusNumber); // TODO: Detect first EISA or MCA, before ISA
1327 DetectAcpiBios(SystemKey, &BusNumber);
1328
1329 TRACE("DetectHardware() Done\n");
1330 return SystemKey;
1331 }
1332
1333 VOID
1334 PcHwIdle(VOID)
1335 {
1336 REGS Regs;
1337
1338 /* Select APM 1.0+ function */
1339 Regs.b.ah = 0x53;
1340
1341 /* Function 05h: CPU idle */
1342 Regs.b.al = 0x05;
1343
1344 /* Call INT 15h */
1345 Int386(0x15, &Regs, &Regs);
1346
1347 /* Check if successfull (CF set on error) */
1348 if (INT386_SUCCESS(Regs))
1349 return;
1350
1351 /*
1352 * No futher processing here.
1353 * Optionally implement HLT instruction handling.
1354 */
1355 }
1356
1357
1358 /******************************************************************************/
1359
1360 VOID
1361 PcMachInit(const char *CmdLine)
1362 {
1363 /* Setup vtbl */
1364 MachVtbl.ConsPutChar = PcConsPutChar;
1365 MachVtbl.ConsKbHit = PcConsKbHit;
1366 MachVtbl.ConsGetCh = PcConsGetCh;
1367 MachVtbl.VideoClearScreen = PcVideoClearScreen;
1368 MachVtbl.VideoSetDisplayMode = PcVideoSetDisplayMode;
1369 MachVtbl.VideoGetDisplaySize = PcVideoGetDisplaySize;
1370 MachVtbl.VideoGetBufferSize = PcVideoGetBufferSize;
1371 MachVtbl.VideoSetTextCursorPosition = PcVideoSetTextCursorPosition;
1372 MachVtbl.VideoHideShowTextCursor = PcVideoHideShowTextCursor;
1373 MachVtbl.VideoPutChar = PcVideoPutChar;
1374 MachVtbl.VideoCopyOffScreenBufferToVRAM = PcVideoCopyOffScreenBufferToVRAM;
1375 MachVtbl.VideoIsPaletteFixed = PcVideoIsPaletteFixed;
1376 MachVtbl.VideoSetPaletteColor = PcVideoSetPaletteColor;
1377 MachVtbl.VideoGetPaletteColor = PcVideoGetPaletteColor;
1378 MachVtbl.VideoSync = PcVideoSync;
1379 MachVtbl.Beep = PcBeep;
1380 MachVtbl.PrepareForReactOS = PcPrepareForReactOS;
1381 MachVtbl.GetMemoryMap = PcMemGetMemoryMap;
1382 MachVtbl.DiskGetBootPath = PcDiskGetBootPath;
1383 MachVtbl.DiskReadLogicalSectors = PcDiskReadLogicalSectors;
1384 MachVtbl.DiskGetDriveGeometry = PcDiskGetDriveGeometry;
1385 MachVtbl.DiskGetCacheableBlockCount = PcDiskGetCacheableBlockCount;
1386 MachVtbl.GetTime = PcGetTime;
1387 MachVtbl.InitializeBootDevices = PcInitializeBootDevices;
1388 MachVtbl.HwDetect = PcHwDetect;
1389 MachVtbl.HwIdle = PcHwIdle;
1390 }
1391
1392 VOID
1393 PcPrepareForReactOS(IN BOOLEAN Setup)
1394 {
1395 /* On PC, prepare video and turn off the floppy motor */
1396 PcVideoPrepareForReactOS(Setup);
1397 DiskStopFloppyMotor();
1398 }
1399
1400 /* EOF */