moxa.c revision 33f0f88f1c51ae5c2d593d26960c760ea154c2e2
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           moxa.c  -- MOXA Intellio family multiport serial driver.
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Copyright (C) 1999-2000  Moxa Technologies (support@moxa.com.tw).
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      This code is loosely based on the Linux serial driver, written by
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Linus Torvalds, Theodore T'so and others.
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      This program is free software; you can redistribute it and/or modify
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      it under the terms of the GNU General Public License as published by
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      the Free Software Foundation; either version 2 of the License, or
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      (at your option) any later version.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      This program is distributed in the hope that it will be useful,
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      but WITHOUT ANY WARRANTY; without even the implied warranty of
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      GNU General Public License for more details.
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      You should have received a copy of the GNU General Public License
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      along with this program; if not, write to the Free Software
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    MOXA Intellio Series Driver
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      for             : LINUX
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      date            : 1999/1/7
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      version         : 5.1
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/config.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/signal.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h>
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h>
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_flip.h>
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/major.h>
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fcntl.h>
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ptrace.h>
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/serial.h>
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_driver.h>
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h>
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h>
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define		MOXA_VERSION		"5.1k"
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXAMAJOR       172
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXACUMAJOR     173
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define put_to_user(arg1, arg2) put_user(arg1, (unsigned long *)arg2)
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define get_from_user(arg1, arg2) get_user(arg1, (unsigned int *)arg2)
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_BOARDS 		4	/* Don't change this value */
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_PORTS_PER_BOARD	32	/* Don't change this value */
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_PORTS 		128	/* Don't change this value */
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Define the Moxa PCI vendor and device IDs.
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_BUS_TYPE_ISA		0
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_BUS_TYPE_PCI		1
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef	PCI_VENDOR_ID_MOXA
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	PCI_VENDOR_ID_MOXA	0x1393
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef PCI_DEVICE_ID_CP204J
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCI_DEVICE_ID_CP204J	0x2040
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef PCI_DEVICE_ID_C218
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCI_DEVICE_ID_C218	0x2180
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef PCI_DEVICE_ID_C320
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCI_DEVICE_ID_C320	0x3200
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum {
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MOXA_BOARD_C218_PCI = 1,
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MOXA_BOARD_C218_ISA,
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MOXA_BOARD_C320_PCI,
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MOXA_BOARD_C320_ISA,
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MOXA_BOARD_CP204J,
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *moxa_brdname[] =
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"C218 Turbo PCI series",
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"C218 Turbo ISA series",
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"C320 Turbo PCI series",
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"C320 Turbo ISA series",
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"CP-204J series",
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_device_id moxa_pcibrds[] = {
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C218, PCI_ANY_ID, PCI_ANY_ID,
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  0, 0, MOXA_BOARD_C218_PCI },
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C320, PCI_ANY_ID, PCI_ANY_ID,
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  0, 0, MOXA_BOARD_C320_PCI },
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP204J, PCI_ANY_ID, PCI_ANY_ID,
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  0, 0, MOXA_BOARD_CP204J },
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0 }
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, moxa_pcibrds);
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_PCI */
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct _moxa_isa_board_conf {
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int boardType;
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int numPorts;
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long baseAddr;
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} moxa_isa_board_conf;
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic moxa_isa_board_conf moxa_isa_boards[] =
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*       {MOXA_BOARD_C218_ISA,8,0xDC000}, */
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct _moxa_pci_devinfo {
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort busNum;
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort devNum;
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} moxa_pci_devinfo;
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct _moxa_board_conf {
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int boardType;
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int numPorts;
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long baseAddr;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int busType;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxa_pci_devinfo pciInfo;
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} moxa_board_conf;
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic moxa_board_conf moxa_boards[MAX_BOARDS];
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __iomem *moxaBaseAddr[MAX_BOARDS];
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct moxa_str {
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int type;
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int port;
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int close_delay;
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned short closing_wait;
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int count;
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int blocked_open;
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long event; /* long req'd for set_bit --RR */
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int asyncflags;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long statusflags;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tty_struct *tty;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int cflag;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wait_queue_head_t open_wait;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wait_queue_head_t close_wait;
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct work_struct tqueue;
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mxser_mstatus {
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tcflag_t cflag;
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int cts;
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int dsr;
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ri;
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int dcd;
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mxser_mstatus GMStatus[MAX_PORTS];
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* statusflags */
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXSTOPPED	0x1
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LOWWAIT 	0x2
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EMPTYWAIT	0x4
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define THROTTLE	0x8
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* event */
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_EVENT_HANGUP	1
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SERIAL_DO_RESTART
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SERIAL_TYPE_NORMAL	1
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WAKEUP_CHARS		256
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PORTNO(x)		((x)->index)
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int verbose = 0;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ttymajor = MOXAMAJOR;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Variables for insmod */
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int baseaddr[] 	= 	{0, 0, 0, 0};
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int type[]	=	{0, 0, 0, 0};
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int numports[] 	=	{0, 0, 0, 0};
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("William Chen");
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(type, int, NULL, 0);
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(baseaddr, int, NULL, 0);
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(numports, int, NULL, 0);
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(ttymajor, int, 0);
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(verbose, bool, 0644);
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct tty_driver *moxaDriver;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct moxa_str moxaChannels[MAX_PORTS];
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned char *moxaXmitBuff;
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaTimer_on;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct timer_list moxaTimer;
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaEmptyTimer_on[MAX_PORTS];
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct timer_list moxaEmptyTimer[MAX_PORTS];
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct semaphore moxaBuffSem;
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * static functions:
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void do_moxa_softint(void *);
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_open(struct tty_struct *, struct file *);
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_close(struct tty_struct *, struct file *);
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_write(struct tty_struct *, const unsigned char *, int);
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_write_room(struct tty_struct *);
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_flush_buffer(struct tty_struct *);
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_chars_in_buffer(struct tty_struct *);
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_flush_chars(struct tty_struct *);
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_put_char(struct tty_struct *, unsigned char);
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long);
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_throttle(struct tty_struct *);
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_unthrottle(struct tty_struct *);
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_set_termios(struct tty_struct *, struct termios *);
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_stop(struct tty_struct *);
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_start(struct tty_struct *);
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_hangup(struct tty_struct *);
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_tiocmget(struct tty_struct *tty, struct file *file);
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_tiocmset(struct tty_struct *tty, struct file *file,
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 unsigned int set, unsigned int clear);
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_poll(unsigned long);
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_tty_param(struct tty_struct *);
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int block_till_ready(struct tty_struct *, struct file *,
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    struct moxa_str *);
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void setup_empty_event(struct tty_struct *);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void check_xmit_empty(unsigned long);
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void shut_down(struct moxa_str *);
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void receive_data(struct moxa_str *);
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * moxa board interface functions:
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaDriverInit(void);
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaDriverIoctl(unsigned int, unsigned long, int);
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaDriverPoll(void);
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortsOfCard(int);
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortIsValid(int);
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaPortEnable(int);
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaPortDisable(int);
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic long MoxaPortGetMaxBaud(int);
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic long MoxaPortSetBaud(int, long);
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortSetTermio(int, struct termios *);
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortGetLineOut(int, int *, int *);
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaPortLineCtrl(int, int, int);
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaPortFlowCtrl(int, int, int, int, int, int);
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortLineStatus(int);
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortDCDChange(int);
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortDCDON(int);
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaPortFlushData(int, int);
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortWriteData(int, unsigned char *, int);
27233f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Coxstatic int MoxaPortReadData(int, struct tty_struct *tty);
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortTxQueue(int);
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortRxQueue(int);
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortTxFree(int);
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaPortTxDisable(int);
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaPortTxEnable(int);
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortResetBrkCnt(int);
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaPortSendBreak(int, int);
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_get_serial_info(struct moxa_str *, struct serial_struct __user *);
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_set_serial_info(struct moxa_str *, struct serial_struct __user *);
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaSetFifo(int port, int enable);
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct tty_operations moxa_ops = {
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.open = moxa_open,
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.close = moxa_close,
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.write = moxa_write,
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.write_room = moxa_write_room,
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.flush_buffer = moxa_flush_buffer,
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.chars_in_buffer = moxa_chars_in_buffer,
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.flush_chars = moxa_flush_chars,
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.put_char = moxa_put_char,
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ioctl = moxa_ioctl,
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.throttle = moxa_throttle,
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.unthrottle = moxa_unthrottle,
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.set_termios = moxa_set_termios,
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.stop = moxa_stop,
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.start = moxa_start,
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.hangup = moxa_hangup,
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.tiocmget = moxa_tiocmget,
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.tiocmset = moxa_tiocmset,
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30433f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Coxstatic spinlock_t moxa_lock = SPIN_LOCK_UNLOCKED;
30533f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf * board)
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	board->baseAddr = pci_resource_start (p, 2);
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	board->boardType = board_type;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (board_type) {
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_BOARD_C218_ISA:
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_BOARD_C218_PCI:
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		board->numPorts = 8;
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_BOARD_CP204J:
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		board->numPorts = 4;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		board->numPorts = 0;
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	board->busType = MOXA_BUS_TYPE_PCI;
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	board->pciInfo.busNum = p->bus->number;
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	board->pciInfo.devNum = p->devfn >> 3;
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_PCI */
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init moxa_init(void)
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, numBoards;
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch;
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "MOXA Intellio family driver version %s\n", MOXA_VERSION);
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaDriver = alloc_tty_driver(MAX_PORTS + 1);
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!moxaDriver)
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_MUTEX(&moxaBuffSem);
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaDriver->owner = THIS_MODULE;
3449b4e3b13b147e9b737de63188a9ae740eaa8c36dSergey Vlasov	moxaDriver->name = "ttyMX";
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaDriver->devfs_name = "tts/a";
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaDriver->major = ttymajor;
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaDriver->minor_start = 0;
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaDriver->type = TTY_DRIVER_TYPE_SERIAL;
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaDriver->subtype = SERIAL_TYPE_NORMAL;
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaDriver->init_termios = tty_std_termios;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaDriver->init_termios.c_iflag = 0;
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaDriver->init_termios.c_oflag = 0;
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaDriver->init_termios.c_lflag = 0;
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaDriver->flags = TTY_DRIVER_REAL_RAW;
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tty_set_operations(moxaDriver, &moxa_ops);
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaXmitBuff = NULL;
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0, ch = moxaChannels; i < MAX_PORTS; i++, ch++) {
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->type = PORT_16550A;
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->port = i;
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		INIT_WORK(&ch->tqueue, do_moxa_softint, ch);
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->tty = NULL;
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->close_delay = 5 * HZ / 10;
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->closing_wait = 30 * HZ;
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->count = 0;
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->blocked_open = 0;
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		init_waitqueue_head(&ch->open_wait);
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		init_waitqueue_head(&ch->close_wait);
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MAX_BOARDS; i++) {
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxa_boards[i].boardType = 0;
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxa_boards[i].numPorts = 0;
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxa_boards[i].baseAddr = 0;
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxa_boards[i].busType = 0;
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxa_boards[i].pciInfo.busNum = 0;
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxa_boards[i].pciInfo.devNum = 0;
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MoxaDriverInit();
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("Tty devices major number = %d\n", ttymajor);
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tty_register_driver(moxaDriver)) {
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "Couldn't install MOXA Smartio family driver !\n");
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_tty_driver(moxaDriver);
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MAX_PORTS; i++) {
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		init_timer(&moxaEmptyTimer[i]);
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaEmptyTimer[i].function = check_xmit_empty;
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaEmptyTimer[i].data = (unsigned long) & moxaChannels[i];
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaEmptyTimer_on[i] = 0;
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_timer(&moxaTimer);
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaTimer.function = moxa_poll;
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaTimer.expires = jiffies + (HZ / 50);
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaTimer_on = 1;
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	add_timer(&moxaTimer);
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Find the boards defined in source code */
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	numBoards = 0;
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MAX_BOARDS; i++) {
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA) ||
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 (moxa_isa_boards[i].boardType == MOXA_BOARD_C320_ISA)) {
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxa_boards[numBoards].boardType = moxa_isa_boards[i].boardType;
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA)
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				moxa_boards[numBoards].numPorts = 8;
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				moxa_boards[numBoards].numPorts = moxa_isa_boards[i].numPorts;
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA;
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxa_boards[numBoards].baseAddr = moxa_isa_boards[i].baseAddr;
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (verbose)
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk("Board %2d: %s board(baseAddr=%lx)\n",
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       numBoards + 1,
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       moxa_brdname[moxa_boards[numBoards].boardType - 1],
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       moxa_boards[numBoards].baseAddr);
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			numBoards++;
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Find the boards defined form module args. */
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MAX_BOARDS; i++) {
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((type[i] == MOXA_BOARD_C218_ISA) ||
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    (type[i] == MOXA_BOARD_C320_ISA)) {
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (verbose)
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk("Board %2d: %s board(baseAddr=%lx)\n",
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       numBoards + 1,
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       moxa_brdname[type[i] - 1],
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       (unsigned long) baseaddr[i]);
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (numBoards >= MAX_BOARDS) {
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (verbose)
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					printk("More than %d MOXA Intellio family boards found. Board is ignored.", MAX_BOARDS);
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxa_boards[numBoards].boardType = type[i];
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA)
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				moxa_boards[numBoards].numPorts = 8;
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				moxa_boards[numBoards].numPorts = numports[i];
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA;
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxa_boards[numBoards].baseAddr = baseaddr[i];
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			numBoards++;
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Find PCI boards here */
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct pci_dev *p = NULL;
453fe971071a89c5c5184fc9f3482c7a8e997cf0520Tobias Klauser		int n = ARRAY_SIZE(moxa_pcibrds) - 1;
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = 0;
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (i < n) {
456881a8c120acf7ec09c90289e2996b7c70f51e996Amit Gud			while ((p = pci_get_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL)
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			{
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (pci_enable_device(p))
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					continue;
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (numBoards >= MAX_BOARDS) {
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (verbose)
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						printk("More than %d MOXA Intellio family boards found. Board is ignored.", MAX_BOARDS);
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				} else {
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					moxa_get_PCI_conf(p, moxa_pcibrds[i].driver_data,
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						&moxa_boards[numBoards]);
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					numBoards++;
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			i++;
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < numBoards; i++) {
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaBaseAddr[i] = ioremap((unsigned long) moxa_boards[i].baseAddr, 0x4000);
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit moxa_exit(void)
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (verbose)
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("Unloading module moxa ...\n");
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (moxaTimer_on)
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		del_timer(&moxaTimer);
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MAX_PORTS; i++)
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (moxaEmptyTimer_on[i])
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			del_timer(&moxaEmptyTimer[i]);
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tty_unregister_driver(moxaDriver))
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("Couldn't unregister MOXA Intellio family serial driver\n");
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	put_tty_driver(moxaDriver);
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (verbose)
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("Done\n");
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(moxa_init);
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(moxa_exit);
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void do_moxa_softint(void *private_)
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch = (struct moxa_str *) private_;
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tty_struct *tty;
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ch && (tty = ch->tty)) {
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (test_and_clear_bit(MOXA_EVENT_HANGUP, &ch->event)) {
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tty_hangup(tty);	/* FIXME: module removal race here - AKPM */
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			wake_up_interruptible(&ch->open_wait);
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_open(struct tty_struct *tty, struct file *filp)
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch;
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int port;
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retval;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long page;
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	port = PORTNO(tty);
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (port == MAX_PORTS) {
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!MoxaPortIsValid(port)) {
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tty->driver_data = NULL;
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-ENODEV);
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&moxaBuffSem);
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!moxaXmitBuff) {
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		page = get_zeroed_page(GFP_KERNEL);
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!page) {
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			up(&moxaBuffSem);
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-ENOMEM);
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* This test is guarded by the BuffSem so no longer needed
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   delete me in 2.5 */
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (moxaXmitBuff)
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			free_page(page);
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxaXmitBuff = (unsigned char *) page;
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&moxaBuffSem);
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch = &moxaChannels[port];
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->count++;
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tty->driver_data = ch;
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->tty = tty;
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(ch->asyncflags & ASYNC_INITIALIZED)) {
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->statusflags = 0;
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_tty_param(tty);
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MoxaPortLineCtrl(ch->port, 1, 1);
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MoxaPortEnable(ch->port);
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->asyncflags |= ASYNC_INITIALIZED;
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	retval = block_till_ready(tty, filp, ch);
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxa_unthrottle(tty);
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ch->type == PORT_16550A) {
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MoxaSetFifo(ch->port, 1);
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MoxaSetFifo(ch->port, 0);
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (retval);
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_close(struct tty_struct *tty, struct file *filp)
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch;
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int port;
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	port = PORTNO(tty);
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (port == MAX_PORTS) {
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!MoxaPortIsValid(port)) {
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SERIAL_DEBUG_CLOSE
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("Invalid portno in moxa_close\n");
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tty->driver_data = NULL;
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tty->driver_data == NULL) {
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tty_hung_up_p(filp)) {
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch = (struct moxa_str *) tty->driver_data;
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((tty->count == 1) && (ch->count != 1)) {
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("moxa_close: bad serial port count; tty->count is 1, "
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       "ch->count is %d\n", ch->count);
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->count = 1;
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (--ch->count < 0) {
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("moxa_close: bad serial port count, device=%s\n",
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       tty->name);
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->count = 0;
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ch->count) {
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->asyncflags |= ASYNC_CLOSING;
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->cflag = tty->termios->c_cflag;
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ch->asyncflags & ASYNC_INITIALIZED) {
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		setup_empty_event(tty);
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tty_wait_until_sent(tty, 30 * HZ);	/* 30 seconds timeout */
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaEmptyTimer_on[ch->port] = 0;
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		del_timer(&moxaEmptyTimer[ch->port]);
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	shut_down(ch);
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MoxaPortFlushData(port, 2);
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tty->driver->flush_buffer)
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tty->driver->flush_buffer(tty);
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tty_ldisc_flush(tty);
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tty->closing = 0;
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->event = 0;
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->tty = NULL;
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ch->blocked_open) {
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ch->close_delay) {
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			msleep_interruptible(jiffies_to_msecs(ch->close_delay));
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wake_up_interruptible(&ch->open_wait);
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wake_up_interruptible(&ch->close_wait);
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_write(struct tty_struct *tty,
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      const unsigned char *buf, int count)
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch;
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len, port;
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch = (struct moxa_str *) tty->driver_data;
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ch == NULL)
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	port = ch->port;
65033f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox
65133f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	spin_lock_irqsave(&moxa_lock, flags);
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	len = MoxaPortWriteData(port, (unsigned char *) buf, count);
65333f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	spin_unlock_irqrestore(&moxa_lock, flags);
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*********************************************
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ( !(ch->statusflags & LOWWAIT) &&
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     ((len != count) || (MoxaPortTxFree(port) <= 100)) )
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	************************************************/
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->statusflags |= LOWWAIT;
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (len);
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_write_room(struct tty_struct *tty)
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch;
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tty->stopped)
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch = (struct moxa_str *) tty->driver_data;
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ch == NULL)
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (MoxaPortTxFree(ch->port));
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_flush_buffer(struct tty_struct *tty)
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ch == NULL)
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MoxaPortFlushData(ch->port, 1);
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tty_wakeup(tty);
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_chars_in_buffer(struct tty_struct *tty)
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int chars;
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Sigh...I have to check if driver_data is NULL here, because
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * if an open() fails, the TTY subsystem eventually calls
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * tty_wait_until_sent(), which calls the driver's chars_in_buffer()
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * routine.  And since the open() failed, we return 0 here.  TDJ
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ch == NULL)
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	chars = MoxaPortTxQueue(ch->port);
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chars) {
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Make it possible to wakeup anything waiting for output
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * in tty_ioctl.c, etc.
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(ch->statusflags & EMPTYWAIT))
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			setup_empty_event(tty);
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (chars);
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_flush_chars(struct tty_struct *tty)
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Don't think I need this, because this is called to empty the TX
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * buffer for the 16450, 16550, etc.
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_put_char(struct tty_struct *tty, unsigned char c)
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch;
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int port;
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch = (struct moxa_str *) tty->driver_data;
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ch == NULL)
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	port = ch->port;
72833f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	spin_lock_irqsave(&moxa_lock, flags);
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaXmitBuff[0] = c;
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MoxaPortWriteData(port, moxaXmitBuff, 1);
73133f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	spin_unlock_irqrestore(&moxa_lock, flags);
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/************************************************
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) )
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*************************************************/
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->statusflags |= LOWWAIT;
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_tiocmget(struct tty_struct *tty, struct file *file)
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int port;
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int flag = 0, dtr, rts;
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	port = PORTNO(tty);
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((port != MAX_PORTS) && (!ch))
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-EINVAL);
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MoxaPortGetLineOut(ch->port, &dtr, &rts);
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dtr)
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		flag |= TIOCM_DTR;
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rts)
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		flag |= TIOCM_RTS;
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dtr = MoxaPortLineStatus(ch->port);
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dtr & 1)
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		flag |= TIOCM_CTS;
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dtr & 2)
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		flag |= TIOCM_DSR;
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dtr & 4)
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		flag |= TIOCM_CD;
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return flag;
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_tiocmset(struct tty_struct *tty, struct file *file,
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 unsigned int set, unsigned int clear)
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int port;
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int dtr, rts;
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	port = PORTNO(tty);
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((port != MAX_PORTS) && (!ch))
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-EINVAL);
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MoxaPortGetLineOut(ch->port, &dtr, &rts);
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (set & TIOCM_RTS)
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rts = 1;
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (set & TIOCM_DTR)
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dtr = 1;
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (clear & TIOCM_RTS)
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rts = 0;
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (clear & TIOCM_DTR)
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dtr = 0;
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MoxaPortLineCtrl(ch->port, dtr, rts);
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_ioctl(struct tty_struct *tty, struct file *file,
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      unsigned int cmd, unsigned long arg)
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register int port;
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __user *argp = (void __user *)arg;
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retval;
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	port = PORTNO(tty);
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((port != MAX_PORTS) && (!ch))
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-EINVAL);
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case TCSBRK:		/* SVID version: non-zero arg --> no break */
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retval = tty_check_change(tty);
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (retval)
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (retval);
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		setup_empty_event(tty);
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tty_wait_until_sent(tty, 0);
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!arg)
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MoxaPortSendBreak(ch->port, 0);
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case TCSBRKP:		/* support for POSIX tcsendbreak() */
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retval = tty_check_change(tty);
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (retval)
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (retval);
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		setup_empty_event(tty);
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tty_wait_until_sent(tty, 0);
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MoxaPortSendBreak(ch->port, arg);
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case TIOCGSOFTCAR:
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) argp);
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case TIOCSSOFTCAR:
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(get_user(retval, (unsigned long __user *) argp))
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		arg = retval;
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 (arg ? CLOCAL : 0));
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (C_CLOCAL(tty))
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ch->asyncflags &= ~ASYNC_CHECK_CD;
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ch->asyncflags |= ASYNC_CHECK_CD;
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case TIOCGSERIAL:
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return moxa_get_serial_info(ch, argp);
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case TIOCSSERIAL:
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return moxa_set_serial_info(ch, argp);
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retval = MoxaDriverIoctl(cmd, arg, port);
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (retval);
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_throttle(struct tty_struct *tty)
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->statusflags |= THROTTLE;
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_unthrottle(struct tty_struct *tty)
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->statusflags &= ~THROTTLE;
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_set_termios(struct tty_struct *tty,
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     struct termios *old_termios)
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ch == NULL)
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_tty_param(tty);
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(old_termios->c_cflag & CLOCAL) &&
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (tty->termios->c_cflag & CLOCAL))
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wake_up_interruptible(&ch->open_wait);
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_stop(struct tty_struct *tty)
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ch == NULL)
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MoxaPortTxDisable(ch->port);
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->statusflags |= TXSTOPPED;
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_start(struct tty_struct *tty)
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ch == NULL)
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(ch->statusflags & TXSTOPPED))
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MoxaPortTxEnable(ch->port);
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->statusflags &= ~TXSTOPPED;
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_hangup(struct tty_struct *tty)
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxa_flush_buffer(tty);
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	shut_down(ch);
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->event = 0;
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->count = 0;
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->tty = NULL;
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wake_up_interruptible(&ch->open_wait);
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_poll(unsigned long ignored)
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register int card;
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch;
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tty_struct *tp;
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, ports;
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaTimer_on = 0;
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	del_timer(&moxaTimer);
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (MoxaDriverPoll() < 0) {
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaTimer.function = moxa_poll;
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaTimer.expires = jiffies + (HZ / 50);
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaTimer_on = 1;
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		add_timer(&moxaTimer);
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (card = 0; card < MAX_BOARDS; card++) {
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((ports = MoxaPortsOfCard(card)) <= 0)
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch = &moxaChannels[card * MAX_PORTS_PER_BOARD];
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < ports; i++, ch++) {
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((ch->asyncflags & ASYNC_INITIALIZED) == 0)
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(ch->statusflags & THROTTLE) &&
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    (MoxaPortRxQueue(ch->port) > 0))
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				receive_data(ch);
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((tp = ch->tty) == 0)
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ch->statusflags & LOWWAIT) {
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS) {
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (!tp->stopped) {
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						ch->statusflags &= ~LOWWAIT;
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						tty_wakeup(tp);
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!I_IGNBRK(tp) && (MoxaPortResetBrkCnt(ch->port) > 0)) {
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tty_insert_flip_char(tp, 0, TTY_BREAK);
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tty_schedule_flip(tp);
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (MoxaPortDCDChange(ch->port)) {
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (ch->asyncflags & ASYNC_CHECK_CD) {
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (MoxaPortDCDON(ch->port))
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						wake_up_interruptible(&ch->open_wait);
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					else {
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						set_bit(MOXA_EVENT_HANGUP, &ch->event);
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						schedule_work(&ch->tqueue);
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaTimer.function = moxa_poll;
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaTimer.expires = jiffies + (HZ / 50);
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaTimer_on = 1;
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	add_timer(&moxaTimer);
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************************/
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_tty_param(struct tty_struct *tty)
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register struct termios *ts;
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch;
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rts, cts, txflow, rxflow, xany;
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch = (struct moxa_str *) tty->driver_data;
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ts = tty->termios;
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ts->c_cflag & CLOCAL)
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->asyncflags &= ~ASYNC_CHECK_CD;
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->asyncflags |= ASYNC_CHECK_CD;
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rts = cts = txflow = rxflow = xany = 0;
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ts->c_cflag & CRTSCTS)
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rts = cts = 1;
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ts->c_iflag & IXON)
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		txflow = 1;
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ts->c_iflag & IXOFF)
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rxflow = 1;
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ts->c_iflag & IXANY)
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		xany = 1;
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MoxaPortFlowCtrl(ch->port, rts, cts, txflow, rxflow, xany);
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MoxaPortSetTermio(ch->port, ts);
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int block_till_ready(struct tty_struct *tty, struct file *filp,
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    struct moxa_str *ch)
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DECLARE_WAITQUEUE(wait,current);
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retval;
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int do_clocal = C_CLOCAL(tty);
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If the device is in the middle of being closed, then block
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * until it's done, and then try again.
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tty_hung_up_p(filp) || (ch->asyncflags & ASYNC_CLOSING)) {
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ch->asyncflags & ASYNC_CLOSING)
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			interruptible_sleep_on(&ch->close_wait);
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SERIAL_DO_RESTART
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ch->asyncflags & ASYNC_HUP_NOTIFY)
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-EAGAIN);
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-ERESTARTSYS);
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-EAGAIN);
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If non-blocking mode is set, then make the check up front
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * and then exit.
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (filp->f_flags & O_NONBLOCK) {
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Block waiting for the carrier detect and the line to become free
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	retval = 0;
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	add_wait_queue(&ch->open_wait, &wait);
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SERIAL_DEBUG_OPEN
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("block_til_ready before block: ttys%d, count = %d\n",
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       ch->line, ch->count);
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
103433f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	spin_lock_irqsave(&moxa_lock, flags);
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!tty_hung_up_p(filp))
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->count--;
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->blocked_open++;
103833f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	spin_unlock_irqrestore(&moxa_lock, flags);
103933f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (1) {
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_current_state(TASK_INTERRUPTIBLE);
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tty_hung_up_p(filp) ||
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    !(ch->asyncflags & ASYNC_INITIALIZED)) {
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SERIAL_DO_RESTART
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ch->asyncflags & ASYNC_HUP_NOTIFY)
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				retval = -EAGAIN;
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				retval = -ERESTARTSYS;
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			retval = -EAGAIN;
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(ch->asyncflags & ASYNC_CLOSING) && (do_clocal ||
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						MoxaPortDCDON(ch->port)))
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (signal_pending(current)) {
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			retval = -ERESTARTSYS;
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		schedule();
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_current_state(TASK_RUNNING);
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	remove_wait_queue(&ch->open_wait, &wait);
106633f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox
106733f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	spin_lock_irqsave(&moxa_lock, flags);
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!tty_hung_up_p(filp))
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->count++;
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->blocked_open--;
107133f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	spin_unlock_irqrestore(&moxa_lock, flags);
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SERIAL_DEBUG_OPEN
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("block_til_ready after blocking: ttys%d, count = %d\n",
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       ch->line, ch->count);
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval)
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (retval);
107833f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	/* FIXME: review to see if we need to use set_bit on these */
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
108033f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	return 0;
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void setup_empty_event(struct tty_struct *tty)
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch = tty->driver_data;
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
108833f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	spin_lock_irqsave(&moxa_lock, flags);
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->statusflags |= EMPTYWAIT;
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaEmptyTimer_on[ch->port] = 0;
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	del_timer(&moxaEmptyTimer[ch->port]);
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaEmptyTimer[ch->port].expires = jiffies + HZ;
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaEmptyTimer_on[ch->port] = 1;
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	add_timer(&moxaEmptyTimer[ch->port]);
109533f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	spin_unlock_irqrestore(&moxa_lock, flags);
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void check_xmit_empty(unsigned long data)
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch;
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch = (struct moxa_str *) data;
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaEmptyTimer_on[ch->port] = 0;
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	del_timer(&moxaEmptyTimer[ch->port]);
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ch->tty && (ch->statusflags & EMPTYWAIT)) {
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (MoxaPortTxQueue(ch->port) == 0) {
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ch->statusflags &= ~EMPTYWAIT;
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tty_wakeup(ch->tty);
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaEmptyTimer[ch->port].expires = jiffies + HZ;
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaEmptyTimer_on[ch->port] = 1;
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		add_timer(&moxaEmptyTimer[ch->port]);
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->statusflags &= ~EMPTYWAIT;
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void shut_down(struct moxa_str *ch)
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tty_struct *tp;
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(ch->asyncflags & ASYNC_INITIALIZED))
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tp = ch->tty;
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MoxaPortDisable(ch->port);
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If we're a modem control device and HUPCL is on, drop RTS & DTR.
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tp->termios->c_cflag & HUPCL)
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MoxaPortLineCtrl(ch->port, 0, 0);
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->asyncflags &= ~ASYNC_INITIALIZED;
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void receive_data(struct moxa_str *ch)
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tty_struct *tp;
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct termios *ts;
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ts = NULL;
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tp = ch->tty;
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tp)
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ts = tp->termios;
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/**************************************************
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ( !tp || !ts || !(ts->c_cflag & CREAD) ) {
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*****************************************************/
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!tp || !ts) {
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MoxaPortFlushData(ch->port, 0);
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
115533f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	spin_lock_irqsave(&moxa_lock, flags);
115633f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	MoxaPortReadData(ch->port, tp);
115733f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	spin_unlock_irqrestore(&moxa_lock, flags);
115833f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	tty_schedule_flip(tp);
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Magic_code	0x404
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    System Configuration
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    for C218 BIOS initialization
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218_ConfBase	0x800
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218_status	(C218_ConfBase + 0)	/* BIOS running status    */
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218_diag	(C218_ConfBase + 2)	/* diagnostic status      */
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218_key	(C218_ConfBase + 4)	/* WORD (0x218 for C218) */
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218DLoad_len	(C218_ConfBase + 6)	/* WORD           */
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218check_sum	(C218_ConfBase + 8)	/* BYTE           */
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218chksum_ok	(C218_ConfBase + 0x0a)	/* BYTE (1:ok)            */
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218_TestRx	(C218_ConfBase + 0x10)	/* 8 bytes for 8 ports    */
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218_TestTx	(C218_ConfBase + 0x18)	/* 8 bytes for 8 ports    */
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218_RXerr	(C218_ConfBase + 0x20)	/* 8 bytes for 8 ports    */
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218_ErrFlag	(C218_ConfBase + 0x28)	/* 8 bytes for 8 ports    */
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218_LoadBuf	0x0F00
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218_KeyCode	0x218
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CP204J_KeyCode	0x204
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    for C320 BIOS initialization
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320_ConfBase	0x800
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320_LoadBuf	0x0f00
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define STS_init	0x05	/* for C320_status        */
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320_status	C320_ConfBase + 0	/* BIOS running status    */
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320_diag	C320_ConfBase + 2	/* diagnostic status      */
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320_key	C320_ConfBase + 4	/* WORD (0320H for C320) */
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320DLoad_len	C320_ConfBase + 6	/* WORD           */
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320check_sum	C320_ConfBase + 8	/* WORD           */
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320chksum_ok	C320_ConfBase + 0x0a	/* WORD (1:ok)            */
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320bapi_len	C320_ConfBase + 0x0c	/* WORD           */
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320UART_no	C320_ConfBase + 0x0e	/* WORD           */
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320_KeyCode	0x320
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FixPage_addr	0x0000	/* starting addr of static page  */
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DynPage_addr	0x2000	/* starting addr of dynamic page */
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218_start	0x3000	/* starting addr of C218 BIOS prg */
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Control_reg	0x1ff0	/* select page and reset control */
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define HW_reset	0x80
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Function Codes
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_CardReset	0x80
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_ChannelReset 1	/* C320 firmware not supported */
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_EnableCH	2
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_DisableCH	3
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetParam	4
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetMode	5
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetRate	6
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_LineControl	7
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_LineStatus	8
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_XmitControl	9
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_FlushQueue	10
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SendBreak	11
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_StopBreak	12
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_LoopbackON	13
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_LoopbackOFF	14
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_ClrIrqTable	15
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SendXon	16
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetTermIrq	17	/* C320 firmware not supported */
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetCntIrq	18	/* C320 firmware not supported */
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetBreakIrq	19
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetLineIrq	20
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetFlowCtl	21
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_GenIrq	22
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_InCD180	23
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_OutCD180	24
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_InUARTreg	23
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_OutUARTreg	24
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetXonXoff	25
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_OutCD180CCR	26
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_ExtIQueue	27
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_ExtOQueue	28
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_ClrLineIrq	29
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_HWFlowCtl	30
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_GetClockRate 35
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetBaud	36
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetDataMode  41
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_GetCCSR      43
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_GetDataError 45
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_RxControl	50
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_ImmSend	51
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetXonState	52
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetXoffState	53
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetRxFIFOTrig 54
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetTxFIFOCnt 55
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_UnixRate	56
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_UnixResetTimer 57
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RxFIFOTrig1	0
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RxFIFOTrig4	1
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RxFIFOTrig8	2
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RxFIFOTrig14	3
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Dual-Ported RAM
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRAM_global	0
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INT_data	(DRAM_global + 0)
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Config_base	(DRAM_global + 0x108)
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IRQindex	(INT_data + 0)
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IRQpending	(INT_data + 4)
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IRQtable	(INT_data + 8)
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Interrupt Status
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IntrRx		0x01	/* receiver data O.K.             */
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IntrTx		0x02	/* transmit buffer empty  */
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IntrFunc	0x04	/* function complete              */
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IntrBreak	0x08	/* received break         */
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IntrLine	0x10	/* line status change
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   for transmitter                */
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IntrIntr	0x20	/* received INTR code             */
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IntrQuit	0x40	/* received QUIT code             */
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IntrEOF 	0x80	/* received EOF code              */
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IntrRxTrigger 	0x100	/* rx data count reach tigger value */
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IntrTxTrigger 	0x200	/* tx data count below trigger value */
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Magic_no	(Config_base + 0)
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Card_model_no	(Config_base + 2)
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Total_ports	(Config_base + 4)
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Module_cnt	(Config_base + 8)
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Module_no	(Config_base + 10)
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Timer_10ms	(Config_base + 14)
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Disable_IRQ	(Config_base + 20)
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMS320_PORT1	(Config_base + 22)
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMS320_PORT2	(Config_base + 24)
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMS320_CLOCK	(Config_base + 26)
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    DATA BUFFER in DRAM
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Extern_table	0x400	/* Base address of the external table
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   (24 words *    64) total 3K bytes
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   (24 words * 128) total 6K bytes */
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Extern_size	0x60	/* 96 bytes                       */
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RXrptr		0x00	/* read pointer for RX buffer     */
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RXwptr		0x02	/* write pointer for RX buffer    */
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXrptr		0x04	/* read pointer for TX buffer     */
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXwptr		0x06	/* write pointer for TX buffer    */
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define HostStat	0x08	/* IRQ flag and general flag      */
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FlagStat	0x0A
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FlowControl	0x0C	/* B7 B6 B5 B4 B3 B2 B1 B0              */
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					/*  x  x  x  x  |  |  |  |            */
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					/*              |  |  |  + CTS flow   */
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					/*              |  |  +--- RTS flow   */
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					/*              |  +------ TX Xon/Xoff */
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					/*              +--------- RX Xon/Xoff */
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Break_cnt	0x0E	/* received break count   */
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CD180TXirq	0x10	/* if non-0: enable TX irq        */
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_mask 	0x12
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_mask 	0x14
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Ofs_rxb 	0x16
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Ofs_txb 	0x18
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Page_rxb	0x1A
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Page_txb	0x1C
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EndPage_rxb	0x1E
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EndPage_txb	0x20
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Data_error	0x22
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RxTrigger	0x28
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TxTrigger	0x2a
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define rRXwptr 	0x34
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Low_water	0x36
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FuncCode	0x40
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FuncArg 	0x42
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FuncArg1	0x44
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218rx_size	0x2000	/* 8K bytes */
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218tx_size	0x8000	/* 32K bytes */
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218rx_mask	(C218rx_size - 1)
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218tx_mask	(C218tx_size - 1)
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8rx_size	0x2000
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8tx_size	0x8000
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8rx_mask	(C320p8rx_size - 1)
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8tx_mask	(C320p8tx_size - 1)
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p16rx_size	0x2000
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p16tx_size	0x4000
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p16rx_mask	(C320p16rx_size - 1)
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p16tx_mask	(C320p16tx_size - 1)
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p24rx_size	0x2000
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p24tx_size	0x2000
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p24rx_mask	(C320p24rx_size - 1)
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p24tx_mask	(C320p24tx_size - 1)
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p32rx_size	0x1000
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p32tx_size	0x1000
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p32rx_mask	(C320p32rx_size - 1)
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p32tx_mask	(C320p32tx_size - 1)
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Page_size	0x2000
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Page_mask	(Page_size - 1)
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218rx_spage	3
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218tx_spage	4
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218rx_pageno	1
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218tx_pageno	4
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218buf_pageno	5
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8rx_spage	3
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8tx_spage	4
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8rx_pgno	1
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8tx_pgno	4
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8buf_pgno	5
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p16rx_spage 3
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p16tx_spage 4
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p16rx_pgno	1
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p16tx_pgno	2
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p16buf_pgno 3
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p24rx_spage 3
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p24tx_spage 4
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p24rx_pgno	1
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p24tx_pgno	1
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p24buf_pgno 2
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p32rx_spage 3
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p32tx_ofs	C320p32rx_size
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p32tx_spage 3
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p32buf_pgno 1
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Host Status
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WakeupRx	0x01
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WakeupTx	0x02
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WakeupBreak	0x08
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WakeupLine	0x10
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WakeupIntr	0x20
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WakeupQuit	0x40
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WakeupEOF	0x80	/* used in VTIME control */
14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WakeupRxTrigger	0x100
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WakeupTxTrigger	0x200
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Flag status
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Rx_over		0x01
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Xoff_state	0x02
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Tx_flowOff	0x04
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Tx_enable	0x08
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CTS_state	0x10
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DSR_state	0x20
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DCD_state	0x80
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    FlowControl
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CTS_FlowCtl	1
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RTS_FlowCtl	2
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Tx_FlowCtl	4
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Rx_FlowCtl	8
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IXM_IXANY	0x10
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LowWater	128
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DTR_ON		1
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RTS_ON		2
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CTS_ON		1
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DSR_ON		2
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DCD_ON		8
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* mode definition */
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	MX_CS8		0x03
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	MX_CS7		0x02
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	MX_CS6		0x01
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	MX_CS5		0x00
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	MX_STOP1	0x00
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	MX_STOP15	0x04
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	MX_STOP2	0x08
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	MX_PARNONE	0x00
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	MX_PAREVEN	0x40
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	MX_PARODD	0xC0
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Query
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define QueryPort	MAX_PORTS
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mon_str {
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int tick;
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rxcnt[MAX_PORTS];
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int txcnt[MAX_PORTS];
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct mon_str mon_st;
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define 	DCD_changed	0x01
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define 	DCD_oldstate	0x80
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned char moxaBuff[10240];
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __iomem *moxaIntNdx[MAX_BOARDS];
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __iomem *moxaIntPend[MAX_BOARDS];
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __iomem *moxaIntTable[MAX_BOARDS];
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char moxaChkPort[MAX_PORTS];
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char moxaLineCtrl[MAX_PORTS];
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __iomem *moxaTableAddr[MAX_PORTS];
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic long moxaCurBaud[MAX_PORTS];
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char moxaDCDState[MAX_PORTS];
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char moxaLowChkFlag[MAX_PORTS];
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaLowWaterChk;
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaCard;
14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic mon_st moxaLog;
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaFuncTout;
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ushort moxaBreakCnt[MAX_PORTS];
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxadelay(int);
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxafunc(void __iomem *, int, ushort);
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void wait_finish(void __iomem *);
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void low_water_check(void __iomem *);
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaloadbios(int, unsigned char __user *, int);
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxafindcard(int);
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaload320b(int, unsigned char __user *, int);
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaloadcode(int, unsigned char __user *, int);
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaloadc218(int, void __iomem *, int);
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaloadc320(int, void __iomem *, int, int *);
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Driver level functions: 					     *
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	1. MoxaDriverInit(void);					     *
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	2. MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port);   *
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	3. MoxaDriverPoll(void);					     *
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaDriverInit(void)
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaFuncTout = HZ / 2;	/* 500 mini-seconds */
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaCard = 0;
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaLog.tick = 0;
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaLowWaterChk = 0;
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MAX_PORTS; i++) {
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaChkPort[i] = 0;
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaLowChkFlag[i] = 0;
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaLineCtrl[i] = 0;
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaLog.rxcnt[i] = 0;
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaLog.txcnt[i] = 0;
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	MOXA		0x400
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GET_IQUEUE 	(MOXA + 1)	/* get input buffered count */
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GET_OQUEUE 	(MOXA + 2)	/* get output buffered count */
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_INIT_DRIVER	(MOXA + 6)	/* moxaCard=0 */
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_LOAD_BIOS		(MOXA + 9)	/* download BIOS */
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_FIND_BOARD		(MOXA + 10)	/* Check if MOXA card exist? */
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_LOAD_C320B		(MOXA + 11)	/* download 320B firmware */
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_LOAD_CODE		(MOXA + 12)	/* download firmware */
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GETDATACOUNT       (MOXA + 23)
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GET_IOQUEUE	(MOXA + 27)
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_FLUSH_QUEUE	(MOXA + 28)
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GET_CONF		(MOXA + 35)	/* configuration */
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GET_MAJOR          (MOXA + 63)
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GET_CUMAJOR        (MOXA + 64)
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GETMSTATUS         (MOXA + 65)
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct moxaq_str {
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int inq;
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int outq;
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dl_str {
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char __user *buf;
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len;
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int cardno;
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct moxaq_str temp_queue[MAX_PORTS];
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dl_str dltmp;
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortFlushData(int port, int mode)
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((mode < 0) || (mode > 2))
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_FlushQueue, mode);
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mode != 1) {
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaLowChkFlag[port] = 0;
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		low_water_check(ofsAddr);
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port)
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int status;
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int MoxaPortTxQueue(int), MoxaPortRxQueue(int);
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __user *argp = (void __user *)arg;
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (port == QueryPort) {
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((cmd != MOXA_GET_CONF) && (cmd != MOXA_INIT_DRIVER) &&
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    (cmd != MOXA_LOAD_BIOS) && (cmd != MOXA_FIND_BOARD) && (cmd != MOXA_LOAD_C320B) &&
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 (cmd != MOXA_LOAD_CODE) && (cmd != MOXA_GETDATACOUNT) &&
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  (cmd != MOXA_GET_IOQUEUE) && (cmd != MOXA_GET_MAJOR) &&
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    (cmd != MOXA_GET_CUMAJOR) && (cmd != MOXA_GETMSTATUS))
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-EINVAL);
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_GET_CONF:
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(copy_to_user(argp, &moxa_boards, MAX_BOARDS * sizeof(moxa_board_conf)))
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_INIT_DRIVER:
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((int) arg == 0x404)
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MoxaDriverInit();
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_GETDATACOUNT:
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaLog.tick = jiffies;
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(copy_to_user(argp, &moxaLog, sizeof(mon_st)))
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_FLUSH_QUEUE:
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MoxaPortFlushData(port, arg);
15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_GET_IOQUEUE:
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < MAX_PORTS; i++) {
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (moxaChkPort[i]) {
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				temp_queue[i].inq = MoxaPortRxQueue(i);
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				temp_queue[i].outq = MoxaPortTxQueue(i);
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(copy_to_user(argp, temp_queue, sizeof(struct moxaq_str) * MAX_PORTS))
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_GET_OQUEUE:
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = MoxaPortTxQueue(port);
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return put_user(i, (unsigned long __user *)argp);
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_GET_IQUEUE:
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = MoxaPortRxQueue(port);
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return put_user(i, (unsigned long __user *)argp);
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_GET_MAJOR:
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(copy_to_user(argp, &ttymajor, sizeof(int)))
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_GET_CUMAJOR:
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = 0;
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(copy_to_user(argp, &i, sizeof(int)))
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_GETMSTATUS:
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < MAX_PORTS; i++) {
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			GMStatus[i].ri = 0;
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			GMStatus[i].dcd = 0;
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			GMStatus[i].dsr = 0;
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			GMStatus[i].cts = 0;
16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!moxaChkPort[i]) {
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				status = MoxaPortLineStatus(moxaChannels[i].port);
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (status & 1)
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					GMStatus[i].cts = 1;
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (status & 2)
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					GMStatus[i].dsr = 1;
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (status & 4)
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					GMStatus[i].dcd = 1;
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!moxaChannels[i].tty || !moxaChannels[i].tty->termios)
16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				GMStatus[i].cflag = moxaChannels[i].cflag;
16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				GMStatus[i].cflag = moxaChannels[i].tty->termios->c_cflag;
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(copy_to_user(argp, GMStatus, sizeof(struct mxser_mstatus) * MAX_PORTS))
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-ENOIOCTLCMD);
16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_LOAD_BIOS:
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_FIND_BOARD:
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_LOAD_C320B:
16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_LOAD_CODE:
16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(copy_from_user(&dltmp, argp, sizeof(struct dl_str)))
16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(dltmp.cardno < 0 || dltmp.cardno >= MAX_BOARDS)
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(cmd)
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_LOAD_BIOS:
16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = moxaloadbios(dltmp.cardno, dltmp.buf, dltmp.len);
16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (i);
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_FIND_BOARD:
16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return moxafindcard(dltmp.cardno);
16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_LOAD_C320B:
16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaload320b(dltmp.cardno, dltmp.buf, dltmp.len);
16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default: /* to keep gcc happy */
16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_LOAD_CODE:
16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = moxaloadcode(dltmp.cardno, dltmp.buf, dltmp.len);
16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i == -1)
16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-EFAULT);
16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (i);
16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaDriverPoll(void)
16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register ushort temp;
16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register int card;
16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ip;
16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int port, p, ports;
16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (moxaCard == 0)
16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-1);
16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (card = 0; card < MAX_BOARDS; card++) {
16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((ports = moxa_boards[card].numPorts) == 0)
16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (readb(moxaIntPend[card]) == 0xff) {
16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ip = moxaIntTable[card] + readb(moxaIntNdx[card]);
16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			p = card * MAX_PORTS_PER_BOARD;
16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ports <<= 1;
16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (port = 0; port < ports; port += 2, p++) {
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((temp = readw(ip + port)) != 0) {
16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					writew(0, ip + port);
17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ofsAddr = moxaTableAddr[p];
17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (temp & IntrTx)
17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						writew(readw(ofsAddr + HostStat) & ~WakeupTx, ofsAddr + HostStat);
17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (temp & IntrBreak) {
17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						moxaBreakCnt[p]++;
17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (temp & IntrLine) {
17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						if (readb(ofsAddr + FlagStat) & DCD_state) {
17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							if ((moxaDCDState[p] & DCD_oldstate) == 0)
17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds								moxaDCDState[p] = (DCD_oldstate |
17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds										   DCD_changed);
17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						} else {
17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							if (moxaDCDState[p] & DCD_oldstate)
17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds								moxaDCDState[p] = DCD_changed;
17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						}
17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			writeb(0, moxaIntPend[card]);
17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (moxaLowWaterChk) {
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			p = card * MAX_PORTS_PER_BOARD;
17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (port = 0; port < ports; port++, p++) {
17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (moxaLowChkFlag[p]) {
17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					moxaLowChkFlag[p] = 0;
17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ofsAddr = moxaTableAddr[p];
17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					low_water_check(ofsAddr);
17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaLowWaterChk = 0;
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************
17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Card level function:						     *
17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	1. MoxaPortsOfCard(int cardno); 				     *
17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/
17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortsOfCard(int cardno)
17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (moxa_boards[cardno].boardType == 0)
17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (moxa_boards[cardno].numPorts);
17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************
17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Port level functions:						     *
17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	1.  MoxaPortIsValid(int port);					     *
17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	2.  MoxaPortEnable(int port);					     *
17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	3.  MoxaPortDisable(int port);					     *
17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	4.  MoxaPortGetMaxBaud(int port);				     *
17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	5.  MoxaPortGetCurBaud(int port);				     *
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	6.  MoxaPortSetBaud(int port, long baud);			     *
17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	7.  MoxaPortSetMode(int port, int databit, int stopbit, int parity); *
17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	8.  MoxaPortSetTermio(int port, unsigned char *termio); 	     *
17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	9.  MoxaPortGetLineOut(int port, int *dtrState, int *rtsState);      *
17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	10. MoxaPortLineCtrl(int port, int dtrState, int rtsState);	     *
17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	11. MoxaPortFlowCtrl(int port, int rts, int cts, int rx, int tx,int xany);    *
17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	12. MoxaPortLineStatus(int port);				     *
17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	13. MoxaPortDCDChange(int port);				     *
17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	14. MoxaPortDCDON(int port);					     *
17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	15. MoxaPortFlushData(int port, int mode);	                     *
17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	16. MoxaPortWriteData(int port, unsigned char * buffer, int length); *
176533f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox *	17. MoxaPortReadData(int port, struct tty_struct *tty); 	     *
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	18. MoxaPortTxBufSize(int port);				     *
17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	19. MoxaPortRxBufSize(int port);				     *
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	20. MoxaPortTxQueue(int port);					     *
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	21. MoxaPortTxFree(int port);					     *
17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	22. MoxaPortRxQueue(int port);					     *
17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	23. MoxaPortRxFree(int port);					     *
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	24. MoxaPortTxDisable(int port);				     *
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	25. MoxaPortTxEnable(int port); 				     *
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	26. MoxaPortGetBrkCnt(int port);				     *
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	27. MoxaPortResetBrkCnt(int port);				     *
17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	28. MoxaPortSetXonXoff(int port, int xonValue, int xoffValue);	     *
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	29. MoxaPortIsTxHold(int port); 				     *
17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	30. MoxaPortSendBreak(int port, int ticks);			     *
17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/
17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Moxa Port Number Description:
17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      MOXA serial driver supports up to 4 MOXA-C218/C320 boards. And,
17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      the port number using in MOXA driver functions will be 0 to 31 for
17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      first MOXA board, 32 to 63 for second, 64 to 95 for third and 96
17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      to 127 for fourth. For example, if you setup three MOXA boards,
17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      first board is C218, second board is C320-16 and third board is
17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      C320-32. The port number of first board (C218 - 8 ports) is from
17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      0 to 7. The port number of second board (C320 - 16 ports) is form
17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      32 to 47. The port number of third board (C320 - 32 ports) is from
17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      64 to 95. And those port numbers form 8 to 31, 48 to 63 and 96 to
17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      127 will be invalid.
17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Moxa Functions Description:
17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 1:     Driver initialization routine, this routine must be
17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      called when initialized driver.
17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaDriverInit();
18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 2:     Moxa driver private IOCTL command processing.
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port);
18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           unsigned int cmd   : IOCTL command
18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           unsigned long arg  : IOCTL argument
18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0  (OK)
18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      -EINVAL
18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      -ENOIOCTLCMD
18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 3:     Moxa driver polling process routine.
18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaDriverPoll(void);
18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       ; polling O.K.
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      -1      : no any Moxa card.
18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 4:     Get the ports of this card.
18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortsOfCard(int cardno);
18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int cardno         : card number (0 - 3)
18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       : this card is invalid
18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      8/16/24/32
18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 5:     Check this port is valid or invalid
18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortIsValid(int port);
18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127, ref port description)
18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       : this port is invalid
18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      1       : this port is valid
18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 6:     Enable this port to start Tx/Rx data.
18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaPortEnable(int port);
18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 7:     Disable this port
18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaPortDisable(int port);
18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 8:     Get the maximun available baud rate of this port.
18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      long MoxaPortGetMaxBaud(int port);
18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       : this port is invalid
18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      38400/57600/115200 bps
18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 9:     Get the current baud rate of this port.
18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      long MoxaPortGetCurBaud(int port);
18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       : this port is invalid
18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      50 - 115200 bps
18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 10:    Setting baud rate of this port.
18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      long MoxaPortSetBaud(int port, long baud);
18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           long baud          : baud rate (50 - 115200)
18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       : this port is invalid or baud < 50
18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      50 - 115200 : the real baud rate set to the port, if
18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                    the argument baud is large than maximun
18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                    available baud rate, the real setting
18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                    baud rate will be the maximun baud rate.
18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 11:    Setting the data-bits/stop-bits/parity of this port
18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortSetMode(int port, int databits, int stopbits, int parity);
18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int databits       : data bits (8/7/6/5)
18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int stopbits       : stop bits (2/1/0, 0 show 1.5 stop bits)
18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int parity     : parity (0:None,1:Odd,2:Even,3:Mark,4:Space)
18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    -1      : invalid parameter
18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      0       : setting O.K.
18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 12:    Configure the port.
18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortSetTermio(int port, struct termios *termio);
19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           struct termios * termio : termio structure pointer
19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    -1      : this port is invalid or termio == NULL
19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      0       : setting O.K.
19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 13:    Get the DTR/RTS state of this port.
19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortGetLineOut(int port, int *dtrState, int *rtsState);
19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int * dtrState     : pointer to INT to receive the current DTR
19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                state. (if NULL, this function will not
19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                write to this address)
19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int * rtsState     : pointer to INT to receive the current RTS
19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                state. (if NULL, this function will not
19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                write to this address)
19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    -1      : this port is invalid
19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      0       : O.K.
19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 14:    Setting the DTR/RTS output state of this port.
19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaPortLineCtrl(int port, int dtrState, int rtsState);
19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int dtrState       : DTR output state (0: off, 1: on)
19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int rtsState       : RTS output state (0: off, 1: on)
19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 15:    Setting the flow control of this port.
19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaPortFlowCtrl(int port, int rtsFlow, int ctsFlow, int rxFlow,
19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                            int txFlow,int xany);
19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int rtsFlow        : H/W RTS flow control (0: no, 1: yes)
19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int ctsFlow        : H/W CTS flow control (0: no, 1: yes)
19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int rxFlow         : S/W Rx XON/XOFF flow control (0: no, 1: yes)
19391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int txFlow         : S/W Tx XON/XOFF flow control (0: no, 1: yes)
19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int xany           : S/W XANY flow control (0: no, 1: yes)
19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 16:    Get ths line status of this port
19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortLineStatus(int port);
19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    Bit 0 - CTS state (0: off, 1: on)
19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      Bit 1 - DSR state (0: off, 1: on)
19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      Bit 2 - DCD state (0: off, 1: on)
19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 17:    Check the DCD state has changed since the last read
19541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      of this function.
19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortDCDChange(int port);
19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       : no changed
19601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      1       : DCD has changed
19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 18:    Check ths current DCD state is ON or not.
19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
19651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortDCDON(int port);
19661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       : DCD off
19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      1       : DCD on
19701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 19:    Flush the Rx/Tx buffer data of this port.
19731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
19741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaPortFlushData(int port, int mode);
19751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int mode
19771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      0       : flush the Rx buffer
19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      1       : flush the Tx buffer
19791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      2       : flush the Rx and Tx buffer
19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 20:    Write data.
19831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortWriteData(int port, unsigned char * buffer, int length);
19851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           unsigned char * buffer     : pointer to write data buffer.
19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int length         : write data length
19881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0 - length      : real write data length
19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 21:    Read data.
19931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
199433f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox *      int  MoxaPortReadData(int port, struct tty_struct *tty);
19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
199633f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox *	     struct tty_struct *tty : tty for data
19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0 - length      : real read data length
19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 22:    Get the Tx buffer size of this port
20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortTxBufSize(int port);
20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    ..      : Tx buffer size
20071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 23:    Get the Rx buffer size of this port
20101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortRxBufSize(int port);
20121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    ..      : Rx buffer size
20151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 24:    Get the Tx buffer current queued data bytes
20181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortTxQueue(int port);
20201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    ..      : Tx buffer current queued data bytes
20231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 25:    Get the Tx buffer current free space
20261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortTxFree(int port);
20281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    ..      : Tx buffer current free space
20311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 26:    Get the Rx buffer current queued data bytes
20341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortRxQueue(int port);
20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    ..      : Rx buffer current queued data bytes
20391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 27:    Get the Rx buffer current free space
20421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortRxFree(int port);
20441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    ..      : Rx buffer current free space
20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 28:    Disable port data transmission.
20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaPortTxDisable(int port);
20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 29:    Enable port data transmission.
20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaPortTxEnable(int port);
20581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 30:    Get the received BREAK signal count.
20621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortGetBrkCnt(int port);
20641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0 - ..  : BREAK signal count
20671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 31:    Get the received BREAK signal count and reset it.
20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortResetBrkCnt(int port);
20721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0 - ..  : BREAK signal count
20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 32:    Set the S/W flow control new XON/XOFF value, default
20781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      XON is 0x11 & XOFF is 0x13.
20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaPortSetXonXoff(int port, int xonValue, int xoffValue);
20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int xonValue       : new XON value (0 - 255)
20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int xoffValue      : new XOFF value (0 - 255)
20841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 33:    Check this port's transmission is hold by remote site
20871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      because the flow control.
20881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortIsTxHold(int port);
20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       : normal
20931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      1       : hold by remote site
20941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 34:    Send out a BREAK signal.
20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaPortSendBreak(int port, int ms100);
20991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
21001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int ms100          : break signal time interval.
21011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                unit: 100 mini-second. if ms100 == 0, it will
21021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                send out a about 250 ms BREAK signal.
21031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortIsValid(int port)
21061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (moxaCard == 0)
21091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
21101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (moxaChkPort[port] == 0)
21111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
21121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (1);
21131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortEnable(int port)
21161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
21181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int MoxaPortLineStatus(int);
21191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short lowwater = 512;
21201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
21221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(lowwater, ofsAddr + Low_water);
21231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaBreakCnt[port] = 0;
21241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
21251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
21261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxafunc(ofsAddr, FC_SetBreakIrq, 0);
21271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
21281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(readw(ofsAddr + HostStat) | WakeupBreak, ofsAddr + HostStat);
21291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_SetLineIrq, Magic_code);
21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_FlushQueue, 2);
21331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_EnableCH, Magic_code);
21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MoxaPortLineStatus(port);
21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortDisable(int port)
21391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr = moxaTableAddr[port];
21411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_SetFlowCtl, 0);	/* disable flow control */
21431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code);
21441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(0, ofsAddr + HostStat);
21451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_DisableCH, Magic_code);
21461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslong MoxaPortGetMaxBaud(int port)
21491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI))
21521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (460800L);
21531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
21541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (921600L);
21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslong MoxaPortSetBaud(int port, long baud)
21591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
21611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long max, clock;
21621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int val;
21631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((baud < 50L) || ((max = MoxaPortGetMaxBaud(port)) == 0))
21651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
21661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (baud > max)
21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = max;
21691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (max == 38400L)
21701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		clock = 614400L;	/* for 9.8304 Mhz : max. 38400 bps */
21711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if (max == 57600L)
21721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		clock = 691200L;	/* for 11.0592 Mhz : max. 57600 bps */
21731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
21741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		clock = 921600L;	/* for 14.7456 Mhz : max. 115200 bps */
21751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = clock / baud;
21761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_SetBaud, val);
21771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	baud = clock / val;
21781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaCurBaud[port] = baud;
21791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (baud);
21801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortSetTermio(int port, struct termios *termio)
21831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
21851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tcflag_t cflag;
21861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long baud;
21871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tcflag_t mode = 0;
21881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (moxaChkPort[port] == 0 || termio == 0)
21901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-1);
21911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
21921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cflag = termio->c_cflag;	/* termio->c_cflag */
21931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mode = termio->c_cflag & CSIZE;
21951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mode == CS5)
21961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode = MX_CS5;
21971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if (mode == CS6)
21981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode = MX_CS6;
21991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if (mode == CS7)
22001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode = MX_CS7;
22011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if (mode == CS8)
22021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode = MX_CS8;
22031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (termio->c_cflag & CSTOPB) {
22051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mode == MX_CS5)
22061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mode |= MX_STOP15;
22071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
22081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mode |= MX_STOP2;
22091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
22101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode |= MX_STOP1;
22111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (termio->c_cflag & PARENB) {
22131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (termio->c_cflag & PARODD)
22141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mode |= MX_PARODD;
22151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
22161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mode |= MX_PAREVEN;
22171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode |= MX_PARNONE;
22191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_SetDataMode, (ushort) mode);
22211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cflag &= (CBAUD | CBAUDEX);
22231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef B921600
22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	B921600	(B460800+1)
22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
22261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cflag) {
22271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B921600:
22281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 921600L;
22291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B460800:
22311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 460800L;
22321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B230400:
22341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 230400L;
22351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B115200:
22371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 115200L;
22381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B57600:
22401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 57600L;
22411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B38400:
22431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 38400L;
22441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B19200:
22461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 19200L;
22471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B9600:
22491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 9600L;
22501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B4800:
22521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 4800L;
22531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B2400:
22551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 2400L;
22561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B1800:
22581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 1800L;
22591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B1200:
22611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 1200L;
22621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B600:
22641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 600L;
22651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B300:
22671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 300L;
22681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B200:
22701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 200L;
22711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B150:
22731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 150L;
22741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B134:
22761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 134L;
22771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B110:
22791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 110L;
22801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B75:
22821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 75L;
22831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case B50:
22851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 50L;
22861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
22881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		baud = 0;
22891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
22901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
22911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
22921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (baud == 921600L)
22931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-1);
22941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
22951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MoxaPortSetBaud(port, baud);
22961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (termio->c_iflag & (IXON | IXOFF | IXANY)) {
22981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writeb(termio->c_cc[VSTART], ofsAddr + FuncArg);
22991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1);
23001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writeb(FC_SetXonXoff, ofsAddr + FuncCode);
23011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wait_finish(ofsAddr);
23021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
23041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
23051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
23061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortGetLineOut(int port, int *dtrState, int *rtsState)
23081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
23091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!MoxaPortIsValid(port))
23111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-1);
23121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dtrState) {
23131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (moxaLineCtrl[port] & DTR_ON)
23141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*dtrState = 1;
23151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
23161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*dtrState = 0;
23171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
23181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rtsState) {
23191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (moxaLineCtrl[port] & RTS_ON)
23201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*rtsState = 1;
23211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
23221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*rtsState = 0;
23231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
23241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
23251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
23261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortLineCtrl(int port, int dtr, int rts)
23281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
23291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
23301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int mode;
23311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
23331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mode = 0;
23341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dtr)
23351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode |= DTR_ON;
23361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rts)
23371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode |= RTS_ON;
23381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaLineCtrl[port] = mode;
23391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_LineControl, mode);
23401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
23411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortFlowCtrl(int port, int rts, int cts, int txflow, int rxflow, int txany)
23431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
23441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
23451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int mode;
23461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
23481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mode = 0;
23491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rts)
23501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode |= RTS_FlowCtl;
23511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cts)
23521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode |= CTS_FlowCtl;
23531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (txflow)
23541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode |= Tx_FlowCtl;
23551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rxflow)
23561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode |= Rx_FlowCtl;
23571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (txany)
23581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode |= IXM_IXANY;
23591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_SetFlowCtl, mode);
23601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
23611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortLineStatus(int port)
23631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
23641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
23651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val;
23661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
23681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
23691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
23701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxafunc(ofsAddr, FC_LineStatus, 0);
23711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val = readw(ofsAddr + FuncArg);
23721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
23731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val = readw(ofsAddr + FlagStat) >> 4;
23741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
23751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val &= 0x0B;
23761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (val & 8) {
23771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= 4;
23781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((moxaDCDState[port] & DCD_oldstate) == 0)
23791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxaDCDState[port] = (DCD_oldstate | DCD_changed);
23801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
23811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (moxaDCDState[port] & DCD_oldstate)
23821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxaDCDState[port] = DCD_changed;
23831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
23841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val &= 7;
23851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (val);
23861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
23871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortDCDChange(int port)
23891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
23901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int n;
23911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (moxaChkPort[port] == 0)
23931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
23941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	n = moxaDCDState[port];
23951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaDCDState[port] &= ~DCD_changed;
23961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	n &= DCD_changed;
23971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (n);
23981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
23991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortDCDON(int port)
24011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int n;
24031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (moxaChkPort[port] == 0)
24051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
24061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (moxaDCDState[port] & DCD_oldstate)
24071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		n = 1;
24081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
24091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		n = 0;
24101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (n);
24111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
24151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   int MoxaDumpMem(int port, unsigned char * buffer, int len)
24161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   {
24171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   int          i;
24181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   unsigned long                baseAddr,ofsAddr,ofs;
24191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD];
24211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   ofs = baseAddr + DynPage_addr + pageofs;
24221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   if (len > 0x2000L)
24231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   len = 0x2000L;
24241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   for (i = 0; i < len; i++)
24251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   buffer[i] = readb(ofs+i);
24261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   }
24271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
24281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortWriteData(int port, unsigned char * buffer, int len)
24311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int c, total, i;
24331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort tail;
24341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int cnt;
24351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort head, tx_mask, spage, epage;
24361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort pageno, pageofs, bufhead;
24371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *baseAddr, *ofsAddr, *ofs;
24381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
24401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD];
24411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tx_mask = readw(ofsAddr + TX_mask);
24421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spage = readw(ofsAddr + Page_txb);
24431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epage = readw(ofsAddr + EndPage_txb);
24441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tail = readw(ofsAddr + TXwptr);
24451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	head = readw(ofsAddr + TXrptr);
24461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	c = (head > tail) ? (head - tail - 1)
24471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    : (head - tail + tx_mask);
24481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (c > len)
24491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		c = len;
24501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaLog.txcnt[port] += c;
24511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	total = c;
24521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (spage == epage) {
24531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bufhead = readw(ofsAddr + Ofs_txb);
24541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(spage, baseAddr + Control_reg);
24551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (c > 0) {
24561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (head > tail)
24571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				len = head - tail - 1;
24581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
24591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				len = tx_mask + 1 - tail;
24601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			len = (c > len) ? len : c;
24611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ofs = baseAddr + DynPage_addr + bufhead + tail;
24621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (i = 0; i < len; i++)
24631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writeb(*buffer++, ofs + i);
24641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tail = (tail + len) & tx_mask;
24651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			c -= len;
24661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
24671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(tail, ofsAddr + TXwptr);
24681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
24691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len = c;
24701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pageno = spage + (tail >> 13);
24711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pageofs = tail & Page_mask;
24721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do {
24731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cnt = Page_size - pageofs;
24741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cnt > c)
24751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				cnt = c;
24761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			c -= cnt;
24771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			writeb(pageno, baseAddr + Control_reg);
24781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ofs = baseAddr + DynPage_addr + pageofs;
24791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (i = 0; i < cnt; i++)
24801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writeb(*buffer++, ofs + i);
24811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (c == 0) {
24821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew((tail + len) & tx_mask, ofsAddr + TXwptr);
24831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
24841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
24851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (++pageno == epage)
24861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pageno = spage;
24871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pageofs = 0;
24881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} while (1);
24891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
24901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writeb(1, ofsAddr + CD180TXirq);	/* start to send */
24911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (total);
24921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
249433f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Coxint MoxaPortReadData(int port, struct tty_struct *tty)
24951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register ushort head, pageofs;
24971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, count, cnt, len, total, remain;
24981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort tail, rx_mask, spage, epage;
24991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort pageno, bufhead;
25001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *baseAddr, *ofsAddr, *ofs;
25011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
25031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD];
25041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	head = readw(ofsAddr + RXrptr);
25051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tail = readw(ofsAddr + RXwptr);
25061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rx_mask = readw(ofsAddr + RX_mask);
25071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spage = readw(ofsAddr + Page_rxb);
25081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epage = readw(ofsAddr + EndPage_rxb);
25091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = (tail >= head) ? (tail - head)
25101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    : (tail - head + rx_mask + 1);
25111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count == 0)
251233f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox		return 0;
25131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251433f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	total = count;
25151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	remain = count - total;
25161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaLog.rxcnt[port] += total;
25171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = total;
25181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (spage == epage) {
25191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bufhead = readw(ofsAddr + Ofs_rxb);
25201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(spage, baseAddr + Control_reg);
25211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (count > 0) {
25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (tail >= head)
25231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				len = tail - head;
25241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
25251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				len = rx_mask + 1 - head;
25261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			len = (count > len) ? len : count;
25271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ofs = baseAddr + DynPage_addr + bufhead + head;
25281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (i = 0; i < len; i++)
252933f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox				tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL);
25301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			head = (head + len) & rx_mask;
25311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			count -= len;
25321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
25331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(head, ofsAddr + RXrptr);
25341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
25351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len = count;
25361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pageno = spage + (head >> 13);
25371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pageofs = head & Page_mask;
25381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do {
25391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cnt = Page_size - pageofs;
25401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cnt > count)
25411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				cnt = count;
25421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			count -= cnt;
25431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			writew(pageno, baseAddr + Control_reg);
25441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ofs = baseAddr + DynPage_addr + pageofs;
25451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (i = 0; i < cnt; i++)
254633f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox				tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL);
25471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (count == 0) {
25481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew((head + len) & rx_mask, ofsAddr + RXrptr);
25491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
25501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
25511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (++pageno == epage)
25521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pageno = spage;
25531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pageofs = 0;
25541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} while (1);
25551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
25561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((readb(ofsAddr + FlagStat) & Xoff_state) && (remain < LowWater)) {
25571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaLowWaterChk = 1;
25581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaLowChkFlag[port] = 1;
25591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
25601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (total);
25611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortTxQueue(int port)
25651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
25671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort rptr, wptr, mask;
25681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len;
25691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
25711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rptr = readw(ofsAddr + TXrptr);
25721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wptr = readw(ofsAddr + TXwptr);
25731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = readw(ofsAddr + TX_mask);
25741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	len = (wptr - rptr) & mask;
25751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (len);
25761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortTxFree(int port)
25791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
25811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort rptr, wptr, mask;
25821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len;
25831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
25851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rptr = readw(ofsAddr + TXrptr);
25861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wptr = readw(ofsAddr + TXwptr);
25871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = readw(ofsAddr + TX_mask);
25881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	len = mask - ((wptr - rptr) & mask);
25891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (len);
25901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortRxQueue(int port)
25931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
25951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort rptr, wptr, mask;
25961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len;
25971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
25991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rptr = readw(ofsAddr + RXrptr);
26001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wptr = readw(ofsAddr + RXwptr);
26011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = readw(ofsAddr + RX_mask);
26021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	len = (wptr - rptr) & mask;
26031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (len);
26041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
26051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortTxDisable(int port)
26081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
26091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
26101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
26121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_SetXoffState, Magic_code);
26131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
26141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortTxEnable(int port)
26161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
26171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
26181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
26201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_SetXonState, Magic_code);
26211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
26221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortResetBrkCnt(int port)
26251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
26261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort cnt;
26271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cnt = moxaBreakCnt[port];
26281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaBreakCnt[port] = 0;
26291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (cnt);
26301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
26311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortSendBreak(int port, int ms100)
26341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
26351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
26361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
26381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ms100) {
26391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxafunc(ofsAddr, FC_SendBreak, Magic_code);
26401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxadelay(ms100 * (HZ / 10));
26411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
26421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxafunc(ofsAddr, FC_SendBreak, Magic_code);
26431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxadelay(HZ / 4);	/* 250 ms */
26441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
26451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_StopBreak, Magic_code);
26461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
26471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_get_serial_info(struct moxa_str *info,
26491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				struct serial_struct __user *retinfo)
26501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
26511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct serial_struct tmp;
26521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(&tmp, 0, sizeof(tmp));
26541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp.type = info->type;
26551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp.line = info->port;
26561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp.port = 0;
26571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp.irq = 0;
26581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp.flags = info->asyncflags;
26591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp.baud_base = 921600;
26601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp.close_delay = info->close_delay;
26611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp.closing_wait = info->closing_wait;
26621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp.custom_divisor = 0;
26631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp.hub6 = 0;
26641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
26651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
26661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
26671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
26681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_set_serial_info(struct moxa_str *info,
26711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				struct serial_struct __user *new_info)
26721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
26731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct serial_struct new_serial;
26741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(copy_from_user(&new_serial, new_info, sizeof(new_serial)))
26761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
26771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((new_serial.irq != 0) ||
26791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (new_serial.port != 0) ||
26801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds//           (new_serial.type != info->type) ||
26811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (new_serial.custom_divisor != 0) ||
26821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (new_serial.baud_base != 921600))
26831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-EPERM);
26841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!capable(CAP_SYS_ADMIN)) {
26861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (((new_serial.flags & ~ASYNC_USR_MASK) !=
26871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     (info->asyncflags & ~ASYNC_USR_MASK)))
26881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-EPERM);
26891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
26901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		info->close_delay = new_serial.close_delay * HZ / 100;
26911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		info->closing_wait = new_serial.closing_wait * HZ / 100;
26921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
26931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_serial.flags = (new_serial.flags & ~ASYNC_FLAGS);
26951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_serial.flags |= (info->asyncflags & ASYNC_FLAGS);
26961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (new_serial.type == PORT_16550A) {
26981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MoxaSetFifo(info->port, 1);
26991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
27001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MoxaSetFifo(info->port, 0);
27011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
27021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info->type = new_serial.type;
27041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
27051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************
27101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Static local functions: 					     *
27111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/
27121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
27131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * moxadelay - delays a specified number ticks
27141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
27151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxadelay(int tick)
27161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long st, et;
27181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st = jiffies;
27201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	et = st + tick;
27211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (time_before(jiffies, et));
27221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxafunc(void __iomem *ofsAddr, int cmd, ushort arg)
27251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(arg, ofsAddr + FuncArg);
27281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(cmd, ofsAddr + FuncCode);
27291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wait_finish(ofsAddr);
27301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void wait_finish(void __iomem *ofsAddr)
27331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long i, j;
27351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = jiffies;
27371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (readw(ofsAddr + FuncCode) != 0) {
27381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		j = jiffies;
27391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((j - i) > moxaFuncTout) {
27401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
27411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
27421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
27431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void low_water_check(void __iomem *ofsAddr)
27461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len;
27481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort rptr, wptr, mask;
27491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (readb(ofsAddr + FlagStat) & Xoff_state) {
27511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rptr = readw(ofsAddr + RXrptr);
27521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wptr = readw(ofsAddr + RXwptr);
27531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask = readw(ofsAddr + RX_mask);
27541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len = (wptr - rptr) & mask;
27551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (len <= Low_water)
27561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxafunc(ofsAddr, FC_SendXon, 0);
27571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
27581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaloadbios(int cardno, unsigned char __user *tmp, int len)
27611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *baseAddr;
27631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
27641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(copy_from_user(moxaBuff, tmp, len))
27661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
27671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	baseAddr = moxaBaseAddr[cardno];
27681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writeb(HW_reset, baseAddr + Control_reg);	/* reset */
27691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxadelay(1);		/* delay 10 ms */
27701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 4096; i++)
27711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writeb(0, baseAddr + i);	/* clear fix page */
27721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < len; i++)
27731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writeb(moxaBuff[i], baseAddr + i);	/* download BIOS */
27741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writeb(0, baseAddr + Control_reg);	/* restart */
27751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
27761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxafindcard(int cardno)
27791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *baseAddr;
27811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort tmp;
27821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	baseAddr = moxaBaseAddr[cardno];
27841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (moxa_boards[cardno].boardType) {
27851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_BOARD_C218_ISA:
27861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_BOARD_C218_PCI:
27871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((tmp = readw(baseAddr + C218_key)) != C218_KeyCode) {
27881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-1);
27891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
27901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
27911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_BOARD_CP204J:
27921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((tmp = readw(baseAddr + C218_key)) != CP204J_KeyCode) {
27931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-1);
27941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
27951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
27961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
27971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((tmp = readw(baseAddr + C320_key)) != C320_KeyCode) {
27981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-1);
27991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
28001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((tmp = readw(baseAddr + C320_status)) != STS_init) {
28011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-2);
28021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
28031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
28041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
28051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
28061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaload320b(int cardno, unsigned char __user *tmp, int len)
28081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
28091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *baseAddr;
28101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
28111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(len > sizeof(moxaBuff))
28131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
28141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(copy_from_user(moxaBuff, tmp, len))
28151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
28161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	baseAddr = moxaBaseAddr[cardno];
28171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(len - 7168 - 2, baseAddr + C320bapi_len);
28181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writeb(1, baseAddr + Control_reg);	/* Select Page 1 */
28191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 7168; i++)
28201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writeb(moxaBuff[i], baseAddr + DynPage_addr + i);
28211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writeb(2, baseAddr + Control_reg);	/* Select Page 2 */
28221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < (len - 7168); i++)
28231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writeb(moxaBuff[i + 7168], baseAddr + DynPage_addr + i);
28241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
28251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
28261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaloadcode(int cardno, unsigned char __user *tmp, int len)
28281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
28291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *baseAddr, *ofsAddr;
28301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retval, port, i;
28311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(copy_from_user(moxaBuff, tmp, len))
28331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
28341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	baseAddr = moxaBaseAddr[cardno];
28351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (moxa_boards[cardno].boardType) {
28361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_BOARD_C218_ISA:
28371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_BOARD_C218_PCI:
28381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_BOARD_CP204J:
28391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retval = moxaloadc218(cardno, baseAddr, len);
28401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (retval)
28411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (retval);
28421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		port = cardno * MAX_PORTS_PER_BOARD;
28431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) {
28441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxaChkPort[port] = 1;
28451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxaCurBaud[port] = 9600L;
28461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxaDCDState[port] = 0;
28471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxaTableAddr[port] = baseAddr + Extern_table + Extern_size * i;
28481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ofsAddr = moxaTableAddr[port];
28491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			writew(C218rx_mask, ofsAddr + RX_mask);
28501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			writew(C218tx_mask, ofsAddr + TX_mask);
28511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb);
28521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb);
28531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb);
28551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb);
28561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
28581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
28591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
28601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retval = moxaloadc320(cardno, baseAddr, len,
28611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      &moxa_boards[cardno].numPorts);
28621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (retval)
28631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (retval);
28641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		port = cardno * MAX_PORTS_PER_BOARD;
28651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) {
28661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxaChkPort[port] = 1;
28671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxaCurBaud[port] = 9600L;
28681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxaDCDState[port] = 0;
28691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxaTableAddr[port] = baseAddr + Extern_table + Extern_size * i;
28701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ofsAddr = moxaTableAddr[port];
28711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (moxa_boards[cardno].numPorts == 8) {
28721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p8rx_mask, ofsAddr + RX_mask);
28731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p8tx_mask, ofsAddr + TX_mask);
28741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb);
28751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb);
28761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb);
28771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb);
28781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (moxa_boards[cardno].numPorts == 16) {
28801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p16rx_mask, ofsAddr + RX_mask);
28811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p16tx_mask, ofsAddr + TX_mask);
28821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb);
28831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb);
28841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb);
28851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb);
28861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (moxa_boards[cardno].numPorts == 24) {
28881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p24rx_mask, ofsAddr + RX_mask);
28891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p24tx_mask, ofsAddr + TX_mask);
28901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb);
28911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb);
28921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb);
28931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
28941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (moxa_boards[cardno].numPorts == 32) {
28951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p32rx_mask, ofsAddr + RX_mask);
28961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p32tx_mask, ofsAddr + TX_mask);
28971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p32tx_ofs, ofsAddr + Ofs_txb);
28981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb);
28991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb);
29001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb);
29011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
29021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
29031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
29041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
29051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
29071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
29081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaloadc218(int cardno, void __iomem *baseAddr, int len)
29101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
29111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char retry;
29121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, j, len1, len2;
29131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort usum, *ptr, keycode;
29141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (moxa_boards[cardno].boardType == MOXA_BOARD_CP204J)
29161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		keycode = CP204J_KeyCode;
29171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
29181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		keycode = C218_KeyCode;
29191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	usum = 0;
29201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	len1 = len >> 1;
29211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ptr = (ushort *) moxaBuff;
29221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < len1; i++)
29231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		usum += *(ptr + i);
29241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	retry = 0;
29251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
29261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len1 = len >> 1;
29271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		j = 0;
29281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (len1) {
29291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			len2 = (len1 > 2048) ? 2048 : len1;
29301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			len1 -= len2;
29311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (i = 0; i < len2 << 1; i++)
29321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writeb(moxaBuff[i + j], baseAddr + C218_LoadBuf + i);
29331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			j += i;
29341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			writew(len2, baseAddr + C218DLoad_len);
29361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			writew(0, baseAddr + C218_key);
29371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (i = 0; i < 100; i++) {
29381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (readw(baseAddr + C218_key) == keycode)
29391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					break;
29401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				moxadelay(1);	/* delay 10 ms */
29411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
29421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (readw(baseAddr + C218_key) != keycode) {
29431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (-1);
29441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
29451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
29461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(0, baseAddr + C218DLoad_len);
29471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(usum, baseAddr + C218check_sum);
29481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(0, baseAddr + C218_key);
29491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < 100; i++) {
29501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (readw(baseAddr + C218_key) == keycode)
29511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
29521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxadelay(1);	/* delay 10 ms */
29531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
29541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retry++;
29551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while ((readb(baseAddr + C218chksum_ok) != 1) && (retry < 3));
29561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (readb(baseAddr + C218chksum_ok) != 1) {
29571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-1);
29581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(0, baseAddr + C218_key);
29601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 100; i++) {
29611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (readw(baseAddr + Magic_no) == Magic_code)
29621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
29631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxadelay(1);	/* delay 10 ms */
29641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (readw(baseAddr + Magic_no) != Magic_code) {
29661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-1);
29671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(1, baseAddr + Disable_IRQ);
29691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(0, baseAddr + Magic_no);
29701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 100; i++) {
29711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (readw(baseAddr + Magic_no) == Magic_code)
29721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
29731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxadelay(1);	/* delay 10 ms */
29741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (readw(baseAddr + Magic_no) != Magic_code) {
29761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-1);
29771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaCard = 1;
29791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaIntNdx[cardno] = baseAddr + IRQindex;
29801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaIntPend[cardno] = baseAddr + IRQpending;
29811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaIntTable[cardno] = baseAddr + IRQtable;
29821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
29831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
29841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPorts)
29861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
29871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort usum;
29881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, j, wlen, len2, retry;
29891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort *uptr;
29901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	usum = 0;
29921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wlen = len >> 1;
29931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uptr = (ushort *) moxaBuff;
29941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < wlen; i++)
29951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		usum += uptr[i];
29961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	retry = 0;
29971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	j = 0;
29981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
29991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (wlen) {
30001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (wlen > 2048)
30011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				len2 = 2048;
30021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
30031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				len2 = wlen;
30041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			wlen -= len2;
30051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			len2 <<= 1;
30061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (i = 0; i < len2; i++)
30071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				writeb(moxaBuff[j + i], baseAddr + C320_LoadBuf + i);
30081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			len2 >>= 1;
30091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			j += i;
30101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			writew(len2, baseAddr + C320DLoad_len);
30111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			writew(0, baseAddr + C320_key);
30121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (i = 0; i < 10; i++) {
30131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (readw(baseAddr + C320_key) == C320_KeyCode)
30141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					break;
30151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				moxadelay(1);
30161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
30171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (readw(baseAddr + C320_key) != C320_KeyCode)
30181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (-1);
30191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
30201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(0, baseAddr + C320DLoad_len);
30211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(usum, baseAddr + C320check_sum);
30221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(0, baseAddr + C320_key);
30231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < 10; i++) {
30241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (readw(baseAddr + C320_key) == C320_KeyCode)
30251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
30261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			moxadelay(1);
30271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
30281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retry++;
30291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while ((readb(baseAddr + C320chksum_ok) != 1) && (retry < 3));
30301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (readb(baseAddr + C320chksum_ok) != 1)
30311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-1);
30321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(0, baseAddr + C320_key);
30331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 600; i++) {
30341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (readw(baseAddr + Magic_no) == Magic_code)
30351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
30361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxadelay(1);
30371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
30381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (readw(baseAddr + Magic_no) != Magic_code)
30391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-100);
30401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (moxa_boards[cardno].busType == MOXA_BUS_TYPE_PCI) {		/* ASIC board */
30421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(0x3800, baseAddr + TMS320_PORT1);
30431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(0x3900, baseAddr + TMS320_PORT2);
30441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(28499, baseAddr + TMS320_CLOCK);
30451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
30461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(0x3200, baseAddr + TMS320_PORT1);
30471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(0x3400, baseAddr + TMS320_PORT2);
30481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writew(19999, baseAddr + TMS320_CLOCK);
30491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
30501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(1, baseAddr + Disable_IRQ);
30511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(0, baseAddr + Magic_no);
30521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 500; i++) {
30531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (readw(baseAddr + Magic_no) == Magic_code)
30541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
30551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxadelay(1);
30561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
30571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (readw(baseAddr + Magic_no) != Magic_code)
30581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-102);
30591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	j = readw(baseAddr + Module_cnt);
30611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (j <= 0)
30621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-101);
30631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*numPorts = j * 8;
30641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(j, baseAddr + Module_no);
30651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(0, baseAddr + Magic_no);
30661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 600; i++) {
30671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (readw(baseAddr + Magic_no) == Magic_code)
30681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
30691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxadelay(1);
30701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
30711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (readw(baseAddr + Magic_no) != Magic_code)
30721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-102);
30731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaCard = 1;
30741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaIntNdx[cardno] = baseAddr + IRQindex;
30751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaIntPend[cardno] = baseAddr + IRQpending;
30761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaIntTable[cardno] = baseAddr + IRQtable;
30771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
30781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
30791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
30811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslong MoxaPortGetCurBaud(int port)
30821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
30831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (moxaChkPort[port] == 0)
30851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
30861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (moxaCurBaud[port]);
30871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
30881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif  /*  0  */
30891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaSetFifo(int port, int enable)
30911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
30921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr = moxaTableAddr[port];
30931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!enable) {
30951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0);
30961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxafunc(ofsAddr, FC_SetTxFIFOCnt, 1);
30971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
30981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxafunc(ofsAddr, FC_SetRxFIFOTrig, 3);
30991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16);
31001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
31011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
31021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
31041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortSetMode(int port, int databits, int stopbits, int parity)
31051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
31061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
31071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val;
31081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = 0;
31101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (databits) {
31111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 5:
31121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= 0;
31131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
31141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 6:
31151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= 1;
31161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
31171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 7:
31181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= 2;
31191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
31201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 8:
31211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= 3;
31221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
31231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
31241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-1);
31251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
31261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (stopbits) {
31271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0:
31281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= 0;
31291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;		/* stop bits 1.5 */
31301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1:
31311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= 0;
31321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
31331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2:
31341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= 4;
31351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
31361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
31371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-1);
31381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
31391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (parity) {
31401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0:
31411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= 0x00;
31421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;		/* None  */
31431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1:
31441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= 0x08;
31451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;		/* Odd   */
31461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2:
31471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= 0x18;
31481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;		/* Even  */
31491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 3:
31501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= 0x28;
31511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;		/* Mark  */
31521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 4:
31531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= 0x38;
31541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;		/* Space */
31551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
31561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-1);
31571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
31581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
31591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_SetMode, val);
31601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
31611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
31621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortTxBufSize(int port)
31641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
31651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
31661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int size;
31671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
31691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	size = readw(ofsAddr + TX_mask);
31701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (size);
31711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
31721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortRxBufSize(int port)
31741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
31751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
31761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int size;
31771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
31791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	size = readw(ofsAddr + RX_mask);
31801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (size);
31811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
31821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortRxFree(int port)
31841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
31851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
31861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ushort rptr, wptr, mask;
31871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len;
31881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
31901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rptr = readw(ofsAddr + RXrptr);
31911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wptr = readw(ofsAddr + RXwptr);
31921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = readw(ofsAddr + RX_mask);
31931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	len = mask - ((wptr - rptr) & mask);
31941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (len);
31951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
31961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortGetBrkCnt(int port)
31971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
31981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (moxaBreakCnt[port]);
31991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
32001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortSetXonXoff(int port, int xonValue, int xoffValue)
32021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
32031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
32041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
32061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(xonValue, ofsAddr + FuncArg);
32071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(xoffValue, ofsAddr + FuncArg1);
32081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(FC_SetXonXoff, ofsAddr + FuncCode);
32091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wait_finish(ofsAddr);
32101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
32111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortIsTxHold(int port)
32131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
32141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
32151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val;
32161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
32181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
32191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
32201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxafunc(ofsAddr, FC_GetCCSR, 0);
32211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val = readw(ofsAddr + FuncArg);
32221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val & 0x04)
32231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (1);
32241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
32251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (readw(ofsAddr + FlagStat) & Tx_flowOff)
32261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (1);
32271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
32281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
32291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
32301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
3231