linux/drivers/tty/mxser.c

// SPDX-License-Identifier: GPL-2.0+
/*
 *          mxser.c  -- MOXA Smartio/Industio family multiport serial driver.
 *
 *      Copyright (C) 1999-2006  Moxa Technologies ([email protected]).
 *	Copyright (C) 2006-2008  Jiri Slaby <[email protected]>
 *
 *      This code is loosely based on the 1.8 moxa driver which is based on
 *	Linux serial driver, written by Linus Torvalds, Theodore T'so and
 *	others.
 *
 *	Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox
 *	<[email protected]>. The original 1.8 code is available on
 *	www.moxa.com.
 *	- Fixed x86_64 cleanness
 */

#include <linux/module.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/serial_reg.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/fcntl.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/ratelimit.h>

#include <asm/io.h>
#include <asm/irq.h>
#include <linux/uaccess.h>

/*
 *	Semi-public control interfaces
 */

/*
 *	MOXA ioctls
 */

#define MOXA
#define MOXA_SET_OP_MODE
#define MOXA_GET_OP_MODE

#define RS232_MODE
#define RS485_2WIRE_MODE
#define RS422_MODE
#define RS485_4WIRE_MODE
#define OP_MODE_MASK

/* --------------------------------------------------- */

/*
 * Follow just what Moxa Must chip defines.
 *
 * When LCR register (offset 0x03) is written the following value, the Must chip
 * will enter enhanced mode. And a write to EFR (offset 0x02) bit 6,7 will
 * change bank.
 */
#define MOXA_MUST_ENTER_ENHANCED

/* when enhanced mode is enabled, access to general bank register */
#define MOXA_MUST_GDL_REGISTER
#define MOXA_MUST_GDL_MASK
#define MOXA_MUST_GDL_HAS_BAD_DATA

#define MOXA_MUST_LSR_RERR
/* enhanced register bank select and enhanced mode setting register */
/* This works only when LCR register equals to 0xBF */
#define MOXA_MUST_EFR_REGISTER
#define MOXA_MUST_EFR_EFRB_ENABLE
/* enhanced register bank set 0, 1, 2 */
#define MOXA_MUST_EFR_BANK0
#define MOXA_MUST_EFR_BANK1
#define MOXA_MUST_EFR_BANK2
#define MOXA_MUST_EFR_BANK3
#define MOXA_MUST_EFR_BANK_MASK

/* set XON1 value register, when LCR=0xBF and change to bank0 */
#define MOXA_MUST_XON1_REGISTER

/* set XON2 value register, when LCR=0xBF and change to bank0 */
#define MOXA_MUST_XON2_REGISTER

/* set XOFF1 value register, when LCR=0xBF and change to bank0 */
#define MOXA_MUST_XOFF1_REGISTER

/* set XOFF2 value register, when LCR=0xBF and change to bank0 */
#define MOXA_MUST_XOFF2_REGISTER

#define MOXA_MUST_RBRTL_REGISTER
#define MOXA_MUST_RBRTH_REGISTER
#define MOXA_MUST_RBRTI_REGISTER
#define MOXA_MUST_THRTL_REGISTER
#define MOXA_MUST_ENUM_REGISTER
#define MOXA_MUST_HWID_REGISTER
#define MOXA_MUST_ECR_REGISTER
#define MOXA_MUST_CSR_REGISTER

#define MOXA_MUST_FCR_GDA_MODE_ENABLE
#define MOXA_MUST_FCR_GDA_ONLY_ENABLE

#define MOXA_MUST_IER_ECTSI
#define MOXA_MUST_IER_ERTSI
#define MOXA_MUST_IER_XINT
#define MOXA_MUST_IER_EGDAI

#define MOXA_MUST_RECV_ISR

/* GDA interrupt pending */
#define MOXA_MUST_IIR_GDA
#define MOXA_MUST_IIR_RDA
#define MOXA_MUST_IIR_RTO
#define MOXA_MUST_IIR_LSR

/* received Xon/Xoff or specical interrupt pending */
#define MOXA_MUST_IIR_XSC

/* RTS/CTS change state interrupt pending */
#define MOXA_MUST_IIR_RTSCTS
#define MOXA_MUST_IIR_MASK

#define MOXA_MUST_MCR_XON_FLAG
#define MOXA_MUST_MCR_XON_ANY
#define MOXA_MUST_MCR_TX_XON

#define MOXA_MUST_EFR_SF_MASK
#define MOXA_MUST_EFR_SF_TX1
#define MOXA_MUST_EFR_SF_TX2
#define MOXA_MUST_EFR_SF_TX12
#define MOXA_MUST_EFR_SF_TX_NO
#define MOXA_MUST_EFR_SF_TX_MASK
#define MOXA_MUST_EFR_SF_RX_NO
#define MOXA_MUST_EFR_SF_RX1
#define MOXA_MUST_EFR_SF_RX2
#define MOXA_MUST_EFR_SF_RX12
#define MOXA_MUST_EFR_SF_RX_MASK

#define MXSERMAJOR

#define MXSER_BOARDS
#define MXSER_PORTS_PER_BOARD
#define MXSER_PORTS
#define MXSER_ISR_PASS_LIMIT

#define WAKEUP_CHARS

#define MXSER_BAUD_BASE
#define MXSER_CUSTOM_DIVISOR

#define PCI_DEVICE_ID_MOXA_RC7000
#define PCI_DEVICE_ID_MOXA_CP102
#define PCI_DEVICE_ID_MOXA_CP102UL
#define PCI_DEVICE_ID_MOXA_CP102U
#define PCI_DEVICE_ID_MOXA_CP102UF
#define PCI_DEVICE_ID_MOXA_C104
#define PCI_DEVICE_ID_MOXA_CP104U
#define PCI_DEVICE_ID_MOXA_CP104JU
#define PCI_DEVICE_ID_MOXA_CP104EL
#define PCI_DEVICE_ID_MOXA_POS104UL
#define PCI_DEVICE_ID_MOXA_CB108
#define PCI_DEVICE_ID_MOXA_CP112UL
#define PCI_DEVICE_ID_MOXA_CT114
#define PCI_DEVICE_ID_MOXA_CP114
#define PCI_DEVICE_ID_MOXA_CB114
#define PCI_DEVICE_ID_MOXA_CP114UL
#define PCI_DEVICE_ID_MOXA_CP118U
#define PCI_DEVICE_ID_MOXA_CP118EL
#define PCI_DEVICE_ID_MOXA_CP132
#define PCI_DEVICE_ID_MOXA_CP132U
#define PCI_DEVICE_ID_MOXA_CP134U
#define PCI_DEVICE_ID_MOXA_CB134I
#define PCI_DEVICE_ID_MOXA_CP138U
#define PCI_DEVICE_ID_MOXA_C168
#define PCI_DEVICE_ID_MOXA_CP168U
#define PCI_DEVICE_ID_MOXA_CP168EL

#define MXSER_NPORTS(ddata)
#define MXSER_HIGHBAUD

enum mxser_must_hwid {};

static const struct {} Gpci_uart_info[] =;
#define UART_INFO_NUM


/* driver_data correspond to the lines in the structure above
   see also ISA probe function before you change something */
static const struct pci_device_id mxser_pcibrds[] =;
MODULE_DEVICE_TABLE(pci, mxser_pcibrds);

static int ttymajor =;

/* Variables for insmod */

MODULE_AUTHOR();
MODULE_DESCRIPTION();
module_param(ttymajor, int, 0);
MODULE_LICENSE();

struct mxser_board;

struct mxser_port {};

struct mxser_board {};

static DECLARE_BITMAP(mxser_boards, MXSER_BOARDS);
static struct tty_driver *mxvar_sdriver;

static u8 __mxser_must_set_EFR(unsigned long baseio, u8 clear, u8 set,
		bool restore_LCR)
{}

static u8 mxser_must_select_bank(unsigned long baseio, u8 bank)
{}

static void mxser_set_must_xon1_value(unsigned long baseio, u8 value)
{}

static void mxser_set_must_xoff1_value(unsigned long baseio, u8 value)
{}

static void mxser_set_must_fifo_value(struct mxser_port *info)
{}

static void mxser_set_must_enum_value(unsigned long baseio, u8 value)
{}

static u8 mxser_get_must_hardware_id(unsigned long baseio)
{}

static void mxser_must_set_EFR(unsigned long baseio, u8 clear, u8 set)
{}

static void mxser_must_set_enhance_mode(unsigned long baseio, bool enable)
{}

static void mxser_must_no_sw_flow_control(unsigned long baseio)
{}

static void mxser_must_set_tx_sw_flow_control(unsigned long baseio, bool enable)
{}

static void mxser_must_set_rx_sw_flow_control(unsigned long baseio, bool enable)
{}

static enum mxser_must_hwid mxser_must_get_hwid(unsigned long io)
{}

static bool mxser_16550A_or_MUST(struct mxser_port *info)
{}

static void mxser_process_txrx_fifo(struct mxser_port *info)
{}

static void __mxser_start_tx(struct mxser_port *info)
{}

static void mxser_start_tx(struct mxser_port *info)
{}

static void __mxser_stop_tx(struct mxser_port *info)
{}

static bool mxser_carrier_raised(struct tty_port *port)
{}

static void mxser_dtr_rts(struct tty_port *port, bool active)
{}

static int mxser_set_baud(struct tty_struct *tty, speed_t newspd)
{}

static void mxser_handle_cts(struct tty_struct *tty, struct mxser_port *info,
		u8 msr)
{}

/*
 * This routine is called to set the UART divisor registers to match
 * the specified baud rate for a serial port.
 */
static void mxser_change_speed(struct tty_struct *tty,
			       const struct ktermios *old_termios)
{}

static u8 mxser_check_modem_status(struct tty_struct *tty,
				struct mxser_port *port)
{}

static void mxser_disable_and_clear_FIFO(struct mxser_port *info)
{}

static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
{}

/*
 * To stop accepting input, we disable the receive line status interrupts, and
 * tell the interrupt driver to stop checking the data ready bit in the line
 * status register.
 */
