static int pci_cfg_modify (pci_dev_t bdf, ulong addr, ulong size, ulong value, int incrflag) { ulong i; int nbytes; uint val4; ushort val2; u_char val1; /* Print the address, followed by value. Then accept input for * the next value. A non-converted value exits. */ do { printf("%08lx:", addr); if (size == 4) { pci_read_config_dword(bdf, addr, &val4); printf(" %08x", val4); } else if (size == 2) { pci_read_config_word(bdf, addr, &val2); printf(" %04x", val2); } else { pci_read_config_byte(bdf, addr, &val1); printf(" %02x", val1); } nbytes = cli_readline(" ? "); if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) { /* <CR> pressed as only input, don't modify current * location and move to next. "-" pressed will go back. */ if (incrflag) addr += nbytes ? -size : size; nbytes = 1; /* good enough to not time out */ bootretry_reset_cmd_timeout(); } #ifdef CONFIG_BOOT_RETRY_TIME else if (nbytes == -2) { break; /* timed out, exit the command */ } #endif else { char *endp; i = simple_strtoul(console_buffer, &endp, 16); nbytes = endp - console_buffer; if (nbytes) { /* good enough to not time out */ bootretry_reset_cmd_timeout(); pci_cfg_write (bdf, addr, size, i); if (incrflag) addr += size; } } } while (nbytes); return 0; }
static int pci_cfg_modify(pci_dev_t bdf, ulong addr, ulong size, ulong value, int incrflag) #endif { ulong i; int nbytes; ulong val; /* Print the address, followed by value. Then accept input for * the next value. A non-converted value exits. */ do { printf("%08lx:", addr); #ifdef CONFIG_DM_PCI dm_pci_read_config(dev, addr, &val, size); #else val = pci_read_config(bdf, addr, size); #endif printf(" %0*lx", pci_field_width(size), val); nbytes = cli_readline(" ? "); if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) { /* <CR> pressed as only input, don't modify current * location and move to next. "-" pressed will go back. */ if (incrflag) addr += nbytes ? -size : size; nbytes = 1; /* good enough to not time out */ bootretry_reset_cmd_timeout(); } #ifdef CONFIG_BOOT_RETRY_TIME else if (nbytes == -2) { break; /* timed out, exit the command */ } #endif else { char *endp; i = simple_strtoul(console_buffer, &endp, 16); nbytes = endp - console_buffer; if (nbytes) { /* good enough to not time out */ bootretry_reset_cmd_timeout(); #ifdef CONFIG_DM_PCI dm_pci_write_config(dev, addr, i, size); #else pci_cfg_write(bdf, addr, size, i); #endif if (incrflag) addr += size; } } } while (nbytes); return 0; }
/* PCI Configuration Space access commands * * Syntax: * pci display[.b, .w, .l] bus.device.function} [addr] [len] * pci next[.b, .w, .l] bus.device.function [addr] * pci modify[.b, .w, .l] bus.device.function [addr] * pci write[.b, .w, .l] bus.device.function addr value */ static int do_pci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { ulong addr = 0, value = 0, size = 0; pci_dev_t bdf = 0; char cmd = 's'; if (argc > 1) cmd = argv[1][0]; switch (cmd) { case 'd': /* display */ case 'n': /* next */ case 'm': /* modify */ case 'w': /* write */ /* Check for a size specification. */ size = cmd_get_data_size(argv[1], 4); if (argc > 3) addr = simple_strtoul(argv[3], NULL, 16); if (argc > 4) value = simple_strtoul(argv[4], NULL, 16); case 'h': /* header */ if (argc < 3) goto usage; if ((bdf = get_pci_dev(argv[2])) == -1) return 1; break; #ifdef CONFIG_CMD_PCI_ENUM case 'e': break; #endif default: /* scan bus */ value = 1; /* short listing */ bdf = 0; /* bus number */ if (argc > 1) { if (argv[argc-1][0] == 'l') { value = 0; argc--; } if (argc > 1) bdf = simple_strtoul(argv[1], NULL, 16); } pciinfo(bdf, value); return 0; } switch (argv[1][0]) { case 'h': /* header */ pci_header_show(bdf); return 0; case 'd': /* display */ return pci_cfg_display(bdf, addr, size, value); #ifdef CONFIG_CMD_PCI_ENUM case 'e': pci_init(); return 0; #endif case 'n': /* next */ if (argc < 4) goto usage; return pci_cfg_modify(bdf, addr, size, value, 0); case 'm': /* modify */ if (argc < 4) goto usage; return pci_cfg_modify(bdf, addr, size, value, 1); case 'w': /* write */ if (argc < 5) goto usage; return pci_cfg_write(bdf, addr, size, value); } return 1; usage: return CMD_RET_USAGE; }
void pci_cfg_e1k(net_info_t *net) { pci_cfg_dev_vdr_t dvd; e1k_info_t *e1k = &net->arch; pci_cfg_val_t *pci = &net->pci; /* search dev */ dvd.vendor = PCI_CFG_VENDOR_INTEL; dvd.device = PCI_CFG_DEVICE_i82545EM_C; if(!pci_search(pci_check_dvd, dvd.raw, 1, pci)) { dvd.device = PCI_CFG_DEVICE_i82540EM; if(!pci_search(pci_check_dvd, dvd.raw, 1, pci)) goto __not_found; } pci->addr.reg = PCI_CFG_CLASS_REV_OFFSET; pci_cfg_read(pci); if(pci->cr.class != PCI_CFG_CLASS_i8254x) goto __not_found; pci->addr.reg = PCI_CFG_CMD_STS_OFFSET; pci_cfg_read(pci); /* dma enable */ if(!pci->cs.cmd.mm || !pci->cs.cmd.bus_master) { pci->cs.cmd.mm = 1; pci->cs.cmd.bus_master = 1; pci_cfg_write(pci); } pci_cfg_read(pci); debug(PCI_E1000, "e1k CMD/STS 0x%x 0x%x | CMD io %d mm %d dma %d\n" ,pci->cs.cmd.raw, pci->cs.sts.raw ,pci->cs.cmd.io, pci->cs.cmd.mm, pci->cs.cmd.bus_master); /* BAR regs */ if(!pci_read_bar(pci, 0) && pci->br.io) panic("could not read i8254x registers (bar0 0x%x)", pci->br.raw); e1k->base.linear = pci->br.raw & 0xfffffff0; if(pci->br.type == PCI_CFG_MEM_BAR_64) { raw64_t addr = { .low = 0 }; pci_read_bar(pci, 1); addr.high = pci->data.raw; e1k->base.linear += addr.raw; } debug(PCI_E1000, "e1k BAR 0x%X\n", e1k->base.linear); setptr(e1k->ctl, e1k->base.linear + 0); setptr(e1k->sts, e1k->base.linear + 8); setptr(e1k->eerd, e1k->base.linear + 0x14); setptr(e1k->fcal, e1k->base.linear + 0x28); setptr(e1k->fcah, e1k->base.linear + 0x2c); setptr(e1k->fct, e1k->base.linear + 0x30); setptr(e1k->fcttv, e1k->base.linear + 0x170); setptr(e1k->icr, e1k->base.linear + 0xc0); setptr(e1k->ics, e1k->base.linear + 0xc8); setptr(e1k->ims, e1k->base.linear + 0xd0); setptr(e1k->imc, e1k->base.linear + 0xd8); setptr(e1k->rx.ctl, e1k->base.linear + 0x100); setptr(e1k->rx.bal, e1k->base.linear + 0x2800); setptr(e1k->rx.bah, e1k->base.linear + 0x2804); setptr(e1k->rx.dl, e1k->base.linear + 0x2808); setptr(e1k->rx.dh, e1k->base.linear + 0x2810); setptr(e1k->rx.dt, e1k->base.linear + 0x2818); setptr(e1k->tx.ctl, e1k->base.linear + 0x400); setptr(e1k->tx.ipg, e1k->base.linear + 0x410); setptr(e1k->tx.bal, e1k->base.linear + 0x3800); setptr(e1k->tx.bah, e1k->base.linear + 0x3804); setptr(e1k->tx.dl, e1k->base.linear + 0x3808); setptr(e1k->tx.dh, e1k->base.linear + 0x3810); setptr(e1k->tx.dt, e1k->base.linear + 0x3818); setptr(e1k->mta, e1k->base.linear + 0x5200); setptr(e1k->ra, e1k->base.linear + 0x5400); /* Interrupt line */ pci->addr.reg = PCI_CFG_INT_OFFSET; pci_cfg_read(pci); net->irq = pci->data.blow; debug(PCI_E1000, "e1k irq line %d\n", net->irq); return; __not_found: panic("no i8254x ethernet controller found"); }
/* PCI Configuration Space access commands * * Syntax: * pci display[.b, .w, .l] bus.device.function} [addr] [len] * pci next[.b, .w, .l] bus.device.function [addr] * pci modify[.b, .w, .l] bus.device.function [addr] * pci write[.b, .w, .l] bus.device.function addr value */ static int do_pci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { ulong addr = 0, value = 0, cmd_size = 0; enum pci_size_t size = PCI_SIZE_32; #ifdef CONFIG_DM_PCI struct udevice *dev, *bus; #else pci_dev_t dev; #endif int busnum = 0; pci_dev_t bdf = 0; char cmd = 's'; int ret = 0; if (argc > 1) cmd = argv[1][0]; switch (cmd) { case 'd': /* display */ case 'n': /* next */ case 'm': /* modify */ case 'w': /* write */ /* Check for a size specification. */ cmd_size = cmd_get_data_size(argv[1], 4); size = (cmd_size == 4) ? PCI_SIZE_32 : cmd_size - 1; if (argc > 3) addr = simple_strtoul(argv[3], NULL, 16); if (argc > 4) value = simple_strtoul(argv[4], NULL, 16); case 'h': /* header */ #ifdef CONFIG_DM_PCI case 'b': /* bars */ #endif if (argc < 3) goto usage; if ((bdf = get_pci_dev(argv[2])) == -1) return 1; break; #if defined(CONFIG_DM_PCI) case 'e': pci_init(); return 0; #endif case 'r': /* no break */ default: /* scan bus */ value = 1; /* short listing */ if (argc > 1) { if (cmd != 'r' && argv[argc-1][0] == 'l') { value = 0; argc--; } if (argc > 1) busnum = simple_strtoul(argv[1], NULL, 16); } #ifdef CONFIG_DM_PCI ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, &bus); if (ret) { printf("No such bus\n"); return CMD_RET_FAILURE; } if (cmd == 'r') pci_show_regions(bus); else pciinfo(bus, value); #else pciinfo(busnum, value); #endif return 0; } #ifdef CONFIG_DM_PCI ret = dm_pci_bus_find_bdf(bdf, &dev); if (ret) { printf("No such device\n"); return CMD_RET_FAILURE; } #else dev = bdf; #endif switch (argv[1][0]) { case 'h': /* header */ pci_header_show(dev); break; case 'd': /* display */ return pci_cfg_display(dev, addr, size, value); case 'n': /* next */ if (argc < 4) goto usage; ret = pci_cfg_modify(dev, addr, size, value, 0); break; case 'm': /* modify */ if (argc < 4) goto usage; ret = pci_cfg_modify(dev, addr, size, value, 1); break; case 'w': /* write */ if (argc < 5) goto usage; #ifdef CONFIG_DM_PCI ret = dm_pci_write_config(dev, addr, value, size); #else ret = pci_cfg_write(dev, addr, size, value); #endif break; #ifdef CONFIG_DM_PCI case 'b': /* bars */ return pci_bar_show(dev); #endif default: ret = CMD_RET_USAGE; break; } return ret; usage: return CMD_RET_USAGE; }