drivers/accessibility/speakup/serialio.c
Source file repositories/reference/linux-study-clean/drivers/accessibility/speakup/serialio.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/accessibility/speakup/serialio.c- Extension
.c- Size
- 8064 bytes
- Lines
- 319
- Domain
- Driver Families
- Bucket
- drivers/accessibility
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/interrupt.hlinux/ioport.hspk_types.hspeakup.hspk_priv.hserialio.hlinux/serial_core.hasm/serial.h
Detected Declarations
function synth_readbuf_handlerfunction start_serial_interruptfunction spk_serial_send_xcharfunction spk_serial_tiocmsetfunction spk_serial_synth_probefunction spk_stop_serial_interruptfunction spk_serial_wait_for_xmitrfunction spk_serial_infunction spk_serial_in_nowaitfunction spk_serial_flush_bufferfunction spk_serial_releaseexport spk_serial_io_opsexport spk_serial_synth_probeexport spk_stop_serial_interruptexport spk_serial_synth_immediateexport spk_serial_release
Annotated Snippet
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;
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);
}
spin_unlock_irqrestore(&speakup_info.spinlock, flags);
return IRQ_HANDLED;
}
static void start_serial_interrupt(int irq)
{
int rv;
if (!synth->read_buff_add)
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 */
}
static void spk_serial_send_xchar(struct spk_synth *synth, char ch)
{
int timeout = SPK_XMITR_TIMEOUT;
while (spk_serial_tx_busy()) {
if (!--timeout)
break;
udelay(1);
}
outb(ch, speakup_info.port_tts);
}
static void spk_serial_tiocmset(struct spk_synth *in_synth, unsigned int set, unsigned int clear)
{
int old = inb(speakup_info.port_tts + UART_MCR);
Annotation
- Immediate include surface: `linux/interrupt.h`, `linux/ioport.h`, `spk_types.h`, `speakup.h`, `spk_priv.h`, `serialio.h`, `linux/serial_core.h`, `asm/serial.h`.
- Detected declarations: `function synth_readbuf_handler`, `function start_serial_interrupt`, `function spk_serial_send_xchar`, `function spk_serial_tiocmset`, `function spk_serial_synth_probe`, `function spk_stop_serial_interrupt`, `function spk_serial_wait_for_xmitr`, `function spk_serial_in`, `function spk_serial_in_nowait`, `function spk_serial_flush_buffer`.
- Atlas domain: Driver Families / drivers/accessibility.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.