moxa.c revision 037182346f0991683cc7320a257c3f6089432cee
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * moxa.c -- MOXA Intellio family multiport serial driver. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999-2000 Moxa Technologies (support@moxa.com.tw). 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This code is loosely based on the Linux serial driver, written by 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Linus Torvalds, Theodore T'so and others. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version. 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MOXA Intellio Series Driver 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for : LINUX 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * date : 1999/1/7 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * version : 5.1 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 28037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#include <linux/firmware.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/signal.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_flip.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/major.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fcntl.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ptrace.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/serial.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_driver.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h> 4595e0791480af8347460d0cbe34a46eca7e77d0d0Jiri Slaby#include <linux/completion.h> 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h> 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#include "moxa.h" 52037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 5311324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MOXA_VERSION "5.1k" 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 55037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#define MOXA_FW_HDRLEN 32 56037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 5711324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MOXAMAJOR 172 5811324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MOXACUMAJOR 173 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6011324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MAX_BOARDS 4 /* Don't change this value */ 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_PORTS_PER_BOARD 32 /* Don't change this value */ 6211324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MAX_PORTS (MAX_BOARDS * MAX_PORTS_PER_BOARD) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Define the Moxa PCI vendor and device IDs. 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6711324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MOXA_BUS_TYPE_ISA 0 6811324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MOXA_BUS_TYPE_PCI 1 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum { 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MOXA_BOARD_C218_PCI = 1, 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MOXA_BOARD_C218_ISA, 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MOXA_BOARD_C320_PCI, 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MOXA_BOARD_C320_ISA, 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MOXA_BOARD_CP204J, 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *moxa_brdname[] = 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "C218 Turbo PCI series", 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "C218 Turbo ISA series", 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "C320 Turbo PCI series", 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "C320 Turbo ISA series", 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CP-204J series", 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_device_id moxa_pcibrds[] = { 895ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C218), 905ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby .driver_data = MOXA_BOARD_C218_PCI }, 915ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C320), 925ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby .driver_data = MOXA_BOARD_C320_PCI }, 935ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP204J), 945ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby .driver_data = MOXA_BOARD_CP204J }, 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0 } 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, moxa_pcibrds); 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_PCI */ 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 100037182346f0991683cc7320a257c3f6089432ceeJiri Slabystruct moxa_port; 101037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 1028f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic struct moxa_board_conf { 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int boardType; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int numPorts; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int busType; 1068f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby 1078f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int loadstat; 1088f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby 109037182346f0991683cc7320a257c3f6089432ceeJiri Slaby struct moxa_port *ports; 110037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 1118f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby void __iomem *basemem; 1128f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby void __iomem *intNdx; 1138f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby void __iomem *intPend; 1148f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby void __iomem *intTable; 1158f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby} moxa_boards[MAX_BOARDS]; 1168f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby 1178f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystruct mxser_mstatus { 1188f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby tcflag_t cflag; 1198f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int cts; 1208f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int dsr; 1218f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int ri; 1228f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int dcd; 1239dff89cd82af7bccc706fed288b1c33a51c3b937Jiri Slaby}; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1258f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystruct moxaq_str { 1268f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int inq; 1278f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int outq; 1288f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby}; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1308f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystruct moxa_port { 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int type; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int port; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int close_delay; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short closing_wait; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int count; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int blocked_open; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long event; /* long req'd for set_bit --RR */ 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int asyncflags; 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long statusflags; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tty_struct *tty; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int cflag; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_queue_head_t open_wait; 14395e0791480af8347460d0cbe34a46eca7e77d0d0Jiri Slaby struct completion close_wait; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1458f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct timer_list emptyTimer; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1478f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby char chkPort; 1488f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby char lineCtrl; 1498f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby void __iomem *tableAddr; 1508f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby long curBaud; 1518f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby char DCDState; 1528f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby char lowChkFlag; 1538f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby 1548f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ushort breakCnt; 1558f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby}; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* statusflags */ 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXSTOPPED 0x1 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LOWWAIT 0x2 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EMPTYWAIT 0x4 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define THROTTLE 0x8 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SERIAL_DO_RESTART 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WAKEUP_CHARS 256 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ttymajor = MOXAMAJOR; 168037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxaCard; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Variables for insmod */ 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE 171d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabystatic unsigned long baseaddr[MAX_BOARDS]; 172d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabystatic unsigned int type[MAX_BOARDS]; 173d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabystatic unsigned int numports[MAX_BOARDS]; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("William Chen"); 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver"); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE 180d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabymodule_param_array(type, uint, NULL, 0); 181d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri SlabyMODULE_PARM_DESC(type, "card type: C218=2, C320=4"); 182d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabymodule_param_array(baseaddr, ulong, NULL, 0); 183d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri SlabyMODULE_PARM_DESC(baseaddr, "base address"); 184d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabymodule_param_array(numports, uint, NULL, 0); 185d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri SlabyMODULE_PARM_DESC(numports, "numports (ignored for C218)"); 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(ttymajor, int, 0); 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * static functions: 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_open(struct tty_struct *, struct file *); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_close(struct tty_struct *, struct file *); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_write(struct tty_struct *, const unsigned char *, int); 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_write_room(struct tty_struct *); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_flush_buffer(struct tty_struct *); 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_chars_in_buffer(struct tty_struct *); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_flush_chars(struct tty_struct *); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_put_char(struct tty_struct *, unsigned char); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_throttle(struct tty_struct *); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_unthrottle(struct tty_struct *); 203606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Coxstatic void moxa_set_termios(struct tty_struct *, struct ktermios *); 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_stop(struct tty_struct *); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_start(struct tty_struct *); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_hangup(struct tty_struct *); 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_tiocmget(struct tty_struct *tty, struct file *file); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_tiocmset(struct tty_struct *tty, struct file *file, 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int set, unsigned int clear); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_poll(unsigned long); 211db1acaa632870ec87b65e062bc72ca375837a1f6Alan Coxstatic void moxa_set_tty_param(struct tty_struct *, struct ktermios *); 2126f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic int moxa_block_till_ready(struct tty_struct *, struct file *, 2138f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *); 2146f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic void moxa_setup_empty_event(struct tty_struct *); 2156f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic void moxa_check_xmit_empty(unsigned long); 2166f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic void moxa_shut_down(struct moxa_port *); 2176f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic void moxa_receive_data(struct moxa_port *); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * moxa board interface functions: 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaDriverIoctl(unsigned int, unsigned long, int); 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaDriverPoll(void); 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortsOfCard(int); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortIsValid(int); 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaPortEnable(int); 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaPortDisable(int); 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic long MoxaPortGetMaxBaud(int); 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic long MoxaPortSetBaud(int, long); 229606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Coxstatic int MoxaPortSetTermio(int, struct ktermios *, speed_t); 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortGetLineOut(int, int *, int *); 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaPortLineCtrl(int, int, int); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaPortFlowCtrl(int, int, int, int, int, int); 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortLineStatus(int); 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortDCDChange(int); 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortDCDON(int); 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaPortFlushData(int, int); 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortWriteData(int, unsigned char *, int); 23833f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Coxstatic int MoxaPortReadData(int, struct tty_struct *tty); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortTxQueue(int); 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortRxQueue(int); 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortTxFree(int); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaPortTxDisable(int); 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaPortTxEnable(int); 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int MoxaPortResetBrkCnt(int); 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaPortSendBreak(int, int); 2468f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic int moxa_get_serial_info(struct moxa_port *, struct serial_struct __user *); 2478f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic int moxa_set_serial_info(struct moxa_port *, struct serial_struct __user *); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaSetFifo(int port, int enable); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 250b68e31d0ebbcc909d1941f9f230c9d062a3a13d3Jeff Dikestatic const struct tty_operations moxa_ops = { 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .open = moxa_open, 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .close = moxa_close, 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write = moxa_write, 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write_room = moxa_write_room, 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .flush_buffer = moxa_flush_buffer, 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chars_in_buffer = moxa_chars_in_buffer, 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .flush_chars = moxa_flush_chars, 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .put_char = moxa_put_char, 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .ioctl = moxa_ioctl, 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .throttle = moxa_throttle, 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .unthrottle = moxa_unthrottle, 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_termios = moxa_set_termios, 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .stop = moxa_stop, 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .start = moxa_start, 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hangup = moxa_hangup, 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .tiocmget = moxa_tiocmget, 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .tiocmset = moxa_tiocmset, 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 270aa7e5221fb47badbea618cc62704d6e4a4bcce15Jiri Slabystatic struct tty_driver *moxaDriver; 2718f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic struct moxa_port moxa_ports[MAX_PORTS]; 272aa7e5221fb47badbea618cc62704d6e4a4bcce15Jiri Slabystatic DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); 27334af946a22724c4e2b204957f2b24b22a0fb121cIngo Molnarstatic DEFINE_SPINLOCK(moxa_lock); 27433f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox 275037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_check_fw_model(struct moxa_board_conf *brd, u8 model) 276037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 277037182346f0991683cc7320a257c3f6089432ceeJiri Slaby switch (brd->boardType) { 278037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_ISA: 279037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_PCI: 280037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (model != 1) 281037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 282037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 283037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_CP204J: 284037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (model != 3) 285037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 286037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 287037182346f0991683cc7320a257c3f6089432ceeJiri Slaby default: 288037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (model != 2) 289037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 290037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 291037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 292037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 293037182346f0991683cc7320a257c3f6089432ceeJiri Slabyerr: 294037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EINVAL; 295037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 296037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 297037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_check_fw(const void *ptr) 298037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 299037182346f0991683cc7320a257c3f6089432ceeJiri Slaby const __le16 *lptr = ptr; 300037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 301037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (*lptr != cpu_to_le16(0x7980)) 302037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EINVAL; 303037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 304037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 305037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 306037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 307037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_load_bios(struct moxa_board_conf *brd, const u8 *buf, 308037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t len) 309037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 310037182346f0991683cc7320a257c3f6089432ceeJiri Slaby void __iomem *baseAddr = brd->basemem; 311037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u16 tmp; 312037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 313037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writeb(HW_reset, baseAddr + Control_reg); /* reset */ 314037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 315037182346f0991683cc7320a257c3f6089432ceeJiri Slaby memset_io(baseAddr, 0, 4096); 316037182346f0991683cc7320a257c3f6089432ceeJiri Slaby memcpy_toio(baseAddr, buf, len); /* download BIOS */ 317037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writeb(0, baseAddr + Control_reg); /* restart */ 318037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 319037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(2000); 320037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 321037182346f0991683cc7320a257c3f6089432ceeJiri Slaby switch (brd->boardType) { 322037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_ISA: 323037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_PCI: 324037182346f0991683cc7320a257c3f6089432ceeJiri Slaby tmp = readw(baseAddr + C218_key); 325037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (tmp != C218_KeyCode) 326037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 327037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 328037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_CP204J: 329037182346f0991683cc7320a257c3f6089432ceeJiri Slaby tmp = readw(baseAddr + C218_key); 330037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (tmp != CP204J_KeyCode) 331037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 332037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 333037182346f0991683cc7320a257c3f6089432ceeJiri Slaby default: 334037182346f0991683cc7320a257c3f6089432ceeJiri Slaby tmp = readw(baseAddr + C320_key); 335037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (tmp != C320_KeyCode) 336037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 337037182346f0991683cc7320a257c3f6089432ceeJiri Slaby tmp = readw(baseAddr + C320_status); 338037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (tmp != STS_init) { 339037182346f0991683cc7320a257c3f6089432ceeJiri Slaby printk(KERN_ERR "moxa: bios upload failed -- CPU/Basic " 340037182346f0991683cc7320a257c3f6089432ceeJiri Slaby "module not found\n"); 341037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 342037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 343037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 344037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 345037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 346037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 347037182346f0991683cc7320a257c3f6089432ceeJiri Slabyerr: 348037182346f0991683cc7320a257c3f6089432ceeJiri Slaby printk(KERN_ERR "moxa: bios upload failed -- board not found\n"); 349037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 350037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 351037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 352037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_load_320b(struct moxa_board_conf *brd, const u8 *ptr, 353037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t len) 354037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 355037182346f0991683cc7320a257c3f6089432ceeJiri Slaby void __iomem *baseAddr = brd->basemem; 356037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 357037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (len < 7168) { 358037182346f0991683cc7320a257c3f6089432ceeJiri Slaby printk(KERN_ERR "moxa: invalid 320 bios -- too short\n"); 359037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EINVAL; 360037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 361037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 362037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(len - 7168 - 2, baseAddr + C320bapi_len); 363037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writeb(1, baseAddr + Control_reg); /* Select Page 1 */ 364037182346f0991683cc7320a257c3f6089432ceeJiri Slaby memcpy_toio(baseAddr + DynPage_addr, ptr, 7168); 365037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writeb(2, baseAddr + Control_reg); /* Select Page 2 */ 366037182346f0991683cc7320a257c3f6089432ceeJiri Slaby memcpy_toio(baseAddr + DynPage_addr, ptr + 7168, len - 7168); 367037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 368037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 369037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 370037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 371037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_load_c218(struct moxa_board_conf *brd, const void *ptr, 372037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t len) 373037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 374037182346f0991683cc7320a257c3f6089432ceeJiri Slaby void __iomem *baseAddr = brd->basemem; 375037182346f0991683cc7320a257c3f6089432ceeJiri Slaby const u16 *uptr = ptr; 376037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t wlen, len2, j; 377037182346f0991683cc7320a257c3f6089432ceeJiri Slaby unsigned int i, retry; 378037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u16 usum, keycode; 379037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 380037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (brd->boardType == MOXA_BOARD_CP204J) 381037182346f0991683cc7320a257c3f6089432ceeJiri Slaby keycode = CP204J_KeyCode; 382037182346f0991683cc7320a257c3f6089432ceeJiri Slaby else 383037182346f0991683cc7320a257c3f6089432ceeJiri Slaby keycode = C218_KeyCode; 384037182346f0991683cc7320a257c3f6089432ceeJiri Slaby usum = 0; 385037182346f0991683cc7320a257c3f6089432ceeJiri Slaby wlen = len >> 1; 386037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < wlen; i++) 387037182346f0991683cc7320a257c3f6089432ceeJiri Slaby usum += le16_to_cpu(uptr[i]); 388037182346f0991683cc7320a257c3f6089432ceeJiri Slaby retry = 0; 389037182346f0991683cc7320a257c3f6089432ceeJiri Slaby do { 390037182346f0991683cc7320a257c3f6089432ceeJiri Slaby wlen = len >> 1; 391037182346f0991683cc7320a257c3f6089432ceeJiri Slaby j = 0; 392037182346f0991683cc7320a257c3f6089432ceeJiri Slaby while (wlen) { 393037182346f0991683cc7320a257c3f6089432ceeJiri Slaby len2 = (wlen > 2048) ? 2048 : wlen; 394037182346f0991683cc7320a257c3f6089432ceeJiri Slaby wlen -= len2; 395037182346f0991683cc7320a257c3f6089432ceeJiri Slaby memcpy_toio(baseAddr + C218_LoadBuf, ptr + j, 396037182346f0991683cc7320a257c3f6089432ceeJiri Slaby len2 << 1); 397037182346f0991683cc7320a257c3f6089432ceeJiri Slaby j += len2 << 1; 398037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 399037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(len2, baseAddr + C218DLoad_len); 400037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0, baseAddr + C218_key); 401037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < 100; i++) { 402037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + C218_key) == keycode) 403037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 404037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 405037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 406037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + C218_key) != keycode) 407037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 408037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 409037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0, baseAddr + C218DLoad_len); 410037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(usum, baseAddr + C218check_sum); 411037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0, baseAddr + C218_key); 412037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < 100; i++) { 413037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + C218_key) == keycode) 414037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 415037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 416037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 417037182346f0991683cc7320a257c3f6089432ceeJiri Slaby retry++; 418037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } while ((readb(baseAddr + C218chksum_ok) != 1) && (retry < 3)); 419037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readb(baseAddr + C218chksum_ok) != 1) 420037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 421037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 422037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0, baseAddr + C218_key); 423037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < 100; i++) { 424037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) == Magic_code) 425037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 426037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 427037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 428037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) != Magic_code) 429037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 430037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 431037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(1, baseAddr + Disable_IRQ); 432037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0, baseAddr + Magic_no); 433037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < 100; i++) { 434037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) == Magic_code) 435037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 436037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 437037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 438037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) != Magic_code) 439037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 440037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 441037182346f0991683cc7320a257c3f6089432ceeJiri Slaby moxaCard = 1; 442037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->intNdx = baseAddr + IRQindex; 443037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->intPend = baseAddr + IRQpending; 444037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->intTable = baseAddr + IRQtable; 445037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 446037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 447037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 448037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 449037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_load_c320(struct moxa_board_conf *brd, const void *ptr, 450037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t len) 451037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 452037182346f0991683cc7320a257c3f6089432ceeJiri Slaby void __iomem *baseAddr = brd->basemem; 453037182346f0991683cc7320a257c3f6089432ceeJiri Slaby const u16 *uptr = ptr; 454037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t wlen, len2, j; 455037182346f0991683cc7320a257c3f6089432ceeJiri Slaby unsigned int i, retry; 456037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u16 usum; 457037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 458037182346f0991683cc7320a257c3f6089432ceeJiri Slaby usum = 0; 459037182346f0991683cc7320a257c3f6089432ceeJiri Slaby wlen = len >> 1; 460037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < wlen; i++) 461037182346f0991683cc7320a257c3f6089432ceeJiri Slaby usum += le16_to_cpu(uptr[i]); 462037182346f0991683cc7320a257c3f6089432ceeJiri Slaby retry = 0; 463037182346f0991683cc7320a257c3f6089432ceeJiri Slaby do { 464037182346f0991683cc7320a257c3f6089432ceeJiri Slaby wlen = len >> 1; 465037182346f0991683cc7320a257c3f6089432ceeJiri Slaby j = 0; 466037182346f0991683cc7320a257c3f6089432ceeJiri Slaby while (wlen) { 467037182346f0991683cc7320a257c3f6089432ceeJiri Slaby len2 = (wlen > 2048) ? 2048 : wlen; 468037182346f0991683cc7320a257c3f6089432ceeJiri Slaby wlen -= len2; 469037182346f0991683cc7320a257c3f6089432ceeJiri Slaby memcpy_toio(baseAddr + C320_LoadBuf, ptr + j, 470037182346f0991683cc7320a257c3f6089432ceeJiri Slaby len2 << 1); 471037182346f0991683cc7320a257c3f6089432ceeJiri Slaby j += len2 << 1; 472037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(len2, baseAddr + C320DLoad_len); 473037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0, baseAddr + C320_key); 474037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < 10; i++) { 475037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + C320_key) == C320_KeyCode) 476037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 477037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 478037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 479037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + C320_key) != C320_KeyCode) 480037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 481037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 482037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0, baseAddr + C320DLoad_len); 483037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(usum, baseAddr + C320check_sum); 484037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0, baseAddr + C320_key); 485037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < 10; i++) { 486037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + C320_key) == C320_KeyCode) 487037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 488037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 489037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 490037182346f0991683cc7320a257c3f6089432ceeJiri Slaby retry++; 491037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } while ((readb(baseAddr + C320chksum_ok) != 1) && (retry < 3)); 492037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readb(baseAddr + C320chksum_ok) != 1) 493037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 494037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 495037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0, baseAddr + C320_key); 496037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < 600; i++) { 497037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) == Magic_code) 498037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 499037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 500037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 501037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) != Magic_code) 502037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 503037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 504037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (brd->busType == MOXA_BUS_TYPE_PCI) { /* ASIC board */ 505037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0x3800, baseAddr + TMS320_PORT1); 506037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0x3900, baseAddr + TMS320_PORT2); 507037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(28499, baseAddr + TMS320_CLOCK); 508037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } else { 509037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0x3200, baseAddr + TMS320_PORT1); 510037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0x3400, baseAddr + TMS320_PORT2); 511037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(19999, baseAddr + TMS320_CLOCK); 512037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 513037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(1, baseAddr + Disable_IRQ); 514037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0, baseAddr + Magic_no); 515037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < 500; i++) { 516037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) == Magic_code) 517037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 518037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 519037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 520037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) != Magic_code) 521037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 522037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 523037182346f0991683cc7320a257c3f6089432ceeJiri Slaby j = readw(baseAddr + Module_cnt); 524037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (j <= 0) 525037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 526037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->numPorts = j * 8; 527037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(j, baseAddr + Module_no); 528037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0, baseAddr + Magic_no); 529037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < 600; i++) { 530037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) == Magic_code) 531037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 532037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 533037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 534037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) != Magic_code) 535037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 536037182346f0991683cc7320a257c3f6089432ceeJiri Slaby moxaCard = 1; 537037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->intNdx = baseAddr + IRQindex; 538037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->intPend = baseAddr + IRQpending; 539037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->intTable = baseAddr + IRQtable; 540037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 541037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 542037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 543037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 544037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_load_code(struct moxa_board_conf *brd, const void *ptr, 545037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t len) 546037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 547037182346f0991683cc7320a257c3f6089432ceeJiri Slaby void __iomem *ofsAddr, *baseAddr = brd->basemem; 548037182346f0991683cc7320a257c3f6089432ceeJiri Slaby struct moxa_port *port; 549037182346f0991683cc7320a257c3f6089432ceeJiri Slaby int retval, i; 550037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 551037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (len % 2) { 552037182346f0991683cc7320a257c3f6089432ceeJiri Slaby printk(KERN_ERR "moxa: C2XX bios length is not even\n"); 553037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EINVAL; 554037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 555037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 556037182346f0991683cc7320a257c3f6089432ceeJiri Slaby switch (brd->boardType) { 557037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_ISA: 558037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_PCI: 559037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_CP204J: 560037182346f0991683cc7320a257c3f6089432ceeJiri Slaby retval = moxa_load_c218(brd, ptr, len); 561037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (retval) 562037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return retval; 563037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port = brd->ports; 564037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < brd->numPorts; i++, port++) { 565037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port->chkPort = 1; 566037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port->curBaud = 9600L; 567037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port->DCDState = 0; 568037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port->tableAddr = baseAddr + Extern_table + 569037182346f0991683cc7320a257c3f6089432ceeJiri Slaby Extern_size * i; 570037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ofsAddr = port->tableAddr; 571037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C218rx_mask, ofsAddr + RX_mask); 572037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C218tx_mask, ofsAddr + TX_mask); 573037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb); 574037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb); 575037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 576037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb); 577037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb); 578037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 579037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 580037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 581037182346f0991683cc7320a257c3f6089432ceeJiri Slaby default: 582037182346f0991683cc7320a257c3f6089432ceeJiri Slaby retval = moxa_load_c320(brd, ptr, len); /* fills in numPorts */ 583037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (retval) 584037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return retval; 585037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port = brd->ports; 586037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < brd->numPorts; i++, port++) { 587037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port->chkPort = 1; 588037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port->curBaud = 9600L; 589037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port->DCDState = 0; 590037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port->tableAddr = baseAddr + Extern_table + 591037182346f0991683cc7320a257c3f6089432ceeJiri Slaby Extern_size * i; 592037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ofsAddr = port->tableAddr; 593037182346f0991683cc7320a257c3f6089432ceeJiri Slaby switch (brd->numPorts) { 594037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case 8: 595037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p8rx_mask, ofsAddr + RX_mask); 596037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p8tx_mask, ofsAddr + TX_mask); 597037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb); 598037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb); 599037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb); 600037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb); 601037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 602037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 603037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case 16: 604037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p16rx_mask, ofsAddr + RX_mask); 605037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p16tx_mask, ofsAddr + TX_mask); 606037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb); 607037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb); 608037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb); 609037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb); 610037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 611037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 612037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case 24: 613037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p24rx_mask, ofsAddr + RX_mask); 614037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p24tx_mask, ofsAddr + TX_mask); 615037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb); 616037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb); 617037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb); 618037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb); 619037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 620037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case 32: 621037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p32rx_mask, ofsAddr + RX_mask); 622037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p32tx_mask, ofsAddr + TX_mask); 623037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p32tx_ofs, ofsAddr + Ofs_txb); 624037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb); 625037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb); 626037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb); 627037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb); 628037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 629037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 630037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 631037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 632037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 633037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->loadstat = 1; 634037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 635037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 636037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 637037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_load_fw(struct moxa_board_conf *brd, const struct firmware *fw) 638037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 639037182346f0991683cc7320a257c3f6089432ceeJiri Slaby void *ptr = fw->data; 640037182346f0991683cc7320a257c3f6089432ceeJiri Slaby char rsn[64]; 641037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u16 lens[5]; 642037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t len; 643037182346f0991683cc7320a257c3f6089432ceeJiri Slaby unsigned int a, lenp, lencnt; 644037182346f0991683cc7320a257c3f6089432ceeJiri Slaby int ret = -EINVAL; 645037182346f0991683cc7320a257c3f6089432ceeJiri Slaby struct { 646037182346f0991683cc7320a257c3f6089432ceeJiri Slaby __le32 magic; /* 0x34303430 */ 647037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u8 reserved1[2]; 648037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u8 type; /* UNIX = 3 */ 649037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u8 model; /* C218T=1, C320T=2, CP204=3 */ 650037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u8 reserved2[8]; 651037182346f0991683cc7320a257c3f6089432ceeJiri Slaby __le16 len[5]; 652037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } *hdr = ptr; 653037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 654037182346f0991683cc7320a257c3f6089432ceeJiri Slaby BUILD_BUG_ON(ARRAY_SIZE(hdr->len) != ARRAY_SIZE(lens)); 655037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 656037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (fw->size < MOXA_FW_HDRLEN) { 657037182346f0991683cc7320a257c3f6089432ceeJiri Slaby strcpy(rsn, "too short (even header won't fit)"); 658037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 659037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 660037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (hdr->magic != cpu_to_le32(0x30343034)) { 661037182346f0991683cc7320a257c3f6089432ceeJiri Slaby sprintf(rsn, "bad magic: %.8x", le32_to_cpu(hdr->magic)); 662037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 663037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 664037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (hdr->type != 3) { 665037182346f0991683cc7320a257c3f6089432ceeJiri Slaby sprintf(rsn, "not for linux, type is %u", hdr->type); 666037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 667037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 668037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (moxa_check_fw_model(brd, hdr->model)) { 669037182346f0991683cc7320a257c3f6089432ceeJiri Slaby sprintf(rsn, "not for this card, model is %u", hdr->model); 670037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 671037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 672037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 673037182346f0991683cc7320a257c3f6089432ceeJiri Slaby len = MOXA_FW_HDRLEN; 674037182346f0991683cc7320a257c3f6089432ceeJiri Slaby lencnt = hdr->model == 2 ? 5 : 3; 675037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (a = 0; a < ARRAY_SIZE(lens); a++) { 676037182346f0991683cc7320a257c3f6089432ceeJiri Slaby lens[a] = le16_to_cpu(hdr->len[a]); 677037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (lens[a] && len + lens[a] <= fw->size && 678037182346f0991683cc7320a257c3f6089432ceeJiri Slaby moxa_check_fw(&fw->data[len])) 679037182346f0991683cc7320a257c3f6089432ceeJiri Slaby printk(KERN_WARNING "moxa firmware: unexpected input " 680037182346f0991683cc7320a257c3f6089432ceeJiri Slaby "at offset %u, but going on\n", (u32)len); 681037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (!lens[a] && a < lencnt) { 682037182346f0991683cc7320a257c3f6089432ceeJiri Slaby sprintf(rsn, "too few entries in fw file"); 683037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 684037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 685037182346f0991683cc7320a257c3f6089432ceeJiri Slaby len += lens[a]; 686037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 687037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 688037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (len != fw->size) { 689037182346f0991683cc7320a257c3f6089432ceeJiri Slaby sprintf(rsn, "bad length: %u (should be %u)", (u32)fw->size, 690037182346f0991683cc7320a257c3f6089432ceeJiri Slaby (u32)len); 691037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 692037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 693037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 694037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ptr += MOXA_FW_HDRLEN; 695037182346f0991683cc7320a257c3f6089432ceeJiri Slaby lenp = 0; /* bios */ 696037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 697037182346f0991683cc7320a257c3f6089432ceeJiri Slaby strcpy(rsn, "read above"); 698037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 699037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ret = moxa_load_bios(brd, ptr, lens[lenp]); 700037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (ret) 701037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 702037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 703037182346f0991683cc7320a257c3f6089432ceeJiri Slaby /* we skip the tty section (lens[1]), since we don't need it */ 704037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ptr += lens[lenp] + lens[lenp + 1]; 705037182346f0991683cc7320a257c3f6089432ceeJiri Slaby lenp += 2; /* comm */ 706037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 707037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (hdr->model == 2) { 708037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ret = moxa_load_320b(brd, ptr, lens[lenp]); 709037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (ret) 710037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 711037182346f0991683cc7320a257c3f6089432ceeJiri Slaby /* skip another tty */ 712037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ptr += lens[lenp] + lens[lenp + 1]; 713037182346f0991683cc7320a257c3f6089432ceeJiri Slaby lenp += 2; 714037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 715037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 716037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ret = moxa_load_code(brd, ptr, lens[lenp]); 717037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (ret) 718037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 719037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 720037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 721037182346f0991683cc7320a257c3f6089432ceeJiri Slabyerr: 722037182346f0991683cc7320a257c3f6089432ceeJiri Slaby printk(KERN_ERR "firmware failed to load, reason: %s\n", rsn); 723037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return ret; 724037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 725037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 726037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_init_board(struct moxa_board_conf *brd, struct device *dev) 727037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 728037182346f0991683cc7320a257c3f6089432ceeJiri Slaby const struct firmware *fw; 729037182346f0991683cc7320a257c3f6089432ceeJiri Slaby const char *file; 730037182346f0991683cc7320a257c3f6089432ceeJiri Slaby int ret; 731037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 732037182346f0991683cc7320a257c3f6089432ceeJiri Slaby switch (brd->boardType) { 733037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_ISA: 734037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_PCI: 735037182346f0991683cc7320a257c3f6089432ceeJiri Slaby file = "c218tunx.cod"; 736037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 737037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_CP204J: 738037182346f0991683cc7320a257c3f6089432ceeJiri Slaby file = "cp204unx.cod"; 739037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 740037182346f0991683cc7320a257c3f6089432ceeJiri Slaby default: 741037182346f0991683cc7320a257c3f6089432ceeJiri Slaby file = "c320tunx.cod"; 742037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 743037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 744037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 745037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ret = request_firmware(&fw, file, dev); 746037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (ret) { 747037182346f0991683cc7320a257c3f6089432ceeJiri Slaby printk(KERN_ERR "request_firmware failed\n"); 748037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto end; 749037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 750037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 751037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ret = moxa_load_fw(brd, fw); 752037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 753037182346f0991683cc7320a257c3f6089432ceeJiri Slaby release_firmware(fw); 754037182346f0991683cc7320a257c3f6089432ceeJiri Slabyend: 755037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return ret; 756037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 757037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI 7599cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slabystatic int __devinit moxa_pci_probe(struct pci_dev *pdev, 7609cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby const struct pci_device_id *ent) 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7629cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby struct moxa_board_conf *board; 7639cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby unsigned int i; 7649cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby int board_type = ent->driver_data; 7659cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby int retval; 7669cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 7679cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby retval = pci_enable_device(pdev); 7687aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby if (retval) { 7697aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby dev_err(&pdev->dev, "can't enable pci device\n"); 7709cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby goto err; 7717aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby } 7729cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 7739cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby for (i = 0; i < MAX_BOARDS; i++) 7749cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby if (moxa_boards[i].basemem == NULL) 7759cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby break; 7769cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 7779cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby retval = -ENODEV; 7789cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby if (i >= MAX_BOARDS) { 7797aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby dev_warn(&pdev->dev, "more than %u MOXA Intellio family boards " 7809cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby "found. Board is ignored.\n", MAX_BOARDS); 7819cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby goto err; 7829cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby } 7839cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 7849cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby board = &moxa_boards[i]; 785037182346f0991683cc7320a257c3f6089432ceeJiri Slaby board->ports = &moxa_ports[i * MAX_PORTS_PER_BOARD]; 786e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby 787e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby retval = pci_request_region(pdev, 2, "moxa-base"); 788e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby if (retval) { 789e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby dev_err(&pdev->dev, "can't request pci region 2\n"); 790e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby goto err; 791e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby } 792e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby 793e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby board->basemem = ioremap(pci_resource_start(pdev, 2), 0x4000); 7947aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby if (board->basemem == NULL) { 7957aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby dev_err(&pdev->dev, "can't remap io space 2\n"); 796e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby goto err_reg; 7977aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby } 7989cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board->boardType = board_type; 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (board_type) { 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MOXA_BOARD_C218_ISA: 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MOXA_BOARD_C218_PCI: 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board->numPorts = 8; 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MOXA_BOARD_CP204J: 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board->numPorts = 4; 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board->numPorts = 0; 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board->busType = MOXA_BUS_TYPE_PCI; 814a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby 815037182346f0991683cc7320a257c3f6089432ceeJiri Slaby retval = moxa_init_board(board, &pdev->dev); 816037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (retval) 817037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err_base; 818037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 8199cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby pci_set_drvdata(pdev, board); 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 822037182346f0991683cc7320a257c3f6089432ceeJiri Slabyerr_base: 823037182346f0991683cc7320a257c3f6089432ceeJiri Slaby iounmap(board->basemem); 824037182346f0991683cc7320a257c3f6089432ceeJiri Slaby board->basemem = NULL; 825e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slabyerr_reg: 826e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby pci_release_region(pdev, 2); 8279cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slabyerr: 8289cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby return retval; 8299cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby} 8309cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 8319cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slabystatic void __devexit moxa_pci_remove(struct pci_dev *pdev) 8329cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby{ 8339cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby struct moxa_board_conf *brd = pci_get_drvdata(pdev); 8349cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 835e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby iounmap(brd->basemem); 8369cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby brd->basemem = NULL; 837e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby pci_release_region(pdev, 2); 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 839a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby 840a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slabystatic struct pci_driver moxa_pci_driver = { 841a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby .name = "moxa", 842a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby .id_table = moxa_pcibrds, 843a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby .probe = moxa_pci_probe, 844a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby .remove = __devexit_p(moxa_pci_remove) 845a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby}; 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_PCI */ 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init moxa_init(void) 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8508f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch; 851d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby unsigned int i, isabrds = 0; 852d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby int retval = 0; 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8547aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby printk(KERN_INFO "MOXA Intellio family driver version %s\n", 8557aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby MOXA_VERSION); 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver = alloc_tty_driver(MAX_PORTS + 1); 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!moxaDriver) 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->owner = THIS_MODULE; 8619b4e3b13b147e9b737de63188a9ae740eaa8c36dSergey Vlasov moxaDriver->name = "ttyMX"; 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->major = ttymajor; 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->minor_start = 0; 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->type = TTY_DRIVER_TYPE_SERIAL; 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->subtype = SERIAL_TYPE_NORMAL; 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->init_termios = tty_std_termios; 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; 868606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox moxaDriver->init_termios.c_ispeed = 9600; 869606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox moxaDriver->init_termios.c_ospeed = 9600; 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->flags = TTY_DRIVER_REAL_RAW; 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_set_operations(moxaDriver, &moxa_ops); 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8738f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby for (i = 0, ch = moxa_ports; i < MAX_PORTS; i++, ch++) { 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->type = PORT_16550A; 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->port = i; 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->close_delay = 5 * HZ / 10; 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->closing_wait = 30 * HZ; 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_waitqueue_head(&ch->open_wait); 88095e0791480af8347460d0cbe34a46eca7e77d0d0Jiri Slaby init_completion(&ch->close_wait); 8818f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby 8826f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby setup_timer(&ch->emptyTimer, moxa_check_xmit_empty, 8838f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby (unsigned long)ch); 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8867aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby pr_debug("Moxa tty devices major number = %d\n", ttymajor); 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tty_register_driver(moxaDriver)) { 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "Couldn't install MOXA Smartio family driver !\n"); 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_tty_driver(moxaDriver); 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 894aa7e5221fb47badbea618cc62704d6e4a4bcce15Jiri Slaby mod_timer(&moxaTimer, jiffies + HZ / 50); 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 896d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby /* Find the boards defined from module args. */ 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE 898d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby { 899d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby struct moxa_board_conf *brd = moxa_boards; 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_BOARDS; i++) { 901d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby if (!baseaddr[i]) 902d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby break; 903d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby if (type[i] == MOXA_BOARD_C218_ISA || 904d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby type[i] == MOXA_BOARD_C320_ISA) { 9057aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n", 906d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby isabrds + 1, moxa_brdname[type[i] - 1], 907d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby baseaddr[i]); 908d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby brd->boardType = type[i]; 909037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->ports = &moxa_ports[isabrds * MAX_PORTS_PER_BOARD]; 910d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 : 911d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby numports[i]; 912d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby brd->busType = MOXA_BUS_TYPE_ISA; 913d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby brd->basemem = ioremap(baseaddr[i], 0x4000); 914d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby if (!brd->basemem) { 915d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby printk(KERN_ERR "moxa: can't remap %lx\n", 916d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby baseaddr[i]); 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 919037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (moxa_init_board(brd, NULL)) { 920037182346f0991683cc7320a257c3f6089432ceeJiri Slaby iounmap(brd->basemem); 921037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->basemem = NULL; 922037182346f0991683cc7320a257c3f6089432ceeJiri Slaby continue; 923037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 924d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby 925d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby brd++; 926d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby isabrds++; 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 929d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby } 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 931a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI 933a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby retval = pci_register_driver(&moxa_pci_driver); 934a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby if (retval) { 935a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby printk(KERN_ERR "Can't register moxa pci driver!\n"); 936d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby if (isabrds) 937a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby retval = 0; 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 940a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby 941a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby return retval; 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit moxa_exit(void) 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 948c251ae0d7514563c7fdace0d390175454761228bJiri Slaby del_timer_sync(&moxaTimer); 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_PORTS; i++) 9518f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby del_timer_sync(&moxa_ports[i].emptyTimer); 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tty_unregister_driver(moxaDriver)) 9547aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby printk(KERN_ERR "Couldn't unregister MOXA Intellio family " 9557aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby "serial driver\n"); 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_tty_driver(moxaDriver); 95786fbf1486a44a4bce4fdcbe3665a7d8a62ba958aJiri Slaby 9589cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby#ifdef CONFIG_PCI 959a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby pci_unregister_driver(&moxa_pci_driver); 9609cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby#endif 961a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby 962a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby for (i = 0; i < MAX_BOARDS; i++) 9638f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if (moxa_boards[i].basemem) 9648f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby iounmap(moxa_boards[i].basemem); 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(moxa_init); 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(moxa_exit); 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_open(struct tty_struct *tty, struct file *filp) 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9728f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch; 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int port; 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 97611324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby port = tty->index; 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (port == MAX_PORTS) { 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!MoxaPortIsValid(port)) { 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty->driver_data = NULL; 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-ENODEV); 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9858f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ch = &moxa_ports[port]; 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->count++; 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty->driver_data = ch; 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->tty = tty; 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(ch->asyncflags & ASYNC_INITIALIZED)) { 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags = 0; 991db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox moxa_set_tty_param(tty, tty->termios); 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortLineCtrl(ch->port, 1, 1); 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortEnable(ch->port); 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->asyncflags |= ASYNC_INITIALIZED; 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9966f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby retval = moxa_block_till_ready(tty, filp, ch); 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxa_unthrottle(tty); 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch->type == PORT_16550A) { 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaSetFifo(ch->port, 1); 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaSetFifo(ch->port, 0); 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (retval); 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_close(struct tty_struct *tty, struct file *filp) 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10118f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch; 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int port; 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 101411324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby port = tty->index; 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (port == MAX_PORTS) { 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!MoxaPortIsValid(port)) { 10197aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby pr_debug("Invalid portno in moxa_close\n"); 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty->driver_data = NULL; 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tty->driver_data == NULL) { 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tty_hung_up_p(filp)) { 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10298f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ch = (struct moxa_port *) tty->driver_data; 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((tty->count == 1) && (ch->count != 1)) { 10327aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby printk(KERN_WARNING "moxa_close: bad serial port count; " 10337aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby "tty->count is 1, ch->count is %d\n", ch->count); 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->count = 1; 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (--ch->count < 0) { 10377aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby printk(KERN_WARNING "moxa_close: bad serial port count, " 10387aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby "device=%s\n", tty->name); 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->count = 0; 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch->count) { 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->asyncflags |= ASYNC_CLOSING; 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->cflag = tty->termios->c_cflag; 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch->asyncflags & ASYNC_INITIALIZED) { 10486f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_setup_empty_event(tty); 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ 10508f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby del_timer_sync(&moxa_ports[ch->port].emptyTimer); 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10526f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_shut_down(ch); 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortFlushData(port, 2); 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tty->driver->flush_buffer) 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty->driver->flush_buffer(tty); 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_ldisc_flush(tty); 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty->closing = 0; 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->event = 0; 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->tty = NULL; 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch->blocked_open) { 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch->close_delay) { 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep_interruptible(jiffies_to_msecs(ch->close_delay)); 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up_interruptible(&ch->open_wait); 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); 106995e0791480af8347460d0cbe34a46eca7e77d0d0Jiri Slaby complete_all(&ch->close_wait); 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_write(struct tty_struct *tty, 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const unsigned char *buf, int count) 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10758f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch; 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len, port; 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10798f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ch = (struct moxa_port *) tty->driver_data; 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = ch->port; 108333f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox 108433f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox spin_lock_irqsave(&moxa_lock, flags); 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = MoxaPortWriteData(port, (unsigned char *) buf, count); 108633f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox spin_unlock_irqrestore(&moxa_lock, flags); 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /********************************************* 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ( !(ch->statusflags & LOWWAIT) && 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((len != count) || (MoxaPortTxFree(port) <= 100)) ) 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************************************/ 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags |= LOWWAIT; 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (len); 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_write_room(struct tty_struct *tty) 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10988f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch; 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tty->stopped) 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 11028f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ch = (struct moxa_port *) tty->driver_data; 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (MoxaPortTxFree(ch->port)); 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_flush_buffer(struct tty_struct *tty) 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11108f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = (struct moxa_port *) tty->driver_data; 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortFlushData(ch->port, 1); 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_wakeup(tty); 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_chars_in_buffer(struct tty_struct *tty) 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int chars; 11218f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = (struct moxa_port *) tty->driver_data; 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Sigh...I have to check if driver_data is NULL here, because 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * if an open() fails, the TTY subsystem eventually calls 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tty_wait_until_sent(), which calls the driver's chars_in_buffer() 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * routine. And since the open() failed, we return 0 here. TDJ 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chars = MoxaPortTxQueue(ch->port); 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chars) { 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Make it possible to wakeup anything waiting for output 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in tty_ioctl.c, etc. 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(ch->statusflags & EMPTYWAIT)) 11386f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_setup_empty_event(tty); 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (chars); 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_flush_chars(struct tty_struct *tty) 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Don't think I need this, because this is called to empty the TX 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * buffer for the 16450, 16550, etc. 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_put_char(struct tty_struct *tty, unsigned char c) 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11538f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch; 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int port; 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11578f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ch = (struct moxa_port *) tty->driver_data; 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = ch->port; 116133f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox spin_lock_irqsave(&moxa_lock, flags); 1162f204d2672044f0f7061d645f0f59f8535b63d106Jiri Slaby MoxaPortWriteData(port, &c, 1); 116333f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox spin_unlock_irqrestore(&moxa_lock, flags); 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /************************************************ 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) ) 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *************************************************/ 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags |= LOWWAIT; 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_tiocmget(struct tty_struct *tty, struct file *file) 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11728f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = (struct moxa_port *) tty->driver_data; 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int port; 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int flag = 0, dtr, rts; 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 117611324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby port = tty->index; 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((port != MAX_PORTS) && (!ch)) 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EINVAL); 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortGetLineOut(ch->port, &dtr, &rts); 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dtr) 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flag |= TIOCM_DTR; 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rts) 11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flag |= TIOCM_RTS; 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dtr = MoxaPortLineStatus(ch->port); 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dtr & 1) 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flag |= TIOCM_CTS; 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dtr & 2) 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flag |= TIOCM_DSR; 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dtr & 4) 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flag |= TIOCM_CD; 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return flag; 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_tiocmset(struct tty_struct *tty, struct file *file, 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int set, unsigned int clear) 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11988f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = (struct moxa_port *) tty->driver_data; 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int port; 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int dtr, rts; 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 120211324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby port = tty->index; 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((port != MAX_PORTS) && (!ch)) 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EINVAL); 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortGetLineOut(ch->port, &dtr, &rts); 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set & TIOCM_RTS) 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rts = 1; 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set & TIOCM_DTR) 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dtr = 1; 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clear & TIOCM_RTS) 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rts = 0; 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clear & TIOCM_DTR) 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dtr = 0; 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortLineCtrl(ch->port, dtr, rts); 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_ioctl(struct tty_struct *tty, struct file *file, 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int cmd, unsigned long arg) 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12228f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = (struct moxa_port *) tty->driver_data; 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register int port; 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __user *argp = (void __user *)arg; 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 122711324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby port = tty->index; 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((port != MAX_PORTS) && (!ch)) 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EINVAL); 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TCSBRK: /* SVID version: non-zero arg --> no break */ 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = tty_check_change(tty); 12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (retval); 12366f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_setup_empty_event(tty); 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_wait_until_sent(tty, 0); 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!arg) 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortSendBreak(ch->port, 0); 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TCSBRKP: /* support for POSIX tcsendbreak() */ 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = tty_check_change(tty); 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (retval); 12456f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_setup_empty_event(tty); 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_wait_until_sent(tty, 0); 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortSendBreak(ch->port, arg); 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TIOCGSOFTCAR: 12509e9fc313ffa3cb92f7f81a8e076566bc9d582351Jiri Slaby return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)argp); 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TIOCSSOFTCAR: 12529e9fc313ffa3cb92f7f81a8e076566bc9d582351Jiri Slaby if (get_user(retval, (int __user *)argp)) 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arg = retval; 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (arg ? CLOCAL : 0)); 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (C_CLOCAL(tty)) 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->asyncflags &= ~ASYNC_CHECK_CD; 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->asyncflags |= ASYNC_CHECK_CD; 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TIOCGSERIAL: 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return moxa_get_serial_info(ch, argp); 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TIOCSSERIAL: 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return moxa_set_serial_info(ch, argp); 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = MoxaDriverIoctl(cmd, arg, port); 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (retval); 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_throttle(struct tty_struct *tty) 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12758f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = (struct moxa_port *) tty->driver_data; 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags |= THROTTLE; 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_unthrottle(struct tty_struct *tty) 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12828f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = (struct moxa_port *) tty->driver_data; 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags &= ~THROTTLE; 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_set_termios(struct tty_struct *tty, 1288606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox struct ktermios *old_termios) 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12908f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = (struct moxa_port *) tty->driver_data; 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1294db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox moxa_set_tty_param(tty, old_termios); 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(old_termios->c_cflag & CLOCAL) && 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (tty->termios->c_cflag & CLOCAL)) 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up_interruptible(&ch->open_wait); 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_stop(struct tty_struct *tty) 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13028f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = (struct moxa_port *) tty->driver_data; 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortTxDisable(ch->port); 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags |= TXSTOPPED; 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_start(struct tty_struct *tty) 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13138f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = (struct moxa_port *) tty->driver_data; 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(ch->statusflags & TXSTOPPED)) 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortTxEnable(ch->port); 13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags &= ~TXSTOPPED; 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_hangup(struct tty_struct *tty) 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13278f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = (struct moxa_port *) tty->driver_data; 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxa_flush_buffer(tty); 13306f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_shut_down(ch); 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->event = 0; 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->count = 0; 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE; 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->tty = NULL; 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up_interruptible(&ch->open_wait); 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_poll(unsigned long ignored) 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register int card; 13418f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch; 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tty_struct *tp; 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, ports; 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&moxaTimer); 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (MoxaDriverPoll() < 0) { 1348aa7e5221fb47badbea618cc62704d6e4a4bcce15Jiri Slaby mod_timer(&moxaTimer, jiffies + HZ / 50); 13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (card = 0; card < MAX_BOARDS; card++) { 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ports = MoxaPortsOfCard(card)) <= 0) 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 13548f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ch = &moxa_ports[card * MAX_PORTS_PER_BOARD]; 13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < ports; i++, ch++) { 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ch->asyncflags & ASYNC_INITIALIZED) == 0) 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(ch->statusflags & THROTTLE) && 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (MoxaPortRxQueue(ch->port) > 0)) 13606f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_receive_data(ch); 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((tp = ch->tty) == 0) 13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch->statusflags & LOWWAIT) { 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS) { 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!tp->stopped) { 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags &= ~LOWWAIT; 13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_wakeup(tp); 13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!I_IGNBRK(tp) && (MoxaPortResetBrkCnt(ch->port) > 0)) { 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_insert_flip_char(tp, 0, TTY_BREAK); 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_schedule_flip(tp); 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (MoxaPortDCDChange(ch->port)) { 13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch->asyncflags & ASYNC_CHECK_CD) { 13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (MoxaPortDCDON(ch->port)) 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up_interruptible(&ch->open_wait); 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 1380ba196df3d6432c5c20429e8e447c5db7abedb8f3Jiri Slaby tty_hangup(tp); 1381ba196df3d6432c5c20429e8e447c5db7abedb8f3Jiri Slaby wake_up_interruptible(&ch->open_wait); 1382ba196df3d6432c5c20429e8e447c5db7abedb8f3Jiri Slaby ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE; 13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1389aa7e5221fb47badbea618cc62704d6e4a4bcce15Jiri Slaby mod_timer(&moxaTimer, jiffies + HZ / 50); 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************************/ 13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1394db1acaa632870ec87b65e062bc72ca375837a1f6Alan Coxstatic void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_termios) 13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1396606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox register struct ktermios *ts; 13978f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch; 1398db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox int rts, cts, txflow, rxflow, xany, baud; 13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14008f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ch = (struct moxa_port *) tty->driver_data; 14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ts = tty->termios; 14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ts->c_cflag & CLOCAL) 14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->asyncflags &= ~ASYNC_CHECK_CD; 14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->asyncflags |= ASYNC_CHECK_CD; 14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rts = cts = txflow = rxflow = xany = 0; 14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ts->c_cflag & CRTSCTS) 14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rts = cts = 1; 14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ts->c_iflag & IXON) 14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds txflow = 1; 14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ts->c_iflag & IXOFF) 14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rxflow = 1; 14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ts->c_iflag & IXANY) 14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds xany = 1; 1415db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox 1416db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox /* Clear the features we don't support */ 1417db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox ts->c_cflag &= ~CMSPAR; 14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortFlowCtrl(ch->port, rts, cts, txflow, rxflow, xany); 1419db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox baud = MoxaPortSetTermio(ch->port, ts, tty_get_baud_rate(tty)); 1420db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox if (baud == -1) 1421db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox baud = tty_termios_baud_rate(old_termios); 1422db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox /* Not put the baud rate into the termios data */ 1423db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox tty_encode_baud_rate(tty, baud, baud); 14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14266f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, 14278f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch) 14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DECLARE_WAITQUEUE(wait,current); 14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int do_clocal = C_CLOCAL(tty); 14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the device is in the middle of being closed, then block 14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * until it's done, and then try again. 14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tty_hung_up_p(filp) || (ch->asyncflags & ASYNC_CLOSING)) { 14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch->asyncflags & ASYNC_CLOSING) 144095e0791480af8347460d0cbe34a46eca7e77d0d0Jiri Slaby wait_for_completion_interruptible(&ch->close_wait); 14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SERIAL_DO_RESTART 14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch->asyncflags & ASYNC_HUP_NOTIFY) 14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EAGAIN); 14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-ERESTARTSYS); 14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EAGAIN); 14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If non-blocking mode is set, then make the check up front 14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and then exit. 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (filp->f_flags & O_NONBLOCK) { 14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->asyncflags |= ASYNC_NORMAL_ACTIVE; 14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Block waiting for the carrier detect and the line to become free 14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_wait_queue(&ch->open_wait, &wait); 14637aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby pr_debug("block_til_ready before block: ttys%d, count = %d\n", 14647aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby ch->port, ch->count); 146533f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox spin_lock_irqsave(&moxa_lock, flags); 14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!tty_hung_up_p(filp)) 14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->count--; 14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->blocked_open++; 146933f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox spin_unlock_irqrestore(&moxa_lock, flags); 147033f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox 14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (1) { 14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_current_state(TASK_INTERRUPTIBLE); 14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tty_hung_up_p(filp) || 14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !(ch->asyncflags & ASYNC_INITIALIZED)) { 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SERIAL_DO_RESTART 14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch->asyncflags & ASYNC_HUP_NOTIFY) 14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EAGAIN; 14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -ERESTARTSYS; 14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EAGAIN; 14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(ch->asyncflags & ASYNC_CLOSING) && (do_clocal || 14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortDCDON(ch->port))) 14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (signal_pending(current)) { 14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -ERESTARTSYS; 14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule(); 14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_current_state(TASK_RUNNING); 14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_wait_queue(&ch->open_wait, &wait); 149733f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox 149833f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox spin_lock_irqsave(&moxa_lock, flags); 14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!tty_hung_up_p(filp)) 15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->count++; 15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->blocked_open--; 150233f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox spin_unlock_irqrestore(&moxa_lock, flags); 15037aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby pr_debug("block_til_ready after blocking: ttys%d, count = %d\n", 15047aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby ch->port, ch->count); 15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) 15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (retval); 150733f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox /* FIXME: review to see if we need to use set_bit on these */ 15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->asyncflags |= ASYNC_NORMAL_ACTIVE; 150933f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox return 0; 15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15126f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic void moxa_setup_empty_event(struct tty_struct *tty) 15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15148f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = tty->driver_data; 15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 151733f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox spin_lock_irqsave(&moxa_lock, flags); 15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags |= EMPTYWAIT; 15198f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby mod_timer(&moxa_ports[ch->port].emptyTimer, jiffies + HZ); 152033f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox spin_unlock_irqrestore(&moxa_lock, flags); 15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15236f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic void moxa_check_xmit_empty(unsigned long data) 15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15258f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch; 15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15278f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ch = (struct moxa_port *) data; 15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch->tty && (ch->statusflags & EMPTYWAIT)) { 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (MoxaPortTxQueue(ch->port) == 0) { 15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags &= ~EMPTYWAIT; 15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_wakeup(ch->tty); 15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1534c43422053bea7a5ce09f18d0c50a606fe1a549f4Jiri Slaby mod_timer(&moxa_ports[ch->port].emptyTimer, 1535c43422053bea7a5ce09f18d0c50a606fe1a549f4Jiri Slaby round_jiffies(jiffies + HZ)); 15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags &= ~EMPTYWAIT; 15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15406f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic void moxa_shut_down(struct moxa_port *ch) 15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tty_struct *tp; 15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(ch->asyncflags & ASYNC_INITIALIZED)) 15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tp = ch->tty; 15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortDisable(ch->port); 15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If we're a modem control device and HUPCL is on, drop RTS & DTR. 15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tp->termios->c_cflag & HUPCL) 15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortLineCtrl(ch->port, 0, 0); 15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->asyncflags &= ~ASYNC_INITIALIZED; 15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15606f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic void moxa_receive_data(struct moxa_port *ch) 15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tty_struct *tp; 1563606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox struct ktermios *ts; 15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ts = NULL; 15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tp = ch->tty; 15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tp) 15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ts = tp->termios; 15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /************************************************** 1571037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if ( !tp || !ts || !(ts->c_cflag & CREAD) ) { 1572037182346f0991683cc7320a257c3f6089432ceeJiri Slaby *****************************************************/ 1573037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (!tp || !ts) { 1574037182346f0991683cc7320a257c3f6089432ceeJiri Slaby MoxaPortFlushData(ch->port, 0); 1575037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return; 1576037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 1577037182346f0991683cc7320a257c3f6089432ceeJiri Slaby spin_lock_irqsave(&moxa_lock, flags); 1578037182346f0991683cc7320a257c3f6089432ceeJiri Slaby MoxaPortReadData(ch->port, tp); 1579037182346f0991683cc7320a257c3f6089432ceeJiri Slaby spin_unlock_irqrestore(&moxa_lock, flags); 1580037182346f0991683cc7320a257c3f6089432ceeJiri Slaby tty_schedule_flip(tp); 1581037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Query 15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mon_str { 15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int tick; 15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rxcnt[MAX_PORTS]; 15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int txcnt[MAX_PORTS]; 15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DCD_changed 0x01 15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DCD_oldstate 0x80 15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxaLowWaterChk; 15979dff89cd82af7bccc706fed288b1c33a51c3b937Jiri Slabystatic struct mon_str moxaLog; 15989fa372a850b9ffcb177eb9ac0b75963b2f9af233Jiri Slabystatic int moxaFuncTout = HZ / 2; 15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxafunc(void __iomem *, int, ushort); 16016f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic void moxa_wait_finish(void __iomem *); 16026f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic void moxa_low_water_check(void __iomem *); 16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************************************************** 16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Driver level functions: * 16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2. MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port); * 16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3. MoxaDriverPoll(void); * 16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/ 16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA 0x400 16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GET_IQUEUE (MOXA + 1) /* get input buffered count */ 16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GET_OQUEUE (MOXA + 2) /* get output buffered count */ 16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GETDATACOUNT (MOXA + 23) 16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GET_IOQUEUE (MOXA + 27) 16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_FLUSH_QUEUE (MOXA + 28) 16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GET_CONF (MOXA + 35) /* configuration */ 16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GET_MAJOR (MOXA + 63) 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GET_CUMAJOR (MOXA + 64) 16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MOXA_GETMSTATUS (MOXA + 65) 16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortFlushData(int port, int mode) 16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((mode < 0) || (mode > 2)) 16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 16258f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[port].tableAddr; 16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_FlushQueue, mode); 16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mode != 1) { 16288f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby moxa_ports[port].lowChkFlag = 0; 16296f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_low_water_check(ofsAddr); 16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port) 16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status; 16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int MoxaPortTxQueue(int), MoxaPortRxQueue(int); 16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __user *argp = (void __user *)arg; 16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 164011324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby if (port == MAX_PORTS) { 1641037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if ((cmd != MOXA_GET_CONF) && (cmd != MOXA_GETDATACOUNT) && 1642037182346f0991683cc7320a257c3f6089432ceeJiri Slaby (cmd != MOXA_GET_IOQUEUE) && (cmd != MOXA_GET_MAJOR) && 16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (cmd != MOXA_GET_CUMAJOR) && (cmd != MOXA_GETMSTATUS)) 16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EINVAL); 16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MOXA_GETDATACOUNT: 16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaLog.tick = jiffies; 16499dff89cd82af7bccc706fed288b1c33a51c3b937Jiri Slaby if(copy_to_user(argp, &moxaLog, sizeof(struct mon_str))) 16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MOXA_FLUSH_QUEUE: 16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortFlushData(port, arg); 16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 16558f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby case MOXA_GET_IOQUEUE: { 16568f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxaq_str __user *argm = argp; 1657181d6f4fac7f01ede95284954ea1231939dca0d9Jiri Slaby struct moxaq_str tmp; 16588f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby 16598f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby for (i = 0; i < MAX_PORTS; i++, argm++) { 1660181d6f4fac7f01ede95284954ea1231939dca0d9Jiri Slaby memset(&tmp, 0, sizeof(tmp)); 1661181d6f4fac7f01ede95284954ea1231939dca0d9Jiri Slaby if (moxa_ports[i].chkPort) { 1662181d6f4fac7f01ede95284954ea1231939dca0d9Jiri Slaby tmp.inq = MoxaPortRxQueue(i); 1663181d6f4fac7f01ede95284954ea1231939dca0d9Jiri Slaby tmp.outq = MoxaPortTxQueue(i); 16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1665181d6f4fac7f01ede95284954ea1231939dca0d9Jiri Slaby if (copy_to_user(argm, &tmp, sizeof(tmp))) 16668f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby return -EFAULT; 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 16698f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby } case MOXA_GET_OQUEUE: 16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = MoxaPortTxQueue(port); 16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return put_user(i, (unsigned long __user *)argp); 16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MOXA_GET_IQUEUE: 16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = MoxaPortRxQueue(port); 16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return put_user(i, (unsigned long __user *)argp); 16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MOXA_GET_MAJOR: 16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(copy_to_user(argp, &ttymajor, sizeof(int))) 16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MOXA_GET_CUMAJOR: 16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = 0; 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(copy_to_user(argp, &i, sizeof(int))) 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 16848f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby case MOXA_GETMSTATUS: { 16858f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct mxser_mstatus __user *argm = argp; 1686181d6f4fac7f01ede95284954ea1231939dca0d9Jiri Slaby struct mxser_mstatus tmp; 16878f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *p; 16888f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby 16898f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby for (i = 0; i < MAX_PORTS; i++, argm++) { 16908f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby p = &moxa_ports[i]; 1691181d6f4fac7f01ede95284954ea1231939dca0d9Jiri Slaby memset(&tmp, 0, sizeof(tmp)); 16928f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if (!p->chkPort) { 16938f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby goto copy; 16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 16958f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby status = MoxaPortLineStatus(p->port); 16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & 1) 1697181d6f4fac7f01ede95284954ea1231939dca0d9Jiri Slaby tmp.cts = 1; 16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & 2) 1699181d6f4fac7f01ede95284954ea1231939dca0d9Jiri Slaby tmp.dsr = 1; 17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & 4) 1701181d6f4fac7f01ede95284954ea1231939dca0d9Jiri Slaby tmp.dcd = 1; 17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17048f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if (!p->tty || !p->tty->termios) 1705181d6f4fac7f01ede95284954ea1231939dca0d9Jiri Slaby tmp.cflag = p->cflag; 17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1707181d6f4fac7f01ede95284954ea1231939dca0d9Jiri Slaby tmp.cflag = p->tty->termios->c_cflag; 17088f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabycopy: 1709181d6f4fac7f01ede95284954ea1231939dca0d9Jiri Slaby if (copy_to_user(argm, &tmp, sizeof(tmp))) 17108f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby return -EFAULT; 17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1715037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 1716037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -ENOIOCTLCMD; 17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaDriverPoll(void) 17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17218f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_board_conf *brd; 17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register ushort temp; 17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register int card; 17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ip; 17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int port, p, ports; 17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (moxaCard == 0) 17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-1); 17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (card = 0; card < MAX_BOARDS; card++) { 17318f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby brd = &moxa_boards[card]; 17328f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if (brd->loadstat == 0) 173301cfaf0d12ae5fa092cc916ca4066ee1598e857dDirk Eibach continue; 17348f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if ((ports = brd->numPorts) == 0) 17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 17368f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if (readb(brd->intPend) == 0xff) { 17378f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ip = brd->intTable + readb(brd->intNdx); 17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = card * MAX_PORTS_PER_BOARD; 17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ports <<= 1; 17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (port = 0; port < ports; port += 2, p++) { 17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((temp = readw(ip + port)) != 0) { 17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(0, ip + port); 17438f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[p].tableAddr; 17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (temp & IntrTx) 17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(readw(ofsAddr + HostStat) & ~WakeupTx, ofsAddr + HostStat); 17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (temp & IntrBreak) { 17478f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby moxa_ports[p].breakCnt++; 17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (temp & IntrLine) { 17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (readb(ofsAddr + FlagStat) & DCD_state) { 17518f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if ((moxa_ports[p].DCDState & DCD_oldstate) == 0) 17528f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby moxa_ports[p].DCDState = (DCD_oldstate | 17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DCD_changed); 17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 17558f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if (moxa_ports[p].DCDState & DCD_oldstate) 17568f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby moxa_ports[p].DCDState = DCD_changed; 17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17618f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby writeb(0, brd->intPend); 17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (moxaLowWaterChk) { 17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = card * MAX_PORTS_PER_BOARD; 17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (port = 0; port < ports; port++, p++) { 17668f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if (moxa_ports[p].lowChkFlag) { 17678f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby moxa_ports[p].lowChkFlag = 0; 17688f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[p].tableAddr; 17696f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_low_water_check(ofsAddr); 17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaLowWaterChk = 0; 17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************************************************** 17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Card level function: * 17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1. MoxaPortsOfCard(int cardno); * 17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/ 17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortsOfCard(int cardno) 17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (moxa_boards[cardno].boardType == 0) 17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (moxa_boards[cardno].numPorts); 17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************************************************** 17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Port level functions: * 17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1. MoxaPortIsValid(int port); * 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2. MoxaPortEnable(int port); * 17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3. MoxaPortDisable(int port); * 17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4. MoxaPortGetMaxBaud(int port); * 17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6. MoxaPortSetBaud(int port, long baud); * 17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8. MoxaPortSetTermio(int port, unsigned char *termio); * 17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 9. MoxaPortGetLineOut(int port, int *dtrState, int *rtsState); * 17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10. MoxaPortLineCtrl(int port, int dtrState, int rtsState); * 18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11. MoxaPortFlowCtrl(int port, int rts, int cts, int rx, int tx,int xany); * 18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 12. MoxaPortLineStatus(int port); * 18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 13. MoxaPortDCDChange(int port); * 18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 14. MoxaPortDCDON(int port); * 18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15. MoxaPortFlushData(int port, int mode); * 18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16. MoxaPortWriteData(int port, unsigned char * buffer, int length); * 180633f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox * 17. MoxaPortReadData(int port, struct tty_struct *tty); * 18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20. MoxaPortTxQueue(int port); * 18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 21. MoxaPortTxFree(int port); * 18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 22. MoxaPortRxQueue(int port); * 18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 24. MoxaPortTxDisable(int port); * 18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 25. MoxaPortTxEnable(int port); * 18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 27. MoxaPortResetBrkCnt(int port); * 18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 30. MoxaPortSendBreak(int port, int ticks); * 18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/ 18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Moxa Port Number Description: 18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MOXA serial driver supports up to 4 MOXA-C218/C320 boards. And, 18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the port number using in MOXA driver functions will be 0 to 31 for 18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * first MOXA board, 32 to 63 for second, 64 to 95 for third and 96 18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to 127 for fourth. For example, if you setup three MOXA boards, 18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * first board is C218, second board is C320-16 and third board is 18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * C320-32. The port number of first board (C218 - 8 ports) is from 18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 to 7. The port number of second board (C320 - 16 ports) is form 18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 32 to 47. The port number of third board (C320 - 32 ports) is from 18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 64 to 95. And those port numbers form 8 to 31, 48 to 63 and 96 to 18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 127 will be invalid. 18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Moxa Functions Description: 18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 1: Driver initialization routine, this routine must be 18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * called when initialized driver. 18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaDriverInit(); 18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 2: Moxa driver private IOCTL command processing. 18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port); 18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsigned int cmd : IOCTL command 18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsigned long arg : IOCTL argument 18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 (OK) 18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL 18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -ENOIOCTLCMD 18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 3: Moxa driver polling process routine. 18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaDriverPoll(void); 18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 ; polling O.K. 18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -1 : no any Moxa card. 18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 4: Get the ports of this card. 18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortsOfCard(int cardno); 18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int cardno : card number (0 - 3) 18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 : this card is invalid 18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8/16/24/32 18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 5: Check this port is valid or invalid 18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortIsValid(int port); 18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127, ref port description) 18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 : this port is invalid 18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 : this port is valid 18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 6: Enable this port to start Tx/Rx data. 18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortEnable(int port); 18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 7: Disable this port 18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortDisable(int port); 18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 8: Get the maximun available baud rate of this port. 18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * long MoxaPortGetMaxBaud(int port); 18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 : this port is invalid 18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 38400/57600/115200 bps 18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 10: Setting baud rate of this port. 19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * long MoxaPortSetBaud(int port, long baud); 19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * long baud : baud rate (50 - 115200) 19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 : this port is invalid or baud < 50 19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 50 - 115200 : the real baud rate set to the port, if 19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the argument baud is large than maximun 19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * available baud rate, the real setting 19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * baud rate will be the maximun baud rate. 19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 12: Configure the port. 19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 1914606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox * int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud); 19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 1916606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox * struct ktermios * termio : termio structure pointer 1917c7bce3097c0f9bbed76ee6fd03742f2624031a45Alan Cox * speed_t baud : baud rate 19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: -1 : this port is invalid or termio == NULL 19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 : setting O.K. 19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 13: Get the DTR/RTS state of this port. 19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortGetLineOut(int port, int *dtrState, int *rtsState); 19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int * dtrState : pointer to INT to receive the current DTR 19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * state. (if NULL, this function will not 19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * write to this address) 19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int * rtsState : pointer to INT to receive the current RTS 19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * state. (if NULL, this function will not 19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * write to this address) 19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: -1 : this port is invalid 19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 : O.K. 19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 14: Setting the DTR/RTS output state of this port. 19391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortLineCtrl(int port, int dtrState, int rtsState); 19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int dtrState : DTR output state (0: off, 1: on) 19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int rtsState : RTS output state (0: off, 1: on) 19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 15: Setting the flow control of this port. 19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortFlowCtrl(int port, int rtsFlow, int ctsFlow, int rxFlow, 19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int txFlow,int xany); 19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int rtsFlow : H/W RTS flow control (0: no, 1: yes) 19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int ctsFlow : H/W CTS flow control (0: no, 1: yes) 19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int rxFlow : S/W Rx XON/XOFF flow control (0: no, 1: yes) 19541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int txFlow : S/W Tx XON/XOFF flow control (0: no, 1: yes) 19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int xany : S/W XANY flow control (0: no, 1: yes) 19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 16: Get ths line status of this port 19591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 19601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortLineStatus(int port); 19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: Bit 0 - CTS state (0: off, 1: on) 19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bit 1 - DSR state (0: off, 1: on) 19651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bit 2 - DCD state (0: off, 1: on) 19661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 17: Check the DCD state has changed since the last read 19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of this function. 19701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 19711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortDCDChange(int port); 19721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 19731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 : no changed 19751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 : DCD has changed 19761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 18: Check ths current DCD state is ON or not. 19791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortDCDON(int port); 19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 : DCD off 19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 : DCD on 19851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 19: Flush the Rx/Tx buffer data of this port. 19881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortFlushData(int port, int mode); 19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int mode 19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 : flush the Rx buffer 19931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 : flush the Tx buffer 19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2 : flush the Rx and Tx buffer 19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 20: Write data. 19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortWriteData(int port, unsigned char * buffer, int length); 20001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsigned char * buffer : pointer to write data buffer. 20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int length : write data length 20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 - length : real write data length 20051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 21: Read data. 20081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 200933f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox * int MoxaPortReadData(int port, struct tty_struct *tty); 20101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 201133f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox * struct tty_struct *tty : tty for data 20121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 - length : real read data length 20141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 24: Get the Tx buffer current queued data bytes 20171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 20181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortTxQueue(int port); 20191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 20201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: .. : Tx buffer current queued data bytes 20221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 25: Get the Tx buffer current free space 20251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 20261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortTxFree(int port); 20271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 20281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: .. : Tx buffer current free space 20301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 26: Get the Rx buffer current queued data bytes 20331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 20341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortRxQueue(int port); 20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: .. : Rx buffer current queued data bytes 20381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 28: Disable port data transmission. 20411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 20421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortTxDisable(int port); 20431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 20441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 29: Enable port data transmission. 20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortTxEnable(int port); 20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 31: Get the received BREAK signal count and reset it. 20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortResetBrkCnt(int port); 20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 - .. : BREAK signal count 20581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 34: Send out a BREAK signal. 20611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 20621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortSendBreak(int port, int ms100); 20631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 20641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int ms100 : break signal time interval. 20651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unit: 100 mini-second. if ms100 == 0, it will 20661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * send out a about 250 ms BREAK signal. 20671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortIsValid(int port) 20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (moxaCard == 0) 20721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 20738f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if (moxa_ports[port].chkPort == 0) 20741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (1); 20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortEnable(int port) 20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int MoxaPortLineStatus(int); 20821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short lowwater = 512; 20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20848f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[port].tableAddr; 20851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(lowwater, ofsAddr + Low_water); 20868f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby moxa_ports[port].breakCnt = 0; 20871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || 20881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) { 20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetBreakIrq, 0); 20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(readw(ofsAddr + HostStat) | WakeupBreak, ofsAddr + HostStat); 20921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetLineIrq, Magic_code); 20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_FlushQueue, 2); 20961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_EnableCH, Magic_code); 20981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortLineStatus(port); 20991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortDisable(int port) 21021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21038f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby void __iomem *ofsAddr = moxa_ports[port].tableAddr; 21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetFlowCtl, 0); /* disable flow control */ 21061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code); 21071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(0, ofsAddr + HostStat); 21081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_DisableCH, Magic_code); 21091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslong MoxaPortGetMaxBaud(int port) 21121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || 21141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) 21151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (460800L); 21161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 21171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (921600L); 21181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslong MoxaPortSetBaud(int port, long baud) 21221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 21241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long max, clock; 21251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int val; 21261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((baud < 50L) || ((max = MoxaPortGetMaxBaud(port)) == 0)) 21281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 21298f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[port].tableAddr; 21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (baud > max) 21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds baud = max; 21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (max == 38400L) 21331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clock = 614400L; /* for 9.8304 Mhz : max. 38400 bps */ 21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (max == 57600L) 21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clock = 691200L; /* for 11.0592 Mhz : max. 57600 bps */ 21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 21371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clock = 921600L; /* for 14.7456 Mhz : max. 115200 bps */ 21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = clock / baud; 21391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetBaud, val); 21401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds baud = clock / val; 21418f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby moxa_ports[port].curBaud = baud; 21421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (baud); 21431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2145606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Coxint MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud) 21461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 21481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tcflag_t cflag; 21491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tcflag_t mode = 0; 21501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21518f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if (moxa_ports[port].chkPort == 0 || termio == 0) 21521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-1); 21538f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[port].tableAddr; 21541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cflag = termio->c_cflag; /* termio->c_cflag */ 21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = termio->c_cflag & CSIZE; 21571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mode == CS5) 21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = MX_CS5; 21591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (mode == CS6) 21601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = MX_CS6; 21611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (mode == CS7) 21621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = MX_CS7; 21631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (mode == CS8) 21641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = MX_CS8; 21651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (termio->c_cflag & CSTOPB) { 21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mode == MX_CS5) 21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_STOP15; 21691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 21701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_STOP2; 21711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 21721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_STOP1; 21731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (termio->c_cflag & PARENB) { 21751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (termio->c_cflag & PARODD) 21761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_PARODD; 21771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 21781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_PAREVEN; 21791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 21801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_PARNONE; 21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetDataMode, (ushort) mode); 21831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || 21851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) { 2186c7bce3097c0f9bbed76ee6fd03742f2624031a45Alan Cox if (baud >= 921600L) 21871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-1); 21881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2189db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox baud = MoxaPortSetBaud(port, baud); 21901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (termio->c_iflag & (IXON | IXOFF | IXANY)) { 21921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(termio->c_cc[VSTART], ofsAddr + FuncArg); 21931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1); 21941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(FC_SetXonXoff, ofsAddr + FuncCode); 21956f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_wait_finish(ofsAddr); 21961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2198db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox return (baud); 21991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortGetLineOut(int port, int *dtrState, int *rtsState) 22021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!MoxaPortIsValid(port)) 22051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-1); 22061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dtrState) { 22078f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if (moxa_ports[port].lineCtrl & DTR_ON) 22081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *dtrState = 1; 22091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 22101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *dtrState = 0; 22111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rtsState) { 22138f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if (moxa_ports[port].lineCtrl & RTS_ON) 22141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *rtsState = 1; 22151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 22161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *rtsState = 0; 22171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 22191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortLineCtrl(int port, int dtr, int rts) 22221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int mode; 22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22268f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[port].tableAddr; 22271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = 0; 22281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dtr) 22291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= DTR_ON; 22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rts) 22311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= RTS_ON; 22328f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby moxa_ports[port].lineCtrl = mode; 22331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_LineControl, mode); 22341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortFlowCtrl(int port, int rts, int cts, int txflow, int rxflow, int txany) 22371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 22391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int mode; 22401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22418f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[port].tableAddr; 22421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = 0; 22431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rts) 22441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= RTS_FlowCtl; 22451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cts) 22461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= CTS_FlowCtl; 22471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (txflow) 22481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= Tx_FlowCtl; 22491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rxflow) 22501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= Rx_FlowCtl; 22511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (txany) 22521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= IXM_IXANY; 22531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetFlowCtl, mode); 22541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortLineStatus(int port) 22571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 22591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val; 22601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22618f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[port].tableAddr; 22621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || 22631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) { 22641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_LineStatus, 0); 22651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = readw(ofsAddr + FuncArg); 22661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 22671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = readw(ofsAddr + FlagStat) >> 4; 22681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val &= 0x0B; 22701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val & 8) { 22711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val |= 4; 22728f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if ((moxa_ports[port].DCDState & DCD_oldstate) == 0) 22738f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby moxa_ports[port].DCDState = (DCD_oldstate | DCD_changed); 22741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 22758f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if (moxa_ports[port].DCDState & DCD_oldstate) 22768f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby moxa_ports[port].DCDState = DCD_changed; 22771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val &= 7; 22791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (val); 22801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortDCDChange(int port) 22831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 22851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22868f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if (moxa_ports[port].chkPort == 0) 22871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 22888f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby n = moxa_ports[port].DCDState; 22898f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby moxa_ports[port].DCDState &= ~DCD_changed; 22901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n &= DCD_changed; 22911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (n); 22921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortDCDON(int port) 22951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 22971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22988f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if (moxa_ports[port].chkPort == 0) 22991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 23008f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby if (moxa_ports[port].DCDState & DCD_oldstate) 23011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n = 1; 23021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 23031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n = 0; 23041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (n); 23051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 23061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortWriteData(int port, unsigned char * buffer, int len) 23081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 23091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int c, total, i; 23101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort tail; 23111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int cnt; 23121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort head, tx_mask, spage, epage; 23131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort pageno, pageofs, bufhead; 23141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *baseAddr, *ofsAddr, *ofs; 23151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23168f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[port].tableAddr; 23178f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby baseAddr = moxa_boards[port / MAX_PORTS_PER_BOARD].basemem; 23181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tx_mask = readw(ofsAddr + TX_mask); 23191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spage = readw(ofsAddr + Page_txb); 23201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds epage = readw(ofsAddr + EndPage_txb); 23211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tail = readw(ofsAddr + TXwptr); 23221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head = readw(ofsAddr + TXrptr); 23231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c = (head > tail) ? (head - tail - 1) 23241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : (head - tail + tx_mask); 23251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (c > len) 23261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c = len; 23271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaLog.txcnt[port] += c; 23281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds total = c; 23291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (spage == epage) { 23301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bufhead = readw(ofsAddr + Ofs_txb); 23311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(spage, baseAddr + Control_reg); 23321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (c > 0) { 23331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (head > tail) 23341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = head - tail - 1; 23351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 23361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = tx_mask + 1 - tail; 23371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = (c > len) ? len : c; 23381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ofs = baseAddr + DynPage_addr + bufhead + tail; 23391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < len; i++) 23401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(*buffer++, ofs + i); 23411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tail = (tail + len) & tx_mask; 23421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c -= len; 23431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(tail, ofsAddr + TXwptr); 23451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 23461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = c; 23471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageno = spage + (tail >> 13); 23481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageofs = tail & Page_mask; 23491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 23501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnt = Page_size - pageofs; 23511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnt > c) 23521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnt = c; 23531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c -= cnt; 23541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(pageno, baseAddr + Control_reg); 23551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ofs = baseAddr + DynPage_addr + pageofs; 23561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < cnt; i++) 23571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(*buffer++, ofs + i); 23581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (c == 0) { 23591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew((tail + len) & tx_mask, ofsAddr + TXwptr); 23601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 23611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (++pageno == epage) 23631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageno = spage; 23641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageofs = 0; 23651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (1); 23661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(1, ofsAddr + CD180TXirq); /* start to send */ 23681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (total); 23691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 23701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 237133f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Coxint MoxaPortReadData(int port, struct tty_struct *tty) 23721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 23731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register ushort head, pageofs; 23741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, count, cnt, len, total, remain; 23751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort tail, rx_mask, spage, epage; 23761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort pageno, bufhead; 23771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *baseAddr, *ofsAddr, *ofs; 23781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23798f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[port].tableAddr; 23808f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby baseAddr = moxa_boards[port / MAX_PORTS_PER_BOARD].basemem; 23811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head = readw(ofsAddr + RXrptr); 23821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tail = readw(ofsAddr + RXwptr); 23831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rx_mask = readw(ofsAddr + RX_mask); 23841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spage = readw(ofsAddr + Page_rxb); 23851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds epage = readw(ofsAddr + EndPage_rxb); 23861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = (tail >= head) ? (tail - head) 23871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : (tail - head + rx_mask + 1); 23881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count == 0) 238933f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox return 0; 23901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 239133f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox total = count; 23921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remain = count - total; 23931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaLog.rxcnt[port] += total; 23941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = total; 23951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (spage == epage) { 23961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bufhead = readw(ofsAddr + Ofs_rxb); 23971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(spage, baseAddr + Control_reg); 23981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (count > 0) { 23991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tail >= head) 24001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = tail - head; 24011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 24021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = rx_mask + 1 - head; 24031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = (count > len) ? len : count; 24041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ofs = baseAddr + DynPage_addr + bufhead + head; 24051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < len; i++) 240633f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL); 24071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head = (head + len) & rx_mask; 24081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count -= len; 24091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(head, ofsAddr + RXrptr); 24111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 24121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = count; 24131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageno = spage + (head >> 13); 24141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageofs = head & Page_mask; 24151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 24161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnt = Page_size - pageofs; 24171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnt > count) 24181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnt = count; 24191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count -= cnt; 24201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(pageno, baseAddr + Control_reg); 24211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ofs = baseAddr + DynPage_addr + pageofs; 24221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < cnt; i++) 242333f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL); 24241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count == 0) { 24251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew((head + len) & rx_mask, ofsAddr + RXrptr); 24261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (++pageno == epage) 24291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageno = spage; 24301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageofs = 0; 24311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (1); 24321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((readb(ofsAddr + FlagStat) & Xoff_state) && (remain < LowWater)) { 24341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaLowWaterChk = 1; 24358f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby moxa_ports[port].lowChkFlag = 1; 24361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (total); 24381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortTxQueue(int port) 24421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 24441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort rptr, wptr, mask; 24451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 24461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24478f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[port].tableAddr; 24481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rptr = readw(ofsAddr + TXrptr); 24491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wptr = readw(ofsAddr + TXwptr); 24501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = readw(ofsAddr + TX_mask); 24511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = (wptr - rptr) & mask; 24521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (len); 24531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortTxFree(int port) 24561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 24581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort rptr, wptr, mask; 24591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 24601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24618f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[port].tableAddr; 24621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rptr = readw(ofsAddr + TXrptr); 24631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wptr = readw(ofsAddr + TXwptr); 24641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = readw(ofsAddr + TX_mask); 24651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = mask - ((wptr - rptr) & mask); 24661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (len); 24671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortRxQueue(int port) 24701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 24721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort rptr, wptr, mask; 24731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 24741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24758f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[port].tableAddr; 24761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rptr = readw(ofsAddr + RXrptr); 24771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wptr = readw(ofsAddr + RXwptr); 24781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = readw(ofsAddr + RX_mask); 24791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = (wptr - rptr) & mask; 24801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (len); 24811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortTxDisable(int port) 24851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 24871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24888f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[port].tableAddr; 24891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetXoffState, Magic_code); 24901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortTxEnable(int port) 24931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 24951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24968f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[port].tableAddr; 24971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetXonState, Magic_code); 24981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint MoxaPortResetBrkCnt(int port) 25021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort cnt; 25048f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby cnt = moxa_ports[port].breakCnt; 25058f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby moxa_ports[port].breakCnt = 0; 25061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cnt); 25071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid MoxaPortSendBreak(int port, int ms100) 25111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 25131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25148f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ofsAddr = moxa_ports[port].tableAddr; 25151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ms100) { 25161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SendBreak, Magic_code); 251724c032f1dd393c995545ecefa8c1585ae9ef6b37Jiri Slaby msleep(ms100 * 10); 25181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 25191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SendBreak, Magic_code); 252024c032f1dd393c995545ecefa8c1585ae9ef6b37Jiri Slaby msleep(250); 25211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_StopBreak, Magic_code); 25231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25258f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic int moxa_get_serial_info(struct moxa_port *info, 25261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct serial_struct __user *retinfo) 25271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct serial_struct tmp; 25291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&tmp, 0, sizeof(tmp)); 25311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.type = info->type; 25321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.line = info->port; 25331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.port = 0; 25341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.irq = 0; 25351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.flags = info->asyncflags; 25361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.baud_base = 921600; 25371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.close_delay = info->close_delay; 25381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.closing_wait = info->closing_wait; 25391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.custom_divisor = 0; 25401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.hub6 = 0; 25411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(copy_to_user(retinfo, &tmp, sizeof(*retinfo))) 25421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 25431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 25441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25478f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic int moxa_set_serial_info(struct moxa_port *info, 25481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct serial_struct __user *new_info) 25491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct serial_struct new_serial; 25511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(copy_from_user(&new_serial, new_info, sizeof(new_serial))) 25531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 25541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((new_serial.irq != 0) || 25561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (new_serial.port != 0) || 25571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// (new_serial.type != info->type) || 25581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (new_serial.custom_divisor != 0) || 25591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (new_serial.baud_base != 921600)) 25601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EPERM); 25611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_ADMIN)) { 25631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((new_serial.flags & ~ASYNC_USR_MASK) != 25641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (info->asyncflags & ~ASYNC_USR_MASK))) 25651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EPERM); 25661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 25671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->close_delay = new_serial.close_delay * HZ / 100; 25681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->closing_wait = new_serial.closing_wait * HZ / 100; 25691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_serial.flags = (new_serial.flags & ~ASYNC_FLAGS); 25721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_serial.flags |= (info->asyncflags & ASYNC_FLAGS); 25731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (new_serial.type == PORT_16550A) { 25751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaSetFifo(info->port, 1); 25761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 25771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaSetFifo(info->port, 0); 25781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->type = new_serial.type; 25811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 25821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************************************************** 25871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Static local functions: * 25881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/ 25891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxafunc(void __iomem *ofsAddr, int cmd, ushort arg) 25901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(arg, ofsAddr + FuncArg); 25931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(cmd, ofsAddr + FuncCode); 25946f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_wait_finish(ofsAddr); 25951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25976f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic void moxa_wait_finish(void __iomem *ofsAddr) 25981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long i, j; 26001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = jiffies; 26021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (readw(ofsAddr + FuncCode) != 0) { 26031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds j = jiffies; 26041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((j - i) > moxaFuncTout) { 26051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 26061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 26071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 26081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 26091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26106f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic void moxa_low_water_check(void __iomem *ofsAddr) 26111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 26131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort rptr, wptr, mask; 26141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (readb(ofsAddr + FlagStat) & Xoff_state) { 26161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rptr = readw(ofsAddr + RXrptr); 26171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wptr = readw(ofsAddr + RXwptr); 26181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = readw(ofsAddr + RX_mask); 26191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = (wptr - rptr) & mask; 26201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len <= Low_water) 26211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SendXon, 0); 26221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 26231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 26241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void MoxaSetFifo(int port, int enable) 26261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26278f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby void __iomem *ofsAddr = moxa_ports[port].tableAddr; 26281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!enable) { 26301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0); 26311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetTxFIFOCnt, 1); 26321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 26331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetRxFIFOTrig, 3); 26341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16); 26351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 26361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2637