UINT8 PciRead8 ( UINT8 Segment, UINT8 Bus, UINT8 DevFunc, UINT8 Register ) /*++ Routine Description: Perform an one byte PCI config cycle read Arguments: Segment - PCI Segment ACPI _SEG Bus - PCI Bus DevFunc - PCI Device(7:3) and Func(2:0) Register - PCI config space register Returns: Data read from PCI config space --*/ { EFI_STATUS Status; UINT32 PciAddress; UINT32 PciAddress1; UINT8 Data; PciAddress = GetPciAddress (Segment, Bus, DevFunc, Register); // // Set bit 31 for PCI config access // PciAddress1 = PciAddress; PciAddress = ((PciAddress & 0xFFFFFFFC) | (0x80000000)); Status = EfiIoWrite (EfiCpuIoWidthUint32, PCI_CONFIG_INDEX_PORT, 1, &PciAddress); if (EFI_ERROR (Status)) { return 0; } EfiIoRead (EfiCpuIoWidthUint8, (PCI_CONFIG_DATA_PORT + (PciAddress1 & 0x3)), 1, &Data); return Data; }
UINT32 IoRead32 ( IN UINT64 Address ) /*++ Routine Description: Do a four byte IO read Arguments: Address - IO address to read Returns: Data read --*/ { UINT32 Buffer; Buffer = 0; EfiIoRead (EfiCpuIoWidthUint32, Address, 1, &Buffer); return Buffer; }
UINT16 IoRead16 ( IN UINT64 Address ) /*++ Routine Description: Do a two byte IO read Arguments: Address - IO address to read Returns: Data read --*/ { UINT16 Buffer; Buffer = 0; EfiIoRead (EfiCpuIoWidthUint16, Address, 1, &Buffer); return Buffer; }
// // Delay Primative // VOID EfiStall ( IN UINTN Microseconds ) /*++ Routine Description: Delay for at least the request number of microseconds Arguments: Microseconds - Number of microseconds to delay. Returns: NONE --*/ { UINT8 Data; UINT8 InitialState; UINTN CycleIterations; CycleIterations = 0; Data = 0; InitialState = 0; if (EfiAtRuntime ()) { // // The time-source is 30 us granular, so calibrate the timing loop // based on this baseline // Error is possible 30us. // CycleIterations = (Microseconds - 1) / 30 + 1; // // Use the DMA Refresh timer in port 0x61. Cheap but effective. // The only issue is that the granularity is 30us, and we want to // guarantee "at least" one full transition to avoid races. // // // _____________/----------\__________/-------- // // |<--15us-->|<--15us-->| // // --------------------------------------------------> Time (us) // while (CycleIterations--) { EfiIoRead (EfiCpuIoWidthUint8, 0x61, 1, &Data); Data &= REFRESH_CYCLE_TOGGLE_BIT; InitialState = Data; // // Capture first transition (strictly less than one period) // while (InitialState == Data) { EfiIoRead (EfiCpuIoWidthUint8, 0x61, 1, &Data); Data &= REFRESH_CYCLE_TOGGLE_BIT; } InitialState = Data; // // Capture next transition (guarantee at least one full pulse) // while (InitialState == Data) { EfiIoRead (EfiCpuIoWidthUint8, 0x61, 1, &Data); Data &= REFRESH_CYCLE_TOGGLE_BIT; } } } else { gBS->Stall (Microseconds); } }