static int rs_set_real_termios (void *ptr) { struct rs_port *port = ptr; int t; switch (port->gs.baud) { /* Save some typing work... */ #define e(x) case x:t= TX3912_UART_CTRL2_B ## x ; break e(300);e(600);e(1200);e(2400);e(4800);e(9600); e(19200);e(38400);e(57600);e(76800);e(115200);e(230400); case 0 :t = -1; break; default: /* Can I return "invalid"? */ t = TX3912_UART_CTRL2_B9600; printk (KERN_INFO "rs: unsupported baud rate: %d.\n", port->gs.baud); break; } #undef e if (t >= 0) { /* Jim: Set Hardware Baud rate - there is some good code in drivers/char/serial.c */ /* Program hardware for parity, data bits, stop bits (note: these are hardcoded to 8N1 */ UartA_Ctrl1 &= 0xf000000f; UartA_Ctrl1 &= ~(UART_DIS_TXD | SER_SEVEN_BIT | SER_EVEN_PARITY | SER_TWO_STOP); #define CFLAG port->gs.tty->termios->c_cflag if (C_PARENB(port->gs.tty)) { if (!C_PARODD(port->gs.tty)) UartA_Ctrl1 |= SER_EVEN_PARITY; else UartA_Ctrl1 |= SER_ODD_PARITY; } if ((CFLAG & CSIZE)==CS6) printk(KERN_ERR "6 bits not supported\n"); if ((CFLAG & CSIZE)==CS5) printk(KERN_ERR "5 bits not supported\n"); if ((CFLAG & CSIZE)==CS7) UartA_Ctrl1 |= SER_SEVEN_BIT; if (C_CSTOPB(port->gs.tty)) UartA_Ctrl1 |= SER_TWO_STOP; outl(t, port->base + TX3912_UART_CTRL2); outl(0, port->base + TX3912_UART_DMA_CTRL1); outl(0, port->base + TX3912_UART_DMA_CTRL2); UartA_Ctrl1 |= TX3912_UART_CTRL1_UARTON; /* wait until UARTA is stable */ while (~UartA_Ctrl1 & TX3912_UART_CTRL1_UARTON); } func_exit (); return 0; }
static int rs_set_real_termios (void *ptr) { unsigned int ctrl1 = 0; unsigned int ctrl2 = 0; /* Set baud rate */ switch (rs_port->gs.baud) { case 0: goto done; case 1200: ctrl2 = TX3912_UART_CTRL2_B1200; break; case 2400: ctrl2 = TX3912_UART_CTRL2_B2400; break; case 4800: ctrl2 = TX3912_UART_CTRL2_B4800; break; case 9600: ctrl2 = TX3912_UART_CTRL2_B9600; break; case 19200: ctrl2 = TX3912_UART_CTRL2_B19200; break; case 38400: ctrl2 = TX3912_UART_CTRL2_B38400; break; case 57600: ctrl2 = TX3912_UART_CTRL2_B57600; break; case 115200: default: ctrl2 = TX3912_UART_CTRL2_B115200; break; } /* Clear current UARTA settings */ ctrl1 = inl(TX3912_UARTA_CTRL1) & 0xf000000f; /* Set parity */ if(C_PARENB(rs_port->gs.tty)) { if (!C_PARODD(rs_port->gs.tty)) ctrl1 |= (TX3912_UART_CTRL1_ENPARITY | TX3912_UART_CTRL1_EVENPARITY); else ctrl1 |= TX3912_UART_CTRL1_ENPARITY; } /* Set data size */ switch(rs_port->gs.tty->termios->c_cflag & CSIZE) { case CS7: ctrl1 |= TX3912_UART_CTRL1_BIT_7; break; case CS5: case CS6: printk(KERN_ERR "Data byte size unsupported. Defaulting to CS8\n"); case CS8: default: ctrl1 &= ~TX3912_UART_CTRL1_BIT_7; } /* Set stop bits */ if(C_CSTOPB(rs_port->gs.tty)) ctrl1 |= TX3912_UART_CTRL1_TWOSTOP; /* Write the control registers */ outl(ctrl2, TX3912_UARTA_CTRL2); outl(0, TX3912_UARTA_DMA_CTRL1); outl(0, TX3912_UARTA_DMA_CTRL2); outl(ctrl1, TX3912_UARTA_CTRL1); /* Loop until the UART is on */ while(~inl(TX3912_UARTA_CTRL1) & TX3912_UART_CTRL1_UARTON); done: func_exit(); return 0; }
static void mxu1_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct mxu1_port *mxport = usb_get_serial_port_data(port); struct mxu1_uart_config *config; tcflag_t cflag, iflag; speed_t baud; int status; unsigned int mcr; dev_dbg(&port->dev, "%s\n", __func__); cflag = tty->termios.c_cflag; iflag = tty->termios.c_iflag; if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios) && tty->termios.c_iflag == old_termios->c_iflag) { dev_dbg(&port->dev, "%s - nothing to change\n", __func__); return; } dev_dbg(&port->dev, "%s - clfag %08x, iflag %08x\n", __func__, cflag, iflag); if (old_termios) { dev_dbg(&port->dev, "%s - old clfag %08x, old iflag %08x\n", __func__, old_termios->c_cflag, old_termios->c_iflag); } config = kzalloc(sizeof(*config), GFP_KERNEL); if (!config) return; config->wFlags = 0; /* these flags must be set */ config->wFlags |= MXU1_UART_ENABLE_MS_INTS; config->wFlags |= MXU1_UART_ENABLE_AUTO_START_DMA; if (mxport->mxp_send_break == MXU1_LCR_BREAK) config->wFlags |= MXU1_UART_SEND_BREAK_SIGNAL; config->bUartMode = (u8)(mxport->mxp_uart_mode); switch (C_CSIZE(tty)) { case CS5: config->bDataBits = MXU1_UART_5_DATA_BITS; break; case CS6: config->bDataBits = MXU1_UART_6_DATA_BITS; break; case CS7: config->bDataBits = MXU1_UART_7_DATA_BITS; break; default: case CS8: config->bDataBits = MXU1_UART_8_DATA_BITS; break; } if (C_PARENB(tty)) { config->wFlags |= MXU1_UART_ENABLE_PARITY_CHECKING; if (C_CMSPAR(tty)) { if (C_PARODD(tty)) config->bParity = MXU1_UART_MARK_PARITY; else config->bParity = MXU1_UART_SPACE_PARITY; } else { if (C_PARODD(tty)) config->bParity = MXU1_UART_ODD_PARITY; else config->bParity = MXU1_UART_EVEN_PARITY; } } else { config->bParity = MXU1_UART_NO_PARITY; } if (C_CSTOPB(tty)) config->bStopBits = MXU1_UART_2_STOP_BITS; else config->bStopBits = MXU1_UART_1_STOP_BITS; if (C_CRTSCTS(tty)) { /* RTS flow control must be off to drop RTS for baud rate B0 */ if (C_BAUD(tty) != B0) config->wFlags |= MXU1_UART_ENABLE_RTS_IN; config->wFlags |= MXU1_UART_ENABLE_CTS_OUT; } if (I_IXOFF(tty) || I_IXON(tty)) { config->cXon = START_CHAR(tty); config->cXoff = STOP_CHAR(tty); if (I_IXOFF(tty)) config->wFlags |= MXU1_UART_ENABLE_X_IN; if (I_IXON(tty)) config->wFlags |= MXU1_UART_ENABLE_X_OUT; } baud = tty_get_baud_rate(tty); if (!baud) baud = 9600; config->wBaudRate = MXU1_BAUD_BASE / baud; dev_dbg(&port->dev, "%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d\n", __func__, baud, config->wBaudRate, config->wFlags, config->bDataBits, config->bParity, config->bStopBits, config->cXon, config->cXoff, config->bUartMode); cpu_to_be16s(&config->wBaudRate); cpu_to_be16s(&config->wFlags); status = mxu1_send_ctrl_data_urb(port->serial, MXU1_SET_CONFIG, 0, MXU1_UART1_PORT, (u8 *)config, sizeof(*config)); if (status) dev_err(&port->dev, "cannot set config: %d\n", status); mutex_lock(&mxport->mxp_mutex); mcr = mxport->mxp_mcr; if (C_BAUD(tty) == B0) mcr &= ~(MXU1_MCR_DTR | MXU1_MCR_RTS); else if (old_termios && (old_termios->c_cflag & CBAUD) == B0) mcr |= ~(MXU1_MCR_DTR | MXU1_MCR_RTS); status = mxu1_set_mcr(port, mcr); if (status) dev_err(&port->dev, "cannot set modem control: %d\n", status); else mxport->mxp_mcr = mcr; mutex_unlock(&mxport->mxp_mutex); kfree(config); }
static void pl2303_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct pl2303_serial_private *spriv = usb_get_serial_data(serial); struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned char *buf; int i; u8 control; if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios)) return; buf = kzalloc(7, GFP_KERNEL); if (!buf) { dev_err(&port->dev, "%s - out of memory.\n", __func__); /* Report back no change occurred */ if (old_termios) tty->termios = *old_termios; return; } i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, 0, 0, buf, 7, 100); dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); switch (C_CSIZE(tty)) { case CS5: buf[6] = 5; break; case CS6: buf[6] = 6; break; case CS7: buf[6] = 7; break; default: case CS8: buf[6] = 8; } dev_dbg(&port->dev, "data bits = %d\n", buf[6]); /* For reference buf[0]:buf[3] baud rate value */ pl2303_encode_baudrate(tty, port, &buf[0]); /* For reference buf[4]=0 is 1 stop bits */ /* For reference buf[4]=1 is 1.5 stop bits */ /* For reference buf[4]=2 is 2 stop bits */ if (C_CSTOPB(tty)) { /* * NOTE: Comply with "real" UARTs / RS232: * use 1.5 instead of 2 stop bits with 5 data bits */ if (C_CSIZE(tty) == CS5) { buf[4] = 1; dev_dbg(&port->dev, "stop bits = 1.5\n"); } else { buf[4] = 2; dev_dbg(&port->dev, "stop bits = 2\n"); } } else { buf[4] = 0; dev_dbg(&port->dev, "stop bits = 1\n"); } if (C_PARENB(tty)) { /* For reference buf[5]=0 is none parity */ /* For reference buf[5]=1 is odd parity */ /* For reference buf[5]=2 is even parity */ /* For reference buf[5]=3 is mark parity */ /* For reference buf[5]=4 is space parity */ if (C_PARODD(tty)) { if (tty->termios.c_cflag & CMSPAR) { buf[5] = 3; dev_dbg(&port->dev, "parity = mark\n"); } else { buf[5] = 1; dev_dbg(&port->dev, "parity = odd\n"); } } else { if (tty->termios.c_cflag & CMSPAR) { buf[5] = 4; dev_dbg(&port->dev, "parity = space\n"); } else { buf[5] = 2; dev_dbg(&port->dev, "parity = even\n"); } } } else { buf[5] = 0; dev_dbg(&port->dev, "parity = none\n"); } /* * Some PL2303 are known to lose bytes if you change serial settings * even to the same values as before. Thus we actually need to filter * in this specific case. * * Note that the tty_termios_hw_change check above is not sufficient * as a previously requested baud rate may differ from the one * actually used (and stored in old_termios). * * NOTE: No additional locking needed for line_settings as it is * only used in set_termios, which is serialised against itself. */ if (!old_termios || memcmp(buf, priv->line_settings, 7)) { i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, 0, 0, buf, 7, 100); dev_dbg(&port->dev, "0x21:0x20:0:0 %d\n", i); if (i == 7) memcpy(priv->line_settings, buf, 7); } /* change control lines if we are switching to or from B0 */ spin_lock_irqsave(&priv->lock, flags); control = priv->line_control; if (C_BAUD(tty) == B0) priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); else if (old_termios && (old_termios->c_cflag & CBAUD) == B0) priv->line_control |= (CONTROL_DTR | CONTROL_RTS); if (control != priv->line_control) { control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags); pl2303_set_control_lines(port, control); } else { spin_unlock_irqrestore(&priv->lock, flags); } memset(buf, 0, 7); i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, 0, 0, buf, 7, 100); dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); if (C_CRTSCTS(tty)) { if (spriv->type == HX) pl2303_vendor_write(0x0, 0x61, serial); else pl2303_vendor_write(0x0, 0x41, serial); } else { pl2303_vendor_write(0x0, 0x0, serial); } kfree(buf); }