drivers/tty/serial/jsm/jsm_cls.c

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

File Facts

System
Linux kernel
Corpus path
drivers/tty/serial/jsm/jsm_cls.c
Extension
.c
Size
23015 bytes
Lines
900
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 (linestatus & error_mask)  {
			readb(&ch->ch_cls_uart->txrx);
			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.
		 *
		 * I decided that I wanted to ditch the oldest data first,
		 * I hope thats okay with everyone? Yes? Good.
		 */
		while (qleft < 1) {
			tail = (tail + 1) & RQUEUEMASK;
			ch->ch_r_tail = tail;
			ch->ch_err_overrun++;
			qleft++;
		}

		ch->ch_equeue[head] = linestatus & (UART_LSR_BI | UART_LSR_PE
								 | UART_LSR_FE);
		ch->ch_rqueue[head] = readb(&ch->ch_cls_uart->txrx);

		qleft--;

		if (ch->ch_equeue[head] & UART_LSR_PE)
			ch->ch_err_parity++;
		if (ch->ch_equeue[head] & UART_LSR_BI)
			ch->ch_err_break++;
		if (ch->ch_equeue[head] & UART_LSR_FE)
			ch->ch_err_frame++;

		/* Add to, and flip head if needed */
		head = (head + 1) & RQUEUEMASK;
		ch->ch_rxcount++;
	}

	/*
	 * Write new final heads to channel structure.
	 */
	ch->ch_r_head = head & RQUEUEMASK;
	ch->ch_e_head = head & EQUEUEMASK;

	spin_unlock_irqrestore(&ch->ch_lock, flags);
}

static void cls_copy_data_from_queue_to_uart(struct jsm_channel *ch)
{
	struct tty_port *tport;
	int n;
	u32 len_written = 0;

	if (!ch)
		return;

	tport = &ch->uart_port.state->port;

	/* If port is "stopped", don't send any data to the UART */
	if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_BREAK_SENDING))
		return;

	/* We have to do it this way, because of the EXAR TXFIFO count bug. */
	if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM)))
		return;

	n = 32;
	while (n > 0) {
		unsigned char c;

		if (!kfifo_get(&tport->xmit_fifo, &c))
			break;

		writeb(c, &ch->ch_cls_uart->txrx);
		n--;
		ch->ch_txcount++;
		len_written++;
	}

	if (len_written > ch->ch_t_tlevel)
		ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);

	if (kfifo_is_empty(&tport->xmit_fifo))
		uart_write_wakeup(&ch->uart_port);
}

static void cls_parse_modem(struct jsm_channel *ch, u8 signals)
{
	u8 msignals = signals;

Annotation

Implementation Notes