^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * moxa.c -- MOXA Intellio family multiport serial driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 1999-2000 Moxa Technologies (support@moxa.com).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This code is loosely based on the Linux serial driver, written by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Linus Torvalds, Theodore T'so and others.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * MOXA Intellio Series Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * for : LINUX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * date : 1999/1/7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * version : 5.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/tty_flip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/major.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/serial.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/tty_driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/ratelimit.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include "moxa.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define MOXA_VERSION "6.0k"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define MOXA_FW_HDRLEN 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define MOXAMAJOR 172
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define MAX_BOARDS 4 /* Don't change this value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define MAX_PORTS_PER_BOARD 32 /* Don't change this value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define MAX_PORTS (MAX_BOARDS * MAX_PORTS_PER_BOARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define MOXA_IS_320(brd) ((brd)->boardType == MOXA_BOARD_C320_ISA || \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) (brd)->boardType == MOXA_BOARD_C320_PCI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * Define the Moxa PCI vendor and device IDs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define MOXA_BUS_TYPE_ISA 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define MOXA_BUS_TYPE_PCI 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) MOXA_BOARD_C218_PCI = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) MOXA_BOARD_C218_ISA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) MOXA_BOARD_C320_PCI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) MOXA_BOARD_C320_ISA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) MOXA_BOARD_CP204J,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static char *moxa_brdname[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) "C218 Turbo PCI series",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) "C218 Turbo ISA series",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) "C320 Turbo PCI series",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) "C320 Turbo ISA series",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) "CP-204J series",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static const struct pci_device_id moxa_pcibrds[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C218),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .driver_data = MOXA_BOARD_C218_PCI },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C320),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .driver_data = MOXA_BOARD_C320_PCI },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP204J),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .driver_data = MOXA_BOARD_CP204J },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) { 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) MODULE_DEVICE_TABLE(pci, moxa_pcibrds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #endif /* CONFIG_PCI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct moxa_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static struct moxa_board_conf {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int boardType;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int numPorts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int busType;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) unsigned int ready;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct moxa_port *ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) void __iomem *basemem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) void __iomem *intNdx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) void __iomem *intPend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) void __iomem *intTable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) } moxa_boards[MAX_BOARDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct mxser_mstatus {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) tcflag_t cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int cts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int dsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int ri;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) int dcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct moxaq_str {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int inq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int outq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct moxa_port {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct tty_port port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct moxa_board_conf *board;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) void __iomem *tableAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) unsigned long statusflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) u8 DCDState; /* Protected by the port lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) u8 lineCtrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) u8 lowChkFlag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct mon_str {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int tick;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) int rxcnt[MAX_PORTS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int txcnt[MAX_PORTS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /* statusflags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define TXSTOPPED 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define LOWWAIT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define EMPTYWAIT 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define WAKEUP_CHARS 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static int ttymajor = MOXAMAJOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static struct mon_str moxaLog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static unsigned int moxaFuncTout = HZ / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static unsigned int moxaLowWaterChk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static DEFINE_MUTEX(moxa_openlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static DEFINE_SPINLOCK(moxa_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static unsigned long baseaddr[MAX_BOARDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static unsigned int type[MAX_BOARDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static unsigned int numports[MAX_BOARDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static struct tty_port moxa_service_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) MODULE_AUTHOR("William Chen");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) MODULE_FIRMWARE("c218tunx.cod");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) MODULE_FIRMWARE("cp204unx.cod");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) MODULE_FIRMWARE("c320tunx.cod");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) module_param_array(type, uint, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) MODULE_PARM_DESC(type, "card type: C218=2, C320=4");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) module_param_hw_array(baseaddr, ulong, ioport, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) MODULE_PARM_DESC(baseaddr, "base address");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) module_param_array(numports, uint, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) MODULE_PARM_DESC(numports, "numports (ignored for C218)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) module_param(ttymajor, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * static functions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static int moxa_open(struct tty_struct *, struct file *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static void moxa_close(struct tty_struct *, struct file *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static int moxa_write(struct tty_struct *, const unsigned char *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static int moxa_write_room(struct tty_struct *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static void moxa_flush_buffer(struct tty_struct *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static int moxa_chars_in_buffer(struct tty_struct *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static void moxa_set_termios(struct tty_struct *, struct ktermios *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static void moxa_stop(struct tty_struct *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static void moxa_start(struct tty_struct *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static void moxa_hangup(struct tty_struct *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static int moxa_tiocmget(struct tty_struct *tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static int moxa_tiocmset(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) unsigned int set, unsigned int clear);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static void moxa_poll(struct timer_list *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static void moxa_set_tty_param(struct tty_struct *, struct ktermios *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static void moxa_shutdown(struct tty_port *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static int moxa_carrier_raised(struct tty_port *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static void moxa_dtr_rts(struct tty_port *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * moxa board interface functions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static void MoxaPortEnable(struct moxa_port *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static void MoxaPortDisable(struct moxa_port *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static int MoxaPortSetTermio(struct moxa_port *, struct ktermios *, speed_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static int MoxaPortGetLineOut(struct moxa_port *, int *, int *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static void MoxaPortLineCtrl(struct moxa_port *, int, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static int MoxaPortLineStatus(struct moxa_port *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static void MoxaPortFlushData(struct moxa_port *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static int MoxaPortWriteData(struct tty_struct *, const unsigned char *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static int MoxaPortReadData(struct moxa_port *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static int MoxaPortTxQueue(struct moxa_port *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static int MoxaPortRxQueue(struct moxa_port *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static int MoxaPortTxFree(struct moxa_port *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static void MoxaPortTxDisable(struct moxa_port *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static void MoxaPortTxEnable(struct moxa_port *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static int moxa_get_serial_info(struct tty_struct *, struct serial_struct *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static int moxa_set_serial_info(struct tty_struct *, struct serial_struct *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static void MoxaSetFifo(struct moxa_port *port, int enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * I/O functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static DEFINE_SPINLOCK(moxafunc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static void moxa_wait_finish(void __iomem *ofsAddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) unsigned long end = jiffies + moxaFuncTout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) while (readw(ofsAddr + FuncCode) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (time_after(jiffies, end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (readw(ofsAddr + FuncCode) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) printk_ratelimited(KERN_WARNING "moxa function expired\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) spin_lock_irqsave(&moxafunc_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) writew(arg, ofsAddr + FuncArg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) writew(cmd, ofsAddr + FuncCode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) moxa_wait_finish(ofsAddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) spin_unlock_irqrestore(&moxafunc_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static int moxafuncret(void __iomem *ofsAddr, u16 cmd, u16 arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) u16 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) spin_lock_irqsave(&moxafunc_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) writew(arg, ofsAddr + FuncArg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) writew(cmd, ofsAddr + FuncCode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) moxa_wait_finish(ofsAddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) ret = readw(ofsAddr + FuncArg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) spin_unlock_irqrestore(&moxafunc_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static void moxa_low_water_check(void __iomem *ofsAddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) u16 rptr, wptr, mask, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (readb(ofsAddr + FlagStat) & Xoff_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) rptr = readw(ofsAddr + RXrptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) wptr = readw(ofsAddr + RXwptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) mask = readw(ofsAddr + RX_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) len = (wptr - rptr) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (len <= Low_water)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) moxafunc(ofsAddr, FC_SendXon, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * TTY operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static int moxa_ioctl(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct moxa_port *ch = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) void __user *argp = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) int status, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (tty->index == MAX_PORTS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (cmd != MOXA_GETDATACOUNT && cmd != MOXA_GET_IOQUEUE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) cmd != MOXA_GETMSTATUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) } else if (!ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) case MOXA_GETDATACOUNT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) moxaLog.tick = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (copy_to_user(argp, &moxaLog, sizeof(moxaLog)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) case MOXA_FLUSH_QUEUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) MoxaPortFlushData(ch, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) case MOXA_GET_IOQUEUE: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct moxaq_str __user *argm = argp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct moxaq_str tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct moxa_port *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) unsigned int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) for (i = 0; i < MAX_BOARDS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) p = moxa_boards[i].ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) memset(&tmp, 0, sizeof(tmp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) spin_lock_bh(&moxa_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (moxa_boards[i].ready) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) tmp.inq = MoxaPortRxQueue(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) tmp.outq = MoxaPortTxQueue(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) spin_unlock_bh(&moxa_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (copy_to_user(argm, &tmp, sizeof(tmp)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) } case MOXA_GET_OQUEUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) status = MoxaPortTxQueue(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) ret = put_user(status, (unsigned long __user *)argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) case MOXA_GET_IQUEUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) status = MoxaPortRxQueue(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) ret = put_user(status, (unsigned long __user *)argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) case MOXA_GETMSTATUS: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct mxser_mstatus __user *argm = argp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct mxser_mstatus tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct moxa_port *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) unsigned int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) for (i = 0; i < MAX_BOARDS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) p = moxa_boards[i].ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct tty_struct *ttyp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) memset(&tmp, 0, sizeof(tmp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) spin_lock_bh(&moxa_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (!moxa_boards[i].ready) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) spin_unlock_bh(&moxa_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) goto copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) status = MoxaPortLineStatus(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) spin_unlock_bh(&moxa_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (status & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) tmp.cts = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (status & 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) tmp.dsr = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (status & 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) tmp.dcd = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) ttyp = tty_port_tty_get(&p->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (!ttyp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) tmp.cflag = p->cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) tmp.cflag = ttyp->termios.c_cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) tty_kref_put(ttyp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) copy:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (copy_to_user(argm, &tmp, sizeof(tmp)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) ret = -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static int moxa_break_ctl(struct tty_struct *tty, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) struct moxa_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) Magic_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static const struct tty_operations moxa_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) .open = moxa_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) .close = moxa_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) .write = moxa_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) .write_room = moxa_write_room,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) .flush_buffer = moxa_flush_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) .chars_in_buffer = moxa_chars_in_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) .ioctl = moxa_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) .set_termios = moxa_set_termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) .stop = moxa_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) .start = moxa_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) .hangup = moxa_hangup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) .break_ctl = moxa_break_ctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) .tiocmget = moxa_tiocmget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) .tiocmset = moxa_tiocmset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) .set_serial = moxa_set_serial_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) .get_serial = moxa_get_serial_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static const struct tty_port_operations moxa_port_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) .carrier_raised = moxa_carrier_raised,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) .dtr_rts = moxa_dtr_rts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) .shutdown = moxa_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) static struct tty_driver *moxaDriver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) static DEFINE_TIMER(moxaTimer, moxa_poll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * HW init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static int moxa_check_fw_model(struct moxa_board_conf *brd, u8 model)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) switch (brd->boardType) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) case MOXA_BOARD_C218_ISA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) case MOXA_BOARD_C218_PCI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (model != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) case MOXA_BOARD_CP204J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (model != 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (model != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) static int moxa_check_fw(const void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) const __le16 *lptr = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (*lptr != cpu_to_le16(0x7980))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) static int moxa_load_bios(struct moxa_board_conf *brd, const u8 *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) void __iomem *baseAddr = brd->basemem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) u16 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) writeb(HW_reset, baseAddr + Control_reg); /* reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) memset_io(baseAddr, 0, 4096);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) memcpy_toio(baseAddr, buf, len); /* download BIOS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) writeb(0, baseAddr + Control_reg); /* restart */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) msleep(2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) switch (brd->boardType) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) case MOXA_BOARD_C218_ISA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) case MOXA_BOARD_C218_PCI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) tmp = readw(baseAddr + C218_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (tmp != C218_KeyCode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) case MOXA_BOARD_CP204J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) tmp = readw(baseAddr + C218_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (tmp != CP204J_KeyCode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) tmp = readw(baseAddr + C320_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (tmp != C320_KeyCode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) tmp = readw(baseAddr + C320_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (tmp != STS_init) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) printk(KERN_ERR "MOXA: bios upload failed -- CPU/Basic "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) "module not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) printk(KERN_ERR "MOXA: bios upload failed -- board not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) static int moxa_load_320b(struct moxa_board_conf *brd, const u8 *ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) void __iomem *baseAddr = brd->basemem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (len < 7168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) printk(KERN_ERR "MOXA: invalid 320 bios -- too short\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) writew(len - 7168 - 2, baseAddr + C320bapi_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) writeb(1, baseAddr + Control_reg); /* Select Page 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) memcpy_toio(baseAddr + DynPage_addr, ptr, 7168);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) writeb(2, baseAddr + Control_reg); /* Select Page 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) memcpy_toio(baseAddr + DynPage_addr, ptr + 7168, len - 7168);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) static int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) void __iomem *baseAddr = brd->basemem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) const __le16 *uptr = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) size_t wlen, len2, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) unsigned long key, loadbuf, loadlen, checksum, checksum_ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) unsigned int i, retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) u16 usum, keycode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) keycode = (brd->boardType == MOXA_BOARD_CP204J) ? CP204J_KeyCode :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) C218_KeyCode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) switch (brd->boardType) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) case MOXA_BOARD_CP204J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) case MOXA_BOARD_C218_ISA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) case MOXA_BOARD_C218_PCI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) key = C218_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) loadbuf = C218_LoadBuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) loadlen = C218DLoad_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) checksum = C218check_sum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) checksum_ok = C218chksum_ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) key = C320_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) keycode = C320_KeyCode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) loadbuf = C320_LoadBuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) loadlen = C320DLoad_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) checksum = C320check_sum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) checksum_ok = C320chksum_ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) usum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) wlen = len >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) for (i = 0; i < wlen; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) usum += le16_to_cpu(uptr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) retry = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) wlen = len >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) while (wlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) len2 = (wlen > 2048) ? 2048 : wlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) wlen -= len2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) memcpy_toio(baseAddr + loadbuf, ptr + j, len2 << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) j += len2 << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) writew(len2, baseAddr + loadlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) writew(0, baseAddr + key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) for (i = 0; i < 100; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (readw(baseAddr + key) == keycode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (readw(baseAddr + key) != keycode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) writew(0, baseAddr + loadlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) writew(usum, baseAddr + checksum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) writew(0, baseAddr + key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) for (i = 0; i < 100; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (readw(baseAddr + key) == keycode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) retry++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) } while ((readb(baseAddr + checksum_ok) != 1) && (retry < 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (readb(baseAddr + checksum_ok) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) writew(0, baseAddr + key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) for (i = 0; i < 600; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (readw(baseAddr + Magic_no) == Magic_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (readw(baseAddr + Magic_no) != Magic_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (MOXA_IS_320(brd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (brd->busType == MOXA_BUS_TYPE_PCI) { /* ASIC board */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) writew(0x3800, baseAddr + TMS320_PORT1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) writew(0x3900, baseAddr + TMS320_PORT2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) writew(28499, baseAddr + TMS320_CLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) writew(0x3200, baseAddr + TMS320_PORT1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) writew(0x3400, baseAddr + TMS320_PORT2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) writew(19999, baseAddr + TMS320_CLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) writew(1, baseAddr + Disable_IRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) writew(0, baseAddr + Magic_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) for (i = 0; i < 500; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (readw(baseAddr + Magic_no) == Magic_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (readw(baseAddr + Magic_no) != Magic_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (MOXA_IS_320(brd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) j = readw(baseAddr + Module_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (j <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) brd->numPorts = j * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) writew(j, baseAddr + Module_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) writew(0, baseAddr + Magic_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) for (i = 0; i < 600; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (readw(baseAddr + Magic_no) == Magic_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (readw(baseAddr + Magic_no) != Magic_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) brd->intNdx = baseAddr + IRQindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) brd->intPend = baseAddr + IRQpending;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) brd->intTable = baseAddr + IRQtable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static int moxa_load_code(struct moxa_board_conf *brd, const void *ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) void __iomem *ofsAddr, *baseAddr = brd->basemem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) struct moxa_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) int retval, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (len % 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) printk(KERN_ERR "MOXA: bios length is not even\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) retval = moxa_real_load_code(brd, ptr, len); /* may change numPorts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) switch (brd->boardType) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) case MOXA_BOARD_C218_ISA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) case MOXA_BOARD_C218_PCI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) case MOXA_BOARD_CP204J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) port = brd->ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) for (i = 0; i < brd->numPorts; i++, port++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) port->board = brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) port->DCDState = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) port->tableAddr = baseAddr + Extern_table +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) Extern_size * i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) ofsAddr = port->tableAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) writew(C218rx_mask, ofsAddr + RX_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) writew(C218tx_mask, ofsAddr + TX_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) port = brd->ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) for (i = 0; i < brd->numPorts; i++, port++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) port->board = brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) port->DCDState = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) port->tableAddr = baseAddr + Extern_table +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) Extern_size * i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) ofsAddr = port->tableAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) switch (brd->numPorts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) writew(C320p8rx_mask, ofsAddr + RX_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) writew(C320p8tx_mask, ofsAddr + TX_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) writew(C320p16rx_mask, ofsAddr + RX_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) writew(C320p16tx_mask, ofsAddr + TX_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) writew(C320p24rx_mask, ofsAddr + RX_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) writew(C320p24tx_mask, ofsAddr + TX_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) writew(C320p32rx_mask, ofsAddr + RX_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) writew(C320p32tx_mask, ofsAddr + TX_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) writew(C320p32tx_ofs, ofsAddr + Ofs_txb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) static int moxa_load_fw(struct moxa_board_conf *brd, const struct firmware *fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) const void *ptr = fw->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) char rsn[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) u16 lens[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) unsigned int a, lenp, lencnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) __le32 magic; /* 0x34303430 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) u8 reserved1[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) u8 type; /* UNIX = 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) u8 model; /* C218T=1, C320T=2, CP204=3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) u8 reserved2[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) __le16 len[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) } const *hdr = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) BUILD_BUG_ON(ARRAY_SIZE(hdr->len) != ARRAY_SIZE(lens));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (fw->size < MOXA_FW_HDRLEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) strcpy(rsn, "too short (even header won't fit)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (hdr->magic != cpu_to_le32(0x30343034)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) sprintf(rsn, "bad magic: %.8x", le32_to_cpu(hdr->magic));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) if (hdr->type != 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) sprintf(rsn, "not for linux, type is %u", hdr->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (moxa_check_fw_model(brd, hdr->model)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) sprintf(rsn, "not for this card, model is %u", hdr->model);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) len = MOXA_FW_HDRLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) lencnt = hdr->model == 2 ? 5 : 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) for (a = 0; a < ARRAY_SIZE(lens); a++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) lens[a] = le16_to_cpu(hdr->len[a]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (lens[a] && len + lens[a] <= fw->size &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) moxa_check_fw(&fw->data[len]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) printk(KERN_WARNING "MOXA firmware: unexpected input "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) "at offset %u, but going on\n", (u32)len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (!lens[a] && a < lencnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) sprintf(rsn, "too few entries in fw file");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) len += lens[a];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (len != fw->size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) sprintf(rsn, "bad length: %u (should be %u)", (u32)fw->size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) (u32)len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) ptr += MOXA_FW_HDRLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) lenp = 0; /* bios */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) strcpy(rsn, "read above");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) ret = moxa_load_bios(brd, ptr, lens[lenp]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) /* we skip the tty section (lens[1]), since we don't need it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) ptr += lens[lenp] + lens[lenp + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) lenp += 2; /* comm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (hdr->model == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) ret = moxa_load_320b(brd, ptr, lens[lenp]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) /* skip another tty */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) ptr += lens[lenp] + lens[lenp + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) lenp += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) ret = moxa_load_code(brd, ptr, lens[lenp]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) printk(KERN_ERR "firmware failed to load, reason: %s\n", rsn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) const struct firmware *fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) const char *file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) struct moxa_port *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) unsigned int i, first_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) brd->ports = kcalloc(MAX_PORTS_PER_BOARD, sizeof(*brd->ports),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (brd->ports == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) printk(KERN_ERR "cannot allocate memory for ports\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) tty_port_init(&p->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) p->port.ops = &moxa_port_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) p->type = PORT_16550A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) switch (brd->boardType) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) case MOXA_BOARD_C218_ISA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) case MOXA_BOARD_C218_PCI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) file = "c218tunx.cod";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) case MOXA_BOARD_CP204J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) file = "cp204unx.cod";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) file = "c320tunx.cod";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) ret = request_firmware(&fw, file, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) printk(KERN_ERR "MOXA: request_firmware failed. Make sure "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) "you've placed '%s' file into your firmware "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) "loader directory (e.g. /lib/firmware)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) ret = moxa_load_fw(brd, fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) release_firmware(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) spin_lock_bh(&moxa_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) brd->ready = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (!timer_pending(&moxaTimer))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) mod_timer(&moxaTimer, jiffies + HZ / 50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) spin_unlock_bh(&moxa_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) first_idx = (brd - moxa_boards) * MAX_PORTS_PER_BOARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) for (i = 0; i < brd->numPorts; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) tty_port_register_device(&brd->ports[i].port, moxaDriver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) first_idx + i, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) err_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) for (i = 0; i < MAX_PORTS_PER_BOARD; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) tty_port_destroy(&brd->ports[i].port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) kfree(brd->ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) static void moxa_board_deinit(struct moxa_board_conf *brd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) unsigned int a, opened, first_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) mutex_lock(&moxa_openlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) spin_lock_bh(&moxa_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) brd->ready = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) spin_unlock_bh(&moxa_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /* pci hot-un-plug support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) for (a = 0; a < brd->numPorts; a++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (tty_port_initialized(&brd->ports[a].port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) tty_port_tty_hangup(&brd->ports[a].port, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) for (a = 0; a < MAX_PORTS_PER_BOARD; a++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) tty_port_destroy(&brd->ports[a].port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) opened = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) for (a = 0; a < brd->numPorts; a++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (tty_port_initialized(&brd->ports[a].port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) opened++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) mutex_unlock(&moxa_openlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) if (!opened)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) msleep(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) mutex_lock(&moxa_openlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) first_idx = (brd - moxa_boards) * MAX_PORTS_PER_BOARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) for (a = 0; a < brd->numPorts; a++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) tty_unregister_device(moxaDriver, first_idx + a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) iounmap(brd->basemem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) brd->basemem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) kfree(brd->ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) static int moxa_pci_probe(struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) const struct pci_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) struct moxa_board_conf *board;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) int board_type = ent->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) retval = pci_enable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) dev_err(&pdev->dev, "can't enable pci device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) for (i = 0; i < MAX_BOARDS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) if (moxa_boards[i].basemem == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) retval = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (i >= MAX_BOARDS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) dev_warn(&pdev->dev, "more than %u MOXA Intellio family boards "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) "found. Board is ignored.\n", MAX_BOARDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) board = &moxa_boards[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) retval = pci_request_region(pdev, 2, "moxa-base");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) dev_err(&pdev->dev, "can't request pci region 2\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) board->basemem = ioremap(pci_resource_start(pdev, 2), 0x4000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (board->basemem == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) dev_err(&pdev->dev, "can't remap io space 2\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) goto err_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) board->boardType = board_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) switch (board_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) case MOXA_BOARD_C218_ISA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) case MOXA_BOARD_C218_PCI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) board->numPorts = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) case MOXA_BOARD_CP204J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) board->numPorts = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) board->numPorts = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) board->busType = MOXA_BUS_TYPE_PCI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) retval = moxa_init_board(board, &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) goto err_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) pci_set_drvdata(pdev, board);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) dev_info(&pdev->dev, "board '%s' ready (%u ports, firmware loaded)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) moxa_brdname[board_type - 1], board->numPorts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) err_base:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) iounmap(board->basemem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) board->basemem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) err_reg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) pci_release_region(pdev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) static void moxa_pci_remove(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) struct moxa_board_conf *brd = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) moxa_board_deinit(brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) pci_release_region(pdev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) static struct pci_driver moxa_pci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) .name = "moxa",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) .id_table = moxa_pcibrds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) .probe = moxa_pci_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) .remove = moxa_pci_remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) #endif /* CONFIG_PCI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) static int __init moxa_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) unsigned int isabrds = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) struct moxa_board_conf *brd = moxa_boards;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) printk(KERN_INFO "MOXA Intellio family driver version %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) MOXA_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) tty_port_init(&moxa_service_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) moxaDriver = tty_alloc_driver(MAX_PORTS + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) TTY_DRIVER_REAL_RAW |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) TTY_DRIVER_DYNAMIC_DEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (IS_ERR(moxaDriver))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return PTR_ERR(moxaDriver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) moxaDriver->name = "ttyMX";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) moxaDriver->major = ttymajor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) moxaDriver->minor_start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) moxaDriver->type = TTY_DRIVER_TYPE_SERIAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) moxaDriver->subtype = SERIAL_TYPE_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) moxaDriver->init_termios = tty_std_termios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) moxaDriver->init_termios.c_ispeed = 9600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) moxaDriver->init_termios.c_ospeed = 9600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) tty_set_operations(moxaDriver, &moxa_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) /* Having one more port only for ioctls is ugly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) tty_port_link_device(&moxa_service_port, moxaDriver, MAX_PORTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (tty_register_driver(moxaDriver)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) printk(KERN_ERR "can't register MOXA Smartio tty driver!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) put_tty_driver(moxaDriver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) /* Find the boards defined from module args. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) for (i = 0; i < MAX_BOARDS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) if (!baseaddr[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) if (type[i] == MOXA_BOARD_C218_ISA ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) type[i] == MOXA_BOARD_C320_ISA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) isabrds + 1, moxa_brdname[type[i] - 1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) baseaddr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) brd->boardType = type[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) numports[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) brd->busType = MOXA_BUS_TYPE_ISA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) brd->basemem = ioremap(baseaddr[i], 0x4000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (!brd->basemem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) printk(KERN_ERR "MOXA: can't remap %lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) baseaddr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (moxa_init_board(brd, NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) iounmap(brd->basemem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) brd->basemem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) printk(KERN_INFO "MOXA isa board found at 0x%.8lx and "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) "ready (%u ports, firmware loaded)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) baseaddr[i], brd->numPorts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) brd++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) isabrds++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) retval = pci_register_driver(&moxa_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) printk(KERN_ERR "Can't register MOXA pci driver!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (isabrds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) static void __exit moxa_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) pci_unregister_driver(&moxa_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) for (i = 0; i < MAX_BOARDS; i++) /* ISA boards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if (moxa_boards[i].ready)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) moxa_board_deinit(&moxa_boards[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) del_timer_sync(&moxaTimer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) if (tty_unregister_driver(moxaDriver))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) printk(KERN_ERR "Couldn't unregister MOXA Intellio family "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) "serial driver\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) put_tty_driver(moxaDriver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) module_init(moxa_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) module_exit(moxa_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) static void moxa_shutdown(struct tty_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) struct moxa_port *ch = container_of(port, struct moxa_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) MoxaPortDisable(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) MoxaPortFlushData(ch, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) static int moxa_carrier_raised(struct tty_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) struct moxa_port *ch = container_of(port, struct moxa_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) int dcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) spin_lock_irq(&port->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) dcd = ch->DCDState;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) spin_unlock_irq(&port->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) return dcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) static void moxa_dtr_rts(struct tty_port *port, int onoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) struct moxa_port *ch = container_of(port, struct moxa_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) MoxaPortLineCtrl(ch, onoff, onoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) static int moxa_open(struct tty_struct *tty, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) struct moxa_board_conf *brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) struct moxa_port *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) int port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) port = tty->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (port == MAX_PORTS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) return capable(CAP_SYS_ADMIN) ? 0 : -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) if (mutex_lock_interruptible(&moxa_openlock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) brd = &moxa_boards[port / MAX_PORTS_PER_BOARD];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) if (!brd->ready) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) mutex_unlock(&moxa_openlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) if (port % MAX_PORTS_PER_BOARD >= brd->numPorts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) mutex_unlock(&moxa_openlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) ch = &brd->ports[port % MAX_PORTS_PER_BOARD];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) ch->port.count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) tty->driver_data = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) tty_port_tty_set(&ch->port, tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) mutex_lock(&ch->port.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) if (!tty_port_initialized(&ch->port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) ch->statusflags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) moxa_set_tty_param(tty, &tty->termios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) MoxaPortLineCtrl(ch, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) MoxaPortEnable(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) MoxaSetFifo(ch, ch->type == PORT_16550A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) tty_port_set_initialized(&ch->port, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) mutex_unlock(&ch->port.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) mutex_unlock(&moxa_openlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) return tty_port_block_til_ready(&ch->port, tty, filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) static void moxa_close(struct tty_struct *tty, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) struct moxa_port *ch = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) ch->cflag = tty->termios.c_cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) tty_port_close(&ch->port, tty, filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) static int moxa_write(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) const unsigned char *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) struct moxa_port *ch = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) if (ch == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) spin_lock_irqsave(&moxa_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) len = MoxaPortWriteData(tty, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) spin_unlock_irqrestore(&moxa_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) set_bit(LOWWAIT, &ch->statusflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) static int moxa_write_room(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) struct moxa_port *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (tty->stopped)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) ch = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) if (ch == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) return MoxaPortTxFree(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) static void moxa_flush_buffer(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) struct moxa_port *ch = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (ch == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) MoxaPortFlushData(ch, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) tty_wakeup(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) static int moxa_chars_in_buffer(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) struct moxa_port *ch = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) int chars;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) chars = MoxaPortTxQueue(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) if (chars)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) * Make it possible to wakeup anything waiting for output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) * in tty_ioctl.c, etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) set_bit(EMPTYWAIT, &ch->statusflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) return chars;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) static int moxa_tiocmget(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) struct moxa_port *ch = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) int flag = 0, dtr, rts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) MoxaPortGetLineOut(ch, &dtr, &rts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) if (dtr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) flag |= TIOCM_DTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) if (rts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) flag |= TIOCM_RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) dtr = MoxaPortLineStatus(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) if (dtr & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) flag |= TIOCM_CTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) if (dtr & 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) flag |= TIOCM_DSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) if (dtr & 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) flag |= TIOCM_CD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) return flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) static int moxa_tiocmset(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) unsigned int set, unsigned int clear)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) struct moxa_port *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) int dtr, rts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) mutex_lock(&moxa_openlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) ch = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) if (!ch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) mutex_unlock(&moxa_openlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) MoxaPortGetLineOut(ch, &dtr, &rts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) if (set & TIOCM_RTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) rts = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) if (set & TIOCM_DTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) dtr = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) if (clear & TIOCM_RTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) rts = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) if (clear & TIOCM_DTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) dtr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) MoxaPortLineCtrl(ch, dtr, rts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) mutex_unlock(&moxa_openlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) static void moxa_set_termios(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) struct ktermios *old_termios)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) struct moxa_port *ch = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) if (ch == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) moxa_set_tty_param(tty, old_termios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) wake_up_interruptible(&ch->port.open_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) static void moxa_stop(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) struct moxa_port *ch = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (ch == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) MoxaPortTxDisable(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) set_bit(TXSTOPPED, &ch->statusflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) static void moxa_start(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) struct moxa_port *ch = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) if (ch == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (!test_bit(TXSTOPPED, &ch->statusflags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) MoxaPortTxEnable(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) clear_bit(TXSTOPPED, &ch->statusflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) static void moxa_hangup(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) struct moxa_port *ch = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) tty_port_hangup(&ch->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) dcd = !!dcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) spin_lock_irqsave(&p->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) if (dcd != p->DCDState) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) p->DCDState = dcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) spin_unlock_irqrestore(&p->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) if (!dcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) tty_port_tty_hangup(&p->port, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) spin_unlock_irqrestore(&p->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) u16 __iomem *ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) struct tty_struct *tty = tty_port_tty_get(&p->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) void __iomem *ofsAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) unsigned int inited = tty_port_initialized(&p->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) u16 intr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) if (tty) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) if (test_bit(EMPTYWAIT, &p->statusflags) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) MoxaPortTxQueue(p) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) clear_bit(EMPTYWAIT, &p->statusflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) tty_wakeup(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) if (test_bit(LOWWAIT, &p->statusflags) && !tty->stopped &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) MoxaPortTxQueue(p) <= WAKEUP_CHARS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) clear_bit(LOWWAIT, &p->statusflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) tty_wakeup(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) if (inited && !tty_throttled(tty) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) MoxaPortRxQueue(p) > 0) { /* RX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) MoxaPortReadData(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) tty_schedule_flip(&p->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) clear_bit(EMPTYWAIT, &p->statusflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) MoxaPortFlushData(p, 0); /* flush RX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) if (!handle) /* nothing else to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) goto put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) intr = readw(ip); /* port irq status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) if (intr == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) goto put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) writew(0, ip); /* ACK port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) ofsAddr = p->tableAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) if (intr & IntrTx) /* disable tx intr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) writew(readw(ofsAddr + HostStat) & ~WakeupTx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) ofsAddr + HostStat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) if (!inited)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) goto put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) if (tty && (intr & IntrBreak) && !I_IGNBRK(tty)) { /* BREAK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) tty_insert_flip_char(&p->port, 0, TTY_BREAK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) tty_schedule_flip(&p->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) if (intr & IntrLine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) tty_kref_put(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) static void moxa_poll(struct timer_list *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) struct moxa_board_conf *brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) u16 __iomem *ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) unsigned int card, port, served = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) spin_lock(&moxa_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) for (card = 0; card < MAX_BOARDS; card++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) brd = &moxa_boards[card];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) if (!brd->ready)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) served++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) ip = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) if (readb(brd->intPend) == 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) ip = brd->intTable + readb(brd->intNdx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) for (port = 0; port < brd->numPorts; port++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) moxa_poll_port(&brd->ports[port], !!ip, ip + port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) if (ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) writeb(0, brd->intPend); /* ACK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) if (moxaLowWaterChk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) struct moxa_port *p = brd->ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) for (port = 0; port < brd->numPorts; port++, p++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) if (p->lowChkFlag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) p->lowChkFlag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) moxa_low_water_check(p->tableAddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) moxaLowWaterChk = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) if (served)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) mod_timer(&moxaTimer, jiffies + HZ / 50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) spin_unlock(&moxa_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) /******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_termios)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) register struct ktermios *ts = &tty->termios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) struct moxa_port *ch = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) int rts, cts, txflow, rxflow, xany, baud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) rts = cts = txflow = rxflow = xany = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) if (ts->c_cflag & CRTSCTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) rts = cts = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) if (ts->c_iflag & IXON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) txflow = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) if (ts->c_iflag & IXOFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) rxflow = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) if (ts->c_iflag & IXANY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) xany = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) MoxaPortFlowCtrl(ch, rts, cts, txflow, rxflow, xany);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) baud = MoxaPortSetTermio(ch, ts, tty_get_baud_rate(tty));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) if (baud == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) baud = tty_termios_baud_rate(old_termios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) /* Not put the baud rate into the termios data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) tty_encode_baud_rate(tty, baud, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) /*****************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) * Driver level functions: *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) static void MoxaPortFlushData(struct moxa_port *port, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) void __iomem *ofsAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) if (mode < 0 || mode > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) ofsAddr = port->tableAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) moxafunc(ofsAddr, FC_FlushQueue, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) if (mode != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) port->lowChkFlag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) moxa_low_water_check(ofsAddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) * Moxa Port Number Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) * MOXA serial driver supports up to 4 MOXA-C218/C320 boards. And,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) * the port number using in MOXA driver functions will be 0 to 31 for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) * first MOXA board, 32 to 63 for second, 64 to 95 for third and 96
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) * to 127 for fourth. For example, if you setup three MOXA boards,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) * first board is C218, second board is C320-16 and third board is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) * C320-32. The port number of first board (C218 - 8 ports) is from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) * 0 to 7. The port number of second board (C320 - 16 ports) is form
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) * 32 to 47. The port number of third board (C320 - 32 ports) is from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) * 64 to 95. And those port numbers form 8 to 31, 48 to 63 and 96 to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) * 127 will be invalid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) * Moxa Functions Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) * Function 1: Driver initialization routine, this routine must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) * called when initialized driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) * void MoxaDriverInit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) * Function 2: Moxa driver private IOCTL command processing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) * int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) * unsigned int cmd : IOCTL command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) * unsigned long arg : IOCTL argument
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) * return: 0 (OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) * -EINVAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) * -ENOIOCTLCMD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) * Function 6: Enable this port to start Tx/Rx data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) * void MoxaPortEnable(int port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) * Function 7: Disable this port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) * void MoxaPortDisable(int port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) * Function 10: Setting baud rate of this port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) * speed_t MoxaPortSetBaud(int port, speed_t baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) * long baud : baud rate (50 - 115200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) * return: 0 : this port is invalid or baud < 50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) * 50 - 115200 : the real baud rate set to the port, if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) * the argument baud is large than maximun
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) * available baud rate, the real setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) * baud rate will be the maximun baud rate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) * Function 12: Configure the port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) * int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) * struct ktermios * termio : termio structure pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) * speed_t baud : baud rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) * return: -1 : this port is invalid or termio == NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) * 0 : setting O.K.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) * Function 13: Get the DTR/RTS state of this port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) * int MoxaPortGetLineOut(int port, int *dtrState, int *rtsState);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) * int * dtrState : pointer to INT to receive the current DTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) * state. (if NULL, this function will not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) * write to this address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) * int * rtsState : pointer to INT to receive the current RTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) * state. (if NULL, this function will not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) * write to this address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) * return: -1 : this port is invalid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) * 0 : O.K.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) * Function 14: Setting the DTR/RTS output state of this port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) * void MoxaPortLineCtrl(int port, int dtrState, int rtsState);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) * int dtrState : DTR output state (0: off, 1: on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) * int rtsState : RTS output state (0: off, 1: on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) * Function 15: Setting the flow control of this port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) * void MoxaPortFlowCtrl(int port, int rtsFlow, int ctsFlow, int rxFlow,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) * int txFlow,int xany);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) * int rtsFlow : H/W RTS flow control (0: no, 1: yes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) * int ctsFlow : H/W CTS flow control (0: no, 1: yes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) * int rxFlow : S/W Rx XON/XOFF flow control (0: no, 1: yes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) * int txFlow : S/W Tx XON/XOFF flow control (0: no, 1: yes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) * int xany : S/W XANY flow control (0: no, 1: yes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) * Function 16: Get ths line status of this port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) * int MoxaPortLineStatus(int port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) * return: Bit 0 - CTS state (0: off, 1: on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) * Bit 1 - DSR state (0: off, 1: on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) * Bit 2 - DCD state (0: off, 1: on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) * Function 19: Flush the Rx/Tx buffer data of this port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) * void MoxaPortFlushData(int port, int mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) * int mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) * 0 : flush the Rx buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) * 1 : flush the Tx buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) * 2 : flush the Rx and Tx buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) * Function 20: Write data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) * int MoxaPortWriteData(int port, unsigned char * buffer, int length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) * unsigned char * buffer : pointer to write data buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) * int length : write data length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) * return: 0 - length : real write data length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) * Function 21: Read data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) * int MoxaPortReadData(int port, struct tty_struct *tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) * struct tty_struct *tty : tty for data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) * return: 0 - length : real read data length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) * Function 24: Get the Tx buffer current queued data bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) * int MoxaPortTxQueue(int port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) * return: .. : Tx buffer current queued data bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) * Function 25: Get the Tx buffer current free space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) * int MoxaPortTxFree(int port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) * return: .. : Tx buffer current free space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) * Function 26: Get the Rx buffer current queued data bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) * int MoxaPortRxQueue(int port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) * return: .. : Rx buffer current queued data bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) * Function 28: Disable port data transmission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) * void MoxaPortTxDisable(int port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) * Function 29: Enable port data transmission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) * void MoxaPortTxEnable(int port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) * Function 31: Get the received BREAK signal count and reset it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) * Syntax:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) * int MoxaPortResetBrkCnt(int port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) * int port : port number (0 - 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) * return: 0 - .. : BREAK signal count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) static void MoxaPortEnable(struct moxa_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) void __iomem *ofsAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) u16 lowwater = 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) ofsAddr = port->tableAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) writew(lowwater, ofsAddr + Low_water);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) if (MOXA_IS_320(port->board))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) moxafunc(ofsAddr, FC_SetBreakIrq, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) writew(readw(ofsAddr + HostStat) | WakeupBreak,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) ofsAddr + HostStat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) moxafunc(ofsAddr, FC_SetLineIrq, Magic_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) moxafunc(ofsAddr, FC_FlushQueue, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) moxafunc(ofsAddr, FC_EnableCH, Magic_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) MoxaPortLineStatus(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) static void MoxaPortDisable(struct moxa_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) void __iomem *ofsAddr = port->tableAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) moxafunc(ofsAddr, FC_SetFlowCtl, 0); /* disable flow control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) writew(0, ofsAddr + HostStat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) moxafunc(ofsAddr, FC_DisableCH, Magic_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) static speed_t MoxaPortSetBaud(struct moxa_port *port, speed_t baud)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) void __iomem *ofsAddr = port->tableAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) unsigned int clock, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) speed_t max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) max = MOXA_IS_320(port->board) ? 460800 : 921600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) if (baud < 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) if (baud > max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) baud = max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) clock = 921600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) val = clock / baud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) moxafunc(ofsAddr, FC_SetBaud, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) baud = clock / val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) return baud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) speed_t baud)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) void __iomem *ofsAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) tcflag_t mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) ofsAddr = port->tableAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) mode = termio->c_cflag & CSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) if (mode == CS5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) mode = MX_CS5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) else if (mode == CS6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) mode = MX_CS6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) else if (mode == CS7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) mode = MX_CS7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) else if (mode == CS8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) mode = MX_CS8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) if (termio->c_cflag & CSTOPB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) if (mode == MX_CS5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) mode |= MX_STOP15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) mode |= MX_STOP2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) mode |= MX_STOP1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) if (termio->c_cflag & PARENB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) if (termio->c_cflag & PARODD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) if (termio->c_cflag & CMSPAR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) mode |= MX_PARMARK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) mode |= MX_PARODD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) if (termio->c_cflag & CMSPAR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) mode |= MX_PARSPACE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) mode |= MX_PAREVEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) mode |= MX_PARNONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) moxafunc(ofsAddr, FC_SetDataMode, (u16)mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) if (MOXA_IS_320(port->board) && baud >= 921600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) baud = MoxaPortSetBaud(port, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) if (termio->c_iflag & (IXON | IXOFF | IXANY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) spin_lock_irq(&moxafunc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) writeb(termio->c_cc[VSTART], ofsAddr + FuncArg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) writeb(FC_SetXonXoff, ofsAddr + FuncCode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) moxa_wait_finish(ofsAddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) spin_unlock_irq(&moxafunc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) return baud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) static int MoxaPortGetLineOut(struct moxa_port *port, int *dtrState,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) int *rtsState)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) if (dtrState)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) *dtrState = !!(port->lineCtrl & DTR_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) if (rtsState)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) *rtsState = !!(port->lineCtrl & RTS_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) static void MoxaPortLineCtrl(struct moxa_port *port, int dtr, int rts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) u8 mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) if (dtr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) mode |= DTR_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) if (rts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) mode |= RTS_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) port->lineCtrl = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) moxafunc(port->tableAddr, FC_LineControl, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) static void MoxaPortFlowCtrl(struct moxa_port *port, int rts, int cts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) int txflow, int rxflow, int txany)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) int mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) if (rts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) mode |= RTS_FlowCtl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) if (cts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) mode |= CTS_FlowCtl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) if (txflow)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) mode |= Tx_FlowCtl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) if (rxflow)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) mode |= Rx_FlowCtl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) if (txany)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) mode |= IXM_IXANY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) moxafunc(port->tableAddr, FC_SetFlowCtl, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) static int MoxaPortLineStatus(struct moxa_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) void __iomem *ofsAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) ofsAddr = port->tableAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) if (MOXA_IS_320(port->board))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) val = moxafuncret(ofsAddr, FC_LineStatus, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) val = readw(ofsAddr + FlagStat) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) val &= 0x0B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) if (val & 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) val |= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) moxa_new_dcdstate(port, val & 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) val &= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) static int MoxaPortWriteData(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) const unsigned char *buffer, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) struct moxa_port *port = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) void __iomem *baseAddr, *ofsAddr, *ofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) unsigned int c, total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) u16 head, tail, tx_mask, spage, epage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) u16 pageno, pageofs, bufhead;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) ofsAddr = port->tableAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) baseAddr = port->board->basemem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) tx_mask = readw(ofsAddr + TX_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) spage = readw(ofsAddr + Page_txb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) epage = readw(ofsAddr + EndPage_txb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) tail = readw(ofsAddr + TXwptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) head = readw(ofsAddr + TXrptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) c = (head > tail) ? (head - tail - 1) : (head - tail + tx_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) if (c > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) c = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) moxaLog.txcnt[port->port.tty->index] += c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) total = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) if (spage == epage) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) bufhead = readw(ofsAddr + Ofs_txb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) writew(spage, baseAddr + Control_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) while (c > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) if (head > tail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) len = head - tail - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) len = tx_mask + 1 - tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) len = (c > len) ? len : c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) ofs = baseAddr + DynPage_addr + bufhead + tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) memcpy_toio(ofs, buffer, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) buffer += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) tail = (tail + len) & tx_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) c -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) pageno = spage + (tail >> 13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) pageofs = tail & Page_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) while (c > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) len = Page_size - pageofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) if (len > c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) len = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) writeb(pageno, baseAddr + Control_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) ofs = baseAddr + DynPage_addr + pageofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) memcpy_toio(ofs, buffer, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) buffer += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) if (++pageno == epage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) pageno = spage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) pageofs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) c -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) tail = (tail + total) & tx_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) writew(tail, ofsAddr + TXwptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) writeb(1, ofsAddr + CD180TXirq); /* start to send */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) return total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) static int MoxaPortReadData(struct moxa_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) struct tty_struct *tty = port->port.tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) unsigned char *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) void __iomem *baseAddr, *ofsAddr, *ofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) unsigned int count, len, total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) u16 tail, rx_mask, spage, epage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) u16 pageno, pageofs, bufhead, head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) ofsAddr = port->tableAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) baseAddr = port->board->basemem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) head = readw(ofsAddr + RXrptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) tail = readw(ofsAddr + RXwptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) rx_mask = readw(ofsAddr + RX_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) spage = readw(ofsAddr + Page_rxb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) epage = readw(ofsAddr + EndPage_rxb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) count = (tail >= head) ? (tail - head) : (tail - head + rx_mask + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) if (count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) total = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) moxaLog.rxcnt[tty->index] += total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) if (spage == epage) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) bufhead = readw(ofsAddr + Ofs_rxb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) writew(spage, baseAddr + Control_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) while (count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) ofs = baseAddr + DynPage_addr + bufhead + head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) len = (tail >= head) ? (tail - head) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) (rx_mask + 1 - head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) len = tty_prepare_flip_string(&port->port, &dst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) min(len, count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) memcpy_fromio(dst, ofs, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) head = (head + len) & rx_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) count -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) pageno = spage + (head >> 13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) pageofs = head & Page_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) while (count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) writew(pageno, baseAddr + Control_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) ofs = baseAddr + DynPage_addr + pageofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) len = tty_prepare_flip_string(&port->port, &dst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) min(Page_size - pageofs, count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) memcpy_fromio(dst, ofs, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) count -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) pageofs = (pageofs + len) & Page_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) if (pageofs == 0 && ++pageno == epage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) pageno = spage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) head = (head + total) & rx_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) writew(head, ofsAddr + RXrptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) if (readb(ofsAddr + FlagStat) & Xoff_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) moxaLowWaterChk = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) port->lowChkFlag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) return total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) static int MoxaPortTxQueue(struct moxa_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) void __iomem *ofsAddr = port->tableAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) u16 rptr, wptr, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) rptr = readw(ofsAddr + TXrptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) wptr = readw(ofsAddr + TXwptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) mask = readw(ofsAddr + TX_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) return (wptr - rptr) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) static int MoxaPortTxFree(struct moxa_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) void __iomem *ofsAddr = port->tableAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) u16 rptr, wptr, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) rptr = readw(ofsAddr + TXrptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) wptr = readw(ofsAddr + TXwptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) mask = readw(ofsAddr + TX_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) return mask - ((wptr - rptr) & mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) static int MoxaPortRxQueue(struct moxa_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) void __iomem *ofsAddr = port->tableAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) u16 rptr, wptr, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) rptr = readw(ofsAddr + RXrptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) wptr = readw(ofsAddr + RXwptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) mask = readw(ofsAddr + RX_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) return (wptr - rptr) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) static void MoxaPortTxDisable(struct moxa_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) moxafunc(port->tableAddr, FC_SetXoffState, Magic_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) static void MoxaPortTxEnable(struct moxa_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) moxafunc(port->tableAddr, FC_SetXonState, Magic_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) static int moxa_get_serial_info(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) struct serial_struct *ss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) struct moxa_port *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) if (tty->index == MAX_PORTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) mutex_lock(&info->port.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) ss->type = info->type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) ss->line = info->port.tty->index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) ss->flags = info->port.flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) ss->baud_base = 921600,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) ss->close_delay = jiffies_to_msecs(info->port.close_delay) / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) mutex_unlock(&info->port.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) static int moxa_set_serial_info(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) struct serial_struct *ss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) struct moxa_port *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) unsigned int close_delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) if (tty->index == MAX_PORTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) if (ss->irq != 0 || ss->port != 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) ss->custom_divisor != 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) ss->baud_base != 921600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) close_delay = msecs_to_jiffies(ss->close_delay * 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) mutex_lock(&info->port.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) if (!capable(CAP_SYS_ADMIN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) if (close_delay != info->port.close_delay ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) ss->type != info->type ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) ((ss->flags & ~ASYNC_USR_MASK) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) (info->port.flags & ~ASYNC_USR_MASK))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) mutex_unlock(&info->port.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) info->port.close_delay = close_delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) MoxaSetFifo(info, ss->type == PORT_16550A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) info->type = ss->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) mutex_unlock(&info->port.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) /*****************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) * Static local functions: *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) static void MoxaSetFifo(struct moxa_port *port, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) void __iomem *ofsAddr = port->tableAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) if (!enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) moxafunc(ofsAddr, FC_SetTxFIFOCnt, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) moxafunc(ofsAddr, FC_SetRxFIFOTrig, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) }