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