📄 hpidrv.c
字号:
#ifndef __KERNEL__#define __KERNEL__#endif#ifndef MODULE#define MODULE#endif#include<linux/module.h>#include<linux/kernel.h>#include<linux/init.h>#include <linux/slab.h>#ifndef pgprot_noncachedstatic inline pgprot_t pgprot_noncached(pgprot_t _prot){ unsigned long prot = pgprot_val(_prot); #if defined(__i386__) || defined(__x86_64__) /* On PPro and successors, PCD alone doesn't always mean uncached because of interactions with the MTRRs. PCD | PWT means definitely uncached. */ if (boot_cpu_data.x86 > 3) prot |= _PAGE_PCD | _PAGE_PWT;#elif defined(__powerpc__) prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;#elif defined(__mc68000__)#ifdef SUN3_PAGE_NOCACHE if (MMU_IS_SUN3) prot |= SUN3_PAGE_NOCACHE; else#endif if (MMU_IS_851 || MMU_IS_030) prot |= _PAGE_NOCACHE030; /* Use no-cache mode, serialized */ else if (MMU_IS_040 || MMU_IS_060) prot = (prot & _CACHEMASK040) | _PAGE_NOCACHE_S;#endif return __pgprot(prot);} #endif /* !pgprot_noncached */#ifdef CONFIG_SMP#define __SMP__#endif#include<linux/config.h>#include<linux/sched.h>#include<linux/mm.h>#include<linux/mman.h>#include<linux/fs.h>#include<asm/uaccess.h>//#include<asm-arm/arch-at91rm9200/AT91RM9200.h>#include<asm/pgtable.h>#include<asm/hardware.h>#define DEVICE_NAME "at91_HPI"#define HPIRAW_MINOR 1#define L_PTE_WRITE (1 << 5)#define L_PTE_DIRTY (1 << 7)#define MAPLEN (4096*4096)static int HPI_major = 0;static int Device_Open = 0;static int hpi_open(struct inode *inode,struct file *filp);static int hpi_release(struct inode *inode,struct file *filp);static int hpi_mmap(struct file *filp,struct vm_area_struct *vma);void hpi_vopen(struct vm_area_struct *vma);void hpi_vclose(struct vm_area_struct *vma);struct file_operations hpi_fops={ open: hpi_open, release: hpi_release, mmap: hpi_mmap,};static struct vm_operations_struct hpi_vm_ops={ open: hpi_vopen, close: hpi_vclose,};static int hpi_open(struct inode *inode,struct file *filp){ printk(KERN_INFO"device_open (%p,%p)\n",inode,filp); if(Device_Open) return -EBUSY; Device_Open++; MOD_INC_USE_COUNT; return 0;}static int hpi_release(struct inode *inode,struct file *filp){ printk(KERN_INFO"device_release (%p,%p)\n",inode,filp); Device_Open--; MOD_DEC_USE_COUNT; return 0;}static int hpi_mmap(struct file *filp,struct vm_area_struct *vma){ unsigned long offset = vma->vm_pgoff<<PAGE_SHIFT; unsigned long size = vma->vm_end - vma->vm_start; if (offset & ~PAGE_MASK) { printk("offset not aligned: %ld\n", offset); return -ENXIO; } if (size>MAPLEN) { printk("size too big\n"); return(-ENXIO); } vma->vm_flags |=VM_RESERVED; vma->vm_flags |=VM_WRITE; if(remap_page_range(vma->vm_start,((0x40000000)),vma->vm_end-vma->vm_start,(__pgprot(pgprot_val(pgprot_noncached(vma->vm_page_prot))|(L_PTE_WRITE|L_PTE_DIRTY)))))// if(remap_page_range(vma->vm_start,((0x40000000)),vma->vm_end-vma->vm_start,(__pgprot(pgprot_val(pgprot_noncached(vma->vm_page_prot))))))// if(remap_page_range(vma->vm_start,((0x40000000)),vma->vm_end-vma->vm_start,vma->vm_page_prot)) return -EAGAIN; if (offset == 0) { vma->vm_ops = &hpi_vm_ops; /* call the open routine to increment the usage count */ hpi_vopen(vma); }else { printk("offset out of range\n"); return -ENXIO; } return(0);}void hpi_vopen(struct vm_area_struct *vma){ printk(KERN_NOTICE"HPI VMA open,vit %lx,phys %lx \n",vma->vm_start,vma->vm_pgoff<<PAGE_SHIFT); MOD_INC_USE_COUNT;}void hpi_vclose(struct vm_area_struct *vma){ printk(KERN_NOTICE"HPI VMA close.\n"); MOD_DEC_USE_COUNT;}/*#ifdef CONFIG_DEVFS_FSstatic devfs_handle_t devfs_HPI_dir,devfs_HPIraw;#endif*/static int __init AT91_HPI_init(void){ // AT91PS_SYS->EBI_SMC2_CSR[3]=0x00004083; int ret; ret = register_chrdev(0,DEVICE_NAME,&hpi_fops); if(ret<0){ printk(DEVICE_NAME"can't get major number\n"); return ret; } HPI_major =ret; /*#ifdef CONFIG_DEVFS_FS devfs_HPI_dir = devfs_mk_dir(NULL,"hpi",NULL); devfs_HPIraw = devfs_register(devfs_HPI_dir,"0",DEVFS_FL_DEFAULT,HPI_major,HPIRAW_MINOR,S_IFCHR | S_IRUSR |S_IWUSR, &hpi_fops,NULL);#endif*/ printk(DEVICE_NAME"initialized\n"); return 0;}static void __exit AT91_HPI_exit(void){/*#ifdef CONFIG_DEVFS_FS devfs_unregister(devfs_HPIraw); devfs_unregister(devfs_HPI_dir);#endif*/ unregister_chrdev(HPI_major,DEVICE_NAME); printk(DEVICE_NAME"clearnuped\n");}module_init(AT91_HPI_init);module_exit(AT91_HPI_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("WYH<njust_wyh@hotmail.com>");MODULE_DESCRIPTION("hpi driver for AT91RM9200 & TMS320VC5402");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -