/*-----------------------------------------------------------------------------*/ /* Include Header Files */ /*-----------------------------------------------------------------------------*/ #include #include #include #include //for NVT_TIMER_BASE_VIRT #include #include #define __MODULE__ vos_ioctl #define __DBGLVL__ 8 // 0=FATAL, 1=ERR, 2=WRN, 3=UNIT, 4=FUNC, 5=IND, 6=MSG, 7=VALUE, 8=USER #define __DBGFLT__ "*" #include #include #include #include #include #include #include #include #include "vos_ioctl.h" /*-----------------------------------------------------------------------------*/ /* Local Types Declarations */ /*-----------------------------------------------------------------------------*/ #define VOS_IOCTL_MINOR_CNT 1 #define VOS_STRCPY(dst, src, dst_size) do { \ strncpy(dst, src, (dst_size)-1); \ dst[(dst_size)-1] = '\0'; \ } while(0) typedef struct { dev_t devt; struct cdev cdev; struct class *p_class; struct device *p_device; } VOS_IOCTL_T; /*-----------------------------------------------------------------------------*/ /* Local Global Variables */ /*-----------------------------------------------------------------------------*/ unsigned int vos_ioctl_debug_level = NVT_DBG_WRN; static VOS_IOCTL_T g_ioctl = {0}; module_param_named(vos_ioctl_debug_level, vos_ioctl_debug_level, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(vos_ioctl_debug_level, "Debug message level"); //============================================================================= // platform device //============================================================================= static int _dev_register(void); static void _dev_unregister(void); static int _dev_platdrv_probe(struct platform_device *pdev); static int _dev_platdrv_remove(struct platform_device *pdev); static int _dev_fops_open (struct inode *inode, struct file *file); static int _dev_fops_release (struct inode *inode, struct file *file); static long _dev_fops_ioctl (struct file *file, unsigned int cmd, unsigned long arg); static void _dev_platdev_release(struct device *dev) { } static struct platform_device _dev_platdev_struct = { .name = VOS_IOCTL_DEV_NAME, .id = 0, .resource = NULL, .dev = { .release = _dev_platdev_release, }, }; static struct platform_driver _dev_platdrv_struct = { .probe = _dev_platdrv_probe, .remove = _dev_platdrv_remove, .driver = { .name = VOS_IOCTL_DEV_NAME, .owner = THIS_MODULE, }, }; // Kernel interface static struct file_operations _dev_fops = { .owner = THIS_MODULE, .open = _dev_fops_open, .release = _dev_fops_release, .unlocked_ioctl = _dev_fops_ioctl, }; /*-----------------------------------------------------------------------------*/ /* Interface Functions */ /*-----------------------------------------------------------------------------*/ void vos_ioctl_init(void *param) { DBG_FUNC_BEGIN("\r\n"); if (0 != _dev_register()) { DBG_ERR("_dev_register failed\r\n"); goto END_INIT; } END_INIT: DBG_FUNC_END("\r\n"); return; } void vos_ioctl_exit(void) { _dev_unregister(); } /*-----------------------------------------------------------------------------*/ /* Kernel IOCTL */ /*-----------------------------------------------------------------------------*/ static int _dev_register(void) { //register device if (0 != platform_device_register(&_dev_platdev_struct)) { DBG_ERR("platform_device_register failed\n"); return -1; } if (0 != platform_driver_register(&_dev_platdrv_struct)) { DBG_ERR("platform_driver_register failed\n"); return -1; } return 0; } static void _dev_unregister(void) { platform_driver_unregister(&_dev_platdrv_struct); platform_device_unregister(&_dev_platdev_struct); } static int _dev_platdrv_probe(struct platform_device *pdev) { int reg_err = 0, cdev_err = 0; reg_err = vos_alloc_chrdev_region(&g_ioctl.devt, VOS_IOCTL_MINOR_CNT, VOS_IOCTL_DEV_NAME); if (reg_err) { DBG_ERR(" alloc_chrdev_region failed!\n"); goto _dev_platdrv_probe_err; } cdev_init(&g_ioctl.cdev, &_dev_fops); g_ioctl.cdev.owner = THIS_MODULE; cdev_err = cdev_add(&g_ioctl.cdev, g_ioctl.devt, VOS_IOCTL_MINOR_CNT); if (cdev_err) { DBG_ERR(" cdev_add failed!\n"); goto _dev_platdrv_probe_err; } g_ioctl.p_class = class_create(THIS_MODULE, VOS_IOCTL_DEV_NAME); if (IS_ERR(g_ioctl.p_class)) { DBG_ERR(" class_create failed!\n"); goto _dev_platdrv_probe_err; } g_ioctl.p_device = device_create(g_ioctl.p_class, NULL, g_ioctl.devt, NULL, VOS_IOCTL_DEV_NAME); if (NULL == g_ioctl.p_device) { DBG_ERR(" device_create failed!\n"); goto _dev_platdrv_probe_err; } return 0; _dev_platdrv_probe_err: if (g_ioctl.p_device) { device_destroy(g_ioctl.p_class, g_ioctl.devt); } if (g_ioctl.p_class) { class_destroy(g_ioctl.p_class); } if (!cdev_err) { cdev_del(&g_ioctl.cdev); } if (!reg_err) { vos_unregister_chrdev_region(g_ioctl.devt, VOS_IOCTL_MINOR_CNT); } return -1; } static int _dev_platdrv_remove(struct platform_device *pdev) { device_destroy(g_ioctl.p_class, g_ioctl.devt); class_destroy(g_ioctl.p_class); cdev_del(&g_ioctl.cdev); vos_unregister_chrdev_region(g_ioctl.devt, VOS_IOCTL_MINOR_CNT); return 0; } static int _dev_fops_open(struct inode *inode, struct file *file) { return 0; } static int _dev_fops_release(struct inode *inode, struct file *file) { return 0; } static long _dev_fops_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; switch (cmd) { // CPU IOCTL case VOS_CPU_IOCMD_DCACHE_SYNC: ret = _IOFUNC_CPU_IOCMD_DCACHE_SYNC(arg); break; case VOS_CPU_IOCMD_GET_PHY_ADDR: ret = _IOFUNC_CPU_IOCMD_GET_PHY_ADDR(arg); break; case VOS_CPU_IOCMD_SYNC_CPU: ret = _IOFUNC_CPU_IOCMD_SYNC_CPU(arg); break; // DEBUG IOCTL case VOS_DEBUG_IOCMD_HALT: ret = _IOFUNC_DEBUG_IOCMD_HALT(arg); break; // FLAG IOCTL case VOS_FLAG_IOCMD_CREATE: ret = _IOFUNC_FLAG_IOCMD_CREATE(arg); break; case VOS_FLAG_IOCMD_SET: ret = _IOFUNC_FLAG_IOCMD_SET(arg); break; case VOS_FLAG_IOCMD_CLR: ret = _IOFUNC_FLAG_IOCMD_CLR(arg); break; case VOS_FLAG_IOCMD_WAIT: ret = _IOFUNC_FLAG_IOCMD_WAIT(arg); break; case VOS_FLAG_IOCMD_CHK: ret = _IOFUNC_FLAG_IOCMD_CHK(arg); break; case VOS_FLAG_IOCMD_DESTROY: ret = _IOFUNC_FLAG_IOCMD_DESTROY(arg); break; // SEM IOCTL case VOS_SEM_IOCMD_CREATE: ret = _IOFUNC_SEM_IOCMD_CREATE(arg); break; case VOS_SEM_IOCMD_WAIT: ret = _IOFUNC_SEM_IOCMD_WAIT(arg); break; case VOS_SEM_IOCMD_SIG: ret = _IOFUNC_SEM_IOCMD_SIG(arg); break; case VOS_SEM_IOCMD_DESTROY: ret = _IOFUNC_SEM_IOCMD_DESTROY(arg); break; // TASK IOCTL case VOS_TASK_IOCMD_SET_UINFO: ret = _IOFUNC_TASK_IOCMD_SET_UINFO(arg); break; case VOS_TASK_IOCMD_GET_UINFO: ret = _IOFUNC_TASK_IOCMD_GET_UINFO(arg); break; case VOS_TASK_IOCMD_REG_N_RUN: ret = _IOFUNC_TASK_IOCMD_REG_N_RUN(arg); break; case VOS_TASK_IOCMD_SET_PRIORITY: ret = _IOFUNC_TASK_IOCMD_SET_PRIORITY(arg); break; case VOS_TASK_IOCMD_DESTROY: ret = _IOFUNC_TASK_IOCMD_DESTROY(arg); break; case VOS_TASK_IOCMD_RETURN: ret = _IOFUNC_TASK_IOCMD_RETURN(arg); break; case VOS_TASK_IOCMD_RESUME: ret = _IOFUNC_TASK_IOCMD_RESUME(arg); break; case VOS_TASK_IOCMD_CONVERT_HDL: ret = _IOFUNC_TASK_IOCMD_CONVERT_HDL(arg); break; // PERF IOCTL case VOS_PERF_IOCMD_MARK: ret = _IOFUNC_PERF_IOCMD_MARK(arg); break; case VOS_PERF_IOCMD_LIST_MARK: ret = _IOFUNC_PERF_IOCMD_LIST_MARK(arg); break; case VOS_PERF_IOCMD_LIST_DUMP: ret = _IOFUNC_PERF_IOCMD_LIST_DUMP(arg); break; case VOS_PERF_IOCMD_LIST_RESET: ret = _IOFUNC_PERF_IOCMD_LIST_RESET(arg); break; default: DBG_WRN("Unknown IOCMD 0x%08X\n", (u32)cmd); ret = -EINVAL; break; } return ret; }