1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/interrupt.h> 3 #include <linux/ioport.h> 4 5 #include "spk_types.h" 6 #include "speakup.h" 7 #include "spk_priv.h" 8 #include "serialio.h" 9 10 #include <linux/serial_core.h> 11 #include <linux/serial.h> 12 13 static int timeouts; 14 15 static int spk_serial_out(struct spk_synth *in_synth, const char ch); 16 static void spk_serial_send_xchar(struct spk_synth *in_synth, char ch); 17 static void spk_serial_tiocmset(struct spk_synth *in_synth, unsigned int set, unsigned int clear); 18 static unsigned char spk_serial_in(struct spk_synth *in_synth); 19 static unsigned char spk_serial_in_nowait(struct spk_synth *in_synth); 20 static void spk_serial_flush_buffer(struct spk_synth *in_synth); 21 static int spk_serial_wait_for_xmitr(struct spk_synth *in_synth); 22 23 struct spk_io_ops spk_serial_io_ops = { 24 .synth_out = spk_serial_out, 25 .send_xchar = spk_serial_send_xchar, 26 .tiocmset = spk_serial_tiocmset, 27 .synth_in = spk_serial_in, 28 .synth_in_nowait = spk_serial_in_nowait, 29 .flush_buffer = spk_serial_flush_buffer, 30 .wait_for_xmitr = spk_serial_wait_for_xmitr, 31 }; 32 EXPORT_SYMBOL_GPL(spk_serial_io_ops); 33 34 static void spk_serial_send_xchar(struct spk_synth *synth, char ch) 35 { 36 int timeout = SPK_XMITR_TIMEOUT; 37 38 while (spk_serial_tx_busy()) { 39 if (!--timeout) 40 break; 41 udelay(1); 42 } 43 outb(ch, speakup_info.port_tts); 44 } 45 46 static void spk_serial_tiocmset(struct spk_synth *in_synth, unsigned int set, unsigned int clear) 47 { 48 int old = inb(speakup_info.port_tts + UART_MCR); 49 50 outb((old & ~clear) | set, speakup_info.port_tts + UART_MCR); 51 } 52 53 static int spk_serial_wait_for_xmitr(struct spk_synth *in_synth) 54 { 55 int tmout = SPK_XMITR_TIMEOUT; 56 57 if ((in_synth->alive) && (timeouts >= NUM_DISABLE_TIMEOUTS)) { 58 pr_warn("%s: too many timeouts, deactivating speakup\n", 59 in_synth->long_name); 60 in_synth->alive = 0; 61 /* No synth any more, so nobody will restart TTYs, and we thus 62 * need to do it ourselves. Now that there is no synth we can 63 * let application flood anyway 64 */ 65 speakup_start_ttys(); 66 timeouts = 0; 67 return 0; 68 } 69 while (spk_serial_tx_busy()) { 70 if (--tmout == 0) { 71 pr_warn("%s: timed out (tx busy)\n", 72 in_synth->long_name); 73 timeouts++; 74 return 0; 75 } 76 udelay(1); 77 } 78 tmout = SPK_CTS_TIMEOUT; 79 while (!((inb_p(speakup_info.port_tts + UART_MSR)) & UART_MSR_CTS)) { 80 /* CTS */ 81 if (--tmout == 0) { 82 timeouts++; 83 return 0; 84 } 85 udelay(1); 86 } 87 timeouts = 0; 88 return 1; 89 } 90 91 static unsigned char spk_serial_in(struct spk_synth *in_synth) 92 { 93 int tmout = SPK_SERIAL_TIMEOUT; 94 95 while (!(inb_p(speakup_info.port_tts + UART_LSR) & UART_LSR_DR)) { 96 if (--tmout == 0) { 97 pr_warn("time out while waiting for input.\n"); 98 return 0xff; 99 } 100 udelay(1); 101 } 102 return inb_p(speakup_info.port_tts + UART_RX); 103 } 104 105 static unsigned char spk_serial_in_nowait(struct spk_synth *in_synth) 106 { 107 unsigned char lsr; 108 109 lsr = inb_p(speakup_info.port_tts + UART_LSR); 110 if (!(lsr & UART_LSR_DR)) 111 return 0; 112 return inb_p(speakup_info.port_tts + UART_RX); 113 } 114 115 static void spk_serial_flush_buffer(struct spk_synth *in_synth) 116 { 117 /* TODO: flush the UART 16550 buffer */ 118 } 119 120 static int spk_serial_out(struct spk_synth *in_synth, const char ch) 121 { 122 if (in_synth->alive && spk_serial_wait_for_xmitr(in_synth)) { 123 outb_p(ch, speakup_info.port_tts); 124 return 1; 125 } 126 return 0; 127 } 128