/*++ Copyright (c) 1996-2001 Microsoft Corporation Module Name: init8x.c Abstract: This module contains the initialization code for AMDAGP8X.SYS. Author: John Vert (jvert) 10/21/1997 Revision History: --*/ /* ****************************************************************************** * Archive File : $Archive: /Drivers/OS/Hammer/AGP/XP/amdagp/Init8x.c $ * * $History: Init8x.c $ * * ****************************************************************************** */ #include "amdagp8x.h" #define MAX_DEVICES 32 #ifdef DISPLAY ULONG ErrorControl = 2; #else ULONG ErrorControl = 0; #endif ULONG VendorID = 0; ULONG DeviceID = 0; ULONG AgpLokarSlotID = 0; ULONG AgpHammerSlotID = 0; ULONG_PTR OutPostBase; ULONG AgpExtensionSize = sizeof(AGP_AMD_EXTENSION); // // Function Name: DisplayStatus() // // Description: // This routine displays the status value in the Post Display. // // Parameter: // StatusValue - Value to display. // // Return: None. // void DisplayStatus( IN UCHAR StatusValue ) { UCHAR to80; if (ErrorControl) { to80 = StatusValue & 0xFF; WRITE_PORT_UCHAR((PUCHAR)OutPostBase, to80); } } // // Function Name: FindLokar() // // Description: // This routine locates which device number is assigned to Lokar. // // Parameter: // SlotID - Returned slot ID for Lokar. // // Return: None. // void FindLokar( OUT PULONG SlotID ) { PCI_SLOT_NUMBER SlotNum; ULONG dev, TargetID; SlotNum.u.AsULONG = 0; *SlotID = 0; for (dev = 0; dev < MAX_DEVICES; dev++) { SlotNum.u.bits.DeviceNumber = dev; ReadAMDConfig(SlotNum.u.AsULONG, &TargetID, 0, sizeof(TargetID)); if (((TargetID & DEVICEID_MASK) >> 16) == DEVICE_LOKAR) { *SlotID = SlotNum.u.AsULONG; AGPLOG(AGP_NOISE, ("FindLokar - SlotID=%x\n", *SlotID)); break; } } } // // Function Name: FindHammer() // // Description: // This routine locates which device number is assigned to Hammer. // // Parameter: // SlotID - Returned slot ID for Hammer. // // Return: None. // void FindHammer( OUT PULONG SlotID ) { PCI_SLOT_NUMBER SlotNum; ULONG dev, TargetID; SlotNum.u.AsULONG = 0; SlotNum.u.bits.FunctionNumber = 3; *SlotID = 0; for (dev = 0; dev < MAX_DEVICES; dev++) { SlotNum.u.bits.DeviceNumber = dev; ReadAMDConfig(SlotNum.u.AsULONG, &TargetID, 0, sizeof(TargetID)); if (((TargetID & DEVICEID_MASK) >> 16) == DEVICE_HAMMER) { *SlotID = SlotNum.u.AsULONG; AGPLOG(AGP_NOISE, ("FindHammer - SlotID=%x\n", *SlotID)); break; } } } // // Function Name: AgpInitializeTarget() // // Description: // Entrypoint for target initialization. This is called first. // // Parameters: // AgpExtension - Supplies the AGP extension. // // Return: // STATUS_SUCCESS on success, otherwise STATUS_UNSUCCESSFUL. // NTSTATUS AgpInitializeTarget( IN PVOID AgpExtension ) { ULONG TargetId = 0; UNICODE_STRING tempString; unsigned short tempBuffer[20]; PAGP_AMD_EXTENSION Extension = AgpExtension; // // This driver is not MP safe! If there is more than one processor // we simply fail start // if (KeNumberProcessors > 1) { return STATUS_NOT_SUPPORTED; } // // Register OutPostCode port, if specified by ErrorControl // if (ErrorControl) { PHYSICAL_ADDRESS PortAddress; PHYSICAL_ADDRESS MappedAddress; ULONG MemType = 1; PortAddress.LowPart = 0x80; PortAddress.HighPart = 0; HalTranslateBusAddress(Isa, 0, PortAddress, &MemType, &MappedAddress); if (MemType == 0) OutPostBase = (ULONG_PTR)MmMapIoSpace(MappedAddress, 1, FALSE); else OutPostBase = (ULONG_PTR)MappedAddress.LowPart; } if (ErrorControl == 2) AgpLogLevel = AGP_NOISE; // Log everything // // Make sure we are really loaded only on AMD Hammer / Lokar // FindLokar(&AgpLokarSlotID); FindHammer(&AgpHammerSlotID); ReadAMDConfig(AgpLokarSlotID, &TargetId, 0, sizeof(TargetId)); VendorID = TargetId & VENDORID_MASK; DeviceID = (TargetId & DEVICEID_MASK) >> 16; ASSERT(VendorID == VENDOR_AMD); if (VendorID != VENDOR_AMD || DeviceID != DEVICE_LOKAR) { AGPLOG(AGP_CRITICAL, ("AGPAMD - AgpInitializeTarget called for platform %08lx which is not an AMD!\n", VendorID)); return(STATUS_UNSUCCESSFUL); } // // Initialize our chipset-specific extension // Extension->ApertureStart.QuadPart = 0; Extension->ApertureLength = 0; Extension->Gart = NULL; Extension->GartLength = 0; Extension->GartPhysical.QuadPart = 0; Extension->SpecialTarget = 0; DisplayStatus(0x10); return(STATUS_SUCCESS); } // // Function Name: AgpInitializeMaster() // // Description: // Entrypoint for master initialization. This is called after target // initialization and should be used to initialize the AGP // capabilities of both master and target. // // Parameters: // AgpExtension - Supplies the AGP extension. // AgpCapabilities - Returns the capabilities of this AGP device. // // Return: // STATUS_SUCCESS on success, otherwise NTSTATUS. // NTSTATUS AgpInitializeMaster( IN PVOID AgpExtension, OUT ULONG *AgpCapabilities ) { NTSTATUS Status; PCI_AGP_CAPABILITY MasterCap; PCI_AGP_CAPABILITY TargetCap; PAGP_AMD_EXTENSION Extension = AgpExtension; ULONG SBAEnable = 0; ULONG FWEnable = 0; ULONG FourGBEnable = 0; ULONG AperturePointer; ULONG DataRate; ULONG IrongateRev = 0; BOOLEAN ReverseInit; #if DBG PCI_AGP_CAPABILITY CurrentCap; #endif // // Indicate that we can map memory through the GART aperture // *AgpCapabilities = AGP_CAPABILITIES_MAP_PHYSICAL; // // Get the master and target AGP capabilities // Status = AgpLibGetMasterCapability(AgpExtension, &MasterCap); if (!NT_SUCCESS(Status)) { AGPLOG(AGP_CRITICAL, ("AGPAMDInitializeDevice - AgpLibGetMasterCapability failed %08lx\n", Status)); DisplayStatus(0xA0); return(Status); } // // Some broken cards (Matrox Millenium II "AGP") report no valid // supported transfer rates. These are not really AGP cards. They // have an AGP Capabilities structure that reports no capabilities. // if (MasterCap.AGPStatus.Rate == 0) { AGPLOG(AGP_CRITICAL, ("AGPAMDInitializeDevice - AgpLibGetMasterCapability returned no valid transfer rate\n")); return(STATUS_INVALID_DEVICE_REQUEST); } Status = AgpLibGetPciDeviceCapability(AGP_GART_BUS_ID, AgpLokarSlotID, &TargetCap); if (!NT_SUCCESS(Status)) { AGPLOG(AGP_CRITICAL, ("AGPAMDInitializeDevice - AgpLibGetPciDeviceCapability failed %08lx\n", Status)); DisplayStatus(0xA1); return(Status); } // // Determine the greatest common denominator for data rate. // DataRate = TargetCap.AGPStatus.Rate & MasterCap.AGPStatus.Rate; AGP_ASSERT(DataRate != 0); // // Select the highest common rate. // if (DataRate & PCI_AGP_RATE_4X) { DataRate = PCI_AGP_RATE_4X; } else if (DataRate & PCI_AGP_RATE_2X) { DataRate = PCI_AGP_RATE_2X; } else if (DataRate & PCI_AGP_RATE_1X) { DataRate = PCI_AGP_RATE_1X; } // // Previously a call was made to change the rate (successfully), // use this rate again now // if (Extension->SpecialTarget & AGP_FLAG_SPECIAL_RESERVE) { DataRate = (ULONG)((Extension->SpecialTarget & AGP_FLAG_SPECIAL_RESERVE) >> AGP_FLAG_SET_RATE_SHIFT); } // // Enable SBA if both master and target support it. // SBAEnable = (TargetCap.AGPStatus.SideBandAddressing & MasterCap.AGPStatus.SideBandAddressing); // // Enable FastWrite if both master and target support it. // FWEnable = (TargetCap.AGPStatus.FastWrite & MasterCap.AGPStatus.FastWrite); // // Enable 4GB addressing if aperture pointer is 64-bit. // ReadAMDConfig(AgpLokarSlotID, &AperturePointer, APBASE_OFFSET, sizeof(AperturePointer)); if (AperturePointer & APBASE_64BIT_MASK) FourGBEnable = 1; // // Enable the Master first. // ReverseInit = (Extension->SpecialTarget & AGP_FLAG_REVERSE_INITIALIZATION) == AGP_FLAG_REVERSE_INITIALIZATION; if (ReverseInit) { MasterCap.AGPCommand.Rate = DataRate; MasterCap.AGPCommand.AGPEnable = 1; MasterCap.AGPCommand.SBAEnable = SBAEnable; MasterCap.AGPCommand.RequestQueueDepth = TargetCap.AGPStatus.RequestQueueDepthMaximum; MasterCap.AGPCommand.FastWriteEnable = FWEnable; MasterCap.AGPCommand.FourGBEnable = FourGBEnable; Status = AgpLibSetMasterCapability(AgpExtension, &MasterCap); if (!NT_SUCCESS(Status)) { AGPLOG(AGP_CRITICAL, ("AGPAMDInitializeDevice - AgpLibSetMasterCapability %08lx failed %08lx\n", &MasterCap, Status)); DisplayStatus(0xA3); }else { AGPLOG(AGP_NOISE, ("AgpInitializeMaster - DataRate=%d, SBAEnable=%d\n", DataRate, SBAEnable)); } } // // Now enable the Target. // TargetCap.AGPCommand.Rate = DataRate; TargetCap.AGPCommand.AGPEnable = 1; TargetCap.AGPCommand.SBAEnable = SBAEnable; TargetCap.AGPCommand.FastWriteEnable = FWEnable; TargetCap.AGPCommand.FourGBEnable = FourGBEnable; Status = AgpLibSetPciDeviceCapability(AGP_GART_BUS_ID, AgpLokarSlotID, &TargetCap); if (!NT_SUCCESS(Status)) { AGPLOG(AGP_CRITICAL, ("AGPAMDInitializeDevice - AgpLibSetPciDeviceCapability %08lx for target failed %08lx\n", &TargetCap, Status)); DisplayStatus(0xA2); return(Status); } if (!ReverseInit) { MasterCap.AGPCommand.Rate = DataRate; MasterCap.AGPCommand.AGPEnable = 1; MasterCap.AGPCommand.SBAEnable = SBAEnable; MasterCap.AGPCommand.RequestQueueDepth = TargetCap.AGPStatus.RequestQueueDepthMaximum; MasterCap.AGPCommand.FastWriteEnable = FWEnable; MasterCap.AGPCommand.FourGBEnable = FourGBEnable; Status = AgpLibSetMasterCapability(AgpExtension, &MasterCap); if (!NT_SUCCESS(Status)) { AGPLOG(AGP_CRITICAL, ("AGPAMDInitializeDevice - AgpLibSetMasterCapability %08lx failed %08lx\n", &MasterCap, Status)); DisplayStatus(0xA3); }else { AGPLOG(AGP_NOISE, ("AgpInitializeMaster - DataRate=%d, SBAEnable=%d\n", DataRate, SBAEnable)); } } #ifdef DEBUG2 // // Read them back, see if it worked // Status = AgpLibGetMasterCapability(AgpExtension, &CurrentCap); AGP_ASSERT(NT_SUCCESS(Status)); AGP_ASSERT(RtlEqualMemory(&CurrentCap.AGPCommand, &MasterCap.AGPCommand, sizeof(CurrentCap.AGPCommand))); Status = AgpLibGetPciDeviceCapability(AGP_GART_BUS_ID, AgpLokarSlotID, &CurrentCap); AGP_ASSERT(NT_SUCCESS(Status)); AGP_ASSERT(RtlEqualMemory(&CurrentCap.AGPCommand, &TargetCap.AGPCommand, sizeof(CurrentCap.AGPCommand))); #endif DisplayStatus(0x20); return(Status); }