#include #include #include #include #include #include #include #include #include #include #include "ip1811.h" #include "ip1811fdat.h" static struct cdev ip1811_cdev; struct class *ip1811_class; static DEFINE_MUTEX(ip1811_mutex); u8 CPU_IF_SPEED_NORMAL; #define IP1811_MAJOR 248 #define IP1811_NAME "ip1811_cdev" //#define IP1811DEBUG MODULE_LICENSE ("GPL"); static int ip1811_open(struct inode *inode, struct file *fs) { #ifdef IP1811DEBUG printk("ip1811: open...\n"); #endif try_module_get(THIS_MODULE); return 0; } static int ip1811_release(struct inode *inode, struct file *file) { module_put(THIS_MODULE); #ifdef IP1811DEBUG printk("ip1811: release!\n"); #endif return 0; } static ssize_t ip1811_read(struct file *filp, char __user *buffer, size_t length, loff_t *offset) { // return simple_read_from_buffer(buffer, length, offset, msg, 200); return 0; } static ssize_t ip1811_write(struct file *filp, const char __user *buff, size_t len, loff_t *off) { /* if (len > 199) return -EINVAL; copy_from_user(msg, buff, len); msg[len] = '\0'; return len;*/ return 0; } static int ip1811_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { int ret; unsigned long len, cmdid, fno, fsubg, fgrp, fusg; void *cptr; char *cdata, *cmptr; int offset_t; #ifdef IP1811DEBUG printk(KERN_ALERT "ip1811: +ioctl...\n"); #endif len = (int)(_IOC_SIZE(cmd)); cptr = (void *)arg; offset_t = sizeof(void*) + sizeof(unsigned long); do { cdata = kmalloc(len, GFP_KERNEL); cmptr=cdata; if (!cdata) { printk(KERN_ERR "cdata==NULL"); ret = -ENOMEM; goto out_ip1811_ioctl; } #if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0) if(access_ok(VERIFY_READ, cptr, len)){ #else if(access_ok(cptr, len)){ #endif if(copy_from_user(cdata, cptr, len)){ printk(KERN_ERR "copy_from_user fail. len:%ld",(unsigned long)len); ret=-EFAULT; goto out_ip1811_ioctl; } } else{ printk(KERN_ERR "[switchDriver] copy_from_user access fail by %s:%d CMD:%x\n",__FUNCTION__,__LINE__,cmd); ret = -EFAULT; goto out_ip1811_ioctl; } if(cmptr!=cdata){ printk(KERN_ERR "cdata error org: %p, after: %p", cmptr, cdata); } cmdid = *((unsigned long *)(cdata+offset_t)); fno = (cmdid >> _CMDID_NRSHIFT) & _CMDID_NRMASK; fsubg=(cmdid >> _CMDID_SUBGSHIFT) & _CMDID_SUBGMASK; fgrp= (cmdid >> _CMDID_GRPSHIFT) & _CMDID_GRPMASK; fusg= (cmdid >> _CMDID_USGSHIFT) & _CMDID_USGMASK; #ifdef IP1811DEBUG printk(KERN_ALERT "cmdid=0x%08x\n", (unsigned int)cmdid); #endif if (fusg == _CMDID_USG_COMMON) { switch (fgrp) { case _CMDID_GRP_BASIC: switch (fsubg) { case _CMDID_SUBG_SMI: ret = func_of_common_smi[fno](cdata, len); break; case _CMDID_SUBG_CAP: ret = func_of_common_cap[fno](cdata, len); break; case _CMDID_SUBG_LUT: ret = func_of_common_lut[fno](cdata, len); break; case _CMDID_SUBG_SNIFFER: ret = func_of_common_sniffer[fno](cdata, len); break; case _CMDID_SUBG_STORM: ret = func_of_common_storm[fno](cdata, len); break; case _CMDID_SUBG_EOC: ret = func_of_common_eoc[fno](cdata, len); break; case _CMDID_SUBG_LD: ret = func_of_common_ld[fno](cdata, len); break; case _CMDID_SUBG_WOL: ret = func_of_common_wol[fno](cdata, len); break; case _CMDID_SUBG_STAG: ret = func_of_common_stag[fno](cdata, len); break; case _CMDID_SUB_BANDWIDTH: ret = func_of_common_bandwidth[fno](cdata, len); break; case _CMDID_SUBG_MISC: ret = func_of_common_misc[fno](cdata, len); break; default: ret = -EINVAL; } break; case _CMDID_GRP_VLAN: switch (fsubg) { case _CMDID_SUBG_VLAN: ret = func_of_common_vlan[fno](cdata, len); break; default: ret = -EINVAL; } break; case _CMDID_GRP_QOS: switch (fsubg) { case _CMDID_SUB_BANDWIDTH: ret = func_of_common_bandwidth[fno](cdata, len); break; default: ret = -EINVAL; } break; case _CMDID_GRP_SEC: switch (fsubg) { case _CMDID_SUBG_IMP: ret = func_of_common_imp[fno](cdata, len); break; case _CMDID_SUBG_COS: ret = func_of_common_cos[fno](cdata, len); break; default: ret = -EINVAL; } break; case _CMDID_GRP_ADV: switch (fsubg) { case _CMDID_SUBG_STP: ret = func_of_common_stp[fno](cdata, len); break; case _CMDID_SUBG_LACP: ret = func_of_common_lacp[fno](cdata, len); break; default: ret = -EINVAL; } break; default: ret = -EINVAL; } } else if (fusg == _CMDID_USG_IP1811) { switch (fgrp) { case _CMDID_GRP_BASIC: switch (fsubg) { case _CMDID_SUBG_CAP: ret = func_of_common_cap[fno](cdata, len); break; case _CMDID_SUBG_LUT: ret = func_of_ip1811_lut[fno](cdata, len); break; case _CMDID_SUBG_SNIFFER: ret = func_of_ip1811_sniffer[fno](cdata, len); break; case _CMDID_SUBG_STORM: ret = func_of_ip1811_storm[fno](cdata, len); break; case _CMDID_SUBG_EOC: ret = func_of_ip1811_eoc[fno](cdata, len); break; case _CMDID_SUBG_LD: ret = func_of_ip1811_ld[fno](cdata, len); break; case _CMDID_SUBG_WOL: ret = func_of_ip1811_wol[fno](cdata, len); break; case _CMDID_SUBG_IGMP: ret = func_of_ip1811_igmp[fno](cdata, len); break; case _CMDID_SUBG_PTP: ret = func_of_ip1811_ptp[fno](cdata, len); break; default: ret = -EINVAL; } break; case _CMDID_GRP_VLAN: switch (fsubg) { case _CMDID_SUBG_VLAN: ret = func_of_ip1811_vlan[fno](cdata, len); break; default: ret = -EINVAL; } break; case _CMDID_GRP_QOS: switch (fsubg) { case _CMDID_SUB_QOS: ret = func_of_ip1811_qos[fno](cdata, len); break; default: ret = -EINVAL; } break; case _CMDID_GRP_ACL: switch (fsubg) { case _CMDID_SUBG_ACL: ret = func_of_ip1811_acl[fno](cdata, len); break; default: ret = -EINVAL; } break; case _CMDID_GRP_SEC: switch (fsubg) { case _CMDID_SUBG_IMP: ret = func_of_ip1811_imp[fno](cdata, len); break; default: ret = -EINVAL; } break; case _CMDID_GRP_ADV: switch (fsubg) { case _CMDID_SUBG_STP: ret = func_of_ip1811_stp[fno](cdata, len); break; case _CMDID_SUBG_LACP: ret = func_of_ip1811_lacp[fno](cdata, len); break; default: ret = -EINVAL; } break; case _CMDID_GRP_MON: switch (fsubg) { case _CMDID_SUBG_MIB_COUNTER: ret = func_of_ip1811_mib_counter[fno](cdata, len); break; default: ret = -EINVAL; } break; case _CMDID_GRP_HSR: switch (fsubg) { case _CMDID_SUBG_HSR: ret = func_of_ip1811_hsr[fno](cdata, len); break; default: ret = -EINVAL; } break; default: ret = -EINVAL; } } else ret = -EINVAL; if (ret < 0) goto out_ip1811_ioctl; #if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0) if(access_ok(WERIFY_WRITE, cptr, len)){ #else if(access_ok(cptr, len)){ #endif if (copy_to_user(cptr, cdata, len)) { printk(KERN_ERR "copy_touser fail."); ret = -EFAULT; goto out_ip1811_ioctl; } } else{ printk(KERN_ERR "[switchDriver] copy_from_user access fail by %s:%d CMD:%x\n",__FUNCTION__,__LINE__,cmd); ret=-EFAULT; goto out_ip1811_ioctl; } cptr= (void *)*((unsigned long *)cdata); len = *((unsigned long *)(cdata+4)); kfree(cdata); cdata = NULL; } while (cptr); out_ip1811_ioctl: if(cdata) { //memset(cdata, 0x0, len); kfree(cdata); } #ifdef IP1811DEBUG printk(KERN_ALERT "ip1811: -ioctl...\n"); #endif return (ret < 0) ? ret : 0; } static void lock_key_ioctl(void) { mutex_lock(&ip1811_mutex); } static void unlock_key_ioctl(void) { mutex_unlock(&ip1811_mutex); } static long ip1811_unlocked_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { int ret; lock_key_ioctl(); ret = ip1811_ioctl(filep, cmd, arg); unlock_key_ioctl(); return ret; } static struct file_operations ip1811_fops = { .owner = THIS_MODULE, .read = ip1811_read, .write = ip1811_write, .unlocked_ioctl = ip1811_unlocked_ioctl, .open = ip1811_open, .release = ip1811_release }; extern u16 Read_Reg(u8 regaddr); extern void Write_Reg(u8 regaddr, u16 value); extern void IP2Page(u8 page); extern u16 Read_Reg_0_With_1s(void); /* ==================================================================================== */ static int __init ip1811_init(void) { int result; result = register_chrdev_region(MKDEV(IP1811_MAJOR, 0), 1, IP1811_NAME); if (result < 0) { printk(KERN_WARNING "ip1811: can't get major %d\n", IP1811_MAJOR); return result; } cdev_init(&ip1811_cdev, &ip1811_fops); ip1811_cdev.owner = THIS_MODULE; result = cdev_add(&ip1811_cdev, MKDEV(IP1811_MAJOR, 0), 1); if (result) { printk(KERN_WARNING "ip1811: error %d adding driver\n", result); return result; } CPU_IF_SPEED_NORMAL = 0; //set to normal speed initially IP2Page(0); if( (Read_Reg_0_With_1s() & 0xFFF0) == 0x8120 ) { printk("ip1811: CPU I/F High speed."); } else { CPU_IF_SPEED_NORMAL = 1; printk("ip1811: CPU I/F Normal speed."); } // for acl_man init. acl_init(); printk(" Driver loaded!\n"); return 0; /* fail_return: if(ip1811_cdev){ cdev_del(ip1811_cdev); kfree(ip1811_cdev); ip1811_cdev=NULL; } if(devno) unregister_chrdev_region(devno, 1); if(ip1811_class) class_destroy(ip1811_class); return -1; */ } static void __exit ip1811_exit(void) { /* if(ip1811_cdev){ cdev_del(ip1811_cdev); kfree(ip1811_cdev); ip1811_cdev=NULL; } if(devno) unregister_chrdev_region(devno, 1); if(ip1811_class) class_destroy(ip1811_class); */ cdev_del(&ip1811_cdev); unregister_chrdev_region(MKDEV(IP1811_MAJOR, 0), 1); printk("ip1811: Driver unloaded!\n"); } module_init(ip1811_init); module_exit(ip1811_exit);