📄 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 0xff#define MEMSIZE 0x3fff#define PCI_MAJOR 0#define VENDOR 0x10b5#define DEVICE 0x9054int PCI_major = PCI_MAJOR;//DECLARE_WAIT_QUEUE_HEAD(wq);//int wake = 0;//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; u32 mem, io; u8 irq, pin; 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);// pci_read_config_dword(mydev,PCI_BASE_ADDRESS_1,&io_addr);// pci_read_config_byte(mydev,PCI_INTERRUPT_LINE,&irq);// pci_read_config_byte(mydev,PCI_INTERRUPT_PIN,&pin); pci_read_config_dword(mydev,PCI_BASE_ADDRESS_2,&mem_addr); pci_read_config_dword(mydev,PCI_BASE_ADDRESS_1,&io_addr); flag = mem_addr; if(flag&0x0001) mem_addr &= (~0x00000003);//This port is I/O else mem_addr &= (~0x0000000f); flag = io_addr; if(flag&0x0001) io_addr &= (~0x00000003);//This port is I/O else io_addr &= (~0x0000000f); printk("<1> The device has been finded.\nMenAddr=0x%x IoAddr=0x%x Irq=0x%d Pin=0x%x mem=0x%x io=0x%x\n",mem_addr,io_addr,irq,pin,mem,io); // mem &= (~0x0000000f); mem = ioremap(0xec014000,0xff);// writel(0xffffffff, mem); printk("The range is %x\n",readl(mem)); 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); // writel(0xffff0000,Device->MemVirAddr);// printk("The range is 0x%x\n",readl(Device->MemVirAddr));// printk("The range is 0x%x\n",readl(Device->MemVirAddr+4));// printk("The range is 0x%x\n",readl(Device->MemVirAddr+8));// printk("The range is 0x%x\n",readl(Device->MemVirAddr+12));// printk("The range is 0x%x\n",readl(Device->MemVirAddr+0x2000)); int i; for(i=0;i<64;i++) { printk("%d: 0x%x ",i,readl(Device->MemVirAddr+i*4)); } 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 Read 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; struct PCI_device *dev =filp->private_data; u8 *buffer; u8 *pt; unsigned long baseaddr; int i; buffer = kmalloc(count,GFP_KERNEL); if(buffer == NULL) { printk("<1> Allocate Mem in Read function failed.\n"); return(-ENOMEM); } memset(buffer,0,count); baseaddr = dev->MemVirAddr; pt = buffer; for(i=0; i<count; i++, pt++) { *pt = (u8)(readl(baseaddr+(i/4)) & 0xff);// *pt = readb(baseaddr+i); printk("%d: 0x%x ", i, *pt); } printk("\n"); copy_to_user(buf,buffer,count); 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; struct PCI_device *dev =filp->private_data; u8 *buffer; u32 *pt; unsigned long baseaddr; int i; buffer = kmalloc(count,GFP_KERNEL); if(buffer == NULL) { printk("<1> Allocate Mem in Read function failed.\n"); return(-ENOMEM); } memset(buffer,0,count); copy_from_user(buffer,buf,count); baseaddr = dev->MemVirAddr; pt = (u32*)buffer; for(i=0; i<count; i+=4, pt++) { printk("%d: 0x%x ", i, *pt); writel(*pt, baseaddr+i); } printk("\n"); 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,*/};/****************************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"); 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 + -