You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

pciextra.c 2.0KB

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