Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenhardware.c
Go to the documentation of this file.
00001 /* 00002 * FreeLoader 00003 * 00004 * Copyright (C) 2003, 2004 Eric Kohl 00005 * Copyright (C) 2009 Hervé Poussineau 00006 * 00007 * This program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License along 00018 * with this program; if not, write to the Free Software Foundation, Inc., 00019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00020 */ 00021 00022 #include <freeldr.h> 00023 00024 #define NDEBUG 00025 #include <debug.h> 00026 00027 #define MILLISEC (10) 00028 #define PRECISION (8) 00029 00030 #define HZ (100) 00031 #define CLOCK_TICK_RATE (1193182) 00032 #define LATCH (CLOCK_TICK_RATE / HZ) 00033 00034 00035 /* No Mouse */ 00036 #define MOUSE_TYPE_NONE 0 00037 /* Microsoft Mouse with 2 buttons */ 00038 #define MOUSE_TYPE_MICROSOFT 1 00039 /* Logitech Mouse with 3 buttons */ 00040 #define MOUSE_TYPE_LOGITECH 2 00041 /* Microsoft Wheel Mouse (aka Z Mouse) */ 00042 #define MOUSE_TYPE_WHEELZ 3 00043 /* Mouse Systems Mouse */ 00044 #define MOUSE_TYPE_MOUSESYSTEMS 4 00045 00046 00047 /* PS2 stuff */ 00048 00049 /* Controller registers. */ 00050 #define CONTROLLER_REGISTER_STATUS 0x64 00051 #define CONTROLLER_REGISTER_CONTROL 0x64 00052 #define CONTROLLER_REGISTER_DATA 0x60 00053 00054 /* Controller commands. */ 00055 #define CONTROLLER_COMMAND_READ_MODE 0x20 00056 #define CONTROLLER_COMMAND_WRITE_MODE 0x60 00057 #define CONTROLLER_COMMAND_GET_VERSION 0xA1 00058 #define CONTROLLER_COMMAND_MOUSE_DISABLE 0xA7 00059 #define CONTROLLER_COMMAND_MOUSE_ENABLE 0xA8 00060 #define CONTROLLER_COMMAND_TEST_MOUSE 0xA9 00061 #define CONTROLLER_COMMAND_SELF_TEST 0xAA 00062 #define CONTROLLER_COMMAND_KEYBOARD_TEST 0xAB 00063 #define CONTROLLER_COMMAND_KEYBOARD_DISABLE 0xAD 00064 #define CONTROLLER_COMMAND_KEYBOARD_ENABLE 0xAE 00065 #define CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER 0xD3 00066 #define CONTROLLER_COMMAND_WRITE_MOUSE 0xD4 00067 00068 /* Controller status */ 00069 #define CONTROLLER_STATUS_OUTPUT_BUFFER_FULL 0x01 00070 #define CONTROLLER_STATUS_INPUT_BUFFER_FULL 0x02 00071 #define CONTROLLER_STATUS_SELF_TEST 0x04 00072 #define CONTROLLER_STATUS_COMMAND 0x08 00073 #define CONTROLLER_STATUS_UNLOCKED 0x10 00074 #define CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL 0x20 00075 #define CONTROLLER_STATUS_GENERAL_TIMEOUT 0x40 00076 #define CONTROLLER_STATUS_PARITY_ERROR 0x80 00077 #define AUX_STATUS_OUTPUT_BUFFER_FULL (CONTROLLER_STATUS_OUTPUT_BUFFER_FULL | \ 00078 CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) 00079 00080 /* Timeout in ms for sending to keyboard controller. */ 00081 #define CONTROLLER_TIMEOUT 250 00082 00083 DBG_DEFAULT_CHANNEL(HWDETECT); 00084 00085 static unsigned int delay_count = 1; 00086 00087 extern UCHAR PcBiosDiskCount; 00088 00089 PCHAR 00090 GetHarddiskIdentifier( 00091 UCHAR DriveNumber); 00092 00093 VOID 00094 HwInitializeBiosDisks(VOID); 00095 00096 /* FUNCTIONS ****************************************************************/ 00097 00098 00099 static VOID 00100 __StallExecutionProcessor(ULONG Loops) 00101 { 00102 register volatile unsigned int i; 00103 for (i = 0; i < Loops; i++); 00104 } 00105 00106 00107 VOID StallExecutionProcessor(ULONG Microseconds) 00108 { 00109 ULONGLONG LoopCount = ((ULONGLONG)delay_count * (ULONGLONG)Microseconds) / 1000ULL; 00110 __StallExecutionProcessor((ULONG)LoopCount); 00111 } 00112 00113 00114 static ULONG 00115 Read8254Timer(VOID) 00116 { 00117 ULONG Count; 00118 00119 WRITE_PORT_UCHAR((PUCHAR)0x43, 0x00); 00120 Count = READ_PORT_UCHAR((PUCHAR)0x40); 00121 Count |= READ_PORT_UCHAR((PUCHAR)0x40) << 8; 00122 00123 return Count; 00124 } 00125 00126 00127 static VOID 00128 WaitFor8254Wraparound(VOID) 00129 { 00130 ULONG CurCount; 00131 ULONG PrevCount = ~0; 00132 LONG Delta; 00133 00134 CurCount = Read8254Timer(); 00135 00136 do 00137 { 00138 PrevCount = CurCount; 00139 CurCount = Read8254Timer(); 00140 Delta = CurCount - PrevCount; 00141 00142 /* 00143 * This limit for delta seems arbitrary, but it isn't, it's 00144 * slightly above the level of error a buggy Mercury/Neptune 00145 * chipset timer can cause. 00146 */ 00147 } 00148 while (Delta < 300); 00149 } 00150 00151 00152 VOID 00153 HalpCalibrateStallExecution(VOID) 00154 { 00155 ULONG i; 00156 ULONG calib_bit; 00157 ULONG CurCount; 00158 00159 /* Initialise timer interrupt with MILLISECOND ms interval */ 00160 WRITE_PORT_UCHAR((PUCHAR)0x43, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */ 00161 WRITE_PORT_UCHAR((PUCHAR)0x40, LATCH & 0xff); /* LSB */ 00162 WRITE_PORT_UCHAR((PUCHAR)0x40, LATCH >> 8); /* MSB */ 00163 00164 /* Stage 1: Coarse calibration */ 00165 00166 WaitFor8254Wraparound(); 00167 00168 delay_count = 1; 00169 00170 do { 00171 delay_count <<= 1; /* Next delay count to try */ 00172 00173 WaitFor8254Wraparound(); 00174 00175 __StallExecutionProcessor(delay_count); /* Do the delay */ 00176 00177 CurCount = Read8254Timer(); 00178 } while (CurCount > LATCH / 2); 00179 00180 delay_count >>= 1; /* Get bottom value for delay */ 00181 00182 /* Stage 2: Fine calibration */ 00183 00184 calib_bit = delay_count; /* Which bit are we going to test */ 00185 00186 for(i=0;i<PRECISION;i++) { 00187 calib_bit >>= 1; /* Next bit to calibrate */ 00188 if(!calib_bit) break; /* If we have done all bits, stop */ 00189 00190 delay_count |= calib_bit; /* Set the bit in delay_count */ 00191 00192 WaitFor8254Wraparound(); 00193 00194 __StallExecutionProcessor(delay_count); /* Do the delay */ 00195 00196 CurCount = Read8254Timer(); 00197 if (CurCount <= LATCH / 2) /* If a tick has passed, turn the */ 00198 delay_count &= ~calib_bit; /* calibrated bit back off */ 00199 } 00200 00201 /* We're finished: Do the finishing touches */ 00202 delay_count /= (MILLISEC / 2); /* Calculate delay_count for 1ms */ 00203 } 00204 00205 static VOID 00206 DetectPnpBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber) 00207 { 00208 PCM_PARTIAL_RESOURCE_LIST PartialResourceList; 00209 PCM_PNP_BIOS_DEVICE_NODE DeviceNode; 00210 PCM_PNP_BIOS_INSTALLATION_CHECK InstData; 00211 PCONFIGURATION_COMPONENT_DATA BusKey; 00212 ULONG x; 00213 ULONG NodeSize = 0; 00214 ULONG NodeCount = 0; 00215 UCHAR NodeNumber; 00216 ULONG FoundNodeCount; 00217 int i; 00218 ULONG PnpBufferSize; 00219 ULONG Size; 00220 char *Ptr; 00221 00222 InstData = (PCM_PNP_BIOS_INSTALLATION_CHECK)PnpBiosSupported(); 00223 if (InstData == NULL || strncmp((CHAR*)InstData->Signature, "$PnP", 4)) 00224 { 00225 TRACE("PnP-BIOS not supported\n"); 00226 return; 00227 } 00228 00229 TRACE("PnP-BIOS supported\n"); 00230 TRACE("Signature '%c%c%c%c'\n", 00231 InstData->Signature[0], InstData->Signature[1], 00232 InstData->Signature[2], InstData->Signature[3]); 00233 00234 x = PnpBiosGetDeviceNodeCount(&NodeSize, &NodeCount); 00235 if (x == 0x82) 00236 { 00237 TRACE("PnP-BIOS function 'Get Number of System Device Nodes' not supported\n"); 00238 return; 00239 } 00240 00241 NodeCount &= 0xFF; // needed since some fscked up BIOSes return 00242 // wrong info (e.g. Mac Virtual PC) 00243 // e.g. look: http://my.execpc.com/~geezer/osd/pnp/pnp16.c 00244 if (x != 0 || NodeSize == 0 || NodeCount == 0) 00245 { 00246 ERR("PnP-BIOS failed to enumerate device nodes\n"); 00247 return; 00248 } 00249 TRACE("MaxNodeSize %u NodeCount %u\n", NodeSize, NodeCount); 00250 TRACE("Estimated buffer size %u\n", NodeSize * NodeCount); 00251 00252 /* Set 'Configuration Data' value */ 00253 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) 00254 + sizeof(CM_PNP_BIOS_INSTALLATION_CHECK) + (NodeSize * NodeCount); 00255 PartialResourceList = MmHeapAlloc(Size); 00256 if (PartialResourceList == NULL) 00257 { 00258 ERR("Failed to allocate resource descriptor\n"); 00259 return; 00260 } 00261 memset(PartialResourceList, 0, Size); 00262 00263 /* Initialize resource descriptor */ 00264 PartialResourceList->Version = 1; 00265 PartialResourceList->Revision = 1; 00266 PartialResourceList->Count = 1; 00267 PartialResourceList->PartialDescriptors[0].Type = 00268 CmResourceTypeDeviceSpecific; 00269 PartialResourceList->PartialDescriptors[0].ShareDisposition = 00270 CmResourceShareUndetermined; 00271 00272 /* The buffer starts after PartialResourceList->PartialDescriptors[0] */ 00273 Ptr = (char *)(PartialResourceList + 1); 00274 00275 /* Set instalation check data */ 00276 memcpy (Ptr, InstData, sizeof(CM_PNP_BIOS_INSTALLATION_CHECK)); 00277 Ptr += sizeof(CM_PNP_BIOS_INSTALLATION_CHECK); 00278 00279 /* Copy device nodes */ 00280 FoundNodeCount = 0; 00281 PnpBufferSize = sizeof(CM_PNP_BIOS_INSTALLATION_CHECK); 00282 for (i = 0; i < 0xFF; i++) 00283 { 00284 NodeNumber = (UCHAR)i; 00285 00286 x = PnpBiosGetDeviceNode(&NodeNumber, (PVOID)DISKREADBUFFER); 00287 if (x == 0) 00288 { 00289 DeviceNode = (PCM_PNP_BIOS_DEVICE_NODE)DISKREADBUFFER; 00290 00291 TRACE("Node: %u Size %u (0x%x)\n", 00292 DeviceNode->Node, 00293 DeviceNode->Size, 00294 DeviceNode->Size); 00295 00296 if (PnpBufferSize + DeviceNode->Size > Size) 00297 { 00298 ERR("Buffer too small!\n"); 00299 break; 00300 } 00301 00302 memcpy (Ptr, 00303 DeviceNode, 00304 DeviceNode->Size); 00305 00306 Ptr += DeviceNode->Size; 00307 PnpBufferSize += DeviceNode->Size; 00308 00309 FoundNodeCount++; 00310 if (FoundNodeCount >= NodeCount) 00311 break; 00312 } 00313 } 00314 00315 /* Set real data size */ 00316 PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize = 00317 PnpBufferSize; 00318 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + PnpBufferSize; 00319 00320 TRACE("Real buffer size: %u\n", PnpBufferSize); 00321 TRACE("Resource size: %u\n", Size); 00322 00323 /* Create component key */ 00324 FldrCreateComponentKey(SystemKey, 00325 AdapterClass, 00326 MultiFunctionAdapter, 00327 0x0, 00328 0x0, 00329 0xFFFFFFFF, 00330 "PNP BIOS", 00331 PartialResourceList, 00332 Size, 00333 &BusKey); 00334 00335 (*BusNumber)++; 00336 00337 MmHeapFree(PartialResourceList); 00338 } 00339 00340 00341 00342 static PCM_PARTIAL_RESOURCE_LIST 00343 GetHarddiskConfigurationData(UCHAR DriveNumber, ULONG* pSize) 00344 { 00345 PCM_PARTIAL_RESOURCE_LIST PartialResourceList; 00346 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry; 00347 EXTENDED_GEOMETRY ExtGeometry; 00348 GEOMETRY Geometry; 00349 ULONG Size; 00350 00351 // 00352 // Initialize returned size 00353 // 00354 *pSize = 0; 00355 00356 /* Set 'Configuration Data' value */ 00357 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + 00358 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA); 00359 PartialResourceList = MmHeapAlloc(Size); 00360 if (PartialResourceList == NULL) 00361 { 00362 ERR("Failed to allocate a full resource descriptor\n"); 00363 return NULL; 00364 } 00365 00366 memset(PartialResourceList, 0, Size); 00367 PartialResourceList->Version = 1; 00368 PartialResourceList->Revision = 1; 00369 PartialResourceList->Count = 1; 00370 PartialResourceList->PartialDescriptors[0].Type = 00371 CmResourceTypeDeviceSpecific; 00372 // PartialResourceList->PartialDescriptors[0].ShareDisposition = 00373 // PartialResourceList->PartialDescriptors[0].Flags = 00374 PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize = 00375 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA); 00376 00377 /* Get pointer to geometry data */ 00378 DiskGeometry = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST)); 00379 00380 /* Get the disk geometry */ 00381 ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY); 00382 if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size)) 00383 { 00384 DiskGeometry->BytesPerSector = ExtGeometry.BytesPerSector; 00385 DiskGeometry->NumberOfCylinders = ExtGeometry.Cylinders; 00386 DiskGeometry->SectorsPerTrack = ExtGeometry.SectorsPerTrack; 00387 DiskGeometry->NumberOfHeads = ExtGeometry.Heads; 00388 } 00389 else if(MachDiskGetDriveGeometry(DriveNumber, &Geometry)) 00390 { 00391 DiskGeometry->BytesPerSector = Geometry.BytesPerSector; 00392 DiskGeometry->NumberOfCylinders = Geometry.Cylinders; 00393 DiskGeometry->SectorsPerTrack = Geometry.Sectors; 00394 DiskGeometry->NumberOfHeads = Geometry.Heads; 00395 } 00396 else 00397 { 00398 TRACE("Reading disk geometry failed\n"); 00399 MmHeapFree(PartialResourceList); 00400 return NULL; 00401 } 00402 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n", 00403 DriveNumber, 00404 DiskGeometry->NumberOfCylinders, 00405 DiskGeometry->NumberOfHeads, 00406 DiskGeometry->SectorsPerTrack, 00407 DiskGeometry->BytesPerSector); 00408 00409 // 00410 // Return configuration data 00411 // 00412 *pSize = Size; 00413 return PartialResourceList; 00414 } 00415 00416 static UCHAR 00417 GetFloppyCount(VOID) 00418 { 00419 UCHAR Data; 00420 00421 WRITE_PORT_UCHAR((PUCHAR)0x70, 0x10); 00422 Data = READ_PORT_UCHAR((PUCHAR)0x71); 00423 00424 return ((Data & 0xF0) ? 1 : 0) + ((Data & 0x0F) ? 1 : 0); 00425 } 00426 00427 00428 static UCHAR 00429 GetFloppyType(UCHAR DriveNumber) 00430 { 00431 UCHAR Data; 00432 00433 WRITE_PORT_UCHAR((PUCHAR)0x70, 0x10); 00434 Data = READ_PORT_UCHAR((PUCHAR)0x71); 00435 00436 if (DriveNumber == 0) 00437 return Data >> 4; 00438 else if (DriveNumber == 1) 00439 return Data & 0x0F; 00440 00441 return 0; 00442 } 00443 00444 00445 static PVOID 00446 GetInt1eTable(VOID) 00447 { 00448 PUSHORT SegPtr = (PUSHORT)0x7A; 00449 PUSHORT OfsPtr = (PUSHORT)0x78; 00450 00451 return (PVOID)((ULONG_PTR)(((ULONG)(*SegPtr)) << 4) + (ULONG)(*OfsPtr)); 00452 } 00453 00454 00455 static VOID 00456 DetectBiosFloppyPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey) 00457 { 00458 PCM_PARTIAL_RESOURCE_LIST PartialResourceList; 00459 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 00460 PCM_FLOPPY_DEVICE_DATA FloppyData; 00461 CHAR Identifier[20]; 00462 PCONFIGURATION_COMPONENT_DATA PeripheralKey; 00463 ULONG Size; 00464 UCHAR FloppyNumber; 00465 UCHAR FloppyType; 00466 ULONG MaxDensity[6] = {0, 360, 1200, 720, 1440, 2880}; 00467 PUCHAR Ptr; 00468 00469 for (FloppyNumber = 0; FloppyNumber < 2; FloppyNumber++) 00470 { 00471 FloppyType = GetFloppyType(FloppyNumber); 00472 00473 if ((FloppyType > 5) || (FloppyType == 0)) 00474 continue; 00475 00476 if (!DiskResetController(FloppyNumber)) 00477 continue; 00478 00479 Ptr = GetInt1eTable(); 00480 00481 /* Set 'Identifier' value */ 00482 sprintf(Identifier, "FLOPPY%d", FloppyNumber + 1); 00483 00484 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + 00485 sizeof(CM_FLOPPY_DEVICE_DATA); 00486 PartialResourceList = MmHeapAlloc(Size); 00487 if (PartialResourceList == NULL) 00488 { 00489 ERR("Failed to allocate resource descriptor\n"); 00490 return; 00491 } 00492 00493 memset(PartialResourceList, 0, Size); 00494 PartialResourceList->Version = 1; 00495 PartialResourceList->Revision = 1; 00496 PartialResourceList->Count = 1; 00497 00498 PartialDescriptor = &PartialResourceList->PartialDescriptors[0]; 00499 PartialDescriptor->Type = CmResourceTypeDeviceSpecific; 00500 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; 00501 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_FLOPPY_DEVICE_DATA); 00502 00503 FloppyData = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST)); 00504 FloppyData->Version = 2; 00505 FloppyData->Revision = 0; 00506 FloppyData->MaxDensity = MaxDensity[FloppyType]; 00507 FloppyData->MountDensity = 0; 00508 RtlCopyMemory(&FloppyData->StepRateHeadUnloadTime, 00509 Ptr, 00510 11); 00511 FloppyData->MaximumTrackValue = (FloppyType == 1) ? 39 : 79; 00512 FloppyData->DataTransferRate = 0; 00513 00514 FldrCreateComponentKey(ControllerKey, 00515 PeripheralClass, 00516 FloppyDiskPeripheral, 00517 Input | Output, 00518 FloppyNumber, 00519 0xFFFFFFFF, 00520 Identifier, 00521 PartialResourceList, 00522 Size, 00523 &PeripheralKey); 00524 00525 MmHeapFree(PartialResourceList); 00526 } 00527 } 00528 00529 00530 static VOID 00531 DetectBiosFloppyController(PCONFIGURATION_COMPONENT_DATA BusKey) 00532 { 00533 PCONFIGURATION_COMPONENT_DATA ControllerKey; 00534 PCM_PARTIAL_RESOURCE_LIST PartialResourceList; 00535 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 00536 ULONG Size; 00537 ULONG FloppyCount; 00538 00539 FloppyCount = GetFloppyCount(); 00540 TRACE("Floppy count: %u\n", 00541 FloppyCount); 00542 00543 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + 00544 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); 00545 PartialResourceList = MmHeapAlloc(Size); 00546 if (PartialResourceList == NULL) 00547 { 00548 ERR("Failed to allocate resource descriptor\n"); 00549 return; 00550 } 00551 memset(PartialResourceList, 0, Size); 00552 00553 /* Initialize resource descriptor */ 00554 PartialResourceList->Version = 1; 00555 PartialResourceList->Revision = 1; 00556 PartialResourceList->Count = 3; 00557 00558 /* Set IO Port */ 00559 PartialDescriptor = &PartialResourceList->PartialDescriptors[0]; 00560 PartialDescriptor->Type = CmResourceTypePort; 00561 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; 00562 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO; 00563 PartialDescriptor->u.Port.Start.LowPart = 0x03F0; 00564 PartialDescriptor->u.Port.Start.HighPart = 0x0; 00565 PartialDescriptor->u.Port.Length = 8; 00566 00567 /* Set Interrupt */ 00568 PartialDescriptor = &PartialResourceList->PartialDescriptors[1]; 00569 PartialDescriptor->Type = CmResourceTypeInterrupt; 00570 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; 00571 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; 00572 PartialDescriptor->u.Interrupt.Level = 6; 00573 PartialDescriptor->u.Interrupt.Vector = 6; 00574 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF; 00575 00576 /* Set DMA channel */ 00577 PartialDescriptor = &PartialResourceList->PartialDescriptors[2]; 00578 PartialDescriptor->Type = CmResourceTypeDma; 00579 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; 00580 PartialDescriptor->Flags = 0; 00581 PartialDescriptor->u.Dma.Channel = 2; 00582 PartialDescriptor->u.Dma.Port = 0; 00583 00584 /* Create floppy disk controller */ 00585 FldrCreateComponentKey(BusKey, 00586 ControllerClass, 00587 DiskController, 00588 Output | Input, 00589 0x0, 00590 0xFFFFFFFF, 00591 NULL, 00592 PartialResourceList, 00593 Size, 00594 &ControllerKey); 00595 TRACE("Created key: DiskController\\0\n"); 00596 00597 MmHeapFree(PartialResourceList); 00598 00599 if (FloppyCount) DetectBiosFloppyPeripheral(ControllerKey); 00600 } 00601 00602 static PCONFIGURATION_COMPONENT_DATA 00603 DetectSystem(VOID) 00604 { 00605 PCONFIGURATION_COMPONENT_DATA SystemKey; 00606 PCM_PARTIAL_RESOURCE_LIST PartialResourceList; 00607 PCM_INT13_DRIVE_PARAMETER Int13Drives; 00608 GEOMETRY Geometry; 00609 UCHAR DiskCount; 00610 USHORT i; 00611 ULONG Size; 00612 00613 DiskCount = PcBiosDiskCount; 00614 00615 /* Allocate resource descriptor */ 00616 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + 00617 sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount; 00618 PartialResourceList = MmHeapAlloc(Size); 00619 if (PartialResourceList == NULL) 00620 { 00621 ERR("Failed to allocate resource descriptor\n"); 00622 return NULL; 00623 } 00624 00625 /* Initialize resource descriptor */ 00626 memset(PartialResourceList, 0, Size); 00627 PartialResourceList->Version = 1; 00628 PartialResourceList->Revision = 1; 00629 PartialResourceList->Count = 1; 00630 PartialResourceList->PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific; 00631 PartialResourceList->PartialDescriptors[0].ShareDisposition = 0; 00632 PartialResourceList->PartialDescriptors[0].Flags = 0; 00633 PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize = 00634 sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount; 00635 00636 /* Get harddisk Int13 geometry data */ 00637 Int13Drives = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST)); 00638 for (i = 0; i < DiskCount; i++) 00639 { 00640 if (MachDiskGetDriveGeometry(0x80 + i, &Geometry)) 00641 { 00642 Int13Drives[i].DriveSelect = 0x80 + i; 00643 Int13Drives[i].MaxCylinders = Geometry.Cylinders - 1; 00644 Int13Drives[i].SectorsPerTrack = (USHORT)Geometry.Sectors; 00645 Int13Drives[i].MaxHeads = (USHORT)Geometry.Heads - 1; 00646 Int13Drives[i].NumberDrives = DiskCount; 00647 00648 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n", 00649 0x80 + i, 00650 Geometry.Cylinders - 1, 00651 Geometry.Heads -1, 00652 Geometry.Sectors, 00653 Geometry.BytesPerSector); 00654 } 00655 } 00656 00657 FldrCreateComponentKey(NULL, 00658 SystemClass, 00659 MaximumType, 00660 0x0, 00661 0x0, 00662 0xFFFFFFFF, 00663 NULL, 00664 PartialResourceList, 00665 Size, 00666 &SystemKey); 00667 00668 MmHeapFree(PartialResourceList); 00669 00670 return SystemKey; 00671 } 00672 00673 static VOID 00674 DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA BusKey) 00675 { 00676 PCONFIGURATION_COMPONENT_DATA DiskKey, ControllerKey; 00677 ULONG i; 00678 00679 FldrCreateComponentKey(BusKey, 00680 ControllerClass, 00681 DiskController, 00682 Output | Input, 00683 0x0, 00684 0xFFFFFFFF, 00685 NULL, 00686 NULL, 00687 0, 00688 &ControllerKey); 00689 TRACE("Created key: DiskController\\0\n"); 00690 00691 /* Create and fill subkey for each harddisk */ 00692 for (i = 0; i < PcBiosDiskCount; i++) 00693 { 00694 PCM_PARTIAL_RESOURCE_LIST PartialResourceList; 00695 ULONG Size; 00696 PCHAR Identifier; 00697 UCHAR DriveNumber = 0x80 + (UCHAR)i; 00698 00699 /* Get disk values */ 00700 PartialResourceList = GetHarddiskConfigurationData(DriveNumber, &Size); 00701 Identifier = GetHarddiskIdentifier(DriveNumber); 00702 00703 /* Create disk key */ 00704 FldrCreateComponentKey(ControllerKey, 00705 PeripheralClass, 00706 DiskPeripheral, 00707 Output | Input, 00708 0x0, 00709 0xFFFFFFFF, 00710 Identifier, 00711 PartialResourceList, 00712 Size, 00713 &DiskKey); 00714 } 00715 00716 } 00717 00718 static VOID 00719 InitializeSerialPort(PUCHAR Port, 00720 UCHAR LineControl) 00721 { 00722 WRITE_PORT_UCHAR(Port + 3, 0x80); /* set DLAB on */ 00723 WRITE_PORT_UCHAR(Port, 0x60); /* speed LO byte */ 00724 WRITE_PORT_UCHAR(Port + 1, 0); /* speed HI byte */ 00725 WRITE_PORT_UCHAR(Port + 3, LineControl); 00726 WRITE_PORT_UCHAR(Port + 1, 0); /* set comm and DLAB to 0 */ 00727 WRITE_PORT_UCHAR(Port + 4, 0x09); /* DR int enable */ 00728 READ_PORT_UCHAR(Port + 5); /* clear error bits */ 00729 } 00730 00731 00732 static ULONG 00733 DetectSerialMouse(PUCHAR Port) 00734 { 00735 CHAR Buffer[4]; 00736 ULONG i; 00737 ULONG TimeOut; 00738 UCHAR LineControl; 00739 00740 /* Shutdown mouse or something like that */ 00741 LineControl = READ_PORT_UCHAR(Port + 4); 00742 WRITE_PORT_UCHAR(Port + 4, (LineControl & ~0x02) | 0x01); 00743 StallExecutionProcessor(100000); 00744 00745 /* 00746 * Clear buffer 00747 * Maybe there is no serial port although BIOS reported one (this 00748 * is the case on Apple hardware), or the serial port is misbehaving, 00749 * therefore we must give up after some time. 00750 */ 00751 TimeOut = 200; 00752 while (READ_PORT_UCHAR(Port + 5) & 0x01) 00753 { 00754 if (--TimeOut == 0) 00755 return MOUSE_TYPE_NONE; 00756 READ_PORT_UCHAR(Port); 00757 } 00758 00759 /* 00760 * Send modem control with 'Data Terminal Ready', 'Request To Send' and 00761 * 'Output Line 2' message. This enables mouse to identify. 00762 */ 00763 WRITE_PORT_UCHAR(Port + 4, 0x0b); 00764 00765 /* Wait 10 milliseconds for the mouse getting ready */ 00766 StallExecutionProcessor(10000); 00767 00768 /* Read first four bytes, which contains Microsoft Mouse signs */ 00769 TimeOut = 200; 00770 for (i = 0; i < 4; i++) 00771 { 00772 while (((READ_PORT_UCHAR(Port + 5) & 1) == 0) && (TimeOut > 0)) 00773 { 00774 StallExecutionProcessor(1000); 00775 --TimeOut; 00776 if (TimeOut == 0) 00777 return MOUSE_TYPE_NONE; 00778 } 00779 Buffer[i] = READ_PORT_UCHAR(Port); 00780 } 00781 00782 TRACE("Mouse data: %x %x %x %x\n", 00783 Buffer[0],Buffer[1],Buffer[2],Buffer[3]); 00784 00785 /* Check that four bytes for signs */ 00786 for (i = 0; i < 4; ++i) 00787 { 00788 if (Buffer[i] == 'B') 00789 { 00790 /* Sign for Microsoft Ballpoint */ 00791 // DbgPrint("Microsoft Ballpoint device detected\n"); 00792 // DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET\n"); 00793 return MOUSE_TYPE_NONE; 00794 } 00795 else if (Buffer[i] == 'M') 00796 { 00797 /* Sign for Microsoft Mouse protocol followed by button specifier */ 00798 if (i == 3) 00799 { 00800 /* Overflow Error */ 00801 return MOUSE_TYPE_NONE; 00802 } 00803 00804 switch (Buffer[i + 1]) 00805 { 00806 case '3': 00807 TRACE("Microsoft Mouse with 3-buttons detected\n"); 00808 return MOUSE_TYPE_LOGITECH; 00809 00810 case 'Z': 00811 TRACE("Microsoft Wheel Mouse detected\n"); 00812 return MOUSE_TYPE_WHEELZ; 00813 00814 /* case '2': */ 00815 default: 00816 TRACE("Microsoft Mouse with 2-buttons detected\n"); 00817 return MOUSE_TYPE_MICROSOFT; 00818 } 00819 } 00820 } 00821 00822 return MOUSE_TYPE_NONE; 00823 } 00824 00825 00826 static ULONG 00827 GetSerialMousePnpId(PUCHAR Port, char *Buffer) 00828 { 00829 ULONG TimeOut; 00830 ULONG i = 0; 00831 char c; 00832 char x; 00833 00834 WRITE_PORT_UCHAR(Port + 4, 0x09); 00835 00836 /* Wait 10 milliseconds for the mouse getting ready */ 00837 StallExecutionProcessor(10000); 00838 00839 WRITE_PORT_UCHAR(Port + 4, 0x0b); 00840 00841 StallExecutionProcessor(10000); 00842 00843 for (;;) 00844 { 00845 TimeOut = 200; 00846 while (((READ_PORT_UCHAR(Port + 5) & 1) == 0) && (TimeOut > 0)) 00847 { 00848 StallExecutionProcessor(1000); 00849 --TimeOut; 00850 if (TimeOut == 0) 00851 { 00852 return 0; 00853 } 00854 } 00855 00856 c = READ_PORT_UCHAR(Port); 00857 if (c == 0x08 || c == 0x28) 00858 break; 00859 } 00860 00861 Buffer[i++] = c; 00862 x = c + 1; 00863 00864 for (;;) 00865 { 00866 TimeOut = 200; 00867 while (((READ_PORT_UCHAR(Port + 5) & 1) == 0) && (TimeOut > 0)) 00868 { 00869 StallExecutionProcessor(1000); 00870 --TimeOut; 00871 if (TimeOut == 0) 00872 return 0; 00873 } 00874 c = READ_PORT_UCHAR(Port); 00875 Buffer[i++] = c; 00876 if (c == x) 00877 break; 00878 if (i >= 256) 00879 break; 00880 } 00881 00882 return i; 00883 } 00884 00885 00886 static VOID 00887 DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey, 00888 PUCHAR Base) 00889 { 00890 CM_PARTIAL_RESOURCE_LIST PartialResourceList; 00891 char Buffer[256]; 00892 CHAR Identifier[256]; 00893 PCONFIGURATION_COMPONENT_DATA PeripheralKey; 00894 ULONG MouseType; 00895 ULONG Length; 00896 ULONG i; 00897 ULONG j; 00898 ULONG k; 00899 00900 TRACE("DetectSerialPointerPeripheral()\n"); 00901 00902 Identifier[0] = 0; 00903 00904 InitializeSerialPort(Base, 2); 00905 MouseType = DetectSerialMouse(Base); 00906 00907 if (MouseType != MOUSE_TYPE_NONE) 00908 { 00909 Length = GetSerialMousePnpId(Base, Buffer); 00910 TRACE( "PnP ID length: %u\n", Length); 00911 00912 if (Length != 0) 00913 { 00914 /* Convert PnP sting to ASCII */ 00915 if (Buffer[0] == 0x08) 00916 { 00917 for (i = 0; i < Length; i++) 00918 Buffer[i] += 0x20; 00919 } 00920 Buffer[Length] = 0; 00921 00922 TRACE("PnP ID string: %s\n", Buffer); 00923 00924 /* Copy PnpId string */ 00925 for (i = 0; i < 7; i++) 00926 { 00927 Identifier[i] = Buffer[3+i]; 00928 } 00929 memcpy(&Identifier[7], 00930 L" - ", 00931 3 * sizeof(WCHAR)); 00932 00933 /* Skip device serial number */ 00934 i = 10; 00935 if (Buffer[i] == '\\') 00936 { 00937 for (j = ++i; i < Length; ++i) 00938 { 00939 if (Buffer[i] == '\\') 00940 break; 00941 } 00942 if (i >= Length) 00943 i -= 3; 00944 } 00945 00946 /* Skip PnP class */ 00947 if (Buffer[i] == '\\') 00948 { 00949 for (j = ++i; i < Length; ++i) 00950 { 00951 if (Buffer[i] == '\\') 00952 break; 00953 } 00954 00955 if (i >= Length) 00956 i -= 3; 00957 } 00958 00959 /* Skip compatible PnP Id */ 00960 if (Buffer[i] == '\\') 00961 { 00962 for (j = ++i; i < Length; ++i) 00963 { 00964 if (Buffer[i] == '\\') 00965 break; 00966 } 00967 if (Buffer[j] == '*') 00968 ++j; 00969 if (i >= Length) 00970 i -= 3; 00971 } 00972 00973 /* Get product description */ 00974 if (Buffer[i] == '\\') 00975 { 00976 for (j = ++i; i < Length; ++i) 00977 { 00978 if (Buffer[i] == ';') 00979 break; 00980 } 00981 if (i >= Length) 00982 i -= 3; 00983 if (i > j + 1) 00984 { 00985 for (k = 0; k < i - j; k++) 00986 { 00987 Identifier[k + 10] = Buffer[k + j]; 00988 } 00989 Identifier[10 + (i-j)] = 0; 00990 } 00991 } 00992 00993 TRACE("Identifier string: %s\n", Identifier); 00994 } 00995 00996 if (Length == 0 || strlen(Identifier) < 11) 00997 { 00998 switch (MouseType) 00999 { 01000 case MOUSE_TYPE_LOGITECH: 01001 strcpy(Identifier, "LOGITECH SERIAL MOUSE"); 01002 break; 01003 01004 case MOUSE_TYPE_WHEELZ: 01005 strcpy(Identifier, "MICROSOFT SERIAL MOUSE WITH WHEEL"); 01006 break; 01007 01008 case MOUSE_TYPE_MICROSOFT: 01009 default: 01010 strcpy(Identifier, "MICROSOFT SERIAL MOUSE"); 01011 break; 01012 } 01013 } 01014 01015 /* Set 'Configuration Data' value */ 01016 memset(&PartialResourceList, 0, sizeof(CM_PARTIAL_RESOURCE_LIST)); 01017 PartialResourceList.Version = 1; 01018 PartialResourceList.Revision = 1; 01019 PartialResourceList.Count = 0; 01020 01021 /* Create 'PointerPeripheral' key */ 01022 FldrCreateComponentKey(ControllerKey, 01023 PeripheralClass, 01024 PointerPeripheral, 01025 Input, 01026 0x0, 01027 0xFFFFFFFF, 01028 Identifier, 01029 &PartialResourceList, 01030 sizeof(CM_PARTIAL_RESOURCE_LIST) - 01031 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR), 01032 &PeripheralKey); 01033 01034 TRACE("Created key: PointerPeripheral\\0\n"); 01035 } 01036 } 01037 01038 01039 static VOID 01040 DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey) 01041 { 01042 PCM_PARTIAL_RESOURCE_LIST PartialResourceList; 01043 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 01044 PCM_SERIAL_DEVICE_DATA SerialDeviceData; 01045 ULONG Irq[4] = {4, 3, 4, 3}; 01046 ULONG Base; 01047 CHAR Buffer[80]; 01048 PUSHORT BasePtr; 01049 ULONG ControllerNumber = 0; 01050 PCONFIGURATION_COMPONENT_DATA ControllerKey; 01051 ULONG i; 01052 ULONG Size; 01053 01054 TRACE("DetectSerialPorts()\n"); 01055 01056 ControllerNumber = 0; 01057 BasePtr = (PUSHORT)0x400; 01058 for (i = 0; i < 2; i++, BasePtr++) 01059 { 01060 Base = (ULONG)*BasePtr; 01061 if (Base == 0) 01062 continue; 01063 01064 TRACE("Found COM%u port at 0x%x\n", i + 1, Base); 01065 01066 /* Set 'Identifier' value */ 01067 sprintf(Buffer, "COM%ld", i + 1); 01068 01069 /* Build full device descriptor */ 01070 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + 01071 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) + 01072 sizeof(CM_SERIAL_DEVICE_DATA); 01073 PartialResourceList = MmHeapAlloc(Size); 01074 if (PartialResourceList == NULL) 01075 { 01076 ERR("Failed to allocate resource descriptor\n"); 01077 continue; 01078 } 01079 memset(PartialResourceList, 0, Size); 01080 01081 /* Initialize resource descriptor */ 01082 PartialResourceList->Version = 1; 01083 PartialResourceList->Revision = 1; 01084 PartialResourceList->Count = 3; 01085 01086 /* Set IO Port */ 01087 PartialDescriptor = &PartialResourceList->PartialDescriptors[0]; 01088 PartialDescriptor->Type = CmResourceTypePort; 01089 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; 01090 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO; 01091 PartialDescriptor->u.Port.Start.LowPart = Base; 01092 PartialDescriptor->u.Port.Start.HighPart = 0x0; 01093 PartialDescriptor->u.Port.Length = 7; 01094 01095 /* Set Interrupt */ 01096 PartialDescriptor = &PartialResourceList->PartialDescriptors[1]; 01097 PartialDescriptor->Type = CmResourceTypeInterrupt; 01098 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; 01099 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; 01100 PartialDescriptor->u.Interrupt.Level = Irq[i]; 01101 PartialDescriptor->u.Interrupt.Vector = Irq[i]; 01102 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF; 01103 01104 /* Set serial data (device specific) */ 01105 PartialDescriptor = &PartialResourceList->PartialDescriptors[2]; 01106 PartialDescriptor->Type = CmResourceTypeDeviceSpecific; 01107 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; 01108 PartialDescriptor->Flags = 0; 01109 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_SERIAL_DEVICE_DATA); 01110 01111 SerialDeviceData = 01112 (PCM_SERIAL_DEVICE_DATA)&PartialResourceList->PartialDescriptors[3]; 01113 SerialDeviceData->BaudClock = 1843200; /* UART Clock frequency (Hertz) */ 01114 01115 /* Create controller key */ 01116 FldrCreateComponentKey(BusKey, 01117 ControllerClass, 01118 SerialController, 01119 Output | Input | ConsoleIn | ConsoleOut, 01120 ControllerNumber, 01121 0xFFFFFFFF, 01122 Buffer, 01123 PartialResourceList, 01124 Size, 01125 &ControllerKey); 01126 01127 MmHeapFree(PartialResourceList); 01128 01129 if (!Rs232PortInUse(Base)) 01130 { 01131 /* Detect serial mouse */ 01132 DetectSerialPointerPeripheral(ControllerKey, UlongToPtr(Base)); 01133 } 01134 01135 ControllerNumber++; 01136 } 01137 } 01138 01139 01140 static VOID 01141 DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey) 01142 { 01143 PCM_PARTIAL_RESOURCE_LIST PartialResourceList; 01144 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 01145 ULONG Irq[3] = {7, 5, (ULONG)-1}; 01146 CHAR Buffer[80]; 01147 PCONFIGURATION_COMPONENT_DATA ControllerKey; 01148 PUSHORT BasePtr; 01149 ULONG Base; 01150 ULONG ControllerNumber; 01151 ULONG i; 01152 ULONG Size; 01153 01154 TRACE("DetectParallelPorts() called\n"); 01155 01156 ControllerNumber = 0; 01157 BasePtr = (PUSHORT)0x408; 01158 for (i = 0; i < 3; i++, BasePtr++) 01159 { 01160 Base = (ULONG)*BasePtr; 01161 if (Base == 0) 01162 continue; 01163 01164 TRACE("Parallel port %u: %x\n", ControllerNumber, Base); 01165 01166 /* Set 'Identifier' value */ 01167 sprintf(Buffer, "PARALLEL%ld", i + 1); 01168 01169 /* Build full device descriptor */ 01170 Size = sizeof(CM_PARTIAL_RESOURCE_LIST); 01171 if (Irq[i] != (ULONG)-1) 01172 Size += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); 01173 01174 PartialResourceList = MmHeapAlloc(Size); 01175 if (PartialResourceList == NULL) 01176 { 01177 ERR("Failed to allocate resource descriptor\n"); 01178 continue; 01179 } 01180 memset(PartialResourceList, 0, Size); 01181 01182 /* Initialize resource descriptor */ 01183 PartialResourceList->Version = 1; 01184 PartialResourceList->Revision = 1; 01185 PartialResourceList->Count = (Irq[i] != (ULONG)-1) ? 2 : 1; 01186 01187 /* Set IO Port */ 01188 PartialDescriptor = &PartialResourceList->PartialDescriptors[0]; 01189 PartialDescriptor->Type = CmResourceTypePort; 01190 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; 01191 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO; 01192 PartialDescriptor->u.Port.Start.LowPart = Base; 01193 PartialDescriptor->u.Port.Start.HighPart = 0x0; 01194 PartialDescriptor->u.Port.Length = 3; 01195 01196 /* Set Interrupt */ 01197 if (Irq[i] != (ULONG)-1) 01198 { 01199 PartialDescriptor = &PartialResourceList->PartialDescriptors[1]; 01200 PartialDescriptor->Type = CmResourceTypeInterrupt; 01201 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; 01202 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; 01203 PartialDescriptor->u.Interrupt.Level = Irq[i]; 01204 PartialDescriptor->u.Interrupt.Vector = Irq[i]; 01205 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF; 01206 } 01207 01208 /* Create controller key */ 01209 FldrCreateComponentKey(BusKey, 01210 ControllerClass, 01211 ParallelController, 01212 Output, 01213 ControllerNumber, 01214 0xFFFFFFFF, 01215 Buffer, 01216 PartialResourceList, 01217 Size, 01218 &ControllerKey); 01219 01220 MmHeapFree(PartialResourceList); 01221 01222 ControllerNumber++; 01223 } 01224 01225 TRACE("DetectParallelPorts() done\n"); 01226 } 01227 01228 01229 static BOOLEAN 01230 DetectKeyboardDevice(VOID) 01231 { 01232 UCHAR Status; 01233 UCHAR Scancode; 01234 ULONG Loops; 01235 BOOLEAN Result = TRUE; 01236 01237 /* Identify device */ 01238 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA, 01239 0xF2); 01240 01241 /* Wait for reply */ 01242 for (Loops = 0; Loops < 100; Loops++) 01243 { 01244 StallExecutionProcessor(10000); 01245 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS); 01246 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0) 01247 break; 01248 } 01249 01250 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) == 0) 01251 { 01252 /* PC/XT keyboard or no keyboard */ 01253 Result = FALSE; 01254 } 01255 01256 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA); 01257 if (Scancode != 0xFA) 01258 { 01259 /* No ACK received */ 01260 Result = FALSE; 01261 } 01262 01263 StallExecutionProcessor(10000); 01264 01265 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS); 01266 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) == 0) 01267 { 01268 /* Found AT keyboard */ 01269 return Result; 01270 } 01271 01272 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA); 01273 if (Scancode != 0xAB) 01274 { 01275 /* No 0xAB received */ 01276 Result = FALSE; 01277 } 01278 01279 StallExecutionProcessor(10000); 01280 01281 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS); 01282 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) == 0) 01283 { 01284 /* No byte in buffer */ 01285 Result = FALSE; 01286 } 01287 01288 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA); 01289 if (Scancode != 0x41) 01290 { 01291 /* No 0x41 received */ 01292 Result = FALSE; 01293 } 01294 01295 /* Found MF-II keyboard */ 01296 return Result; 01297 } 01298 01299 01300 static VOID 01301 DetectKeyboardPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey) 01302 { 01303 PCM_PARTIAL_RESOURCE_LIST PartialResourceList; 01304 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 01305 PCM_KEYBOARD_DEVICE_DATA KeyboardData; 01306 PCONFIGURATION_COMPONENT_DATA PeripheralKey; 01307 ULONG Size; 01308 01309 /* HACK: don't call DetectKeyboardDevice() as it fails in Qemu 0.8.2 */ 01310 if (TRUE || DetectKeyboardDevice()) 01311 { 01312 /* Set 'Configuration Data' value */ 01313 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + 01314 sizeof(CM_KEYBOARD_DEVICE_DATA); 01315 PartialResourceList = MmHeapAlloc(Size); 01316 if (PartialResourceList == NULL) 01317 { 01318 ERR("Failed to allocate resource descriptor\n"); 01319 return; 01320 } 01321 01322 /* Initialize resource descriptor */ 01323 memset(PartialResourceList, 0, Size); 01324 PartialResourceList->Version = 1; 01325 PartialResourceList->Revision = 1; 01326 PartialResourceList->Count = 1; 01327 01328 PartialDescriptor = &PartialResourceList->PartialDescriptors[0]; 01329 PartialDescriptor->Type = CmResourceTypeDeviceSpecific; 01330 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; 01331 PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_KEYBOARD_DEVICE_DATA); 01332 01333 KeyboardData = (PCM_KEYBOARD_DEVICE_DATA)(PartialDescriptor + 1); 01334 KeyboardData->Version = 1; 01335 KeyboardData->Revision = 1; 01336 KeyboardData->Type = 4; 01337 KeyboardData->Subtype = 0; 01338 KeyboardData->KeyboardFlags = 0x20; 01339 01340 /* Create controller key */ 01341 FldrCreateComponentKey(ControllerKey, 01342 PeripheralClass, 01343 KeyboardPeripheral, 01344 Input | ConsoleIn, 01345 0x0, 01346 0xFFFFFFFF, 01347 "PCAT_ENHANCED", 01348 PartialResourceList, 01349 Size, 01350 &PeripheralKey); 01351 TRACE("Created key: KeyboardPeripheral\\0\n"); 01352 01353 MmHeapFree(PartialResourceList); 01354 } 01355 } 01356 01357 01358 static VOID 01359 DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey) 01360 { 01361 PCM_PARTIAL_RESOURCE_LIST PartialResourceList; 01362 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 01363 PCONFIGURATION_COMPONENT_DATA ControllerKey; 01364 ULONG Size; 01365 01366 /* Set 'Configuration Data' value */ 01367 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + 01368 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); 01369 PartialResourceList = MmHeapAlloc(Size); 01370 if (PartialResourceList == NULL) 01371 { 01372 ERR("Failed to allocate resource descriptor\n"); 01373 return; 01374 } 01375 01376 /* Initialize resource descriptor */ 01377 memset(PartialResourceList, 0, Size); 01378 PartialResourceList->Version = 1; 01379 PartialResourceList->Revision = 1; 01380 PartialResourceList->Count = 3; 01381 01382 /* Set Interrupt */ 01383 PartialDescriptor = &PartialResourceList->PartialDescriptors[0]; 01384 PartialDescriptor->Type = CmResourceTypeInterrupt; 01385 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; 01386 PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; 01387 PartialDescriptor->u.Interrupt.Level = 1; 01388 PartialDescriptor->u.Interrupt.Vector = 1; 01389 PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF; 01390 01391 /* Set IO Port 0x60 */ 01392 PartialDescriptor = &PartialResourceList->PartialDescriptors[1]; 01393 PartialDescriptor->Type = CmResourceTypePort; 01394 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; 01395 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO; 01396 PartialDescriptor->u.Port.Start.LowPart = 0x60; 01397 PartialDescriptor->u.Port.Start.HighPart = 0x0; 01398 PartialDescriptor->u.Port.Length = 1; 01399 01400 /* Set IO Port 0x64 */ 01401 PartialDescriptor = &PartialResourceList->PartialDescriptors[2]; 01402 PartialDescriptor->Type = CmResourceTypePort; 01403 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; 01404 PartialDescriptor->Flags = CM_RESOURCE_PORT_IO; 01405 PartialDescriptor->u.Port.Start.LowPart = 0x64; 01406 PartialDescriptor->u.Port.Start.HighPart = 0x0; 01407 PartialDescriptor->u.Port.Length = 1; 01408 01409 /* Create controller key */ 01410 FldrCreateComponentKey(BusKey, 01411 ControllerClass, 01412 KeyboardController, 01413 Input | ConsoleIn, 01414 0x0, 01415 0xFFFFFFFF, 01416 NULL, 01417 PartialResourceList, 01418 Size, 01419 &ControllerKey); 01420 TRACE("Created key: KeyboardController\\0\n"); 01421 01422 MmHeapFree(PartialResourceList); 01423 01424 DetectKeyboardPeripheral(ControllerKey); 01425 } 01426 01427 01428 static VOID 01429 PS2ControllerWait(VOID) 01430 { 01431 ULONG Timeout; 01432 UCHAR Status; 01433 01434 for (Timeout = 0; Timeout < CONTROLLER_TIMEOUT; Timeout++) 01435 { 01436 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS); 01437 if ((Status & CONTROLLER_STATUS_INPUT_BUFFER_FULL) == 0) 01438 return; 01439 01440 /* Sleep for one millisecond */ 01441 StallExecutionProcessor(1000); 01442 } 01443 } 01444 01445 01446 static BOOLEAN 01447 DetectPS2AuxPort(VOID) 01448 { 01449 #if 1 01450 /* Current detection is too unreliable. Just do as if 01451 * the PS/2 aux port is always present 01452 */ 01453 return TRUE; 01454 #else 01455 ULONG Loops; 01456 UCHAR Status; 01457 01458 /* Put the value 0x5A in the output buffer using the 01459 * "WriteAuxiliary Device Output Buffer" command (0xD3). 01460 * Poll the Status Register for a while to see if the value really turns up 01461 * in the Data Register. If the KEYBOARD_STATUS_MOUSE_OBF bit is also set 01462 * to 1 in the Status Register, we assume this controller has an 01463 * Auxiliary Port (a.k.a. Mouse Port). 01464 */ 01465 PS2ControllerWait(); 01466 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL, 01467 CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER); 01468 PS2ControllerWait(); 01469 01470 /* 0x5A is a random dummy value */ 01471 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA, 01472 0x5A); 01473 01474 for (Loops = 0; Loops < 10; Loops++) 01475 { 01476 StallExecutionProcessor(10000); 01477 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS); 01478 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0) 01479 break; 01480 } 01481 01482 READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA); 01483 01484 return (Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL); 01485 #endif 01486 } 01487 01488 01489 static BOOLEAN 01490 DetectPS2AuxDevice(VOID) 01491 { 01492 UCHAR Scancode; 01493 UCHAR Status; 01494 ULONG Loops; 01495 BOOLEAN Result = TRUE; 01496 01497 PS2ControllerWait(); 01498 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL, 01499 CONTROLLER_COMMAND_WRITE_MOUSE); 01500 PS2ControllerWait(); 01501 01502 /* Identify device */ 01503 WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA, 01504 0xF2); 01505 01506 /* Wait for reply */ 01507 for (Loops = 0; Loops < 100; Loops++) 01508 { 01509 StallExecutionProcessor(10000); 01510 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS); 01511 if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0) 01512 break; 01513 } 01514 01515 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS); 01516 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0) 01517 Result = FALSE; 01518 01519 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA); 01520 if (Scancode != 0xFA) 01521 Result = FALSE; 01522 01523 StallExecutionProcessor(10000); 01524 01525 Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS); 01526 if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0) 01527 Result = FALSE; 01528 01529 Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA); 01530 if (Scancode != 0x00) 01531 Result = FALSE; 01532 01533 return Result; 01534 } 01535 01536 01537 static VOID 01538 DetectPS2Mouse(PCONFIGURATION_COMPONENT_DATA BusKey) 01539 { 01540 CM_PARTIAL_RESOURCE_LIST PartialResourceList; 01541 PCONFIGURATION_COMPONENT_DATA ControllerKey; 01542 PCONFIGURATION_COMPONENT_DATA PeripheralKey; 01543 01544 if (DetectPS2AuxPort()) 01545 { 01546 TRACE("Detected PS2 port\n"); 01547 01548 memset(&PartialResourceList, 0, sizeof(CM_PARTIAL_RESOURCE_LIST)); 01549 01550 /* Initialize resource descriptor */ 01551 PartialResourceList.Version = 1; 01552 PartialResourceList.Revision = 1; 01553 PartialResourceList.Count = 1; 01554 01555 /* Set Interrupt */ 01556 PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeInterrupt; 01557 PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareUndetermined; 01558 PartialResourceList.PartialDescriptors[0].Flags = CM_RESOURCE_INTERRUPT_LATCHED; 01559 PartialResourceList.PartialDescriptors[0].u.Interrupt.Level = 12; 01560 PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector = 12; 01561 PartialResourceList.PartialDescriptors[0].u.Interrupt.Affinity = 0xFFFFFFFF; 01562 01563 /* Create controller key */ 01564 FldrCreateComponentKey(BusKey, 01565 ControllerClass, 01566 PointerController, 01567 Input, 01568 0x0, 01569 0xFFFFFFFF, 01570 NULL, 01571 &PartialResourceList, 01572 sizeof(CM_PARTIAL_RESOURCE_LIST), 01573 &ControllerKey); 01574 TRACE("Created key: PointerController\\0\n"); 01575 01576 if (DetectPS2AuxDevice()) 01577 { 01578 TRACE("Detected PS2 mouse\n"); 01579 01580 /* Initialize resource descriptor */ 01581 memset(&PartialResourceList, 0, sizeof(CM_PARTIAL_RESOURCE_LIST)); 01582 PartialResourceList.Version = 1; 01583 PartialResourceList.Revision = 1; 01584 PartialResourceList.Count = 0; 01585 01586 /* Create peripheral key */ 01587 FldrCreateComponentKey(ControllerKey, 01588 ControllerClass, 01589 PointerPeripheral, 01590 Input, 01591 0x0, 01592 0xFFFFFFFF, 01593 "MICROSOFT PS2 MOUSE", 01594 &PartialResourceList, 01595 sizeof(CM_PARTIAL_RESOURCE_LIST) - 01596 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR), 01597 &PeripheralKey); 01598 TRACE("Created key: PointerPeripheral\\0\n"); 01599 } 01600 } 01601 } 01602 01603 01604 static VOID 01605 DetectDisplayController(PCONFIGURATION_COMPONENT_DATA BusKey) 01606 { 01607 CHAR Buffer[80]; 01608 PCONFIGURATION_COMPONENT_DATA ControllerKey; 01609 USHORT VesaVersion; 01610 01611 /* FIXME: Set 'ComponentInformation' value */ 01612 01613 VesaVersion = BiosIsVesaSupported(); 01614 if (VesaVersion != 0) 01615 { 01616 TRACE("VESA version %c.%c\n", 01617 (VesaVersion >> 8) + '0', 01618 (VesaVersion & 0xFF) + '0'); 01619 } 01620 else 01621 { 01622 TRACE("VESA not supported\n"); 01623 } 01624 01625 if (VesaVersion >= 0x0200) 01626 { 01627 strcpy(Buffer, "VBE Display"); 01628 } 01629 else 01630 { 01631 strcpy(Buffer, "VGA Display"); 01632 } 01633 01634 FldrCreateComponentKey(BusKey, 01635 ControllerClass, 01636 DisplayController, 01637 0x0, 01638 0x0, 01639 0xFFFFFFFF, 01640 Buffer, 01641 NULL, 01642 0, 01643 &ControllerKey); 01644 TRACE("Created key: DisplayController\\0\n"); 01645 01646 /* FIXME: Add display peripheral (monitor) data */ 01647 } 01648 01649 01650 static VOID 01651 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber) 01652 { 01653 PCM_PARTIAL_RESOURCE_LIST PartialResourceList; 01654 PCONFIGURATION_COMPONENT_DATA BusKey; 01655 ULONG Size; 01656 01657 /* Increment bus number */ 01658 (*BusNumber)++; 01659 01660 /* Set 'Configuration Data' value */ 01661 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) - 01662 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); 01663 PartialResourceList = MmHeapAlloc(Size); 01664 if (PartialResourceList == NULL) 01665 { 01666 ERR("Failed to allocate resource descriptor\n"); 01667 return; 01668 } 01669 01670 /* Initialize resource descriptor */ 01671 memset(PartialResourceList, 0, Size); 01672 PartialResourceList->Version = 1; 01673 PartialResourceList->Revision = 1; 01674 PartialResourceList->Count = 0; 01675 01676 /* Create new bus key */ 01677 FldrCreateComponentKey(SystemKey, 01678 AdapterClass, 01679 MultiFunctionAdapter, 01680 0x0, 01681 0x0, 01682 0xFFFFFFFF, 01683 "ISA", 01684 PartialResourceList, 01685 Size, 01686 &BusKey); 01687 01688 MmHeapFree(PartialResourceList); 01689 01690 /* Detect ISA/BIOS devices */ 01691 DetectBiosDisks(BusKey); 01692 01693 DetectBiosFloppyController(BusKey); 01694 01695 DetectSerialPorts(BusKey); 01696 01697 DetectParallelPorts(BusKey); 01698 01699 DetectKeyboardController(BusKey); 01700 01701 DetectPS2Mouse(BusKey); 01702 01703 DetectDisplayController(BusKey); 01704 01705 /* FIXME: Detect more ISA devices */ 01706 } 01707 01708 01709 PCONFIGURATION_COMPONENT_DATA 01710 PcHwDetect(VOID) 01711 { 01712 PCONFIGURATION_COMPONENT_DATA SystemKey; 01713 ULONG BusNumber = 0; 01714 01715 TRACE("DetectHardware()\n"); 01716 01717 HwInitializeBiosDisks(); 01718 01719 /* Create the 'System' key */ 01720 SystemKey = DetectSystem(); 01721 01722 /* Detect buses */ 01723 DetectPciBios(SystemKey, &BusNumber); 01724 DetectApmBios(SystemKey, &BusNumber); 01725 DetectPnpBios(SystemKey, &BusNumber); 01726 DetectIsaBios(SystemKey, &BusNumber); 01727 DetectAcpiBios(SystemKey, &BusNumber); 01728 01729 TRACE("DetectHardware() Done\n"); 01730 01731 return SystemKey; 01732 } 01733 01734 VOID 01735 PcHwIdle(VOID) 01736 { 01737 REGS Regs; 01738 01739 /* Select APM 1.0+ function */ 01740 Regs.b.ah = 0x53; 01741 01742 /* Function 05h: CPU idle */ 01743 Regs.b.al = 0x05; 01744 01745 /* Call INT 15h */ 01746 Int386(0x15, &Regs, &Regs); 01747 01748 /* Check if successfull (CF set on error) */ 01749 if (INT386_SUCCESS(Regs)) 01750 return; 01751 01752 /* 01753 * No futher processing here. 01754 * Optionally implement HLT instruction handling. 01755 */ 01756 } 01757 01758 /* EOF */ Generated on Fri May 25 2012 04:17:09 for ReactOS by
1.7.6.1
|