最近使用XILINX的7系列芯片做产品用到了PCIE接口。用到了XDMA的驱动,但是由于强实时性要求,需要自己从更底层研究驱动。
这里作为学习笔记,记录学习过程以及一些过程,算是情景分析。
1,软硬件环境:
使用UBUNTU 16,板子使用的是XTRX的PCIE版。使用dmesg命令查看驱动打印的输出。使用
sudo dmesg -C && dmesg -Tw
这个命令清除之前显示的内容并实时显示新内容
2,挂在驱动时运行情景。
执行命令
sudo insmod ./xtrx.ko
在代码里面找xtrx_init,
可以看到这是静态初始化的代码。也就是说执行insmod命令好这个无参函数就开始执行。我们看看代码具体做了什么。
static int __init xtrx_init(void)
{
int err;
printk(KERN_INFO PFX "liwei ---------------------startup here-------------------- %d\n", __LINE__ );
printk(KERN_INFO PFX "liwei xtrx_init %d\n", __LINE__ );
err = uart_register_driver(&xtrx_uart_driver);
if (err) {
printk(KERN_NOTICE PFX "Unable to initialize UART driver: %d\n", err);
goto failed_uart;
}
err = alloc_chrdev_region(&dev_first, 0, MAX_XTRX_DEVS, DRV_NAME);
if (err) {
printk(KERN_NOTICE PFX "Unable to allocate chrdev region: %d\n", err);
goto failed_chrdev;
}
xtrx_class = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(xtrx_class)) {
printk(KERN_NOTICE PFX "Unable to register xtrx class\n");
goto failed_setup_cdev;
}
err = pci_register_driver(&xtrx_driver);
if (err) {
printk(KERN_NOTICE PFX "Unable to register PCI driver: %d\n", err);
goto failed_pci;
}
return 0;
failed_pci:
class_unregister(xtrx_class);
class_destroy(xtrx_class);
failed_setup_cdev:
unregister_chrdev_region(dev_first, devices);
failed_chrdev:
uart_unregister_driver(&xtrx_uart_driver);
failed_uart:
return err;
}
这个驱动集成了对多个逻辑外设的控制,其实pcie相关的函数我们只看pci_register_driver就可以。
pci_register_driver()
是 Linux 内核中用于注册 PCI 设备驱动程序的函数。该函数允许内核在设备探测过程中将驱动程序与合适的 PCI 设备进行匹配。下面是一个在内核模块中使用 pci_register_driver()
的基本示例:
///人工智能生成不保证编译通过,供学习参考
#include <linux/pci.h>
/* PCI 设备 ID 表 */
static const struct pci_device_id my_pci_tbl[] = {
{ PCI_DEVICE(0x1234, 0x5678) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, my_pci_tbl);
/* PCI 驱动程序结构 */
static struct pci_driver my_pci_driver = {
.name = "my_pci_driver",
.id_table = my_pci_tbl,
.probe = my_pci_probe,
.remove = my_pci_remove,
};
static int __init my_pci_init(void)
{
return pci_register_driver(&my_pci_driver);
}
static void __exit my_pci_exit(void)
{
pci_unregister_driver(&my_pci_driver);
}
module_init(my_pci_init);
module_exit(my_pci_exit);
在这个例子中,my_pci_tbl
数组定义了驱动程序支持的 PCI 设备 ID。my_pci_driver
结构包含了驱动程序的名称、设备 ID 表以及 probe
和 remove
回调函数。
在模块的初始化函数 (my_pci_init()
) 中调用 pci_register_driver()
函数将驱动程序注册到 PCI 子系统。在模块的退出函数 (my_pci_exit()
) 中调用 pci_unregister_driver()
函数来注销驱动程序。
当在设备探测过程中找到匹配的 PCI 设备时,会调用 my_pci_probe()
函数来初始化设备。当设备被移除时,会调用 my_pci_remove()
函数来清理设备。
pci_register_driver()
函数在成功时返回 0,在失败时返回负的错误码。
上述斜体是拷贝自人工智能聊天工具,
具体到咱们的代码:这里我们看到 module_init指定的函数调用的pcie_register_driver用一个结构进行了初始化,这个初始化结构如下:
这里看到xtrx_pci_table罗列若干对pid和vid这点和USB有点相似。这PID和VID在VIVADO软件里可以对应设置,如下:
这个结构里面还指出了两个函数probe和remove .
从内核打印的输出log里面我们看到了probe函数被调用了,
我们跟进去看看probe的情景
static int xtrx_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
printk(KERN_INFO PFX "liwei xtrx_probe %d\n", __LINE__ );
printk(KERN_INFO PFX "liwei --------------------------------------------------- %d\n", __LINE__ );
struct xtrx_dev* xtrxdev;
int err;
void __iomem* bar0_addr;
void __iomem* bar1_addr;
unsigned xtrx_no = devices;
printk(KERN_INFO PFX "Initializing %s\n", pci_name(pdev));
#ifdef VA_DMA_ADDR_FIXUP
printk(KERN_INFO PFX "Buggy va/dma mapping on the platform! Fixup enabled\n");
#endif
err = pci_enable_device(pdev);
if (err) {
dev_err(&pdev->dev, "Cannot enable PCI device, "
"aborting.\n");
return err;
}
/* Reconfigure MaxReadReq to 4KB */
pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL,
PCI_EXP_DEVCTL_READRQ, PCI_EXP_DEVCTL_READRQ_4096B);
pci_set_master(pdev);
if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
dev_err(&pdev->dev,"No suitable consistent DMA available.\n");
goto err_disable_pdev;
}
/*
* Check for BARs. We expect 0: 4KB
*/
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
pci_resource_len(pdev, 0) < 1 << 12) {
dev_err(&pdev->dev, "Missing UL BAR, aborting.\n");
err = -ENODEV;
goto err_disable_pdev;
}
err = pci_request_regions(pdev, DRV_NAME);
if (err) {
dev_err(&pdev->dev, "Cannot obtain PCI resources, "
"aborting.\n");
goto err_disable_pdev;
}
bar0_addr = pci_iomap(pdev, 0, 1 << 12);
if (!bar0_addr) {
dev_err(&pdev->dev, "Failed to map BAR 0.\n");
goto err_free_res;
}
bar1_addr = pci_iomap(pdev, 1, 1 << 16);
if (!bar0_addr) {
dev_err(&pdev->dev, "Failed to map BAR 0.\n");
goto err_unmap0;
}
xtrxdev = kzalloc(sizeof(*xtrxdev), GFP_KERNEL);
if (!xtrxdev) {
dev_err(&pdev->dev, "Failed to allocate memory.\n");
err = -ENOMEM;
goto err_unmap1;
}
pci_set_drvdata(pdev, xtrxdev);
xtrxdev->bar0_addr = bar0_addr;
xtrxdev->bar1_addr = bar1_addr;
xtrxdev->devno = xtrx_no;
xtrxdev->pdev = pdev;
xtrxdev->locked_msk = 0;
xtrxdev->gps_ctrl_state = 0;
xtrxdev->sim_ctrl_state = 0;
xtrxdev->pwr_msk = 0;
xtrxdev->valid = 0;
spin_lock_init(&xtrxdev->slock);
xtrxdev->shared_mmap = (char*)get_zeroed_page(GFP_KERNEL);
if (!xtrxdev->shared_mmap) {
dev_err(&pdev->dev, "Failed to allocate kernel mmap memory.\n");
err = -ENOMEM;
goto err_alloc0;
}
xtrxdev->hwid = xtrx_readl(xtrxdev, GP_PORT_RD_HWCFG);
xtrxdev->pps = pps_register_source(&xtrx_pps_info,
PPS_CAPTUREASSERT | PPS_OFFSETASSERT);
if (!xtrxdev->pps) {
dev_err(&pdev->dev, "Failed to register 1PPS source.\n");
}
init_waitqueue_head(&xtrxdev->queue_ctrl);
init_waitqueue_head(&xtrxdev->queue_tx);
init_waitqueue_head(&xtrxdev->queue_rx);
init_waitqueue_head(&xtrxdev->onepps_ctrl);
init_waitqueue_head(&xtrxdev->queue_i2c);
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,11,0)
err = pci_enable_msi_range(pdev, XTRX_MSI_COUNT, XTRX_MSI_COUNT);
#else
err = pci_alloc_irq_vectors(pdev, XTRX_MSI_COUNT, XTRX_MSI_COUNT, PCI_IRQ_MSI);
#endif
if (err == XTRX_MSI_COUNT) {
xtrxdev->inttype = XTRX_MSI_4;
err = request_irq(pdev->irq + INT_1PPS, xtrx_msi_irq_pps, 0, "xtrx_pps", xtrxdev);
if (err) {
dev_err(&pdev->dev, "Failed to register CTRL MSI.\n");
err = -ENODEV;
goto err_msi;
}
err = request_irq(pdev->irq + INT_DMA_TX, xtrx_msi_irq_tx, 0, "xtrx_tx", xtrxdev);
if (err) {
dev_err(&pdev->dev, "Failed to register TX MSI.\n");
err = -ENODEV;
goto err_irq_0;
}
err = request_irq(pdev->irq + INT_DMA_RX, xtrx_msi_irq_rx, 0, "xtrx_rx", xtrxdev);
if (err) {
dev_err(&pdev->dev, "Failed to register RX MSI.\n");
err = -ENODEV;
goto err_irq_1;
}
err = request_irq(pdev->irq + 3, xtrx_msi_irq_other, 0, "xtrx_other", xtrxdev);
if (err) {
dev_err(&pdev->dev, "Failed to register OTHER MSI.\n");
err = -ENODEV;
goto err_irq_2;
}
} else {
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,11,0)
err = pci_enable_msi_range(pdev, 1, 1);
#else
err = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
#endif
if (err == 1) {
xtrxdev->inttype = XTRX_MSI_SINGLE;
err = request_irq(pdev->irq, xtrx_msi_irq_single, 0, "xtrx_msi_single", xtrxdev);
if (err) {
dev_err(&pdev->dev, "Failed to register SINGLE MSI.\n");
err = -ENODEV;
goto err_msi;
}
} else {
dev_err(&pdev->dev, "Failed to enable MSI, falling back to legacy mode.\n");
xtrxdev->inttype = XTRX_LEGACY;
err = request_irq(pdev->irq, xtrx_irq_legacy, IRQF_SHARED, "xtrx_legacy", xtrxdev);
if (err) {
dev_err(&pdev->dev, "Failed to register Legacy interrupt.\n");
err = -ENODEV;
goto err_alloc1;
}
}
}
/* Clear pending interrupts */
xtrx_readl(xtrxdev, GP_PORT_RD_INTERRUPTS);
/* Enable interrupts */
xtrx_writel(xtrxdev, GP_PORT_WR_INT_PCIE, (1U << INT_PCIE_I_FLAG) | 0xfff);
// Mark that we don't have preallocated buffers
xtrxdev->buf_rx_size = 0;
xtrxdev->buf_tx_size = 0;
memset(xtrxdev->buf_rx, 0, sizeof(xtrxdev->buf_rx));
memset(xtrxdev->buf_tx, 0, sizeof(xtrxdev->buf_tx));
err = xtrx_allocdma_rx(xtrxdev, BUF_SIZE);
if (err) {
dev_err(&pdev->dev, "Failed to register RX DMA buffers.\n");
err = -ENODEV;
goto err_irq_3;
}
err = xtrx_allocdma_tx(xtrxdev, BUF_SIZE);
if (err) {
dev_err(&pdev->dev, "Failed to register TX DMA buffers.\n");
err = -ENODEV;
goto err_rx_bufs;
}
err = xtrx_uart_init(xtrxdev, xtrx_no);
if (err) {
goto err_uart;
}
xtrxdev->valid = 1;
xtrxdev->cdevice = device_create(xtrx_class,
&pdev->dev,
MKDEV(MAJOR(dev_first), MINOR(dev_first) + devices),
NULL,
DEVICE_NAME "%d",
devices);
if (IS_ERR(xtrxdev->cdevice)) {
printk(KERN_NOTICE PFX "Unable to register device class\n");
goto failed_device;
}
err = xtrx_setup_cdev(xtrxdev);
if (err) {
printk(KERN_NOTICE PFX "Error %d initializing cdev\n", err);
goto failed_cdev;
}
devices++;
xtrxdev->next = xtrx_list;
xtrx_list = xtrxdev;
return 0;
//cdev_del(&xtrxdev->cdev);
failed_cdev:
device_destroy(xtrx_class, MKDEV(MAJOR(dev_first), MINOR(dev_first) + devices));
failed_device:
xtrx_uart_deinit(xtrxdev);
err_uart:
xtrx_freedma_tx(xtrxdev);
err_rx_bufs:
xtrx_freedma_rx(xtrxdev);
err_irq_3:
xtrx_writel(xtrxdev, GP_PORT_WR_INT_PCIE, (1U << INT_PCIE_I_FLAG));
xtrx_readl(xtrxdev, GP_PORT_RD_INTERRUPTS);
if (xtrxdev->inttype == XTRX_LEGACY) {
free_irq(pdev->irq, xtrxdev);
} else if (xtrxdev->inttype == XTRX_MSI_SINGLE) {
free_irq(pdev->irq, xtrxdev);
pci_disable_msi(pdev);
} else if (xtrxdev->inttype == XTRX_MSI_4) {
free_irq(pdev->irq + 3, xtrxdev);
err_irq_2:
free_irq(pdev->irq + 2, xtrxdev);
err_irq_1:
free_irq(pdev->irq + 1, xtrxdev);
err_irq_0:
free_irq(pdev->irq + 0, xtrxdev);
err_msi:
pci_disable_msi(pdev);
}
err_alloc1:
if (xtrxdev->pps) {
pps_unregister_source(xtrxdev->pps);
}
free_page((unsigned long)xtrxdev->shared_mmap);
err_alloc0:
kfree(xtrxdev);
err_unmap1:
pci_iounmap(pdev, bar1_addr);
err_unmap0:
pci_iounmap(pdev, bar0_addr);
err_free_res:
pci_release_regions(pdev);
err_disable_pdev:
pci_clear_master(pdev); /* Nobody seems to do this */
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
return err;
};
这就比较多了哈。在开始分析之前最好需要一些基本知识垫底,之后再分析就成了这个基础知识的应用实例了。我们下个blog再写。下面是完整的log信息:
Last login: Fri Jun 28 09:21:16 2024 from 192.168.5.217
za@a:~$sudo dmesg -C && dmesg -Tw
[sudo] password for a:
[五 6月 28 09:24:48 2024] xtrx: liwei ---------------------startup here-------------------- 1558
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_init 1559
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_probe 1201
[五 6月 28 09:24:48 2024] xtrx: liwei --------------------------------------------------- 1202
[五 6月 28 09:24:48 2024] xtrx: Initializing 0000:01:00.0
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_readl[194] off=0000001a return=04000113
[五 6月 28 09:24:48 2024] pps pps1: new PPS source xtrx_pps
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_readl[194] off=00000001 return=00000000
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_writel[187] off=00000001 d=00008fff
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_allocdma_rx 682
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_allocdma 650
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_set_dma_bufs 621
[五 6月 28 09:24:48 2024] xtrx: buf[0]=21820000 [virt 000000006fc894be] => 218207ff
[五 6月 28 09:24:48 2024] xtrx: buf[1]=21828000 [virt 0000000065f2c3e7] => 218287ff
[五 6月 28 09:24:48 2024] xtrx: buf[2]=21830000 [virt 000000001c1ebb66] => 218307ff
[五 6月 28 09:24:48 2024] xtrx: buf[3]=21838000 [virt 000000005522f2e9] => 218387ff
[五 6月 28 09:24:48 2024] xtrx: buf[4]=21840000 [virt 00000000e09cdfb6] => 218407ff
[五 6月 28 09:24:48 2024] xtrx: buf[5]=21848000 [virt 000000006fce65f0] => 218487ff
[五 6月 28 09:24:48 2024] xtrx: buf[6]=21850000 [virt 000000006018dc4a] => 218507ff
[五 6月 28 09:24:48 2024] xtrx: buf[7]=21858000 [virt 00000000f80e6177] => 218587ff
[五 6月 28 09:24:48 2024] xtrx: buf[8]=21860000 [virt 00000000887b0551] => 218607ff
[五 6月 28 09:24:48 2024] xtrx: buf[9]=21868000 [virt 000000004760bb6e] => 218687ff
[五 6月 28 09:24:48 2024] xtrx: buf[10]=21870000 [virt 00000000a7b9fb64] => 218707ff
[五 6月 28 09:24:48 2024] xtrx: buf[11]=21878000 [virt 0000000040407799] => 218787ff
[五 6月 28 09:24:48 2024] xtrx: buf[12]=21880000 [virt 000000004145c18f] => 218807ff
[五 6月 28 09:24:48 2024] xtrx: buf[13]=21888000 [virt 000000002b334677] => 218887ff
[五 6月 28 09:24:48 2024] xtrx: buf[14]=21890000 [virt 0000000079d1f4c7] => 218907ff
[五 6月 28 09:24:48 2024] xtrx: buf[15]=21898000 [virt 0000000031dac545] => 218987ff
[五 6月 28 09:24:48 2024] xtrx: buf[16]=218a0000 [virt 000000009da889e5] => 218a07ff
[五 6月 28 09:24:48 2024] xtrx: buf[17]=218a8000 [virt 000000000c789d14] => 218a87ff
[五 6月 28 09:24:48 2024] xtrx: buf[18]=218b0000 [virt 00000000ee27b209] => 218b07ff
[五 6月 28 09:24:48 2024] xtrx: buf[19]=218b8000 [virt 00000000ee2a56fa] => 218b87ff
[五 6月 28 09:24:48 2024] xtrx: buf[20]=218c0000 [virt 00000000d3a6e9a5] => 218c07ff
[五 6月 28 09:24:48 2024] xtrx: buf[21]=218c8000 [virt 000000008aa954df] => 218c87ff
[五 6月 28 09:24:48 2024] xtrx: buf[22]=218d0000 [virt 00000000aeaf240e] => 218d07ff
[五 6月 28 09:24:48 2024] xtrx: buf[23]=218d8000 [virt 00000000727a1b04] => 218d87ff
[五 6月 28 09:24:48 2024] xtrx: buf[24]=218e0000 [virt 00000000c61b0dd6] => 218e07ff
[五 6月 28 09:24:48 2024] xtrx: buf[25]=218e8000 [virt 00000000bf5bb660] => 218e87ff
[五 6月 28 09:24:48 2024] xtrx: buf[26]=218f0000 [virt 00000000d371946b] => 218f07ff
[五 6月 28 09:24:48 2024] xtrx: buf[27]=218f8000 [virt 0000000001c30e6d] => 218f87ff
[五 6月 28 09:24:48 2024] xtrx: buf[28]=21900000 [virt 0000000016fc4af6] => 219007ff
[五 6月 28 09:24:48 2024] xtrx: buf[29]=21908000 [virt 0000000019310411] => 219087ff
[五 6月 28 09:24:48 2024] xtrx: buf[30]=21910000 [virt 00000000a8de86a3] => 219107ff
[五 6月 28 09:24:48 2024] xtrx: buf[31]=21918000 [virt 00000000b638a065] => 219187ff
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_update_rxdma_len 637
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_writel[187] off=00000220 d=800007ff
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_allocdma_tx 669
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_allocdma 650
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_set_dma_bufs 621
[五 6月 28 09:24:48 2024] xtrx: buf[0]=21920000 [virt 00000000860cc5d5] => 219207ff
[五 6月 28 09:24:48 2024] xtrx: buf[1]=21928000 [virt 00000000f83b63c8] => 219287ff
[五 6月 28 09:24:48 2024] xtrx: buf[2]=21930000 [virt 00000000e330ff31] => 219307ff
[五 6月 28 09:24:48 2024] xtrx: buf[3]=21938000 [virt 00000000201b4ddb] => 219387ff
[五 6月 28 09:24:48 2024] xtrx: buf[4]=21940000 [virt 00000000fca0f5ce] => 219407ff
[五 6月 28 09:24:48 2024] xtrx: buf[5]=21948000 [virt 000000006fec8be3] => 219487ff
[五 6月 28 09:24:48 2024] xtrx: buf[6]=21950000 [virt 000000001bf9e18b] => 219507ff
[五 6月 28 09:24:48 2024] xtrx: buf[7]=21958000 [virt 00000000c42130e0] => 219587ff
[五 6月 28 09:24:48 2024] xtrx: buf[8]=21960000 [virt 0000000026d14254] => 219607ff
[五 6月 28 09:24:48 2024] xtrx: buf[9]=21968000 [virt 00000000215fc23b] => 219687ff
[五 6月 28 09:24:48 2024] xtrx: buf[10]=21970000 [virt 00000000af93cabe] => 219707ff
[五 6月 28 09:24:48 2024] xtrx: buf[11]=21978000 [virt 0000000077a34b82] => 219787ff
[五 6月 28 09:24:48 2024] xtrx: buf[12]=21980000 [virt 000000001ffe1ef5] => 219807ff
[五 6月 28 09:24:48 2024] xtrx: buf[13]=21988000 [virt 00000000b2206b69] => 219887ff
[五 6月 28 09:24:48 2024] xtrx: buf[14]=21990000 [virt 0000000016188eac] => 219907ff
[五 6月 28 09:24:48 2024] xtrx: buf[15]=21998000 [virt 0000000033d73a66] => 219987ff
[五 6月 28 09:24:48 2024] xtrx: buf[16]=219a0000 [virt 0000000061dcb081] => 219a07ff
[五 6月 28 09:24:48 2024] xtrx: buf[17]=219a8000 [virt 00000000a4415696] => 219a87ff
[五 6月 28 09:24:48 2024] xtrx: buf[18]=219b0000 [virt 00000000147bf061] => 219b07ff
[五 6月 28 09:24:48 2024] xtrx: buf[19]=219b8000 [virt 000000002b96edbc] => 219b87ff
[五 6月 28 09:24:48 2024] xtrx: buf[20]=219c0000 [virt 00000000171aed14] => 219c07ff
[五 6月 28 09:24:48 2024] xtrx: buf[21]=219c8000 [virt 00000000c4d6b7b7] => 219c87ff
[五 6月 28 09:24:48 2024] xtrx: buf[22]=219d0000 [virt 000000001f8137c3] => 219d07ff
[五 6月 28 09:24:48 2024] xtrx: buf[23]=219d8000 [virt 00000000b4355c52] => 219d87ff
[五 6月 28 09:24:48 2024] xtrx: buf[24]=219e0000 [virt 0000000064b5a531] => 219e07ff
[五 6月 28 09:24:48 2024] xtrx: buf[25]=219e8000 [virt 00000000e5b35ea8] => 219e87ff
[五 6月 28 09:24:48 2024] xtrx: buf[26]=219f0000 [virt 0000000081287884] => 219f07ff
[五 6月 28 09:24:48 2024] xtrx: buf[27]=219f8000 [virt 00000000506c4344] => 219f87ff
[五 6月 28 09:24:48 2024] xtrx: buf[28]=21a00000 [virt 000000005a8f5b48] => 21a007ff
[五 6月 28 09:24:48 2024] xtrx: buf[29]=21a08000 [virt 000000000f3a8421] => 21a087ff
[五 6月 28 09:24:48 2024] xtrx: buf[30]=21a10000 [virt 000000009212845c] => 21a107ff
[五 6月 28 09:24:48 2024] xtrx: buf[31]=21a18000 [virt 0000000077661f83] => 21a187ff
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_uart_init 567
[五 6月 28 09:24:48 2024] xtrx: Port config: 0 (1)
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_uart_request_port [395]
[五 6月 28 09:24:48 2024] xtrx: Port request: 0
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_uart_type [388]
[五 6月 28 09:24:48 2024] 0000:01:00.0: ttyXTRX0 at MMIO 0x0 (irq = 0, base_baud = 9600) is a xtrx_uart
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_uart_set_mctrl [266]
[五 6月 28 09:24:48 2024] xtrx: Port config: 1 (1)
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_uart_request_port [395]
[五 6月 28 09:24:48 2024] xtrx: Port request: 1
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_uart_type [388]
[五 6月 28 09:24:48 2024] 0000:01:00.0: ttyXTRX1 at MMIO 0x0 (irq = 0, base_baud = 9600) is a xtrx_uart
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_uart_set_mctrl [266]
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_dev_from_uart_port[252]
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_writel[187] off=00000006 d=00000000
[五 6月 28 09:24:48 2024] xtrx: SIM mctrl=0
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_setup_cdev 1188