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