pci.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2011-2014 Kevin Lange
  5. *
  6. * ToAruOS PCI Initialization
  7. */
  8. #include <kernel/system.h>
  9. #include <kernel/pci.h>
  10. #include "pci_list.h"
  11. void pci_write_field(uint32_t device, int field, int size, uint32_t value) {
  12. outportl(PCI_ADDRESS_PORT, pci_get_addr(device, field));
  13. outportl(PCI_VALUE_PORT, value);
  14. }
  15. uint32_t pci_read_field(uint32_t device, int field, int size) {
  16. outportl(PCI_ADDRESS_PORT, pci_get_addr(device, field));
  17. if (size == 4) {
  18. uint32_t t = inportl(PCI_VALUE_PORT);
  19. return t;
  20. } else if (size == 2) {
  21. uint16_t t = inports(PCI_VALUE_PORT + (field & 2));
  22. return t;
  23. } else if (size == 1) {
  24. uint8_t t = inportb(PCI_VALUE_PORT + (field & 3));
  25. return t;
  26. }
  27. return 0xFFFF;
  28. }
  29. uint16_t pci_find_type(uint32_t dev) {
  30. return (pci_read_field(dev, PCI_CLASS, 1) << 8) | pci_read_field(dev, PCI_SUBCLASS, 1);
  31. }
  32. const char * pci_vendor_lookup(unsigned short vendor_id) {
  33. for (unsigned int i = 0; i < PCI_VENTABLE_LEN; ++i) {
  34. if (PciVenTable[i].VenId == vendor_id) {
  35. return PciVenTable[i].VenFull;
  36. }
  37. }
  38. return "";
  39. }
  40. const char * pci_device_lookup(unsigned short vendor_id, unsigned short device_id) {
  41. for (unsigned int i = 0; i < PCI_DEVTABLE_LEN; ++i) {
  42. if (PciDevTable[i].VenId == vendor_id && PciDevTable[i].DevId == device_id) {
  43. return PciDevTable[i].ChipDesc;
  44. }
  45. }
  46. return "";
  47. }
  48. void pci_scan_hit(pci_func_t f, uint32_t dev, void * extra) {
  49. int dev_vend = (int)pci_read_field(dev, PCI_VENDOR_ID, 2);
  50. int dev_dvid = (int)pci_read_field(dev, PCI_DEVICE_ID, 2);
  51. f(dev, dev_vend, dev_dvid, extra);
  52. }
  53. void pci_scan_func(pci_func_t f, int type, int bus, int slot, int func, void * extra) {
  54. uint32_t dev = pci_box_device(bus, slot, func);
  55. if (type == -1 || type == pci_find_type(dev)) {
  56. pci_scan_hit(f, dev, extra);
  57. }
  58. if (pci_find_type(dev) == PCI_TYPE_BRIDGE) {
  59. pci_scan_bus(f, type, pci_read_field(dev, PCI_SECONDARY_BUS, 1), extra);
  60. }
  61. }
  62. void pci_scan_slot(pci_func_t f, int type, int bus, int slot, void * extra) {
  63. uint32_t dev = pci_box_device(bus, slot, 0);
  64. if (pci_read_field(dev, PCI_VENDOR_ID, 2) == PCI_NONE) {
  65. return;
  66. }
  67. pci_scan_func(f, type, bus, slot, 0, extra);
  68. if (!pci_read_field(dev, PCI_HEADER_TYPE, 1)) {
  69. return;
  70. }
  71. for (int func = 1; func < 8; func++) {
  72. uint32_t dev = pci_box_device(bus, slot, func);
  73. if (pci_read_field(dev, PCI_VENDOR_ID, 2) != PCI_NONE) {
  74. pci_scan_func(f, type, bus, slot, func, extra);
  75. }
  76. }
  77. }
  78. void pci_scan_bus(pci_func_t f, int type, int bus, void * extra) {
  79. for (int slot = 0; slot < 32; ++slot) {
  80. pci_scan_slot(f, type, bus, slot, extra);
  81. }
  82. }
  83. void pci_scan(pci_func_t f, int type, void * extra) {
  84. if ((pci_read_field(0, PCI_HEADER_TYPE, 1) & 0x80) == 0) {
  85. pci_scan_bus(f,type,0,extra);
  86. return;
  87. }
  88. for (int func = 0; func < 8; ++func) {
  89. uint32_t dev = pci_box_device(0, 0, func);
  90. if (pci_read_field(dev, PCI_VENDOR_ID, 2) != PCI_NONE) {
  91. pci_scan_bus(f, type, func, extra);
  92. } else {
  93. break;
  94. }
  95. }
  96. }