|
|
1.1 ! root 1: FILE_LICENCE ( GPL2_OR_LATER ); ! 2: ! 3: #include <stdint.h> ! 4: #include <ipxe/pci.h> ! 5: ! 6: /** ! 7: * Look for a PCI capability ! 8: * ! 9: * @v pci PCI device to query ! 10: * @v cap Capability code ! 11: * @ret address Address of capability, or 0 if not found ! 12: * ! 13: * Determine whether or not a device supports a given PCI capability. ! 14: * Returns the address of the requested capability structure within ! 15: * the device's PCI configuration space, or 0 if the device does not ! 16: * support it. ! 17: */ ! 18: int pci_find_capability ( struct pci_device *pci, int cap ) { ! 19: uint16_t status; ! 20: uint8_t pos, id; ! 21: uint8_t hdr_type; ! 22: int ttl = 48; ! 23: ! 24: pci_read_config_word ( pci, PCI_STATUS, &status ); ! 25: if ( ! ( status & PCI_STATUS_CAP_LIST ) ) ! 26: return 0; ! 27: ! 28: pci_read_config_byte ( pci, PCI_HEADER_TYPE, &hdr_type ); ! 29: switch ( hdr_type & 0x7F ) { ! 30: case PCI_HEADER_TYPE_NORMAL: ! 31: case PCI_HEADER_TYPE_BRIDGE: ! 32: default: ! 33: pci_read_config_byte ( pci, PCI_CAPABILITY_LIST, &pos ); ! 34: break; ! 35: case PCI_HEADER_TYPE_CARDBUS: ! 36: pci_read_config_byte ( pci, PCI_CB_CAPABILITY_LIST, &pos ); ! 37: break; ! 38: } ! 39: while ( ttl-- && pos >= 0x40 ) { ! 40: pos &= ~3; ! 41: pci_read_config_byte ( pci, pos + PCI_CAP_LIST_ID, &id ); ! 42: DBG ( "PCI Capability: %d\n", id ); ! 43: if ( id == 0xff ) ! 44: break; ! 45: if ( id == cap ) ! 46: return pos; ! 47: pci_read_config_byte ( pci, pos + PCI_CAP_LIST_NEXT, &pos ); ! 48: } ! 49: return 0; ! 50: } ! 51: ! 52: /** ! 53: * Find the size of a PCI BAR ! 54: * ! 55: * @v pci PCI device ! 56: * @v reg PCI register number ! 57: * @ret size BAR size ! 58: * ! 59: * It should not be necessary for any Etherboot code to call this ! 60: * function. ! 61: */ ! 62: unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg ) { ! 63: uint16_t cmd; ! 64: uint32_t start, size; ! 65: ! 66: /* Save the original command register */ ! 67: pci_read_config_word ( pci, PCI_COMMAND, &cmd ); ! 68: /* Save the original bar */ ! 69: pci_read_config_dword ( pci, reg, &start ); ! 70: /* Compute which bits can be set */ ! 71: pci_write_config_dword ( pci, reg, ~0 ); ! 72: pci_read_config_dword ( pci, reg, &size ); ! 73: /* Restore the original size */ ! 74: pci_write_config_dword ( pci, reg, start ); ! 75: /* Find the significant bits */ ! 76: /* Restore the original command register. This reenables decoding. */ ! 77: pci_write_config_word ( pci, PCI_COMMAND, cmd ); ! 78: if ( start & PCI_BASE_ADDRESS_SPACE_IO ) { ! 79: size &= PCI_BASE_ADDRESS_IO_MASK; ! 80: } else { ! 81: size &= PCI_BASE_ADDRESS_MEM_MASK; ! 82: } ! 83: /* Find the lowest bit set */ ! 84: size = size & ~( size - 1 ); ! 85: return size; ! 86: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.