📄 driver.c
字号:
#include <linux/unistd.h>#include <linux/module.h>#if defined(CONFIG_SMP)#define __SMP__#endif#include <linux/wait.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/mm.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/types.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/fcntl.h>#define PCINAME "09449device"#define IOSIZE 8#define MEMSIZE 0X8000#define PCI_MAJOR 0#define VENDOR 0x12BE#define DEVICE 0x3042DECLARE_WAIT_QUEUE_HEAD(wq);int wake = 0;int PCI_major = PCI_MAJOR;struct DMA_data{ dma_addr_t PciAddr; int Count; void *Handle;};struct PCI_device { const char *Name; unsigned long MemVirAddr; unsigned long MemPhyAddr; unsigned int MemSize; unsigned long IoAddr; unsigned int IoSize; unsigned int IrqNum; unsigned int PciMajor; struct pci_dev *MyDev; struct DMA_data DmaData;} *Device;void PCI_interrupt(int ,void *,struct pt_regs *);Regwrite(unsigned long flag,unsigned long addr){ unsigned long init; init = readl(addr); init = init | flag; writel(init,addr);}static int PCI_init(void){ int res; struct pci_dev *mydev; u32 mem_addr,io_addr,flag; u8 irq; Device = kmalloc(sizeof(struct PCI_device),GFP_KERNEL); if(Device == NULL) { printk(" KERN_ALERT allocate device memory failed.\n"); return(-ENOMEM); } memset(Device,0,sizeof(struct PCI_device)); mydev = pci_find_device(VENDOR,DEVICE,NULL); if(mydev == NULL){ printk("<1> Find the device failed.\n"); return(-ENODEV); } pci_read_config_dword(mydev,PCI_BASE_ADDRESS_0,&mem_addr); pci_read_config_dword(mydev,PCI_BASE_ADDRESS_1,&io_addr); pci_read_config_byte(mydev,PCI_INTERRUPT_LINE,&irq); flag = mem_addr; if(flag&0x0001) mem_addr &= (~0x0003);//This port is I/O else mem_addr &= (~0x000f); flag = io_addr; if(flag&0x0001) io_addr &= (~0x0003);//This port is I/O else io_addr &= (~0x000f); printk("<1> The device has been finded.\nMenAddr=%x IoAddr=%x Irq=%d\n",mem_addr,io_addr,irq); Device->Name = PCINAME; Device->MemPhyAddr =mem_addr; Device->IoAddr =io_addr; Device->MemSize = MEMSIZE; Device->IoSize = IOSIZE; Device->IrqNum = irq; Device->PciMajor = PCI_major; Device->MyDev = mydev; if(check_mem_region(Device->MemPhyAddr,Device->MemSize)) {printk("<1> Requested MEM already in use.\n"); return -EBUSY; } request_mem_region(Device->MemPhyAddr,Device->MemSize,Device->Name); printk("<1> Request MEM success.\n"); if(request_region(Device->IoAddr,Device->IoSize,Device->Name) != NULL) printk("<1> Request I/O port success.\n"); else {printk("<1> Request I/O port failed.\n"); return(-1); } res = request_irq(Device->IrqNum,PCI_interrupt,SA_SHIRQ|SA_INTERRUPT,Device->Name,Device); if(res < 0){ printk("<1> Request IRP feiled.\n"); return res; } printk("<1> Request IRO success.\n"); Device->MemVirAddr = (long)ioremap(Device->MemPhyAddr,Device->MemSize); printk("<1> The vir addr is %x\n",Device->MemVirAddr); return 0;}/**********************Function interrupt****************************/void PCI_interrupt(int irq,void *dev_id,struct pt_regs *regs){ struct PCI_device *dev = dev_id; u32 rw,flag; if(dev->Name == PCINAME) {// printk("<1> The IRQ roution start execute\n"); flag = readl(dev->MemVirAddr + 0x04e4);// printk("<1> The INT flag is %x\n",flag); if(flag & 0x00000020) { flag |=0x00000020; Regwrite(flag,dev->MemVirAddr + 0x04e4); rw = readl(dev->MemVirAddr + 0x04bc); if(rw &= 1) { wake_up_interruptible(&wq); wake = 1; printk("<1> The DMA read has been completed.\n"); pci_unmap_single(dev->MyDev,dev->DmaData.PciAddr, dev->DmaData.Count,PCI_DMA_TODEVICE); } else { printk("<1> The DMA write has completed.\n"); pci_unmap_single(dev->MyDev,dev->DmaData.PciAddr, dev->DmaData.Count,PCI_DMA_TODEVICE); kfree(dev->DmaData.Handle); } }// else printk("<1> The DMA complete flag is not set.\n"); }}/*****************************PCI open**********************************/int PCI_open(struct inode *inode,struct file *filp){ filp->private_data = Device; MOD_INC_USE_COUNT; return 0;} /*****************************Functin PCI_release**************************/int PCI_release(struct inode *inode,struct file *filp){// struct PCI_device *dev = filp->private_data; MOD_DEC_USE_COUNT; return 0;}/*************************PCI read***************************************/ssize_t PCI_read(struct file *filp,char *buf,size_t count,loff_t *offp){ unsigned long Locaddr = 0x4000; unsigned long Start = 0x00000001; unsigned long Int = 0x00200000; struct PCI_device *dev =filp->private_data; dma_addr_t Busaddr; u32 *buffer; buffer = kmalloc(sizeof(u32) * (count/4),GFP_KERNEL); if(buffer == NULL) { printk("<1> Allocate Mem in Write function failed.\n"); return(-ENOMEM); } memset(buffer,0,sizeof(u32)*(count/4)); Busaddr = pci_map_single(dev->MyDev,buffer, count,PCI_DMA_TODEVICE); Regwrite(Int,dev->MemVirAddr + 0x04e4);//INT writel(Busaddr,dev->MemVirAddr + 0x04b4);//HOST writel(Locaddr,dev->MemVirAddr + 0x04b0);//LOCAL writel(count,dev->MemVirAddr + 0x04b8);//SIZE writel(Start,dev->MemVirAddr + 0x04bc);//START dev->DmaData.PciAddr = Busaddr; dev->DmaData.Count = count; dev->DmaData.Handle = buffer; wait_event_interruptible(wq,wake); printk("<1> The read routine has waked up\n"); copy_to_user(buf,buffer,count); kfree(dev->DmaData.Handle); wake = 0; return count;}/***************************PCI write************************************/ssize_t PCI_write(struct file *filp,char *buf,size_t count,loff_t *offp){ unsigned long Locaddr = 0x4000; unsigned long Start = 0x00000000; unsigned long Int = 0x00200000; struct PCI_device *dev =filp->private_data; dma_addr_t Busaddr; u32 *buffer; buffer = kmalloc(sizeof(u32) * (count/4),GFP_KERNEL); if(buffer == NULL) { printk("<1> Allocate Mem in Write function failed.\n"); return(-ENOMEM); } memset(buffer,0,sizeof(u32)*(count/4)); copy_from_user(buffer,buf,count); Busaddr = pci_map_single(dev->MyDev,buffer, count,PCI_DMA_TODEVICE); Regwrite(Int,dev->MemVirAddr + 0x04e4);//INT writel(Busaddr,dev->MemVirAddr + 0x04b4);//HOST writel(Locaddr,dev->MemVirAddr + 0x04b0);//LOCAL writel(count,dev->MemVirAddr + 0x04b8);//SIZE writel(Start,dev->MemVirAddr + 0x04bc);//START dev->DmaData.PciAddr = Busaddr; dev->DmaData.Count = count; dev->DmaData.Handle = buffer; return count;}//////////////////////////////IOCTL FUNCTION////////////////////////////////////int PCI_ioctl (struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg){ unsigned long Int; struct PCI_device *dev = filp->private_data; unsigned long fifo; switch(cmd){ case 1: { Int = readl(dev->MemVirAddr + 0x04e4); printk("<1> The INT value is :%x\n",Int); break; } case 2: { writel(0x00000001,dev->MemVirAddr + 0x04e0); writel(0x00000000,dev->MemVirAddr + 0x04e0); printk("<1> The system has been reseted.\n"); break; } default: printk("<1> The argument wrong!\n"); } }/**************************File operations define************************/struct file_operations PCI_fops = {// NULL,// NULL, read : PCI_read, //readwrite: PCI_write, //write// NULL, // NULL, //EMM_poll,ioctl: PCI_ioctl, //ioctl// NULL, open : PCI_open, //open // NULL,release: PCI_release, //release/* NULL, NULL, NULL, NULL, NULL, NULL, NULL,*/};int test_read(void)//test the I/O port function{ int i; u32 buf[6]; for(i=0;i<6;i++) { buf[i]=i; } for(i=0;i<6;i++) { outw(0x0034 + i*4,Device->IoAddr); buf[i]= inl(Device->IoAddr + 4); printk("<1> The No.%x Reg's Value is: %x\n",i,buf[i]); }} /****************************Module initialize******************************/int init_module(void){ int res; EXPORT_NO_SYMBOLS; res = register_chrdev(PCI_major,PCINAME,&PCI_fops); if(res < 0) { printk("<1> PCI device register failed.\n"); return res; } if(PCI_major == 0) PCI_major = res; if(PCI_init() < 0) printk("<1> PCI device initializition failed.\n"); else printk("<1> MYPCI initializition success.\n"); test_read(); return 0;}/****************************Module release********************************/void cleanup_module(void){ unregister_chrdev(PCI_major,PCINAME); release_mem_region(Device->MemPhyAddr,Device->MemSize); release_region(Device->IoAddr,Device->IoSize); free_irq(Device->IrqNum,Device); iounmap((void*)Device->MemVirAddr); printk("<1> MYPCI release success.\n");}MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -