ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

hardware.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.