📄 pciioctl.c
字号:
#ifndef __KERNEL__# define __KERNEL__#endif#ifndef MODULE# define MODULE#endif#define __NO_VERSION__#include <linux/kernel.h>#include <linux/module.h>#include <linux/errno.h>#include <linux/pci.h>#include <math.h>#include <asm/io.h>#include <asm/segment.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/poll.h>#include <asm/uaccess.h>#include <rtai_sched.h>#include <rtai_leds.h>#include <rtai_fifos.h>#include <rtai_shm.h>#include <linux/ioctl.h>#include <linux/delay.h>#include <linux/time.h>#include "pciioctl.h"#include "portdefine.h"#include "pgm.h"#define IK_VENDOR 0x8086#define IK_DEVICE 0x24c5#define DRV_NAME "IK220"#define TV_2s 2000000000#define TV_1ms 1000000#define TV_100us 100000 static RT_TASK task_one;MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;int Xbaseport;int Ybaseport;int cardbaseport;int cardconfreg;static int codemode;int latchstate;//read_write_t IK_read(struct inode *inode,struct file *filp,char *buf,count_t count);//read_write_t IK_write(struct inode *inode,struct file *filp,char *buf,count_t count);/* pre-defined function */int IK_open(struct inode *inode,struct file *filp);int IK_release(struct inode *inode,struct file *filp);int IK_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg);// input and output function defined void IKoutw(int axisbase,int adr,int data){ int address; address=axisbase+adr; writew(data,address);}int IKinw(int axisbase,int adr,int *pbuffer){ int address; address=axisbase+adr; *pbuffer=readw(address); return TRUE;}int IKinl(int axisbase,int adr,int *pbuffer){ int address; address=axisbase+adr; *((int*)pbuffer)=readw(address); *((int*)(pbuffer+1))=readw(address+1); return TRUE;} int IKoutcmd(int ax,int IK220CMD){ int reg; IKoutw(ax,CMDPORT,IK220CMD); IKinw(ax,DATPORT0,®); if(reg!=IK220CMD) { printk("error when write cmd to IK220"); return FALSE; } return TRUE;}int timeout(unsigned long just,unsigned long tv){ unsigned long now; now=rt_get_time_ns(); just=just+tv; if(now>=just) return TRUE; else return FALSE;}int ramwrite(int axisadd,int ramadd,int data){ int reg; unsigned long tv_just; IKoutw(axisadd,CONTROLREG,BOOTMODE); tv_just=rt_get_time_ns(); do { IKinw(axisadd,STATUSREG,®); } while(!(reg&PIPEEMPTY)&&!timeout(tv_just,TV_1ms)); IKinw(axisadd,STATUSREG,®); if(!(reg&PIPEEMPTY)) return FALSE; IKoutw(axisadd,G28PORT0,ramadd); IKoutw(axisadd,G28PORT1,data); IKoutw(axisadd,CONTROLREG,WRITERAMMODE); return TRUE;}int download(int add,int *ppgmdata,int pgmsize){ int i; int ramadr; if((pgmsize<(3*2))|(pgmsize>65536+2)*2) return FALSE; ppgmdata++; ramadr=*ppgmdata++; for(i=1;i<=(pgmsize/2)-2;i++) if(!(ramwrite(add,ramadr++,*ppgmdata++))) return FALSE-1; return TRUE;}int IK220init(int addr){ int reg; unsigned long tv_just; if(!download(addr,&pgm220[0],sizeof(pgm220))) return FALSE; if(!IKinw(addr,CLRFLAG1REG,®)) return FALSE-1; IKoutw(addr,CONTROLREG,RUNMODE); tv_just=rt_get_time_ns(); do { if(!IKinw(addr,FLAG1REG,®)) return FALSE-3; } while(!(reg&G28SEM10)&&!timeout(tv_just,TV_2s)); if(!IKinw(addr,FLAG1REG,®)) return FALSE-4; if(!(reg&G28SEM10)) { printk("timeout!\n"); return FALSE-5; } if(!IKinw(addr,CLRFLAG1REG,®)) return FALSE-6; return TRUE; }int Get48val(int adr,int la){ int reg; double data=0; double *pdata=(double *)&data; int count=0; int *pcount=(int*)&count; IKinw(adr,STAPORT,®); if(!(reg&(1<<la))) { printk("error latch for get data"); return FALSE; } IKoutcmd(adr,(int)(CMDGETCNT0+la)); IKinl(adr,DATPORT1,pcount); pcount=pcount+2; IKinw(adr,DATPORT3,pcount); if(*pcount&0x8000) { pcount=pcount+1; *pcount=0xFFFF; } *pdata=(double)count/65536.0; return *pdata;}// read parameter to registerint IK220writepar(int address,int parnum,long parval){ int reg; IKoutw(address,DATPORT1,parnum); IKoutw(address,DATPORT2,(parval&&0xFFFF)); //write high 16 bit IKoutw(address,DATPORT1,(parnum>>16)); //write low 16 bit if(!IKoutcmd(address,CMDWRITEPAR)) return FALSE; IKinw(address,DATPORT2,®); if(reg!=0) return FALSE; return TRUE;}int latchint(int address) //card base address{ int reg,data; reg=address+CONFREG_CNTRL; data=readl(reg); data=data&0xFFFFFEFF; writel(data,reg); udelay(2); data=data|0x00000100; writel(data,reg); return TRUE;}int IKlatch(int address,int la) //axis base address{ if(!IKoutcmd(address,(int)(CMDLATCH0+la))) return FALSE; else return TRUE;}int IKlatched(int addr,int la,int *ls){ int reg; *ls=FALSE; IKinw(addr,STAPORT,®); if((reg&(1<<la))) *ls=TRUE; return *ls;}int IKwaitlatched(int addr,int la){ int reg; unsigned long tv_just; tv_just=rt_get_time_ns(); do { IKinw(addr,STAPORT,®); } while(!(reg&(1<<la))&&!timeout(tv_just,TV_100us)); IKinw(addr,STAPORT,®); if(!(reg&(1<<la))) return FALSE; return TRUE;}int IKstart(int addr){ if(!IKoutcmd(addr,CMDSTART)) return FALSE; return TRUE;}int IKreset(int addr){ if(!IKoutcmd(addr,CMDRESET)) return FALSE; return TRUE;}int IKstop(int addr){ if(!IKoutcmd(addr,CMDSTOP)) return FALSE; return TRUE;}// file operations for user to control kernel modulestatic struct file_operations IK_fops={ owner: THIS_MODULE,// read: IK_read,// write: IK_write, open: IK_open, release: IK_release, ioctl: IK_ioctl,};int IK_open(struct inode *inode,struct file *filp){ MOD_INC_USE_COUNT; printk("now open the device\n"); return 0;} int IK_release(struct inode *inode,struct file *filp){ MOD_DEC_USE_COUNT; return 0;}// ioctlsint IK_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg){ int ret=0; switch(cmd) {// #ifdef IK_DEBUG case IK_IOCHARDRESET: while(MOD_IN_USE) MOD_DEC_USE_COUNT; MOD_INC_USE_COUNT;// #endif case IK_IOCSTART: IKstart(Xbaseport); IKstart(Ybaseport); sample_period=resetnum*1000000; rt_task_make_periodic_relative_ns(&task_one,0,sample_period); ret=1; checkstate=1; break; case IK_IOCSTOP: IKstop(Xbaseport); IKstop(Ybaseport); rt_task_suspend(&task_one); ret=2; checkstate=0; break; case IK_IOCRESET: rt_task_suspend(&task_one); if(arg==1) IKreset(Xbaseport); else if(arg==2) IKreset(Ybaseport); else { IKreset(Xbaseport); IKreset(Ybaseport); } rt_task_make_periodic_relative_ns(&task_one,0,sample_period); break; // code mode select:incremental or Endata model case IK_IOCENCODE: if(arg==1||arg==0) { if(!IK220writepar(Xbaseport,1,arg)) { printk("error when write par for code X"); break; }
if(!IK220writepar(Ybaseport,1,arg))
{
printk("error when write par for code Y");
break;
}// no Endata if(arg==1) //if select ENDAT model// when debug {// reset code model// if(!IK220reseten(AXIS,&enstatus))// printk("error in reseten");// configen(not understand???// if(!IK220configen(AXIS,&enstatus,...))// } } else printk("wrong input command\n"); if(arg==0) codemode=0; else codemode=1; ret=3; break; // signal model select case IK_IOCSIGNAL: if(arg==1||arg==0) { if(!IK220writepar(Xbaseport,2,arg))
{ printk("error when write par for X axis signal\n ");
break;
}
if(!IK220writepar(Ybaseport,2,arg))
{
printk("error when write par for Y axis signal\n ");
break;
} } else printk("wrong input command for signal"); ret=4; break;// set sampling period case IK_IOCSETPERIOD: if(checkstate==1) { printk("Stop the task first!\n"); break; } resetnum=arg; ret=5; break; case IK_IOCREAD: break; default: return -10; } return 1;}// PCI drivers for getting IK_card informations static struct pci_device_id IK_pci_tbl[] __initdata={ {IK_VENDOR,IK_DEVICE,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, {0,}};/* Get card informations get iobase port address,memory address, configure port address... Initialize registers*/static int __init IK_probe(struct pci_dev *dev,const struct pci_device_id *id){ int ionum;///////////////////////////////////////////////////////////////////////////////////////////Get PORTBASE,Xbaseport,Ybaseport,MEMBASE,remap address... /////////////////////////////////////////////////////////////////////////////// if(pci_enable_device(dev)) return -EIO; printk("irq=%d",dev->irq); for(ionum=0;ionum<6;ionum++) { cardbaseport=pci_resource_start(dev,ionum); if(cardbaseport!=0) printk("IOBASE%d=%x ",ionum,cardbaseport); } Xbaseport=0; Ybaseport=0; cardbaseport=0; cardconfreg=0;/////////////////////////////////////////////////////////////////////////////////////////// Init ... //////////////////////////////////////////////////////////////////////////////// IK220init(Xbaseport); //init X axis IK220init(Ybaseport); //init Y axis encodetype=0; //init code type signaltype=1; //init signal type IK220writepar(Xbaseport,1,encodetype); IK220writepar(Xbaseport,2,encodetype); IK220writepar(Ybaseport,1,encodetype); IK220writepar(Ybaseport,2,encodetype); latchint(cardconfreg); //init int latch IKlatch(Xbaseport,0); //latch0 for X axis IKlatch(Ybaseport,0); //latch0 for Y axis // IKstart(Xbaseport); //start X axis counter // IKstart(Ybaseport); //start Y axis counter return 0;}/* Free memory space Unregisting all...*/static void __devexit IK_remove(struct pci_dev *dev){ printk("remove device irq=%d\n",dev->irq);}static struct pci_driver IK_driver={ name:DRV_NAME, id_table:IK_pci_tbl, probe:IK_probe, remove:__devexit_p(IK_remove),};/* * Task for get x,y axis data and save them in memory * or put them to user space and do control with the data */static void IK_task(int fifo){ while(1) { printk("now in rt_task\t"); if(codemode) //Endata model {// xposition=GetEnval(Xbaseport,latchx); // yposition=GetEnval(Ybaseport,latchy); } else //incremental model { if(!IKlatched(Xbaseport,0,&latchstate)) { if(IKwaitlatched(Xbaseport,0)) xposition=Get48val(Xbaseport,0); else printk("latched X axis failed\n"); } else xposition=Get48val(Xbaseport,0); if(!IKlatched(Ybaseport,0,&latchstate)) { if(IKwaitlatched(Xbaseport,0)) xposition=Get48val(Ybaseport,0); else printk("latched Y axis failed\n"); } else xposition=Get48val(Ybaseport,0); xpresent=xpresent+xposition; ypresent=ypresent+yposition; } rt_task_wait_period(); }}static int __init IK_init_module(void){ int result; resetnum=10; rt_task_init(&task_one,IK_task,0,10000,0,1,0); rt_set_oneshot_mode(); start_rt_timer(1); result=register_chrdev(140,"PCI_IK",&IK_fops); if(result<0) { printk("PCI_IK:can't register"); return result; } else return pci_module_init(&IK_driver);}static void __exit IK_cleanup_module(void){ unregister_chrdev(140,"PCI_IK"); pci_unregister_driver(&IK_driver); printk("test finished!");} module_init(IK_init_module);module_exit(IK_cleanup_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -