📄 synclink_cs.c
字号:
/* if B0 rate (hangup) specified then negate DTR and RTS */ /* otherwise assert DTR and RTS */ if (cflag & CBAUD) info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; else info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); /* byte size and parity */ switch (cflag & CSIZE) { case CS5: info->params.data_bits = 5; break; case CS6: info->params.data_bits = 6; break; case CS7: info->params.data_bits = 7; break; case CS8: info->params.data_bits = 8; break; default: info->params.data_bits = 7; break; } if (cflag & CSTOPB) info->params.stop_bits = 2; else info->params.stop_bits = 1; info->params.parity = ASYNC_PARITY_NONE; if (cflag & PARENB) { if (cflag & PARODD) info->params.parity = ASYNC_PARITY_ODD; else info->params.parity = ASYNC_PARITY_EVEN;#ifdef CMSPAR if (cflag & CMSPAR) info->params.parity = ASYNC_PARITY_SPACE;#endif } /* calculate number of jiffies to transmit a full * FIFO (32 bytes) at specified data rate */ bits_per_char = info->params.data_bits + info->params.stop_bits + 1; /* if port data rate is set to 460800 or less then * allow tty settings to override, otherwise keep the * current data rate. */ if (info->params.data_rate <= 460800) { info->params.data_rate = tty_get_baud_rate(info->tty); } if ( info->params.data_rate ) { info->timeout = (32*HZ*bits_per_char) / info->params.data_rate; } info->timeout += HZ/50; /* Add .02 seconds of slop */ if (cflag & CRTSCTS) info->flags |= ASYNC_CTS_FLOW; else info->flags &= ~ASYNC_CTS_FLOW; if (cflag & CLOCAL) info->flags &= ~ASYNC_CHECK_CD; else info->flags |= ASYNC_CHECK_CD; /* process tty input control flags */ info->read_status_mask = 0; if (I_INPCK(info->tty)) info->read_status_mask |= BIT7 | BIT6; if (I_IGNPAR(info->tty)) info->ignore_status_mask |= BIT7 | BIT6; mgslpc_program_hw(info);}/* Add a character to the transmit buffer */static void mgslpc_put_char(struct tty_struct *tty, unsigned char ch){ MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) { printk( "%s(%d):mgslpc_put_char(%d) on %s\n", __FILE__,__LINE__,ch,info->device_name); } if (mgslpc_paranoia_check(info, tty->name, "mgslpc_put_char")) return; if (!tty || !info->tx_buf) return; spin_lock_irqsave(&info->lock,flags); if (info->params.mode == MGSL_MODE_ASYNC || !info->tx_active) { if (info->tx_count < TXBUFSIZE - 1) { info->tx_buf[info->tx_put++] = ch; info->tx_put &= TXBUFSIZE-1; info->tx_count++; } } spin_unlock_irqrestore(&info->lock,flags);}/* Enable transmitter so remaining characters in the * transmit buffer are sent. */static void mgslpc_flush_chars(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_flush_chars() entry on %s tx_count=%d\n", __FILE__,__LINE__,info->device_name,info->tx_count); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_flush_chars")) return; if (info->tx_count <= 0 || tty->stopped || tty->hw_stopped || !info->tx_buf) return; if (debug_level >= DEBUG_LEVEL_INFO) printk( "%s(%d):mgslpc_flush_chars() entry on %s starting transmitter\n", __FILE__,__LINE__,info->device_name); spin_lock_irqsave(&info->lock,flags); if (!info->tx_active) tx_start(info); spin_unlock_irqrestore(&info->lock,flags);}/* Send a block of data * * Arguments: * * tty pointer to tty information structure * buf pointer to buffer containing send data * count size of send data in bytes * * Returns: number of characters written */static int mgslpc_write(struct tty_struct * tty, const unsigned char *buf, int count){ int c, ret = 0; MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk( "%s(%d):mgslpc_write(%s) count=%d\n", __FILE__,__LINE__,info->device_name,count); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_write") || !tty || !info->tx_buf) goto cleanup; if (info->params.mode == MGSL_MODE_HDLC) { if (count > TXBUFSIZE) { ret = -EIO; goto cleanup; } if (info->tx_active) goto cleanup; else if (info->tx_count) goto start; } for (;;) { c = min(count, min(TXBUFSIZE - info->tx_count - 1, TXBUFSIZE - info->tx_put)); if (c <= 0) break; memcpy(info->tx_buf + info->tx_put, buf, c); spin_lock_irqsave(&info->lock,flags); info->tx_put = (info->tx_put + c) & (TXBUFSIZE-1); info->tx_count += c; spin_unlock_irqrestore(&info->lock,flags); buf += c; count -= c; ret += c; }start: if (info->tx_count && !tty->stopped && !tty->hw_stopped) { spin_lock_irqsave(&info->lock,flags); if (!info->tx_active) tx_start(info); spin_unlock_irqrestore(&info->lock,flags); }cleanup: if (debug_level >= DEBUG_LEVEL_INFO) printk( "%s(%d):mgslpc_write(%s) returning=%d\n", __FILE__,__LINE__,info->device_name,ret); return ret;}/* Return the count of free bytes in transmit buffer */static int mgslpc_write_room(struct tty_struct *tty){ MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; int ret; if (mgslpc_paranoia_check(info, tty->name, "mgslpc_write_room")) return 0; if (info->params.mode == MGSL_MODE_HDLC) { /* HDLC (frame oriented) mode */ if (info->tx_active) return 0; else return HDLC_MAX_FRAME_SIZE; } else { ret = TXBUFSIZE - info->tx_count - 1; if (ret < 0) ret = 0; } if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_write_room(%s)=%d\n", __FILE__,__LINE__, info->device_name, ret); return ret;}/* Return the count of bytes in transmit buffer */static int mgslpc_chars_in_buffer(struct tty_struct *tty){ MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; int rc; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_chars_in_buffer(%s)\n", __FILE__,__LINE__, info->device_name ); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_chars_in_buffer")) return 0; if (info->params.mode == MGSL_MODE_HDLC) rc = info->tx_active ? info->max_frame_size : 0; else rc = info->tx_count; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_chars_in_buffer(%s)=%d\n", __FILE__,__LINE__, info->device_name, rc); return rc;}/* Discard all data in the send buffer */static void mgslpc_flush_buffer(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_flush_buffer(%s) entry\n", __FILE__,__LINE__, info->device_name ); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_flush_buffer")) return; spin_lock_irqsave(&info->lock,flags); info->tx_count = info->tx_put = info->tx_get = 0; del_timer(&info->tx_timer); spin_unlock_irqrestore(&info->lock,flags); wake_up_interruptible(&tty->write_wait); tty_wakeup(tty);}/* Send a high-priority XON/XOFF character */static void mgslpc_send_xchar(struct tty_struct *tty, char ch){ MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_send_xchar(%s,%d)\n", __FILE__,__LINE__, info->device_name, ch ); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_send_xchar")) return; info->x_char = ch; if (ch) { spin_lock_irqsave(&info->lock,flags); if (!info->tx_enabled) tx_start(info); spin_unlock_irqrestore(&info->lock,flags); }}/* Signal remote device to throttle send data (our receive data) */static void mgslpc_throttle(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_throttle(%s) entry\n", __FILE__,__LINE__, info->device_name ); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_throttle")) return; if (I_IXOFF(tty)) mgslpc_send_xchar(tty, STOP_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); }}/* 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->name, "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 *user_icount){ int err; if (debug_level >= DEBUG_LEVEL_INFO) printk("get_params(%s)\n", info->device_name); if (!user_icount) { memset(&info->icount, 0, sizeof(info->icount)); } else { 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 *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 __user *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 __user *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 __user *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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -