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 + -
显示快捷键?