moxa.c revision a8f5cda067e2eeefe49fe386caf0f61fc5c825e0
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> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h> 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 50037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#include "moxa.h" 51037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 5211324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MOXA_VERSION "5.1k" 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 54037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#define MOXA_FW_HDRLEN 32 55037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 5611324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MOXAMAJOR 172 5711324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MOXACUMAJOR 173 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5911324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MAX_BOARDS 4 /* Don't change this value */ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_PORTS_PER_BOARD 32 /* Don't change this value */ 6111324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MAX_PORTS (MAX_BOARDS * MAX_PORTS_PER_BOARD) 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Define the Moxa PCI vendor and device IDs. 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6611324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MOXA_BUS_TYPE_ISA 0 6711324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MOXA_BUS_TYPE_PCI 1 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum { 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MOXA_BOARD_C218_PCI = 1, 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MOXA_BOARD_C218_ISA, 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MOXA_BOARD_C320_PCI, 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MOXA_BOARD_C320_ISA, 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MOXA_BOARD_CP204J, 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *moxa_brdname[] = 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "C218 Turbo PCI series", 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "C218 Turbo ISA series", 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "C320 Turbo PCI series", 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "C320 Turbo ISA series", 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CP-204J series", 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_device_id moxa_pcibrds[] = { 885ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C218), 895ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby .driver_data = MOXA_BOARD_C218_PCI }, 905ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C320), 915ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby .driver_data = MOXA_BOARD_C320_PCI }, 925ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP204J), 935ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby .driver_data = MOXA_BOARD_CP204J }, 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0 } 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, moxa_pcibrds); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_PCI */ 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 99037182346f0991683cc7320a257c3f6089432ceeJiri Slabystruct moxa_port; 100037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 1018f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic struct moxa_board_conf { 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int boardType; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int numPorts; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int busType; 1058f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby 106810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby unsigned int ready; 1078f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby 108037182346f0991683cc7320a257c3f6089432ceeJiri Slaby struct moxa_port *ports; 109037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 1108f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby void __iomem *basemem; 1118f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby void __iomem *intNdx; 1128f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby void __iomem *intPend; 1138f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby void __iomem *intTable; 1148f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby} moxa_boards[MAX_BOARDS]; 1158f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby 1168f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystruct mxser_mstatus { 1178f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby tcflag_t cflag; 1188f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int cts; 1198f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int dsr; 1208f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int ri; 1218f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int dcd; 1229dff89cd82af7bccc706fed288b1c33a51c3b937Jiri Slaby}; 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1248f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystruct moxaq_str { 1258f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int inq; 1268f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int outq; 1278f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby}; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1298f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystruct moxa_port { 130b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby struct moxa_board_conf *board; 1317bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby struct tty_struct *tty; 1327bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby void __iomem *tableAddr; 1337bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int type; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int close_delay; 136a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby unsigned int count; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int asyncflags; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int cflag; 1397bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby unsigned long statusflags; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_queue_head_t open_wait; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1427bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby u8 DCDState; 1437bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby u8 lineCtrl; 1447bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby u8 lowChkFlag; 1458f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby}; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystruct mon_str { 14874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby int tick; 14974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby int rxcnt[MAX_PORTS]; 15074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby int txcnt[MAX_PORTS]; 15174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby}; 15274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* statusflags */ 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TXSTOPPED 0x1 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LOWWAIT 0x2 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EMPTYWAIT 0x4 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define THROTTLE 0x8 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SERIAL_DO_RESTART 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WAKEUP_CHARS 256 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ttymajor = MOXAMAJOR; 16474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic struct mon_str moxaLog; 16574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic unsigned int moxaFuncTout = HZ / 2; 1667bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic unsigned int moxaLowWaterChk; 167a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slabystatic DEFINE_MUTEX(moxa_openlock); 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Variables for insmod */ 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE 170d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabystatic unsigned long baseaddr[MAX_BOARDS]; 171d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabystatic unsigned int type[MAX_BOARDS]; 172d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabystatic unsigned int numports[MAX_BOARDS]; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("William Chen"); 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver"); 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE 179d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabymodule_param_array(type, uint, NULL, 0); 180d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri SlabyMODULE_PARM_DESC(type, "card type: C218=2, C320=4"); 181d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabymodule_param_array(baseaddr, ulong, NULL, 0); 182d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri SlabyMODULE_PARM_DESC(baseaddr, "base address"); 183d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabymodule_param_array(numports, uint, NULL, 0); 184d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri SlabyMODULE_PARM_DESC(numports, "numports (ignored for C218)"); 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(ttymajor, int, 0); 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * static functions: 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_open(struct tty_struct *, struct file *); 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_close(struct tty_struct *, struct file *); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_write(struct tty_struct *, const unsigned char *, int); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_write_room(struct tty_struct *); 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_flush_buffer(struct tty_struct *); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_chars_in_buffer(struct tty_struct *); 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_flush_chars(struct tty_struct *); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_put_char(struct tty_struct *, unsigned char); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_throttle(struct tty_struct *); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_unthrottle(struct tty_struct *); 201606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Coxstatic void moxa_set_termios(struct tty_struct *, struct ktermios *); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_stop(struct tty_struct *); 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_start(struct tty_struct *); 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_hangup(struct tty_struct *); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_tiocmget(struct tty_struct *tty, struct file *file); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_tiocmset(struct tty_struct *tty, struct file *file, 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int set, unsigned int clear); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_poll(unsigned long); 209db1acaa632870ec87b65e062bc72ca375837a1f6Alan Coxstatic void moxa_set_tty_param(struct tty_struct *, struct ktermios *); 2106f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic void moxa_setup_empty_event(struct tty_struct *); 2116f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic void moxa_shut_down(struct moxa_port *); 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * moxa board interface functions: 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 215b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortEnable(struct moxa_port *); 216b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortDisable(struct moxa_port *); 217b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortSetTermio(struct moxa_port *, struct ktermios *, speed_t); 218b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortGetLineOut(struct moxa_port *, int *, int *); 219b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortLineCtrl(struct moxa_port *, int, int); 220b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int); 221b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortLineStatus(struct moxa_port *); 222b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortFlushData(struct moxa_port *, int); 2232108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slabystatic int MoxaPortWriteData(struct moxa_port *, const unsigned char *, int); 2247bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int MoxaPortReadData(struct moxa_port *); 225b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortTxQueue(struct moxa_port *); 226b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortRxQueue(struct moxa_port *); 227b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortTxFree(struct moxa_port *); 228b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortTxDisable(struct moxa_port *); 229b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortTxEnable(struct moxa_port *); 2308f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic int moxa_get_serial_info(struct moxa_port *, struct serial_struct __user *); 2318f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic int moxa_set_serial_info(struct moxa_port *, struct serial_struct __user *); 232b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaSetFifo(struct moxa_port *port, int enable); 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby/* 23574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby * I/O functions 23674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby */ 23774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 23874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void moxa_wait_finish(void __iomem *ofsAddr) 23974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby{ 24074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby unsigned long end = jiffies + moxaFuncTout; 24174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 24274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby while (readw(ofsAddr + FuncCode) != 0) 24374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (time_after(jiffies, end)) 24474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby return; 24574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (readw(ofsAddr + FuncCode) != 0 && printk_ratelimit()) 24674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby printk(KERN_WARNING "moxa function expired\n"); 24774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby} 24874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 24974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void moxafunc(void __iomem *ofsAddr, int cmd, ushort arg) 25074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby{ 25174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby writew(arg, ofsAddr + FuncArg); 25274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby writew(cmd, ofsAddr + FuncCode); 25374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby moxa_wait_finish(ofsAddr); 25474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby} 25574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 2567bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void moxa_low_water_check(void __iomem *ofsAddr) 2577bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby{ 2587bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby u16 rptr, wptr, mask, len; 2597bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 2607bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (readb(ofsAddr + FlagStat) & Xoff_state) { 2617bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby rptr = readw(ofsAddr + RXrptr); 2627bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby wptr = readw(ofsAddr + RXwptr); 2637bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby mask = readw(ofsAddr + RX_mask); 2647bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby len = (wptr - rptr) & mask; 2657bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (len <= Low_water) 2667bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby moxafunc(ofsAddr, FC_SendXon, 0); 2677bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby } 2687bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby} 2697bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 27074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby/* 27174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby * TTY operations 27274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby */ 27374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 27474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic int moxa_ioctl(struct tty_struct *tty, struct file *file, 27574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby unsigned int cmd, unsigned long arg) 27674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby{ 27774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby struct moxa_port *ch = tty->driver_data; 27874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby void __user *argp = (void __user *)arg; 279a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby int status, ret = 0; 28074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 28174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (tty->index == MAX_PORTS) { 28274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (cmd != MOXA_GETDATACOUNT && cmd != MOXA_GET_IOQUEUE && 28374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby cmd != MOXA_GETMSTATUS) 28474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby return -EINVAL; 28574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } else if (!ch) 28674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby return -ENODEV; 28774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 28874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby switch (cmd) { 28974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby case MOXA_GETDATACOUNT: 29074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby moxaLog.tick = jiffies; 291a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (copy_to_user(argp, &moxaLog, sizeof(moxaLog))) 292a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ret = -EFAULT; 293a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 29474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby case MOXA_FLUSH_QUEUE: 29574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby MoxaPortFlushData(ch, arg); 296a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 29774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby case MOXA_GET_IOQUEUE: { 29874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby struct moxaq_str __user *argm = argp; 29974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby struct moxaq_str tmp; 30074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby struct moxa_port *p; 30174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby unsigned int i, j; 30274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 303a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_lock(&moxa_openlock); 30474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby for (i = 0; i < MAX_BOARDS; i++) { 30574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby p = moxa_boards[i].ports; 30674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { 30774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby memset(&tmp, 0, sizeof(tmp)); 30874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (moxa_boards[i].ready) { 30974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby tmp.inq = MoxaPortRxQueue(p); 31074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby tmp.outq = MoxaPortTxQueue(p); 31174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } 312a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (copy_to_user(argm, &tmp, sizeof(tmp))) { 313a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 31474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby return -EFAULT; 315a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby } 31674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } 31774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } 318a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 319a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 32074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } case MOXA_GET_OQUEUE: 32174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby status = MoxaPortTxQueue(ch); 322a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ret = put_user(status, (unsigned long __user *)argp); 323a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 32474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby case MOXA_GET_IQUEUE: 32574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby status = MoxaPortRxQueue(ch); 326a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ret = put_user(status, (unsigned long __user *)argp); 327a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 32874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby case MOXA_GETMSTATUS: { 32974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby struct mxser_mstatus __user *argm = argp; 33074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby struct mxser_mstatus tmp; 33174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby struct moxa_port *p; 33274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby unsigned int i, j; 33374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 334a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_lock(&moxa_openlock); 33574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby for (i = 0; i < MAX_BOARDS; i++) { 33674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby p = moxa_boards[i].ports; 33774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { 33874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby memset(&tmp, 0, sizeof(tmp)); 33974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (!moxa_boards[i].ready) 34074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby goto copy; 34174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 34274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby status = MoxaPortLineStatus(p); 34374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (status & 1) 34474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby tmp.cts = 1; 34574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (status & 2) 34674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby tmp.dsr = 1; 34774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (status & 4) 34874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby tmp.dcd = 1; 34974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 35074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (!p->tty || !p->tty->termios) 35174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby tmp.cflag = p->cflag; 35274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby else 35374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby tmp.cflag = p->tty->termios->c_cflag; 35474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabycopy: 355a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (copy_to_user(argm, &tmp, sizeof(tmp))) { 356a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 35774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby return -EFAULT; 358a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby } 35974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } 36074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } 361a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 362a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 36374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } 36474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby case TIOCGSERIAL: 365a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_lock(&moxa_openlock); 366a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ret = moxa_get_serial_info(ch, argp); 367a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 368a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 36974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby case TIOCSSERIAL: 370a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_lock(&moxa_openlock); 371a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ret = moxa_set_serial_info(ch, argp); 372a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 373a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 374a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby default: 375a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ret = -ENOIOCTLCMD; 37674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } 377a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby return ret; 37874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby} 37974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 38074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void moxa_break_ctl(struct tty_struct *tty, int state) 38174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby{ 38274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby struct moxa_port *port = tty->driver_data; 38374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 38474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak, 38574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby Magic_code); 38674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby} 38774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 388b68e31d0ebbcc909d1941f9f230c9d062a3a13d3Jeff Dikestatic const struct tty_operations moxa_ops = { 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .open = moxa_open, 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .close = moxa_close, 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write = moxa_write, 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write_room = moxa_write_room, 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .flush_buffer = moxa_flush_buffer, 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chars_in_buffer = moxa_chars_in_buffer, 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .flush_chars = moxa_flush_chars, 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .put_char = moxa_put_char, 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .ioctl = moxa_ioctl, 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .throttle = moxa_throttle, 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .unthrottle = moxa_unthrottle, 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_termios = moxa_set_termios, 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .stop = moxa_stop, 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .start = moxa_start, 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hangup = moxa_hangup, 40474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby .break_ctl = moxa_break_ctl, 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .tiocmget = moxa_tiocmget, 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .tiocmset = moxa_tiocmset, 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 409aa7e5221fb47badbea618cc62704d6e4a4bcce15Jiri Slabystatic struct tty_driver *moxaDriver; 410aa7e5221fb47badbea618cc62704d6e4a4bcce15Jiri Slabystatic DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); 41134af946a22724c4e2b204957f2b24b22a0fb121cIngo Molnarstatic DEFINE_SPINLOCK(moxa_lock); 41233f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox 41374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby/* 41474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby * HW init 41574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby */ 41674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 417037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_check_fw_model(struct moxa_board_conf *brd, u8 model) 418037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 419037182346f0991683cc7320a257c3f6089432ceeJiri Slaby switch (brd->boardType) { 420037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_ISA: 421037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_PCI: 422037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (model != 1) 423037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 424037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 425037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_CP204J: 426037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (model != 3) 427037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 428037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 429037182346f0991683cc7320a257c3f6089432ceeJiri Slaby default: 430037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (model != 2) 431037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 432037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 433037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 434037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 435037182346f0991683cc7320a257c3f6089432ceeJiri Slabyerr: 436037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EINVAL; 437037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 438037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 439037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_check_fw(const void *ptr) 440037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 441037182346f0991683cc7320a257c3f6089432ceeJiri Slaby const __le16 *lptr = ptr; 442037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 443037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (*lptr != cpu_to_le16(0x7980)) 444037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EINVAL; 445037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 446037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 447037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 448037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 449037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_load_bios(struct moxa_board_conf *brd, const u8 *buf, 450037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t len) 451037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 452037182346f0991683cc7320a257c3f6089432ceeJiri Slaby void __iomem *baseAddr = brd->basemem; 453037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u16 tmp; 454037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 455037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writeb(HW_reset, baseAddr + Control_reg); /* reset */ 456037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 457037182346f0991683cc7320a257c3f6089432ceeJiri Slaby memset_io(baseAddr, 0, 4096); 458037182346f0991683cc7320a257c3f6089432ceeJiri Slaby memcpy_toio(baseAddr, buf, len); /* download BIOS */ 459037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writeb(0, baseAddr + Control_reg); /* restart */ 460037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 461037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(2000); 462037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 463037182346f0991683cc7320a257c3f6089432ceeJiri Slaby switch (brd->boardType) { 464037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_ISA: 465037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_PCI: 466037182346f0991683cc7320a257c3f6089432ceeJiri Slaby tmp = readw(baseAddr + C218_key); 467037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (tmp != C218_KeyCode) 468037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 469037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 470037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_CP204J: 471037182346f0991683cc7320a257c3f6089432ceeJiri Slaby tmp = readw(baseAddr + C218_key); 472037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (tmp != CP204J_KeyCode) 473037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 474037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 475037182346f0991683cc7320a257c3f6089432ceeJiri Slaby default: 476037182346f0991683cc7320a257c3f6089432ceeJiri Slaby tmp = readw(baseAddr + C320_key); 477037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (tmp != C320_KeyCode) 478037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 479037182346f0991683cc7320a257c3f6089432ceeJiri Slaby tmp = readw(baseAddr + C320_status); 480037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (tmp != STS_init) { 481037182346f0991683cc7320a257c3f6089432ceeJiri Slaby printk(KERN_ERR "moxa: bios upload failed -- CPU/Basic " 482037182346f0991683cc7320a257c3f6089432ceeJiri Slaby "module not found\n"); 483037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 484037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 485037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 486037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 487037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 488037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 489037182346f0991683cc7320a257c3f6089432ceeJiri Slabyerr: 490037182346f0991683cc7320a257c3f6089432ceeJiri Slaby printk(KERN_ERR "moxa: bios upload failed -- board not found\n"); 491037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 492037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 493037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 494037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_load_320b(struct moxa_board_conf *brd, const u8 *ptr, 495037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t len) 496037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 497037182346f0991683cc7320a257c3f6089432ceeJiri Slaby void __iomem *baseAddr = brd->basemem; 498037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 499037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (len < 7168) { 500037182346f0991683cc7320a257c3f6089432ceeJiri Slaby printk(KERN_ERR "moxa: invalid 320 bios -- too short\n"); 501037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EINVAL; 502037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 503037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 504037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(len - 7168 - 2, baseAddr + C320bapi_len); 505037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writeb(1, baseAddr + Control_reg); /* Select Page 1 */ 506037182346f0991683cc7320a257c3f6089432ceeJiri Slaby memcpy_toio(baseAddr + DynPage_addr, ptr, 7168); 507037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writeb(2, baseAddr + Control_reg); /* Select Page 2 */ 508037182346f0991683cc7320a257c3f6089432ceeJiri Slaby memcpy_toio(baseAddr + DynPage_addr, ptr + 7168, len - 7168); 509037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 510037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 511037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 512037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 5135292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slabystatic int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr, 514037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t len) 515037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 516037182346f0991683cc7320a257c3f6089432ceeJiri Slaby void __iomem *baseAddr = brd->basemem; 517037182346f0991683cc7320a257c3f6089432ceeJiri Slaby const u16 *uptr = ptr; 518037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t wlen, len2, j; 5195292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby unsigned long key, loadbuf, loadlen, checksum, checksum_ok; 5205292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby unsigned int i, retry, c320; 521037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u16 usum, keycode; 522037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 5235292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby c320 = brd->boardType == MOXA_BOARD_C320_PCI || 5245292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby brd->boardType == MOXA_BOARD_C320_ISA; 5255292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby keycode = (brd->boardType == MOXA_BOARD_CP204J) ? CP204J_KeyCode : 5265292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby C218_KeyCode; 527037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 5285292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby switch (brd->boardType) { 5295292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby case MOXA_BOARD_CP204J: 5305292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby case MOXA_BOARD_C218_ISA: 5315292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby case MOXA_BOARD_C218_PCI: 5325292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby key = C218_key; 5335292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby loadbuf = C218_LoadBuf; 5345292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby loadlen = C218DLoad_len; 5355292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby checksum = C218check_sum; 5365292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby checksum_ok = C218chksum_ok; 5375292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby break; 5385292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby default: 5395292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby key = C320_key; 5405292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby keycode = C320_KeyCode; 5415292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby loadbuf = C320_LoadBuf; 5425292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby loadlen = C320DLoad_len; 5435292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby checksum = C320check_sum; 5445292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby checksum_ok = C320chksum_ok; 5455292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby break; 546037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 547037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 548037182346f0991683cc7320a257c3f6089432ceeJiri Slaby usum = 0; 549037182346f0991683cc7320a257c3f6089432ceeJiri Slaby wlen = len >> 1; 550037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < wlen; i++) 551037182346f0991683cc7320a257c3f6089432ceeJiri Slaby usum += le16_to_cpu(uptr[i]); 552037182346f0991683cc7320a257c3f6089432ceeJiri Slaby retry = 0; 553037182346f0991683cc7320a257c3f6089432ceeJiri Slaby do { 554037182346f0991683cc7320a257c3f6089432ceeJiri Slaby wlen = len >> 1; 555037182346f0991683cc7320a257c3f6089432ceeJiri Slaby j = 0; 556037182346f0991683cc7320a257c3f6089432ceeJiri Slaby while (wlen) { 557037182346f0991683cc7320a257c3f6089432ceeJiri Slaby len2 = (wlen > 2048) ? 2048 : wlen; 558037182346f0991683cc7320a257c3f6089432ceeJiri Slaby wlen -= len2; 5595292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby memcpy_toio(baseAddr + loadbuf, ptr + j, len2 << 1); 560037182346f0991683cc7320a257c3f6089432ceeJiri Slaby j += len2 << 1; 5615292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby 5625292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(len2, baseAddr + loadlen); 5635292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0, baseAddr + key); 5645292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby for (i = 0; i < 100; i++) { 5655292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (readw(baseAddr + key) == keycode) 566037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 567037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 568037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 5695292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (readw(baseAddr + key) != keycode) 570037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 571037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 5725292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0, baseAddr + loadlen); 5735292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(usum, baseAddr + checksum); 5745292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0, baseAddr + key); 5755292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby for (i = 0; i < 100; i++) { 5765292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (readw(baseAddr + key) == keycode) 577037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 578037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 579037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 580037182346f0991683cc7320a257c3f6089432ceeJiri Slaby retry++; 5815292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby } while ((readb(baseAddr + checksum_ok) != 1) && (retry < 3)); 5825292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (readb(baseAddr + checksum_ok) != 1) 583037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 584037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 5855292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0, baseAddr + key); 586037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < 600; i++) { 587037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) == Magic_code) 588037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 589037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 590037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 591037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) != Magic_code) 592037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 593037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 5945292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (c320) { 5955292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (brd->busType == MOXA_BUS_TYPE_PCI) { /* ASIC board */ 5965292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0x3800, baseAddr + TMS320_PORT1); 5975292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0x3900, baseAddr + TMS320_PORT2); 5985292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(28499, baseAddr + TMS320_CLOCK); 5995292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby } else { 6005292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0x3200, baseAddr + TMS320_PORT1); 6015292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0x3400, baseAddr + TMS320_PORT2); 6025292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(19999, baseAddr + TMS320_CLOCK); 6035292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby } 604037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 605037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(1, baseAddr + Disable_IRQ); 606037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0, baseAddr + Magic_no); 607037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < 500; i++) { 608037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) == Magic_code) 609037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 610037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 611037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 612037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) != Magic_code) 613037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 614037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 6155292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (c320) { 6165292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby j = readw(baseAddr + Module_cnt); 6175292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (j <= 0) 6185292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby return -EIO; 6195292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby brd->numPorts = j * 8; 6205292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(j, baseAddr + Module_no); 6215292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0, baseAddr + Magic_no); 6225292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby for (i = 0; i < 600; i++) { 6235292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (readw(baseAddr + Magic_no) == Magic_code) 6245292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby break; 6255292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby msleep(10); 6265292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby } 6275292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (readw(baseAddr + Magic_no) != Magic_code) 6285292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby return -EIO; 629037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 630037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->intNdx = baseAddr + IRQindex; 631037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->intPend = baseAddr + IRQpending; 632037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->intTable = baseAddr + IRQtable; 633037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 634037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 635037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 636037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 637037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_load_code(struct moxa_board_conf *brd, const void *ptr, 638037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t len) 639037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 640037182346f0991683cc7320a257c3f6089432ceeJiri Slaby void __iomem *ofsAddr, *baseAddr = brd->basemem; 641037182346f0991683cc7320a257c3f6089432ceeJiri Slaby struct moxa_port *port; 642037182346f0991683cc7320a257c3f6089432ceeJiri Slaby int retval, i; 643037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 644037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (len % 2) { 6455292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby printk(KERN_ERR "moxa: bios length is not even\n"); 646037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EINVAL; 647037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 648037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 6495292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby retval = moxa_real_load_code(brd, ptr, len); /* may change numPorts */ 6505292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (retval) 6515292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby return retval; 6525292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby 653037182346f0991683cc7320a257c3f6089432ceeJiri Slaby switch (brd->boardType) { 654037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_ISA: 655037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_PCI: 656037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_CP204J: 657037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port = brd->ports; 658037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < brd->numPorts; i++, port++) { 659b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby port->board = brd; 660037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port->DCDState = 0; 661037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port->tableAddr = baseAddr + Extern_table + 662037182346f0991683cc7320a257c3f6089432ceeJiri Slaby Extern_size * i; 663037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ofsAddr = port->tableAddr; 664037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C218rx_mask, ofsAddr + RX_mask); 665037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C218tx_mask, ofsAddr + TX_mask); 666037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb); 667037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb); 668037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 669037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb); 670037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb); 671037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 672037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 673037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 674037182346f0991683cc7320a257c3f6089432ceeJiri Slaby default: 675037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port = brd->ports; 676037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < brd->numPorts; i++, port++) { 677b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby port->board = brd; 678037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port->DCDState = 0; 679037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port->tableAddr = baseAddr + Extern_table + 680037182346f0991683cc7320a257c3f6089432ceeJiri Slaby Extern_size * i; 681037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ofsAddr = port->tableAddr; 682037182346f0991683cc7320a257c3f6089432ceeJiri Slaby switch (brd->numPorts) { 683037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case 8: 684037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p8rx_mask, ofsAddr + RX_mask); 685037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p8tx_mask, ofsAddr + TX_mask); 686037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb); 687037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb); 688037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb); 689037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb); 690037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 691037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 692037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case 16: 693037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p16rx_mask, ofsAddr + RX_mask); 694037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p16tx_mask, ofsAddr + TX_mask); 695037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb); 696037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb); 697037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb); 698037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb); 699037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 700037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 701037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case 24: 702037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p24rx_mask, ofsAddr + RX_mask); 703037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p24tx_mask, ofsAddr + TX_mask); 704037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb); 705037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb); 706037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb); 707037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb); 708037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 709037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case 32: 710037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p32rx_mask, ofsAddr + RX_mask); 711037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p32tx_mask, ofsAddr + TX_mask); 712037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p32tx_ofs, ofsAddr + Ofs_txb); 713037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb); 714037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb); 715037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb); 716037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb); 717037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 718037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 719037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 720037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 721037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 722037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 723037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 724037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 725037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_load_fw(struct moxa_board_conf *brd, const struct firmware *fw) 726037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 727037182346f0991683cc7320a257c3f6089432ceeJiri Slaby void *ptr = fw->data; 728037182346f0991683cc7320a257c3f6089432ceeJiri Slaby char rsn[64]; 729037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u16 lens[5]; 730037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t len; 731037182346f0991683cc7320a257c3f6089432ceeJiri Slaby unsigned int a, lenp, lencnt; 732037182346f0991683cc7320a257c3f6089432ceeJiri Slaby int ret = -EINVAL; 733037182346f0991683cc7320a257c3f6089432ceeJiri Slaby struct { 734037182346f0991683cc7320a257c3f6089432ceeJiri Slaby __le32 magic; /* 0x34303430 */ 735037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u8 reserved1[2]; 736037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u8 type; /* UNIX = 3 */ 737037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u8 model; /* C218T=1, C320T=2, CP204=3 */ 738037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u8 reserved2[8]; 739037182346f0991683cc7320a257c3f6089432ceeJiri Slaby __le16 len[5]; 740037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } *hdr = ptr; 741037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 742037182346f0991683cc7320a257c3f6089432ceeJiri Slaby BUILD_BUG_ON(ARRAY_SIZE(hdr->len) != ARRAY_SIZE(lens)); 743037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 744037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (fw->size < MOXA_FW_HDRLEN) { 745037182346f0991683cc7320a257c3f6089432ceeJiri Slaby strcpy(rsn, "too short (even header won't fit)"); 746037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 747037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 748037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (hdr->magic != cpu_to_le32(0x30343034)) { 749037182346f0991683cc7320a257c3f6089432ceeJiri Slaby sprintf(rsn, "bad magic: %.8x", le32_to_cpu(hdr->magic)); 750037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 751037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 752037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (hdr->type != 3) { 753037182346f0991683cc7320a257c3f6089432ceeJiri Slaby sprintf(rsn, "not for linux, type is %u", hdr->type); 754037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 755037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 756037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (moxa_check_fw_model(brd, hdr->model)) { 757037182346f0991683cc7320a257c3f6089432ceeJiri Slaby sprintf(rsn, "not for this card, model is %u", hdr->model); 758037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 759037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 760037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 761037182346f0991683cc7320a257c3f6089432ceeJiri Slaby len = MOXA_FW_HDRLEN; 762037182346f0991683cc7320a257c3f6089432ceeJiri Slaby lencnt = hdr->model == 2 ? 5 : 3; 763037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (a = 0; a < ARRAY_SIZE(lens); a++) { 764037182346f0991683cc7320a257c3f6089432ceeJiri Slaby lens[a] = le16_to_cpu(hdr->len[a]); 765037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (lens[a] && len + lens[a] <= fw->size && 766037182346f0991683cc7320a257c3f6089432ceeJiri Slaby moxa_check_fw(&fw->data[len])) 767037182346f0991683cc7320a257c3f6089432ceeJiri Slaby printk(KERN_WARNING "moxa firmware: unexpected input " 768037182346f0991683cc7320a257c3f6089432ceeJiri Slaby "at offset %u, but going on\n", (u32)len); 769037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (!lens[a] && a < lencnt) { 770037182346f0991683cc7320a257c3f6089432ceeJiri Slaby sprintf(rsn, "too few entries in fw file"); 771037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 772037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 773037182346f0991683cc7320a257c3f6089432ceeJiri Slaby len += lens[a]; 774037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 775037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 776037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (len != fw->size) { 777037182346f0991683cc7320a257c3f6089432ceeJiri Slaby sprintf(rsn, "bad length: %u (should be %u)", (u32)fw->size, 778037182346f0991683cc7320a257c3f6089432ceeJiri Slaby (u32)len); 779037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 780037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 781037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 782037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ptr += MOXA_FW_HDRLEN; 783037182346f0991683cc7320a257c3f6089432ceeJiri Slaby lenp = 0; /* bios */ 784037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 785037182346f0991683cc7320a257c3f6089432ceeJiri Slaby strcpy(rsn, "read above"); 786037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 787037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ret = moxa_load_bios(brd, ptr, lens[lenp]); 788037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (ret) 789037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 790037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 791037182346f0991683cc7320a257c3f6089432ceeJiri Slaby /* we skip the tty section (lens[1]), since we don't need it */ 792037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ptr += lens[lenp] + lens[lenp + 1]; 793037182346f0991683cc7320a257c3f6089432ceeJiri Slaby lenp += 2; /* comm */ 794037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 795037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (hdr->model == 2) { 796037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ret = moxa_load_320b(brd, ptr, lens[lenp]); 797037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (ret) 798037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 799037182346f0991683cc7320a257c3f6089432ceeJiri Slaby /* skip another tty */ 800037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ptr += lens[lenp] + lens[lenp + 1]; 801037182346f0991683cc7320a257c3f6089432ceeJiri Slaby lenp += 2; 802037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 803037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 804037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ret = moxa_load_code(brd, ptr, lens[lenp]); 805037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (ret) 806037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 807037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 808037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 809037182346f0991683cc7320a257c3f6089432ceeJiri Slabyerr: 810037182346f0991683cc7320a257c3f6089432ceeJiri Slaby printk(KERN_ERR "firmware failed to load, reason: %s\n", rsn); 811037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return ret; 812037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 813037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 814037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_init_board(struct moxa_board_conf *brd, struct device *dev) 815037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 816037182346f0991683cc7320a257c3f6089432ceeJiri Slaby const struct firmware *fw; 817037182346f0991683cc7320a257c3f6089432ceeJiri Slaby const char *file; 818810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby struct moxa_port *p; 819810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby unsigned int i; 820037182346f0991683cc7320a257c3f6089432ceeJiri Slaby int ret; 821037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 822810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby brd->ports = kcalloc(MAX_PORTS_PER_BOARD, sizeof(*brd->ports), 823810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby GFP_KERNEL); 824810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby if (brd->ports == NULL) { 825810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby printk(KERN_ERR "cannot allocate memory for ports\n"); 826810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby ret = -ENOMEM; 827810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby goto err; 828810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby } 829810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby 830810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) { 831810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby p->type = PORT_16550A; 832810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby p->close_delay = 5 * HZ / 10; 833810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; 834810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby init_waitqueue_head(&p->open_wait); 835810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby } 836810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby 837037182346f0991683cc7320a257c3f6089432ceeJiri Slaby switch (brd->boardType) { 838037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_ISA: 839037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_PCI: 840037182346f0991683cc7320a257c3f6089432ceeJiri Slaby file = "c218tunx.cod"; 841037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 842037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_CP204J: 843037182346f0991683cc7320a257c3f6089432ceeJiri Slaby file = "cp204unx.cod"; 844037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 845037182346f0991683cc7320a257c3f6089432ceeJiri Slaby default: 846037182346f0991683cc7320a257c3f6089432ceeJiri Slaby file = "c320tunx.cod"; 847037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 848037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 849037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 850037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ret = request_firmware(&fw, file, dev); 851037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (ret) { 852037182346f0991683cc7320a257c3f6089432ceeJiri Slaby printk(KERN_ERR "request_firmware failed\n"); 853810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby goto err_free; 854037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 855037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 856037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ret = moxa_load_fw(brd, fw); 857037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 858037182346f0991683cc7320a257c3f6089432ceeJiri Slaby release_firmware(fw); 859810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby 860810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby if (ret) 861810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby goto err_free; 862810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby 8632a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby spin_lock_bh(&moxa_lock); 864810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby brd->ready = 1; 8650bcc4caadc8f5396b52950ee03c67b76875602dfJiri Slaby if (!timer_pending(&moxaTimer)) 8660bcc4caadc8f5396b52950ee03c67b76875602dfJiri Slaby mod_timer(&moxaTimer, jiffies + HZ / 50); 8672a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby spin_unlock_bh(&moxa_lock); 8680bcc4caadc8f5396b52950ee03c67b76875602dfJiri Slaby 869810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby return 0; 870810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slabyerr_free: 871810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby kfree(brd->ports); 872810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slabyerr: 873037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return ret; 874037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 875037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 876810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slabystatic void moxa_board_deinit(struct moxa_board_conf *brd) 877810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby{ 878a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby unsigned int a, opened; 879a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby 880a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_lock(&moxa_openlock); 8817bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby spin_lock_bh(&moxa_lock); 882810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby brd->ready = 0; 8837bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby spin_unlock_bh(&moxa_lock); 884a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby 885a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby /* pci hot-un-plug support */ 886a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby for (a = 0; a < brd->numPorts; a++) 887a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (brd->ports[a].asyncflags & ASYNC_INITIALIZED) 888a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby tty_hangup(brd->ports[a].tty); 889a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby while (1) { 890a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby opened = 0; 891a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby for (a = 0; a < brd->numPorts; a++) 892a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (brd->ports[a].asyncflags & ASYNC_INITIALIZED) 893a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby opened++; 894a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 895a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (!opened) 896a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 897a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby msleep(50); 898a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_lock(&moxa_openlock); 899a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby } 900a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby 901810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby iounmap(brd->basemem); 902810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby brd->basemem = NULL; 903810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby kfree(brd->ports); 904810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby} 905810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI 9079cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slabystatic int __devinit moxa_pci_probe(struct pci_dev *pdev, 9089cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby const struct pci_device_id *ent) 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9109cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby struct moxa_board_conf *board; 9119cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby unsigned int i; 9129cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby int board_type = ent->driver_data; 9139cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby int retval; 9149cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 9159cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby retval = pci_enable_device(pdev); 9167aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby if (retval) { 9177aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby dev_err(&pdev->dev, "can't enable pci device\n"); 9189cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby goto err; 9197aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby } 9209cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 9219cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby for (i = 0; i < MAX_BOARDS; i++) 9229cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby if (moxa_boards[i].basemem == NULL) 9239cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby break; 9249cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 9259cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby retval = -ENODEV; 9269cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby if (i >= MAX_BOARDS) { 9277aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby dev_warn(&pdev->dev, "more than %u MOXA Intellio family boards " 9289cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby "found. Board is ignored.\n", MAX_BOARDS); 9299cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby goto err; 9309cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby } 9319cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 9329cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby board = &moxa_boards[i]; 933e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby 934e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby retval = pci_request_region(pdev, 2, "moxa-base"); 935e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby if (retval) { 936e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby dev_err(&pdev->dev, "can't request pci region 2\n"); 937e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby goto err; 938e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby } 939e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby 940e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby board->basemem = ioremap(pci_resource_start(pdev, 2), 0x4000); 9417aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby if (board->basemem == NULL) { 9427aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby dev_err(&pdev->dev, "can't remap io space 2\n"); 943e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby goto err_reg; 9447aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby } 9459cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board->boardType = board_type; 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (board_type) { 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MOXA_BOARD_C218_ISA: 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MOXA_BOARD_C218_PCI: 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board->numPorts = 8; 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MOXA_BOARD_CP204J: 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board->numPorts = 4; 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board->numPorts = 0; 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board->busType = MOXA_BUS_TYPE_PCI; 961a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby 962037182346f0991683cc7320a257c3f6089432ceeJiri Slaby retval = moxa_init_board(board, &pdev->dev); 963037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (retval) 964037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err_base; 965037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 9669cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby pci_set_drvdata(pdev, board); 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 969037182346f0991683cc7320a257c3f6089432ceeJiri Slabyerr_base: 970037182346f0991683cc7320a257c3f6089432ceeJiri Slaby iounmap(board->basemem); 971037182346f0991683cc7320a257c3f6089432ceeJiri Slaby board->basemem = NULL; 972e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slabyerr_reg: 973e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby pci_release_region(pdev, 2); 9749cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slabyerr: 9759cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby return retval; 9769cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby} 9779cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 9789cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slabystatic void __devexit moxa_pci_remove(struct pci_dev *pdev) 9799cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby{ 9809cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby struct moxa_board_conf *brd = pci_get_drvdata(pdev); 9819cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 982810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby moxa_board_deinit(brd); 983810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby 984e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby pci_release_region(pdev, 2); 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 986a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby 987a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slabystatic struct pci_driver moxa_pci_driver = { 988a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby .name = "moxa", 989a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby .id_table = moxa_pcibrds, 990a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby .probe = moxa_pci_probe, 991a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby .remove = __devexit_p(moxa_pci_remove) 992a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby}; 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_PCI */ 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init moxa_init(void) 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 997810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby unsigned int isabrds = 0; 998d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby int retval = 0; 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10007aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby printk(KERN_INFO "MOXA Intellio family driver version %s\n", 10017aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby MOXA_VERSION); 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver = alloc_tty_driver(MAX_PORTS + 1); 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!moxaDriver) 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->owner = THIS_MODULE; 10079b4e3b13b147e9b737de63188a9ae740eaa8c36dSergey Vlasov moxaDriver->name = "ttyMX"; 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->major = ttymajor; 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->minor_start = 0; 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->type = TTY_DRIVER_TYPE_SERIAL; 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->subtype = SERIAL_TYPE_NORMAL; 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->init_termios = tty_std_termios; 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; 1014606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox moxaDriver->init_termios.c_ispeed = 9600; 1015606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox moxaDriver->init_termios.c_ospeed = 9600; 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->flags = TTY_DRIVER_REAL_RAW; 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_set_operations(moxaDriver, &moxa_ops); 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10197aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby pr_debug("Moxa tty devices major number = %d\n", ttymajor); 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tty_register_driver(moxaDriver)) { 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "Couldn't install MOXA Smartio family driver !\n"); 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_tty_driver(moxaDriver); 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1027d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby /* Find the boards defined from module args. */ 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE 1029d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby { 1030d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby struct moxa_board_conf *brd = moxa_boards; 1031810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby unsigned int i; 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_BOARDS; i++) { 1033d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby if (!baseaddr[i]) 1034d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby break; 1035d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby if (type[i] == MOXA_BOARD_C218_ISA || 1036d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby type[i] == MOXA_BOARD_C320_ISA) { 10377aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n", 1038d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby isabrds + 1, moxa_brdname[type[i] - 1], 1039d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby baseaddr[i]); 1040d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby brd->boardType = type[i]; 1041d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 : 1042d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby numports[i]; 1043d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby brd->busType = MOXA_BUS_TYPE_ISA; 1044d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby brd->basemem = ioremap(baseaddr[i], 0x4000); 1045d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby if (!brd->basemem) { 1046d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby printk(KERN_ERR "moxa: can't remap %lx\n", 1047d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby baseaddr[i]); 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1050037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (moxa_init_board(brd, NULL)) { 1051037182346f0991683cc7320a257c3f6089432ceeJiri Slaby iounmap(brd->basemem); 1052037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->basemem = NULL; 1053037182346f0991683cc7320a257c3f6089432ceeJiri Slaby continue; 1054037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 1055d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby 1056d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby brd++; 1057d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby isabrds++; 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1060d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby } 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1062a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI 1064a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby retval = pci_register_driver(&moxa_pci_driver); 1065a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby if (retval) { 1066a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby printk(KERN_ERR "Can't register moxa pci driver!\n"); 1067d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby if (isabrds) 1068a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby retval = 0; 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1071a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby 1072a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby return retval; 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit moxa_exit(void) 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10799cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby#ifdef CONFIG_PCI 1080a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby pci_unregister_driver(&moxa_pci_driver); 10819cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby#endif 1082a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby 1083810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby for (i = 0; i < MAX_BOARDS; i++) /* ISA boards */ 1084810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby if (moxa_boards[i].ready) 1085810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby moxa_board_deinit(&moxa_boards[i]); 10862a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby 10872a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby del_timer_sync(&moxaTimer); 10882a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby 10892a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby if (tty_unregister_driver(moxaDriver)) 10902a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby printk(KERN_ERR "Couldn't unregister MOXA Intellio family " 10912a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby "serial driver\n"); 10922a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby put_tty_driver(moxaDriver); 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(moxa_init); 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(moxa_exit); 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1098a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slabystatic void moxa_close_port(struct moxa_port *ch) 1099a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby{ 1100a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby moxa_shut_down(ch); 1101a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby MoxaPortFlushData(ch, 2); 1102a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE; 1103a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ch->tty->driver_data = NULL; 1104a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ch->tty = NULL; 1105a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby} 1106a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby 1107a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slabystatic int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, 1108a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby struct moxa_port *ch) 1109a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby{ 1110a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby DEFINE_WAIT(wait); 1111a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby int retval = 0; 1112a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby u8 dcd; 1113a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby 1114a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby while (1) { 1115a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby prepare_to_wait(&ch->open_wait, &wait, TASK_INTERRUPTIBLE); 1116a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (tty_hung_up_p(filp)) { 1117a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#ifdef SERIAL_DO_RESTART 1118a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby retval = -ERESTARTSYS; 1119a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#else 1120a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby retval = -EAGAIN; 1121a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby#endif 1122a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 1123a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby } 1124a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby spin_lock_bh(&moxa_lock); 1125a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby dcd = ch->DCDState; 1126a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby spin_unlock_bh(&moxa_lock); 1127a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (dcd) 1128a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 1129a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby 1130a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (signal_pending(current)) { 1131a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby retval = -ERESTARTSYS; 1132a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 1133a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby } 1134a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby schedule(); 1135a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby } 1136a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby finish_wait(&ch->open_wait, &wait); 1137a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby 1138a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby return retval; 1139a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby} 1140a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_open(struct tty_struct *tty, struct file *filp) 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1143810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby struct moxa_board_conf *brd; 11448f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch; 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int port; 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 114811324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby port = tty->index; 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (port == MAX_PORTS) { 115074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby return capable(CAP_SYS_ADMIN) ? 0 : -EPERM; 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1152a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (mutex_lock_interruptible(&moxa_openlock)) 1153a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby return -ERESTARTSYS; 1154810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby brd = &moxa_boards[port / MAX_PORTS_PER_BOARD]; 1155a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (!brd->ready) { 1156a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 1157810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby return -ENODEV; 1158a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby } 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1160810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby ch = &brd->ports[port % MAX_PORTS_PER_BOARD]; 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->count++; 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty->driver_data = ch; 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->tty = tty; 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(ch->asyncflags & ASYNC_INITIALIZED)) { 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags = 0; 1166db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox moxa_set_tty_param(tty, tty->termios); 1167b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortLineCtrl(ch, 1, 1); 1168b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortEnable(ch); 1169a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby MoxaSetFifo(ch, ch->type == PORT_16550A); 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->asyncflags |= ASYNC_INITIALIZED; 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1172a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1174a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby retval = 0; 1175a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (!(filp->f_flags & O_NONBLOCK) && !C_CLOCAL(tty)) 1176a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby retval = moxa_block_till_ready(tty, filp, ch); 1177a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_lock(&moxa_openlock); 1178a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (retval) { 1179a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (ch->count) /* 0 means already hung up... */ 1180a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (--ch->count == 0) 1181a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby moxa_close_port(ch); 1182a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby } else 1183a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ch->asyncflags |= ASYNC_NORMAL_ACTIVE; 1184a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1186a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby return retval; 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_close(struct tty_struct *tty, struct file *filp) 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11918f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch; 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int port; 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 119411324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby port = tty->index; 1195a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (port == MAX_PORTS || tty_hung_up_p(filp)) 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1198a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_lock(&moxa_openlock); 1199a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ch = tty->driver_data; 1200a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (ch == NULL) 1201a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby goto unlock; 1202a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (tty->count == 1 && ch->count != 1) { 12037aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby printk(KERN_WARNING "moxa_close: bad serial port count; " 12047aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby "tty->count is 1, ch->count is %d\n", ch->count); 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->count = 1; 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (--ch->count < 0) { 12087aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby printk(KERN_WARNING "moxa_close: bad serial port count, " 12097aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby "device=%s\n", tty->name); 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->count = 0; 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1212a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (ch->count) 1213a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby goto unlock; 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->cflag = tty->termios->c_cflag; 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch->asyncflags & ASYNC_INITIALIZED) { 12176f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_setup_empty_event(tty); 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1221a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby moxa_close_port(ch); 1222a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slabyunlock: 1223a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_write(struct tty_struct *tty, 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const unsigned char *buf, int count) 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1229b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby struct moxa_port *ch = tty->driver_data; 1230b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby int len; 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 1233b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby return 0; 123433f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox 12357bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby spin_lock_bh(&moxa_lock); 12362108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby len = MoxaPortWriteData(ch, buf, count); 12377bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby spin_unlock_bh(&moxa_lock); 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /********************************************* 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ( !(ch->statusflags & LOWWAIT) && 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((len != count) || (MoxaPortTxFree(port) <= 100)) ) 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************************************/ 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags |= LOWWAIT; 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (len); 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_write_room(struct tty_struct *tty) 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12498f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch; 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tty->stopped) 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 1253b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby ch = tty->driver_data; 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 1256b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby return MoxaPortTxFree(ch); 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_flush_buffer(struct tty_struct *tty) 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1261b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby struct moxa_port *ch = tty->driver_data; 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1265b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortFlushData(ch, 1); 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_wakeup(tty); 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_chars_in_buffer(struct tty_struct *tty) 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1271b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby struct moxa_port *ch = tty->driver_data; 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int chars; 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Sigh...I have to check if driver_data is NULL here, because 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * if an open() fails, the TTY subsystem eventually calls 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tty_wait_until_sent(), which calls the driver's chars_in_buffer() 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * routine. And since the open() failed, we return 0 here. TDJ 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 1282b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby chars = MoxaPortTxQueue(ch); 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chars) { 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Make it possible to wakeup anything waiting for output 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in tty_ioctl.c, etc. 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(ch->statusflags & EMPTYWAIT)) 12896f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_setup_empty_event(tty); 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (chars); 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_flush_chars(struct tty_struct *tty) 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Don't think I need this, because this is called to empty the TX 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * buffer for the 16450, 16550, etc. 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_put_char(struct tty_struct *tty, unsigned char c) 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1304b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby struct moxa_port *ch = tty->driver_data; 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 13087bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby spin_lock_bh(&moxa_lock); 1309b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortWriteData(ch, &c, 1); 13107bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby spin_unlock_bh(&moxa_lock); 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /************************************************ 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) ) 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *************************************************/ 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags |= LOWWAIT; 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_tiocmget(struct tty_struct *tty, struct file *file) 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1319a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby struct moxa_port *ch; 13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int flag = 0, dtr, rts; 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1322a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_lock(&moxa_openlock); 1323a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ch = tty->driver_data; 1324a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (!ch) { 1325a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 132674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby return -EINVAL; 1327a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby } 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1329b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortGetLineOut(ch, &dtr, &rts); 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dtr) 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flag |= TIOCM_DTR; 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rts) 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flag |= TIOCM_RTS; 1334b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby dtr = MoxaPortLineStatus(ch); 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dtr & 1) 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flag |= TIOCM_CTS; 13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dtr & 2) 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flag |= TIOCM_DSR; 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dtr & 4) 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flag |= TIOCM_CD; 1341a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return flag; 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_tiocmset(struct tty_struct *tty, struct file *file, 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int set, unsigned int clear) 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1348a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby struct moxa_port *ch; 13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int port; 13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int dtr, rts; 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 135211324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby port = tty->index; 1353a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_lock(&moxa_openlock); 1354a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ch = tty->driver_data; 1355a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (!ch) { 1356a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 135774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby return -EINVAL; 1358a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby } 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1360b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortGetLineOut(ch, &dtr, &rts); 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set & TIOCM_RTS) 13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rts = 1; 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set & TIOCM_DTR) 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dtr = 1; 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clear & TIOCM_RTS) 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rts = 0; 13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clear & TIOCM_DTR) 13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dtr = 0; 1369b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortLineCtrl(ch, dtr, rts); 1370a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_throttle(struct tty_struct *tty) 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13768f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = (struct moxa_port *) tty->driver_data; 13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags |= THROTTLE; 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_unthrottle(struct tty_struct *tty) 13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13838f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = (struct moxa_port *) tty->driver_data; 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags &= ~THROTTLE; 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_set_termios(struct tty_struct *tty, 1389606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox struct ktermios *old_termios) 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13918f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = (struct moxa_port *) tty->driver_data; 13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1395db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox moxa_set_tty_param(tty, old_termios); 13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(old_termios->c_cflag & CLOCAL) && 13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (tty->termios->c_cflag & CLOCAL)) 13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up_interruptible(&ch->open_wait); 13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_stop(struct tty_struct *tty) 14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14038f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = (struct moxa_port *) tty->driver_data; 14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1407b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortTxDisable(ch); 14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags |= TXSTOPPED; 14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_start(struct tty_struct *tty) 14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14148f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = (struct moxa_port *) tty->driver_data; 14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(ch->statusflags & TXSTOPPED)) 14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1422b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortTxEnable(ch); 14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags &= ~TXSTOPPED; 14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_hangup(struct tty_struct *tty) 14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1428a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby struct moxa_port *ch; 14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1430a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_lock(&moxa_openlock); 1431a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ch = tty->driver_data; 1432a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (ch == NULL) { 1433a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 1434a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby return; 1435a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby } 14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->count = 0; 1437a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby moxa_close_port(ch); 1438a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 1439a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby 14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up_interruptible(&ch->open_wait); 14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14437bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) 14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14457bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby dcd = !!dcd; 14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14477bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if ((dcd != p->DCDState) && p->tty && C_CLOCAL(p->tty)) { 1448a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (!dcd) 14497bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby tty_hangup(p->tty); 14507bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby } 14517bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby p->DCDState = dcd; 14527bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby} 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14547bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int moxa_poll_port(struct moxa_port *p, unsigned int handle, 14557bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby u16 __iomem *ip) 14567bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby{ 14577bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby struct tty_struct *tty = p->tty; 14587bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby void __iomem *ofsAddr; 14597bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby unsigned int inited = p->asyncflags & ASYNC_INITIALIZED; 14607bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby u16 intr; 14617bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14627bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (tty) { 14637bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if ((p->statusflags & EMPTYWAIT) && 14647bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby MoxaPortTxQueue(p) == 0) { 14657bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby p->statusflags &= ~EMPTYWAIT; 14667bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby tty_wakeup(tty); 14677bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby } 14687bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if ((p->statusflags & LOWWAIT) && !tty->stopped && 14697bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby MoxaPortTxQueue(p) <= WAKEUP_CHARS) { 14707bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby p->statusflags &= ~LOWWAIT; 14717bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby tty_wakeup(tty); 14727bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby } 14737bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14747bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (inited && !(p->statusflags & THROTTLE) && 14757bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby MoxaPortRxQueue(p) > 0) { /* RX */ 14767bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby MoxaPortReadData(p); 14777bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby tty_schedule_flip(tty); 14787bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby } 14797bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby } else { 14807bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby p->statusflags &= ~EMPTYWAIT; 14817bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby MoxaPortFlushData(p, 0); /* flush RX */ 14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14830bcc4caadc8f5396b52950ee03c67b76875602dfJiri Slaby 14847bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (!handle) /* nothing else to do */ 14857bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby return 0; 14867bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14877bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby intr = readw(ip); /* port irq status */ 14887bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (intr == 0) 14897bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby return 0; 14907bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14917bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby writew(0, ip); /* ACK port */ 14927bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby ofsAddr = p->tableAddr; 14937bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (intr & IntrTx) /* disable tx intr */ 14947bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby writew(readw(ofsAddr + HostStat) & ~WakeupTx, 14957bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby ofsAddr + HostStat); 14967bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14977bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (!inited) 14987bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby return 0; 14997bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 15007bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (tty && (intr & IntrBreak) && !I_IGNBRK(tty)) { /* BREAK */ 15017bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby tty_insert_flip_char(tty, 0, TTY_BREAK); 15027bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby tty_schedule_flip(tty); 15037bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby } 15047bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 15057bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (intr & IntrLine) 15067bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state); 15077bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 15087bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby return 0; 15097bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby} 15107bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 15117bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void moxa_poll(unsigned long ignored) 15127bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby{ 15137bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby struct moxa_board_conf *brd; 15147bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby u16 __iomem *ip; 15152a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby unsigned int card, port, served = 0; 15167bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 15177bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby spin_lock(&moxa_lock); 15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (card = 0; card < MAX_BOARDS; card++) { 15197bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby brd = &moxa_boards[card]; 15207bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (!brd->ready) 15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 15227bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 15232a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby served++; 15242a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby 15257bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby ip = NULL; 15267bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (readb(brd->intPend) == 0xff) 15277bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby ip = brd->intTable + readb(brd->intNdx); 15287bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 15297bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby for (port = 0; port < brd->numPorts; port++) 15307bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby moxa_poll_port(&brd->ports[port], !!ip, ip + port); 15317bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 15327bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (ip) 15337bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby writeb(0, brd->intPend); /* ACK */ 15347bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 15357bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (moxaLowWaterChk) { 15367bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby struct moxa_port *p = brd->ports; 15377bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby for (port = 0; port < brd->numPorts; port++, p++) 15387bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (p->lowChkFlag) { 15397bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby p->lowChkFlag = 0; 15407bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby moxa_low_water_check(p->tableAddr); 15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15447bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby moxaLowWaterChk = 0; 15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15462a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby if (served) 15472a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby mod_timer(&moxaTimer, jiffies + HZ / 50); 15482a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby spin_unlock(&moxa_lock); 15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************************/ 15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1553db1acaa632870ec87b65e062bc72ca375837a1f6Alan Coxstatic void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_termios) 15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1555606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox register struct ktermios *ts; 15568f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch; 1557db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox int rts, cts, txflow, rxflow, xany, baud; 15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15598f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby ch = (struct moxa_port *) tty->driver_data; 15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ts = tty->termios; 15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rts = cts = txflow = rxflow = xany = 0; 15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ts->c_cflag & CRTSCTS) 15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rts = cts = 1; 15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ts->c_iflag & IXON) 15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds txflow = 1; 15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ts->c_iflag & IXOFF) 15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rxflow = 1; 15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ts->c_iflag & IXANY) 15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds xany = 1; 1570db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox 1571db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox /* Clear the features we don't support */ 1572db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox ts->c_cflag &= ~CMSPAR; 1573b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortFlowCtrl(ch, rts, cts, txflow, rxflow, xany); 1574b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby baud = MoxaPortSetTermio(ch, ts, tty_get_baud_rate(tty)); 1575db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox if (baud == -1) 1576db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox baud = tty_termios_baud_rate(old_termios); 1577db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox /* Not put the baud rate into the termios data */ 1578db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox tty_encode_baud_rate(tty, baud, baud); 15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15816f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic void moxa_setup_empty_event(struct tty_struct *tty) 15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15838f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch = tty->driver_data; 15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15857bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby spin_lock_bh(&moxa_lock); 15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags |= EMPTYWAIT; 15877bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby spin_unlock_bh(&moxa_lock); 15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15906f56b658b4e5c4486641ce62f331150954c4de37Jiri Slabystatic void moxa_shut_down(struct moxa_port *ch) 15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1592a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby struct tty_struct *tp = ch->tty; 15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(ch->asyncflags & ASYNC_INITIALIZED)) 15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1597b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortDisable(ch); 15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If we're a modem control device and HUPCL is on, drop RTS & DTR. 16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1602a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (C_HUPCL(tp)) 1603b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortLineCtrl(ch, 0, 0); 16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1605a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby spin_lock_bh(&moxa_lock); 16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->asyncflags &= ~ASYNC_INITIALIZED; 1607a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby spin_unlock_bh(&moxa_lock); 16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************************************************** 16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Driver level functions: * 16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/ 16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1614b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortFlushData(struct moxa_port *port, int mode) 16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((mode < 0) || (mode > 2)) 16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1619b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby ofsAddr = port->tableAddr; 16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_FlushQueue, mode); 16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mode != 1) { 1622b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby port->lowChkFlag = 0; 16236f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_low_water_check(ofsAddr); 16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************************************************** 16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Port level functions: * 16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2. MoxaPortEnable(int port); * 16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3. MoxaPortDisable(int port); * 16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4. MoxaPortGetMaxBaud(int port); * 16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6. MoxaPortSetBaud(int port, long baud); * 16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8. MoxaPortSetTermio(int port, unsigned char *termio); * 16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 9. MoxaPortGetLineOut(int port, int *dtrState, int *rtsState); * 16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10. MoxaPortLineCtrl(int port, int dtrState, int rtsState); * 16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11. MoxaPortFlowCtrl(int port, int rts, int cts, int rx, int tx,int xany); * 16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 12. MoxaPortLineStatus(int port); * 16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15. MoxaPortFlushData(int port, int mode); * 16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16. MoxaPortWriteData(int port, unsigned char * buffer, int length); * 164033f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox * 17. MoxaPortReadData(int port, struct tty_struct *tty); * 16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20. MoxaPortTxQueue(int port); * 16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 21. MoxaPortTxFree(int port); * 16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 22. MoxaPortRxQueue(int port); * 16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 24. MoxaPortTxDisable(int port); * 16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 25. MoxaPortTxEnable(int port); * 16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 27. MoxaPortResetBrkCnt(int port); * 16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/ 16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Moxa Port Number Description: 16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MOXA serial driver supports up to 4 MOXA-C218/C320 boards. And, 16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the port number using in MOXA driver functions will be 0 to 31 for 16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * first MOXA board, 32 to 63 for second, 64 to 95 for third and 96 16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to 127 for fourth. For example, if you setup three MOXA boards, 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * first board is C218, second board is C320-16 and third board is 16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * C320-32. The port number of first board (C218 - 8 ports) is from 16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 to 7. The port number of second board (C320 - 16 ports) is form 16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 32 to 47. The port number of third board (C320 - 32 ports) is from 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 64 to 95. And those port numbers form 8 to 31, 48 to 63 and 96 to 16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 127 will be invalid. 16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Moxa Functions Description: 16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 1: Driver initialization routine, this routine must be 16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * called when initialized driver. 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaDriverInit(); 16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 2: Moxa driver private IOCTL command processing. 16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port); 16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsigned int cmd : IOCTL command 16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsigned long arg : IOCTL argument 16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 (OK) 16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -ENOIOCTLCMD 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 6: Enable this port to start Tx/Rx data. 16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortEnable(int port); 16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 7: Disable this port 16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortDisable(int port); 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 8: Get the maximun available baud rate of this port. 16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * long MoxaPortGetMaxBaud(int port); 16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 : this port is invalid 17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 38400/57600/115200 bps 17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 10: Setting baud rate of this port. 17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * long MoxaPortSetBaud(int port, long baud); 17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * long baud : baud rate (50 - 115200) 17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 : this port is invalid or baud < 50 17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 50 - 115200 : the real baud rate set to the port, if 17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the argument baud is large than maximun 17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * available baud rate, the real setting 17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * baud rate will be the maximun baud rate. 17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 12: Configure the port. 17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 1720606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox * int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud); 17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 1722606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox * struct ktermios * termio : termio structure pointer 1723c7bce3097c0f9bbed76ee6fd03742f2624031a45Alan Cox * speed_t baud : baud rate 17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: -1 : this port is invalid or termio == NULL 17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 : setting O.K. 17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 13: Get the DTR/RTS state of this port. 17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortGetLineOut(int port, int *dtrState, int *rtsState); 17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int * dtrState : pointer to INT to receive the current DTR 17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * state. (if NULL, this function will not 17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * write to this address) 17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int * rtsState : pointer to INT to receive the current RTS 17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * state. (if NULL, this function will not 17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * write to this address) 17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: -1 : this port is invalid 17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 : O.K. 17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 14: Setting the DTR/RTS output state of this port. 17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortLineCtrl(int port, int dtrState, int rtsState); 17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int dtrState : DTR output state (0: off, 1: on) 17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int rtsState : RTS output state (0: off, 1: on) 17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 15: Setting the flow control of this port. 17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortFlowCtrl(int port, int rtsFlow, int ctsFlow, int rxFlow, 17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int txFlow,int xany); 17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int rtsFlow : H/W RTS flow control (0: no, 1: yes) 17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int ctsFlow : H/W CTS flow control (0: no, 1: yes) 17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int rxFlow : S/W Rx XON/XOFF flow control (0: no, 1: yes) 17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int txFlow : S/W Tx XON/XOFF flow control (0: no, 1: yes) 17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int xany : S/W XANY flow control (0: no, 1: yes) 17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 16: Get ths line status of this port 17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortLineStatus(int port); 17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: Bit 0 - CTS state (0: off, 1: on) 17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bit 1 - DSR state (0: off, 1: on) 17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bit 2 - DCD state (0: off, 1: on) 17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 19: Flush the Rx/Tx buffer data of this port. 17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortFlushData(int port, int mode); 17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int mode 17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 : flush the Rx buffer 17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 : flush the Tx buffer 17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2 : flush the Rx and Tx buffer 17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 20: Write data. 17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortWriteData(int port, unsigned char * buffer, int length); 17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsigned char * buffer : pointer to write data buffer. 17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int length : write data length 17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 - length : real write data length 17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 21: Read data. 17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 179633f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox * int MoxaPortReadData(int port, struct tty_struct *tty); 17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 179833f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox * struct tty_struct *tty : tty for data 17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 - length : real read data length 18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 24: Get the Tx buffer current queued data bytes 18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortTxQueue(int port); 18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: .. : Tx buffer current queued data bytes 18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 25: Get the Tx buffer current free space 18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortTxFree(int port); 18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: .. : Tx buffer current free space 18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 26: Get the Rx buffer current queued data bytes 18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortRxQueue(int port); 18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: .. : Rx buffer current queued data bytes 18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 28: Disable port data transmission. 18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortTxDisable(int port); 18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 29: Enable port data transmission. 18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortTxEnable(int port); 18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 31: Get the received BREAK signal count and reset it. 18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortResetBrkCnt(int port); 18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 - .. : BREAK signal count 18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1849b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortEnable(struct moxa_port *port) 18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short lowwater = 512; 18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1854b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby ofsAddr = port->tableAddr; 18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(lowwater, ofsAddr + Low_water); 1856b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby if (port->board->boardType == MOXA_BOARD_C320_ISA || 1857b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby port->board->boardType == MOXA_BOARD_C320_PCI) { 18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetBreakIrq, 0); 18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(readw(ofsAddr + HostStat) | WakeupBreak, ofsAddr + HostStat); 18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetLineIrq, Magic_code); 18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_FlushQueue, 2); 18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_EnableCH, Magic_code); 18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortLineStatus(port); 18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1870b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortDisable(struct moxa_port *port) 18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1872b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby void __iomem *ofsAddr = port->tableAddr; 18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetFlowCtl, 0); /* disable flow control */ 18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code); 18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(0, ofsAddr + HostStat); 18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_DisableCH, Magic_code); 18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1880b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic long MoxaPortGetMaxBaud(struct moxa_port *port) 18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1882b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby if (port->board->boardType == MOXA_BOARD_C320_ISA || 1883b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby port->board->boardType == MOXA_BOARD_C320_PCI) 18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (460800L); 18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (921600L); 18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1890b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic long MoxaPortSetBaud(struct moxa_port *port, long baud) 18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long max, clock; 18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int val; 18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((baud < 50L) || ((max = MoxaPortGetMaxBaud(port)) == 0)) 18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 1898b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby ofsAddr = port->tableAddr; 18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (baud > max) 19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds baud = max; 19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (max == 38400L) 19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clock = 614400L; /* for 9.8304 Mhz : max. 38400 bps */ 19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (max == 57600L) 19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clock = 691200L; /* for 11.0592 Mhz : max. 57600 bps */ 19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clock = 921600L; /* for 14.7456 Mhz : max. 115200 bps */ 19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = clock / baud; 19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetBaud, val); 19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds baud = clock / val; 19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (baud); 19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1913b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio, 1914b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby speed_t baud) 19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tcflag_t cflag; 19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tcflag_t mode = 0; 19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1920b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby ofsAddr = port->tableAddr; 19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cflag = termio->c_cflag; /* termio->c_cflag */ 19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = termio->c_cflag & CSIZE; 19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mode == CS5) 19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = MX_CS5; 19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (mode == CS6) 19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = MX_CS6; 19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (mode == CS7) 19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = MX_CS7; 19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (mode == CS8) 19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = MX_CS8; 19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (termio->c_cflag & CSTOPB) { 19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mode == MX_CS5) 19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_STOP15; 19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_STOP2; 19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 19391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_STOP1; 19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (termio->c_cflag & PARENB) { 19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (termio->c_cflag & PARODD) 19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_PARODD; 19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_PAREVEN; 19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_PARNONE; 19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetDataMode, (ushort) mode); 19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1951b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby if (port->board->boardType == MOXA_BOARD_C320_ISA || 1952b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby port->board->boardType == MOXA_BOARD_C320_PCI) { 1953c7bce3097c0f9bbed76ee6fd03742f2624031a45Alan Cox if (baud >= 921600L) 19541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-1); 19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1956db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox baud = MoxaPortSetBaud(port, baud); 19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (termio->c_iflag & (IXON | IXOFF | IXANY)) { 19591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(termio->c_cc[VSTART], ofsAddr + FuncArg); 19601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1); 19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(FC_SetXonXoff, ofsAddr + FuncCode); 19626f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_wait_finish(ofsAddr); 19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1965db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox return (baud); 19661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1968b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortGetLineOut(struct moxa_port *port, int *dtrState, 1969b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby int *rtsState) 19701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1972b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby if (dtrState) 1973b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *dtrState = !!(port->lineCtrl & DTR_ON); 1974b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby if (rtsState) 1975b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *rtsState = !!(port->lineCtrl & RTS_ON); 1976b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby 19771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1980b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortLineCtrl(struct moxa_port *port, int dtr, int rts) 19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1982b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby int mode = 0; 19831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dtr) 19851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= DTR_ON; 19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rts) 19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= RTS_ON; 1988b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby port->lineCtrl = mode; 1989b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby moxafunc(port->tableAddr, FC_LineControl, mode); 19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1992b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortFlowCtrl(struct moxa_port *port, int rts, int cts, 1993b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby int txflow, int rxflow, int txany) 19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1995b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby int mode = 0; 19961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rts) 19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= RTS_FlowCtl; 19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cts) 20001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= CTS_FlowCtl; 20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (txflow) 20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= Tx_FlowCtl; 20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rxflow) 20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= Rx_FlowCtl; 20051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (txany) 20061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= IXM_IXANY; 2007b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby moxafunc(port->tableAddr, FC_SetFlowCtl, mode); 20081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2010b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortLineStatus(struct moxa_port *port) 20111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 20131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val; 20141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2015b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby ofsAddr = port->tableAddr; 2016b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby if (port->board->boardType == MOXA_BOARD_C320_ISA || 2017b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby port->board->boardType == MOXA_BOARD_C320_PCI) { 20181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_LineStatus, 0); 20191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = readw(ofsAddr + FuncArg); 20201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = readw(ofsAddr + FlagStat) >> 4; 20221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val &= 0x0B; 20247bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (val & 8) 20251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val |= 4; 2026a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby spin_lock_bh(&moxa_lock); 20277bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby moxa_new_dcdstate(port, val & 8); 2028a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby spin_unlock_bh(&moxa_lock); 20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val &= 7; 20307bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby return val; 20311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20332108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slabystatic int MoxaPortWriteData(struct moxa_port *port, 20342108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby const unsigned char *buffer, int len) 20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *baseAddr, *ofsAddr, *ofs; 20372108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby unsigned int c, total; 20382108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby u16 head, tail, tx_mask, spage, epage; 20392108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby u16 pageno, pageofs, bufhead; 20401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2041b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby ofsAddr = port->tableAddr; 2042b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby baseAddr = port->board->basemem; 20431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tx_mask = readw(ofsAddr + TX_mask); 20441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spage = readw(ofsAddr + Page_txb); 20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds epage = readw(ofsAddr + EndPage_txb); 20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tail = readw(ofsAddr + TXwptr); 20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head = readw(ofsAddr + TXrptr); 20482108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby c = (head > tail) ? (head - tail - 1) : (head - tail + tx_mask); 20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (c > len) 20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c = len; 2051b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby moxaLog.txcnt[port->tty->index] += c; 20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds total = c; 20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (spage == epage) { 20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bufhead = readw(ofsAddr + Ofs_txb); 20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(spage, baseAddr + Control_reg); 20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (c > 0) { 20571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (head > tail) 20581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = head - tail - 1; 20591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 20601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = tx_mask + 1 - tail; 20611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = (c > len) ? len : c; 20621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ofs = baseAddr + DynPage_addr + bufhead + tail; 20632108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby memcpy_toio(ofs, buffer, len); 20642108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby buffer += len; 20651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tail = (tail + len) & tx_mask; 20661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c -= len; 20671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageno = spage + (tail >> 13); 20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageofs = tail & Page_mask; 20712108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby while (c > 0) { 20722108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby len = Page_size - pageofs; 20732108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby if (len > c) 20742108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby len = c; 20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(pageno, baseAddr + Control_reg); 20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ofs = baseAddr + DynPage_addr + pageofs; 20772108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby memcpy_toio(ofs, buffer, len); 20782108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby buffer += len; 20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (++pageno == epage) 20801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageno = spage; 20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageofs = 0; 20822108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby c -= len; 20832108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby } 20842108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby tail = (tail + total) & tx_mask; 20851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20862108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby writew(tail, ofsAddr + TXwptr); 20871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(1, ofsAddr + CD180TXirq); /* start to send */ 20882108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby return total; 20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20917bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int MoxaPortReadData(struct moxa_port *port) 20921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20937bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby struct tty_struct *tty = port->tty; 20942108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby unsigned char *dst; 20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *baseAddr, *ofsAddr, *ofs; 20962108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby unsigned int count, len, total; 20972108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby u16 tail, rx_mask, spage, epage; 20982108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby u16 pageno, pageofs, bufhead, head; 20991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2100b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby ofsAddr = port->tableAddr; 2101b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby baseAddr = port->board->basemem; 21021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head = readw(ofsAddr + RXrptr); 21031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tail = readw(ofsAddr + RXwptr); 21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rx_mask = readw(ofsAddr + RX_mask); 21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spage = readw(ofsAddr + Page_rxb); 21061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds epage = readw(ofsAddr + EndPage_rxb); 21072108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby count = (tail >= head) ? (tail - head) : (tail - head + rx_mask + 1); 21081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count == 0) 210933f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox return 0; 21101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211133f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox total = count; 21127bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby moxaLog.rxcnt[tty->index] += total; 21131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (spage == epage) { 21141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bufhead = readw(ofsAddr + Ofs_rxb); 21151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(spage, baseAddr + Control_reg); 21161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (count > 0) { 21171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ofs = baseAddr + DynPage_addr + bufhead + head; 21182108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby len = (tail >= head) ? (tail - head) : 21192108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby (rx_mask + 1 - head); 21202108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby len = tty_prepare_flip_string(tty, &dst, 21212108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby min(len, count)); 21222108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby memcpy_fromio(dst, ofs, len); 21231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head = (head + len) & rx_mask; 21241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count -= len; 21251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 21271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageno = spage + (head >> 13); 21281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageofs = head & Page_mask; 21292108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby while (count > 0) { 21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(pageno, baseAddr + Control_reg); 21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ofs = baseAddr + DynPage_addr + pageofs; 21322108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby len = tty_prepare_flip_string(tty, &dst, 21332108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby min(Page_size - pageofs, count)); 21342108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby memcpy_fromio(dst, ofs, len); 21352108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby 21362108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby count -= len; 21372108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby pageofs = (pageofs + len) & Page_mask; 21382108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby if (pageofs == 0 && ++pageno == epage) 21391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageno = spage; 21402108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby } 21412108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby head = (head + total) & rx_mask; 21421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21432108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby writew(head, ofsAddr + RXrptr); 21442108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby if (readb(ofsAddr + FlagStat) & Xoff_state) { 21451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaLowWaterChk = 1; 2146b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby port->lowChkFlag = 1; 21471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21482108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby return total; 21491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2152b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortTxQueue(struct moxa_port *port) 21531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2154b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby void __iomem *ofsAddr = port->tableAddr; 21552108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby u16 rptr, wptr, mask; 21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rptr = readw(ofsAddr + TXrptr); 21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wptr = readw(ofsAddr + TXwptr); 21591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = readw(ofsAddr + TX_mask); 21602108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby return (wptr - rptr) & mask; 21611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2163b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortTxFree(struct moxa_port *port) 21641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2165b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby void __iomem *ofsAddr = port->tableAddr; 21662108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby u16 rptr, wptr, mask; 21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rptr = readw(ofsAddr + TXrptr); 21691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wptr = readw(ofsAddr + TXwptr); 21701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = readw(ofsAddr + TX_mask); 21712108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby return mask - ((wptr - rptr) & mask); 21721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2174b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortRxQueue(struct moxa_port *port) 21751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2176b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby void __iomem *ofsAddr = port->tableAddr; 21772108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby u16 rptr, wptr, mask; 21781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rptr = readw(ofsAddr + RXrptr); 21801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wptr = readw(ofsAddr + RXwptr); 21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = readw(ofsAddr + RX_mask); 21822108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby return (wptr - rptr) & mask; 21831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2185b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortTxDisable(struct moxa_port *port) 21861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2187b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby moxafunc(port->tableAddr, FC_SetXoffState, Magic_code); 21881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2190b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortTxEnable(struct moxa_port *port) 21911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2192b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby moxafunc(port->tableAddr, FC_SetXonState, Magic_code); 21931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21958f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic int moxa_get_serial_info(struct moxa_port *info, 21961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct serial_struct __user *retinfo) 21971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct serial_struct tmp; 21991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&tmp, 0, sizeof(tmp)); 22011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.type = info->type; 2202b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby tmp.line = info->tty->index; 22031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.port = 0; 22041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.irq = 0; 22051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.flags = info->asyncflags; 22061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.baud_base = 921600; 22071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.close_delay = info->close_delay; 22081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.custom_divisor = 0; 22091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.hub6 = 0; 22101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(copy_to_user(retinfo, &tmp, sizeof(*retinfo))) 22111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 22121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 22131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22168f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic int moxa_set_serial_info(struct moxa_port *info, 22171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct serial_struct __user *new_info) 22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct serial_struct new_serial; 22201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(copy_from_user(&new_serial, new_info, sizeof(new_serial))) 22221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 22231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((new_serial.irq != 0) || 22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (new_serial.port != 0) || 22261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// (new_serial.type != info->type) || 22271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (new_serial.custom_divisor != 0) || 22281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (new_serial.baud_base != 921600)) 22291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EPERM); 22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_ADMIN)) { 22321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((new_serial.flags & ~ASYNC_USR_MASK) != 22331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (info->asyncflags & ~ASYNC_USR_MASK))) 22341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EPERM); 22351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 22361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->close_delay = new_serial.close_delay * HZ / 100; 22371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_serial.flags = (new_serial.flags & ~ASYNC_FLAGS); 22401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_serial.flags |= (info->asyncflags & ASYNC_FLAGS); 22411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (new_serial.type == PORT_16550A) { 2243b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaSetFifo(info, 1); 22441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2245b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaSetFifo(info, 0); 22461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->type = new_serial.type; 22491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 22501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************************************************** 22551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Static local functions: * 22561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/ 22571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2258b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaSetFifo(struct moxa_port *port, int enable) 22591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2260b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby void __iomem *ofsAddr = port->tableAddr; 22611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!enable) { 22631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0); 22641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetTxFIFOCnt, 1); 22651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 22661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetRxFIFOTrig, 3); 22671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16); 22681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2270