mxser.c

来自「linux 内核源代码」· C语言 代码 · 共 2,454 行 · 第 1/5 页

C
2,454
字号
/* *          mxser.c  -- MOXA Smartio/Industio family multiport serial driver. * *      Copyright (C) 1999-2001  Moxa Technologies (support@moxa.com.tw). * *      This code is loosely based on the Linux serial driver, written by *      Linus Torvalds, Theodore T'so and others. * *      This program is free software; you can redistribute it and/or modify *      it under the terms of the GNU General Public License as published by *      the Free Software Foundation; either version 2 of the License, or *      (at your option) any later version. * *      This program is distributed in the hope that it will be useful, *      but WITHOUT ANY WARRANTY; without even the implied warranty of *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *      GNU General Public License for more details. * *      You should have received a copy of the GNU General Public License *      along with this program; if not, write to the Free Software *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *	Original release	10/26/00 * *	02/06/01	Support MOXA Industio family boards. *	02/06/01	Support TIOCGICOUNT. *	02/06/01	Fix the problem for connecting to serial mouse. *	02/06/01	Fix the problem for H/W flow control. *	02/06/01	Fix the compling warning when CONFIG_PCI *			don't be defined. * *	Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox *	<alan@redhat.com>. The original 1.8 code is available on www.moxa.com. *	- Fixed x86_64 cleanness *	- Fixed sleep with spinlock held in mxser_send_break */#include <linux/module.h>#include <linux/autoconf.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/gfp.h>#include <linux/ioport.h>#include <linux/mm.h>#include <linux/delay.h>#include <linux/pci.h>#include <linux/bitops.h>#include <asm/system.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/uaccess.h>#include "mxser.h"#define	MXSER_VERSION	"1.8"#define	MXSERMAJOR	 174#define	MXSERCUMAJOR	 175#define	MXSER_EVENT_TXLOW	1#define	MXSER_EVENT_HANGUP	2#define MXSER_BOARDS		4	/* Max. boards */#define MXSER_PORTS		32	/* Max. ports */#define MXSER_PORTS_PER_BOARD	8	/* Max. ports per board */#define MXSER_ISR_PASS_LIMIT	256#define	MXSER_ERR_IOADDR	-1#define	MXSER_ERR_IRQ		-2#define	MXSER_ERR_IRQ_CONFLIT	-3#define	MXSER_ERR_VECTOR	-4#define SERIAL_TYPE_NORMAL	1#define SERIAL_TYPE_CALLOUT	2#define WAKEUP_CHARS		256#define UART_MCR_AFE		0x20#define UART_LSR_SPECIAL	0x1E#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : IRQF_DISABLED)#define C168_ASIC_ID    1#define C104_ASIC_ID    2#define C102_ASIC_ID	0xB#define CI132_ASIC_ID	4#define CI134_ASIC_ID	3#define CI104J_ASIC_ID  5enum {	MXSER_BOARD_C168_ISA = 1,	MXSER_BOARD_C104_ISA,	MXSER_BOARD_CI104J,	MXSER_BOARD_C168_PCI,	MXSER_BOARD_C104_PCI,	MXSER_BOARD_C102_ISA,	MXSER_BOARD_CI132,	MXSER_BOARD_CI134,	MXSER_BOARD_CP132,	MXSER_BOARD_CP114,	MXSER_BOARD_CT114,	MXSER_BOARD_CP102,	MXSER_BOARD_CP104U,	MXSER_BOARD_CP168U,	MXSER_BOARD_CP132U,	MXSER_BOARD_CP134U,	MXSER_BOARD_CP104JU,	MXSER_BOARD_RC7000,	MXSER_BOARD_CP118U,	MXSER_BOARD_CP102UL,	MXSER_BOARD_CP102U,};static char *mxser_brdname[] = {	"C168 series",	"C104 series",	"CI-104J series",	"C168H/PCI series",	"C104H/PCI series",	"C102 series",	"CI-132 series",	"CI-134 series",	"CP-132 series",	"CP-114 series",	"CT-114 series",	"CP-102 series",	"CP-104U series",	"CP-168U series",	"CP-132U series",	"CP-134U series",	"CP-104JU series",	"Moxa UC7000 Serial",	"CP-118U series",	"CP-102UL series",	"CP-102U series",};static int mxser_numports[] = {	8,			/* C168-ISA */	4,			/* C104-ISA */	4,			/* CI104J */	8,			/* C168-PCI */	4,			/* C104-PCI */	2,			/* C102-ISA */	2,			/* CI132 */	4,			/* CI134 */	2,			/* CP132 */	4,			/* CP114 */	4,			/* CT114 */	2,			/* CP102 */	4,			/* CP104U */	8,			/* CP168U */	2,			/* CP132U */	4,			/* CP134U */	4,			/* CP104JU */	8,			/* RC7000 */	8,			/* CP118U */	2,			/* CP102UL */	2,			/* CP102U */};#define UART_TYPE_NUM	2static const unsigned int Gmoxa_uart_id[UART_TYPE_NUM] = {	MOXA_MUST_MU150_HWID,	MOXA_MUST_MU860_HWID};/* This is only for PCI */#define UART_INFO_NUM	3struct mxpciuart_info {	int type;	int tx_fifo;	int rx_fifo;	int xmit_fifo_size;	int rx_high_water;	int rx_trigger;	int rx_low_water;	long max_baud;};static const struct mxpciuart_info Gpci_uart_info[UART_INFO_NUM] = {	{MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L},	{MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L},	{MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L}};#ifdef CONFIG_PCIstatic struct pci_device_id mxser_pcibrds[] = {	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C168, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_C168_PCI},	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_C104_PCI},	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP132},	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP114},	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CT114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CT114},	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP102},	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP104U},	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP168U},	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP132U},	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP134U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP134U},	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104JU, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP104JU},	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_RC7000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_RC7000},	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP118U},	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102UL, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP102UL},	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP102U},	{0}};MODULE_DEVICE_TABLE(pci, mxser_pcibrds);#endiftypedef struct _moxa_pci_info {	unsigned short busNum;	unsigned short devNum;	struct pci_dev *pdev;	/* add by Victor Yu. 06-23-2003 */} moxa_pci_info;static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 };static int ttymajor = MXSERMAJOR;static int calloutmajor = MXSERCUMAJOR;static int verbose = 0;/* Variables for insmod */MODULE_AUTHOR("Casper Yang");MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver");module_param_array(ioaddr, int, NULL, 0);module_param(ttymajor, int, 0);module_param(calloutmajor, int, 0);module_param(verbose, bool, 0);MODULE_LICENSE("GPL");struct mxser_log {	int tick;	unsigned long rxcnt[MXSER_PORTS];	unsigned long txcnt[MXSER_PORTS];};struct mxser_mon {	unsigned long rxcnt;	unsigned long txcnt;	unsigned long up_rxcnt;	unsigned long up_txcnt;	int modem_status;	unsigned char hold_reason;};struct mxser_mon_ext {	unsigned long rx_cnt[32];	unsigned long tx_cnt[32];	unsigned long up_rxcnt[32];	unsigned long up_txcnt[32];	int modem_status[32];	long baudrate[32];	int databits[32];	int stopbits[32];	int parity[32];	int flowctrl[32];	int fifo[32];	int iftype[32];};struct mxser_hwconf {	int board_type;	int ports;	int irq;	int vector;	int vector_mask;	int uart_type;	int ioaddr[MXSER_PORTS_PER_BOARD];	int baud_base[MXSER_PORTS_PER_BOARD];	moxa_pci_info pciInfo;	int IsMoxaMustChipFlag;	/* add by Victor Yu. 08-30-2002 */	int MaxCanSetBaudRate[MXSER_PORTS_PER_BOARD];	/* add by Victor Yu. 09-04-2002 */	int opmode_ioaddr[MXSER_PORTS_PER_BOARD];	/* add by Victor Yu. 01-05-2004 */};struct mxser_struct {	int port;	int base;		/* port base address */	int irq;		/* port using irq no. */	int vector;		/* port irq vector */	int vectormask;		/* port vector mask */	int rx_high_water;	int rx_trigger;		/* Rx fifo trigger level */	int rx_low_water;	int baud_base;		/* max. speed */	int flags;		/* defined in tty.h */	int type;		/* UART type */	struct tty_struct *tty;	int read_status_mask;	int ignore_status_mask;	int xmit_fifo_size;	int custom_divisor;	int x_char;		/* xon/xoff character */	int close_delay;	unsigned short closing_wait;	int IER;		/* Interrupt Enable Register */	int MCR;		/* Modem control register */	unsigned long event;	int count;		/* # of fd on device */	int blocked_open;	/* # of blocked opens */	unsigned char *xmit_buf;	int xmit_head;	int xmit_tail;	int xmit_cnt;	struct work_struct tqueue;	struct ktermios normal_termios;	struct ktermios callout_termios;	wait_queue_head_t open_wait;	wait_queue_head_t close_wait;	wait_queue_head_t delta_msr_wait;	struct async_icount icount;	/* kernel counters for the 4 input interrupts */	int timeout;	int IsMoxaMustChipFlag;	/* add by Victor Yu. 08-30-2002 */	int MaxCanSetBaudRate;	/* add by Victor Yu. 09-04-2002 */	int opmode_ioaddr;	/* add by Victor Yu. 01-05-2004 */	unsigned char stop_rx;	unsigned char ldisc_stop_rx;	long realbaud;	struct mxser_mon mon_data;	unsigned char err_shadow;	spinlock_t slock;};struct mxser_mstatus {	tcflag_t cflag;	int cts;	int dsr;	int ri;	int dcd;};static struct mxser_mstatus GMStatus[MXSER_PORTS];static int mxserBoardCAP[MXSER_BOARDS] = {	0, 0, 0, 0	/*  0x180, 0x280, 0x200, 0x320 */};static struct tty_driver *mxvar_sdriver;static struct mxser_struct mxvar_table[MXSER_PORTS];static struct tty_struct *mxvar_tty[MXSER_PORTS + 1];static struct ktermios *mxvar_termios[MXSER_PORTS + 1];static struct ktermios *mxvar_termios_locked[MXSER_PORTS + 1];static struct mxser_log mxvar_log;static int mxvar_diagflag;static unsigned char mxser_msr[MXSER_PORTS + 1];static struct mxser_mon_ext mon_data_ext;static int mxser_set_baud_method[MXSER_PORTS + 1];static spinlock_t gm_lock;/* * This is used to figure out the divisor speeds and the timeouts */static struct mxser_hwconf mxsercfg[MXSER_BOARDS];/* * static functions: */static void mxser_getcfg(int board, struct mxser_hwconf *hwconf);static int mxser_init(void);/* static void   mxser_poll(unsigned long); */static int mxser_get_ISA_conf(int, struct mxser_hwconf *);static void mxser_do_softint(struct work_struct *);static int mxser_open(struct tty_struct *, struct file *);static void mxser_close(struct tty_struct *, struct file *);static int mxser_write(struct tty_struct *, const unsigned char *, int);static int mxser_write_room(struct tty_struct *);static void mxser_flush_buffer(struct tty_struct *);static int mxser_chars_in_buffer(struct tty_struct *);static void mxser_flush_chars(struct tty_struct *);static void mxser_put_char(struct tty_struct *, unsigned char);static int mxser_ioctl(struct tty_struct *, struct file *, uint, ulong);static int mxser_ioctl_special(unsigned int, void __user *);static void mxser_throttle(struct tty_struct *);static void mxser_unthrottle(struct tty_struct *);static void mxser_set_termios(struct tty_struct *, struct ktermios *);static void mxser_stop(struct tty_struct *);static void mxser_start(struct tty_struct *);static void mxser_hangup(struct tty_struct *);static void mxser_rs_break(struct tty_struct *, int);static irqreturn_t mxser_interrupt(int, void *);static void mxser_receive_chars(struct mxser_struct *, int *);static void mxser_transmit_chars(struct mxser_struct *);static void mxser_check_modem_status(struct mxser_struct *, int);static int mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *);static int mxser_startup(struct mxser_struct *);static void mxser_shutdown(struct mxser_struct *);static int mxser_change_speed(struct mxser_struct *, struct ktermios *old_termios);static int mxser_get_serial_info(struct mxser_struct *, struct serial_struct __user *);static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct __user *);static int mxser_get_lsr_info(struct mxser_struct *, unsigned int __user *);static void mxser_send_break(struct mxser_struct *, int);static int mxser_tiocmget(struct tty_struct *, struct file *);static int mxser_tiocmset(struct tty_struct *, struct file *, unsigned int, unsigned int);static int mxser_set_baud(struct mxser_struct *info, long newspd);static void mxser_wait_until_sent(struct tty_struct *tty, int timeout);static void mxser_startrx(struct tty_struct *tty);static void mxser_stoprx(struct tty_struct *tty);#ifdef CONFIG_PCIstatic int CheckIsMoxaMust(int io){	u8 oldmcr, hwid;	int i;	outb(0, io + UART_LCR);	DISABLE_MOXA_MUST_ENCHANCE_MODE(io);	oldmcr = inb(io + UART_MCR);	outb(0, io + UART_MCR);	SET_MOXA_MUST_XON1_VALUE(io, 0x11);	if ((hwid = inb(io + UART_MCR)) != 0) {		outb(oldmcr, io + UART_MCR);		return MOXA_OTHER_UART;	}	GET_MOXA_MUST_HARDWARE_ID(io, &hwid);	for (i = 0; i < UART_TYPE_NUM; i++) {		if (hwid == Gmoxa_uart_id[i])			return (int)hwid;	}	return MOXA_OTHER_UART;}#endif/* above is modified by Victor Yu. 08-15-2002 */static const struct tty_operations mxser_ops = {	.open = mxser_open,	.close = mxser_close,	.write = mxser_write,	.put_char = mxser_put_char,	.flush_chars = mxser_flush_chars,	.write_room = mxser_write_room,	.chars_in_buffer = mxser_chars_in_buffer,	.flush_buffer = mxser_flush_buffer,	.ioctl = mxser_ioctl,	.throttle = mxser_throttle,	.unthrottle = mxser_unthrottle,	.set_termios = mxser_set_termios,	.stop = mxser_stop,	.start = mxser_start,	.hangup = mxser_hangup,	.break_ctl = mxser_rs_break,	.wait_until_sent = mxser_wait_until_sent,	.tiocmget = mxser_tiocmget,	.tiocmset = mxser_tiocmset,};/* * The MOXA Smartio/Industio serial driver boot-time initialization code! */static int __init mxser_module_init(void){	int ret;	if (verbose)		printk(KERN_DEBUG "Loading module mxser ...\n");	ret = mxser_init();	if (verbose)		printk(KERN_DEBUG "Done.\n");	return ret;}static void __exit mxser_module_exit(void){	int i, err;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?