cmd_pci.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. /*
  2. * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  3. * Andreas Heppel <aheppel@sysgo.de>
  4. *
  5. * (C) Copyright 2002
  6. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  7. * Wolfgang Grandegger, DENX Software Engineering, wg@denx.de.
  8. *
  9. * See file CREDITS for list of people who contributed to this
  10. * project.
  11. *
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU General Public License as
  14. * published by the Free Software Foundation; either version 2 of
  15. * the License, or (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  25. * MA 02111-1307 USA
  26. */
  27. /*
  28. * PCI routines
  29. */
  30. #include <common.h>
  31. #ifdef CONFIG_PCI
  32. #include <command.h>
  33. #include <cmd_boot.h>
  34. #include <asm/processor.h>
  35. #include <asm/io.h>
  36. #include <cmd_pci.h>
  37. #include <pci.h>
  38. #if (CONFIG_COMMANDS & CFG_CMD_PCI)
  39. extern int cmd_get_data_size(char* arg, int default_size);
  40. unsigned char ShortPCIListing = 1;
  41. /*
  42. * Follows routines for the output of infos about devices on PCI bus.
  43. */
  44. void pci_header_show(pci_dev_t dev);
  45. void pci_header_show_brief(pci_dev_t dev);
  46. /*
  47. * Subroutine: pciinfo
  48. *
  49. * Description: Show information about devices on PCI bus.
  50. * Depending on the define CFG_SHORT_PCI_LISTING
  51. * the output will be more or less exhaustive.
  52. *
  53. * Inputs: bus_no the number of the bus to be scanned.
  54. *
  55. * Return: None
  56. *
  57. */
  58. void pciinfo(int BusNum, int ShortPCIListing)
  59. {
  60. int Device;
  61. int Function;
  62. unsigned char HeaderType;
  63. unsigned short VendorID;
  64. pci_dev_t dev;
  65. printf("Scanning PCI devices on bus %d\n", BusNum);
  66. if (ShortPCIListing) {
  67. printf("BusDevFun VendorId DeviceId Device Class Sub-Class\n");
  68. printf("_____________________________________________________________\n");
  69. }
  70. for (Device = 0; Device < PCI_MAX_PCI_DEVICES; Device++) {
  71. HeaderType = 0;
  72. VendorID = 0;
  73. for (Function = 0; Function < PCI_MAX_PCI_FUNCTIONS; Function++) {
  74. /*
  75. * If this is not a multi-function device, we skip the rest.
  76. */
  77. if (Function && !(HeaderType & 0x80))
  78. break;
  79. dev = PCI_BDF(BusNum, Device, Function);
  80. pci_read_config_word(dev, PCI_VENDOR_ID, &VendorID);
  81. if ((VendorID == 0xFFFF) || (VendorID == 0x0000))
  82. continue;
  83. pci_read_config_byte(dev, PCI_HEADER_TYPE, &HeaderType);
  84. if (ShortPCIListing)
  85. {
  86. printf("%02x.%02x.%02x ", BusNum, Device, Function);
  87. pci_header_show_brief(dev);
  88. }
  89. else
  90. {
  91. printf("\nFound PCI device %02x.%02x.%02x:\n",
  92. BusNum, Device, Function);
  93. pci_header_show(dev);
  94. }
  95. }
  96. }
  97. }
  98. char* pci_classes_str(u8 class)
  99. {
  100. static char *pci_classes[] = {
  101. "Build before PCI Rev2.0",
  102. "Mass storage controller",
  103. "Network controller ",
  104. "Display controller ",
  105. "Multimedia device ",
  106. "Memory controller ",
  107. "Bridge device ",
  108. "Simple comm. controller",
  109. "Base system peripheral ",
  110. "Input device ",
  111. "Docking station ",
  112. "Processor ",
  113. "Serial bus controller ",
  114. "Reserved entry ",
  115. "Does not fit any class "
  116. };
  117. if (class < (sizeof pci_classes / sizeof *pci_classes))
  118. return pci_classes[(int) class];
  119. return "??? ";
  120. }
  121. /*
  122. * Subroutine: pci_header_show_brief
  123. *
  124. * Description: Reads and prints the header of the
  125. * specified PCI device in short form.
  126. *
  127. * Inputs: dev Bus+Device+Function number
  128. *
  129. * Return: None
  130. *
  131. */
  132. void pci_header_show_brief(pci_dev_t dev)
  133. {
  134. u16 vendor, device;
  135. u8 class, subclass;
  136. pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
  137. pci_read_config_word(dev, PCI_DEVICE_ID, &device);
  138. pci_read_config_byte(dev, PCI_CLASS_CODE, &class);
  139. pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &subclass);
  140. printf("0x%.4x 0x%.4x %s 0x%.2x\n",
  141. vendor, device,
  142. pci_classes_str(class), subclass);
  143. }
  144. /*
  145. * Subroutine: PCI_Header_Show
  146. *
  147. * Description: Reads the header of the specified PCI device.
  148. *
  149. * Inputs: BusDevFunc Bus+Device+Function number
  150. *
  151. * Return: None
  152. *
  153. */
  154. void pci_header_show(pci_dev_t dev)
  155. {
  156. u8 _byte, header_type;
  157. u16 _word;
  158. u32 _dword;
  159. #define PRINT(msg, type, reg) \
  160. pci_read_config_##type(dev, reg, &_##type); \
  161. printf(msg, _##type)
  162. #define PRINT2(msg, type, reg, func) \
  163. pci_read_config_##type(dev, reg, &_##type); \
  164. printf(msg, _##type, func(_##type))
  165. pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
  166. PRINT (" vendor ID = 0x%.4x\n", word, PCI_VENDOR_ID);
  167. PRINT (" device ID = 0x%.4x\n", word, PCI_DEVICE_ID);
  168. PRINT (" command register = 0x%.4x\n", word, PCI_COMMAND);
  169. PRINT (" status register = 0x%.4x\n", word, PCI_STATUS);
  170. PRINT (" revision ID = 0x%.2x\n", byte, PCI_REVISION_ID);
  171. PRINT2(" class code = 0x%.2x (%s)\n", byte, PCI_CLASS_CODE,
  172. pci_classes_str);
  173. PRINT (" sub class code = 0x%.2x\n", byte, PCI_CLASS_SUB_CODE);
  174. PRINT (" programming interface = 0x%.2x\n", byte, PCI_CLASS_PROG);
  175. PRINT (" cache line = 0x%.2x\n", byte, PCI_CACHE_LINE_SIZE);
  176. PRINT (" latency time = 0x%.2x\n", byte, PCI_LATENCY_TIMER);
  177. PRINT (" header type = 0x%.2x\n", byte, PCI_HEADER_TYPE);
  178. PRINT (" BIST = 0x%.2x\n", byte, PCI_BIST);
  179. PRINT (" base address 0 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_0);
  180. PRINT (" base address 1 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_1);
  181. if (header_type & 0x01) { /* PCI-to-PCI bridge */
  182. PRINT (" primary bus number = 0x%.2x\n", byte, PCI_PRIMARY_BUS);
  183. PRINT (" secondary bus number = 0x%.2x\n", byte, PCI_SECONDARY_BUS);
  184. PRINT (" subordinate bus number = 0x%.2x\n", byte, PCI_SUBORDINATE_BUS);
  185. PRINT (" secondary latency timer = 0x%.2x\n", byte, PCI_SEC_LATENCY_TIMER);
  186. PRINT (" IO base = 0x%.2x\n", byte, PCI_IO_BASE);
  187. PRINT (" IO limit = 0x%.2x\n", byte, PCI_IO_LIMIT);
  188. PRINT (" secondary status = 0x%.4x\n", word, PCI_SEC_STATUS);
  189. PRINT (" memory base = 0x%.4x\n", word, PCI_MEMORY_BASE);
  190. PRINT (" memory limit = 0x%.4x\n", word, PCI_MEMORY_LIMIT);
  191. PRINT (" prefetch memory base = 0x%.4x\n", word, PCI_PREF_MEMORY_BASE);
  192. PRINT (" prefetch memory limit = 0x%.4x\n", word, PCI_PREF_MEMORY_LIMIT);
  193. PRINT (" prefetch memory base upper = 0x%.8x\n", dword, PCI_PREF_BASE_UPPER32);
  194. PRINT (" prefetch memory limit upper = 0x%.8x\n", dword, PCI_PREF_LIMIT_UPPER32);
  195. PRINT (" IO base upper 16 bits = 0x%.4x\n", word, PCI_IO_BASE_UPPER16);
  196. PRINT (" IO limit upper 16 bits = 0x%.4x\n", word, PCI_IO_LIMIT_UPPER16);
  197. PRINT (" expansion ROM base address = 0x%.8x\n", dword, PCI_ROM_ADDRESS1);
  198. PRINT (" interrupt line = 0x%.2x\n", byte, PCI_INTERRUPT_LINE);
  199. PRINT (" interrupt pin = 0x%.2x\n", byte, PCI_INTERRUPT_PIN);
  200. PRINT (" bridge control = 0x%.4x\n", word, PCI_BRIDGE_CONTROL);
  201. } else { /* PCI device */
  202. PRINT(" base address 2 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_2);
  203. PRINT(" base address 3 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_3);
  204. PRINT(" base address 4 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_4);
  205. PRINT(" base address 5 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_5);
  206. PRINT(" cardBus CIS pointer = 0x%.8x\n", dword, PCI_CARDBUS_CIS);
  207. PRINT(" sub system vendor ID = 0x%.4x\n", word, PCI_SUBSYSTEM_VENDOR_ID);
  208. PRINT(" sub system ID = 0x%.4x\n", word, PCI_SUBSYSTEM_ID);
  209. PRINT(" expansion ROM base address = 0x%.8x\n", dword, PCI_ROM_ADDRESS);
  210. PRINT(" interrupt line = 0x%.2x\n", byte, PCI_INTERRUPT_LINE);
  211. PRINT(" interrupt pin = 0x%.2x\n", byte, PCI_INTERRUPT_PIN);
  212. PRINT(" min Grant = 0x%.2x\n", byte, PCI_MIN_GNT);
  213. PRINT(" max Latency = 0x%.2x\n", byte, PCI_MAX_LAT);
  214. }
  215. #undef PRINT
  216. #undef PRINT2
  217. }
  218. /* Convert the "bus.device.function" identifier into a number.
  219. */
  220. static pci_dev_t get_pci_dev(char* name)
  221. {
  222. char cnum[12];
  223. int len, i, iold, n;
  224. int bdfs[3] = {0,0,0};
  225. len = strlen(name);
  226. if (len > 8)
  227. return -1;
  228. for (i = 0, iold = 0, n = 0; i < len; i++) {
  229. if (name[i] == '.') {
  230. memcpy(cnum, &name[iold], i - iold);
  231. cnum[i - iold] = '\0';
  232. bdfs[n++] = simple_strtoul(cnum, NULL, 16);
  233. iold = i + 1;
  234. }
  235. }
  236. strcpy(cnum, &name[iold]);
  237. if (n == 0)
  238. n = 1;
  239. bdfs[n] = simple_strtoul(cnum, NULL, 16);
  240. return PCI_BDF(bdfs[0], bdfs[1], bdfs[2]);
  241. }
  242. static int pci_cfg_display(pci_dev_t bdf, ulong addr, ulong size, ulong length)
  243. {
  244. #define DISP_LINE_LEN 16
  245. ulong i, nbytes, linebytes;
  246. int rc = 0;
  247. if (length == 0)
  248. length = 0x40 / size; /* Standard PCI configuration space */
  249. /* Print the lines.
  250. * once, and all accesses are with the specified bus width.
  251. */
  252. nbytes = length * size;
  253. do {
  254. uint val4;
  255. ushort val2;
  256. u_char val1;
  257. printf("%08lx:", addr);
  258. linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
  259. for (i=0; i<linebytes; i+= size) {
  260. if (size == 4) {
  261. pci_read_config_dword(bdf, addr, &val4);
  262. printf(" %08x", val4);
  263. } else if (size == 2) {
  264. pci_read_config_word(bdf, addr, &val2);
  265. printf(" %04x", val2);
  266. } else {
  267. pci_read_config_byte(bdf, addr, &val1);
  268. printf(" %02x", val1);
  269. }
  270. addr += size;
  271. }
  272. printf("\n");
  273. nbytes -= linebytes;
  274. if (ctrlc()) {
  275. rc = 1;
  276. break;
  277. }
  278. } while (nbytes > 0);
  279. return (rc);
  280. }
  281. static int pci_cfg_write (pci_dev_t bdf, ulong addr, ulong size, ulong value)
  282. {
  283. if (size == 4) {
  284. pci_write_config_dword(bdf, addr, value);
  285. }
  286. else if (size == 2) {
  287. ushort val = value & 0xffff;
  288. pci_write_config_word(bdf, addr, val);
  289. }
  290. else {
  291. u_char val = value & 0xff;
  292. pci_write_config_byte(bdf, addr, val);
  293. }
  294. return 0;
  295. }
  296. static int
  297. pci_cfg_modify (pci_dev_t bdf, ulong addr, ulong size, ulong value, int incrflag)
  298. {
  299. ulong i;
  300. int nbytes;
  301. extern char console_buffer[];
  302. uint val4;
  303. ushort val2;
  304. u_char val1;
  305. /* Print the address, followed by value. Then accept input for
  306. * the next value. A non-converted value exits.
  307. */
  308. do {
  309. printf("%08lx:", addr);
  310. if (size == 4) {
  311. pci_read_config_dword(bdf, addr, &val4);
  312. printf(" %08x", val4);
  313. }
  314. else if (size == 2) {
  315. pci_read_config_word(bdf, addr, &val2);
  316. printf(" %04x", val2);
  317. }
  318. else {
  319. pci_read_config_byte(bdf, addr, &val1);
  320. printf(" %02x", val1);
  321. }
  322. nbytes = readline (" ? ");
  323. if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
  324. /* <CR> pressed as only input, don't modify current
  325. * location and move to next. "-" pressed will go back.
  326. */
  327. if (incrflag)
  328. addr += nbytes ? -size : size;
  329. nbytes = 1;
  330. #ifdef CONFIG_BOOT_RETRY_TIME
  331. reset_cmd_timeout(); /* good enough to not time out */
  332. #endif
  333. }
  334. #ifdef CONFIG_BOOT_RETRY_TIME
  335. else if (nbytes == -2) {
  336. break; /* timed out, exit the command */
  337. }
  338. #endif
  339. else {
  340. char *endp;
  341. i = simple_strtoul(console_buffer, &endp, 16);
  342. nbytes = endp - console_buffer;
  343. if (nbytes) {
  344. #ifdef CONFIG_BOOT_RETRY_TIME
  345. /* good enough to not time out
  346. */
  347. reset_cmd_timeout();
  348. #endif
  349. pci_cfg_write (bdf, addr, size, i);
  350. if (incrflag)
  351. addr += size;
  352. }
  353. }
  354. } while (nbytes);
  355. return 0;
  356. }
  357. /* PCI Configuration Space access commands
  358. *
  359. * Syntax:
  360. * pci display[.b, .w, .l] bus.device.function} [addr] [len]
  361. * pci next[.b, .w, .l] bus.device.function [addr]
  362. * pci modify[.b, .w, .l] bus.device.function [addr]
  363. * pci write[.b, .w, .l] bus.device.function addr value
  364. */
  365. int do_pci (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  366. {
  367. ulong addr = 0, value = 0, size = 0;
  368. pci_dev_t bdf = 0;
  369. char cmd = 's';
  370. if (argc > 1)
  371. cmd = argv[1][0];
  372. switch (cmd) {
  373. case 'd': /* display */
  374. case 'n': /* next */
  375. case 'm': /* modify */
  376. case 'w': /* write */
  377. /* Check for a size specification. */
  378. size = cmd_get_data_size(argv[1], 4);
  379. if (argc > 3)
  380. addr = simple_strtoul(argv[3], NULL, 16);
  381. if (argc > 4)
  382. value = simple_strtoul(argv[4], NULL, 16);
  383. case 'h': /* header */
  384. if (argc < 3)
  385. goto usage;
  386. if ((bdf = get_pci_dev(argv[2])) == -1)
  387. return 1;
  388. break;
  389. default: /* scan bus */
  390. value = 1; /* short listing */
  391. bdf = 0; /* bus number */
  392. if (argc > 1) {
  393. if (argv[argc-1][0] == 'l') {
  394. value = 0;
  395. argc--;
  396. }
  397. if (argc > 1)
  398. bdf = simple_strtoul(argv[1], NULL, 16);
  399. }
  400. pciinfo(bdf, value);
  401. return 0;
  402. }
  403. switch (argv[1][0]) {
  404. case 'h': /* header */
  405. pci_header_show(bdf);
  406. return 0;
  407. case 'd': /* display */
  408. return pci_cfg_display(bdf, addr, size, value);
  409. case 'n': /* next */
  410. if (argc < 4)
  411. goto usage;
  412. return pci_cfg_modify(bdf, addr, size, value, 0);
  413. case 'm': /* modify */
  414. if (argc < 4)
  415. goto usage;
  416. return pci_cfg_modify(bdf, addr, size, value, 1);
  417. case 'w': /* write */
  418. if (argc < 5)
  419. goto usage;
  420. return pci_cfg_write(bdf, addr, size, value);
  421. }
  422. return 1;
  423. usage:
  424. printf ("Usage:\n%s\n", cmdtp->usage);
  425. return 1;
  426. }
  427. #endif /* (CONFIG_COMMANDS & CFG_CMD_PCI) */
  428. #endif /* CONFIG_PCI */