Detect display controller. Distinguish VGA and VBE display devices.
[reactos.git] / freeldr / freeldr / arch / i386 / hardware.c
index 6cc640c..7b37551 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  FreeLoader
  *
- *  Copyright (C) 2003  Eric Kohl
+ *  Copyright (C) 2003, 2004  Eric Kohl
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
 #include <disk.h>
 #include <mm.h>
 #include <portio.h>
+#include <video.h>
 
 #include "../../reactos/registry.h"
 #include "hardware.h"
@@ -167,6 +168,16 @@ typedef struct _CM_FLOPPY_DEVICE_DATA
 } __attribute__((packed)) CM_FLOPPY_DEVICE_DATA, *PCM_FLOPPY_DEVICE_DATA;
 
 
+typedef struct _CM_KEYBOARD_DEVICE_DATA
+{
+  U16 Version;
+  U16 Revision;
+  U8 Type;
+  U8 Subtype;
+  U16 KeyboardFlags;
+} __attribute__((packed)) CM_KEYBOARD_DEVICE_DATA, *PCM_KEYBOARD_DEVICE_DATA;
+
+
 static char Hex[] = "0123456789ABCDEF";
 static unsigned int delay_count = 1;
 
@@ -885,7 +896,9 @@ DetectBiosFloppyController(HKEY SystemKey,
   U32 FloppyCount;
 
   FloppyCount = GetFloppyCount();
-/*  printf ("Floppy count: %u\n", FloppyCount);*/
+  DbgPrint((DPRINT_HWDETECT,
+           "Floppy count: %u\n",
+           FloppyCount));
 
   if (FloppyCount == 0)
     return;
@@ -1456,6 +1469,244 @@ DetectSerialPorts(HKEY BusKey)
 }
 
 
