xapp1022里:
static int XPCIe_init(void)
{
gDev = pci_find_device (PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILINX_PCIE, gDev);
if (NULL == gDev) {
printk(/*KERN_WARNING*/"%s: Init: Hardware not found.\n", gDrvrName);
//return (CRIT_ERR);
return (-1);
}
if (0 > pci_enable_device(gDev)) {
printk(/*KERN_WARNING*/"%s: Init: Device not enabled.\n", gDrvrName);
//return (CRIT_ERR);
return (-1);
}
// Get Base Address of registers from pci structure. Should come from pci_dev
// structure, but that element seems to be missing on the development system.
gBaseHdwr = pci_resource_start (gDev, 0);
if (0 > gBaseHdwr) {
printk(/*KERN_WARNING*/"%s: Init: Base Address not set.\n", gDrvrName);
//return (CRIT_ERR);
return (-1);
}
printk(/*KERN_WARNING*/"Base hw val %X\n", (unsigned int)gBaseHdwr);
gBaseLen = pci_resource_len (gDev, 0);
printk(/*KERN_WARNING*/"Base hw len %d\n", (unsigned int)gBaseLen);
// Remap the I/O register block so that it can be safely accessed.
// I/O register block starts at gBaseHdwr and is 32 bytes long.
// It is cast to char because that is the way Linus does it.
// Reference "/usr/src/Linux-2.4/Documentation/IO-mapping.txt".
gBaseVirt = ioremap(gBaseHdwr, gBaseLen);
if (!gBaseVirt) {
printk(/*KERN_WARNING*/"%s: Init: Could not remap memory.\n", gDrvrName);
//return (CRIT_ERR);
return (-1);
}
printk(/*KERN_WARNING*/"Virt hw val %X\n", (unsigned int)gBaseVirt);
// Get IRQ from pci_dev structure. It may have been remapped by the kernel,
// and this value will be the correct one.
gIrq = gDev->irq;
printk("irq: %d\n",gIrq);
//--- START: Initialize Hardware
// Try to gain exclusive control of memory for demo hardware.
if (0 > check_mem_region(gBaseHdwr, KINBURN_REGISTER_SIZE)) {
printk(/*KERN_WARNING*/"%s: Init: Memory in use.\n", gDrvrName);
//return (CRIT_ERR);
return (-1);
}
request_mem_region(gBaseHdwr, KINBURN_REGISTER_SIZE, "3GIO_Demo_Drv");
gStatFlags = gStatFlags | HAVE_REGION;
printk(/*KERN_WARNING*/"%s: Init: Initialize Hardware Done..\n",gDrvrName);
// Request IRQ from OS.
#if 0
if (0 > request_irq(gIrq, &XPCIe_IRQHandler,/* SA_INTERRUPT |*/ SA_SHIRQ, gDrvrName, gDev)) {
printk(/*KERN_WARNING*/"%s: Init: Unable to allocate IRQ",gDrvrName);
return (-1);
}
gStatFlags = gStatFlags | HAVE_IRQ;
#endif
initcode();
//--- END: Initialize Hardware
//--- START: Allocate Buffers
gBufferUnaligned = kmalloc(BUF_SIZE, GFP_KERNEL);
gReadBuffer = gBufferUnaligned;
if (NULL == gBufferUnaligned) {
printk(KERN_CRIT"%s: Init: Unable to allocate gBuffer.\n",gDrvrName);
return (-1);
}
gWriteBuffer = kmalloc(BUF_SIZE, GFP_KERNEL);
if (NULL == gWriteBuffer) {
printk(KERN_CRIT"%s: Init: Unable to allocate gBuffer.\n",gDrvrName);
return (-1);
}
//--- END: Allocate Buffers
//--- START: Register Driver
// Register with the kernel as a character device.
// Abort if it fails.
if (0 > register_chrdev(gDrvrMajor, gDrvrName, &XPCIe_Intf)) {
printk(KERN_WARNING"%s: Init: will not register\n", gDrvrName);
return (CRIT_ERR);
}
printk(KERN_INFO"%s: Init: module registered\n", gDrvrName);
gStatFlags = gStatFlags | HAVE_KREG;
printk("%s driver is loaded\n", gDrvrName);
return 0;
}
gBaseHdwr = pci_resource_start (gDev, 0)从resource结构获得BAR0空间的基地址,该地址 为存储器域的物理地址,不是PCI总线域的物理地址(pci_read_config_word()函数获取)。
ioremap()函数将存储器域的物理地址映射成为Linux系统中的虚拟地址,然后可以用gBaseVirt全局指针访问板卡中存储器映射的寄存器。
比如:
u32 XPCIe_ReadReg (u32 dw_offset)
{
u32 ret = 0;
u32 reg_addr = (u32)(gBaseVirt + dw_offset);
ret = readb((void*)reg_addr);
return ret;
}
void XPCIe_WriteReg (u32 dw_offset, u32 val)
{
u32 reg_addr = (u32)(gBaseVirt + dw_offset);
writeb(val, (void*)reg_addr);
}