📄 driver.c
字号:
#include <linux/unistd.h>#include <linux/module.h>#if defined(CONFIG_SMP)#define __SMP__#endif#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 "testpcidevice"#define IOSIZE 64#define PCI_MAJOR 0#define VENDOR 0x10e8#define DEVICE 0x4750int PCI_major = PCI_MAJOR;int succ = 1;struct DMA_data { dma_addr_t PciAddr; unsigned int Count; void *Handle; };struct PCI_device { const char *Name; unsigned long BaseAddr; 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 *);static int PCI_init(void){ int res; struct pci_dev *mydev; u32 pci_addr,flag,memaddr; 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"); kfree(Device); return(-ENODEV); } pci_read_config_dword(mydev,PCI_BASE_ADDRESS_0,&pci_addr); pci_read_config_byte(mydev,PCI_INTERRUPT_LINE,&irq); flag = pci_addr; if(flag&0x0001) pci_addr &= (~0x0003);//This port is I/O else pci_addr &= (~0x000f); printk("<1> The device has been finded.Addr=%x Irq=%d\n",pci_addr,irq); Device->Name = PCINAME; Device->BaseAddr =pci_addr; Device->IoSize = IOSIZE; Device->IrqNum = irq; Device->PciMajor = PCI_major; Device->MyDev = mydev; /* res = check_region(Device->BaseAddr,Device->IoSize); if(res < 0){ printk("<1> Check I/O port failed.\n"); return res; }*/ if(request_region(Device->BaseAddr,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"); return 0;}MCSRwrite(unsigned long flag,unsigned long addr){ unsigned long init; init = inl(addr); init = init | flag; outl(init,addr);}/**********************Function interrupt****************************/void PCI_interrupt(int irq,void *dev_id,struct pt_regs *regs){ struct PCI_device *dev = dev_id; u32 flag,MCSR; if(dev->Name == PCINAME) { printk("<1> The IRQ roution start execute\n"); flag = inl(dev->BaseAddr + 0x38); printk("<1> The INT flag is %x\n",flag); MCSR = inl(dev->BaseAddr + 0x3c); printk("<1> The MCSR register is : %x\n",MCSR); MCSR = inl(dev->BaseAddr + 0x3c); printk("<1> The MCSR register is : %x\n",MCSR); if(flag & 0x00080000) { printk("<1> The DMA transfer has completed.\n"); flag |=0x00080000; outl(flag,dev->BaseAddr + 0x38); pci_unmap_single(dev->MyDev,dev->DmaData.PciAddr, dev->DmaData.Count,PCI_DMA_TODEVICE); kfree(dev->DmaData.Handle); MCSR = inl(dev->BaseAddr + 0x3c); printk("<1> The MCSR register is : %x\n",MCSR); } 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){ int i; u8 data; char offset; copy_from_user(&offset,buf,1); printk("The buf value is : %x\n",offset); for(i=0;i<count;i++) { data = inb(Device->BaseAddr + offset + i); copy_to_user(buf,&data,1); buf++; } printk("<1> PCI_read has execution\n");}/***************************PCI write************************************/ssize_t PCI_write(struct file *filp,char *buf,size_t count,loff_t *offp){ unsigned long Size = count; unsigned long Start = 0x00004000; dma_addr_t Busaddr; u32 *buffer,MCSR; 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(Device->MyDev,buffer, count,PCI_DMA_TODEVICE);// outl(Int,Device->BaseAddr + 0x38);//INTCSR// MCSRwrite(Fifo,Device->BaseAddr + 0x3c);//MCSR outl(Busaddr,Device->BaseAddr + 0x2c);//MRAR outl(Size,Device->BaseAddr + 0x30);//MRTC MCSRwrite(Start,Device->BaseAddr + 0x3c); MCSR = inb(Device->BaseAddr + 0x3c); printk("<1> start MCSR is %x\n",MCSR); Device->DmaData.PciAddr = Busaddr; Device->DmaData.Count = count; Device->DmaData.Handle = buffer; printk("<1> The vir address is :%x\nThe phy address is :%x\n",buffer,Busaddr); return count;}int PCI_ioctl (struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg){ unsigned long Int = 0x00008000; unsigned long Fifo = 0x00003000; unsigned long Ffre = 0x02000000; struct PCI_device *dev = filp->private_data; unsigned long fifo; switch(cmd){ case 1: { outl(Int,dev->BaseAddr + 0x38);//INTCSR MCSRwrite(Ffre,dev->BaseAddr + 0x3c); MCSRwrite(Fifo,dev->BaseAddr + 0x3c);//MCSR fifo = inl(dev->BaseAddr + 0x3c); printk("<1> The FIFO has been reseted,value=%x\n",fifo); 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"); succ = 0; } else printk("<1> MYPCI initializition success.\n"); return 0;}/****************************Module release********************************/void cleanup_module(void){ unregister_chrdev(PCI_major,PCINAME); release_region(Device->BaseAddr,Device->IoSize); free_irq(Device->IrqNum,Device); if(succ) kfree(Device); printk("<1> MYPCI release success.\n");}MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -