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 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  2. #include <stdint.h>
  3. #include <ipxe/pci.h>
  4. static int pci_find_capability_common ( struct pci_device *pci,
  5. uint8_t pos, int cap ) {
  6. uint8_t id;
  7. int ttl = 48;
  8. while ( ttl-- && pos >= 0x40 ) {
  9. pos &= ~3;
  10. pci_read_config_byte ( pci, pos + PCI_CAP_ID, &id );
  11. DBG ( "PCI Capability: %d\n", id );
  12. if ( id == 0xff )
  13. break;
  14. if ( id == cap )
  15. return pos;
  16. pci_read_config_byte ( pci, pos + PCI_CAP_NEXT, &pos );
  17. }
  18. return 0;
  19. }
  20. /**
  21. * Look for a PCI capability
  22. *
  23. * @v pci PCI device to query
  24. * @v cap Capability code
  25. * @ret address Address of capability, or 0 if not found
  26. *
  27. * Determine whether or not a device supports a given PCI capability.
  28. * Returns the address of the requested capability structure within
  29. * the device's PCI configuration space, or 0 if the device does not
  30. * support it.
  31. */
  32. int pci_find_capability ( struct pci_device *pci, int cap ) {
  33. uint16_t status;
  34. uint8_t pos;
  35. uint8_t hdr_type;
  36. pci_read_config_word ( pci, PCI_STATUS, &status );
  37. if ( ! ( status & PCI_STATUS_CAP_LIST ) )
  38. return 0;
  39. pci_read_config_byte ( pci, PCI_HEADER_TYPE, &hdr_type );
  40. switch ( hdr_type & PCI_HEADER_TYPE_MASK ) {
  41. case PCI_HEADER_TYPE_NORMAL:
  42. case PCI_HEADER_TYPE_BRIDGE:
  43. default:
  44. pci_read_config_byte ( pci, PCI_CAPABILITY_LIST, &pos );
  45. break;
  46. case PCI_HEADER_TYPE_CARDBUS:
  47. pci_read_config_byte ( pci, PCI_CB_CAPABILITY_LIST, &pos );
  48. break;
  49. }
  50. return pci_find_capability_common ( pci, pos, cap );
  51. }
  52. /**
  53. * Look for another PCI capability
  54. *
  55. * @v pci PCI device to query
  56. * @v pos Address of the current capability
  57. * @v cap Capability code
  58. * @ret address Address of capability, or 0 if not found
  59. *
  60. * Determine whether or not a device supports a given PCI capability
  61. * starting the search at a given address within the device's PCI
  62. * configuration space. Returns the address of the next capability
  63. * structure within the device's PCI configuration space, or 0 if the
  64. * device does not support another such capability.
  65. */
  66. int pci_find_next_capability ( struct pci_device *pci, int pos, int cap ) {
  67. uint8_t new_pos;
  68. pci_read_config_byte ( pci, pos + PCI_CAP_NEXT, &new_pos );
  69. return pci_find_capability_common ( pci, new_pos, cap );
  70. }
  71. /**
  72. * Find the size of a PCI BAR
  73. *
  74. * @v pci PCI device
  75. * @v reg PCI register number
  76. * @ret size BAR size
  77. *
  78. * It should not be necessary for any Etherboot code to call this
  79. * function.
  80. */
  81. unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg ) {
  82. uint16_t cmd;
  83. uint32_t start, size;
  84. /* Save the original command register */
  85. pci_read_config_word ( pci, PCI_COMMAND, &cmd );
  86. /* Save the original bar */
  87. pci_read_config_dword ( pci, reg, &start );
  88. /* Compute which bits can be set */
  89. pci_write_config_dword ( pci, reg, ~0 );
  90. pci_read_config_dword ( pci, reg, &size );
  91. /* Restore the original size */
  92. pci_write_config_dword ( pci, reg, start );
  93. /* Find the significant bits */
  94. /* Restore the original command register. This reenables decoding. */
  95. pci_write_config_word ( pci, PCI_COMMAND, cmd );
  96. if ( start & PCI_BASE_ADDRESS_SPACE_IO ) {
  97. size &= ~PCI_BASE_ADDRESS_IO_MASK;
  98. } else {
  99. size &= ~PCI_BASE_ADDRESS_MEM_MASK;
  100. }
  101. /* Find the lowest bit set */
  102. size = size & ~( size - 1 );
  103. return size;
  104. }