/******************************************************************************* NAME $RCSfile: nicI210Diag.c,v $ SUMMARY Intel Ethernet Controller (I210) diagnostics VERSION $Revision: 1.0 $ UPDATE DATE $Date: 2014/07/30 04:16:50 $ PROGRAMMER $Author: TCS $ COPYRIGHT: DESCRIPTION: REFERENCE: *******************************************************************************/ //#ifndef NIC_KERNEL_MODULE_C #define NIC_KERNEL_MODULE_C #include #include #include #include #include #include #include #include #include "nicI210IOCTL.h" #include #undef TRUE #undef FALSE #include "commRpt.h" #include "commMEC.h" #define _GPL_ #define stringify(s) tostring(s) #define tostring(s) #s static int nicI210_major; static struct class *nicI210_module_class; #define IS_VALID_NAME_ON_PP(name) \ do { \ if (strcmp(name, "em1") && strcmp(name, "em2")) { \ printk("Invalid eth interface (%s) for nic I210 \n", name); \ return (-EINVAL); \ } \ } while(0) extern int igbLoopbackTest(const char *name, LOOPBACK_TYPE type, struct block_cus blocks); extern int igbLinkTest(const char *name); extern int igbEepromTest(const char *name); extern int igbIntrTest(const char *name); extern int igbMDIORead(const char *name, int page, int reg, u16 *PHY_data); extern int igbMDIOWrite(const char *name, int page, int reg, u16 PHY_data); int nicI210MdiTest(const char *name) { int ret; //IS_VALID_NAME_ON_PP(name); ret = igbLinkTest(name); return (ret); } int nicI210EepromTest(const char *name) { int ret; //IS_VALID_NAME_ON_PP(name); ret = igbEepromTest(name); return (ret); } int nicI210IntrTest(const char *name) { int ret; //IS_VALID_NAME_ON_PP(name); ret = igbIntrTest(name); return (ret); } int nicI210LoopbackTest(const char *name, LOOPBACK_TYPE type, struct block_cus blocks) { int ret; //IS_VALID_NAME_ON_PP(name); ret = igbLoopbackTest(name, type, blocks); return (ret); } int nicI210MDIORead(const char *name, int page, int reg, int *PHY_data) { int ret; ret = igbMDIORead(name, page, reg, (u16 *)PHY_data); return (ret); } int nicI210MDIOWrite(const char *name, int page, int reg, int PHY_data) { int ret; ret = igbMDIOWrite(name, page, reg, (u16 )PHY_data); return (ret); } int nicI210_open(struct inode *inod, struct file *filp) { int major, minor; major = imajor(inod); minor = iminor(inod); try_module_get(THIS_MODULE); return 0; } int nicI210_release(struct inode *inod, struct file *filp) { module_put(THIS_MODULE); return 0; } //int nicI210_ioctl(struct file *filp, unsigned int cmd, void *arg) long nicI210_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) != NICI210_MODULE_IOC_MAGIC) { return -ENOTTY; } if (_IOC_NR(cmd) > NICI210_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_NICI210_IGBMDIORead) || (cmd == IOCTL_NICI210_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("nicI210_ioctl : Copy from user space error!\n"); return -EFAULT; } switch (cmd) { case IOCTL_NICI210_LOOPBACK: ret = nicI210LoopbackTest(ker_ag.ethname, ker_ag.type, ker_ag.blocks); printk("[## eth ##] LoopbackTesfinishret:(%d)\n", ret); break; case IOCTL_NICI210_IGBEEPROMTEST: ret = nicI210EepromTest(ker_ag.ethname); printk("[## eth ##] EepromTestfinishret:(%d)\n", ret); break; case IOCTL_NICI210_IGBINTRTEST: ret = nicI210IntrTest(ker_ag.ethname); printk("[## eth ##] IntrTesfinishret:(%d)\n", ret); break; case IOCTL_NICI210_IGBMDITEST: ret = nicI210MdiTest(ker_ag.ethname); printk("[## eth ##] MdiTesfinishret:(%d)\n", ret); break; case IOCTL_NICI210_IGBIEEETEST: printk("[## eth ##] IEEETest not supported\n"); return -ENOTTY; case IOCTL_NICI210_IGBMDIORead: ret = nicI210MDIORead(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_NICI210_IGBMDIOWrite: ret = nicI210MDIOWrite(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 nicI210_unlocked_ioctl(struct file *File, unsigned int Cmd, unsigned long Arg) { //return nicI210_ioctl(File, Cmd, (void *)Arg); return nicI210_ioctl(File, Cmd, Arg); } struct file_operations nicI210_fops = { .owner = THIS_MODULE, .open = nicI210_open, .unlocked_ioctl = nicI210_ioctl, .release = nicI210_release, }; int nicI210_init_module(void) { int ret_num = 0; nicI210_major = 0; ret_num = register_chrdev(NICI210_DYNAMIC_MAJOR, NICI210_DEVICE_NAME, &nicI210_fops); nicI210_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) { nicI210_module_class = class_create(THIS_MODULE, NICI210_DEVICE_NAME); device_create(nicI210_module_class, NULL, MKDEV(nicI210_major, 0), NULL, "%s", NICI210_DEVICE_NAME); printk(KERN_INFO "NIC I210 kernel module have been loaded successfully (MAJOR_NUM=%d)!\n", ret_num); } return 0; } void nicI210_cleanup_module(void) { unregister_chrdev(nicI210_major, NICI210_DEVICE_NAME); device_destroy(nicI210_module_class, MKDEV(nicI210_major, 0)); class_destroy(nicI210_module_class); } module_init(nicI210_init_module); module_exit(nicI210_cleanup_module); MODULE_AUTHOR("rain_wang@jabil.com"); MODULE_DESCRIPTION("NetApp NIC I210 Diag Code"); MODULE_LICENSE("GPL"); MODULE_VERSION("0.1");