4 * Copyright (C) 2003, 2004 Eric Kohl
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #define CLOCK_TICK_RATE (1193182)
31 #define LATCH (CLOCK_TICK_RATE / HZ)
35 #define MOUSE_TYPE_NONE 0
36 /* Microsoft Mouse with 2 buttons */
37 #define MOUSE_TYPE_MICROSOFT 1
38 /* Logitech Mouse with 3 buttons */
39 #define MOUSE_TYPE_LOGITECH 2
40 /* Microsoft Wheel Mouse (aka Z Mouse) */
41 #define MOUSE_TYPE_WHEELZ 3
42 /* Mouse Systems Mouse */
43 #define MOUSE_TYPE_MOUSESYSTEMS 4
48 /* Controller registers. */
49 #define CONTROLLER_REGISTER_STATUS 0x64
50 #define CONTROLLER_REGISTER_CONTROL 0x64
51 #define CONTROLLER_REGISTER_DATA 0x60
53 /* Controller commands. */
54 #define CONTROLLER_COMMAND_READ_MODE 0x20
55 #define CONTROLLER_COMMAND_WRITE_MODE 0x60
56 #define CONTROLLER_COMMAND_GET_VERSION 0xA1
57 #define CONTROLLER_COMMAND_MOUSE_DISABLE 0xA7
58 #define CONTROLLER_COMMAND_MOUSE_ENABLE 0xA8
59 #define CONTROLLER_COMMAND_TEST_MOUSE 0xA9
60 #define CONTROLLER_COMMAND_SELF_TEST 0xAA
61 #define CONTROLLER_COMMAND_KEYBOARD_TEST 0xAB
62 #define CONTROLLER_COMMAND_KEYBOARD_DISABLE 0xAD
63 #define CONTROLLER_COMMAND_KEYBOARD_ENABLE 0xAE
64 #define CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER 0xD3
65 #define CONTROLLER_COMMAND_WRITE_MOUSE 0xD4
67 /* Controller status */
68 #define CONTROLLER_STATUS_OUTPUT_BUFFER_FULL 0x01
69 #define CONTROLLER_STATUS_INPUT_BUFFER_FULL 0x02
70 #define CONTROLLER_STATUS_SELF_TEST 0x04
71 #define CONTROLLER_STATUS_COMMAND 0x08
72 #define CONTROLLER_STATUS_UNLOCKED 0x10
73 #define CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL 0x20
74 #define CONTROLLER_STATUS_GENERAL_TIMEOUT 0x40
75 #define CONTROLLER_STATUS_PARITY_ERROR 0x80
76 #define AUX_STATUS_OUTPUT_BUFFER_FULL (CONTROLLER_STATUS_OUTPUT_BUFFER_FULL | \
77 CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL)
79 /* Timeout in ms for sending to keyboard controller. */
80 #define CONTROLLER_TIMEOUT 250
82 static CHAR Hex
[] = "0123456789abcdef";
83 static unsigned int delay_count
= 1;
85 extern ULONG reactos_disk_count
;
86 extern ARC_DISK_SIGNATURE reactos_arc_disk_info
[];
87 extern char reactos_arc_strings
[32][256];
89 /* FUNCTIONS ****************************************************************/
93 __StallExecutionProcessor(ULONG Loops
)
95 register volatile unsigned int i
;
96 for (i
= 0; i
< Loops
; i
++);
100 VOID
StallExecutionProcessor(ULONG Microseconds
)
102 ULONGLONG LoopCount
= ((ULONGLONG
)delay_count
* (ULONGLONG
)Microseconds
) / 1000ULL;
103 __StallExecutionProcessor((ULONG
)LoopCount
);
112 WRITE_PORT_UCHAR((PUCHAR
)0x43, 0x00);
113 Count
= READ_PORT_UCHAR((PUCHAR
)0x40);
114 Count
|= READ_PORT_UCHAR((PUCHAR
)0x40) << 8;
121 WaitFor8254Wraparound(VOID
)
124 ULONG PrevCount
= ~0;
127 CurCount
= Read8254Timer();
131 PrevCount
= CurCount
;
132 CurCount
= Read8254Timer();
133 Delta
= CurCount
- PrevCount
;
136 * This limit for delta seems arbitrary, but it isn't, it's
137 * slightly above the level of error a buggy Mercury/Neptune
138 * chipset timer can cause.
146 HalpCalibrateStallExecution(VOID
)
152 /* Initialise timer interrupt with MILLISECOND ms interval */
153 WRITE_PORT_UCHAR((PUCHAR
)0x43, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */
154 WRITE_PORT_UCHAR((PUCHAR
)0x40, LATCH
& 0xff); /* LSB */
155 WRITE_PORT_UCHAR((PUCHAR
)0x40, LATCH
>> 8); /* MSB */
157 /* Stage 1: Coarse calibration */
159 WaitFor8254Wraparound();
164 delay_count
<<= 1; /* Next delay count to try */
166 WaitFor8254Wraparound();
168 __StallExecutionProcessor(delay_count
); /* Do the delay */
170 CurCount
= Read8254Timer();
171 } while (CurCount
> LATCH
/ 2);
173 delay_count
>>= 1; /* Get bottom value for delay */
175 /* Stage 2: Fine calibration */
177 calib_bit
= delay_count
; /* Which bit are we going to test */
179 for(i
=0;i
<PRECISION
;i
++) {
180 calib_bit
>>= 1; /* Next bit to calibrate */
181 if(!calib_bit
) break; /* If we have done all bits, stop */
183 delay_count
|= calib_bit
; /* Set the bit in delay_count */
185 WaitFor8254Wraparound();
187 __StallExecutionProcessor(delay_count
); /* Do the delay */
189 CurCount
= Read8254Timer();
190 if (CurCount
<= LATCH
/ 2) /* If a tick has passed, turn the */
191 delay_count
&= ~calib_bit
; /* calibrated bit back off */
194 /* We're finished: Do the finishing touches */
195 delay_count
/= (MILLISEC
/ 2); /* Calculate delay_count for 1ms */
199 DetectPnpBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
201 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
202 PCM_PNP_BIOS_DEVICE_NODE DeviceNode
;
203 PCM_PNP_BIOS_INSTALLATION_CHECK InstData
;
204 PCONFIGURATION_COMPONENT_DATA BusKey
;
209 ULONG FoundNodeCount
;
215 InstData
= (PCM_PNP_BIOS_INSTALLATION_CHECK
)PnpBiosSupported();
216 if (InstData
== NULL
|| strncmp((CHAR
*)InstData
->Signature
, "$PnP", 4))
218 DPRINTM(DPRINT_HWDETECT
, "PnP-BIOS not supported\n");
221 DPRINTM(DPRINT_HWDETECT
, "Signature '%c%c%c%c'\n",
222 InstData
->Signature
[0], InstData
->Signature
[1],
223 InstData
->Signature
[2], InstData
->Signature
[3]);
226 x
= PnpBiosGetDeviceNodeCount(&NodeSize
, &NodeCount
);
227 NodeCount
&= 0xFF; // needed since some fscked up BIOSes return
228 // wrong info (e.g. Mac Virtual PC)
229 // e.g. look: http://my.execpc.com/~geezer/osd/pnp/pnp16.c
230 if (x
!= 0 || NodeSize
== 0 || NodeCount
== 0)
232 DPRINTM(DPRINT_HWDETECT
, "PnP-BIOS failed to enumerate device nodes\n");
235 DPRINTM(DPRINT_HWDETECT
, "PnP-BIOS supported\n");
236 DPRINTM(DPRINT_HWDETECT
, "MaxNodeSize %u NodeCount %u\n", NodeSize
, NodeCount
);
237 DPRINTM(DPRINT_HWDETECT
, "Estimated buffer size %u\n", NodeSize
* NodeCount
);
239 /* Set 'Configuration Data' value */
240 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) + (NodeSize
* NodeCount
);
241 PartialResourceList
= MmHeapAlloc(Size
);
242 if (PartialResourceList
== NULL
)
244 DPRINTM(DPRINT_HWDETECT
,
245 "Failed to allocate resource descriptor\n");
248 memset(PartialResourceList
, 0, Size
);
250 /* Initialize resource descriptor */
251 PartialResourceList
->Version
= 1;
252 PartialResourceList
->Revision
= 1;
253 PartialResourceList
->Count
= 1;
254 PartialResourceList
->PartialDescriptors
[0].Type
=
255 CmResourceTypeDeviceSpecific
;
256 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
=
257 CmResourceShareUndetermined
;
259 Ptr
= (char *)(((ULONG_PTR
)&PartialResourceList
->PartialDescriptors
[0]) +
260 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
262 /* Set instalation check data */
263 memcpy (Ptr
, InstData
, sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
));
264 Ptr
+= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
266 /* Copy device nodes */
268 PnpBufferSize
= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
269 for (i
= 0; i
< 0xFF; i
++)
271 NodeNumber
= (UCHAR
)i
;
273 x
= PnpBiosGetDeviceNode(&NodeNumber
, (PVOID
)DISKREADBUFFER
);
276 DeviceNode
= (PCM_PNP_BIOS_DEVICE_NODE
)DISKREADBUFFER
;
278 DPRINTM(DPRINT_HWDETECT
,
279 "Node: %u Size %u (0x%x)\n",
288 Ptr
+= DeviceNode
->Size
;
289 PnpBufferSize
+= DeviceNode
->Size
;
292 if (FoundNodeCount
>= NodeCount
)
297 /* Set real data size */
298 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
300 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) + PnpBufferSize
;
302 DPRINTM(DPRINT_HWDETECT
, "Real buffer size: %u\n", PnpBufferSize
);
303 DPRINTM(DPRINT_HWDETECT
, "Resource size: %u\n", Size
);
305 /* Create component key */
306 FldrCreateComponentKey(SystemKey
,
308 MultiFunctionAdapter
,
319 MmHeapFree(PartialResourceList
);
324 static PCM_PARTIAL_RESOURCE_LIST
325 GetHarddiskConfigurationData(ULONG DriveNumber
, ULONG
* pSize
)
327 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
328 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
329 EXTENDED_GEOMETRY ExtGeometry
;
334 // Initialize returned size
338 /* Set 'Configuration Data' value */
339 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
340 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
341 PartialResourceList
= MmHeapAlloc(Size
);
342 if (PartialResourceList
== NULL
)
344 DPRINTM(DPRINT_HWDETECT
,
345 "Failed to allocate a full resource descriptor\n");
349 memset(PartialResourceList
, 0, Size
);
350 PartialResourceList
->Version
= 1;
351 PartialResourceList
->Revision
= 1;
352 PartialResourceList
->Count
= 1;
353 PartialResourceList
->PartialDescriptors
[0].Type
=
354 CmResourceTypeDeviceSpecific
;
355 // PartialResourceList->PartialDescriptors[0].ShareDisposition =
356 // PartialResourceList->PartialDescriptors[0].Flags =
357 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
358 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
360 /* Get pointer to geometry data */
361 DiskGeometry
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
363 /* Get the disk geometry */
364 ExtGeometry
.Size
= sizeof(EXTENDED_GEOMETRY
);
365 if (DiskGetExtendedDriveParameters(DriveNumber
, &ExtGeometry
, ExtGeometry
.Size
))
367 DiskGeometry
->BytesPerSector
= ExtGeometry
.BytesPerSector
;
368 DiskGeometry
->NumberOfCylinders
= ExtGeometry
.Cylinders
;
369 DiskGeometry
->SectorsPerTrack
= ExtGeometry
.SectorsPerTrack
;
370 DiskGeometry
->NumberOfHeads
= ExtGeometry
.Heads
;
372 else if(MachDiskGetDriveGeometry(DriveNumber
, &Geometry
))
374 DiskGeometry
->BytesPerSector
= Geometry
.BytesPerSector
;
375 DiskGeometry
->NumberOfCylinders
= Geometry
.Cylinders
;
376 DiskGeometry
->SectorsPerTrack
= Geometry
.Sectors
;
377 DiskGeometry
->NumberOfHeads
= Geometry
.Heads
;
381 DPRINTM(DPRINT_HWDETECT
, "Reading disk geometry failed\n");
382 MmHeapFree(PartialResourceList
);
385 DPRINTM(DPRINT_HWDETECT
,
386 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
388 DiskGeometry
->NumberOfCylinders
,
389 DiskGeometry
->NumberOfHeads
,
390 DiskGeometry
->SectorsPerTrack
,
391 DiskGeometry
->BytesPerSector
);
394 // Return configuration data
397 return PartialResourceList
;
400 typedef struct tagDISKCONTEXT
404 ULONGLONG SectorOffset
;
405 ULONGLONG SectorNumber
;
408 static LONG
DiskClose(ULONG FileId
)
410 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
416 static LONG
DiskGetFileInformation(ULONG FileId
, FILEINFORMATION
* Information
)
421 static LONG
DiskOpen(CHAR
* Path
, OPENMODE OpenMode
, ULONG
* FileId
)
423 DISKCONTEXT
* Context
;
424 ULONG DriveNumber
, DrivePartition
, SectorSize
;
425 ULONGLONG SectorOffset
= 0;
426 PARTITION_TABLE_ENTRY PartitionTableEntry
;
429 if (!DissectArcPath(Path
, FileName
, &DriveNumber
, &DrivePartition
))
431 SectorSize
= (DrivePartition
== 0xff ? 2048 : 512);
432 if (DrivePartition
!= 0xff && DrivePartition
!= 0)
434 if (!MachDiskGetPartitionEntry(DriveNumber
, DrivePartition
, &PartitionTableEntry
))
436 SectorOffset
= PartitionTableEntry
.SectorCountBeforePartition
;
439 Context
= MmHeapAlloc(sizeof(DISKCONTEXT
));
442 Context
->DriveNumber
= DriveNumber
;
443 Context
->SectorSize
= SectorSize
;
444 Context
->SectorOffset
= SectorOffset
;
445 Context
->SectorNumber
= 0;
446 FsSetDeviceSpecific(*FileId
, Context
);
451 static LONG
DiskRead(ULONG FileId
, VOID
* Buffer
, ULONG N
, ULONG
* Count
)
453 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
454 UCHAR
* Ptr
= (UCHAR
*)Buffer
;
459 if (N
& (Context
->SectorSize
- 1))
462 for (i
= 0; i
< N
/ Context
->SectorSize
; i
++)
464 ret
= MachDiskReadLogicalSectors(
465 Context
->DriveNumber
,
466 Context
->SectorNumber
+ Context
->SectorOffset
+ i
,
468 (PVOID
)DISKREADBUFFER
);
471 RtlCopyMemory(Ptr
, (PVOID
)DISKREADBUFFER
, Context
->SectorSize
);
472 Ptr
+= Context
->SectorSize
;
479 static LONG
DiskSeek(ULONG FileId
, LARGE_INTEGER
* Position
, SEEKMODE SeekMode
)
481 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
483 if (SeekMode
!= SeekAbsolute
)
485 if (Position
->LowPart
& (Context
->SectorSize
- 1))
488 /* FIXME: take HighPart into account */
489 Context
->SectorNumber
= Position
->LowPart
/ Context
->SectorSize
;
493 static const DEVVTBL DiskVtbl
= {
495 DiskGetFileInformation
,
502 GetHarddiskIdentifier(PCHAR Identifier
,
505 PMASTER_BOOT_RECORD Mbr
;
511 PARTITION_TABLE_ENTRY PartitionTableEntry
;
514 if (!MachDiskReadLogicalSectors(DriveNumber
, 0ULL, 1, (PVOID
)DISKREADBUFFER
))
516 DPRINTM(DPRINT_HWDETECT
, "Reading MBR failed\n");
520 Buffer
= (ULONG
*)DISKREADBUFFER
;
521 Mbr
= (PMASTER_BOOT_RECORD
)DISKREADBUFFER
;
523 Signature
= Mbr
->Signature
;
524 DPRINTM(DPRINT_HWDETECT
, "Signature: %x\n", Signature
);
526 /* Calculate the MBR checksum */
528 for (i
= 0; i
< 128; i
++)
530 Checksum
+= Buffer
[i
];
532 Checksum
= ~Checksum
+ 1;
533 DPRINTM(DPRINT_HWDETECT
, "Checksum: %x\n", Checksum
);
535 /* Fill out the ARC disk block */
536 reactos_arc_disk_info
[reactos_disk_count
].Signature
= Signature
;
537 reactos_arc_disk_info
[reactos_disk_count
].CheckSum
= Checksum
;
538 sprintf(ArcName
, "multi(0)disk(0)rdisk(%lu)", reactos_disk_count
);
539 strcpy(reactos_arc_strings
[reactos_disk_count
], ArcName
);
540 reactos_arc_disk_info
[reactos_disk_count
].ArcName
=
541 reactos_arc_strings
[reactos_disk_count
];
542 reactos_disk_count
++;
544 sprintf(ArcName
, "multi(0)disk(0)rdisk(%lu)partition(0)", DriveNumber
- 0x80);
545 FsRegisterDevice(ArcName
, &DiskVtbl
);
549 DiskReportError(FALSE
);
550 while (MachDiskGetPartitionEntry(DriveNumber
, i
, &PartitionTableEntry
))
552 if (PartitionTableEntry
.SystemIndicator
!= PARTITION_ENTRY_UNUSED
)
554 sprintf(ArcName
, "multi(0)disk(0)rdisk(%lu)partition(%lu)", DriveNumber
- 0x80, i
);
555 FsRegisterDevice(ArcName
, &DiskVtbl
);
559 DiskReportError(TRUE
);
561 /* Convert checksum and signature to identifier string */
562 Identifier
[0] = Hex
[(Checksum
>> 28) & 0x0F];
563 Identifier
[1] = Hex
[(Checksum
>> 24) & 0x0F];
564 Identifier
[2] = Hex
[(Checksum
>> 20) & 0x0F];
565 Identifier
[3] = Hex
[(Checksum
>> 16) & 0x0F];
566 Identifier
[4] = Hex
[(Checksum
>> 12) & 0x0F];
567 Identifier
[5] = Hex
[(Checksum
>> 8) & 0x0F];
568 Identifier
[6] = Hex
[(Checksum
>> 4) & 0x0F];
569 Identifier
[7] = Hex
[Checksum
& 0x0F];
571 Identifier
[9] = Hex
[(Signature
>> 28) & 0x0F];
572 Identifier
[10] = Hex
[(Signature
>> 24) & 0x0F];
573 Identifier
[11] = Hex
[(Signature
>> 20) & 0x0F];
574 Identifier
[12] = Hex
[(Signature
>> 16) & 0x0F];
575 Identifier
[13] = Hex
[(Signature
>> 12) & 0x0F];
576 Identifier
[14] = Hex
[(Signature
>> 8) & 0x0F];
577 Identifier
[15] = Hex
[(Signature
>> 4) & 0x0F];
578 Identifier
[16] = Hex
[Signature
& 0x0F];
579 Identifier
[17] = '-';
580 Identifier
[18] = 'A';
582 DPRINTM(DPRINT_HWDETECT
, "Identifier: %s\n", Identifier
);
590 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0x10);
591 Data
= READ_PORT_UCHAR((PUCHAR
)0x71);
593 return ((Data
& 0xF0) ? 1 : 0) + ((Data
& 0x0F) ? 1 : 0);
598 GetFloppyType(UCHAR DriveNumber
)
602 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0x10);
603 Data
= READ_PORT_UCHAR((PUCHAR
)0x71);
605 if (DriveNumber
== 0)
607 else if (DriveNumber
== 1)
617 PUSHORT SegPtr
= (PUSHORT
)0x7A;
618 PUSHORT OfsPtr
= (PUSHORT
)0x78;
620 return (PVOID
)((ULONG_PTR
)(((ULONG
)(*SegPtr
)) << 4) + (ULONG
)(*OfsPtr
));
625 DetectBiosFloppyPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
)
627 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
628 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
629 PCM_FLOPPY_DEVICE_DATA FloppyData
;
631 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
635 ULONG MaxDensity
[6] = {0, 360, 1200, 720, 1440, 2880};
638 for (FloppyNumber
= 0; FloppyNumber
< 2; FloppyNumber
++)
640 FloppyType
= GetFloppyType(FloppyNumber
);
642 if ((FloppyType
> 5) || (FloppyType
== 0))
645 DiskResetController(FloppyNumber
);
647 Ptr
= GetInt1eTable();
649 /* Set 'Identifier' value */
650 sprintf(Identifier
, "FLOPPY%ld", FloppyNumber
+ 1);
652 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
653 sizeof(CM_FLOPPY_DEVICE_DATA
);
654 PartialResourceList
= MmHeapAlloc(Size
);
655 if (PartialResourceList
== NULL
)
657 DPRINTM(DPRINT_HWDETECT
,
658 "Failed to allocate resource descriptor\n");
662 memset(PartialResourceList
, 0, Size
);
663 PartialResourceList
->Version
= 1;
664 PartialResourceList
->Revision
= 1;
665 PartialResourceList
->Count
= 1;
667 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
668 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
669 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
670 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_FLOPPY_DEVICE_DATA
);
672 FloppyData
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
673 FloppyData
->Version
= 2;
674 FloppyData
->Revision
= 0;
675 FloppyData
->MaxDensity
= MaxDensity
[FloppyType
];
676 FloppyData
->MountDensity
= 0;
677 RtlCopyMemory(&FloppyData
->StepRateHeadUnloadTime
,
680 FloppyData
->MaximumTrackValue
= (FloppyType
== 1) ? 39 : 79;
681 FloppyData
->DataTransferRate
= 0;
683 FldrCreateComponentKey(ControllerKey
,
685 FloppyDiskPeripheral
,
694 MmHeapFree(PartialResourceList
);
700 DetectBiosFloppyController(PCONFIGURATION_COMPONENT_DATA BusKey
)
702 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
703 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
704 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
708 FloppyCount
= GetFloppyCount();
709 DPRINTM(DPRINT_HWDETECT
,
710 "Floppy count: %u\n",
713 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
714 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
715 PartialResourceList
= MmHeapAlloc(Size
);
716 if (PartialResourceList
== NULL
)
718 DPRINTM(DPRINT_HWDETECT
,
719 "Failed to allocate resource descriptor\n");
722 memset(PartialResourceList
, 0, Size
);
724 /* Initialize resource descriptor */
725 PartialResourceList
->Version
= 1;
726 PartialResourceList
->Revision
= 1;
727 PartialResourceList
->Count
= 3;
730 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
731 PartialDescriptor
->Type
= CmResourceTypePort
;
732 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
733 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
734 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x03F0;
735 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
736 PartialDescriptor
->u
.Port
.Length
= 8;
739 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
740 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
741 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
742 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
743 PartialDescriptor
->u
.Interrupt
.Level
= 6;
744 PartialDescriptor
->u
.Interrupt
.Vector
= 6;
745 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
747 /* Set DMA channel */
748 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
749 PartialDescriptor
->Type
= CmResourceTypeDma
;
750 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
751 PartialDescriptor
->Flags
= 0;
752 PartialDescriptor
->u
.Dma
.Channel
= 2;
753 PartialDescriptor
->u
.Dma
.Port
= 0;
755 /* Create floppy disk controller */
756 FldrCreateComponentKey(BusKey
,
766 DPRINTM(DPRINT_HWDETECT
, "Created key: DiskController\\0\n");
768 MmHeapFree(PartialResourceList
);
770 if (FloppyCount
) DetectBiosFloppyPeripheral(ControllerKey
);
773 static PCONFIGURATION_COMPONENT_DATA
776 PCONFIGURATION_COMPONENT_DATA SystemKey
;
777 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
778 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
785 /* Count the number of visible drives */
786 DiskReportError(FALSE
);
789 /* There are some really broken BIOSes out there. There are even BIOSes
790 * that happily report success when you ask them to read from non-existent
791 * harddisks. So, we set the buffer to known contents first, then try to
792 * read. If the BIOS reports success but the buffer contents haven't
793 * changed then we fail anyway */
794 memset((PVOID
) DISKREADBUFFER
, 0xcd, 512);
795 while (MachDiskReadLogicalSectors(0x80 + DiskCount
, 0ULL, 1, (PVOID
)DISKREADBUFFER
))
798 for (i
= 0; ! Changed
&& i
< 512; i
++)
800 Changed
= ((PUCHAR
)DISKREADBUFFER
)[i
] != 0xcd;
804 DPRINTM(DPRINT_HWDETECT
, "BIOS reports success for disk %d but data didn't change\n",
809 memset((PVOID
) DISKREADBUFFER
, 0xcd, 512);
811 DiskReportError(TRUE
);
812 DPRINTM(DPRINT_HWDETECT
, "BIOS reports %d harddisk%s\n",
813 (int)DiskCount
, (DiskCount
== 1) ? "": "s");
815 /* Allocate resource descriptor */
816 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
817 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
818 PartialResourceList
= MmHeapAlloc(Size
);
819 if (PartialResourceList
== NULL
)
821 DPRINTM(DPRINT_HWDETECT
,
822 "Failed to allocate resource descriptor\n");
826 /* Initialize resource descriptor */
827 memset(PartialResourceList
, 0, Size
);
828 PartialResourceList
->Version
= 1;
829 PartialResourceList
->Revision
= 1;
830 PartialResourceList
->Count
= 1;
831 PartialResourceList
->PartialDescriptors
[0].Type
= CmResourceTypeDeviceSpecific
;
832 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
= 0;
833 PartialResourceList
->PartialDescriptors
[0].Flags
= 0;
834 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
835 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
837 /* Get harddisk Int13 geometry data */
838 Int13Drives
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
839 for (i
= 0; i
< DiskCount
; i
++)
841 if (MachDiskGetDriveGeometry(0x80 + i
, &Geometry
))
843 Int13Drives
[i
].DriveSelect
= 0x80 + i
;
844 Int13Drives
[i
].MaxCylinders
= Geometry
.Cylinders
- 1;
845 Int13Drives
[i
].SectorsPerTrack
= Geometry
.Sectors
;
846 Int13Drives
[i
].MaxHeads
= Geometry
.Heads
- 1;
847 Int13Drives
[i
].NumberDrives
= DiskCount
;
849 DPRINTM(DPRINT_HWDETECT
,
850 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
852 Geometry
.Cylinders
- 1,
855 Geometry
.BytesPerSector
);
859 FldrCreateComponentKey(NULL
,
870 MmHeapFree(PartialResourceList
);
876 GetDiskCount(PCONFIGURATION_COMPONENT_DATA BusKey
)
878 PCONFIGURATION_COMPONENT_DATA System
;
879 ULONG ConfigurationDataLength
;
883 // Get root component
886 while (System
->Parent
)
887 System
= System
->Parent
;
890 // Get root configuration data length
892 ConfigurationDataLength
= System
->ComponentEntry
.ConfigurationDataLength
;
895 // We assume that nothing wrong happened, and that configuration
896 // only consists of one CM_PARTIAL_RESOURCE_LIST entry, followed
897 // by n entries of CM_INT13_DRIVE_PARAMETER
899 if (ConfigurationDataLength
> 0)
900 DiskCount
= (ConfigurationDataLength
- sizeof(CM_PARTIAL_RESOURCE_LIST
))
901 / sizeof(CM_INT13_DRIVE_PARAMETER
);
904 // Return number of disks
906 DPRINTM(DPRINT_HWDETECT
, "Retrieving %lu INT13 disks\\0\n");
911 DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA BusKey
)
913 PCONFIGURATION_COMPONENT_DATA DiskKey
, ControllerKey
;
914 BOOLEAN BootDriveReported
= FALSE
;
916 ULONG DiskCount
= GetDiskCount(BusKey
);
919 FldrCreateComponentKey(BusKey
,
929 DPRINTM(DPRINT_HWDETECT
, "Created key: DiskController\\0\n");
931 /* Create and fill subkey for each harddisk */
932 for (i
= 0; i
< DiskCount
; i
++)
934 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
938 if (BootDrive
== 0x80 + i
)
939 BootDriveReported
= TRUE
;
941 /* Get disk values */
942 PartialResourceList
= GetHarddiskConfigurationData(0x80 + i
, &Size
);
943 GetHarddiskIdentifier(Identifier
, 0x80 + i
);
945 /* Create disk key */
946 FldrCreateComponentKey(ControllerKey
,
958 /* Get the drive we're booting from */
959 MachDiskGetBootPath(BootPath
, sizeof(BootPath
));
961 /* Add it, if it's a floppy or cdrom */
962 if ((BootDrive
>= 0x80 && !BootDriveReported
) ||
963 DiskIsDriveRemovable(BootDrive
))
965 /* TODO: Check if it's really a cdrom drive */
966 FsRegisterDevice(BootPath
, &DiskVtbl
);
971 InitializeSerialPort(PUCHAR Port
,
974 WRITE_PORT_UCHAR(Port
+ 3, 0x80); /* set DLAB on */
975 WRITE_PORT_UCHAR(Port
, 0x60); /* speed LO byte */
976 WRITE_PORT_UCHAR(Port
+ 1, 0); /* speed HI byte */
977 WRITE_PORT_UCHAR(Port
+ 3, LineControl
);
978 WRITE_PORT_UCHAR(Port
+ 1, 0); /* set comm and DLAB to 0 */
979 WRITE_PORT_UCHAR(Port
+ 4, 0x09); /* DR int enable */
980 READ_PORT_UCHAR(Port
+ 5); /* clear error bits */
985 DetectSerialMouse(PUCHAR Port
)
992 /* Shutdown mouse or something like that */
993 LineControl
= READ_PORT_UCHAR(Port
+ 4);
994 WRITE_PORT_UCHAR(Port
+ 4, (LineControl
& ~0x02) | 0x01);
995 StallExecutionProcessor(100000);
999 * Maybe there is no serial port although BIOS reported one (this
1000 * is the case on Apple hardware), or the serial port is misbehaving,
1001 * therefore we must give up after some time.
1004 while (READ_PORT_UCHAR(Port
+ 5) & 0x01)
1007 return MOUSE_TYPE_NONE
;
1008 READ_PORT_UCHAR(Port
);
1012 * Send modem control with 'Data Terminal Ready', 'Request To Send' and
1013 * 'Output Line 2' message. This enables mouse to identify.
1015 WRITE_PORT_UCHAR(Port
+ 4, 0x0b);
1017 /* Wait 10 milliseconds for the mouse getting ready */
1018 StallExecutionProcessor(10000);
1020 /* Read first four bytes, which contains Microsoft Mouse signs */
1022 for (i
= 0; i
< 4; i
++)
1024 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
1026 StallExecutionProcessor(1000);
1029 return MOUSE_TYPE_NONE
;
1031 Buffer
[i
] = READ_PORT_UCHAR(Port
);
1034 DPRINTM(DPRINT_HWDETECT
,
1035 "Mouse data: %x %x %x %x\n",
1036 Buffer
[0],Buffer
[1],Buffer
[2],Buffer
[3]);
1038 /* Check that four bytes for signs */
1039 for (i
= 0; i
< 4; ++i
)
1041 if (Buffer
[i
] == 'B')
1043 /* Sign for Microsoft Ballpoint */
1044 // DbgPrint("Microsoft Ballpoint device detected\n");
1045 // DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET\n");
1046 return MOUSE_TYPE_NONE
;
1048 else if (Buffer
[i
] == 'M')
1050 /* Sign for Microsoft Mouse protocol followed by button specifier */
1053 /* Overflow Error */
1054 return MOUSE_TYPE_NONE
;
1057 switch (Buffer
[i
+ 1])
1060 DPRINTM(DPRINT_HWDETECT
,
1061 "Microsoft Mouse with 3-buttons detected\n");
1062 return MOUSE_TYPE_LOGITECH
;
1065 DPRINTM(DPRINT_HWDETECT
,
1066 "Microsoft Wheel Mouse detected\n");
1067 return MOUSE_TYPE_WHEELZ
;
1071 DPRINTM(DPRINT_HWDETECT
,
1072 "Microsoft Mouse with 2-buttons detected\n");
1073 return MOUSE_TYPE_MICROSOFT
;
1078 return MOUSE_TYPE_NONE
;
1083 GetSerialMousePnpId(PUCHAR Port
, char *Buffer
)
1090 WRITE_PORT_UCHAR(Port
+ 4, 0x09);
1092 /* Wait 10 milliseconds for the mouse getting ready */
1093 StallExecutionProcessor(10000);
1095 WRITE_PORT_UCHAR(Port
+ 4, 0x0b);
1097 StallExecutionProcessor(10000);
1102 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
1104 StallExecutionProcessor(1000);
1112 c
= READ_PORT_UCHAR(Port
);
1113 if (c
== 0x08 || c
== 0x28)
1123 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
1125 StallExecutionProcessor(1000);
1130 c
= READ_PORT_UCHAR(Port
);
1143 DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
,
1146 CM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1148 CHAR Identifier
[256];
1149 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
1156 DPRINTM(DPRINT_HWDETECT
,
1157 "DetectSerialPointerPeripheral()\n");
1161 InitializeSerialPort(Base
, 2);
1162 MouseType
= DetectSerialMouse(Base
);
1164 if (MouseType
!= MOUSE_TYPE_NONE
)
1166 Length
= GetSerialMousePnpId(Base
, Buffer
);
1167 DPRINTM(DPRINT_HWDETECT
,
1168 "PnP ID length: %u\n",
1173 /* Convert PnP sting to ASCII */
1174 if (Buffer
[0] == 0x08)
1176 for (i
= 0; i
< Length
; i
++)
1181 DPRINTM(DPRINT_HWDETECT
,
1182 "PnP ID string: %s\n",
1185 /* Copy PnpId string */
1186 for (i
= 0; i
< 7; i
++)
1188 Identifier
[i
] = Buffer
[3+i
];
1190 memcpy(&Identifier
[7],
1194 /* Skip device serial number */
1196 if (Buffer
[i
] == '\\')
1198 for (j
= ++i
; i
< Length
; ++i
)
1200 if (Buffer
[i
] == '\\')
1207 /* Skip PnP class */
1208 if (Buffer
[i
] == '\\')
1210 for (j
= ++i
; i
< Length
; ++i
)
1212 if (Buffer
[i
] == '\\')
1220 /* Skip compatible PnP Id */
1221 if (Buffer
[i
] == '\\')
1223 for (j
= ++i
; i
< Length
; ++i
)
1225 if (Buffer
[i
] == '\\')
1228 if (Buffer
[j
] == '*')
1234 /* Get product description */
1235 if (Buffer
[i
] == '\\')
1237 for (j
= ++i
; i
< Length
; ++i
)
1239 if (Buffer
[i
] == ';')
1246 for (k
= 0; k
< i
- j
; k
++)
1248 Identifier
[k
+ 10] = Buffer
[k
+ j
];
1250 Identifier
[10 + (i
-j
)] = 0;
1254 DPRINTM(DPRINT_HWDETECT
,
1255 "Identifier string: %s\n",
1259 if (Length
== 0 || strlen(Identifier
) < 11)
1263 case MOUSE_TYPE_LOGITECH
:
1265 "LOGITECH SERIAL MOUSE");
1268 case MOUSE_TYPE_WHEELZ
:
1270 "MICROSOFT SERIAL MOUSE WITH WHEEL");
1273 case MOUSE_TYPE_MICROSOFT
:
1276 "MICROSOFT SERIAL MOUSE");
1281 /* Set 'Configuration Data' value */
1282 memset(&PartialResourceList
, 0, sizeof(CM_PARTIAL_RESOURCE_LIST
));
1283 PartialResourceList
.Version
= 1;
1284 PartialResourceList
.Revision
= 1;
1285 PartialResourceList
.Count
= 0;
1287 /* Create 'PointerPeripheral' key */
1288 FldrCreateComponentKey(ControllerKey
,
1295 &PartialResourceList
,
1296 sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1297 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
),
1300 DPRINTM(DPRINT_HWDETECT
,
1301 "Created key: PointerPeripheral\\0\n");
1307 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
1309 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1310 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1311 PCM_SERIAL_DEVICE_DATA SerialDeviceData
;
1312 ULONG Irq
[4] = {4, 3, 4, 3};
1316 ULONG ControllerNumber
= 0;
1317 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1321 DPRINTM(DPRINT_HWDETECT
, "DetectSerialPorts()\n");
1323 ControllerNumber
= 0;
1324 BasePtr
= (PUSHORT
)0x400;
1325 for (i
= 0; i
< 4; i
++, BasePtr
++)
1327 Base
= (ULONG
)*BasePtr
;
1331 DPRINTM(DPRINT_HWDETECT
,
1332 "Found COM%u port at 0x%x\n",
1336 /* Set 'Identifier' value */
1337 sprintf(Buffer
, "COM%ld", i
+ 1);
1339 /* Build full device descriptor */
1340 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
1341 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) +
1342 sizeof(CM_SERIAL_DEVICE_DATA
);
1343 PartialResourceList
= MmHeapAlloc(Size
);
1344 if (PartialResourceList
== NULL
)
1346 DPRINTM(DPRINT_HWDETECT
,
1347 "Failed to allocate resource descriptor\n");
1350 memset(PartialResourceList
, 0, Size
);
1352 /* Initialize resource descriptor */
1353 PartialResourceList
->Version
= 1;
1354 PartialResourceList
->Revision
= 1;
1355 PartialResourceList
->Count
= 3;
1358 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1359 PartialDescriptor
->Type
= CmResourceTypePort
;
1360 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1361 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1362 PartialDescriptor
->u
.Port
.Start
.LowPart
= Base
;
1363 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1364 PartialDescriptor
->u
.Port
.Length
= 7;
1367 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
1368 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
1369 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1370 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1371 PartialDescriptor
->u
.Interrupt
.Level
= Irq
[i
];
1372 PartialDescriptor
->u
.Interrupt
.Vector
= 0;
1373 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1375 /* Set serial data (device specific) */
1376 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
1377 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
1378 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1379 PartialDescriptor
->Flags
= 0;
1380 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_SERIAL_DEVICE_DATA
);
1383 (PCM_SERIAL_DEVICE_DATA
)&PartialResourceList
->PartialDescriptors
[3];
1384 SerialDeviceData
->BaudClock
= 1843200; /* UART Clock frequency (Hertz) */
1386 /* Create controller key */
1387 FldrCreateComponentKey(BusKey
,
1390 Output
| Input
| ConsoleIn
| ConsoleOut
,
1394 PartialResourceList
,
1398 MmHeapFree(PartialResourceList
);
1400 if (!Rs232PortInUse(Base
))
1402 /* Detect serial mouse */
1403 DetectSerialPointerPeripheral(ControllerKey
, UlongToPtr(Base
));
1412 DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
1414 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1415 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1416 ULONG Irq
[3] = {7, 5, (ULONG
)-1};
1418 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1421 ULONG ControllerNumber
;
1425 DPRINTM(DPRINT_HWDETECT
, "DetectParallelPorts() called\n");
1427 ControllerNumber
= 0;
1428 BasePtr
= (PUSHORT
)0x408;
1429 for (i
= 0; i
< 3; i
++, BasePtr
++)
1431 Base
= (ULONG
)*BasePtr
;
1435 DPRINTM(DPRINT_HWDETECT
,
1436 "Parallel port %u: %x\n",
1440 /* Set 'Identifier' value */
1441 sprintf(Buffer
, "PARALLEL%ld", i
+ 1);
1443 /* Build full device descriptor */
1444 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
);
1445 if (Irq
[i
] != (ULONG
)-1)
1446 Size
+= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1448 PartialResourceList
= MmHeapAlloc(Size
);
1449 if (PartialResourceList
== NULL
)
1451 DPRINTM(DPRINT_HWDETECT
,
1452 "Failed to allocate resource descriptor\n");
1455 memset(PartialResourceList
, 0, Size
);
1457 /* Initialize resource descriptor */
1458 PartialResourceList
->Version
= 1;
1459 PartialResourceList
->Revision
= 1;
1460 PartialResourceList
->Count
= (Irq
[i
] != (ULONG
)-1) ? 2 : 1;
1463 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1464 PartialDescriptor
->Type
= CmResourceTypePort
;
1465 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1466 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1467 PartialDescriptor
->u
.Port
.Start
.LowPart
= Base
;
1468 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1469 PartialDescriptor
->u
.Port
.Length
= 3;
1472 if (Irq
[i
] != (ULONG
)-1)
1474 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
1475 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
1476 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1477 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1478 PartialDescriptor
->u
.Interrupt
.Level
= Irq
[i
];
1479 PartialDescriptor
->u
.Interrupt
.Vector
= 0;
1480 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1483 /* Create controller key */
1484 FldrCreateComponentKey(BusKey
,
1491 PartialResourceList
,
1495 MmHeapFree(PartialResourceList
);
1500 DPRINTM(DPRINT_HWDETECT
, "DetectParallelPorts() done\n");
1505 DetectKeyboardDevice(VOID
)
1510 BOOLEAN Result
= TRUE
;
1512 /* Identify device */
1513 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
,
1516 /* Wait for reply */
1517 for (Loops
= 0; Loops
< 100; Loops
++)
1519 StallExecutionProcessor(10000);
1520 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1521 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1525 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
1527 /* PC/XT keyboard or no keyboard */
1531 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1532 if (Scancode
!= 0xFA)
1534 /* No ACK received */
1538 StallExecutionProcessor(10000);
1540 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1541 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
1543 /* Found AT keyboard */
1547 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1548 if (Scancode
!= 0xAB)
1550 /* No 0xAB received */
1554 StallExecutionProcessor(10000);
1556 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1557 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
1559 /* No byte in buffer */
1563 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1564 if (Scancode
!= 0x41)
1566 /* No 0x41 received */
1570 /* Found MF-II keyboard */
1576 DetectKeyboardPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
)
1578 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1579 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1580 PCM_KEYBOARD_DEVICE_DATA KeyboardData
;
1581 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
1584 /* HACK: don't call DetectKeyboardDevice() as it fails in Qemu 0.8.2 */
1585 if (TRUE
|| DetectKeyboardDevice())
1587 /* Set 'Configuration Data' value */
1588 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
1589 sizeof(CM_KEYBOARD_DEVICE_DATA
);
1590 PartialResourceList
= MmHeapAlloc(Size
);
1591 if (PartialResourceList
== NULL
)
1593 DPRINTM(DPRINT_HWDETECT
,
1594 "Failed to allocate resource descriptor\n");
1598 /* Initialize resource descriptor */
1599 memset(PartialResourceList
, 0, Size
);
1600 PartialResourceList
->Version
= 1;
1601 PartialResourceList
->Revision
= 1;
1602 PartialResourceList
->Count
= 1;
1604 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1605 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
1606 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1607 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_KEYBOARD_DEVICE_DATA
);
1609 KeyboardData
= (PCM_KEYBOARD_DEVICE_DATA
)(PartialDescriptor
+ 1);
1610 KeyboardData
->Version
= 1;
1611 KeyboardData
->Revision
= 1;
1612 KeyboardData
->Type
= 4;
1613 KeyboardData
->Subtype
= 0;
1614 KeyboardData
->KeyboardFlags
= 0x20;
1616 /* Create controller key */
1617 FldrCreateComponentKey(ControllerKey
,
1624 PartialResourceList
,
1627 DPRINTM(DPRINT_HWDETECT
, "Created key: KeyboardPeripheral\\0\n");
1629 MmHeapFree(PartialResourceList
);
1635 DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey
)
1637 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1638 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1639 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1642 /* Set 'Configuration Data' value */
1643 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
1644 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1645 PartialResourceList
= MmHeapAlloc(Size
);
1646 if (PartialResourceList
== NULL
)
1648 DPRINTM(DPRINT_HWDETECT
,
1649 "Failed to allocate resource descriptor\n");
1653 /* Initialize resource descriptor */
1654 memset(PartialResourceList
, 0, Size
);
1655 PartialResourceList
->Version
= 1;
1656 PartialResourceList
->Revision
= 1;
1657 PartialResourceList
->Count
= 3;
1660 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1661 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
1662 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1663 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1664 PartialDescriptor
->u
.Interrupt
.Level
= 1;
1665 PartialDescriptor
->u
.Interrupt
.Vector
= 0;
1666 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1668 /* Set IO Port 0x60 */
1669 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
1670 PartialDescriptor
->Type
= CmResourceTypePort
;
1671 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1672 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1673 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x60;
1674 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1675 PartialDescriptor
->u
.Port
.Length
= 1;
1677 /* Set IO Port 0x64 */
1678 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
1679 PartialDescriptor
->Type
= CmResourceTypePort
;
1680 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1681 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1682 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x64;
1683 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1684 PartialDescriptor
->u
.Port
.Length
= 1;
1686 /* Create controller key */
1687 FldrCreateComponentKey(BusKey
,
1694 PartialResourceList
,
1697 DPRINTM(DPRINT_HWDETECT
, "Created key: KeyboardController\\0\n");
1699 MmHeapFree(PartialResourceList
);
1701 DetectKeyboardPeripheral(ControllerKey
);
1706 PS2ControllerWait(VOID
)
1711 for (Timeout
= 0; Timeout
< CONTROLLER_TIMEOUT
; Timeout
++)
1713 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1714 if ((Status
& CONTROLLER_STATUS_INPUT_BUFFER_FULL
) == 0)
1717 /* Sleep for one millisecond */
1718 StallExecutionProcessor(1000);
1724 DetectPS2AuxPort(VOID
)
1727 /* Current detection is too unreliable. Just do as if
1728 * the PS/2 aux port is always present
1735 /* Put the value 0x5A in the output buffer using the
1736 * "WriteAuxiliary Device Output Buffer" command (0xD3).
1737 * Poll the Status Register for a while to see if the value really turns up
1738 * in the Data Register. If the KEYBOARD_STATUS_MOUSE_OBF bit is also set
1739 * to 1 in the Status Register, we assume this controller has an
1740 * Auxiliary Port (a.k.a. Mouse Port).
1742 PS2ControllerWait();
1743 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_CONTROL
,
1744 CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER
);
1745 PS2ControllerWait();
1747 /* 0x5A is a random dummy value */
1748 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
,
1751 for (Loops
= 0; Loops
< 10; Loops
++)
1753 StallExecutionProcessor(10000);
1754 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1755 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1759 READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1761 return (Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
);
1767 DetectPS2AuxDevice(VOID
)
1772 BOOLEAN Result
= TRUE
;
1774 PS2ControllerWait();
1775 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_CONTROL
,
1776 CONTROLLER_COMMAND_WRITE_MOUSE
);
1777 PS2ControllerWait();
1779 /* Identify device */
1780 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
,
1783 /* Wait for reply */
1784 for (Loops
= 0; Loops
< 100; Loops
++)
1786 StallExecutionProcessor(10000);
1787 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1788 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1792 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1793 if ((Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
) == 0)
1796 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1797 if (Scancode
!= 0xFA)
1800 StallExecutionProcessor(10000);
1802 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1803 if ((Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
) == 0)
1806 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1807 if (Scancode
!= 0x00)
1815 DetectPS2Mouse(PCONFIGURATION_COMPONENT_DATA BusKey
)
1817 CM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1818 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1819 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
1821 if (DetectPS2AuxPort())
1823 DPRINTM(DPRINT_HWDETECT
, "Detected PS2 port\n");
1825 memset(&PartialResourceList
, 0, sizeof(CM_PARTIAL_RESOURCE_LIST
));
1827 /* Initialize resource descriptor */
1828 PartialResourceList
.Version
= 1;
1829 PartialResourceList
.Revision
= 1;
1830 PartialResourceList
.Count
= 1;
1833 PartialResourceList
.PartialDescriptors
[0].Type
= CmResourceTypeInterrupt
;
1834 PartialResourceList
.PartialDescriptors
[0].ShareDisposition
= CmResourceShareUndetermined
;
1835 PartialResourceList
.PartialDescriptors
[0].Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1836 PartialResourceList
.PartialDescriptors
[0].u
.Interrupt
.Level
= 12;
1837 PartialResourceList
.PartialDescriptors
[0].u
.Interrupt
.Vector
= 0;
1838 PartialResourceList
.PartialDescriptors
[0].u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1840 /* Create controller key */
1841 FldrCreateComponentKey(BusKey
,
1848 &PartialResourceList
,
1849 sizeof(CM_PARTIAL_RESOURCE_LIST
),
1851 DPRINTM(DPRINT_HWDETECT
, "Created key: PointerController\\0\n");
1853 if (DetectPS2AuxDevice())
1855 DPRINTM(DPRINT_HWDETECT
, "Detected PS2 mouse\n");
1857 /* Initialize resource descriptor */
1858 memset(&PartialResourceList
, 0, sizeof(CM_PARTIAL_RESOURCE_LIST
));
1859 PartialResourceList
.Version
= 1;
1860 PartialResourceList
.Revision
= 1;
1861 PartialResourceList
.Count
= 0;
1863 /* Create peripheral key */
1864 FldrCreateComponentKey(ControllerKey
,
1870 "MICROSOFT PS2 MOUSE",
1871 &PartialResourceList
,
1872 sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1873 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
),
1875 DPRINTM(DPRINT_HWDETECT
, "Created key: PointerPeripheral\\0\n");
1882 DetectDisplayController(PCONFIGURATION_COMPONENT_DATA BusKey
)
1885 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1888 /* FIXME: Set 'ComponentInformation' value */
1890 VesaVersion
= BiosIsVesaSupported();
1891 if (VesaVersion
!= 0)
1893 DPRINTM(DPRINT_HWDETECT
,
1894 "VESA version %c.%c\n",
1895 (VesaVersion
>> 8) + '0',
1896 (VesaVersion
& 0xFF) + '0');
1900 DPRINTM(DPRINT_HWDETECT
,
1901 "VESA not supported\n");
1904 if (VesaVersion
>= 0x0200)
1915 FldrCreateComponentKey(BusKey
,
1925 DPRINTM(DPRINT_HWDETECT
, "Created key: DisplayController\\0\n");
1927 /* FIXME: Add display peripheral (monitor) data */
1932 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
1934 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1935 PCONFIGURATION_COMPONENT_DATA BusKey
;
1938 /* Increment bus number */
1941 /* Set 'Configuration Data' value */
1942 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1943 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1944 PartialResourceList
= MmHeapAlloc(Size
);
1945 if (PartialResourceList
== NULL
)
1947 DPRINTM(DPRINT_HWDETECT
,
1948 "Failed to allocate resource descriptor\n");
1952 /* Initialize resource descriptor */
1953 memset(PartialResourceList
, 0, Size
);
1954 PartialResourceList
->Version
= 1;
1955 PartialResourceList
->Revision
= 1;
1956 PartialResourceList
->Count
= 0;
1958 /* Create new bus key */
1959 FldrCreateComponentKey(SystemKey
,
1961 MultiFunctionAdapter
,
1966 PartialResourceList
,
1970 MmHeapFree(PartialResourceList
);
1972 /* Detect ISA/BIOS devices */
1973 DetectBiosDisks(BusKey
);
1975 DetectBiosFloppyController(BusKey
);
1977 DetectSerialPorts(BusKey
);
1979 DetectParallelPorts(BusKey
);
1981 DetectKeyboardController(BusKey
);
1983 DetectPS2Mouse(BusKey
);
1985 DetectDisplayController(BusKey
);
1987 /* FIXME: Detect more ISA devices */
1991 PCONFIGURATION_COMPONENT_DATA
1994 PCONFIGURATION_COMPONENT_DATA SystemKey
;
1995 ULONG BusNumber
= 0;
1997 DPRINTM(DPRINT_HWDETECT
, "DetectHardware()\n");
1999 /* Create the 'System' key */
2000 SystemKey
= DetectSystem();
2003 DetectPciBios(SystemKey
, &BusNumber
);
2004 DetectApmBios(SystemKey
, &BusNumber
);
2005 DetectPnpBios(SystemKey
, &BusNumber
);
2006 DetectIsaBios(SystemKey
, &BusNumber
);
2007 DetectAcpiBios(SystemKey
, &BusNumber
);
2009 DPRINTM(DPRINT_HWDETECT
, "DetectHardware() Done\n");