VOID NTAPI PPBridge_SaveLimits(IN PPCI_CONFIGURATOR_CONTEXT Context) { PIO_RESOURCE_DESCRIPTOR Limit; PULONG BarArray; PHYSICAL_ADDRESS MemoryLimit; ULONG i; PPCI_COMMON_HEADER Working; PPCI_PDO_EXTENSION PdoExtension; /* Get the pointers from the context */ Working = Context->PciData; PdoExtension = Context->PdoExtension; /* Scan the BARs into the limit descriptors */ BarArray = Working->u.type1.BaseAddresses; Limit = PdoExtension->Resources->Limit; /* First of all, loop all the BARs */ for (i = 0; i < PCI_TYPE1_ADDRESSES; i++) { /* Create a descriptor for their limits */ if (PciCreateIoDescriptorFromBarLimit(&Limit[i], &BarArray[i], FALSE)) { /* This was a 64-bit descriptor, make sure there's space */ ASSERT((i + 1) < PCI_TYPE1_ADDRESSES); /* Skip the next descriptor since this one is double sized */ i++; Limit[i].Type = CmResourceTypeNull; } } /* Check if this is a subtractive decode bridge */ if (PciBridgeIsSubtractiveDecode(Context)) { /* This bridge is subtractive */ PdoExtension->Dependent.type1.SubtractiveDecode = TRUE; /* Subtractive bridges cannot use legacy ISA or VGA functionality */ PdoExtension->Dependent.type1.IsaBitSet = FALSE; PdoExtension->Dependent.type1.VgaBitSet = FALSE; } /* For normal decode bridges, we'll need to find the bridge limits too */ if (!PdoExtension->Dependent.type1.SubtractiveDecode) { /* Loop the descriptors that are left, to store the bridge limits */ for (i = PCI_TYPE1_ADDRESSES; i < 5; i++) { /* No 64-bit memory addresses, and set the address to 0 to begin */ MemoryLimit.HighPart = 0; (&Limit[i])->u.Port.MinimumAddress.QuadPart = 0; /* Are we getting the I/O limit? */ if (i == 2) { /* There should be one, get it */ ASSERT(Working->u.type1.IOLimit != 0); ASSERT((Working->u.type1.IOLimit & 0x0E) == 0); MemoryLimit.LowPart = PciBridgeIoLimit(Working); /* Build a descriptor for this limit */ (&Limit[i])->Type = CmResourceTypePort; (&Limit[i])->Flags = CM_RESOURCE_PORT_WINDOW_DECODE | CM_RESOURCE_PORT_POSITIVE_DECODE; (&Limit[i])->u.Port.Alignment = 0x1000; (&Limit[i])->u.Port.MinimumAddress.QuadPart = 0; (&Limit[i])->u.Port.MaximumAddress = MemoryLimit; (&Limit[i])->u.Port.Length = 0; } else if (i == 3) { /* There should be a valid memory limit, get it */ ASSERT((Working->u.type1.MemoryLimit & 0xF) == 0); MemoryLimit.LowPart = PciBridgeMemoryLimit(Working); /* Build the descriptor for it */ (&Limit[i])->Flags = CM_RESOURCE_MEMORY_READ_WRITE; (&Limit[i])->Type = CmResourceTypeMemory; (&Limit[i])->u.Memory.Alignment = 0x100000; (&Limit[i])->u.Memory.MinimumAddress.QuadPart = 0; (&Limit[i])->u.Memory.MaximumAddress = MemoryLimit; (&Limit[i])->u.Memory.Length = 0; } else if (Working->u.type1.PrefetchLimit) { /* Get the prefetch memory limit, if there is one */ MemoryLimit = PciBridgePrefetchMemoryLimit(Working); /* Write out the descriptor for it */ (&Limit[i])->Flags = CM_RESOURCE_MEMORY_PREFETCHABLE; (&Limit[i])->Type = CmResourceTypeMemory; (&Limit[i])->u.Memory.Alignment = 0x100000; (&Limit[i])->u.Memory.MinimumAddress.QuadPart = 0; (&Limit[i])->u.Memory.MaximumAddress = MemoryLimit; (&Limit[i])->u.Memory.Length = 0; } else { /* Blank descriptor */ (&Limit[i])->Type = CmResourceTypeNull; } } } /* Does the ROM have its own BAR? */ if (Working->u.type1.ROMBaseAddress & PCI_ROMADDRESS_ENABLED) { /* Build a limit for it as well */ PciCreateIoDescriptorFromBarLimit(&Limit[i], &Working->u.type1.ROMBaseAddress, TRUE); } }
VOID NTAPI Device_SaveLimits(IN PPCI_CONFIGURATOR_CONTEXT Context) { PPCI_COMMON_HEADER Current, PciData; PPCI_PDO_EXTENSION PdoExtension; PULONG BarArray; PIO_RESOURCE_DESCRIPTOR Limit; ULONG i; /* Get pointers from the context */ PdoExtension = Context->PdoExtension; Current = Context->Current; PciData = Context->PciData; /* And get the array of bARs */ BarArray = PciData->u.type0.BaseAddresses; /* First, check for IDE controllers that are not in native mode */ if ((PdoExtension->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) && (PdoExtension->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR) && (PdoExtension->ProgIf & 5) != 5) { /* They should not be using any non-legacy resources */ BarArray[0] = 0; BarArray[1] = 0; BarArray[2] = 0; BarArray[3] = 0; } else if ((PdoExtension->VendorId == 0x5333) && ((PdoExtension->DeviceId == 0x88F0) || (PdoExtension->DeviceId == 0x8880))) { /* * The problem is caused by the S3 Vision 968/868 video controller which * is used on the Diamond Stealth 64 Video 3000 series, Number Nine 9FX * motion 771, and other popular video cards, all containing a memory bug. * The 968/868 claims to require 32 MB of memory, but it actually decodes * 64 MB of memory. */ for (i = 0; i < PCI_TYPE0_ADDRESSES; i++) { /* Find its 32MB RAM BAR */ if (BarArray[i] == 0xFE000000) { /* Increase it to 64MB to make sure nobody touches the buffer */ BarArray[i] = 0xFC000000; DPRINT1("PCI - Adjusted broken S3 requirement from 32MB to 64MB\n"); } } } /* Check for Cirrus Logic GD5430/5440 cards */ if ((PdoExtension->VendorId == 0x1013) && (PdoExtension->DeviceId == 0xA0)) { /* Check for the I/O port requirement */ if (BarArray[1] == 0xFC01) { /* Check for completely bogus BAR */ if (Current->u.type0.BaseAddresses[1] == 1) { /* Ignore it */ BarArray[1] = 0; DPRINT1("PCI - Ignored Cirrus GD54xx broken IO requirement (400 ports)\n"); } else { /* Otherwise, this BAR seems okay */ DPRINT1("PCI - Cirrus GD54xx 400 port IO requirement has a valid setting (%08x)\n", Current->u.type0.BaseAddresses[1]); } } else if (BarArray[1]) { /* Strange, the I/O BAR was not found as expected (or at all) */ DPRINT1("PCI - Warning Cirrus Adapter 101300a0 has unexpected resource requirement (%08x)\n", BarArray[1]); } } /* Finally, process all the limit descriptors */ Limit = PdoExtension->Resources->Limit; for (i = 0; i < PCI_TYPE0_ADDRESSES; i++) { /* And build them based on the BARs */ if (PciCreateIoDescriptorFromBarLimit(&Limit[i], &BarArray[i], FALSE)) { /* This function returns TRUE if the BAR was 64-bit, handle this */ ASSERT((i + 1) < PCI_TYPE0_ADDRESSES); i++; Limit[i].Type = CmResourceTypeNull; } } /* Create the last descriptor based on the ROM address */ PciCreateIoDescriptorFromBarLimit(&Limit[i], &PciData->u.type0.ROMBaseAddress, TRUE); }