+static BOOLEAN
+DetectKeyboardDevice(VOID)
+{
+  UCHAR Status;
+  UCHAR Scancode;
+
+  WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
+                  0xF2);
+
+  KeStallExecutionProcessor(10000);
+
+  Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
+  if ((Status & 0x01) != 0x01)
+    {
+      /* PC/XT keyboard or no keyboard */
+      return FALSE;
+    }
+
+  Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
+  if (Scancode != 0xFA)
+    {
+      /* No ACK received */
+      return FALSE;
+    }
+
+  KeStallExecutionProcessor(10000);
+  Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
+  if ((Status & 0x01) != 0x01)
+    {
+      /* Found AT keyboard */
+      return TRUE;
+    }
+
+  Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
+  if (Scancode != 0xAB)
+    {
+      /* No 0xAB received */
+      return FALSE;
+    }
+
+  KeStallExecutionProcessor(10000);
+  Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
+  if ((Status & 0x01) != 0x01)
+    {
+      /* No byte in buffer */
+      return FALSE;
+    }
+
+  Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
+  if (Scancode != 0x41)
+    {
+      /* No 0x41 received */
+      return FALSE;
+    }
+
+  /* Found MF-II keyboard */
+  return TRUE;
+}
+
+
+static VOID
+DetectKeyboardPeripheral(HKEY ControllerKey)
+{
+  PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
+  PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
+  PCM_KEYBOARD_DEVICE_DATA KeyboardData;
+  HKEY PeripheralKey;
+  char Buffer[80];
+  U32 Size;
+  S32 Error;
+
+  if (DetectKeyboardDevice())
+  {
+    /* Create controller key */
+    Error = RegCreateKey(ControllerKey,
+                        "KeyboardPeripheral\\0",
+                        &PeripheralKey);
+    if (Error != ERROR_SUCCESS)
+    {
+      DbgPrint((DPRINT_HWDETECT, "Failed to create peripheral key\n"));
+      return;
+    }
+    DbgPrint((DPRINT_HWDETECT, "Created key: KeyboardPeripheral\\0\n"));
+
+    /* Set 'ComponentInformation' value */
+    SetComponentInformation(ControllerKey,
+                           0x28,
+                           0,
+                           0xFFFFFFFF);
+
+    /* Set 'Configuration Data' value */
+    Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
+          sizeof(CM_KEYBOARD_DEVICE_DATA);
+    FullResourceDescriptor = MmAllocateMemory(Size);
+    if (FullResourceDescriptor == NULL)
+    {
+      DbgPrint((DPRINT_HWDETECT,
+               "Failed to allocate resource descriptor\n"));
+      return;
+    }
+
+    /* Initialize resource descriptor */
+    memset(FullResourceDescriptor, 0, Size);
+    FullResourceDescriptor->InterfaceType = Isa;
+    FullResourceDescriptor->BusNumber = 0;
+    FullResourceDescriptor->PartialResourceList.Count = 1;
+
+    PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0];
+    PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
+    PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
+    PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_KEYBOARD_DEVICE_DATA);
+
+    KeyboardData = ((PVOID)FullResourceDescriptor) + sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
+    KeyboardData->Version = 0;
+    KeyboardData->Revision = 0;
+    KeyboardData->Type = 4;
+    KeyboardData->Subtype = 0;
+    KeyboardData->KeyboardFlags = 0x20;
+
+    /* Set 'Configuration Data' value */
+    Error = RegSetValue(PeripheralKey,
+                       "Configuration Data",
+                       REG_FULL_RESOURCE_DESCRIPTOR,
+                       (PU8)FullResourceDescriptor,
+                       Size);
+    MmFreeMemory(FullResourceDescriptor);
+    if (Error != ERROR_SUCCESS)
+    {
+      DbgPrint((DPRINT_HWDETECT,
+               "RegSetValue(Configuration Data) failed (Error %u)\n",
+               (int)Error));
+    }
+
+    /* Set 'Identifier' value */
+    strcpy(Buffer,
+          "PCAT_ENHANCED");
+    Error = RegSetValue(ControllerKey,
+                       "Identifier",
+                       REG_SZ,
+                       (PU8)Buffer,
+                       strlen(Buffer) + 1);
+    if (Error != ERROR_SUCCESS)
+    {
+      DbgPrint((DPRINT_HWDETECT,
+               "RegSetValue() failed (Error %u)\n",
+               (int)Error));
+    }
+  }
+}
+
+
+static VOID
+DetectKeyboardController(HKEY BusKey)
+{
+  PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
+  PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
+  HKEY ControllerKey;
+  U32 Size;
+  S32 Error;
+
+  /* Create controller key */
+  Error = RegCreateKey(BusKey,
+                      "KeyboardController\\0",
+                      &ControllerKey);
+  if (Error != ERROR_SUCCESS)
+    {
+      DbgPrint((DPRINT_HWDETECT, "Failed to create controller key\n"));
+      return;
+    }
+  DbgPrint((DPRINT_HWDETECT, "Created key: KeyboardController\\0\n"));
+
+  /* Set 'ComponentInformation' value */
+  SetComponentInformation(ControllerKey,
+                         0x28,
+                         0,
+                         0xFFFFFFFF);
+
+  /* Set 'Configuration Data' value */
+  Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
+         2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
+  FullResourceDescriptor = MmAllocateMemory(Size);
+  if (FullResourceDescriptor == NULL)
+    {
+      DbgPrint((DPRINT_HWDETECT,
+               "Failed to allocate resource descriptor\n"));
+      return;
+    }
+
+  /* Initialize resource descriptor */
+  memset(FullResourceDescriptor, 0, Size);
+  FullResourceDescriptor->InterfaceType = Isa;
+  FullResourceDescriptor->BusNumber = 0;
+  FullResourceDescriptor->PartialResourceList.Count = 3;
+
+  /* Set Interrupt */
+  PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0];
+  PartialDescriptor->Type = CmResourceTypeInterrupt;
+  PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
+  PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+  PartialDescriptor->u.Interrupt.Level = 1;
+  PartialDescriptor->u.Interrupt.Vector = 1;
+  PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
+
+  /* Set IO Port 0x60 */
+  PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[1];
+  PartialDescriptor->Type = CmResourceTypePort;
+  PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+  PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
+  PartialDescriptor->u.Port.Start = (U64)0x60;
+  PartialDescriptor->u.Port.Length = 1;
+
+  /* Set IO Port 0x64 */
+  PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[2];
+  PartialDescriptor->Type = CmResourceTypePort;
+  PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+  PartialDescriptor->Flags = CM_RESOURCE_PORT_IO;
+  PartialDescriptor->u.Port.Start = (U64)0x64;
+  PartialDescriptor->u.Port.Length = 1;
+
+  /* Set 'Configuration Data' value */
+  Error = RegSetValue(ControllerKey,
+                     "Configuration Data",
+                     REG_FULL_RESOURCE_DESCRIPTOR,
+                     (PU8)FullResourceDescriptor,
+                     Size);
+  MmFreeMemory(FullResourceDescriptor);
+  if (Error != ERROR_SUCCESS)
+    {
+      DbgPrint((DPRINT_HWDETECT,
+               "RegSetValue(Configuration Data) failed (Error %u)\n",
+               (int)Error));
+      return;
+    }
+
+  DetectKeyboardPeripheral(ControllerKey);
+}
+
+
 static VOID
 PS2ControllerWait(VOID)
 {
@@ -1680,6 +1931,75 @@ DetectPS2Mouse(HKEY BusKey)
 }
 
 
