⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcicommon.c

📁 1. 8623L平台
💻 C
📖 第 1 页 / 共 2 页
字号:
    }        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 + -