/********************************************************************************************************* ** 函数名称: __selPtyAdd ** 功能描述: 向指定的 pty wake up list 添加一个等待节点. (ioctl FIOSELECT 使用) ** 输 入 : p_ptyddev Ty 虚拟设备控制块 lArg select wake up node 控制结构 ** 输 出 : NONE ** 全局变量: ** 调用模块: *********************************************************************************************************/ VOID __selPtyAdd (P_PTY_D_DEV p_ptyddev, LONG lArg) { REGISTER TY_DEV_ID ptyDev; REGISTER PLW_SEL_WAKEUPNODE pselwunNode = (PLW_SEL_WAKEUPNODE)lArg; REGISTER P_PTY_H_DEV p_ptyhdev = (P_PTY_H_DEV)_LIST_ENTRY(p_ptyddev, PTY_DEV, PTYDEV_ptyddev); /* 获得 HOST 端口 */ ptyDev = &p_ptyhdev->PTYHDEV_tydevTyDev; SEL_WAKE_NODE_ADD(&p_ptyddev->PTYDDEV_selwulList, pselwunNode); /* 添加节点 */ switch (pselwunNode->SELWUN_seltypType) { case SELREAD: /* 等待数据可读 */ if ((rngNBytes(ptyDev->TYDEV_vxringidWrBuf) > 0) || (ptyDev->TYDEV_tydevwrstat.TYDEVWRSTAT_bCR)) { SEL_WAKE_UP(pselwunNode); /* 检测主机是否有数据需要发送 */ } else { ptyDev->TYDEV_tydevwrstat.TYDEVWRSTAT_bBusy = LW_FALSE; /* 确保可以被 Startup 激活 */ } break; case SELWRITE: /* 等待数据可写 */ if (rngFreeBytes(ptyDev->TYDEV_vxringidRdBuf) > 0) { /* 检测主机接收缓存是否有空间 */ SEL_WAKE_UP(pselwunNode); /* 唤醒节点 */ } break; case SELEXCEPT: /* 等待设备异常 */ if ((LW_DEV_GET_USE_COUNT(&p_ptyddev->PTYDDEV_devhdrDevice) == 0) || (LW_DEV_GET_USE_COUNT(&p_ptyhdev->PTYHDEV_tydevTyDev.TYDEV_devhdrHdr) == 0)) { /* 设备关闭了 */ SEL_WAKE_UP(pselwunNode); /* 唤醒节点 */ } break; } }
/********************************************************************************************************* ** 函数名称: _hotplugIoctl ** 功能描述: 控制热插拔消息文件 ** 输 入 : photplugfil 热插拔消息文件 ** iRequest 功能 ** lArg 参数 ** 输 出 : ERROR ** 全局变量: ** 调用模块: *********************************************************************************************************/ static INT _hotplugIoctl (PLW_HOTPLUG_FILE photplugfil, INT iRequest, LONG lArg) { PLW_SEL_WAKEUPNODE pselwunNode; struct stat *pstatGet; PLW_BMSG pbmsg; switch (iRequest) { case FIONREAD: HOTPLUG_DEV_LOCK(); *(INT *)lArg = _bmsgNBytes(photplugfil->HOTPFIL_pbmsg); HOTPLUG_DEV_UNLOCK(); break; case FIONMSGS: HOTPLUG_DEV_LOCK(); if (!_bmsgIsEmpty(photplugfil->HOTPFIL_pbmsg)) { *(INT *)lArg = 1; /* 目前暂不通知具体消息数量 */ } else { *(INT *)lArg = 0; } HOTPLUG_DEV_UNLOCK(); break; case FIONBIO: HOTPLUG_DEV_LOCK(); if (*(INT *)lArg) { photplugfil->HOTPFIL_iFlag |= O_NONBLOCK; } else { photplugfil->HOTPFIL_iFlag &= ~O_NONBLOCK; } HOTPLUG_DEV_UNLOCK(); break; case FIORFLUSH: case FIOFLUSH: HOTPLUG_DEV_LOCK(); _bmsgFlush(photplugfil->HOTPFIL_pbmsg); HOTPLUG_DEV_UNLOCK(); break; case FIORBUFSET: if (lArg < LW_HOTPLUG_DEV_MAX_MSGSIZE) { _ErrorHandle(EMSGSIZE); return (PX_ERROR); } pbmsg = _bmsgCreate((size_t)lArg); if (pbmsg) { HOTPLUG_DEV_LOCK(); _bmsgDelete(photplugfil->HOTPFIL_pbmsg); photplugfil->HOTPFIL_pbmsg = pbmsg; HOTPLUG_DEV_UNLOCK(); } else { _ErrorHandle(ENOMEM); return (PX_ERROR); } break; case LW_HOTPLUG_FIOSETMSG: photplugfil->HOTPFIL_iMsg = (INT)lArg; break; case FIOFSTATGET: pstatGet = (struct stat *)lArg; if (pstatGet) { pstatGet->st_dev = (dev_t)&_G_hotplugdev; pstatGet->st_ino = (ino_t)0; /* 相当于唯一节点 */ pstatGet->st_mode = 0444 | S_IFCHR; pstatGet->st_nlink = 1; pstatGet->st_uid = 0; pstatGet->st_gid = 0; pstatGet->st_rdev = 1; pstatGet->st_size = (off_t)_bmsgSizeGet(photplugfil->HOTPFIL_pbmsg); pstatGet->st_blksize = 0; pstatGet->st_blocks = 0; pstatGet->st_atime = API_RootFsTime(LW_NULL); pstatGet->st_mtime = API_RootFsTime(LW_NULL); pstatGet->st_ctime = API_RootFsTime(LW_NULL); } else { return (PX_ERROR); } break; case FIOSELECT: pselwunNode = (PLW_SEL_WAKEUPNODE)lArg; SEL_WAKE_NODE_ADD(&_G_hotplugdev.HOTPDEV_selwulList, pselwunNode); switch (pselwunNode->SELWUN_seltypType) { case SELREAD: if ((photplugfil->HOTPFIL_pbmsg == LW_NULL) || _bmsgNBytes(photplugfil->HOTPFIL_pbmsg)) { SEL_WAKE_UP(pselwunNode); } break; case SELWRITE: SEL_WAKE_UP(pselwunNode); break; case SELEXCEPT: /* 不退出 */ break; } break; case FIOUNSELECT: SEL_WAKE_NODE_DELETE(&_G_hotplugdev.HOTPDEV_selwulList, (PLW_SEL_WAKEUPNODE)lArg); break; default: _ErrorHandle(ERROR_IO_UNKNOWN_REQUEST); return (PX_ERROR); } return (ERROR_NONE); }
/********************************************************************************************************* ** 函数名称: __canIoctl ** 功能描述: CAN 设备控制 ** 输 入 : ** pcanDev CAN 设备 ** cmd 控制命令 ** lArg 参数 ** 输 出 : ERROR_NONE or PX_ERROR ** 全局变量: ** 调用模块: *********************************************************************************************************/ static INT __canIoctl (__CAN_DEV *pcanDev, INT cmd, LONG lArg) { INTREG iregInterLevel; INT iStatus = ERROR_NONE; struct stat *pstat; PLW_SEL_WAKEUPNODE pselwunNode; struct timeval *timevalTemp; __CAN_PORT *pcanport = (__CAN_PORT *)pcanDev; CAN_DRV_FUNCS *pCanDevFuncs = pcanport->CANPORT_pcanchan->pDrvFuncs; CANDEV_LOCK(pcanDev); /* 等待设备使用权 */ if (pCanDevFuncs->ioctl) { iStatus = pCanDevFuncs->ioctl(pcanport->CANPORT_pcanchan, cmd, (PVOID)lArg); } else { iStatus = ENOSYS; } if ((iStatus == ENOSYS) || ((iStatus == PX_ERROR) && (errno == ENOSYS))) { /* 驱动程序无法识别的命令 */ iStatus = ERROR_NONE; /* 清除驱动程序错误 */ switch (cmd) { case FIONREAD: /* 读缓冲区有效数据数量 */ { LONG lNFrame = __canQCount(pcanDev->CAN_pcanqRecvQueue); *((INT *)lArg) = (INT)(lNFrame * sizeof(CAN_FRAME)); } break; case FIONWRITE: { LONG lNFrame = __canQCount(pcanDev->CAN_pcanqSendQueue); *((INT *)lArg) = (INT)(lNFrame * sizeof(CAN_FRAME)); } break; case FIOFLUSH: /* 清空设备缓冲区 */ __canFlushRd(pcanport); __canFlushWrt(pcanport); break; case FIOWFLUSH: __canFlushRd(pcanport); /* 清空写缓冲区 */ break; case FIORFLUSH: __canFlushWrt(pcanport); /* 清空读缓冲区 */ break; case FIOFSTATGET: /* 获得文件属性 */ pstat = (struct stat *)lArg; pstat->st_dev = (dev_t)pcanDev; pstat->st_ino = (ino_t)0; /* 相当于唯一节点 */ pstat->st_mode = 0666 | S_IFCHR; /* 默认属性 */ pstat->st_nlink = 1; pstat->st_uid = 0; pstat->st_gid = 0; pstat->st_rdev = 1; pstat->st_size = 0; pstat->st_blksize = 0; pstat->st_blocks = 0; pstat->st_atime = API_RootFsTime(LW_NULL); /* 默认使用 root fs 基准时间 */ pstat->st_mtime = API_RootFsTime(LW_NULL); pstat->st_ctime = API_RootFsTime(LW_NULL); break; case FIOSELECT: pselwunNode = (PLW_SEL_WAKEUPNODE)lArg; SEL_WAKE_NODE_ADD(&pcanDev->CAN_selwulList, pselwunNode); switch (pselwunNode->SELWUN_seltypType) { case SELREAD: /* 等待数据可读 */ if (__canQCount(pcanDev->CAN_pcanqRecvQueue) > 0) { SEL_WAKE_UP(pselwunNode); /* 唤醒节点 */ } break; case SELWRITE: if (__canQFreeNum(pcanDev->CAN_pcanqSendQueue) > 0) { SEL_WAKE_UP(pselwunNode); /* 唤醒节点 */ } break; case SELEXCEPT: /* 总线是否异常 */ LW_SPIN_LOCK_QUICK(&pcanport->CANPORT_can.CAN_slLock, &iregInterLevel); if (pcanDev->CAN_uiBusState != CAN_DEV_BUS_ERROR_NONE) { LW_SPIN_UNLOCK_QUICK(&pcanport->CANPORT_can.CAN_slLock, iregInterLevel); SEL_WAKE_UP(pselwunNode); /* 唤醒节点 */ } else { LW_SPIN_UNLOCK_QUICK(&pcanport->CANPORT_can.CAN_slLock, iregInterLevel); } break; } break; case FIOUNSELECT: SEL_WAKE_NODE_DELETE(&pcanDev->CAN_selwulList, (PLW_SEL_WAKEUPNODE)lArg); break; case CAN_DEV_GET_BUS_STATE: /* 获取 CAN 控制器状态 */ LW_SPIN_LOCK_QUICK(&pcanport->CANPORT_can.CAN_slLock, &iregInterLevel); *((LONG *)lArg) = pcanDev->CAN_uiBusState; pcanDev->CAN_uiBusState = CAN_DEV_BUS_ERROR_NONE; /* 读取后清除状态 */ LW_SPIN_UNLOCK_QUICK(&pcanport->CANPORT_can.CAN_slLock, iregInterLevel); break; case FIOWTIMEOUT: if (lArg) { timevalTemp = (struct timeval *)lArg; pcanDev->CAN_ulSendTimeout = __timevalToTick(timevalTemp); /* 转换为系统时钟 */ } else { pcanDev->CAN_ulSendTimeout = LW_OPTION_WAIT_INFINITE; } break; case FIORTIMEOUT: if (lArg) { timevalTemp = (struct timeval *)lArg; pcanDev->CAN_ulRecvTimeout = __timevalToTick(timevalTemp); /* 转换为系统时钟 */ } else { pcanDev->CAN_ulRecvTimeout = LW_OPTION_WAIT_INFINITE; } break; default: _ErrorHandle(ERROR_IO_UNKNOWN_REQUEST); iStatus = PX_ERROR; break; } } CANDEV_UNLOCK(pcanDev); /* 释放设备使用权 */ return (iStatus); }
/********************************************************************************************************* ** 函数名称: _evtfdIoctl ** 功能描述: 控制 eventfd 文件 ** 输 入 : pevtfdfil eventfd 文件 ** iRequest 功能 ** lArg 参数 ** 输 出 : ERROR ** 全局变量: ** 调用模块: *********************************************************************************************************/ static INT _evtfdIoctl (PLW_EVTFD_FILE pevtfdfil, INT iRequest, LONG lArg) { struct stat *pstatGet; PLW_SEL_WAKEUPNODE pselwunNode; switch (iRequest) { case FIONBIO: if (*(INT *)lArg) { pevtfdfil->EF_iFlag |= O_NONBLOCK; } else { pevtfdfil->EF_iFlag &= ~O_NONBLOCK; } break; case FIOFSTATGET: pstatGet = (struct stat *)lArg; if (pstatGet) { pstatGet->st_dev = (dev_t)&_G_evtfddev; pstatGet->st_ino = (ino_t)0; /* 相当于唯一节点 */ pstatGet->st_mode = 0666 | S_IFCHR; pstatGet->st_nlink = 1; pstatGet->st_uid = 0; pstatGet->st_gid = 0; pstatGet->st_rdev = 1; pstatGet->st_size = 0; pstatGet->st_blksize = 0; pstatGet->st_blocks = 0; pstatGet->st_atime = API_RootFsTime(LW_NULL); pstatGet->st_mtime = API_RootFsTime(LW_NULL); pstatGet->st_ctime = API_RootFsTime(LW_NULL); } else { _ErrorHandle(EINVAL); return (PX_ERROR); } break; case FIOSELECT: pselwunNode = (PLW_SEL_WAKEUPNODE)lArg; SEL_WAKE_NODE_ADD(&pevtfdfil->EF_selwulist, pselwunNode); switch (pselwunNode->SELWUN_seltypType) { case SELREAD: if (__evtfd_can_read(pevtfdfil)) { SEL_WAKE_UP(pselwunNode); } break; case SELWRITE: if (__evtfd_can_write(pevtfdfil)) { SEL_WAKE_UP(pselwunNode); } break; case SELEXCEPT: break; } break; case FIOUNSELECT: SEL_WAKE_NODE_DELETE(&pevtfdfil->EF_selwulist, (PLW_SEL_WAKEUPNODE)lArg); break; default: _ErrorHandle(ERROR_IO_UNKNOWN_REQUEST); return (PX_ERROR); } return (ERROR_NONE); }