commit 8a9ed86fe103af80e7ef17408e52be3edcd6ca4e
Author: sono <sono.hasis.com>
Date:   Wed Jul 29 19:44:32 2020 +0430

    First

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e642811
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+test
+*.order
+*.symvers
+*.ko
+*.mod
+*.mod.*
+*.o
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..515c555
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+# If KERNELRELEASE is defined, we've been invoked from the
+# kernel build system and can use its language.
+# Otherwise we were called directly from the command
+# line; invoke the kernel build system.
+
+ifneq ($(KERNELRELEASE),)
+	obj-m := usdpci.o
+else
+	KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+	PWD := $(shell pwd)
+
+default:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+clean:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
+endif
+
+install:
+	sudo cp ./usdpci.ko /lib/modules/`uname -r`/
+	sudo depmod -a
+	sudo cp usdpci.rules /etc/udev/rules.d/
diff --git a/run b/run
new file mode 100755
index 0000000..916188e
--- /dev/null
+++ b/run
@@ -0,0 +1,7 @@
+sudo rmmod usdpci
+make clean
+make
+sudo make install
+sudo insmod usdpci.ko
+dmesg
+echo hello
diff --git a/usdpci.c b/usdpci.c
new file mode 100644
index 0000000..c53406c
--- /dev/null
+++ b/usdpci.c
@@ -0,0 +1,322 @@
+#include <linux/init.h>
+
+#include <linux/module.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/interrupt.h>
+
+#include <linux/highmem.h>
+
+#include <linux/spinlock.h>
+#include <linux/spinlock_types.h>
+
+#include <linux/fs.h>
+#include <linux/cdev.h>
+
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+#include <linux/poll.h>
+
+
+#define DMA_ADDR_OFFSET 32
+#define PRINT(A) printk(KERN_ALERT ">>>>> #A %x\n", A);
+
+MODULE_AUTHOR("Talaie");
+MODULE_LICENSE("Dual BSD/GPL");
+
+static struct pci_device_id pcie_ids[] =
+{
+    {PCI_DEVICE(0x10ee, 0x7024)},
+    {0, },
+};
+MODULE_DEVICE_TABLE(pci, pcie_ids);
+
+static irqreturn_t interrupt_handler(int irq, void *p);
+
+static struct pci_dev *pcidev = NULL;
+
+static unsigned int chrdev_major = 0;
+static unsigned int chrdev_minor = 0;
+
+static unsigned int ioctl_alloc_dma = 0;
+static unsigned int ioctl_refresh_link = 1;
+
+static unsigned long bar0_addr;
+static unsigned long bar0_size = 4*1024; //TODO ask about size. 4KB
+static void* bar0_ptr;
+static unsigned int irq;
+
+
+struct page** dma_pages = NULL;
+unsigned int dma_pages_count = 0;
+void* dma_addr = NULL;
+unsigned long mmap_buffersize = 4 * 1024; //4KB
+
+
+
+/*************************************************************************************************/
+static int __init pcie_init(void);
+static int chrdev_init(void);
+static int usd_open(struct inode *inode, struct file *flip);
+static int usd_mmap(struct file *filp, struct vm_area_struct *vma);
+static unsigned int usd_poll (struct file *filp, poll_table *wait);
+static int __init pcie_probe (struct pci_dev *dev, const struct pci_device_id *id);
+static void pcie_remove(struct pci_dev *dev);
+static void __exit pcie_exit(void);
+
+/*************************************************************************************************/
+static dev_t chrdev;
+static struct cdev cdev;
+static struct class *class = NULL;
+
+#define DEV_NAME  "usd_reg"
+
+struct file_operations chrdev_fops = 
+{
+    .owner = THIS_MODULE,
+    .open = usd_open,
+    .mmap = usd_mmap,
+    .poll = usd_poll
+};
+
+/*************************************************************************************************/
+static struct  pci_driver pci_driver =
+{
+  .name = "usdpci",
+  .id_table = pcie_ids,
+	.probe = pcie_probe,
+	.remove = __exit_p(pcie_remove),
+};
+
+/*************************************************************************************************/
+#define PRINT_PREFIX  "USDriver PCIe"
+#define PRINT_ALERT(STR)  printk(KERN_ALERT "%s %s\n", PRINT_PREFIX, STR)
+#define PRINT_WARN(STR)  printk(KERN_WARN "%s %s\n", PRINT_PREFIX, STR)
+
+/*************************************************************************************************/
+static int __init pcie_init(void)
+{
+  int res = 0;
+	PRINT_ALERT("driver initializing");
+
+	res = pci_register_driver(&pci_driver);
+	if ( res ) {
+		PRINT_ALERT("device not found");
+		return res;
+	}
+
+	PRINT_ALERT("register driver success" );
+
+	res = chrdev_init();
+	if ( res ) {
+		PRINT_ALERT("character device file creation failed");
+		return res;
+	}
+
+	PRINT_ALERT("driver loaded");
+	return res;
+}
+
+/*************************************************************************************************/
+static int chrdev_init(void)
+{
+  PRINT_ALERT("chrdev_init");
+
+  int res = 0;
+  struct device *device = NULL;
+
+  res = alloc_chrdev_region(&chrdev, 0, 1, DEV_NAME);
+
+  if(res < 0)
+  {
+      return -1;
+  }
+
+  cdev_init(&cdev, &chrdev_fops);
+  res = cdev_add(&cdev, chrdev, 1);
+
+	if (res)
+  {
+		unregister_chrdev_region(chrdev, 1);
+		return res;
+	}
+
+	class = class_create(THIS_MODULE, "usdpci");
+	device = device_create(class, NULL, 0, NULL, "usd_regs0");
+
+  return 0;
+}
+
+/*************************************************************************************************/
+static int usd_open(struct inode *inode, struct file *flip)
+{
+  return 0;
+}
+
+/*************************************************************************************************/
+static int usd_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+  return 0;
+}
+
+/*************************************************************************************************/
+static unsigned int usd_poll (struct file *filp, poll_table *wait) 
+{
+  return 0;
+}
+
+/*************************************************************************************************/
+static int __init pcie_probe (struct pci_dev *dev, const struct pci_device_id *id)
+{   
+  bar0_ptr = pci_iomap(dev, 0, 64 * 1024);//4KB
+  u8* bar0_data = (u8*)bar0_ptr;
+  int rc = 0;
+
+  if(bar0_data == 0)
+  {
+    PRINT_ALERT("driver failed to map BAR 0");
+    rc = 1;
+    goto probe_fail_release_region;
+  }
+
+  pci_set_master(dev);
+
+  // int i = 0;
+  // for( i = 0; i < 1; i++)
+  // {
+    // int r32 = ioread32(&bar0_data[i*4]);
+    // printk(KERN_ALERT "Read: %x (%d)\n", r32, i);
+  // }
+
+  iowrite32(0x45670000, &bar0_data[0x8018]);
+  int r32 = ioread32(&bar0_data[0x8018]);
+  printk(KERN_ALERT "Read: %x\n", r32);
+  return 0;
+
+  probe_fail_release_region:
+    pci_release_regions(dev);
+  probe_fail:
+    pci_disable_device(dev);
+  probe_fail_enable:
+    return rc;
+}
+
+/*************************************************************************************************/
+static void pcie_remove(struct pci_dev *dev)
+{
+  PRINT_ALERT("remove driver");
+
+	int i;
+	u8* bar0_data;
+	bar0_data = (u8*)bar0_ptr;
+	for ( i = 0; i < dma_pages_count; i++ ) {
+		pci_unmap_single(pcidev, bar0_data[DMA_ADDR_OFFSET + 4*i], PAGE_SIZE, DMA_BIDIRECTIONAL);
+		__free_page(dma_pages[i]);
+	}
+	if (dma_pages != NULL) kfree(dma_pages);
+	printk(KERN_ALERT "Freed DMA pages\n");
+
+	pci_clear_master(dev);
+	printk(KERN_ALERT "Cleared PCIe master\n");
+
+	pci_iounmap(dev, bar0_ptr);
+	printk(KERN_ALERT "IOunmap\n");
+
+	pci_release_regions(dev);
+	printk(KERN_ALERT "pci_release_regions\n");
+
+	pci_disable_device(dev);
+	printk(KERN_ALERT "pci_disable_device\n");
+}
+
+/*************************************************************************************************/
+static void __exit pcie_exit(void)
+{
+	int i;
+	u8* bar0_data;
+	bar0_data = (u8*)bar0_ptr;
+	
+	printk(KERN_ALERT "USDriver PCIe driver unloading\n");
+
+	printk(KERN_ALERT "USDriver PCIe driver unregistering\n");
+	pci_unregister_driver(&pci_driver);
+
+	printk(KERN_ALERT "USDriver PCIe unregister_chrdev_region\n");
+	unregister_chrdev_region(chrdev, 1);
+
+	printk(KERN_ALERT "USDriver PCIe cdev_del\n");
+	cdev_del(&cdev);
+	
+	printk(KERN_ALERT "USDriver PCIe device_destroy\n");
+	device_destroy(class, chrdev);
+	
+	printk(KERN_ALERT "USDriver PCIe class_destroy\n");
+	class_destroy(class);
+	printk(KERN_ALERT "USDriver PCIe driver unloaded\n");
+}
+
+module_init(pcie_init);
+module_exit(pcie_exit);
+
+/*************************************************************************************************/
+
+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* bar0_data;
+    bar0_data = (u8*)bar0_ptr;
+
+    printk(KERN_ALERT "USDriver DMA buffer alloc request: %d pages\n", bufcount);
+    if( dma_pages != NULL)
+    {
+        printk(KERN_ALERT "USDriver DMA buffer already exist! Strange!\n");
+    }
+
+    dma_pages = kmalloc(4*1024*1024 * bufcount, GFP_KERNEL);
+    if(dma_pages == NULL)
+    {
+        printk(KERN_ERR "USDriver DMA dma_pages alloc failed! \n" );
+        return 1;
+    }
+
+    for(bufidx = 0; bufidx <  bufcount; bufidx++)
+    {
+        void __iomem *maddr = NULL;
+        struct page *pages = alloc_pages(gfp_mask, 10);
+        if(pages == NULL)
+        {
+            printk(KERN_ERR "USDriver DMA buffer alloc failed! \n" );
+			return 1;
+        }
+        maddr = page_address(pages);
+        dma_pages[bufidx] = pages;
+
+        bus_addr = pci_map_single(pcidev, maddr,  1024 * PAGE_SIZE, DMA_BIDIRECTIONAL);
+		printk(KERN_ALERT ">>>>>[%d]    0x%x\n", bufidx, bus_addr);
+        iowrite32(bus_addr, &bar0_data[DMA_ADDR_OFFSET + (4 * bufidx)]);
+        wmb();
+        if(pci_dma_mapping_error(pcidev, bus_addr))
+        {
+            return 1;
+        }
+    }
+    dma_pages_count = bufcount;
+
+    printk(KERN_ALERT "USDriver DMA buffer alloc successful\n");
+	return 0;
+}
+
+
+/*************************************************************************************************/
+/*************************************************************************************************/
+/*************************************************************************************************/
+/*************************************************************************************************/
+/*************************************************************************************************/
+/*************************************************************************************************/
+/*************************************************************************************************/
+/*************************************************************************************************/
diff --git a/usdpci.rules b/usdpci.rules
new file mode 100644
index 0000000..93ead97
--- /dev/null
+++ b/usdpci.rules
@@ -0,0 +1,2 @@
+ACTION=="add",SUBSYSTEM=="pci",ATTR{vendor}=="0x10ee", ATTR{device}="0x0007", RUN+="/sbin/modprobe uscpci"
+KERNEL=="usd_regs0",MODE="666"