/*++ Copyright (c) 2012 Minoca Corp. All Rights Reserved Module Name: rootbus.c Abstract: This module implements support for the PCI root bus on PC/AT systems through I/O ports CF8/CFC. Author: Evan Green 17-Sep-2012 Environment: Kernel --*/ // // ------------------------------------------------------------------- Includes // #include "pci.h" #include // // ---------------------------------------------------------------- Definitions // // // --------------------------------------------------------------------- Macros // // // This macro creates the address value used to read from or write to PCI // configuration space. All parameters should be UCHARs. // #define PCI_CONFIG_ADDRESS(_Bus, _Device, _Function, _Register) \ (((ULONG)(_Bus) << 16) | ((ULONG)(_Device) << 11) | \ ((ULONG)(_Function) << 8) | ((_Register) & 0xFF) | 0x80000000) // // ------------------------------------------------------ Data Type Definitions // // // ----------------------------------------------- Internal Function Prototypes // // // -------------------------------------------------------------------- Globals // // // ------------------------------------------------------------------ Functions // ULONGLONG PcipRootReadConfig ( UCHAR Bus, UCHAR Device, UCHAR Function, ULONG Register, ULONG AccessSize ) /*++ Routine Description: This routine reads from PCI Configuration Space on the root PCI bus. Arguments: Bus - Supplies the bus number to read from. Device - Supplies the device number to read from. Valid values are 0 to 31. Function - Supplies the PCI function to read from. Valid values are 0 to 7. Register - Supplies the configuration register to read from. AccessSize - Supplies the size of the access to make. Valid values are 1, 2, 4, and 8. Return Value: Returns the value read from the bus, or 0xFFFFFFFF on error. --*/ { ULONG Address; ULONGLONG Value; // // Create the configuration address and write it into the address port. // Address = PCI_CONFIG_ADDRESS(Bus, Device, Function, Register); HlIoPortOutLong(PCI_ROOT_CONFIG_ADDRESS, Address); // // Read the data at that address. // switch (AccessSize) { case sizeof(UCHAR): Value = HlIoPortInByte(PCI_ROOT_CONFIG_DATA); break; case sizeof(USHORT): Value = HlIoPortInShort(PCI_ROOT_CONFIG_DATA); break; case sizeof(ULONG): Value = HlIoPortInLong(PCI_ROOT_CONFIG_DATA); break; case sizeof(ULONGLONG): Value = HlIoPortInLong(PCI_ROOT_CONFIG_DATA); HlIoPortOutLong(PCI_ROOT_CONFIG_ADDRESS, Address + 4); Value |= ((ULONGLONG)HlIoPortInLong(PCI_ROOT_CONFIG_DATA)) << 32; break; default: ASSERT(FALSE); Value = -1; break; } return Value; } VOID PcipRootWriteConfig ( UCHAR Bus, UCHAR Device, UCHAR Function, ULONG Register, ULONG AccessSize, ULONGLONG Value ) /*++ Routine Description: This routine writes to PCI Configuration Space on the PCI root bus. Arguments: Bus - Supplies the bus number to write to. Device - Supplies the device number to write to. Valid values are 0 to 31. Function - Supplies the PCI function to write to. Valid values are 0 to 7. Register - Supplies the configuration register to write to. AccessSize - Supplies the size of the access to make. Valid values are 1, 2, 4, and 8. Value - Supplies the value to write to the register. Return Value: None. --*/ { ULONG Address; // // Create the configuration address and write it into the address port. // Address = PCI_CONFIG_ADDRESS(Bus, Device, Function, Register); HlIoPortOutLong(PCI_ROOT_CONFIG_ADDRESS, Address); // // Write the data at that address. // switch (AccessSize) { case sizeof(UCHAR): HlIoPortOutByte(PCI_ROOT_CONFIG_DATA, (UCHAR)Value); break; case sizeof(USHORT): HlIoPortOutShort(PCI_ROOT_CONFIG_DATA, (USHORT)Value); break; case sizeof(ULONG): HlIoPortOutLong(PCI_ROOT_CONFIG_DATA, (ULONG)Value); break; case sizeof(ULONGLONG): HlIoPortOutLong(PCI_ROOT_CONFIG_DATA, (ULONG)Value); HlIoPortOutLong(PCI_ROOT_CONFIG_ADDRESS, Address + 4); HlIoPortOutLong(PCI_ROOT_CONFIG_DATA, (ULONG)(Value >> 32)); break; default: ASSERT(FALSE); break; } return; } // // --------------------------------------------------------- Internal Functions //