#include #include #include #include static unsigned long phys; module_param(phys, ulong, 0); static unsigned long size = PAGE_SIZE; module_param(size, ulong, 0); static unsigned long newvec; module_param(newvec, ulong, 0); static unsigned long test_write; module_param(test_write, ulong, 0); static unsigned long entry_nr = ~0UL; module_param(entry_nr, ulong, 0); #define PCI_MSIX_ENTRY_SIZE 16 static void __iomem *test_setup(unsigned long phys_addr, unsigned long size) { void __iomem *result; phys_addr = (phys_addr + PAGE_SIZE - 1) & PAGE_MASK; size = (size + PAGE_SIZE -1 ) & PAGE_MASK; result = ioremap_nocache(phys_addr, size); if (!result) printk("ioremap for %lx %lx failed\n", phys_addr, size); return result; } static int read_vector(void * base, int entry_num) { void __iomem *p; uint32_t val, i; p = base + entry_num * PCI_MSIX_ENTRY_SIZE; for (i = 0; i < 4; i ++) { val = readl(p); printk(" p %p val %x\n", p, val); p += 4; } return val; } static void write_vector(void *base, int entry_num, int new_vector) { void __iomem *p; uint32_t val; p = base + entry_num * PCI_MSIX_ENTRY_SIZE + 8; val = readl(p); printk("p %p val %x\n", p, val); val &= ~0xff; val |= (new_vector | ~0xff); writel(val, p); printk("Now write finished\n"); } static int __init ro_msi_init(void) { void __iomem * vaddr; if (!phys || (entry_nr == ~0UL)) { printk("No physical address or entry number specified\n"); return -EINVAL; } if (test_write && !newvec) { printk("new vector not specified for write test\n"); return -EINVAL; } printk("ro_msi init\n"); vaddr = test_setup(phys, size); if (!vaddr) { printk("Failed to setup the iomap\n"); return -EINVAL; } read_vector(vaddr, entry_nr); if (test_write) write_vector(vaddr, entry_nr, newvec); iounmap(vaddr); return 0; } static void __exit ro_msi_exit(void) { printk("ro msi exit\n"); } module_init(ro_msi_init); module_exit(ro_msi_exit);