branch update for HEAD-2003050101
[reactos.git] / hal / halx86 / pci.c
index b5493c5..820ecbb 100644 (file)
 
 /* INCLUDES *****************************************************************/
 
+#include <roscfg.h>
 #include <ddk/ntddk.h>
 #include <bus.h>
+#ifdef MP
+#include <mps.h>
+#endif
+
 
 #define NDEBUG
 #include <internal/debug.h>
@@ -27,6 +32,9 @@
 
 /* MACROS ******************************************************************/
 
+/* FIXME These are also defined in drivers/bus/pci/pcidef.h.
+   Maybe put PCI definitions in a central include file??? */
+
 /* access type 1 macros */
 #define CONFIG_CMD(bus, dev_fn, where) \
        (0x80000000 | (((ULONG)(bus)) << 16) | (((dev_fn) & 0x1F) << 11) | (((dev_fn) & 0xE0) << 3) | ((where) & ~3))
 #define FUNC(dev_fn) \
        ((((dev_fn) & 0xE0) >> 4) | 0xf0)
 
+#define  PCI_BASE_ADDRESS_SPACE        0x01    /* 0 = memory, 1 = I/O */
+#define  PCI_BASE_ADDRESS_SPACE_IO 0x01
+#define  PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+#define  PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define  PCI_BASE_ADDRESS_MEM_TYPE_32  0x00    /* 32 bit address */
+#define  PCI_BASE_ADDRESS_MEM_TYPE_1M  0x02    /* Below 1M [obsolete] */
+#define  PCI_BASE_ADDRESS_MEM_TYPE_64  0x04    /* 64 bit address */
+#define  PCI_BASE_ADDRESS_MEM_PREFETCH 0x08    /* prefetchable? */
+#define  PCI_BASE_ADDRESS_MEM_MASK     (~0x0fUL)
+#define  PCI_BASE_ADDRESS_IO_MASK      (~0x03UL)
+/* bit 1 is reserved if address_space = 1 */
+
 
 /* GLOBALS ******************************************************************/
 
+#define TAG_PCI  TAG('P', 'C', 'I', 'H')
+
 static ULONG BusConfigType = 0;  /* undetermined config type */
 static KSPIN_LOCK PciLock;
 
@@ -93,7 +115,7 @@ ReadPciConfigUshort(UCHAR Bus,
      case 1:
         KeAcquireSpinLock(&PciLock, &oldIrql);
        WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
-       *Value = READ_PORT_USHORT((PUSHORT)0xCFC + (Offset & 1));
+       *Value = READ_PORT_USHORT((PUSHORT)0xCFC + (Offset & 2));
        KeReleaseSpinLock(&PciLock, oldIrql);
        return STATUS_SUCCESS;
 
@@ -193,7 +215,7 @@ WritePciConfigUshort(UCHAR Bus,
      case 1:
         KeAcquireSpinLock(&PciLock, &oldIrql);
        WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
-       WRITE_PORT_USHORT((PUSHORT)0xCFC + (Offset & 1), Value);
+       WRITE_PORT_USHORT((PUSHORT)0xCFC + (Offset & 2), Value);
        KeReleaseSpinLock(&PciLock, oldIrql);
        return STATUS_SUCCESS;
 
@@ -529,9 +551,15 @@ HalpGetPciInterruptVector(PVOID BusHandler,
                          PKIRQL Irql,
                          PKAFFINITY Affinity)
 {
+#ifdef MP
+  *Irql = PROFILE_LEVEL - BusInterruptVector;
+  *Affinity = 0xFFFFFFFF;
+  return IRQ2VECTOR(BusInterruptVector);
+#else
   *Irql = PROFILE_LEVEL - BusInterruptVector;
   *Affinity = 0xFFFFFFFF;
   return BusInterruptVector;
+#endif
 }
 
 static BOOLEAN STDCALL
@@ -562,6 +590,134 @@ HalpTranslatePciAddress(PBUS_HANDLER BusHandler,
    return TRUE;
 }
 
+/*
+ * Find the extent of a PCI decode..
+ */
+static ULONG STDCALL
+PciSize(ULONG Base, ULONG Mask)
+{
+  ULONG Size = Mask & Base;   /* Find the significant bits */
+  Size = Size & ~(Size - 1);  /* Get the lowest of them to find the decode size */
+  return Size;
+}
+
+static NTSTATUS STDCALL
+HalpAssignPciSlotResources(IN PBUS_HANDLER BusHandler,
+                          IN ULONG BusNumber,
+                          IN PUNICODE_STRING RegistryPath,
+                          IN PUNICODE_STRING DriverClassName,
+                          IN PDRIVER_OBJECT DriverObject,
+                          IN PDEVICE_OBJECT DeviceObject,
+                          IN ULONG SlotNumber,
+                          IN OUT PCM_RESOURCE_LIST *AllocatedResources)
+{
+  UINT Address;
+  UINT NoAddresses;
+  ULONG BaseAddresses[PCI_TYPE0_ADDRESSES];
+  ULONG Size[PCI_TYPE0_ADDRESSES];
+  NTSTATUS Status = STATUS_SUCCESS;
+  UCHAR Offset;
+  PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+
+  /* FIXME: Should handle 64-bit addresses */
+
+  /* Read the PCI configuration space for the device and store base address and
+     size information in temporary storage. Count the number of valid base addresses */
+  NoAddresses = 0;
+  for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
+    {
+      Offset = offsetof(PCI_COMMON_CONFIG, u.type0.BaseAddresses[Address]);
+      Status = ReadPciConfigUlong(BusNumber, SlotNumber,
+                                  Offset, BaseAddresses + Address);
+      if (! NT_SUCCESS(Status))
+       {
+         return Status;
+       }
+      if (0xffffffff == BaseAddresses[Address])
+       {
+         BaseAddresses[Address] = 0;
+       }
+      if (0 != BaseAddresses[Address])
+       {
+         NoAddresses++;
+         Status = WritePciConfigUlong(BusNumber, SlotNumber, Offset, 0xffffffff);
+         if (! NT_SUCCESS(Status))
+           {
+             WritePciConfigUlong(BusNumber, SlotNumber, Offset, BaseAddresses[Address]);
+             return Status;
+           }
+         Status = ReadPciConfigUlong(BusNumber, SlotNumber,
+                                     Offset, Size + Address);
+         if (! NT_SUCCESS(Status))
+           {
+             WritePciConfigUlong(BusNumber, SlotNumber, Offset, BaseAddresses[Address]);
+             return Status;
+           }
+         Status = WritePciConfigUlong(BusNumber, SlotNumber, Offset, BaseAddresses[Address]);
+         if (! NT_SUCCESS(Status))
+           {
+             return Status;
+           }
+
+       }
+    }
+
+  /* Allocate output buffer and initialize */
+  *AllocatedResources = ExAllocatePoolWithTag(PagedPool,
+                                              sizeof(CM_RESOURCE_LIST) +
+                                              (NoAddresses - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR),
+                                              TAG_PCI);
+  if (NULL == *AllocatedResources)
+    {
+    return STATUS_NO_MEMORY;
+    }
+  (*AllocatedResources)->Count = 1;
+  (*AllocatedResources)->List[0].InterfaceType = PCIBus;
+  (*AllocatedResources)->List[0].BusNumber = BusNumber;
+  (*AllocatedResources)->List[0].PartialResourceList.Version = 1;
+  (*AllocatedResources)->List[0].PartialResourceList.Revision = 1;
+  (*AllocatedResources)->List[0].PartialResourceList.Count = NoAddresses;
+  Descriptor = (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
+
+  /* Store configuration information */
+  for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
+    {
+      if (0 != BaseAddresses[Address])
+       {
+         if (PCI_BASE_ADDRESS_SPACE_MEMORY ==
+              (BaseAddresses[Address] & PCI_BASE_ADDRESS_SPACE))
+           {
+             Descriptor->Type = CmResourceTypeMemory;
+             Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
+             Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;             /* FIXME Just a guess */
+             Descriptor->u.Memory.Start.QuadPart = (BaseAddresses[Address] & PCI_BASE_ADDRESS_MEM_MASK);
+             Descriptor->u.Memory.Length = PciSize(Size[Address], PCI_BASE_ADDRESS_MEM_MASK);
+           }
+         else if (PCI_BASE_ADDRESS_SPACE_IO ==
+                   (BaseAddresses[Address] & PCI_BASE_ADDRESS_SPACE))
+           {
+             Descriptor->Type = CmResourceTypePort;
+             Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
+             Descriptor->Flags = CM_RESOURCE_PORT_IO;                       /* FIXME Just a guess */
+             Descriptor->u.Port.Start.QuadPart = BaseAddresses[Address] &= PCI_BASE_ADDRESS_IO_MASK;
+             Descriptor->u.Port.Length = PciSize(Size[Address], PCI_BASE_ADDRESS_IO_MASK & 0xffff);
+           }
+         else
+           {
+             assert(FALSE);
+             return STATUS_UNSUCCESSFUL;
+           }
+         Descriptor++;
+       }
+    }
+
+  assert(Descriptor == (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors + NoAddresses);
+
+  /* FIXME: Should store the resources in the registry resource map */
+
+  return Status;
+}
+
 
 VOID
 HalpInitPciBus(VOID)
@@ -590,8 +746,8 @@ HalpInitPciBus(VOID)
     (pTranslateBusAddress)HalpTranslatePciAddress;
 //     BusHandler->AdjustResourceList =
 //             (pGetSetBusData)HalpAdjustPciResourceList;
-//     BusHandler->AssignSlotResources =
-//             (pGetSetBusData)HalpAssignPciSlotResources;
+  BusHandler->AssignSlotResources =
+    (pAssignSlotResources)HalpAssignPciSlotResources;
 
 
   /* agp bus (bus 1) handler */
@@ -606,8 +762,8 @@ HalpInitPciBus(VOID)
     (pTranslateBusAddress)HalpTranslatePciAddress;
 //     BusHandler->AdjustResourceList =
 //             (pGetSetBusData)HalpAdjustPciResourceList;
-//     BusHandler->AssignSlotResources =
-//             (pGetSetBusData)HalpAssignPciSlotResources;
+  BusHandler->AssignSlotResources =
+    (pAssignSlotResources)HalpAssignPciSlotResources;
 
   DPRINT("HalpInitPciBus() finished.\n");
 }