File indexing completed on 2025-05-11 08:24:19
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 #ifdef HAVE_CONFIG_H
0031 #include "config.h"
0032 #endif
0033
0034 #include <inttypes.h>
0035 #include <limits.h>
0036 #include <stdlib.h>
0037 #include <stdio.h>
0038 #include <string.h>
0039 #include <errno.h>
0040 #include <pci.h>
0041 #include <pci/cfg.h>
0042 #include <pci/access.h>
0043 #include <sys/endian.h>
0044
0045 #include <rtems.h>
0046 #include <rtems/shell.h>
0047 #include "internal.h"
0048
0049 static void usage(void);
0050
0051 struct shell_pci_modifier {
0052 char *name;
0053 int (*func)(int argc, char *argv[], struct shell_pci_modifier *mod);
0054 int data;
0055 };
0056
0057 static unsigned long get_pciid_from_string(char *arg)
0058 {
0059 unsigned long pciid;
0060 char *bus_str, *dev_str, *fun_str;
0061 unsigned long busno, devno, funno;
0062
0063 dev_str = strstr(arg, ":");
0064 if (dev_str == NULL) {
0065
0066 pciid = strtoul(arg, NULL, 16);
0067 if (pciid == ULONG_MAX)
0068 return ~0;
0069 } else {
0070
0071 bus_str = arg;
0072 *dev_str = '\0';
0073 dev_str++;
0074 fun_str = strstr(dev_str, ":");
0075 if (fun_str == NULL)
0076 return ~0;
0077 *fun_str = '\0';
0078 fun_str++;
0079
0080 busno = strtoul(bus_str, NULL, 16);
0081 if (busno == ULONG_MAX)
0082 return ~0;
0083 devno = strtoul(dev_str, NULL, 16);
0084 if (devno == ULONG_MAX)
0085 return ~0;
0086 funno = strtoul(fun_str, NULL, 16);
0087 if (funno == ULONG_MAX)
0088 return ~0;
0089 pciid = PCI_DEV(busno, devno, funno);
0090 }
0091
0092 return pciid;
0093 }
0094
0095
0096
0097
0098 static int shell_pci_pcfg(
0099 int argc,
0100 char *argv[],
0101 struct shell_pci_modifier *mod)
0102 {
0103 if (argc != 2)
0104 return -1;
0105
0106 pci_cfg_print();
0107
0108 return 0;
0109 }
0110
0111 static int shell_pci_ls(
0112 int argc,
0113 char *argv[],
0114 struct shell_pci_modifier *mod)
0115 {
0116 unsigned long pciid;
0117
0118 if (argc == 2) {
0119
0120 pci_print();
0121 } else if (argc > 3) {
0122 return -1;
0123 } else {
0124 pciid = get_pciid_from_string(argv[2]);
0125 if ((pciid & 0xffff0000) != 0)
0126 return -1;
0127
0128 pci_print_dev((pci_dev_t)pciid);
0129 }
0130 return 0;
0131 }
0132
0133 static int shell_pci_rX(
0134 unsigned long pciid,
0135 int offset,
0136 int size)
0137 {
0138 uint8_t data8;
0139 uint16_t data16;
0140 uint32_t data32;
0141 int result;
0142
0143 switch(size) {
0144 case 1:
0145 result = pci_cfg_r8(pciid, offset, &data8);
0146 if (result == PCISTS_OK)
0147 printf(" r08[0x%02x]: 0x%02x DEC=%d\n", offset, data8, data8);
0148 break;
0149
0150 case 2:
0151 result = pci_cfg_r16(pciid, offset, &data16);
0152 if (result == PCISTS_OK)
0153 printf(" r16[0x%02x]: 0x%04x DEC=%d\n", offset, data16, data16);
0154 break;
0155
0156 case 4:
0157 result = pci_cfg_r32(pciid, offset, &data32);
0158 if (result == PCISTS_OK)
0159 printf(" r32[0x%02x]: 0x%08" PRIx32 " DEC=%" PRIu32 "\n",
0160 offset, data32, data32);
0161 break;
0162
0163 default:
0164 return PCISTS_EINVAL;
0165 }
0166 return result;
0167 }
0168
0169 static int shell_pci_wX(
0170 unsigned long pciid,
0171 int offset,
0172 uint32_t data,
0173 int size)
0174 {
0175 uint8_t data8;
0176 uint16_t data16;
0177 int result;
0178
0179 switch(size) {
0180 case 1:
0181 if (data > 0xff)
0182 return PCISTS_EINVAL;
0183 data8 = data & 0xff;
0184 result = pci_cfg_w8(pciid, offset, data8);
0185 if (result == PCISTS_OK)
0186 printf(" w08[0x%02x]: 0x%02x DEC=%d\n", offset, data8, data8);
0187 break;
0188
0189 case 2:
0190 if (data > 0xffff)
0191 return PCISTS_EINVAL;
0192 data16 = data & 0xffff;
0193 result = pci_cfg_w16(pciid, offset, data16);
0194 if (result == PCISTS_OK)
0195 printf(" w16[0x%02x]: 0x%04x DEC=%d\n", offset, data16, data16);
0196 break;
0197
0198 case 4:
0199 result = pci_cfg_w32(pciid, offset, data);
0200 if (result == PCISTS_OK)
0201 printf(" w32[0x%02x]: 0x%08" PRIx32 " DEC=%" PRIu32 "\n",
0202 offset, data, data);
0203 break;
0204
0205 default:
0206 return PCISTS_EINVAL;
0207 }
0208 return result;
0209 }
0210
0211 static int shell_pci_read(
0212 int argc,
0213 char *argv[],
0214 struct shell_pci_modifier *mod)
0215 {
0216 unsigned long pciid, offset;
0217 int result, size;
0218
0219 if (argc != 4)
0220 return -1;
0221
0222 pciid = get_pciid_from_string(argv[2]);
0223 if ((pciid & 0xffff0000) != 0)
0224 return -1;
0225
0226 offset = strtoul(argv[3], NULL, 0);
0227 if (offset > 256)
0228 return -1;
0229
0230 size = mod->data;
0231 result = shell_pci_rX(pciid, offset, size);
0232 switch (result) {
0233 default:
0234 case PCISTS_OK:
0235 break;
0236
0237 case PCISTS_ERR:
0238 case PCISTS_EINVAL:
0239 puts(" Bad input argument\n");
0240 return PCISTS_EINVAL;
0241
0242 case PCISTS_MSTABRT:
0243 puts(" Master abort while reading configuration space");
0244 return PCISTS_MSTABRT;
0245 }
0246
0247 return 0;
0248 }
0249
0250 static int shell_pci_write(
0251 int argc,
0252 char *argv[],
0253 struct shell_pci_modifier *mod)
0254 {
0255 unsigned long pciid, offset;
0256 int result, size;
0257 uint32_t data;
0258
0259 if (argc != 5)
0260 return -1;
0261
0262 pciid = get_pciid_from_string(argv[2]);
0263 if ((pciid & 0xffff0000) != 0)
0264 return -1;
0265
0266 offset = strtoul(argv[3], NULL, 0);
0267 if (offset > 256)
0268 return -1;
0269
0270 data = strtoul(argv[4], NULL, 0);
0271 if (data == ULONG_MAX && errno == ERANGE)
0272 return -1;
0273
0274 size = mod->data;
0275 result = shell_pci_wX(pciid, offset, data, size);
0276 switch (result) {
0277 default:
0278 case PCISTS_OK:
0279 break;
0280
0281 case PCISTS_ERR:
0282 case PCISTS_EINVAL:
0283 puts(" Bad input argument\n");
0284 return PCISTS_EINVAL;
0285
0286 case PCISTS_MSTABRT:
0287 puts(" Master abort while reading configuration space");
0288 return PCISTS_MSTABRT;
0289 }
0290 return 0;
0291 }
0292
0293 static int shell_pci_pciid(
0294 int argc,
0295 char *argv[],
0296 struct shell_pci_modifier *mod)
0297 {
0298 unsigned long pciid;
0299
0300 if (argc != 3)
0301 return -1;
0302
0303 pciid = get_pciid_from_string(argv[2]);
0304 if ((pciid & 0xffff0000) != 0)
0305 return -1;
0306
0307 printf(" PCIID: 0x%lx [%lx:%lx:%lx]\n", pciid, PCI_DEV_EXPAND(pciid));
0308 return 0;
0309 }
0310
0311 static int shell_pci_getdev(
0312 int argc,
0313 char *argv[],
0314 struct shell_pci_modifier *mod)
0315 {
0316 unsigned long pciid;
0317 struct pci_dev *dev;
0318
0319 if (argc != 3)
0320 return -1;
0321
0322 pciid = get_pciid_from_string(argv[2]);
0323 if ((pciid & 0xffff0000) != 0)
0324 return -1;
0325
0326 if (pci_get_dev(pciid, &dev)) {
0327 printf(" GETDEV: no device on [%lx:%lx:%lx]\n", PCI_DEV_EXPAND(pciid));
0328 return 0;
0329 }
0330
0331 printf(" PCI RAM DEVICE: %p\n", dev);
0332 return 0;
0333 }
0334
0335 static int shell_pci_infodev(
0336 int argc,
0337 char *argv[],
0338 struct shell_pci_modifier *mod)
0339 {
0340 unsigned long arg;
0341 struct pci_dev *dev;
0342 struct pci_bus *bus;
0343 struct pci_res *res;
0344 char *type_str, *str1, *res_types[3] = {" IO16", "MEMIO", "MEM"};
0345 int i, res_avail;
0346
0347 if (argc != 3)
0348 return -1;
0349
0350 arg = strtoul(argv[2], NULL, 0);
0351 if (arg == ULONG_MAX && errno == ERANGE)
0352 return -1;
0353
0354 dev = (struct pci_dev *)arg;
0355 if (!dev) {
0356 printf(" INFODEV: invalid device\n");
0357 return 0;
0358 }
0359
0360 if (dev->flags & PCI_DEV_BRIDGE) {
0361 type_str = "PCI-to-PCI BRIDGE";
0362 if (!dev->bus)
0363 type_str = "PCI HOST BRIDGE";
0364 } else
0365 type_str = "PCI DEVICE";
0366 printf(" %s at [%x:%x:%x]\n", type_str, PCI_DEV_EXPAND(dev->busdevfun));
0367
0368 bus = (struct pci_bus *)dev;
0369 if (bus) {
0370 printf(" PRIMARY: BUS 0x%x\n", bus->pri);
0371 printf(" SECONDARY: BUS 0x%x\n", bus->num);
0372 printf(" SUB ORDINATE: BUS 0x%x\n", bus->sord);
0373 }
0374
0375 printf(" PCIID: 0x%04x\n", dev->busdevfun);
0376 bus = dev->bus;
0377 if (!bus) {
0378 printf(" AT BUS: via Host Bridge\n");
0379 } else {
0380 printf(" AT BUS: 0x%x via Bridge at [%x:%x:%x]\n", bus->num,
0381 PCI_DEV_EXPAND(bus->dev.busdevfun));
0382 }
0383 printf(" VENDOR: 0x%04x\n", dev->vendor);
0384 printf(" DEVICE: 0x%04x\n", dev->device);
0385 printf(" SUB VENDOR: 0x%04x\n", dev->subvendor);
0386 printf(" SUB DEVICE: 0x%04x\n", dev->subdevice);
0387 printf(" CLASS: 0x%06" PRIx32 "\n", dev->classrev >> 8);
0388 printf(" REVISION: 0x%02" PRIx32 "\n", dev->classrev & 0xff);
0389 printf(" IRQ: %d\n", dev->sysirq);
0390
0391 res_avail = 0;
0392 for (i = 0; i < DEV_RES_CNT; i++) {
0393 res = &dev->resources[i];
0394
0395 if ((res->flags & PCI_RES_TYPE_MASK) == 0)
0396 continue;
0397
0398 str1 = res_types[(res->flags & PCI_RES_TYPE_MASK) - 1];
0399 if (res->flags & PCI_RES_IO32)
0400 str1 = " IO32";
0401
0402 if (res_avail == 0) {
0403 puts(" RESOURCES:");
0404 res_avail = 1;
0405 }
0406
0407 if (res->flags & PCI_RES_FAIL) {
0408 printf(" %s[%d]: NOT ASSIGNED", str1, i);
0409 continue;
0410 }
0411
0412 printf(" %s[%d]: %08" PRIx32 "-%08" PRIx32 "\n",
0413 str1, i, res->start, res->end - 1);
0414 }
0415
0416 if (res_avail == 0)
0417 puts(" NO CONFIGURED RESOURCES AVAILABLE");
0418
0419 return 0;
0420 }
0421
0422 static int pci_summary(void)
0423 {
0424 char *str;
0425 char *cfglib_strs[5] = {"NONE", "AUTO", "STATIC", "READ", "PERIPHERAL"};
0426
0427 if (pci_system_type == PCI_SYSTEM_HOST)
0428 str = "HOST";
0429 else if (pci_system_type == PCI_SYSTEM_PERIPHERAL)
0430 str = "PERIPHERAL";
0431 else
0432 str = "UNKNOWN / UNINITIALIZED";
0433 printf(" SYSTEM: %s\n", str);
0434
0435 if (pci_config_lib_type > PCI_CONFIG_LIB_PERIPHERAL) {
0436 puts(" Bad configuration library");
0437 return 1;
0438 }
0439 printf(" CFG LIBRARY: %s\n", cfglib_strs[pci_config_lib_type]);
0440 printf(" NO. PCI BUSES: %d buses\n", pci_bus_count());
0441 printf(" PCI ENDIAN: %s\n", pci_endian ? "Big" : "Little");
0442 #if BYTE_ORDER == LITTLE_ENDIAN
0443 puts(" MACHINE ENDIAN: Little");
0444 #else
0445 puts(" MACHINE ENDIAN: Big");
0446 #endif
0447
0448 return 0;
0449 }
0450
0451 static const char pci_usage_str[] =
0452 " usage:\n"
0453 " pci ls [bus:dev:fun|PCIID] List one or all devices\n"
0454 " pci r{8|16|32} bus:dev:fun OFS Configuration space read\n"
0455 " pci r{8|16|32} PCIID OFS Configuration space read\n"
0456 " access by PCIID\n"
0457 " pci w{8|16|32} bus:dev:fun OFS D Configuration space write\n"
0458 " pci w{8|16|32} PCIID OFS D Configuration space write\n"
0459 " access by PCIID\n"
0460 " pci pciid bus:dev:fun Print PCIID for bus:dev:fun\n"
0461 " pci pciid PCIID Print bus:dev:fun for PCIID\n"
0462 " pci pcfg Print current PCI config for\n"
0463 " static configuration library\n"
0464 " pci getdev {PCIID|bus:dev:fun} Get PCI Device from RAM tree\n"
0465 " pci infodev DEV_ADR Info about a PCI RAM Device\n"
0466 " pci --help\n";
0467
0468 static void usage(void)
0469 {
0470 puts(pci_usage_str);
0471 }
0472
0473 static int shell_pci_usage(
0474 int argc,
0475 char *argv[],
0476 struct shell_pci_modifier *mod)
0477 {
0478 usage();
0479 return 0;
0480 }
0481
0482 #define MODIFIER_NUM 12
0483 static struct shell_pci_modifier shell_pci_modifiers[MODIFIER_NUM] =
0484 {
0485 {"ls", shell_pci_ls, 0},
0486 {"r8", shell_pci_read, 1},
0487 {"r16", shell_pci_read, 2},
0488 {"r32", shell_pci_read, 4},
0489 {"w8", shell_pci_write, 1},
0490 {"w16", shell_pci_write, 2},
0491 {"w32", shell_pci_write, 4},
0492 {"pciid", shell_pci_pciid, 0},
0493 {"pcfg", shell_pci_pcfg, 0},
0494 {"getdev", shell_pci_getdev, 0},
0495 {"infodev", shell_pci_infodev, 0},
0496 {"--help", shell_pci_usage},
0497 };
0498
0499 static struct shell_pci_modifier *shell_pci_find_modifier(char *name)
0500 {
0501 struct shell_pci_modifier *mod;
0502 int i;
0503
0504 if (name == NULL)
0505 return NULL;
0506
0507 for (i=0, mod=&shell_pci_modifiers[0]; i<MODIFIER_NUM; i++, mod++) {
0508 if (strcmp(name, mod->name) == 0)
0509 return mod;
0510 }
0511
0512 return NULL;
0513 }
0514
0515 static int rtems_shell_main_pci(
0516 int argc,
0517 char *argv[]
0518 )
0519 {
0520 struct shell_pci_modifier *mod;
0521 int rc;
0522
0523 if (argc < 2) {
0524
0525 pci_summary();
0526 rc = 0;
0527 } else if ((mod=shell_pci_find_modifier(argv[1])) != NULL) {
0528 rc = mod->func(argc, argv, mod);
0529 } else {
0530 rc = -1;
0531 }
0532
0533 if (rc < 0) {
0534 printf(" invalid argument\n");
0535 usage();
0536 }
0537
0538 return rc;
0539 }
0540
0541 rtems_shell_cmd_t rtems_shell_PCI_Command = {
0542 "pci",
0543 pci_usage_str,
0544 "system",
0545 rtems_shell_main_pci,
0546 NULL,
0547 NULL
0548 };