moxa.c revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           moxa.c  -- MOXA Intellio family multiport serial driver.
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5b9705b603d1d29471aa2977e6310f4f9a4e85925Jiri Slaby *      Copyright (C) 1999-2000  Moxa Technologies (support@moxa.com.tw).
6b9705b603d1d29471aa2977e6310f4f9a4e85925Jiri Slaby *
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
29037182346f0991683cc7320a257c3f6089432ceeJiri Slaby *      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>
51037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#include <linux/pci.h>
52037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#include <linux/init.h>
53b9705b603d1d29471aa2977e6310f4f9a4e85925Jiri Slaby#include <linux/bitops.h>
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#include <asm/system.h>
56037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#include <asm/io.h>
5711324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#include <asm/uaccess.h>
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5911324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define		MOXA_VERSION		"5.1k"
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6111324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MOXAMAJOR       172
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXACUMAJOR     173
6308d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby
6408d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby#define put_to_user(arg1, arg2) put_user(arg1, (unsigned long *)arg2)
6508d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby#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 */
6911324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MAX_PORTS 		128	/* Don't change this value */
7011324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby
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 {
915ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby	MOXA_BOARD_C218_PCI = 1,
925ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby	MOXA_BOARD_C218_ISA,
935ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby	MOXA_BOARD_C320_PCI,
945ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby	MOXA_BOARD_C320_ISA,
955ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby	MOXA_BOARD_CP204J,
965ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby};
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *moxa_brdname[] =
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"C218 Turbo PCI series",
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"C218 Turbo ISA series",
102037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	"C320 Turbo PCI series",
103037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	"C320 Turbo ISA series",
1048f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby	"CP-204J series",
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI
1088f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic struct pci_device_id moxa_pcibrds[] = {
109810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C218, PCI_ANY_ID, PCI_ANY_ID,
1108f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby	  0, 0, MOXA_BOARD_C218_PCI },
111037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C320, PCI_ANY_ID, PCI_ANY_ID,
112037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	  0, 0, MOXA_BOARD_C320_PCI },
1138f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP204J, PCI_ANY_ID, PCI_ANY_ID,
1148f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby	  0, 0, MOXA_BOARD_CP204J },
1158f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby	{ 0 }
1168f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby};
1178f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri SlabyMODULE_DEVICE_TABLE(pci, moxa_pcibrds);
1188f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby#endif /* CONFIG_PCI */
1198f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby
1208f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabytypedef struct _moxa_isa_board_conf {
1218f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby	int boardType;
1228f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby	int numPorts;
1238f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby	unsigned long baseAddr;
1248f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby} moxa_isa_board_conf;
1259dff89cd82af7bccc706fed288b1c33a51c3b937Jiri Slaby
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic moxa_isa_board_conf moxa_isa_boards[] =
1278f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby{
1288f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby/*       {MOXA_BOARD_C218_ISA,8,0xDC000}, */
1298f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby};
1308f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct _moxa_pci_devinfo {
1328f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby	ushort busNum;
1339de6a51fee08f9e7020074738150441305e83af2Alan Cox	ushort devNum;
134b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby} moxa_pci_devinfo;
1357bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby
1367bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabytypedef struct _moxa_board_conf {
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int boardType;
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int numPorts;
1397bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby	unsigned long baseAddr;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int busType;
1417bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby	moxa_pci_devinfo pciInfo;
1427bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby} moxa_board_conf;
1437bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby
1448f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic moxa_board_conf moxa_boards[MAX_BOARDS];
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __iomem *moxaBaseAddr[MAX_BOARDS];
14674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby
14774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystruct moxa_str {
14874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	int type;
14974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	int port;
15074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	int close_delay;
15174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	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};
16374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby
16474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystruct mxser_mstatus {
1657bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby	tcflag_t cflag;
166a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	int cts;
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int dsr;
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ri;
169d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby	int dcd;
170d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby};
171d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby
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
178d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby#define THROTTLE	0x8
179d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby
180d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby/* event */
181d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby#define MOXA_EVENT_HANGUP	1
182d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby
183d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby#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};
198606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Coxstatic 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);
206db1acaa632870ec87b65e062bc72ca375837a1f6Alan Coxmodule_param_array(baseaddr, int, NULL, 0);
2076f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabymodule_param_array(numports, int, NULL, 0);
2086f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby#endif
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(ttymajor, int, 0);
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(verbose, bool, 0644);
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
212b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic struct tty_driver *moxaDriver;
213b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic struct moxa_str moxaChannels[MAX_PORTS];
214b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic unsigned char *moxaXmitBuff;
215b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int moxaTimer_on;
216b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic struct timer_list moxaTimer;
217b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int moxaEmptyTimer_on[MAX_PORTS];
218b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic struct timer_list moxaEmptyTimer[MAX_PORTS];
219b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic struct semaphore moxaBuffSem;
2202108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby
2217bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby/*
222b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby * static functions:
223b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby */
224b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void do_moxa_softint(void *);
225b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int moxa_open(struct tty_struct *, struct file *);
226b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void moxa_close(struct tty_struct *, struct file *);
2278f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic int moxa_write(struct tty_struct *, const unsigned char *, int);
2288f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic int moxa_write_room(struct tty_struct *);
229b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void moxa_flush_buffer(struct tty_struct *);
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_chars_in_buffer(struct tty_struct *);
23174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void moxa_flush_chars(struct tty_struct *);
23274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void moxa_put_char(struct tty_struct *, unsigned char);
23374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int moxa_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long);
23474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void moxa_throttle(struct tty_struct *);
23574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void moxa_unthrottle(struct tty_struct *);
23674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void moxa_set_termios(struct tty_struct *, struct termios *);
23774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void moxa_stop(struct tty_struct *);
23874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void moxa_start(struct tty_struct *);
23974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void moxa_hangup(struct tty_struct *);
24074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int moxa_tiocmget(struct tty_struct *tty, struct file *file);
24174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int moxa_tiocmset(struct tty_struct *tty, struct file *file,
24274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby			 unsigned int set, unsigned int clear);
24374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void moxa_poll(unsigned long);
24474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void set_tty_param(struct tty_struct *);
24574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int block_till_ready(struct tty_struct *, struct file *,
246eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby			    struct moxa_str *);
24774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void setup_empty_event(struct tty_struct *);
24874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void check_xmit_empty(unsigned long);
24974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void shut_down(struct moxa_str *);
25074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void receive_data(struct moxa_str *);
25174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby/*
25274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby * moxa board interface functions:
2537bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby */
2547bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void MoxaDriverInit(void);
2557bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int MoxaDriverIoctl(unsigned int, unsigned long, int);
2567bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int MoxaDriverPoll(void);
2577bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int MoxaPortsOfCard(int);
2587bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int MoxaPortIsValid(int);
2597bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void MoxaPortEnable(int);
2607bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void MoxaPortDisable(int);
2617bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic long MoxaPortGetMaxBaud(int);
2627bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic long MoxaPortSetBaud(int, long);
2637bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int MoxaPortSetTermio(int, struct termios *);
2647bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int MoxaPortGetLineOut(int, int *, int *);
2657bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void MoxaPortLineCtrl(int, int, int);
2667bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void MoxaPortFlowCtrl(int, int, int, int, int, int);
26774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int MoxaPortLineStatus(int);
26874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int MoxaPortDCDChange(int);
26974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int MoxaPortDCDON(int);
27074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void MoxaPortFlushData(int, int);
27174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int MoxaPortWriteData(int, unsigned char *, int);
27274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int MoxaPortReadData(int, unsigned char *, int);
27374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int MoxaPortTxQueue(int);
27474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int MoxaPortRxQueue(int);
27574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int MoxaPortTxFree(int);
276a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slabystatic void MoxaPortTxDisable(int);
27774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void MoxaPortTxEnable(int);
27874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int MoxaPortResetBrkCnt(int);
27974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void MoxaPortSendBreak(int, int);
28074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int moxa_get_serial_info(struct moxa_str *, struct serial_struct __user *);
28174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int moxa_set_serial_info(struct moxa_str *, struct serial_struct __user *);
28274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void MoxaSetFifo(int port, int enable);
28374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby
28474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic struct tty_operations moxa_ops = {
28574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	.open = moxa_open,
28674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	.close = moxa_close,
28774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	.write = moxa_write,
288a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	.write_room = moxa_write_room,
289a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	.flush_buffer = moxa_flush_buffer,
290a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	.chars_in_buffer = moxa_chars_in_buffer,
29174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	.flush_chars = moxa_flush_chars,
29274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	.put_char = moxa_put_char,
293a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	.ioctl = moxa_ioctl,
29474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	.throttle = moxa_throttle,
29574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	.unthrottle = moxa_unthrottle,
29674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	.set_termios = moxa_set_termios,
29774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	.stop = moxa_stop,
29874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	.start = moxa_start,
29974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	.hangup = moxa_hangup,
300a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	.tiocmget = moxa_tiocmget,
30174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	.tiocmset = moxa_tiocmset,
30274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby};
30374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby
30474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby#ifdef CONFIG_PCI
30574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf * board)
30674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby{
30774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	board->baseAddr = pci_resource_start (p, 2);
30874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	board->boardType = board_type;
309a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	switch (board_type) {
310a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	case MOXA_BOARD_C218_ISA:
31174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	case MOXA_BOARD_C218_PCI:
312a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		board->numPorts = 8;
31374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby		break;
31474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby
315a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	case MOXA_BOARD_CP204J:
316a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		board->numPorts = 4;
31774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby		break;
31874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	default:
319a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		board->numPorts = 0;
320a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		break;
32174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	}
32274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	board->busType = MOXA_BUS_TYPE_PCI;
323a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	board->pciInfo.busNum = p->bus->number;
324a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	board->pciInfo.devNum = p->devfn >> 3;
32574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby
32674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	return (0);
32774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby}
32874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby#endif /* CONFIG_PCI */
32974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby
33074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int __init moxa_init(void)
331a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby{
33274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	int i, numBoards;
33374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	struct moxa_str *ch;
33474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby
33574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	printk(KERN_INFO "MOXA Intellio family driver version %s\n", MOXA_VERSION);
33674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	moxaDriver = alloc_tty_driver(MAX_PORTS + 1);
33774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	if (!moxaDriver)
33874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby		return -ENOMEM;
33974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby
34074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	init_MUTEX(&moxaBuffSem);
34174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	moxaDriver->owner = THIS_MODULE;
34274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	moxaDriver->name = "ttya";
34374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	moxaDriver->devfs_name = "tts/a";
34474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	moxaDriver->major = ttymajor;
34574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	moxaDriver->minor_start = 0;
34674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	moxaDriver->type = TTY_DRIVER_TYPE_SERIAL;
3479de6a51fee08f9e7020074738150441305e83af2Alan Cox	moxaDriver->subtype = SERIAL_TYPE_NORMAL;
34874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	moxaDriver->init_termios = tty_std_termios;
34974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	moxaDriver->init_termios.c_iflag = 0;
3509de6a51fee08f9e7020074738150441305e83af2Alan Cox	moxaDriver->init_termios.c_oflag = 0;
35174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
352a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	moxaDriver->init_termios.c_lflag = 0;
353a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	moxaDriver->flags = TTY_DRIVER_REAL_RAW;
35474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	tty_set_operations(moxaDriver, &moxa_ops);
355a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
35674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	moxaXmitBuff = NULL;
35774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby
358a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	for (i = 0, ch = moxaChannels; i < MAX_PORTS; i++, ch++) {
359a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		ch->type = PORT_16550A;
36074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby		ch->port = i;
36174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby		INIT_WORK(&ch->tqueue, do_moxa_softint, ch);
362a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		ch->tty = NULL;
363a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		ch->close_delay = 5 * HZ / 10;
364a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		ch->closing_wait = 30 * HZ;
365a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		ch->count = 0;
36674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby		ch->blocked_open = 0;
367a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		ch->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
368a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		init_waitqueue_head(&ch->open_wait);
369a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		init_waitqueue_head(&ch->close_wait);
370a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	}
371a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
372a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	for (i = 0; i < MAX_BOARDS; i++) {
37374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby		moxa_boards[i].boardType = 0;
374a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		moxa_boards[i].numPorts = 0;
37574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby		moxa_boards[i].baseAddr = 0;
37674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby		moxa_boards[i].busType = 0;
37774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby		moxa_boards[i].pciInfo.busNum = 0;
37874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby		moxa_boards[i].pciInfo.devNum = 0;
37974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	}
38074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	MoxaDriverInit();
38174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	printk("Tty devices major number = %d\n", ttymajor);
38274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby
38374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	if (tty_register_driver(moxaDriver)) {
38474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby		printk(KERN_ERR "Couldn't install MOXA Smartio family driver !\n");
385b68e31d0ebbcc909d1941f9f230c9d062a3a13d3Jeff Dike		put_tty_driver(moxaDriver);
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MAX_PORTS; i++) {
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		init_timer(&moxaEmptyTimer[i]);
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaEmptyTimer[i].function = check_xmit_empty;
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaEmptyTimer[i].data = (unsigned long) & moxaChannels[i];
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaEmptyTimer_on[i] = 0;
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_timer(&moxaTimer);
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaTimer.function = moxa_poll;
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaTimer.expires = jiffies + (HZ / 50);
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaTimer_on = 1;
39974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby	add_timer(&moxaTimer);
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Find the boards defined in source code */
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	numBoards = 0;
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MAX_BOARDS; i++) {
404aa7e5221fb47badbea618cc62704d6e4a4bcce15Jiri Slaby		if ((moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA) ||
405aa7e5221fb47badbea618cc62704d6e4a4bcce15Jiri Slaby		 (moxa_isa_boards[i].boardType == MOXA_BOARD_C320_ISA)) {
40634af946a22724c4e2b204957f2b24b22a0fb121cIngo Molnar			moxa_boards[numBoards].boardType = moxa_isa_boards[i].boardType;
40733f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox			if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA)
40874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby				moxa_boards[numBoards].numPorts = 8;
40974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby			else
41074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby				moxa_boards[numBoards].numPorts = moxa_isa_boards[i].numPorts;
41174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby			moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA;
412037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			moxa_boards[numBoards].baseAddr = moxa_isa_boards[i].baseAddr;
413037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			if (verbose)
414037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				printk("Board %2d: %s board(baseAddr=%lx)\n",
415037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				       numBoards + 1,
416037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				       moxa_brdname[moxa_boards[numBoards].boardType - 1],
417037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				       moxa_boards[numBoards].baseAddr);
418037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			numBoards++;
419037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		}
420037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	}
421037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	/* Find the boards defined form module args. */
422037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#ifdef MODULE
423037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	for (i = 0; i < MAX_BOARDS; i++) {
424037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		if ((type[i] == MOXA_BOARD_C218_ISA) ||
425037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		    (type[i] == MOXA_BOARD_C320_ISA)) {
426037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			if (verbose)
427037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				printk("Board %2d: %s board(baseAddr=%lx)\n",
428037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				       numBoards + 1,
429037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				       moxa_brdname[type[i] - 1],
430037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				       (unsigned long) baseaddr[i]);
431037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			if (numBoards >= MAX_BOARDS) {
432037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				if (verbose)
433037182346f0991683cc7320a257c3f6089432ceeJiri Slaby					printk("More than %d MOXA Intellio family boards found. Board is ignored.", MAX_BOARDS);
434037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				continue;
435037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			}
436037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			moxa_boards[numBoards].boardType = type[i];
437037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA)
438037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				moxa_boards[numBoards].numPorts = 8;
439037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			else
440037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				moxa_boards[numBoards].numPorts = numports[i];
441037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA;
442037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			moxa_boards[numBoards].baseAddr = baseaddr[i];
443037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			numBoards++;
444037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		}
445037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	}
446037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#endif
447037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	/* Find PCI boards here */
448037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#ifdef CONFIG_PCI
449037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	{
450037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		struct pci_dev *p = NULL;
451037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		int n = (sizeof(moxa_pcibrds) / sizeof(moxa_pcibrds[0])) - 1;
452037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		i = 0;
453037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		while (i < n) {
454037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			while ((p = pci_find_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL)
455037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			{
456037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				if (pci_enable_device(p))
457037182346f0991683cc7320a257c3f6089432ceeJiri Slaby					continue;
458037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				if (numBoards >= MAX_BOARDS) {
459037182346f0991683cc7320a257c3f6089432ceeJiri Slaby					if (verbose)
460037182346f0991683cc7320a257c3f6089432ceeJiri Slaby						printk("More than %d MOXA Intellio family boards found. Board is ignored.", MAX_BOARDS);
461037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				} else {
462037182346f0991683cc7320a257c3f6089432ceeJiri Slaby					moxa_get_PCI_conf(p, moxa_pcibrds[i].driver_data,
463037182346f0991683cc7320a257c3f6089432ceeJiri Slaby						&moxa_boards[numBoards]);
464037182346f0991683cc7320a257c3f6089432ceeJiri Slaby					numBoards++;
465037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				}
466037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			}
467037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			i++;
468037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		}
469037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	}
470037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#endif
471037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	for (i = 0; i < numBoards; i++) {
472037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		moxaBaseAddr[i] = ioremap((unsigned long) moxa_boards[i].baseAddr, 0x4000);
473037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	}
474037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
475037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	return (0);
476eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby}
477037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
478037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic void __exit moxa_exit(void)
479037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{
480037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	int i;
481037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
482037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (verbose)
483037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		printk("Unloading module moxa ...\n");
484037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
485eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby	if (moxaTimer_on)
486037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		del_timer(&moxaTimer);
487037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
488037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	for (i = 0; i < MAX_PORTS; i++)
489037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		if (moxaEmptyTimer_on[i])
490037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			del_timer(&moxaEmptyTimer[i]);
491037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
492037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (tty_unregister_driver(moxaDriver))
493037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		printk("Couldn't unregister MOXA Intellio family serial driver\n");
494037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	put_tty_driver(moxaDriver);
495eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby	if (verbose)
496037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		printk("Done\n");
497037182346f0991683cc7320a257c3f6089432ceeJiri Slaby}
498037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
499037182346f0991683cc7320a257c3f6089432ceeJiri Slabymodule_init(moxa_init);
500037182346f0991683cc7320a257c3f6089432ceeJiri Slabymodule_exit(moxa_exit);
501037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
502037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic void do_moxa_softint(void *private_)
503037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{
504037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	struct moxa_str *ch = (struct moxa_str *) private_;
505037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	struct tty_struct *tty;
506037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
507037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (ch && (tty = ch->tty)) {
5085292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		if (test_and_clear_bit(MOXA_EVENT_HANGUP, &ch->event)) {
509037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			tty_hangup(tty);	/* FIXME: module removal race here - AKPM */
510037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			wake_up_interruptible(&ch->open_wait);
511037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
512037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		}
513037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	}
5145292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby}
51508d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby
516037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_open(struct tty_struct *tty, struct file *filp)
517037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{
5185292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	struct moxa_str *ch;
5195292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	int port;
520037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	int retval;
5215292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	unsigned long page;
5225292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby
5235292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	port = PORTNO(tty);
5245292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	if (port == MAX_PORTS) {
5255292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		return (0);
5265292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	}
5275292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	if (!MoxaPortIsValid(port)) {
5285292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		tty->driver_data = NULL;
5295292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		return (-ENODEV);
5305292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	}
5315292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	down(&moxaBuffSem);
5325292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	if (!moxaXmitBuff) {
5335292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		page = get_zeroed_page(GFP_KERNEL);
5345292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		if (!page) {
5355292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby			up(&moxaBuffSem);
5365292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby			return (-ENOMEM);
5375292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		}
5385292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		/* This test is guarded by the BuffSem so no longer needed
539037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		   delete me in 2.5 */
540037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		if (moxaXmitBuff)
541037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			free_page(page);
542037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		else
543037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			moxaXmitBuff = (unsigned char *) page;
544037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	}
545037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	up(&moxaBuffSem);
546037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
547037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	ch = &moxaChannels[port];
548037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	ch->count++;
549037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	tty->driver_data = ch;
550037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	ch->tty = tty;
551037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (!(ch->asyncflags & ASYNC_INITIALIZED)) {
5525292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		ch->statusflags = 0;
553037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		set_tty_param(tty);
5545292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		MoxaPortLineCtrl(ch->port, 1, 1);
5555292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		MoxaPortEnable(ch->port);
5565292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		ch->asyncflags |= ASYNC_INITIALIZED;
5575292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	}
5585292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	retval = block_till_ready(tty, filp, ch);
559037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
560037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	moxa_unthrottle(tty);
561037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
5625292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	if (ch->type == PORT_16550A) {
563037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		MoxaSetFifo(ch->port, 1);
564037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	} else {
5655292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		MoxaSetFifo(ch->port, 0);
5665292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	}
5675292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby
5685292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	return (retval);
5695292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby}
570037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
571037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic void moxa_close(struct tty_struct *tty, struct file *filp)
572037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{
573037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	struct moxa_str *ch;
5745292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	int port;
5755292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby
576037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	port = PORTNO(tty);
577037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (port == MAX_PORTS) {
5785292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		return;
579037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	}
580037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (!MoxaPortIsValid(port)) {
581037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#ifdef SERIAL_DEBUG_CLOSE
582037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		printk("Invalid portno in moxa_close\n");
583037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#endif
584037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		tty->driver_data = NULL;
585037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		return;
586037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	}
58708d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby	if (tty->driver_data == NULL) {
5885292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		return;
5895292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	}
5905292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	if (tty_hung_up_p(filp)) {
5915292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		return;
5925292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	}
5935292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	ch = (struct moxa_str *) tty->driver_data;
5945292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby
5955292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	if ((tty->count == 1) && (ch->count != 1)) {
5965292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		printk("moxa_close: bad serial port count; tty->count is 1, "
597037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		       "ch->count is %d\n", ch->count);
598037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		ch->count = 1;
599037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	}
600037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (--ch->count < 0) {
601037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		printk("moxa_close: bad serial port count, device=%s\n",
602037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		       tty->name);
603037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		ch->count = 0;
604037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	}
605037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (ch->count) {
606037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		return;
607037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	}
60808d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby	ch->asyncflags |= ASYNC_CLOSING;
6095292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby
6105292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	ch->cflag = tty->termios->c_cflag;
6115292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	if (ch->asyncflags & ASYNC_INITIALIZED) {
6125292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		setup_empty_event(tty);
6135292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		tty_wait_until_sent(tty, 30 * HZ);	/* 30 seconds timeout */
6145292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		moxaEmptyTimer_on[ch->port] = 0;
6155292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		del_timer(&moxaEmptyTimer[ch->port]);
6165292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	}
6175292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	shut_down(ch);
6185292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	MoxaPortFlushData(port, 2);
6195292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby
6205292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	if (tty->driver->flush_buffer)
6215292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby		tty->driver->flush_buffer(tty);
622037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	tty_ldisc_flush(tty);
623037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
624037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	tty->closing = 0;
625037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	ch->event = 0;
626037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	ch->tty = NULL;
627037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (ch->blocked_open) {
628037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		if (ch->close_delay) {
629037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			msleep_interruptible(jiffies_to_msecs(ch->close_delay));
630037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		}
631037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		wake_up_interruptible(&ch->open_wait);
632037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	}
633037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
634037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	wake_up_interruptible(&ch->close_wait);
635037182346f0991683cc7320a257c3f6089432ceeJiri Slaby}
636037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
637037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_write(struct tty_struct *tty,
638eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby		      const unsigned char *buf, int count)
639037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{
640037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	struct moxa_str *ch;
641037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	int len, port;
6425292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	unsigned long flags;
6435292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby
6445292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	ch = (struct moxa_str *) tty->driver_data;
6455292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby	if (ch == NULL)
646037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		return (0);
647037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	port = ch->port;
648037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	save_flags(flags);
649037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	cli();
650037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	len = MoxaPortWriteData(port, (unsigned char *) buf, count);
651037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	restore_flags(flags);
652b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby
653037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	/*********************************************
654037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if ( !(ch->statusflags & LOWWAIT) &&
655037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	     ((len != count) || (MoxaPortTxFree(port) <= 100)) )
656037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	************************************************/
657037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	ch->statusflags |= LOWWAIT;
658037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	return (len);
659037182346f0991683cc7320a257c3f6089432ceeJiri Slaby}
660037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
661037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_write_room(struct tty_struct *tty)
662037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{
663037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	struct moxa_str *ch;
664037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
665037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (tty->stopped)
666037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		return (0);
667037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	ch = (struct moxa_str *) tty->driver_data;
668037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (ch == NULL)
669037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		return (0);
670b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby	return (MoxaPortTxFree(ch->port));
671037182346f0991683cc7320a257c3f6089432ceeJiri Slaby}
672037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
673037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic void moxa_flush_buffer(struct tty_struct *tty)
674037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{
675037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
676037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
677037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (ch == NULL)
678037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		return;
679037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	MoxaPortFlushData(ch->port, 1);
680037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	tty_wakeup(tty);
681037182346f0991683cc7320a257c3f6089432ceeJiri Slaby}
682037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
683037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_chars_in_buffer(struct tty_struct *tty)
684037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{
685037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	int chars;
686037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
687037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
688037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	/*
689037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	 * Sigh...I have to check if driver_data is NULL here, because
690037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	 * if an open() fails, the TTY subsystem eventually calls
691037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	 * tty_wait_until_sent(), which calls the driver's chars_in_buffer()
692037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	 * routine.  And since the open() failed, we return 0 here.  TDJ
693037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	 */
694037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (ch == NULL)
695037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		return (0);
696037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	chars = MoxaPortTxQueue(ch->port);
697037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (chars) {
698037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		/*
699037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		 * Make it possible to wakeup anything waiting for output
700037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		 * in tty_ioctl.c, etc.
701037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		 */
702037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		if (!(ch->statusflags & EMPTYWAIT))
703037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			setup_empty_event(tty);
704037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	}
705037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	return (chars);
706037182346f0991683cc7320a257c3f6089432ceeJiri Slaby}
707037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
708037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic void moxa_flush_chars(struct tty_struct *tty)
709037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{
710037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	/*
711037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	 * Don't think I need this, because this is called to empty the TX
712037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	 * buffer for the 16450, 16550, etc.
713037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	 */
714037182346f0991683cc7320a257c3f6089432ceeJiri Slaby}
715037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
716037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic void moxa_put_char(struct tty_struct *tty, unsigned char c)
717037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{
718037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	struct moxa_str *ch;
719037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	int port;
7202bca76e89bc43f86136080536858048ebffab3e3David Howells	unsigned long flags;
721037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
722037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	ch = (struct moxa_str *) tty->driver_data;
723037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (ch == NULL)
724037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		return;
725037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	port = ch->port;
726037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	save_flags(flags);
727037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	cli();
728037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	moxaXmitBuff[0] = c;
729037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	MoxaPortWriteData(port, moxaXmitBuff, 1);
730037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	restore_flags(flags);
731037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	/************************************************
732037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) )
7332bca76e89bc43f86136080536858048ebffab3e3David Howells	*************************************************/
734037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	ch->statusflags |= LOWWAIT;
735037182346f0991683cc7320a257c3f6089432ceeJiri Slaby}
736037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
737037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_tiocmget(struct tty_struct *tty, struct file *file)
738037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{
739037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
740037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	int port;
741037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	int flag = 0, dtr, rts;
742037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
743037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	port = PORTNO(tty);
744037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if ((port != MAX_PORTS) && (!ch))
745037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		return (-EINVAL);
746037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
747037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	MoxaPortGetLineOut(ch->port, &dtr, &rts);
748037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (dtr)
749037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		flag |= TIOCM_DTR;
750037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (rts)
751037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		flag |= TIOCM_RTS;
752037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	dtr = MoxaPortLineStatus(ch->port);
753037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (dtr & 1)
754037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		flag |= TIOCM_CTS;
755037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (dtr & 2)
756037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		flag |= TIOCM_DSR;
757037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (dtr & 4)
758037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		flag |= TIOCM_CD;
759037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	return flag;
760eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby}
761037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
762037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_tiocmset(struct tty_struct *tty, struct file *file,
763037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			 unsigned int set, unsigned int clear)
764037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{
765037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
766037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	int port;
767037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	int dtr, rts;
768037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
769037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	port = PORTNO(tty);
770037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if ((port != MAX_PORTS) && (!ch))
771037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		return (-EINVAL);
772037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
773037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	MoxaPortGetLineOut(ch->port, &dtr, &rts);
774037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (set & TIOCM_RTS)
775037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		rts = 1;
776037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (set & TIOCM_DTR)
777037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		dtr = 1;
778037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (clear & TIOCM_RTS)
779037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		rts = 0;
780037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if (clear & TIOCM_DTR)
781037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		dtr = 0;
782037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	MoxaPortLineCtrl(ch->port, dtr, rts);
783037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	return 0;
784037182346f0991683cc7320a257c3f6089432ceeJiri Slaby}
785037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
786037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_ioctl(struct tty_struct *tty, struct file *file,
787037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		      unsigned int cmd, unsigned long arg)
788037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{
789037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
790037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	register int port;
791037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	void __user *argp = (void __user *)arg;
792037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	int retval;
793037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
794037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	port = PORTNO(tty);
795037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	if ((port != MAX_PORTS) && (!ch))
796037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		return (-EINVAL);
797037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
798037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	switch (cmd) {
799037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	case TCSBRK:		/* SVID version: non-zero arg --> no break */
800037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		retval = tty_check_change(tty);
801037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		if (retval)
802037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			return (retval);
803037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		setup_empty_event(tty);
804037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		tty_wait_until_sent(tty, 0);
805037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		if (!arg)
806037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			MoxaPortSendBreak(ch->port, 0);
807037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		return (0);
808037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	case TCSBRKP:		/* support for POSIX tcsendbreak() */
809037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		retval = tty_check_change(tty);
810037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		if (retval)
811810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby			return (retval);
812810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby		setup_empty_event(tty);
813037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		tty_wait_until_sent(tty, 0);
814037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		MoxaPortSendBreak(ch->port, arg);
815810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby		return (0);
816810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	case TIOCGSOFTCAR:
817810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby		return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) argp);
818810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	case TIOCSSOFTCAR:
819810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby		if(get_user(retval, (unsigned long __user *) argp))
820810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby			return -EFAULT;
821810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby		arg = retval;
822810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby		tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |
823810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby					 (arg ? CLOCAL : 0));
82444b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox		if (C_CLOCAL(tty))
825810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby			ch->asyncflags &= ~ASYNC_CHECK_CD;
826810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby		else
827810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby			ch->asyncflags |= ASYNC_CHECK_CD;
828810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby		return (0);
829037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	case TIOCGSERIAL:
830037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		return moxa_get_serial_info(ch, argp);
831037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
832037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	case TIOCSSERIAL:
833037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		return moxa_set_serial_info(ch, argp);
834037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	default:
835037182346f0991683cc7320a257c3f6089432ceeJiri Slaby		retval = MoxaDriverIoctl(cmd, arg, port);
836037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	}
837037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	return (retval);
838037182346f0991683cc7320a257c3f6089432ceeJiri Slaby}
839037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
840037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic void moxa_throttle(struct tty_struct *tty)
841037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{
842037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
843037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
844ec09cd562135158dcb8a6c08e5a9efa36febedb1Jiri Slaby	ch->statusflags |= THROTTLE;
845ec09cd562135158dcb8a6c08e5a9efa36febedb1Jiri Slaby}
846ec09cd562135158dcb8a6c08e5a9efa36febedb1Jiri Slaby
847ec09cd562135158dcb8a6c08e5a9efa36febedb1Jiri Slabystatic void moxa_unthrottle(struct tty_struct *tty)
848810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby{
849037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
850037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
851037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	ch->statusflags &= ~THROTTLE;
852037182346f0991683cc7320a257c3f6089432ceeJiri Slaby}
853037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
854810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slabystatic void moxa_set_termios(struct tty_struct *tty,
855810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby			     struct termios *old_termios)
856810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby{
857810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
8582a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby
859810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	if (ch == NULL)
8600bcc4caadc8f5396b52950ee03c67b76875602dfJiri Slaby		return;
8610bcc4caadc8f5396b52950ee03c67b76875602dfJiri Slaby	set_tty_param(tty);
8622a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby	if (!(old_termios->c_cflag & CLOCAL) &&
8630bcc4caadc8f5396b52950ee03c67b76875602dfJiri Slaby	    (tty->termios->c_cflag & CLOCAL))
864810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby		wake_up_interruptible(&ch->open_wait);
865810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby}
866810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby
867810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slabystatic void moxa_stop(struct tty_struct *tty)
868037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{
869037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
870037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
871810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	if (ch == NULL)
872810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby		return;
873a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	MoxaPortTxDisable(ch->port);
874a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	ch->statusflags |= TXSTOPPED;
875a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby}
8767bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby
877810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby
8787bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void moxa_start(struct tty_struct *tty)
879a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby{
880a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
881a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
8829de6a51fee08f9e7020074738150441305e83af2Alan Cox	if (ch == NULL)
8839de6a51fee08f9e7020074738150441305e83af2Alan Cox		return;
884a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
885a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	if (!(ch->statusflags & TXSTOPPED))
886a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		return;
8879de6a51fee08f9e7020074738150441305e83af2Alan Cox
888a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	MoxaPortTxEnable(ch->port);
889a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	ch->statusflags &= ~TXSTOPPED;
890a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby}
891a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
892a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slabystatic void moxa_hangup(struct tty_struct *tty)
893a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby{
894a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
895a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
896810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	moxa_flush_buffer(tty);
897810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	shut_down(ch);
898810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	ch->event = 0;
899810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	ch->count = 0;
900810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->tty = NULL;
9029cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby	wake_up_interruptible(&ch->open_wait);
9039cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby}
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9059cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slabystatic void moxa_poll(unsigned long ignored)
9069cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby{
9079cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby	register int card;
9089cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby	struct moxa_str *ch;
9099cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby	struct tty_struct *tp;
9109cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby	int i, ports;
9117aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby
9127aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby	moxaTimer_on = 0;
9139cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby	del_timer(&moxaTimer);
9147aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby
9159cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby	if (MoxaDriverPoll() < 0) {
9169cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby		moxaTimer.function = moxa_poll;
9179cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby		moxaTimer.expires = jiffies + (HZ / 50);
9189cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby		moxaTimer_on = 1;
9199cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby		add_timer(&moxaTimer);
9209cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby		return;
9219cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby	}
9227aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby	for (card = 0; card < MAX_BOARDS; card++) {
9239cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby		if ((ports = MoxaPortsOfCard(card)) <= 0)
9249cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby			continue;
9259cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby		ch = &moxaChannels[card * MAX_PORTS_PER_BOARD];
9269cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby		for (i = 0; i < ports; i++, ch++) {
9279cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby			if ((ch->asyncflags & ASYNC_INITIALIZED) == 0)
928e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby				continue;
929e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby			if (!(ch->statusflags & THROTTLE) &&
930e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby			    (MoxaPortRxQueue(ch->port) > 0))
931e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby				receive_data(ch);
932e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby			if ((tp = ch->tty) == 0)
933e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby				continue;
934e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby			if (ch->statusflags & LOWWAIT) {
93524cb233520f01971d6d873cb52c64bbbb0665ac0Alan Cox				if (MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS) {
9367aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby					if (!tp->stopped) {
9377aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby						ch->statusflags &= ~LOWWAIT;
938e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby						tty_wakeup(tp);
9397aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby					}
9409cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby				}
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!I_IGNBRK(tp) && (MoxaPortResetBrkCnt(ch->port) > 0)) {
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tty_insert_flip_char(tp, 0, TTY_BREAK);
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tty_schedule_flip(tp);
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (MoxaPortDCDChange(ch->port)) {
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (ch->asyncflags & ASYNC_CHECK_CD) {
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (MoxaPortDCDON(ch->port))
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						wake_up_interruptible(&ch->open_wait);
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					else {
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						set_bit(MOXA_EVENT_HANGUP, &ch->event);
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						schedule_work(&ch->tqueue);
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
956a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby		}
957037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	}
958037182346f0991683cc7320a257c3f6089432ceeJiri Slaby
959037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	moxaTimer.function = moxa_poll;
960037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	moxaTimer.expires = jiffies + (HZ / 50);
9619cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby	moxaTimer_on = 1;
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	add_timer(&moxaTimer);
963bb9f910a1153101a2f92620f1e7d0fda786c9812Jiri Slaby}
964bb9f910a1153101a2f92620f1e7d0fda786c9812Jiri Slaby
965bb9f910a1153101a2f92620f1e7d0fda786c9812Jiri Slaby/******************************************************************************/
966eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby
967037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic void set_tty_param(struct tty_struct *tty)
968037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{
969037182346f0991683cc7320a257c3f6089432ceeJiri Slaby	register struct termios *ts;
970e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby	struct moxa_str *ch;
971e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby	int rts, cts, txflow, rxflow, xany;
9729cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby
9739cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby	ch = (struct moxa_str *) tty->driver_data;
9749cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby	ts = tty->termios;
9759cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby	if (ts->c_cflag & CLOCAL)
9769cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby		ch->asyncflags &= ~ASYNC_CHECK_CD;
9779cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby	else
9789cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby		ch->asyncflags |= ASYNC_CHECK_CD;
9799cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby	rts = cts = txflow = rxflow = xany = 0;
980810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	if (ts->c_cflag & CRTSCTS)
981810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby		rts = cts = 1;
982e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby	if (ts->c_iflag & IXON)
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		txflow = 1;
984a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby	if (ts->c_iflag & IXOFF)
985a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby		rxflow = 1;
986a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby	if (ts->c_iflag & IXANY)
987a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby		xany = 1;
988a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby	MoxaPortFlowCtrl(ch->port, rts, cts, txflow, rxflow, xany);
989a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby	MoxaPortSetTermio(ch->port, ts);
990a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby}
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int block_till_ready(struct tty_struct *tty, struct file *filp,
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    struct moxa_str *ch)
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
995810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	DECLARE_WAITQUEUE(wait,current);
996d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby	unsigned long flags;
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retval;
9987aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby	int do_clocal = C_CLOCAL(tty);
9997aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If the device is in the middle of being closed, then block
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * until it's done, and then try again.
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tty_hung_up_p(filp) || (ch->asyncflags & ASYNC_CLOSING)) {
10059b4e3b13b147e9b737de63188a9ae740eaa8c36dSergey Vlasov		if (ch->asyncflags & ASYNC_CLOSING)
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			interruptible_sleep_on(&ch->close_wait);
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SERIAL_DO_RESTART
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ch->asyncflags & ASYNC_HUP_NOTIFY)
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-EAGAIN);
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-ERESTARTSYS);
1012606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox#else
1013606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox		return (-EAGAIN);
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If non-blocking mode is set, then make the check up front
1018eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby	 * and then exit.
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (filp->f_flags & O_NONBLOCK) {
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
1023d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby	}
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1025d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby	 * Block waiting for the carrier detect and the line to become free
1026d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby	 */
1027810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	retval = 0;
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	add_wait_queue(&ch->open_wait, &wait);
1029d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby#ifdef SERIAL_DEBUG_OPEN
1030d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby	printk("block_til_ready before block: ttys%d, count = %d\n",
1031d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby	       ch->line, ch->count);
1032d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby#endif
10337aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby	save_flags(flags);
1034d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby	cli();
1035d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby	if (!tty_hung_up_p(filp))
1036d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby		ch->count--;
1037d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby	restore_flags(flags);
1038d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby	ch->blocked_open++;
1039d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby	while (1) {
104024cb233520f01971d6d873cb52c64bbbb0665ac0Alan Cox		set_current_state(TASK_INTERRUPTIBLE);
1041d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby		if (tty_hung_up_p(filp) ||
1042eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby		    !(ch->asyncflags & ASYNC_INITIALIZED)) {
1043d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby#ifdef SERIAL_DO_RESTART
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ch->asyncflags & ASYNC_HUP_NOTIFY)
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				retval = -EAGAIN;
1046037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			else
1047037182346f0991683cc7320a257c3f6089432ceeJiri Slaby				retval = -ERESTARTSYS;
1048037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#else
1049037182346f0991683cc7320a257c3f6089432ceeJiri Slaby			retval = -EAGAIN;
1050037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#endif
1051d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby			break;
1052bb9f910a1153101a2f92620f1e7d0fda786c9812Jiri Slaby		}
1053bb9f910a1153101a2f92620f1e7d0fda786c9812Jiri Slaby		if (!(ch->asyncflags & ASYNC_CLOSING) && (do_clocal ||
1054bb9f910a1153101a2f92620f1e7d0fda786c9812Jiri Slaby						MoxaPortDCDON(ch->port)))
1055bb9f910a1153101a2f92620f1e7d0fda786c9812Jiri Slaby			break;
1056d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby
1057d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby		if (signal_pending(current)) {
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			retval = -ERESTARTSYS;
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1060d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby		}
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		schedule();
1062a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby	}
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_current_state(TASK_RUNNING);
1064a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby	remove_wait_queue(&ch->open_wait, &wait);
1065a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby	if (!tty_hung_up_p(filp))
1066eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby		ch->count++;
1067d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby	ch->blocked_open--;
1068a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby#ifdef SERIAL_DEBUG_OPEN
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("block_til_ready after blocking: ttys%d, count = %d\n",
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       ch->line, ch->count);
1071a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby#endif
1072a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby	if (retval)
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (retval);
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1077eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void setup_empty_event(struct tty_struct *tty)
10799cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby{
1080a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby	struct moxa_str *ch = tty->driver_data;
10819cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby	unsigned long flags;
1082a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby
1083810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	save_flags(flags);
1084810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	cli();
1085810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	ch->statusflags |= EMPTYWAIT;
10862a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby	moxaEmptyTimer_on[ch->port] = 0;
10872a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby	del_timer(&moxaEmptyTimer[ch->port]);
10882a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby	moxaEmptyTimer[ch->port].expires = jiffies + HZ;
10892a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby	moxaEmptyTimer_on[ch->port] = 1;
10902a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby	add_timer(&moxaEmptyTimer[ch->port]);
10912a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby	restore_flags(flags);
10922a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby}
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void check_xmit_empty(unsigned long data)
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct moxa_str *ch;
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1098a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	ch = (struct moxa_str *) data;
1099a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	moxaEmptyTimer_on[ch->port] = 0;
1100a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	del_timer(&moxaEmptyTimer[ch->port]);
1101a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	if (ch->tty && (ch->statusflags & EMPTYWAIT)) {
11029de6a51fee08f9e7020074738150441305e83af2Alan Cox		if (MoxaPortTxQueue(ch->port) == 0) {
11039de6a51fee08f9e7020074738150441305e83af2Alan Cox			ch->statusflags &= ~EMPTYWAIT;
11049de6a51fee08f9e7020074738150441305e83af2Alan Cox			tty_wakeup(ch->tty);
1105a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby			return;
1106a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		}
1107a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		moxaEmptyTimer[ch->port].expires = jiffies + HZ;
1108a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		moxaEmptyTimer_on[ch->port] = 1;
1109a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		add_timer(&moxaEmptyTimer[ch->port]);
1110a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	} else
1111a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		ch->statusflags &= ~EMPTYWAIT;
1112a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby}
1113a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
1114a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slabystatic void shut_down(struct moxa_str *ch)
11159de6a51fee08f9e7020074738150441305e83af2Alan Cox{
1116a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	struct tty_struct *tp;
1117a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
1118a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	if (!(ch->asyncflags & ASYNC_INITIALIZED))
1119a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		return;
1120a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
1121a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	tp = ch->tty;
1122a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
1123a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	MoxaPortDisable(ch->port);
1124a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
1125a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	/*
1126a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	 * If we're a modem control device and HUPCL is on, drop RTS & DTR.
1127a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	 */
1128a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	if (tp->termios->c_cflag & HUPCL)
1129a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		MoxaPortLineCtrl(ch->port, 0, 0);
1130a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
1131a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	ch->asyncflags &= ~ASYNC_INITIALIZED;
1132a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby}
1133a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
1134a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slabystatic void receive_data(struct moxa_str *ch)
1135a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby{
11369de6a51fee08f9e7020074738150441305e83af2Alan Cox	struct tty_struct *tp;
1137a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	struct termios *ts;
1138a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	int i, count, rc, space;
1139a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	unsigned char *charptr, *flagptr;
1140a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	unsigned long flags;
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ts = NULL;
1143810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	tp = ch->tty;
11448f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby	if (tp)
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ts = tp->termios;
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/**************************************************
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ( !tp || !ts || !(ts->c_cflag & CREAD) ) {
114811324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby	*****************************************************/
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!tp || !ts) {
115074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby		MoxaPortFlushData(ch->port, 0);
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1152a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	}
1153a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	space = TTY_FLIPBUF_SIZE - tp->flip.count;
1154810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	if (space <= 0)
1155a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby		return;
1156a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	charptr = tp->flip.char_buf_ptr;
1157810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	flagptr = tp->flip.flag_buf_ptr;
1158a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	rc = tp->flip.count;
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	save_flags(flags);
1160810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby	cli();
11619de6a51fee08f9e7020074738150441305e83af2Alan Cox	count = MoxaPortReadData(ch->port, charptr, space);
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	restore_flags(flags);
11639de6a51fee08f9e7020074738150441305e83af2Alan Cox	for (i = 0; i < count; i++)
11649de6a51fee08f9e7020074738150441305e83af2Alan Cox		*flagptr++ = 0;
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	charptr += count;
1166db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox	rc += count;
1167b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby	tp->flip.count = rc;
1168b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby	tp->flip.char_buf_ptr = charptr;
1169a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	tp->flip.flag_buf_ptr = flagptr;
11709de6a51fee08f9e7020074738150441305e83af2Alan Cox	tty_schedule_flip(ch->tty);
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1172a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Magic_code	0x404
1174a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
1175a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby/*
1176a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby *    System Configuration
1177a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby */
1178a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby/*
11799de6a51fee08f9e7020074738150441305e83af2Alan Cox *    for C218 BIOS initialization
11809de6a51fee08f9e7020074738150441305e83af2Alan Cox */
1181a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define C218_ConfBase	0x800
1182a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define C218_status	(C218_ConfBase + 0)	/* BIOS running status    */
11839de6a51fee08f9e7020074738150441305e83af2Alan Cox#define C218_diag	(C218_ConfBase + 2)	/* diagnostic status      */
1184a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define C218_key	(C218_ConfBase + 4)	/* WORD (0x218 for C218) */
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218DLoad_len	(C218_ConfBase + 6)	/* WORD           */
1186a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define C218check_sum	(C218_ConfBase + 8)	/* BYTE           */
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218chksum_ok	(C218_ConfBase + 0x0a)	/* BYTE (1:ok)            */
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218_TestRx	(C218_ConfBase + 0x10)	/* 8 bytes for 8 ports    */
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218_TestTx	(C218_ConfBase + 0x18)	/* 8 bytes for 8 ports    */
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218_RXerr	(C218_ConfBase + 0x20)	/* 8 bytes for 8 ports    */
11918f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby#define C218_ErrFlag	(C218_ConfBase + 0x28)	/* 8 bytes for 8 ports    */
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218_LoadBuf	0x0F00
119411324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define C218_KeyCode	0x218
1195a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define CP204J_KeyCode	0x204
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1198a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby *    for C320 BIOS initialization
1199a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby */
1200a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define C320_ConfBase	0x800
1201a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define C320_LoadBuf	0x0f00
12029de6a51fee08f9e7020074738150441305e83af2Alan Cox#define STS_init	0x05	/* for C320_status        */
12037aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby
12049de6a51fee08f9e7020074738150441305e83af2Alan Cox#define C320_status	C320_ConfBase + 0	/* BIOS running status    */
12059de6a51fee08f9e7020074738150441305e83af2Alan Cox#define C320_diag	C320_ConfBase + 2	/* diagnostic status      */
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320_key	C320_ConfBase + 4	/* WORD (0320H for C320) */
12079de6a51fee08f9e7020074738150441305e83af2Alan Cox#define C320DLoad_len	C320_ConfBase + 6	/* WORD           */
12087aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby#define C320check_sum	C320_ConfBase + 8	/* WORD           */
12097aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby#define C320chksum_ok	C320_ConfBase + 0x0a	/* WORD (1:ok)            */
12109de6a51fee08f9e7020074738150441305e83af2Alan Cox#define C320bapi_len	C320_ConfBase + 0x0c	/* WORD           */
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320UART_no	C320_ConfBase + 0x0e	/* WORD           */
12129de6a51fee08f9e7020074738150441305e83af2Alan Cox
1213a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define C320_KeyCode	0x320
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FixPage_addr	0x0000	/* starting addr of static page  */
12169de6a51fee08f9e7020074738150441305e83af2Alan Cox#define DynPage_addr	0x2000	/* starting addr of dynamic page */
12176f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby#define C218_start	0x3000	/* starting addr of C218 BIOS prg */
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Control_reg	0x1ff0	/* select page and reset control */
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define HW_reset	0x80
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1221a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby/*
1222a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby *    Function Codes
1223a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby */
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_CardReset	0x80
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_ChannelReset 1	/* C320 firmware not supported */
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_EnableCH	2
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_DisableCH	3
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetParam	4
1229b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby#define FC_SetMode	5
1230b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby#define FC_SetRate	6
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_LineControl	7
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_LineStatus	8
1233b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby#define FC_XmitControl	9
123433f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox#define FC_FlushQueue	10
12357bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define FC_SendBreak	11
12362108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby#define FC_StopBreak	12
12377bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define FC_LoopbackON	13
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_LoopbackOFF	14
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_ClrIrqTable	15
1240eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby#define FC_SendXon	16
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetTermIrq	17	/* C320 firmware not supported */
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetCntIrq	18	/* C320 firmware not supported */
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetBreakIrq	19
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetLineIrq	20
12458f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby#define FC_SetFlowCtl	21
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_GenIrq	22
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_InCD180	23
1248eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby#define FC_OutCD180	24
1249b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby#define FC_InUARTreg	23
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_OutUARTreg	24
1251eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby#define FC_SetXonXoff	25
1252b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby#define FC_OutCD180CCR	26
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_ExtIQueue	27
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_ExtOQueue	28
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_ClrLineIrq	29
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_HWFlowCtl	30
1257b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby#define FC_GetClockRate 35
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetBaud	36
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetDataMode  41
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_GetCCSR      43
1261b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby#define FC_GetDataError 45
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_RxControl	50
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_ImmSend	51
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetXonState	52
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetXoffState	53
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_SetRxFIFOTrig 54
1267b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby#define FC_SetTxFIFOCnt 55
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_UnixRate	56
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FC_UnixResetTimer 57
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RxFIFOTrig1	0
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RxFIFOTrig4	1
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RxFIFOTrig8	2
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RxFIFOTrig14	3
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1277eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby *    Dual-Ported RAM
1278978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox */
1279b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby#define DRAM_global	0
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INT_data	(DRAM_global + 0)
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Config_base	(DRAM_global + 0x108)
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IRQindex	(INT_data + 0)
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IRQpending	(INT_data + 4)
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IRQtable	(INT_data + 8)
12866f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1288978e595f88a1fba5869aa42a4af4fba36f33ecacAlan Cox *    Interrupt Status
1289eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby */
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IntrRx		0x01	/* receiver data O.K.             */
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IntrTx		0x02	/* transmit buffer empty  */
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IntrFunc	0x04	/* function complete              */
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IntrBreak	0x08	/* received break         */
1294a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define IntrLine	0x10	/* line status change
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   for transmitter                */
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IntrIntr	0x20	/* received INTR code             */
1297a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define IntrQuit	0x40	/* received QUIT code             */
1298a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define IntrEOF 	0x80	/* received EOF code              */
1299a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
1300a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define IntrRxTrigger 	0x100	/* rx data count reach tigger value */
130174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby#define IntrTxTrigger 	0x200	/* tx data count below trigger value */
1302a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Magic_no	(Config_base + 0)
1304b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby#define Card_model_no	(Config_base + 2)
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Total_ports	(Config_base + 4)
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Module_cnt	(Config_base + 8)
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Module_no	(Config_base + 10)
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Timer_10ms	(Config_base + 14)
1309b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby#define Disable_IRQ	(Config_base + 20)
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMS320_PORT1	(Config_base + 22)
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMS320_PORT2	(Config_base + 24)
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMS320_CLOCK	(Config_base + 26)
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    DATA BUFFER in DRAM
1316a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby */
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Extern_table	0x400	/* Base address of the external table
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   (24 words *    64) total 3K bytes
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   (24 words * 128) total 6K bytes */
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Extern_size	0x60	/* 96 bytes                       */
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RXrptr		0x00	/* read pointer for RX buffer     */
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RXwptr		0x02	/* write pointer for RX buffer    */
1323a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define TXrptr		0x04	/* read pointer for TX buffer     */
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXwptr		0x06	/* write pointer for TX buffer    */
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define HostStat	0x08	/* IRQ flag and general flag      */
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FlagStat	0x0A
132711324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define FlowControl	0x0C	/* B7 B6 B5 B4 B3 B2 B1 B0              */
1328a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby					/*  x  x  x  x  |  |  |  |            */
1329a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby					/*              |  |  |  + CTS flow   */
1330a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby					/*              |  |  +--- RTS flow   */
1331a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby					/*              |  +------ TX Xon/Xoff */
133274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby					/*              +--------- RX Xon/Xoff */
1333a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define Break_cnt	0x0E	/* received break count   */
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CD180TXirq	0x10	/* if non-0: enable TX irq        */
1335b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby#define RX_mask 	0x12
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_mask 	0x14
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Ofs_rxb 	0x16
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Ofs_txb 	0x18
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Page_rxb	0x1A
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Page_txb	0x1C
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EndPage_rxb	0x1E
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EndPage_txb	0x20
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Data_error	0x22
1344b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby#define RxTrigger	0x28
1345a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define TxTrigger	0x2a
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define rRXwptr 	0x34
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Low_water	0x36
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FuncCode	0x40
1351eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby#define FuncArg 	0x42
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FuncArg1	0x44
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218rx_size	0x2000	/* 8K bytes */
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218tx_size	0x8000	/* 32K bytes */
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218rx_mask	(C218rx_size - 1)
1358eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby#define C218tx_mask	(C218tx_size - 1)
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8rx_size	0x2000
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8tx_size	0x8000
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8rx_mask	(C320p8rx_size - 1)
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8tx_mask	(C320p8tx_size - 1)
1364eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p16rx_size	0x2000
1366eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby#define C320p16tx_size	0x4000
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p16rx_mask	(C320p16rx_size - 1)
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p16tx_mask	(C320p16tx_size - 1)
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1370db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox#define C320p24rx_size	0x2000
1371eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby#define C320p24tx_size	0x2000
13729de6a51fee08f9e7020074738150441305e83af2Alan Cox#define C320p24rx_mask	(C320p24rx_size - 1)
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p24tx_mask	(C320p24tx_size - 1)
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p32rx_size	0x1000
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p32tx_size	0x1000
1377eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby#define C320p32rx_mask	(C320p32rx_size - 1)
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p32tx_mask	(C320p32tx_size - 1)
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Page_size	0x2000
1381b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby#define Page_mask	(Page_size - 1)
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218rx_spage	3
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218tx_spage	4
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218rx_pageno	1
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218tx_pageno	4
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C218buf_pageno	5
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1388eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby#define C320p8rx_spage	3
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8tx_spage	4
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8rx_pgno	1
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8tx_pgno	4
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p8buf_pgno	5
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p16rx_spage 3
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p16tx_spage 4
1396b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby#define C320p16rx_pgno	1
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p16tx_pgno	2
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p16buf_pgno 3
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p24rx_spage 3
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p24tx_spage 4
1402a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define C320p24rx_pgno	1
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C320p24tx_pgno	1
1404a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define C320p24buf_pgno 2
1405a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
1406a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define C320p32rx_spage 3
1407a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define C320p32tx_ofs	C320p32rx_size
1408a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define C320p32tx_spage 3
1409a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define C320p32buf_pgno 1
14109de6a51fee08f9e7020074738150441305e83af2Alan Cox
1411a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby/*
1412a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby *    Host Status
1413a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby */
14149de6a51fee08f9e7020074738150441305e83af2Alan Cox#define WakeupRx	0x01
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WakeupTx	0x02
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WakeupBreak	0x08
14177bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define WakeupLine	0x10
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WakeupIntr	0x20
14197bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define WakeupQuit	0x40
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WakeupEOF	0x80	/* used in VTIME control */
14219de6a51fee08f9e7020074738150441305e83af2Alan Cox#define WakeupRxTrigger	0x100
1422a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#define WakeupTxTrigger	0x200
14239de6a51fee08f9e7020074738150441305e83af2Alan Cox/*
14247bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby *    Flag status
14257bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby */
14267bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define Rx_over		0x01
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Xoff_state	0x02
14287bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define Tx_flowOff	0x04
14297bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define Tx_enable	0x08
14307bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define CTS_state	0x10
14319de6a51fee08f9e7020074738150441305e83af2Alan Cox#define DSR_state	0x20
14327bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define DCD_state	0x80
14339de6a51fee08f9e7020074738150441305e83af2Alan Cox/*
14347bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby *    FlowControl
14357bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby */
14367bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define CTS_FlowCtl	1
14377bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define RTS_FlowCtl	2
14387bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define Tx_FlowCtl	4
14397bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define Rx_FlowCtl	8
14407bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define IXM_IXANY	0x10
14417bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby
14427bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define LowWater	128
14437bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby
14447bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define DTR_ON		1
14457bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define RTS_ON		2
14467bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define CTS_ON		1
14477bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define DSR_ON		2
14487bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define DCD_ON		8
14497bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby
14507bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby/* mode definition */
14517bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define	MX_CS8		0x03
14527bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define	MX_CS7		0x02
14537bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define	MX_CS6		0x01
14547bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define	MX_CS5		0x00
14557bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	MX_STOP1	0x00
14570bcc4caadc8f5396b52950ee03c67b76875602dfJiri Slaby#define	MX_STOP15	0x04
14587bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define	MX_STOP2	0x08
14597bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby
14607bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define	MX_PARNONE	0x00
14617bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define	MX_PAREVEN	0x40
14627bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define	MX_PARODD	0xC0
14637bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby
14647bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby/*
14657bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby *    Query
14667bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby */
14677bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define QueryPort	MAX_PORTS
14687bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby
14697bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby
14707bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby
14717bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystruct mon_str {
14727bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby	int tick;
14737bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby	int rxcnt[MAX_PORTS];
14747bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby	int txcnt[MAX_PORTS];
14757bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby};
14767bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabytypedef struct mon_str mon_st;
14777bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby
14787bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define 	DCD_changed	0x01
14797bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby#define 	DCD_oldstate	0x80
14807bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby
14817bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic unsigned char moxaBuff[10240];
14827bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void __iomem *moxaIntNdx[MAX_BOARDS];
14837bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void __iomem *moxaIntPend[MAX_BOARDS];
14847bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void __iomem *moxaIntTable[MAX_BOARDS];
14857bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic char moxaChkPort[MAX_PORTS];
14867bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic char moxaLineCtrl[MAX_PORTS];
14877bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void __iomem *moxaTableAddr[MAX_PORTS];
14887bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic long moxaCurBaud[MAX_PORTS];
14892a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slabystatic char moxaDCDState[MAX_PORTS];
14907bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic char moxaLowChkFlag[MAX_PORTS];
14917bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int moxaLowWaterChk;
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaCard;
14937bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic mon_st moxaLog;
14947bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int moxaFuncTout;
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ushort moxaBreakCnt[MAX_PORTS];
14967bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby
14972a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slabystatic void moxadelay(int);
14982a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slabystatic void moxafunc(void __iomem *, int, ushort);
14997bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void wait_finish(void __iomem *);
15007bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void low_water_check(void __iomem *);
15017bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int moxaloadbios(int, unsigned char __user *, int);
15027bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int moxafindcard(int);
15037bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int moxaload320b(int, unsigned char __user *, int);
15047bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int moxaloadcode(int, unsigned char __user *, int);
15057bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int moxaloadc218(int, void __iomem *, int);
15067bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int moxaloadc320(int, void __iomem *, int, int *);
15077bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby
15087bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby/*****************************************************************************
15097bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby *	Driver level functions: 					     *
15107bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby *	1. MoxaDriverInit(void);					     *
15117bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby *	2. MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port);   *
15127bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby *	3. MoxaDriverPoll(void);					     *
15137bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby *****************************************************************************/
15147bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabyvoid MoxaDriverInit(void)
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15187bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby	moxaFuncTout = HZ / 2;	/* 500 mini-seconds */
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaCard = 0;
15202a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby	moxaLog.tick = 0;
15212a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby	moxaLowWaterChk = 0;
15222a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby	for (i = 0; i < MAX_PORTS; i++) {
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaChkPort[i] = 0;
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaLowChkFlag[i] = 0;
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaLineCtrl[i] = 0;
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaLog.rxcnt[i] = 0;
1527db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox		moxaLog.txcnt[i] = 0;
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1529eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby}
1530eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby
1531db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox#define	MOXA		0x400
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GET_IQUEUE 	(MOXA + 1)	/* get input buffered count */
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GET_OQUEUE 	(MOXA + 2)	/* get output buffered count */
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_INIT_DRIVER	(MOXA + 6)	/* moxaCard=0 */
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_LOAD_BIOS		(MOXA + 9)	/* download BIOS */
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_FIND_BOARD		(MOXA + 10)	/* Check if MOXA card exist? */
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_LOAD_C320B		(MOXA + 11)	/* download 320B firmware */
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_LOAD_CODE		(MOXA + 12)	/* download firmware */
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GETDATACOUNT       (MOXA + 23)
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GET_IOQUEUE	(MOXA + 27)
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_FLUSH_QUEUE	(MOXA + 28)
1542db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox#define MOXA_GET_CONF		(MOXA + 35)	/* configuration */
1543db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox#define MOXA_GET_MAJOR          (MOXA + 63)
1544db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox#define MOXA_GET_CUMAJOR        (MOXA + 64)
1545b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby#define MOXA_GETMSTATUS         (MOXA + 65)
1546b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby
1547db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox
1548db1acaa632870ec87b65e062bc72ca375837a1f6Alan Coxstruct moxaq_str {
1549db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox	int inq;
1550db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox	int outq;
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15536f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystruct dl_str {
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char __user *buf;
15558f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby	int len;
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int cardno;
15577bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby};
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15597bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic struct moxaq_str temp_queue[MAX_PORTS];
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dl_str dltmp;
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15626f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabyvoid MoxaPortFlushData(int port, int mode)
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15649de6a51fee08f9e7020074738150441305e83af2Alan Cox	void __iomem *ofsAddr;
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((mode < 0) || (mode > 2))
15669de6a51fee08f9e7020074738150441305e83af2Alan Cox		return;
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_FlushQueue, mode);
1569b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby	if (mode != 1) {
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaLowChkFlag[port] = 0;
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		low_water_check(ofsAddr);
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1574a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby
1575b4173f45758a5b5185acb302c507289e661d9419Jiri Slabyint MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port)
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1577a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	int i;
15789de6a51fee08f9e7020074738150441305e83af2Alan Cox	int status;
1579a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby	int MoxaPortTxQueue(int), MoxaPortRxQueue(int);
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __user *argp = (void __user *)arg;
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (port == QueryPort) {
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((cmd != MOXA_GET_CONF) && (cmd != MOXA_INIT_DRIVER) &&
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    (cmd != MOXA_LOAD_BIOS) && (cmd != MOXA_FIND_BOARD) && (cmd != MOXA_LOAD_C320B) &&
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 (cmd != MOXA_LOAD_CODE) && (cmd != MOXA_GETDATACOUNT) &&
1586b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby		  (cmd != MOXA_GET_IOQUEUE) && (cmd != MOXA_GET_MAJOR) &&
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    (cmd != MOXA_GET_CUMAJOR) && (cmd != MOXA_GETMSTATUS))
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-EINVAL);
1589eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby	}
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
1591b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby	case MOXA_GET_CONF:
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(copy_to_user(argp, &moxa_boards, MAX_BOARDS * sizeof(moxa_board_conf)))
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
1594b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby		return (0);
15956f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby	case MOXA_INIT_DRIVER:
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((int) arg == 0x404)
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MoxaDriverInit();
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_GETDATACOUNT:
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaLog.tick = jiffies;
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(copy_to_user(argp, &moxaLog, sizeof(mon_st)))
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_FLUSH_QUEUE:
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MoxaPortFlushData(port, arg);
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_GET_IOQUEUE:
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < MAX_PORTS; i++) {
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (moxaChkPort[i]) {
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				temp_queue[i].inq = MoxaPortRxQueue(i);
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				temp_queue[i].outq = MoxaPortTxQueue(i);
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(copy_to_user(argp, temp_queue, sizeof(struct moxaq_str) * MAX_PORTS))
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_GET_OQUEUE:
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = MoxaPortTxQueue(port);
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return put_user(i, (unsigned long __user *)argp);
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_GET_IQUEUE:
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = MoxaPortRxQueue(port);
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return put_user(i, (unsigned long __user *)argp);
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_GET_MAJOR:
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(copy_to_user(argp, &ttymajor, sizeof(int)))
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_GET_CUMAJOR:
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = 0;
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(copy_to_user(argp, &i, sizeof(int)))
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_GETMSTATUS:
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < MAX_PORTS; i++) {
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			GMStatus[i].ri = 0;
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			GMStatus[i].dcd = 0;
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			GMStatus[i].dsr = 0;
16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			GMStatus[i].cts = 0;
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!moxaChkPort[i]) {
16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				status = MoxaPortLineStatus(moxaChannels[i].port);
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (status & 1)
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					GMStatus[i].cts = 1;
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (status & 2)
16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					GMStatus[i].dsr = 1;
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (status & 4)
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					GMStatus[i].dcd = 1;
16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
164908d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!moxaChannels[i].tty || !moxaChannels[i].tty->termios)
16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				GMStatus[i].cflag = moxaChannels[i].cflag;
16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				GMStatus[i].cflag = moxaChannels[i].tty->termios->c_cflag;
16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(copy_to_user(argp, GMStatus, sizeof(struct mxser_mstatus) * MAX_PORTS))
16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-ENOIOCTLCMD);
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_LOAD_BIOS:
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_FIND_BOARD:
1662606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox	case MOXA_LOAD_C320B:
16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_LOAD_CODE:
1664606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox		break;
1665c7bce3097c0f9bbed76ee6fd03742f2624031a45Alan Cox	}
16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(copy_from_user(&dltmp, argp, sizeof(struct dl_str)))
16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(dltmp.cardno < 0 || dltmp.cardno >= MAX_BOARDS)
16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(cmd)
16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_LOAD_BIOS:
16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = moxaloadbios(dltmp.cardno, dltmp.buf, dltmp.len);
16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (i);
16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_FIND_BOARD:
16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return moxafindcard(dltmp.cardno);
16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_LOAD_C320B:
16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		moxaload320b(dltmp.cardno, dltmp.buf, dltmp.len);
16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default: /* to keep gcc happy */
16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MOXA_LOAD_CODE:
16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = moxaloadcode(dltmp.cardno, dltmp.buf, dltmp.len);
16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i == -1)
16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-EFAULT);
16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (i);
16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaDriverPoll(void)
16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register ushort temp;
16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register int card;
16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ip;
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int port, p, ports;
16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (moxaCard == 0)
17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-1);
17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (card = 0; card < MAX_BOARDS; card++) {
17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((ports = moxa_boards[card].numPorts) == 0)
17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (readb(moxaIntPend[card]) == 0xff) {
17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ip = moxaIntTable[card] + readb(moxaIntNdx[card]);
17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			p = card * MAX_PORTS_PER_BOARD;
17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ports <<= 1;
17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (port = 0; port < ports; port += 2, p++) {
17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((temp = readw(ip + port)) != 0) {
17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					writew(0, ip + port);
17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ofsAddr = moxaTableAddr[p];
17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (temp & IntrTx)
17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						writew(readw(ofsAddr + HostStat) & ~WakeupTx, ofsAddr + HostStat);
17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (temp & IntrBreak) {
17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						moxaBreakCnt[p]++;
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (temp & IntrLine) {
17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						if (readb(ofsAddr + FlagStat) & DCD_state) {
17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							if ((moxaDCDState[p] & DCD_oldstate) == 0)
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds								moxaDCDState[p] = (DCD_oldstate |
17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds										   DCD_changed);
17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						} else {
17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							if (moxaDCDState[p] & DCD_oldstate)
17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds								moxaDCDState[p] = DCD_changed;
17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						}
17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			writeb(0, moxaIntPend[card]);
17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (moxaLowWaterChk) {
17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			p = card * MAX_PORTS_PER_BOARD;
17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (port = 0; port < ports; port++, p++) {
17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (moxaLowChkFlag[p]) {
17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					moxaLowChkFlag[p] = 0;
17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ofsAddr = moxaTableAddr[p];
173833f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox					low_water_check(ofsAddr);
17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
174033f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox			}
17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxaLowWaterChk = 0;
17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************
17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Card level function:						     *
17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	1. MoxaPortsOfCard(int cardno); 				     *
17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/
17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortsOfCard(int cardno)
17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (moxa_boards[cardno].boardType == 0)
17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (moxa_boards[cardno].numPorts);
17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************
17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Port level functions:						     *
17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	1.  MoxaPortIsValid(int port);					     *
17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	2.  MoxaPortEnable(int port);					     *
17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	3.  MoxaPortDisable(int port);					     *
17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	4.  MoxaPortGetMaxBaud(int port);				     *
17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	5.  MoxaPortGetCurBaud(int port);				     *
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	6.  MoxaPortSetBaud(int port, long baud);			     *
17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	7.  MoxaPortSetMode(int port, int databit, int stopbit, int parity); *
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	8.  MoxaPortSetTermio(int port, unsigned char *termio); 	     *
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	9.  MoxaPortGetLineOut(int port, int *dtrState, int *rtsState);      *
17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	10. MoxaPortLineCtrl(int port, int dtrState, int rtsState);	     *
17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	11. MoxaPortFlowCtrl(int port, int rts, int cts, int rx, int tx,int xany);    *
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	12. MoxaPortLineStatus(int port);				     *
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	13. MoxaPortDCDChange(int port);				     *
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	14. MoxaPortDCDON(int port);					     *
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	15. MoxaPortFlushData(int port, int mode);	                     *
17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	16. MoxaPortWriteData(int port, unsigned char * buffer, int length); *
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	17. MoxaPortReadData(int port, unsigned char * buffer, int length);  *
17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	18. MoxaPortTxBufSize(int port);				     *
17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	19. MoxaPortRxBufSize(int port);				     *
17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	20. MoxaPortTxQueue(int port);					     *
17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	21. MoxaPortTxFree(int port);					     *
17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	22. MoxaPortRxQueue(int port);					     *
17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	23. MoxaPortRxFree(int port);					     *
17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	24. MoxaPortTxDisable(int port);				     *
17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	25. MoxaPortTxEnable(int port); 				     *
17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	26. MoxaPortGetBrkCnt(int port);				     *
17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	27. MoxaPortResetBrkCnt(int port);				     *
17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	28. MoxaPortSetXonXoff(int port, int xonValue, int xoffValue);	     *
17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	29. MoxaPortIsTxHold(int port); 				     *
17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	30. MoxaPortSendBreak(int port, int ticks);			     *
1791b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *****************************************************************************/
17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Moxa Port Number Description:
1794eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby *
17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      MOXA serial driver supports up to 4 MOXA-C218/C320 boards. And,
1796b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *      the port number using in MOXA driver functions will be 0 to 31 for
17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      first MOXA board, 32 to 63 for second, 64 to 95 for third and 96
179808d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby *      to 127 for fourth. For example, if you setup three MOXA boards,
17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      first board is C218, second board is C320-16 and third board is
1800eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby *      C320-32. The port number of first board (C218 - 8 ports) is from
1801eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby *      0 to 7. The port number of second board (C320 - 16 ports) is form
1802eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby *      32 to 47. The port number of third board (C320 - 32 ports) is from
18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      64 to 95. And those port numbers form 8 to 31, 48 to 63 and 96 to
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      127 will be invalid.
18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Moxa Functions Description:
18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 1:     Driver initialization routine, this routine must be
18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      called when initialized driver.
1811b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *      Syntax:
18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaDriverInit();
1813b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *
18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 2:     Moxa driver private IOCTL command processing.
18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port);
18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           unsigned int cmd   : IOCTL command
18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           unsigned long arg  : IOCTL argument
182108d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby *           int port           : port number (0 - 127)
18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
182308d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby *           return:    0  (OK)
182408d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby *                      -EINVAL
182508d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby *                      -ENOIOCTLCMD
18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
182708d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby *
182808d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby *      Function 3:     Moxa driver polling process routine.
1829eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby *      Syntax:
18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaDriverPoll(void);
18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
183208d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby *           return:    0       ; polling O.K.
18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      -1      : no any Moxa card.
18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1836eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby *      Function 4:     Get the ports of this card.
18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortsOfCard(int cardno);
1839b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *
1840b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *           int cardno         : card number (0 - 3)
18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       : this card is invalid
18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      8/16/24/32
18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1846b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *      Function 5:     Check this port is valid or invalid
18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortIsValid(int port);
18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127, ref port description)
18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       : this port is invalid
18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      1       : this port is valid
18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 6:     Enable this port to start Tx/Rx data.
18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaPortEnable(int port);
18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 7:     Disable this port
18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaPortDisable(int port);
18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 8:     Get the maximun available baud rate of this port.
18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      long MoxaPortGetMaxBaud(int port);
18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       : this port is invalid
18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      38400/57600/115200 bps
18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1875eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby *
18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 9:     Get the current baud rate of this port.
187708d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby *      Syntax:
187808d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby *      long MoxaPortGetCurBaud(int port);
187908d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby *           int port           : port number (0 - 127)
1880db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox *
18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       : this port is invalid
18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      50 - 115200 bps
18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 10:    Setting baud rate of this port.
18866f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby *      Syntax:
18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      long MoxaPortSetBaud(int port, long baud);
18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
1889eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby *           long baud          : baud rate (50 - 115200)
18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       : this port is invalid or baud < 50
1892b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *                      50 - 115200 : the real baud rate set to the port, if
1893b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *                                    the argument baud is large than maximun
18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                    available baud rate, the real setting
1895b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *                                    baud rate will be the maximun baud rate.
1896b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *
1897b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *
1898b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *      Function 11:    Setting the data-bits/stop-bits/parity of this port
1899b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *      Syntax:
1900eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby *      int  MoxaPortSetMode(int port, int databits, int stopbits, int parity);
19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int databits       : data bits (8/7/6/5)
1903b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *           int stopbits       : stop bits (2/1/0, 0 show 1.5 stop bits)
19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int parity     : parity (0:None,1:Odd,2:Even,3:Mark,4:Space)
1905eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby *
19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    -1      : invalid parameter
19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      0       : setting O.K.
19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 12:    Configure the port.
1911b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *      Syntax:
1912b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *      int  MoxaPortSetTermio(int port, struct termios *termio);
19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           struct termios * termio : termio structure pointer
1915b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *
1916b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *           return:    -1      : this port is invalid or termio == NULL
19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      0       : setting O.K.
1918b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *
19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 13:    Get the DTR/RTS state of this port.
19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortGetLineOut(int port, int *dtrState, int *rtsState);
19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int * dtrState     : pointer to INT to receive the current DTR
19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                state. (if NULL, this function will not
19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                write to this address)
19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int * rtsState     : pointer to INT to receive the current RTS
19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                state. (if NULL, this function will not
19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                write to this address)
1930b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *
19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    -1      : this port is invalid
19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      0       : O.K.
1933b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *
19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 14:    Setting the DTR/RTS output state of this port.
19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaPortLineCtrl(int port, int dtrState, int rtsState);
1938b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *           int port           : port number (0 - 127)
193908d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby *           int dtrState       : DTR output state (0: off, 1: on)
19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int rtsState       : RTS output state (0: off, 1: on)
19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 15:    Setting the flow control of this port.
19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaPortFlowCtrl(int port, int rtsFlow, int ctsFlow, int rxFlow,
19467bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby *                            int txFlow,int xany);
19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
1948a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby *           int rtsFlow        : H/W RTS flow control (0: no, 1: yes)
19497bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby *           int ctsFlow        : H/W CTS flow control (0: no, 1: yes)
1950a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby *           int rxFlow         : S/W Rx XON/XOFF flow control (0: no, 1: yes)
19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int txFlow         : S/W Tx XON/XOFF flow control (0: no, 1: yes)
19527bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby *           int xany           : S/W XANY flow control (0: no, 1: yes)
19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19552108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      Function 16:    Get ths line status of this port
19562108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      Syntax:
19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortLineStatus(int port);
19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19592108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *
19602108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *           return:    Bit 0 - CTS state (0: off, 1: on)
19612108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *                      Bit 1 - DSR state (0: off, 1: on)
19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      Bit 2 - DCD state (0: off, 1: on)
1963b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *
1964b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *
19651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 17:    Check the DCD state has changed since the last read
19661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      of this function.
19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
19681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortDCDChange(int port);
19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19702108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *
19711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       : no changed
19721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      1       : DCD has changed
19739de6a51fee08f9e7020074738150441305e83af2Alan Cox *
19741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 18:    Check ths current DCD state is ON or not.
19761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
19771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortDCDON(int port);
19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       : DCD off
19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      1       : DCD on
19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 19:    Flush the Rx/Tx buffer data of this port.
19852108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      Syntax:
19862108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      void MoxaPortFlushData(int port, int mode);
19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int mode
19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      0       : flush the Rx buffer
19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      1       : flush the Tx buffer
19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      2       : flush the Rx and Tx buffer
19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19932108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *
19942108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      Function 20:    Write data.
19952108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      Syntax:
19962108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      int  MoxaPortWriteData(int port, unsigned char * buffer, int length);
19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           unsigned char * buffer     : pointer to write data buffer.
19992108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *           int length         : write data length
20002108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *
20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0 - length      : real write data length
20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20042108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      Function 21:    Read data.
20052108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      Syntax:
20062108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      int  MoxaPortReadData(int port, unsigned char * buffer, int length);
20071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20082108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *           unsigned char * buffer     : pointer to read data buffer.
20091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int length         : read data buffer length
20102108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *
20111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0 - length      : real read data length
20121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20137bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby *
20141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 22:    Get the Tx buffer size of this port
20159de6a51fee08f9e7020074738150441305e83af2Alan Cox *      Syntax:
20162108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      int  MoxaPortTxBufSize(int port);
20171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20182108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *
20192108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *           return:    ..      : Tx buffer size
20202108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *
20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2022b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *      Function 23:    Get the Rx buffer size of this port
2023b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *      Syntax:
20241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortRxBufSize(int port);
20251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    ..      : Rx buffer size
20281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20292108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *
20301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 24:    Get the Tx buffer current queued data bytes
203133f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox *      Syntax:
20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortTxQueue(int port);
203333f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox *           int port           : port number (0 - 127)
20347bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby *
20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    ..      : Tx buffer current queued data bytes
20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 25:    Get the Tx buffer current free space
20391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20402108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      int  MoxaPortTxFree(int port);
20412108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *           int port           : port number (0 - 127)
20422108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *
20432108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *           return:    ..      : Tx buffer current free space
20442108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *
20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 26:    Get the Rx buffer current queued data bytes
20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortRxQueue(int port);
20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20512108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *           return:    ..      : Rx buffer current queued data bytes
20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20542108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      Function 27:    Get the Rx buffer current free space
20552108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      Syntax:
20562108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      int  MoxaPortRxFree(int port);
20572108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *           int port           : port number (0 - 127)
20582108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *
20592108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *           return:    ..      : Rx buffer current free space
20602108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *
20611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20622108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      Function 28:    Disable port data transmission.
20632108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      Syntax:
20641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaPortTxDisable(int port);
20652108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *           int port           : port number (0 - 127)
20662108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *
20671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2068b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *      Function 29:    Enable port data transmission.
20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20702108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      void MoxaPortTxEnable(int port);
20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2074b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *      Function 30:    Get the received BREAK signal count.
20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
2076b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *      int  MoxaPortGetBrkCnt(int port);
20772108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *           int port           : port number (0 - 127)
20781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0 - ..  : BREAK signal count
20801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20822108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      Function 31:    Get the received BREAK signal count and reset it.
20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortResetBrkCnt(int port);
2085b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *           int port           : port number (0 - 127)
20861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2087b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *           return:    0 - ..  : BREAK signal count
20882108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *
20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Function 32:    Set the S/W flow control new XON/XOFF value, default
20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      XON is 0x11 & XOFF is 0x13.
20921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
20932108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      void MoxaPortSetXonXoff(int port, int xonValue, int xoffValue);
20941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int xonValue       : new XON value (0 - 255)
2096b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *           int xoffValue      : new XOFF value (0 - 255)
20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2098b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *
20992108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *      Function 33:    Check this port's transmission is hold by remote site
21001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      because the flow control.
21011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
21021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      int  MoxaPortIsTxHold(int port);
21031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int port           : port number (0 - 127)
21042108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby *
21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           return:    0       : normal
21061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      1       : hold by remote site
2107b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *
21081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2109b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *      Function 34:    Send out a BREAK signal.
21101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      Syntax:
21111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      void MoxaPortSendBreak(int port, int ms100);
2112b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *           int port           : port number (0 - 127)
21131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *           int ms100          : break signal time interval.
2114b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *                                unit: 100 mini-second. if ms100 == 0, it will
21151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                send out a about 250 ms BREAK signal.
21161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
21178f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby */
2118eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slabyint MoxaPortIsValid(int port)
21191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2120eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby
2121eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby	if (moxaCard == 0)
21229de6a51fee08f9e7020074738150441305e83af2Alan Cox		return (0);
21239de6a51fee08f9e7020074738150441305e83af2Alan Cox	if (moxaChkPort[port] == 0)
2124eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby		return (0);
212544b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox	return (1);
2126eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby}
2127eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby
21281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortEnable(int port)
21291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
21318f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby	int MoxaPortLineStatus(int);
2132eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby	short lowwater = 512;
21331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ofsAddr = moxaTableAddr[port];
21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writew(lowwater, ofsAddr + Low_water);
2136eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby	moxaBreakCnt[port] = 0;
21371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
2139eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby		moxafunc(ofsAddr, FC_SetBreakIrq, 0);
2140eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby	} else {
2141eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby		writew(readw(ofsAddr + HostStat) | WakeupBreak, ofsAddr + HostStat);
2142eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby	}
21431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_SetLineIrq, Magic_code);
21451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_FlushQueue, 2);
21469de6a51fee08f9e7020074738150441305e83af2Alan Cox
2147eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby	moxafunc(ofsAddr, FC_EnableCH, Magic_code);
2148eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby	MoxaPortLineStatus(port);
214944b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox}
21501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortDisable(int port)
21529de6a51fee08f9e7020074738150441305e83af2Alan Cox{
21531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr = moxaTableAddr[port];
2154eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby
21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_SetFlowCtl, 0);	/* disable flow control */
21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code);
2157eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby	writew(0, ofsAddr + HostStat);
21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	moxafunc(ofsAddr, FC_DisableCH, Magic_code);
21591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslong MoxaPortGetMaxBaud(int port)
21621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
21641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI))
21651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (460800L);
2166b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby	else
21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (921600L);
2168b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby}
21691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslong MoxaPortSetBaud(int port, long baud)
21721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ofsAddr;
21741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long max, clock;
21751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int val;
21761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((baud < 50L) || ((max = MoxaPortGetMaxBaud(port)) == 0))
2178		return (0);
2179	ofsAddr = moxaTableAddr[port];
2180	if (baud > max)
2181		baud = max;
2182	if (max == 38400L)
2183		clock = 614400L;	/* for 9.8304 Mhz : max. 38400 bps */
2184	else if (max == 57600L)
2185		clock = 691200L;	/* for 11.0592 Mhz : max. 57600 bps */
2186	else
2187		clock = 921600L;	/* for 14.7456 Mhz : max. 115200 bps */
2188	val = clock / baud;
2189	moxafunc(ofsAddr, FC_SetBaud, val);
2190	baud = clock / val;
2191	moxaCurBaud[port] = baud;
2192	return (baud);
2193}
2194
2195int MoxaPortSetTermio(int port, struct termios *termio)
2196{
2197	void __iomem *ofsAddr;
2198	tcflag_t cflag;
2199	long baud;
2200	tcflag_t mode = 0;
2201
2202	if (moxaChkPort[port] == 0 || termio == 0)
2203		return (-1);
2204	ofsAddr = moxaTableAddr[port];
2205	cflag = termio->c_cflag;	/* termio->c_cflag */
2206
2207	mode = termio->c_cflag & CSIZE;
2208	if (mode == CS5)
2209		mode = MX_CS5;
2210	else if (mode == CS6)
2211		mode = MX_CS6;
2212	else if (mode == CS7)
2213		mode = MX_CS7;
2214	else if (mode == CS8)
2215		mode = MX_CS8;
2216
2217	if (termio->c_cflag & CSTOPB) {
2218		if (mode == MX_CS5)
2219			mode |= MX_STOP15;
2220		else
2221			mode |= MX_STOP2;
2222	} else
2223		mode |= MX_STOP1;
2224
2225	if (termio->c_cflag & PARENB) {
2226		if (termio->c_cflag & PARODD)
2227			mode |= MX_PARODD;
2228		else
2229			mode |= MX_PAREVEN;
2230	} else
2231		mode |= MX_PARNONE;
2232
2233	moxafunc(ofsAddr, FC_SetDataMode, (ushort) mode);
2234
2235	cflag &= (CBAUD | CBAUDEX);
2236#ifndef B921600
2237#define	B921600	(B460800+1)
2238#endif
2239	switch (cflag) {
2240	case B921600:
2241		baud = 921600L;
2242		break;
2243	case B460800:
2244		baud = 460800L;
2245		break;
2246	case B230400:
2247		baud = 230400L;
2248		break;
2249	case B115200:
2250		baud = 115200L;
2251		break;
2252	case B57600:
2253		baud = 57600L;
2254		break;
2255	case B38400:
2256		baud = 38400L;
2257		break;
2258	case B19200:
2259		baud = 19200L;
2260		break;
2261	case B9600:
2262		baud = 9600L;
2263		break;
2264	case B4800:
2265		baud = 4800L;
2266		break;
2267	case B2400:
2268		baud = 2400L;
2269		break;
2270	case B1800:
2271		baud = 1800L;
2272		break;
2273	case B1200:
2274		baud = 1200L;
2275		break;
2276	case B600:
2277		baud = 600L;
2278		break;
2279	case B300:
2280		baud = 300L;
2281		break;
2282	case B200:
2283		baud = 200L;
2284		break;
2285	case B150:
2286		baud = 150L;
2287		break;
2288	case B134:
2289		baud = 134L;
2290		break;
2291	case B110:
2292		baud = 110L;
2293		break;
2294	case B75:
2295		baud = 75L;
2296		break;
2297	case B50:
2298		baud = 50L;
2299		break;
2300	default:
2301		baud = 0;
2302	}
2303	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
2304	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
2305		if (baud == 921600L)
2306			return (-1);
2307	}
2308	MoxaPortSetBaud(port, baud);
2309
2310	if (termio->c_iflag & (IXON | IXOFF | IXANY)) {
2311		writeb(termio->c_cc[VSTART], ofsAddr + FuncArg);
2312		writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1);
2313		writeb(FC_SetXonXoff, ofsAddr + FuncCode);
2314		wait_finish(ofsAddr);
2315
2316	}
2317	return (0);
2318}
2319
2320int MoxaPortGetLineOut(int port, int *dtrState, int *rtsState)
2321{
2322
2323	if (!MoxaPortIsValid(port))
2324		return (-1);
2325	if (dtrState) {
2326		if (moxaLineCtrl[port] & DTR_ON)
2327			*dtrState = 1;
2328		else
2329			*dtrState = 0;
2330	}
2331	if (rtsState) {
2332		if (moxaLineCtrl[port] & RTS_ON)
2333			*rtsState = 1;
2334		else
2335			*rtsState = 0;
2336	}
2337	return (0);
2338}
2339
2340void MoxaPortLineCtrl(int port, int dtr, int rts)
2341{
2342	void __iomem *ofsAddr;
2343	int mode;
2344
2345	ofsAddr = moxaTableAddr[port];
2346	mode = 0;
2347	if (dtr)
2348		mode |= DTR_ON;
2349	if (rts)
2350		mode |= RTS_ON;
2351	moxaLineCtrl[port] = mode;
2352	moxafunc(ofsAddr, FC_LineControl, mode);
2353}
2354
2355void MoxaPortFlowCtrl(int port, int rts, int cts, int txflow, int rxflow, int txany)
2356{
2357	void __iomem *ofsAddr;
2358	int mode;
2359
2360	ofsAddr = moxaTableAddr[port];
2361	mode = 0;
2362	if (rts)
2363		mode |= RTS_FlowCtl;
2364	if (cts)
2365		mode |= CTS_FlowCtl;
2366	if (txflow)
2367		mode |= Tx_FlowCtl;
2368	if (rxflow)
2369		mode |= Rx_FlowCtl;
2370	if (txany)
2371		mode |= IXM_IXANY;
2372	moxafunc(ofsAddr, FC_SetFlowCtl, mode);
2373}
2374
2375int MoxaPortLineStatus(int port)
2376{
2377	void __iomem *ofsAddr;
2378	int val;
2379
2380	ofsAddr = moxaTableAddr[port];
2381	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
2382	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
2383		moxafunc(ofsAddr, FC_LineStatus, 0);
2384		val = readw(ofsAddr + FuncArg);
2385	} else {
2386		val = readw(ofsAddr + FlagStat) >> 4;
2387	}
2388	val &= 0x0B;
2389	if (val & 8) {
2390		val |= 4;
2391		if ((moxaDCDState[port] & DCD_oldstate) == 0)
2392			moxaDCDState[port] = (DCD_oldstate | DCD_changed);
2393	} else {
2394		if (moxaDCDState[port] & DCD_oldstate)
2395			moxaDCDState[port] = DCD_changed;
2396	}
2397	val &= 7;
2398	return (val);
2399}
2400
2401int MoxaPortDCDChange(int port)
2402{
2403	int n;
2404
2405	if (moxaChkPort[port] == 0)
2406		return (0);
2407	n = moxaDCDState[port];
2408	moxaDCDState[port] &= ~DCD_changed;
2409	n &= DCD_changed;
2410	return (n);
2411}
2412
2413int MoxaPortDCDON(int port)
2414{
2415	int n;
2416
2417	if (moxaChkPort[port] == 0)
2418		return (0);
2419	if (moxaDCDState[port] & DCD_oldstate)
2420		n = 1;
2421	else
2422		n = 0;
2423	return (n);
2424}
2425
2426
2427/*
2428   int MoxaDumpMem(int port, unsigned char * buffer, int len)
2429   {
2430   int          i;
2431   unsigned long                baseAddr,ofsAddr,ofs;
2432
2433   baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD];
2434   ofs = baseAddr + DynPage_addr + pageofs;
2435   if (len > 0x2000L)
2436   len = 0x2000L;
2437   for (i = 0; i < len; i++)
2438   buffer[i] = readb(ofs+i);
2439   }
2440 */
2441
2442
2443int MoxaPortWriteData(int port, unsigned char * buffer, int len)
2444{
2445	int c, total, i;
2446	ushort tail;
2447	int cnt;
2448	ushort head, tx_mask, spage, epage;
2449	ushort pageno, pageofs, bufhead;
2450	void __iomem *baseAddr, *ofsAddr, *ofs;
2451
2452	ofsAddr = moxaTableAddr[port];
2453	baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD];
2454	tx_mask = readw(ofsAddr + TX_mask);
2455	spage = readw(ofsAddr + Page_txb);
2456	epage = readw(ofsAddr + EndPage_txb);
2457	tail = readw(ofsAddr + TXwptr);
2458	head = readw(ofsAddr + TXrptr);
2459	c = (head > tail) ? (head - tail - 1)
2460	    : (head - tail + tx_mask);
2461	if (c > len)
2462		c = len;
2463	moxaLog.txcnt[port] += c;
2464	total = c;
2465	if (spage == epage) {
2466		bufhead = readw(ofsAddr + Ofs_txb);
2467		writew(spage, baseAddr + Control_reg);
2468		while (c > 0) {
2469			if (head > tail)
2470				len = head - tail - 1;
2471			else
2472				len = tx_mask + 1 - tail;
2473			len = (c > len) ? len : c;
2474			ofs = baseAddr + DynPage_addr + bufhead + tail;
2475			for (i = 0; i < len; i++)
2476				writeb(*buffer++, ofs + i);
2477			tail = (tail + len) & tx_mask;
2478			c -= len;
2479		}
2480		writew(tail, ofsAddr + TXwptr);
2481	} else {
2482		len = c;
2483		pageno = spage + (tail >> 13);
2484		pageofs = tail & Page_mask;
2485		do {
2486			cnt = Page_size - pageofs;
2487			if (cnt > c)
2488				cnt = c;
2489			c -= cnt;
2490			writeb(pageno, baseAddr + Control_reg);
2491			ofs = baseAddr + DynPage_addr + pageofs;
2492			for (i = 0; i < cnt; i++)
2493				writeb(*buffer++, ofs + i);
2494			if (c == 0) {
2495				writew((tail + len) & tx_mask, ofsAddr + TXwptr);
2496				break;
2497			}
2498			if (++pageno == epage)
2499				pageno = spage;
2500			pageofs = 0;
2501		} while (1);
2502	}
2503	writeb(1, ofsAddr + CD180TXirq);	/* start to send */
2504	return (total);
2505}
2506
2507int MoxaPortReadData(int port, unsigned char * buffer, int space)
2508{
2509	register ushort head, pageofs;
2510	int i, count, cnt, len, total, remain;
2511	ushort tail, rx_mask, spage, epage;
2512	ushort pageno, bufhead;
2513	void __iomem *baseAddr, *ofsAddr, *ofs;
2514
2515	ofsAddr = moxaTableAddr[port];
2516	baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD];
2517	head = readw(ofsAddr + RXrptr);
2518	tail = readw(ofsAddr + RXwptr);
2519	rx_mask = readw(ofsAddr + RX_mask);
2520	spage = readw(ofsAddr + Page_rxb);
2521	epage = readw(ofsAddr + EndPage_rxb);
2522	count = (tail >= head) ? (tail - head)
2523	    : (tail - head + rx_mask + 1);
2524	if (count == 0)
2525		return (0);
2526
2527	total = (space > count) ? count : space;
2528	remain = count - total;
2529	moxaLog.rxcnt[port] += total;
2530	count = total;
2531	if (spage == epage) {
2532		bufhead = readw(ofsAddr + Ofs_rxb);
2533		writew(spage, baseAddr + Control_reg);
2534		while (count > 0) {
2535			if (tail >= head)
2536				len = tail - head;
2537			else
2538				len = rx_mask + 1 - head;
2539			len = (count > len) ? len : count;
2540			ofs = baseAddr + DynPage_addr + bufhead + head;
2541			for (i = 0; i < len; i++)
2542				*buffer++ = readb(ofs + i);
2543			head = (head + len) & rx_mask;
2544			count -= len;
2545		}
2546		writew(head, ofsAddr + RXrptr);
2547	} else {
2548		len = count;
2549		pageno = spage + (head >> 13);
2550		pageofs = head & Page_mask;
2551		do {
2552			cnt = Page_size - pageofs;
2553			if (cnt > count)
2554				cnt = count;
2555			count -= cnt;
2556			writew(pageno, baseAddr + Control_reg);
2557			ofs = baseAddr + DynPage_addr + pageofs;
2558			for (i = 0; i < cnt; i++)
2559				*buffer++ = readb(ofs + i);
2560			if (count == 0) {
2561				writew((head + len) & rx_mask, ofsAddr + RXrptr);
2562				break;
2563			}
2564			if (++pageno == epage)
2565				pageno = spage;
2566			pageofs = 0;
2567		} while (1);
2568	}
2569	if ((readb(ofsAddr + FlagStat) & Xoff_state) && (remain < LowWater)) {
2570		moxaLowWaterChk = 1;
2571		moxaLowChkFlag[port] = 1;
2572	}
2573	return (total);
2574}
2575
2576
2577int MoxaPortTxQueue(int port)
2578{
2579	void __iomem *ofsAddr;
2580	ushort rptr, wptr, mask;
2581	int len;
2582
2583	ofsAddr = moxaTableAddr[port];
2584	rptr = readw(ofsAddr + TXrptr);
2585	wptr = readw(ofsAddr + TXwptr);
2586	mask = readw(ofsAddr + TX_mask);
2587	len = (wptr - rptr) & mask;
2588	return (len);
2589}
2590
2591int MoxaPortTxFree(int port)
2592{
2593	void __iomem *ofsAddr;
2594	ushort rptr, wptr, mask;
2595	int len;
2596
2597	ofsAddr = moxaTableAddr[port];
2598	rptr = readw(ofsAddr + TXrptr);
2599	wptr = readw(ofsAddr + TXwptr);
2600	mask = readw(ofsAddr + TX_mask);
2601	len = mask - ((wptr - rptr) & mask);
2602	return (len);
2603}
2604
2605int MoxaPortRxQueue(int port)
2606{
2607	void __iomem *ofsAddr;
2608	ushort rptr, wptr, mask;
2609	int len;
2610
2611	ofsAddr = moxaTableAddr[port];
2612	rptr = readw(ofsAddr + RXrptr);
2613	wptr = readw(ofsAddr + RXwptr);
2614	mask = readw(ofsAddr + RX_mask);
2615	len = (wptr - rptr) & mask;
2616	return (len);
2617}
2618
2619
2620void MoxaPortTxDisable(int port)
2621{
2622	void __iomem *ofsAddr;
2623
2624	ofsAddr = moxaTableAddr[port];
2625	moxafunc(ofsAddr, FC_SetXoffState, Magic_code);
2626}
2627
2628void MoxaPortTxEnable(int port)
2629{
2630	void __iomem *ofsAddr;
2631
2632	ofsAddr = moxaTableAddr[port];
2633	moxafunc(ofsAddr, FC_SetXonState, Magic_code);
2634}
2635
2636
2637int MoxaPortResetBrkCnt(int port)
2638{
2639	ushort cnt;
2640	cnt = moxaBreakCnt[port];
2641	moxaBreakCnt[port] = 0;
2642	return (cnt);
2643}
2644
2645
2646void MoxaPortSendBreak(int port, int ms100)
2647{
2648	void __iomem *ofsAddr;
2649
2650	ofsAddr = moxaTableAddr[port];
2651	if (ms100) {
2652		moxafunc(ofsAddr, FC_SendBreak, Magic_code);
2653		moxadelay(ms100 * (HZ / 10));
2654	} else {
2655		moxafunc(ofsAddr, FC_SendBreak, Magic_code);
2656		moxadelay(HZ / 4);	/* 250 ms */
2657	}
2658	moxafunc(ofsAddr, FC_StopBreak, Magic_code);
2659}
2660
2661static int moxa_get_serial_info(struct moxa_str *info,
2662				struct serial_struct __user *retinfo)
2663{
2664	struct serial_struct tmp;
2665
2666	memset(&tmp, 0, sizeof(tmp));
2667	tmp.type = info->type;
2668	tmp.line = info->port;
2669	tmp.port = 0;
2670	tmp.irq = 0;
2671	tmp.flags = info->asyncflags;
2672	tmp.baud_base = 921600;
2673	tmp.close_delay = info->close_delay;
2674	tmp.closing_wait = info->closing_wait;
2675	tmp.custom_divisor = 0;
2676	tmp.hub6 = 0;
2677	if(copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
2678		return -EFAULT;
2679	return (0);
2680}
2681
2682
2683static int moxa_set_serial_info(struct moxa_str *info,
2684				struct serial_struct __user *new_info)
2685{
2686	struct serial_struct new_serial;
2687
2688	if(copy_from_user(&new_serial, new_info, sizeof(new_serial)))
2689		return -EFAULT;
2690
2691	if ((new_serial.irq != 0) ||
2692	    (new_serial.port != 0) ||
2693//           (new_serial.type != info->type) ||
2694	    (new_serial.custom_divisor != 0) ||
2695	    (new_serial.baud_base != 921600))
2696		return (-EPERM);
2697
2698	if (!capable(CAP_SYS_ADMIN)) {
2699		if (((new_serial.flags & ~ASYNC_USR_MASK) !=
2700		     (info->asyncflags & ~ASYNC_USR_MASK)))
2701			return (-EPERM);
2702	} else {
2703		info->close_delay = new_serial.close_delay * HZ / 100;
2704		info->closing_wait = new_serial.closing_wait * HZ / 100;
2705	}
2706
2707	new_serial.flags = (new_serial.flags & ~ASYNC_FLAGS);
2708	new_serial.flags |= (info->asyncflags & ASYNC_FLAGS);
2709
2710	if (new_serial.type == PORT_16550A) {
2711		MoxaSetFifo(info->port, 1);
2712	} else {
2713		MoxaSetFifo(info->port, 0);
2714	}
2715
2716	info->type = new_serial.type;
2717	return (0);
2718}
2719
2720
2721
2722/*****************************************************************************
2723 *	Static local functions: 					     *
2724 *****************************************************************************/
2725/*
2726 * moxadelay - delays a specified number ticks
2727 */
2728static void moxadelay(int tick)
2729{
2730	unsigned long st, et;
2731
2732	st = jiffies;
2733	et = st + tick;
2734	while (time_before(jiffies, et));
2735}
2736
2737static void moxafunc(void __iomem *ofsAddr, int cmd, ushort arg)
2738{
2739
2740	writew(arg, ofsAddr + FuncArg);
2741	writew(cmd, ofsAddr + FuncCode);
2742	wait_finish(ofsAddr);
2743}
2744
2745static void wait_finish(void __iomem *ofsAddr)
2746{
2747	unsigned long i, j;
2748
2749	i = jiffies;
2750	while (readw(ofsAddr + FuncCode) != 0) {
2751		j = jiffies;
2752		if ((j - i) > moxaFuncTout) {
2753			return;
2754		}
2755	}
2756}
2757
2758static void low_water_check(void __iomem *ofsAddr)
2759{
2760	int len;
2761	ushort rptr, wptr, mask;
2762
2763	if (readb(ofsAddr + FlagStat) & Xoff_state) {
2764		rptr = readw(ofsAddr + RXrptr);
2765		wptr = readw(ofsAddr + RXwptr);
2766		mask = readw(ofsAddr + RX_mask);
2767		len = (wptr - rptr) & mask;
2768		if (len <= Low_water)
2769			moxafunc(ofsAddr, FC_SendXon, 0);
2770	}
2771}
2772
2773static int moxaloadbios(int cardno, unsigned char __user *tmp, int len)
2774{
2775	void __iomem *baseAddr;
2776	int i;
2777
2778	if(copy_from_user(moxaBuff, tmp, len))
2779		return -EFAULT;
2780	baseAddr = moxaBaseAddr[cardno];
2781	writeb(HW_reset, baseAddr + Control_reg);	/* reset */
2782	moxadelay(1);		/* delay 10 ms */
2783	for (i = 0; i < 4096; i++)
2784		writeb(0, baseAddr + i);	/* clear fix page */
2785	for (i = 0; i < len; i++)
2786		writeb(moxaBuff[i], baseAddr + i);	/* download BIOS */
2787	writeb(0, baseAddr + Control_reg);	/* restart */
2788	return (0);
2789}
2790
2791static int moxafindcard(int cardno)
2792{
2793	void __iomem *baseAddr;
2794	ushort tmp;
2795
2796	baseAddr = moxaBaseAddr[cardno];
2797	switch (moxa_boards[cardno].boardType) {
2798	case MOXA_BOARD_C218_ISA:
2799	case MOXA_BOARD_C218_PCI:
2800		if ((tmp = readw(baseAddr + C218_key)) != C218_KeyCode) {
2801			return (-1);
2802		}
2803		break;
2804	case MOXA_BOARD_CP204J:
2805		if ((tmp = readw(baseAddr + C218_key)) != CP204J_KeyCode) {
2806			return (-1);
2807		}
2808		break;
2809	default:
2810		if ((tmp = readw(baseAddr + C320_key)) != C320_KeyCode) {
2811			return (-1);
2812		}
2813		if ((tmp = readw(baseAddr + C320_status)) != STS_init) {
2814			return (-2);
2815		}
2816	}
2817	return (0);
2818}
2819
2820static int moxaload320b(int cardno, unsigned char __user *tmp, int len)
2821{
2822	void __iomem *baseAddr;
2823	int i;
2824
2825	if(len > sizeof(moxaBuff))
2826		return -EINVAL;
2827	if(copy_from_user(moxaBuff, tmp, len))
2828		return -EFAULT;
2829	baseAddr = moxaBaseAddr[cardno];
2830	writew(len - 7168 - 2, baseAddr + C320bapi_len);
2831	writeb(1, baseAddr + Control_reg);	/* Select Page 1 */
2832	for (i = 0; i < 7168; i++)
2833		writeb(moxaBuff[i], baseAddr + DynPage_addr + i);
2834	writeb(2, baseAddr + Control_reg);	/* Select Page 2 */
2835	for (i = 0; i < (len - 7168); i++)
2836		writeb(moxaBuff[i + 7168], baseAddr + DynPage_addr + i);
2837	return (0);
2838}
2839
2840static int moxaloadcode(int cardno, unsigned char __user *tmp, int len)
2841{
2842	void __iomem *baseAddr, *ofsAddr;
2843	int retval, port, i;
2844
2845	if(copy_from_user(moxaBuff, tmp, len))
2846		return -EFAULT;
2847	baseAddr = moxaBaseAddr[cardno];
2848	switch (moxa_boards[cardno].boardType) {
2849	case MOXA_BOARD_C218_ISA:
2850	case MOXA_BOARD_C218_PCI:
2851	case MOXA_BOARD_CP204J:
2852		retval = moxaloadc218(cardno, baseAddr, len);
2853		if (retval)
2854			return (retval);
2855		port = cardno * MAX_PORTS_PER_BOARD;
2856		for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) {
2857			moxaChkPort[port] = 1;
2858			moxaCurBaud[port] = 9600L;
2859			moxaDCDState[port] = 0;
2860			moxaTableAddr[port] = baseAddr + Extern_table + Extern_size * i;
2861			ofsAddr = moxaTableAddr[port];
2862			writew(C218rx_mask, ofsAddr + RX_mask);
2863			writew(C218tx_mask, ofsAddr + TX_mask);
2864			writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb);
2865			writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb);
2866
2867			writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb);
2868			writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb);
2869
2870		}
2871		break;
2872	default:
2873		retval = moxaloadc320(cardno, baseAddr, len,
2874				      &moxa_boards[cardno].numPorts);
2875		if (retval)
2876			return (retval);
2877		port = cardno * MAX_PORTS_PER_BOARD;
2878		for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) {
2879			moxaChkPort[port] = 1;
2880			moxaCurBaud[port] = 9600L;
2881			moxaDCDState[port] = 0;
2882			moxaTableAddr[port] = baseAddr + Extern_table + Extern_size * i;
2883			ofsAddr = moxaTableAddr[port];
2884			if (moxa_boards[cardno].numPorts == 8) {
2885				writew(C320p8rx_mask, ofsAddr + RX_mask);
2886				writew(C320p8tx_mask, ofsAddr + TX_mask);
2887				writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb);
2888				writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb);
2889				writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb);
2890				writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb);
2891
2892			} else if (moxa_boards[cardno].numPorts == 16) {
2893				writew(C320p16rx_mask, ofsAddr + RX_mask);
2894				writew(C320p16tx_mask, ofsAddr + TX_mask);
2895				writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb);
2896				writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb);
2897				writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb);
2898				writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb);
2899
2900			} else if (moxa_boards[cardno].numPorts == 24) {
2901				writew(C320p24rx_mask, ofsAddr + RX_mask);
2902				writew(C320p24tx_mask, ofsAddr + TX_mask);
2903				writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb);
2904				writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb);
2905				writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb);
2906				writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
2907			} else if (moxa_boards[cardno].numPorts == 32) {
2908				writew(C320p32rx_mask, ofsAddr + RX_mask);
2909				writew(C320p32tx_mask, ofsAddr + TX_mask);
2910				writew(C320p32tx_ofs, ofsAddr + Ofs_txb);
2911				writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb);
2912				writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb);
2913				writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb);
2914				writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
2915			}
2916		}
2917		break;
2918	}
2919	return (0);
2920}
2921
2922static int moxaloadc218(int cardno, void __iomem *baseAddr, int len)
2923{
2924	char retry;
2925	int i, j, len1, len2;
2926	ushort usum, *ptr, keycode;
2927
2928	if (moxa_boards[cardno].boardType == MOXA_BOARD_CP204J)
2929		keycode = CP204J_KeyCode;
2930	else
2931		keycode = C218_KeyCode;
2932	usum = 0;
2933	len1 = len >> 1;
2934	ptr = (ushort *) moxaBuff;
2935	for (i = 0; i < len1; i++)
2936		usum += *(ptr + i);
2937	retry = 0;
2938	do {
2939		len1 = len >> 1;
2940		j = 0;
2941		while (len1) {
2942			len2 = (len1 > 2048) ? 2048 : len1;
2943			len1 -= len2;
2944			for (i = 0; i < len2 << 1; i++)
2945				writeb(moxaBuff[i + j], baseAddr + C218_LoadBuf + i);
2946			j += i;
2947
2948			writew(len2, baseAddr + C218DLoad_len);
2949			writew(0, baseAddr + C218_key);
2950			for (i = 0; i < 100; i++) {
2951				if (readw(baseAddr + C218_key) == keycode)
2952					break;
2953				moxadelay(1);	/* delay 10 ms */
2954			}
2955			if (readw(baseAddr + C218_key) != keycode) {
2956				return (-1);
2957			}
2958		}
2959		writew(0, baseAddr + C218DLoad_len);
2960		writew(usum, baseAddr + C218check_sum);
2961		writew(0, baseAddr + C218_key);
2962		for (i = 0; i < 100; i++) {
2963			if (readw(baseAddr + C218_key) == keycode)
2964				break;
2965			moxadelay(1);	/* delay 10 ms */
2966		}
2967		retry++;
2968	} while ((readb(baseAddr + C218chksum_ok) != 1) && (retry < 3));
2969	if (readb(baseAddr + C218chksum_ok) != 1) {
2970		return (-1);
2971	}
2972	writew(0, baseAddr + C218_key);
2973	for (i = 0; i < 100; i++) {
2974		if (readw(baseAddr + Magic_no) == Magic_code)
2975			break;
2976		moxadelay(1);	/* delay 10 ms */
2977	}
2978	if (readw(baseAddr + Magic_no) != Magic_code) {
2979		return (-1);
2980	}
2981	writew(1, baseAddr + Disable_IRQ);
2982	writew(0, baseAddr + Magic_no);
2983	for (i = 0; i < 100; i++) {
2984		if (readw(baseAddr + Magic_no) == Magic_code)
2985			break;
2986		moxadelay(1);	/* delay 10 ms */
2987	}
2988	if (readw(baseAddr + Magic_no) != Magic_code) {
2989		return (-1);
2990	}
2991	moxaCard = 1;
2992	moxaIntNdx[cardno] = baseAddr + IRQindex;
2993	moxaIntPend[cardno] = baseAddr + IRQpending;
2994	moxaIntTable[cardno] = baseAddr + IRQtable;
2995	return (0);
2996}
2997
2998static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPorts)
2999{
3000	ushort usum;
3001	int i, j, wlen, len2, retry;
3002	ushort *uptr;
3003
3004	usum = 0;
3005	wlen = len >> 1;
3006	uptr = (ushort *) moxaBuff;
3007	for (i = 0; i < wlen; i++)
3008		usum += uptr[i];
3009	retry = 0;
3010	j = 0;
3011	do {
3012		while (wlen) {
3013			if (wlen > 2048)
3014				len2 = 2048;
3015			else
3016				len2 = wlen;
3017			wlen -= len2;
3018			len2 <<= 1;
3019			for (i = 0; i < len2; i++)
3020				writeb(moxaBuff[j + i], baseAddr + C320_LoadBuf + i);
3021			len2 >>= 1;
3022			j += i;
3023			writew(len2, baseAddr + C320DLoad_len);
3024			writew(0, baseAddr + C320_key);
3025			for (i = 0; i < 10; i++) {
3026				if (readw(baseAddr + C320_key) == C320_KeyCode)
3027					break;
3028				moxadelay(1);
3029			}
3030			if (readw(baseAddr + C320_key) != C320_KeyCode)
3031				return (-1);
3032		}
3033		writew(0, baseAddr + C320DLoad_len);
3034		writew(usum, baseAddr + C320check_sum);
3035		writew(0, baseAddr + C320_key);
3036		for (i = 0; i < 10; i++) {
3037			if (readw(baseAddr + C320_key) == C320_KeyCode)
3038				break;
3039			moxadelay(1);
3040		}
3041		retry++;
3042	} while ((readb(baseAddr + C320chksum_ok) != 1) && (retry < 3));
3043	if (readb(baseAddr + C320chksum_ok) != 1)
3044		return (-1);
3045	writew(0, baseAddr + C320_key);
3046	for (i = 0; i < 600; i++) {
3047		if (readw(baseAddr + Magic_no) == Magic_code)
3048			break;
3049		moxadelay(1);
3050	}
3051	if (readw(baseAddr + Magic_no) != Magic_code)
3052		return (-100);
3053
3054	if (moxa_boards[cardno].busType == MOXA_BUS_TYPE_PCI) {		/* ASIC board */
3055		writew(0x3800, baseAddr + TMS320_PORT1);
3056		writew(0x3900, baseAddr + TMS320_PORT2);
3057		writew(28499, baseAddr + TMS320_CLOCK);
3058	} else {
3059		writew(0x3200, baseAddr + TMS320_PORT1);
3060		writew(0x3400, baseAddr + TMS320_PORT2);
3061		writew(19999, baseAddr + TMS320_CLOCK);
3062	}
3063	writew(1, baseAddr + Disable_IRQ);
3064	writew(0, baseAddr + Magic_no);
3065	for (i = 0; i < 500; i++) {
3066		if (readw(baseAddr + Magic_no) == Magic_code)
3067			break;
3068		moxadelay(1);
3069	}
3070	if (readw(baseAddr + Magic_no) != Magic_code)
3071		return (-102);
3072
3073	j = readw(baseAddr + Module_cnt);
3074	if (j <= 0)
3075		return (-101);
3076	*numPorts = j * 8;
3077	writew(j, baseAddr + Module_no);
3078	writew(0, baseAddr + Magic_no);
3079	for (i = 0; i < 600; i++) {
3080		if (readw(baseAddr + Magic_no) == Magic_code)
3081			break;
3082		moxadelay(1);
3083	}
3084	if (readw(baseAddr + Magic_no) != Magic_code)
3085		return (-102);
3086	moxaCard = 1;
3087	moxaIntNdx[cardno] = baseAddr + IRQindex;
3088	moxaIntPend[cardno] = baseAddr + IRQpending;
3089	moxaIntTable[cardno] = baseAddr + IRQtable;
3090	return (0);
3091}
3092
3093#if 0
3094long MoxaPortGetCurBaud(int port)
3095{
3096
3097	if (moxaChkPort[port] == 0)
3098		return (0);
3099	return (moxaCurBaud[port]);
3100}
3101#endif  /*  0  */
3102
3103static void MoxaSetFifo(int port, int enable)
3104{
3105	void __iomem *ofsAddr = moxaTableAddr[port];
3106
3107	if (!enable) {
3108		moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0);
3109		moxafunc(ofsAddr, FC_SetTxFIFOCnt, 1);
3110	} else {
3111		moxafunc(ofsAddr, FC_SetRxFIFOTrig, 3);
3112		moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16);
3113	}
3114}
3115
3116#if 0
3117int MoxaPortSetMode(int port, int databits, int stopbits, int parity)
3118{
3119	void __iomem *ofsAddr;
3120	int val;
3121
3122	val = 0;
3123	switch (databits) {
3124	case 5:
3125		val |= 0;
3126		break;
3127	case 6:
3128		val |= 1;
3129		break;
3130	case 7:
3131		val |= 2;
3132		break;
3133	case 8:
3134		val |= 3;
3135		break;
3136	default:
3137		return (-1);
3138	}
3139	switch (stopbits) {
3140	case 0:
3141		val |= 0;
3142		break;		/* stop bits 1.5 */
3143	case 1:
3144		val |= 0;
3145		break;
3146	case 2:
3147		val |= 4;
3148		break;
3149	default:
3150		return (-1);
3151	}
3152	switch (parity) {
3153	case 0:
3154		val |= 0x00;
3155		break;		/* None  */
3156	case 1:
3157		val |= 0x08;
3158		break;		/* Odd   */
3159	case 2:
3160		val |= 0x18;
3161		break;		/* Even  */
3162	case 3:
3163		val |= 0x28;
3164		break;		/* Mark  */
3165	case 4:
3166		val |= 0x38;
3167		break;		/* Space */
3168	default:
3169		return (-1);
3170	}
3171	ofsAddr = moxaTableAddr[port];
3172	moxafunc(ofsAddr, FC_SetMode, val);
3173	return (0);
3174}
3175
3176int MoxaPortTxBufSize(int port)
3177{
3178	void __iomem *ofsAddr;
3179	int size;
3180
3181	ofsAddr = moxaTableAddr[port];
3182	size = readw(ofsAddr + TX_mask);
3183	return (size);
3184}
3185
3186int MoxaPortRxBufSize(int port)
3187{
3188	void __iomem *ofsAddr;
3189	int size;
3190
3191	ofsAddr = moxaTableAddr[port];
3192	size = readw(ofsAddr + RX_mask);
3193	return (size);
3194}
3195
3196int MoxaPortRxFree(int port)
3197{
3198	void __iomem *ofsAddr;
3199	ushort rptr, wptr, mask;
3200	int len;
3201
3202	ofsAddr = moxaTableAddr[port];
3203	rptr = readw(ofsAddr + RXrptr);
3204	wptr = readw(ofsAddr + RXwptr);
3205	mask = readw(ofsAddr + RX_mask);
3206	len = mask - ((wptr - rptr) & mask);
3207	return (len);
3208}
3209int MoxaPortGetBrkCnt(int port)
3210{
3211	return (moxaBreakCnt[port]);
3212}
3213
3214void MoxaPortSetXonXoff(int port, int xonValue, int xoffValue)
3215{
3216	void __iomem *ofsAddr;
3217
3218	ofsAddr = moxaTableAddr[port];
3219	writew(xonValue, ofsAddr + FuncArg);
3220	writew(xoffValue, ofsAddr + FuncArg1);
3221	writew(FC_SetXonXoff, ofsAddr + FuncCode);
3222	wait_finish(ofsAddr);
3223}
3224
3225int MoxaPortIsTxHold(int port)
3226{
3227	void __iomem *ofsAddr;
3228	int val;
3229
3230	ofsAddr = moxaTableAddr[port];
3231	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
3232	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
3233		moxafunc(ofsAddr, FC_GetCCSR, 0);
3234		val = readw(ofsAddr + FuncArg);
3235		if (val & 0x04)
3236			return (1);
3237	} else {
3238		if (readw(ofsAddr + FlagStat) & Tx_flowOff)
3239			return (1);
3240	}
3241	return (0);
3242}
3243#endif
3244