host-bridge.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. * host bridge related code
  3. */
  4. #include <linux/kernel.h>
  5. #include <linux/init.h>
  6. #include <linux/pci.h>
  7. #include <linux/module.h>
  8. #include "pci.h"
  9. static struct pci_bus *find_pci_root_bus(struct pci_bus *bus)
  10. {
  11. while (bus->parent)
  12. bus = bus->parent;
  13. return bus;
  14. }
  15. static struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus)
  16. {
  17. struct pci_bus *root_bus = find_pci_root_bus(bus);
  18. return to_pci_host_bridge(root_bus->bridge);
  19. }
  20. void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
  21. void (*release_fn)(struct pci_host_bridge *),
  22. void *release_data)
  23. {
  24. bridge->release_fn = release_fn;
  25. bridge->release_data = release_data;
  26. }
  27. static bool resource_contains(struct resource *res1, struct resource *res2)
  28. {
  29. return res1->start <= res2->start && res1->end >= res2->end;
  30. }
  31. void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
  32. struct resource *res)
  33. {
  34. struct pci_host_bridge *bridge = find_pci_host_bridge(bus);
  35. struct pci_host_bridge_window *window;
  36. resource_size_t offset = 0;
  37. list_for_each_entry(window, &bridge->windows, list) {
  38. if (resource_type(res) != resource_type(window->res))
  39. continue;
  40. if (resource_contains(window->res, res)) {
  41. offset = window->offset;
  42. break;
  43. }
  44. }
  45. region->start = res->start - offset;
  46. region->end = res->end - offset;
  47. }
  48. EXPORT_SYMBOL(pcibios_resource_to_bus);
  49. static bool region_contains(struct pci_bus_region *region1,
  50. struct pci_bus_region *region2)
  51. {
  52. return region1->start <= region2->start && region1->end >= region2->end;
  53. }
  54. void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
  55. struct pci_bus_region *region)
  56. {
  57. struct pci_host_bridge *bridge = find_pci_host_bridge(bus);
  58. struct pci_host_bridge_window *window;
  59. resource_size_t offset = 0;
  60. list_for_each_entry(window, &bridge->windows, list) {
  61. struct pci_bus_region bus_region;
  62. if (resource_type(res) != resource_type(window->res))
  63. continue;
  64. bus_region.start = window->res->start - window->offset;
  65. bus_region.end = window->res->end - window->offset;
  66. if (region_contains(&bus_region, region)) {
  67. offset = window->offset;
  68. break;
  69. }
  70. }
  71. res->start = region->start + offset;
  72. res->end = region->end + offset;
  73. }
  74. EXPORT_SYMBOL(pcibios_bus_to_resource);