Commit 945d2a60 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

staging: dgnc: delete dgnc_neo.* files

As the Neo devices were never actually supported by the driver, delete
the files that purported to control that type of device as they are not
needed.  This will let us shrink the driver a lot over time.

Cc: Lidza Louina <lidza.louina@gmail.com>
Cc: Mark Hounschell <markh@compro.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2238965f
obj-$(CONFIG_DGNC) += dgnc.o
dgnc-objs := dgnc_cls.o dgnc_driver.o\
dgnc_neo.o\
dgnc_tty.o
......@@ -13,7 +13,6 @@
#include "dgnc_pci.h"
#include "dgnc_tty.h"
#include "dgnc_cls.h"
#include "dgnc_neo.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Digi International, http://www.digi.com");
......
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*/
#include <linux/kernel.h>
#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);
static inline void neo_parse_isr(struct dgnc_board *brd, uint port);
static void neo_copy_data_from_uart_to_queue(struct channel_t *ch);
static inline void neo_clear_break(struct channel_t *ch, int force);
static inline void neo_set_cts_flow_control(struct channel_t *ch);
static inline void neo_set_rts_flow_control(struct channel_t *ch);
static inline void neo_set_ixon_flow_control(struct channel_t *ch);
static inline void neo_set_ixoff_flow_control(struct channel_t *ch);
static inline void neo_set_no_output_flow_control(struct channel_t *ch);
static inline void neo_set_no_input_flow_control(struct channel_t *ch);
static inline void neo_set_new_start_stop_chars(struct channel_t *ch);
static void neo_parse_modem(struct channel_t *ch, unsigned char signals);
static void neo_tasklet(unsigned long data);
static void neo_vpd(struct dgnc_board *brd);
static void neo_uart_init(struct channel_t *ch);
static void neo_uart_off(struct channel_t *ch);
static int neo_drain(struct tty_struct *tty, uint seconds);
static void neo_param(struct tty_struct *tty);
static void neo_assert_modem_signals(struct channel_t *ch);
static void neo_flush_uart_write(struct channel_t *ch);
static void neo_flush_uart_read(struct channel_t *ch);
static void neo_disable_receiver(struct channel_t *ch);
static void neo_enable_receiver(struct channel_t *ch);
static void neo_send_break(struct channel_t *ch, int msecs);
static void neo_send_start_character(struct channel_t *ch);
static void neo_send_stop_character(struct channel_t *ch);
static void neo_copy_data_from_queue_to_uart(struct channel_t *ch);
static uint neo_get_uart_bytes_left(struct channel_t *ch);
static void neo_send_immediate_char(struct channel_t *ch, unsigned char c);
static irqreturn_t neo_intr(int irq, void *voidbrd);
struct board_ops dgnc_neo_ops = {
.tasklet = neo_tasklet,
.intr = neo_intr,
.uart_init = neo_uart_init,
.uart_off = neo_uart_off,
.drain = neo_drain,
.param = neo_param,
.vpd = neo_vpd,
.assert_modem_signals = neo_assert_modem_signals,
.flush_uart_write = neo_flush_uart_write,
.flush_uart_read = neo_flush_uart_read,
.disable_receiver = neo_disable_receiver,
.enable_receiver = neo_enable_receiver,
.send_break = neo_send_break,
.send_start_character = neo_send_start_character,
.send_stop_character = neo_send_stop_character,
.copy_data_from_queue_to_uart = neo_copy_data_from_queue_to_uart,
.get_uart_bytes_left = neo_get_uart_bytes_left,
.send_immediate_char = neo_send_immediate_char
};
/*
* This function allows calls to ensure that all outstanding
* PCI writes have been completed, by doing a PCI read against
* a non-destructive, read-only location on the Neo card.
*
* In this case, we are reading the DVID (Read-only Device Identification)
* value of the Neo card.
*/
static inline void neo_pci_posting_flush(struct dgnc_board *bd)
{
readb(bd->re_map_membase + 0x8D);
}
static inline void neo_set_cts_flow_control(struct channel_t *ch)
{
unsigned char ier = readb(&ch->ch_neo_uart->ier);
unsigned char efr = readb(&ch->ch_neo_uart->efr);
/* Turn on auto CTS flow control */
ier |= UART_17158_IER_CTSDSR;
efr |= (UART_17158_EFR_ECB | UART_17158_EFR_CTSDSR);
/* Turn off auto Xon flow control */
efr &= ~UART_17158_EFR_IXON;
/*
* Why? Because Exar's spec says we have to zero it
* out before setting it
*/
writeb(0, &ch->ch_neo_uart->efr);
/* Turn on UART enhanced bits */
writeb(efr, &ch->ch_neo_uart->efr);
/* Turn on table D, with 8 char hi/low watermarks */
writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY,
&ch->ch_neo_uart->fctr);
/* Feed the UART our trigger levels */
writeb(8, &ch->ch_neo_uart->tfifo);
ch->ch_t_tlevel = 8;
writeb(ier, &ch->ch_neo_uart->ier);
neo_pci_posting_flush(ch->ch_bd);
}
static inline void neo_set_rts_flow_control(struct channel_t *ch)
{
unsigned char ier = readb(&ch->ch_neo_uart->ier);
unsigned char efr = readb(&ch->ch_neo_uart->efr);
/* Turn on auto RTS flow control */
ier |= UART_17158_IER_RTSDTR;
efr |= (UART_17158_EFR_ECB | UART_17158_EFR_RTSDTR);
/* Turn off auto Xoff flow control */
ier &= ~UART_17158_IER_XOFF;
efr &= ~UART_17158_EFR_IXOFF;
/*
* Why? Because Exar's spec says we have to zero it
* out before setting it
*/
writeb(0, &ch->ch_neo_uart->efr);
/* Turn on UART enhanced bits */
writeb(efr, &ch->ch_neo_uart->efr);
writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY,
&ch->ch_neo_uart->fctr);
ch->ch_r_watermark = 4;
writeb(32, &ch->ch_neo_uart->rfifo);
ch->ch_r_tlevel = 32;
writeb(ier, &ch->ch_neo_uart->ier);
/*
* From the Neo UART spec sheet:
* The auto RTS/DTR function must be started by asserting
* RTS/DTR# output pin (MCR bit-0 or 1 to logic 1 after
* it is enabled.
*/
ch->ch_mostat |= UART_MCR_RTS;
neo_pci_posting_flush(ch->ch_bd);
}
static inline void neo_set_ixon_flow_control(struct channel_t *ch)
{
unsigned char ier = readb(&ch->ch_neo_uart->ier);
unsigned char efr = readb(&ch->ch_neo_uart->efr);
/* Turn off auto CTS flow control */
ier &= ~UART_17158_IER_CTSDSR;
efr &= ~UART_17158_EFR_CTSDSR;
/* Turn on auto Xon flow control */
efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXON);
/*
* Why? Because Exar's spec says we have to zero it
* out before setting it
*/
writeb(0, &ch->ch_neo_uart->efr);
/* Turn on UART enhanced bits */
writeb(efr, &ch->ch_neo_uart->efr);
writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY,
&ch->ch_neo_uart->fctr);
ch->ch_r_watermark = 4;
writeb(32, &ch->ch_neo_uart->rfifo);
ch->ch_r_tlevel = 32;
/* Tell UART what start/stop chars it should be looking for */
writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
writeb(0, &ch->ch_neo_uart->xonchar2);
writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
writeb(0, &ch->ch_neo_uart->xoffchar2);
writeb(ier, &ch->ch_neo_uart->ier);
neo_pci_posting_flush(ch->ch_bd);
}
static inline void neo_set_ixoff_flow_control(struct channel_t *ch)
{
unsigned char ier = readb(&ch->ch_neo_uart->ier);
unsigned char efr = readb(&ch->ch_neo_uart->efr);
/* Turn off auto RTS flow control */
ier &= ~UART_17158_IER_RTSDTR;
efr &= ~UART_17158_EFR_RTSDTR;
/* Turn on auto Xoff flow control */
ier |= UART_17158_IER_XOFF;
efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXOFF);
/*
* Why? Because Exar's spec says we have to zero it
* out before setting it
*/
writeb(0, &ch->ch_neo_uart->efr);
/* Turn on UART enhanced bits */
writeb(efr, &ch->ch_neo_uart->efr);
/* Turn on table D, with 8 char hi/low watermarks */
writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY,
&ch->ch_neo_uart->fctr);
writeb(8, &ch->ch_neo_uart->tfifo);
ch->ch_t_tlevel = 8;
/* Tell UART what start/stop chars it should be looking for */
writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
writeb(0, &ch->ch_neo_uart->xonchar2);
writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
writeb(0, &ch->ch_neo_uart->xoffchar2);
writeb(ier, &ch->ch_neo_uart->ier);
neo_pci_posting_flush(ch->ch_bd);
}
static inline void neo_set_no_input_flow_control(struct channel_t *ch)
{
unsigned char ier = readb(&ch->ch_neo_uart->ier);
unsigned char efr = readb(&ch->ch_neo_uart->efr);
/* Turn off auto RTS flow control */
ier &= ~UART_17158_IER_RTSDTR;
efr &= ~UART_17158_EFR_RTSDTR;
/* Turn off auto Xoff flow control */
ier &= ~UART_17158_IER_XOFF;
if (ch->ch_c_iflag & IXON)
efr &= ~(UART_17158_EFR_IXOFF);
else
efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXOFF);
/*
* Why? Because Exar's spec says we have to zero
* it out before setting it
*/
writeb(0, &ch->ch_neo_uart->efr);
/* Turn on UART enhanced bits */
writeb(efr, &ch->ch_neo_uart->efr);
/* Turn on table D, with 8 char hi/low watermarks */
writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY,
&ch->ch_neo_uart->fctr);
ch->ch_r_watermark = 0;
writeb(16, &ch->ch_neo_uart->tfifo);
ch->ch_t_tlevel = 16;
writeb(16, &ch->ch_neo_uart->rfifo);
ch->ch_r_tlevel = 16;
writeb(ier, &ch->ch_neo_uart->ier);
neo_pci_posting_flush(ch->ch_bd);
}
static inline void neo_set_no_output_flow_control(struct channel_t *ch)
{
unsigned char ier = readb(&ch->ch_neo_uart->ier);
unsigned char efr = readb(&ch->ch_neo_uart->efr);
/* Turn off auto CTS flow control */
ier &= ~UART_17158_IER_CTSDSR;
efr &= ~UART_17158_EFR_CTSDSR;
/* Turn off auto Xon flow control */
if (ch->ch_c_iflag & IXOFF)
efr &= ~UART_17158_EFR_IXON;
else
efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXON);
/*
* Why? Because Exar's spec says we have to zero it
* out before setting it
*/
writeb(0, &ch->ch_neo_uart->efr);
/* Turn on UART enhanced bits */
writeb(efr, &ch->ch_neo_uart->efr);
/* Turn on table D, with 8 char hi/low watermarks */
writeb(UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY,
&ch->ch_neo_uart->fctr);
ch->ch_r_watermark = 0;
writeb(16, &ch->ch_neo_uart->tfifo);
ch->ch_t_tlevel = 16;
writeb(16, &ch->ch_neo_uart->rfifo);
ch->ch_r_tlevel = 16;
writeb(ier, &ch->ch_neo_uart->ier);
neo_pci_posting_flush(ch->ch_bd);
}
/* change UARTs start/stop chars */
static inline void neo_set_new_start_stop_chars(struct channel_t *ch)
{
/* if hardware flow control is set, then skip this whole thing */
if (ch->ch_digi.digi_flags & (CTSPACE | RTSPACE) ||
ch->ch_c_cflag & CRTSCTS)
return;
/* Tell UART what start/stop chars it should be looking for */
writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
writeb(0, &ch->ch_neo_uart->xonchar2);
writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
writeb(0, &ch->ch_neo_uart->xoffchar2);
neo_pci_posting_flush(ch->ch_bd);
}
/* 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);
if (!ch->ch_stop_sending_break) {
spin_unlock_irqrestore(&ch->ch_lock, flags);
return;
}
if (ch->ch_flags & CH_BREAK_SENDING) {
if (force ||
time_after_eq(jiffies, ch->ch_stop_sending_break)) {
unsigned char temp = readb(&ch->ch_neo_uart->lcr);
writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr);
neo_pci_posting_flush(ch->ch_bd);
ch->ch_flags &= ~(CH_BREAK_SENDING);
ch->ch_stop_sending_break = 0;
}
}
spin_unlock_irqrestore(&ch->ch_lock, flags);
}
/* Parse the ISR register. */
static inline void neo_parse_isr(struct dgnc_board *brd, uint port)
{
struct channel_t *ch;
unsigned char isr;
unsigned char cause;
unsigned long flags;
ch = brd->channels[port];
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);
if (isr & UART_IIR_NO_INT)
break;
/*
* Yank off the upper 2 bits,
* which just show that the FIFO's are enabled.
*/
isr &= ~(UART_17158_IIR_FIFO_ENABLED);
if (isr & (UART_17158_IIR_RDI_TIMEOUT | UART_IIR_RDI)) {
/* Read data from uart -> queue */
neo_copy_data_from_uart_to_queue(ch);
/*
* Call our tty layer to enforce queue
* flow control if needed.
*/
spin_lock_irqsave(&ch->ch_lock, flags);
dgnc_check_queue_flow_control(ch);
spin_unlock_irqrestore(&ch->ch_lock, flags);
}
if (isr & UART_IIR_THRI) {
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);
neo_copy_data_from_queue_to_uart(ch);
}
if (isr & UART_17158_IIR_XONXOFF) {
cause = readb(&ch->ch_neo_uart->xoffchar1);
/*
* Since the UART detected either an XON or
* XOFF match, we need to figure out which
* one it was, so we can suspend or resume data flow.
*/
if (cause == UART_17158_XON_DETECT) {
/* resume output if stopped */
if (brd->channels[port]->ch_flags & CH_STOP) {
spin_lock_irqsave(&ch->ch_lock,
flags);
ch->ch_flags &= ~(CH_STOP);
spin_unlock_irqrestore(&ch->ch_lock,
flags);
}
} else if (cause == UART_17158_XOFF_DETECT) {
if (!(brd->channels[port]->ch_flags &
CH_STOP)) {
spin_lock_irqsave(&ch->ch_lock,
flags);
ch->ch_flags |= CH_STOP;
spin_unlock_irqrestore(&ch->ch_lock,
flags);
}
}
}
if (isr & UART_17158_IIR_HWFLOW_STATE_CHANGE) {
/*
* If we get here, this means the hardware is
* doing auto flow control. Check to see whether
* RTS/DTR or CTS/DSR caused this interrupt.
*/
cause = readb(&ch->ch_neo_uart->mcr);
/* Which pin is doing auto flow? RTS or DTR? */
if ((cause & 0x4) == 0) {
if (cause & UART_MCR_RTS) {
spin_lock_irqsave(&ch->ch_lock,
flags);
ch->ch_mostat |= UART_MCR_RTS;
spin_unlock_irqrestore(&ch->ch_lock,
flags);
} else {
spin_lock_irqsave(&ch->ch_lock,
flags);
ch->ch_mostat &= ~(UART_MCR_RTS);
spin_unlock_irqrestore(&ch->ch_lock,
flags);
}
} else {
if (cause & UART_MCR_DTR) {
spin_lock_irqsave(&ch->ch_lock,
flags);
ch->ch_mostat |= UART_MCR_DTR;
spin_unlock_irqrestore(&ch->ch_lock,
flags);
} else {
spin_lock_irqsave(&ch->ch_lock,
flags);
ch->ch_mostat &= ~(UART_MCR_DTR);
spin_unlock_irqrestore(&ch->ch_lock,
flags);
}
}
}
neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
}
}
static inline void neo_parse_lsr(struct dgnc_board *brd, uint port)
{
struct channel_t *ch;
int linestatus;
unsigned long flags;
if (!brd)
return;
if (port >= brd->maxports)
return;
ch = brd->channels[port];
if (!ch)
return;
linestatus = readb(&ch->ch_neo_uart->lsr);
ch->ch_cached_lsr |= linestatus;
if (ch->ch_cached_lsr & UART_LSR_DR) {
neo_copy_data_from_uart_to_queue(ch);
spin_lock_irqsave(&ch->ch_lock, flags);
dgnc_check_queue_flow_control(ch);
spin_unlock_irqrestore(&ch->ch_lock, flags);
}
/*
* The next 3 tests should *NOT* happen, as the above test
* should encapsulate all 3... At least, thats what Exar says.
*/
if (linestatus & UART_LSR_PE)
ch->ch_err_parity++;
if (linestatus & UART_LSR_FE)
ch->ch_err_frame++;
if (linestatus & UART_LSR_BI)
ch->ch_err_break++;
if (linestatus & UART_LSR_OE) {
/*
* Rx Oruns. Exar says that an orun will NOT corrupt
* the FIFO. It will just replace the holding register
* with this new data byte. So basically just ignore this.
* Probably we should eventually have an orun stat in our
* driver...
*/
ch->ch_err_overrun++;
}
if (linestatus & UART_LSR_THRE) {
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);
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);
neo_copy_data_from_queue_to_uart(ch);
}
}
/* Send any/all changes to the line to the UART. */
static void neo_param(struct tty_struct *tty)
{
unsigned char lcr = 0;
unsigned char uart_lcr = 0;
unsigned char ier = 0;
unsigned char uart_ier = 0;
uint baud = 9600;
int quot = 0;
struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
if (!tty)
return;
un = (struct un_t *)tty->driver_data;
if (!un)
return;
ch = un->un_ch;
if (!ch)
return;
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 = 0;
ch->ch_r_tail = 0;
ch->ch_e_head = 0;
ch->ch_e_tail = 0;
ch->ch_w_head = 0;
ch->ch_w_tail = 0;
neo_flush_uart_write(ch);
neo_flush_uart_read(ch);
/* The baudrate is B0 so all modem lines are to be dropped. */
ch->ch_flags |= (CH_BAUD0);
ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR);
neo_assert_modem_signals(ch);
ch->ch_old_baud = 0;
return;
} else if (ch->ch_custom_speed) {
baud = ch->ch_custom_speed;
/* Handle transition from B0 */
if (ch->ch_flags & CH_BAUD0) {
ch->ch_flags &= ~(CH_BAUD0);
/*
* Bring back up RTS and DTR...
* Also handle RTS or DTR toggle if set.
*/
if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE))
ch->ch_mostat |= (UART_MCR_RTS);
if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE))
ch->ch_mostat |= (UART_MCR_DTR);
}
} else {
int iindex = 0;
int jindex = 0;
ulong bauds[4][16] = {
{ /* slowbaud */
0, 50, 75, 110,
134, 150, 200, 300,
600, 1200, 1800, 2400,
4800, 9600, 19200, 38400 },
{ /* slowbaud & CBAUDEX */
0, 57600, 115200, 230400,
460800, 150, 200, 921600,
600, 1200, 1800, 2400,
4800, 9600, 19200, 38400 },
{ /* fastbaud */
0, 57600, 76800, 115200,
131657, 153600, 230400, 460800,
921600, 1200, 1800, 2400,
4800, 9600, 19200, 38400 },
{ /* fastbaud & CBAUDEX */
0, 57600, 115200, 230400,
460800, 150, 200, 921600,
600, 1200, 1800, 2400,
4800, 9600, 19200, 38400 }
};
/*
* Only use the TXPrint baud rate if the terminal unit
* is NOT open
*/
if (!(ch->ch_tun.un_flags & UN_ISOPEN) &&
(un->un_type == DGNC_PRINT))
baud = C_BAUD(ch->ch_pun.un_tty) & 0xff;
else
baud = C_BAUD(ch->ch_tun.un_tty) & 0xff;
if (ch->ch_c_cflag & CBAUDEX)
iindex = 1;
if (ch->ch_digi.digi_flags & DIGI_FAST)
iindex += 2;
jindex = baud;
if ((iindex >= 0) && (iindex < 4) &&
(jindex >= 0) && (jindex < 16))
baud = bauds[iindex][jindex];
else
baud = 0;
if (baud == 0)
baud = 9600;
/* Handle transition from B0 */
if (ch->ch_flags & CH_BAUD0) {
ch->ch_flags &= ~(CH_BAUD0);
/*
* Bring back up RTS and DTR...
* Also handle RTS or DTR toggle if set.
*/
if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE))
ch->ch_mostat |= (UART_MCR_RTS);
if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE))
ch->ch_mostat |= (UART_MCR_DTR);
}
}
if (ch->ch_c_cflag & PARENB)
lcr |= UART_LCR_PARITY;
if (!(ch->ch_c_cflag & PARODD))
lcr |= UART_LCR_EPAR;
#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;
}
uart_ier = readb(&ch->ch_neo_uart->ier);
ier = uart_ier;
uart_lcr = readb(&ch->ch_neo_uart->lcr);
if (baud == 0)
baud = 9600;
quot = ch->ch_bd->bd_dividend / baud;
if (quot != 0 && ch->ch_old_baud != baud) {
ch->ch_old_baud = baud;
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);
else
ier &= ~(UART_IER_RDI | UART_IER_RLSI);
/*
* Have the UART interrupt on modem signal changes ONLY when
* we are in hardware flow control mode, or CLOCAL/FORCEDCD is not set.
*/
if ((ch->ch_digi.digi_flags & CTSPACE) ||
(ch->ch_digi.digi_flags & RTSPACE) ||
(ch->ch_c_cflag & CRTSCTS) ||
!(ch->ch_digi.digi_flags & DIGI_FORCEDCD) ||
!(ch->ch_c_cflag & CLOCAL))
ier |= UART_IER_MSI;
else
ier &= ~UART_IER_MSI;
ier |= UART_IER_THRI;
if (ier != uart_ier)
writeb(ier, &ch->ch_neo_uart->ier);
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 ((ch->ch_startc == _POSIX_VDISABLE) ||
(ch->ch_stopc == _POSIX_VDISABLE))
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_digi.digi_flags & RTSPACE || ch->ch_c_cflag & CRTSCTS) {
neo_set_rts_flow_control(ch);
} else if (ch->ch_c_iflag & IXOFF) {
if ((ch->ch_startc == _POSIX_VDISABLE) ||
(ch->ch_stopc == _POSIX_VDISABLE))
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);
neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
}
/* Board poller function. */
static void neo_tasklet(unsigned long data)
{
struct dgnc_board *bd = (struct dgnc_board *)data;
struct channel_t *ch;
unsigned long flags;
int i;
int state = 0;
int ports = 0;
if (!bd)
return;
spin_lock_irqsave(&bd->bd_lock, flags);
state = bd->state;
ports = bd->nasync;
spin_unlock_irqrestore(&bd->bd_lock, flags);
/*
* Do NOT allow the interrupt routine to read the intr registers
* Until we release this lock.
*/
spin_lock_irqsave(&bd->bd_intr_lock, flags);
if ((state == BOARD_READY) && (ports > 0)) {
for (i = 0; i < ports; i++) {
ch = bd->channels[i];
if (!ch)
continue;
/*
* NOTE: Remember you CANNOT hold any channel
* locks when calling the input routine.
*
* During input processing, its possible we
* will call the Linux ld, which might in turn,
* do a callback right back into us, resulting
* in us trying to grab the channel lock twice!
*/
dgnc_input(ch);
/*
* Channel lock is grabbed and then released
* inside both of these routines, but neither
* call anything else that could call back into us.
*/
neo_copy_data_from_queue_to_uart(ch);
dgnc_wakeup_writes(ch);
dgnc_carrier(ch);
/*
* Check to see if we need to turn off a sending break.
* The timing check is done inside clear_break()
*/
if (ch->ch_stop_sending_break)
neo_clear_break(ch, 0);
}
}
spin_unlock_irqrestore(&bd->bd_intr_lock, flags);
}
/* Neo specific interrupt handler. */
static irqreturn_t neo_intr(int irq, void *voidbrd)
{
struct dgnc_board *brd = voidbrd;
struct channel_t *ch;
int port = 0;
int type;
u32 uart_poll;
unsigned long flags;
unsigned long flags2;
if (!brd)
return IRQ_NONE;
/* Lock out the slow poller from running on this board. */
spin_lock_irqsave(&brd->bd_intr_lock, flags);
/*
* Read in "extended" IRQ information from the 32bit Neo register.
* Bits 0-7: What port triggered the interrupt.
* Bits 8-31: Each 3bits indicate what type of interrupt occurred.
*/
uart_poll = readl(brd->re_map_membase + UART_17158_POLL_ADDR_OFFSET);
/*
* If 0, no interrupts pending.
* This can happen if the IRQ is shared among a couple Neo/Classic
* boards.
*/
if (!uart_poll) {
spin_unlock_irqrestore(&brd->bd_intr_lock, flags);
return IRQ_NONE;
}
while ((uart_poll & 0xff) != 0) {
type = uart_poll >> (8 + (port * 3));
type &= 0x7;
uart_poll &= ~(0x01 << port);
switch (type) {
case UART_17158_RXRDY_TIMEOUT:
/*
* RXRDY Time-out is cleared by reading data in the
* RX FIFO until it falls below the trigger level.
*/
if (port >= brd->nasync)
break;
ch = brd->channels[port];
neo_copy_data_from_uart_to_queue(ch);
/*
* Call our tty layer to enforce queue flow control if
* needed.
*/
spin_lock_irqsave(&ch->ch_lock, flags2);
dgnc_check_queue_flow_control(ch);
spin_unlock_irqrestore(&ch->ch_lock, flags2);
break;
case UART_17158_RX_LINE_STATUS:
/* RXRDY and RX LINE Status (logic OR of LSR[4:1]) */
neo_parse_lsr(brd, port);
break;
case UART_17158_TXRDY:
/*
* TXRDY interrupt clears after reading ISR register
* for the UART channel.
*/
/*
* Yes, this is odd...
* Why would I check EVERY possibility of type of
* interrupt, when we know its TXRDY???
* Becuz for some reason, even tho we got triggered for
* TXRDY, it seems to be occasionally wrong. Instead of
* TX, which it should be, I was getting things like
* RXDY too. Weird.
*/
neo_parse_isr(brd, port);
break;
case UART_17158_MSR:
/* MSR or flow control was seen. */
neo_parse_isr(brd, port);
break;
default:
break;
}
port++;
}
tasklet_schedule(&brd->helper_tasklet);
spin_unlock_irqrestore(&brd->bd_intr_lock, flags);
return IRQ_HANDLED;
}
/*
* Neo specific way of turning off the receiver.
* Used as a way to enforce queue flow control when in
* hardware flow control mode.
*/
static void neo_disable_receiver(struct channel_t *ch)
{
unsigned char tmp = readb(&ch->ch_neo_uart->ier);
tmp &= ~(UART_IER_RDI);
writeb(tmp, &ch->ch_neo_uart->ier);
neo_pci_posting_flush(ch->ch_bd);
}
/*
* Neo specific way of turning on the receiver.
* Used as a way to un-enforce queue flow control when in
* hardware flow control mode.
*/
static void neo_enable_receiver(struct channel_t *ch)
{
unsigned char tmp = readb(&ch->ch_neo_uart->ier);
tmp |= (UART_IER_RDI);
writeb(tmp, &ch->ch_neo_uart->ier);
neo_pci_posting_flush(ch->ch_bd);
}
static void neo_copy_data_from_uart_to_queue(struct channel_t *ch)
{
int qleft = 0;
unsigned char linestatus = 0;
unsigned char error_mask = 0;
int n = 0;
int total = 0;
ushort head;
ushort tail;
unsigned long flags;
if (!ch)
return;
spin_lock_irqsave(&ch->ch_lock, flags);
head = ch->ch_r_head & RQUEUEMASK;
tail = ch->ch_r_tail & RQUEUEMASK;
linestatus = ch->ch_cached_lsr;
ch->ch_cached_lsr = 0;
qleft = tail - head - 1;
if (qleft < 0)
qleft += RQUEUEMASK + 1;
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);
/*
* EXAR chip bug - RX FIFO COUNT - Fudge factor.
*
* This resolves a problem/bug with the Exar chip that sometimes
* returns a bogus value in the rfifo register.
* The count can be any where from 0-3 bytes "off".
* Bizarre, but true.
*/
if ((ch->ch_bd->dvid & 0xf0) >= UART_XR17E158_DVID)
total -= 1;
else
total -= 3;
}
total = min(total, qleft);
while (total > 0) {
linestatus = readb(&ch->ch_neo_uart->lsr);
if (linestatus & UART_17158_RX_FIFO_DATA_ERROR)
break;
/* Make sure we don't go over the end of our queue */
n = min(((uint)total), (RQUEUESIZE - (uint)head));
/*
* Cut down n even further if needed, this is to fix
* a problem with memcpy_fromio() with the Neo on the
* IBM pSeries platform.
* 15 bytes max appears to be the magic number.
*/
n = min_t(uint, n, 12);
/*
* Since we are grabbing the linestatus register, which
* will reset some bits after our read, we need to ensure
* we don't miss our TX FIFO emptys.
*/
if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR))
ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
linestatus = 0;
memcpy_fromio(ch->ch_rqueue + head,
&ch->ch_neo_uart->txrxburst, n);
/*
* Since RX_FIFO_DATA_ERROR was 0, we are guaranteed
* that all the data currently in the FIFO is free of
* breaks and parity/frame/orun errors.
*/
memset(ch->ch_equeue + head, 0, n);
head = (head + n) & RQUEUEMASK;
total -= n;
qleft -= n;
ch->ch_rxcount += n;
}
/*
* Create a mask to determine whether we should
* insert the character (if any) into our queue.
*/
if (ch->ch_c_iflag & IGNBRK)
error_mask |= UART_LSR_BI;
/*
* Now cleanup any leftover bytes still in the UART.
* Also deal with any possible queue overflow here as well.
*/
while (1) {
/*
* Its possible we have a linestatus from the loop above
* this, so we "OR" on any extra bits.
*/
linestatus |= readb(&ch->ch_neo_uart->lsr);
/*
* If the chip tells us there is no more data pending to
* be read, we can then leave.
* But before we do, cache the linestatus, just in case.
*/
if (!(linestatus & UART_LSR_DR)) {
ch->ch_cached_lsr = linestatus;
break;
}
/* No need to store this bit */
linestatus &= ~UART_LSR_DR;
/*
* Since we are grabbing the linestatus register, which
* will reset some bits after our read, we need to ensure
* we don't miss our TX FIFO emptys.
*/
if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR)) {
linestatus &= ~(UART_LSR_THRE |
UART_17158_TX_AND_FIFO_CLR);
ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
}
if (linestatus & error_mask) {
unsigned char discard;
linestatus = 0;
memcpy_fromio(&discard, &ch->ch_neo_uart->txrxburst, 1);
continue;
}
/*
* 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;
ch->ch_r_tail = tail;
ch->ch_err_overrun++;
qleft++;
}
memcpy_fromio(ch->ch_rqueue + head,
&ch->ch_neo_uart->txrxburst, 1);
ch->ch_equeue[head] = (unsigned char)linestatus;
linestatus = 0;
head = (head + 1) & RQUEUEMASK;
qleft--;
ch->ch_rxcount++;
}
ch->ch_r_head = head & RQUEUEMASK;
ch->ch_e_head = head & EQUEUEMASK;
spin_unlock_irqrestore(&ch->ch_lock, flags);
}
/*
* This function basically goes to sleep for secs, or until
* it gets signalled that the port has fully drained.
*/
static int neo_drain(struct tty_struct *tty, uint seconds)
{
unsigned long flags;
struct channel_t *ch;
struct un_t *un;
if (!tty)
return -ENXIO;
un = (struct un_t *)tty->driver_data;
if (!un)
return -ENXIO;
ch = un->un_ch;
if (!ch)
return -ENXIO;
spin_lock_irqsave(&ch->ch_lock, flags);
un->un_flags |= UN_EMPTY;
spin_unlock_irqrestore(&ch->ch_lock, flags);
/* If returned value is non-zero, user ctrl-c'ed us */
return wait_event_interruptible_timeout(un->un_flags_wait,
((un->un_flags & UN_EMPTY) == 0),
msecs_to_jiffies(seconds * 1000));
}
/*
* Flush the WRITE FIFO on the Neo.
* 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)
return;
writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT),
&ch->ch_neo_uart->isr_fcr);
neo_pci_posting_flush(ch->ch_bd);
for (i = 0; i < 10; i++) {
/*
* Check to see if the UART completely flushed the FIFO
* FIFO.
*/
tmp = readb(&ch->ch_neo_uart->isr_fcr);
if (tmp & 4)
udelay(10);
else
break;
}
ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
}
/*
* Flush the READ FIFO on the Neo.
* 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)
return;
writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR,
&ch->ch_neo_uart->isr_fcr);
neo_pci_posting_flush(ch->ch_bd);
for (i = 0; i < 10; i++) {
/*
* Check to see if the UART feels it completely flushed the
* FIFO.
*/
tmp = readb(&ch->ch_neo_uart->isr_fcr);
if (tmp & 2)
udelay(10);
else
break;
}
}
static void neo_copy_data_from_queue_to_uart(struct channel_t *ch)
{
ushort head;
ushort tail;
int n;
int s;
int qlen;
uint len_written = 0;
unsigned long flags;
if (!ch)
return;
spin_lock_irqsave(&ch->ch_lock, flags);
if (ch->ch_w_tail == ch->ch_w_head)
goto exit_unlock;
/* If port is "stopped", don't send any data to the UART */
if ((ch->ch_flags & CH_FORCED_STOP) ||
(ch->ch_flags & CH_BREAK_SENDING))
goto exit_unlock;
if (!(ch->ch_flags & CH_FIFO_ENABLED)) {
/* Send data directly to txrx register */
unsigned char lsrbits = readb(&ch->ch_neo_uart->lsr);
ch->ch_cached_lsr |= lsrbits;
if (ch->ch_cached_lsr & UART_LSR_THRE) {
ch->ch_cached_lsr &= ~(UART_LSR_THRE);
/*
* If RTS Toggle mode is on, turn on RTS now if not
* already set, and make sure we get an event when the
* data transfer has completed.
*/
if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) {
if (!(ch->ch_mostat & UART_MCR_RTS)) {
ch->ch_mostat |= (UART_MCR_RTS);
neo_assert_modem_signals(ch);
}
ch->ch_tun.un_flags |= (UN_EMPTY);
}
/*
* If DTR Toggle mode is on, turn on DTR now if not
* already set, and make sure we get an event when the
* data transfer has completed.
*/
if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) {
if (!(ch->ch_mostat & UART_MCR_DTR)) {
ch->ch_mostat |= (UART_MCR_DTR);
neo_assert_modem_signals(ch);
}
ch->ch_tun.un_flags |= (UN_EMPTY);
}
writeb(ch->ch_wqueue[ch->ch_w_tail],
&ch->ch_neo_uart->txrx);
ch->ch_w_tail++;
ch->ch_w_tail &= WQUEUEMASK;
ch->ch_txcount++;
}
goto exit_unlock;
}
/* We have to do it this way, because of the EXAR TXFIFO count bug. */
if ((ch->ch_bd->dvid & 0xf0) < UART_XR17E158_DVID) {
if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM)))
goto exit_unlock;
len_written = 0;
n = readb(&ch->ch_neo_uart->tfifo);
if ((unsigned int)n > ch->ch_t_tlevel)
goto exit_unlock;
n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel;
} else {
n = UART_17158_TX_FIFOSIZE - readb(&ch->ch_neo_uart->tfifo);
}
head = ch->ch_w_head & WQUEUEMASK;
tail = ch->ch_w_tail & WQUEUEMASK;
qlen = (head - tail) & WQUEUEMASK;
n = min(n, qlen);
while (n > 0) {
s = ((head >= tail) ? head : WQUEUESIZE) - tail;
s = min(s, n);
if (s <= 0)
break;
/*
* If RTS Toggle mode is on, turn on RTS now if not already set,
* and make sure we get an event when the data transfer has
* completed.
*/
if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) {
if (!(ch->ch_mostat & UART_MCR_RTS)) {
ch->ch_mostat |= (UART_MCR_RTS);
neo_assert_modem_signals(ch);
}
ch->ch_tun.un_flags |= (UN_EMPTY);
}
/*
* If DTR Toggle mode is on, turn on DTR now if not already set,
* and make sure we get an event when the data transfer has
* completed.
*/
if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) {
if (!(ch->ch_mostat & UART_MCR_DTR)) {
ch->ch_mostat |= (UART_MCR_DTR);
neo_assert_modem_signals(ch);
}
ch->ch_tun.un_flags |= (UN_EMPTY);
}
memcpy_toio(&ch->ch_neo_uart->txrxburst,
ch->ch_wqueue + tail, s);
tail = (tail + s) & WQUEUEMASK;
n -= s;
ch->ch_txcount += s;
len_written += s;
}
ch->ch_w_tail = tail & WQUEUEMASK;
if (len_written > 0) {
neo_pci_posting_flush(ch->ch_bd);
ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
}
exit_unlock:
spin_unlock_irqrestore(&ch->ch_lock, flags);
}
static void neo_parse_modem(struct channel_t *ch, unsigned char signals)
{
unsigned char msignals = signals;
if (!ch)
return;
/*
* Do altpin switching. Altpin switches DCD and DSR.
* This prolly breaks DSRPACE, so we should be more clever here.
*/
if (ch->ch_digi.digi_flags & DIGI_ALTPIN) {
unsigned char mswap = msignals;
if (mswap & UART_MSR_DDCD) {
msignals &= ~UART_MSR_DDCD;
msignals |= UART_MSR_DDSR;
}
if (mswap & UART_MSR_DDSR) {
msignals &= ~UART_MSR_DDSR;
msignals |= UART_MSR_DDCD;
}
if (mswap & UART_MSR_DCD) {
msignals &= ~UART_MSR_DCD;
msignals |= UART_MSR_DSR;
}
if (mswap & UART_MSR_DSR) {
msignals &= ~UART_MSR_DSR;
msignals |= UART_MSR_DCD;
}
}
/* Scrub off lower bits. They signify delta's */
msignals &= 0xf0;
if (msignals & UART_MSR_DCD)
ch->ch_mistat |= UART_MSR_DCD;
else
ch->ch_mistat &= ~UART_MSR_DCD;
if (msignals & UART_MSR_DSR)
ch->ch_mistat |= UART_MSR_DSR;
else
ch->ch_mistat &= ~UART_MSR_DSR;
if (msignals & UART_MSR_RI)
ch->ch_mistat |= UART_MSR_RI;
else
ch->ch_mistat &= ~UART_MSR_RI;
if (msignals & UART_MSR_CTS)
ch->ch_mistat |= UART_MSR_CTS;
else
ch->ch_mistat &= ~UART_MSR_CTS;
}
/* Make the UART raise any of the output signals we want up */
static void neo_assert_modem_signals(struct channel_t *ch)
{
unsigned char out;
if (!ch)
return;
out = ch->ch_mostat;
if (ch->ch_flags & CH_LOOPBACK)
out |= UART_MCR_LOOP;
writeb(out, &ch->ch_neo_uart->mcr);
neo_pci_posting_flush(ch->ch_bd);
/* Give time for the UART to actually raise/drop the signals */
udelay(10);
}
static void neo_send_start_character(struct channel_t *ch)
{
if (!ch)
return;
if (ch->ch_startc != _POSIX_VDISABLE) {
ch->ch_xon_sends++;
writeb(ch->ch_startc, &ch->ch_neo_uart->txrx);
neo_pci_posting_flush(ch->ch_bd);
udelay(10);
}
}
static void neo_send_stop_character(struct channel_t *ch)
{
if (!ch)
return;
if (ch->ch_stopc != _POSIX_VDISABLE) {
ch->ch_xoff_sends++;
writeb(ch->ch_stopc, &ch->ch_neo_uart->txrx);
neo_pci_posting_flush(ch->ch_bd);
udelay(10);
}
}
/* neo_uart_init */
static void neo_uart_init(struct channel_t *ch)
{
writeb(0, &ch->ch_neo_uart->ier);
writeb(0, &ch->ch_neo_uart->efr);
writeb(UART_EFR_ECB, &ch->ch_neo_uart->efr);
/* Clear out UART and FIFO */
readb(&ch->ch_neo_uart->txrx);
writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
&ch->ch_neo_uart->isr_fcr);
readb(&ch->ch_neo_uart->lsr);
readb(&ch->ch_neo_uart->msr);
ch->ch_flags |= CH_FIFO_ENABLED;
/* Assert any signals we want up */
writeb(ch->ch_mostat, &ch->ch_neo_uart->mcr);
neo_pci_posting_flush(ch->ch_bd);
}
/* Make the UART completely turn off. */
static void neo_uart_off(struct channel_t *ch)
{
/* Turn off UART enhanced bits */
writeb(0, &ch->ch_neo_uart->efr);
/* Stop all interrupts from occurring. */
writeb(0, &ch->ch_neo_uart->ier);
neo_pci_posting_flush(ch->ch_bd);
}
static uint neo_get_uart_bytes_left(struct channel_t *ch)
{
unsigned char left = 0;
unsigned char lsr = readb(&ch->ch_neo_uart->lsr);
/* We must cache the LSR as some of the bits get reset once read... */
ch->ch_cached_lsr |= lsr;
/* Determine whether the Transmitter is empty or not */
if (!(lsr & UART_LSR_TEMT)) {
if (ch->ch_flags & CH_TX_FIFO_EMPTY)
tasklet_schedule(&ch->ch_bd->helper_tasklet);
left = 1;
} else {
ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
left = 0;
}
return left;
}
/* Channel lock MUST be held by the calling function! */
static void neo_send_break(struct channel_t *ch, int msecs)
{
/* If we receive a time of 0, this means turn off the break. */
if (msecs == 0) {
if (ch->ch_flags & CH_BREAK_SENDING) {
unsigned char temp = readb(&ch->ch_neo_uart->lcr);
writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr);
neo_pci_posting_flush(ch->ch_bd);
ch->ch_flags &= ~(CH_BREAK_SENDING);
ch->ch_stop_sending_break = 0;
}
return;
}
/*
* Set the time we should stop sending the break.
* If we are already sending a break, toss away the existing
* time to stop, and use this new value instead.
*/
ch->ch_stop_sending_break = jiffies + dgnc_jiffies_from_ms(msecs);
/* Tell the UART to start sending the break */
if (!(ch->ch_flags & CH_BREAK_SENDING)) {
unsigned char temp = readb(&ch->ch_neo_uart->lcr);
writeb((temp | UART_LCR_SBC), &ch->ch_neo_uart->lcr);
neo_pci_posting_flush(ch->ch_bd);
ch->ch_flags |= (CH_BREAK_SENDING);
}
}
/*
* Sends a specific character as soon as possible to the UART,
* jumping over any bytes that might be in the write queue.
*
* The channel lock MUST be held by the calling function.
*/
static void neo_send_immediate_char(struct channel_t *ch, unsigned char c)
{
if (!ch)
return;
writeb(c, &ch->ch_neo_uart->txrx);
neo_pci_posting_flush(ch->ch_bd);
}
static unsigned int neo_read_eeprom(unsigned char __iomem *base,
unsigned int address)
{
unsigned int enable;
unsigned int bits;
unsigned int databit;
unsigned int val;
/* enable chip select */
writeb(NEO_EECS, base + NEO_EEREG);
/* READ */
enable = address | 0x180;
for (bits = 9; bits--; ) {
databit = (enable & (1 << bits)) ? NEO_EEDI : 0;
/* Set read address */
writeb(databit | NEO_EECS, base + NEO_EEREG);
writeb(databit | NEO_EECS | NEO_EECK, base + NEO_EEREG);
}
val = 0;
for (bits = 17; bits--; ) {
/* clock to EEPROM */
writeb(NEO_EECS, base + NEO_EEREG);
writeb(NEO_EECS | NEO_EECK, base + NEO_EEREG);
val <<= 1;
/* read EEPROM */
if (readb(base + NEO_EEREG) & NEO_EEDO)
val |= 1;
}
/* clock falling edge */
writeb(NEO_EECS, base + NEO_EEREG);
/* drop chip select */
writeb(0x00, base + NEO_EEREG);
return val;
}
static void neo_vpd(struct dgnc_board *brd)
{
unsigned int i = 0;
unsigned int a;
if (!brd)
return;
if (!brd->re_map_membase)
return;
/* Store the VPD into our buffer */
for (i = 0; i < NEO_VPD_IMAGESIZE; i++) {
a = neo_read_eeprom(brd->re_map_membase, i);
brd->vpd[i * 2] = a & 0xff;
brd->vpd[(i * 2) + 1] = (a >> 8) & 0xff;
}
/*
* brd->vpd has different name tags by below index.
* 0x08 : long resource name tag
* 0x10 : long resource name tage (PCI-66 files)
* 0x7F : small resource end tag
*/
if (((brd->vpd[0x08] != 0x82) &&
(brd->vpd[0x10] != 0x82)) ||
(brd->vpd[0x7F] != 0x78)) {
memset(brd->vpd, '\0', NEO_VPD_IMAGESIZE);
} else {
/* Search for the serial number */
for (i = 0; i < NEO_VPD_IMAGEBYTES - 3; i++)
if (brd->vpd[i] == 'S' && brd->vpd[i + 1] == 'N')
strncpy(brd->serial_num, &brd->vpd[i + 3], 9);
}
}
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*/
#ifndef _DGNC_NEO_H
#define _DGNC_NEO_H
#include "dgnc_driver.h"
/**
* struct neo_uart_struct - Per channel/port NEO UART structure
*
* key - W = read write
* - R = read only
* - U = unused
*
* @txrx: (RW) Holding Register.
* @ier: (RW) Interrupt Enable Register.
* @isr_fcr: (RW) Interrupt Status Reg/Fifo Control Register.
* @lcr: (RW) Line Control Register.
* @mcr: (RW) Modem Control Register.
* @lsr: (RW) Line Status Register.
* @msr: (RW) Modem Status Register.
* @spr: (RW) Scratch Pad Register.
* @fctr: (RW) Feature Control Register.
* @efr: (RW) Enhanced Function Register.
* @tfifo: (RW) Transmit FIFO Register.
* @rfifo: (RW) Receive FIFO Register.
* @xoffchar1: (RW) XOff Character 1 Register.
* @xoffchar2: (RW) XOff Character 2 Register.
* @xonchar1: (RW) Xon Character 1 Register.
* @xonchar2: (RW) XOn Character 2 Register.
* @reserved1: (U) Reserved by Exar.
* @txrxburst: (RW) 64 bytes of RX/TX FIFO Data.
* @reserved2: (U) Reserved by Exar.
* @rxburst_with_errors: (R) bytes of RX FIFO Data + LSR.
*/
struct neo_uart_struct {
u8 txrx;
u8 ier;
u8 isr_fcr;
u8 lcr;
u8 mcr;
u8 lsr;
u8 msr;
u8 spr;
u8 fctr;
u8 efr;
u8 tfifo;
u8 rfifo;
u8 xoffchar1;
u8 xoffchar2;
u8 xonchar1;
u8 xonchar2;
u8 reserved1[0x2ff - 0x200];
u8 txrxburst[64];
u8 reserved2[0x37f - 0x340];
u8 rxburst_with_errors[64];
};
/* Where to read the extended interrupt register (32bits instead of 8bits) */
#define UART_17158_POLL_ADDR_OFFSET 0x80
/* These are the current dvid's of the Neo boards */
#define UART_XR17C158_DVID 0x20
#define UART_XR17D158_DVID 0x20
#define UART_XR17E158_DVID 0x40
#define NEO_EECK 0x10 /* Clock */
#define NEO_EECS 0x20 /* Chip Select */
#define NEO_EEDI 0x40 /* Data In is an Output Pin */
#define NEO_EEDO 0x80 /* Data Out is an Input Pin */
#define NEO_EEREG 0x8E /* offset to EEPROM control reg */
#define NEO_VPD_IMAGESIZE 0x40 /* size of image to read from EEPROM in words */
#define NEO_VPD_IMAGEBYTES (NEO_VPD_IMAGESIZE * 2)
/*
* These are the redefinitions for the FCTR on the XR17C158, since
* Exar made them different than their earlier design. (XR16C854)
*/
/* These are only applicable when table D is selected */
#define UART_17158_FCTR_RTS_NODELAY 0x00
#define UART_17158_FCTR_RTS_4DELAY 0x01
#define UART_17158_FCTR_RTS_6DELAY 0x02
#define UART_17158_FCTR_RTS_8DELAY 0x03
#define UART_17158_FCTR_RTS_12DELAY 0x12
#define UART_17158_FCTR_RTS_16DELAY 0x05
#define UART_17158_FCTR_RTS_20DELAY 0x13
#define UART_17158_FCTR_RTS_24DELAY 0x06
#define UART_17158_FCTR_RTS_28DELAY 0x14
#define UART_17158_FCTR_RTS_32DELAY 0x07
#define UART_17158_FCTR_RTS_36DELAY 0x16
#define UART_17158_FCTR_RTS_40DELAY 0x08
#define UART_17158_FCTR_RTS_44DELAY 0x09
#define UART_17158_FCTR_RTS_48DELAY 0x10
#define UART_17158_FCTR_RTS_52DELAY 0x11
#define UART_17158_FCTR_RTS_IRDA 0x10
#define UART_17158_FCTR_RS485 0x20
#define UART_17158_FCTR_TRGA 0x00
#define UART_17158_FCTR_TRGB 0x40
#define UART_17158_FCTR_TRGC 0x80
#define UART_17158_FCTR_TRGD 0xC0
/* 17158 trigger table selects.. */
#define UART_17158_FCTR_BIT6 0x40
#define UART_17158_FCTR_BIT7 0x80
/* 17158 TX/RX memmapped buffer offsets */
#define UART_17158_RX_FIFOSIZE 64
#define UART_17158_TX_FIFOSIZE 64
/* 17158 Extended IIR's */
#define UART_17158_IIR_RDI_TIMEOUT 0x0C /* Receiver data TIMEOUT */
#define UART_17158_IIR_XONXOFF 0x10 /* Received an XON/XOFF char */
#define UART_17158_IIR_HWFLOW_STATE_CHANGE 0x20 /* CTS/DSR or RTS/DTR
* state change
*/
#define UART_17158_IIR_FIFO_ENABLED 0xC0 /* 16550 FIFOs are Enabled */
/*
* These are the extended interrupts that get sent
* back to us from the UART's 32bit interrupt register
*/
#define UART_17158_RX_LINE_STATUS 0x1 /* RX Ready */
#define UART_17158_RXRDY_TIMEOUT 0x2 /* RX Ready Timeout */
#define UART_17158_TXRDY 0x3 /* TX Ready */
#define UART_17158_MSR 0x4 /* Modem State Change */
#define UART_17158_TX_AND_FIFO_CLR 0x40 /* Transmitter Holding
* Reg Empty
*/
#define UART_17158_RX_FIFO_DATA_ERROR 0x80 /* UART detected an RX FIFO
* Data error
*/
/*
* These are the EXTENDED definitions for the 17C158's Interrupt
* Enable Register.
*/
#define UART_17158_EFR_ECB 0x10 /* Enhanced control bit */
#define UART_17158_EFR_IXON 0x2 /* Receiver compares Xon1/Xoff1 */
#define UART_17158_EFR_IXOFF 0x8 /* Transmit Xon1/Xoff1 */
#define UART_17158_EFR_RTSDTR 0x40 /* Auto RTS/DTR Flow Control Enable */
#define UART_17158_EFR_CTSDSR 0x80 /* Auto CTS/DSR Flow Control Enable */
#define UART_17158_XOFF_DETECT 0x1 /* Indicates whether chip saw an
* incoming XOFF char
*/
#define UART_17158_XON_DETECT 0x2 /* Indicates whether chip saw an
* incoming XON char
*/
#define UART_17158_IER_RSVD1 0x10 /* Reserved by Exar */
#define UART_17158_IER_XOFF 0x20 /* Xoff Interrupt Enable */
#define UART_17158_IER_RTSDTR 0x40 /* Output Interrupt Enable */
#define UART_17158_IER_CTSDSR 0x80 /* Input Interrupt Enable */
extern struct board_ops dgnc_neo_ops;
#endif /* _DGNC_NEO_H */
......@@ -24,7 +24,6 @@
#include <linux/pci.h>
#include "dgnc_driver.h"
#include "dgnc_tty.h"
#include "dgnc_neo.h"
#include "dgnc_cls.h"
/* Default transparent print information. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment