drivers/tty/serial/rsci.c

Source file repositories/reference/linux-study-clean/drivers/tty/serial/rsci.c

File Facts

System
Linux kernel
Corpus path
drivers/tty/serial/rsci.c
Extension
.c
Size
20178 bytes
Lines
739
Domain
Driver Families
Bucket
drivers/tty
Inferred role
Driver Families: implementation source
Status
source 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.

Dependency Surface

Detected Declarations

Annotated Snippet

if (port->x_char) {
			c = port->x_char;
			port->x_char = 0;
		} else if (stopped || !kfifo_get(&tport->xmit_fifo, &c)) {
			break;
		}

		rsci_clear_CFC(port, CFCLR_TDREC);
		rsci_serial_out(port, TDR, c);

		port->icount.tx++;
	} while (--count > 0);

	if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
		uart_write_wakeup(port);

	if (kfifo_is_empty(&tport->xmit_fifo)) {
		ctrl = rsci_serial_in(port, CCR0);
		ctrl &= ~CCR0_TIE;
		ctrl |= CCR0_TEIE;
		rsci_serial_out(port, CCR0, ctrl);
	}
}

static void rsci_receive_chars(struct uart_port *port)
{
	struct tty_port *tport = &port->state->port;
	u32 rdat, status, frsr_status = 0;
	int i, count, copied = 0;
	unsigned char flag;

	status = rsci_serial_in(port, CSR);
	frsr_status = rsci_serial_in(port, FRSR);

	if (!(status & CSR_RDRF) && !(frsr_status & FRSR_DR))
		return;

	while (1) {
		/* Don't copy more bytes than there is room for in the buffer */
		count = tty_buffer_request_room(tport, rsci_rxfill(port));

		/* If for any reason we can't copy more data, we're done! */
		if (count == 0)
			break;

		for (i = 0; i < count; i++) {
			char c;

			rdat = rsci_serial_in(port, RDR);
			/* 9-bits data is not supported yet */
			c = rdat & RDR_RDAT_MSK;

			if (uart_handle_sysrq_char(port, c)) {
				count--;
				i--;
				continue;
			}

			/*
			 * Store data and status.
			 * Non FIFO mode is not supported
			 */
			if (rdat & RDR_FFER) {
				flag = TTY_FRAME;
				port->icount.frame++;
			} else if (rdat & RDR_FPER) {
				flag = TTY_PARITY;
				port->icount.parity++;
			} else {
				flag = TTY_NORMAL;
			}

			tty_insert_flip_char(tport, c, flag);
		}

		rsci_serial_in(port, CSR); /* dummy read */
		rsci_clear_DRxC(port);

		copied += count;
		port->icount.rx += count;
	}

	if (copied) {
		/* Tell the rest of the system the news. New characters! */
		tty_flip_buffer_push(tport);
	} else {
		/* TTY buffers full; read from RX reg to prevent lockup */
		rsci_serial_in(port, RDR);
		rsci_serial_in(port, CSR); /* dummy read */
		rsci_clear_DRxC(port);

Annotation

Implementation Notes