mips处理器linux内核pci初始化和设备枚举详解

本文详细介绍了Linux内核在MIPS处理器上PCI总线的初始化过程,包括pci控制器注册和设备枚举。首先,展示了如何在龙芯1A开发板上设置PCI内存和I/O资源,注册pci控制器。接着,深入讲解了pci总线枚举的过程,包括pci_scan_bus、pci_scan_slot和pci_scan_single_device等函数,阐述了如何遍历PCI总线,识别和填充pci_dev结构体。最后,提到了中断号的分配和固定。整个过程揭示了Linux内核如何管理和初始化PCI设备。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  linux启动过程中pci总线初始化主要包括2部分,pci控制器的注册和pci设备的枚举,pci总线和其他总线一个很重要的区别就是pci总线的枚举,在启动过程中遍历pci总线树上所有可能的dev func,记录下所有存在的设备的vendor id  设备名等,这个是做为后面pci设备驱动初始化中注册pci设备驱动需要匹配的重要依据,类似于platform驱动。

  先说pci控制器注册,这个与具体开发板相关,以龙芯1A开发板2.6.33内核为例,在arch/mips/loongson/sb2f/pci.c中部分代码如下:

static struct resource loongson_pci_mem_resource = {
    .name   = "pci memory space",
    .start  = 0x14000000UL,
    .end    = 0x17ffffffUL,
    .flags  = IORESOURCE_MEM,
};

static struct resource loongson_pci_io_resource = {
    .name   = "pci io space",
    .start  = 0x00004000UL,
    .end    = IO_SPACE_LIMIT,
    .flags  = IORESOURCE_IO,
};

static struct pci_controller  loongson_pci_controller = {
    .pci_ops        = &sb2f_pci_pci_ops,
    .io_resource    = &loongson_pci_io_resource,
    .mem_resource   = &loongson_pci_mem_resource,
    .mem_offset     = 0x00000000UL,
    .io_offset      = 0x00000000UL,
};

static void __init setup_pcimap(void)
{
    /*
     * local to PCI mapping for CPU accessing PCI space
     * CPU address space [256M,448M] is window for accessing pci space
     * we set pcimap_lo[0,1,2] to map it to pci space[0M,64M], [320M,448M]
     *
     * pcimap: PCI_MAP2  PCI_Mem_Lo2 PCI_Mem_Lo1 PCI_Mem_Lo0
     *       [<2G]   [384M,448M] [320M,384M] [0M,64M]
     */
    SB2F_PCIMAP = 0x46140;
}

static int __init pcibios_init(void)
{
    setup_pcimap();

    //loongson_pci_controller.io_map_base = mips_io_port_base;

    if(!disablepci)
    {
        register_pci_conroller(&loongson_pci_controller);
    }

    return 0;
}
在pcibios_init函数中setup_pcimap中设置pci总线的3个mem space空间的高6位, register_pci_conroller函数是对pci控制器提供的mem和io资源做一下检查 然后将pci控制器添加到内核的pci控制器链表中。

这就完成了对特定pci控制器的初始化。特别要注意控制器结构体中的pci_ops成员,这个成员提供的读写函数就是对pci设备配置寄存器的读写。


接下来来看pci总线的枚举,这是非常重要的一部分。

在arch/mips/pci/pci.c中

static int __init pcibios_init(void)
{
    struct pci_controller *hose;
    /* Scan all of the recorded PCI controllers.  */
    for (hose = hose_head; hose; hose = hose->next)
    {   
        pcibios_scanbus(hose);
    }   

    pci_fixup_irqs(pci_common_swizzle, pcibios_map_irq);

    pci_initialized = 1;

    return 0;
}


在这个pcibios_init函数中,遍历内核pci控制器链表每一个成员,这里我们只有一个控制器,只有一个成员。然后调用pcibus_scanbus来遍历总线,扫描设备。

-------》》》》pcibus_scanbus  参数:hose  pci控制器结构体

static void __devinit pcibios_scanbus(struct pci_controller *hose)
{
    static int next_busno;
    static int need_domain_info;
    struct pci_bus *bus;

    if (!hose->iommu)
        PCI_DMA_BUS_IS_PHYS = 1;

    if (hose->get_busno && pci_probe_only)
        next_busno = (*hose->get_busno)();

    bus = pci_scan_bus(next_busno, hose->pci_ops, hose);
    hose->bus = bus;

    need_domain_info = need_domain_info || hose->index;
    hose->need_domain_info = need_domain_info;
    if (bus) {
        next_busno = bus->subordinate + 1;
        /* Don't allow 8-bit bus number overflow inside the hose -
           reserve some space for bridges. */
        if (next_busno > 224) {
            next_busno = 0;
            need_domain_info = 1;
        }

        if (!pci_probe_only) {
            pci_bus_size_bridges(bus);
            pci_bus_assign_resources(bus);
            pci_enable_bridges(bus);
        }
    }
}
从前面pci控制器的注册可以知道get_busno为NULL,并且pci_probe_only为0,因此next_busno为0。调用pci_scan_bus

--------》》》》pci_scan_bus 参数:next_busno=0 hose->pci_ops hose

static inline struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops,
                       void *sysdata)
{       
    struct pci_bus *root_bus;
    root_bus = pci_scan_bus_parented(NULL, bus, ops, sysdata);
    if (root_bus)
        pci_bus_add_devices(root_bus);
    return root_bus;
}   
这个函数实现对pci根总线的初始化

------》》》》pci_scan_bus_parented 参数:NULL 0 hose->ops hose

struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
        int bus, struct pci_ops *ops, void *sysdata)
{       
    struct pci_bus *b;
    
    b = pci_create_bus(parent, bus, ops, sysdata);
    if (b)
       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值