龙芯软件开发(26)-- PCI设备初始化4

本文详细解析了PCI设备的搜索过程及配置方法,包括通过PCI标识进行设备搜索、判断设备存在性、读取PCI信息并分类设备,以及完成设备的总线带宽分配和内存映射空间分配。
AI助手已提取文章相关产品:
继续来分析 PCI 设备的搜索过程,下面就是通过调用搜索程序来实现的。
for (i = 0, pb = _pci_head; i < pci_roots; i++, pb = pb->next) {
_pci_scan_dev(pb, i, 0, init);
}
接着去看看函数 _pci_scan_dev 的实现:
static void
_pci_scan_dev (struct pci_device *dev, int bus, int device, int initialise)
{
for(; device < 32; device++) {
_pci_query_dev (dev, bus, device, initialise);
}
}
上面是根据 PCI 的总线定义,可以知道它最多有 32 个设备,因此就需要把这 32 个设备进行枚举。下面的搜索过程是通过 PCI 的标识来进行的,因为每个 PCI 插槽存在设备时,它的 ID 不为 0xFFFF FFFF ,根据这样的特征,就可以知道是否存在 PCI 设备了。
static void
_pci_query_dev (struct pci_device *dev, int bus, int device, int initialise)
{
pcitag_t tag;
pcireg_t id;
pcireg_t misc;
tag = _pci_make_tag(bus, device, 0);
if (!_pci_canscan (tag))
return;
上面组成 PCI 标识地址。
if (_pciverbose >= 2)
_pci_bdfprintf (bus, device, -1, "probe...");
id = _pci_conf_read(tag, PCI_ID_REG);
上面读取 PCI ID 标识。
if (_pciverbose >= 2) {
PRINTF ("completed/n");
}
if (id == 0 || id == 0xffffffff) {
return;
}
上面判断是否存在 PCI 设备,如果不存在就返回。
misc = _pci_conf_read(tag, PCI_BHLC_REG);
if (PCI_HDRTYPE_MULTIFN(misc)) {
int function;
for (function = 0; function < 8; function++) {
tag = _pci_make_tag(bus, device, function);
id = _pci_conf_read(tag, PCI_ID_REG);
if (id == 0 || id == 0xffffffff) {
return;
}
_pci_query_dev_func (dev, tag, initialise);
}
}
else {
_pci_query_dev_func (dev, tag, initialise);
}
上面读取 PCI 信息,并分类 PCI 设备,然后保存到 PCI 设备列表里。
}
找到所有设备之后,就需要把 PCI 的总线带宽分配,并分别分配设备的内存映射空间。通过下面的程序实现的:
static void
_setup_pcibuses (int initialise)
{
struct pci_bus *pb;
struct pci_device *pd;
unsigned int def_ltim, max_ltim;
int i;
SBD_DISPLAY ("PCIS", CHKPNT_PCIS);
for(pb = _pci_bushead; pb != NULL; pb = pb->next) {
if (pb->ndev == 0)
return;
if (initialise) {
/* convert largest minimum grant time to cycle count */
/*XXX 66/33 Mhz */ max_ltim = pb->min_gnt * 33 / 4;
/* now see how much bandwidth is left to distribute */
if (pb->bandwidth <= 0) {
if (_pciverbose) {
_pci_bdfprintf (pb->bus, -1, -1,
"WARN: total bandwidth exceeded/n");
}
def_ltim = 1;
}
else {
/* calculate a fair share for each device */
def_ltim = pb->bandwidth / pb->ndev;
if (def_ltim > pb->max_lat) {
/* would exceed critical time for some device */
def_ltim = pb->max_lat;
}
/* convert to cycle count */
def_ltim = def_ltim * 33 / 4;
}
/* most devices don't implement bottom three bits */
def_ltim = (def_ltim + 7) & ~7;
max_ltim = (max_ltim + 7) & ~7;
pb->def_ltim = MIN (def_ltim, 255);
pb->max_ltim = MIN (MAX (max_ltim, def_ltim), 255);
}
}
SBD_DISPLAY ("PCIR", CHKPNT_PCIR);
_pci_hwreinit ();
/* setup the individual device windows */
SBD_DISPLAY ("PCIW", CHKPNT_PCIW);
for(i = 0, pd = _pci_head; i < pci_roots; i++, pd = pd->next) {
_pci_setup_windows (pd);
}
}
到这里,就已经把 PCI 局部总线上的设备配置完成。 PCI 总线配置是非常复杂的,不但有众多的设备,还有内存空间的分配,还有设备的 DMA 选择,还有桥设备在上面的转换等等。

您可能感兴趣的与本文相关内容

虽然给定引用未直接提及在龙芯UEFI中添加LPC设备初始化的方法,但可基于UEFI相关知识和龙芯平台特点来分析思路。 UEFI是一个标准化的固件接口,具有开放性、可扩展性等特点,龙芯也研制了在MIPS架构上的UEFI版本。要在龙芯UEFI中添加LPC设备初始化,可从以下方面着手: ### 基于EDKII开源框架 由于龙芯国产计算平台的UEFIBIOS实现是以开源框架EDKII为基础的,可参考EDKII中已有的设备初始化代码结构和流程。在EDKII框架中找到合适的模块,添加LPC设备初始化的代码。例如,在相关的驱动模块中,按照UEFI的驱动开发规范,编写LPC设备初始化的函数。 ### 结合龙芯启动过程 龙芯3号处理器上电后从特定地址(0xBFC00000,32位虚拟地址,实际物理地址为0x1fc00000)开始取指执行,启动过程中需要对处理器核、内存、外设等进行初始化。可在启动过程的外设初始化阶段添加LPC设备初始化操作。在初始化代码中,对LPC设备的寄存器进行配置,设置其工作模式、时钟频率等参数。 以下是一个简单的伪代码示例,展示在UEFI中添加LPC设备初始化函数的基本结构: ```python # 假设这是一个UEFI驱动模块中的代码 def lpc_device_initialization(): # 初始化LPC设备寄存器 lpc_register_configuration() # 设置LPC设备工作模式 lpc_mode_setup() # 配置LPC设备时钟频率 lpc_clock_frequency_config() # 其他初始化操作 other_lpc_initialization() def lpc_register_configuration(): # 具体的寄存器配置代码 pass def lpc_mode_setup(): # 设置工作模式的代码 pass def lpc_clock_frequency_config(): # 配置时钟频率的代码 pass def other_lpc_initialization(): # 其他初始化操作代码 pass # 在UEFI启动过程的外设初始化阶段调用LPC设备初始化函数 if __name__ == "__main__": # 模拟UEFI启动过程 # 其他初始化操作 # ... # 调用LPC设备初始化函数 lpc_device_initialization() # 继续其他启动流程 # ... ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值