📄 synclink_cs.c
字号:
}}/* Signal remote device to stop throttling send data (our receive data) */static void mgslpc_unthrottle(struct tty_struct * tty){ MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_unthrottle(%s) entry\n", __FILE__,__LINE__, info->device_name ); if (mgslpc_paranoia_check(info, tty->device, "mgslpc_unthrottle")) return; if (I_IXOFF(tty)) { if (info->x_char) info->x_char = 0; else mgslpc_send_xchar(tty, START_CHAR(tty)); } if (tty->termios->c_cflag & CRTSCTS) { spin_lock_irqsave(&info->lock,flags); info->serial_signals |= SerialSignal_RTS; set_signals(info); spin_unlock_irqrestore(&info->lock,flags); }}/* get the current serial statistics */static int get_stats(MGSLPC_INFO * info, struct mgsl_icount *user_icount){ int err; if (debug_level >= DEBUG_LEVEL_INFO) printk("get_params(%s)\n", info->device_name); COPY_TO_USER(err,user_icount, &info->icount, sizeof(struct mgsl_icount)); if (err) return -EFAULT; return 0;}/* get the current serial parameters */static int get_params(MGSLPC_INFO * info, MGSL_PARAMS *user_params){ int err; if (debug_level >= DEBUG_LEVEL_INFO) printk("get_params(%s)\n", info->device_name); COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); if (err) return -EFAULT; return 0;}/* set the serial parameters * * Arguments: * * info pointer to device instance data * new_params user buffer containing new serial params * * Returns: 0 if success, otherwise error code */static int set_params(MGSLPC_INFO * info, MGSL_PARAMS *new_params){ unsigned long flags; MGSL_PARAMS tmp_params; int err; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):set_params %s\n", __FILE__,__LINE__, info->device_name ); COPY_FROM_USER(err,&tmp_params, new_params, sizeof(MGSL_PARAMS)); if (err) { if ( debug_level >= DEBUG_LEVEL_INFO ) printk( "%s(%d):set_params(%s) user buffer copy failed\n", __FILE__,__LINE__,info->device_name); return -EFAULT; } spin_lock_irqsave(&info->lock,flags); memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); spin_unlock_irqrestore(&info->lock,flags); mgslpc_change_params(info); return 0;}static int get_txidle(MGSLPC_INFO * info, int*idle_mode){ int err; if (debug_level >= DEBUG_LEVEL_INFO) printk("get_txidle(%s)=%d\n", info->device_name, info->idle_mode); COPY_TO_USER(err,idle_mode, &info->idle_mode, sizeof(int)); if (err) return -EFAULT; return 0;}static int set_txidle(MGSLPC_INFO * info, int idle_mode){ unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("set_txidle(%s,%d)\n", info->device_name, idle_mode); spin_lock_irqsave(&info->lock,flags); info->idle_mode = idle_mode; tx_set_idle(info); spin_unlock_irqrestore(&info->lock,flags); return 0;}static int get_interface(MGSLPC_INFO * info, int*if_mode){ int err; if (debug_level >= DEBUG_LEVEL_INFO) printk("get_interface(%s)=%d\n", info->device_name, info->if_mode); COPY_TO_USER(err,if_mode, &info->if_mode, sizeof(int)); if (err) return -EFAULT; return 0;}static int set_interface(MGSLPC_INFO * info, int if_mode){ unsigned long flags; unsigned char val; if (debug_level >= DEBUG_LEVEL_INFO) printk("set_interface(%s,%d)\n", info->device_name, if_mode); spin_lock_irqsave(&info->lock,flags); info->if_mode = if_mode; val = read_reg(info, PVR) & 0x0f; switch (info->if_mode) { case MGSL_INTERFACE_RS232: val |= PVR_RS232; break; case MGSL_INTERFACE_V35: val |= PVR_V35; break; case MGSL_INTERFACE_RS422: val |= PVR_RS422; break; } write_reg(info, PVR, val); spin_unlock_irqrestore(&info->lock,flags); return 0;}static int set_txenable(MGSLPC_INFO * info, int enable){ unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("set_txenable(%s,%d)\n", info->device_name, enable); spin_lock_irqsave(&info->lock,flags); if (enable) { if (!info->tx_enabled) tx_start(info); } else { if (info->tx_enabled) tx_stop(info); } spin_unlock_irqrestore(&info->lock,flags); return 0;}static int tx_abort(MGSLPC_INFO * info){ unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("tx_abort(%s)\n", info->device_name); spin_lock_irqsave(&info->lock,flags); if (info->tx_active && info->tx_count && info->params.mode == MGSL_MODE_HDLC) { /* clear data count so FIFO is not filled on next IRQ. * This results in underrun and abort transmission. */ info->tx_count = info->tx_put = info->tx_get = 0; info->tx_aborting = TRUE; } spin_unlock_irqrestore(&info->lock,flags); return 0;}static int set_rxenable(MGSLPC_INFO * info, int enable){ unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("set_rxenable(%s,%d)\n", info->device_name, enable); spin_lock_irqsave(&info->lock,flags); if (enable) { if (!info->rx_enabled) rx_start(info); } else { if (info->rx_enabled) rx_stop(info); } spin_unlock_irqrestore(&info->lock,flags); return 0;}/* wait for specified event to occur * * Arguments: info pointer to device instance data * mask pointer to bitmask of events to wait for * Return Value: 0 if successful and bit mask updated with * of events triggerred, * otherwise error code */static int wait_events(MGSLPC_INFO * info, int * mask_ptr){ unsigned long flags; int s; int rc=0; struct mgsl_icount cprev, cnow; int events; int mask; struct _input_signal_events oldsigs, newsigs; DECLARE_WAITQUEUE(wait, current); COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int)); if (rc) return -EFAULT; if (debug_level >= DEBUG_LEVEL_INFO) printk("wait_events(%s,%d)\n", info->device_name, mask); spin_lock_irqsave(&info->lock,flags); /* return immediately if state matches requested events */ get_signals(info); s = info->serial_signals; events = mask & ( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) + ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) + ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) + ((s & SerialSignal_RI) ? MgslEvent_RiActive :MgslEvent_RiInactive) ); if (events) { spin_unlock_irqrestore(&info->lock,flags); goto exit; } /* save current irq counts */ cprev = info->icount; oldsigs = info->input_signal_events; if ((info->params.mode == MGSL_MODE_HDLC) && (mask & MgslEvent_ExitHuntMode)) irq_enable(info, CHA, IRQ_EXITHUNT); set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&info->event_wait_q, &wait); spin_unlock_irqrestore(&info->lock,flags); for(;;) { schedule(); if (signal_pending(current)) { rc = -ERESTARTSYS; break; } /* get current irq counts */ spin_lock_irqsave(&info->lock,flags); cnow = info->icount; newsigs = info->input_signal_events; set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irqrestore(&info->lock,flags); /* if no change, wait aborted for some reason */ if (newsigs.dsr_up == oldsigs.dsr_up && newsigs.dsr_down == oldsigs.dsr_down && newsigs.dcd_up == oldsigs.dcd_up && newsigs.dcd_down == oldsigs.dcd_down && newsigs.cts_up == oldsigs.cts_up && newsigs.cts_down == oldsigs.cts_down && newsigs.ri_up == oldsigs.ri_up && newsigs.ri_down == oldsigs.ri_down && cnow.exithunt == cprev.exithunt && cnow.rxidle == cprev.rxidle) { rc = -EIO; break; } events = mask & ( (newsigs.dsr_up != oldsigs.dsr_up ? MgslEvent_DsrActive:0) + (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) + (newsigs.dcd_up != oldsigs.dcd_up ? MgslEvent_DcdActive:0) + (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) + (newsigs.cts_up != oldsigs.cts_up ? MgslEvent_CtsActive:0) + (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) + (newsigs.ri_up != oldsigs.ri_up ? MgslEvent_RiActive:0) + (newsigs.ri_down != oldsigs.ri_down ? MgslEvent_RiInactive:0) + (cnow.exithunt != cprev.exithunt ? MgslEvent_ExitHuntMode:0) + (cnow.rxidle != cprev.rxidle ? MgslEvent_IdleReceived:0) ); if (events) break; cprev = cnow; oldsigs = newsigs; } remove_wait_queue(&info->event_wait_q, &wait); set_current_state(TASK_RUNNING); if (mask & MgslEvent_ExitHuntMode) { spin_lock_irqsave(&info->lock,flags); if (!waitqueue_active(&info->event_wait_q)) irq_disable(info, CHA, IRQ_EXITHUNT); spin_unlock_irqrestore(&info->lock,flags); }exit: if (rc == 0) PUT_USER(rc, events, mask_ptr); return rc;}static int modem_input_wait(MGSLPC_INFO *info,int arg){ unsigned long flags; int rc; struct mgsl_icount cprev, cnow; DECLARE_WAITQUEUE(wait, current); /* save current irq counts */ spin_lock_irqsave(&info->lock,flags); cprev = info->icount; add_wait_queue(&info->status_event_wait_q, &wait); set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irqrestore(&info->lock,flags); for(;;) { schedule(); if (signal_pending(current)) { rc = -ERESTARTSYS; break; } /* get new irq counts */ spin_lock_irqsave(&info->lock,flags); cnow = info->icount; set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irqrestore(&info->lock,flags); /* if no change, wait aborted for some reason */ if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { rc = -EIO; break; } /* check for change in caller specified modem input */ if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) || (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) || (arg & TIOCM_CD && cnow.dcd != cprev.dcd) || (arg & TIOCM_CTS && cnow.cts != cprev.cts)) { rc = 0; break; } cprev = cnow; } remove_wait_queue(&info->status_event_wait_q, &wait); set_current_state(TASK_RUNNING); return rc;}/* Return state of the serial control/status signals * * Arguments: info pointer to device instance data * value pointer to int to hold returned info * * Return Value: 0 if success, otherwise error code */static int get_modem_info(MGSLPC_INFO * info, unsigned int *value){ unsigned int result; unsigned long flags; int err; spin_lock_irqsave(&info->lock,flags); get_signals(info); spin_unlock_irqrestore(&info->lock,flags); result = ((info->serial_signals & SerialSignal_RTS) ? TIOCM_RTS:0) | ((info->serial_signals & SerialSignal_DTR) ? TIOCM_DTR:0) | ((info->serial_signals & SerialSignal_DCD) ? TIOCM_CAR:0) | ((info->serial_signals & SerialSignal_RI) ? TIOCM_RNG:0) | ((info->serial_signals & SerialSignal_DSR) ? TIOCM_DSR:0) | ((info->serial_signals & SerialSignal_CTS) ? TIOCM_CTS:0); if (debug_level >= DEBUG_LEVEL_INFO) printk("mgslpc_get_modem_info %s value=%08X\n", info->device_name, result); PUT_USER(err,result,value); return err ? -EFAULT : 0;}/* Set the state of the modem control signals (DTR/RTS) * * Arguments: * * info pointer to device instance data * cmd signal command: TIOCMBIS = set bit TIOCMBIC = clear bit * TIOCMSET = set/clear signal values * value bit mask for command * * Return Value: 0 if success, otherwise error code */static int set_modem_info(MGSLPC_INFO * info, unsigned int cmd, unsigned int *value){ int error; unsigned int arg; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("mgslpc_set_modem_info %s\n", info->device_name); GET_USER(error,arg,value); if (error) return error; switch (cmd) { case TIOCMBIS: if (arg & TIOCM_RTS) info->serial_signals |= SerialSignal_RTS; if (arg & TIOCM_DTR) info->serial_signals |= SerialSignal_DTR; break; case TIOCMBIC: if (arg & TIOCM_RTS) info->serial_signals &= ~SerialSignal_RTS; if (arg & TIOCM_DTR) info->serial_signals &= ~SerialSignal_DTR; break; case TIOCMSET: if (arg & TIOCM_RTS) info->serial_signals |= SerialSignal_RTS; else info->serial_signals &= ~SerialSignal_RTS; if (arg & TIOCM_DTR) info->serial_signals |= SerialSignal_DTR; else info->serial_signals &= ~SerialSignal_DTR; break; default: return -EINVAL; } spin_lock_irqsave(&info->lock,flags); set_signals(info); spin_unlock_irqrestore(&info->lock,flags); return 0;}/* Set or clear transmit break condition * * Arguments: tty pointer to tty instance data * break_state -1=set break condition, 0=clear */static void mgslpc_break(struct tty_struct *tty, int break_state){ MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_break(%s,%d)\n", __FILE__,__LINE__, info->device_name, break_state); if (mgslpc_paranoia_check(info, tty->device, "mgslpc_break")) return; spin_lock_irqsave(&info->lock,flags); if (break_state == -1) set_reg_bits(info, CHA+DAFO, BIT6); else clear_reg_bit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -