pci.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * (C) Copyright 2002
  3. * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. #include <common.h>
  24. #include <pci.h>
  25. #include <asm/io.h>
  26. #include <asm/pci.h>
  27. #undef PCI_ROM_SCAN_VERBOSE
  28. int pci_shadow_rom(pci_dev_t dev, unsigned char *dest)
  29. {
  30. struct pci_controller *hose;
  31. int res = -1;
  32. int i;
  33. u32 rom_addr;
  34. u32 addr_reg;
  35. u32 size;
  36. u16 vendor;
  37. u16 device;
  38. u32 class_code;
  39. u32 pci_data;
  40. hose = pci_bus_to_hose(PCI_BUS(dev));
  41. debug("pci_shadow_rom() asked to shadow device %x to %x\n",
  42. dev, (u32)dest);
  43. pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
  44. pci_read_config_word(dev, PCI_DEVICE_ID, &device);
  45. pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_code);
  46. class_code &= 0xffffff00;
  47. class_code >>= 8;
  48. debug("PCI Header Vendor %04x device %04x class %06x\n",
  49. vendor, device, class_code);
  50. /* Enable the rom addess decoder */
  51. pci_write_config_dword(dev, PCI_ROM_ADDRESS, (u32)PCI_ROM_ADDRESS_MASK);
  52. pci_read_config_dword(dev, PCI_ROM_ADDRESS, &addr_reg);
  53. if (!addr_reg) {
  54. /* register unimplemented */
  55. printf("pci_chadow_rom: device do not seem to have a rom\n");
  56. return -1;
  57. }
  58. size = (~(addr_reg&PCI_ROM_ADDRESS_MASK)) + 1;
  59. debug("ROM is %d bytes\n", size);
  60. rom_addr = pci_get_rom_window(hose, size);
  61. debug("ROM mapped at %x\n", rom_addr);
  62. pci_write_config_dword(dev, PCI_ROM_ADDRESS,
  63. pci_phys_to_mem(dev, rom_addr)
  64. |PCI_ROM_ADDRESS_ENABLE);
  65. for (i = rom_addr; i < rom_addr + size; i += 512) {
  66. if (readw(i) == 0xaa55) {
  67. #ifdef PCI_ROM_SCAN_VERBOSE
  68. printf("ROM signature found\n");
  69. #endif
  70. pci_data = readw(0x18 + i);
  71. pci_data += i;
  72. if (0 == memcmp((void *)pci_data, "PCIR", 4)) {
  73. #ifdef PCI_ROM_SCAN_VERBOSE
  74. printf("Fount PCI rom image at offset %d\n",
  75. i - rom_addr);
  76. printf("Vendor %04x device %04x class %06x\n",
  77. readw(pci_data + 4), readw(pci_data + 6),
  78. readl(pci_data + 0x0d) & 0xffffff);
  79. printf("%s\n",
  80. (readw(pci_data + 0x15) & 0x80) ?
  81. "Last image" : "More images follow");
  82. switch (readb(pci_data + 0x14)) {
  83. case 0:
  84. printf("X86 code\n");
  85. break;
  86. case 1:
  87. printf("Openfirmware code\n");
  88. break;
  89. case 2:
  90. printf("PARISC code\n");
  91. break;
  92. }
  93. printf("Image size %d\n",
  94. readw(pci_data + 0x10) * 512);
  95. #endif
  96. /*
  97. * FixMe: I think we should compare the class
  98. * code bytes as well but I have no reference
  99. * on the exact order of these bytes in the PCI
  100. * ROM header
  101. */
  102. if (readw(pci_data + 4) == vendor &&
  103. readw(pci_data + 6) == device &&
  104. readb(pci_data + 0x14) == 0) {
  105. #ifdef PCI_ROM_SCAN_VERBOSE
  106. printf("Suitable ROM image found\n");
  107. #endif
  108. memmove(dest, (void *)rom_addr,
  109. readw(pci_data + 0x10) * 512);
  110. res = 0;
  111. break;
  112. }
  113. if (readw(pci_data + 0x15) & 0x80)
  114. break;
  115. }
  116. }
  117. }
  118. #ifdef PCI_ROM_SCAN_VERBOSE
  119. if (res)
  120. printf("No suitable image found\n");
  121. #endif
  122. /* disable PAR register and PCI device ROM address devocer */
  123. pci_remove_rom_window(hose, rom_addr);
  124. pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
  125. return res;
  126. }
  127. #ifdef PCI_BIOS_DEBUG
  128. void print_bios_bios_stat(void)
  129. {
  130. printf("16 bit functions:\n");
  131. printf("pci_bios_present: %d\n",
  132. RELOC_16_LONG(0xf000, num_pci_bios_present));
  133. printf("pci_bios_find_device: %d\n",
  134. RELOC_16_LONG(0xf000, num_pci_bios_find_device));
  135. printf("pci_bios_find_class: %d\n",
  136. RELOC_16_LONG(0xf000, num_pci_bios_find_class));
  137. printf("pci_bios_generate_special_cycle: %d\n",
  138. RELOC_16_LONG(0xf000,
  139. num_pci_bios_generate_special_cycle));
  140. printf("pci_bios_read_cfg_byte: %d\n",
  141. RELOC_16_LONG(0xf000, num_pci_bios_read_cfg_byte));
  142. printf("pci_bios_read_cfg_word: %d\n",
  143. RELOC_16_LONG(0xf000, num_pci_bios_read_cfg_word));
  144. printf("pci_bios_read_cfg_dword: %d\n",
  145. RELOC_16_LONG(0xf000, num_pci_bios_read_cfg_dword));
  146. printf("pci_bios_write_cfg_byte: %d\n",
  147. RELOC_16_LONG(0xf000, num_pci_bios_write_cfg_byte));
  148. printf("pci_bios_write_cfg_word: %d\n",
  149. RELOC_16_LONG(0xf000, num_pci_bios_write_cfg_word));
  150. printf("pci_bios_write_cfg_dword: %d\n",
  151. RELOC_16_LONG(0xf000, num_pci_bios_write_cfg_dword));
  152. printf("pci_bios_get_irq_routing: %d\n",
  153. RELOC_16_LONG(0xf000, num_pci_bios_get_irq_routing));
  154. printf("pci_bios_set_irq: %d\n",
  155. RELOC_16_LONG(0xf000, num_pci_bios_set_irq));
  156. printf("pci_bios_unknown_function: %d\n",
  157. RELOC_16_LONG(0xf000, num_pci_bios_unknown_function));
  158. }
  159. #endif