|
源码如下:
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> //#include <linux/slab.h> //#include <linux/completion.h> //#include <linux/poll.h>
//#include <asm/hardware.h> #include <asm/irq.h> #include <asm/uaccess.h> #include <asm/semaphore.h> #include <errno.h> //*************************** #ifndef CONFIG_PCI #define CONFIG_PCI #endif #include <linux/pci.h> /* 预定义所需变量 */ #define jmk_VendorID 0x104c #define jmk_DeviceID 0xa106
unsigned int jmk_major=0; struct pci_dev *jmkdev=NULL; /* 定义卡可用资源区域 */ unsigned long base0start=0,base0len=0; unsigned long base1start=0,base1len=0; unsigned long base2start=0,base2len=0; unsigned long offset=0,step=0; unsigned long i=0;//测试用作计数 void *iomembase=NULL; // 这是2.4后的接口定义 /* 读取数据协议base0 buf[0] 要读取数据区域(0:mem 2:io) buf[1] 要读取的数据类型(0:byte 1jmktest:word 2:dword) buf[2] 要读取的数据起始地址偏移量 buf[3] 地址递增步长 count 要读字节数 */ void jmk_read_base0_dword(unsigned long *buf,size_t count) { /* 获取参数 */ offset=buf[2]; step=buf[3]; /* 读取数据 */ for(i=0;i<count;i++) { //memcpy_fromio(buf,iomembase+offset,count); buf[i]=readl(iomembase+offset); offset+=step; } return; } /* 读取数据协议base2 buf[0] 要读取数据区域(0:mem 2:io) buf[1] 要读取的数据起始地址偏移量 */ void jmk_read_base2_dword(unsigned long *buf) { /* 获取参数 */ offset=buf[1]; /* 读取数据 */ buf[0]=inl(base2start+offset); return; } static int jmk_read(struct file *file, unsigned long *buf, size_t count, loff_t *offset) { /* 取参数 */
switch(buf[0]) { case 0: switch(buf[1]) { case 0: break; case 1: break; case 2: jmk_read_base0_dword(buf,count); //printk("recv base0 cmd!\n"); break; default: count=-1; break; } break; case 1: //printk("recv base1 cmd!\n"); break; case 2: jmk_read_base2_dword(buf); //printk("recv base2 cmd!\n"); break; default: //printk("recv default cmd!\n"); count=-1; break; }
return count; }
/* 写入数据协议base0 buf[0] 要写入数据区域(0:mem 2:io) buf[1] 要写入的数据类型(0:byte 1jmktest:word 2:dword) buf[2] 要写入的数据起始地址偏移量 buf[3] 地址递增步长 buf[4] 写入数据的起始地址 count 要读字节数 */ void jmk_write_base0_dword(unsigned long *buf,size_t count) { /* 获取参数 */ offset=buf[2]; step=buf[3]; /* 写入数据 */ for(i=0;i<count;i++) { writel(buf[i+4],iomembase+offset); offset+=step; } return; } /* 写入数据协议base2 buf[0] 要写入数据区域(0:mem 2:io) buf[1] 要写入的数据起始地址偏移量 buf[2] 写入数据的起始地址 */ void jmk_write_base2_dword(unsigned long *buf) { /* 获取参数 */ offset=buf[1]; /* 写入数据 */ outl(buf[2],base2start+offset); return; } static int jmk_write(struct file *file, unsigned long *buf, size_t count, loff_t *offset) { /* 取参数 */
switch(buf[0]) { case 0: switch(buf[1]) { case 0: break; case 1: break; case 2: jmk_write_base0_dword(buf,count); // printk("recv base0 cmd!\n"); break; default: count=-1; break; } break; case 1: //printk("recv base1 cmd!\n"); break; case 2: jmk_write_base2_dword(buf); //printk("recv base2 cmd!\n"); break; default: //printk("recv default cmd!\n"); count=-1; break; }
return count; } static int jmk_open(struct inode *inode,struct file *file ) { MOD_INC_USE_COUNT; return 0; } // 在2.4中要一个返回值发现加密卡 static int jmk_release(struct inode *inode, struct file *file) { MOD_DEC_USE_COUNT; return 0; }
static struct file_operations jmk_fops = { open: jmk_open, read: jmk_read, write: jmk_write, release: jmk_release, owner: THIS_MODULE, }; //发现卡 //********************************************** /* 主模块开始256 */ int init_module(void) { int result; unsigned long endsrc=0; result = register_chrdev(0,"jmkdev",&jmk_fops); if(result<0) { printk("jmk : can't get major number"); return result; } if(jmk_major==0) { jmk_major=result; printk("jmk major number is %d!\n",jmk_major); } printk("hello world!\n"); /* 开始查找卡 */ jmkdev=pci_find_device(jmk_VendorID,jmk_DeviceID,NULL); if(!jmkdev) { printk("no kard!\n"); return -1; } else { printk("found card!\n"); } /* 启用卡 */ pci_enable_device(jmkdev);
/* 查找卡资源 */ /* base 0 */ base0start=pci_resource_start(jmkdev,0); endsrc=pci_resource_end(jmkdev,0); base0len=endsrc-base0start; printk("base 0 addr is 0x%x,len is 0x%x!\n",base0start,base0len); /* base 1 */ base1start=pci_resource_start(jmkdev,1); endsrc=pci_resource_end(jmkdev,1); base1len=endsrc-base1start; printk("base 1 addr is 0x%x,len is 0x%x!\n",base1start,base1len); /* base 2 */ base2start=pci_resource_start(jmkdev,2); endsrc=pci_resource_end(jmkdev,2); base2len=endsrc-base2start; printk("base 2 addr is 0x%x,len is 0x%x!\n",base2start,base2len); /* 申请使用io内存 */ request_mem_region(base0start,base0len,"jmkdev"); /* 映射io内存 */ iomembase=ioremap(base0start,base0len);
if(iomembase==NULL) { printk("can't get iomem!\n"); } else { printk("get iomem addr is 0x%x!\n",iomembase); }
/* 测试获取数据base2 */ /* endsrc=inl(base2start+0x8); printk("dspp the data is 0x%x!\n",endsrc); endsrc=0x400; outl(endsrc,base2start+0x8); endsrc=inl(base2start+0x8); printk("dspp the data is 0x%x!\n",endsrc); endsrc=inl(base0start); printk("base0start the data is 0x%x!\n",endsrc); */ /* 测试获取数据base0 */
endsrc=readl(iomembase); printk("base0 the data is 0x%x!\n",endsrc);
return 0; } void cleanup_module(void) { /* 释放io内存映射 */ iounmap(iomembase); /* 释放注册 */ release_mem_region(base0start,base0len); /* 禁用设备 */ pci_disable_device(jmkdev); /* 施放内存 */ //free_page(buffer); unregister_chrdev(jmk_major,"jmkdev"); printk("Goodbye cruel world!\n");
}
|