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 /* Create component key */
240 FldrCreateComponentKey(SystemKey
,
241 L
"MultifunctionAdapter",
244 MultiFunctionAdapter
,
248 /* Set the component information */
249 FldrSetComponentInformation(BusKey
,
254 /* Set the identifier */
255 FldrSetIdentifier(BusKey
, "PNP BIOS");
257 /* Set 'Configuration Data' value */
258 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) + (NodeSize
* NodeCount
);
259 PartialResourceList
= MmHeapAlloc(Size
);
260 if (PartialResourceList
== NULL
)
262 DPRINTM(DPRINT_HWDETECT
,
263 "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 Ptr
= (char *)(((ULONG_PTR
)&PartialResourceList
->PartialDescriptors
[0]) +
278 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
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 DPRINTM(DPRINT_HWDETECT
,
297 "Node: %u Size %u (0x%x)\n",
306 Ptr
+= DeviceNode
->Size
;
307 PnpBufferSize
+= DeviceNode
->Size
;
310 if (FoundNodeCount
>= NodeCount
)
315 /* Set real data size */
316 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
318 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) + PnpBufferSize
;
320 DPRINTM(DPRINT_HWDETECT
, "Real buffer size: %u\n", PnpBufferSize
);
321 DPRINTM(DPRINT_HWDETECT
, "Resource size: %u\n", Size
);
323 FldrSetConfigurationData(BusKey
, PartialResourceList
, Size
);
324 MmHeapFree(PartialResourceList
);
330 SetHarddiskConfigurationData(PCONFIGURATION_COMPONENT_DATA DiskKey
,
333 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
334 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
335 EXTENDED_GEOMETRY ExtGeometry
;
339 /* Set 'Configuration Data' value */
340 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
341 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
342 PartialResourceList
= MmHeapAlloc(Size
);
343 if (PartialResourceList
== NULL
)
345 DPRINTM(DPRINT_HWDETECT
,
346 "Failed to allocate a full resource descriptor\n");
350 memset(PartialResourceList
, 0, Size
);
351 PartialResourceList
->Version
= 1;
352 PartialResourceList
->Revision
= 1;
353 PartialResourceList
->Count
= 1;
354 PartialResourceList
->PartialDescriptors
[0].Type
=
355 CmResourceTypeDeviceSpecific
;
356 // PartialResourceList->PartialDescriptors[0].ShareDisposition =
357 // PartialResourceList->PartialDescriptors[0].Flags =
358 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
359 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
361 /* Get pointer to geometry data */
362 DiskGeometry
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
364 /* Get the disk geometry */
365 ExtGeometry
.Size
= sizeof(EXTENDED_GEOMETRY
);
366 if (DiskGetExtendedDriveParameters(DriveNumber
, &ExtGeometry
, ExtGeometry
.Size
))
368 DiskGeometry
->BytesPerSector
= ExtGeometry
.BytesPerSector
;
369 DiskGeometry
->NumberOfCylinders
= ExtGeometry
.Cylinders
;
370 DiskGeometry
->SectorsPerTrack
= ExtGeometry
.SectorsPerTrack
;
371 DiskGeometry
->NumberOfHeads
= ExtGeometry
.Heads
;
373 else if(MachDiskGetDriveGeometry(DriveNumber
, &Geometry
))
375 DiskGeometry
->BytesPerSector
= Geometry
.BytesPerSector
;
376 DiskGeometry
->NumberOfCylinders
= Geometry
.Cylinders
;
377 DiskGeometry
->SectorsPerTrack
= Geometry
.Sectors
;
378 DiskGeometry
->NumberOfHeads
= Geometry
.Heads
;
382 DPRINTM(DPRINT_HWDETECT
, "Reading disk geometry failed\n");
383 MmHeapFree(PartialResourceList
);
386 DPRINTM(DPRINT_HWDETECT
,
387 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
389 DiskGeometry
->NumberOfCylinders
,
390 DiskGeometry
->NumberOfHeads
,
391 DiskGeometry
->SectorsPerTrack
,
392 DiskGeometry
->BytesPerSector
);
394 FldrSetConfigurationData(DiskKey
, PartialResourceList
, Size
);
395 MmHeapFree(PartialResourceList
);
398 typedef struct tagDISKCONTEXT
402 ULONGLONG SectorOffset
;
403 ULONGLONG SectorNumber
;
406 static LONG
DiskClose(ULONG FileId
)
408 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
414 static LONG
DiskGetFileInformation(ULONG FileId
, FILEINFORMATION
* Information
)
419 static LONG
DiskOpen(CHAR
* Path
, OPENMODE OpenMode
, ULONG
* FileId
)
421 DISKCONTEXT
* Context
;
422 ULONG DriveNumber
, DrivePartition
, SectorSize
;
423 ULONGLONG SectorOffset
= 0;
424 PARTITION_TABLE_ENTRY PartitionTableEntry
;
427 if (!DissectArcPath(Path
, FileName
, &DriveNumber
, &DrivePartition
))
429 SectorSize
= (DrivePartition
== 0xff ? 2048 : 512);
430 if (DrivePartition
!= 0xff && DrivePartition
!= 0)
432 if (!MachDiskGetPartitionEntry(DriveNumber
, DrivePartition
, &PartitionTableEntry
))
434 SectorOffset
= PartitionTableEntry
.SectorCountBeforePartition
;
437 Context
= MmHeapAlloc(sizeof(DISKCONTEXT
));
440 Context
->DriveNumber
= DriveNumber
;
441 Context
->SectorSize
= SectorSize
;
442 Context
->SectorOffset
= SectorOffset
;
443 Context
->SectorNumber
= 0;
444 FsSetDeviceSpecific(*FileId
, Context
);
449 static LONG
DiskRead(ULONG FileId
, VOID
* Buffer
, ULONG N
, ULONG
* Count
)
451 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
455 if (N
& (Context
->SectorSize
- 1))
458 ret
= MachDiskReadLogicalSectors(
459 Context
->DriveNumber
,
460 Context
->SectorNumber
+ Context
->SectorOffset
,
461 N
/ Context
->SectorSize
,
470 static LONG
DiskSeek(ULONG FileId
, LARGE_INTEGER
* Position
, SEEKMODE SeekMode
)
472 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
474 if (SeekMode
!= SeekAbsolute
)
476 if (Position
->LowPart
& (Context
->SectorSize
- 1))
479 /* FIXME: take HighPart into account */
480 Context
->SectorNumber
= Position
->LowPart
/ Context
->SectorSize
;
484 static const DEVVTBL DiskVtbl
= {
486 DiskGetFileInformation
,
493 SetHarddiskIdentifier(PCONFIGURATION_COMPONENT_DATA DiskKey
,
496 PMASTER_BOOT_RECORD Mbr
;
503 PARTITION_TABLE_ENTRY PartitionTableEntry
;
506 if (!MachDiskReadLogicalSectors(DriveNumber
, 0ULL, 1, (PVOID
)DISKREADBUFFER
))
508 DPRINTM(DPRINT_HWDETECT
, "Reading MBR failed\n");
512 Buffer
= (ULONG
*)DISKREADBUFFER
;
513 Mbr
= (PMASTER_BOOT_RECORD
)DISKREADBUFFER
;
515 Signature
= Mbr
->Signature
;
516 DPRINTM(DPRINT_HWDETECT
, "Signature: %x\n", Signature
);
518 /* Calculate the MBR checksum */
520 for (i
= 0; i
< 128; i
++)
522 Checksum
+= Buffer
[i
];
524 Checksum
= ~Checksum
+ 1;
525 DPRINTM(DPRINT_HWDETECT
, "Checksum: %x\n", Checksum
);
527 /* Fill out the ARC disk block */
528 reactos_arc_disk_info
[reactos_disk_count
].Signature
= Signature
;
529 reactos_arc_disk_info
[reactos_disk_count
].CheckSum
= Checksum
;
530 sprintf(ArcName
, "multi(0)disk(0)rdisk(%lu)", reactos_disk_count
);
531 strcpy(reactos_arc_strings
[reactos_disk_count
], ArcName
);
532 reactos_arc_disk_info
[reactos_disk_count
].ArcName
=
533 reactos_arc_strings
[reactos_disk_count
];
534 reactos_disk_count
++;
536 sprintf(ArcName
, "multi(0)disk(0)rdisk(%lu)partition(0)", DriveNumber
- 0x80);
537 FsRegisterDevice(ArcName
, &DiskVtbl
);
542 while (MachDiskGetPartitionEntry(DriveNumber
, i
, &PartitionTableEntry
))
544 if (PartitionTableEntry
.SystemIndicator
!= PARTITION_ENTRY_UNUSED
)
546 sprintf(ArcName
, "multi(0)disk(0)rdisk(%lu)partition(%lu)", DriveNumber
- 0x80, i
);
547 FsRegisterDevice(ArcName
, &DiskVtbl
);
553 /* Convert checksum and signature to identifier string */
554 Identifier
[0] = Hex
[(Checksum
>> 28) & 0x0F];
555 Identifier
[1] = Hex
[(Checksum
>> 24) & 0x0F];
556 Identifier
[2] = Hex
[(Checksum
>> 20) & 0x0F];
557 Identifier
[3] = Hex
[(Checksum
>> 16) & 0x0F];
558 Identifier
[4] = Hex
[(Checksum
>> 12) & 0x0F];
559 Identifier
[5] = Hex
[(Checksum
>> 8) & 0x0F];
560 Identifier
[6] = Hex
[(Checksum
>> 4) & 0x0F];
561 Identifier
[7] = Hex
[Checksum
& 0x0F];
563 Identifier
[9] = Hex
[(Signature
>> 28) & 0x0F];
564 Identifier
[10] = Hex
[(Signature
>> 24) & 0x0F];
565 Identifier
[11] = Hex
[(Signature
>> 20) & 0x0F];
566 Identifier
[12] = Hex
[(Signature
>> 16) & 0x0F];
567 Identifier
[13] = Hex
[(Signature
>> 12) & 0x0F];
568 Identifier
[14] = Hex
[(Signature
>> 8) & 0x0F];
569 Identifier
[15] = Hex
[(Signature
>> 4) & 0x0F];
570 Identifier
[16] = Hex
[Signature
& 0x0F];
571 Identifier
[17] = '-';
572 Identifier
[18] = 'A';
574 DPRINTM(DPRINT_HWDETECT
, "Identifier: %s\n", Identifier
);
577 FldrSetIdentifier(DiskKey
, Identifier
);
585 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0x10);
586 Data
= READ_PORT_UCHAR((PUCHAR
)0x71);
588 return ((Data
& 0xF0) ? 1 : 0) + ((Data
& 0x0F) ? 1 : 0);
593 GetFloppyType(UCHAR DriveNumber
)
597 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0x10);
598 Data
= READ_PORT_UCHAR((PUCHAR
)0x71);
600 if (DriveNumber
== 0)
602 else if (DriveNumber
== 1)
612 PUSHORT SegPtr
= (PUSHORT
)0x7A;
613 PUSHORT OfsPtr
= (PUSHORT
)0x78;
615 return (PVOID
)((ULONG_PTR
)(((ULONG
)(*SegPtr
)) << 4) + (ULONG
)(*OfsPtr
));
620 DetectBiosFloppyPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
)
622 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
623 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
624 PCM_FLOPPY_DEVICE_DATA FloppyData
;
626 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
630 ULONG MaxDensity
[6] = {0, 360, 1200, 720, 1440, 2880};
633 for (FloppyNumber
= 0; FloppyNumber
< 2; FloppyNumber
++)
635 FloppyType
= GetFloppyType(FloppyNumber
);
637 if ((FloppyType
> 5) || (FloppyType
== 0))
640 DiskResetController(FloppyNumber
);
642 Ptr
= GetInt1eTable();
644 FldrCreateComponentKey(ControllerKey
,
645 L
"FloppyDiskPeripheral",
648 FloppyDiskPeripheral
,
651 /* Set 'ComponentInformation' value */
652 FldrSetComponentInformation(PeripheralKey
,
657 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
658 sizeof(CM_FLOPPY_DEVICE_DATA
);
659 PartialResourceList
= MmHeapAlloc(Size
);
660 if (PartialResourceList
== NULL
)
662 DPRINTM(DPRINT_HWDETECT
,
663 "Failed to allocate resource descriptor\n");
667 memset(PartialResourceList
, 0, Size
);
668 PartialResourceList
->Version
= 1;
669 PartialResourceList
->Revision
= 1;
670 PartialResourceList
->Count
= 1;
672 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
673 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
674 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
675 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_FLOPPY_DEVICE_DATA
);
677 FloppyData
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
678 FloppyData
->Version
= 2;
679 FloppyData
->Revision
= 0;
680 FloppyData
->MaxDensity
= MaxDensity
[FloppyType
];
681 FloppyData
->MountDensity
= 0;
682 RtlCopyMemory(&FloppyData
->StepRateHeadUnloadTime
,
685 FloppyData
->MaximumTrackValue
= (FloppyType
== 1) ? 39 : 79;
686 FloppyData
->DataTransferRate
= 0;
688 /* Set 'Configuration Data' value */
689 FldrSetConfigurationData(PeripheralKey
, PartialResourceList
, Size
);
690 MmHeapFree(PartialResourceList
);
692 /* Set 'Identifier' value */
693 sprintf(Identifier
, "FLOPPY%ld", FloppyNumber
+ 1);
694 FldrSetIdentifier(PeripheralKey
, Identifier
);
700 DetectBiosFloppyController(PCONFIGURATION_COMPONENT_DATA BusKey
,
701 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 /* Set 'Configuration Data' value */
756 FldrSetConfigurationData(ControllerKey
, PartialResourceList
, Size
);
757 MmHeapFree(PartialResourceList
);
759 if (FloppyCount
) DetectBiosFloppyPeripheral(ControllerKey
);
763 DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA SystemKey
,
764 PCONFIGURATION_COMPONENT_DATA BusKey
)
766 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
767 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
769 PCONFIGURATION_COMPONENT_DATA DiskKey
, ControllerKey
;
775 /* Count the number of visible drives */
776 DiskReportError(FALSE
);
779 /* There are some really broken BIOSes out there. There are even BIOSes
780 * that happily report success when you ask them to read from non-existent
781 * harddisks. So, we set the buffer to known contents first, then try to
782 * read. If the BIOS reports success but the buffer contents haven't
783 * changed then we fail anyway */
784 memset((PVOID
) DISKREADBUFFER
, 0xcd, 512);
785 while (MachDiskReadLogicalSectors(0x80 + DiskCount
, 0ULL, 1, (PVOID
)DISKREADBUFFER
))
788 for (i
= 0; ! Changed
&& i
< 512; i
++)
790 Changed
= ((PUCHAR
)DISKREADBUFFER
)[i
] != 0xcd;
794 DPRINTM(DPRINT_HWDETECT
, "BIOS reports success for disk %d but data didn't change\n",
799 memset((PVOID
) DISKREADBUFFER
, 0xcd, 512);
801 DiskReportError(TRUE
);
802 DPRINTM(DPRINT_HWDETECT
, "BIOS reports %d harddisk%s\n",
803 (int)DiskCount
, (DiskCount
== 1) ? "": "s");
805 FldrCreateComponentKey(BusKey
,
811 DPRINTM(DPRINT_HWDETECT
, "Created key: DiskController\\0\n");
813 /* Set 'ComponentInformation' value */
814 FldrSetComponentInformation(ControllerKey
,
815 Output
| Input
| Removable
,
819 DetectBiosFloppyController(BusKey
, ControllerKey
);
821 /* Allocate resource descriptor */
822 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
823 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
824 PartialResourceList
= MmHeapAlloc(Size
);
825 if (PartialResourceList
== NULL
)
827 DPRINTM(DPRINT_HWDETECT
,
828 "Failed to allocate resource descriptor\n");
832 /* Initialize resource descriptor */
833 memset(PartialResourceList
, 0, Size
);
834 PartialResourceList
->Version
= 1;
835 PartialResourceList
->Revision
= 1;
836 PartialResourceList
->Count
= 1;
837 PartialResourceList
->PartialDescriptors
[0].Type
= CmResourceTypeDeviceSpecific
;
838 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
= 0;
839 PartialResourceList
->PartialDescriptors
[0].Flags
= 0;
840 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
841 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
843 /* Get harddisk Int13 geometry data */
844 Int13Drives
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
845 for (i
= 0; i
< DiskCount
; i
++)
847 if (MachDiskGetDriveGeometry(0x80 + i
, &Geometry
))
849 Int13Drives
[i
].DriveSelect
= 0x80 + i
;
850 Int13Drives
[i
].MaxCylinders
= Geometry
.Cylinders
- 1;
851 Int13Drives
[i
].SectorsPerTrack
= Geometry
.Sectors
;
852 Int13Drives
[i
].MaxHeads
= Geometry
.Heads
- 1;
853 Int13Drives
[i
].NumberDrives
= DiskCount
;
855 DPRINTM(DPRINT_HWDETECT
,
856 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
858 Geometry
.Cylinders
- 1,
861 Geometry
.BytesPerSector
);
865 /* Set 'Configuration Data' value */
866 FldrSetConfigurationData(SystemKey
, PartialResourceList
, Size
);
867 MmHeapFree(PartialResourceList
);
869 /* Create and fill subkey for each harddisk */
870 for (i
= 0; i
< DiskCount
; i
++)
872 /* Create disk key */
873 FldrCreateComponentKey(ControllerKey
,
880 /* Set 'ComponentInformation' value */
881 FldrSetComponentInformation(DiskKey
,
886 /* Set disk values */
887 SetHarddiskConfigurationData(DiskKey
, 0x80 + i
);
888 SetHarddiskIdentifier(DiskKey
, 0x80 + i
);
891 /* Also add one cdrom drive */
892 FsRegisterDevice("multi(0)disk(0)cdrom(224)", &DiskVtbl
);
896 InitializeSerialPort(PUCHAR Port
,
899 WRITE_PORT_UCHAR(Port
+ 3, 0x80); /* set DLAB on */
900 WRITE_PORT_UCHAR(Port
, 0x60); /* speed LO byte */
901 WRITE_PORT_UCHAR(Port
+ 1, 0); /* speed HI byte */
902 WRITE_PORT_UCHAR(Port
+ 3, LineControl
);
903 WRITE_PORT_UCHAR(Port
+ 1, 0); /* set comm and DLAB to 0 */
904 WRITE_PORT_UCHAR(Port
+ 4, 0x09); /* DR int enable */
905 READ_PORT_UCHAR(Port
+ 5); /* clear error bits */
910 DetectSerialMouse(PUCHAR Port
)
917 /* Shutdown mouse or something like that */
918 LineControl
= READ_PORT_UCHAR(Port
+ 4);
919 WRITE_PORT_UCHAR(Port
+ 4, (LineControl
& ~0x02) | 0x01);
920 StallExecutionProcessor(100000);
924 * Maybe there is no serial port although BIOS reported one (this
925 * is the case on Apple hardware), or the serial port is misbehaving,
926 * therefore we must give up after some time.
929 while (READ_PORT_UCHAR(Port
+ 5) & 0x01)
932 return MOUSE_TYPE_NONE
;
933 READ_PORT_UCHAR(Port
);
937 * Send modem control with 'Data Terminal Ready', 'Request To Send' and
938 * 'Output Line 2' message. This enables mouse to identify.
940 WRITE_PORT_UCHAR(Port
+ 4, 0x0b);
942 /* Wait 10 milliseconds for the mouse getting ready */
943 StallExecutionProcessor(10000);
945 /* Read first four bytes, which contains Microsoft Mouse signs */
947 for (i
= 0; i
< 4; i
++)
949 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
951 StallExecutionProcessor(1000);
954 return MOUSE_TYPE_NONE
;
956 Buffer
[i
] = READ_PORT_UCHAR(Port
);
959 DPRINTM(DPRINT_HWDETECT
,
960 "Mouse data: %x %x %x %x\n",
961 Buffer
[0],Buffer
[1],Buffer
[2],Buffer
[3]);
963 /* Check that four bytes for signs */
964 for (i
= 0; i
< 4; ++i
)
966 if (Buffer
[i
] == 'B')
968 /* Sign for Microsoft Ballpoint */
969 // DbgPrint("Microsoft Ballpoint device detected\n");
970 // DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET\n");
971 return MOUSE_TYPE_NONE
;
973 else if (Buffer
[i
] == 'M')
975 /* Sign for Microsoft Mouse protocol followed by button specifier */
979 return MOUSE_TYPE_NONE
;
982 switch (Buffer
[i
+ 1])
985 DPRINTM(DPRINT_HWDETECT
,
986 "Microsoft Mouse with 3-buttons detected\n");
987 return MOUSE_TYPE_LOGITECH
;
990 DPRINTM(DPRINT_HWDETECT
,
991 "Microsoft Wheel Mouse detected\n");
992 return MOUSE_TYPE_WHEELZ
;
996 DPRINTM(DPRINT_HWDETECT
,
997 "Microsoft Mouse with 2-buttons detected\n");
998 return MOUSE_TYPE_MICROSOFT
;
1003 return MOUSE_TYPE_NONE
;
1008 GetSerialMousePnpId(PUCHAR Port
, char *Buffer
)
1015 WRITE_PORT_UCHAR(Port
+ 4, 0x09);
1017 /* Wait 10 milliseconds for the mouse getting ready */
1018 StallExecutionProcessor(10000);
1020 WRITE_PORT_UCHAR(Port
+ 4, 0x0b);
1022 StallExecutionProcessor(10000);
1027 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
1029 StallExecutionProcessor(1000);
1037 c
= READ_PORT_UCHAR(Port
);
1038 if (c
== 0x08 || c
== 0x28)
1048 while (((READ_PORT_UCHAR(Port
+ 5) & 1) == 0) && (TimeOut
> 0))
1050 StallExecutionProcessor(1000);
1055 c
= READ_PORT_UCHAR(Port
);
1068 DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
,
1071 CM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1073 CHAR Identifier
[256];
1074 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
1081 DPRINTM(DPRINT_HWDETECT
,
1082 "DetectSerialPointerPeripheral()\n");
1086 InitializeSerialPort(Base
, 2);
1087 MouseType
= DetectSerialMouse(Base
);
1089 if (MouseType
!= MOUSE_TYPE_NONE
)
1091 Length
= GetSerialMousePnpId(Base
, Buffer
);
1092 DPRINTM(DPRINT_HWDETECT
,
1093 "PnP ID length: %u\n",
1098 /* Convert PnP sting to ASCII */
1099 if (Buffer
[0] == 0x08)
1101 for (i
= 0; i
< Length
; i
++)
1106 DPRINTM(DPRINT_HWDETECT
,
1107 "PnP ID string: %s\n",
1110 /* Copy PnpId string */
1111 for (i
= 0; i
< 7; i
++)
1113 Identifier
[i
] = Buffer
[3+i
];
1115 memcpy(&Identifier
[7],
1119 /* Skip device serial number */
1121 if (Buffer
[i
] == '\\')
1123 for (j
= ++i
; i
< Length
; ++i
)
1125 if (Buffer
[i
] == '\\')
1132 /* Skip PnP class */
1133 if (Buffer
[i
] == '\\')
1135 for (j
= ++i
; i
< Length
; ++i
)
1137 if (Buffer
[i
] == '\\')
1145 /* Skip compatible PnP Id */
1146 if (Buffer
[i
] == '\\')
1148 for (j
= ++i
; i
< Length
; ++i
)
1150 if (Buffer
[i
] == '\\')
1153 if (Buffer
[j
] == '*')
1159 /* Get product description */
1160 if (Buffer
[i
] == '\\')
1162 for (j
= ++i
; i
< Length
; ++i
)
1164 if (Buffer
[i
] == ';')
1171 for (k
= 0; k
< i
- j
; k
++)
1173 Identifier
[k
+ 10] = Buffer
[k
+ j
];
1175 Identifier
[10 + (i
-j
)] = 0;
1179 DPRINTM(DPRINT_HWDETECT
,
1180 "Identifier string: %s\n",
1184 if (Length
== 0 || strlen(Identifier
) < 11)
1188 case MOUSE_TYPE_LOGITECH
:
1190 "LOGITECH SERIAL MOUSE");
1193 case MOUSE_TYPE_WHEELZ
:
1195 "MICROSOFT SERIAL MOUSE WITH WHEEL");
1198 case MOUSE_TYPE_MICROSOFT
:
1201 "MICROSOFT SERIAL MOUSE");
1206 /* Create 'PointerPeripheral' key */
1207 FldrCreateComponentKey(ControllerKey
,
1208 L
"PointerPeripheral",
1213 DPRINTM(DPRINT_HWDETECT
,
1214 "Created key: PointerPeripheral\\0\n");
1216 /* Set 'ComponentInformation' value */
1217 FldrSetComponentInformation(PeripheralKey
,
1222 /* Set 'Configuration Data' value */
1223 memset(&PartialResourceList
, 0, sizeof(CM_PARTIAL_RESOURCE_LIST
));
1224 PartialResourceList
.Version
= 1;
1225 PartialResourceList
.Revision
= 1;
1226 PartialResourceList
.Count
= 0;
1228 FldrSetConfigurationData(PeripheralKey
,
1229 &PartialResourceList
,
1230 sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1231 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1233 /* Set 'Identifier' value */
1234 FldrSetIdentifier(PeripheralKey
, Identifier
);
1240 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
1242 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1243 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1244 PCM_SERIAL_DEVICE_DATA SerialDeviceData
;
1245 ULONG Irq
[4] = {4, 3, 4, 3};
1249 ULONG ControllerNumber
= 0;
1250 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1254 DPRINTM(DPRINT_HWDETECT
, "DetectSerialPorts()\n");
1256 ControllerNumber
= 0;
1257 BasePtr
= (PUSHORT
)0x400;
1258 for (i
= 0; i
< 4; i
++, BasePtr
++)
1260 Base
= (ULONG
)*BasePtr
;
1264 DPRINTM(DPRINT_HWDETECT
,
1265 "Found COM%u port at 0x%x\n",
1269 /* Create controller key */
1270 FldrCreateComponentKey(BusKey
,
1271 L
"SerialController",
1277 /* Set 'ComponentInformation' value */
1278 FldrSetComponentInformation(ControllerKey
,
1279 Output
| Input
| ConsoleIn
| ConsoleOut
,
1283 /* Build full device descriptor */
1284 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
1285 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) +
1286 sizeof(CM_SERIAL_DEVICE_DATA
);
1287 PartialResourceList
= MmHeapAlloc(Size
);
1288 if (PartialResourceList
== NULL
)
1290 DPRINTM(DPRINT_HWDETECT
,
1291 "Failed to allocate resource descriptor\n");
1294 memset(PartialResourceList
, 0, Size
);
1296 /* Initialize resource descriptor */
1297 PartialResourceList
->Version
= 1;
1298 PartialResourceList
->Revision
= 1;
1299 PartialResourceList
->Count
= 3;
1302 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1303 PartialDescriptor
->Type
= CmResourceTypePort
;
1304 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1305 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1306 PartialDescriptor
->u
.Port
.Start
.LowPart
= Base
;
1307 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1308 PartialDescriptor
->u
.Port
.Length
= 7;
1311 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
1312 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
1313 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1314 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1315 PartialDescriptor
->u
.Interrupt
.Level
= Irq
[i
];
1316 PartialDescriptor
->u
.Interrupt
.Vector
= 0;
1317 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1319 /* Set serial data (device specific) */
1320 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
1321 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
1322 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1323 PartialDescriptor
->Flags
= 0;
1324 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_SERIAL_DEVICE_DATA
);
1327 (PCM_SERIAL_DEVICE_DATA
)&PartialResourceList
->PartialDescriptors
[3];
1328 SerialDeviceData
->BaudClock
= 1843200; /* UART Clock frequency (Hertz) */
1330 /* Set 'Configuration Data' value */
1331 FldrSetConfigurationData(ControllerKey
, PartialResourceList
, Size
);
1332 MmHeapFree(PartialResourceList
);
1334 /* Set 'Identifier' value */
1335 sprintf(Buffer
, "COM%ld", i
+ 1);
1336 FldrSetIdentifier(ControllerKey
, Buffer
);
1337 DPRINTM(DPRINT_HWDETECT
,
1338 "Created value: Identifier %s\n",
1341 if (!Rs232PortInUse(Base
))
1343 /* Detect serial mouse */
1344 DetectSerialPointerPeripheral(ControllerKey
, UlongToPtr(Base
));
1353 DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey
)
1355 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1356 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1357 ULONG Irq
[3] = {7, 5, (ULONG
)-1};
1359 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1362 ULONG ControllerNumber
;
1366 DPRINTM(DPRINT_HWDETECT
, "DetectParallelPorts() called\n");
1368 ControllerNumber
= 0;
1369 BasePtr
= (PUSHORT
)0x408;
1370 for (i
= 0; i
< 3; i
++, BasePtr
++)
1372 Base
= (ULONG
)*BasePtr
;
1376 DPRINTM(DPRINT_HWDETECT
,
1377 "Parallel port %u: %x\n",
1381 /* Create controller key */
1382 FldrCreateComponentKey(BusKey
,
1383 L
"ParallelController",
1389 /* Set 'ComponentInformation' value */
1390 FldrSetComponentInformation(ControllerKey
,
1395 /* Build full device descriptor */
1396 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
);
1397 if (Irq
[i
] != (ULONG
)-1)
1398 Size
+= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1400 PartialResourceList
= MmHeapAlloc(Size
);
1401 if (PartialResourceList
== NULL
)
1403 DPRINTM(DPRINT_HWDETECT
,
1404 "Failed to allocate resource descriptor\n");
1407 memset(PartialResourceList
, 0, Size
);
1409 /* Initialize resource descriptor */
1410 PartialResourceList
->Version
= 1;
1411 PartialResourceList
->Revision
= 1;
1412 PartialResourceList
->Count
= (Irq
[i
] != (ULONG
)-1) ? 2 : 1;
1415 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1416 PartialDescriptor
->Type
= CmResourceTypePort
;
1417 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1418 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1419 PartialDescriptor
->u
.Port
.Start
.LowPart
= Base
;
1420 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1421 PartialDescriptor
->u
.Port
.Length
= 3;
1424 if (Irq
[i
] != (ULONG
)-1)
1426 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
1427 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
1428 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1429 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1430 PartialDescriptor
->u
.Interrupt
.Level
= Irq
[i
];
1431 PartialDescriptor
->u
.Interrupt
.Vector
= 0;
1432 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1435 /* Set 'Configuration Data' value */
1436 FldrSetConfigurationData(ControllerKey
, PartialResourceList
, Size
);
1437 MmHeapFree(PartialResourceList
);
1439 /* Set 'Identifier' value */
1440 sprintf(Buffer
, "PARALLEL%ld", i
+ 1);
1441 FldrSetIdentifier(ControllerKey
, Buffer
);
1442 DPRINTM(DPRINT_HWDETECT
,
1443 "Created value: Identifier %s\n",
1449 DPRINTM(DPRINT_HWDETECT
, "DetectParallelPorts() done\n");
1454 DetectKeyboardDevice(VOID
)
1459 BOOLEAN Result
= TRUE
;
1461 /* Identify device */
1462 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
,
1465 /* Wait for reply */
1466 for (Loops
= 0; Loops
< 100; Loops
++)
1468 StallExecutionProcessor(10000);
1469 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1470 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1474 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
1476 /* PC/XT keyboard or no keyboard */
1480 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1481 if (Scancode
!= 0xFA)
1483 /* No ACK received */
1487 StallExecutionProcessor(10000);
1489 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1490 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
1492 /* Found AT keyboard */
1496 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1497 if (Scancode
!= 0xAB)
1499 /* No 0xAB received */
1503 StallExecutionProcessor(10000);
1505 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1506 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) == 0)
1508 /* No byte in buffer */
1512 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1513 if (Scancode
!= 0x41)
1515 /* No 0x41 received */
1519 /* Found MF-II keyboard */
1525 DetectKeyboardPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey
)
1527 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1528 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1529 PCM_KEYBOARD_DEVICE_DATA KeyboardData
;
1530 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
1533 /* HACK: don't call DetectKeyboardDevice() as it fails in Qemu 0.8.2 */
1534 if (TRUE
|| DetectKeyboardDevice())
1536 /* Create controller key */
1537 FldrCreateComponentKey(ControllerKey
,
1538 L
"KeyboardPeripheral",
1543 DPRINTM(DPRINT_HWDETECT
, "Created key: KeyboardPeripheral\\0\n");
1545 /* Set 'ComponentInformation' value */
1546 FldrSetComponentInformation(PeripheralKey
,
1551 /* Set 'Configuration Data' value */
1552 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
1553 sizeof(CM_KEYBOARD_DEVICE_DATA
);
1554 PartialResourceList
= MmHeapAlloc(Size
);
1555 if (PartialResourceList
== NULL
)
1557 DPRINTM(DPRINT_HWDETECT
,
1558 "Failed to allocate resource descriptor\n");
1562 /* Initialize resource descriptor */
1563 memset(PartialResourceList
, 0, Size
);
1564 PartialResourceList
->Version
= 1;
1565 PartialResourceList
->Revision
= 1;
1566 PartialResourceList
->Count
= 1;
1568 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1569 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
1570 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1571 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(CM_KEYBOARD_DEVICE_DATA
);
1573 KeyboardData
= (PCM_KEYBOARD_DEVICE_DATA
)(PartialDescriptor
+ 1);
1574 KeyboardData
->Version
= 1;
1575 KeyboardData
->Revision
= 1;
1576 KeyboardData
->Type
= 4;
1577 KeyboardData
->Subtype
= 0;
1578 KeyboardData
->KeyboardFlags
= 0x20;
1580 /* Set 'Configuration Data' value */
1581 FldrSetConfigurationData(PeripheralKey
, PartialResourceList
, Size
);
1582 MmHeapFree(PartialResourceList
);
1584 /* Set 'Identifier' value */
1585 FldrSetIdentifier(PeripheralKey
, "PCAT_ENHANCED");
1591 DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey
)
1593 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1594 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1595 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1598 /* Create controller key */
1599 FldrCreateComponentKey(BusKey
,
1600 L
"KeyboardController",
1605 DPRINTM(DPRINT_HWDETECT
, "Created key: KeyboardController\\0\n");
1607 /* Set 'ComponentInformation' value */
1608 FldrSetComponentInformation(ControllerKey
,
1613 /* Set 'Configuration Data' value */
1614 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
1615 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1616 PartialResourceList
= MmHeapAlloc(Size
);
1617 if (PartialResourceList
== NULL
)
1619 DPRINTM(DPRINT_HWDETECT
,
1620 "Failed to allocate resource descriptor\n");
1624 /* Initialize resource descriptor */
1625 memset(PartialResourceList
, 0, Size
);
1626 PartialResourceList
->Version
= 1;
1627 PartialResourceList
->Revision
= 1;
1628 PartialResourceList
->Count
= 3;
1631 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
1632 PartialDescriptor
->Type
= CmResourceTypeInterrupt
;
1633 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
1634 PartialDescriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1635 PartialDescriptor
->u
.Interrupt
.Level
= 1;
1636 PartialDescriptor
->u
.Interrupt
.Vector
= 0;
1637 PartialDescriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1639 /* Set IO Port 0x60 */
1640 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
1641 PartialDescriptor
->Type
= CmResourceTypePort
;
1642 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1643 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1644 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x60;
1645 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1646 PartialDescriptor
->u
.Port
.Length
= 1;
1648 /* Set IO Port 0x64 */
1649 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[2];
1650 PartialDescriptor
->Type
= CmResourceTypePort
;
1651 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1652 PartialDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
1653 PartialDescriptor
->u
.Port
.Start
.LowPart
= 0x64;
1654 PartialDescriptor
->u
.Port
.Start
.HighPart
= 0x0;
1655 PartialDescriptor
->u
.Port
.Length
= 1;
1657 /* Set 'Configuration Data' value */
1658 FldrSetConfigurationData(ControllerKey
, PartialResourceList
, Size
);
1659 MmHeapFree(PartialResourceList
);
1661 DetectKeyboardPeripheral(ControllerKey
);
1666 PS2ControllerWait(VOID
)
1671 for (Timeout
= 0; Timeout
< CONTROLLER_TIMEOUT
; Timeout
++)
1673 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1674 if ((Status
& CONTROLLER_STATUS_INPUT_BUFFER_FULL
) == 0)
1677 /* Sleep for one millisecond */
1678 StallExecutionProcessor(1000);
1684 DetectPS2AuxPort(VOID
)
1687 /* Current detection is too unreliable. Just do as if
1688 * the PS/2 aux port is always present
1695 /* Put the value 0x5A in the output buffer using the
1696 * "WriteAuxiliary Device Output Buffer" command (0xD3).
1697 * Poll the Status Register for a while to see if the value really turns up
1698 * in the Data Register. If the KEYBOARD_STATUS_MOUSE_OBF bit is also set
1699 * to 1 in the Status Register, we assume this controller has an
1700 * Auxiliary Port (a.k.a. Mouse Port).
1702 PS2ControllerWait();
1703 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_CONTROL
,
1704 CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER
);
1705 PS2ControllerWait();
1707 /* 0x5A is a random dummy value */
1708 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
,
1711 for (Loops
= 0; Loops
< 10; Loops
++)
1713 StallExecutionProcessor(10000);
1714 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1715 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1719 READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1721 return (Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
);
1727 DetectPS2AuxDevice(VOID
)
1732 BOOLEAN Result
= TRUE
;
1734 PS2ControllerWait();
1735 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_CONTROL
,
1736 CONTROLLER_COMMAND_WRITE_MOUSE
);
1737 PS2ControllerWait();
1739 /* Identify device */
1740 WRITE_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
,
1743 /* Wait for reply */
1744 for (Loops
= 0; Loops
< 100; Loops
++)
1746 StallExecutionProcessor(10000);
1747 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1748 if ((Status
& CONTROLLER_STATUS_OUTPUT_BUFFER_FULL
) != 0)
1752 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1753 if ((Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
) == 0)
1756 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1757 if (Scancode
!= 0xFA)
1760 StallExecutionProcessor(10000);
1762 Status
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_STATUS
);
1763 if ((Status
& CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL
) == 0)
1766 Scancode
= READ_PORT_UCHAR((PUCHAR
)CONTROLLER_REGISTER_DATA
);
1767 if (Scancode
!= 0x00)
1775 DetectPS2Mouse(PCONFIGURATION_COMPONENT_DATA BusKey
)
1777 CM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1778 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1779 PCONFIGURATION_COMPONENT_DATA PeripheralKey
;
1781 if (DetectPS2AuxPort())
1783 DPRINTM(DPRINT_HWDETECT
, "Detected PS2 port\n");
1785 /* Create controller key */
1786 FldrCreateComponentKey(BusKey
,
1787 L
"PointerController",
1792 DPRINTM(DPRINT_HWDETECT
, "Created key: PointerController\\0\n");
1794 /* Set 'ComponentInformation' value */
1795 FldrSetComponentInformation(ControllerKey
,
1800 memset(&PartialResourceList
, 0, sizeof(CM_PARTIAL_RESOURCE_LIST
));
1802 /* Initialize resource descriptor */
1803 PartialResourceList
.Version
= 1;
1804 PartialResourceList
.Revision
= 1;
1805 PartialResourceList
.Count
= 1;
1808 PartialResourceList
.PartialDescriptors
[0].Type
= CmResourceTypeInterrupt
;
1809 PartialResourceList
.PartialDescriptors
[0].ShareDisposition
= CmResourceShareUndetermined
;
1810 PartialResourceList
.PartialDescriptors
[0].Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
1811 PartialResourceList
.PartialDescriptors
[0].u
.Interrupt
.Level
= 12;
1812 PartialResourceList
.PartialDescriptors
[0].u
.Interrupt
.Vector
= 0;
1813 PartialResourceList
.PartialDescriptors
[0].u
.Interrupt
.Affinity
= 0xFFFFFFFF;
1815 /* Set 'Configuration Data' value */
1816 FldrSetConfigurationData(ControllerKey
,
1817 &PartialResourceList
,
1818 sizeof(CM_PARTIAL_RESOURCE_LIST
));
1820 if (DetectPS2AuxDevice())
1822 DPRINTM(DPRINT_HWDETECT
, "Detected PS2 mouse\n");
1824 /* Create peripheral key */
1825 FldrCreateComponentKey(ControllerKey
,
1826 L
"PointerPeripheral",
1831 DPRINTM(DPRINT_HWDETECT
, "Created key: PointerPeripheral\\0\n");
1833 /* Set 'ComponentInformation' value */
1834 FldrSetComponentInformation(PeripheralKey
,
1839 /* Initialize resource descriptor */
1840 memset(&PartialResourceList
, 0, sizeof(CM_PARTIAL_RESOURCE_LIST
));
1841 PartialResourceList
.Version
= 1;
1842 PartialResourceList
.Revision
= 1;
1843 PartialResourceList
.Count
= 0;
1845 /* Set 'Configuration Data' value */
1846 FldrSetConfigurationData(PeripheralKey
,
1847 &PartialResourceList
,
1848 sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1849 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1851 /* Set 'Identifier' value */
1852 FldrSetIdentifier(PeripheralKey
, "MICROSOFT PS2 MOUSE");
1859 DetectDisplayController(PCONFIGURATION_COMPONENT_DATA BusKey
)
1862 PCONFIGURATION_COMPONENT_DATA ControllerKey
;
1865 FldrCreateComponentKey(BusKey
,
1866 L
"DisplayController",
1871 DPRINTM(DPRINT_HWDETECT
, "Created key: DisplayController\\0\n");
1873 /* Set 'ComponentInformation' value */
1874 FldrSetComponentInformation(ControllerKey
,
1879 /* FIXME: Set 'ComponentInformation' value */
1881 VesaVersion
= BiosIsVesaSupported();
1882 if (VesaVersion
!= 0)
1884 DPRINTM(DPRINT_HWDETECT
,
1885 "VESA version %c.%c\n",
1886 (VesaVersion
>> 8) + '0',
1887 (VesaVersion
& 0xFF) + '0');
1891 DPRINTM(DPRINT_HWDETECT
,
1892 "VESA not supported\n");
1895 if (VesaVersion
>= 0x0200)
1906 /* Set 'Identifier' value */
1907 FldrSetIdentifier(ControllerKey
, Buffer
);
1909 /* FIXME: Add display peripheral (monitor) data */
1914 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
1916 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
1917 PCONFIGURATION_COMPONENT_DATA BusKey
;
1920 /* Create new bus key */
1921 FldrCreateComponentKey(SystemKey
,
1922 L
"MultifunctionAdapter",
1925 MultiFunctionAdapter
,
1928 /* Set 'Component Information' value similar to my NT4 box */
1929 FldrSetComponentInformation(BusKey
,
1934 /* Increment bus number */
1937 /* Set 'Identifier' value */
1938 FldrSetIdentifier(BusKey
, "ISA");
1940 /* Set 'Configuration Data' value */
1941 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
1942 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1943 PartialResourceList
= MmHeapAlloc(Size
);
1944 if (PartialResourceList
== NULL
)
1946 DPRINTM(DPRINT_HWDETECT
,
1947 "Failed to allocate resource descriptor\n");
1951 /* Initialize resource descriptor */
1952 memset(PartialResourceList
, 0, Size
);
1953 PartialResourceList
->Version
= 1;
1954 PartialResourceList
->Revision
= 1;
1955 PartialResourceList
->Count
= 0;
1957 /* Set 'Configuration Data' value */
1958 FldrSetConfigurationData(BusKey
, PartialResourceList
, Size
);
1959 MmHeapFree(PartialResourceList
);
1961 /* Detect ISA/BIOS devices */
1962 DetectBiosDisks(SystemKey
, BusKey
);
1964 DetectSerialPorts(BusKey
);
1966 DetectParallelPorts(BusKey
);
1968 DetectKeyboardController(BusKey
);
1970 DetectPS2Mouse(BusKey
);
1972 DetectDisplayController(BusKey
);
1974 /* FIXME: Detect more ISA devices */
1978 PCONFIGURATION_COMPONENT_DATA
1981 PCONFIGURATION_COMPONENT_DATA SystemKey
;
1982 ULONG BusNumber
= 0;
1984 DPRINTM(DPRINT_HWDETECT
, "DetectHardware()\n");
1986 /* Create the 'System' key */
1987 FldrCreateSystemKey(&SystemKey
);
1989 /* Set empty component information */
1990 FldrSetComponentInformation(SystemKey
,
1996 DetectPciBios(SystemKey
, &BusNumber
);
1997 DetectApmBios(SystemKey
, &BusNumber
);
1998 DetectPnpBios(SystemKey
, &BusNumber
);
1999 DetectIsaBios(SystemKey
, &BusNumber
);
2000 DetectAcpiBios(SystemKey
, &BusNumber
);
2002 DPRINTM(DPRINT_HWDETECT
, "DetectHardware() Done\n");