From 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 Mon Sep 17 00:00:00 2001 From: Yunhong Jiang Date: Tue, 4 Aug 2015 12:17:53 -0700 Subject: Add the rt linux 4.1.3-rt3 as base Import the rt linux 4.1.3-rt3 as OPNFV kvm base. It's from git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git linux-4.1.y-rt and the base is: commit 0917f823c59692d751951bf5ea699a2d1e2f26a2 Author: Sebastian Andrzej Siewior Date: Sat Jul 25 12:13:34 2015 +0200 Prepare v4.1.3-rt3 Signed-off-by: Sebastian Andrzej Siewior We lose all the git history this way and it's not good. We should apply another opnfv project repo in future. Change-Id: I87543d81c9df70d99c5001fbdf646b202c19f423 Signed-off-by: Yunhong Jiang --- kernel/drivers/staging/speakup/serialio.c | 220 ++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 kernel/drivers/staging/speakup/serialio.c (limited to 'kernel/drivers/staging/speakup/serialio.c') diff --git a/kernel/drivers/staging/speakup/serialio.c b/kernel/drivers/staging/speakup/serialio.c new file mode 100644 index 000000000..1d9d51bdf --- /dev/null +++ b/kernel/drivers/staging/speakup/serialio.c @@ -0,0 +1,220 @@ +#include +#include + +#include "spk_types.h" +#include "speakup.h" +#include "spk_priv.h" +#include "serialio.h" + +#ifndef SERIAL_PORT_DFNS +#define SERIAL_PORT_DFNS +#endif + +static void start_serial_interrupt(int irq); + +static const struct old_serial_port rs_table[] = { + SERIAL_PORT_DFNS +}; +static const struct old_serial_port *serstate; +static int timeouts; + +const struct old_serial_port *spk_serial_init(int index) +{ + int baud = 9600, quot = 0; + unsigned int cval = 0; + int cflag = CREAD | HUPCL | CLOCAL | B9600 | CS8; + const struct old_serial_port *ser = rs_table + index; + int err; + + /* Divisor, bytesize and parity */ + quot = ser->baud_base / baud; + cval = cflag & (CSIZE | CSTOPB); +#if defined(__powerpc__) || defined(__alpha__) + cval >>= 8; +#else /* !__powerpc__ && !__alpha__ */ + cval >>= 4; +#endif /* !__powerpc__ && !__alpha__ */ + if (cflag & PARENB) + cval |= UART_LCR_PARITY; + if (!(cflag & PARODD)) + cval |= UART_LCR_EPAR; + if (synth_request_region(ser->port, 8)) { + /* try to take it back. */ + pr_info("Ports not available, trying to steal them\n"); + __release_region(&ioport_resource, ser->port, 8); + err = synth_request_region(ser->port, 8); + if (err) { + pr_warn("Unable to allocate port at %x, errno %i", + ser->port, err); + return NULL; + } + } + + /* Disable UART interrupts, set DTR and RTS high + * and set speed. */ + outb(cval | UART_LCR_DLAB, ser->port + UART_LCR); /* set DLAB */ + outb(quot & 0xff, ser->port + UART_DLL); /* LS of divisor */ + outb(quot >> 8, ser->port + UART_DLM); /* MS of divisor */ + outb(cval, ser->port + UART_LCR); /* reset DLAB */ + + /* Turn off Interrupts */ + outb(0, ser->port + UART_IER); + outb(UART_MCR_DTR | UART_MCR_RTS, ser->port + UART_MCR); + + /* If we read 0xff from the LSR, there is no UART here. */ + if (inb(ser->port + UART_LSR) == 0xff) { + synth_release_region(ser->port, 8); + serstate = NULL; + return NULL; + } + + mdelay(1); + speakup_info.port_tts = ser->port; + serstate = ser; + + start_serial_interrupt(ser->irq); + + return ser; +} + +static irqreturn_t synth_readbuf_handler(int irq, void *dev_id) +{ + unsigned long flags; +/*printk(KERN_ERR "in irq\n"); */ +/*pr_warn("in IRQ\n"); */ + int c; + + spin_lock_irqsave(&speakup_info.spinlock, flags); + while (inb_p(speakup_info.port_tts + UART_LSR) & UART_LSR_DR) { + + c = inb_p(speakup_info.port_tts+UART_RX); + synth->read_buff_add((u_char) c); +/*printk(KERN_ERR "c = %d\n", c); */ +/*pr_warn("C = %d\n", c); */ + } + spin_unlock_irqrestore(&speakup_info.spinlock, flags); + return IRQ_HANDLED; +} + +static void start_serial_interrupt(int irq) +{ + int rv; + + if (synth->read_buff_add == NULL) + return; + + rv = request_irq(irq, synth_readbuf_handler, IRQF_SHARED, + "serial", (void *) synth_readbuf_handler); + + if (rv) + pr_err("Unable to request Speakup serial I R Q\n"); + /* Set MCR */ + outb(UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2, + speakup_info.port_tts + UART_MCR); + /* Turn on Interrupts */ + outb(UART_IER_MSI|UART_IER_RLSI|UART_IER_RDI, + speakup_info.port_tts + UART_IER); + inb(speakup_info.port_tts+UART_LSR); + inb(speakup_info.port_tts+UART_RX); + inb(speakup_info.port_tts+UART_IIR); + inb(speakup_info.port_tts+UART_MSR); + outb(1, speakup_info.port_tts + UART_FCR); /* Turn FIFO On */ +} + +void spk_stop_serial_interrupt(void) +{ + if (speakup_info.port_tts == 0) + return; + + if (synth->read_buff_add == NULL) + return; + + /* Turn off interrupts */ + outb(0, speakup_info.port_tts+UART_IER); + /* Free IRQ */ + free_irq(serstate->irq, (void *) synth_readbuf_handler); +} + +int spk_wait_for_xmitr(void) +{ + int tmout = SPK_XMITR_TIMEOUT; + + if ((synth->alive) && (timeouts >= NUM_DISABLE_TIMEOUTS)) { + pr_warn("%s: too many timeouts, deactivating speakup\n", + synth->long_name); + synth->alive = 0; + /* No synth any more, so nobody will restart TTYs, and we thus + * need to do it ourselves. Now that there is no synth we can + * let application flood anyway */ + speakup_start_ttys(); + timeouts = 0; + return 0; + } + while (spk_serial_tx_busy()) { + if (--tmout == 0) { + pr_warn("%s: timed out (tx busy)\n", synth->long_name); + timeouts++; + return 0; + } + udelay(1); + } + tmout = SPK_CTS_TIMEOUT; + while (!((inb_p(speakup_info.port_tts + UART_MSR)) & UART_MSR_CTS)) { + /* CTS */ + if (--tmout == 0) { + /* pr_warn("%s: timed out (cts)\n", + * synth->long_name); */ + timeouts++; + return 0; + } + udelay(1); + } + timeouts = 0; + return 1; +} + +unsigned char spk_serial_in(void) +{ + int tmout = SPK_SERIAL_TIMEOUT; + + while (!(inb_p(speakup_info.port_tts + UART_LSR) & UART_LSR_DR)) { + if (--tmout == 0) { + pr_warn("time out while waiting for input.\n"); + return 0xff; + } + udelay(1); + } + return inb_p(speakup_info.port_tts + UART_RX); +} +EXPORT_SYMBOL_GPL(spk_serial_in); + +unsigned char spk_serial_in_nowait(void) +{ + unsigned char lsr; + + lsr = inb_p(speakup_info.port_tts + UART_LSR); + if (!(lsr & UART_LSR_DR)) + return 0; + return inb_p(speakup_info.port_tts + UART_RX); +} +EXPORT_SYMBOL_GPL(spk_serial_in_nowait); + +int spk_serial_out(const char ch) +{ + if (synth->alive && spk_wait_for_xmitr()) { + outb_p(ch, speakup_info.port_tts); + return 1; + } + return 0; +} +EXPORT_SYMBOL_GPL(spk_serial_out); + +void spk_serial_release(void) +{ + if (speakup_info.port_tts == 0) + return; + synth_release_region(speakup_info.port_tts, 8); + speakup_info.port_tts = 0; +} +EXPORT_SYMBOL_GPL(spk_serial_release); + -- cgit 1.2.3-korg