+static VOID
+DetectDisplayController(HKEY BusKey)
+{
+  CHAR Buffer[80];
+  HKEY ControllerKey;
+  U16 VesaVersion;
+  S32 Error;
+
+  Error = RegCreateKey(BusKey,
+                      "DisplayController\\0",
+                      &ControllerKey);
+  if (Error != ERROR_SUCCESS)
+    {
+      DbgPrint((DPRINT_HWDETECT, "Failed to create controller key\n"));
+      return;
+    }
+  DbgPrint((DPRINT_HWDETECT, "Created key: PointerController\\0\n"));
+
+  /* Set 'ComponentInformation' value */
+  SetComponentInformation(ControllerKey,
+                         0x00,
+                         0,
+                         0xFFFFFFFF);
+
+  /* FIXME: Set 'ComponentInformation' value */
+
+  VesaVersion = BiosIsVesaSupported();
+  if (VesaVersion != 0)
+    {
+      DbgPrint((DPRINT_HWDETECT,
+               "VESA version %c.%c\n",
+               (VesaVersion >> 8) + '0',
+               (VesaVersion & 0xFF) + '0'));
+    }
+  else
+    {
+      DbgPrint((DPRINT_HWDETECT,
+               "VESA not supported\n"));
+    }
+
+  if (VesaVersion >= 0x0200)
+    {
+      strcpy(Buffer,
+             "VBE Display");
+    }
+  else
+    {
+      strcpy(Buffer,
+             "VGA Display");
+    }
+
+  /* Set 'Identifier' value */
+  Error = RegSetValue(ControllerKey,
+                     "Identifier",
+                     REG_SZ,
+                     (PU8)Buffer,
+                     strlen(Buffer) + 1);
+  if (Error != ERROR_SUCCESS)
+    {
+      DbgPrint((DPRINT_HWDETECT,
+               "RegSetValue() failed (Error %u)\n",
+               (int)Error));
+      return;
+    }
+
+  /* FIXME: Add display peripheral (monitor) data */
+}
+
+
 static VOID
 DetectIsaBios(HKEY SystemKey, U32 *BusNumber)
 {
@@ -1701,6 +2021,12 @@ DetectIsaBios(HKEY SystemKey, U32 *BusNumber)
       return;
     }
 
+  /* Set 'Component Information' value similar to my NT4 box */
+  SetComponentInformation(BusKey,
+                          0x0,
+                          0x0,
+                          0xFFFFFFFF);
+
   /* Increment bus number */
   (*BusNumber)++;
 
@@ -1734,7 +2060,7 @@ DetectIsaBios(HKEY SystemKey, U32 *BusNumber)
   FullResourceDescriptor->PartialResourceList.Count = 0;
 
   /* Set 'Configuration Data' value */
-  Error = RegSetValue(SystemKey,
+  Error = RegSetValue(BusKey,
                      "Configuration Data",
                      REG_FULL_RESOURCE_DESCRIPTOR,
                      (PU8) FullResourceDescriptor,
@@ -1748,7 +2074,6 @@ DetectIsaBios(HKEY SystemKey, U32 *BusNumber)
       return;
     }
 
-
   /* Detect ISA/BIOS devices */
   DetectBiosDisks(SystemKey, BusKey);
 
@@ -1757,15 +2082,15 @@ DetectIsaBios(HKEY SystemKey, U32 *BusNumber)
   DetectSerialPorts(BusKey);
 
 #if 0
-  DetectBiosParallelPorts();
+  DetectParallelPorts(BusKey);
 #endif
 
-#if 0
-  DetectBiosKeyboard(BusKey);
-#endif
+  DetectKeyboardController(BusKey);
 
   DetectPS2Mouse(BusKey);
 
+  DetectDisplayController(BusKey);
+
   /* FIXME: Detect more ISA devices */
 }