📄 pcicommon.c
字号:
} for (i = 0; i < basecount; ++i) { iotype = pdev->base_addr[i] & PCI_BASE_ADDRESS_SPACE; memtype = (pdev->base_addr[i] & PCI_BASE_ADDRESS_MEM_TYPE_MASK) >> 1; prefetch = (pdev->base_addr[i] & PCI_BASE_ADDRESS_MEM_PREFETCH) ? 0 : 1; uart_printf(" Base Address %d = %08x", i, pdev->resource[i].start); if (pdev->base_addr[i] != 0x00000000 && pdev->base_addr[i] != 0xffffffff) uart_printf(" (%s, %s, %s)", s_strIoType[iotype], s_strMemType[memtype], s_strPrefetch[prefetch]); uart_printf(" (%08x)\n", pdev->resource[i].size); } // Buses if (pdev->is_bridge) { uart_printf(" Buses = %08x (primary = %02x, secondary = %02x, subordinate = %02x)\n", pdev->buses, pdev->primary_bus, pdev->secondary_bus, pdev->subordinate_bus); }}void pci_dump_idsel(int idsel, int readonly){ struct my_pci_dev devinfo, *pdev; if (pci_select(idsel) == 0) return; if ((pdev = pci_get_info(&devinfo, readonly)) == NULL) return; pdev->idsel = idsel; pci_dump(pdev);}//// APIs for PCI-based device drivers//// scan PCI bus and find the desired device // 0 value of ID means "don't care"// return the first matched device informationstruct my_pci_dev *pci_lookup(unsigned int vendor_id, unsigned int device_id, struct my_pci_dev *pdev){ int i; unsigned int mask = 0; unsigned int idword = 0; if (g_pciop == NULL) return NULL; if (vendor_id != 0) { mask |= 0x0000ffff; idword |= vendor_id; } if (device_id != 0) { mask |= 0xffff0000; idword |= (device_id << 16); } // Agent detection for (i = g_pciop->idsel_start; i <= g_pciop->idsel_end; ++i) { if ((pci_select(i) & mask) == idword) { pci_get_info(pdev, 0); pdev->idsel = i; return pdev; } } return NULL;}struct my_pci_dev *pci_lookup_idsel(int idsel, struct my_pci_dev *pdev){ if (g_pciop == NULL) return NULL; if (idsel >= g_pciop->idsel_start && idsel <= g_pciop->idsel_end) { if (pci_select(idsel)) { pci_get_info(pdev, 0); pdev->idsel = idsel; return pdev; } } return NULL;}// configure base address of PCI device (PCI I/O and PCI memory)// this function must be called once. at this time it doesn't support configuring // multiple devicesvoid pci_configure_device(struct my_pci_dev *pdev){ int i, isioaddr; unsigned int baseaddr, basesize; unsigned int memory_start = 0, io_start = 0; if (g_pciop == NULL) return; // select device if (pci_select(pdev->idsel) == 0) return; // enable device g_pciop->write_config_word(PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); // setup base address for (i = 0; i < 6; ++i) { // detect the size of each base address g_pciop->read_config_dword(PCI_BASE_ADDRESS_0 + 4 * i, &baseaddr); g_pciop->write_config_dword(PCI_BASE_ADDRESS_0 + 4 * i, 0xffffffff); g_pciop->read_config_dword(PCI_BASE_ADDRESS_0 + 4 * i, &basesize); if (basesize != 0) { // determine the starting address and the size isioaddr = (basesize & PCI_BASE_ADDRESS_SPACE_IO); baseaddr = (isioaddr ? io_start : memory_start); basesize &= (isioaddr ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK); basesize = ~basesize + 1; // if the address is not aligned, make it aligned if (baseaddr & (basesize - 1)) { baseaddr += basesize; baseaddr &= ~(basesize - 1); } // write configuration to PCI configuration area (bus address) // and setup the host address if (isioaddr) { io_start += basesize; baseaddr += g_pciop->pciio_base(pdev->idsel); g_pciop->write_config_dword(PCI_BASE_ADDRESS_0 + 4 * i, baseaddr - g_pciop->io_offset); } else { memory_start += basesize; baseaddr += g_pciop->pcimemory_base(pdev->idsel); g_pciop->write_config_dword(PCI_BASE_ADDRESS_0 + 4 * i, baseaddr - g_pciop->mem_offset); } } else baseaddr = 0; pdev->resource[i].start = baseaddr; } // setup IRQ if (pdev->irqpin) { pdev->irqline = PCI_IRQ_MAP(pdev->idsel, pdev->irqpin); g_pciop->write_config_byte(PCI_INTERRUPT_LINE, pdev->irqline); }}//// Test functions//#ifdef CONFIG_ENABLE_FULLFUNCTION// PCI configuration space testvoid pci_test_config(void){ unsigned int data32, data32_new, data32_16, data32_8; int i, j; // read by "byte" "word" "dword" and compare them uart_puts("Configuration Read Test\n"); for (i = 0; i < 0x40; i += 4) { pci_read_config_dword(i, &data32); for (j = 0; j < 4; j += 2) pci_read_config_word(i + j, (unsigned short *) ((unsigned int) &data32_16 + j)); for (j = 0; j < 4; ++j) pci_read_config_byte(i + j, (unsigned char *) ((unsigned int) &data32_8 + j)); uart_printf("Configuration 0x%02x : %08x, %08x, %08x ", i, data32, data32_16, data32_8); if (data32 != data32_16) uart_puts("WORD_FAIL "); if (data32 != data32_8) uart_puts("BYTE_FAIL "); uart_puts("\n"); } PAUSE // write base addresses by "byte" "word" "dword" and see the difference uart_puts("Configuration Write Test\n"); for (i = PCI_BASE_ADDRESS_0; i < PCI_BASE_ADDRESS_1; i += 4) { pci_read_config_dword(i, &data32); uart_printf("Configuration 0x%02x : %08x\n", i , data32); data32_new = 0x89abcdef; pci_write_config_dword(i, data32_new); pci_read_config_dword(i, &data32); uart_printf(" DWORD : (%08x) %08x\n", data32_new, data32); data32_new = 0x11223344; uart_printf(" WORD : (%08x) ", data32_new); for (j = 0; j < 4; j += 2) { pci_write_config_word(i + j, *(unsigned short *) ((unsigned int) &data32_new + j)); pci_read_config_dword(i, &data32); uart_printf("%08x ", data32); } uart_puts("\n"); data32_new = 0xaabbccdd; uart_printf(" BYTE : (%08x) ", data32_new); for (j = 0; j < 4; ++j) { pci_write_config_byte(i + j, *(unsigned char *) ((unsigned int) &data32_new + j)); pci_read_config_dword(i, &data32); uart_printf("%08x ", data32); } uart_puts("\n"); }}// I/O & memory space testvoid pci_test_io_memory(int idsel, int isio){ struct my_pci_dev devinfo, *pdev; unsigned int baseaddr; unsigned int (*pfread)(unsigned int addr) = isio ? pci_inl : pci_readl; void (*pfwrite)(unsigned int data, unsigned int addr) = isio ? pci_outl : pci_writel; char *str = isio ? "I/O" : "Memory"; int i; if ((pdev = pci_lookup_idsel(idsel, &devinfo)) == NULL) return; pci_configure_device(pdev); uart_puts("Device information :\n"); pci_dump(pdev); for (i = 0, baseaddr = 0; i < 6; ++i) { if (pdev->resource[i].isio >= 0 && ((pdev->resource[i].isio && isio) || (!pdev->resource[i].isio && !isio))) { baseaddr = pdev->resource[i].start; break; } } if (i == 6) { uart_puts("No resource found\n"); return; } else uart_printf("Use base address %d : %08x\n", i, baseaddr); PAUSE uart_printf("%s Read Test :\n", str); for (i = 0; i < 0x10; i += 4) uart_printf(" Read %08x : %08x\n", baseaddr + i, pfread(baseaddr + i)); PAUSE uart_printf("%s Write Test :\n", str); pfwrite(0x11111111, baseaddr + 0x00); pfwrite(0x22222222, baseaddr + 0x04); pfwrite(0x33333333, baseaddr + 0x08); pfwrite(0x44444444, baseaddr + 0x0c); PAUSE uart_printf("%s Read Test :\n", str); for (i = 0; i < 0x10; i += 4) uart_printf(" Read %08x : %08x\n", baseaddr + i, pfread(baseaddr + i));}void pci_test_em86xx(int idsel){ static struct { char *name; unsigned int addr; } s_edge_info_list[] = { { "EDGE_STATUS", REG_BASE_CPU + CPU_edge_status }, { "EDGE_RAWSTAT", REG_BASE_CPU + CPU_edge_rawstat }, { "EDGE_CONFIG_RISE", REG_BASE_CPU + CPU_edge_config_fall }, { "EDGE_CONFIG_FALL", REG_BASE_CPU + CPU_edge_config_rise }, { NULL, 0 }, }; struct my_pci_dev devinfo, *pdev; if ((pdev = pci_lookup_idsel(idsel, &devinfo)) != NULL) { unsigned int baseaddr; unsigned int memsize, regsize, membase, data; int i; pci_configure_device(pdev); pci_dump(pdev); baseaddr = pdev->resource[0].start; // setup PCI slave memsize = pci_readl(baseaddr + REG_BASE_HOST + PCI_devcfg_reg3) & 0x07; memsize = 1 << memsize; regsize = (memsize << 20) >> 3; // memory size / 8 uart_printf("Configure EM86XX as slave with %dMB memory\n", memsize); membase = MEMORY_BASE_DRAMCTRL0; for (i = 2; i < memsize; ++i) { pci_writel(EM86XX_DRAM_C2NC(membase), baseaddr + REG_BASE_HOST + PCI_region_base + (i * 4)); membase += regsize; } // dump some registers for (i = 0; s_edge_info_list[i].name; ++i) { data = pci_readl(baseaddr + s_edge_info_list[i].addr); uart_printf("Register %s (%08x) = %08x\n", s_edge_info_list[i].name, s_edge_info_list[i].addr, data); } }}int pci_test(int argc, char *argv[]){ int doall = (argv[0] && strcmp(argv[0], "all") == 0) ? 1 : 0; int idsel = 0; if (g_pciop == NULL) return 0; if (argv[1]) idsel = atoi(argv[1]); if (argv[0] == NULL) { uart_puts("PCI Test :\n"); uart_puts(" Available commands : " "config " "io " "memory " "em86xx" "\n"); } else { if (pci_select(idsel) == 0) { uart_printf("PCI device not found at IDSEL %d\n", idsel); return 0; } if (doall || strcmp(argv[0], "config") == 0) pci_test_config(); if (doall || strcmp(argv[0], "io") == 0) pci_test_io_memory(idsel, 1); if (doall || strcmp(argv[0], "memory") == 0) pci_test_io_memory(idsel, 0); if (strcmp(argv[0], "em86xx") == 0) pci_test_em86xx(idsel); } if (g_pciop->test) return g_pciop->test(argc, argv); return 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -