/* CPLD test byTX 2013.1.31:add cpld_ioctl */ #include #include #include #include //#include //for file opration #include //for cdev create #include //#include //#include //#include //#include //#include //#include //#include //copy_to_user #include //class_create #include //#include //#include //#include //#include //ioremap defined here #include #include "slaveSerial.h" //#include #include MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Gatieme"); MODULE_DESCRIPTION("hello world"); static void __iomem *io_base; struct cdev *cpld_cdev; struct class *cpld_class; dev_t devid; static int cpld_open(struct inode *inode, struct file *file) { //可配置eint18,并复位cpld printk("cpld open\n"); return 0; } //read ,do not change f_pos ssize_t cpld_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { unsigned short int tmp; #if DEBUG_PRINT printk("f_pos=0x%x\n",*(unsigned int*)f_pos); #endif tmp=ioread16(io_base+(*f_pos)); #if DEBUG_PRINT printk("cpld read =0x%x\n",tmp); #endif //return copy_to_user(buf,(char *)&tmp,sizeof(unsigned short int)); *(unsigned short int*)buf=tmp; return 2;//always read 2bytes } //write ,do not change f_pos ssize_t cpld_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { #if DEBUG_PRINT printk("f_pos=0x%x count=%d\n",*(unsigned int*)f_pos,count); #endif if(count==2) { iowrite16(*(unsigned short int*)buf,io_base+(*f_pos)); #if DEBUG_PRINT printk("write data=0x%x\n",*(unsigned short int*)buf); #endif return count; } /* else if(count==FPGA_BURST_SIZE)//多字节连续写入 { for(i=0;i=0 && offsetf_pos = new_pos; return new_pos; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) static int cpld_ioctl(struct inode *indoe, struct file *file, unsigned int cmd, unsigned long arg) { #else //long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); //long (*compat_ioctl) (struct file *file, unsigned int cmd, unsigned long arg) static long cpld_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { //struct inode *inode = file->f_dentry->d_inode; struct inode *inode = inode = file_inode(file); #endif switch(cmd) { case CMD_START_SHIFT: shiftWordOut((unsigned short int)arg,io_base); break; case CMD_START_PROG: set_prog_b(io_base,0); //?????? 这函数功能-设置boot值,io_base+REG_PROG_B_OFFSET set_prog_b(io_base,0); set_prog_b(io_base,1); break; case CMD_CHECK_DONE: return check_done(io_base); //这check_done在slaveSerial.c中,检查是否下载完成 case CMD_SET_LED: iowrite16((arg>0)?SET_LED_ON:SET_LED_OFF, io_base+REG_LED_OFFSET); break; case CMD_SEND_LOW_BYTE: shiftByteOut((char)arg,io_base); break; case CMD_SEND_HIGH_BYTE: shiftByteOut((char)(arg>>8),io_base); break; case CMD_CHECK_INIT: return get_init_bit(io_base); break; case CMD_SET_CONTROL: iowrite16((unsigned short int)arg,io_base+REG_CONTROL_OFFSET); ///?????REG_CONTROL_OFFSET在哪里定义的?arg是要设置的值,第二个参数是地址 break; case CMD_SET_DATA: iowrite16((unsigned short int)arg,io_base+REG_DATA_OFFSET); break; default: break; } return 0; } static struct file_operations cpld_fops = { .owner = THIS_MODULE, .open = cpld_open, .read = cpld_read, .write = cpld_write, .llseek = cpld_llseek, #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) .ioctl = cpld_ioctl, #else .compat_ioctl = cpld_compat_ioctl, #endif }; static int __init cpld_init(void) { //创建字符设备 cpld_cdev=cdev_alloc(); cdev_init(cpld_cdev, &cpld_fops); cpld_cdev->owner = THIS_MODULE; alloc_chrdev_region(&devid, 0, 1, "cpld"); cdev_add(cpld_cdev,devid,1); cpld_class = class_create(THIS_MODULE,"cpld_class"); device_create(cpld_class, NULL, devid, NULL,"cpld"); //申请内存 io_base=ioremap(CPLD_BASE,CPLD_SIZE); if(io_base==0) printk("failed to ioremap cpld\n"); else printk("cpld test reg.=0x%x\n",ioread16(io_base+REG_TEST_OFFSET)); printk("CPLD initialized.\n"); return 0; } static void __exit cpld_exit(void) { unregister_chrdev_region(devid,1); device_destroy(cpld_class , devid); class_destroy(cpld_class); cdev_del(cpld_cdev); iounmap(io_base); printk("cpld exit\n"); } module_init(cpld_init); module_exit(cpld_exit);