diff options
Diffstat (limited to 'drivers/staging/dgnc/dgnc_neo.c')
-rw-r--r-- | drivers/staging/dgnc/dgnc_neo.c | 228 |
1 files changed, 46 insertions, 182 deletions
diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index 3eefefe..1943e66 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -14,15 +14,15 @@ */ #include <linux/kernel.h> -#include <linux/sched.h> /* For jiffies, task states */ -#include <linux/interrupt.h> /* For tasklet and interrupt structs/defines */ -#include <linux/delay.h> /* For udelay */ -#include <linux/io.h> /* For read[bwl]/write[bwl] */ -#include <linux/serial.h> /* For struct async_serial */ -#include <linux/serial_reg.h> /* For the various UART offsets */ - -#include "dgnc_driver.h" /* Driver main header file */ -#include "dgnc_neo.h" /* Our header file */ +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/serial.h> +#include <linux/serial_reg.h> + +#include "dgnc_driver.h" +#include "dgnc_neo.h" #include "dgnc_tty.h" static inline void neo_parse_lsr(struct dgnc_board *brd, uint port); @@ -96,12 +96,7 @@ static inline void neo_set_cts_flow_control(struct channel_t *ch) unsigned char efr = readb(&ch->ch_neo_uart->efr); /* Turn on auto CTS flow control */ -#if 1 ier |= UART_17158_IER_CTSDSR; -#else - ier &= ~(UART_17158_IER_CTSDSR); -#endif - efr |= (UART_17158_EFR_ECB | UART_17158_EFR_CTSDSR); /* Turn off auto Xon flow control */ @@ -135,11 +130,7 @@ static inline void neo_set_rts_flow_control(struct channel_t *ch) unsigned char efr = readb(&ch->ch_neo_uart->efr); /* Turn on auto RTS flow control */ -#if 1 ier |= UART_17158_IER_RTSDTR; -#else - ier &= ~(UART_17158_IER_RTSDTR); -#endif efr |= (UART_17158_EFR_ECB | UART_17158_EFR_RTSDTR); /* Turn off auto Xoff flow control */ @@ -358,20 +349,17 @@ static inline void neo_set_new_start_stop_chars(struct channel_t *ch) } /* No locks are assumed to be held when calling this function. */ - static inline void neo_clear_break(struct channel_t *ch, int force) { unsigned long flags; spin_lock_irqsave(&ch->ch_lock, flags); - /* Bail if we aren't currently sending a break. */ if (!ch->ch_stop_sending_break) { spin_unlock_irqrestore(&ch->ch_lock, flags); return; } - /* Turn break off, and unset some variables */ if (ch->ch_flags & CH_BREAK_SENDING) { if (force || time_after_eq(jiffies, ch->ch_stop_sending_break)) { @@ -387,7 +375,6 @@ static inline void neo_clear_break(struct channel_t *ch, int force) } /* Parse the ISR register. */ - static inline void neo_parse_isr(struct dgnc_board *brd, uint port) { struct channel_t *ch; @@ -396,14 +383,13 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) unsigned long flags; ch = brd->channels[port]; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; /* Here we try to figure out what caused the interrupt to happen */ while (1) { isr = readb(&ch->ch_neo_uart->isr_fcr); - /* Bail if no pending interrupt */ if (isr & UART_IIR_NO_INT) break; @@ -426,7 +412,6 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) } if (isr & UART_IIR_THRI) { - /* Transfer data (if any) from Write Queue -> UART. */ spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); spin_unlock_irqrestore(&ch->ch_lock, flags); @@ -442,10 +427,7 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) * one it was, so we can suspend or resume data flow. */ if (cause == UART_17158_XON_DETECT) { - /* - * Is output stopped right now, if so, - * resume it - */ + /* resume output if stopped */ if (brd->channels[port]->ch_flags & CH_STOP) { spin_lock_irqsave(&ch->ch_lock, flags); @@ -504,7 +486,6 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) } } - /* Parse any modem signal changes */ neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr)); } } @@ -515,18 +496,14 @@ static inline void neo_parse_lsr(struct dgnc_board *brd, uint port) int linestatus; unsigned long flags; - /* - * Check to make sure it didn't receive interrupt with a null board - * associated or a board pointer that wasn't ours. - */ - if (!brd || brd->magic != DGNC_BOARD_MAGIC) + if (!brd) return; if (port >= brd->maxports) return; ch = brd->channels[port]; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; linestatus = readb(&ch->ch_neo_uart->lsr); @@ -534,7 +511,6 @@ static inline void neo_parse_lsr(struct dgnc_board *brd, uint port) ch->ch_cached_lsr |= linestatus; if (ch->ch_cached_lsr & UART_LSR_DR) { - /* Read data from uart -> queue */ neo_copy_data_from_uart_to_queue(ch); spin_lock_irqsave(&ch->ch_lock, flags); dgnc_check_queue_flow_control(ch); @@ -571,22 +547,17 @@ static inline void neo_parse_lsr(struct dgnc_board *brd, uint port) ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); spin_unlock_irqrestore(&ch->ch_lock, flags); - /* Transfer data (if any) from Write Queue -> UART. */ neo_copy_data_from_queue_to_uart(ch); } else if (linestatus & UART_17158_TX_AND_FIFO_CLR) { spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); spin_unlock_irqrestore(&ch->ch_lock, flags); - /* Transfer data (if any) from Write Queue -> UART. */ neo_copy_data_from_queue_to_uart(ch); } } -/* - * neo_param() - * Send any/all changes to the line to the UART. - */ +/* Send any/all changes to the line to the UART. */ static void neo_param(struct tty_struct *tty) { unsigned char lcr = 0; @@ -599,23 +570,22 @@ static void neo_param(struct tty_struct *tty) struct channel_t *ch; struct un_t *un; - if (!tty || tty->magic != TTY_MAGIC) + if (!tty) return; un = (struct un_t *)tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) + 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 = 0; ch->ch_r_tail = 0; @@ -724,10 +694,6 @@ static void neo_param(struct tty_struct *tty) 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; @@ -796,16 +762,11 @@ static void neo_param(struct tty_struct *tty) if (ier != uart_ier) writeb(ier, &ch->ch_neo_uart->ier); - /* Set new start/stop chars */ neo_set_new_start_stop_chars(ch); if (ch->ch_digi.digi_flags & CTSPACE || 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 == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) neo_set_no_output_flow_control(ch); @@ -818,10 +779,6 @@ static void neo_param(struct tty_struct *tty) if (ch->ch_digi.digi_flags & RTSPACE || 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 == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) neo_set_no_input_flow_control(ch); @@ -843,12 +800,10 @@ static void neo_param(struct tty_struct *tty) neo_assert_modem_signals(ch); - /* Get current status of the modem signals now */ neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr)); } -/* Our board poller function. */ - +/* Board poller function. */ static void neo_tasklet(unsigned long data) { struct dgnc_board *bd = (struct dgnc_board *)data; @@ -858,10 +813,9 @@ static void neo_tasklet(unsigned long data) int state = 0; int ports = 0; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) + if (!bd) return; - /* Cache a couple board values */ spin_lock_irqsave(&bd->bd_lock, flags); state = bd->state; ports = bd->nasync; @@ -873,15 +827,10 @@ static void neo_tasklet(unsigned long data) */ spin_lock_irqsave(&bd->bd_intr_lock, flags); - /* If board is ready, parse deeper to see if there is anything to do. */ - if ((state == BOARD_READY) && (ports > 0)) { - /* Loop on each port */ for (i = 0; i < ports; i++) { ch = bd->channels[i]; - - /* Just being careful... */ - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) continue; /* @@ -903,10 +852,6 @@ static void neo_tasklet(unsigned long data) neo_copy_data_from_queue_to_uart(ch); dgnc_wakeup_writes(ch); - /* - * Call carrier carrier function, in case something - * has changed. - */ dgnc_carrier(ch); /* @@ -918,15 +863,10 @@ static void neo_tasklet(unsigned long data) } } - /* Allow interrupt routine to access the interrupt register again */ spin_unlock_irqrestore(&bd->bd_intr_lock, flags); } -/* - * dgnc_neo_intr() - * - * Neo specific interrupt handler. - */ +/* Neo specific interrupt handler. */ static irqreturn_t neo_intr(int irq, void *voidbrd) { struct dgnc_board *brd = voidbrd; @@ -937,11 +877,7 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) unsigned long flags; unsigned long flags2; - /* - * Check to make sure it didn't receive interrupt with a null board - * associated or a board pointer that wasn't ours. - */ - if (!brd || brd->magic != DGNC_BOARD_MAGIC) + if (!brd) return IRQ_NONE; /* Lock out the slow poller from running on this board. */ @@ -964,19 +900,12 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) return IRQ_NONE; } - /* - * At this point, we have at least SOMETHING to service, dig - * further... - */ - - /* Loop on each port */ while ((uart_poll & 0xff) != 0) { type = uart_poll >> (8 + (port * 3)); type &= 0x7; uart_poll &= ~(0x01 << port); - /* Switch on type of interrupt we have */ switch (type) { case UART_17158_RXRDY_TIMEOUT: /* @@ -984,7 +913,6 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) * RX FIFO until it falls below the trigger level. */ - /* Verify the port is in range. */ if (port >= brd->nasync) break; @@ -1027,27 +955,17 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) break; case UART_17158_MSR: - /* MSR or flow control was seen. */ - neo_parse_isr(brd, port); break; default: - /* - * The UART triggered us with a bogus interrupt type. - * It appears the Exar chip, when REALLY bogged down, - * will throw these once and awhile. - * Its harmless, just ignore it and move on. - */ break; } port++; } - /* Schedule tasklet to more in-depth servicing at a better time. */ - tasklet_schedule(&brd->helper_tasklet); spin_unlock_irqrestore(&brd->bd_intr_lock, flags); @@ -1094,32 +1012,23 @@ static void neo_copy_data_from_uart_to_queue(struct channel_t *ch) ushort tail; unsigned long flags; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; spin_lock_irqsave(&ch->ch_lock, flags); - /* cache head and tail of queue */ head = ch->ch_r_head & RQUEUEMASK; tail = ch->ch_r_tail & RQUEUEMASK; - /* Get our cached LSR */ linestatus = ch->ch_cached_lsr; ch->ch_cached_lsr = 0; - /* Store how much space we have left in the queue */ qleft = tail - head - 1; if (qleft < 0) qleft += RQUEUEMASK + 1; - /* - * If the UART is not in FIFO mode, force the FIFO copy to - * NOT be run, by setting total to 0. - * - * On the other hand, if the UART IS in FIFO mode, then ask - * the UART to give us an approximation of data it has RX'ed. - */ if (!(ch->ch_flags & CH_FIFO_ENABLED)) { + /* force the FIFO copy to NOT be run */ total = 0; } else { total = readb(&ch->ch_neo_uart->rfifo); @@ -1138,26 +1047,11 @@ static void neo_copy_data_from_uart_to_queue(struct channel_t *ch) total -= 3; } - /* - * Finally, bound the copy to make sure we don't overflow - * our own queue... - * The byte by byte copy loop below this loop this will - * deal with the queue overflow possibility. - */ total = min(total, qleft); while (total > 0) { - /* - * Grab the linestatus register, we need to check - * to see if there are any errors in the FIFO. - */ linestatus = readb(&ch->ch_neo_uart->lsr); - /* - * Break out if there is a FIFO error somewhere. - * This will allow us to go byte by byte down below, - * finding the exact location of the error. - */ if (linestatus & UART_17158_RX_FIFO_DATA_ERROR) break; @@ -1182,7 +1076,6 @@ static void neo_copy_data_from_uart_to_queue(struct channel_t *ch) linestatus = 0; - /* Copy data from uart to the queue */ memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, n); @@ -1193,7 +1086,6 @@ static void neo_copy_data_from_uart_to_queue(struct channel_t *ch) */ memset(ch->ch_equeue + head, 0, n); - /* Add to and flip head if needed */ head = (head + n) & RQUEUEMASK; total -= n; qleft -= n; @@ -1242,8 +1134,6 @@ static void neo_copy_data_from_uart_to_queue(struct channel_t *ch) ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); } - /* Discard character if we are ignoring the error mask. */ - if (linestatus & error_mask) { unsigned char discard; @@ -1253,13 +1143,10 @@ static void neo_copy_data_from_uart_to_queue(struct channel_t *ch) } /* - * If our queue is full, we have no choice but to drop some - * data. - * The assumption is that HWFLOW or SWFLOW should have stopped - * things way way before we got to this point. - * - * I decided that I wanted to ditch the oldest data first, - * I hope thats okay with everyone? Yes? Good. + * If our queue is full, we have no choice but to drop + * some data. The assumption is that HWFLOW or SWFLOW + * should have stopped things way way before we got to + * this point. */ while (qleft < 1) { tail = (tail + 1) & RQUEUEMASK; @@ -1272,18 +1159,14 @@ static void neo_copy_data_from_uart_to_queue(struct channel_t *ch) &ch->ch_neo_uart->txrxburst, 1); ch->ch_equeue[head] = (unsigned char)linestatus; - /* Ditch any remaining linestatus value. */ linestatus = 0; - /* Add to and flip head if needed */ head = (head + 1) & RQUEUEMASK; qleft--; ch->ch_rxcount++; } - /* Write new final heads to channel structure. */ - ch->ch_r_head = head & RQUEUEMASK; ch->ch_e_head = head & EQUEUEMASK; @@ -1301,25 +1184,21 @@ static int neo_drain(struct tty_struct *tty, uint seconds) struct un_t *un; int rc = 0; - if (!tty || tty->magic != TTY_MAGIC) + if (!tty) return -ENXIO; un = (struct un_t *)tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return -ENXIO; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return -ENXIO; spin_lock_irqsave(&ch->ch_lock, flags); un->un_flags |= UN_EMPTY; spin_unlock_irqrestore(&ch->ch_lock, flags); - /* - * Go to sleep waiting for the tty layer to wake me back up when - * the empty flag goes away. - */ rc = wait_event_interruptible_timeout(un->un_flags_wait, ((un->un_flags & UN_EMPTY) == 0), msecs_to_jiffies(seconds * 1000)); @@ -1330,15 +1209,14 @@ static int neo_drain(struct tty_struct *tty, uint seconds) /* * Flush the WRITE FIFO on the Neo. - * - * NOTE: Channel lock MUST be held before calling this function! + * Channel lock MUST be held before calling this function! */ static void neo_flush_uart_write(struct channel_t *ch) { unsigned char tmp = 0; int i = 0; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), @@ -1347,7 +1225,7 @@ static void neo_flush_uart_write(struct channel_t *ch) for (i = 0; i < 10; i++) { /* - * Check to see if the UART feels it completely flushed the + * Check to see if the UART completely flushed the FIFO * FIFO. */ tmp = readb(&ch->ch_neo_uart->isr_fcr); @@ -1362,15 +1240,14 @@ static void neo_flush_uart_write(struct channel_t *ch) /* * Flush the READ FIFO on the Neo. - * - * NOTE: Channel lock MUST be held before calling this function! + * Channel lock MUST be held before calling this function! */ static void neo_flush_uart_read(struct channel_t *ch) { unsigned char tmp = 0; int i = 0; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR, @@ -1400,12 +1277,11 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch) uint len_written = 0; unsigned long flags; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; spin_lock_irqsave(&ch->ch_lock, flags); - /* No data to write to the UART */ if (ch->ch_w_tail == ch->ch_w_head) goto exit_unlock; @@ -1414,12 +1290,10 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch) (ch->ch_flags & CH_BREAK_SENDING)) goto exit_unlock; - /* If FIFOs are disabled. Send data directly to txrx register */ - if (!(ch->ch_flags & CH_FIFO_ENABLED)) { + /* Send data directly to txrx register */ unsigned char lsrbits = readb(&ch->ch_neo_uart->lsr); - /* Cache the LSR bits for later parsing */ ch->ch_cached_lsr |= lsrbits; if (ch->ch_cached_lsr & UART_LSR_THRE) { ch->ch_cached_lsr &= ~(UART_LSR_THRE); @@ -1477,12 +1351,10 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch) n = UART_17158_TX_FIFOSIZE - readb(&ch->ch_neo_uart->tfifo); } - /* cache head and tail of queue */ head = ch->ch_w_head & WQUEUEMASK; tail = ch->ch_w_tail & WQUEUEMASK; qlen = (head - tail) & WQUEUEMASK; - /* Find minimum of the FIFO space, versus queue length */ n = min(n, qlen); while (n > 0) { @@ -1521,14 +1393,12 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch) memcpy_toio(&ch->ch_neo_uart->txrxburst, ch->ch_wqueue + tail, s); - /* Add and flip queue if needed */ tail = (tail + s) & WQUEUEMASK; n -= s; ch->ch_txcount += s; len_written += s; } - /* Update the final tail */ ch->ch_w_tail = tail & WQUEUEMASK; if (len_written > 0) { @@ -1544,7 +1414,7 @@ static void neo_parse_modem(struct channel_t *ch, unsigned char signals) { unsigned char msignals = signals; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; /* @@ -1572,10 +1442,7 @@ static void neo_parse_modem(struct channel_t *ch, unsigned char signals) } } - /* - * Scrub off lower bits. They signify delta's, which I don't care - * about - */ + /* Scrub off lower bits. They signify delta's */ msignals &= 0xf0; if (msignals & UART_MSR_DCD) @@ -1604,7 +1471,7 @@ static void neo_assert_modem_signals(struct channel_t *ch) { unsigned char out; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; out = ch->ch_mostat; @@ -1621,7 +1488,7 @@ static void neo_assert_modem_signals(struct channel_t *ch) static void neo_send_start_character(struct channel_t *ch) { - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; if (ch->ch_startc != _POSIX_VDISABLE) { @@ -1634,7 +1501,7 @@ static void neo_send_start_character(struct channel_t *ch) static void neo_send_stop_character(struct channel_t *ch) { - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; if (ch->ch_stopc != _POSIX_VDISABLE) { @@ -1668,7 +1535,6 @@ static void neo_uart_init(struct channel_t *ch) } /* Make the UART completely turn off. */ - static void neo_uart_off(struct channel_t *ch) { /* Turn off UART enhanced bits */ @@ -1735,8 +1601,6 @@ static void neo_send_break(struct channel_t *ch, int msecs) } /* - * neo_send_immediate_char. - * * Sends a specific character as soon as possible to the UART, * jumping over any bytes that might be in the write queue. * @@ -1744,7 +1608,7 @@ static void neo_send_break(struct channel_t *ch, int msecs) */ static void neo_send_immediate_char(struct channel_t *ch, unsigned char c) { - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; writeb(c, &ch->ch_neo_uart->txrx); @@ -1797,7 +1661,7 @@ static void neo_vpd(struct dgnc_board *brd) unsigned int i = 0; unsigned int a; - if (!brd || brd->magic != DGNC_BOARD_MAGIC) + if (!brd) return; if (!brd->re_map_membase) |