STRUCT UART_OPS(9)
π NAME π
okay bestie, meet struct uart_ops(9) from the Kernel API Manual β it is literally the interface between serial_core and the driver. That's the whole name-and-purpose vibe. π
β¨ SYNOPSIS β¨
Here's the struct in all its glory β copy it exactly, no edits, no "fixing" the semicolons:
struct uart_ops {
unsigned int (*tx_empty)(struct uart_port *);
void (*set_mctrl)(struct uart_port *, unsigned int mctrl);
unsigned int (*get_mctrl)(struct uart_port *);
void (*stop_tx)(struct uart_port *);
void (*start_tx)(struct uart_port *);
void (*throttle)(struct uart_port *);
void (*unthrottle)(struct uart_port *);
void (*send_xchar)(struct uart_port *, char ch);
void (*stop_rx)(struct uart_port *);
void (*start_rx)(struct uart_port *);
void (*enable_ms)(struct uart_port *);
void (*break_ctl)(struct uart_port *, int ctl);
int (*startup)(struct uart_port *);
void (*shutdown)(struct uart_port *);
void (*flush_buffer)(struct uart_port *);
void (*set_termios)(struct uart_port *, struct ktermios *new, const
struct ktermios *old);
void (*set_ldisc)(struct uart_port *, struct ktermios *);
void (*pm)(struct uart_port *, unsigned int state, unsigned int
oldstate);
const char *(*type)(struct uart_port *);
void (*release_port)(struct uart_port *);
int (*request_port)(struct uart_port *);
void (*config_port)(struct uart_port *, int);
int (*verify_port)(struct uart_port *, struct serial_struct *);
int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
#ifdef CONFIG_CONSOLE_POLL;
int (*poll_init)(struct uart_port *);
void (*poll_put_char)(struct uart_port *, unsigned char);
int (*poll_get_char)(struct uart_port *);
#endif;
};
π«Ά Members π«Ά
Every member, signature kept exactly as-is:
tx_emptyβunsigned int ()(struct uart_port *port)set_mctrlβvoid ()(struct uart_port *port, unsigned int mctrl)get_mctrlβunsigned int ()(struct uart_port *port)stop_txβvoid ()(struct uart_port *port)start_txβvoid ()(struct uart_port *port)throttleβvoid ()(struct uart_port *port)unthrottleβvoid ()(struct uart_port *port)send_xcharβvoid ()(struct uart_port *port, char ch)stop_rxβvoid ()(struct uart_port *port)start_rxβvoid ()(struct uart_port *port)enable_msβvoid ()(struct uart_port *port)break_ctlβvoid ()(struct uart_port *port, int ctl)startupβint ()(struct uart_port *port)shutdownβvoid ()(struct uart_port *port)flush_bufferβvoid ()(struct uart_port *port)set_termiosβvoid ()(struct uart_port *port, struct ktermios *new, struct ktermios *old)set_ldiscβvoid ()(struct uart_port *port, struct ktermios *termios)pmβvoid ()(struct uart_port *port, unsigned int state, unsigned int oldstate)typeβconst char *()(struct uart_port *port)release_portβvoid ()(struct uart_port *port)request_portβint ()(struct uart_port *port)config_portβvoid ()(struct uart_port *port, int type)verify_portβint ()(struct uart_port *port, struct serial_struct *serinfo)ioctlβint ()(struct uart_port *port, unsigned int cmd, unsigned long arg)poll_initβint ()(struct uart_port *port)poll_put_charβvoid ()(struct uart_port *port, unsigned char ch)poll_get_charβint ()(struct uart_port *port)
π Description π
This struct is the full menu of operations you can do on the actual physical hardware. Like, every hardware move the serial core might need? It's in here, bestie. π₯
tx_empty β tests whether the transmitter fifo and shifter for the port is empty. If it is empty, this function should return TIOCSER_TEMT; otherwise return 0. If the port does not support this operation, then it should return TIOCSER_TEMT. Locking: none. Interrupts: caller dependent. This call must not sleep.
set_mctrl β sets the modem control lines for port to the state described by mctrl. The relevant bits of mctrl are:
TIOCM_RTSβ RTS signal.TIOCM_DTRβ DTR signal.TIOCM_OUT1β OUT1 signal.TIOCM_OUT2β OUT2 signal.TIOCM_LOOPβ Set the port into loopback mode.
If the appropriate bit is set, the signal should be driven active. If the bit is clear, the signal should be driven inactive. Locking: port->lock taken. Interrupts: locally disabled. This call must not sleep.
get_mctrl β returns the current state of modem control inputs of port. The state of the outputs should not be returned, since the core keeps track of their state. The state information should include:
TIOCM_CARβ state of DCD signalTIOCM_CTSβ state of CTS signalTIOCM_DSRβ state of DSR signalTIOCM_RIβ state of RI signal
The bit is set if the signal is currently driven active. If the port does not support CTS, DCD or DSR, the driver should indicate that the signal is permanently active. If RI is not available, the signal should not be indicated as active. Locking: port->lock taken. Interrupts: locally disabled. This call must not sleep.
stop_tx β stop transmitting characters. This might be due to the CTS line becoming inactive or the tty layer indicating we want to stop transmission due to an XOFF character. The driver should stop transmitting characters as soon as possible. Locking: port->lock taken. Interrupts: locally disabled. This call must not sleep.
start_tx β start transmitting characters. Locking: port->lock taken. Interrupts: locally disabled. This call must not sleep.
throttle β notify the serial driver that input buffers for the line discipline are close to full, and it should somehow signal that no more characters should be sent to the serial port. This will be called only if hardware assisted flow control is enabled. Locking: serialized with unthrottle and termios modification by the tty layer.
unthrottle β notify the serial driver that characters can now be sent to the serial port without fear of overrunning the input buffers of the line disciplines. This will be called only if hardware assisted flow control is enabled. Locking: serialized with throttle and termios modification by the tty layer.
send_xchar β transmit a high priority character, even if the port is stopped. This is used to implement XON/XOFF flow control and tcflow. If the serial driver does not implement this function, the tty core will append the character to the circular buffer and then call start_tx / stop_tx to flush the data out. Do not transmit if ch == ' ' (__DISABLED_CHAR). Locking: none. Interrupts: caller dependent.
start_rx β start receiving characters. Locking: port->lock taken. Interrupts: locally disabled. This call must not sleep.
stop_rx β stop receiving characters; the port is in the process of being closed. Locking: port->lock taken. Interrupts: locally disabled. This call must not sleep.
enable_ms β enable the modem status interrupts. This method may be called multiple times. Modem status interrupts should be disabled when the shutdown method is called. Locking: port->lock taken. Interrupts: locally disabled. This call must not sleep.
break_ctl β control the transmission of a break signal. If ctl is nonzero, the break signal should be transmitted. The signal should be terminated when another call is made with a zero ctl. Locking: caller holds tty_port->mutex.
startup β grab any interrupt resources and initialise any low level driver state. Enable the port for reception. It should not activate RTS nor DTR; this will be done via a separate call to set_mctrl. This method will only be called when the port is initially opened. Locking: port_sem taken. Interrupts: globally disabled.
shutdown β disable the port, disable any break condition that may be in effect, and free any interrupt resources. It should not disable RTS nor DTR; this will have already been done via a separate call to set_mctrl. Drivers must not access port->state once this call has completed. This method will only be called when there are no more users of this port. Locking: port_sem taken. Interrupts: caller dependent.
flush_buffer β flush any write buffers, reset any DMA state and stop any ongoing DMA transfers. This will be called whenever the port->state->xmit circular buffer is cleared. Locking: port->lock taken. Interrupts: locally disabled. This call must not sleep.
set_termios β change the port parameters, including word length, parity, stop bits. Update port->read_status_mask and port->ignore_status_mask to indicate the types of events we are interested in receiving. Relevant ktermios::c_cflag bits are:
CSIZEβ word sizeCSTOPBβ 2 stop bitsPARENBβ parity enablePARODDβ odd parity (whenPARENBis in force)ADDRBβ address bit (changed throughuart_port::rs485_config).CREADβ enable reception of characters (if not set, still receive characters from the port, but throw them away).CRTSCTSβ if set, enable CTS status change reporting.CLOCALβ if not set, enable modem status change reporting.
Relevant ktermios::c_iflag bits are:
INPCKβ enable frame and parity error events to be passed to the TTY layer.BRKINT/PARMRKβ both of these enable break events to be passed to the TTY layer.IGNPARβ ignore parity and framing errors.IGNBRKβ ignore break errors. IfIGNPARis also set, ignore overrun errors as well.
The interaction of the ktermios::c_iflag bits is as follows (parity error given as an example):
- Parity error
n/a;INPCK0;IGNPARn/aβ character received, marked asTTY_NORMAL. - Parity error
None;INPCK1;IGNPARn/aβ character received, marked asTTY_NORMAL. - Parity error
Yes;INPCK1;IGNPAR0β character received, marked asTTY_PARITY. - Parity error
Yes;INPCK1;IGNPAR1β character discarded.
Okay so the member tour is still going β picking up exactly where we left off, no heading repeat, just vibes and facts:
set_termios(the tail end of it, anyway) β other flags may be set (egxon/xoffcharacters) if your hardware supports hardware βsoftβ flow control π©΅Locking:caller holdstty_port->mutexInterrupts:caller pending- This call must not sleep
set_ldiscβ the notifier for a discipline change. SeeDocumentation/driver-api/tty/tty_ldisc.rstfor the whole entire lore β¨Locking:caller holdstty_port->mutex
pmβ perform any power management related activities on the specified port state.stateindicates the new state (defined byenum uart_pm_state), andoldstateindicates the previous one.- This function should not be used to grab any resources π ββοΈ
- This will be called when the port is initially opened and finally closed, except when the port is also the system console. This will occur even if
CONFIG_PMis not set. Locking:noneInterrupts:caller pending
typeβ return a pointer to a string constant describing the specified port, or returnNULL, in which case the string'unknown'is substituted.Locking:noneInterrupts:caller pending
release_portβ release any memory and IO region resources currently in use by the port.Locking:noneInterrupts:caller pending
request_portβ request any memory and IO region resources required by the port. If any of it fails, no resources should be registered when this function returns, and it should return-ENOSPCon failure πLocking:noneInterrupts:caller pending
config_portβ perform any autoconfiguration steps required for the port.typecontains a bit mask of the required configuration.UART_CONFIG_TYPEindicates that the port requires detection and identification β andport->typeshould be set to the type found, orPORT_UNKNOWNif no port was detected.UART_CONFIG_IRQindicates autoconfiguration of the interrupt signal, which should be probed using standard kernel autoprobing techniques. This is not necessary on platforms where ports have interrupts internally hard wired (eg system on a chip implementations).Locking:noneInterrupts:caller pending
verify_portβ verify that the new serial port information contained withinserinfois suitable for this port type.Locking:noneInterrupts:caller pending
ioctlβ perform any port specific IOCTLs. IOCTL commands must be defined using the standard numbering system found in<asm/ioctl.h>.Locking:noneInterrupts:caller pending
poll_initβ called by kgdb to perform the minimal hardware initialization needed to supportpoll_put_charandpoll_get_char. Unlikestartup, it should not request interrupts.Locking:tty_mutexandtty_port->mutextakenInterrupts:n/a
poll_put_charβ called by kgdb to write a single characterchdirectly to the serial port. It can and should block until there is space in the TX FIFO πLocking:noneInterrupts:caller pending- This call must not sleep
poll_get_charβ called by kgdb to read a single character directly from the serial port. If data is available, it should be returned; otherwise the function should returnNO_POLL_CHARimmediately, no hesitation, no waiting around πLocking:noneInterrupts:caller pending- This call must not sleep
π SEE ALSO π
Kernel file ./include/linux/serial_core.h β go read the source bestie, it's giving main character energy:
uart_port_set_cons(9)uart_port_lock(9)uart_port_lock_irq(9)uart_port_lock_irqsave(9)uart_port_trylock(9)uart_port_trylock_irqsave(9)uart_port_unlock(9)uart_port_unlock_irq(9)uart_port_unlock_irqrestore(9)enum uart_pm_state(9)uart_xmit_advance(9)enum UART_TX_FLAGS(9)uart_port_tx_limited(9)uart_port_tx_limited_flags(9)uart_port_tx(9)uart_port_tx_flags(9)
π«Ά And that's the whole page, bestie! This one lives in ./include/linux, dated October 2026, and it's literally page struct uart_ops(9) β you ate that, periodt ππ
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms