|  | @@ -3,6 +3,24 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
		
	
		
			
			| 3 | 3 |  #include <stdint.h>
 | 
		
	
		
			
			| 4 | 4 |  #include <ipxe/pci.h>
 | 
		
	
		
			
			| 5 | 5 |  
 | 
		
	
		
			
			|  | 6 | +static int pci_find_capability_common ( struct pci_device *pci,
 | 
		
	
		
			
			|  | 7 | +					uint8_t pos, int cap ) {
 | 
		
	
		
			
			|  | 8 | +	uint8_t id;
 | 
		
	
		
			
			|  | 9 | +	int ttl = 48;
 | 
		
	
		
			
			|  | 10 | +
 | 
		
	
		
			
			|  | 11 | +	while ( ttl-- && pos >= 0x40 ) {
 | 
		
	
		
			
			|  | 12 | +		pos &= ~3;
 | 
		
	
		
			
			|  | 13 | +		pci_read_config_byte ( pci, pos + PCI_CAP_ID, &id );
 | 
		
	
		
			
			|  | 14 | +		DBG ( "PCI Capability: %d\n", id );
 | 
		
	
		
			
			|  | 15 | +		if ( id == 0xff )
 | 
		
	
		
			
			|  | 16 | +			break;
 | 
		
	
		
			
			|  | 17 | +		if ( id == cap )
 | 
		
	
		
			
			|  | 18 | +			return pos;
 | 
		
	
		
			
			|  | 19 | +		pci_read_config_byte ( pci, pos + PCI_CAP_NEXT, &pos );
 | 
		
	
		
			
			|  | 20 | +	}
 | 
		
	
		
			
			|  | 21 | +	return 0;
 | 
		
	
		
			
			|  | 22 | +}
 | 
		
	
		
			
			|  | 23 | +
 | 
		
	
		
			
			| 6 | 24 |  /**
 | 
		
	
		
			
			| 7 | 25 |   * Look for a PCI capability
 | 
		
	
		
			
			| 8 | 26 |   *
 | 
		
	
	
		
			
			|  | @@ -17,9 +35,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
		
	
		
			
			| 17 | 35 |   */
 | 
		
	
		
			
			| 18 | 36 |  int pci_find_capability ( struct pci_device *pci, int cap ) {
 | 
		
	
		
			
			| 19 | 37 |  	uint16_t status;
 | 
		
	
		
			
			| 20 |  | -	uint8_t pos, id;
 | 
		
	
		
			
			|  | 38 | +	uint8_t pos;
 | 
		
	
		
			
			| 21 | 39 |  	uint8_t hdr_type;
 | 
		
	
		
			
			| 22 |  | -	int ttl = 48;
 | 
		
	
		
			
			| 23 | 40 |  
 | 
		
	
		
			
			| 24 | 41 |  	pci_read_config_word ( pci, PCI_STATUS, &status );
 | 
		
	
		
			
			| 25 | 42 |  	if ( ! ( status & PCI_STATUS_CAP_LIST ) )
 | 
		
	
	
		
			
			|  | @@ -36,17 +53,28 @@ int pci_find_capability ( struct pci_device *pci, int cap ) {
 | 
		
	
		
			
			| 36 | 53 |  		pci_read_config_byte ( pci, PCI_CB_CAPABILITY_LIST, &pos );
 | 
		
	
		
			
			| 37 | 54 |  		break;
 | 
		
	
		
			
			| 38 | 55 |  	}
 | 
		
	
		
			
			| 39 |  | -	while ( ttl-- && pos >= 0x40 ) {
 | 
		
	
		
			
			| 40 |  | -		pos &= ~3;
 | 
		
	
		
			
			| 41 |  | -		pci_read_config_byte ( pci, pos + PCI_CAP_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_NEXT, &pos );
 | 
		
	
		
			
			| 48 |  | -	}
 | 
		
	
		
			
			| 49 |  | -	return 0;
 | 
		
	
		
			
			|  | 56 | +	return pci_find_capability_common ( pci, pos, cap );
 | 
		
	
		
			
			|  | 57 | +}
 | 
		
	
		
			
			|  | 58 | +
 | 
		
	
		
			
			|  | 59 | +/**
 | 
		
	
		
			
			|  | 60 | + * Look for another PCI capability
 | 
		
	
		
			
			|  | 61 | + *
 | 
		
	
		
			
			|  | 62 | + * @v pci		PCI device to query
 | 
		
	
		
			
			|  | 63 | + * @v pos		Address of the current capability
 | 
		
	
		
			
			|  | 64 | + * @v cap		Capability code
 | 
		
	
		
			
			|  | 65 | + * @ret address		Address of capability, or 0 if not found
 | 
		
	
		
			
			|  | 66 | + *
 | 
		
	
		
			
			|  | 67 | + * Determine whether or not a device supports a given PCI capability
 | 
		
	
		
			
			|  | 68 | + * starting the search at a given address within the device's PCI
 | 
		
	
		
			
			|  | 69 | + * configuration space. Returns the address of the next capability
 | 
		
	
		
			
			|  | 70 | + * structure within the device's PCI configuration space, or 0 if the
 | 
		
	
		
			
			|  | 71 | + * device does not support another such capability.
 | 
		
	
		
			
			|  | 72 | + */
 | 
		
	
		
			
			|  | 73 | +int pci_find_next_capability ( struct pci_device *pci, int pos, int cap ) {
 | 
		
	
		
			
			|  | 74 | +	uint8_t new_pos;
 | 
		
	
		
			
			|  | 75 | +
 | 
		
	
		
			
			|  | 76 | +	pci_read_config_byte ( pci, pos + PCI_CAP_NEXT, &new_pos );
 | 
		
	
		
			
			|  | 77 | +	return pci_find_capability_common ( pci, new_pos, cap );
 | 
		
	
		
			
			| 50 | 78 |  }
 | 
		
	
		
			
			| 51 | 79 |  
 | 
		
	
		
			
			| 52 | 80 |  /**
 |