diff --git a/api/api.cpp b/api/api.cpp index 27df598..57056c1 100644 --- a/api/api.cpp +++ b/api/api.cpp @@ -18,6 +18,9 @@ UltraSoundDevice::UltraSoundDevice() files[1] = open("/proc/usd_reg_1", O_RDWR, 0); bars[1]= mmap(NULL, 128 * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_SHARED, files[1], 0); + + files[2] = open("/proc/usd_reg_2", O_RDWR, 0); + bars[2]= mmap(NULL, 8 * 1024, PROT_READ | PROT_WRITE, MAP_SHARED, files[2], 0); } /*************************************************************************************************/ @@ -25,6 +28,7 @@ UltraSoundDevice::~UltraSoundDevice() { munmap(bars[0], 64 * 1024); munmap(bars[1], 128 * 1024 * 1024); + munmap(bars[2], 8 * 1024); for(int i = 0; i < BAR_NUM; i++) { diff --git a/api/api.h b/api/api.h index 6bdadb2..759a0f0 100644 --- a/api/api.h +++ b/api/api.h @@ -1,6 +1,6 @@ #include "stdint.h" -#define BAR_NUM 2 +#define BAR_NUM 3 #define DEV_NAME "usd_reg" class UltraSoundDevice diff --git a/usdpci.c b/usdpci.c index 8a7e42a..8d3bc77 100644 --- a/usdpci.c +++ b/usdpci.c @@ -58,6 +58,8 @@ static int usd_open_2(struct inode *inode, struct file *flip); static int usd_close_2(struct inode *inode, struct file *filp); static int usd_mmap_2(struct file *filp, struct vm_area_struct *vma); +static int create_dma_buffer(unsigned int bufcount); + /*************************************************************************************************/ static dev_t chrdev; static struct cdev cdev; @@ -67,7 +69,10 @@ static struct class *class = NULL; #define CLASS_NAME "usdpci" /*************************************************************************************************/ -#define TOTAL_BAR_NUM 2 +struct page** dma_pages = NULL; + +/*************************************************************************************************/ +#define TOTAL_BAR_NUM 3 struct bar_t{ unsigned long bar_addr; @@ -117,13 +122,11 @@ static int __init pcie_init(void) bars[1].chrdev_fops.release = usd_close_1; bars[1].bar_size = 128 * 1024 * 1024; - // bars[2].chrdev_fops = { - // .owner = THIS_MODULE, - // .open = usd_open_2, - // .mmap = usd_mmap_2, - // .release = usd_close_2 - // }; - // bars[2].bar_size = 4 * 1024; + bars[2].chrdev_fops.owner = THIS_MODULE; + bars[2].chrdev_fops.open = usd_open_2; + bars[2].chrdev_fops.mmap = usd_mmap_2; + bars[2].chrdev_fops.release = usd_close_2; + bars[2].bar_size = 8 * 1024; PRINT_ALERT("register driver success" ); @@ -256,11 +259,65 @@ static int usd_mmap_2(struct file *filp, struct vm_area_struct *vma) return 0; } +/*************************************************************************************************/ +static int create_dma_buffer(unsigned int bufcount) +{ + int i; + int bufidx = 0; + unsigned int gfp_mask = GFP_KERNEL | __GFP_DMA; + dma_addr_t bus_addr; + u8* bar2_data; + bar2_data = (u8*)bars[2].bar_ptr; + + + printk(KERN_ALERT "USDriver PCIe DMA buffer alloc request: %d pages\n", bufcount); + + if ( dma_pages != NULL ) + { + PRINT_ALERT("DMA buffer already exist! Strange!"); + } + + dma_pages = kmalloc(sizeof(struct page*) * bufcount, GFP_KERNEL); + if ( dma_pages == NULL ) { + PRINT_ALERT("DMA dma_pages alloc failed!" ); + return 1; + } + + for ( bufidx = 0; bufidx < bufcount; bufidx++ ) { + void __iomem *maddr = NULL; + struct page *pages = alloc_page(gfp_mask); + if ( pages == NULL ) { + PRINT_ALERT("DMA buffer alloc failed!" ); + return 1; + } + maddr = page_address(pages); + dma_pages[bufidx] = pages; + + bus_addr = pci_map_single(pcidev, maddr, PAGE_SIZE, DMA_BIDIRECTIONAL); + printk(KERN_ALERT "%d -- [%d] -- >>%lx\n", PAGE_SIZE, bufidx, bus_addr); + + iowrite32(bus_addr >> 32, &bar2_data[bufidx * 8]); + wmb(); + + iowrite32(bus_addr, &bar2_data[bufidx * 8 + 4]); + wmb(); + + if ( pci_dma_mapping_error(pcidev, bus_addr) ) { + return 1; + } + } + + PRINT_ALERT("DMA buffer alloc successful"); + return 0; +} + /*************************************************************************************************/ static int __init pcie_probe (struct pci_dev *dev, const struct pci_device_id *id) { int rc = 0; + pcidev = dev; + rc = pci_enable_device(dev); if(rc) { @@ -294,6 +351,7 @@ static int __init pcie_probe (struct pci_dev *dev, const struct pci_device_id *i goto probe_fail_release_region; } + /***************BAR 1***********************/ if(!(pci_resource_flags(dev, 1) & IORESOURCE_MEM)) { printk(KERN_ERR "USDriver PCIe driver incorrect BAR configuration\n" ); @@ -319,18 +377,33 @@ static int __init pcie_probe (struct pci_dev *dev, const struct pci_device_id *i goto probe_fail_release_region; } - pci_set_master(dev); + /*************************BAR2***************************************/ + if(!(pci_resource_flags(dev, 2) & IORESOURCE_MEM)) + { + printk(KERN_ERR "USDriver PCIe driver incorrect BAR configuration\n" ); + rc = 1; + goto probe_fail; + } - void * temp = kmalloc(1024 * 1024 * 4, GFP_KERNEL); - u64 phs = virt_to_phys(temp); - memset(temp, 0, 1024 * 1024 * 4); - int i = 0; - u32* counter = (u32*)temp; - for ( ; i < 256 * 1024; i++) - counter[i] = i; - bar0_data[0x82] = phs >> 32; - bar0_data[0x83] = phs; - bar0_data[0x2002] = 0x8000; + bars[2].bar_addr = pci_resource_start(dev, 2); + rc = pci_request_region(dev, 2, "bar2"); + if(rc) + { + PRINT_ALERT("driver pci_request_regions bar2 failed"); + goto probe_fail; + } + + bars[2].bar_ptr = pci_iomap(dev, 2, bars[2].bar_size); + u32* bar2_data = (u32*)bars[2].bar_ptr; + + if(bar2_data == 0) + { + PRINT_ALERT("driver failed to map BAR 2"); + rc = 1; + goto probe_fail_release_region; + } + + pci_set_master(dev); printk(KERN_ALERT "-----------------------------------\n"); printk(KERN_ALERT "BAR0 reg 0 = 0x%x\n", ioread32(bar0_data)); @@ -338,8 +411,12 @@ static int __init pcie_probe (struct pci_dev *dev, const struct pci_device_id *i printk(KERN_ALERT "BAR1 reg 0 = 0x%x\n", ioread32(bar1_data)); printk(KERN_ALERT "-----------------------------------\n"); + create_dma_buffer(2); + return 0; + map_error_handling: + PRINT_ALERT("DMA ERR"); probe_fail_release_region: pci_release_regions(dev); probe_fail: @@ -358,6 +435,7 @@ static void pcie_remove(struct pci_dev *dev) pci_iounmap(dev, bars[0].bar_ptr); pci_iounmap(dev, bars[1].bar_ptr); + pci_iounmap(dev, bars[2].bar_ptr); PRINT_ALERT("IOunmap"); pci_release_regions(dev);