- Detect PCI busses
authorCasper Hornstrup <chorns@users.sourceforge.net>
Fri, 25 Apr 2003 19:32:51 +0000 (19:32 +0000)
committerCasper Hornstrup <chorns@users.sourceforge.net>
Fri, 25 Apr 2003 19:32:51 +0000 (19:32 +0000)
- Detect IDE controllers and devices
- Improved RegEnumValue()

svn path=/trunk/; revision=4581

12 files changed:
freeldr/freeldr/CHANGELOG
freeldr/freeldr/debug.c
freeldr/freeldr/fs/ext2.c
freeldr/freeldr/include/debug.h
freeldr/freeldr/include/freeldr.h
freeldr/freeldr/include/version.h
freeldr/freeldr/reactos/arcname.c
freeldr/freeldr/reactos/hwdetect.c
freeldr/freeldr/reactos/hwdetect.h
freeldr/freeldr/reactos/registry.c
freeldr/freeldr/ui/ui.c
freeldr/freeldr/video/pixel.c

index 9df0278..6fabd70 100644 (file)
@@ -1,3 +1,9 @@
+Changes in v1.8.9 (4/25/2003) (chorns)
+
+- Detect PCI busses
+- Detect IDE controllers and devices
+- Improved RegEnumValue()
+
 Changes in v1.8.8 (4/25/2003) (ekohl)
 
 - Added memmove().
index 68787c9..4c9a6b0 100644 (file)
@@ -204,6 +204,18 @@ VOID DebugPrintHeader(U32 Mask)
                DebugPrintChar(':');
                DebugPrintChar(' ');
                break;
+       case DPRINT_HWDETECT:
+               DebugPrintChar('H');
+               DebugPrintChar('W');
+               DebugPrintChar('D');
+               DebugPrintChar('E');
+               DebugPrintChar('T');
+               DebugPrintChar('E');
+               DebugPrintChar('C');
+               DebugPrintChar('T');
+               DebugPrintChar(':');
+               DebugPrintChar(' ');
+               break;
        default:
                DebugPrintChar('U');
                DebugPrintChar('N');
index 5526fde..483d8c0 100644 (file)
@@ -845,7 +845,7 @@ BOOL Ext2ReadBlock(U32 BlockNumber, PVOID Buffer)
        // Make sure its a valid block
        if (BlockNumber > Ext2SuperBlock->s_blocks_count)
        {
-               sprintf(ErrorString, "Error reading block %d - block out of range.", BlockNumber);
+               sprintf(ErrorString, "Error reading block %d - block out of range.", (int) BlockNumber);
                FileSystemError(ErrorString);
                return FALSE;
        }
index 33f522c..94c2fa4 100644 (file)
@@ -34,6 +34,7 @@
        #define DPRINT_REGISTRY         0x00000080  // OR this with DebugPrintMask to enable registry messages
        #define DPRINT_REACTOS          0x00000100  // OR this with DebugPrintMask to enable ReactOS messages
        #define DPRINT_LINUX              0x00000200  // OR this with DebugPrintMask to enable Linux messages
+  #define DPRINT_HWDETECT              0x00000400  // OR this with DebugPrintMask to enable hardware detection messages
 
        VOID    DebugInit(VOID);
        VOID    DebugPrint(U32 Mask, char *format, ...);
index 76ca59f..926b644 100644 (file)
@@ -26,6 +26,7 @@
 
 #define BOOL   int
 #define BOOLEAN        int
+typedef BOOLEAN *PBOOLEAN;
 
 #define CHAR   char
 #define PCHAR  char *
@@ -61,6 +62,10 @@ typedef S64                                  __s64;
 
 #endif // __i386__
 
+typedef U8 *PU8;
+typedef U16 *PU16;
+typedef U32 *PU32;
+
 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
 
 #define PACKED __attribute__((packed))
index 3055fc7..20a12da 100644 (file)
@@ -22,7 +22,7 @@
 
 
 /* just some stuff */
-#define VERSION                        "FreeLoader v1.8.8"
+#define VERSION                        "FreeLoader v1.8.9"
 #define COPYRIGHT              "Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>"
 #define AUTHOR_EMAIL   "<brianp@sginet.com>"
 #define BY_AUTHOR              "by Brian Palmer"
@@ -36,7 +36,7 @@
 //
 #define FREELOADER_MAJOR_VERSION       1
 #define FREELOADER_MINOR_VERSION       8
-#define FREELOADER_PATCH_VERSION       8
+#define FREELOADER_PATCH_VERSION       9
 
 
 PUCHAR GetFreeLoaderVersionString(VOID);
index 083ff89..9430445 100644 (file)
@@ -85,7 +85,7 @@ void ConstructArcPath(PUCHAR ArcPath, PUCHAR SystemFolder, U32 Disk, U32 Partiti
                 * floppy disk path:
                 *  multi(0)disk(0)fdisk(x)\path
                 */
-               sprintf(tmp, "fdisk(%d)", Disk);
+               sprintf(tmp, "fdisk(%d)", (int) Disk);
                strcat(ArcPath, tmp);
        }
        else
@@ -94,7 +94,7 @@ void ConstructArcPath(PUCHAR ArcPath, PUCHAR SystemFolder, U32 Disk, U32 Partiti
                 * hard disk path:
                 *  multi(0)disk(0)rdisk(x)partition(y)\path
                 */
-               sprintf(tmp, "rdisk(%d)partition(%d)", (Disk - 0x80), Partition);
+               sprintf(tmp, "rdisk(%d)partition(%d)", (int) (Disk - 0x80), (int) Partition);
                strcat(ArcPath, tmp);
        }
 
index 5c530ba..8898949 100644 (file)
 
 #include <freeldr.h>
 #include <rtl.h>
+#include <mm.h>
+#include <portio.h>
+#include "registry.h"
+#include "hwdetect.h"
 #include <debug.h>
 
