Home | History | Annotate | Download | only in bus
      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  */
     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 }
     87