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 ****************************************************************/
105 __StallExecutionProcessor(ULONG Loops
)
107 register volatile unsigned int i
;
108 for (i
= 0; i
< Loops
; i
++);
112 VOID
StallExecutionProcessor(ULONG Microseconds
)
114 ULONGLONG LoopCount
= ((ULONGLONG
)delay_count
* (ULONGLONG
)Microseconds
) / 1000ULL;
115 __StallExecutionProcessor((ULONG
)LoopCount
);
124 WRITE_PORT_UCHAR((PUCHAR
)0x43, 0x00);
125 Count
= READ_PORT_UCHAR((PUCHAR
)0x40);
126 Count
|= READ_PORT_UCHAR((PUCHAR
)0x40) << 8;
133 WaitFor8254Wraparound(VOID
)
136 ULONG PrevCount
= ~0;
139 CurCount
= Read8254Timer();
143 PrevCount
= CurCount
;
144 CurCount
= Read8254Timer();
145 Delta
= CurCount
- PrevCount
;
148 * This limit for delta seems arbitrary, but it isn't, it's
149 * slightly above the level of error a buggy Mercury/Neptune
150 * chipset timer can cause.
158 HalpCalibrateStallExecution(VOID
)
164 /* Initialise timer interrupt with MILLISECOND ms interval */
165 WRITE_PORT_UCHAR((PUCHAR
)0x43, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */
166 WRITE_PORT_UCHAR((PUCHAR
)0x40, LATCH
& 0xff); /* LSB */
167 WRITE_PORT_UCHAR((PUCHAR
)0x40, LATCH
>> 8); /* MSB */
169 /* Stage 1: Coarse calibration */
171 WaitFor8254Wraparound();
176 delay_count
<<= 1; /* Next delay count to try */
178 WaitFor8254Wraparound();
180 __StallExecutionProcessor(delay_count
); /* Do the delay */
182 CurCount
= Read8254Timer();
183 } while (CurCount
> LATCH
/ 2);
185 delay_count
>>= 1; /* Get bottom value for delay */
187 /* Stage 2: Fine calibration */
189 calib_bit
= delay_count
; /* Which bit are we going to test */
191 for(i
=0;i
<PRECISION
;i
++) {
192 calib_bit
>>= 1; /* Next bit to calibrate */
193 if(!calib_bit
) break; /* If we have done all bits, stop */
195 delay_count
|= calib_bit
; /* Set the bit in delay_count */
197 WaitFor8254Wraparound();
199 __StallExecutionProcessor(delay_count
); /* Do the delay */
201 CurCount
= Read8254Timer();
202 if (CurCount
<= LATCH
/ 2) /* If a tick has passed, turn the */
203 delay_count
&= ~calib_bit
; /* calibrated bit back off */
206 /* We're finished: Do the finishing touches */
207 delay_count
/= (MILLISEC
/ 2); /* Calculate delay_count for 1ms */
211 DetectPnpBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
213 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
214 PCM_PNP_BIOS_DEVICE_NODE DeviceNode
;
215 PCM_PNP_BIOS_INSTALLATION_CHECK InstData
;
216 PCONFIGURATION_COMPONENT_DATA BusKey
;
221 ULONG FoundNodeCount
;
227 InstData
= (PCM_PNP_BIOS_INSTALLATION_CHECK
)PnpBiosSupported();
228 if (InstData
== NULL
|| strncmp((CHAR
*)InstData
->Signature
, "$PnP", 4))
230 TRACE("PnP-BIOS not supported\n");
234 TRACE("PnP-BIOS supported\n");
235 TRACE("Signature '%c%c%c%c'\n",
236 InstData
->Signature
[0], InstData
->Signature
[1],
237 InstData
->Signature
[2], InstData
->Signature
[3]);
239 x
= PnpBiosGetDeviceNodeCount(&NodeSize
, &NodeCount
);
242 TRACE("PnP-BIOS function 'Get Number of System Device Nodes' not supported\n");
246 NodeCount
&= 0xFF; // needed since some fscked up BIOSes return
247 // wrong info (e.g. Mac Virtual PC)
248 // e.g. look: http://my.execpc.com/~geezer/osd/pnp/pnp16.c
249 if (x
!= 0 || NodeSize
== 0 || NodeCount
== 0)
251 ERR("PnP-BIOS failed to enumerate device nodes\n");
254 TRACE("MaxNodeSize %u NodeCount %u\n", NodeSize
, NodeCount
);
255 TRACE("Estimated buffer size %u\n", NodeSize
* NodeCount
);
257 /* Set 'Configuration Data' value */
258 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
)
259 + sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
) + (NodeSize
* NodeCount
);
260 PartialResourceList
= MmHeapAlloc(Size
);
261 if (PartialResourceList
== NULL
)
263 ERR("Failed to allocate resource descriptor\n");
266 memset(PartialResourceList
, 0, Size
);
268 /* Initialize resource descriptor */
269 PartialResourceList
->Version
= 1;
270 PartialResourceList
->Revision
= 1;
271 PartialResourceList
->Count
= 1;
272 PartialResourceList
->PartialDescriptors
[0].Type
=
273 CmResourceTypeDeviceSpecific
;
274 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
=
275 CmResourceShareUndetermined
;
277 /* The buffer starts after PartialResourceList->PartialDescriptors[0] */
278 Ptr
= (char *)(PartialResourceList
+ 1);
280 /* Set instalation check data */
281 memcpy (Ptr
, InstData
, sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
));
282 Ptr
+= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
284 /* Copy device nodes */
286 PnpBufferSize
= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
287 for (i
= 0; i
< 0xFF; i
++)
289 NodeNumber
= (UCHAR
)i
;
291 x
= PnpBiosGetDeviceNode(&NodeNumber
, (PVOID
)DISKREADBUFFER
);
294 DeviceNode
= (PCM_PNP_BIOS_DEVICE_NODE
)DISKREADBUFFER
;
296 TRACE("Node: %u Size %u (0x%x)\n",
301 if (PnpBufferSize
+ DeviceNode
->Size
> Size
)
303 ERR("Buffer too small!\n");
311 Ptr
+= DeviceNode
->Size
;
312 PnpBufferSize
+= DeviceNode
->Size
;
315 if (FoundNodeCount
>= NodeCount
)
320 /* Set real data size */
321 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
323 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) + PnpBufferSize
;
325 TRACE("Real buffer size: %u\n", PnpBufferSize
);
326 TRACE("Resource size: %u\n", Size
);
328 /* Create component key */
329 FldrCreateComponentKey(SystemKey
,
331 MultiFunctionAdapter
,
342 MmHeapFree(PartialResourceList
);
347 static PCM_PARTIAL_RESOURCE_LIST
348 GetHarddiskConfigurationData(UCHAR DriveNumber
, ULONG
* pSize
)
350 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
351 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
352 EXTENDED_GEOMETRY ExtGeometry
;
357 // Initialize returned size
361 /* Set 'Configuration Data' value */
362 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
363 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
364 PartialResourceList
= MmHeapAlloc(Size
);
365 if (PartialResourceList
== NULL
)
367 ERR("Failed to allocate a full resource descriptor\n");
371 memset(PartialResourceList
, 0, Size
);
372 PartialResourceList
->Version
= 1;
373 PartialResourceList
->Revision
= 1;
374 PartialResourceList
->Count
= 1;
375 PartialResourceList
->PartialDescriptors
[0].Type
=
376 CmResourceTypeDeviceSpecific
;
377 // PartialResourceList->PartialDescriptors[0].ShareDisposition =
378 // PartialResourceList->PartialDescriptors[0].Flags =
379 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
380 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
382 /* Get pointer to geometry data */
383 DiskGeometry
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
385 /* Get the disk geometry */
386 ExtGeometry
.Size
= sizeof(EXTENDED_GEOMETRY
);
387 if (DiskGetExtendedDriveParameters(DriveNumber
, &ExtGeometry
, ExtGeometry
.Size
))
389 DiskGeometry
->BytesPerSector
= ExtGeometry
.BytesPerSector
;
390 DiskGeometry
->NumberOfCylinders
= ExtGeometry
.Cylinders
;
391 DiskGeometry
->SectorsPerTrack
= ExtGeometry
.SectorsPerTrack
;
392 DiskGeometry
->NumberOfHeads
= ExtGeometry
.Heads
;
394 else if(MachDiskGetDriveGeometry(DriveNumber
, &Geometry
))
396 DiskGeometry
->BytesPerSector
= Geometry
.BytesPerSector
;
397 DiskGeometry
->NumberOfCylinders
= Geometry
.Cylinders
;
398 DiskGeometry
->SectorsPerTrack
= Geometry
.Sectors
;
399 DiskGeometry
->NumberOfHeads
= Geometry
.Heads
;
403 TRACE("Reading disk geometry failed\n");
404 MmHeapFree(PartialResourceList
);
407 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
409 DiskGeometry
->NumberOfCylinders
,
410 DiskGeometry
->NumberOfHeads
,
411 DiskGeometry
->SectorsPerTrack
,
412 DiskGeometry
->BytesPerSector
);
415 // Return configuration data
418 return PartialResourceList
;
426 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0x10);
427 Data
= READ_PORT_UCHAR((PUCHAR
)0x71);
429 return ((Data
& 0xF0) ? 1 : 0) + ((Data
& 0x0F) ? 1 : 0);
434 GetFloppyType(UCHAR DriveNumber
)
438 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0x10);
439 Data
= READ_PORT_UCHAR((PUCHAR
)0x71);
441 if (DriveNumber
== 0)
443 else if (DriveNumber
== 1)
453 PUSHORT SegPtr
= (PUSHORT
)0x7A;
454 PUSHORT OfsPtr
= (PUSHORT
)0x78;
456 return (PVOID
)((ULONG_PTR
)(((ULONG
)(*SegPtr
)) << 4) + (ULONG
)(*OfsPtr
));
461 DetectBiosFloppyPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
)
463 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
464 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
465 PCM_FLOPPY_DEVICE_DATA FloppyData
;
467 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
471 ULONG MaxDensity
[6] = {0, 360, 1200, 720, 1440, 2880};
474 for (FloppyNumber
= 0; FloppyNumber
< 2; FloppyNumber
++)
476 FloppyType
= GetFloppyType(FloppyNumber
);
478 if ((FloppyType
> 5) || (FloppyType
== 0))
481 if (!DiskResetController(FloppyNumber
))
484 Ptr
= GetInt1eTable();
486 /* Set 'Identifier' value */
487 sprintf(Identifier
, "FLOPPY%d", FloppyNumber
+ 1);
489 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
490 sizeof(CM_FLOPPY_DEVICE_DATA
);
491 PartialResourceList
= MmHeapAlloc(Size
);
492 if (PartialResourceList
== NULL
)
494 ERR("Failed to allocate resource descriptor\n");
498 memset(PartialResourceList
, 0, Size
);
499 PartialResourceList
->Version
= 1;
500 PartialResourceList
->Revision
= 1;
501 PartialResourceList
->Count
= 1;
503 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
504 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
505 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
506 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_FLOPPY_DEVICE_DATA
);
508 FloppyData
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
509 FloppyData
->Version
= 2;
510 FloppyData
->Revision
= 0;
511 FloppyData
->MaxDensity
= MaxDensity
[FloppyType
];
512 FloppyData
->MountDensity
= 0;
513 RtlCopyMemory(&FloppyData
->StepRateHeadUnloadTime
,
516 FloppyData
->MaximumTrackValue
= (FloppyType
== 1) ? 39 : 79;
517 FloppyData
->DataTransferRate
= 0;
519 FldrCreateComponentKey(ControllerKey
,
521 FloppyDiskPeripheral
,
530 MmHeapFree(PartialResourceList
);
536 DetectBiosFloppyController(PCONFIGURATION_COMPONENT_DATA BusKey
)
538 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
539 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
540 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
544 FloppyCount
= GetFloppyCount();
545 TRACE("Floppy count: %u\n",
548 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
549 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
550 PartialResourceList
= MmHeapAlloc(Size
);
551 if (PartialResourceList
== NULL
)
553 ERR("Failed to allocate resource descriptor\n");
556 memset(PartialResourceList
, 0, Size
);
558 /* Initialize resource descriptor */
559 PartialResourceList
->Version
= 1;
560 PartialResourceList
->Revision
= 1;
561 PartialResourceList
->Count
= 3;
564 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
565 PartialDescriptor
->Type
= CmResourceTypePort
;
566 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
567 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
568 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x03F0;
569 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
570 PartialDescriptor
->u
.Port
.Length
= 8;
573 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
574 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
575 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
576 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
577 PartialDescriptor
->u
.Interrupt
.Level
= 6;
578 PartialDescriptor
->u
.Interrupt
.Vector
= 6;
579 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
581 /* Set DMA channel */
582 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
583 PartialDescriptor
->Type
= CmResourceTypeDma
;
584 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
585 PartialDescriptor
->Flags
= 0;
586 PartialDescriptor
->u
.Dma
.Channel
= 2;
587 PartialDescriptor
->u
.Dma
.Port
= 0;
589 /* Create floppy disk controller */
590 FldrCreateComponentKey(BusKey
,
600 TRACE("Created key: DiskController\\0\n");
602 MmHeapFree(PartialResourceList
);
604 if (FloppyCount
) DetectBiosFloppyPeripheral(ControllerKey
);
607 static PCONFIGURATION_COMPONENT_DATA
610 PCONFIGURATION_COMPONENT_DATA SystemKey
;
611 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
612 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
618 DiskCount
= PcBiosDiskCount
;
620 /* Allocate resource descriptor */
621 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
622 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
623 PartialResourceList
= MmHeapAlloc(Size
);
624 if (PartialResourceList
== NULL
)
626 ERR("Failed to allocate resource descriptor\n");
630 /* Initialize resource descriptor */
631 memset(PartialResourceList
, 0, Size
);
632 PartialResourceList
->Version
= 1;
633 PartialResourceList
->Revision
= 1;
634 PartialResourceList
->Count
= 1;
635 PartialResourceList
->PartialDescriptors
[0].Type
= CmResourceTypeDeviceSpecific
;
636 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
= 0;
637 PartialResourceList
->PartialDescriptors
[0].Flags
= 0;
638 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
639 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
641 /* Get harddisk Int13 geometry data */
642 Int13Drives
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
643 for (i
= 0; i
< DiskCount
; i
++)
645 if (MachDiskGetDriveGeometry(0x80 + i
, &Geometry
))
647 Int13Drives
[i
].DriveSelect
= 0x80 + i
;
648 Int13Drives
[i
].MaxCylinders
= Geometry
.Cylinders
- 1;
649 Int13Drives
[i
].SectorsPerTrack
= (USHORT
)Geometry
.Sectors
;
650 Int13Drives
[i
].MaxHeads
= (USHORT
)Geometry
.Heads
- 1;
651 Int13Drives
[i
].NumberDrives
= DiskCount
;
653 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
655 Geometry
.Cylinders
- 1,
658 Geometry
.BytesPerSector
);
662 FldrCreateComponentKey(NULL
,
673 MmHeapFree(PartialResourceList
);
679 DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA BusKey
)
681 PCONFIGURATION_COMPONENT_DATA DiskKey
, ControllerKey
;
684 FldrCreateComponentKey(BusKey
,
694 TRACE("Created key: DiskController\\0\n");
696 /* Create and fill subkey for each harddisk */
697 for (i
= 0; i
< PcBiosDiskCount
; i
++)
699 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
702 UCHAR DriveNumber
= 0x80 + (UCHAR
)i
;
704 /* Get disk values */
705 PartialResourceList
= GetHarddiskConfigurationData(DriveNumber
, &Size
);
706 Identifier
= GetHarddiskIdentifier(DriveNumber
);
708 /* Create disk key */
709 FldrCreateComponentKey(ControllerKey
,
724 InitializeSerialPort(PUCHAR Port
,
727 WRITE_PORT_UCHAR(Port
+ 3, 0x80); /* set DLAB on */
728 WRITE_PORT_UCHAR(Port
, 0x60); /* speed LO byte */
729 WRITE_PORT_UCHAR(Port
+ 1, 0); /* speed HI byte */
730 WRITE_PORT_UCHAR(Port
+ 3, LineControl
);
731 WRITE_PORT_UCHAR(Port
+ 1, 0); /* set comm and DLAB to 0 */
732 WRITE_PORT_UCHAR(Port
+ 4, 0x09); /* DR int enable */
733 READ_PORT_UCHAR(Port
+ 5); /* clear error bits */
738 DetectSerialMouse(PUCHAR Port
)
745 /* Shutdown mouse or something like that */
746 LineControl
= READ_PORT_UCHAR(Port
+ 4);
747 WRITE_PORT_UCHAR(Port
+ 4, (LineControl
& ~0x02) | 0x01);
748 StallExecutionProcessor(100000);
752 * Maybe there is no serial port although BIOS reported one (this
753 * is the case on Apple hardware), or the serial port is misbehaving,
754 * therefore we must give up after some time.
757 while (READ_PORT_UCHAR(Port
+ 5) & 0x01)
760 return MOUSE_TYPE_NONE
;
761 READ_PORT_UCHAR(Port
);
765 * Send modem control with 'Data Terminal Ready', 'Request To Send' and
766 * 'Output Line 2' message. This enables mouse to identify.
768 WRITE_PORT_UCHAR(Port
+ 4, 0x0b);
770 /* Wait 10 milliseconds for the mouse getting ready */
771 StallExecutionProcessor(10000);
773 /* Read first four bytes, which contains Microsoft Mouse signs */
775 for (i
= 0; i
< 4; i
++)
777 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
779 StallExecutionProcessor(1000);
782 return MOUSE_TYPE_NONE
;
784 Buffer
[i
] = READ_PORT_UCHAR(Port
);
787 TRACE("Mouse data: %x %x %x %x\n",
788 Buffer
[0],Buffer
[1],Buffer
[2],Buffer
[3]);
790 /* Check that four bytes for signs */
791 for (i
= 0; i
< 4; ++i
)
793 if (Buffer
[i
] == 'B')
795 /* Sign for Microsoft Ballpoint */
796 // DbgPrint("Microsoft Ballpoint device detected\n");
797 // DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET\n");
798 return MOUSE_TYPE_NONE
;
800 else if (Buffer
[i
] == 'M')
802 /* Sign for Microsoft Mouse protocol followed by button specifier */
806 return MOUSE_TYPE_NONE
;
809 switch (Buffer
[i
+ 1])
812 TRACE("Microsoft Mouse with 3-buttons detected\n");
813 return MOUSE_TYPE_LOGITECH
;
816 TRACE("Microsoft Wheel Mouse detected\n");
817 return MOUSE_TYPE_WHEELZ
;
821 TRACE("Microsoft Mouse with 2-buttons detected\n");
822 return MOUSE_TYPE_MICROSOFT
;
827 return MOUSE_TYPE_NONE
;
832 GetSerialMousePnpId(PUCHAR Port
, char *Buffer
)
839 WRITE_PORT_UCHAR(Port
+ 4, 0x09);
841 /* Wait 10 milliseconds for the mouse getting ready */
842 StallExecutionProcessor(10000);
844 WRITE_PORT_UCHAR(Port
+ 4, 0x0b);
846 StallExecutionProcessor(10000);
851 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
853 StallExecutionProcessor(1000);
861 c
= READ_PORT_UCHAR(Port
);
862 if (c
== 0x08 || c
== 0x28)
872 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
874 StallExecutionProcessor(1000);
879 c
= READ_PORT_UCHAR(Port
);
892 DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
,
895 CM_PARTIAL_RESOURCE_LIST PartialResourceList
;
897 CHAR Identifier
[256];
898 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
905 TRACE("DetectSerialPointerPeripheral()\n");
909 InitializeSerialPort(Base
, 2);
910 MouseType
= DetectSerialMouse(Base
);
912 if (MouseType
!= MOUSE_TYPE_NONE
)
914 Length
= GetSerialMousePnpId(Base
, Buffer
);
915 TRACE( "PnP ID length: %u\n", Length
);
919 /* Convert PnP sting to ASCII */
920 if (Buffer
[0] == 0x08)
922 for (i
= 0; i
< Length
; i
++)
927 TRACE("PnP ID string: %s\n", Buffer
);
929 /* Copy PnpId string */
930 for (i
= 0; i
< 7; i
++)
932 Identifier
[i
] = Buffer
[3+i
];
934 memcpy(&Identifier
[7],
938 /* Skip device serial number */
940 if (Buffer
[i
] == '\\')
942 for (j
= ++i
; i
< Length
; ++i
)
944 if (Buffer
[i
] == '\\')
952 if (Buffer
[i
] == '\\')
954 for (j
= ++i
; i
< Length
; ++i
)
956 if (Buffer
[i
] == '\\')
964 /* Skip compatible PnP Id */
965 if (Buffer
[i
] == '\\')
967 for (j
= ++i
; i
< Length
; ++i
)
969 if (Buffer
[i
] == '\\')
972 if (Buffer
[j
] == '*')
978 /* Get product description */
979 if (Buffer
[i
] == '\\')
981 for (j
= ++i
; i
< Length
; ++i
)
983 if (Buffer
[i
] == ';')
990 for (k
= 0; k
< i
- j
; k
++)
992 Identifier
[k
+ 10] = Buffer
[k
+ j
];
994 Identifier
[10 + (i
-j
)] = 0;
998 TRACE("Identifier string: %s\n", Identifier
);
1001 if (Length
== 0 || strlen(Identifier
) < 11)
1005 case MOUSE_TYPE_LOGITECH
:
1006 strcpy(Identifier
, "LOGITECH SERIAL MOUSE");
1009 case MOUSE_TYPE_WHEELZ
:
1010 strcpy(Identifier
, "MICROSOFT SERIAL MOUSE WITH WHEEL");
1013 case MOUSE_TYPE_MICROSOFT
:
1015 strcpy(Identifier
, "MICROSOFT SERIAL MOUSE");
1020 /* Set 'Configuration Data' value */
1021 memset(&PartialResourceList
, 0, sizeof(CM_PARTIAL_RESOURCE_LIST
));
1022 PartialResourceList
.Version
= 1;
1023 PartialResourceList
.Revision
= 1;
1024 PartialResourceList
.Count
= 0;
1026 /* Create 'PointerPeripheral' key */
1027 FldrCreateComponentKey(ControllerKey
,
1034 &PartialResourceList
,
1035 sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1036 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
),
1039 TRACE("Created key: PointerPeripheral\\0\n");
1045 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
1047 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1048 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1049 PCM_SERIAL_DEVICE_DATA SerialDeviceData
;
1050 ULONG Irq
[MAX_COM_PORTS
] = {4, 3, 4, 3};
1054 ULONG ControllerNumber
= 0;
1055 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1059 TRACE("DetectSerialPorts()\n");
1062 * The BIOS data area 0x400 holds the address of the first valid COM port.
1063 * Each COM port address is stored in a 2-byte field.
1064 * Infos at: http://www.bioscentral.com/misc/bda.htm
1066 BasePtr
= (PUSHORT
)0x400;
1068 for (i
= 0; i
< MAX_COM_PORTS
; i
++, BasePtr
++)
1070 Base
= (ULONG
)*BasePtr
;
1071 if (Base
== 0 || !CpDoesPortExist((PUCHAR
)Base
))
1074 TRACE("Found COM%u port at 0x%x\n", i
+ 1, Base
);
1076 /* Set 'Identifier' value */
1077 sprintf(Buffer
, "COM%ld", i
+ 1);
1079 /* Build full device descriptor */
1080 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
1081 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) +
1082 sizeof(CM_SERIAL_DEVICE_DATA
);
1083 PartialResourceList
= MmHeapAlloc(Size
);
1084 if (PartialResourceList
== NULL
)
1086 ERR("Failed to allocate resource descriptor\n");
1089 memset(PartialResourceList
, 0, Size
);
1091 /* Initialize resource descriptor */
1092 PartialResourceList
->Version
= 1;
1093 PartialResourceList
->Revision
= 1;
1094 PartialResourceList
->Count
= 3;
1097 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1098 PartialDescriptor
->Type
= CmResourceTypePort
;
1099 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1100 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1101 PartialDescriptor
->u
.Port
.Start
.LowPart
= Base
;
1102 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1103 PartialDescriptor
->u
.Port
.Length
= 7;
1106 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
1107 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
1108 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1109 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1110 PartialDescriptor
->u
.Interrupt
.Level
= Irq
[i
];
1111 PartialDescriptor
->u
.Interrupt
.Vector
= Irq
[i
];
1112 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1114 /* Set serial data (device specific) */
1115 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
1116 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
1117 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1118 PartialDescriptor
->Flags
= 0;
1119 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_SERIAL_DEVICE_DATA
);
1122 (PCM_SERIAL_DEVICE_DATA
)&PartialResourceList
->PartialDescriptors
[3];
1123 SerialDeviceData
->BaudClock
= 1843200; /* UART Clock frequency (Hertz) */
1125 /* Create controller key */
1126 FldrCreateComponentKey(BusKey
,
1129 Output
| Input
| ConsoleIn
| ConsoleOut
,
1133 PartialResourceList
,
1137 MmHeapFree(PartialResourceList
);
1139 if (!Rs232PortInUse(UlongToPtr(Base
)))
1141 /* Detect serial mouse */
1142 DetectSerialPointerPeripheral(ControllerKey
, UlongToPtr(Base
));
1151 DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
1153 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1154 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1155 ULONG Irq
[MAX_LPT_PORTS
] = {7, 5, (ULONG
)-1};
1157 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1160 ULONG ControllerNumber
= 0;
1164 TRACE("DetectParallelPorts() called\n");
1167 * The BIOS data area 0x408 holds the address of the first valid LPT port.
1168 * Each LPT port address is stored in a 2-byte field.
1169 * Infos at: http://www.bioscentral.com/misc/bda.htm
1171 BasePtr
= (PUSHORT
)0x408;
1173 for (i
= 0; i
< MAX_LPT_PORTS
; i
++, BasePtr
++)
1175 Base
= (ULONG
)*BasePtr
;
1179 TRACE("Parallel port %u: %x\n", ControllerNumber
, Base
);
1181 /* Set 'Identifier' value */
1182 sprintf(Buffer
, "PARALLEL%ld", i
+ 1);
1184 /* Build full device descriptor */
1185 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
);
1186 if (Irq
[i
] != (ULONG
)-1)
1187 Size
+= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1189 PartialResourceList
= MmHeapAlloc(Size
);
1190 if (PartialResourceList
== NULL
)
1192 ERR("Failed to allocate resource descriptor\n");
1195 memset(PartialResourceList
, 0, Size
);
1197 /* Initialize resource descriptor */
1198 PartialResourceList
->Version
= 1;
1199 PartialResourceList
->Revision
= 1;
1200 PartialResourceList
->Count
= (Irq
[i
] != (ULONG
)-1) ? 2 : 1;
1203 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1204 PartialDescriptor
->Type
= CmResourceTypePort
;
1205 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1206 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1207 PartialDescriptor
->u
.Port
.Start
.LowPart
= Base
;
1208 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1209 PartialDescriptor
->u
.Port
.Length
= 3;
1212 if (Irq
[i
] != (ULONG
)-1)
1214 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
1215 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
1216 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1217 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1218 PartialDescriptor
->u
.Interrupt
.Level
= Irq
[i
];
1219 PartialDescriptor
->u
.Interrupt
.Vector
= Irq
[i
];
1220 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1223 /* Create controller key */
1224 FldrCreateComponentKey(BusKey
,
1231 PartialResourceList
,
1235 MmHeapFree(PartialResourceList
);
1240 TRACE("DetectParallelPorts() done\n");
1245 DetectKeyboardDevice(VOID
)
1250 BOOLEAN Result
= TRUE
;
1252 /* Identify device */
1253 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
,
1256 /* Wait for reply */
1257 for (Loops
= 0; Loops
< 100; Loops
++)
1259 StallExecutionProcessor(10000);
1260 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1261 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1265 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
1267 /* PC/XT keyboard or no keyboard */
1271 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1272 if (Scancode
!= 0xFA)
1274 /* No ACK received */
1278 StallExecutionProcessor(10000);
1280 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1281 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
1283 /* Found AT keyboard */
1287 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1288 if (Scancode
!= 0xAB)
1290 /* No 0xAB received */
1294 StallExecutionProcessor(10000);
1296 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1297 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
1299 /* No byte in buffer */
1303 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1304 if (Scancode
!= 0x41)
1306 /* No 0x41 received */
1310 /* Found MF-II keyboard */
1316 DetectKeyboardPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
)
1318 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1319 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1320 PCM_KEYBOARD_DEVICE_DATA KeyboardData
;
1321 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
1324 /* HACK: don't call DetectKeyboardDevice() as it fails in Qemu 0.8.2 */
1325 if (TRUE
|| DetectKeyboardDevice())
1327 /* Set 'Configuration Data' value */
1328 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
1329 sizeof(CM_KEYBOARD_DEVICE_DATA
);
1330 PartialResourceList
= MmHeapAlloc(Size
);
1331 if (PartialResourceList
== NULL
)
1333 ERR("Failed to allocate resource descriptor\n");
1337 /* Initialize resource descriptor */
1338 memset(PartialResourceList
, 0, Size
);
1339 PartialResourceList
->Version
= 1;
1340 PartialResourceList
->Revision
= 1;
1341 PartialResourceList
->Count
= 1;
1343 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1344 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
1345 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1346 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_KEYBOARD_DEVICE_DATA
);
1348 KeyboardData
= (PCM_KEYBOARD_DEVICE_DATA
)(PartialDescriptor
+ 1);
1349 KeyboardData
->Version
= 1;
1350 KeyboardData
->Revision
= 1;
1351 KeyboardData
->Type
= 4;
1352 KeyboardData
->Subtype
= 0;
1353 KeyboardData
->KeyboardFlags
= 0x20;
1355 /* Create controller key */
1356 FldrCreateComponentKey(ControllerKey
,
1363 PartialResourceList
,
1366 TRACE("Created key: KeyboardPeripheral\\0\n");
1368 MmHeapFree(PartialResourceList
);
1374 DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey
)
1376 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1377 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1378 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1381 /* Set 'Configuration Data' value */
1382 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
1383 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1384 PartialResourceList
= MmHeapAlloc(Size
);
1385 if (PartialResourceList
== NULL
)
1387 ERR("Failed to allocate resource descriptor\n");
1391 /* Initialize resource descriptor */
1392 memset(PartialResourceList
, 0, Size
);
1393 PartialResourceList
->Version
= 1;
1394 PartialResourceList
->Revision
= 1;
1395 PartialResourceList
->Count
= 3;
1398 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1399 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
1400 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1401 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1402 PartialDescriptor
->u
.Interrupt
.Level
= 1;
1403 PartialDescriptor
->u
.Interrupt
.Vector
= 1;
1404 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1406 /* Set IO Port 0x60 */
1407 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
1408 PartialDescriptor
->Type
= CmResourceTypePort
;
1409 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1410 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1411 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x60;
1412 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1413 PartialDescriptor
->u
.Port
.Length
= 1;
1415 /* Set IO Port 0x64 */
1416 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
1417 PartialDescriptor
->Type
= CmResourceTypePort
;
1418 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1419 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1420 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x64;
1421 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1422 PartialDescriptor
->u
.Port
.Length
= 1;
1424 /* Create controller key */
1425 FldrCreateComponentKey(BusKey
,
1432 PartialResourceList
,
1435 TRACE("Created key: KeyboardController\\0\n");
1437 MmHeapFree(PartialResourceList
);
1439 DetectKeyboardPeripheral(ControllerKey
);
1444 PS2ControllerWait(VOID
)
1449 for (Timeout
= 0; Timeout
< CONTROLLER_TIMEOUT
; Timeout
++)
1451 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1452 if ((Status
& CONTROLLER_STATUS_INPUT_BUFFER_FULL
) == 0)
1455 /* Sleep for one millisecond */
1456 StallExecutionProcessor(1000);
1462 DetectPS2AuxPort(VOID
)
1465 /* Current detection is too unreliable. Just do as if
1466 * the PS/2 aux port is always present
1473 /* Put the value 0x5A in the output buffer using the
1474 * "WriteAuxiliary Device Output Buffer" command (0xD3).
1475 * Poll the Status Register for a while to see if the value really turns up
1476 * in the Data Register. If the KEYBOARD_STATUS_MOUSE_OBF bit is also set
1477 * to 1 in the Status Register, we assume this controller has an
1478 * Auxiliary Port (a.k.a. Mouse Port).
1480 PS2ControllerWait();
1481 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_CONTROL
,
1482 CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER
);
1483 PS2ControllerWait();
1485 /* 0x5A is a random dummy value */
1486 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
,
1489 for (Loops
= 0; Loops
< 10; Loops
++)
1491 StallExecutionProcessor(10000);
1492 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1493 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1497 READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1499 return (Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
);
1505 DetectPS2AuxDevice(VOID
)
1510 BOOLEAN Result
= TRUE
;
1512 PS2ControllerWait();
1513 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_CONTROL
,
1514 CONTROLLER_COMMAND_WRITE_MOUSE
);
1515 PS2ControllerWait();
1517 /* Identify device */
1518 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
,
1521 /* Wait for reply */
1522 for (Loops
= 0; Loops
< 100; Loops
++)
1524 StallExecutionProcessor(10000);
1525 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1526 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1530 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1531 if ((Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
) == 0)
1534 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1535 if (Scancode
!= 0xFA)
1538 StallExecutionProcessor(10000);
1540 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1541 if ((Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
) == 0)
1544 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1545 if (Scancode
!= 0x00)
1553 DetectPS2Mouse(PCONFIGURATION_COMPONENT_DATA BusKey
)
1555 CM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1556 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1557 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
1559 if (DetectPS2AuxPort())
1561 TRACE("Detected PS2 port\n");
1563 memset(&PartialResourceList
, 0, sizeof(CM_PARTIAL_RESOURCE_LIST
));
1565 /* Initialize resource descriptor */
1566 PartialResourceList
.Version
= 1;
1567 PartialResourceList
.Revision
= 1;
1568 PartialResourceList
.Count
= 1;
1571 PartialResourceList
.PartialDescriptors
[0].Type
= CmResourceTypeInterrupt
;
1572 PartialResourceList
.PartialDescriptors
[0].ShareDisposition
= CmResourceShareUndetermined
;
1573 PartialResourceList
.PartialDescriptors
[0].Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1574 PartialResourceList
.PartialDescriptors
[0].u
.Interrupt
.Level
= 12;
1575 PartialResourceList
.PartialDescriptors
[0].u
.Interrupt
.Vector
= 12;
1576 PartialResourceList
.PartialDescriptors
[0].u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1578 /* Create controller key */
1579 FldrCreateComponentKey(BusKey
,
1586 &PartialResourceList
,
1587 sizeof(CM_PARTIAL_RESOURCE_LIST
),
1589 TRACE("Created key: PointerController\\0\n");
1591 if (DetectPS2AuxDevice())
1593 TRACE("Detected PS2 mouse\n");
1595 /* Initialize resource descriptor */
1596 memset(&PartialResourceList
, 0, sizeof(CM_PARTIAL_RESOURCE_LIST
));
1597 PartialResourceList
.Version
= 1;
1598 PartialResourceList
.Revision
= 1;
1599 PartialResourceList
.Count
= 0;
1601 /* Create peripheral key */
1602 FldrCreateComponentKey(ControllerKey
,
1608 "MICROSOFT PS2 MOUSE",
1609 &PartialResourceList
,
1610 sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1611 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
),
1613 TRACE("Created key: PointerPeripheral\\0\n");
1620 DetectDisplayController(PCONFIGURATION_COMPONENT_DATA BusKey
)
1623 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1626 /* FIXME: Set 'ComponentInformation' value */
1628 VesaVersion
= BiosIsVesaSupported();
1629 if (VesaVersion
!= 0)
1631 TRACE("VESA version %c.%c\n",
1632 (VesaVersion
>> 8) + '0',
1633 (VesaVersion
& 0xFF) + '0');
1637 TRACE("VESA not supported\n");
1640 if (VesaVersion
>= 0x0200)
1642 strcpy(Buffer
, "VBE Display");
1646 strcpy(Buffer
, "VGA Display");
1649 FldrCreateComponentKey(BusKey
,
1659 TRACE("Created key: DisplayController\\0\n");
1661 /* FIXME: Add display peripheral (monitor) data */
1666 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
1668 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1669 PCONFIGURATION_COMPONENT_DATA BusKey
;
1672 /* Increment bus number */
1675 /* Set 'Configuration Data' value */
1676 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1677 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1678 PartialResourceList
= MmHeapAlloc(Size
);
1679 if (PartialResourceList
== NULL
)
1681 ERR("Failed to allocate resource descriptor\n");
1685 /* Initialize resource descriptor */
1686 memset(PartialResourceList
, 0, Size
);
1687 PartialResourceList
->Version
= 1;
1688 PartialResourceList
->Revision
= 1;
1689 PartialResourceList
->Count
= 0;
1691 /* Create new bus key */
1692 FldrCreateComponentKey(SystemKey
,
1694 MultiFunctionAdapter
,
1699 PartialResourceList
,
1703 MmHeapFree(PartialResourceList
);
1705 /* Detect ISA/BIOS devices */
1706 DetectBiosDisks(BusKey
);
1708 DetectBiosFloppyController(BusKey
);
1710 DetectSerialPorts(BusKey
);
1712 DetectParallelPorts(BusKey
);
1714 DetectKeyboardController(BusKey
);
1716 DetectPS2Mouse(BusKey
);
1718 DetectDisplayController(BusKey
);
1720 /* FIXME: Detect more ISA devices */
1724 PCONFIGURATION_COMPONENT_DATA
1727 PCONFIGURATION_COMPONENT_DATA SystemKey
;
1728 ULONG BusNumber
= 0;
1730 TRACE("DetectHardware()\n");
1732 HwInitializeBiosDisks();
1734 /* Create the 'System' key */
1735 SystemKey
= DetectSystem();
1738 DetectPciBios(SystemKey
, &BusNumber
);
1739 DetectApmBios(SystemKey
, &BusNumber
);
1740 DetectPnpBios(SystemKey
, &BusNumber
);
1741 DetectIsaBios(SystemKey
, &BusNumber
);
1742 DetectAcpiBios(SystemKey
, &BusNumber
);
1744 TRACE("DetectHardware() Done\n");
1754 /* Select APM 1.0+ function */
1757 /* Function 05h: CPU idle */
1761 Int386(0x15, &Regs
, &Regs
);
1763 /* Check if successfull (CF set on error) */
1764 if (INT386_SUCCESS(Regs
))
1768 * No futher processing here.
1769 * Optionally implement HLT instruction handling.