|
|
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.