11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * moxa.c -- MOXA Intellio family multiport serial driver. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5b9705b603d1d29471aa2977e6310f4f9a4e85925Jiri Slaby * Copyright (C) 1999-2000 Moxa Technologies (support@moxa.com). 6b9705b603d1d29471aa2977e6310f4f9a4e85925Jiri Slaby * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This code is loosely based on the Linux serial driver, written by 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Linus Torvalds, Theodore T'so and others. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version. 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MOXA Intellio Series Driver 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for : LINUX 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * date : 1999/1/7 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * version : 5.1 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 29037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#include <linux/firmware.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/signal.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_flip.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/major.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fcntl.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ptrace.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/serial.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty_driver.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h> 465a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 475a3c6b251d587715f8b87a50216e4c085c655777Manuel Zerpies#include <linux/ratelimit.h> 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 52037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#include "moxa.h" 53037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 54b9705b603d1d29471aa2977e6310f4f9a4e85925Jiri Slaby#define MOXA_VERSION "6.0k" 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 56037182346f0991683cc7320a257c3f6089432ceeJiri Slaby#define MOXA_FW_HDRLEN 32 57037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 5811324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MOXAMAJOR 172 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6011324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MAX_BOARDS 4 /* Don't change this value */ 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_PORTS_PER_BOARD 32 /* Don't change this value */ 6211324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MAX_PORTS (MAX_BOARDS * MAX_PORTS_PER_BOARD) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6408d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby#define MOXA_IS_320(brd) ((brd)->boardType == MOXA_BOARD_C320_ISA || \ 6508d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby (brd)->boardType == MOXA_BOARD_C320_PCI) 6608d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Define the Moxa PCI vendor and device IDs. 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7011324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MOXA_BUS_TYPE_ISA 0 7111324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby#define MOXA_BUS_TYPE_PCI 1 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum { 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MOXA_BOARD_C218_PCI = 1, 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MOXA_BOARD_C218_ISA, 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MOXA_BOARD_C320_PCI, 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MOXA_BOARD_C320_ISA, 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MOXA_BOARD_CP204J, 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *moxa_brdname[] = 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "C218 Turbo PCI series", 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "C218 Turbo ISA series", 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "C320 Turbo PCI series", 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "C320 Turbo ISA series", 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CP-204J series", 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_device_id moxa_pcibrds[] = { 925ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C218), 935ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby .driver_data = MOXA_BOARD_C218_PCI }, 945ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C320), 955ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby .driver_data = MOXA_BOARD_C320_PCI }, 965ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP204J), 975ebb4078af0dab866fdf57f84f72b9e9a7e8c6b8Jiri Slaby .driver_data = MOXA_BOARD_CP204J }, 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0 } 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, moxa_pcibrds); 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_PCI */ 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 103037182346f0991683cc7320a257c3f6089432ceeJiri Slabystruct moxa_port; 104037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 1058f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic struct moxa_board_conf { 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int boardType; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int numPorts; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int busType; 1098f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby 110810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby unsigned int ready; 1118f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby 112037182346f0991683cc7320a257c3f6089432ceeJiri Slaby struct moxa_port *ports; 113037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 1148f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby void __iomem *basemem; 1158f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby void __iomem *intNdx; 1168f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby void __iomem *intPend; 1178f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby void __iomem *intTable; 1188f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby} moxa_boards[MAX_BOARDS]; 1198f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby 1208f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystruct mxser_mstatus { 1218f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby tcflag_t cflag; 1228f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int cts; 1238f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int dsr; 1248f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int ri; 1258f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int dcd; 1269dff89cd82af7bccc706fed288b1c33a51c3b937Jiri Slaby}; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1288f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystruct moxaq_str { 1298f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int inq; 1308f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby int outq; 1318f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby}; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1338f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystruct moxa_port { 1349de6a51fee08f9e7020074738150441305e83af2Alan Cox struct tty_port port; 135b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby struct moxa_board_conf *board; 1367bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby void __iomem *tableAddr; 1377bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int type; 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int cflag; 1407bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby unsigned long statusflags; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1428482bcd58530ad5857d7187854132f2b846db681Alan Cox u8 DCDState; /* Protected by the port lock */ 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 */ 154a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox#define TXSTOPPED 1 155a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox#define LOWWAIT 2 156a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox#define EMPTYWAIT 3 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SERIAL_DO_RESTART 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WAKEUP_CHARS 256 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ttymajor = MOXAMAJOR; 16374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic struct mon_str moxaLog; 16474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic unsigned int moxaFuncTout = HZ / 2; 1657bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic unsigned int moxaLowWaterChk; 166a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slabystatic DEFINE_MUTEX(moxa_openlock); 167e8c62103fd5fecc8d2086bae244b32d089892175Alan Coxstatic DEFINE_SPINLOCK(moxa_lock); 168c6fc826e4c51d2c54913c2a6d800159a2c7dac4bRakib Mullick 169d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabystatic unsigned long baseaddr[MAX_BOARDS]; 170d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabystatic unsigned int type[MAX_BOARDS]; 171d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabystatic unsigned int numports[MAX_BOARDS]; 172793be8984fb979ae8887609862842cbb1f60bfafJiri Slabystatic struct tty_port moxa_service_port; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("William Chen"); 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver"); 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 177e6c4ef984ebbd1a0458503417da91f3de47cbbe0Ben HutchingsMODULE_FIRMWARE("c218tunx.cod"); 178e6c4ef984ebbd1a0458503417da91f3de47cbbe0Ben HutchingsMODULE_FIRMWARE("cp204unx.cod"); 179e6c4ef984ebbd1a0458503417da91f3de47cbbe0Ben HutchingsMODULE_FIRMWARE("c320tunx.cod"); 180c6fc826e4c51d2c54913c2a6d800159a2c7dac4bRakib Mullick 181d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabymodule_param_array(type, uint, NULL, 0); 182d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri SlabyMODULE_PARM_DESC(type, "card type: C218=2, C320=4"); 183d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabymodule_param_array(baseaddr, ulong, NULL, 0); 184d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri SlabyMODULE_PARM_DESC(baseaddr, "base address"); 185d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slabymodule_param_array(numports, uint, NULL, 0); 186d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri SlabyMODULE_PARM_DESC(numports, "numports (ignored for C218)"); 187c6fc826e4c51d2c54913c2a6d800159a2c7dac4bRakib Mullick 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(ttymajor, int, 0); 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * static functions: 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_open(struct tty_struct *, struct file *); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_close(struct tty_struct *, struct file *); 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_write(struct tty_struct *, const unsigned char *, int); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_write_room(struct tty_struct *); 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_flush_buffer(struct tty_struct *); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_chars_in_buffer(struct tty_struct *); 199606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Coxstatic void moxa_set_termios(struct tty_struct *, struct ktermios *); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_stop(struct tty_struct *); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_start(struct tty_struct *); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_hangup(struct tty_struct *); 20360b33c133ca0b7c0b6072c87234b63fee6e80558Alan Coxstatic int moxa_tiocmget(struct tty_struct *tty); 20420b9d17715017ae4dd4ec87fabc36d33b9de708eAlan Coxstatic int moxa_tiocmset(struct tty_struct *tty, 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int set, unsigned int clear); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_poll(unsigned long); 207db1acaa632870ec87b65e062bc72ca375837a1f6Alan Coxstatic void moxa_set_tty_param(struct tty_struct *, struct ktermios *); 208f176178ba09d27cc33988435e2c9fe078b44998cAlan Coxstatic void moxa_shutdown(struct tty_port *); 20931f35939d1d9bcfb3099b32c67b896d2792603f9Alan Coxstatic int moxa_carrier_raised(struct tty_port *); 210f176178ba09d27cc33988435e2c9fe078b44998cAlan Coxstatic void moxa_dtr_rts(struct tty_port *, int); 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * moxa board interface functions: 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 214b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortEnable(struct moxa_port *); 215b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortDisable(struct moxa_port *); 216b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortSetTermio(struct moxa_port *, struct ktermios *, speed_t); 217b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortGetLineOut(struct moxa_port *, int *, int *); 218b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortLineCtrl(struct moxa_port *, int, int); 219b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int); 220b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortLineStatus(struct moxa_port *); 221b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortFlushData(struct moxa_port *, int); 222d450b5a0196b6442cf3f29fc611d9c8daa56b559Alan Coxstatic int MoxaPortWriteData(struct tty_struct *, const unsigned char *, int); 2237bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int MoxaPortReadData(struct moxa_port *); 224b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortTxQueue(struct moxa_port *); 225b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortRxQueue(struct moxa_port *); 226b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortTxFree(struct moxa_port *); 227b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortTxDisable(struct moxa_port *); 228b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortTxEnable(struct moxa_port *); 2298f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic int moxa_get_serial_info(struct moxa_port *, struct serial_struct __user *); 2308f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic int moxa_set_serial_info(struct moxa_port *, struct serial_struct __user *); 231b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaSetFifo(struct moxa_port *port, int enable); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby/* 23474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby * I/O functions 23574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby */ 23674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 237a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Coxstatic DEFINE_SPINLOCK(moxafunc_lock); 238a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox 23974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabystatic void moxa_wait_finish(void __iomem *ofsAddr) 24074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby{ 24174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby unsigned long end = jiffies + moxaFuncTout; 24274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 24374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby while (readw(ofsAddr + FuncCode) != 0) 24474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (time_after(jiffies, end)) 24574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby return; 2465a3c6b251d587715f8b87a50216e4c085c655777Manuel Zerpies if (readw(ofsAddr + FuncCode) != 0) 2475a3c6b251d587715f8b87a50216e4c085c655777Manuel Zerpies printk_ratelimited(KERN_WARNING "moxa function expired\n"); 24874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby} 24974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 250eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slabystatic void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg) 25174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby{ 252f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox unsigned long flags; 253f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox spin_lock_irqsave(&moxafunc_lock, flags); 25474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby writew(arg, ofsAddr + FuncArg); 25574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby writew(cmd, ofsAddr + FuncCode); 25674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby moxa_wait_finish(ofsAddr); 257f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox spin_unlock_irqrestore(&moxafunc_lock, flags); 258f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox} 259f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox 260f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Coxstatic int moxafuncret(void __iomem *ofsAddr, u16 cmd, u16 arg) 261f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox{ 262f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox unsigned long flags; 263f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox u16 ret; 264f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox spin_lock_irqsave(&moxafunc_lock, flags); 265f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox writew(arg, ofsAddr + FuncArg); 266f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox writew(cmd, ofsAddr + FuncCode); 267f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox moxa_wait_finish(ofsAddr); 268f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox ret = readw(ofsAddr + FuncArg); 269f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox spin_unlock_irqrestore(&moxafunc_lock, flags); 270f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox return ret; 27174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby} 27274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 2737bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void moxa_low_water_check(void __iomem *ofsAddr) 2747bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby{ 2757bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby u16 rptr, wptr, mask, len; 2767bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 2777bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (readb(ofsAddr + FlagStat) & Xoff_state) { 2787bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby rptr = readw(ofsAddr + RXrptr); 2797bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby wptr = readw(ofsAddr + RXwptr); 2807bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby mask = readw(ofsAddr + RX_mask); 2817bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby len = (wptr - rptr) & mask; 2827bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (len <= Low_water) 2837bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby moxafunc(ofsAddr, FC_SendXon, 0); 2847bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby } 2857bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby} 2867bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 28774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby/* 28874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby * TTY operations 28974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby */ 29074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 2916caa76b7786891b42b66a0e61e2c2fff2c884620Alan Coxstatic int moxa_ioctl(struct tty_struct *tty, 29274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby unsigned int cmd, unsigned long arg) 29374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby{ 29474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby struct moxa_port *ch = tty->driver_data; 29574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby void __user *argp = (void __user *)arg; 296a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby int status, ret = 0; 29774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 29874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (tty->index == MAX_PORTS) { 29974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (cmd != MOXA_GETDATACOUNT && cmd != MOXA_GET_IOQUEUE && 30074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby cmd != MOXA_GETMSTATUS) 30174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby return -EINVAL; 30274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } else if (!ch) 30374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby return -ENODEV; 30474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 30574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby switch (cmd) { 30674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby case MOXA_GETDATACOUNT: 30774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby moxaLog.tick = jiffies; 308a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (copy_to_user(argp, &moxaLog, sizeof(moxaLog))) 309a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ret = -EFAULT; 310a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 31174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby case MOXA_FLUSH_QUEUE: 31274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby MoxaPortFlushData(ch, arg); 313a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 31474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby case MOXA_GET_IOQUEUE: { 31574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby struct moxaq_str __user *argm = argp; 31674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby struct moxaq_str tmp; 31774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby struct moxa_port *p; 31874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby unsigned int i, j; 31974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 32074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby for (i = 0; i < MAX_BOARDS; i++) { 32174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby p = moxa_boards[i].ports; 32274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { 32374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby memset(&tmp, 0, sizeof(tmp)); 324e8c62103fd5fecc8d2086bae244b32d089892175Alan Cox spin_lock_bh(&moxa_lock); 32574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (moxa_boards[i].ready) { 32674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby tmp.inq = MoxaPortRxQueue(p); 32774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby tmp.outq = MoxaPortTxQueue(p); 32874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } 329e8c62103fd5fecc8d2086bae244b32d089892175Alan Cox spin_unlock_bh(&moxa_lock); 330e8c62103fd5fecc8d2086bae244b32d089892175Alan Cox if (copy_to_user(argm, &tmp, sizeof(tmp))) 33174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby return -EFAULT; 33274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } 33374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } 334a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 33574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } case MOXA_GET_OQUEUE: 33674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby status = MoxaPortTxQueue(ch); 337a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ret = put_user(status, (unsigned long __user *)argp); 338a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 33974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby case MOXA_GET_IQUEUE: 34074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby status = MoxaPortRxQueue(ch); 341a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ret = put_user(status, (unsigned long __user *)argp); 342a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 34374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby case MOXA_GETMSTATUS: { 34474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby struct mxser_mstatus __user *argm = argp; 34574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby struct mxser_mstatus tmp; 34674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby struct moxa_port *p; 34774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby unsigned int i, j; 34874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 34974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby for (i = 0; i < MAX_BOARDS; i++) { 35074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby p = moxa_boards[i].ports; 35174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { 352d450b5a0196b6442cf3f29fc611d9c8daa56b559Alan Cox struct tty_struct *ttyp; 35374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby memset(&tmp, 0, sizeof(tmp)); 354e8c62103fd5fecc8d2086bae244b32d089892175Alan Cox spin_lock_bh(&moxa_lock); 355e8c62103fd5fecc8d2086bae244b32d089892175Alan Cox if (!moxa_boards[i].ready) { 356e8c62103fd5fecc8d2086bae244b32d089892175Alan Cox spin_unlock_bh(&moxa_lock); 35774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby goto copy; 358e8c62103fd5fecc8d2086bae244b32d089892175Alan Cox } 35974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 36074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby status = MoxaPortLineStatus(p); 361e8c62103fd5fecc8d2086bae244b32d089892175Alan Cox spin_unlock_bh(&moxa_lock); 362e8c62103fd5fecc8d2086bae244b32d089892175Alan Cox 36374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (status & 1) 36474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby tmp.cts = 1; 36574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (status & 2) 36674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby tmp.dsr = 1; 36774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby if (status & 4) 36874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby tmp.dcd = 1; 36974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 370d450b5a0196b6442cf3f29fc611d9c8daa56b559Alan Cox ttyp = tty_port_tty_get(&p->port); 371adc8d746caa67fff4b53ba3e5163a6cbacc3b523Alan Cox if (!ttyp) 37274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby tmp.cflag = p->cflag; 37374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby else 374adc8d746caa67fff4b53ba3e5163a6cbacc3b523Alan Cox tmp.cflag = ttyp->termios.c_cflag; 375df43daaae926c3710eda911ec048808c904572feJulia Lawall tty_kref_put(ttyp); 37674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slabycopy: 377e8c62103fd5fecc8d2086bae244b32d089892175Alan Cox if (copy_to_user(argm, &tmp, sizeof(tmp))) 37874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby return -EFAULT; 37974d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } 38074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } 381a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 38274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } 38374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby case TIOCGSERIAL: 384a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox mutex_lock(&ch->port.mutex); 385a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ret = moxa_get_serial_info(ch, argp); 386a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox mutex_unlock(&ch->port.mutex); 387a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 38874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby case TIOCSSERIAL: 389a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox mutex_lock(&ch->port.mutex); 390a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ret = moxa_set_serial_info(ch, argp); 391a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox mutex_unlock(&ch->port.mutex); 392a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 393a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby default: 394a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ret = -ENOIOCTLCMD; 39574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby } 396a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby return ret; 39774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby} 39874d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 3999e98966c7bb94355689478bc84cc3e0c190f977eAlan Coxstatic int moxa_break_ctl(struct tty_struct *tty, int state) 40074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby{ 40174d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby struct moxa_port *port = tty->driver_data; 40274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 40374d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak, 40474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby Magic_code); 4059e98966c7bb94355689478bc84cc3e0c190f977eAlan Cox return 0; 40674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby} 40774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 408b68e31d0ebbcc909d1941f9f230c9d062a3a13d3Jeff Dikestatic const struct tty_operations moxa_ops = { 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .open = moxa_open, 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .close = moxa_close, 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write = moxa_write, 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write_room = moxa_write_room, 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .flush_buffer = moxa_flush_buffer, 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chars_in_buffer = moxa_chars_in_buffer, 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .ioctl = moxa_ioctl, 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_termios = moxa_set_termios, 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .stop = moxa_stop, 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .start = moxa_start, 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hangup = moxa_hangup, 42074d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby .break_ctl = moxa_break_ctl, 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .tiocmget = moxa_tiocmget, 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .tiocmset = moxa_tiocmset, 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42531f35939d1d9bcfb3099b32c67b896d2792603f9Alan Coxstatic const struct tty_port_operations moxa_port_ops = { 42631f35939d1d9bcfb3099b32c67b896d2792603f9Alan Cox .carrier_raised = moxa_carrier_raised, 427f176178ba09d27cc33988435e2c9fe078b44998cAlan Cox .dtr_rts = moxa_dtr_rts, 428f176178ba09d27cc33988435e2c9fe078b44998cAlan Cox .shutdown = moxa_shutdown, 42931f35939d1d9bcfb3099b32c67b896d2792603f9Alan Cox}; 43031f35939d1d9bcfb3099b32c67b896d2792603f9Alan Cox 431aa7e5221fb47badbea618cc62704d6e4a4bcce15Jiri Slabystatic struct tty_driver *moxaDriver; 432aa7e5221fb47badbea618cc62704d6e4a4bcce15Jiri Slabystatic DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); 43333f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox 43474d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby/* 43574d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby * HW init 43674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby */ 43774d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby 438037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_check_fw_model(struct moxa_board_conf *brd, u8 model) 439037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 440037182346f0991683cc7320a257c3f6089432ceeJiri Slaby switch (brd->boardType) { 441037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_ISA: 442037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_PCI: 443037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (model != 1) 444037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 445037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 446037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_CP204J: 447037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (model != 3) 448037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 449037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 450037182346f0991683cc7320a257c3f6089432ceeJiri Slaby default: 451037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (model != 2) 452037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 453037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 454037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 455037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 456037182346f0991683cc7320a257c3f6089432ceeJiri Slabyerr: 457037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EINVAL; 458037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 459037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 460037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_check_fw(const void *ptr) 461037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 462037182346f0991683cc7320a257c3f6089432ceeJiri Slaby const __le16 *lptr = ptr; 463037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 464037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (*lptr != cpu_to_le16(0x7980)) 465037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EINVAL; 466037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 467037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 468037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 469037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 470037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_load_bios(struct moxa_board_conf *brd, const u8 *buf, 471037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t len) 472037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 473037182346f0991683cc7320a257c3f6089432ceeJiri Slaby void __iomem *baseAddr = brd->basemem; 474037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u16 tmp; 475037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 476037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writeb(HW_reset, baseAddr + Control_reg); /* reset */ 477037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 478037182346f0991683cc7320a257c3f6089432ceeJiri Slaby memset_io(baseAddr, 0, 4096); 479037182346f0991683cc7320a257c3f6089432ceeJiri Slaby memcpy_toio(baseAddr, buf, len); /* download BIOS */ 480037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writeb(0, baseAddr + Control_reg); /* restart */ 481037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 482037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(2000); 483037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 484037182346f0991683cc7320a257c3f6089432ceeJiri Slaby switch (brd->boardType) { 485037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_ISA: 486037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_PCI: 487037182346f0991683cc7320a257c3f6089432ceeJiri Slaby tmp = readw(baseAddr + C218_key); 488037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (tmp != C218_KeyCode) 489037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 490037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 491037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_CP204J: 492037182346f0991683cc7320a257c3f6089432ceeJiri Slaby tmp = readw(baseAddr + C218_key); 493037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (tmp != CP204J_KeyCode) 494037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 495037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 496037182346f0991683cc7320a257c3f6089432ceeJiri Slaby default: 497037182346f0991683cc7320a257c3f6089432ceeJiri Slaby tmp = readw(baseAddr + C320_key); 498037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (tmp != C320_KeyCode) 499037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 500037182346f0991683cc7320a257c3f6089432ceeJiri Slaby tmp = readw(baseAddr + C320_status); 501037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (tmp != STS_init) { 502eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby printk(KERN_ERR "MOXA: bios upload failed -- CPU/Basic " 503037182346f0991683cc7320a257c3f6089432ceeJiri Slaby "module not found\n"); 504037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 505037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 506037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 507037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 508037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 509037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 510037182346f0991683cc7320a257c3f6089432ceeJiri Slabyerr: 511eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby printk(KERN_ERR "MOXA: bios upload failed -- board not found\n"); 512037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 513037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 514037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 515037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_load_320b(struct moxa_board_conf *brd, const u8 *ptr, 516037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t len) 517037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 518037182346f0991683cc7320a257c3f6089432ceeJiri Slaby void __iomem *baseAddr = brd->basemem; 519037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 520037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (len < 7168) { 521eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby printk(KERN_ERR "MOXA: invalid 320 bios -- too short\n"); 522037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EINVAL; 523037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 524037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 525037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(len - 7168 - 2, baseAddr + C320bapi_len); 526037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writeb(1, baseAddr + Control_reg); /* Select Page 1 */ 527037182346f0991683cc7320a257c3f6089432ceeJiri Slaby memcpy_toio(baseAddr + DynPage_addr, ptr, 7168); 528037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writeb(2, baseAddr + Control_reg); /* Select Page 2 */ 529037182346f0991683cc7320a257c3f6089432ceeJiri Slaby memcpy_toio(baseAddr + DynPage_addr, ptr + 7168, len - 7168); 530037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 531037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 532037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 533037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 5345292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slabystatic int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr, 535037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t len) 536037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 537037182346f0991683cc7320a257c3f6089432ceeJiri Slaby void __iomem *baseAddr = brd->basemem; 538b46f69cd24b9020433f8f153e7d9194b5bfdf5e2Harvey Harrison const __le16 *uptr = ptr; 539037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t wlen, len2, j; 5405292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby unsigned long key, loadbuf, loadlen, checksum, checksum_ok; 54108d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby unsigned int i, retry; 542037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u16 usum, keycode; 543037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 5445292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby keycode = (brd->boardType == MOXA_BOARD_CP204J) ? CP204J_KeyCode : 5455292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby C218_KeyCode; 546037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 5475292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby switch (brd->boardType) { 5485292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby case MOXA_BOARD_CP204J: 5495292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby case MOXA_BOARD_C218_ISA: 5505292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby case MOXA_BOARD_C218_PCI: 5515292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby key = C218_key; 5525292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby loadbuf = C218_LoadBuf; 5535292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby loadlen = C218DLoad_len; 5545292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby checksum = C218check_sum; 5555292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby checksum_ok = C218chksum_ok; 5565292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby break; 5575292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby default: 5585292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby key = C320_key; 5595292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby keycode = C320_KeyCode; 5605292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby loadbuf = C320_LoadBuf; 5615292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby loadlen = C320DLoad_len; 5625292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby checksum = C320check_sum; 5635292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby checksum_ok = C320chksum_ok; 5645292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby break; 565037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 566037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 567037182346f0991683cc7320a257c3f6089432ceeJiri Slaby usum = 0; 568037182346f0991683cc7320a257c3f6089432ceeJiri Slaby wlen = len >> 1; 569037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < wlen; i++) 570037182346f0991683cc7320a257c3f6089432ceeJiri Slaby usum += le16_to_cpu(uptr[i]); 571037182346f0991683cc7320a257c3f6089432ceeJiri Slaby retry = 0; 572037182346f0991683cc7320a257c3f6089432ceeJiri Slaby do { 573037182346f0991683cc7320a257c3f6089432ceeJiri Slaby wlen = len >> 1; 574037182346f0991683cc7320a257c3f6089432ceeJiri Slaby j = 0; 575037182346f0991683cc7320a257c3f6089432ceeJiri Slaby while (wlen) { 576037182346f0991683cc7320a257c3f6089432ceeJiri Slaby len2 = (wlen > 2048) ? 2048 : wlen; 577037182346f0991683cc7320a257c3f6089432ceeJiri Slaby wlen -= len2; 5785292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby memcpy_toio(baseAddr + loadbuf, ptr + j, len2 << 1); 579037182346f0991683cc7320a257c3f6089432ceeJiri Slaby j += len2 << 1; 5805292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby 5815292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(len2, baseAddr + loadlen); 5825292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0, baseAddr + key); 5835292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby for (i = 0; i < 100; i++) { 5845292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (readw(baseAddr + key) == keycode) 585037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 586037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 587037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 5885292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (readw(baseAddr + key) != keycode) 589037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 590037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 5915292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0, baseAddr + loadlen); 5925292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(usum, baseAddr + checksum); 5935292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0, baseAddr + key); 5945292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby for (i = 0; i < 100; i++) { 5955292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (readw(baseAddr + key) == keycode) 596037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 597037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 598037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 599037182346f0991683cc7320a257c3f6089432ceeJiri Slaby retry++; 6005292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby } while ((readb(baseAddr + checksum_ok) != 1) && (retry < 3)); 6015292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (readb(baseAddr + checksum_ok) != 1) 602037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 603037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 6045292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0, baseAddr + key); 605037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < 600; i++) { 606037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) == Magic_code) 607037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 608037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 609037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 610037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) != Magic_code) 611037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 612037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 61308d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby if (MOXA_IS_320(brd)) { 6145292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (brd->busType == MOXA_BUS_TYPE_PCI) { /* ASIC board */ 6155292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0x3800, baseAddr + TMS320_PORT1); 6165292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0x3900, baseAddr + TMS320_PORT2); 6175292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(28499, baseAddr + TMS320_CLOCK); 6185292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby } else { 6195292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0x3200, baseAddr + TMS320_PORT1); 6205292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0x3400, baseAddr + TMS320_PORT2); 6215292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(19999, baseAddr + TMS320_CLOCK); 6225292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby } 623037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 624037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(1, baseAddr + Disable_IRQ); 625037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(0, baseAddr + Magic_no); 626037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < 500; i++) { 627037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) == Magic_code) 628037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 629037182346f0991683cc7320a257c3f6089432ceeJiri Slaby msleep(10); 630037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 631037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (readw(baseAddr + Magic_no) != Magic_code) 632037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EIO; 633037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 63408d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby if (MOXA_IS_320(brd)) { 6355292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby j = readw(baseAddr + Module_cnt); 6365292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (j <= 0) 6375292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby return -EIO; 6385292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby brd->numPorts = j * 8; 6395292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(j, baseAddr + Module_no); 6405292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby writew(0, baseAddr + Magic_no); 6415292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby for (i = 0; i < 600; i++) { 6425292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (readw(baseAddr + Magic_no) == Magic_code) 6435292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby break; 6445292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby msleep(10); 6455292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby } 6465292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (readw(baseAddr + Magic_no) != Magic_code) 6475292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby return -EIO; 648037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 649037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->intNdx = baseAddr + IRQindex; 650037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->intPend = baseAddr + IRQpending; 651037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->intTable = baseAddr + IRQtable; 652037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 653037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 654037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 655037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 656037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_load_code(struct moxa_board_conf *brd, const void *ptr, 657037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t len) 658037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 659037182346f0991683cc7320a257c3f6089432ceeJiri Slaby void __iomem *ofsAddr, *baseAddr = brd->basemem; 660037182346f0991683cc7320a257c3f6089432ceeJiri Slaby struct moxa_port *port; 661037182346f0991683cc7320a257c3f6089432ceeJiri Slaby int retval, i; 662037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 663037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (len % 2) { 664eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby printk(KERN_ERR "MOXA: bios length is not even\n"); 665037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return -EINVAL; 666037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 667037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 6685292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby retval = moxa_real_load_code(brd, ptr, len); /* may change numPorts */ 6695292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby if (retval) 6705292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby return retval; 6715292bcd38e4bcd147905941b5e37b5b0da1a5577Jiri Slaby 672037182346f0991683cc7320a257c3f6089432ceeJiri Slaby switch (brd->boardType) { 673037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_ISA: 674037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_PCI: 675037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_CP204J: 676037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port = brd->ports; 677037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < brd->numPorts; i++, port++) { 678b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby port->board = brd; 679037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port->DCDState = 0; 680037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port->tableAddr = baseAddr + Extern_table + 681037182346f0991683cc7320a257c3f6089432ceeJiri Slaby Extern_size * i; 682037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ofsAddr = port->tableAddr; 683037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C218rx_mask, ofsAddr + RX_mask); 684037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C218tx_mask, ofsAddr + TX_mask); 685037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb); 686037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb); 687037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 688037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb); 689037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb); 690037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 691037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 692037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 693037182346f0991683cc7320a257c3f6089432ceeJiri Slaby default: 694037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port = brd->ports; 695037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (i = 0; i < brd->numPorts; i++, port++) { 696b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby port->board = brd; 697037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port->DCDState = 0; 698037182346f0991683cc7320a257c3f6089432ceeJiri Slaby port->tableAddr = baseAddr + Extern_table + 699037182346f0991683cc7320a257c3f6089432ceeJiri Slaby Extern_size * i; 700037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ofsAddr = port->tableAddr; 701037182346f0991683cc7320a257c3f6089432ceeJiri Slaby switch (brd->numPorts) { 702037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case 8: 703037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p8rx_mask, ofsAddr + RX_mask); 704037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p8tx_mask, ofsAddr + TX_mask); 705037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb); 706037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb); 707037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb); 708037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb); 709037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 710037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 711037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case 16: 712037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p16rx_mask, ofsAddr + RX_mask); 713037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p16tx_mask, ofsAddr + TX_mask); 714037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb); 715037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb); 716037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb); 717037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb); 718037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 719037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 720037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case 24: 721037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p24rx_mask, ofsAddr + RX_mask); 722037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p24tx_mask, ofsAddr + TX_mask); 723037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb); 724037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb); 725037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb); 726037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb); 727037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 728037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case 32: 729037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p32rx_mask, ofsAddr + RX_mask); 730037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p32tx_mask, ofsAddr + TX_mask); 731037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p32tx_ofs, ofsAddr + Ofs_txb); 732037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb); 733037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb); 734037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb); 735037182346f0991683cc7320a257c3f6089432ceeJiri Slaby writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb); 736037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 737037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 738037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 739037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 740037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 741037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 742037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 743037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 744037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_load_fw(struct moxa_board_conf *brd, const struct firmware *fw) 745037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 7462bca76e89bc43f86136080536858048ebffab3e3David Howells const void *ptr = fw->data; 747037182346f0991683cc7320a257c3f6089432ceeJiri Slaby char rsn[64]; 748037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u16 lens[5]; 749037182346f0991683cc7320a257c3f6089432ceeJiri Slaby size_t len; 750037182346f0991683cc7320a257c3f6089432ceeJiri Slaby unsigned int a, lenp, lencnt; 751037182346f0991683cc7320a257c3f6089432ceeJiri Slaby int ret = -EINVAL; 752037182346f0991683cc7320a257c3f6089432ceeJiri Slaby struct { 753037182346f0991683cc7320a257c3f6089432ceeJiri Slaby __le32 magic; /* 0x34303430 */ 754037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u8 reserved1[2]; 755037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u8 type; /* UNIX = 3 */ 756037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u8 model; /* C218T=1, C320T=2, CP204=3 */ 757037182346f0991683cc7320a257c3f6089432ceeJiri Slaby u8 reserved2[8]; 758037182346f0991683cc7320a257c3f6089432ceeJiri Slaby __le16 len[5]; 7592bca76e89bc43f86136080536858048ebffab3e3David Howells } const *hdr = ptr; 760037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 761037182346f0991683cc7320a257c3f6089432ceeJiri Slaby BUILD_BUG_ON(ARRAY_SIZE(hdr->len) != ARRAY_SIZE(lens)); 762037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 763037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (fw->size < MOXA_FW_HDRLEN) { 764037182346f0991683cc7320a257c3f6089432ceeJiri Slaby strcpy(rsn, "too short (even header won't fit)"); 765037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 766037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 767037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (hdr->magic != cpu_to_le32(0x30343034)) { 768037182346f0991683cc7320a257c3f6089432ceeJiri Slaby sprintf(rsn, "bad magic: %.8x", le32_to_cpu(hdr->magic)); 769037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 770037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 771037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (hdr->type != 3) { 772037182346f0991683cc7320a257c3f6089432ceeJiri Slaby sprintf(rsn, "not for linux, type is %u", hdr->type); 773037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 774037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 775037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (moxa_check_fw_model(brd, hdr->model)) { 776037182346f0991683cc7320a257c3f6089432ceeJiri Slaby sprintf(rsn, "not for this card, model is %u", hdr->model); 777037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 778037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 779037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 780037182346f0991683cc7320a257c3f6089432ceeJiri Slaby len = MOXA_FW_HDRLEN; 781037182346f0991683cc7320a257c3f6089432ceeJiri Slaby lencnt = hdr->model == 2 ? 5 : 3; 782037182346f0991683cc7320a257c3f6089432ceeJiri Slaby for (a = 0; a < ARRAY_SIZE(lens); a++) { 783037182346f0991683cc7320a257c3f6089432ceeJiri Slaby lens[a] = le16_to_cpu(hdr->len[a]); 784037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (lens[a] && len + lens[a] <= fw->size && 785037182346f0991683cc7320a257c3f6089432ceeJiri Slaby moxa_check_fw(&fw->data[len])) 786eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby printk(KERN_WARNING "MOXA firmware: unexpected input " 787037182346f0991683cc7320a257c3f6089432ceeJiri Slaby "at offset %u, but going on\n", (u32)len); 788037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (!lens[a] && a < lencnt) { 789037182346f0991683cc7320a257c3f6089432ceeJiri Slaby sprintf(rsn, "too few entries in fw file"); 790037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 791037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 792037182346f0991683cc7320a257c3f6089432ceeJiri Slaby len += lens[a]; 793037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 794037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 795037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (len != fw->size) { 796037182346f0991683cc7320a257c3f6089432ceeJiri Slaby sprintf(rsn, "bad length: %u (should be %u)", (u32)fw->size, 797037182346f0991683cc7320a257c3f6089432ceeJiri Slaby (u32)len); 798037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 799037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 800037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 801037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ptr += MOXA_FW_HDRLEN; 802037182346f0991683cc7320a257c3f6089432ceeJiri Slaby lenp = 0; /* bios */ 803037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 804037182346f0991683cc7320a257c3f6089432ceeJiri Slaby strcpy(rsn, "read above"); 805037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 806037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ret = moxa_load_bios(brd, ptr, lens[lenp]); 807037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (ret) 808037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 809037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 810037182346f0991683cc7320a257c3f6089432ceeJiri Slaby /* we skip the tty section (lens[1]), since we don't need it */ 811037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ptr += lens[lenp] + lens[lenp + 1]; 812037182346f0991683cc7320a257c3f6089432ceeJiri Slaby lenp += 2; /* comm */ 813037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 814037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (hdr->model == 2) { 815037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ret = moxa_load_320b(brd, ptr, lens[lenp]); 816037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (ret) 817037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 818037182346f0991683cc7320a257c3f6089432ceeJiri Slaby /* skip another tty */ 819037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ptr += lens[lenp] + lens[lenp + 1]; 820037182346f0991683cc7320a257c3f6089432ceeJiri Slaby lenp += 2; 821037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 822037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 823037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ret = moxa_load_code(brd, ptr, lens[lenp]); 824037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (ret) 825037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err; 826037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 827037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return 0; 828037182346f0991683cc7320a257c3f6089432ceeJiri Slabyerr: 829037182346f0991683cc7320a257c3f6089432ceeJiri Slaby printk(KERN_ERR "firmware failed to load, reason: %s\n", rsn); 830037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return ret; 831037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 832037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 833037182346f0991683cc7320a257c3f6089432ceeJiri Slabystatic int moxa_init_board(struct moxa_board_conf *brd, struct device *dev) 834037182346f0991683cc7320a257c3f6089432ceeJiri Slaby{ 835037182346f0991683cc7320a257c3f6089432ceeJiri Slaby const struct firmware *fw; 836037182346f0991683cc7320a257c3f6089432ceeJiri Slaby const char *file; 837810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby struct moxa_port *p; 838793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby unsigned int i, first_idx; 839037182346f0991683cc7320a257c3f6089432ceeJiri Slaby int ret; 840037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 841810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby brd->ports = kcalloc(MAX_PORTS_PER_BOARD, sizeof(*brd->ports), 842810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby GFP_KERNEL); 843810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby if (brd->ports == NULL) { 844810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby printk(KERN_ERR "cannot allocate memory for ports\n"); 845810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby ret = -ENOMEM; 846810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby goto err; 847810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby } 848810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby 849810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) { 85044b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox tty_port_init(&p->port); 85131f35939d1d9bcfb3099b32c67b896d2792603f9Alan Cox p->port.ops = &moxa_port_ops; 852810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby p->type = PORT_16550A; 853810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; 854810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby } 855810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby 856037182346f0991683cc7320a257c3f6089432ceeJiri Slaby switch (brd->boardType) { 857037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_ISA: 858037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_C218_PCI: 859037182346f0991683cc7320a257c3f6089432ceeJiri Slaby file = "c218tunx.cod"; 860037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 861037182346f0991683cc7320a257c3f6089432ceeJiri Slaby case MOXA_BOARD_CP204J: 862037182346f0991683cc7320a257c3f6089432ceeJiri Slaby file = "cp204unx.cod"; 863037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 864037182346f0991683cc7320a257c3f6089432ceeJiri Slaby default: 865037182346f0991683cc7320a257c3f6089432ceeJiri Slaby file = "c320tunx.cod"; 866037182346f0991683cc7320a257c3f6089432ceeJiri Slaby break; 867037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 868037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 869037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ret = request_firmware(&fw, file, dev); 870037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (ret) { 871ec09cd562135158dcb8a6c08e5a9efa36febedb1Jiri Slaby printk(KERN_ERR "MOXA: request_firmware failed. Make sure " 872ec09cd562135158dcb8a6c08e5a9efa36febedb1Jiri Slaby "you've placed '%s' file into your firmware " 873ec09cd562135158dcb8a6c08e5a9efa36febedb1Jiri Slaby "loader directory (e.g. /lib/firmware)\n", 874ec09cd562135158dcb8a6c08e5a9efa36febedb1Jiri Slaby file); 875810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby goto err_free; 876037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 877037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 878037182346f0991683cc7320a257c3f6089432ceeJiri Slaby ret = moxa_load_fw(brd, fw); 879037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 880037182346f0991683cc7320a257c3f6089432ceeJiri Slaby release_firmware(fw); 881810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby 882810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby if (ret) 883810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby goto err_free; 884810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby 8852a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby spin_lock_bh(&moxa_lock); 886810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby brd->ready = 1; 8870bcc4caadc8f5396b52950ee03c67b76875602dfJiri Slaby if (!timer_pending(&moxaTimer)) 8880bcc4caadc8f5396b52950ee03c67b76875602dfJiri Slaby mod_timer(&moxaTimer, jiffies + HZ / 50); 8892a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby spin_unlock_bh(&moxa_lock); 8900bcc4caadc8f5396b52950ee03c67b76875602dfJiri Slaby 891793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby first_idx = (brd - moxa_boards) * MAX_PORTS_PER_BOARD; 892793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby for (i = 0; i < brd->numPorts; i++) 893793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby tty_port_register_device(&brd->ports[i].port, moxaDriver, 894793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby first_idx + i, dev); 895793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby 896810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby return 0; 897810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slabyerr_free: 898191c5f10275cfbb36802edadbdb10c73537327b4Jiri Slaby for (i = 0; i < MAX_PORTS_PER_BOARD; i++) 899191c5f10275cfbb36802edadbdb10c73537327b4Jiri Slaby tty_port_destroy(&brd->ports[i].port); 900810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby kfree(brd->ports); 901810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slabyerr: 902037182346f0991683cc7320a257c3f6089432ceeJiri Slaby return ret; 903037182346f0991683cc7320a257c3f6089432ceeJiri Slaby} 904037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 905810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slabystatic void moxa_board_deinit(struct moxa_board_conf *brd) 906810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby{ 907793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby unsigned int a, opened, first_idx; 908a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby 909a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_lock(&moxa_openlock); 9107bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby spin_lock_bh(&moxa_lock); 911810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby brd->ready = 0; 9127bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby spin_unlock_bh(&moxa_lock); 913a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby 914a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby /* pci hot-un-plug support */ 915a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby for (a = 0; a < brd->numPorts; a++) 916aa27a094e2c2e0cc59914e56113b860f524f4479Jiri Slaby if (brd->ports[a].port.flags & ASYNC_INITIALIZED) 917aa27a094e2c2e0cc59914e56113b860f524f4479Jiri Slaby tty_port_tty_hangup(&brd->ports[a].port, false); 918aa27a094e2c2e0cc59914e56113b860f524f4479Jiri Slaby 919191c5f10275cfbb36802edadbdb10c73537327b4Jiri Slaby for (a = 0; a < MAX_PORTS_PER_BOARD; a++) 920191c5f10275cfbb36802edadbdb10c73537327b4Jiri Slaby tty_port_destroy(&brd->ports[a].port); 921aa27a094e2c2e0cc59914e56113b860f524f4479Jiri Slaby 922a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby while (1) { 923a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby opened = 0; 924a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby for (a = 0; a < brd->numPorts; a++) 9259de6a51fee08f9e7020074738150441305e83af2Alan Cox if (brd->ports[a].port.flags & ASYNC_INITIALIZED) 926a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby opened++; 927a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 928a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (!opened) 929a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby break; 930a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby msleep(50); 931a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_lock(&moxa_openlock); 932a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby } 933a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby 934793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby first_idx = (brd - moxa_boards) * MAX_PORTS_PER_BOARD; 935793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby for (a = 0; a < brd->numPorts; a++) 936793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby tty_unregister_device(moxaDriver, first_idx + a); 937793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby 938810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby iounmap(brd->basemem); 939810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby brd->basemem = NULL; 940810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby kfree(brd->ports); 941810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby} 942810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI 9449671f09921d93e722a28ae9610d478e092ac5466Bill Pembertonstatic int moxa_pci_probe(struct pci_dev *pdev, 9459cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby const struct pci_device_id *ent) 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9479cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby struct moxa_board_conf *board; 9489cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby unsigned int i; 9499cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby int board_type = ent->driver_data; 9509cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby int retval; 9519cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 9529cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby retval = pci_enable_device(pdev); 9537aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby if (retval) { 9547aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby dev_err(&pdev->dev, "can't enable pci device\n"); 9559cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby goto err; 9567aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby } 9579cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 9589cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby for (i = 0; i < MAX_BOARDS; i++) 9599cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby if (moxa_boards[i].basemem == NULL) 9609cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby break; 9619cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 9629cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby retval = -ENODEV; 9639cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby if (i >= MAX_BOARDS) { 9647aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby dev_warn(&pdev->dev, "more than %u MOXA Intellio family boards " 9659cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby "found. Board is ignored.\n", MAX_BOARDS); 9669cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby goto err; 9679cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby } 9689cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 9699cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby board = &moxa_boards[i]; 970e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby 971e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby retval = pci_request_region(pdev, 2, "moxa-base"); 972e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby if (retval) { 973e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby dev_err(&pdev->dev, "can't request pci region 2\n"); 974e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby goto err; 975e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby } 976e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby 97724cb233520f01971d6d873cb52c64bbbb0665ac0Alan Cox board->basemem = ioremap_nocache(pci_resource_start(pdev, 2), 0x4000); 9787aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby if (board->basemem == NULL) { 9797aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby dev_err(&pdev->dev, "can't remap io space 2\n"); 980386d95b3ad6f6dad61d0be379873dca66595c1e4Julia Lawall retval = -ENOMEM; 981e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby goto err_reg; 9827aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby } 9839cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board->boardType = board_type; 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (board_type) { 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MOXA_BOARD_C218_ISA: 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MOXA_BOARD_C218_PCI: 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board->numPorts = 8; 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MOXA_BOARD_CP204J: 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board->numPorts = 4; 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board->numPorts = 0; 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board->busType = MOXA_BUS_TYPE_PCI; 999a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby 1000037182346f0991683cc7320a257c3f6089432ceeJiri Slaby retval = moxa_init_board(board, &pdev->dev); 1001037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (retval) 1002037182346f0991683cc7320a257c3f6089432ceeJiri Slaby goto err_base; 1003037182346f0991683cc7320a257c3f6089432ceeJiri Slaby 10049cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby pci_set_drvdata(pdev, board); 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1006bb9f910a1153101a2f92620f1e7d0fda786c9812Jiri Slaby dev_info(&pdev->dev, "board '%s' ready (%u ports, firmware loaded)\n", 1007bb9f910a1153101a2f92620f1e7d0fda786c9812Jiri Slaby moxa_brdname[board_type - 1], board->numPorts); 1008bb9f910a1153101a2f92620f1e7d0fda786c9812Jiri Slaby 1009eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby return 0; 1010037182346f0991683cc7320a257c3f6089432ceeJiri Slabyerr_base: 1011037182346f0991683cc7320a257c3f6089432ceeJiri Slaby iounmap(board->basemem); 1012037182346f0991683cc7320a257c3f6089432ceeJiri Slaby board->basemem = NULL; 1013e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slabyerr_reg: 1014e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby pci_release_region(pdev, 2); 10159cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slabyerr: 10169cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby return retval; 10179cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby} 10189cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 1019ae8d8a146725a966bd7c59c94f4d0016dcf7a04fBill Pembertonstatic void moxa_pci_remove(struct pci_dev *pdev) 10209cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby{ 10219cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby struct moxa_board_conf *brd = pci_get_drvdata(pdev); 10229cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby 1023810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby moxa_board_deinit(brd); 1024810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby 1025e46a5e3ff06b70690d567bdc81faf6c1c32e742fJiri Slaby pci_release_region(pdev, 2); 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1027a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby 1028a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slabystatic struct pci_driver moxa_pci_driver = { 1029a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby .name = "moxa", 1030a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby .id_table = moxa_pcibrds, 1031a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby .probe = moxa_pci_probe, 103291116cba5da0c33f3093b804e487bea02b830bfbBill Pemberton .remove = moxa_pci_remove 1033a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby}; 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_PCI */ 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init moxa_init(void) 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1038810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby unsigned int isabrds = 0; 1039d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby int retval = 0; 1040c6fc826e4c51d2c54913c2a6d800159a2c7dac4bRakib Mullick struct moxa_board_conf *brd = moxa_boards; 1041c6fc826e4c51d2c54913c2a6d800159a2c7dac4bRakib Mullick unsigned int i; 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10437aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby printk(KERN_INFO "MOXA Intellio family driver version %s\n", 10447aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby MOXA_VERSION); 1045793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby 1046793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby tty_port_init(&moxa_service_port); 1047793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby 1048793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby moxaDriver = tty_alloc_driver(MAX_PORTS + 1, 1049793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby TTY_DRIVER_REAL_RAW | 1050793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby TTY_DRIVER_DYNAMIC_DEV); 1051c3a6344ae475763b6fb0fb2ec3639004f500d0f1Dan Carpenter if (IS_ERR(moxaDriver)) 1052c3a6344ae475763b6fb0fb2ec3639004f500d0f1Dan Carpenter return PTR_ERR(moxaDriver); 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10549b4e3b13b147e9b737de63188a9ae740eaa8c36dSergey Vlasov moxaDriver->name = "ttyMX"; 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->major = ttymajor; 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->minor_start = 0; 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->type = TTY_DRIVER_TYPE_SERIAL; 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->subtype = SERIAL_TYPE_NORMAL; 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->init_termios = tty_std_termios; 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; 1061606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox moxaDriver->init_termios.c_ispeed = 9600; 1062606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox moxaDriver->init_termios.c_ospeed = 9600; 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_set_operations(moxaDriver, &moxa_ops); 1064793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby /* Having one more port only for ioctls is ugly */ 1065793be8984fb979ae8887609862842cbb1f60bfafJiri Slaby tty_port_link_device(&moxa_service_port, moxaDriver, MAX_PORTS); 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tty_register_driver(moxaDriver)) { 1068eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby printk(KERN_ERR "can't register MOXA Smartio tty driver!\n"); 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_tty_driver(moxaDriver); 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1073d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby /* Find the boards defined from module args. */ 1074c6fc826e4c51d2c54913c2a6d800159a2c7dac4bRakib Mullick 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_BOARDS; i++) { 1076d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby if (!baseaddr[i]) 1077d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby break; 1078d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby if (type[i] == MOXA_BOARD_C218_ISA || 1079d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby type[i] == MOXA_BOARD_C320_ISA) { 10807aeb95daf37dbd72f63cdd52d86a8b5d89e59394Jiri Slaby pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n", 1081d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby isabrds + 1, moxa_brdname[type[i] - 1], 1082d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby baseaddr[i]); 1083d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby brd->boardType = type[i]; 1084d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 : 1085d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby numports[i]; 1086d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby brd->busType = MOXA_BUS_TYPE_ISA; 108724cb233520f01971d6d873cb52c64bbbb0665ac0Alan Cox brd->basemem = ioremap_nocache(baseaddr[i], 0x4000); 1088d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby if (!brd->basemem) { 1089eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby printk(KERN_ERR "MOXA: can't remap %lx\n", 1090d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby baseaddr[i]); 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1093037182346f0991683cc7320a257c3f6089432ceeJiri Slaby if (moxa_init_board(brd, NULL)) { 1094037182346f0991683cc7320a257c3f6089432ceeJiri Slaby iounmap(brd->basemem); 1095037182346f0991683cc7320a257c3f6089432ceeJiri Slaby brd->basemem = NULL; 1096037182346f0991683cc7320a257c3f6089432ceeJiri Slaby continue; 1097037182346f0991683cc7320a257c3f6089432ceeJiri Slaby } 1098d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby 1099e0525393baf07b1bb6e537ddbe7dfae3621649dfHans Wennborg printk(KERN_INFO "MOXA isa board found at 0x%.8lx and " 1100bb9f910a1153101a2f92620f1e7d0fda786c9812Jiri Slaby "ready (%u ports, firmware loaded)\n", 1101bb9f910a1153101a2f92620f1e7d0fda786c9812Jiri Slaby baseaddr[i], brd->numPorts); 1102bb9f910a1153101a2f92620f1e7d0fda786c9812Jiri Slaby 1103d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby brd++; 1104d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby isabrds++; 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1107a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI 1109a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby retval = pci_register_driver(&moxa_pci_driver); 1110a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby if (retval) { 1111eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby printk(KERN_ERR "Can't register MOXA pci driver!\n"); 1112d353eca4e0480fddcb088c4692e1edba0a82eac9Jiri Slaby if (isabrds) 1113a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby retval = 0; 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1116a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby 1117a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby return retval; 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit moxa_exit(void) 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1122eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby unsigned int i; 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11249cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby#ifdef CONFIG_PCI 1125a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby pci_unregister_driver(&moxa_pci_driver); 11269cde5bf027556bd1e58caa14bfe8cdba64192eddJiri Slaby#endif 1127a784bf7c195f9eca1188562c54952e4bf9791437Jiri Slaby 1128810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby for (i = 0; i < MAX_BOARDS; i++) /* ISA boards */ 1129810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby if (moxa_boards[i].ready) 1130810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby moxa_board_deinit(&moxa_boards[i]); 11312a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby 11322a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby del_timer_sync(&moxaTimer); 11332a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby 11342a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby if (tty_unregister_driver(moxaDriver)) 11352a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby printk(KERN_ERR "Couldn't unregister MOXA Intellio family " 11362a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby "serial driver\n"); 11372a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby put_tty_driver(moxaDriver); 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(moxa_init); 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(moxa_exit); 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1143f176178ba09d27cc33988435e2c9fe078b44998cAlan Coxstatic void moxa_shutdown(struct tty_port *port) 1144a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby{ 1145f176178ba09d27cc33988435e2c9fe078b44998cAlan Cox struct moxa_port *ch = container_of(port, struct moxa_port, port); 1146f176178ba09d27cc33988435e2c9fe078b44998cAlan Cox MoxaPortDisable(ch); 1147a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby MoxaPortFlushData(ch, 2); 1148a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby} 1149a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby 115031f35939d1d9bcfb3099b32c67b896d2792603f9Alan Coxstatic int moxa_carrier_raised(struct tty_port *port) 115131f35939d1d9bcfb3099b32c67b896d2792603f9Alan Cox{ 115231f35939d1d9bcfb3099b32c67b896d2792603f9Alan Cox struct moxa_port *ch = container_of(port, struct moxa_port, port); 115331f35939d1d9bcfb3099b32c67b896d2792603f9Alan Cox int dcd; 115431f35939d1d9bcfb3099b32c67b896d2792603f9Alan Cox 11558482bcd58530ad5857d7187854132f2b846db681Alan Cox spin_lock_irq(&port->lock); 115631f35939d1d9bcfb3099b32c67b896d2792603f9Alan Cox dcd = ch->DCDState; 11578482bcd58530ad5857d7187854132f2b846db681Alan Cox spin_unlock_irq(&port->lock); 115831f35939d1d9bcfb3099b32c67b896d2792603f9Alan Cox return dcd; 115931f35939d1d9bcfb3099b32c67b896d2792603f9Alan Cox} 116031f35939d1d9bcfb3099b32c67b896d2792603f9Alan Cox 1161f176178ba09d27cc33988435e2c9fe078b44998cAlan Coxstatic void moxa_dtr_rts(struct tty_port *port, int onoff) 1162a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby{ 1163f176178ba09d27cc33988435e2c9fe078b44998cAlan Cox struct moxa_port *ch = container_of(port, struct moxa_port, port); 1164f176178ba09d27cc33988435e2c9fe078b44998cAlan Cox MoxaPortLineCtrl(ch, onoff, onoff); 1165a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby} 1166a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby 1167f176178ba09d27cc33988435e2c9fe078b44998cAlan Cox 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_open(struct tty_struct *tty, struct file *filp) 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1170810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby struct moxa_board_conf *brd; 11718f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch; 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int port; 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 117411324edd4ad34981764b25bed44d46a1507b62e1Jiri Slaby port = tty->index; 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (port == MAX_PORTS) { 117674d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby return capable(CAP_SYS_ADMIN) ? 0 : -EPERM; 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1178a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (mutex_lock_interruptible(&moxa_openlock)) 1179a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby return -ERESTARTSYS; 1180810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby brd = &moxa_boards[port / MAX_PORTS_PER_BOARD]; 1181a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (!brd->ready) { 1182a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 1183810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby return -ENODEV; 1184a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby } 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1186f0e8527726b9e56649b9eafde3bc0fbc4dd2dd47Dirk Eibach if (port % MAX_PORTS_PER_BOARD >= brd->numPorts) { 1187f0e8527726b9e56649b9eafde3bc0fbc4dd2dd47Dirk Eibach mutex_unlock(&moxa_openlock); 1188f0e8527726b9e56649b9eafde3bc0fbc4dd2dd47Dirk Eibach return -ENODEV; 1189f0e8527726b9e56649b9eafde3bc0fbc4dd2dd47Dirk Eibach } 1190f0e8527726b9e56649b9eafde3bc0fbc4dd2dd47Dirk Eibach 1191810ab09b2f3a4e9a6f553e3d1e84a27f4074de9cJiri Slaby ch = &brd->ports[port % MAX_PORTS_PER_BOARD]; 11929de6a51fee08f9e7020074738150441305e83af2Alan Cox ch->port.count++; 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty->driver_data = ch; 1194d450b5a0196b6442cf3f29fc611d9c8daa56b559Alan Cox tty_port_tty_set(&ch->port, tty); 1195f176178ba09d27cc33988435e2c9fe078b44998cAlan Cox mutex_lock(&ch->port.mutex); 11969de6a51fee08f9e7020074738150441305e83af2Alan Cox if (!(ch->port.flags & ASYNC_INITIALIZED)) { 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ch->statusflags = 0; 1198adc8d746caa67fff4b53ba3e5163a6cbacc3b523Alan Cox moxa_set_tty_param(tty, &tty->termios); 1199b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortLineCtrl(ch, 1, 1); 1200b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortEnable(ch); 1201a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby MoxaSetFifo(ch, ch->type == PORT_16550A); 12029de6a51fee08f9e7020074738150441305e83af2Alan Cox ch->port.flags |= ASYNC_INITIALIZED; 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1204f176178ba09d27cc33988435e2c9fe078b44998cAlan Cox mutex_unlock(&ch->port.mutex); 1205a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12077c31bdb6b2a7118150df1668444fd1b7f1df3b85Jiri Slaby return tty_port_block_til_ready(&ch->port, tty, filp); 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_close(struct tty_struct *tty, struct file *filp) 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1212f176178ba09d27cc33988435e2c9fe078b44998cAlan Cox struct moxa_port *ch = tty->driver_data; 1213adc8d746caa67fff4b53ba3e5163a6cbacc3b523Alan Cox ch->cflag = tty->termios.c_cflag; 1214f176178ba09d27cc33988435e2c9fe078b44998cAlan Cox tty_port_close(&ch->port, tty, filp); 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_write(struct tty_struct *tty, 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const unsigned char *buf, int count) 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1220b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby struct moxa_port *ch = tty->driver_data; 12210ad7c9af3e1cbb97082062266705d6cb5fb207eeJiri Slaby unsigned long flags; 1222b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby int len; 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 1225b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby return 0; 122633f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox 12270ad7c9af3e1cbb97082062266705d6cb5fb207eeJiri Slaby spin_lock_irqsave(&moxa_lock, flags); 1228d450b5a0196b6442cf3f29fc611d9c8daa56b559Alan Cox len = MoxaPortWriteData(tty, buf, count); 12290ad7c9af3e1cbb97082062266705d6cb5fb207eeJiri Slaby spin_unlock_irqrestore(&moxa_lock, flags); 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1231a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox set_bit(LOWWAIT, &ch->statusflags); 1232eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby return len; 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_write_room(struct tty_struct *tty) 12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12378f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slaby struct moxa_port *ch; 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tty->stopped) 1240eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby return 0; 1241b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby ch = tty->driver_data; 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 1243eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby return 0; 1244b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby return MoxaPortTxFree(ch); 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_flush_buffer(struct tty_struct *tty) 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1249b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby struct moxa_port *ch = tty->driver_data; 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1253b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortFlushData(ch, 1); 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_wakeup(tty); 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int moxa_chars_in_buffer(struct tty_struct *tty) 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1259b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby struct moxa_port *ch = tty->driver_data; 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int chars; 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1262b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby chars = MoxaPortTxQueue(ch); 1263f710ebd7f70801e31751f2c49fe4b92a477d24ebAlan Cox if (chars) 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Make it possible to wakeup anything waiting for output 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in tty_ioctl.c, etc. 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1268f710ebd7f70801e31751f2c49fe4b92a477d24ebAlan Cox set_bit(EMPTYWAIT, &ch->statusflags); 1269eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby return chars; 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 127260b33c133ca0b7c0b6072c87234b63fee6e80558Alan Coxstatic int moxa_tiocmget(struct tty_struct *tty) 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12748482bcd58530ad5857d7187854132f2b846db681Alan Cox struct moxa_port *ch = tty->driver_data; 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int flag = 0, dtr, rts; 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1277b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortGetLineOut(ch, &dtr, &rts); 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dtr) 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flag |= TIOCM_DTR; 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rts) 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flag |= TIOCM_RTS; 1282b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby dtr = MoxaPortLineStatus(ch); 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dtr & 1) 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flag |= TIOCM_CTS; 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dtr & 2) 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flag |= TIOCM_DSR; 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dtr & 4) 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flag |= TIOCM_CD; 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return flag; 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 129220b9d17715017ae4dd4ec87fabc36d33b9de708eAlan Coxstatic int moxa_tiocmset(struct tty_struct *tty, 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int set, unsigned int clear) 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1295a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby struct moxa_port *ch; 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int dtr, rts; 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1298a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_lock(&moxa_openlock); 1299a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby ch = tty->driver_data; 1300a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby if (!ch) { 1301a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 130274d7d97b9e2a090a4b1812b5074ac6c539234ebbJiri Slaby return -EINVAL; 1303a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby } 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1305b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortGetLineOut(ch, &dtr, &rts); 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set & TIOCM_RTS) 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rts = 1; 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set & TIOCM_DTR) 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dtr = 1; 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clear & TIOCM_RTS) 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rts = 0; 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clear & TIOCM_DTR) 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dtr = 0; 1314b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortLineCtrl(ch, dtr, rts); 1315a8f5cda067e2eeefe49fe386caf0f61fc5c825e0Jiri Slaby mutex_unlock(&moxa_openlock); 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_set_termios(struct tty_struct *tty, 1320eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby struct ktermios *old_termios) 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1322eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby struct moxa_port *ch = tty->driver_data; 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1326db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox moxa_set_tty_param(tty, old_termios); 1327eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty)) 13289de6a51fee08f9e7020074738150441305e83af2Alan Cox wake_up_interruptible(&ch->port.open_wait); 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_stop(struct tty_struct *tty) 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1333eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby struct moxa_port *ch = tty->driver_data; 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1337b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortTxDisable(ch); 1338a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox set_bit(TXSTOPPED, &ch->statusflags); 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_start(struct tty_struct *tty) 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1344eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby struct moxa_port *ch = tty->driver_data; 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == NULL) 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 134958112dfbfe02d803566a2c6c8bd97b5fa3c62cdcDan Carpenter if (!test_bit(TXSTOPPED, &ch->statusflags)) 13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1352b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortTxEnable(ch); 1353a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox clear_bit(TXSTOPPED, &ch->statusflags); 13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void moxa_hangup(struct tty_struct *tty) 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1358a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox struct moxa_port *ch = tty->driver_data; 1359f176178ba09d27cc33988435e2c9fe078b44998cAlan Cox tty_port_hangup(&ch->port); 13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13627bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13648482bcd58530ad5857d7187854132f2b846db681Alan Cox unsigned long flags; 13657bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby dcd = !!dcd; 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13678482bcd58530ad5857d7187854132f2b846db681Alan Cox spin_lock_irqsave(&p->port.lock, flags); 1368d450b5a0196b6442cf3f29fc611d9c8daa56b559Alan Cox if (dcd != p->DCDState) { 13698482bcd58530ad5857d7187854132f2b846db681Alan Cox p->DCDState = dcd; 13708482bcd58530ad5857d7187854132f2b846db681Alan Cox spin_unlock_irqrestore(&p->port.lock, flags); 1371aa27a094e2c2e0cc59914e56113b860f524f4479Jiri Slaby if (!dcd) 1372aa27a094e2c2e0cc59914e56113b860f524f4479Jiri Slaby tty_port_tty_hangup(&p->port, true); 13737bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby } 13748482bcd58530ad5857d7187854132f2b846db681Alan Cox else 13758482bcd58530ad5857d7187854132f2b846db681Alan Cox spin_unlock_irqrestore(&p->port.lock, flags); 13767bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby} 13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13787bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int moxa_poll_port(struct moxa_port *p, unsigned int handle, 13797bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby u16 __iomem *ip) 13807bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby{ 1381d450b5a0196b6442cf3f29fc611d9c8daa56b559Alan Cox struct tty_struct *tty = tty_port_tty_get(&p->port); 13827bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby void __iomem *ofsAddr; 13839de6a51fee08f9e7020074738150441305e83af2Alan Cox unsigned int inited = p->port.flags & ASYNC_INITIALIZED; 13847bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby u16 intr; 13857bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 13867bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (tty) { 1387a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox if (test_bit(EMPTYWAIT, &p->statusflags) && 13887bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby MoxaPortTxQueue(p) == 0) { 1389a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox clear_bit(EMPTYWAIT, &p->statusflags); 13907bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby tty_wakeup(tty); 13917bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby } 1392a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox if (test_bit(LOWWAIT, &p->statusflags) && !tty->stopped && 13937bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby MoxaPortTxQueue(p) <= WAKEUP_CHARS) { 1394a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox clear_bit(LOWWAIT, &p->statusflags); 13957bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby tty_wakeup(tty); 13967bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby } 13977bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 1398f9b412a8c9adb17d50922f91962e8b1e48789430Alan Cox if (inited && !test_bit(TTY_THROTTLED, &tty->flags) && 13997bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby MoxaPortRxQueue(p) > 0) { /* RX */ 14007bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby MoxaPortReadData(p); 14016732c8bb8671acbdac6cdc93dd72ddd581dd5e25Jiri Slaby tty_schedule_flip(&p->port); 14027bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby } 14037bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby } else { 1404a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox clear_bit(EMPTYWAIT, &p->statusflags); 14057bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby MoxaPortFlushData(p, 0); /* flush RX */ 14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14070bcc4caadc8f5396b52950ee03c67b76875602dfJiri Slaby 14087bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (!handle) /* nothing else to do */ 14090e0fd7d73ed130583dca16405b029f56bf65109fJiri Slaby goto put; 14107bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14117bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby intr = readw(ip); /* port irq status */ 14127bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (intr == 0) 14130e0fd7d73ed130583dca16405b029f56bf65109fJiri Slaby goto put; 14147bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14157bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby writew(0, ip); /* ACK port */ 14167bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby ofsAddr = p->tableAddr; 14177bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (intr & IntrTx) /* disable tx intr */ 14187bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby writew(readw(ofsAddr + HostStat) & ~WakeupTx, 14197bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby ofsAddr + HostStat); 14207bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14217bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (!inited) 14220e0fd7d73ed130583dca16405b029f56bf65109fJiri Slaby goto put; 14237bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14247bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (tty && (intr & IntrBreak) && !I_IGNBRK(tty)) { /* BREAK */ 142592a19f9cec9a80ad93c06e115822deb729e2c6adJiri Slaby tty_insert_flip_char(&p->port, 0, TTY_BREAK); 14266732c8bb8671acbdac6cdc93dd72ddd581dd5e25Jiri Slaby tty_schedule_flip(&p->port); 14277bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby } 14287bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14297bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (intr & IntrLine) 14307bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state); 14310e0fd7d73ed130583dca16405b029f56bf65109fJiri Slabyput: 14320e0fd7d73ed130583dca16405b029f56bf65109fJiri Slaby tty_kref_put(tty); 14337bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14347bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby return 0; 14357bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby} 14367bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14377bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic void moxa_poll(unsigned long ignored) 14387bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby{ 14397bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby struct moxa_board_conf *brd; 14407bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby u16 __iomem *ip; 14412a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby unsigned int card, port, served = 0; 14427bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14437bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby spin_lock(&moxa_lock); 14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (card = 0; card < MAX_BOARDS; card++) { 14457bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby brd = &moxa_boards[card]; 14467bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (!brd->ready) 14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 14487bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14492a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby served++; 14502a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby 14517bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby ip = NULL; 14527bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (readb(brd->intPend) == 0xff) 14537bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby ip = brd->intTable + readb(brd->intNdx); 14547bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14557bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby for (port = 0; port < brd->numPorts; port++) 14567bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby moxa_poll_port(&brd->ports[port], !!ip, ip + port); 14577bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14587bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (ip) 14597bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby writeb(0, brd->intPend); /* ACK */ 14607bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby 14617bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (moxaLowWaterChk) { 14627bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby struct moxa_port *p = brd->ports; 14637bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby for (port = 0; port < brd->numPorts; port++, p++) 14647bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (p->lowChkFlag) { 14657bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby p->lowChkFlag = 0; 14667bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby moxa_low_water_check(p->tableAddr); 14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14707bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby moxaLowWaterChk = 0; 14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14722a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby if (served) 14732a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby mod_timer(&moxaTimer, jiffies + HZ / 50); 14742a5413416b6b2fd8a5a38601a4fe3b56a52cfb86Jiri Slaby spin_unlock(&moxa_lock); 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************************/ 14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1479db1acaa632870ec87b65e062bc72ca375837a1f6Alan Coxstatic void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_termios) 14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1481adc8d746caa67fff4b53ba3e5163a6cbacc3b523Alan Cox register struct ktermios *ts = &tty->termios; 1482eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby struct moxa_port *ch = tty->driver_data; 1483db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox int rts, cts, txflow, rxflow, xany, baud; 14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rts = cts = txflow = rxflow = xany = 0; 14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ts->c_cflag & CRTSCTS) 14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rts = cts = 1; 14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ts->c_iflag & IXON) 14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds txflow = 1; 14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ts->c_iflag & IXOFF) 14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rxflow = 1; 14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ts->c_iflag & IXANY) 14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds xany = 1; 1494db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox 1495db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox /* Clear the features we don't support */ 1496db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox ts->c_cflag &= ~CMSPAR; 1497b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby MoxaPortFlowCtrl(ch, rts, cts, txflow, rxflow, xany); 1498b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby baud = MoxaPortSetTermio(ch, ts, tty_get_baud_rate(tty)); 1499db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox if (baud == -1) 1500db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox baud = tty_termios_baud_rate(old_termios); 1501db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox /* Not put the baud rate into the termios data */ 1502db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox tty_encode_baud_rate(tty, baud, baud); 15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************************************************** 15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Driver level functions: * 15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/ 15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1509b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortFlushData(struct moxa_port *port, int mode) 15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 1512eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby if (mode < 0 || mode > 2) 15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1514b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby ofsAddr = port->tableAddr; 15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_FlushQueue, mode); 15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mode != 1) { 1517b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby port->lowChkFlag = 0; 15186f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_low_water_check(ofsAddr); 15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Moxa Port Number Description: 15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MOXA serial driver supports up to 4 MOXA-C218/C320 boards. And, 15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the port number using in MOXA driver functions will be 0 to 31 for 15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * first MOXA board, 32 to 63 for second, 64 to 95 for third and 96 15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to 127 for fourth. For example, if you setup three MOXA boards, 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * first board is C218, second board is C320-16 and third board is 15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * C320-32. The port number of first board (C218 - 8 ports) is from 15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 to 7. The port number of second board (C320 - 16 ports) is form 15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 32 to 47. The port number of third board (C320 - 32 ports) is from 15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 64 to 95. And those port numbers form 8 to 31, 48 to 63 and 96 to 15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 127 will be invalid. 15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Moxa Functions Description: 15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 1: Driver initialization routine, this routine must be 15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * called when initialized driver. 15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaDriverInit(); 15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 2: Moxa driver private IOCTL command processing. 15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port); 15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsigned int cmd : IOCTL command 15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsigned long arg : IOCTL argument 15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 (OK) 15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL 15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -ENOIOCTLCMD 15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 6: Enable this port to start Tx/Rx data. 15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortEnable(int port); 15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 7: Disable this port 15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortDisable(int port); 15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 10: Setting baud rate of this port. 15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 157208d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby * speed_t MoxaPortSetBaud(int port, speed_t baud); 15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * long baud : baud rate (50 - 115200) 15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 : this port is invalid or baud < 50 15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 50 - 115200 : the real baud rate set to the port, if 15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the argument baud is large than maximun 15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * available baud rate, the real setting 15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * baud rate will be the maximun baud rate. 15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 12: Configure the port. 15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 1585606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox * int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud); 15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 1587606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox * struct ktermios * termio : termio structure pointer 1588c7bce3097c0f9bbed76ee6fd03742f2624031a45Alan Cox * speed_t baud : baud rate 15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: -1 : this port is invalid or termio == NULL 15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 : setting O.K. 15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 13: Get the DTR/RTS state of this port. 15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortGetLineOut(int port, int *dtrState, int *rtsState); 15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int * dtrState : pointer to INT to receive the current DTR 15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * state. (if NULL, this function will not 16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * write to this address) 16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int * rtsState : pointer to INT to receive the current RTS 16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * state. (if NULL, this function will not 16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * write to this address) 16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: -1 : this port is invalid 16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 : O.K. 16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 14: Setting the DTR/RTS output state of this port. 16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortLineCtrl(int port, int dtrState, int rtsState); 16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int dtrState : DTR output state (0: off, 1: on) 16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int rtsState : RTS output state (0: off, 1: on) 16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 15: Setting the flow control of this port. 16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortFlowCtrl(int port, int rtsFlow, int ctsFlow, int rxFlow, 16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int txFlow,int xany); 16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int rtsFlow : H/W RTS flow control (0: no, 1: yes) 16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int ctsFlow : H/W CTS flow control (0: no, 1: yes) 16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int rxFlow : S/W Rx XON/XOFF flow control (0: no, 1: yes) 16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int txFlow : S/W Tx XON/XOFF flow control (0: no, 1: yes) 16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int xany : S/W XANY flow control (0: no, 1: yes) 16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 16: Get ths line status of this port 16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortLineStatus(int port); 16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: Bit 0 - CTS state (0: off, 1: on) 16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bit 1 - DSR state (0: off, 1: on) 16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bit 2 - DCD state (0: off, 1: on) 16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 19: Flush the Rx/Tx buffer data of this port. 16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortFlushData(int port, int mode); 16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int mode 16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 : flush the Rx buffer 16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 : flush the Tx buffer 16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2 : flush the Rx and Tx buffer 16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 20: Write data. 16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortWriteData(int port, unsigned char * buffer, int length); 16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsigned char * buffer : pointer to write data buffer. 16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int length : write data length 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 - length : real write data length 16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 21: Read data. 16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 166133f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox * int MoxaPortReadData(int port, struct tty_struct *tty); 16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 166333f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox * struct tty_struct *tty : tty for data 16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 - length : real read data length 16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 24: Get the Tx buffer current queued data bytes 16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortTxQueue(int port); 16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: .. : Tx buffer current queued data bytes 16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 25: Get the Tx buffer current free space 16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortTxFree(int port); 16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: .. : Tx buffer current free space 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 26: Get the Rx buffer current queued data bytes 16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortRxQueue(int port); 16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: .. : Rx buffer current queued data bytes 16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 28: Disable port data transmission. 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortTxDisable(int port); 16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 29: Enable port data transmission. 16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void MoxaPortTxEnable(int port); 17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 31: Get the received BREAK signal count and reset it. 17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Syntax: 17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int MoxaPortResetBrkCnt(int port); 17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * int port : port number (0 - 127) 17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return: 0 - .. : BREAK signal count 17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1714b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortEnable(struct moxa_port *port) 17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 1717eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby u16 lowwater = 512; 17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1719b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby ofsAddr = port->tableAddr; 17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(lowwater, ofsAddr + Low_water); 172108d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby if (MOXA_IS_320(port->board)) 17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetBreakIrq, 0); 1723eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby else 1724eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby writew(readw(ofsAddr + HostStat) | WakeupBreak, 1725eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby ofsAddr + HostStat); 17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetLineIrq, Magic_code); 17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_FlushQueue, 2); 17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_EnableCH, Magic_code); 17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MoxaPortLineStatus(port); 17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1734b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortDisable(struct moxa_port *port) 17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1736b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby void __iomem *ofsAddr = port->tableAddr; 17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetFlowCtl, 0); /* disable flow control */ 17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code); 17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(0, ofsAddr + HostStat); 17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_DisableCH, Magic_code); 17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 174408d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slabystatic speed_t MoxaPortSetBaud(struct moxa_port *port, speed_t baud) 17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 174608d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby void __iomem *ofsAddr = port->tableAddr; 174708d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby unsigned int clock, val; 174808d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby speed_t max; 17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 175008d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby max = MOXA_IS_320(port->board) ? 460800 : 921600; 175108d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby if (baud < 50) 1752eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby return 0; 17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (baud > max) 17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds baud = max; 175508d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby clock = 921600; 17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = clock / baud; 17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetBaud, val); 17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds baud = clock / val; 1759eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby return baud; 17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1762b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio, 1763b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby speed_t baud) 17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tcflag_t mode = 0; 17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1768b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby ofsAddr = port->tableAddr; 17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = termio->c_cflag & CSIZE; 17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mode == CS5) 17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = MX_CS5; 17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (mode == CS6) 17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = MX_CS6; 17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (mode == CS7) 17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = MX_CS7; 17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (mode == CS8) 17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode = MX_CS8; 17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (termio->c_cflag & CSTOPB) { 17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mode == MX_CS5) 17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_STOP15; 17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_STOP2; 17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_STOP1; 17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (termio->c_cflag & PARENB) { 17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (termio->c_cflag & PARODD) 17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_PARODD; 17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_PAREVEN; 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= MX_PARNONE; 17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1796eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby moxafunc(ofsAddr, FC_SetDataMode, (u16)mode); 17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 179808d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby if (MOXA_IS_320(port->board) && baud >= 921600) 179908d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby return -1; 180008d01c792568ba07d2bcf5202dbc8484dbff6747Jiri Slaby 1801db1acaa632870ec87b65e062bc72ca375837a1f6Alan Cox baud = MoxaPortSetBaud(port, baud); 18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (termio->c_iflag & (IXON | IXOFF | IXANY)) { 1804f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox spin_lock_irq(&moxafunc_lock); 18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(termio->c_cc[VSTART], ofsAddr + FuncArg); 18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1); 18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(FC_SetXonXoff, ofsAddr + FuncCode); 18086f56b658b4e5c4486641ce62f331150954c4de37Jiri Slaby moxa_wait_finish(ofsAddr); 1809a808ac0c4a2c5d81ba38a2a76d4ddc1de40d1539Alan Cox spin_unlock_irq(&moxafunc_lock); 18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1812eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby return baud; 18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1815b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortGetLineOut(struct moxa_port *port, int *dtrState, 1816b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby int *rtsState) 18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1818b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby if (dtrState) 1819b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *dtrState = !!(port->lineCtrl & DTR_ON); 1820b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby if (rtsState) 1821b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby *rtsState = !!(port->lineCtrl & RTS_ON); 1822b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby 1823eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby return 0; 18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1826b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortLineCtrl(struct moxa_port *port, int dtr, int rts) 18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1828eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby u8 mode = 0; 18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dtr) 18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= DTR_ON; 18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rts) 18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= RTS_ON; 1834b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby port->lineCtrl = mode; 1835b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby moxafunc(port->tableAddr, FC_LineControl, mode); 18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1838b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortFlowCtrl(struct moxa_port *port, int rts, int cts, 1839b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby int txflow, int rxflow, int txany) 18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1841b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby int mode = 0; 18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rts) 18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= RTS_FlowCtl; 18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cts) 18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= CTS_FlowCtl; 18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (txflow) 18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= Tx_FlowCtl; 18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rxflow) 18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= Rx_FlowCtl; 18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (txany) 18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode |= IXM_IXANY; 1853b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby moxafunc(port->tableAddr, FC_SetFlowCtl, mode); 18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1856b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortLineStatus(struct moxa_port *port) 18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ofsAddr; 18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val; 18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1861b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby ofsAddr = port->tableAddr; 1862f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox if (MOXA_IS_320(port->board)) 1863f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox val = moxafuncret(ofsAddr, FC_LineStatus, 0); 1864f5c5a36d27ae6d9e03c2f1b7890942bf84e92c5bAlan Cox else 18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = readw(ofsAddr + FlagStat) >> 4; 18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val &= 0x0B; 18677bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby if (val & 8) 18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val |= 4; 18697bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby moxa_new_dcdstate(port, val & 8); 18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val &= 7; 18717bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby return val; 18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1874d450b5a0196b6442cf3f29fc611d9c8daa56b559Alan Coxstatic int MoxaPortWriteData(struct tty_struct *tty, 18752108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby const unsigned char *buffer, int len) 18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1877d450b5a0196b6442cf3f29fc611d9c8daa56b559Alan Cox struct moxa_port *port = tty->driver_data; 18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *baseAddr, *ofsAddr, *ofs; 18792108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby unsigned int c, total; 18802108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby u16 head, tail, tx_mask, spage, epage; 18812108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby u16 pageno, pageofs, bufhead; 18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1883b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby ofsAddr = port->tableAddr; 1884b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby baseAddr = port->board->basemem; 18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tx_mask = readw(ofsAddr + TX_mask); 18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spage = readw(ofsAddr + Page_txb); 18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds epage = readw(ofsAddr + EndPage_txb); 18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tail = readw(ofsAddr + TXwptr); 18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head = readw(ofsAddr + TXrptr); 18902108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby c = (head > tail) ? (head - tail - 1) : (head - tail + tx_mask); 18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (c > len) 18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c = len; 18939de6a51fee08f9e7020074738150441305e83af2Alan Cox moxaLog.txcnt[port->port.tty->index] += c; 18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds total = c; 18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (spage == epage) { 18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bufhead = readw(ofsAddr + Ofs_txb); 18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(spage, baseAddr + Control_reg); 18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (c > 0) { 18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (head > tail) 19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = head - tail - 1; 19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = tx_mask + 1 - tail; 19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = (c > len) ? len : c; 19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ofs = baseAddr + DynPage_addr + bufhead + tail; 19052108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby memcpy_toio(ofs, buffer, len); 19062108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby buffer += len; 19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tail = (tail + len) & tx_mask; 19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c -= len; 19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageno = spage + (tail >> 13); 19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageofs = tail & Page_mask; 19132108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby while (c > 0) { 19142108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby len = Page_size - pageofs; 19152108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby if (len > c) 19162108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby len = c; 19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(pageno, baseAddr + Control_reg); 19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ofs = baseAddr + DynPage_addr + pageofs; 19192108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby memcpy_toio(ofs, buffer, len); 19202108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby buffer += len; 19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (++pageno == epage) 19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageno = spage; 19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageofs = 0; 19242108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby c -= len; 19252108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby } 19262108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby tail = (tail + total) & tx_mask; 19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19282108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby writew(tail, ofsAddr + TXwptr); 19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(1, ofsAddr + CD180TXirq); /* start to send */ 19302108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby return total; 19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19337bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slabystatic int MoxaPortReadData(struct moxa_port *port) 19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19359de6a51fee08f9e7020074738150441305e83af2Alan Cox struct tty_struct *tty = port->port.tty; 19362108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby unsigned char *dst; 19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *baseAddr, *ofsAddr, *ofs; 19382108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby unsigned int count, len, total; 19392108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby u16 tail, rx_mask, spage, epage; 19402108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby u16 pageno, pageofs, bufhead, head; 19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1942b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby ofsAddr = port->tableAddr; 1943b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby baseAddr = port->board->basemem; 19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head = readw(ofsAddr + RXrptr); 19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tail = readw(ofsAddr + RXwptr); 19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rx_mask = readw(ofsAddr + RX_mask); 19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spage = readw(ofsAddr + Page_rxb); 19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds epage = readw(ofsAddr + EndPage_rxb); 19492108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby count = (tail >= head) ? (tail - head) : (tail - head + rx_mask + 1); 19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count == 0) 195133f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox return 0; 19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 195333f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox total = count; 19547bcf97d1dd88135b58c7adb7c3bfebab55b21a20Jiri Slaby moxaLog.rxcnt[tty->index] += total; 19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (spage == epage) { 19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bufhead = readw(ofsAddr + Ofs_rxb); 19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(spage, baseAddr + Control_reg); 19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (count > 0) { 19591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ofs = baseAddr + DynPage_addr + bufhead + head; 19602108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby len = (tail >= head) ? (tail - head) : 19612108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby (rx_mask + 1 - head); 19622f69335710884ae6112fc8196ebe29b5cda7b79bJiri Slaby len = tty_prepare_flip_string(&port->port, &dst, 19632108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby min(len, count)); 19642108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby memcpy_fromio(dst, ofs, len); 19651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head = (head + len) & rx_mask; 19661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count -= len; 19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageno = spage + (head >> 13); 19701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageofs = head & Page_mask; 19712108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby while (count > 0) { 19721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(pageno, baseAddr + Control_reg); 19731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ofs = baseAddr + DynPage_addr + pageofs; 19742f69335710884ae6112fc8196ebe29b5cda7b79bJiri Slaby len = tty_prepare_flip_string(&port->port, &dst, 19752108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby min(Page_size - pageofs, count)); 19762108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby memcpy_fromio(dst, ofs, len); 19772108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby 19782108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby count -= len; 19792108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby pageofs = (pageofs + len) & Page_mask; 19802108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby if (pageofs == 0 && ++pageno == epage) 19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pageno = spage; 19822108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby } 19832108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby head = (head + total) & rx_mask; 19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19852108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby writew(head, ofsAddr + RXrptr); 19862108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby if (readb(ofsAddr + FlagStat) & Xoff_state) { 19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxaLowWaterChk = 1; 1988b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby port->lowChkFlag = 1; 19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19902108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby return total; 19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1994b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortTxQueue(struct moxa_port *port) 19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1996b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby void __iomem *ofsAddr = port->tableAddr; 19972108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby u16 rptr, wptr, mask; 19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rptr = readw(ofsAddr + TXrptr); 20001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wptr = readw(ofsAddr + TXwptr); 20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = readw(ofsAddr + TX_mask); 20022108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby return (wptr - rptr) & mask; 20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2005b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortTxFree(struct moxa_port *port) 20061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2007b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby void __iomem *ofsAddr = port->tableAddr; 20082108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby u16 rptr, wptr, mask; 20091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rptr = readw(ofsAddr + TXrptr); 20111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wptr = readw(ofsAddr + TXwptr); 20121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = readw(ofsAddr + TX_mask); 20132108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby return mask - ((wptr - rptr) & mask); 20141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2016b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic int MoxaPortRxQueue(struct moxa_port *port) 20171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2018b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby void __iomem *ofsAddr = port->tableAddr; 20192108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby u16 rptr, wptr, mask; 20201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rptr = readw(ofsAddr + RXrptr); 20221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wptr = readw(ofsAddr + RXwptr); 20231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = readw(ofsAddr + RX_mask); 20242108eba5c531c12f5ae2ed2ef4cee7bf4246897bJiri Slaby return (wptr - rptr) & mask; 20251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2027b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortTxDisable(struct moxa_port *port) 20281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2029b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby moxafunc(port->tableAddr, FC_SetXoffState, Magic_code); 20301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2032b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaPortTxEnable(struct moxa_port *port) 20331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2034b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby moxafunc(port->tableAddr, FC_SetXonState, Magic_code); 20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20378f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic int moxa_get_serial_info(struct moxa_port *info, 2038eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby struct serial_struct __user *retinfo) 20391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2040eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby struct serial_struct tmp = { 2041eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby .type = info->type, 20429de6a51fee08f9e7020074738150441305e83af2Alan Cox .line = info->port.tty->index, 20439de6a51fee08f9e7020074738150441305e83af2Alan Cox .flags = info->port.flags, 2044eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby .baud_base = 921600, 204544b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox .close_delay = info->port.close_delay 2046eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby }; 2047eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; 20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20518f8ecbad09b48e5fe44a8d7f5344e802e9c231c8Jiri Slabystatic int moxa_set_serial_info(struct moxa_port *info, 2052eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby struct serial_struct __user *new_info) 20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct serial_struct new_serial; 20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2056eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) 20571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 20581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2059eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby if (new_serial.irq != 0 || new_serial.port != 0 || 2060eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby new_serial.custom_divisor != 0 || 2061eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby new_serial.baud_base != 921600) 2062eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby return -EPERM; 20631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_ADMIN)) { 20651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((new_serial.flags & ~ASYNC_USR_MASK) != 20669de6a51fee08f9e7020074738150441305e83af2Alan Cox (info->port.flags & ~ASYNC_USR_MASK))) 2067eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby return -EPERM; 2068eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby } else 206944b7d1b37f786c61d0e382b6f72f605f73de284bAlan Cox info->port.close_delay = new_serial.close_delay * HZ / 100; 20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_serial.flags = (new_serial.flags & ~ASYNC_FLAGS); 20729de6a51fee08f9e7020074738150441305e83af2Alan Cox new_serial.flags |= (info->port.flags & ASYNC_FLAGS); 20731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2074eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby MoxaSetFifo(info, new_serial.type == PORT_16550A); 20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->type = new_serial.type; 2077eaa95a8da6366c34d3a61e93109e5f8f8a4e72a0Jiri Slaby return 0; 20781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************************************************** 20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Static local functions: * 20841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/ 20851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2086b4173f45758a5b5185acb302c507289e661d9419Jiri Slabystatic void MoxaSetFifo(struct moxa_port *port, int enable) 20871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2088b4173f45758a5b5185acb302c507289e661d9419Jiri Slaby void __iomem *ofsAddr = port->tableAddr; 20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!enable) { 20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0); 20921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetTxFIFOCnt, 1); 20931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 20941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetRxFIFOTrig, 3); 20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16); 20961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2098