• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 FILE_LICENCE ( GPL2_OR_LATER );
2 
3 #include <stdint.h>
4 #include <gpxe/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  */
pci_find_capability(struct pci_device * pci,int cap)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  */
pci_bar_size(struct pci_device * pci,unsigned int reg)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 }
87