/* * mxser.c -- MOXA Smartio/Industio family multiport serial driver. * * Copyright (C) 1999-2006 Moxa Technologies (support@moxa.com). * Copyright (C) 2006-2008 Jiri Slaby <jirislaby@gmail.com> * * 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. * * 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. * * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox * <alan@lxorguk.ukuu.org.uk>. 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 <asm/uaccess.h> #include "mxser.h" #define MXSER_VERSION "2.0.5" /* 1.14 */#define MXSERMAJOR 174 #define MXSER_BOARDS 4 /* Max. boards */#define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */#define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD)#define MXSER_ISR_PASS_LIMIT 100 /*CheckIsMoxaMust return value*/#define MOXA_OTHER_UART 0x00#define MOXA_MUST_MU150_HWID 0x01#define MOXA_MUST_MU860_HWID 0x02 #define WAKEUP_CHARS 256 #define UART_MCR_AFE 0x20#define UART_LSR_SPECIAL 0x1E #define PCI_DEVICE_ID_POS104UL 0x1044#define PCI_DEVICE_ID_CB108 0x1080#define PCI_DEVICE_ID_CP102UF 0x1023#define PCI_DEVICE_ID_CP112UL 0x1120#define PCI_DEVICE_ID_CB114 0x1142#define PCI_DEVICE_ID_CP114UL 0x1143#define PCI_DEVICE_ID_CB134I 0x1341#define PCI_DEVICE_ID_CP138U 0x1380 #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 5 #define MXSER_HIGHBAUD 1#define MXSER_HAS2 2 /* This is only for PCI */static const struct { 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;} Gpci_uart_info[] = { {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}};#define UART_INFO_NUM ARRAY_SIZE(Gpci_uart_info) struct mxser_cardinfo { char *name; unsigned int nports; unsigned int flags;}; static const struct mxser_cardinfo mxser_cards[] = {/* 0*/ { "C168 series", 8, }, { "C104 series", 4, }, { "CI-104J series", 4, }, { "C168H/PCI series", 8, }, { "C104H/PCI series", 4, },/* 5*/ { "C102 series", 4, MXSER_HAS2 }, /* C102-ISA */ { "CI-132 series", 4, MXSER_HAS2 }, { "CI-134 series", 4, }, { "CP-132 series", 2, }, { "CP-114 series", 4, },/*10*/ { "CT-114 series", 4, }, { "CP-102 series", 2, MXSER_HIGHBAUD }, { "CP-104U series", 4, }, { "CP-168U series", 8, }, { "CP-132U series", 2, },/*15*/ { "CP-134U series", 4, }, { "CP-104JU series", 4, }, { "Moxa UC7000 Serial", 8, }, /* RC7000 */ { "CP-118U series", 8, }, { "CP-102UL series", 2, },/*20*/ { "CP-102U series", 2, }, { "CP-118EL series", 8, }, { "CP-168EL series", 8, }, { "CP-104EL series", 4, }, { "CB-108 series", 8, },/*25*/ { "CB-114 series", 4, }, { "CB-134I series", 4, }, { "CP-138U series", 8, }, { "POS-104UL series", 4, }, { "CP-114UL series", 4, },/*30*/ { "CP-102UF series", 2, }, { "CP-112UL series", 2, },}; /* driver_data correspond to the lines in the structure above see also ISA probe function before you change something */static struct pci_device_id mxser_pcibrds[] = { { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C168), .driver_data = 3 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C104), .driver_data = 4 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132), .driver_data = 8 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114), .driver_data = 9 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CT114), .driver_data = 10 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102), .driver_data = 11 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104U), .driver_data = 12 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168U), .driver_data = 13 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132U), .driver_data = 14 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP134U), .driver_data = 15 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104JU),.driver_data = 16 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_RC7000), .driver_data = 17 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118U), .driver_data = 18 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UL),.driver_data = 19 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102U), .driver_data = 20 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118EL),.driver_data = 21 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168EL),.driver_data = 22 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104EL),.driver_data = 23 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB108), .driver_data = 24 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB114), .driver_data = 25 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB134I), .driver_data = 26 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U), .driver_data = 27 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 28 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL), .driver_data = 29 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF), .driver_data = 30 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP112UL), .driver_data = 31 }, { }};MODULE_DEVICE_TABLE(pci, mxser_pcibrds); static unsigned long ioaddr[MXSER_BOARDS];static int ttymajor = MXSERMAJOR; /* Variables for insmod */ MODULE_AUTHOR("Casper Yang");MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver");module_param_array(ioaddr, ulong, NULL, 0);MODULE_PARM_DESC(ioaddr, "ISA io addresses to look for a moxa board");module_param(ttymajor, int, 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_board; struct mxser_port { struct tty_port port; struct mxser_board *board; unsigned long ioaddr; unsigned long opmode_ioaddr; int max_baud; int rx_high_water; int rx_trigger; /* Rx fifo trigger level */ int rx_low_water; int baud_base; /* max. speed */ int type; /* UART type */ int x_char; /* xon/xoff character */ int IER; /* Interrupt Enable Register */ int MCR; /* Modem control register */ unsigned char stop_rx; unsigned char ldisc_stop_rx; int custom_divisor; unsigned char err_shadow; struct async_icount icount; /* kernel counters for 4 input interrupts */ int timeout; int read_status_mask; int ignore_status_mask; int xmit_fifo_size; int xmit_head; int xmit_tail; int xmit_cnt; struct ktermios normal_termios; struct mxser_mon mon_data; spinlock_t slock;}; struct mxser_board { unsigned int idx; int irq; const struct mxser_cardinfo *info; unsigned long vector; unsigned long vector_mask; int chip_flag; int uart_type; struct mxser_port ports[MXSER_PORTS_PER_BOARD];}; struct mxser_mstatus { tcflag_t cflag; int cts; int dsr; int ri; int dcd;}; static struct mxser_board mxser_boards[MXSER_BOARDS];static struct tty_driver *mxvar_sdriver;static struct mxser_log mxvar_log;static int mxser_set_baud_method[MXSER_PORTS + 1]; static void mxser_enable_must_enchance_mode(unsigned long baseio){ u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr |= MOXA_MUST_EFR_EFRB_ENABLE; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(oldlcr, baseio + UART_LCR);} #ifdef CONFIG_PCIstatic void mxser_disable_must_enchance_mode(unsigned long baseio){ u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_EFRB_ENABLE; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(oldlcr, baseio + UART_LCR);}#endif static void mxser_set_must_xon1_value(unsigned long baseio, u8 value){ u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_BANK_MASK; efr |= MOXA_MUST_EFR_BANK0; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(value, baseio + MOXA_MUST_XON1_REGISTER); outb(oldlcr, baseio + UART_LCR);} static void mxser_set_must_xoff1_value(unsigned long baseio, u8 value){ u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_BANK_MASK; efr |= MOXA_MUST_EFR_BANK0; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(value, baseio + MOXA_MUST_XOFF1_REGISTER); outb(oldlcr, baseio + UART_LCR);} static void mxser_set_must_fifo_value(struct mxser_port *info){ u8 oldlcr; u8 efr; oldlcr = inb(info->ioaddr + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, info->ioaddr + UART_LCR); efr = inb(info->ioaddr + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_BANK_MASK; efr |= MOXA_MUST_EFR_BANK1; outb(efr, info->ioaddr + MOXA_MUST_EFR_REGISTER); outb((u8)info->rx_high_water, info->ioaddr + MOXA_MUST_RBRTH_REGISTER); outb((u8)info->rx_trigger, info->ioaddr + MOXA_MUST_RBRTI_REGISTER); outb((u8)info->rx_low_water, info->ioaddr + MOXA_MUST_RBRTL_REGISTER); outb(oldlcr, info->ioaddr + UART_LCR);} static void mxser_set_must_enum_value(unsigned long baseio, u8 value){ u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_BANK_MASK; efr |= MOXA_MUST_EFR_BANK2; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(value, baseio + MOXA_MUST_ENUM_REGISTER); outb(oldlcr, baseio + UART_LCR);} #ifdef CONFIG_PCIstatic void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId){ u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_BANK_MASK; efr |= MOXA_MUST_EFR_BANK2; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); *pId = inb(baseio + MOXA_MUST_HWID_REGISTER); outb(oldlcr, baseio + UART_LCR);}#endif static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio){ u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_SF_MASK; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(oldlcr, baseio + UART_LCR);} static void mxser_enable_must_tx_software_flow_control(unsigned long baseio){ u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_SF_TX_MASK; efr |= MOXA_MUST_EFR_SF_TX1; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(oldlcr, baseio + UART_LCR);} static void mxser_disable_must_tx_software_flow_control(unsigned long baseio){ u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_SF_TX_MASK; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(oldlcr, baseio + UART_LCR);} static void mxser_enable_must_rx_software_flow_control(unsigned long baseio){ u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_SF_RX_MASK; efr |= MOXA_MUST_EFR_SF_RX1; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(oldlcr, baseio + UART_LCR);} static void mxser_disable_must_rx_software_flow_control(unsigned long baseio){ u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_SF_RX_MASK; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(oldlcr, baseio + UART_LCR);} #ifdef CONFIG_PCIstatic int CheckIsMoxaMust(unsigned long io){ u8 oldmcr, hwid; int i; outb(0, io + UART_LCR); mxser_disable_must_enchance_mode(io); oldmcr = inb(io + UART_MCR); outb(0, io + UART_MCR); mxser_set_must_xon1_value(io, 0x11); if ((hwid = inb(io + UART_MCR)) != 0) {Lines 1–500 of 2778. Load more
/* * mxser.c -- MOXA Smartio/Industio family multiport serial driver. * * Copyright (C) 1999-2006 Moxa Technologies (support@moxa.com). * Copyright (C) 2006-2008 Jiri Slaby <jirislaby@gmail.com> * * 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. * * 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. * * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox * <alan@lxorguk.ukuu.org.uk>. 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 <asm/uaccess.h> #include "mxser.h" #define MXSER_VERSION "2.0.5" /* 1.14 */ #define MXSERMAJOR 174 #define MXSER_BOARDS 4 /* Max. boards */ #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ #define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) #define MXSER_ISR_PASS_LIMIT 100 /*CheckIsMoxaMust return value*/ #define MOXA_OTHER_UART 0x00 #define MOXA_MUST_MU150_HWID 0x01 #define MOXA_MUST_MU860_HWID 0x02 #define WAKEUP_CHARS 256 #define UART_MCR_AFE 0x20 #define UART_LSR_SPECIAL 0x1E #define PCI_DEVICE_ID_POS104UL 0x1044 #define PCI_DEVICE_ID_CB108 0x1080 #define PCI_DEVICE_ID_CP102UF 0x1023 #define PCI_DEVICE_ID_CP112UL 0x1120 #define PCI_DEVICE_ID_CB114 0x1142 #define PCI_DEVICE_ID_CP114UL 0x1143 #define PCI_DEVICE_ID_CB134I 0x1341 #define PCI_DEVICE_ID_CP138U 0x1380 #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 5 #define MXSER_HIGHBAUD 1 #define MXSER_HAS2 2 /* This is only for PCI */ static const struct { 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; } Gpci_uart_info[] = { {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} }; #define UART_INFO_NUM ARRAY_SIZE(Gpci_uart_info) struct mxser_cardinfo { char *name; unsigned int nports; unsigned int flags; }; static const struct mxser_cardinfo mxser_cards[] = { /* 0*/ { "C168 series", 8, }, { "C104 series", 4, }, { "CI-104J series", 4, }, { "C168H/PCI series", 8, }, { "C104H/PCI series", 4, }, /* 5*/ { "C102 series", 4, MXSER_HAS2 }, /* C102-ISA */ { "CI-132 series", 4, MXSER_HAS2 }, { "CI-134 series", 4, }, { "CP-132 series", 2, }, { "CP-114 series", 4, }, /*10*/ { "CT-114 series", 4, }, { "CP-102 series", 2, MXSER_HIGHBAUD }, { "CP-104U series", 4, }, { "CP-168U series", 8, }, { "CP-132U series", 2, }, /*15*/ { "CP-134U series", 4, }, { "CP-104JU series", 4, }, { "Moxa UC7000 Serial", 8, }, /* RC7000 */ { "CP-118U series", 8, }, { "CP-102UL series", 2, }, /*20*/ { "CP-102U series", 2, }, { "CP-118EL series", 8, }, { "CP-168EL series", 8, }, { "CP-104EL series", 4, }, { "CB-108 series", 8, }, /*25*/ { "CB-114 series", 4, }, { "CB-134I series", 4, }, { "CP-138U series", 8, }, { "POS-104UL series", 4, }, { "CP-114UL series", 4, }, /*30*/ { "CP-102UF series", 2, }, { "CP-112UL series", 2, }, }; /* driver_data correspond to the lines in the structure above see also ISA probe function before you change something */ static struct pci_device_id mxser_pcibrds[] = { { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C168), .driver_data = 3 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C104), .driver_data = 4 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132), .driver_data = 8 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114), .driver_data = 9 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CT114), .driver_data = 10 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102), .driver_data = 11 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104U), .driver_data = 12 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168U), .driver_data = 13 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132U), .driver_data = 14 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP134U), .driver_data = 15 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104JU),.driver_data = 16 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_RC7000), .driver_data = 17 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118U), .driver_data = 18 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UL),.driver_data = 19 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102U), .driver_data = 20 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118EL),.driver_data = 21 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168EL),.driver_data = 22 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104EL),.driver_data = 23 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB108), .driver_data = 24 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB114), .driver_data = 25 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB134I), .driver_data = 26 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U), .driver_data = 27 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 28 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL), .driver_data = 29 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF), .driver_data = 30 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP112UL), .driver_data = 31 }, { } }; MODULE_DEVICE_TABLE(pci, mxser_pcibrds); static unsigned long ioaddr[MXSER_BOARDS]; static int ttymajor = MXSERMAJOR; /* Variables for insmod */ MODULE_AUTHOR("Casper Yang"); MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); module_param_array(ioaddr, ulong, NULL, 0); MODULE_PARM_DESC(ioaddr, "ISA io addresses to look for a moxa board"); module_param(ttymajor, int, 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_board; struct mxser_port { struct tty_port port; struct mxser_board *board; unsigned long ioaddr; unsigned long opmode_ioaddr; int max_baud; int rx_high_water; int rx_trigger; /* Rx fifo trigger level */ int rx_low_water; int baud_base; /* max. speed */ int type; /* UART type */ int x_char; /* xon/xoff character */ int IER; /* Interrupt Enable Register */ int MCR; /* Modem control register */ unsigned char stop_rx; unsigned char ldisc_stop_rx; int custom_divisor; unsigned char err_shadow; struct async_icount icount; /* kernel counters for 4 input interrupts */ int timeout; int read_status_mask; int ignore_status_mask; int xmit_fifo_size; int xmit_head; int xmit_tail; int xmit_cnt; struct ktermios normal_termios; struct mxser_mon mon_data; spinlock_t slock; }; struct mxser_board { unsigned int idx; int irq; const struct mxser_cardinfo *info; unsigned long vector; unsigned long vector_mask; int chip_flag; int uart_type; struct mxser_port ports[MXSER_PORTS_PER_BOARD]; }; struct mxser_mstatus { tcflag_t cflag; int cts; int dsr; int ri; int dcd; }; static struct mxser_board mxser_boards[MXSER_BOARDS]; static struct tty_driver *mxvar_sdriver; static struct mxser_log mxvar_log; static int mxser_set_baud_method[MXSER_PORTS + 1]; static void mxser_enable_must_enchance_mode(unsigned long baseio) { u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr |= MOXA_MUST_EFR_EFRB_ENABLE; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(oldlcr, baseio + UART_LCR); } #ifdef CONFIG_PCI static void mxser_disable_must_enchance_mode(unsigned long baseio) { u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_EFRB_ENABLE; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(oldlcr, baseio + UART_LCR); } #endif static void mxser_set_must_xon1_value(unsigned long baseio, u8 value) { u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_BANK_MASK; efr |= MOXA_MUST_EFR_BANK0; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(value, baseio + MOXA_MUST_XON1_REGISTER); outb(oldlcr, baseio + UART_LCR); } static void mxser_set_must_xoff1_value(unsigned long baseio, u8 value) { u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_BANK_MASK; efr |= MOXA_MUST_EFR_BANK0; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(value, baseio + MOXA_MUST_XOFF1_REGISTER); outb(oldlcr, baseio + UART_LCR); } static void mxser_set_must_fifo_value(struct mxser_port *info) { u8 oldlcr; u8 efr; oldlcr = inb(info->ioaddr + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, info->ioaddr + UART_LCR); efr = inb(info->ioaddr + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_BANK_MASK; efr |= MOXA_MUST_EFR_BANK1; outb(efr, info->ioaddr + MOXA_MUST_EFR_REGISTER); outb((u8)info->rx_high_water, info->ioaddr + MOXA_MUST_RBRTH_REGISTER); outb((u8)info->rx_trigger, info->ioaddr + MOXA_MUST_RBRTI_REGISTER); outb((u8)info->rx_low_water, info->ioaddr + MOXA_MUST_RBRTL_REGISTER); outb(oldlcr, info->ioaddr + UART_LCR); } static void mxser_set_must_enum_value(unsigned long baseio, u8 value) { u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_BANK_MASK; efr |= MOXA_MUST_EFR_BANK2; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(value, baseio + MOXA_MUST_ENUM_REGISTER); outb(oldlcr, baseio + UART_LCR); } #ifdef CONFIG_PCI static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId) { u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_BANK_MASK; efr |= MOXA_MUST_EFR_BANK2; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); *pId = inb(baseio + MOXA_MUST_HWID_REGISTER); outb(oldlcr, baseio + UART_LCR); } #endif static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio) { u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_SF_MASK; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(oldlcr, baseio + UART_LCR); } static void mxser_enable_must_tx_software_flow_control(unsigned long baseio) { u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_SF_TX_MASK; efr |= MOXA_MUST_EFR_SF_TX1; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(oldlcr, baseio + UART_LCR); } static void mxser_disable_must_tx_software_flow_control(unsigned long baseio) { u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_SF_TX_MASK; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(oldlcr, baseio + UART_LCR); } static void mxser_enable_must_rx_software_flow_control(unsigned long baseio) { u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_SF_RX_MASK; efr |= MOXA_MUST_EFR_SF_RX1; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(oldlcr, baseio + UART_LCR); } static void mxser_disable_must_rx_software_flow_control(unsigned long baseio) { u8 oldlcr; u8 efr; oldlcr = inb(baseio + UART_LCR); outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); efr &= ~MOXA_MUST_EFR_SF_RX_MASK; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(oldlcr, baseio + UART_LCR); } #ifdef CONFIG_PCI static int CheckIsMoxaMust(unsigned long io) { u8 oldmcr, hwid; int i; outb(0, io + UART_LCR); mxser_disable_must_enchance_mode(io); oldmcr = inb(io + UART_MCR); outb(0, io + UART_MCR); mxser_set_must_xon1_value(io, 0x11); if ((hwid = inb(io + UART_MCR)) != 0) {