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.3KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  2. #include <stdint.h>
  3. #include <ipxe/pci.h>
  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. pci_read_config_word ( pci, PCI_STATUS, &status );
  22. if ( ! ( status & PCI_STATUS_CAP_LIST ) )
  23. return 0;
  24. pci_read_config_byte ( pci, PCI_HEADER_TYPE, &hdr_type );
  25. switch ( hdr_type & 0x7F ) {
  26. case PCI_HEADER_TYPE_NORMAL:
  27. case PCI_HEADER_TYPE_BRIDGE:
  28. default:
  29. pci_read_config_byte ( pci, PCI_CAPABILITY_LIST, &pos );
  30. break;
  31. case PCI_HEADER_TYPE_CARDBUS:
  32. pci_read_config_byte ( pci, PCI_CB_CAPABILITY_LIST, &pos );
  33. break;
  34. }
  35. while ( ttl-- && pos >= 0x40 ) {
  36. pos &= ~3;
  37. pci_read_config_byte ( pci, pos + PCI_CAP_LIST_ID, &id );
  38. DBG ( "PCI Capability: %d\n", id );
  39. if ( id == 0xff )
  40. break;
  41. if ( id == cap )
  42. return pos;
  43. pci_read_config_byte ( pci, pos + PCI_CAP_LIST_NEXT, &pos );
  44. }
  45. return 0;
  46. }
  47. /**
  48. * Find the size of a PCI BAR
  49. *
  50. * @v pci PCI device
  51. * @v reg PCI register number
  52. * @ret size BAR size
  53. *
  54. * It should not be necessary for any Etherboot code to call this
  55. * function.
  56. */
  57. unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg ) {
  58. uint16_t cmd;
  59. uint32_t start, size;
  60. /* Save the original command register */
  61. pci_read_config_word ( pci, PCI_COMMAND, &cmd );
  62. /* Save the original bar */
  63. pci_read_config_dword ( pci, reg, &start );
  64. /* Compute which bits can be set */
  65. pci_write_config_dword ( pci, reg, ~0 );
  66. pci_read_config_dword ( pci, reg, &size );
  67. /* Restore the original size */
  68. pci_write_config_dword ( pci, reg, start );
  69. /* Find the significant bits */
  70. /* Restore the original command register. This reenables decoding. */
  71. pci_write_config_word ( pci, PCI_COMMAND, cmd );
  72. if ( start & PCI_BASE_ADDRESS_SPACE_IO ) {
  73. size &= PCI_BASE_ADDRESS_IO_MASK;
  74. } else {
  75. size &= PCI_BASE_ADDRESS_MEM_MASK;
  76. }
  77. /* Find the lowest bit set */
  78. size = size & ~( size - 1 );
  79. return size;
  80. }