diff options
Diffstat (limited to 'drivers/tty/serial/crisv10.c')
| -rw-r--r-- | drivers/tty/serial/crisv10.c | 393 |
1 files changed, 107 insertions, 286 deletions
diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index 1dfba7b779c..d567ac5d3af 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -34,9 +34,9 @@ static char *serial_version = "$Revision: 1.25 $"; #include <asm/irq.h> #include <asm/dma.h> -#include <asm/system.h> #include <arch/svinto.h> +#include <arch/system.h> /* non-arch dependent serial structures are in linux/serial.h */ #include <linux/serial.h> @@ -169,7 +169,6 @@ static int get_lsr_info(struct e100_serial *info, unsigned int *value); #define DEF_BAUD 115200 /* 115.2 kbit/s */ -#define STD_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) #define DEF_RX 0x20 /* or SERIAL_CTRL_W >> 8 */ /* Default value of tx_ctrl register: has txd(bit 7)=1 (idle) as default */ #define DEF_TX 0x80 /* or SERIAL_CTRL_B */ @@ -246,7 +245,6 @@ static struct e100_serial rs_table[] = { .ifirstadr = R_DMA_CH7_FIRST, .icmdadr = R_DMA_CH7_CMD, .idescradr = R_DMA_CH7_DESCR, - .flags = STD_FLAGS, .rx_ctrl = DEF_RX, .tx_ctrl = DEF_TX, .iseteop = 2, @@ -288,7 +286,6 @@ static struct e100_serial rs_table[] = { #endif }, /* ttyS0 */ -#ifndef CONFIG_SVINTO_SIM { .baud = DEF_BAUD, .ioport = (unsigned char *)R_SERIAL1_CTRL, .irq = 1U << 16, /* uses DMA 8 and 9 */ @@ -300,7 +297,6 @@ static struct e100_serial rs_table[] = { .ifirstadr = R_DMA_CH9_FIRST, .icmdadr = R_DMA_CH9_CMD, .idescradr = R_DMA_CH9_DESCR, - .flags = STD_FLAGS, .rx_ctrl = DEF_RX, .tx_ctrl = DEF_TX, .iseteop = 3, @@ -356,7 +352,6 @@ static struct e100_serial rs_table[] = { .ifirstadr = R_DMA_CH3_FIRST, .icmdadr = R_DMA_CH3_CMD, .idescradr = R_DMA_CH3_DESCR, - .flags = STD_FLAGS, .rx_ctrl = DEF_RX, .tx_ctrl = DEF_TX, .iseteop = 0, @@ -410,7 +405,6 @@ static struct e100_serial rs_table[] = { .ifirstadr = R_DMA_CH5_FIRST, .icmdadr = R_DMA_CH5_CMD, .idescradr = R_DMA_CH5_DESCR, - .flags = STD_FLAGS, .rx_ctrl = DEF_RX, .tx_ctrl = DEF_TX, .iseteop = 1, @@ -452,7 +446,6 @@ static struct e100_serial rs_table[] = { .dma_in_enabled = 0 #endif } /* ttyS3 */ -#endif }; @@ -952,23 +945,10 @@ static const struct control_pins e100_modem_pins[NR_PORTS] = /* Input */ #define E100_DSR_GET(info) ((*e100_modem_pins[(info)->line].dsr_port) & e100_modem_pins[(info)->line].dsr_mask) - -/* - * tmp_buf is used as a temporary buffer by serial_write. We need to - * lock it in case the memcpy_fromfs blocks while swapping in a page, - * and some other program tries to do a serial write at the same time. - * Since the lock will only come under contention when the system is - * swapping and available memory is low, it makes sense to share one - * buffer across all the serial ports, since it significantly saves - * memory if large numbers of serial ports are open. - */ -static unsigned char *tmp_buf; -static DEFINE_MUTEX(tmp_buf_mutex); - /* Calculate the chartime depending on baudrate, numbor of bits etc. */ static void update_char_time(struct e100_serial * info) { - tcflag_t cflags = info->port.tty->termios->c_cflag; + tcflag_t cflags = info->port.tty->termios.c_cflag; int bits; /* calc. number of bits / data byte */ @@ -1053,7 +1033,6 @@ cflag_to_etrax_baud(unsigned int cflag) static inline void e100_dtr(struct e100_serial *info, int set) { -#ifndef CONFIG_SVINTO_SIM unsigned char mask = e100_modem_pins[info->line].dtr_mask; #ifdef SERIAL_DEBUG_IO @@ -1078,7 +1057,6 @@ e100_dtr(struct e100_serial *info, int set) info->line, *e100_modem_pins[info->line].dtr_shadow, E100_DTR_GET(info)); #endif -#endif } /* set = 0 means 3.3V on the pin, bitvalue: 0=active, 1=inactive @@ -1087,7 +1065,6 @@ e100_dtr(struct e100_serial *info, int set) static inline void e100_rts(struct e100_serial *info, int set) { -#ifndef CONFIG_SVINTO_SIM unsigned long flags; local_irq_save(flags); info->rx_ctrl &= ~E100_RTS_MASK; @@ -1097,7 +1074,6 @@ e100_rts(struct e100_serial *info, int set) #ifdef SERIAL_DEBUG_IO printk("ser%i rts %i\n", info->line, set); #endif -#endif } @@ -1105,7 +1081,6 @@ e100_rts(struct e100_serial *info, int set) static inline void e100_ri_out(struct e100_serial *info, int set) { -#ifndef CONFIG_SVINTO_SIM /* RI is active low */ { unsigned char mask = e100_modem_pins[info->line].ri_mask; @@ -1117,12 +1092,10 @@ e100_ri_out(struct e100_serial *info, int set) *e100_modem_pins[info->line].ri_port = *e100_modem_pins[info->line].ri_shadow; local_irq_restore(flags); } -#endif } static inline void e100_cd_out(struct e100_serial *info, int set) { -#ifndef CONFIG_SVINTO_SIM /* CD is active low */ { unsigned char mask = e100_modem_pins[info->line].cd_mask; @@ -1134,27 +1107,22 @@ e100_cd_out(struct e100_serial *info, int set) *e100_modem_pins[info->line].cd_port = *e100_modem_pins[info->line].cd_shadow; local_irq_restore(flags); } -#endif } static inline void e100_disable_rx(struct e100_serial *info) { -#ifndef CONFIG_SVINTO_SIM /* disable the receiver */ info->ioport[REG_REC_CTRL] = (info->rx_ctrl &= ~IO_MASK(R_SERIAL0_REC_CTRL, rec_enable)); -#endif } static inline void e100_enable_rx(struct e100_serial *info) { -#ifndef CONFIG_SVINTO_SIM /* enable the receiver */ info->ioport[REG_REC_CTRL] = (info->rx_ctrl |= IO_MASK(R_SERIAL0_REC_CTRL, rec_enable)); -#endif } /* the rx DMA uses both the dma_descr and the dma_eop interrupts */ @@ -1486,7 +1454,7 @@ rs_stop(struct tty_struct *tty) xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->port.tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, stop); - if (tty->termios->c_iflag & IXON ) { + if (tty->termios.c_iflag & IXON ) { xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); } @@ -1509,7 +1477,7 @@ rs_start(struct tty_struct *tty) info->xmit.tail,SERIAL_XMIT_SIZE))); xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable); - if (tty->termios->c_iflag & IXON ) { + if (tty->termios.c_iflag & IXON ) { xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); } @@ -1572,24 +1540,6 @@ transmit_chars_dma(struct e100_serial *info) unsigned int c, sentl; struct etrax_dma_descr *descr; -#ifdef CONFIG_SVINTO_SIM - /* This will output too little if tail is not 0 always since - * we don't reloop to send the other part. Anyway this SHOULD be a - * no-op - transmit_chars_dma would never really be called during sim - * since rs_write does not write into the xmit buffer then. - */ - if (info->xmit.tail) - printk("Error in serial.c:transmit_chars-dma(), tail!=0\n"); - if (info->xmit.head != info->xmit.tail) { - SIMCOUT(info->xmit.buf + info->xmit.tail, - CIRC_CNT(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE)); - info->xmit.head = info->xmit.tail; /* move back head */ - info->tr_running = 0; - } - return; -#endif /* acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */ *info->oclrintradr = IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) | @@ -1773,8 +1723,7 @@ add_char_and_flag(struct e100_serial *info, unsigned char data, unsigned char fl info->icount.rx++; } else { - struct tty_struct *tty = info->port.tty; - tty_insert_flip_char(tty, data, flag); + tty_insert_flip_char(&info->port, data, flag); info->icount.rx++; } @@ -1861,13 +1810,6 @@ static void receive_chars_dma(struct e100_serial *info) struct tty_struct *tty; unsigned char rstat; -#ifdef CONFIG_SVINTO_SIM - /* No receive in the simulator. Will probably be when the rest of - * the serial interface works, and this piece will just be removed. - */ - return; -#endif - /* Acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */ *info->iclrintradr = IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) | @@ -1953,12 +1895,6 @@ static int start_recv_dma(struct e100_serial *info) static void start_receive(struct e100_serial *info) { -#ifdef CONFIG_SVINTO_SIM - /* No receive in the simulator. Will probably be when the rest of - * the serial interface works, and this piece will just be removed. - */ - return; -#endif if (info->uses_dma_in) { /* reset the input dma channel to be sure it works */ @@ -1991,17 +1927,6 @@ tr_interrupt(int irq, void *dev_id) int i; int handled = 0; -#ifdef CONFIG_SVINTO_SIM - /* No receive in the simulator. Will probably be when the rest of - * the serial interface works, and this piece will just be removed. - */ - { - const char *s = "What? tr_interrupt in simulator??\n"; - SIMCOUT(s,strlen(s)); - } - return IRQ_HANDLED; -#endif - /* find out the line that caused this irq and get it from rs_table */ ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */ @@ -2040,17 +1965,6 @@ rec_interrupt(int irq, void *dev_id) int i; int handled = 0; -#ifdef CONFIG_SVINTO_SIM - /* No receive in the simulator. Will probably be when the rest of - * the serial interface works, and this piece will just be removed. - */ - { - const char *s = "What? rec_interrupt in simulator??\n"; - SIMCOUT(s,strlen(s)); - } - return IRQ_HANDLED; -#endif - /* find out the line that caused this irq and get it from rs_table */ ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */ @@ -2118,22 +2032,15 @@ static int force_eop_if_needed(struct e100_serial *info) static void flush_to_flip_buffer(struct e100_serial *info) { - struct tty_struct *tty; struct etrax_recv_buffer *buffer; unsigned long flags; local_irq_save(flags); - tty = info->port.tty; - - if (!tty) { - local_irq_restore(flags); - return; - } while ((buffer = info->first_recv_buffer) != NULL) { unsigned int count = buffer->length; - tty_insert_flip_string(tty, buffer->buffer, count); + tty_insert_flip_string(&info->port, buffer->buffer, count); info->recv_cnt -= count; if (count == buffer->length) { @@ -2152,7 +2059,7 @@ static void flush_to_flip_buffer(struct e100_serial *info) local_irq_restore(flags); /* This includes a check for low-latency */ - tty_flip_buffer_push(tty); + tty_flip_buffer_push(&info->port); } static void check_flush_timeout(struct e100_serial *info) @@ -2179,7 +2086,7 @@ static void flush_timeout_function(unsigned long data) fast_timers[info->line].function = NULL; serial_fast_timer_expired++; - TIMERD(DEBUG_LOG(info->line, "flush_timout %i ", info->line)); + TIMERD(DEBUG_LOG(info->line, "flush_timeout %i ", info->line)); TIMERD(DEBUG_LOG(info->line, "num expired: %i\n", serial_fast_timer_expired)); check_flush_timeout(info); } @@ -2199,10 +2106,6 @@ timed_flush_handler(unsigned long ptr) struct e100_serial *info; int i; -#ifdef CONFIG_SVINTO_SIM - return; -#endif - for (i = 0; i < NR_PORTS; i++) { info = rs_table + i; if (info->uses_dma_in) @@ -2284,16 +2187,9 @@ TODO: The break will be delayed until an F or V character is received. */ -static -struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info) +static void handle_ser_rx_interrupt_no_dma(struct e100_serial *info) { unsigned long data_read; - struct tty_struct *tty = info->port.tty; - - if (!tty) { - printk("!NO TTY!\n"); - return info; - } /* Read data and status at the same time */ data_read = *((unsigned long *)&info->ioport[REG_DATA_STATUS32]); @@ -2351,8 +2247,7 @@ more_data: data_in, data_read); char flag = TTY_NORMAL; if (info->errorcode == ERRCODE_INSERT_BREAK) { - struct tty_struct *tty = info->port.tty; - tty_insert_flip_char(tty, 0, flag); + tty_insert_flip_char(&info->port, 0, flag); info->icount.rx++; } @@ -2366,7 +2261,7 @@ more_data: info->icount.frame++; flag = TTY_FRAME; } - tty_insert_flip_char(tty, data, flag); + tty_insert_flip_char(&info->port, data, flag); info->errorcode = 0; } info->break_detected_cnt = 0; @@ -2382,7 +2277,7 @@ more_data: log_int(rdpc(), 0, 0); } ); - tty_insert_flip_char(tty, + tty_insert_flip_char(&info->port, IO_EXTRACT(R_SERIAL0_READ, data_in, data_read), TTY_NORMAL); } else { @@ -2397,11 +2292,10 @@ more_data: goto more_data; } - tty_flip_buffer_push(info->port.tty); - return info; + tty_flip_buffer_push(&info->port); } -static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) +static void handle_ser_rx_interrupt(struct e100_serial *info) { unsigned char rstat; @@ -2410,7 +2304,8 @@ static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) #endif /* DEBUG_LOG(info->line, "ser_interrupt stat %03X\n", rstat | (i << 8)); */ if (!info->uses_dma_in) { - return handle_ser_rx_interrupt_no_dma(info); + handle_ser_rx_interrupt_no_dma(info); + return; } /* DMA is used */ rstat = info->ioport[REG_STATUS]; @@ -2517,7 +2412,6 @@ static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) /* Restarting the DMA never hurts */ *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart); START_FLUSH_FAST_TIMER(info, "ser_int"); - return info; } /* handle_ser_rx_interrupt */ static void handle_ser_tx_interrupt(struct e100_serial *info) @@ -2562,8 +2456,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) } /* Normal char-by-char interrupt */ if (info->xmit.head == info->xmit.tail - || info->port.tty->stopped - || info->port.tty->hw_stopped) { + || info->port.tty->stopped) { DFLOW(DEBUG_LOG(info->line, "tx_int: stopped %i\n", info->port.tty->stopped)); e100_disable_serial_tx_ready_irq(info); @@ -2750,7 +2643,7 @@ startup(struct e100_serial * info) /* if it was already initialized, skip this */ - if (info->flags & ASYNC_INITIALIZED) { + if (info->port.flags & ASYNC_INITIALIZED) { local_irq_restore(flags); free_page(xmit_page); return 0; @@ -2765,25 +2658,6 @@ startup(struct e100_serial * info) printk("starting up ttyS%d (xmit_buf 0x%p)...\n", info->line, info->xmit.buf); #endif -#ifdef CONFIG_SVINTO_SIM - /* Bits and pieces collected from below. Better to have them - in one ifdef:ed clause than to mix in a lot of ifdefs, - right? */ - if (info->port.tty) - clear_bit(TTY_IO_ERROR, &info->port.tty->flags); - - info->xmit.head = info->xmit.tail = 0; - info->first_recv_buffer = info->last_recv_buffer = NULL; - info->recv_cnt = info->max_recv_cnt = 0; - - for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++) - info->rec_descr[i].buf = NULL; - - /* No real action in the simulator, but may set info important - to ioctl. */ - change_speed(info); -#else - /* * Clear the FIFO buffers and disable them * (they will be reenabled in change_speed()) @@ -2873,9 +2747,7 @@ startup(struct e100_serial * info) e100_rts(info, 1); e100_dtr(info, 1); -#endif /* CONFIG_SVINTO_SIM */ - - info->flags |= ASYNC_INITIALIZED; + info->port.flags |= ASYNC_INITIALIZED; local_irq_restore(flags); return 0; @@ -2893,7 +2765,6 @@ shutdown(struct e100_serial * info) struct etrax_recv_buffer *buffer; int i; -#ifndef CONFIG_SVINTO_SIM /* shut down the transmitter and receiver */ DFLOW(DEBUG_LOG(info->line, "shutdown %i\n", info->line)); e100_disable_rx(info); @@ -2918,9 +2789,7 @@ shutdown(struct e100_serial * info) info->tr_running = 0; } -#endif /* CONFIG_SVINTO_SIM */ - - if (!(info->flags & ASYNC_INITIALIZED)) + if (!(info->port.flags & ASYNC_INITIALIZED)) return; #ifdef SERIAL_DEBUG_OPEN @@ -2942,7 +2811,7 @@ shutdown(struct e100_serial * info) descr[i].buf = 0; } - if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) { + if (!info->port.tty || (info->port.tty->termios.c_cflag & HUPCL)) { /* hang up DTR and RTS if HUPCL is enabled */ e100_dtr(info, 0); e100_rts(info, 0); /* could check CRTSCTS before doing this */ @@ -2951,7 +2820,7 @@ shutdown(struct e100_serial * info) if (info->port.tty) set_bit(TTY_IO_ERROR, &info->port.tty->flags); - info->flags &= ~ASYNC_INITIALIZED; + info->port.flags &= ~ASYNC_INITIALIZED; local_irq_restore(flags); } @@ -2966,17 +2835,17 @@ change_speed(struct e100_serial *info) unsigned long flags; /* first some safety checks */ - if (!info->port.tty || !info->port.tty->termios) + if (!info->port.tty) return; if (!info->ioport) return; - cflag = info->port.tty->termios->c_cflag; + cflag = info->port.tty->termios.c_cflag; /* possibly, the tx/rx should be disabled first to do this safely */ /* change baud-rate and write it to the hardware */ - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) { + if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) { /* Special baudrate */ u32 mask = 0xFF << (info->line*8); /* Each port has 8 bits */ unsigned long alt_source = @@ -3031,17 +2900,12 @@ change_speed(struct e100_serial *info) IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, normal); r_alt_ser_baudrate_shadow &= ~mask; r_alt_ser_baudrate_shadow |= (alt_source << (info->line*8)); -#ifndef CONFIG_SVINTO_SIM *R_ALT_SER_BAUDRATE = r_alt_ser_baudrate_shadow; -#endif /* CONFIG_SVINTO_SIM */ info->baud = cflag_to_baud(cflag); -#ifndef CONFIG_SVINTO_SIM info->ioport[REG_BAUD] = cflag_to_etrax_baud(cflag); -#endif /* CONFIG_SVINTO_SIM */ } -#ifndef CONFIG_SVINTO_SIM /* start with default settings and then fill in changes */ local_irq_save(flags); /* 8 bit, no/even parity */ @@ -3101,7 +2965,7 @@ change_speed(struct e100_serial *info) info->ioport[REG_REC_CTRL] = info->rx_ctrl; xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->port.tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable); - if (info->port.tty->termios->c_iflag & IXON ) { + if (info->port.tty->termios.c_iflag & IXON ) { DFLOW(DEBUG_LOG(info->line, "FLOW XOFF enabled 0x%02X\n", STOP_CHAR(info->port.tty))); xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); @@ -3109,7 +2973,6 @@ change_speed(struct e100_serial *info) *((unsigned long *)&info->ioport[REG_XOFF]) = xoff; local_irq_restore(flags); -#endif /* !CONFIG_SVINTO_SIM */ update_char_time(info); @@ -3126,7 +2989,6 @@ rs_flush_chars(struct tty_struct *tty) if (info->tr_running || info->xmit.head == info->xmit.tail || tty->stopped || - tty->hw_stopped || !info->xmit.buf) return; @@ -3150,7 +3012,7 @@ static int rs_raw_write(struct tty_struct *tty, /* first some sanity checks */ - if (!tty || !info->xmit.buf || !tmp_buf) + if (!info->xmit.buf) return 0; #ifdef SERIAL_DEBUG_DATA @@ -3159,11 +3021,6 @@ static int rs_raw_write(struct tty_struct *tty, count, info->ioport[REG_STATUS]); #endif -#ifdef CONFIG_SVINTO_SIM - /* Really simple. The output is here and now. */ - SIMCOUT(buf, count); - return count; -#endif local_save_flags(flags); DFLOW(DEBUG_LOG(info->line, "write count %i ", count)); DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty))); @@ -3204,7 +3061,6 @@ static int rs_raw_write(struct tty_struct *tty, if (info->xmit.head != info->xmit.tail && !tty->stopped && - !tty->hw_stopped && !info->tr_running) { start_transmit(info); } @@ -3368,7 +3224,7 @@ rs_throttle(struct tty_struct * tty) DFLOW(DEBUG_LOG(info->line,"rs_throttle %lu\n", tty->ldisc.chars_in_buffer(tty))); /* Do RTS before XOFF since XOFF might take some time */ - if (tty->termios->c_cflag & CRTSCTS) { + if (tty->termios.c_cflag & CRTSCTS) { /* Turn off RTS line */ e100_rts(info, 0); } @@ -3390,7 +3246,7 @@ rs_unthrottle(struct tty_struct * tty) DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc %d\n", tty->ldisc.chars_in_buffer(tty))); DFLOW(DEBUG_LOG(info->line,"rs_unthrottle flip.count: %i\n", tty->flip.count)); /* Do RTS before XOFF since XOFF might take some time */ - if (tty->termios->c_cflag & CRTSCTS) { + if (tty->termios.c_cflag & CRTSCTS) { /* Assert RTS line */ e100_rts(info, 1); } @@ -3428,10 +3284,10 @@ get_serial_info(struct e100_serial * info, tmp.line = info->line; tmp.port = (int)info->ioport; tmp.irq = info->irq; - tmp.flags = info->flags; + tmp.flags = info->port.flags; tmp.baud_base = info->baud_base; - tmp.close_delay = info->close_delay; - tmp.closing_wait = info->closing_wait; + tmp.close_delay = info->port.close_delay; + tmp.closing_wait = info->port.closing_wait; tmp.custom_divisor = info->custom_divisor; if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) return -EFAULT; @@ -3453,16 +3309,16 @@ set_serial_info(struct e100_serial *info, if (!capable(CAP_SYS_ADMIN)) { if ((new_serial.type != info->type) || - (new_serial.close_delay != info->close_delay) || + (new_serial.close_delay != info->port.close_delay) || ((new_serial.flags & ~ASYNC_USR_MASK) != - (info->flags & ~ASYNC_USR_MASK))) + (info->port.flags & ~ASYNC_USR_MASK))) return -EPERM; - info->flags = ((info->flags & ~ASYNC_USR_MASK) | + info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) | (new_serial.flags & ASYNC_USR_MASK)); goto check_and_exit; } - if (info->count > 1) + if (info->port.count > 1) return -EBUSY; /* @@ -3471,16 +3327,16 @@ set_serial_info(struct e100_serial *info, */ info->baud_base = new_serial.baud_base; - info->flags = ((info->flags & ~ASYNC_FLAGS) | + info->port.flags = ((info->port.flags & ~ASYNC_FLAGS) | (new_serial.flags & ASYNC_FLAGS)); info->custom_divisor = new_serial.custom_divisor; info->type = new_serial.type; - info->close_delay = new_serial.close_delay; - info->closing_wait = new_serial.closing_wait; - info->port.tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + info->port.close_delay = new_serial.close_delay; + info->port.closing_wait = new_serial.closing_wait; + info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; check_and_exit: - if (info->flags & ASYNC_INITIALIZED) { + if (info->port.flags & ASYNC_INITIALIZED) { change_speed(info); } else retval = startup(info); @@ -3501,7 +3357,6 @@ static int get_lsr_info(struct e100_serial * info, unsigned int *value) { unsigned int result = TIOCSER_TEMT; -#ifndef CONFIG_SVINTO_SIM unsigned long curr_time = jiffies; unsigned long curr_time_usec = GET_JIFFIES_USEC(); unsigned long elapsed_usec = @@ -3512,7 +3367,6 @@ get_lsr_info(struct e100_serial * info, unsigned int *value) elapsed_usec < 2*info->char_time_usec) { result = 0; } -#endif if (copy_to_user(value, &result, sizeof(int))) return -EFAULT; @@ -3761,10 +3615,8 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) /* Handle turning off CRTSCTS */ if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; + !(tty->termios.c_cflag & CRTSCTS)) rs_start(tty); - } } @@ -3800,7 +3652,7 @@ rs_close(struct tty_struct *tty, struct file * filp) printk("[%d] rs_close ttyS%d, count = %d\n", current->pid, info->line, info->count); #endif - if ((tty->count == 1) && (info->count != 1)) { + if ((tty->count == 1) && (info->port.count != 1)) { /* * Uh, oh. tty->count is 1, which means that the tty * structure will be freed. Info->count should always @@ -3810,32 +3662,32 @@ rs_close(struct tty_struct *tty, struct file * filp) */ printk(KERN_ERR "rs_close: bad serial port count; tty->count is 1, " - "info->count is %d\n", info->count); - info->count = 1; + "info->count is %d\n", info->port.count); + info->port.count = 1; } - if (--info->count < 0) { + if (--info->port.count < 0) { printk(KERN_ERR "rs_close: bad serial port count for ttyS%d: %d\n", - info->line, info->count); - info->count = 0; + info->line, info->port.count); + info->port.count = 0; } - if (info->count) { + if (info->port.count) { local_irq_restore(flags); return; } - info->flags |= ASYNC_CLOSING; + info->port.flags |= ASYNC_CLOSING; /* * Save the termios structure, since this port may have * separate termios for callout and dialin. */ - if (info->flags & ASYNC_NORMAL_ACTIVE) - info->normal_termios = *tty->termios; + if (info->port.flags & ASYNC_NORMAL_ACTIVE) + info->normal_termios = tty->termios; /* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. */ tty->closing = 1; - if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, info->closing_wait); + if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->port.closing_wait); /* * At this point we stop accepting input. To do this, we * disable the serial receiver and the DMA receive interrupt. @@ -3844,11 +3696,10 @@ rs_close(struct tty_struct *tty, struct file * filp) e100_disable_serial_data_irq(info); #endif -#ifndef CONFIG_SVINTO_SIM e100_disable_rx(info); e100_disable_rx_irq(info); - if (info->flags & ASYNC_INITIALIZED) { + if (info->port.flags & ASYNC_INITIALIZED) { /* * Before we drop DTR, make sure the UART transmitter * has completely drained; this is especially @@ -3856,7 +3707,6 @@ rs_close(struct tty_struct *tty, struct file * filp) */ rs_wait_until_sent(tty, HZ); } -#endif shutdown(info); rs_flush_buffer(tty); @@ -3864,13 +3714,13 @@ rs_close(struct tty_struct *tty, struct file * filp) tty->closing = 0; info->event = 0; info->port.tty = NULL; - if (info->blocked_open) { - if (info->close_delay) - schedule_timeout_interruptible(info->close_delay); - wake_up_interruptible(&info->open_wait); + if (info->port.blocked_open) { + if (info->port.close_delay) + schedule_timeout_interruptible(info->port.close_delay); + wake_up_interruptible(&info->port.open_wait); } - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); + info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + wake_up_interruptible(&info->port.close_wait); local_irq_restore(flags); /* port closed */ @@ -3963,10 +3813,10 @@ rs_hangup(struct tty_struct *tty) rs_flush_buffer(tty); shutdown(info); info->event = 0; - info->count = 0; - info->flags &= ~ASYNC_NORMAL_ACTIVE; + info->port.count = 0; + info->port.flags &= ~ASYNC_NORMAL_ACTIVE; info->port.tty = NULL; - wake_up_interruptible(&info->open_wait); + wake_up_interruptible(&info->port.open_wait); } /* @@ -3988,11 +3838,11 @@ block_til_ready(struct tty_struct *tty, struct file * filp, * until it's done, and then try again. */ if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - wait_event_interruptible_tty(info->close_wait, - !(info->flags & ASYNC_CLOSING)); + (info->port.flags & ASYNC_CLOSING)) { + wait_event_interruptible_tty(tty, info->port.close_wait, + !(info->port.flags & ASYNC_CLOSING)); #ifdef SERIAL_DO_RESTART - if (info->flags & ASYNC_HUP_NOTIFY) + if (info->port.flags & ASYNC_HUP_NOTIFY) return -EAGAIN; else return -ERESTARTSYS; @@ -4007,34 +3857,34 @@ block_til_ready(struct tty_struct *tty, struct file * filp, */ if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { - info->flags |= ASYNC_NORMAL_ACTIVE; + info->port.flags |= ASYNC_NORMAL_ACTIVE; return 0; } - if (tty->termios->c_cflag & CLOCAL) { + if (tty->termios.c_cflag & CLOCAL) { do_clocal = 1; } /* * Block waiting for the carrier detect and the line to become * free (i.e., not in use by the callout). While we are in - * this loop, info->count is dropped by one, so that + * this loop, info->port.count is dropped by one, so that * rs_close() knows when to free things. We restore it upon * exit, either normal or abnormal. */ retval = 0; - add_wait_queue(&info->open_wait, &wait); + add_wait_queue(&info->port.open_wait, &wait); #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready before block: ttyS%d, count = %d\n", - info->line, info->count); + info->line, info->port.count); #endif local_irq_save(flags); if (!tty_hung_up_p(filp)) { extra_count++; - info->count--; + info->port.count--; } local_irq_restore(flags); - info->blocked_open++; + info->port.blocked_open++; while (1) { local_irq_save(flags); /* assert RTS and DTR */ @@ -4043,9 +3893,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp, local_irq_restore(flags); set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || - !(info->flags & ASYNC_INITIALIZED)) { + !(info->port.flags & ASYNC_INITIALIZED)) { #ifdef SERIAL_DO_RESTART - if (info->flags & ASYNC_HUP_NOTIFY) + if (info->port.flags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; else retval = -ERESTARTSYS; @@ -4054,7 +3904,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, #endif break; } - if (!(info->flags & ASYNC_CLOSING) && do_clocal) + if (!(info->port.flags & ASYNC_CLOSING) && do_clocal) /* && (do_clocal || DCD_IS_ASSERTED) */ break; if (signal_pending(current)) { @@ -4063,24 +3913,24 @@ block_til_ready(struct tty_struct *tty, struct file * filp, } #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready blocking: ttyS%d, count = %d\n", - info->line, info->count); + info->line, info->port.count); #endif - tty_unlock(); + tty_unlock(tty); schedule(); - tty_lock(); + tty_lock(tty); } set_current_state(TASK_RUNNING); - remove_wait_queue(&info->open_wait, &wait); + remove_wait_queue(&info->port.open_wait, &wait); if (extra_count) - info->count++; - info->blocked_open--; + info->port.count++; + info->port.blocked_open--; #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready after blocking: ttyS%d, count = %d\n", - info->line, info->count); + info->line, info->port.count); #endif if (retval) return retval; - info->flags |= ASYNC_NORMAL_ACTIVE; + info->port.flags |= ASYNC_NORMAL_ACTIVE; return 0; } @@ -4105,54 +3955,33 @@ static int rs_open(struct tty_struct *tty, struct file * filp) { struct e100_serial *info; - int retval, line; - unsigned long page; + int retval; int allocated_resources = 0; - /* find which port we want to open */ - line = tty->index; - - if (line < 0 || line >= NR_PORTS) - return -ENODEV; - - /* find the corresponding e100_serial struct in the table */ - info = rs_table + line; - - /* don't allow the opening of ports that are not enabled in the HW config */ + info = rs_table + tty->index; if (!info->enabled) return -ENODEV; #ifdef SERIAL_DEBUG_OPEN printk("[%d] rs_open %s, count = %d\n", current->pid, tty->name, - info->count); + info->port.count); #endif - info->count++; + info->port.count++; tty->driver_data = info; info->port.tty = tty; - info->port.tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; - - if (!tmp_buf) { - page = get_zeroed_page(GFP_KERNEL); - if (!page) { - return -ENOMEM; - } - if (tmp_buf) - free_page(page); - else - tmp_buf = (unsigned char *) page; - } + info->port.low_latency = !!(info->port.flags & ASYNC_LOW_LATENCY); /* * If the port is in the middle of closing, bail out now */ if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - wait_event_interruptible_tty(info->close_wait, - !(info->flags & ASYNC_CLOSING)); + (info->port.flags & ASYNC_CLOSING)) { + wait_event_interruptible_tty(tty, info->port.close_wait, + !(info->port.flags & ASYNC_CLOSING)); #ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? + return ((info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); #else return -EAGAIN; @@ -4162,7 +3991,7 @@ rs_open(struct tty_struct *tty, struct file * filp) /* * If DMA is enabled try to allocate the irq's. */ - if (info->count == 1) { + if (info->port.count == 1) { allocated_resources = 1; if (info->dma_in_enabled) { if (request_irq(info->dma_in_irq_nbr, @@ -4235,7 +4064,7 @@ rs_open(struct tty_struct *tty, struct file * filp) if (allocated_resources) deinit_port(info); - /* FIXME Decrease count info->count here too? */ + /* FIXME Decrease count info->port.count here too? */ return retval; } @@ -4252,8 +4081,8 @@ rs_open(struct tty_struct *tty, struct file * filp) return retval; } - if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { - *tty->termios = info->normal_termios; + if ((info->port.count == 1) && (info->port.flags & ASYNC_SPLIT_TERMIOS)) { + tty->termios = info->normal_termios; change_speed(info); } @@ -4305,9 +4134,6 @@ static void seq_line_info(struct seq_file *m, struct e100_serial *info) if (info->port.tty->stopped) seq_printf(m, " stopped:%i", (int)info->port.tty->stopped); - if (info->port.tty->hw_stopped) - seq_printf(m, " hw_stopped:%i", - (int)info->port.tty->hw_stopped); } { @@ -4477,14 +4303,12 @@ static int __init rs_init(void) B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */ driver->init_termios.c_ispeed = 115200; driver->init_termios.c_ospeed = 115200; - driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(driver, &rs_ops); serial_driver = driver; - if (tty_register_driver(driver)) - panic("Couldn't register serial driver\n"); - /* do some initializing for the separate ports */ + /* do some initializing for the separate ports */ for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) { if (info->enabled) { if (cris_request_io_interface(info->io_if, @@ -4496,6 +4320,7 @@ static int __init rs_init(void) info->enabled = 0; } } + tty_port_init(&info->port); info->uses_dma_in = 0; info->uses_dma_out = 0; info->line = i; @@ -4505,16 +4330,9 @@ static int __init rs_init(void) info->forced_eop = 0; info->baud_base = DEF_BAUD_BASE; info->custom_divisor = 0; - info->flags = 0; - info->close_delay = 5*HZ/10; - info->closing_wait = 30*HZ; info->x_char = 0; info->event = 0; - info->count = 0; - info->blocked_open = 0; info->normal_termios = driver->init_termios; - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); info->xmit.buf = NULL; info->xmit.tail = info->xmit.head = 0; info->first_recv_buffer = info->last_recv_buffer = NULL; @@ -4535,7 +4353,12 @@ static int __init rs_init(void) printk(KERN_INFO "%s%d at %p is a builtin UART with DMA\n", serial_driver->name, info->line, info->ioport); } + tty_port_link_device(&info->port, driver, i); } + + if (tty_register_driver(driver)) + panic("Couldn't register serial driver\n"); + #ifdef CONFIG_ETRAX_FAST_TIMER #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER memset(fast_timers, 0, sizeof(fast_timers)); @@ -4546,7 +4369,6 @@ static int __init rs_init(void) fast_timer_init(); #endif -#ifndef CONFIG_SVINTO_SIM #ifndef CONFIG_ETRAX_KGDB /* Not needed in simulator. May only complicate stuff. */ /* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */ @@ -4556,7 +4378,6 @@ static int __init rs_init(void) panic("%s: Failed to request irq8", __func__); #endif -#endif /* CONFIG_SVINTO_SIM */ return 0; } |
