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.

pci.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /*
  2. * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * Based in part on pci.c from Etherboot 5.4, by Ken Yap and David
  5. * Munro, in turn based on the Linux kernel's PCI implementation.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of the
  10. * License, or any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20. * 02110-1301, USA.
  21. *
  22. * You can also choose to distribute this program under the terms of
  23. * the Unmodified Binary Distribution Licence (as given in the file
  24. * COPYING.UBDL), provided that you have satisfied its requirements.
  25. */
  26. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  27. #include <stdint.h>
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <errno.h>
  32. #include <ipxe/tables.h>
  33. #include <ipxe/device.h>
  34. #include <ipxe/pci.h>
  35. /** @file
  36. *
  37. * PCI bus
  38. *
  39. */
  40. static void pcibus_remove ( struct root_device *rootdev );
  41. /**
  42. * Read PCI BAR
  43. *
  44. * @v pci PCI device
  45. * @v reg PCI register number
  46. * @ret bar Base address register
  47. *
  48. * Reads the specified PCI base address register, including the flags
  49. * portion. 64-bit BARs will be handled automatically. If the value
  50. * of the 64-bit BAR exceeds the size of an unsigned long (i.e. if the
  51. * high dword is non-zero on a 32-bit platform), then the value
  52. * returned will be zero plus the flags for a 64-bit BAR. Unreachable
  53. * 64-bit BARs are therefore returned as uninitialised 64-bit BARs.
  54. */
  55. static unsigned long pci_bar ( struct pci_device *pci, unsigned int reg ) {
  56. uint32_t low;
  57. uint32_t high;
  58. pci_read_config_dword ( pci, reg, &low );
  59. if ( ( low & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK) )
  60. == (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64) ){
  61. pci_read_config_dword ( pci, reg + 4, &high );
  62. if ( high ) {
  63. if ( sizeof ( unsigned long ) > sizeof ( uint32_t ) ) {
  64. return ( ( ( uint64_t ) high << 32 ) | low );
  65. } else {
  66. DBGC ( pci, PCI_FMT " unhandled 64-bit BAR "
  67. "%08x%08x\n",
  68. PCI_ARGS ( pci ), high, low );
  69. return PCI_BASE_ADDRESS_MEM_TYPE_64;
  70. }
  71. }
  72. }
  73. return low;
  74. }
  75. /**
  76. * Find the start of a PCI BAR
  77. *
  78. * @v pci PCI device
  79. * @v reg PCI register number
  80. * @ret start BAR start address
  81. *
  82. * Reads the specified PCI base address register, and returns the
  83. * address portion of the BAR (i.e. without the flags).
  84. *
  85. * If the address exceeds the size of an unsigned long (i.e. if a
  86. * 64-bit BAR has a non-zero high dword on a 32-bit machine), the
  87. * return value will be zero.
  88. */
  89. unsigned long pci_bar_start ( struct pci_device *pci, unsigned int reg ) {
  90. unsigned long bar;
  91. bar = pci_bar ( pci, reg );
  92. if ( (bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY ){
  93. return ( bar & PCI_BASE_ADDRESS_MEM_MASK );
  94. } else {
  95. return ( bar & PCI_BASE_ADDRESS_IO_MASK );
  96. }
  97. }
  98. /**
  99. * Read membase and ioaddr for a PCI device
  100. *
  101. * @v pci PCI device
  102. *
  103. * This scans through all PCI BARs on the specified device. The first
  104. * valid memory BAR is recorded as pci_device::membase, and the first
  105. * valid IO BAR is recorded as pci_device::ioaddr.
  106. *
  107. * 64-bit BARs are handled automatically. On a 32-bit platform, if a
  108. * 64-bit BAR has a non-zero high dword, it will be regarded as
  109. * invalid.
  110. */
  111. static void pci_read_bases ( struct pci_device *pci ) {
  112. unsigned long bar;
  113. int reg;
  114. for ( reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4 ) {
  115. bar = pci_bar ( pci, reg );
  116. if ( bar & PCI_BASE_ADDRESS_SPACE_IO ) {
  117. if ( ! pci->ioaddr )
  118. pci->ioaddr =
  119. ( bar & PCI_BASE_ADDRESS_IO_MASK );
  120. } else {
  121. if ( ! pci->membase )
  122. pci->membase =
  123. ( bar & PCI_BASE_ADDRESS_MEM_MASK );
  124. /* Skip next BAR if 64-bit */
  125. if ( bar & PCI_BASE_ADDRESS_MEM_TYPE_64 )
  126. reg += 4;
  127. }
  128. }
  129. }
  130. /**
  131. * Enable PCI device
  132. *
  133. * @v pci PCI device
  134. *
  135. * Set device to be a busmaster in case BIOS neglected to do so. Also
  136. * adjust PCI latency timer to a reasonable value, 32.
  137. */
  138. void adjust_pci_device ( struct pci_device *pci ) {
  139. unsigned short new_command, pci_command;
  140. unsigned char pci_latency;
  141. pci_read_config_word ( pci, PCI_COMMAND, &pci_command );
  142. new_command = ( pci_command | PCI_COMMAND_MASTER |
  143. PCI_COMMAND_MEM | PCI_COMMAND_IO );
  144. if ( pci_command != new_command ) {
  145. DBGC ( pci, PCI_FMT " device not enabled by BIOS! Updating "
  146. "PCI command %04x->%04x\n",
  147. PCI_ARGS ( pci ), pci_command, new_command );
  148. pci_write_config_word ( pci, PCI_COMMAND, new_command );
  149. }
  150. pci_read_config_byte ( pci, PCI_LATENCY_TIMER, &pci_latency);
  151. if ( pci_latency < 32 ) {
  152. DBGC ( pci, PCI_FMT " latency timer is unreasonably low at "
  153. "%d. Setting to 32.\n", PCI_ARGS ( pci ), pci_latency );
  154. pci_write_config_byte ( pci, PCI_LATENCY_TIMER, 32);
  155. }
  156. }
  157. /**
  158. * Read PCI device configuration
  159. *
  160. * @v pci PCI device
  161. * @ret rc Return status code
  162. */
  163. int pci_read_config ( struct pci_device *pci ) {
  164. uint16_t busdevfn;
  165. uint8_t hdrtype;
  166. uint32_t tmp;
  167. /* Ignore all but the first function on non-multifunction devices */
  168. if ( PCI_FUNC ( pci->busdevfn ) != 0 ) {
  169. busdevfn = pci->busdevfn;
  170. pci->busdevfn = PCI_FIRST_FUNC ( pci->busdevfn );
  171. pci_read_config_byte ( pci, PCI_HEADER_TYPE, &hdrtype );
  172. pci->busdevfn = busdevfn;
  173. if ( ! ( hdrtype & 0x80 ) )
  174. return -ENODEV;
  175. }
  176. /* Check for physical device presence */
  177. pci_read_config_dword ( pci, PCI_VENDOR_ID, &tmp );
  178. if ( ( tmp == 0xffffffff ) || ( tmp == 0 ) )
  179. return -ENODEV;
  180. /* Populate struct pci_device */
  181. pci->vendor = ( tmp & 0xffff );
  182. pci->device = ( tmp >> 16 );
  183. pci_read_config_dword ( pci, PCI_REVISION, &tmp );
  184. pci->class = ( tmp >> 8 );
  185. pci_read_config_byte ( pci, PCI_INTERRUPT_LINE, &pci->irq );
  186. pci_read_bases ( pci );
  187. /* Initialise generic device component */
  188. snprintf ( pci->dev.name, sizeof ( pci->dev.name ),
  189. "PCI%02x:%02x.%x", PCI_BUS ( pci->busdevfn ),
  190. PCI_SLOT ( pci->busdevfn ), PCI_FUNC ( pci->busdevfn ) );
  191. pci->dev.desc.bus_type = BUS_TYPE_PCI;
  192. pci->dev.desc.location = pci->busdevfn;
  193. pci->dev.desc.vendor = pci->vendor;
  194. pci->dev.desc.device = pci->device;
  195. pci->dev.desc.class = pci->class;
  196. pci->dev.desc.ioaddr = pci->ioaddr;
  197. pci->dev.desc.irq = pci->irq;
  198. INIT_LIST_HEAD ( &pci->dev.siblings );
  199. INIT_LIST_HEAD ( &pci->dev.children );
  200. return 0;
  201. }
  202. /**
  203. * Find next device on PCI bus
  204. *
  205. * @v pci PCI device to fill in
  206. * @v busdevfn Starting bus:dev.fn address
  207. * @ret busdevfn Bus:dev.fn address of next PCI device, or negative error
  208. */
  209. int pci_find_next ( struct pci_device *pci, unsigned int busdevfn ) {
  210. static unsigned int end;
  211. int rc;
  212. /* Determine number of PCI buses */
  213. if ( ! end )
  214. end = PCI_BUSDEVFN ( pci_num_bus(), 0, 0 );
  215. /* Find next PCI device, if any */
  216. for ( ; busdevfn < end ; busdevfn++ ) {
  217. memset ( pci, 0, sizeof ( *pci ) );
  218. pci_init ( pci, busdevfn );
  219. if ( ( rc = pci_read_config ( pci ) ) == 0 )
  220. return busdevfn;
  221. }
  222. return -ENODEV;
  223. }
  224. /**
  225. * Find driver for PCI device
  226. *
  227. * @v pci PCI device
  228. * @ret rc Return status code
  229. */
  230. int pci_find_driver ( struct pci_device *pci ) {
  231. struct pci_driver *driver;
  232. struct pci_device_id *id;
  233. unsigned int i;
  234. for_each_table_entry ( driver, PCI_DRIVERS ) {
  235. if ( ( driver->class.class ^ pci->class ) & driver->class.mask )
  236. continue;
  237. for ( i = 0 ; i < driver->id_count ; i++ ) {
  238. id = &driver->ids[i];
  239. if ( ( id->vendor != PCI_ANY_ID ) &&
  240. ( id->vendor != pci->vendor ) )
  241. continue;
  242. if ( ( id->device != PCI_ANY_ID ) &&
  243. ( id->device != pci->device ) )
  244. continue;
  245. pci_set_driver ( pci, driver, id );
  246. return 0;
  247. }
  248. }
  249. return -ENOENT;
  250. }
  251. /**
  252. * Probe a PCI device
  253. *
  254. * @v pci PCI device
  255. * @ret rc Return status code
  256. *
  257. * Searches for a driver for the PCI device. If a driver is found,
  258. * its probe() routine is called.
  259. */
  260. int pci_probe ( struct pci_device *pci ) {
  261. int rc;
  262. DBGC ( pci, PCI_FMT " (%04x:%04x) has driver \"%s\"\n",
  263. PCI_ARGS ( pci ), pci->vendor, pci->device, pci->id->name );
  264. DBGC ( pci, PCI_FMT " has mem %lx io %lx irq %d\n",
  265. PCI_ARGS ( pci ), pci->membase, pci->ioaddr, pci->irq );
  266. if ( ( rc = pci->driver->probe ( pci ) ) != 0 ) {
  267. DBGC ( pci, PCI_FMT " probe failed: %s\n",
  268. PCI_ARGS ( pci ), strerror ( rc ) );
  269. return rc;
  270. }
  271. return 0;
  272. }
  273. /**
  274. * Remove a PCI device
  275. *
  276. * @v pci PCI device
  277. */
  278. void pci_remove ( struct pci_device *pci ) {
  279. pci->driver->remove ( pci );
  280. DBGC ( pci, PCI_FMT " removed\n", PCI_ARGS ( pci ) );
  281. }
  282. /**
  283. * Probe PCI root bus
  284. *
  285. * @v rootdev PCI bus root device
  286. *
  287. * Scans the PCI bus for devices and registers all devices it can
  288. * find.
  289. */
  290. static int pcibus_probe ( struct root_device *rootdev ) {
  291. struct pci_device *pci = NULL;
  292. int busdevfn = 0;
  293. int rc;
  294. for ( busdevfn = 0 ; 1 ; busdevfn++ ) {
  295. /* Allocate struct pci_device */
  296. if ( ! pci )
  297. pci = malloc ( sizeof ( *pci ) );
  298. if ( ! pci ) {
  299. rc = -ENOMEM;
  300. goto err;
  301. }
  302. /* Find next PCI device, if any */
  303. busdevfn = pci_find_next ( pci, busdevfn );
  304. if ( busdevfn < 0 )
  305. break;
  306. /* Look for a driver */
  307. if ( ( rc = pci_find_driver ( pci ) ) != 0 ) {
  308. DBGC ( pci, PCI_FMT " (%04x:%04x class %06x) has no "
  309. "driver\n", PCI_ARGS ( pci ), pci->vendor,
  310. pci->device, pci->class );
  311. continue;
  312. }
  313. /* Add to device hierarchy */
  314. pci->dev.parent = &rootdev->dev;
  315. list_add ( &pci->dev.siblings, &rootdev->dev.children );
  316. /* Look for a driver */
  317. if ( ( rc = pci_probe ( pci ) ) == 0 ) {
  318. /* pcidev registered, we can drop our ref */
  319. pci = NULL;
  320. } else {
  321. /* Not registered; re-use struct pci_device */
  322. list_del ( &pci->dev.siblings );
  323. }
  324. }
  325. free ( pci );
  326. return 0;
  327. err:
  328. free ( pci );
  329. pcibus_remove ( rootdev );
  330. return rc;
  331. }
  332. /**
  333. * Remove PCI root bus
  334. *
  335. * @v rootdev PCI bus root device
  336. */
  337. static void pcibus_remove ( struct root_device *rootdev ) {
  338. struct pci_device *pci;
  339. struct pci_device *tmp;
  340. list_for_each_entry_safe ( pci, tmp, &rootdev->dev.children,
  341. dev.siblings ) {
  342. pci_remove ( pci );
  343. list_del ( &pci->dev.siblings );
  344. free ( pci );
  345. }
  346. }
  347. /** PCI bus root device driver */
  348. static struct root_driver pci_root_driver = {
  349. .probe = pcibus_probe,
  350. .remove = pcibus_remove,
  351. };
  352. /** PCI bus root device */
  353. struct root_device pci_root_device __root_device = {
  354. .dev = { .name = "PCI" },
  355. .driver = &pci_root_driver,
  356. };