in serial/jsm/jsm_neo.c [925:1090]
static void neo_param(struct jsm_channel *ch)
{
u8 lcr = 0;
u8 uart_lcr, ier;
u32 baud;
int quot;
struct jsm_board *bd;
bd = ch->ch_bd;
if (!bd)
return;
/*
* If baud rate is zero, flush queues, and set mval to drop DTR.
*/
if ((ch->ch_c_cflag & (CBAUD)) == 0) {
ch->ch_r_head = ch->ch_r_tail = 0;
ch->ch_e_head = ch->ch_e_tail = 0;
neo_flush_uart_write(ch);
neo_flush_uart_read(ch);
ch->ch_flags |= (CH_BAUD0);
ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR);
neo_assert_modem_signals(ch);
return;
} else {
int i;
unsigned int cflag;
static struct {
unsigned int rate;
unsigned int cflag;
} baud_rates[] = {
{ 921600, B921600 },
{ 460800, B460800 },
{ 230400, B230400 },
{ 115200, B115200 },
{ 57600, B57600 },
{ 38400, B38400 },
{ 19200, B19200 },
{ 9600, B9600 },
{ 4800, B4800 },
{ 2400, B2400 },
{ 1200, B1200 },
{ 600, B600 },
{ 300, B300 },
{ 200, B200 },
{ 150, B150 },
{ 134, B134 },
{ 110, B110 },
{ 75, B75 },
{ 50, B50 },
};
cflag = C_BAUD(ch->uart_port.state->port.tty);
baud = 9600;
for (i = 0; i < ARRAY_SIZE(baud_rates); i++) {
if (baud_rates[i].cflag == cflag) {
baud = baud_rates[i].rate;
break;
}
}
if (ch->ch_flags & CH_BAUD0)
ch->ch_flags &= ~(CH_BAUD0);
}
if (ch->ch_c_cflag & PARENB)
lcr |= UART_LCR_PARITY;
if (!(ch->ch_c_cflag & PARODD))
lcr |= UART_LCR_EPAR;
/*
* Not all platforms support mark/space parity,
* so this will hide behind an ifdef.
*/
#ifdef CMSPAR
if (ch->ch_c_cflag & CMSPAR)
lcr |= UART_LCR_SPAR;
#endif
if (ch->ch_c_cflag & CSTOPB)
lcr |= UART_LCR_STOP;
switch (ch->ch_c_cflag & CSIZE) {
case CS5:
lcr |= UART_LCR_WLEN5;
break;
case CS6:
lcr |= UART_LCR_WLEN6;
break;
case CS7:
lcr |= UART_LCR_WLEN7;
break;
case CS8:
default:
lcr |= UART_LCR_WLEN8;
break;
}
ier = readb(&ch->ch_neo_uart->ier);
uart_lcr = readb(&ch->ch_neo_uart->lcr);
quot = ch->ch_bd->bd_dividend / baud;
if (quot != 0) {
writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr);
writeb((quot & 0xff), &ch->ch_neo_uart->txrx);
writeb((quot >> 8), &ch->ch_neo_uart->ier);
writeb(lcr, &ch->ch_neo_uart->lcr);
}
if (uart_lcr != lcr)
writeb(lcr, &ch->ch_neo_uart->lcr);
if (ch->ch_c_cflag & CREAD)
ier |= (UART_IER_RDI | UART_IER_RLSI);
ier |= (UART_IER_THRI | UART_IER_MSI);
writeb(ier, &ch->ch_neo_uart->ier);
/* Set new start/stop chars */
neo_set_new_start_stop_chars(ch);
if (ch->ch_c_cflag & CRTSCTS)
neo_set_cts_flow_control(ch);
else if (ch->ch_c_iflag & IXON) {
/* If start/stop is set to disable, then we should disable flow control */
if ((ch->ch_startc == __DISABLED_CHAR) || (ch->ch_stopc == __DISABLED_CHAR))
neo_set_no_output_flow_control(ch);
else
neo_set_ixon_flow_control(ch);
}
else
neo_set_no_output_flow_control(ch);
if (ch->ch_c_cflag & CRTSCTS)
neo_set_rts_flow_control(ch);
else if (ch->ch_c_iflag & IXOFF) {
/* If start/stop is set to disable, then we should disable flow control */
if ((ch->ch_startc == __DISABLED_CHAR) || (ch->ch_stopc == __DISABLED_CHAR))
neo_set_no_input_flow_control(ch);
else
neo_set_ixoff_flow_control(ch);
}
else
neo_set_no_input_flow_control(ch);
/*
* Adjust the RX FIFO Trigger level if baud is less than 9600.
* Not exactly elegant, but this is needed because of the Exar chip's
* delay on firing off the RX FIFO interrupt on slower baud rates.
*/
if (baud < 9600) {
writeb(1, &ch->ch_neo_uart->rfifo);
ch->ch_r_tlevel = 1;
}
neo_assert_modem_signals(ch);
/* Get current status of the modem signals now */
neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
return;
}