static void mxser_stop_rx(struct mxser_port *info)
{}

/*
 * This routine will shutdown a serial port
 */
static void mxser_shutdown_port(struct tty_port *port)
{}

/*
 * This routine is called whenever a serial port is opened.  It
 * enables interrupts for a serial port, linking in its async structure into
 * the IRQ chain.   It also performs the serial-specific
 * initialization for the tty structure.
 */
static int mxser_open(struct tty_struct *tty, struct file *filp)
{}

static void mxser_flush_buffer(struct tty_struct *tty)
{}

static void mxser_close(struct tty_struct *tty, struct file *filp)
{}

static ssize_t mxser_write(struct tty_struct *tty, const u8 *buf, size_t count)
{}

static int mxser_put_char(struct tty_struct *tty, u8 ch)
{}


static void mxser_flush_chars(struct tty_struct *tty)
{}

static unsigned int mxser_write_room(struct tty_struct *tty)
{}

static unsigned int mxser_chars_in_buffer(struct tty_struct *tty)
{}

/*
 * ------------------------------------------------------------
 * friends of mxser_ioctl()
 * ------------------------------------------------------------
 */
static int mxser_get_serial_info(struct tty_struct *tty,
		struct serial_struct *ss)
{}

static int mxser_set_serial_info(struct tty_struct *tty,
		struct serial_struct *ss)
{}

/*
 * mxser_get_lsr_info - get line status register info
 *
 * Purpose: Let user call ioctl() to get info when the UART physically
 *	    is emptied.  On bus types like RS485, the transmitter must
 *	    release the bus after transmitting. This must be done when
 *	    the transmit shift register is empty, not be done when the
 *	    transmit holding register is empty.  This functionality
 *	    allows an RS485 driver to be written in user space.
 */
static int mxser_get_lsr_info(struct mxser_port *info,
		unsigned int __user *value)
{}

static int mxser_tiocmget(struct tty_struct *tty)
{}

static int mxser_tiocmset(struct tty_struct *tty,
		unsigned int set, unsigned int clear)
{}

static int mxser_cflags_changed(struct mxser_port *info, unsigned long arg,
		struct async_icount *cprev)
{}

/* We should likely switch to TIOCGRS485/TIOCSRS485. */
static int mxser_ioctl_op_mode(struct mxser_port *port, int index, bool set,
		int __user *u_opmode)
{}

static int mxser_ioctl(struct tty_struct *tty,
		unsigned int cmd, unsigned long arg)
{}

	/*
	 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
	 * Return: write counters to the user passed counter struct
	 * NB: both 1->0 and 0->1 transitions are counted except for
	 *     RI where only 0->1 is counted.
	 */

static int mxser_get_icount(struct tty_struct *tty,
		struct serial_icounter_struct *icount)

{}

/*
 * This routine is called by the upper-layer tty layer to signal that
 * incoming characters should be throttled.
 */
static void mxser_throttle(struct tty_struct *tty)
{}

static void mxser_unthrottle(struct tty_struct *tty)
{}

/*
 * mxser_stop() and mxser_start()
 *
 * This routines are called before setting or resetting tty->flow.stopped.
 * They enable or disable transmitter interrupts, as necessary.
 */
static void mxser_stop(struct tty_struct *tty)
{}

static void mxser_start(struct tty_struct *tty)
{}

static void mxser_set_termios(struct tty_struct *tty,
			      const struct ktermios *old_termios)
{}

static bool mxser_tx_empty(struct mxser_port *info)
{}

/*
 * mxser_wait_until_sent() --- wait until the transmitter is empty
 */
static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
{}

/*
 * This routine is called by tty_hangup() when a hangup is signaled.
 */
static void mxser_hangup(struct tty_struct *tty)
{}

/*
 * mxser_rs_break() --- routine which turns the break handling on or off
 */
static int mxser_rs_break(struct tty_struct *tty, int break_state)
{}

static bool mxser_receive_chars_new(struct mxser_port *port, u8 status)
{}

static u8 mxser_receive_chars_old(struct tty_struct *tty,
		                struct mxser_port *port, u8 status)
{}

static u8 mxser_receive_chars(struct tty_struct *tty,
		struct mxser_port *port, u8 status)
{}

static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port)
{}

static bool mxser_port_isr(struct mxser_port *port)
{}

/*
 * This is the serial driver's generic interrupt routine
 */
static irqreturn_t mxser_interrupt(int irq, void *dev_id)
{}

static const struct tty_operations mxser_ops =;

static const struct tty_port_operations mxser_port_ops =;

/*
 * The MOXA Smartio/Industio serial driver boot-time initialization code!
 */

static void mxser_initbrd(struct mxser_board *brd, bool high_baud)
{}

static int mxser_probe(struct pci_dev *pdev,
		const struct pci_device_id *ent)
{}

static void mxser_remove(struct pci_dev *pdev)
{}

static struct pci_driver mxser_driver =;

static int __init mxser_module_init(void)
{}

static void __exit mxser_module_exit(void)
{}

module_init();
module_exit(mxser_module_exit);