//#ifndef NIC_KERNEL_MODULE_C #define NIC_KERNEL_MODULE_C #include #include #include #include #include #include #include #include #include "nicX722IOCTL.h" #include #undef TRUE #undef FALSE #define _GPL_ #define stringify(s) tostring(s) #define tostring(s) #s static int nicX722_major; static struct class *nicX722_module_class; #define IS_VALID_NAME_ON_PP(name) \ do { \ if (strcmp(name, "em1") && strcmp(name, "em2")) { \ printk("Invalid eth interface (%s) for nic X722 \n", name); \ return (-EINVAL); \ } \ } while(0) extern int i40eMDIORead(const char *name, u8 page, u16 reg, u16 *PHY_data); extern int i40eMDIOWrite(const char *name, u8 page, u16 reg, u16 PHY_data); int nicX722MDIORead(const char *name, u8 page, u16 reg, u16 *PHY_data) { int ret; printk("<0>JA: nicX722MDIORead name=%s page=%u reg=%u\n", name, page, reg); ret = i40eMDIORead(name, page, reg, (u16 *)PHY_data); printk("<0>JA: nicX722MDIORead name=%s page=%u reg=%u\n", name, page, reg); return (ret); } int nicX722MDIOWrite(const char *name, u8 page, u16 reg, u16 PHY_data) { int ret; ret = i40eMDIOWrite(name, page, reg, (u16 )PHY_data); return (ret); } int nicX722_open(struct inode *inod, struct file *filp) { int major, minor; major = imajor(inod); minor = iminor(inod); try_module_get(THIS_MODULE); return 0; } int nicX722_release(struct inode *inod, struct file *filp) { module_put(THIS_MODULE); return 0; } long nicX722_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0; int ret = 0; argu *ag; argu ker_ag; struct phy_register_info *phy = NULL; struct phy_register_info ker_phy; printk("[## eth ##] ioctl door\n"); if (_IOC_TYPE(cmd) != NICX722_MODULE_IOC_MAGIC) { return -ENOTTY; } if (_IOC_NR(cmd) > NICX722_MODULE_IOC_MAXNUM) { return -ENOTTY; } /* ** The direction is a bitmask, and VERIFY_WRITE catches R/W transfers. ** 'Type' is user-oriented, while access_ok is kernel-oriented, so the ** concept of "read" and "write" is reversed */ if (_IOC_DIR(cmd) & _IOC_READ) { err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); } else if (_IOC_DIR(cmd) & _IOC_WRITE) { err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); } if (err) { printk("[## eth ##] > IODIRM\n"); return -EFAULT; } if ((cmd == IOCTL_NICX722_IGBMDIORead) || (cmd == IOCTL_NICX722_IGBMDIOWrite)) { phy =(struct phy_register_info *) arg; ret = copy_from_user(&ker_phy, phy, sizeof(struct phy_register_info)); } else { ag = (argu *) arg; ret = copy_from_user(&ker_ag, ag, sizeof(argu)); } if (ret) { printk("nicX722_ioctl : Copy from user space error!\n"); return -EFAULT; } switch (cmd) { case IOCTL_NICX722_IGBMDIORead: ret = nicX722MDIORead(ker_phy.ethname, ker_phy.phyPage, ker_phy.phyRegister, &ker_phy.phyData); printk("[## eth ##] MDIOReadfinishret:(%d)\n", ret); //printk("PHY register: Page:%x Register_address:%x PHY_data:%x\n", ker_phy.phyPage, ker_phy.phyRegister, ker_phy.phyData); ret = copy_to_user(phy, &ker_phy, sizeof(struct phy_register_info)); break; case IOCTL_NICX722_IGBMDIOWrite: ret = nicX722MDIOWrite(ker_phy.ethname, ker_phy.phyPage, ker_phy.phyRegister, ker_phy.phyData); printk("[## eth ##] MDIOWritefinishret:(%d)\n", ret); printk("PHY register: Page:%x Register_address:%x PHY_data:%x\n", ker_phy.phyPage, ker_phy.phyRegister, ker_phy.phyData); break; default: printk("[## eth ##] Not a valid IOCTL \n"); return -ENOTTY; } return ret; } long nicX722_unlocked_ioctl(struct file *File, unsigned int Cmd, unsigned long Arg) { //return nicX722_ioctl(File, Cmd, (void *)Arg); return nicX722_ioctl(File, Cmd, Arg); } struct file_operations nicX722_fops = { .owner = THIS_MODULE, .open = nicX722_open, .unlocked_ioctl = nicX722_ioctl, .release = nicX722_release, }; static int __init nicX722_init_module(void) { int ret_num = 0; nicX722_major = 0; ret_num = register_chrdev(NICX722_DYNAMIC_MAJOR, NICX722_DEVICE_NAME, &nicX722_fops); nicX722_major = ret_num; if (ret_num < 0) { printk(KERN_ERR "TPPC476 MODULE: Can't get major device Number !\n"); return ret_num; } if (ret_num >= 0) { nicX722_module_class = class_create(THIS_MODULE, NICX722_DEVICE_NAME); device_create(nicX722_module_class, NULL, MKDEV(nicX722_major, 0), NULL, "%s", NICX722_DEVICE_NAME); printk(KERN_INFO "NIC X722 kernel module have been loaded successfully (MAJOR_NUM=%d)!\n", ret_num); } return 0; } static void __exit nicX722_cleanup_module(void) { unregister_chrdev(nicX722_major, NICX722_DEVICE_NAME); device_destroy(nicX722_module_class, MKDEV(nicX722_major, 0)); class_destroy(nicX722_module_class); } module_init(nicX722_init_module); module_exit(nicX722_cleanup_module); MODULE_AUTHOR("ja_chen@jabil.com"); MODULE_DESCRIPTION("NetApp NIC X722 Diag Code"); MODULE_LICENSE("GPL"); MODULE_VERSION("0.1");