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