+/* ***** BEGIN I/O ***** */
+
+#define MILLISEC     (10)
+#define PRECISION    (8)
+
+static unsigned int delay_count = 1;
+
+static VOID
+__KeStallExecutionProcessor(U32 Loops)
+{
+  register unsigned int i;
+  for (i = 0; i < Loops; i++);
+}
+
+VOID KeStallExecutionProcessor(U32 Microseconds)
+{
+  __KeStallExecutionProcessor((delay_count * Microseconds) / 1000);
+}
+
+#define HZ (100)
+#define CLOCK_TICK_RATE (1193182)
+#define LATCH (CLOCK_TICK_RATE / HZ)
+
+static U32
+Read8254Timer(VOID)
+{
+       U32 Count;
+
+       WRITE_PORT_UCHAR((PU8)0x43, 0x00);
+       Count = READ_PORT_UCHAR((PU8)0x40);
+       Count |= READ_PORT_UCHAR((PU8)0x40) << 8;
+       return Count;
+}
+
+static VOID
+WaitFor8254Wraparound(VOID)
+{
+       U32 CurCount;
+  U32 PrevCount = ~0;
+       S32 Delta;
+
+       CurCount = Read8254Timer();
+
+       do {
+    PrevCount = CurCount;
+    CurCount = Read8254Timer();
+    Delta = CurCount - PrevCount;
+
+    /*
+     * This limit for delta seems arbitrary, but it isn't, it's
+     * slightly above the level of error a buggy Mercury/Neptune
+     * chipset timer can cause.
+     */
+       } while (Delta < 300);
+}
+
+VOID
+HalpCalibrateStallExecution(VOID)
+{
+  U32 i;
+  U32 calib_bit;
+  U32 CurCount;
+
+  /* Initialise timer interrupt with MILLISECOND ms interval        */
+  WRITE_PORT_UCHAR((PU8)0x43, 0x34);  /* binary, mode 2, LSB/MSB, ch 0 */
+  WRITE_PORT_UCHAR((PU8)0x40, LATCH & 0xff); /* LSB */
+  WRITE_PORT_UCHAR((PU8)0x40, LATCH >> 8); /* MSB */
+  
+  /* Stage 1:  Coarse calibration                                   */
+  
+  WaitFor8254Wraparound();
+  
+  delay_count = 1;
+  
+  do {
+    delay_count <<= 1;                  /* Next delay count to try */
+
+    WaitFor8254Wraparound();
+  
+    __KeStallExecutionProcessor(delay_count);      /* Do the delay */
+  
+    CurCount = Read8254Timer();
+  } while (CurCount > LATCH / 2);
+  
+  delay_count >>= 1;              /* Get bottom value for delay     */
+  
+  /* Stage 2:  Fine calibration                                     */
+  
+  calib_bit = delay_count;        /* Which bit are we going to test */
+  
+  for(i=0;i<PRECISION;i++) {
+    calib_bit >>= 1;             /* Next bit to calibrate          */
+    if(!calib_bit) break;        /* If we have done all bits, stop */
+  
+    delay_count |= calib_bit;        /* Set the bit in delay_count */
+  
+    WaitFor8254Wraparound();
+  
+    __KeStallExecutionProcessor(delay_count);      /* Do the delay */
+  
+    CurCount = Read8254Timer();
+    if (CurCount <= LATCH / 2)   /* If a tick has passed, turn the */
+      delay_count &= ~calib_bit; /* calibrated bit back off        */
+  }
+  
+  /* We're finished:  Do the finishing touches                      */
+  
+  delay_count /= (MILLISEC / 2);   /* Calculate delay_count for 1ms */
+}
+
+
+
+/* ***** BEGIN Bus ***** */
+
+/* access type 1 macros */
+#define CONFIG_CMD(bus, dev_fn, where) \
+       (0x80000000 | (((U32)(bus)) << 16) | (((dev_fn) & 0x1F) << 11) | (((dev_fn) & 0xE0) << 3) | ((where) & ~3))
+
+/* access type 2 macros */
+#define IOADDR(dev_fn, where) \
+       (0xC000 | (((dev_fn) & 0x1F) << 8) | (where))
+#define FUNC(dev_fn) \
+       ((((dev_fn) & 0xE0) >> 4) | 0xf0)
+
+static U32 PciBusConfigType = 0;  /* undetermined config type */
+
+static BOOLEAN
+ReadPciConfigUchar(U8 Bus,
+  U8 Slot,
+  U8 Offset,
+  PU8 Value)
+{
+  switch (PciBusConfigType)
+    {
+      case 1:
+        WRITE_PORT_ULONG((PU32)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
+        *Value = READ_PORT_UCHAR((PU8)0xCFC + (Offset & 3));
+        return TRUE;
+      
+      case 2:
+        WRITE_PORT_UCHAR((PU8)0xCF8, FUNC(Slot));
+        WRITE_PORT_UCHAR((PU8)0xCFA, Bus);
+        *Value = READ_PORT_UCHAR((PU8)(IOADDR(Slot, Offset)));
+        WRITE_PORT_UCHAR((PU8)0xCF8, 0);
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOLEAN
+ReadPciConfigUshort(U8 Bus,
+  U8 Slot,
+  U8 Offset,
+  PU16 Value)
+{
+  if ((Offset & 1) != 0)
+    {
+      return FALSE;
+    }
+  
+  switch (PciBusConfigType)
+    {
+      case 1:
+        WRITE_PORT_ULONG((PU32)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
+        *Value = READ_PORT_USHORT((PU16)0xCFC + (Offset & 1));
+        return TRUE;
+
+      case 2:
+        WRITE_PORT_UCHAR((PU8)0xCF8, FUNC(Slot));
+        WRITE_PORT_UCHAR((PU8)0xCFA, Bus);
+        *Value = READ_PORT_USHORT((PU16)(IOADDR(Slot, Offset)));
+        WRITE_PORT_UCHAR((PU8)0xCF8, 0);
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOLEAN
+ReadPciConfigUlong(U8 Bus,
+  U8 Slot,
+  U8 Offset,
+  PU32 Value)
+{
+  if ((Offset & 3) != 0)
+    {
+      return FALSE;
+    }
+  
+  switch (PciBusConfigType)
+    {
+      case 1:
+        WRITE_PORT_ULONG((PU32)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
+        *Value = READ_PORT_ULONG((PU32)0xCFC);
+        return TRUE;
+      
+      case 2:
+        WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
+        WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
+        *Value = READ_PORT_ULONG((PU32)(IOADDR(Slot, Offset)));
+        WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static U32
+GetPciBusConfigType(VOID)
+{
+  U32 Value;
+
+  WRITE_PORT_UCHAR((PU8)0xCFB, 0x01);
+  Value = READ_PORT_ULONG((PU32)0xCF8);
+  WRITE_PORT_ULONG((PU32)0xCF8, 0x80000000);
+  if (READ_PORT_ULONG((PU32)0xCF8) == 0x80000000)
+    {
+      WRITE_PORT_ULONG((PU32)0xCF8, Value);
+      DbgPrint((DPRINT_HWDETECT, "Pci bus type 1 found\n"));
+      return 1;
+    }
+  WRITE_PORT_ULONG((PU32)0xCF8, Value);
+  
+  WRITE_PORT_UCHAR((PU8)0xCFB, 0x00);
+  WRITE_PORT_UCHAR((PU8)0xCF8, 0x00);
+  WRITE_PORT_UCHAR((PU8)0xCFA, 0x00);
+  if (READ_PORT_UCHAR((PU8)0xCF8) == 0x00 &&
+    READ_PORT_UCHAR((PU8)0xCFB) == 0x00)
+    {
+      DbgPrint((DPRINT_HWDETECT, "Pci bus type 2 found\n"));
+      return 2;
+    }
+
+  DbgPrint((DPRINT_HWDETECT, "No pci bus found\n"));
+  return 0;
+}
+
+static U32
+HalpGetPciData(U32 BusNumber,
+  U32 SlotNumber,
+  PVOID Buffer,
+  U32 Offset,
+  U32 Length)
+{
+  PVOID Ptr = Buffer;
+  U32 Address = Offset;
+  U32 Len = Length;
+  U32 Vendor;
+  UCHAR HeaderType;
+  
+  if ((Length == 0) || (PciBusConfigType == 0))
+    return 0;
+  
+  ReadPciConfigUlong(BusNumber,
+    SlotNumber & 0x1F,
+    0x00,
+    &Vendor);
+  /* some broken boards return 0 if a slot is empty: */
+  if (Vendor == 0xFFFFFFFF || Vendor == 0)
+    {
+      if (BusNumber == 0 && Offset == 0 && Length >= 2)
+        {
+          *(PU16)Buffer = PCI_INVALID_VENDORID;
+          return 2;
+        }
+      return 0;
+    }
+  
+  /* 0E=PCI_HEADER_TYPE */
+  ReadPciConfigUchar(BusNumber,
+    SlotNumber & 0x1F,
+    0x0E,
+    &HeaderType);
+  if (((HeaderType & PCI_MULTIFUNCTION) == 0) && ((SlotNumber & 0xE0) != 0))
+    {
+      if (Offset == 0 && Length >= 2)
+        {
+          *(PU16)Buffer = PCI_INVALID_VENDORID;
+          return 2;
+        }
+      return 0;
+    }
+  ReadPciConfigUlong(BusNumber,
+    SlotNumber,
+    0x00,
+    &Vendor);
+
+  /* some broken boards return 0 if a slot is empty: */
+  if (Vendor == 0xFFFFFFFF || Vendor == 0)
+    {
+      if (BusNumber == 0 && Offset == 0 && Length >= 2)
+        {
+          *(PU16)Buffer = PCI_INVALID_VENDORID;
+          return 2;
+        }
+        return 0;
+    }
+  
+  if ((Address & 1) && (Len >= 1))
+    {
+      ReadPciConfigUchar(BusNumber,
+        SlotNumber,
+        Address,
+        Ptr);
+      Ptr = Ptr + 1;
+      Address++;
+      Len--;
+    }
+  
+  if ((Address & 2) && (Len >= 2))
+    {
+      ReadPciConfigUshort(BusNumber,
+        SlotNumber,
+        Address,
+        Ptr);
+      Ptr = Ptr + 2;
+      Address += 2;
+      Len -= 2;
+    }
+  
+  while (Len >= 4)
+    {
+      ReadPciConfigUlong(BusNumber,
+        SlotNumber,
+        Address,
+        Ptr);
+        Ptr = Ptr + 4;
+        Address += 4;
+        Len -= 4;
+    }
+  
+  if (Len >= 2)
+    {
+      ReadPciConfigUshort(BusNumber,
+      SlotNumber,
+      Address,
+      Ptr);
+      Ptr = Ptr + 2;
+      Address += 2;
+      Len -= 2;
+    }
+  
+  if (Len >= 1)
+    {
+      ReadPciConfigUchar(BusNumber,
+        SlotNumber,
+        Address,
+        Ptr);
+      Ptr = Ptr + 1;
+      Address++;
+      Len--;
+    }
+  
+  return Length - Len;
+}
+
+U32
+HalGetBusDataByOffset(BUS_DATA_TYPE BusDataType,
+  U32 BusNumber,
+  U32 SlotNumber,
+  PVOID Buffer,
+  U32 Offset,
+  U32 Length)
+{
+  U32 Result;
+
+  if (BusDataType == PCIConfiguration)
+    {
+      Result = HalpGetPciData(BusNumber,
+        SlotNumber,
+        Buffer,
+        Offset,
+        Length);
+    }
+  else
+    {
+       DbgPrint((DPRINT_WARNING, "Unknown bus data type %d", (U32) BusDataType));
+       Result = 0;
+    }
+
+  return Result;
+}
+
+U32
+HalGetBusData(BUS_DATA_TYPE BusDataType,
+  U32 BusNumber,
+  U32 SlotNumber,
+  PVOID Buffer,
+  U32 Length)
+{
+  return (HalGetBusDataByOffset(BusDataType,
+    BusNumber,
+    SlotNumber,
+    Buffer,
+    0,
+    Length));
+}
+
+/* ***** END Bus ***** */
+
+
+
+/* ***** BEGIN Helper functions ***** */
+
+static LIST_ENTRY BusKeyListHead; /* REGISTRY_BUS_INFORMATION */
+
+static VOID
+RegisterBusKey(HKEY Key, INTERFACE_TYPE BusType, U32 BusNumber)
+{
+  PREGISTRY_BUS_INFORMATION BusKey;
+
+  BusKey = MmAllocateMemory(sizeof(REGISTRY_BUS_INFORMATION));
+  if (BusKey == NULL)
+    return;
+
+  BusKey->BusType = BusType;
+  BusKey->BusNumber = BusNumber;
+  InsertTailList(&BusKeyListHead, &BusKey->ListEntry);
+}
+
+
+static HKEY
+GetBusKey(INTERFACE_TYPE BusType, U32 BusNumber)
+{
+  PREGISTRY_BUS_INFORMATION BusKey;
+  PLIST_ENTRY ListEntry;
+
+  ListEntry = BusKeyListHead.Flink;
+  while (ListEntry != &BusKeyListHead)
+       {
+         BusKey = CONTAINING_RECORD(ListEntry,
+        REGISTRY_BUS_INFORMATION,
+        ListEntry);
+
+      if ((BusKey->BusType == BusType) && (BusKey->BusNumber == BusNumber))
+        {
+          return BusKey->BusKey;
+        }
+
+         ListEntry = ListEntry->Flink;
+       }
+
+  DbgPrint((DPRINT_WARNING, "Key not found for BysType %d and BusNumber %d\n",
+    BusType, BusNumber));
+  return NULL;
+}
+
+
+static HKEY
+CreateOrOpenKey(HKEY RelativeKey, PCHAR KeyName)
+{
+  HKEY Key;
+  S32 Error;
+
+  Error = RegOpenKey(RelativeKey,
+    KeyName,
+    &Key);
+  if (Error == ERROR_SUCCESS)
+    {
+      return Key;
+    }
+
+  Error = RegCreateKey(RelativeKey,
+    KeyName,
+    &Key);
+  if (Error != ERROR_SUCCESS)
+    {
+      DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
+      return NULL;
+    }
+
+  return Key;
+}
+
+/* ***** END Helper functions ***** */
+
+
+
+/* ***** BEGIN ATA ***** */
+
+typedef struct _PCI_NATIVE_CONTROLLER 
+{
+  U16 VendorID;
+  U16 DeviceID;
+} PCI_NATIVE_CONTROLLER, *PPCI_NATIVE_CONTROLLER;
+
+PCI_NATIVE_CONTROLLER const PciNativeController[] = 
+{
+  {
+       0x105A,             // Promise 
+       0x4D68,             // PDC20268, Ultra100TX2
+  },
+  {
+       0x105A,             // Promise 
+       0x4D30,             // PDC20267, Ultra100
+  }
+};
+
+static PCI_SLOT_NUMBER LastSlotNumber;
+
+static BOOLEAN AtdiskPrimaryClaimed = FALSE;
+static BOOLEAN AtdiskSecondaryClaimed = FALSE;
+
+inline void
+IDESwapBytePairs(char *Buf,
+  int Cnt)
+{
+  char t;
+  int i;
+
+  for (i = 0; i < Cnt; i += 2)
+    {
+      t = Buf[i];
+      Buf[i] = Buf[i+1];
+      Buf[i+1] = t;
+    }
+}
+
+/*
+ * AtapiPolledRead
+ *
+ * DESCRIPTION:
+ *   Read a sector of data from the drive in a polled fashion.
+ * ARGUMENTS:
+ *   CommandPort
+ *     Address of command port for drive
+ *   ControlPort
+ *     Address of control port for drive
+ *   PreComp
+ *     Value to write to precomp register
+ *   SectorCnt
+ *     Value to write to sectorCnt register
+ *   SectorNum
+ *     Value to write to sectorNum register
+ *   CylinderLow
+ *     Value to write to CylinderLow register
+ *   CylinderHigh
+ *     Value to write to CylinderHigh register
+ *   DrvHead
+ *     Value to write to Drive/Head register
+ *   Command
+ *     Value to write to Command register
+ *   Buffer
+ *     Buffer for output data
+ * RETURNS:
+ *   0 is success, non 0 is an error code
+ */
+static S32
+AtapiPolledRead(U32 CommandPort,
+  U32 ControlPort,
+  U8 PreComp,
+  U8 SectorCnt,
+  U8 SectorNum,
+  U8 CylinderLow,
+  U8 CylinderHigh,
+  U8 DrvHead,
+  U8 Command,
+  U8 *Buffer)
+{
+  U32 SectorCount = 0;
+  U32 RetryCount;
+  BOOLEAN Junk = FALSE;
+  U8 Status;
+
+  /* Wait for BUSY to clear */
+  for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
+    {
+      Status = IDEReadStatus(CommandPort);
+      if (!(Status & IDE_SR_BUSY))
+        {
+          break;
+        }
+      KeStallExecutionProcessor(10);
+    }
+  if (RetryCount >= IDE_MAX_BUSY_RETRIES)
+    {
+      DbgPrint((DPRINT_HWDETECT, "Drive is BUSY for too long\n"));
+      return(IDE_ER_ABRT);
+    }
+
+  /* Write Drive/Head to select drive */
+  IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);
+  KeStallExecutionProcessor(500);
+
+  /* Disable interrupts */
+  IDEWriteDriveControl(ControlPort, IDE_DC_nIEN);
+  KeStallExecutionProcessor(500);
+
+  /* Issue command to drive */
+  if (DrvHead & IDE_DH_LBA)
+    {
+      DbgPrint((DPRINT_HWDETECT, "READ:DRV=%d:LBA=1:BLK=%d:SC=%x:CM=%x\n",
+            DrvHead & IDE_DH_DRV1 ? 1 : 0,
+            ((DrvHead & 0x0f) << 24) + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum,
+            SectorCnt,
+            Command));
+    }
+  else
+    {
+      DbgPrint((DPRINT_HWDETECT, "READ:DRV=%d:LBA=0:CH=%x:CL=%x:HD=%x:SN=%x:SC=%x:CM=%x\n",
+            DrvHead & IDE_DH_DRV1 ? 1 : 0,
+            CylinderHigh,
+            CylinderLow,
+            DrvHead & 0x0f,
+            SectorNum,
+            SectorCnt,
+            Command));
+    }
+
+  /* Setup command parameters */
+  IDEWritePrecomp(CommandPort, PreComp);
+  IDEWriteSectorCount(CommandPort, SectorCnt);
+  IDEWriteSectorNum(CommandPort, SectorNum);
+  IDEWriteCylinderHigh(CommandPort, CylinderHigh);
+  IDEWriteCylinderLow(CommandPort, CylinderLow);
+  IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);
+
+  /* Issue the command */
+  IDEWriteCommand(CommandPort, Command);
+  KeStallExecutionProcessor(50);
+
+  /* wait for DRQ or error */
+  for (RetryCount = 0; RetryCount < IDE_MAX_POLL_RETRIES; RetryCount++)
+    {
+      Status = IDEReadStatus(CommandPort);
+      if (!(Status & IDE_SR_BUSY))
+       {
+         if (Status & IDE_SR_ERR)
+           {
+             IDEWriteDriveControl(ControlPort, 0);
+             KeStallExecutionProcessor(50);
+             IDEReadStatus(CommandPort);
+
+             return(IDE_ER_ABRT);
+           }
+         if (Status & IDE_SR_DRQ)
+           {
+             break;
+           }
+         else
+           {
+             IDEWriteDriveControl(ControlPort, 0);
+             KeStallExecutionProcessor(50);
+             IDEReadStatus(CommandPort);
+
+             return(IDE_ER_ABRT);
+           }
+       }
+      KeStallExecutionProcessor(10);
+    }
+
+  /*  timed out  */
+  if (RetryCount >= IDE_MAX_POLL_RETRIES)
+    {
+      IDEWriteDriveControl(ControlPort, 0);
+      KeStallExecutionProcessor(50);
+      IDEReadStatus(CommandPort);
+
+      return(IDE_ER_ABRT);
+    }
+
+  while (1)
+    {
+      /* Read data into buffer */
+      if (Junk == FALSE)
+       {
+         IDEReadBlock(CommandPort, Buffer, IDE_SECTOR_BUF_SZ);
+         Buffer += IDE_SECTOR_BUF_SZ;
+       }
+      else
+       {
+         U8 JunkBuffer[IDE_SECTOR_BUF_SZ];
+         IDEReadBlock(CommandPort, JunkBuffer, IDE_SECTOR_BUF_SZ);
+       }
+      SectorCount++;
+
+      /* Check for error or more sectors to read */
+      for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
+       {
+         Status = IDEReadStatus(CommandPort);
+         if (!(Status & IDE_SR_BUSY))
+           {
+             if (Status & IDE_SR_ERR)
+               {
+                 IDEWriteDriveControl(ControlPort, 0);
+                 KeStallExecutionProcessor(50);
+                 IDEReadStatus(CommandPort);
+
+                 return(IDE_ER_ABRT);
+               }
+             if (Status & IDE_SR_DRQ)
+               {
+                 if (SectorCount >= SectorCnt)
+                   {
+                     DbgPrint((DPRINT_HWDETECT, "Buffer size exceeded\n"));
+                     Junk = TRUE;
+                   }
+                 break;
+               }
+             else
+               {
+                 if (SectorCount > SectorCnt)
+                   {
+                     DbgPrint((DPRINT_HWDETECT, "Read %d sectors of junk\n",
+                            SectorCount - SectorCnt));
+                   }
+                 IDEWriteDriveControl(ControlPort, 0);
+                 KeStallExecutionProcessor(50);
+                 IDEReadStatus(CommandPort);
+
+                 return(0);
+               }
+           }
+       }
+    }
+}
+
+/*
+ * AtapiIdentifyDevice
+ *
+ * DESCRIPTION:
+ *   Get the identification block from the drive
+ *
+ * ARGUMENTS:
+ *   CommandPort
+ *     Address of the command port
+ *      ControlPort
+ *     Address of the control port
+ *   DriveNum
+ *     The drive index (0,1)
+ *   Atapi
+ *     Send an ATA(FALSE) or an ATAPI(TRUE) identify comand
+ *   DrvParms
+ *     Address to write drive identication block
+ *
+ * RETURNS:
+ *       TRUE: The drive identification block was retrieved successfully
+ *       FALSE: an error ocurred
+ */
+static BOOLEAN
+AtapiIdentifyDevice(U32 CommandPort,
+  U32 ControlPort,
+  U32 DriveNum,
+  BOOLEAN Atapi,
+  PIDE_DRIVE_IDENTIFY DrvParms)
+{
+  S32 i;
+
+  /* Get the Drive Identify block from drive or die */
+  if (AtapiPolledRead(CommandPort,
+    ControlPort,
+    0,
+    1,
+    0,
+    0,
+    0,
+    (DriveNum ? IDE_DH_DRV1 : 0),
+    (Atapi ? IDE_CMD_IDENT_ATAPI_DRV : IDE_CMD_IDENT_ATA_DRV),
+    (PU8)DrvParms) != 0)
+    {
+      DbgPrint((DPRINT_HWDETECT, "IDEPolledRead() failed\n"));
+      return(FALSE);
+    }
+
+  /* Report on drive parameters if debug mode */
+  IDESwapBytePairs(DrvParms->SerialNumber, 20);
+  IDESwapBytePairs(DrvParms->FirmwareRev, 8);
+  IDESwapBytePairs(DrvParms->ModelNumber, 40);
+  DbgPrint((DPRINT_HWDETECT, "Config:%x  Cyls:%d  Heads:%d  Sectors/Track:%d  Gaps:%d %d\n",
+    DrvParms->ConfigBits,
+    DrvParms->LogicalCyls,
+    DrvParms->LogicalHeads,
+    DrvParms->SectorsPerTrack,
+    DrvParms->InterSectorGap,
+    DrvParms->InterSectorGapSize));
+  DbgPrint((DPRINT_HWDETECT, "Bytes/PLO:%d  Vendor Cnt:%d  Serial number:[%s]\n",
+    DrvParms->BytesInPLO,
+    DrvParms->VendorUniqueCnt,
+    DrvParms->SerialNumber));
+  DbgPrint((DPRINT_HWDETECT, "Cntlr type:%d  BufSiz:%d  ECC bytes:%d  Firmware Rev:[%s]\n",
+    DrvParms->ControllerType,
+    DrvParms->BufferSize * IDE_SECTOR_BUF_SZ,
+    DrvParms->ECCByteCnt,
+    DrvParms->FirmwareRev));
+  DbgPrint((DPRINT_HWDETECT, "Model:[%s]\n", DrvParms->ModelNumber));
+  DbgPrint((DPRINT_HWDETECT, "RWMultMax?:%x  RWMult?:%x  LBA:%d  DMA:%d  MinPIO:%d ns  MinDMA:%d ns\n",
+    (DrvParms->RWMultImplemented),
+    (DrvParms->RWMultCurrent) & 0xff,
+    (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? 1 : 0,
+    (DrvParms->Capabilities & IDE_DRID_DMA_SUPPORTED) ? 1 : 0,
+    DrvParms->MinPIOTransTime,
+    DrvParms->MinDMATransTime));
+  DbgPrint((DPRINT_HWDETECT, "TM:Cyls:%d  Heads:%d  Sectors/Trk:%d Capacity:%d\n",
+    DrvParms->TMCylinders,
+    DrvParms->TMHeads,
+    DrvParms->TMSectorsPerTrk,
+    (U32)(DrvParms->TMCapacityLo + (DrvParms->TMCapacityHi << 16))));
+
+  DbgPrint((DPRINT_HWDETECT, "TM:SectorCount: 0x%x%x = %d\n",
+    DrvParms->TMSectorCountHi,
+    DrvParms->TMSectorCountLo,
+    (U32)((DrvParms->TMSectorCountHi << 16) + DrvParms->TMSectorCountLo)));
+
+  if (!Atapi && 0 != (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED))
+    {
+      /* LBA ATA drives always have a sector size of 512 */
+      DrvParms->BytesPerSector = 512;
+    }
+  else
+    {
+      if (DrvParms->BytesPerSector == 0)
+        {
+          DbgPrint((DPRINT_HWDETECT, "BytesPerSector is 0. Defaulting to 512\n"));
+          DrvParms->BytesPerSector = 512;
+        }
+      else
+        {
+          DbgPrint((DPRINT_HWDETECT, "BytesPerSector %d\n", DrvParms->BytesPerSector));
+          for (i = 15; i >= 0; i--)
+            {
+              if (DrvParms->BytesPerSector & (1 << i))
+                {
+                  DrvParms->BytesPerSector = 1 << i;
+                  break;
+                }
+            }
+        }
+    }
+  DbgPrint((DPRINT_HWDETECT, "BytesPerSector %d\n", DrvParms->BytesPerSector));
+
+  return(TRUE);
+}
+
+/*
+ * AtapiFindDevices
+ *
+ * DESCRIPTION:
+ *   Find all devices on a controller
+ *
+ * ARGUMENTS:
+ *   CommandPort
+ *     Address of the command port
+ *      ControlPort
+ *     Address of the control port
+ *   DeviceParams
+ *     Buffer for drive parameters
+ *
+ * RETURNS:
+ *       Number of devices found
+ */
+static U32
+AtapiFindDevices(U32 CommandPortBase,
+  U32 ControlPortBase,
+  PIDE_DRIVE_IDENTIFY DeviceParams)
+{
+  U32 DevicesFound = 0;
+  U32 UnitNumber;
+  U32 Retries;
+  U8 High, Low;
+
+  DbgPrint((DPRINT_HWDETECT, "AtapiFindDevices(CommandPortBase: %x, ControlPortBase %x)\n",
+    CommandPortBase, ControlPortBase));
+
+  for (UnitNumber = 0; UnitNumber < 2; UnitNumber++)
+    {
+      /* Select drive */
+      IDEWriteDriveHead(CommandPortBase,
+        IDE_DH_FIXED | (UnitNumber ? IDE_DH_DRV1 : 0));
+      KeStallExecutionProcessor(500);
+
+      /* Disable interrupts */
+      IDEWriteDriveControl(ControlPortBase,
+        IDE_DC_nIEN);
+      KeStallExecutionProcessor(500);
+
+      /* Check if a device is attached to the interface */
+      IDEWriteCylinderHigh(CommandPortBase, 0xaa);
+      IDEWriteCylinderLow(CommandPortBase, 0x55);
+
+      High = IDEReadCylinderHigh(CommandPortBase);
+      Low = IDEReadCylinderLow(CommandPortBase);
+
+      IDEWriteCylinderHigh(CommandPortBase, 0);
+      IDEWriteCylinderLow(CommandPortBase, 0);
+
+      if (Low != 0x55 || High != 0xaa)
+        {
+          DbgPrint((DPRINT_HWDETECT, "No Drive found. UnitNumber %d CommandPortBase %x\n",
+            UnitNumber, CommandPortBase));
+          continue;
+        }
+
+      IDEWriteCommand(CommandPortBase, IDE_CMD_RESET);
+
+      for (Retries = 0; Retries < 20000; Retries++)
+        {
+             if (!(IDEReadStatus(CommandPortBase) & IDE_SR_BUSY))
+               {
+                 break;
+               }
+             KeStallExecutionProcessor(150);
+           }
+
+      if (Retries >= 20000)
+        {
+          DbgPrint((DPRINT_HWDETECT, "Timeout on drive %d\n", UnitNumber));
+          continue;
+        }
+
+      High = IDEReadCylinderHigh(CommandPortBase);
+      Low = IDEReadCylinderLow(CommandPortBase);
+
+      DbgPrint((DPRINT_HWDETECT, "Check drive %d: High 0x%x Low 0x%x\n",
+            UnitNumber,
+            High,
+            Low));
+
+      if (High == 0xEB && Low == 0x14)
+        {
+          if (AtapiIdentifyDevice(CommandPortBase,
+            ControlPortBase,
+            UnitNumber,
+            TRUE,
+            &DeviceParams[UnitNumber]))
+            {
+              DbgPrint((DPRINT_HWDETECT, "ATAPI drive found\n"));
+              DevicesFound++;
+               }
+             else
+               {
+                 DbgPrint((DPRINT_HWDETECT, "No ATAPI drive found\n"));
+           }
+        }
+   else
+     {
+       if (AtapiIdentifyDevice(CommandPortBase,
+         ControlPortBase,
+         UnitNumber,
+         FALSE,
+         &DeviceParams[UnitNumber]))
+           {
+            DbgPrint((DPRINT_HWDETECT, "IDE drive found\n"));
+             DevicesFound++;
+           }
+         else
+           {
+             DbgPrint((DPRINT_HWDETECT, "No IDE drive found\n"));
+           }
+      }
+    }
+
+  /* Reset pending interrupts */
+  IDEReadStatus(CommandPortBase);
+  /* Reenable interrupts */
+  IDEWriteDriveControl(ControlPortBase, 0);
+  KeStallExecutionProcessor(500);
+  /* Return with drive 0 selected */
+  IDEWriteDriveHead(CommandPortBase, IDE_DH_FIXED);
+  KeStallExecutionProcessor(500);
+
+  DbgPrint((DPRINT_HWDETECT, "AtapiFindDevices() Done (DevicesFound %d)\n", DevicesFound));
+
+  return(DevicesFound);
+}
+
+// TRUE if a controller was found, FALSE if not
+static BOOLEAN
+AtapiFindCompatiblePciController(U32 SystemIoBusNumber,
+       PU32 SystemSlotNumber,
+  PU32 CommandPortBase,
+  PU32 ControlPortBase,
+       PU32 BusMasterPortBase,
+  PU32 InterruptVector,
+  PU32 DevicesFound,
+  PIDE_DRIVE_IDENTIFY DeviceParams,
+  PBOOLEAN Again)
+{
+  PCI_SLOT_NUMBER SlotNumber;
+  PCI_COMMON_CONFIG PciConfig;
+  U32 DataSize;
+  U32 StartDeviceNumber;
+  U32 DeviceNumber;
+  U32 StartFunctionNumber;
+  U32 FunctionNumber;
+  BOOLEAN ChannelFound;
+  U32 BusMasterBasePort = 0;
+
+  *Again = FALSE;
+
+  /* both channels were claimed: exit */
+  if (AtdiskPrimaryClaimed == TRUE &&
+    AtdiskSecondaryClaimed == TRUE)
+    return FALSE;
+
+  SlotNumber.u.AsULONG = *SystemSlotNumber;
+  StartDeviceNumber = SlotNumber.u.bits.DeviceNumber;
+  StartFunctionNumber = SlotNumber.u.bits.FunctionNumber;
+  for (DeviceNumber = StartDeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
+    {
+      SlotNumber.u.bits.DeviceNumber = DeviceNumber;
+      for (FunctionNumber = StartFunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
+        {
+          SlotNumber.u.bits.FunctionNumber = FunctionNumber;
+          ChannelFound = FALSE;
+  
+          DataSize = HalGetBusData(PCIConfiguration,
+            SystemIoBusNumber,
+            SlotNumber.u.AsULONG,
+            &PciConfig,
+            PCI_COMMON_HDR_LENGTH);
+          if (DataSize != PCI_COMMON_HDR_LENGTH)
+             {
+               if (FunctionNumber == 0)
+                 {
+                   break;
+                 }
+                else
+                 {
+                   continue;
+                 }
+              }
+  
+       DbgPrint((DPRINT_HWDETECT, "BaseClass %x  SubClass %x\n", PciConfig.BaseClass, PciConfig.SubClass));
+       if (PciConfig.BaseClass == 0x01 &&
+           PciConfig.SubClass == 0x01)
+               {
+                  /* both channels are in compatibility mode */
+                  DbgPrint((DPRINT_HWDETECT, "Bus %d  Device %d  Func %d  VenID 0x%x  DevID 0x%x\n",
+                          SystemIoBusNumber,
+                          SlotNumber.u.bits.DeviceNumber,
+                          SlotNumber.u.bits.FunctionNumber,
+                          PciConfig.VendorID,
+                          PciConfig.DeviceID));
+        
+                  DbgPrint((DPRINT_HWDETECT, "Found IDE controller in compatibility mode\n"));
+    
+                  if (PciConfig.ProgIf & 0x80)
+                  {
+                     DbgPrint((DPRINT_HWDETECT, "Found IDE Bus Master controller!\n"));
+                     if (PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_SPACE)
+                     {
+                               BusMasterBasePort = PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_ADDRESS_MASK;
+                               DbgPrint((DPRINT_HWDETECT, "IDE Bus Master Registers at IO %x\n", BusMasterBasePort));
+                     }
+                  }
+                  if (AtdiskPrimaryClaimed == FALSE)
+                  {
+                     /* Both channels unclaimed: Claim primary channel */
+                     DbgPrint((DPRINT_HWDETECT, "Primary channel\n"));
+                  AtdiskPrimaryClaimed = TRUE;
+                  *CommandPortBase = 0x1F0;
+                  *ControlPortBase = 0x3F4;
+                  *BusMasterPortBase = BusMasterBasePort;
+                  *InterruptVector = 14;
+                     *Again = TRUE;
+          
+                  }
+                  else if (AtdiskSecondaryClaimed == FALSE)
+                  {
+                     /* Primary channel already claimed: claim secondary channel */
+                     DbgPrint((DPRINT_HWDETECT, "Secondary channel\n"));
+                  AtdiskSecondaryClaimed = TRUE;
+                  *CommandPortBase = 0x170;
+                  *ControlPortBase = 0x374;
+                  *BusMasterPortBase = BusMasterBasePort ? BusMasterBasePort + 8 : 0;
+                  *InterruptVector = 15;
+                     *Again = FALSE;
+                  }
+        
+                  /* Find attached devices */
+             *DevicesFound = AtapiFindDevices(*CommandPortBase, *ControlPortBase, DeviceParams);
+             *SystemSlotNumber = SlotNumber.u.AsULONG;
+             return TRUE;
+               }
+  
+       if (FunctionNumber == 0 && !(PciConfig.HeaderType & PCI_MULTIFUNCTION))
+               {
+                  break;
+               }
+      }        
+      StartFunctionNumber = 0;
+    }
+  return FALSE;
+}
+
+// TRUE if a controller was found, FALSE if not
+static BOOLEAN
+AtapiFindNativePciController(U32 SystemIoBusNumber,
+       PU32 SystemSlotNumber,
+  PU32 CommandPortBase,
+  PU32 ControlPortBase,
+       PU32 BusMasterPortBase,
+  PU32 InterruptVector,
+  PU32 DevicesFound,
+  PIDE_DRIVE_IDENTIFY DeviceParams,
+  PBOOLEAN Again)
+{
+  PCI_COMMON_CONFIG PciConfig;
+  PCI_SLOT_NUMBER SlotNumber;
+  U32 DataSize;
+  U32 DeviceNumber;
+  U32 StartDeviceNumber;
+  U32 FunctionNumber;
+  U32 StartFunctionNumber;
+  U32 BusMasterBasePort;
+  U32 Count;
+  BOOLEAN ChannelFound;
+
+  SlotNumber.u.AsULONG = *SystemSlotNumber;
+  StartDeviceNumber = SlotNumber.u.bits.DeviceNumber;
+  StartFunctionNumber = SlotNumber.u.bits.FunctionNumber;
+  for (DeviceNumber = StartDeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
+    {
+      SlotNumber.u.bits.DeviceNumber = DeviceNumber;
+      for (FunctionNumber = StartFunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
+        {
+          SlotNumber.u.bits.FunctionNumber = FunctionNumber;
+          DataSize = HalGetBusData(PCIConfiguration,
+            SystemIoBusNumber,
+            SlotNumber.u.AsULONG,
+            &PciConfig,
+            PCI_COMMON_HDR_LENGTH);
+          if (DataSize != PCI_COMMON_HDR_LENGTH)
+            {
+              break;
+            }
+          for (Count = 0; Count < sizeof(PciNativeController)/sizeof(PCI_NATIVE_CONTROLLER); Count++)
+            {
+              if (PciConfig.VendorID == PciNativeController[Count].VendorID &&
+                PciConfig.DeviceID == PciNativeController[Count].DeviceID)
+                {
+                  break;
+                }
+              }
+          if (Count < sizeof(PciNativeController)/sizeof(PCI_NATIVE_CONTROLLER)) 
+            {
+              /* We have found a known native pci ide controller */
+              if ((PciConfig.ProgIf & 0x80) && (PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_SPACE))
+                {
+                  DbgPrint((DPRINT_HWDETECT, "Found IDE Bus Master controller\n"));
+                  BusMasterBasePort = PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_ADDRESS_MASK;
+                  DbgPrint((DPRINT_HWDETECT, "IDE Bus Master Registers at IO %x\n", BusMasterBasePort));
+                }
+              else
+                {
+                  BusMasterBasePort = 0;
+                }
+          
+              DbgPrint((DPRINT_HWDETECT, "VendorID: %04x, DeviceID: %04x\n",
+                PciConfig.VendorID, PciConfig.DeviceID));
+              ChannelFound = FALSE;
+              if (LastSlotNumber.u.AsULONG != SlotNumber.u.AsULONG)
+                {
+                  /* primary channel */
+                  if ((PciConfig.u.type0.BaseAddresses[0] & PCI_ADDRESS_IO_SPACE) &&
+                    (PciConfig.u.type0.BaseAddresses[1] & PCI_ADDRESS_IO_SPACE))
+                    {
+                      /* primary channel is enabled */
+                      ChannelFound = TRUE;
+                      *CommandPortBase = PciConfig.u.type0.BaseAddresses[0] & PCI_ADDRESS_IO_ADDRESS_MASK;
+                      *ControlPortBase = PciConfig.u.type0.BaseAddresses[1] & PCI_ADDRESS_IO_ADDRESS_MASK;
+                      *BusMasterPortBase = BusMasterBasePort;
+                      *InterruptVector = PciConfig.u.type0.InterruptLine;
+    
+                      if (ChannelFound)
+                        {
+                          *DevicesFound = AtapiFindDevices(*CommandPortBase, *ControlPortBase, DeviceParams);
+                          *Again = TRUE;
+                          *SystemSlotNumber = LastSlotNumber.u.AsULONG = SlotNumber.u.AsULONG;
+                          return(TRUE);
+                        }
+                    }
+                }
+              if (!ChannelFound)
+              {
+                /* secondary channel */
+                if ((PciConfig.u.type0.BaseAddresses[2] & PCI_ADDRESS_IO_SPACE) &&
+                  (PciConfig.u.type0.BaseAddresses[3] & PCI_ADDRESS_IO_SPACE))
+                  {
+                    /* secondary channel is enabled */
+                    *CommandPortBase = PciConfig.u.type0.BaseAddresses[2] & PCI_ADDRESS_IO_ADDRESS_MASK;
+                    *ControlPortBase = PciConfig.u.type0.BaseAddresses[3] & PCI_ADDRESS_IO_ADDRESS_MASK;
+                    *BusMasterPortBase = BusMasterBasePort ? BusMasterBasePort + 8 : 0;
+                    *InterruptVector = PciConfig.u.type0.InterruptLine;
+    
+                    if (ChannelFound)
+                      {
+                        *DevicesFound = AtapiFindDevices(*CommandPortBase, *ControlPortBase, DeviceParams);
+                        *Again = FALSE;
+                        LastSlotNumber.u.AsULONG = 0xFFFFFFFF;
+                        return(TRUE);
+                      }
+                  }
+              }
+          }
+        }
+      StartFunctionNumber = 0;
+    }
+  *Again = FALSE;
+  LastSlotNumber.u.AsULONG = 0xFFFFFFFF;
+  
+  return(FALSE);
+}
+
+// TRUE if a controller was found, FALSE if not
+static BOOLEAN
+AtapiFindIsaBusController(U32 SystemIoBusNumber,
+       PU32 SystemSlotNumber,
+  PU32 CommandPortBase,
+  PU32 ControlPortBase,
+       PU32 BusMasterPortBase,
+  PU32 InterruptVector,
+  PU32 DevicesFound,
+  PIDE_DRIVE_IDENTIFY DeviceParams,
+  PBOOLEAN Again)
+{
+  BOOLEAN ChannelFound = FALSE;
+
+  *Again = FALSE;
+
+  if (AtdiskPrimaryClaimed == FALSE)
+    {
+      /* Both channels unclaimed: Claim primary channel */
+      DbgPrint((DPRINT_HWDETECT, "Primary channel\n"));
+      AtdiskPrimaryClaimed = TRUE;
+      ChannelFound = TRUE;
+      *CommandPortBase = 0x1F0;
+      *ControlPortBase = 0x3F4;
+      *BusMasterPortBase = 0;
+      *InterruptVector = 14;
+      *Again = TRUE;
+    }
+  else if (AtdiskSecondaryClaimed == FALSE)
+    {
+      /* Primary channel already claimed: claim secondary channel */
+      DbgPrint((DPRINT_HWDETECT, "Secondary channel\n"));
+      AtdiskSecondaryClaimed = TRUE;
+      ChannelFound = TRUE;
+      *CommandPortBase = 0x170;
+      *ControlPortBase = 0x374;
+      *BusMasterPortBase = 0;
+      *InterruptVector = 15;
+      *Again = FALSE;
+    }
+  else
+    {
+      DbgPrint((DPRINT_HWDETECT, "AtapiFindIsaBusController() both channels claimed\n"));
+      *Again = FALSE;
+      return(FALSE);
+    }
+
+  /* Find attached devices */
+  if (ChannelFound)
+    {
+      *DevicesFound = AtapiFindDevices(*CommandPortBase, *ControlPortBase, DeviceParams);
+      return(TRUE);
+    }
+  *Again = FALSE;
+  return(FALSE);
+}
+
+static VOID
+FindIDEControllers(PDETECTED_STORAGE DetectedStorage)
+{
+  U32 SystemIoBusNumber;
+  U32 SystemSlotNumber;
+  U32 CommandPortBase;
+  U32 ControlPortBase;
+  U32 BusMasterPortBase;
+  U32 InterruptVector;
+  U32 DevicesFound;
+  PDETECTED_STORAGE_CONTROLLER StorageController;
+  BOOLEAN Again;
+  BOOLEAN Found;
+  U32 MaxBus;
+
+  AtdiskPrimaryClaimed = FALSE;
+  AtdiskSecondaryClaimed = FALSE;
+
+/* Search the PCI bus for all IDE controllers */
+
+  MaxBus = 8; /* Max 8 PCI busses */
+
+  SystemIoBusNumber = 0;
+  SystemSlotNumber = 0;
+
+  while (TRUE)
+    {
+         /* Search the PCI bus for compatibility mode IDE controllers */
+      StorageController = MmAllocateMemory(sizeof(DETECTED_STORAGE_CONTROLLER));
+         Found = AtapiFindCompatiblePciController(SystemIoBusNumber,
+        &SystemSlotNumber,
+        &CommandPortBase,
+        &ControlPortBase,
+        &BusMasterPortBase,
+        &InterruptVector,
+        &DevicesFound,
+        &StorageController->IdeDriveIdentify[0],
+        &Again);
+  
+        if (Found)
+          {
+            DbgPrint((DPRINT_HWDETECT, "Found compatible IDE controller\n"));
+
+            StorageController->DriveCount = DevicesFound;
+            StorageController->BusType = PCIBus;
+            StorageController->BusNumber = SystemIoBusNumber;
+            InsertTailList(&DetectedStorage->StorageControllers,
+              &StorageController->ListEntry);
+          }
+        else
+          {
+            MmFreeMemory(StorageController);
+          }
+  
+        if (Again == FALSE)
+          {
+            SystemIoBusNumber++;
+            SystemSlotNumber = 0;
+          }
+  
+        if (SystemIoBusNumber >= MaxBus)
+          {
+            DbgPrint((DPRINT_HWDETECT, "Scanned all PCI buses\n"));
+            break;
+          }
+      }
+
+  /* Search the PCI bus for all IDE controllers */
+
+  SystemIoBusNumber = 0;
+  SystemSlotNumber = 0;
+
+  LastSlotNumber.u.AsULONG = 0;
+
+  while (TRUE)
+    {
+         /* Search the PCI bus for native PCI IDE controllers */
+      StorageController = MmAllocateMemory(sizeof(DETECTED_STORAGE_CONTROLLER));
+         Found = AtapiFindNativePciController(SystemIoBusNumber,
+        &SystemSlotNumber,
+        &CommandPortBase,
+        &ControlPortBase,
+        &BusMasterPortBase,
+        &InterruptVector,
+        &DevicesFound,
+        &StorageController->IdeDriveIdentify[0],
+        &Again);
+
+        if (Found)
+          {
+            DbgPrint((DPRINT_HWDETECT, "Found native PCI IDE controller\n"));
+
+            StorageController->DriveCount = DevicesFound;
+            StorageController->BusType = PCIBus;
+            StorageController->BusNumber = SystemIoBusNumber;
+            InsertTailList(&DetectedStorage->StorageControllers,
+              &StorageController->ListEntry);
+          }
+  
+        if (Again == FALSE)
+          {
+            SystemIoBusNumber++;
+            SystemSlotNumber = 0;
+          }
+        else
+          {
+            MmFreeMemory(StorageController);
+          }
+  
+        if (SystemIoBusNumber >= MaxBus)
+          {
+            DbgPrint((DPRINT_HWDETECT, "Scanned all PCI buses\n"));
+            break;
+          }
+      }
+
+  LastSlotNumber.u.AsULONG = 0xFFFFFFFF;
+
+  SystemIoBusNumber = 0;
+  SystemSlotNumber = 0;
+
+  LastSlotNumber.u.AsULONG = 0;
+
+  while (TRUE)
+    {
+         /* Search the ISA bus for an IDE controller */
+         Found = AtapiFindIsaBusController(SystemIoBusNumber,
+        &SystemSlotNumber,
+        &CommandPortBase,
+        &ControlPortBase,
+        &BusMasterPortBase,
+        &InterruptVector,
+        &DevicesFound,
+        &StorageController->IdeDriveIdentify[0],
+        &Again);
+  
+      if (Found)
+        {
+          DbgPrint((DPRINT_HWDETECT, "Found ISA IDE controller\n"));
+
+          StorageController->DriveCount = DevicesFound;
+          StorageController->BusType = Isa;
+          StorageController->BusNumber = SystemIoBusNumber;
+          InsertTailList(&DetectedStorage->StorageControllers,
+            &StorageController->ListEntry);
+        }
+      else
+        {
+          MmFreeMemory(StorageController);
+        }
+
+      if (Again == FALSE)
+        {
+          break;
+        }
+    }
+}
+
+/* ***** END ATA ***** */
+
+VOID
+DetectStorage(VOID)
+{
+  DETECTED_STORAGE DetectedStorage;
+  PDETECTED_STORAGE_CONTROLLER Controller;
+  PLIST_ENTRY ListEntry;
+  CHAR buf[200];
+  S32 Error;
+  U32 ScsiPortNumber;
+  HKEY ScsiPortKey;
+
+  U32 i;
+  HKEY BusKey;
+  HKEY DiskControllerKey;
+  HKEY DiskPeripheralKey;
+  HKEY DriveKey;
+  CM_INT13_DRIVE_PARAMETER Int13;
+
+  InitializeListHead(&DetectedStorage.StorageControllers);
+
+  FindIDEControllers(&DetectedStorage);
+
+  ScsiPortNumber = 0;
+  ListEntry = DetectedStorage.StorageControllers.Flink;
+  while (ListEntry != &DetectedStorage.StorageControllers)
+       {
+         Controller = CONTAINING_RECORD(ListEntry,
+        DETECTED_STORAGE_CONTROLLER,
+        ListEntry);
+
+      BusKey = GetBusKey(Controller->BusType, Controller->BusNumber);
+    
+      /* Create or open DiskController key */
+      DiskControllerKey = CreateOrOpenKey(BusKey,
+        "DiskController");
+      if (DiskControllerKey == NULL)
+        {
+          DbgPrint((DPRINT_HWDETECT, "CreateOrOpenKey() failed\n"));
+          return;
+        }
+
+      /* Create X key */
+      sprintf(buf, "%d", (int) ScsiPortNumber);
+      Error = RegCreateKey(DiskControllerKey,
+        buf,
+        &ScsiPortKey);
+      if (Error != ERROR_SUCCESS)
+        {
+          DbgPrint((DPRINT_HWDETECT, "RegCreateKey(X) failed (Error %u)\n", (int)Error));
+          return;
+        }
+
+      /* FIXME: Create value: 'Component information' */
+
+      /* FIXME: Create value: 'Configuration data' */
+
+      /* Create DiskPeripheral key */
+      sprintf(buf, "%d", (int) ScsiPortNumber);
+      Error = RegCreateKey(ScsiPortKey,
+        "DiskPeripheral",
+        &DiskPeripheralKey);
+      if (Error != ERROR_SUCCESS)
+        {
+          DbgPrint((DPRINT_HWDETECT, "RegCreateKey(DiskPeripheral) failed (Error %u)\n", (int)Error));
+          return;
+        }
+
+      for (i = 0; i < Controller->DriveCount; i++)
+        {
+          /* Create DiskPeripheral/X key */
+          sprintf(buf, "%d", (int) i);
+          Error = RegCreateKey(DiskPeripheralKey,
+            buf,
+            &DriveKey);
+          if (Error != ERROR_SUCCESS)
+            {
+              DbgPrint((DPRINT_HWDETECT, "RegCreateKey(DiskPeripheral/X) failed (Error %u)\n", (int)Error));
+              return;
+            }
+
+          Int13.DriveSelect = 0;  /* FIXME: What is this? */
+          Int13.MaxCylinders = Controller->IdeDriveIdentify[i].TMCylinders;
+          Int13.SectorsPerTrack = Controller->IdeDriveIdentify[i].TMSectorsPerTrk;
+          Int13.MaxHeads = Controller->IdeDriveIdentify[i].TMHeads;
+          Int13.NumberDrives = Controller->DriveCount; /* FIXME: This does not make sense */ 
+          Error = RegSetValue(DriveKey,
+            "Component information",
+            REG_BINARY,
+            (PU8) &Int13,
+            sizeof(CM_INT13_DRIVE_PARAMETER));
+          if (Error != ERROR_SUCCESS)
+            {
+              DbgPrint((DPRINT_HWDETECT, "RegSetValue(Component information) failed (Error %u)\n", (int)Error));
+              return;
+            }
+
+          /* FIXME: Create value: 'Configuration data' */
+        }
+
+      ScsiPortNumber++;
+         ListEntry = ListEntry->Flink;
+       }
+
+  DbgPrint((DPRINT_HWDETECT, "%d controllers found\n", ScsiPortNumber));
+}
+
+VOID
+PrepareRegistry()
+{
+  HKEY HardwareKey;
+  HKEY DescriptionKey;
+  HKEY SystemKey;
+  HKEY DeviceMapKey;
+  HKEY ResourceMapKey;
+  S32 Error;
+
+  Error = RegOpenKey(NULL,
+    "\\Registry\\Machine\\HARDWARE",
+    &HardwareKey);
+  if (Error != ERROR_SUCCESS)
+    {
+      DbgPrint((DPRINT_HWDETECT, "RegOpenKey(HARDWARE) failed (Error %u)\n", (int)Error));
+      return;
+    }
+
+  /* Create DESCRIPTION key */
+  Error = RegCreateKey(HardwareKey,
+    "DESCRIPTION",
+    &DescriptionKey);
+  if (Error != ERROR_SUCCESS)
+    {
+      DbgPrint((DPRINT_HWDETECT, "RegCreateKey(DESCRIPTION) failed (Error %u)\n", (int)Error));
+      return;
+    }
+
+  /* Create DESCRIPTION/System key */
+  Error = RegCreateKey(DescriptionKey,
+    "System",
+    &SystemKey);
+  if (Error != ERROR_SUCCESS)
+    {
+      DbgPrint((DPRINT_HWDETECT, "RegCreateKey(System) failed (Error %u)\n", (int)Error));
+      return;
+    }
+
+  /* Create DEVICEMAP key */
+  Error = RegCreateKey(HardwareKey,
+    "DEVICEMAP",
+    &DeviceMapKey);
+  if (Error != ERROR_SUCCESS)
+    {
+      DbgPrint((DPRINT_HWDETECT, "RegCreateKey(DEVICEMAP) failed (Error %u)\n", (int)Error));
+      return;
+    }
+
+  /* Create RESOURCEMAP key */
+  Error = RegCreateKey(HardwareKey,
+    "RESOURCEMAP",
+    &ResourceMapKey);
+  if (Error != ERROR_SUCCESS)
+    {
+      DbgPrint((DPRINT_HWDETECT, "RegCreateKey(RESOURCEMAP) failed (Error %u)\n", (int)Error));
+      return;
+    }
+}
+
+VOID
+FindPciBusses(PDETECTED_BUSSES DetectedBusses)
+{
+  PDETECTED_BUS DetectedBus;
+
+  PciBusConfigType = GetPciBusConfigType();
+
+  if (PciBusConfigType == 0)
+    {
+      /* No PCI bus present */
+    }
+  else if (PciBusConfigType == 1)
+    {
+      /* 1 PCI bus present */
+      DetectedBus = MmAllocateMemory(sizeof(DETECTED_BUS));
+      if (DetectedBus == NULL)
+        return;
+
+      DetectedBus->BusType = PCIBus;
+      DetectedBus->BusNumber = 0;
+      strcpy(DetectedBus->Identifier, "PCI");
+      InsertHeadList(&DetectedBusses->Busses, &DetectedBus->ListEntry);
+    }
+  else if (PciBusConfigType == 2)
+    {
+      /* PCI and AGP bus present */
+      DetectedBus = MmAllocateMemory(sizeof(DETECTED_BUS));
+      if (DetectedBus == NULL)
+        return;
+
+      DetectedBus->BusType = PCIBus;
+      DetectedBus->BusNumber = 0;
+      strcpy(DetectedBus->Identifier, "PCI");
+      InsertHeadList(&DetectedBusses->Busses, &DetectedBus->ListEntry);
+
+
+      DetectedBus = MmAllocateMemory(sizeof(DETECTED_BUS));
+      if (DetectedBus == NULL)
+        return;
+
+      DetectedBus->BusType = PCIBus;
+      DetectedBus->BusNumber = 1;
+      strcpy(DetectedBus->Identifier, "PCI");
+      InsertHeadList(&DetectedBusses->Busses, &DetectedBus->ListEntry);
+    }
+  else
+    {
+      /* Unknown PCI bus configuration */
+      DbgPrint((DPRINT_WARNING, "Unknown PCI bus configuration %d\n", PciBusConfigType));
+    }
+}
+
+VOID
+FindIsaBus(PDETECTED_BUSSES DetectedBusses)
+{
+  PDETECTED_BUS DetectedBus;
+
+  /* Assume an ISA bus is present */
+
+  DetectedBus = MmAllocateMemory(sizeof(DETECTED_BUS));
+  if (DetectedBus == NULL)
+    return;
+
+  DetectedBus->BusType = Isa;
+  DetectedBus->BusNumber = 0;
+  strcpy(DetectedBus->Identifier, "ISA");
+
+  InsertHeadList(&DetectedBusses->Busses, &DetectedBus->ListEntry);
+}
+
+VOID
+DetectBusses()
+{
+  CHAR buf[200];
+  DETECTED_BUSSES DetectedBusses;
+  PDETECTED_BUS Bus;
+  S32 Error;
+  U32 BusNumber;
+  PLIST_ENTRY ListEntry;
+  HKEY SystemKey;
+  HKEY MultifunctionAdapterKey;
+  HKEY BusKey;
+
+  InitializeListHead(&DetectedBusses.Busses);
+  FindPciBusses(&DetectedBusses);
+  FindIsaBus(&DetectedBusses);
+
+  Error = RegOpenKey(NULL,
+    "\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
+    &SystemKey);
+  if (Error != ERROR_SUCCESS)
+    {
+      DbgPrint((DPRINT_HWDETECT, "RegOpenKey(System) failed (Error %u)\n", (int)Error));
+      return;
+    }
+
+  /* Create DESCRIPTION/System/MultifunctionAdapter key */
+  Error = RegCreateKey(SystemKey,
+    "MultifunctionAdapter",
+    &MultifunctionAdapterKey);
+  if (Error != ERROR_SUCCESS)
+    {
+      DbgPrint((DPRINT_HWDETECT, "RegCreateKey(MultifunctionAdapter) failed (Error %u)\n", (int)Error));
+      return;
+    }
+
+  BusNumber = 0;
+  ListEntry = DetectedBusses.Busses.Flink;
+  while (ListEntry != &DetectedBusses.Busses)
+       {
+         Bus = CONTAINING_RECORD(ListEntry,
+        DETECTED_BUS,
+        ListEntry);
+
+      /* Create DESCRIPTION/System/MultifunctionAdapter/X key */
+      sprintf(buf, "%d", (int) BusNumber);
+      Error = RegCreateKey(MultifunctionAdapterKey,
+        buf,
+        &BusKey);
+      if (Error != ERROR_SUCCESS)
+        {
+          DbgPrint((DPRINT_HWDETECT, "RegCreateKey(X) failed (Error %u)\n", (int)Error));
+          return;
+        }
+
+      RegisterBusKey(BusKey, Bus->BusType, Bus->BusNumber);
+
+      Error = RegSetValue(BusKey,
+        "Identifier",
+        REG_SZ,
+        (PU8) Bus->Identifier,
+        strlen(Bus->Identifier));
+      if (Error != ERROR_SUCCESS)
+        {
+          DbgPrint((DPRINT_HWDETECT, "RegSetValue(Identifier) failed (Error %u)\n", (int)Error));
+          return;
+        }
+
+      BusNumber++;
+         ListEntry = ListEntry->Flink;
+       }
+
+  DbgPrint((DPRINT_HWDETECT, "%d busses found\n", BusNumber));
+}
+
 VOID
 DetectHardware(VOID)
 {
+  DbgPrint((DPRINT_REACTOS, "DetectHardware()\n"));
+
+  InitializeListHead(&BusKeyListHead);
+
+  HalpCalibrateStallExecution();
+
+  PrepareRegistry();
+
+  DetectBusses();
+
+  DetectStorage();
+
+  DbgPrint((DPRINT_HWDETECT, "DetectHardware() Done\n"));
 }
index 2b401c8..3f92a0d 100644 (file)
 #ifndef __HWDETECT_H
 #define __HWDETECT_H
 
+typedef enum _INTERFACE_TYPE
+{
+  InterfaceTypeUndefined = -1,
+  Internal,
+  Isa,
+  Eisa,
+  MicroChannel,
+  TurboChannel,
+  PCIBus,
+  VMEBus,
+  NuBus,
+  PCMCIABus,
+  CBus,
+  MPIBus,
+  MPSABus,
+  ProcessorInternal,
+  InternalPowerBus,
+  PNPISABus,
+  MaximumInterfaceType
+} INTERFACE_TYPE, *PINTERFACE_TYPE;
+
+typedef enum _BUS_DATA_TYPE
+{
+  ConfigurationSpaceUndefined = -1,
+  Cmos,
+  EisaConfiguration,
+  Pos,
+  CbusConfiguration,
+  PCIConfiguration,
+  VMEConfiguration,
+  NuBusConfiguration,
+  PCMCIAConfiguration,
+  MPIConfiguration,
+  MPSAConfiguration,
+  PNPISAConfiguration,
+  MaximumBusDataType,
+} BUS_DATA_TYPE, *PBUS_DATA_TYPE;
+
+typedef struct _CM_INT13_DRIVE_PARAMETER {
+  U16 DriveSelect;
+  U32 MaxCylinders;
+  U16 SectorsPerTrack;
+  U16 MaxHeads;
+  U16 NumberDrives;
+} CM_INT13_DRIVE_PARAMETER, *PCM_INT13_DRIVE_PARAMETER;
+
+/* PCI bus definitions */
+
+#define PCI_TYPE0_ADDRESSES    6
+#define PCI_TYPE1_ADDRESSES    2
+#define PCI_TYPE2_ADDRESSES    5
+
+typedef struct _PCI_COMMON_CONFIG
+{
+  U16 VendorID;                /* read-only */
+  U16 DeviceID;                /* read-only */
+  U16 Command;
+  U16 Status;
+  U8  RevisionID;              /* read-only */
+  U8  ProgIf;          /* read-only */
+  U8  SubClass;                /* read-only */
+  U8  BaseClass;               /* read-only */
+  U8  CacheLineSize;           /* read-only */
+  U8  LatencyTimer;            /* read-only */
+  U8  HeaderType;              /* read-only */
+  U8  BIST;
+  union
+    {
+      struct _PCI_HEADER_TYPE_0
+       {
+         U32  BaseAddresses[PCI_TYPE0_ADDRESSES];
+         U32  CIS;
+         U16 SubVendorID;
+         U16 SubSystemID;
+         U32  ROMBaseAddress;
+         U32  Reserved2[2];
+      
+         U8  InterruptLine;
+         U8  InterruptPin;             /* read-only */
+         U8  MinimumGrant;             /* read-only */
+         U8  MaximumLatency;   /* read-only */
+       } type0;
+
+      /* PCI to PCI Bridge */
+      struct _PCI_HEADER_TYPE_1
+       {
+         U32  BaseAddresses[PCI_TYPE1_ADDRESSES];
+         U8  PrimaryBus;
+         U8  SecondaryBus;
+         U8  SubordinateBus;
+         U8  SecondaryLatency;
+         U8  IOBase;
+         U8  IOLimit;
+         U16 SecondaryStatus;
+         U16 MemoryBase;
+         U16 MemoryLimit;
+         U16 PrefetchBase;
+         U16 PrefetchLimit;
+         U32  PrefetchBaseUpper32;
+         U32  PrefetchLimitUpper32;
+         U16 IOBaseUpper16;
+         U16 IOLimitUpper16;
+         U8  CapabilitiesPtr;
+         U8  Reserved1[3];
+         U32  ROMBaseAddress;
+         U8  InterruptLine;
+         U8  InterruptPin;
+         U16 BridgeControl;
+       } type1;
+
+      /* PCI to CARDBUS Bridge */
+      struct _PCI_HEADER_TYPE_2
+       {
+         U32  SocketRegistersBaseAddress;
+         U8  CapabilitiesPtr;
+         U8  Reserved;
+         U16 SecondaryStatus;
+         U8  PrimaryBus;
+         U8  SecondaryBus;
+         U8  SubordinateBus;
+         U8  SecondaryLatency;
+         struct
+           {
+             U32 Base;
+             U32 Limit;
+           } Range[PCI_TYPE2_ADDRESSES-1];
+         U8  InterruptLine;
+         U8  InterruptPin;
+         U16 BridgeControl;
+       } type2;
+    } u;
+  U8 DeviceSpecific[192];
+} PCI_COMMON_CONFIG, *PPCI_COMMON_CONFIG;
+
+#define PCI_COMMON_HDR_LENGTH (FIELD_OFFSET (PCI_COMMON_CONFIG, DeviceSpecific))
+
+#define PCI_MAX_DEVICES                     32
+#define PCI_MAX_FUNCTION                    8
+
+#define PCI_INVALID_VENDORID                0xFFFF
+
+/* Bit encodings for PCI_COMMON_CONFIG.HeaderType */
+
+#define PCI_MULTIFUNCTION                   0x80
+#define PCI_DEVICE_TYPE                     0x00
+#define PCI_BRIDGE_TYPE                     0x01
+
+
+/* Bit encodings for PCI_COMMON_CONFIG.Command */
+
+#define PCI_ENABLE_IO_SPACE                 0x0001
+#define PCI_ENABLE_MEMORY_SPACE             0x0002
+#define PCI_ENABLE_BUS_MASTER               0x0004
+#define PCI_ENABLE_SPECIAL_CYCLES           0x0008
+#define PCI_ENABLE_WRITE_AND_INVALIDATE     0x0010
+#define PCI_ENABLE_VGA_COMPATIBLE_PALETTE   0x0020
+#define PCI_ENABLE_PARITY                   0x0040
+#define PCI_ENABLE_WAIT_CYCLE               0x0080
+#define PCI_ENABLE_SERR                     0x0100
+#define PCI_ENABLE_FAST_BACK_TO_BACK        0x0200
+
+
+/* Bit encodings for PCI_COMMON_CONFIG.Status */
+
+#define PCI_STATUS_FAST_BACK_TO_BACK        0x0080
+#define PCI_STATUS_DATA_PARITY_DETECTED     0x0100
+#define PCI_STATUS_DEVSEL                   0x0600  /* 2 bits wide */
+#define PCI_STATUS_SIGNALED_TARGET_ABORT    0x0800
+#define PCI_STATUS_RECEIVED_TARGET_ABORT    0x1000
+#define PCI_STATUS_RECEIVED_MASTER_ABORT    0x2000
+#define PCI_STATUS_SIGNALED_SYSTEM_ERROR    0x4000
+#define PCI_STATUS_DETECTED_PARITY_ERROR    0x8000
+
+
+/* PCI device classes */
+
+#define PCI_CLASS_PRE_20                    0x00
+#define PCI_CLASS_MASS_STORAGE_CTLR         0x01
+#define PCI_CLASS_NETWORK_CTLR              0x02
+#define PCI_CLASS_DISPLAY_CTLR              0x03
+#define PCI_CLASS_MULTIMEDIA_DEV            0x04
+#define PCI_CLASS_MEMORY_CTLR               0x05
+#define PCI_CLASS_BRIDGE_DEV                0x06
+#define PCI_CLASS_SIMPLE_COMMS_CTLR         0x07
+#define PCI_CLASS_BASE_SYSTEM_DEV           0x08
+#define PCI_CLASS_INPUT_DEV                 0x09
+#define PCI_CLASS_DOCKING_STATION           0x0a
+#define PCI_CLASS_PROCESSOR                 0x0b
+#define PCI_CLASS_SERIAL_BUS_CTLR           0x0c
+
+
+/* PCI device subclasses for class 1 (mass storage controllers)*/
+
+#define PCI_SUBCLASS_MSC_SCSI_BUS_CTLR      0x00
+#define PCI_SUBCLASS_MSC_IDE_CTLR           0x01
+#define PCI_SUBCLASS_MSC_FLOPPY_CTLR        0x02
+#define PCI_SUBCLASS_MSC_IPI_CTLR           0x03
+#define PCI_SUBCLASS_MSC_RAID_CTLR          0x04
+#define PCI_SUBCLASS_MSC_OTHER              0x80
+
+
+/* Bit encodes for PCI_COMMON_CONFIG.u.type0.BaseAddresses */
+
+#define PCI_ADDRESS_IO_SPACE                0x00000001
+#define PCI_ADDRESS_MEMORY_TYPE_MASK        0x00000006
+#define PCI_ADDRESS_MEMORY_PREFETCHABLE     0x00000008
+
+#define PCI_ADDRESS_IO_ADDRESS_MASK         0xfffffffc
+#define PCI_ADDRESS_MEMORY_ADDRESS_MASK     0xfffffff0
+#define PCI_ADDRESS_ROM_ADDRESS_MASK        0xfffff800
+
+#define PCI_TYPE_32BIT      0
+#define PCI_TYPE_20BIT      2
+#define PCI_TYPE_64BIT      4
+
+
+/* Bit encodes for PCI_COMMON_CONFIG.u.type0.ROMBaseAddresses */
+
+#define PCI_ROMADDRESS_ENABLED              0x00000001
+
+typedef struct _PCI_SLOT_NUMBER
+{
+  union
+    {
+      struct
+        {
+          U32 DeviceNumber:5;
+          U32 FunctionNumber:3;
+          U32 Reserved:24;
+        } bits;
+      U32 AsULONG;
+    } u;
+} PCI_SLOT_NUMBER, *PPCI_SLOT_NUMBER;
+
+
+
+/* ***** BEGIN ATA ***** */
+
+#define  IDE_SECTOR_BUF_SZ      512
+#define  IDE_MAX_POLL_RETRIES   100000
+#define  IDE_MAX_BUSY_RETRIES   50000
+
+// Control Block offsets and masks
+#define  IDE_REG_DEV_CNTRL      0x0000  /* device control register */
+#define    IDE_DC_nIEN            0x02  /* IRQ enable (active low) */
+
+// Command Block offsets and masks
+#define  IDE_REG_DATA_PORT      0x0000
+#define  IDE_REG_ERROR          0x0001  /* error register */
+#define    IDE_ER_AMNF            0x01  /* address mark not found */
+#define    IDE_ER_TK0NF           0x02  /* Track 0 not found */
+#define    IDE_ER_ABRT            0x04  /* Command aborted */
+#define    IDE_ER_MCR             0x08  /* Media change requested */
+#define    IDE_ER_IDNF            0x10  /* ID not found */
+#define    IDE_ER_MC              0x20  /* Media changed */
+#define    IDE_ER_UNC             0x40  /* Uncorrectable data error */
+#define  IDE_REG_PRECOMP        0x0001
+#define  IDE_REG_SECTOR_CNT     0x0002
+#define  IDE_REG_SECTOR_NUM     0x0003
+#define  IDE_REG_CYL_LOW        0x0004
+#define  IDE_REG_CYL_HIGH       0x0005
+#define  IDE_REG_DRV_HEAD       0x0006
+#define    IDE_DH_FIXED           0xA0
+#define    IDE_DH_LBA             0x40
+#define    IDE_DH_HDMASK          0x0F
+#define    IDE_DH_DRV0            0x00
+#define    IDE_DH_DRV1            0x10
+#define  IDE_REG_STATUS         0x0007
+#define    IDE_SR_BUSY            0x80
+#define    IDE_SR_DRQ             0x08
+#define    IDE_SR_ERR             0x01
+#define  IDE_REG_COMMAND        0x0007
+
+/* IDE/ATA commands */
+#define    IDE_CMD_RESET            0x08
+#define    IDE_CMD_IDENT_ATA_DRV    0xEC
+#define    IDE_CMD_IDENT_ATAPI_DRV  0xA1
+
+/* Access macros for command registers
+   Each macro takes an address of the command port block, and data */
+#define IDEWritePrecomp(Address, Data) \
+  (WRITE_PORT_UCHAR((PU8)((Address) + IDE_REG_PRECOMP), (Data)))
+#define IDEWriteSectorCount(Address, Data) \
+  (WRITE_PORT_UCHAR((PU8)((Address) + IDE_REG_SECTOR_CNT), (Data)))
+#define IDEWriteSectorNum(Address, Data) \
+  (WRITE_PORT_UCHAR((PU8)((Address) + IDE_REG_SECTOR_NUM), (Data)))
+#define IDEReadCylinderLow(Address) \
+  (READ_PORT_UCHAR((PU8)((Address) + IDE_REG_CYL_LOW)))
+#define IDEWriteCylinderLow(Address, Data) \
+  (WRITE_PORT_UCHAR((PU8)((Address) + IDE_REG_CYL_LOW), (Data)))
+#define IDEReadCylinderHigh(Address) \
+  (READ_PORT_UCHAR((PU8)((Address) + IDE_REG_CYL_HIGH)))
+#define IDEWriteCylinderHigh(Address, Data) \
+  (WRITE_PORT_UCHAR((PU8)((Address) + IDE_REG_CYL_HIGH), (Data)))
+#define IDEWriteDriveHead(Address, Data) \
+  (WRITE_PORT_UCHAR((PU8)((Address) + IDE_REG_DRV_HEAD), (Data)))
+#define IDEWriteDriveControl(Address, Data) \
+  (WRITE_PORT_UCHAR((PU8)((Address) + IDE_REG_DEV_CNTRL), (Data)))
+#define IDEReadStatus(Address) \
+  (READ_PORT_UCHAR((PU8)((Address) + IDE_REG_STATUS)))
+#define IDEWriteCommand(Address, Data) \
+  (WRITE_PORT_UCHAR((PU8)((Address) + IDE_REG_COMMAND), (Data)))
+
+/* Data block read and write commands */
+#define IDEReadBlock(Address, Buffer, Count) \
+  (READ_PORT_BUFFER_USHORT((PU16)((Address) + IDE_REG_DATA_PORT), \
+  (PU16)(Buffer), (Count) / 2))
+
+typedef struct _IDE_DRIVE_IDENTIFY
+{
+  U16  ConfigBits;             /*00*/
+  U16  LogicalCyls;            /*01*/
+  U16  Reserved02;             /*02*/
+  U16  LogicalHeads;           /*03*/
+  U16  BytesPerTrack;          /*04*/
+  U16  BytesPerSector;         /*05*/
+  U16  SectorsPerTrack;        /*06*/
+  U8   InterSectorGap;         /*07*/
+  U8   InterSectorGapSize;
+  U8   Reserved08H;            /*08*/
+  U8   BytesInPLO;
+  U16  VendorUniqueCnt;        /*09*/
+  CHAR SerialNumber[20];       /*10*/
+  U16  ControllerType;         /*20*/
+  U16  BufferSize;             /*21*/
+  U16  ECCByteCnt;             /*22*/
+  CHAR FirmwareRev[8];         /*23*/
+  CHAR ModelNumber[40];        /*27*/
+  U16  RWMultImplemented;      /*47*/
+  U16  DWordIo;                       /*48*/
+  U16  Capabilities;           /*49*/
+#define IDE_DRID_STBY_SUPPORTED   0x2000
+#define IDE_DRID_IORDY_SUPPORTED  0x0800
+#define IDE_DRID_IORDY_DISABLE    0x0400
+#define IDE_DRID_LBA_SUPPORTED    0x0200
+#define IDE_DRID_DMA_SUPPORTED    0x0100
+  U16  Reserved50;             /*50*/
+  U16  MinPIOTransTime;        /*51*/
+  U16  MinDMATransTime;        /*52*/
+  U16  TMFieldsValid;          /*53*/
+  U16  TMCylinders;            /*54*/
+  U16  TMHeads;                /*55*/
+  U16  TMSectorsPerTrk;        /*56*/
+  U16  TMCapacityLo;           /*57*/
+  U16  TMCapacityHi;           /*58*/
+  U16  RWMultCurrent;          /*59*/
+  U16  TMSectorCountLo;        /*60*/
+  U16  TMSectorCountHi;        /*61*/
+  U16  Reserved62[193];        /*62*/
+  U16  Checksum;               /*255*/
+} IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY;
+
+/* ***** END ATA ***** */
+
+typedef struct _DETECTED_BUS
+{
+  LIST_ENTRY ListEntry;
+  INTERFACE_TYPE BusType;
+  U32 BusNumber;
+  CHAR Identifier[20];
+} DETECTED_BUS, *PDETECTED_BUS;
+
+typedef struct _DETECTED_BUSSES
+{
+  LIST_ENTRY Busses; /* DETECTED_BUS */
+} DETECTED_BUSSES, *PDETECTED_BUSSES;
+
+
+typedef struct _DETECTED_STORAGE_CONTROLLER
+{
+  LIST_ENTRY ListEntry;
+  INTERFACE_TYPE BusType;
+  U32 BusNumber;
+  U32 DriveCount;
+  IDE_DRIVE_IDENTIFY IdeDriveIdentify[2];
+} DETECTED_STORAGE_CONTROLLER, *PDETECTED_STORAGE_CONTROLLER;
+
+typedef struct _DETECTED_STORAGE
+{
+  LIST_ENTRY StorageControllers; /* DETECTED_STORAGE_CONTROLLER */
+} DETECTED_STORAGE, *PDETECTED_STORAGE;
+
+
+typedef struct _REGISTRY_BUS_INFORMATION
+{
+  LIST_ENTRY ListEntry;
+  HKEY BusKey;
+  INTERFACE_TYPE BusType;
+  U32 BusNumber;
+} REGISTRY_BUS_INFORMATION, *PREGISTRY_BUS_INFORMATION;
+
 VOID DetectHardware(VOID);
 
 #endif /* __HWDETECT_H */
index 63f221b..d54b59f 100644 (file)
@@ -753,10 +753,21 @@ RegEnumValue(HKEY Key,
            *ValueName = 0;
          if (Type != NULL)
            *Type = Key->DataType;
+      if (Data != NULL)
+        {
+          if (Key->DataSize <= sizeof(PUCHAR))
+            {
+              memcpy(Data, &Key->Data, min(Key->DataSize, *DataSize));
+            }
+          else
+            {
+              memcpy(Data, Key->Data, min(Key->DataSize, *DataSize));
+            }
+        }
          if (DataSize != NULL)
-           *DataSize = Key->DataSize;
+           *DataSize = min(Key->DataSize, *DataSize);
 
-         /* FIXME: return more values */
+      return(ERROR_SUCCESS);
        }
     }
 
@@ -777,7 +788,26 @@ RegEnumValue(HKEY Key,
                            VALUE,
                            ValueList);
 
-  /* FIXME: return values */
+  /* enumerate non-default value */
+  if (ValueName != NULL)
+    memcpy(ValueName, Value->Name, min(Value->NameSize, *NameSize));
+  if (Type != NULL)
+    *Type = Value->DataType;
+
+  if (Data != NULL)
+    {
+      if (Value->DataSize <= sizeof(PUCHAR))
+        {
+          memcpy(Data, &Value->Data, min(Value->DataSize, *DataSize));
+        }
+      else
+        {
+          memcpy(Data, Value->Data, min(Value->DataSize, *DataSize));
+        }
+    }
+
+  if (DataSize != NULL)
+    *DataSize = min(Value->DataSize, *DataSize);
 
   return(ERROR_SUCCESS);
 }
index 3b6df58..f8e17da 100644 (file)
@@ -110,7 +110,7 @@ BOOL UiInitialize(VOID)
 
                        if (!VideoSetMode(VideoMode))
                        {
-                               printf("Error: unable to set video display mode 0x%x\n", VideoMode);
+                               printf("Error: unable to set video display mode 0x%x\n", (int) VideoMode);
                                printf("Defaulting to 80x25 text mode.\n");
                                printf("Press any key to continue.\n");
                                getch();
index 35ceb1f..70d7ead 100644 (file)
@@ -46,7 +46,7 @@
 //
 VOID VideoSetPixel16(U32 X, U32 Y, U8 Color)
 {
-       U8              CurrentColor;
+       //U8            CurrentColor;
        U8*             MemoryPointer;
        U32             ByteOffset;
        U8              BitInByte;