10.PCIESwitch-3.Switch的初始化-BIOS-《计算机知识》

admin 2025-11-02 22:24:32 系统网络 来源:ZONE.CI 全球网 0 阅读模式
  • PCIE链路拓展代码
    • 初始化代码
      • 入口过程回顾
      • 第一轮扫描
      • 桥设备扫描

    PCIE链路拓展代码

    上边只是简单介绍了链路过程,但原理是什么?代码流程是什么?注:这里只是简单描述了链路的初始化代码流程,详细代码后续分析

    初始化代码

    入口过程回顾

    1. pci_acpi_scan_root // 主桥信息 struct pci_root_info 和 struct pci_sysdata 初始化, 当前设备只有一个主桥,瓜分了SEG0的 [bus 00-ff]
    2. -> acpi_pci_root_create // ECAM初始化,主桥资源初始化
    3. -> pci_create_root_bus(NULL, busnum, ops->pci_ops,sysdata, &info->resources); // 主桥PCI总线初始化
    4. -> struct pci_host_bridge *bridge = pci_alloc_host_bridge(0); // 创建pci_host_bridge结构
    5. -> pci_register_host_bridge(bridge); // 注册pci_host_bridge , 并初始化 struct pci_bus bus00
    6. -> pci_scan_child_bus(bus); // 扫描bus下所有子设备

    第一轮扫描

    BUS=00(因为我得主机只有一个主桥)

    1. max = bus->busn_res.start; // 这里max==0
    2. // 一条总线有32个接口,一个接口有8个子功能(先不考虑ARI),所以这里只能以8递增
    3. for (devfn = 0; devfn < 0x100; devfn += 8) // PCI总线基于某个BUS,非ARI设备可以拓展8个功能
    4. pci_scan_slot(bus, devfn);
    5. -> if (only_one_child(bus) && (devfn > 0)); // 这里肯定为0,因为 bus0得parent 为NULL
    6. -> pci_scan_single_device(bus, devfn); // !!! 检测设备并初始化设备资源信息
    7. -> for (fn = next_fn(bus, dev, 0); ......); // 初始化 mult-func设备
    8. -> pci_scan_single_device(bus, devfn);
    9. // 给SR-IOV设备预留总线位置 dev->sriov->max_VF_buses 在 sriov_init中compute_max_vf_buses(dev) 实现
    10. max += pci_iov_bus_range(bus);
    11. // 第一次扫描 bus0上边得所有桥设备, 第二次可以直接跳过
    12. if (pci_is_bridge(dev)) // 根据hdr_type字段来区分
    13. max = pci_scan_bridge(bus, dev, max, 0);
    14. // 检测桥设备总线 bus索引
    15. pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
    16. primary = buses & 0xFF;
    17. secondary = (buses >> 8) & 0xFF;
    18. subordinate = (buses >> 16) & 0xFF;
    19. // bus0下边设备得primary bus都为0 ,但primary == bus->number == 0 所以不进这个分支
    20. if (!primary && (primary != bus->number) && secondary && subordinate) {
    21. dev_warn(&dev->dev, "Primary bus is hard wired to 0\n");
    22. primary = bus->number;
    23. }
    24. // 这个是异常分支,不考虑,因此broken==0
    25. if (!pass &&
    26. (primary != bus->number || secondary <= bus->number ||
    27. secondary > subordinate)) {
    28. dev_info(&dev->dev, "bridge configuration invalid ([bus %02x-%02x]), reconfiguring\n",
    29. secondary, subordinate);
    30. broken = 1;
    31. }
    32. // 这里其实 软件只读得, 这个必须为0, P7.5.1.3.13 描述中 软件只读
    33. pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bctl);
    34. pci_write_config_word(dev, PCI_BRIDGE_CONTROL,
    35. bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT);
    36. pci_enable_crs(dev); // 设置CRS功能
    37. // probe默认没pcibios_assign_all_busses, 也不考虑card_bus,
    38. if ((secondary || subordinate) && !pcibios_assign_all_busses() &&
    39. !is_cardbus && !broken) {
    40. child = pci_add_new_bus(bus, dev, secondary); // !!! 分配并创建pci_bus ************
    41. pci_scan_child_bus(child); // !!! 递归扫描子 bus得设备 *************
    42. }

    桥设备扫描

    1. for (pass = 0; pass < 2; pass++)
    2. list_for_each_entry(dev, &bus->devices, bus_list) {
    3. if (pci_is_bridge(dev))
    4. max = pci_scan_bridge(bus, dev, max, pass);
    5. }
    6. ```![c231732a2445ed75495fd1c8d3b7d7d8.png](en-resource://database/779:1)
    01-shell脚本介绍-《shell脚本》 系统网络

    01-shell脚本介绍-《shell脚本》

    一、shell脚本是什么二、为什么要学shell,而不是其他计算机语言三、学习这门课程的优势四、学了能干什么五、学习什么内容六、学习的技巧七、成长路径八、学习环
    评论:0   参与:  21