4 * Copyright (C) 2003, 2004 Eric Kohl
5 * Copyright (C) 2009 Hervé Poussineau
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include <cportlib/cportlib.h>
32 #define CLOCK_TICK_RATE (1193182)
33 #define LATCH (CLOCK_TICK_RATE / HZ)
36 /* Maximum number of COM and LPT ports */
37 #define MAX_COM_PORTS 4
38 #define MAX_LPT_PORTS 3
41 #define MOUSE_TYPE_NONE 0
42 /* Microsoft Mouse with 2 buttons */
43 #define MOUSE_TYPE_MICROSOFT 1
44 /* Logitech Mouse with 3 buttons */
45 #define MOUSE_TYPE_LOGITECH 2
46 /* Microsoft Wheel Mouse (aka Z Mouse) */
47 #define MOUSE_TYPE_WHEELZ 3
48 /* Mouse Systems Mouse */
49 #define MOUSE_TYPE_MOUSESYSTEMS 4
54 /* Controller registers. */
55 #define CONTROLLER_REGISTER_STATUS 0x64
56 #define CONTROLLER_REGISTER_CONTROL 0x64
57 #define CONTROLLER_REGISTER_DATA 0x60
59 /* Controller commands. */
60 #define CONTROLLER_COMMAND_READ_MODE 0x20
61 #define CONTROLLER_COMMAND_WRITE_MODE 0x60
62 #define CONTROLLER_COMMAND_GET_VERSION 0xA1
63 #define CONTROLLER_COMMAND_MOUSE_DISABLE 0xA7
64 #define CONTROLLER_COMMAND_MOUSE_ENABLE 0xA8
65 #define CONTROLLER_COMMAND_TEST_MOUSE 0xA9
66 #define CONTROLLER_COMMAND_SELF_TEST 0xAA
67 #define CONTROLLER_COMMAND_KEYBOARD_TEST 0xAB
68 #define CONTROLLER_COMMAND_KEYBOARD_DISABLE 0xAD
69 #define CONTROLLER_COMMAND_KEYBOARD_ENABLE 0xAE
70 #define CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER 0xD3
71 #define CONTROLLER_COMMAND_WRITE_MOUSE 0xD4
73 /* Controller status */
74 #define CONTROLLER_STATUS_OUTPUT_BUFFER_FULL 0x01
75 #define CONTROLLER_STATUS_INPUT_BUFFER_FULL 0x02
76 #define CONTROLLER_STATUS_SELF_TEST 0x04
77 #define CONTROLLER_STATUS_COMMAND 0x08
78 #define CONTROLLER_STATUS_UNLOCKED 0x10
79 #define CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL 0x20
80 #define CONTROLLER_STATUS_GENERAL_TIMEOUT 0x40
81 #define CONTROLLER_STATUS_PARITY_ERROR 0x80
82 #define AUX_STATUS_OUTPUT_BUFFER_FULL (CONTROLLER_STATUS_OUTPUT_BUFFER_FULL | \
83 CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL)
85 /* Timeout in ms for sending to keyboard controller. */
86 #define CONTROLLER_TIMEOUT 250
88 DBG_DEFAULT_CHANNEL(HWDETECT
);
90 static unsigned int delay_count
= 1;
92 extern UCHAR PcBiosDiskCount
;
95 GetHarddiskIdentifier(
99 HwInitializeBiosDisks(VOID
);
101 /* FUNCTIONS ****************************************************************/
106 __StallExecutionProcessor(ULONG Loops
)
108 register volatile unsigned int i
;
109 for (i
= 0; i
< Loops
; i
++);
113 VOID
StallExecutionProcessor(ULONG Microseconds
)
115 ULONGLONG LoopCount
= ((ULONGLONG
)delay_count
* (ULONGLONG
)Microseconds
) / 1000ULL;
116 __StallExecutionProcessor((ULONG
)LoopCount
);
126 WRITE_PORT_UCHAR((PUCHAR
)0x43, 0x00);
127 Count
= READ_PORT_UCHAR((PUCHAR
)0x40);
128 Count
|= READ_PORT_UCHAR((PUCHAR
)0x40) << 8;
136 WaitFor8254Wraparound(VOID
)
139 ULONG PrevCount
= ~0;
142 CurCount
= Read8254Timer();
146 PrevCount
= CurCount
;
147 CurCount
= Read8254Timer();
148 Delta
= CurCount
- PrevCount
;
151 * This limit for delta seems arbitrary, but it isn't, it's
152 * slightly above the level of error a buggy Mercury/Neptune
153 * chipset timer can cause.
161 HalpCalibrateStallExecution(VOID
)
167 /* Initialise timer interrupt with MILLISECOND ms interval */
168 WRITE_PORT_UCHAR((PUCHAR
)0x43, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */
169 WRITE_PORT_UCHAR((PUCHAR
)0x40, LATCH
& 0xff); /* LSB */
170 WRITE_PORT_UCHAR((PUCHAR
)0x40, LATCH
>> 8); /* MSB */
172 /* Stage 1: Coarse calibration */
174 WaitFor8254Wraparound();
180 /* Next delay count to try */
183 WaitFor8254Wraparound();
186 __StallExecutionProcessor(delay_count
);
188 CurCount
= Read8254Timer();
190 while (CurCount
> LATCH
/ 2);
192 /* Get bottom value for delay */
195 /* Stage 2: Fine calibration */
197 /* Which bit are we going to test */
198 calib_bit
= delay_count
;
200 for (i
= 0; i
< PRECISION
; i
++)
202 /* Next bit to calibrate */
205 /* If we have done all bits, stop */
206 if (!calib_bit
) break;
208 /* Set the bit in delay_count */
209 delay_count
|= calib_bit
;
211 WaitFor8254Wraparound();
214 __StallExecutionProcessor(delay_count
);
216 CurCount
= Read8254Timer();
217 /* If a tick has passed, turn the calibrated bit back off */
218 if (CurCount
<= LATCH
/ 2)
219 delay_count
&= ~calib_bit
;
222 /* We're finished: Do the finishing touches */
224 /* Calculate delay_count for 1ms */
225 delay_count
/= (MILLISEC
/ 2);
230 DetectPnpBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
232 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
233 PCM_PNP_BIOS_DEVICE_NODE DeviceNode
;
234 PCM_PNP_BIOS_INSTALLATION_CHECK InstData
;
235 PCONFIGURATION_COMPONENT_DATA BusKey
;
240 ULONG FoundNodeCount
;
246 InstData
= (PCM_PNP_BIOS_INSTALLATION_CHECK
)PnpBiosSupported();
247 if (InstData
== NULL
|| strncmp((CHAR
*)InstData
->Signature
, "$PnP", 4))
249 TRACE("PnP-BIOS not supported\n");
253 TRACE("PnP-BIOS supported\n");
254 TRACE("Signature '%c%c%c%c'\n",
255 InstData
->Signature
[0], InstData
->Signature
[1],
256 InstData
->Signature
[2], InstData
->Signature
[3]);
258 x
= PnpBiosGetDeviceNodeCount(&NodeSize
, &NodeCount
);
261 TRACE("PnP-BIOS function 'Get Number of System Device Nodes' not supported\n");
265 NodeCount
&= 0xFF; // needed since some fscked up BIOSes return
266 // wrong info (e.g. Mac Virtual PC)
267 // e.g. look: http://my.execpc.com/~geezer/osd/pnp/pnp16.c
268 if (x
!= 0 || NodeSize
== 0 || NodeCount
== 0)
270 ERR("PnP-BIOS failed to enumerate device nodes\n");
273 TRACE("MaxNodeSize %u NodeCount %u\n", NodeSize
, NodeCount
);
274 TRACE("Estimated buffer size %u\n", NodeSize
* NodeCount
);
276 /* Set 'Configuration Data' value */
277 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
)
278 + sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
) + (NodeSize
* NodeCount
);
279 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
280 if (PartialResourceList
== NULL
)
282 ERR("Failed to allocate resource descriptor\n");
285 memset(PartialResourceList
, 0, Size
);
287 /* Initialize resource descriptor */
288 PartialResourceList
->Version
= 1;
289 PartialResourceList
->Revision
= 1;
290 PartialResourceList
->Count
= 1;
291 PartialResourceList
->PartialDescriptors
[0].Type
=
292 CmResourceTypeDeviceSpecific
;
293 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
=
294 CmResourceShareUndetermined
;
296 /* The buffer starts after PartialResourceList->PartialDescriptors[0] */
297 Ptr
= (char *)(PartialResourceList
+ 1);
299 /* Set instalation check data */
300 memcpy (Ptr
, InstData
, sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
));
301 Ptr
+= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
303 /* Copy device nodes */
305 PnpBufferSize
= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
306 for (i
= 0; i
< 0xFF; i
++)
308 NodeNumber
= (UCHAR
)i
;
310 x
= PnpBiosGetDeviceNode(&NodeNumber
, (PVOID
)DISKREADBUFFER
);
313 DeviceNode
= (PCM_PNP_BIOS_DEVICE_NODE
)DISKREADBUFFER
;
315 TRACE("Node: %u Size %u (0x%x)\n",
320 if (PnpBufferSize
+ DeviceNode
->Size
> Size
)
322 ERR("Buffer too small!\n");
326 memcpy(Ptr
, DeviceNode
, DeviceNode
->Size
);
328 Ptr
+= DeviceNode
->Size
;
329 PnpBufferSize
+= DeviceNode
->Size
;
332 if (FoundNodeCount
>= NodeCount
)
337 /* Set real data size */
338 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
340 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) + PnpBufferSize
;
342 TRACE("Real buffer size: %u\n", PnpBufferSize
);
343 TRACE("Resource size: %u\n", Size
);
345 /* Create component key */
346 FldrCreateComponentKey(SystemKey
,
348 MultiFunctionAdapter
,
362 static PCM_PARTIAL_RESOURCE_LIST
363 GetHarddiskConfigurationData(UCHAR DriveNumber
, ULONG
* pSize
)
365 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
366 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
367 EXTENDED_GEOMETRY ExtGeometry
;
372 // Initialize returned size
376 /* Set 'Configuration Data' value */
377 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
378 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
379 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
380 if (PartialResourceList
== NULL
)
382 ERR("Failed to allocate a full resource descriptor\n");
386 memset(PartialResourceList
, 0, Size
);
387 PartialResourceList
->Version
= 1;
388 PartialResourceList
->Revision
= 1;
389 PartialResourceList
->Count
= 1;
390 PartialResourceList
->PartialDescriptors
[0].Type
=
391 CmResourceTypeDeviceSpecific
;
392 // PartialResourceList->PartialDescriptors[0].ShareDisposition =
393 // PartialResourceList->PartialDescriptors[0].Flags =
394 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
395 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
397 /* Get pointer to geometry data */
398 DiskGeometry
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
400 /* Get the disk geometry */
401 ExtGeometry
.Size
= sizeof(EXTENDED_GEOMETRY
);
402 if (DiskGetExtendedDriveParameters(DriveNumber
, &ExtGeometry
, ExtGeometry
.Size
))
404 DiskGeometry
->BytesPerSector
= ExtGeometry
.BytesPerSector
;
405 DiskGeometry
->NumberOfCylinders
= ExtGeometry
.Cylinders
;
406 DiskGeometry
->SectorsPerTrack
= ExtGeometry
.SectorsPerTrack
;
407 DiskGeometry
->NumberOfHeads
= ExtGeometry
.Heads
;
409 else if(MachDiskGetDriveGeometry(DriveNumber
, &Geometry
))
411 DiskGeometry
->BytesPerSector
= Geometry
.BytesPerSector
;
412 DiskGeometry
->NumberOfCylinders
= Geometry
.Cylinders
;
413 DiskGeometry
->SectorsPerTrack
= Geometry
.Sectors
;
414 DiskGeometry
->NumberOfHeads
= Geometry
.Heads
;
418 TRACE("Reading disk geometry failed\n");
419 FrLdrHeapFree(PartialResourceList
, TAG_HW_RESOURCE_LIST
);
422 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
424 DiskGeometry
->NumberOfCylinders
,
425 DiskGeometry
->NumberOfHeads
,
426 DiskGeometry
->SectorsPerTrack
,
427 DiskGeometry
->BytesPerSector
);
430 // Return configuration data
433 return PartialResourceList
;
442 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0x10);
443 Data
= READ_PORT_UCHAR((PUCHAR
)0x71);
445 return ((Data
& 0xF0) ? 1 : 0) + ((Data
& 0x0F) ? 1 : 0);
451 GetFloppyType(UCHAR DriveNumber
)
455 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0x10);
456 Data
= READ_PORT_UCHAR((PUCHAR
)0x71);
458 if (DriveNumber
== 0)
460 else if (DriveNumber
== 1)
471 PUSHORT SegPtr
= (PUSHORT
)0x7A;
472 PUSHORT OfsPtr
= (PUSHORT
)0x78;
474 return (PVOID
)((ULONG_PTR
)(((ULONG
)(*SegPtr
)) << 4) + (ULONG
)(*OfsPtr
));
480 DetectBiosFloppyPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
)
482 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
483 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
484 PCM_FLOPPY_DEVICE_DATA FloppyData
;
486 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
490 ULONG MaxDensity
[6] = {0, 360, 1200, 720, 1440, 2880};
493 for (FloppyNumber
= 0; FloppyNumber
< 2; FloppyNumber
++)
495 FloppyType
= GetFloppyType(FloppyNumber
);
497 if ((FloppyType
> 5) || (FloppyType
== 0))
500 if (!DiskResetController(FloppyNumber
))
503 Ptr
= GetInt1eTable();
505 /* Set 'Identifier' value */
506 sprintf(Identifier
, "FLOPPY%d", FloppyNumber
+ 1);
508 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
509 sizeof(CM_FLOPPY_DEVICE_DATA
);
510 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
511 if (PartialResourceList
== NULL
)
513 ERR("Failed to allocate resource descriptor\n");
517 memset(PartialResourceList
, 0, Size
);
518 PartialResourceList
->Version
= 1;
519 PartialResourceList
->Revision
= 1;
520 PartialResourceList
->Count
= 1;
522 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
523 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
524 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
525 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_FLOPPY_DEVICE_DATA
);
527 FloppyData
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
528 FloppyData
->Version
= 2;
529 FloppyData
->Revision
= 0;
530 FloppyData
->MaxDensity
= MaxDensity
[FloppyType
];
531 FloppyData
->MountDensity
= 0;
532 RtlCopyMemory(&FloppyData
->StepRateHeadUnloadTime
, Ptr
, 11);
533 FloppyData
->MaximumTrackValue
= (FloppyType
== 1) ? 39 : 79;
534 FloppyData
->DataTransferRate
= 0;
536 FldrCreateComponentKey(ControllerKey
,
538 FloppyDiskPeripheral
,
552 DetectBiosFloppyController(PCONFIGURATION_COMPONENT_DATA BusKey
)
554 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
555 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
556 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
560 FloppyCount
= GetFloppyCount();
561 TRACE("Floppy count: %u\n",
564 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
565 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
566 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
567 if (PartialResourceList
== NULL
)
569 ERR("Failed to allocate resource descriptor\n");
572 memset(PartialResourceList
, 0, Size
);
574 /* Initialize resource descriptor */
575 PartialResourceList
->Version
= 1;
576 PartialResourceList
->Revision
= 1;
577 PartialResourceList
->Count
= 3;
580 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
581 PartialDescriptor
->Type
= CmResourceTypePort
;
582 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
583 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
584 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x03F0;
585 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
586 PartialDescriptor
->u
.Port
.Length
= 8;
589 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
590 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
591 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
592 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
593 PartialDescriptor
->u
.Interrupt
.Level
= 6;
594 PartialDescriptor
->u
.Interrupt
.Vector
= 6;
595 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
597 /* Set DMA channel */
598 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
599 PartialDescriptor
->Type
= CmResourceTypeDma
;
600 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
601 PartialDescriptor
->Flags
= 0;
602 PartialDescriptor
->u
.Dma
.Channel
= 2;
603 PartialDescriptor
->u
.Dma
.Port
= 0;
605 /* Create floppy disk controller */
606 FldrCreateComponentKey(BusKey
,
616 TRACE("Created key: DiskController\\0\n");
618 if (FloppyCount
) DetectBiosFloppyPeripheral(ControllerKey
);
622 PCONFIGURATION_COMPONENT_DATA
625 PCONFIGURATION_COMPONENT_DATA SystemKey
;
626 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
627 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
633 DiskCount
= PcBiosDiskCount
;
635 /* Allocate resource descriptor */
636 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
637 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
638 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
639 if (PartialResourceList
== NULL
)
641 ERR("Failed to allocate resource descriptor\n");
645 /* Initialize resource descriptor */
646 memset(PartialResourceList
, 0, Size
);
647 PartialResourceList
->Version
= 1;
648 PartialResourceList
->Revision
= 1;
649 PartialResourceList
->Count
= 1;
650 PartialResourceList
->PartialDescriptors
[0].Type
= CmResourceTypeDeviceSpecific
;
651 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
= 0;
652 PartialResourceList
->PartialDescriptors
[0].Flags
= 0;
653 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
654 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
656 /* Get harddisk Int13 geometry data */
657 Int13Drives
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
658 for (i
= 0; i
< DiskCount
; i
++)
660 if (MachDiskGetDriveGeometry(0x80 + i
, &Geometry
))
662 Int13Drives
[i
].DriveSelect
= 0x80 + i
;
663 Int13Drives
[i
].MaxCylinders
= Geometry
.Cylinders
- 1;
664 Int13Drives
[i
].SectorsPerTrack
= (USHORT
)Geometry
.Sectors
;
665 Int13Drives
[i
].MaxHeads
= (USHORT
)Geometry
.Heads
- 1;
666 Int13Drives
[i
].NumberDrives
= DiskCount
;
668 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
670 Geometry
.Cylinders
- 1,
673 Geometry
.BytesPerSector
);
677 FldrCreateComponentKey(NULL
,
693 DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA BusKey
)
695 PCONFIGURATION_COMPONENT_DATA DiskKey
, ControllerKey
;
698 FldrCreateComponentKey(BusKey
,
708 TRACE("Created key: DiskController\\0\n");
710 /* Create and fill subkey for each harddisk */
711 for (i
= 0; i
< PcBiosDiskCount
; i
++)
713 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
716 UCHAR DriveNumber
= 0x80 + (UCHAR
)i
;
718 /* Get disk values */
719 PartialResourceList
= GetHarddiskConfigurationData(DriveNumber
, &Size
);
720 Identifier
= GetHarddiskIdentifier(DriveNumber
);
722 /* Create disk key */
723 FldrCreateComponentKey(ControllerKey
,
738 InitializeSerialPort(PUCHAR Port
,
741 WRITE_PORT_UCHAR(Port
+ 3, 0x80); /* set DLAB on */
742 WRITE_PORT_UCHAR(Port
, 0x60); /* speed LO byte */
743 WRITE_PORT_UCHAR(Port
+ 1, 0); /* speed HI byte */
744 WRITE_PORT_UCHAR(Port
+ 3, LineControl
);
745 WRITE_PORT_UCHAR(Port
+ 1, 0); /* set comm and DLAB to 0 */
746 WRITE_PORT_UCHAR(Port
+ 4, 0x09); /* DR int enable */
747 READ_PORT_UCHAR(Port
+ 5); /* clear error bits */
753 DetectSerialMouse(PUCHAR Port
)
760 /* Shutdown mouse or something like that */
761 LineControl
= READ_PORT_UCHAR(Port
+ 4);
762 WRITE_PORT_UCHAR(Port
+ 4, (LineControl
& ~0x02) | 0x01);
763 StallExecutionProcessor(100000);
767 * Maybe there is no serial port although BIOS reported one (this
768 * is the case on Apple hardware), or the serial port is misbehaving,
769 * therefore we must give up after some time.
772 while (READ_PORT_UCHAR(Port
+ 5) & 0x01)
775 return MOUSE_TYPE_NONE
;
776 READ_PORT_UCHAR(Port
);
780 * Send modem control with 'Data Terminal Ready', 'Request To Send' and
781 * 'Output Line 2' message. This enables mouse to identify.
783 WRITE_PORT_UCHAR(Port
+ 4, 0x0b);
785 /* Wait 10 milliseconds for the mouse getting ready */
786 StallExecutionProcessor(10000);
788 /* Read first four bytes, which contains Microsoft Mouse signs */
790 for (i
= 0; i
< 4; i
++)
792 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
794 StallExecutionProcessor(1000);
797 return MOUSE_TYPE_NONE
;
799 Buffer
[i
] = READ_PORT_UCHAR(Port
);
802 TRACE("Mouse data: %x %x %x %x\n",
803 Buffer
[0], Buffer
[1], Buffer
[2], Buffer
[3]);
805 /* Check that four bytes for signs */
806 for (i
= 0; i
< 4; ++i
)
808 if (Buffer
[i
] == 'B')
810 /* Sign for Microsoft Ballpoint */
811 // DbgPrint("Microsoft Ballpoint device detected\n");
812 // DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET\n");
813 return MOUSE_TYPE_NONE
;
815 else if (Buffer
[i
] == 'M')
817 /* Sign for Microsoft Mouse protocol followed by button specifier */
821 return MOUSE_TYPE_NONE
;
824 switch (Buffer
[i
+ 1])
827 TRACE("Microsoft Mouse with 3-buttons detected\n");
828 return MOUSE_TYPE_LOGITECH
;
831 TRACE("Microsoft Wheel Mouse detected\n");
832 return MOUSE_TYPE_WHEELZ
;
836 TRACE("Microsoft Mouse with 2-buttons detected\n");
837 return MOUSE_TYPE_MICROSOFT
;
842 return MOUSE_TYPE_NONE
;
847 GetSerialMousePnpId(PUCHAR Port
, char *Buffer
)
854 WRITE_PORT_UCHAR(Port
+ 4, 0x09);
856 /* Wait 10 milliseconds for the mouse getting ready */
857 StallExecutionProcessor(10000);
859 WRITE_PORT_UCHAR(Port
+ 4, 0x0b);
861 StallExecutionProcessor(10000);
866 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
868 StallExecutionProcessor(1000);
876 c
= READ_PORT_UCHAR(Port
);
877 if (c
== 0x08 || c
== 0x28)
887 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
889 StallExecutionProcessor(1000);
894 c
= READ_PORT_UCHAR(Port
);
908 DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
,
911 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
913 CHAR Identifier
[256];
914 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
921 TRACE("DetectSerialPointerPeripheral()\n");
925 InitializeSerialPort(Base
, 2);
926 MouseType
= DetectSerialMouse(Base
);
928 if (MouseType
!= MOUSE_TYPE_NONE
)
930 Length
= GetSerialMousePnpId(Base
, Buffer
);
931 TRACE( "PnP ID length: %u\n", Length
);
935 /* Convert PnP sting to ASCII */
936 if (Buffer
[0] == 0x08)
938 for (i
= 0; i
< Length
; i
++)
943 TRACE("PnP ID string: %s\n", Buffer
);
945 /* Copy PnpId string */
946 for (i
= 0; i
< 7; i
++)
948 Identifier
[i
] = Buffer
[3 + i
];
950 memcpy(&Identifier
[7],
954 /* Skip device serial number */
956 if (Buffer
[i
] == '\\')
958 for (j
= ++i
; i
< Length
; ++i
)
960 if (Buffer
[i
] == '\\')
968 if (Buffer
[i
] == '\\')
970 for (j
= ++i
; i
< Length
; ++i
)
972 if (Buffer
[i
] == '\\')
980 /* Skip compatible PnP Id */
981 if (Buffer
[i
] == '\\')
983 for (j
= ++i
; i
< Length
; ++i
)
985 if (Buffer
[i
] == '\\')
988 if (Buffer
[j
] == '*')
994 /* Get product description */
995 if (Buffer
[i
] == '\\')
997 for (j
= ++i
; i
< Length
; ++i
)
999 if (Buffer
[i
] == ';')
1006 for (k
= 0; k
< i
- j
; k
++)
1008 Identifier
[k
+ 10] = Buffer
[k
+ j
];
1010 Identifier
[10 + (i
- j
)] = 0;
1014 TRACE("Identifier string: %s\n", Identifier
);
1017 if (Length
== 0 || strlen(Identifier
) < 11)
1021 case MOUSE_TYPE_LOGITECH
:
1022 strcpy(Identifier
, "LOGITECH SERIAL MOUSE");
1025 case MOUSE_TYPE_WHEELZ
:
1026 strcpy(Identifier
, "MICROSOFT SERIAL MOUSE WITH WHEEL");
1029 case MOUSE_TYPE_MICROSOFT
:
1031 strcpy(Identifier
, "MICROSOFT SERIAL MOUSE");
1036 /* Set 'Configuration Data' value */
1037 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1038 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1039 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
1040 memset(PartialResourceList
, 0, Size
);
1041 PartialResourceList
->Version
= 1;
1042 PartialResourceList
->Revision
= 1;
1043 PartialResourceList
->Count
= 0;
1045 /* Create 'PointerPeripheral' key */
1046 FldrCreateComponentKey(ControllerKey
,
1053 PartialResourceList
,
1057 TRACE("Created key: PointerPeripheral\\0\n");
1064 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
1066 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1067 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1068 PCM_SERIAL_DEVICE_DATA SerialDeviceData
;
1069 ULONG Irq
[MAX_COM_PORTS
] = {4, 3, 4, 3};
1073 ULONG ControllerNumber
= 0;
1074 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1078 TRACE("DetectSerialPorts()\n");
1081 * The BIOS data area 0x400 holds the address of the first valid COM port.
1082 * Each COM port address is stored in a 2-byte field.
1083 * Infos at: http://www.bioscentral.com/misc/bda.htm
1085 BasePtr
= (PUSHORT
)0x400;
1087 for (i
= 0; i
< MAX_COM_PORTS
; i
++, BasePtr
++)
1089 Base
= (ULONG
) * BasePtr
;
1090 if (Base
== 0 || !CpDoesPortExist((PUCHAR
)Base
))
1093 TRACE("Found COM%u port at 0x%x\n", i
+ 1, Base
);
1095 /* Set 'Identifier' value */
1096 sprintf(Buffer
, "COM%ld", i
+ 1);
1098 /* Build full device descriptor */
1099 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
1100 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) +
1101 sizeof(CM_SERIAL_DEVICE_DATA
);
1102 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
1103 if (PartialResourceList
== NULL
)
1105 ERR("Failed to allocate resource descriptor\n");
1108 memset(PartialResourceList
, 0, Size
);
1110 /* Initialize resource descriptor */
1111 PartialResourceList
->Version
= 1;
1112 PartialResourceList
->Revision
= 1;
1113 PartialResourceList
->Count
= 3;
1116 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1117 PartialDescriptor
->Type
= CmResourceTypePort
;
1118 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1119 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1120 PartialDescriptor
->u
.Port
.Start
.LowPart
= Base
;
1121 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1122 PartialDescriptor
->u
.Port
.Length
= 7;
1125 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
1126 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
1127 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1128 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1129 PartialDescriptor
->u
.Interrupt
.Level
= Irq
[i
];
1130 PartialDescriptor
->u
.Interrupt
.Vector
= Irq
[i
];
1131 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1133 /* Set serial data (device specific) */
1134 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
1135 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
1136 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1137 PartialDescriptor
->Flags
= 0;
1138 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_SERIAL_DEVICE_DATA
);
1141 (PCM_SERIAL_DEVICE_DATA
)&PartialResourceList
->PartialDescriptors
[3];
1142 SerialDeviceData
->BaudClock
= 1843200; /* UART Clock frequency (Hertz) */
1144 /* Create controller key */
1145 FldrCreateComponentKey(BusKey
,
1148 Output
| Input
| ConsoleIn
| ConsoleOut
,
1152 PartialResourceList
,
1156 if (!Rs232PortInUse(UlongToPtr(Base
)))
1158 /* Detect serial mouse */
1159 DetectSerialPointerPeripheral(ControllerKey
, UlongToPtr(Base
));
1168 DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
1170 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1171 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1172 ULONG Irq
[MAX_LPT_PORTS
] = {7, 5, (ULONG
) - 1};
1174 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1177 ULONG ControllerNumber
= 0;
1181 TRACE("DetectParallelPorts() called\n");
1184 * The BIOS data area 0x408 holds the address of the first valid LPT port.
1185 * Each LPT port address is stored in a 2-byte field.
1186 * Infos at: http://www.bioscentral.com/misc/bda.htm
1188 BasePtr
= (PUSHORT
)0x408;
1190 for (i
= 0; i
< MAX_LPT_PORTS
; i
++, BasePtr
++)
1192 Base
= (ULONG
) * BasePtr
;
1196 TRACE("Parallel port %u: %x\n", ControllerNumber
, Base
);
1198 /* Set 'Identifier' value */
1199 sprintf(Buffer
, "PARALLEL%ld", i
+ 1);
1201 /* Build full device descriptor */
1202 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
);
1203 if (Irq
[i
] != (ULONG
) - 1)
1204 Size
+= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1206 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
1207 if (PartialResourceList
== NULL
)
1209 ERR("Failed to allocate resource descriptor\n");
1212 memset(PartialResourceList
, 0, Size
);
1214 /* Initialize resource descriptor */
1215 PartialResourceList
->Version
= 1;
1216 PartialResourceList
->Revision
= 1;
1217 PartialResourceList
->Count
= (Irq
[i
] != (ULONG
) - 1) ? 2 : 1;
1220 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1221 PartialDescriptor
->Type
= CmResourceTypePort
;
1222 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1223 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1224 PartialDescriptor
->u
.Port
.Start
.LowPart
= Base
;
1225 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1226 PartialDescriptor
->u
.Port
.Length
= 3;
1229 if (Irq
[i
] != (ULONG
) - 1)
1231 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
1232 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
1233 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1234 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1235 PartialDescriptor
->u
.Interrupt
.Level
= Irq
[i
];
1236 PartialDescriptor
->u
.Interrupt
.Vector
= Irq
[i
];
1237 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1240 /* Create controller key */
1241 FldrCreateComponentKey(BusKey
,
1248 PartialResourceList
,
1255 TRACE("DetectParallelPorts() done\n");
1261 DetectKeyboardDevice(VOID
)
1266 BOOLEAN Result
= TRUE
;
1268 /* Identify device */
1269 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
, 0xF2);
1271 /* Wait for reply */
1272 for (Loops
= 0; Loops
< 100; Loops
++)
1274 StallExecutionProcessor(10000);
1275 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1276 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1280 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
1282 /* PC/XT keyboard or no keyboard */
1286 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1287 if (Scancode
!= 0xFA)
1289 /* No ACK received */
1293 StallExecutionProcessor(10000);
1295 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1296 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
1298 /* Found AT keyboard */
1302 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1303 if (Scancode
!= 0xAB)
1305 /* No 0xAB received */
1309 StallExecutionProcessor(10000);
1311 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1312 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
1314 /* No byte in buffer */
1318 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1319 if (Scancode
!= 0x41)
1321 /* No 0x41 received */
1325 /* Found MF-II keyboard */
1331 DetectKeyboardPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
)
1333 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1334 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1335 PCM_KEYBOARD_DEVICE_DATA KeyboardData
;
1336 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
1339 /* HACK: don't call DetectKeyboardDevice() as it fails in Qemu 0.8.2
1340 if (DetectKeyboardDevice()) */
1342 /* Set 'Configuration Data' value */
1343 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
1344 sizeof(CM_KEYBOARD_DEVICE_DATA
);
1345 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
1346 if (PartialResourceList
== NULL
)
1348 ERR("Failed to allocate resource descriptor\n");
1352 /* Initialize resource descriptor */
1353 memset(PartialResourceList
, 0, Size
);
1354 PartialResourceList
->Version
= 1;
1355 PartialResourceList
->Revision
= 1;
1356 PartialResourceList
->Count
= 1;
1358 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1359 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
1360 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1361 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_KEYBOARD_DEVICE_DATA
);
1363 KeyboardData
= (PCM_KEYBOARD_DEVICE_DATA
)(PartialDescriptor
+ 1);
1364 KeyboardData
->Version
= 1;
1365 KeyboardData
->Revision
= 1;
1366 KeyboardData
->Type
= 4;
1367 KeyboardData
->Subtype
= 0;
1368 KeyboardData
->KeyboardFlags
= 0x20;
1370 /* Create controller key */
1371 FldrCreateComponentKey(ControllerKey
,
1378 PartialResourceList
,
1381 TRACE("Created key: KeyboardPeripheral\\0\n");
1388 DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey
)
1390 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1391 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1392 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1395 /* Set 'Configuration Data' value */
1396 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
1397 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1398 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
1399 if (PartialResourceList
== NULL
)
1401 ERR("Failed to allocate resource descriptor\n");
1405 /* Initialize resource descriptor */
1406 memset(PartialResourceList
, 0, Size
);
1407 PartialResourceList
->Version
= 1;
1408 PartialResourceList
->Revision
= 1;
1409 PartialResourceList
->Count
= 3;
1412 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1413 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
1414 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1415 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1416 PartialDescriptor
->u
.Interrupt
.Level
= 1;
1417 PartialDescriptor
->u
.Interrupt
.Vector
= 1;
1418 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1420 /* Set IO Port 0x60 */
1421 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
1422 PartialDescriptor
->Type
= CmResourceTypePort
;
1423 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1424 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1425 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x60;
1426 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1427 PartialDescriptor
->u
.Port
.Length
= 1;
1429 /* Set IO Port 0x64 */
1430 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
1431 PartialDescriptor
->Type
= CmResourceTypePort
;
1432 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1433 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1434 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x64;
1435 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1436 PartialDescriptor
->u
.Port
.Length
= 1;
1438 /* Create controller key */
1439 FldrCreateComponentKey(BusKey
,
1446 PartialResourceList
,
1449 TRACE("Created key: KeyboardController\\0\n");
1451 DetectKeyboardPeripheral(ControllerKey
);
1457 PS2ControllerWait(VOID
)
1462 for (Timeout
= 0; Timeout
< CONTROLLER_TIMEOUT
; Timeout
++)
1464 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1465 if ((Status
& CONTROLLER_STATUS_INPUT_BUFFER_FULL
) == 0)
1468 /* Sleep for one millisecond */
1469 StallExecutionProcessor(1000);
1476 DetectPS2AuxPort(VOID
)
1479 /* Current detection is too unreliable. Just do as if
1480 * the PS/2 aux port is always present
1487 /* Put the value 0x5A in the output buffer using the
1488 * "WriteAuxiliary Device Output Buffer" command (0xD3).
1489 * Poll the Status Register for a while to see if the value really turns up
1490 * in the Data Register. If the KEYBOARD_STATUS_MOUSE_OBF bit is also set
1491 * to 1 in the Status Register, we assume this controller has an
1492 * Auxiliary Port (a.k.a. Mouse Port).
1494 PS2ControllerWait();
1495 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_CONTROL
,
1496 CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER
);
1497 PS2ControllerWait();
1499 /* 0x5A is a random dummy value */
1500 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
,
1503 for (Loops
= 0; Loops
< 10; Loops
++)
1505 StallExecutionProcessor(10000);
1506 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1507 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1511 READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1513 return (Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
);
1520 DetectPS2AuxDevice(VOID
)
1525 BOOLEAN Result
= TRUE
;
1527 PS2ControllerWait();
1528 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_CONTROL
,
1529 CONTROLLER_COMMAND_WRITE_MOUSE
);
1530 PS2ControllerWait();
1532 /* Identify device */
1533 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
, 0xF2);
1535 /* Wait for reply */
1536 for (Loops
= 0; Loops
< 100; Loops
++)
1538 StallExecutionProcessor(10000);
1539 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1540 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1544 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1545 if ((Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
) == 0)
1548 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1549 if (Scancode
!= 0xFA)
1552 StallExecutionProcessor(10000);
1554 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1555 if ((Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
) == 0)
1558 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1559 if (Scancode
!= 0x00)
1568 DetectPS2Mouse(PCONFIGURATION_COMPONENT_DATA BusKey
)
1570 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1571 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1572 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
1575 if (DetectPS2AuxPort())
1577 TRACE("Detected PS2 port\n");
1579 PartialResourceList
= FrLdrHeapAlloc(sizeof(CM_PARTIAL_RESOURCE_LIST
), TAG_HW_RESOURCE_LIST
);
1580 memset(PartialResourceList
, 0, sizeof(CM_PARTIAL_RESOURCE_LIST
));
1582 /* Initialize resource descriptor */
1583 PartialResourceList
->Version
= 1;
1584 PartialResourceList
->Revision
= 1;
1585 PartialResourceList
->Count
= 1;
1588 PartialResourceList
->PartialDescriptors
[0].Type
= CmResourceTypeInterrupt
;
1589 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
= CmResourceShareUndetermined
;
1590 PartialResourceList
->PartialDescriptors
[0].Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1591 PartialResourceList
->PartialDescriptors
[0].u
.Interrupt
.Level
= 12;
1592 PartialResourceList
->PartialDescriptors
[0].u
.Interrupt
.Vector
= 12;
1593 PartialResourceList
->PartialDescriptors
[0].u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1595 /* Create controller key */
1596 FldrCreateComponentKey(BusKey
,
1603 PartialResourceList
,
1604 sizeof(CM_PARTIAL_RESOURCE_LIST
),
1606 TRACE("Created key: PointerController\\0\n");
1608 if (DetectPS2AuxDevice())
1610 TRACE("Detected PS2 mouse\n");
1612 /* Initialize resource descriptor */
1613 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1614 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1615 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
1616 memset(PartialResourceList
, 0, Size
);
1617 PartialResourceList
->Version
= 1;
1618 PartialResourceList
->Revision
= 1;
1619 PartialResourceList
->Count
= 0;
1621 /* Create peripheral key */
1622 FldrCreateComponentKey(ControllerKey
,
1628 "MICROSOFT PS2 MOUSE",
1629 PartialResourceList
,
1632 TRACE("Created key: PointerPeripheral\\0\n");
1639 DetectDisplayController(PCONFIGURATION_COMPONENT_DATA BusKey
)
1642 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1645 /* FIXME: Set 'ComponentInformation' value */
1647 VesaVersion
= BiosIsVesaSupported();
1648 if (VesaVersion
!= 0)
1650 TRACE("VESA version %c.%c\n",
1651 (VesaVersion
>> 8) + '0',
1652 (VesaVersion
& 0xFF) + '0');
1656 TRACE("VESA not supported\n");
1659 if (VesaVersion
>= 0x0200)
1661 strcpy(Buffer
, "VBE Display");
1665 strcpy(Buffer
, "VGA Display");
1668 FldrCreateComponentKey(BusKey
,
1678 TRACE("Created key: DisplayController\\0\n");
1680 /* FIXME: Add display peripheral (monitor) data */
1686 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
1688 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1689 PCONFIGURATION_COMPONENT_DATA BusKey
;
1692 /* Increment bus number */
1695 /* Set 'Configuration Data' value */
1696 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1697 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1698 PartialResourceList
= FrLdrHeapAlloc(Size
, TAG_HW_RESOURCE_LIST
);
1699 if (PartialResourceList
== NULL
)
1701 ERR("Failed to allocate resource descriptor\n");
1705 /* Initialize resource descriptor */
1706 memset(PartialResourceList
, 0, Size
);
1707 PartialResourceList
->Version
= 1;
1708 PartialResourceList
->Revision
= 1;
1709 PartialResourceList
->Count
= 0;
1711 /* Create new bus key */
1712 FldrCreateComponentKey(SystemKey
,
1714 MultiFunctionAdapter
,
1719 PartialResourceList
,
1723 /* Detect ISA/BIOS devices */
1724 DetectBiosDisks(BusKey
);
1726 DetectBiosFloppyController(BusKey
);
1728 DetectSerialPorts(BusKey
);
1730 DetectParallelPorts(BusKey
);
1732 DetectKeyboardController(BusKey
);
1734 DetectPS2Mouse(BusKey
);
1736 DetectDisplayController(BusKey
);
1738 /* FIXME: Detect more ISA devices */
1742 PcInitializeBootDevices(VOID
)
1744 return HwInitializeBiosDisks();
1747 PCONFIGURATION_COMPONENT_DATA
1750 PCONFIGURATION_COMPONENT_DATA SystemKey
;
1751 ULONG BusNumber
= 0;
1753 TRACE("DetectHardware()\n");
1755 /* Create the 'System' key */
1756 SystemKey
= DetectSystem();
1759 DetectPciBios(SystemKey
, &BusNumber
);
1760 DetectApmBios(SystemKey
, &BusNumber
);
1761 DetectPnpBios(SystemKey
, &BusNumber
);
1762 DetectIsaBios(SystemKey
, &BusNumber
);
1763 DetectAcpiBios(SystemKey
, &BusNumber
);
1765 TRACE("DetectHardware() Done\n");
1775 /* Select APM 1.0+ function */
1778 /* Function 05h: CPU idle */
1782 Int386(0x15, &Regs
, &Regs
);
1784 /* Check if successfull (CF set on error) */
1785 if (INT386_SUCCESS(Regs
))
1789 * No futher processing here.
1790 * Optionally implement HLT instruction handling.
1795 FrLdrCheckCpuCompatiblity(VOID
)
1797 INT CpuInformation
[4] = {-1};
1800 /* Check if the processor first supports ID 1 */
1801 __cpuid(CpuInformation
, 0);
1803 NumberOfIds
= CpuInformation
[0];
1805 if (NumberOfIds
== 0)
1807 FrLdrBugCheckWithMessage(MISSING_HARDWARE_REQUIREMENTS
,
1810 "ReactOS requires the CPUID instruction to return "
1811 "more than one supported ID.\n\n");
1814 /* NumberOfIds will be greater than 1 if the processor is new enough. */
1815 if (NumberOfIds
== 1)
1817 INT ProcessorFamily
;
1819 /* Get information. */
1820 __cpuid(CpuInformation
, 1);
1822 ProcessorFamily
= (CpuInformation
[0] >> 8) & 0xF;
1824 /* If it's Family 4 or lower, bugcheck. */
1825 if(ProcessorFamily
< 5)
1827 FrLdrBugCheckWithMessage(MISSING_HARDWARE_REQUIREMENTS
,
1830 "Processor is too old (family %u < 5)\n"
1831 "ReactOS requires a Pentium-level processor or newer.",