/*++ Copyright (c) 1993 Weitek Corporation Module Name: pci.c Abstract: This module contains PCI code for the Weitek P9 miniport device driver. Environment: Kernel mode Revision History may be found at the end of this file. --*/ #include "p9.h" #include "p9gbl.h" #include "p9000.h" #include "pci.h" #include "vga.h" #include "p91regs.h" // // OEM specific static data. // extern VOID VLSetModeP91( PHW_DEVICE_EXTENSION HwDeviceExtension ); extern VOID VLEnableP91( PHW_DEVICE_EXTENSION HwDeviceExtension ); VIDEO_ACCESS_RANGE Pci9001DefDACRegRange[] = { { RS_0_PCI_9001_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_1_PCI_9001_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_2_PCI_9001_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_3_PCI_9001_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_4_PCI_9001_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_5_PCI_9001_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_6_PCI_9001_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_7_PCI_9001_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_8_PCI_9001_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_9_PCI_9001_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_A_PCI_9001_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_B_PCI_9001_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_C_PCI_9001_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_D_PCI_9001_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_E_PCI_9001_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_F_PCI_9001_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable } }; VIDEO_ACCESS_RANGE Pci9002DefDACRegRange[] = { { RS_0_PCI_9002_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_1_PCI_9002_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_2_PCI_9002_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_3_PCI_9002_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_4_PCI_9002_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_5_PCI_9002_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_6_PCI_9002_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_7_PCI_9002_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_8_PCI_9002_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_9_PCI_9002_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_A_PCI_9002_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_B_PCI_9002_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_C_PCI_9002_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_D_PCI_9002_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_E_PCI_9002_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable }, { RS_F_PCI_9002_ADDR, // Low address 0x00000000, // Hi address 0x01, // length 1, // Is range in i/o space? 1, // Range should be visible 1 // Range should be shareable } }; /****************************************************************************** ** bIntergraphBoard * * PARAMETERS: HwDeviceExtension * * DESCRIPTION: Determine if we're trying to init an Intergraph Board * * RETURNS: TRUE - if this is an Intergraph Board * FALSE - if this is not an Intergraph Board * * CREATED: 02/20/95 13:33:23 * * BY: c-jeffn * * copyright (c) 1995, Newman Consulting * ******************************************************************************/ BOOLEAN bIntergraphBoard( PHW_DEVICE_EXTENSION HwDeviceExtension ) { ULONG ulRet; UCHAR jConfig66, jOEMId, *pjOEMId; VP_STATUS vpStatus; VIDEO_ACCESS_RANGE AccessRange; BOOLEAN bRet; VideoDebugPrint((2, "P9!bIntergraphBoard - Entry\n")); // Note that the P9100 must be in native mode before this function // is called. bRet = FALSE; // Test to see if the P9100 indicates external io device is there // If not, can't be Intergraph board if ( (HwDeviceExtension->p91State.ulPuConfig & P91_PUC_EXT_IO) == 0 ) goto exit; // Set Bit 4 of Config 66. This will allow access to the Intergraph // Specific registers. jConfig66 = 0x10; ulRet = VideoPortSetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &jConfig66, 0x42, sizeof (UCHAR)); if (ulRet != 1) { VideoDebugPrint((2, "P9!bIntergraphBoard - failed VideoPortSetBusData\n")); VideoDebugPrint((2, "\tulRet: %x\n", ulRet)); goto exit; } // Check P9100 register 0x208 for ID in native mode ulRet = P9_RD_REG(P91_EXT_IO_ID); // Get the external io id value jOEMId = (UCHAR)(ulRet >> 16); // per Weitek programmer's manual if (jOEMId == 0xFE) // This is the id assigned to Intergraph bRet = TRUE; // Need to reset Config register 66 bit 4. jConfig66 = 0x00; ulRet = VideoPortSetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &jConfig66, 0x42, sizeof (UCHAR)); exit: VideoDebugPrint((2, "P9!bIntergraphBoard - Exit: %x\n", bRet)); return (bRet); } // // this thing was 0. PNP forces fix since the system now put the IO // resources at index 1 in the VIDEO_ACCESS_RANGE returned via // VideoPortGetAccessRanges(). // #define IO_ACCESS_INDEX 1 #define VGABIOS_ACCESS_INDEX 2 BOOLEAN PciGetBaseAddr( PHW_DEVICE_EXTENSION HwDeviceExtension ) /*++ Routine Description: Perform board detection and if present return the P9 base address. Arguments: HwDeviceExtension - Pointer to the miniport driver's device extension. Return Value: TRUE - Board found, P9 and Frame buffer address info was placed in the device extension. PCI extended base address was placed in the device extension. FALSE - Board not found. --*/ { VIDEO_ACCESS_RANGE PciAccessRange[3]; PVIDEO_ACCESS_RANGE DefaultDACRegRange; ULONG ulTempAddr; PUCHAR pucBiosAddr; PUCHAR pucBoardAddr; ULONG ulTemp; LONG i; VP_STATUS status; ULONG wcpID; VideoPortZeroMemory(PciAccessRange, 3 * sizeof(VIDEO_ACCESS_RANGE)); VideoDebugPrint((2, "PciGetbaseAddr() ENTRY\n")); // // Only the viper p9000 works on the Siemens boxes // if (HwDeviceExtension->MachineType == SIEMENS || HwDeviceExtension->MachineType == SIEMENS_P9100_VLB) { VideoDebugPrint((1, "PciGetbaseAddr() Failed, line %d\n", __LINE__)); return FALSE; } // // See if the PCI HAL can locate a Weitek 9001 PCI Board. // // // First check for a P9100 // if (PciFindDevice(HwDeviceExtension, WTK_9100_ID, WTK_VENDOR_ID, &HwDeviceExtension->PciSlotNum)) { wcpID = P9100_ID; HwDeviceExtension->usBusType = PCI; // Just a hack to get things working. // NOTE: !!! WE should really do the detection. HwDeviceExtension->p91State.bVideoPowerEnabled = FALSE; // Now make sure we are looking for a P9100, if were not // then fail. if (HwDeviceExtension->P9CoprocInfo.CoprocId != P9100_ID) { VideoDebugPrint((1, "Not a 9100, even though PCIFindDevice() thinks it is\n")); return(FALSE); } #ifdef _MIPS_ // // SNI platform recognition and specific stuff // { extern VP_STATUS GetCPUIdCallback( PVOID HwDeviceExtension, PVOID Context, VIDEO_DEVICE_DATA_TYPE DeviceDataType, PVOID Identifier, ULONG IdentifierLength, PVOID ConfigurationData, ULONG ConfigurationDataLength, PVOID ComponentInformation, ULONG ComponentInformationLength ); if(VideoPortIsCpu(L"RM200PCI") || VideoPortIsCpu(L"RM300PCI") || VideoPortIsCpu(L"RM300PCI MP") || VideoPortIsCpu(L"RM400PCI") || VideoPortIsCpu(L"RM4x0PCI")) { // adjust the VGA physical address with the E/ISA I/O space DriverAccessRanges[1].RangeStart.LowPart += 0x14000000 ; HwDeviceExtension->MachineType = SIEMENS_P9100_PCi; } } #endif } else if (PciFindDevice(HwDeviceExtension, WTK_9001_ID, WTK_VENDOR_ID, &HwDeviceExtension->PciSlotNum)) { wcpID = P9000_ID; // Now make sure we are looking for a P9000, if were not // then fail. if (HwDeviceExtension->P9CoprocInfo.CoprocId != P9000_ID) { VideoDebugPrint((1, "PciGetbaseAddr() Failed !P9000, line %d\n", __LINE__)); return(FALSE); } VideoDebugPrint((2, "PciGetbaseAddr() This is a P900X\n")); // // Read the config space to determine if // this is Rev 1 or 2. This will determine at which addresses // the DAC registers are mapped. // if (!VideoPortGetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &ulTemp, P9001_REV_ID, sizeof(ulTemp))) { VideoDebugPrint((1, "PciGetbaseAddr() Failed, DAC weirdness, line %d\n", __LINE__)); return(FALSE); } // // Got the 9001 rev id. Choose the appropriate table of DAC register // addresses. // switch((UCHAR) (ulTemp)) { case 1 : VideoDebugPrint((2, "PciGetbaseAddr(), DAC id is 1\n")); // // This is a Rev 1 9001, which uses the standard VL DAC // Addresses. All known rev 1 implementations use the // Weitek 5286 VGA chip. // DefaultDACRegRange = VLDefDACRegRange; HwDeviceExtension->AdapterDesc.bWtk5x86 = TRUE; break; case 2 : default: VideoDebugPrint((2, "PciGetbaseAddr(), DAC id is 2 or default\n")); // // This is a Rev 2 9001. Set up the table of DAC register // offsets accordingly. // DefaultDACRegRange = Pci9001DefDACRegRange; // // A Rev 2 9001 is present. Get the BIOS ROM address from the // PCI configuration space so we can do a ROM scan to // determine if this is a Viper PCI adapter. // PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart = 0; PciAccessRange[IO_ACCESS_INDEX].RangeStart.HighPart = 0; if (VideoPortGetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart, P9001_BIOS_BASE_ADDR, sizeof(ULONG)) == 0) { VideoDebugPrint((1, "PciGetbaseAddr() Failed. ROM bios not P9001, line %d\n", __LINE__)); return FALSE; } if (PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart) { // // We found an address for the BIOS. Verify it. // // Set up the access range so we can map out the BIOS ROM // space. This will allow us to scan the ROM and detect the // presence of a Viper PCI adapter. // PciAccessRange[IO_ACCESS_INDEX].RangeInIoSpace = FALSE; PciAccessRange[IO_ACCESS_INDEX].RangeVisible = TRUE; PciAccessRange[IO_ACCESS_INDEX].RangeShareable = TRUE; PciAccessRange[IO_ACCESS_INDEX].RangeLength = 0x1000; // // Check to see if another miniport driver has allocated the // BIOS' memory space. // if (VideoPortVerifyAccessRanges(HwDeviceExtension, 1L, PciAccessRange) != NO_ERROR) { PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart = 0; } } if (PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart == 0) { status = VideoPortGetAccessRanges(HwDeviceExtension, 0, NULL, 3, PciAccessRange, NULL, NULL, &HwDeviceExtension->PciSlotNum); if (status != NO_ERROR) { VideoDebugPrint((1, "PciGetbaseAddr() Failed, GetAccessRanges(), line %d, status:%x\n", __LINE__, status)); return(FALSE); } } // // Map in the BIOS' memory space. If it can't be mapped, // return an error. // PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart.LowPart = 0xC0000; PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart.HighPart = 0x0000; PciAccessRange[VGABIOS_ACCESS_INDEX].RangeLength = BIOS_RANGE_LEN; PciAccessRange[VGABIOS_ACCESS_INDEX].RangeInIoSpace = FALSE; VideoDebugPrint((1, "PciGetbaseAddr() about to get BIOS address, line %d, status:%x\n", __LINE__, status)); if ((pucBiosAddr = VideoPortGetDeviceBase(HwDeviceExtension, PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart, PciAccessRange[VGABIOS_ACCESS_INDEX].RangeLength, PciAccessRange[VGABIOS_ACCESS_INDEX].RangeInIoSpace)) == 0) { VideoDebugPrint((1, "PciGetbaseAddr() Failed on VGA bios, line %d\n", __LINE__)); return(FALSE); } // // Enable the Adapter BIOS. // ulTemp = PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart.LowPart | PCI_BIOS_ENB; VideoDebugPrint((1, "PciGetbaseAddr() about to enable bios, line %d, status:%x\n", __LINE__, status)); VideoPortSetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &ulTemp, P9001_BIOS_BASE_ADDR, sizeof(ULONG)); VideoDebugPrint((1, "PciGetbaseAddr() about to scan rom, line %d, status:%x\n", __LINE__, status)); if (VideoPortScanRom(HwDeviceExtension, pucBiosAddr, BIOS_RANGE_LEN, VIPER_ID_STR)) { // // A Viper PCI is present, use the Viper set mode, // enable/disable video function pointers, and clk // divisor values. Also, Viper PCI does not // use a Weitek VGA. // HwDeviceExtension->AdapterDesc.OEMSetMode = ViperSetMode; HwDeviceExtension->AdapterDesc.P9EnableVideo = ViperPciP9Enable; HwDeviceExtension->AdapterDesc.P9DisableVideo = ViperPciP9Disable; HwDeviceExtension->AdapterDesc.iClkDiv = 4; HwDeviceExtension->AdapterDesc.bWtk5x86 = FALSE; } else { // // All non-Viper Rev 2 implementations use a Weitek // 5286 VGA chip. // HwDeviceExtension->AdapterDesc.bWtk5x86 = TRUE; } // // Restore the BIOS register to it's original value. // VideoDebugPrint((1, "PciGetbaseAddr() about to restore, line %d, status:%x\n", __LINE__, status)); VideoPortSetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &ulTempAddr, P9001_BIOS_BASE_ADDR, sizeof(ULONG)); VideoPortFreeDeviceBase(HwDeviceExtension, (PVOID) pucBiosAddr); break; } } else if (PciFindDevice(HwDeviceExtension, // Search for a Weitek 9002. WTK_9002_ID, WTK_VENDOR_ID, &HwDeviceExtension->PciSlotNum)) { wcpID = P9000_ID; // Now make sure we are looking for a P9000, if were not // then fail. if (HwDeviceExtension->P9CoprocInfo.CoprocId != P9000_ID) { VideoDebugPrint((1, "PciGetbaseAddr() Failed, not a P9002, line %d\n", __LINE__)); return(FALSE); } // // Found a 9002 board. Set up the table of DAC addresses // accordingly. // DefaultDACRegRange = Pci9002DefDACRegRange; } else { // // No Weitek PCI devices were found, return an error. // VideoDebugPrint((1, "PciGetbaseAddr() Failed, line %d\n", __LINE__)); return(FALSE); } // // Get the base address of the adapter. // Some machines rely on the address not changing - if the address changes // the machine randomly appears to corrupt memory. // So use the pre-configured address if it is available. // HwDeviceExtension->P9PhysAddr.LowPart = 0; VideoPortGetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &HwDeviceExtension->P9PhysAddr.LowPart, P9001_BASE_ADDR, sizeof(ULONG)); if (HwDeviceExtension->P9PhysAddr.LowPart == 0) { IO_RESOURCE_DESCRIPTOR ioResource = { IO_RESOURCE_PREFERRED, CmResourceTypeMemory, CmResourceShareDeviceExclusive, 0, CM_RESOURCE_MEMORY_READ_WRITE, 0, { RESERVE_PCI_ADDRESS_SPACE, // Length RESERVE_PCI_ADDRESS_SPACE, // Alignment { 0x10000000, 0 }, // Minimum start address { 0xefffffff, 0} // Maximum end address } }; status = VideoPortGetAccessRanges(HwDeviceExtension, 1, &ioResource, 3, PciAccessRange, NULL, NULL, &HwDeviceExtension->PciSlotNum); if (status == NO_ERROR) { HwDeviceExtension->P9PhysAddr = PciAccessRange[IO_ACCESS_INDEX].RangeStart; // // Save the physical base address in the PCI config space. // VideoPortSetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &HwDeviceExtension->P9PhysAddr.LowPart, P9001_BASE_ADDR, sizeof(ULONG)); } } if (HwDeviceExtension->P9PhysAddr.LowPart == 0) { VideoDebugPrint((1, "PciGetbaseAddr() Failed, line %d\n", __LINE__)); return(FALSE); } // // The P9100 can access the DAC directly, so no I/O space needs to be // allocated for DAC access. // if (wcpID == P9000_ID) { status = VideoPortGetAccessRanges(HwDeviceExtension, 0, NULL, 3, PciAccessRange, NULL, NULL, &HwDeviceExtension->PciSlotNum); if (status == NO_ERROR) { HwDeviceExtension->P9001PhysicalAddress = PciAccessRange[IO_ACCESS_INDEX].RangeStart; } else { VideoDebugPrint((1, "VideoPortGetAccessRanges() Failed with status %x, line %d\n", status, __LINE__)); return(FALSE); } // // If this is a 9002 board, map in and read the VGA id register. // if (DefaultDACRegRange == Pci9002DefDACRegRange) { // // Set up the access range so we can map out the VGA ID register. // PciAccessRange[IO_ACCESS_INDEX].RangeInIoSpace = TRUE; PciAccessRange[IO_ACCESS_INDEX].RangeVisible = TRUE; PciAccessRange[IO_ACCESS_INDEX].RangeShareable = TRUE; PciAccessRange[IO_ACCESS_INDEX].RangeLength = 1; PciAccessRange[IO_ACCESS_INDEX].RangeStart = HwDeviceExtension->P9001PhysicalAddress; PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart += P9002_VGA_ID; // // Map in the VGA ID register. If it can't be mapped, // we can't determine the VGA type, so just use the default. // if ((pucBoardAddr = VideoPortGetDeviceBase(HwDeviceExtension, PciAccessRange[IO_ACCESS_INDEX].RangeStart, PciAccessRange[IO_ACCESS_INDEX].RangeLength, PciAccessRange[IO_ACCESS_INDEX].RangeInIoSpace)) != 0) { HwDeviceExtension->AdapterDesc.bWtk5x86 = (UCHAR)((VideoPortReadPortUchar(pucBoardAddr) & VGA_MSK) == WTK_VGA); VideoPortFreeDeviceBase(HwDeviceExtension, (PVOID) pucBoardAddr); } else { // // Assume this is a 5x86 VGA. // HwDeviceExtension->AdapterDesc.bWtk5x86 = TRUE; } } // // Compute the actual DAC register addresses relative to the PCI // base address. // for (i = 0; i < HwDeviceExtension->Dac.cDacRegs; i++) { // // If this is not a palette addr or data register, and the board // is not using the standard VL addresses, compute the register // address relative to the register base address. // if ((i > 3) && (DefaultDACRegRange != VLDefDACRegRange)) { DefaultDACRegRange[i].RangeStart.LowPart += HwDeviceExtension->P9001PhysicalAddress.LowPart; } } // // Copy the DAC register access range into the global list of access // ranges. // VideoPortMoveMemory(&DriverAccessRanges[NUM_DRIVER_ACCESS_RANGES], DefaultDACRegRange, sizeof(VIDEO_ACCESS_RANGE) * HwDeviceExtension->Dac.cDacRegs); // // This is a hack. Initialize an additional access range to map out // the entire 4K range of contiguous IO space starting at PCI_REG_BASE. // apparently the 9001 decodes accesses over this entire range rather // than the individual register offsets within this range. // // // Set up the access range so we can map the entire 4k IO range. // PciAccessRange[IO_ACCESS_INDEX].RangeInIoSpace = TRUE; PciAccessRange[IO_ACCESS_INDEX].RangeVisible = TRUE; PciAccessRange[IO_ACCESS_INDEX].RangeShareable = TRUE; PciAccessRange[IO_ACCESS_INDEX].RangeLength = P9001_IO_RANGE; PciAccessRange[IO_ACCESS_INDEX].RangeStart = HwDeviceExtension->P9001PhysicalAddress; VideoDebugPrint((1, "PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart.LowPart:%x\n", PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart.LowPart)); VideoPortMoveMemory(&DriverAccessRanges[NUM_DRIVER_ACCESS_RANGES + NUM_DAC_ACCESS_RANGES], &PciAccessRange[IO_ACCESS_INDEX], sizeof(VIDEO_ACCESS_RANGE)); } // end of "if (wcpID == P9000_ID)" block. return(TRUE); } BOOLEAN PciFindDevice( IN PHW_DEVICE_EXTENSION HwDeviceExtension, IN USHORT usDeviceId, IN USHORT usVendorId, IN OUT PULONG pulSlotNum ) /*++ Routine Description: Attempts to find a PCI device which matches the passed device id, vendor id and index. Arguments: HwDeviceExtension - Pointer to the device extension. usDeviceId - PCI Device Id. usVendorId - PCI Vendor Id. pulSlotNum - Input -> Starting Slot Number Output -> If found, the slot number of the matching device. Return Value: TRUE if device found. --*/ { ULONG pciBuffer; PCI_SLOT_NUMBER slotData; PPCI_COMMON_CONFIG pciData; // // // typedef struct _PCI_SLOT_NUMBER { // union { // struct { // ULONG DeviceNumber:5; // ULONG FunctionNumber:3; // ULONG Reserved:24; // } bits; // ULONG AsULONG; // } u; // } PCI_SLOT_NUMBER, *PPCI_SLOT_NUMBER; // slotData.u.AsULONG = 0; pciData = (PPCI_COMMON_CONFIG) &pciBuffer; // // Look at each device. // *pulSlotNum = 0; slotData.u.bits.DeviceNumber = *pulSlotNum; slotData.u.bits.FunctionNumber = 0; if (VideoPortGetBusData(HwDeviceExtension, PCIConfiguration, slotData.u.AsULONG, (PVOID) pciData, 0, sizeof(ULONG)) == 0) { // // Out of functions. Go to next PCI bus. // return(FALSE); } if (pciData->VendorID == PCI_INVALID_VENDORID) { // // No PCI device, or no more functions on device // move to next PCI device. // return(FALSE); } if (pciData->VendorID == usVendorId && pciData->DeviceID == usDeviceId) { *pulSlotNum = slotData.u.AsULONG; return(TRUE); } // // No matching PCI device was found. // return(FALSE); } BOOLEAN PciP9MemEnable( PHW_DEVICE_EXTENSION HwDeviceExtension ) /*++ Routine Description: Enable the physical memory and IO resources for PCI adapters. Arguments: HwDeviceExtension - Pointer to the miniport driver's device extension. Return Value: None. --*/ { ULONG ulTemp; // // Read the PCI command register to determine if the memory/io // resources are enabled. If not, enable them. // if (!VideoPortGetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &ulTemp, P9001_CMD_REG, sizeof(ulTemp))) { return(FALSE); } else if (!(ulTemp & (P9001_MEM_ENB | P9001_IO_ENB))) { ulTemp |= (P9001_MEM_ENB | P9001_IO_ENB); if (!VideoPortSetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &ulTemp, P9001_CMD_REG, sizeof(ulTemp))) { return(FALSE); } } return(TRUE); } VOID ViperPciP9Enable( PHW_DEVICE_EXTENSION HwDeviceExtension ) /*++ Routine Description: Perform the OEM specific tasks necessary to enable the P9. These include memory mapping, setting the sync polarities, and enabling the P9 video output. Arguments: HwDeviceExtension - Pointer to the miniport driver's device extension. Return Value: None. --*/ { USHORT holdit; // // Select external frequency, and clear the polarity bits. // holdit = VGA_RD_REG(MISCIN) | (MISCD | MISCC); holdit &= ~(VIPER_HSYNC_POL_MASK | VIPER_VSYNC_POL_MASK); // // Viper controls h and v sync polarities independently. // if (HwDeviceExtension->VideoData.vp == POSITIVE) { holdit |= VIPER_VSYNC_POL_MASK; } if (HwDeviceExtension->VideoData.hp == POSITIVE) { holdit |= VIPER_HSYNC_POL_MASK; } VGA_WR_REG(MISCOUT, holdit); // // If this is a Weitek VGA, unlock the VGA. // if (HwDeviceExtension->AdapterDesc.bWtk5x86) { UnlockVGARegs(HwDeviceExtension); } // // Enable P9 Video. // VGA_WR_REG(SEQ_INDEX_PORT, SEQ_OUTCNTL_INDEX); VGA_WR_REG(SEQ_DATA_PORT, (VGA_RD_REG(SEQ_DATA_PORT)) | P9_VIDEO_ENB); // // If this is a Weitek VGA, lock the VGA sequencer registers. // if (HwDeviceExtension->AdapterDesc.bWtk5x86) { LockVGARegs(HwDeviceExtension); } return; } BOOLEAN ViperPciP9Disable( PHW_DEVICE_EXTENSION HwDeviceExtension ) /*++ Routine Description: Arguments: HwDeviceExtension - Pointer to the miniport driver's device extension. pPal - Pointer to the array of pallete entries. StartIndex - Specifies the first pallete entry provided in pPal. Count - Number of palette entries in pPal Return Value: TRUE, indicating no int10 is needed to complete the switch --*/ { // // Unlock the VGA extended regs to disable P9 video output. // // // If this is a Weitek VGA, unlock the VGA. // if (HwDeviceExtension->AdapterDesc.bWtk5x86) { UnlockVGARegs(HwDeviceExtension); } VGA_WR_REG(SEQ_INDEX_PORT, SEQ_OUTCNTL_INDEX); VGA_WR_REG(SEQ_DATA_PORT, (VGA_RD_REG(SEQ_DATA_PORT)) & P9_VIDEO_DIS); // // Restore clock select bits. // VGA_WR_REG(MISCOUT, HwDeviceExtension->MiscRegState); // // If this is a Weitek VGA, lock the VGA sequencer registers. // if (HwDeviceExtension->AdapterDesc.bWtk5x86) { LockVGARegs(HwDeviceExtension); } return TRUE; }