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