⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 driver.c

📁 Windows设备驱动程序设计 (*.ppt) intoduce about how to develop the windows 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 + -