📄 synclink_cs.c
字号:
info->flags |= ASYNC_INITIALIZED; return 0;}/* Called by mgslpc_close() and mgslpc_hangup() to shutdown hardware */static void shutdown(MGSLPC_INFO * info){ unsigned long flags; if (!(info->flags & ASYNC_INITIALIZED)) return; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_shutdown(%s)\n", __FILE__,__LINE__, info->device_name ); /* clear status wait queue because status changes */ /* can't happen after shutting down the hardware */ wake_up_interruptible(&info->status_event_wait_q); wake_up_interruptible(&info->event_wait_q); del_timer(&info->tx_timer); if (info->tx_buf) { free_page((unsigned long) info->tx_buf); info->tx_buf = NULL; } spin_lock_irqsave(&info->lock,flags); rx_stop(info); tx_stop(info); /* TODO:disable interrupts instead of reset to preserve signal states */ reset_device(info); if (!info->tty || info->tty->termios->c_cflag & HUPCL) { info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); set_signals(info); } spin_unlock_irqrestore(&info->lock,flags); release_resources(info); if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); info->flags &= ~ASYNC_INITIALIZED;}static void mgslpc_program_hw(MGSLPC_INFO *info){ unsigned long flags; spin_lock_irqsave(&info->lock,flags); rx_stop(info); tx_stop(info); info->tx_count = info->tx_put = info->tx_get = 0; if (info->params.mode == MGSL_MODE_HDLC || info->netcount) hdlc_mode(info); else async_mode(info); set_signals(info); info->dcd_chkcount = 0; info->cts_chkcount = 0; info->ri_chkcount = 0; info->dsr_chkcount = 0; irq_enable(info, CHB, IRQ_DCD | IRQ_CTS); port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI); get_signals(info); if (info->netcount || info->tty->termios->c_cflag & CREAD) rx_start(info); spin_unlock_irqrestore(&info->lock,flags);}/* Reconfigure adapter based on new parameters */static void mgslpc_change_params(MGSLPC_INFO *info){ unsigned cflag; int bits_per_char; if (!info->tty || !info->tty->termios) return; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_change_params(%s)\n", __FILE__,__LINE__, info->device_name ); cflag = info->tty->termios->c_cflag; /* 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 *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -