ia64/linux-2.6.18-xen.hg

annotate drivers/char/moxa.c @ 893:f994bfe9b93b

linux/blktap2: reduce TLB flush scope

c/s 885 added very coarse TLB flushing. Since these flushes always
follow single page updates, single page flushes (when available) are
sufficient.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 04 10:32:57 2009 +0100 (2009-06-04)
parents 831230e53067
children
rev   line source
ian@0 1 /*****************************************************************************/
ian@0 2 /*
ian@0 3 * moxa.c -- MOXA Intellio family multiport serial driver.
ian@0 4 *
ian@0 5 * Copyright (C) 1999-2000 Moxa Technologies (support@moxa.com.tw).
ian@0 6 *
ian@0 7 * This code is loosely based on the Linux serial driver, written by
ian@0 8 * Linus Torvalds, Theodore T'so and others.
ian@0 9 *
ian@0 10 * This program is free software; you can redistribute it and/or modify
ian@0 11 * it under the terms of the GNU General Public License as published by
ian@0 12 * the Free Software Foundation; either version 2 of the License, or
ian@0 13 * (at your option) any later version.
ian@0 14 *
ian@0 15 * This program is distributed in the hope that it will be useful,
ian@0 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ian@0 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ian@0 18 * GNU General Public License for more details.
ian@0 19 *
ian@0 20 * You should have received a copy of the GNU General Public License
ian@0 21 * along with this program; if not, write to the Free Software
ian@0 22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
ian@0 23 */
ian@0 24
ian@0 25 /*
ian@0 26 * MOXA Intellio Series Driver
ian@0 27 * for : LINUX
ian@0 28 * date : 1999/1/7
ian@0 29 * version : 5.1
ian@0 30 */
ian@0 31
ian@0 32 #include <linux/module.h>
ian@0 33 #include <linux/types.h>
ian@0 34 #include <linux/mm.h>
ian@0 35 #include <linux/ioport.h>
ian@0 36 #include <linux/errno.h>
ian@0 37 #include <linux/signal.h>
ian@0 38 #include <linux/sched.h>
ian@0 39 #include <linux/timer.h>
ian@0 40 #include <linux/interrupt.h>
ian@0 41 #include <linux/tty.h>
ian@0 42 #include <linux/tty_flip.h>
ian@0 43 #include <linux/major.h>
ian@0 44 #include <linux/string.h>
ian@0 45 #include <linux/fcntl.h>
ian@0 46 #include <linux/ptrace.h>
ian@0 47 #include <linux/serial.h>
ian@0 48 #include <linux/tty_driver.h>
ian@0 49 #include <linux/delay.h>
ian@0 50 #include <linux/pci.h>
ian@0 51 #include <linux/init.h>
ian@0 52 #include <linux/bitops.h>
ian@0 53
ian@0 54 #include <asm/system.h>
ian@0 55 #include <asm/io.h>
ian@0 56 #include <asm/uaccess.h>
ian@0 57
ian@0 58 #define MOXA_VERSION "5.1k"
ian@0 59
ian@0 60 #define MOXAMAJOR 172
ian@0 61 #define MOXACUMAJOR 173
ian@0 62
ian@0 63 #define put_to_user(arg1, arg2) put_user(arg1, (unsigned long *)arg2)
ian@0 64 #define get_from_user(arg1, arg2) get_user(arg1, (unsigned int *)arg2)
ian@0 65
ian@0 66 #define MAX_BOARDS 4 /* Don't change this value */
ian@0 67 #define MAX_PORTS_PER_BOARD 32 /* Don't change this value */
ian@0 68 #define MAX_PORTS 128 /* Don't change this value */
ian@0 69
ian@0 70 /*
ian@0 71 * Define the Moxa PCI vendor and device IDs.
ian@0 72 */
ian@0 73 #define MOXA_BUS_TYPE_ISA 0
ian@0 74 #define MOXA_BUS_TYPE_PCI 1
ian@0 75
ian@0 76 #ifndef PCI_VENDOR_ID_MOXA
ian@0 77 #define PCI_VENDOR_ID_MOXA 0x1393
ian@0 78 #endif
ian@0 79 #ifndef PCI_DEVICE_ID_CP204J
ian@0 80 #define PCI_DEVICE_ID_CP204J 0x2040
ian@0 81 #endif
ian@0 82 #ifndef PCI_DEVICE_ID_C218
ian@0 83 #define PCI_DEVICE_ID_C218 0x2180
ian@0 84 #endif
ian@0 85 #ifndef PCI_DEVICE_ID_C320
ian@0 86 #define PCI_DEVICE_ID_C320 0x3200
ian@0 87 #endif
ian@0 88
ian@0 89 enum {
ian@0 90 MOXA_BOARD_C218_PCI = 1,
ian@0 91 MOXA_BOARD_C218_ISA,
ian@0 92 MOXA_BOARD_C320_PCI,
ian@0 93 MOXA_BOARD_C320_ISA,
ian@0 94 MOXA_BOARD_CP204J,
ian@0 95 };
ian@0 96
ian@0 97 static char *moxa_brdname[] =
ian@0 98 {
ian@0 99 "C218 Turbo PCI series",
ian@0 100 "C218 Turbo ISA series",
ian@0 101 "C320 Turbo PCI series",
ian@0 102 "C320 Turbo ISA series",
ian@0 103 "CP-204J series",
ian@0 104 };
ian@0 105
ian@0 106 #ifdef CONFIG_PCI
ian@0 107 static struct pci_device_id moxa_pcibrds[] = {
ian@0 108 { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C218, PCI_ANY_ID, PCI_ANY_ID,
ian@0 109 0, 0, MOXA_BOARD_C218_PCI },
ian@0 110 { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C320, PCI_ANY_ID, PCI_ANY_ID,
ian@0 111 0, 0, MOXA_BOARD_C320_PCI },
ian@0 112 { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP204J, PCI_ANY_ID, PCI_ANY_ID,
ian@0 113 0, 0, MOXA_BOARD_CP204J },
ian@0 114 { 0 }
ian@0 115 };
ian@0 116 MODULE_DEVICE_TABLE(pci, moxa_pcibrds);
ian@0 117 #endif /* CONFIG_PCI */
ian@0 118
ian@0 119 typedef struct _moxa_isa_board_conf {
ian@0 120 int boardType;
ian@0 121 int numPorts;
ian@0 122 unsigned long baseAddr;
ian@0 123 } moxa_isa_board_conf;
ian@0 124
ian@0 125 static moxa_isa_board_conf moxa_isa_boards[] =
ian@0 126 {
ian@0 127 /* {MOXA_BOARD_C218_ISA,8,0xDC000}, */
ian@0 128 };
ian@0 129
ian@0 130 typedef struct _moxa_pci_devinfo {
ian@0 131 ushort busNum;
ian@0 132 ushort devNum;
ian@0 133 } moxa_pci_devinfo;
ian@0 134
ian@0 135 typedef struct _moxa_board_conf {
ian@0 136 int boardType;
ian@0 137 int numPorts;
ian@0 138 unsigned long baseAddr;
ian@0 139 int busType;
ian@0 140 moxa_pci_devinfo pciInfo;
ian@0 141 } moxa_board_conf;
ian@0 142
ian@0 143 static moxa_board_conf moxa_boards[MAX_BOARDS];
ian@0 144 static void __iomem *moxaBaseAddr[MAX_BOARDS];
ian@0 145 static int loadstat[MAX_BOARDS];
ian@0 146
ian@0 147 struct moxa_str {
ian@0 148 int type;
ian@0 149 int port;
ian@0 150 int close_delay;
ian@0 151 unsigned short closing_wait;
ian@0 152 int count;
ian@0 153 int blocked_open;
ian@0 154 long event; /* long req'd for set_bit --RR */
ian@0 155 int asyncflags;
ian@0 156 unsigned long statusflags;
ian@0 157 struct tty_struct *tty;
ian@0 158 int cflag;
ian@0 159 wait_queue_head_t open_wait;
ian@0 160 wait_queue_head_t close_wait;
ian@0 161 struct work_struct tqueue;
ian@0 162 };
ian@0 163
ian@0 164 struct mxser_mstatus {
ian@0 165 tcflag_t cflag;
ian@0 166 int cts;
ian@0 167 int dsr;
ian@0 168 int ri;
ian@0 169 int dcd;
ian@0 170 };
ian@0 171
ian@0 172 static struct mxser_mstatus GMStatus[MAX_PORTS];
ian@0 173
ian@0 174 /* statusflags */
ian@0 175 #define TXSTOPPED 0x1
ian@0 176 #define LOWWAIT 0x2
ian@0 177 #define EMPTYWAIT 0x4
ian@0 178 #define THROTTLE 0x8
ian@0 179
ian@0 180 /* event */
ian@0 181 #define MOXA_EVENT_HANGUP 1
ian@0 182
ian@0 183 #define SERIAL_DO_RESTART
ian@0 184
ian@0 185
ian@0 186 #define SERIAL_TYPE_NORMAL 1
ian@0 187
ian@0 188 #define WAKEUP_CHARS 256
ian@0 189
ian@0 190 #define PORTNO(x) ((x)->index)
ian@0 191
ian@0 192 static int verbose = 0;
ian@0 193 static int ttymajor = MOXAMAJOR;
ian@0 194 /* Variables for insmod */
ian@0 195 #ifdef MODULE
ian@0 196 static int baseaddr[] = {0, 0, 0, 0};
ian@0 197 static int type[] = {0, 0, 0, 0};
ian@0 198 static int numports[] = {0, 0, 0, 0};
ian@0 199 #endif
ian@0 200
ian@0 201 MODULE_AUTHOR("William Chen");
ian@0 202 MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
ian@0 203 MODULE_LICENSE("GPL");
ian@0 204 #ifdef MODULE
ian@0 205 module_param_array(type, int, NULL, 0);
ian@0 206 module_param_array(baseaddr, int, NULL, 0);
ian@0 207 module_param_array(numports, int, NULL, 0);
ian@0 208 #endif
ian@0 209 module_param(ttymajor, int, 0);
ian@0 210 module_param(verbose, bool, 0644);
ian@0 211
ian@0 212 static struct tty_driver *moxaDriver;
ian@0 213 static struct moxa_str moxaChannels[MAX_PORTS];
ian@0 214 static unsigned char *moxaXmitBuff;
ian@0 215 static int moxaTimer_on;
ian@0 216 static struct timer_list moxaTimer;
ian@0 217 static int moxaEmptyTimer_on[MAX_PORTS];
ian@0 218 static struct timer_list moxaEmptyTimer[MAX_PORTS];
ian@0 219 static struct semaphore moxaBuffSem;
ian@0 220
ian@0 221 /*
ian@0 222 * static functions:
ian@0 223 */
ian@0 224 static void do_moxa_softint(void *);
ian@0 225 static int moxa_open(struct tty_struct *, struct file *);
ian@0 226 static void moxa_close(struct tty_struct *, struct file *);
ian@0 227 static int moxa_write(struct tty_struct *, const unsigned char *, int);
ian@0 228 static int moxa_write_room(struct tty_struct *);
ian@0 229 static void moxa_flush_buffer(struct tty_struct *);
ian@0 230 static int moxa_chars_in_buffer(struct tty_struct *);
ian@0 231 static void moxa_flush_chars(struct tty_struct *);
ian@0 232 static void moxa_put_char(struct tty_struct *, unsigned char);
ian@0 233 static int moxa_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long);
ian@0 234 static void moxa_throttle(struct tty_struct *);
ian@0 235 static void moxa_unthrottle(struct tty_struct *);
ian@0 236 static void moxa_set_termios(struct tty_struct *, struct termios *);
ian@0 237 static void moxa_stop(struct tty_struct *);
ian@0 238 static void moxa_start(struct tty_struct *);
ian@0 239 static void moxa_hangup(struct tty_struct *);
ian@0 240 static int moxa_tiocmget(struct tty_struct *tty, struct file *file);
ian@0 241 static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
ian@0 242 unsigned int set, unsigned int clear);
ian@0 243 static void moxa_poll(unsigned long);
ian@0 244 static void set_tty_param(struct tty_struct *);
ian@0 245 static int block_till_ready(struct tty_struct *, struct file *,
ian@0 246 struct moxa_str *);
ian@0 247 static void setup_empty_event(struct tty_struct *);
ian@0 248 static void check_xmit_empty(unsigned long);
ian@0 249 static void shut_down(struct moxa_str *);
ian@0 250 static void receive_data(struct moxa_str *);
ian@0 251 /*
ian@0 252 * moxa board interface functions:
ian@0 253 */
ian@0 254 static void MoxaDriverInit(void);
ian@0 255 static int MoxaDriverIoctl(unsigned int, unsigned long, int);
ian@0 256 static int MoxaDriverPoll(void);
ian@0 257 static int MoxaPortsOfCard(int);
ian@0 258 static int MoxaPortIsValid(int);
ian@0 259 static void MoxaPortEnable(int);
ian@0 260 static void MoxaPortDisable(int);
ian@0 261 static long MoxaPortGetMaxBaud(int);
ian@0 262 static long MoxaPortSetBaud(int, long);
ian@0 263 static int MoxaPortSetTermio(int, struct termios *);
ian@0 264 static int MoxaPortGetLineOut(int, int *, int *);
ian@0 265 static void MoxaPortLineCtrl(int, int, int);
ian@0 266 static void MoxaPortFlowCtrl(int, int, int, int, int, int);
ian@0 267 static int MoxaPortLineStatus(int);
ian@0 268 static int MoxaPortDCDChange(int);
ian@0 269 static int MoxaPortDCDON(int);
ian@0 270 static void MoxaPortFlushData(int, int);
ian@0 271 static int MoxaPortWriteData(int, unsigned char *, int);
ian@0 272 static int MoxaPortReadData(int, struct tty_struct *tty);
ian@0 273 static int MoxaPortTxQueue(int);
ian@0 274 static int MoxaPortRxQueue(int);
ian@0 275 static int MoxaPortTxFree(int);
ian@0 276 static void MoxaPortTxDisable(int);
ian@0 277 static void MoxaPortTxEnable(int);
ian@0 278 static int MoxaPortResetBrkCnt(int);
ian@0 279 static void MoxaPortSendBreak(int, int);
ian@0 280 static int moxa_get_serial_info(struct moxa_str *, struct serial_struct __user *);
ian@0 281 static int moxa_set_serial_info(struct moxa_str *, struct serial_struct __user *);
ian@0 282 static void MoxaSetFifo(int port, int enable);
ian@0 283
ian@0 284 static struct tty_operations moxa_ops = {
ian@0 285 .open = moxa_open,
ian@0 286 .close = moxa_close,
ian@0 287 .write = moxa_write,
ian@0 288 .write_room = moxa_write_room,
ian@0 289 .flush_buffer = moxa_flush_buffer,
ian@0 290 .chars_in_buffer = moxa_chars_in_buffer,
ian@0 291 .flush_chars = moxa_flush_chars,
ian@0 292 .put_char = moxa_put_char,
ian@0 293 .ioctl = moxa_ioctl,
ian@0 294 .throttle = moxa_throttle,
ian@0 295 .unthrottle = moxa_unthrottle,
ian@0 296 .set_termios = moxa_set_termios,
ian@0 297 .stop = moxa_stop,
ian@0 298 .start = moxa_start,
ian@0 299 .hangup = moxa_hangup,
ian@0 300 .tiocmget = moxa_tiocmget,
ian@0 301 .tiocmset = moxa_tiocmset,
ian@0 302 };
ian@0 303
ian@0 304 static DEFINE_SPINLOCK(moxa_lock);
ian@0 305
ian@0 306 #ifdef CONFIG_PCI
ian@0 307 static int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf * board)
ian@0 308 {
ian@0 309 board->baseAddr = pci_resource_start (p, 2);
ian@0 310 board->boardType = board_type;
ian@0 311 switch (board_type) {
ian@0 312 case MOXA_BOARD_C218_ISA:
ian@0 313 case MOXA_BOARD_C218_PCI:
ian@0 314 board->numPorts = 8;
ian@0 315 break;
ian@0 316
ian@0 317 case MOXA_BOARD_CP204J:
ian@0 318 board->numPorts = 4;
ian@0 319 break;
ian@0 320 default:
ian@0 321 board->numPorts = 0;
ian@0 322 break;
ian@0 323 }
ian@0 324 board->busType = MOXA_BUS_TYPE_PCI;
ian@0 325 board->pciInfo.busNum = p->bus->number;
ian@0 326 board->pciInfo.devNum = p->devfn >> 3;
ian@0 327
ian@0 328 return (0);
ian@0 329 }
ian@0 330 #endif /* CONFIG_PCI */
ian@0 331
ian@0 332 static int __init moxa_init(void)
ian@0 333 {
ian@0 334 int i, numBoards;
ian@0 335 struct moxa_str *ch;
ian@0 336
ian@0 337 printk(KERN_INFO "MOXA Intellio family driver version %s\n", MOXA_VERSION);
ian@0 338 moxaDriver = alloc_tty_driver(MAX_PORTS + 1);
ian@0 339 if (!moxaDriver)
ian@0 340 return -ENOMEM;
ian@0 341
ian@0 342 init_MUTEX(&moxaBuffSem);
ian@0 343 moxaDriver->owner = THIS_MODULE;
ian@0 344 moxaDriver->name = "ttyMX";
ian@0 345 moxaDriver->major = ttymajor;
ian@0 346 moxaDriver->minor_start = 0;
ian@0 347 moxaDriver->type = TTY_DRIVER_TYPE_SERIAL;
ian@0 348 moxaDriver->subtype = SERIAL_TYPE_NORMAL;
ian@0 349 moxaDriver->init_termios = tty_std_termios;
ian@0 350 moxaDriver->init_termios.c_iflag = 0;
ian@0 351 moxaDriver->init_termios.c_oflag = 0;
ian@0 352 moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
ian@0 353 moxaDriver->init_termios.c_lflag = 0;
ian@0 354 moxaDriver->flags = TTY_DRIVER_REAL_RAW;
ian@0 355 tty_set_operations(moxaDriver, &moxa_ops);
ian@0 356
ian@0 357 moxaXmitBuff = NULL;
ian@0 358
ian@0 359 for (i = 0, ch = moxaChannels; i < MAX_PORTS; i++, ch++) {
ian@0 360 ch->type = PORT_16550A;
ian@0 361 ch->port = i;
ian@0 362 INIT_WORK(&ch->tqueue, do_moxa_softint, ch);
ian@0 363 ch->tty = NULL;
ian@0 364 ch->close_delay = 5 * HZ / 10;
ian@0 365 ch->closing_wait = 30 * HZ;
ian@0 366 ch->count = 0;
ian@0 367 ch->blocked_open = 0;
ian@0 368 ch->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
ian@0 369 init_waitqueue_head(&ch->open_wait);
ian@0 370 init_waitqueue_head(&ch->close_wait);
ian@0 371 }
ian@0 372
ian@0 373 for (i = 0; i < MAX_BOARDS; i++) {
ian@0 374 moxa_boards[i].boardType = 0;
ian@0 375 moxa_boards[i].numPorts = 0;
ian@0 376 moxa_boards[i].baseAddr = 0;
ian@0 377 moxa_boards[i].busType = 0;
ian@0 378 moxa_boards[i].pciInfo.busNum = 0;
ian@0 379 moxa_boards[i].pciInfo.devNum = 0;
ian@0 380 }
ian@0 381 MoxaDriverInit();
ian@0 382 printk("Tty devices major number = %d\n", ttymajor);
ian@0 383
ian@0 384 if (tty_register_driver(moxaDriver)) {
ian@0 385 printk(KERN_ERR "Couldn't install MOXA Smartio family driver !\n");
ian@0 386 put_tty_driver(moxaDriver);
ian@0 387 return -1;
ian@0 388 }
ian@0 389 for (i = 0; i < MAX_PORTS; i++) {
ian@0 390 init_timer(&moxaEmptyTimer[i]);
ian@0 391 moxaEmptyTimer[i].function = check_xmit_empty;
ian@0 392 moxaEmptyTimer[i].data = (unsigned long) & moxaChannels[i];
ian@0 393 moxaEmptyTimer_on[i] = 0;
ian@0 394 }
ian@0 395
ian@0 396 init_timer(&moxaTimer);
ian@0 397 moxaTimer.function = moxa_poll;
ian@0 398 moxaTimer.expires = jiffies + (HZ / 50);
ian@0 399 moxaTimer_on = 1;
ian@0 400 add_timer(&moxaTimer);
ian@0 401
ian@0 402 /* Find the boards defined in source code */
ian@0 403 numBoards = 0;
ian@0 404 for (i = 0; i < MAX_BOARDS; i++) {
ian@0 405 if ((moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA) ||
ian@0 406 (moxa_isa_boards[i].boardType == MOXA_BOARD_C320_ISA)) {
ian@0 407 moxa_boards[numBoards].boardType = moxa_isa_boards[i].boardType;
ian@0 408 if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA)
ian@0 409 moxa_boards[numBoards].numPorts = 8;
ian@0 410 else
ian@0 411 moxa_boards[numBoards].numPorts = moxa_isa_boards[i].numPorts;
ian@0 412 moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA;
ian@0 413 moxa_boards[numBoards].baseAddr = moxa_isa_boards[i].baseAddr;
ian@0 414 if (verbose)
ian@0 415 printk("Board %2d: %s board(baseAddr=%lx)\n",
ian@0 416 numBoards + 1,
ian@0 417 moxa_brdname[moxa_boards[numBoards].boardType - 1],
ian@0 418 moxa_boards[numBoards].baseAddr);
ian@0 419 numBoards++;
ian@0 420 }
ian@0 421 }
ian@0 422 /* Find the boards defined form module args. */
ian@0 423 #ifdef MODULE
ian@0 424 for (i = 0; i < MAX_BOARDS; i++) {
ian@0 425 if ((type[i] == MOXA_BOARD_C218_ISA) ||
ian@0 426 (type[i] == MOXA_BOARD_C320_ISA)) {
ian@0 427 if (verbose)
ian@0 428 printk("Board %2d: %s board(baseAddr=%lx)\n",
ian@0 429 numBoards + 1,
ian@0 430 moxa_brdname[type[i] - 1],
ian@0 431 (unsigned long) baseaddr[i]);
ian@0 432 if (numBoards >= MAX_BOARDS) {
ian@0 433 if (verbose)
ian@0 434 printk("More than %d MOXA Intellio family boards found. Board is ignored.", MAX_BOARDS);
ian@0 435 continue;
ian@0 436 }
ian@0 437 moxa_boards[numBoards].boardType = type[i];
ian@0 438 if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA)
ian@0 439 moxa_boards[numBoards].numPorts = 8;
ian@0 440 else
ian@0 441 moxa_boards[numBoards].numPorts = numports[i];
ian@0 442 moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA;
ian@0 443 moxa_boards[numBoards].baseAddr = baseaddr[i];
ian@0 444 numBoards++;
ian@0 445 }
ian@0 446 }
ian@0 447 #endif
ian@0 448 /* Find PCI boards here */
ian@0 449 #ifdef CONFIG_PCI
ian@0 450 {
ian@0 451 struct pci_dev *p = NULL;
ian@0 452 int n = ARRAY_SIZE(moxa_pcibrds) - 1;
ian@0 453 i = 0;
ian@0 454 while (i < n) {
ian@0 455 while ((p = pci_get_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL)
ian@0 456 {
ian@0 457 if (pci_enable_device(p))
ian@0 458 continue;
ian@0 459 if (numBoards >= MAX_BOARDS) {
ian@0 460 if (verbose)
ian@0 461 printk("More than %d MOXA Intellio family boards found. Board is ignored.", MAX_BOARDS);
ian@0 462 } else {
ian@0 463 moxa_get_PCI_conf(p, moxa_pcibrds[i].driver_data,
ian@0 464 &moxa_boards[numBoards]);
ian@0 465 numBoards++;
ian@0 466 }
ian@0 467 }
ian@0 468 i++;
ian@0 469 }
ian@0 470 }
ian@0 471 #endif
ian@0 472 for (i = 0; i < numBoards; i++) {
ian@0 473 moxaBaseAddr[i] = ioremap((unsigned long) moxa_boards[i].baseAddr, 0x4000);
ian@0 474 }
ian@0 475
ian@0 476 return (0);
ian@0 477 }
ian@0 478
ian@0 479 static void __exit moxa_exit(void)
ian@0 480 {
ian@0 481 int i;
ian@0 482
ian@0 483 if (verbose)
ian@0 484 printk("Unloading module moxa ...\n");
ian@0 485
ian@0 486 if (moxaTimer_on)
ian@0 487 del_timer(&moxaTimer);
ian@0 488
ian@0 489 for (i = 0; i < MAX_PORTS; i++)
ian@0 490 if (moxaEmptyTimer_on[i])
ian@0 491 del_timer(&moxaEmptyTimer[i]);
ian@0 492
ian@0 493 if (tty_unregister_driver(moxaDriver))
ian@0 494 printk("Couldn't unregister MOXA Intellio family serial driver\n");
ian@0 495 put_tty_driver(moxaDriver);
ian@0 496 if (verbose)
ian@0 497 printk("Done\n");
ian@0 498 }
ian@0 499
ian@0 500 module_init(moxa_init);
ian@0 501 module_exit(moxa_exit);
ian@0 502
ian@0 503 static void do_moxa_softint(void *private_)
ian@0 504 {
ian@0 505 struct moxa_str *ch = (struct moxa_str *) private_;
ian@0 506 struct tty_struct *tty;
ian@0 507
ian@0 508 if (ch && (tty = ch->tty)) {
ian@0 509 if (test_and_clear_bit(MOXA_EVENT_HANGUP, &ch->event)) {
ian@0 510 tty_hangup(tty); /* FIXME: module removal race here - AKPM */
ian@0 511 wake_up_interruptible(&ch->open_wait);
ian@0 512 ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
ian@0 513 }
ian@0 514 }
ian@0 515 }
ian@0 516
ian@0 517 static int moxa_open(struct tty_struct *tty, struct file *filp)
ian@0 518 {
ian@0 519 struct moxa_str *ch;
ian@0 520 int port;
ian@0 521 int retval;
ian@0 522 unsigned long page;
ian@0 523
ian@0 524 port = PORTNO(tty);
ian@0 525 if (port == MAX_PORTS) {
ian@0 526 return (0);
ian@0 527 }
ian@0 528 if (!MoxaPortIsValid(port)) {
ian@0 529 tty->driver_data = NULL;
ian@0 530 return (-ENODEV);
ian@0 531 }
ian@0 532 down(&moxaBuffSem);
ian@0 533 if (!moxaXmitBuff) {
ian@0 534 page = get_zeroed_page(GFP_KERNEL);
ian@0 535 if (!page) {
ian@0 536 up(&moxaBuffSem);
ian@0 537 return (-ENOMEM);
ian@0 538 }
ian@0 539 /* This test is guarded by the BuffSem so no longer needed
ian@0 540 delete me in 2.5 */
ian@0 541 if (moxaXmitBuff)
ian@0 542 free_page(page);
ian@0 543 else
ian@0 544 moxaXmitBuff = (unsigned char *) page;
ian@0 545 }
ian@0 546 up(&moxaBuffSem);
ian@0 547
ian@0 548 ch = &moxaChannels[port];
ian@0 549 ch->count++;
ian@0 550 tty->driver_data = ch;
ian@0 551 ch->tty = tty;
ian@0 552 if (!(ch->asyncflags & ASYNC_INITIALIZED)) {
ian@0 553 ch->statusflags = 0;
ian@0 554 set_tty_param(tty);
ian@0 555 MoxaPortLineCtrl(ch->port, 1, 1);
ian@0 556 MoxaPortEnable(ch->port);
ian@0 557 ch->asyncflags |= ASYNC_INITIALIZED;
ian@0 558 }
ian@0 559 retval = block_till_ready(tty, filp, ch);
ian@0 560
ian@0 561 moxa_unthrottle(tty);
ian@0 562
ian@0 563 if (ch->type == PORT_16550A) {
ian@0 564 MoxaSetFifo(ch->port, 1);
ian@0 565 } else {
ian@0 566 MoxaSetFifo(ch->port, 0);
ian@0 567 }
ian@0 568
ian@0 569 return (retval);
ian@0 570 }
ian@0 571
ian@0 572 static void moxa_close(struct tty_struct *tty, struct file *filp)
ian@0 573 {
ian@0 574 struct moxa_str *ch;
ian@0 575 int port;
ian@0 576
ian@0 577 port = PORTNO(tty);
ian@0 578 if (port == MAX_PORTS) {
ian@0 579 return;
ian@0 580 }
ian@0 581 if (!MoxaPortIsValid(port)) {
ian@0 582 #ifdef SERIAL_DEBUG_CLOSE
ian@0 583 printk("Invalid portno in moxa_close\n");
ian@0 584 #endif
ian@0 585 tty->driver_data = NULL;
ian@0 586 return;
ian@0 587 }
ian@0 588 if (tty->driver_data == NULL) {
ian@0 589 return;
ian@0 590 }
ian@0 591 if (tty_hung_up_p(filp)) {
ian@0 592 return;
ian@0 593 }
ian@0 594 ch = (struct moxa_str *) tty->driver_data;
ian@0 595
ian@0 596 if ((tty->count == 1) && (ch->count != 1)) {
ian@0 597 printk("moxa_close: bad serial port count; tty->count is 1, "
ian@0 598 "ch->count is %d\n", ch->count);
ian@0 599 ch->count = 1;
ian@0 600 }
ian@0 601 if (--ch->count < 0) {
ian@0 602 printk("moxa_close: bad serial port count, device=%s\n",
ian@0 603 tty->name);
ian@0 604 ch->count = 0;
ian@0 605 }
ian@0 606 if (ch->count) {
ian@0 607 return;
ian@0 608 }
ian@0 609 ch->asyncflags |= ASYNC_CLOSING;
ian@0 610
ian@0 611 ch->cflag = tty->termios->c_cflag;
ian@0 612 if (ch->asyncflags & ASYNC_INITIALIZED) {
ian@0 613 setup_empty_event(tty);
ian@0 614 tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */
ian@0 615 moxaEmptyTimer_on[ch->port] = 0;
ian@0 616 del_timer(&moxaEmptyTimer[ch->port]);
ian@0 617 }
ian@0 618 shut_down(ch);
ian@0 619 MoxaPortFlushData(port, 2);
ian@0 620
ian@0 621 if (tty->driver->flush_buffer)
ian@0 622 tty->driver->flush_buffer(tty);
ian@0 623 tty_ldisc_flush(tty);
ian@0 624
ian@0 625 tty->closing = 0;
ian@0 626 ch->event = 0;
ian@0 627 ch->tty = NULL;
ian@0 628 if (ch->blocked_open) {
ian@0 629 if (ch->close_delay) {
ian@0 630 msleep_interruptible(jiffies_to_msecs(ch->close_delay));
ian@0 631 }
ian@0 632 wake_up_interruptible(&ch->open_wait);
ian@0 633 }
ian@0 634 ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
ian@0 635 wake_up_interruptible(&ch->close_wait);
ian@0 636 }
ian@0 637
ian@0 638 static int moxa_write(struct tty_struct *tty,
ian@0 639 const unsigned char *buf, int count)
ian@0 640 {
ian@0 641 struct moxa_str *ch;
ian@0 642 int len, port;
ian@0 643 unsigned long flags;
ian@0 644
ian@0 645 ch = (struct moxa_str *) tty->driver_data;
ian@0 646 if (ch == NULL)
ian@0 647 return (0);
ian@0 648 port = ch->port;
ian@0 649
ian@0 650 spin_lock_irqsave(&moxa_lock, flags);
ian@0 651 len = MoxaPortWriteData(port, (unsigned char *) buf, count);
ian@0 652 spin_unlock_irqrestore(&moxa_lock, flags);
ian@0 653
ian@0 654 /*********************************************
ian@0 655 if ( !(ch->statusflags & LOWWAIT) &&
ian@0 656 ((len != count) || (MoxaPortTxFree(port) <= 100)) )
ian@0 657 ************************************************/
ian@0 658 ch->statusflags |= LOWWAIT;
ian@0 659 return (len);
ian@0 660 }
ian@0 661
ian@0 662 static int moxa_write_room(struct tty_struct *tty)
ian@0 663 {
ian@0 664 struct moxa_str *ch;
ian@0 665
ian@0 666 if (tty->stopped)
ian@0 667 return (0);
ian@0 668 ch = (struct moxa_str *) tty->driver_data;
ian@0 669 if (ch == NULL)
ian@0 670 return (0);
ian@0 671 return (MoxaPortTxFree(ch->port));
ian@0 672 }
ian@0 673
ian@0 674 static void moxa_flush_buffer(struct tty_struct *tty)
ian@0 675 {
ian@0 676 struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
ian@0 677
ian@0 678 if (ch == NULL)
ian@0 679 return;
ian@0 680 MoxaPortFlushData(ch->port, 1);
ian@0 681 tty_wakeup(tty);
ian@0 682 }
ian@0 683
ian@0 684 static int moxa_chars_in_buffer(struct tty_struct *tty)
ian@0 685 {
ian@0 686 int chars;
ian@0 687 struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
ian@0 688
ian@0 689 /*
ian@0 690 * Sigh...I have to check if driver_data is NULL here, because
ian@0 691 * if an open() fails, the TTY subsystem eventually calls
ian@0 692 * tty_wait_until_sent(), which calls the driver's chars_in_buffer()
ian@0 693 * routine. And since the open() failed, we return 0 here. TDJ
ian@0 694 */
ian@0 695 if (ch == NULL)
ian@0 696 return (0);
ian@0 697 chars = MoxaPortTxQueue(ch->port);
ian@0 698 if (chars) {
ian@0 699 /*
ian@0 700 * Make it possible to wakeup anything waiting for output
ian@0 701 * in tty_ioctl.c, etc.
ian@0 702 */
ian@0 703 if (!(ch->statusflags & EMPTYWAIT))
ian@0 704 setup_empty_event(tty);
ian@0 705 }
ian@0 706 return (chars);
ian@0 707 }
ian@0 708
ian@0 709 static void moxa_flush_chars(struct tty_struct *tty)
ian@0 710 {
ian@0 711 /*
ian@0 712 * Don't think I need this, because this is called to empty the TX
ian@0 713 * buffer for the 16450, 16550, etc.
ian@0 714 */
ian@0 715 }
ian@0 716
ian@0 717 static void moxa_put_char(struct tty_struct *tty, unsigned char c)
ian@0 718 {
ian@0 719 struct moxa_str *ch;
ian@0 720 int port;
ian@0 721 unsigned long flags;
ian@0 722
ian@0 723 ch = (struct moxa_str *) tty->driver_data;
ian@0 724 if (ch == NULL)
ian@0 725 return;
ian@0 726 port = ch->port;
ian@0 727 spin_lock_irqsave(&moxa_lock, flags);
ian@0 728 moxaXmitBuff[0] = c;
ian@0 729 MoxaPortWriteData(port, moxaXmitBuff, 1);
ian@0 730 spin_unlock_irqrestore(&moxa_lock, flags);
ian@0 731 /************************************************
ian@0 732 if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) )
ian@0 733 *************************************************/
ian@0 734 ch->statusflags |= LOWWAIT;
ian@0 735 }
ian@0 736
ian@0 737 static int moxa_tiocmget(struct tty_struct *tty, struct file *file)
ian@0 738 {
ian@0 739 struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
ian@0 740 int port;
ian@0 741 int flag = 0, dtr, rts;
ian@0 742
ian@0 743 port = PORTNO(tty);
ian@0 744 if ((port != MAX_PORTS) && (!ch))
ian@0 745 return (-EINVAL);
ian@0 746
ian@0 747 MoxaPortGetLineOut(ch->port, &dtr, &rts);
ian@0 748 if (dtr)
ian@0 749 flag |= TIOCM_DTR;
ian@0 750 if (rts)
ian@0 751 flag |= TIOCM_RTS;
ian@0 752 dtr = MoxaPortLineStatus(ch->port);
ian@0 753 if (dtr & 1)
ian@0 754 flag |= TIOCM_CTS;
ian@0 755 if (dtr & 2)
ian@0 756 flag |= TIOCM_DSR;
ian@0 757 if (dtr & 4)
ian@0 758 flag |= TIOCM_CD;
ian@0 759 return flag;
ian@0 760 }
ian@0 761
ian@0 762 static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
ian@0 763 unsigned int set, unsigned int clear)
ian@0 764 {
ian@0 765 struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
ian@0 766 int port;
ian@0 767 int dtr, rts;
ian@0 768
ian@0 769 port = PORTNO(tty);
ian@0 770 if ((port != MAX_PORTS) && (!ch))
ian@0 771 return (-EINVAL);
ian@0 772
ian@0 773 MoxaPortGetLineOut(ch->port, &dtr, &rts);
ian@0 774 if (set & TIOCM_RTS)
ian@0 775 rts = 1;
ian@0 776 if (set & TIOCM_DTR)
ian@0 777 dtr = 1;
ian@0 778 if (clear & TIOCM_RTS)
ian@0 779 rts = 0;
ian@0 780 if (clear & TIOCM_DTR)
ian@0 781 dtr = 0;
ian@0 782 MoxaPortLineCtrl(ch->port, dtr, rts);
ian@0 783 return 0;
ian@0 784 }
ian@0 785
ian@0 786 static int moxa_ioctl(struct tty_struct *tty, struct file *file,
ian@0 787 unsigned int cmd, unsigned long arg)
ian@0 788 {
ian@0 789 struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
ian@0 790 register int port;
ian@0 791 void __user *argp = (void __user *)arg;
ian@0 792 int retval;
ian@0 793
ian@0 794 port = PORTNO(tty);
ian@0 795 if ((port != MAX_PORTS) && (!ch))
ian@0 796 return (-EINVAL);
ian@0 797
ian@0 798 switch (cmd) {
ian@0 799 case TCSBRK: /* SVID version: non-zero arg --> no break */
ian@0 800 retval = tty_check_change(tty);
ian@0 801 if (retval)
ian@0 802 return (retval);
ian@0 803 setup_empty_event(tty);
ian@0 804 tty_wait_until_sent(tty, 0);
ian@0 805 if (!arg)
ian@0 806 MoxaPortSendBreak(ch->port, 0);
ian@0 807 return (0);
ian@0 808 case TCSBRKP: /* support for POSIX tcsendbreak() */
ian@0 809 retval = tty_check_change(tty);
ian@0 810 if (retval)
ian@0 811 return (retval);
ian@0 812 setup_empty_event(tty);
ian@0 813 tty_wait_until_sent(tty, 0);
ian@0 814 MoxaPortSendBreak(ch->port, arg);
ian@0 815 return (0);
ian@0 816 case TIOCGSOFTCAR:
ian@0 817 return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) argp);
ian@0 818 case TIOCSSOFTCAR:
ian@0 819 if(get_user(retval, (unsigned long __user *) argp))
ian@0 820 return -EFAULT;
ian@0 821 arg = retval;
ian@0 822 tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |
ian@0 823 (arg ? CLOCAL : 0));
ian@0 824 if (C_CLOCAL(tty))
ian@0 825 ch->asyncflags &= ~ASYNC_CHECK_CD;
ian@0 826 else
ian@0 827 ch->asyncflags |= ASYNC_CHECK_CD;
ian@0 828 return (0);
ian@0 829 case TIOCGSERIAL:
ian@0 830 return moxa_get_serial_info(ch, argp);
ian@0 831
ian@0 832 case TIOCSSERIAL:
ian@0 833 return moxa_set_serial_info(ch, argp);
ian@0 834 default:
ian@0 835 retval = MoxaDriverIoctl(cmd, arg, port);
ian@0 836 }
ian@0 837 return (retval);
ian@0 838 }
ian@0 839
ian@0 840 static void moxa_throttle(struct tty_struct *tty)
ian@0 841 {
ian@0 842 struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
ian@0 843
ian@0 844 ch->statusflags |= THROTTLE;
ian@0 845 }
ian@0 846
ian@0 847 static void moxa_unthrottle(struct tty_struct *tty)
ian@0 848 {
ian@0 849 struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
ian@0 850
ian@0 851 ch->statusflags &= ~THROTTLE;
ian@0 852 }
ian@0 853
ian@0 854 static void moxa_set_termios(struct tty_struct *tty,
ian@0 855 struct termios *old_termios)
ian@0 856 {
ian@0 857 struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
ian@0 858
ian@0 859 if (ch == NULL)
ian@0 860 return;
ian@0 861 set_tty_param(tty);
ian@0 862 if (!(old_termios->c_cflag & CLOCAL) &&
ian@0 863 (tty->termios->c_cflag & CLOCAL))
ian@0 864 wake_up_interruptible(&ch->open_wait);
ian@0 865 }
ian@0 866
ian@0 867 static void moxa_stop(struct tty_struct *tty)
ian@0 868 {
ian@0 869 struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
ian@0 870
ian@0 871 if (ch == NULL)
ian@0 872 return;
ian@0 873 MoxaPortTxDisable(ch->port);
ian@0 874 ch->statusflags |= TXSTOPPED;
ian@0 875 }
ian@0 876
ian@0 877
ian@0 878 static void moxa_start(struct tty_struct *tty)
ian@0 879 {
ian@0 880 struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
ian@0 881
ian@0 882 if (ch == NULL)
ian@0 883 return;
ian@0 884
ian@0 885 if (!(ch->statusflags & TXSTOPPED))
ian@0 886 return;
ian@0 887
ian@0 888 MoxaPortTxEnable(ch->port);
ian@0 889 ch->statusflags &= ~TXSTOPPED;
ian@0 890 }
ian@0 891
ian@0 892 static void moxa_hangup(struct tty_struct *tty)
ian@0 893 {
ian@0 894 struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
ian@0 895
ian@0 896 moxa_flush_buffer(tty);
ian@0 897 shut_down(ch);
ian@0 898 ch->event = 0;
ian@0 899 ch->count = 0;
ian@0 900 ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
ian@0 901 ch->tty = NULL;
ian@0 902 wake_up_interruptible(&ch->open_wait);
ian@0 903 }
ian@0 904
ian@0 905 static void moxa_poll(unsigned long ignored)
ian@0 906 {
ian@0 907 register int card;
ian@0 908 struct moxa_str *ch;
ian@0 909 struct tty_struct *tp;
ian@0 910 int i, ports;
ian@0 911
ian@0 912 moxaTimer_on = 0;
ian@0 913 del_timer(&moxaTimer);
ian@0 914
ian@0 915 if (MoxaDriverPoll() < 0) {
ian@0 916 moxaTimer.function = moxa_poll;
ian@0 917 moxaTimer.expires = jiffies + (HZ / 50);
ian@0 918 moxaTimer_on = 1;
ian@0 919 add_timer(&moxaTimer);
ian@0 920 return;
ian@0 921 }
ian@0 922 for (card = 0; card < MAX_BOARDS; card++) {
ian@0 923 if ((ports = MoxaPortsOfCard(card)) <= 0)
ian@0 924 continue;
ian@0 925 ch = &moxaChannels[card * MAX_PORTS_PER_BOARD];
ian@0 926 for (i = 0; i < ports; i++, ch++) {
ian@0 927 if ((ch->asyncflags & ASYNC_INITIALIZED) == 0)
ian@0 928 continue;
ian@0 929 if (!(ch->statusflags & THROTTLE) &&
ian@0 930 (MoxaPortRxQueue(ch->port) > 0))
ian@0 931 receive_data(ch);
ian@0 932 if ((tp = ch->tty) == 0)
ian@0 933 continue;
ian@0 934 if (ch->statusflags & LOWWAIT) {
ian@0 935 if (MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS) {
ian@0 936 if (!tp->stopped) {
ian@0 937 ch->statusflags &= ~LOWWAIT;
ian@0 938 tty_wakeup(tp);
ian@0 939 }
ian@0 940 }
ian@0 941 }
ian@0 942 if (!I_IGNBRK(tp) && (MoxaPortResetBrkCnt(ch->port) > 0)) {
ian@0 943 tty_insert_flip_char(tp, 0, TTY_BREAK);
ian@0 944 tty_schedule_flip(tp);
ian@0 945 }
ian@0 946 if (MoxaPortDCDChange(ch->port)) {
ian@0 947 if (ch->asyncflags & ASYNC_CHECK_CD) {
ian@0 948 if (MoxaPortDCDON(ch->port))
ian@0 949 wake_up_interruptible(&ch->open_wait);
ian@0 950 else {
ian@0 951 set_bit(MOXA_EVENT_HANGUP, &ch->event);
ian@0 952 schedule_work(&ch->tqueue);
ian@0 953 }
ian@0 954 }
ian@0 955 }
ian@0 956 }
ian@0 957 }
ian@0 958
ian@0 959 moxaTimer.function = moxa_poll;
ian@0 960 moxaTimer.expires = jiffies + (HZ / 50);
ian@0 961 moxaTimer_on = 1;
ian@0 962 add_timer(&moxaTimer);
ian@0 963 }
ian@0 964
ian@0 965 /******************************************************************************/
ian@0 966
ian@0 967 static void set_tty_param(struct tty_struct *tty)
ian@0 968 {
ian@0 969 register struct termios *ts;
ian@0 970 struct moxa_str *ch;
ian@0 971 int rts, cts, txflow, rxflow, xany;
ian@0 972
ian@0 973 ch = (struct moxa_str *) tty->driver_data;
ian@0 974 ts = tty->termios;
ian@0 975 if (ts->c_cflag & CLOCAL)
ian@0 976 ch->asyncflags &= ~ASYNC_CHECK_CD;
ian@0 977 else
ian@0 978 ch->asyncflags |= ASYNC_CHECK_CD;
ian@0 979 rts = cts = txflow = rxflow = xany = 0;
ian@0 980 if (ts->c_cflag & CRTSCTS)
ian@0 981 rts = cts = 1;
ian@0 982 if (ts->c_iflag & IXON)
ian@0 983 txflow = 1;
ian@0 984 if (ts->c_iflag & IXOFF)
ian@0 985 rxflow = 1;
ian@0 986 if (ts->c_iflag & IXANY)
ian@0 987 xany = 1;
ian@0 988 MoxaPortFlowCtrl(ch->port, rts, cts, txflow, rxflow, xany);
ian@0 989 MoxaPortSetTermio(ch->port, ts);
ian@0 990 }
ian@0 991
ian@0 992 static int block_till_ready(struct tty_struct *tty, struct file *filp,
ian@0 993 struct moxa_str *ch)
ian@0 994 {
ian@0 995 DECLARE_WAITQUEUE(wait,current);
ian@0 996 unsigned long flags;
ian@0 997 int retval;
ian@0 998 int do_clocal = C_CLOCAL(tty);
ian@0 999
ian@0 1000 /*
ian@0 1001 * If the device is in the middle of being closed, then block
ian@0 1002 * until it's done, and then try again.
ian@0 1003 */
ian@0 1004 if (tty_hung_up_p(filp) || (ch->asyncflags & ASYNC_CLOSING)) {
ian@0 1005 if (ch->asyncflags & ASYNC_CLOSING)
ian@0 1006 interruptible_sleep_on(&ch->close_wait);
ian@0 1007 #ifdef SERIAL_DO_RESTART
ian@0 1008 if (ch->asyncflags & ASYNC_HUP_NOTIFY)
ian@0 1009 return (-EAGAIN);
ian@0 1010 else
ian@0 1011 return (-ERESTARTSYS);
ian@0 1012 #else
ian@0 1013 return (-EAGAIN);
ian@0 1014 #endif
ian@0 1015 }
ian@0 1016 /*
ian@0 1017 * If non-blocking mode is set, then make the check up front
ian@0 1018 * and then exit.
ian@0 1019 */
ian@0 1020 if (filp->f_flags & O_NONBLOCK) {
ian@0 1021 ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
ian@0 1022 return (0);
ian@0 1023 }
ian@0 1024 /*
ian@0 1025 * Block waiting for the carrier detect and the line to become free
ian@0 1026 */
ian@0 1027 retval = 0;
ian@0 1028 add_wait_queue(&ch->open_wait, &wait);
ian@0 1029 #ifdef SERIAL_DEBUG_OPEN
ian@0 1030 printk("block_til_ready before block: ttys%d, count = %d\n",
ian@0 1031 ch->line, ch->count);
ian@0 1032 #endif
ian@0 1033 spin_lock_irqsave(&moxa_lock, flags);
ian@0 1034 if (!tty_hung_up_p(filp))
ian@0 1035 ch->count--;
ian@0 1036 ch->blocked_open++;
ian@0 1037 spin_unlock_irqrestore(&moxa_lock, flags);
ian@0 1038
ian@0 1039 while (1) {
ian@0 1040 set_current_state(TASK_INTERRUPTIBLE);
ian@0 1041 if (tty_hung_up_p(filp) ||
ian@0 1042 !(ch->asyncflags & ASYNC_INITIALIZED)) {
ian@0 1043 #ifdef SERIAL_DO_RESTART
ian@0 1044 if (ch->asyncflags & ASYNC_HUP_NOTIFY)
ian@0 1045 retval = -EAGAIN;
ian@0 1046 else
ian@0 1047 retval = -ERESTARTSYS;
ian@0 1048 #else
ian@0 1049 retval = -EAGAIN;
ian@0 1050 #endif
ian@0 1051 break;
ian@0 1052 }
ian@0 1053 if (!(ch->asyncflags & ASYNC_CLOSING) && (do_clocal ||
ian@0 1054 MoxaPortDCDON(ch->port)))
ian@0 1055 break;
ian@0 1056
ian@0 1057 if (signal_pending(current)) {
ian@0 1058 retval = -ERESTARTSYS;
ian@0 1059 break;
ian@0 1060 }
ian@0 1061 schedule();
ian@0 1062 }
ian@0 1063 set_current_state(TASK_RUNNING);
ian@0 1064 remove_wait_queue(&ch->open_wait, &wait);
ian@0 1065
ian@0 1066 spin_lock_irqsave(&moxa_lock, flags);
ian@0 1067 if (!tty_hung_up_p(filp))
ian@0 1068 ch->count++;
ian@0 1069 ch->blocked_open--;
ian@0 1070 spin_unlock_irqrestore(&moxa_lock, flags);
ian@0 1071 #ifdef SERIAL_DEBUG_OPEN
ian@0 1072 printk("block_til_ready after blocking: ttys%d, count = %d\n",
ian@0 1073 ch->line, ch->count);
ian@0 1074 #endif
ian@0 1075 if (retval)
ian@0 1076 return (retval);
ian@0 1077 /* FIXME: review to see if we need to use set_bit on these */
ian@0 1078 ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
ian@0 1079 return 0;
ian@0 1080 }
ian@0 1081
ian@0 1082 static void setup_empty_event(struct tty_struct *tty)
ian@0 1083 {
ian@0 1084 struct moxa_str *ch = tty->driver_data;
ian@0 1085 unsigned long flags;
ian@0 1086
ian@0 1087 spin_lock_irqsave(&moxa_lock, flags);
ian@0 1088 ch->statusflags |= EMPTYWAIT;
ian@0 1089 moxaEmptyTimer_on[ch->port] = 0;
ian@0 1090 del_timer(&moxaEmptyTimer[ch->port]);
ian@0 1091 moxaEmptyTimer[ch->port].expires = jiffies + HZ;
ian@0 1092 moxaEmptyTimer_on[ch->port] = 1;
ian@0 1093 add_timer(&moxaEmptyTimer[ch->port]);
ian@0 1094 spin_unlock_irqrestore(&moxa_lock, flags);
ian@0 1095 }
ian@0 1096
ian@0 1097 static void check_xmit_empty(unsigned long data)
ian@0 1098 {
ian@0 1099 struct moxa_str *ch;
ian@0 1100
ian@0 1101 ch = (struct moxa_str *) data;
ian@0 1102 moxaEmptyTimer_on[ch->port] = 0;
ian@0 1103 del_timer(&moxaEmptyTimer[ch->port]);
ian@0 1104 if (ch->tty && (ch->statusflags & EMPTYWAIT)) {
ian@0 1105 if (MoxaPortTxQueue(ch->port) == 0) {
ian@0 1106 ch->statusflags &= ~EMPTYWAIT;
ian@0 1107 tty_wakeup(ch->tty);
ian@0 1108 return;
ian@0 1109 }
ian@0 1110 moxaEmptyTimer[ch->port].expires = jiffies + HZ;
ian@0 1111 moxaEmptyTimer_on[ch->port] = 1;
ian@0 1112 add_timer(&moxaEmptyTimer[ch->port]);
ian@0 1113 } else
ian@0 1114 ch->statusflags &= ~EMPTYWAIT;
ian@0 1115 }
ian@0 1116
ian@0 1117 static void shut_down(struct moxa_str *ch)
ian@0 1118 {
ian@0 1119 struct tty_struct *tp;
ian@0 1120
ian@0 1121 if (!(ch->asyncflags & ASYNC_INITIALIZED))
ian@0 1122 return;
ian@0 1123
ian@0 1124 tp = ch->tty;
ian@0 1125
ian@0 1126 MoxaPortDisable(ch->port);
ian@0 1127
ian@0 1128 /*
ian@0 1129 * If we're a modem control device and HUPCL is on, drop RTS & DTR.
ian@0 1130 */
ian@0 1131 if (tp->termios->c_cflag & HUPCL)
ian@0 1132 MoxaPortLineCtrl(ch->port, 0, 0);
ian@0 1133
ian@0 1134 ch->asyncflags &= ~ASYNC_INITIALIZED;
ian@0 1135 }
ian@0 1136
ian@0 1137 static void receive_data(struct moxa_str *ch)
ian@0 1138 {
ian@0 1139 struct tty_struct *tp;
ian@0 1140 struct termios *ts;
ian@0 1141 unsigned long flags;
ian@0 1142
ian@0 1143 ts = NULL;
ian@0 1144 tp = ch->tty;
ian@0 1145 if (tp)
ian@0 1146 ts = tp->termios;
ian@0 1147 /**************************************************
ian@0 1148 if ( !tp || !ts || !(ts->c_cflag & CREAD) ) {
ian@0 1149 *****************************************************/
ian@0 1150 if (!tp || !ts) {
ian@0 1151 MoxaPortFlushData(ch->port, 0);
ian@0 1152 return;
ian@0 1153 }
ian@0 1154 spin_lock_irqsave(&moxa_lock, flags);
ian@0 1155 MoxaPortReadData(ch->port, tp);
ian@0 1156 spin_unlock_irqrestore(&moxa_lock, flags);
ian@0 1157 tty_schedule_flip(tp);
ian@0 1158 }
ian@0 1159
ian@0 1160 #define Magic_code 0x404
ian@0 1161
ian@0 1162 /*
ian@0 1163 * System Configuration
ian@0 1164 */
ian@0 1165 /*
ian@0 1166 * for C218 BIOS initialization
ian@0 1167 */
ian@0 1168 #define C218_ConfBase 0x800
ian@0 1169 #define C218_status (C218_ConfBase + 0) /* BIOS running status */
ian@0 1170 #define C218_diag (C218_ConfBase + 2) /* diagnostic status */
ian@0 1171 #define C218_key (C218_ConfBase + 4) /* WORD (0x218 for C218) */
ian@0 1172 #define C218DLoad_len (C218_ConfBase + 6) /* WORD */
ian@0 1173 #define C218check_sum (C218_ConfBase + 8) /* BYTE */
ian@0 1174 #define C218chksum_ok (C218_ConfBase + 0x0a) /* BYTE (1:ok) */
ian@0 1175 #define C218_TestRx (C218_ConfBase + 0x10) /* 8 bytes for 8 ports */
ian@0 1176 #define C218_TestTx (C218_ConfBase + 0x18) /* 8 bytes for 8 ports */
ian@0 1177 #define C218_RXerr (C218_ConfBase + 0x20) /* 8 bytes for 8 ports */
ian@0 1178 #define C218_ErrFlag (C218_ConfBase + 0x28) /* 8 bytes for 8 ports */
ian@0 1179
ian@0 1180 #define C218_LoadBuf 0x0F00
ian@0 1181 #define C218_KeyCode 0x218
ian@0 1182 #define CP204J_KeyCode 0x204
ian@0 1183
ian@0 1184 /*
ian@0 1185 * for C320 BIOS initialization
ian@0 1186 */
ian@0 1187 #define C320_ConfBase 0x800
ian@0 1188 #define C320_LoadBuf 0x0f00
ian@0 1189 #define STS_init 0x05 /* for C320_status */
ian@0 1190
ian@0 1191 #define C320_status C320_ConfBase + 0 /* BIOS running status */
ian@0 1192 #define C320_diag C320_ConfBase + 2 /* diagnostic status */
ian@0 1193 #define C320_key C320_ConfBase + 4 /* WORD (0320H for C320) */
ian@0 1194 #define C320DLoad_len C320_ConfBase + 6 /* WORD */
ian@0 1195 #define C320check_sum C320_ConfBase + 8 /* WORD */
ian@0 1196 #define C320chksum_ok C320_ConfBase + 0x0a /* WORD (1:ok) */
ian@0 1197 #define C320bapi_len C320_ConfBase + 0x0c /* WORD */
ian@0 1198 #define C320UART_no C320_ConfBase + 0x0e /* WORD */
ian@0 1199
ian@0 1200 #define C320_KeyCode 0x320
ian@0 1201
ian@0 1202 #define FixPage_addr 0x0000 /* starting addr of static page */
ian@0 1203 #define DynPage_addr 0x2000 /* starting addr of dynamic page */
ian@0 1204 #define C218_start 0x3000 /* starting addr of C218 BIOS prg */
ian@0 1205 #define Control_reg 0x1ff0 /* select page and reset control */
ian@0 1206 #define HW_reset 0x80
ian@0 1207
ian@0 1208 /*
ian@0 1209 * Function Codes
ian@0 1210 */
ian@0 1211 #define FC_CardReset 0x80
ian@0 1212 #define FC_ChannelReset 1 /* C320 firmware not supported */
ian@0 1213 #define FC_EnableCH 2
ian@0 1214 #define FC_DisableCH 3
ian@0 1215 #define FC_SetParam 4
ian@0 1216 #define FC_SetMode 5
ian@0 1217 #define FC_SetRate 6
ian@0 1218 #define FC_LineControl 7
ian@0 1219 #define FC_LineStatus 8
ian@0 1220 #define FC_XmitControl 9
ian@0 1221 #define FC_FlushQueue 10
ian@0 1222 #define FC_SendBreak 11
ian@0 1223 #define FC_StopBreak 12
ian@0 1224 #define FC_LoopbackON 13
ian@0 1225 #define FC_LoopbackOFF 14
ian@0 1226 #define FC_ClrIrqTable 15
ian@0 1227 #define FC_SendXon 16
ian@0 1228 #define FC_SetTermIrq 17 /* C320 firmware not supported */
ian@0 1229 #define FC_SetCntIrq 18 /* C320 firmware not supported */
ian@0 1230 #define FC_SetBreakIrq 19
ian@0 1231 #define FC_SetLineIrq 20
ian@0 1232 #define FC_SetFlowCtl 21
ian@0 1233 #define FC_GenIrq 22
ian@0 1234 #define FC_InCD180 23
ian@0 1235 #define FC_OutCD180 24
ian@0 1236 #define FC_InUARTreg 23
ian@0 1237 #define FC_OutUARTreg 24
ian@0 1238 #define FC_SetXonXoff 25
ian@0 1239 #define FC_OutCD180CCR 26
ian@0 1240 #define FC_ExtIQueue 27
ian@0 1241 #define FC_ExtOQueue 28
ian@0 1242 #define FC_ClrLineIrq 29
ian@0 1243 #define FC_HWFlowCtl 30
ian@0 1244 #define FC_GetClockRate 35
ian@0 1245 #define FC_SetBaud 36
ian@0 1246 #define FC_SetDataMode 41
ian@0 1247 #define FC_GetCCSR 43
ian@0 1248 #define FC_GetDataError 45
ian@0 1249 #define FC_RxControl 50
ian@0 1250 #define FC_ImmSend 51
ian@0 1251 #define FC_SetXonState 52
ian@0 1252 #define FC_SetXoffState 53
ian@0 1253 #define FC_SetRxFIFOTrig 54
ian@0 1254 #define FC_SetTxFIFOCnt 55
ian@0 1255 #define FC_UnixRate 56
ian@0 1256 #define FC_UnixResetTimer 57
ian@0 1257
ian@0 1258 #define RxFIFOTrig1 0
ian@0 1259 #define RxFIFOTrig4 1
ian@0 1260 #define RxFIFOTrig8 2
ian@0 1261 #define RxFIFOTrig14 3
ian@0 1262
ian@0 1263 /*
ian@0 1264 * Dual-Ported RAM
ian@0 1265 */
ian@0 1266 #define DRAM_global 0
ian@0 1267 #define INT_data (DRAM_global + 0)
ian@0 1268 #define Config_base (DRAM_global + 0x108)
ian@0 1269
ian@0 1270 #define IRQindex (INT_data + 0)
ian@0 1271 #define IRQpending (INT_data + 4)
ian@0 1272 #define IRQtable (INT_data + 8)
ian@0 1273
ian@0 1274 /*
ian@0 1275 * Interrupt Status
ian@0 1276 */
ian@0 1277 #define IntrRx 0x01 /* receiver data O.K. */
ian@0 1278 #define IntrTx 0x02 /* transmit buffer empty */
ian@0 1279 #define IntrFunc 0x04 /* function complete */
ian@0 1280 #define IntrBreak 0x08 /* received break */
ian@0 1281 #define IntrLine 0x10 /* line status change
ian@0 1282 for transmitter */
ian@0 1283 #define IntrIntr 0x20 /* received INTR code */
ian@0 1284 #define IntrQuit 0x40 /* received QUIT code */
ian@0 1285 #define IntrEOF 0x80 /* received EOF code */
ian@0 1286
ian@0 1287 #define IntrRxTrigger 0x100 /* rx data count reach tigger value */
ian@0 1288 #define IntrTxTrigger 0x200 /* tx data count below trigger value */
ian@0 1289
ian@0 1290 #define Magic_no (Config_base + 0)
ian@0 1291 #define Card_model_no (Config_base + 2)
ian@0 1292 #define Total_ports (Config_base + 4)
ian@0 1293 #define Module_cnt (Config_base + 8)
ian@0 1294 #define Module_no (Config_base + 10)
ian@0 1295 #define Timer_10ms (Config_base + 14)
ian@0 1296 #define Disable_IRQ (Config_base + 20)
ian@0 1297 #define TMS320_PORT1 (Config_base + 22)
ian@0 1298 #define TMS320_PORT2 (Config_base + 24)
ian@0 1299 #define TMS320_CLOCK (Config_base + 26)
ian@0 1300
ian@0 1301 /*
ian@0 1302 * DATA BUFFER in DRAM
ian@0 1303 */
ian@0 1304 #define Extern_table 0x400 /* Base address of the external table
ian@0 1305 (24 words * 64) total 3K bytes
ian@0 1306 (24 words * 128) total 6K bytes */
ian@0 1307 #define Extern_size 0x60 /* 96 bytes */
ian@0 1308 #define RXrptr 0x00 /* read pointer for RX buffer */
ian@0 1309 #define RXwptr 0x02 /* write pointer for RX buffer */
ian@0 1310 #define TXrptr 0x04 /* read pointer for TX buffer */
ian@0 1311 #define TXwptr 0x06 /* write pointer for TX buffer */
ian@0 1312 #define HostStat 0x08 /* IRQ flag and general flag */
ian@0 1313 #define FlagStat 0x0A
ian@0 1314 #define FlowControl 0x0C /* B7 B6 B5 B4 B3 B2 B1 B0 */
ian@0 1315 /* x x x x | | | | */
ian@0 1316 /* | | | + CTS flow */
ian@0 1317 /* | | +--- RTS flow */
ian@0 1318 /* | +------ TX Xon/Xoff */
ian@0 1319 /* +--------- RX Xon/Xoff */
ian@0 1320 #define Break_cnt 0x0E /* received break count */
ian@0 1321 #define CD180TXirq 0x10 /* if non-0: enable TX irq */
ian@0 1322 #define RX_mask 0x12
ian@0 1323 #define TX_mask 0x14
ian@0 1324 #define Ofs_rxb 0x16
ian@0 1325 #define Ofs_txb 0x18
ian@0 1326 #define Page_rxb 0x1A
ian@0 1327 #define Page_txb 0x1C
ian@0 1328 #define EndPage_rxb 0x1E
ian@0 1329 #define EndPage_txb 0x20
ian@0 1330 #define Data_error 0x22
ian@0 1331 #define RxTrigger 0x28
ian@0 1332 #define TxTrigger 0x2a
ian@0 1333
ian@0 1334 #define rRXwptr 0x34
ian@0 1335 #define Low_water 0x36
ian@0 1336
ian@0 1337 #define FuncCode 0x40
ian@0 1338 #define FuncArg 0x42
ian@0 1339 #define FuncArg1 0x44
ian@0 1340
ian@0 1341 #define C218rx_size 0x2000 /* 8K bytes */
ian@0 1342 #define C218tx_size 0x8000 /* 32K bytes */
ian@0 1343
ian@0 1344 #define C218rx_mask (C218rx_size - 1)
ian@0 1345 #define C218tx_mask (C218tx_size - 1)
ian@0 1346
ian@0 1347 #define C320p8rx_size 0x2000
ian@0 1348 #define C320p8tx_size 0x8000
ian@0 1349 #define C320p8rx_mask (C320p8rx_size - 1)
ian@0 1350 #define C320p8tx_mask (C320p8tx_size - 1)
ian@0 1351
ian@0 1352 #define C320p16rx_size 0x2000
ian@0 1353 #define C320p16tx_size 0x4000
ian@0 1354 #define C320p16rx_mask (C320p16rx_size - 1)
ian@0 1355 #define C320p16tx_mask (C320p16tx_size - 1)
ian@0 1356
ian@0 1357 #define C320p24rx_size 0x2000
ian@0 1358 #define C320p24tx_size 0x2000
ian@0 1359 #define C320p24rx_mask (C320p24rx_size - 1)
ian@0 1360 #define C320p24tx_mask (C320p24tx_size - 1)
ian@0 1361
ian@0 1362 #define C320p32rx_size 0x1000
ian@0 1363 #define C320p32tx_size 0x1000
ian@0 1364 #define C320p32rx_mask (C320p32rx_size - 1)
ian@0 1365 #define C320p32tx_mask (C320p32tx_size - 1)
ian@0 1366
ian@0 1367 #define Page_size 0x2000
ian@0 1368 #define Page_mask (Page_size - 1)
ian@0 1369 #define C218rx_spage 3
ian@0 1370 #define C218tx_spage 4
ian@0 1371 #define C218rx_pageno 1
ian@0 1372 #define C218tx_pageno 4
ian@0 1373 #define C218buf_pageno 5
ian@0 1374
ian@0 1375 #define C320p8rx_spage 3
ian@0 1376 #define C320p8tx_spage 4
ian@0 1377 #define C320p8rx_pgno 1
ian@0 1378 #define C320p8tx_pgno 4
ian@0 1379 #define C320p8buf_pgno 5
ian@0 1380
ian@0 1381 #define C320p16rx_spage 3
ian@0 1382 #define C320p16tx_spage 4
ian@0 1383 #define C320p16rx_pgno 1
ian@0 1384 #define C320p16tx_pgno 2
ian@0 1385 #define C320p16buf_pgno 3
ian@0 1386
ian@0 1387 #define C320p24rx_spage 3
ian@0 1388 #define C320p24tx_spage 4
ian@0 1389 #define C320p24rx_pgno 1
ian@0 1390 #define C320p24tx_pgno 1
ian@0 1391 #define C320p24buf_pgno 2
ian@0 1392
ian@0 1393 #define C320p32rx_spage 3
ian@0 1394 #define C320p32tx_ofs C320p32rx_size
ian@0 1395 #define C320p32tx_spage 3
ian@0 1396 #define C320p32buf_pgno 1
ian@0 1397
ian@0 1398 /*
ian@0 1399 * Host Status
ian@0 1400 */
ian@0 1401 #define WakeupRx 0x01
ian@0 1402 #define WakeupTx 0x02
ian@0 1403 #define WakeupBreak 0x08
ian@0 1404 #define WakeupLine 0x10
ian@0 1405 #define WakeupIntr 0x20
ian@0 1406 #define WakeupQuit 0x40
ian@0 1407 #define WakeupEOF 0x80 /* used in VTIME control */
ian@0 1408 #define WakeupRxTrigger 0x100
ian@0 1409 #define WakeupTxTrigger 0x200
ian@0 1410 /*
ian@0 1411 * Flag status
ian@0 1412 */
ian@0 1413 #define Rx_over 0x01
ian@0 1414 #define Xoff_state 0x02
ian@0 1415 #define Tx_flowOff 0x04
ian@0 1416 #define Tx_enable 0x08
ian@0 1417 #define CTS_state 0x10
ian@0 1418 #define DSR_state 0x20
ian@0 1419 #define DCD_state 0x80
ian@0 1420 /*
ian@0 1421 * FlowControl
ian@0 1422 */
ian@0 1423 #define CTS_FlowCtl 1
ian@0 1424 #define RTS_FlowCtl 2
ian@0 1425 #define Tx_FlowCtl 4
ian@0 1426 #define Rx_FlowCtl 8
ian@0 1427 #define IXM_IXANY 0x10
ian@0 1428
ian@0 1429 #define LowWater 128
ian@0 1430
ian@0 1431 #define DTR_ON 1
ian@0 1432 #define RTS_ON 2
ian@0 1433 #define CTS_ON 1
ian@0 1434 #define DSR_ON 2
ian@0 1435 #define DCD_ON 8
ian@0 1436
ian@0 1437 /* mode definition */
ian@0 1438 #define MX_CS8 0x03
ian@0 1439 #define MX_CS7 0x02
ian@0 1440 #define MX_CS6 0x01
ian@0 1441 #define MX_CS5 0x00
ian@0 1442
ian@0 1443 #define MX_STOP1 0x00
ian@0 1444 #define MX_STOP15 0x04
ian@0 1445 #define MX_STOP2 0x08
ian@0 1446
ian@0 1447 #define MX_PARNONE 0x00
ian@0 1448 #define MX_PAREVEN 0x40
ian@0 1449 #define MX_PARODD 0xC0
ian@0 1450
ian@0 1451 /*
ian@0 1452 * Query
ian@0 1453 */
ian@0 1454 #define QueryPort MAX_PORTS
ian@0 1455
ian@0 1456
ian@0 1457
ian@0 1458 struct mon_str {
ian@0 1459 int tick;
ian@0 1460 int rxcnt[MAX_PORTS];
ian@0 1461 int txcnt[MAX_PORTS];
ian@0 1462 };
ian@0 1463 typedef struct mon_str mon_st;
ian@0 1464
ian@0 1465 #define DCD_changed 0x01
ian@0 1466 #define DCD_oldstate 0x80
ian@0 1467
ian@0 1468 static unsigned char moxaBuff[10240];
ian@0 1469 static void __iomem *moxaIntNdx[MAX_BOARDS];
ian@0 1470 static void __iomem *moxaIntPend[MAX_BOARDS];
ian@0 1471 static void __iomem *moxaIntTable[MAX_BOARDS];
ian@0 1472 static char moxaChkPort[MAX_PORTS];
ian@0 1473 static char moxaLineCtrl[MAX_PORTS];
ian@0 1474 static void __iomem *moxaTableAddr[MAX_PORTS];
ian@0 1475 static long moxaCurBaud[MAX_PORTS];
ian@0 1476 static char moxaDCDState[MAX_PORTS];
ian@0 1477 static char moxaLowChkFlag[MAX_PORTS];
ian@0 1478 static int moxaLowWaterChk;
ian@0 1479 static int moxaCard;
ian@0 1480 static mon_st moxaLog;
ian@0 1481 static int moxaFuncTout;
ian@0 1482 static ushort moxaBreakCnt[MAX_PORTS];
ian@0 1483
ian@0 1484 static void moxadelay(int);
ian@0 1485 static void moxafunc(void __iomem *, int, ushort);
ian@0 1486 static void wait_finish(void __iomem *);
ian@0 1487 static void low_water_check(void __iomem *);
ian@0 1488 static int moxaloadbios(int, unsigned char __user *, int);
ian@0 1489 static int moxafindcard(int);
ian@0 1490 static int moxaload320b(int, unsigned char __user *, int);
ian@0 1491 static int moxaloadcode(int, unsigned char __user *, int);
ian@0 1492 static int moxaloadc218(int, void __iomem *, int);
ian@0 1493 static int moxaloadc320(int, void __iomem *, int, int *);
ian@0 1494
ian@0 1495 /*****************************************************************************
ian@0 1496 * Driver level functions: *
ian@0 1497 * 1. MoxaDriverInit(void); *
ian@0 1498 * 2. MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port); *
ian@0 1499 * 3. MoxaDriverPoll(void); *
ian@0 1500 *****************************************************************************/
ian@0 1501 void MoxaDriverInit(void)
ian@0 1502 {
ian@0 1503 int i;
ian@0 1504
ian@0 1505 moxaFuncTout = HZ / 2; /* 500 mini-seconds */
ian@0 1506 moxaCard = 0;
ian@0 1507 moxaLog.tick = 0;
ian@0 1508 moxaLowWaterChk = 0;
ian@0 1509 for (i = 0; i < MAX_PORTS; i++) {
ian@0 1510 moxaChkPort[i] = 0;
ian@0 1511 moxaLowChkFlag[i] = 0;
ian@0 1512 moxaLineCtrl[i] = 0;
ian@0 1513 moxaLog.rxcnt[i] = 0;
ian@0 1514 moxaLog.txcnt[i] = 0;
ian@0 1515 }
ian@0 1516 }
ian@0 1517
ian@0 1518 #define MOXA 0x400
ian@0 1519 #define MOXA_GET_IQUEUE (MOXA + 1) /* get input buffered count */
ian@0 1520 #define MOXA_GET_OQUEUE (MOXA + 2) /* get output buffered count */
ian@0 1521 #define MOXA_INIT_DRIVER (MOXA + 6) /* moxaCard=0 */
ian@0 1522 #define MOXA_LOAD_BIOS (MOXA + 9) /* download BIOS */
ian@0 1523 #define MOXA_FIND_BOARD (MOXA + 10) /* Check if MOXA card exist? */
ian@0 1524 #define MOXA_LOAD_C320B (MOXA + 11) /* download 320B firmware */
ian@0 1525 #define MOXA_LOAD_CODE (MOXA + 12) /* download firmware */
ian@0 1526 #define MOXA_GETDATACOUNT (MOXA + 23)
ian@0 1527 #define MOXA_GET_IOQUEUE (MOXA + 27)
ian@0 1528 #define MOXA_FLUSH_QUEUE (MOXA + 28)
ian@0 1529 #define MOXA_GET_CONF (MOXA + 35) /* configuration */
ian@0 1530 #define MOXA_GET_MAJOR (MOXA + 63)
ian@0 1531 #define MOXA_GET_CUMAJOR (MOXA + 64)
ian@0 1532 #define MOXA_GETMSTATUS (MOXA + 65)
ian@0 1533
ian@0 1534
ian@0 1535 struct moxaq_str {
ian@0 1536 int inq;
ian@0 1537 int outq;
ian@0 1538 };
ian@0 1539
ian@0 1540 struct dl_str {
ian@0 1541 char __user *buf;
ian@0 1542 int len;
ian@0 1543 int cardno;
ian@0 1544 };
ian@0 1545
ian@0 1546 static struct moxaq_str temp_queue[MAX_PORTS];
ian@0 1547 static struct dl_str dltmp;
ian@0 1548
ian@0 1549 void MoxaPortFlushData(int port, int mode)
ian@0 1550 {
ian@0 1551 void __iomem *ofsAddr;
ian@0 1552 if ((mode < 0) || (mode > 2))
ian@0 1553 return;
ian@0 1554 ofsAddr = moxaTableAddr[port];
ian@0 1555 moxafunc(ofsAddr, FC_FlushQueue, mode);
ian@0 1556 if (mode != 1) {
ian@0 1557 moxaLowChkFlag[port] = 0;
ian@0 1558 low_water_check(ofsAddr);
ian@0 1559 }
ian@0 1560 }
ian@0 1561
ian@0 1562 int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port)
ian@0 1563 {
ian@0 1564 int i;
ian@0 1565 int status;
ian@0 1566 int MoxaPortTxQueue(int), MoxaPortRxQueue(int);
ian@0 1567 void __user *argp = (void __user *)arg;
ian@0 1568
ian@0 1569 if (port == QueryPort) {
ian@0 1570 if ((cmd != MOXA_GET_CONF) && (cmd != MOXA_INIT_DRIVER) &&
ian@0 1571 (cmd != MOXA_LOAD_BIOS) && (cmd != MOXA_FIND_BOARD) && (cmd != MOXA_LOAD_C320B) &&
ian@0 1572 (cmd != MOXA_LOAD_CODE) && (cmd != MOXA_GETDATACOUNT) &&
ian@0 1573 (cmd != MOXA_GET_IOQUEUE) && (cmd != MOXA_GET_MAJOR) &&
ian@0 1574 (cmd != MOXA_GET_CUMAJOR) && (cmd != MOXA_GETMSTATUS))
ian@0 1575 return (-EINVAL);
ian@0 1576 }
ian@0 1577 switch (cmd) {
ian@0 1578 case MOXA_GET_CONF:
ian@0 1579 if(copy_to_user(argp, &moxa_boards, MAX_BOARDS * sizeof(moxa_board_conf)))
ian@0 1580 return -EFAULT;
ian@0 1581 return (0);
ian@0 1582 case MOXA_INIT_DRIVER:
ian@0 1583 if ((int) arg == 0x404)
ian@0 1584 MoxaDriverInit();
ian@0 1585 return (0);
ian@0 1586 case MOXA_GETDATACOUNT:
ian@0 1587 moxaLog.tick = jiffies;
ian@0 1588 if(copy_to_user(argp, &moxaLog, sizeof(mon_st)))
ian@0 1589 return -EFAULT;
ian@0 1590 return (0);
ian@0 1591 case MOXA_FLUSH_QUEUE:
ian@0 1592 MoxaPortFlushData(port, arg);
ian@0 1593 return (0);
ian@0 1594 case MOXA_GET_IOQUEUE:
ian@0 1595 for (i = 0; i < MAX_PORTS; i++) {
ian@0 1596 if (moxaChkPort[i]) {
ian@0 1597 temp_queue[i].inq = MoxaPortRxQueue(i);
ian@0 1598 temp_queue[i].outq = MoxaPortTxQueue(i);
ian@0 1599 }
ian@0 1600 }
ian@0 1601 if(copy_to_user(argp, temp_queue, sizeof(struct moxaq_str) * MAX_PORTS))
ian@0 1602 return -EFAULT;
ian@0 1603 return (0);
ian@0 1604 case MOXA_GET_OQUEUE:
ian@0 1605 i = MoxaPortTxQueue(port);
ian@0 1606 return put_user(i, (unsigned long __user *)argp);
ian@0 1607 case MOXA_GET_IQUEUE:
ian@0 1608 i = MoxaPortRxQueue(port);
ian@0 1609 return put_user(i, (unsigned long __user *)argp);
ian@0 1610 case MOXA_GET_MAJOR:
ian@0 1611 if(copy_to_user(argp, &ttymajor, sizeof(int)))
ian@0 1612 return -EFAULT;
ian@0 1613 return 0;
ian@0 1614 case MOXA_GET_CUMAJOR:
ian@0 1615 i = 0;
ian@0 1616 if(copy_to_user(argp, &i, sizeof(int)))
ian@0 1617 return -EFAULT;
ian@0 1618 return 0;
ian@0 1619 case MOXA_GETMSTATUS:
ian@0 1620 for (i = 0; i < MAX_PORTS; i++) {
ian@0 1621 GMStatus[i].ri = 0;
ian@0 1622 GMStatus[i].dcd = 0;
ian@0 1623 GMStatus[i].dsr = 0;
ian@0 1624 GMStatus[i].cts = 0;
ian@0 1625 if (!moxaChkPort[i]) {
ian@0 1626 continue;
ian@0 1627 } else {
ian@0 1628 status = MoxaPortLineStatus(moxaChannels[i].port);
ian@0 1629 if (status & 1)
ian@0 1630 GMStatus[i].cts = 1;
ian@0 1631 if (status & 2)
ian@0 1632 GMStatus[i].dsr = 1;
ian@0 1633 if (status & 4)
ian@0 1634 GMStatus[i].dcd = 1;
ian@0 1635 }
ian@0 1636
ian@0 1637 if (!moxaChannels[i].tty || !moxaChannels[i].tty->termios)
ian@0 1638 GMStatus[i].cflag = moxaChannels[i].cflag;
ian@0 1639 else
ian@0 1640 GMStatus[i].cflag = moxaChannels[i].tty->termios->c_cflag;
ian@0 1641 }
ian@0 1642 if(copy_to_user(argp, GMStatus, sizeof(struct mxser_mstatus) * MAX_PORTS))
ian@0 1643 return -EFAULT;
ian@0 1644 return 0;
ian@0 1645 default:
ian@0 1646 return (-ENOIOCTLCMD);
ian@0 1647 case MOXA_LOAD_BIOS:
ian@0 1648 case MOXA_FIND_BOARD:
ian@0 1649 case MOXA_LOAD_C320B:
ian@0 1650 case MOXA_LOAD_CODE:
ian@0 1651 if (!capable(CAP_SYS_RAWIO))
ian@0 1652 return -EPERM;
ian@0 1653 break;
ian@0 1654 }
ian@0 1655
ian@0 1656 if(copy_from_user(&dltmp, argp, sizeof(struct dl_str)))
ian@0 1657 return -EFAULT;
ian@0 1658 if(dltmp.cardno < 0 || dltmp.cardno >= MAX_BOARDS)
ian@0 1659 return -EINVAL;
ian@0 1660
ian@0 1661 switch(cmd)
ian@0 1662 {
ian@0 1663 case MOXA_LOAD_BIOS:
ian@0 1664 i = moxaloadbios(dltmp.cardno, dltmp.buf, dltmp.len);
ian@0 1665 return (i);
ian@0 1666 case MOXA_FIND_BOARD:
ian@0 1667 return moxafindcard(dltmp.cardno);
ian@0 1668 case MOXA_LOAD_C320B:
ian@0 1669 moxaload320b(dltmp.cardno, dltmp.buf, dltmp.len);
ian@0 1670 default: /* to keep gcc happy */
ian@0 1671 return (0);
ian@0 1672 case MOXA_LOAD_CODE:
ian@0 1673 i = moxaloadcode(dltmp.cardno, dltmp.buf, dltmp.len);
ian@0 1674 if (i == -1)
ian@0 1675 return (-EFAULT);
ian@0 1676 return (i);
ian@0 1677
ian@0 1678 }
ian@0 1679 }
ian@0 1680
ian@0 1681 int MoxaDriverPoll(void)
ian@0 1682 {
ian@0 1683 register ushort temp;
ian@0 1684 register int card;
ian@0 1685 void __iomem *ofsAddr;
ian@0 1686 void __iomem *ip;
ian@0 1687 int port, p, ports;
ian@0 1688
ian@0 1689 if (moxaCard == 0)
ian@0 1690 return (-1);
ian@0 1691 for (card = 0; card < MAX_BOARDS; card++) {
ian@0 1692 if (loadstat[card] == 0)
ian@0 1693 continue;
ian@0 1694 if ((ports = moxa_boards[card].numPorts) == 0)
ian@0 1695 continue;
ian@0 1696 if (readb(moxaIntPend[card]) == 0xff) {
ian@0 1697 ip = moxaIntTable[card] + readb(moxaIntNdx[card]);
ian@0 1698 p = card * MAX_PORTS_PER_BOARD;
ian@0 1699 ports <<= 1;
ian@0 1700 for (port = 0; port < ports; port += 2, p++) {
ian@0 1701 if ((temp = readw(ip + port)) != 0) {
ian@0 1702 writew(0, ip + port);
ian@0 1703 ofsAddr = moxaTableAddr[p];
ian@0 1704 if (temp & IntrTx)
ian@0 1705 writew(readw(ofsAddr + HostStat) & ~WakeupTx, ofsAddr + HostStat);
ian@0 1706 if (temp & IntrBreak) {
ian@0 1707 moxaBreakCnt[p]++;
ian@0 1708 }
ian@0 1709 if (temp & IntrLine) {
ian@0 1710 if (readb(ofsAddr + FlagStat) & DCD_state) {
ian@0 1711 if ((moxaDCDState[p] & DCD_oldstate) == 0)
ian@0 1712 moxaDCDState[p] = (DCD_oldstate |
ian@0 1713 DCD_changed);
ian@0 1714 } else {
ian@0 1715 if (moxaDCDState[p] & DCD_oldstate)
ian@0 1716 moxaDCDState[p] = DCD_changed;
ian@0 1717 }
ian@0 1718 }
ian@0 1719 }
ian@0 1720 }
ian@0 1721 writeb(0, moxaIntPend[card]);
ian@0 1722 }
ian@0 1723 if (moxaLowWaterChk) {
ian@0 1724 p = card * MAX_PORTS_PER_BOARD;
ian@0 1725 for (port = 0; port < ports; port++, p++) {
ian@0 1726 if (moxaLowChkFlag[p]) {
ian@0 1727 moxaLowChkFlag[p] = 0;
ian@0 1728 ofsAddr = moxaTableAddr[p];
ian@0 1729 low_water_check(ofsAddr);
ian@0 1730 }
ian@0 1731 }
ian@0 1732 }
ian@0 1733 }
ian@0 1734 moxaLowWaterChk = 0;
ian@0 1735 return (0);
ian@0 1736 }
ian@0 1737
ian@0 1738 /*****************************************************************************
ian@0 1739 * Card level function: *
ian@0 1740 * 1. MoxaPortsOfCard(int cardno); *
ian@0 1741 *****************************************************************************/
ian@0 1742 int MoxaPortsOfCard(int cardno)
ian@0 1743 {
ian@0 1744
ian@0 1745 if (moxa_boards[cardno].boardType == 0)
ian@0 1746 return (0);
ian@0 1747 return (moxa_boards[cardno].numPorts);
ian@0 1748 }
ian@0 1749
ian@0 1750 /*****************************************************************************
ian@0 1751 * Port level functions: *
ian@0 1752 * 1. MoxaPortIsValid(int port); *
ian@0 1753 * 2. MoxaPortEnable(int port); *
ian@0 1754 * 3. MoxaPortDisable(int port); *
ian@0 1755 * 4. MoxaPortGetMaxBaud(int port); *
ian@0 1756 * 5. MoxaPortGetCurBaud(int port); *
ian@0 1757 * 6. MoxaPortSetBaud(int port, long baud); *
ian@0 1758 * 7. MoxaPortSetMode(int port, int databit, int stopbit, int parity); *
ian@0 1759 * 8. MoxaPortSetTermio(int port, unsigned char *termio); *
ian@0 1760 * 9. MoxaPortGetLineOut(int port, int *dtrState, int *rtsState); *
ian@0 1761 * 10. MoxaPortLineCtrl(int port, int dtrState, int rtsState); *
ian@0 1762 * 11. MoxaPortFlowCtrl(int port, int rts, int cts, int rx, int tx,int xany); *
ian@0 1763 * 12. MoxaPortLineStatus(int port); *
ian@0 1764 * 13. MoxaPortDCDChange(int port); *
ian@0 1765 * 14. MoxaPortDCDON(int port); *
ian@0 1766 * 15. MoxaPortFlushData(int port, int mode); *
ian@0 1767 * 16. MoxaPortWriteData(int port, unsigned char * buffer, int length); *
ian@0 1768 * 17. MoxaPortReadData(int port, struct tty_struct *tty); *
ian@0 1769 * 18. MoxaPortTxBufSize(int port); *
ian@0 1770 * 19. MoxaPortRxBufSize(int port); *
ian@0 1771 * 20. MoxaPortTxQueue(int port); *
ian@0 1772 * 21. MoxaPortTxFree(int port); *
ian@0 1773 * 22. MoxaPortRxQueue(int port); *
ian@0 1774 * 23. MoxaPortRxFree(int port); *
ian@0 1775 * 24. MoxaPortTxDisable(int port); *
ian@0 1776 * 25. MoxaPortTxEnable(int port); *
ian@0 1777 * 26. MoxaPortGetBrkCnt(int port); *
ian@0 1778 * 27. MoxaPortResetBrkCnt(int port); *
ian@0 1779 * 28. MoxaPortSetXonXoff(int port, int xonValue, int xoffValue); *
ian@0 1780 * 29. MoxaPortIsTxHold(int port); *
ian@0 1781 * 30. MoxaPortSendBreak(int port, int ticks); *
ian@0 1782 *****************************************************************************/
ian@0 1783 /*
ian@0 1784 * Moxa Port Number Description:
ian@0 1785 *
ian@0 1786 * MOXA serial driver supports up to 4 MOXA-C218/C320 boards. And,
ian@0 1787 * the port number using in MOXA driver functions will be 0 to 31 for
ian@0 1788 * first MOXA board, 32 to 63 for second, 64 to 95 for third and 96
ian@0 1789 * to 127 for fourth. For example, if you setup three MOXA boards,
ian@0 1790 * first board is C218, second board is C320-16 and third board is
ian@0 1791 * C320-32. The port number of first board (C218 - 8 ports) is from
ian@0 1792 * 0 to 7. The port number of second board (C320 - 16 ports) is form
ian@0 1793 * 32 to 47. The port number of third board (C320 - 32 ports) is from
ian@0 1794 * 64 to 95. And those port numbers form 8 to 31, 48 to 63 and 96 to
ian@0 1795 * 127 will be invalid.
ian@0 1796 *
ian@0 1797 *
ian@0 1798 * Moxa Functions Description:
ian@0 1799 *
ian@0 1800 * Function 1: Driver initialization routine, this routine must be
ian@0 1801 * called when initialized driver.
ian@0 1802 * Syntax:
ian@0 1803 * void MoxaDriverInit();
ian@0 1804 *
ian@0 1805 *
ian@0 1806 * Function 2: Moxa driver private IOCTL command processing.
ian@0 1807 * Syntax:
ian@0 1808 * int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port);
ian@0 1809 *
ian@0 1810 * unsigned int cmd : IOCTL command
ian@0 1811 * unsigned long arg : IOCTL argument
ian@0 1812 * int port : port number (0 - 127)
ian@0 1813 *
ian@0 1814 * return: 0 (OK)
ian@0 1815 * -EINVAL
ian@0 1816 * -ENOIOCTLCMD
ian@0 1817 *
ian@0 1818 *
ian@0 1819 * Function 3: Moxa driver polling process routine.
ian@0 1820 * Syntax:
ian@0 1821 * int MoxaDriverPoll(void);
ian@0 1822 *
ian@0 1823 * return: 0 ; polling O.K.
ian@0 1824 * -1 : no any Moxa card.
ian@0 1825 *
ian@0 1826 *
ian@0 1827 * Function 4: Get the ports of this card.
ian@0 1828 * Syntax:
ian@0 1829 * int MoxaPortsOfCard(int cardno);
ian@0 1830 *
ian@0 1831 * int cardno : card number (0 - 3)
ian@0 1832 *
ian@0 1833 * return: 0 : this card is invalid
ian@0 1834 * 8/16/24/32
ian@0 1835 *
ian@0 1836 *
ian@0 1837 * Function 5: Check this port is valid or invalid
ian@0 1838 * Syntax:
ian@0 1839 * int MoxaPortIsValid(int port);
ian@0 1840 * int port : port number (0 - 127, ref port description)
ian@0 1841 *
ian@0 1842 * return: 0 : this port is invalid
ian@0 1843 * 1 : this port is valid
ian@0 1844 *
ian@0 1845 *
ian@0 1846 * Function 6: Enable this port to start Tx/Rx data.
ian@0 1847 * Syntax:
ian@0 1848 * void MoxaPortEnable(int port);
ian@0 1849 * int port : port number (0 - 127)
ian@0 1850 *
ian@0 1851 *
ian@0 1852 * Function 7: Disable this port
ian@0 1853 * Syntax:
ian@0 1854 * void MoxaPortDisable(int port);
ian@0 1855 * int port : port number (0 - 127)
ian@0 1856 *
ian@0 1857 *
ian@0 1858 * Function 8: Get the maximun available baud rate of this port.
ian@0 1859 * Syntax:
ian@0 1860 * long MoxaPortGetMaxBaud(int port);
ian@0 1861 * int port : port number (0 - 127)
ian@0 1862 *
ian@0 1863 * return: 0 : this port is invalid
ian@0 1864 * 38400/57600/115200 bps
ian@0 1865 *
ian@0 1866 *
ian@0 1867 * Function 9: Get the current baud rate of this port.
ian@0 1868 * Syntax:
ian@0 1869 * long MoxaPortGetCurBaud(int port);
ian@0 1870 * int port : port number (0 - 127)
ian@0 1871 *
ian@0 1872 * return: 0 : this port is invalid
ian@0 1873 * 50 - 115200 bps
ian@0 1874 *
ian@0 1875 *
ian@0 1876 * Function 10: Setting baud rate of this port.
ian@0 1877 * Syntax:
ian@0 1878 * long MoxaPortSetBaud(int port, long baud);
ian@0 1879 * int port : port number (0 - 127)
ian@0 1880 * long baud : baud rate (50 - 115200)
ian@0 1881 *
ian@0 1882 * return: 0 : this port is invalid or baud < 50
ian@0 1883 * 50 - 115200 : the real baud rate set to the port, if
ian@0 1884 * the argument baud is large than maximun
ian@0 1885 * available baud rate, the real setting
ian@0 1886 * baud rate will be the maximun baud rate.
ian@0 1887 *
ian@0 1888 *
ian@0 1889 * Function 11: Setting the data-bits/stop-bits/parity of this port
ian@0 1890 * Syntax:
ian@0 1891 * int MoxaPortSetMode(int port, int databits, int stopbits, int parity);
ian@0 1892 * int port : port number (0 - 127)
ian@0 1893 * int databits : data bits (8/7/6/5)
ian@0 1894 * int stopbits : stop bits (2/1/0, 0 show 1.5 stop bits)
ian@0 1895 int parity : parity (0:None,1:Odd,2:Even,3:Mark,4:Space)
ian@0 1896 *
ian@0 1897 * return: -1 : invalid parameter
ian@0 1898 * 0 : setting O.K.
ian@0 1899 *
ian@0 1900 *
ian@0 1901 * Function 12: Configure the port.
ian@0 1902 * Syntax:
ian@0 1903 * int MoxaPortSetTermio(int port, struct termios *termio);
ian@0 1904 * int port : port number (0 - 127)
ian@0 1905 * struct termios * termio : termio structure pointer
ian@0 1906 *
ian@0 1907 * return: -1 : this port is invalid or termio == NULL
ian@0 1908 * 0 : setting O.K.
ian@0 1909 *
ian@0 1910 *
ian@0 1911 * Function 13: Get the DTR/RTS state of this port.
ian@0 1912 * Syntax:
ian@0 1913 * int MoxaPortGetLineOut(int port, int *dtrState, int *rtsState);
ian@0 1914 * int port : port number (0 - 127)
ian@0 1915 * int * dtrState : pointer to INT to receive the current DTR
ian@0 1916 * state. (if NULL, this function will not
ian@0 1917 * write to this address)
ian@0 1918 * int * rtsState : pointer to INT to receive the current RTS
ian@0 1919 * state. (if NULL, this function will not
ian@0 1920 * write to this address)
ian@0 1921 *
ian@0 1922 * return: -1 : this port is invalid
ian@0 1923 * 0 : O.K.
ian@0 1924 *
ian@0 1925 *
ian@0 1926 * Function 14: Setting the DTR/RTS output state of this port.
ian@0 1927 * Syntax:
ian@0 1928 * void MoxaPortLineCtrl(int port, int dtrState, int rtsState);
ian@0 1929 * int port : port number (0 - 127)
ian@0 1930 * int dtrState : DTR output state (0: off, 1: on)
ian@0 1931 * int rtsState : RTS output state (0: off, 1: on)
ian@0 1932 *
ian@0 1933 *
ian@0 1934 * Function 15: Setting the flow control of this port.
ian@0 1935 * Syntax:
ian@0 1936 * void MoxaPortFlowCtrl(int port, int rtsFlow, int ctsFlow, int rxFlow,
ian@0 1937 * int txFlow,int xany);
ian@0 1938 * int port : port number (0 - 127)
ian@0 1939 * int rtsFlow : H/W RTS flow control (0: no, 1: yes)
ian@0 1940 * int ctsFlow : H/W CTS flow control (0: no, 1: yes)
ian@0 1941 * int rxFlow : S/W Rx XON/XOFF flow control (0: no, 1: yes)
ian@0 1942 * int txFlow : S/W Tx XON/XOFF flow control (0: no, 1: yes)
ian@0 1943 * int xany : S/W XANY flow control (0: no, 1: yes)
ian@0 1944 *
ian@0 1945 *
ian@0 1946 * Function 16: Get ths line status of this port
ian@0 1947 * Syntax:
ian@0 1948 * int MoxaPortLineStatus(int port);
ian@0 1949 * int port : port number (0 - 127)
ian@0 1950 *
ian@0 1951 * return: Bit 0 - CTS state (0: off, 1: on)
ian@0 1952 * Bit 1 - DSR state (0: off, 1: on)
ian@0 1953 * Bit 2 - DCD state (0: off, 1: on)
ian@0 1954 *
ian@0 1955 *
ian@0 1956 * Function 17: Check the DCD state has changed since the last read
ian@0 1957 * of this function.
ian@0 1958 * Syntax:
ian@0 1959 * int MoxaPortDCDChange(int port);
ian@0 1960 * int port : port number (0 - 127)
ian@0 1961 *
ian@0 1962 * return: 0 : no changed
ian@0 1963 * 1 : DCD has changed
ian@0 1964 *
ian@0 1965 *
ian@0 1966 * Function 18: Check ths current DCD state is ON or not.
ian@0 1967 * Syntax:
ian@0 1968 * int MoxaPortDCDON(int port);
ian@0 1969 * int port : port number (0 - 127)
ian@0 1970 *
ian@0 1971 * return: 0 : DCD off
ian@0 1972 * 1 : DCD on
ian@0 1973 *
ian@0 1974 *
ian@0 1975 * Function 19: Flush the Rx/Tx buffer data of this port.
ian@0 1976 * Syntax:
ian@0 1977 * void MoxaPortFlushData(int port, int mode);
ian@0 1978 * int port : port number (0 - 127)
ian@0 1979 * int mode
ian@0 1980 * 0 : flush the Rx buffer
ian@0 1981 * 1 : flush the Tx buffer
ian@0 1982 * 2 : flush the Rx and Tx buffer
ian@0 1983 *
ian@0 1984 *
ian@0 1985 * Function 20: Write data.
ian@0 1986 * Syntax:
ian@0 1987 * int MoxaPortWriteData(int port, unsigned char * buffer, int length);
ian@0 1988 * int port : port number (0 - 127)
ian@0 1989 * unsigned char * buffer : pointer to write data buffer.
ian@0 1990 * int length : write data length
ian@0 1991 *
ian@0 1992 * return: 0 - length : real write data length
ian@0 1993 *
ian@0 1994 *
ian@0 1995 * Function 21: Read data.
ian@0 1996 * Syntax:
ian@0 1997 * int MoxaPortReadData(int port, struct tty_struct *tty);
ian@0 1998 * int port : port number (0 - 127)
ian@0 1999 * struct tty_struct *tty : tty for data
ian@0 2000 *
ian@0 2001 * return: 0 - length : real read data length
ian@0 2002 *
ian@0 2003 *
ian@0 2004 * Function 22: Get the Tx buffer size of this port
ian@0 2005 * Syntax:
ian@0 2006 * int MoxaPortTxBufSize(int port);
ian@0 2007 * int port : port number (0 - 127)
ian@0 2008 *
ian@0 2009 * return: .. : Tx buffer size
ian@0 2010 *
ian@0 2011 *
ian@0 2012 * Function 23: Get the Rx buffer size of this port
ian@0 2013 * Syntax:
ian@0 2014 * int MoxaPortRxBufSize(int port);
ian@0 2015 * int port : port number (0 - 127)
ian@0 2016 *
ian@0 2017 * return: .. : Rx buffer size
ian@0 2018 *
ian@0 2019 *
ian@0 2020 * Function 24: Get the Tx buffer current queued data bytes
ian@0 2021 * Syntax:
ian@0 2022 * int MoxaPortTxQueue(int port);
ian@0 2023 * int port : port number (0 - 127)
ian@0 2024 *
ian@0 2025 * return: .. : Tx buffer current queued data bytes
ian@0 2026 *
ian@0 2027 *
ian@0 2028 * Function 25: Get the Tx buffer current free space
ian@0 2029 * Syntax:
ian@0 2030 * int MoxaPortTxFree(int port);
ian@0 2031 * int port : port number (0 - 127)
ian@0 2032 *
ian@0 2033 * return: .. : Tx buffer current free space
ian@0 2034 *
ian@0 2035 *
ian@0 2036 * Function 26: Get the Rx buffer current queued data bytes
ian@0 2037 * Syntax:
ian@0 2038 * int MoxaPortRxQueue(int port);
ian@0 2039 * int port : port number (0 - 127)
ian@0 2040 *
ian@0 2041 * return: .. : Rx buffer current queued data bytes
ian@0 2042 *
ian@0 2043 *
ian@0 2044 * Function 27: Get the Rx buffer current free space
ian@0 2045 * Syntax:
ian@0 2046 * int MoxaPortRxFree(int port);
ian@0 2047 * int port : port number (0 - 127)
ian@0 2048 *
ian@0 2049 * return: .. : Rx buffer current free space
ian@0 2050 *
ian@0 2051 *
ian@0 2052 * Function 28: Disable port data transmission.
ian@0 2053 * Syntax:
ian@0 2054 * void MoxaPortTxDisable(int port);
ian@0 2055 * int port : port number (0 - 127)
ian@0 2056 *
ian@0 2057 *
ian@0 2058 * Function 29: Enable port data transmission.
ian@0 2059 * Syntax:
ian@0 2060 * void MoxaPortTxEnable(int port);
ian@0 2061 * int port : port number (0 - 127)
ian@0 2062 *
ian@0 2063 *
ian@0 2064 * Function 30: Get the received BREAK signal count.
ian@0 2065 * Syntax:
ian@0 2066 * int MoxaPortGetBrkCnt(int port);
ian@0 2067 * int port : port number (0 - 127)
ian@0 2068 *
ian@0 2069 * return: 0 - .. : BREAK signal count
ian@0 2070 *
ian@0 2071 *
ian@0 2072 * Function 31: Get the received BREAK signal count and reset it.
ian@0 2073 * Syntax:
ian@0 2074 * int MoxaPortResetBrkCnt(int port);
ian@0 2075 * int port : port number (0 - 127)
ian@0 2076 *
ian@0 2077 * return: 0 - .. : BREAK signal count
ian@0 2078 *
ian@0 2079 *
ian@0 2080 * Function 32: Set the S/W flow control new XON/XOFF value, default
ian@0 2081 * XON is 0x11 & XOFF is 0x13.
ian@0 2082 * Syntax:
ian@0 2083 * void MoxaPortSetXonXoff(int port, int xonValue, int xoffValue);
ian@0 2084 * int port : port number (0 - 127)
ian@0 2085 * int xonValue : new XON value (0 - 255)
ian@0 2086 * int xoffValue : new XOFF value (0 - 255)
ian@0 2087 *
ian@0 2088 *
ian@0 2089 * Function 33: Check this port's transmission is hold by remote site
ian@0 2090 * because the flow control.
ian@0 2091 * Syntax:
ian@0 2092 * int MoxaPortIsTxHold(int port);
ian@0 2093 * int port : port number (0 - 127)
ian@0 2094 *
ian@0 2095 * return: 0 : normal
ian@0 2096 * 1 : hold by remote site
ian@0 2097 *
ian@0 2098 *
ian@0 2099 * Function 34: Send out a BREAK signal.
ian@0 2100 * Syntax:
ian@0 2101 * void MoxaPortSendBreak(int port, int ms100);
ian@0 2102 * int port : port number (0 - 127)
ian@0 2103 * int ms100 : break signal time interval.
ian@0 2104 * unit: 100 mini-second. if ms100 == 0, it will
ian@0 2105 * send out a about 250 ms BREAK signal.
ian@0 2106 *
ian@0 2107 */
ian@0 2108 int MoxaPortIsValid(int port)
ian@0 2109 {
ian@0 2110
ian@0 2111 if (moxaCard == 0)
ian@0 2112 return (0);
ian@0 2113 if (moxaChkPort[port] == 0)
ian@0 2114 return (0);
ian@0 2115 return (1);
ian@0 2116 }
ian@0 2117
ian@0 2118 void MoxaPortEnable(int port)
ian@0 2119 {
ian@0 2120 void __iomem *ofsAddr;
ian@0 2121 int MoxaPortLineStatus(int);
ian@0 2122 short lowwater = 512;
ian@0 2123
ian@0 2124 ofsAddr = moxaTableAddr[port];
ian@0 2125 writew(lowwater, ofsAddr + Low_water);
ian@0 2126 moxaBreakCnt[port] = 0;
ian@0 2127 if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
ian@0 2128 (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
ian@0 2129 moxafunc(ofsAddr, FC_SetBreakIrq, 0);
ian@0 2130 } else {
ian@0 2131 writew(readw(ofsAddr + HostStat) | WakeupBreak, ofsAddr + HostStat);
ian@0 2132 }
ian@0 2133
ian@0 2134 moxafunc(ofsAddr, FC_SetLineIrq, Magic_code);
ian@0 2135 moxafunc(ofsAddr, FC_FlushQueue, 2);
ian@0 2136
ian@0 2137 moxafunc(ofsAddr, FC_EnableCH, Magic_code);
ian@0 2138 MoxaPortLineStatus(port);
ian@0 2139 }
ian@0 2140
ian@0 2141 void MoxaPortDisable(int port)
ian@0 2142 {
ian@0 2143 void __iomem *ofsAddr = moxaTableAddr[port];
ian@0 2144
ian@0 2145 moxafunc(ofsAddr, FC_SetFlowCtl, 0); /* disable flow control */
ian@0 2146 moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code);
ian@0 2147 writew(0, ofsAddr + HostStat);
ian@0 2148 moxafunc(ofsAddr, FC_DisableCH, Magic_code);
ian@0 2149 }
ian@0 2150
ian@0 2151 long MoxaPortGetMaxBaud(int port)
ian@0 2152 {
ian@0 2153 if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
ian@0 2154 (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI))
ian@0 2155 return (460800L);
ian@0 2156 else
ian@0 2157 return (921600L);
ian@0 2158 }
ian@0 2159
ian@0 2160
ian@0 2161 long MoxaPortSetBaud(int port, long baud)
ian@0 2162 {
ian@0 2163 void __iomem *ofsAddr;
ian@0 2164 long max, clock;
ian@0 2165 unsigned int val;
ian@0 2166
ian@0 2167 if ((baud < 50L) || ((max = MoxaPortGetMaxBaud(port)) == 0))
ian@0 2168 return (0);
ian@0 2169 ofsAddr = moxaTableAddr[port];
ian@0 2170 if (baud > max)
ian@0 2171 baud = max;
ian@0 2172 if (max == 38400L)
ian@0 2173 clock = 614400L; /* for 9.8304 Mhz : max. 38400 bps */
ian@0 2174 else if (max == 57600L)
ian@0 2175 clock = 691200L; /* for 11.0592 Mhz : max. 57600 bps */
ian@0 2176 else
ian@0 2177 clock = 921600L; /* for 14.7456 Mhz : max. 115200 bps */
ian@0 2178 val = clock / baud;
ian@0 2179 moxafunc(ofsAddr, FC_SetBaud, val);
ian@0 2180 baud = clock / val;
ian@0 2181 moxaCurBaud[port] = baud;
ian@0 2182 return (baud);
ian@0 2183 }
ian@0 2184
ian@0 2185 int MoxaPortSetTermio(int port, struct termios *termio)
ian@0 2186 {
ian@0 2187 void __iomem *ofsAddr;
ian@0 2188 tcflag_t cflag;
ian@0 2189 long baud;
ian@0 2190 tcflag_t mode = 0;
ian@0 2191
ian@0 2192 if (moxaChkPort[port] == 0 || termio == 0)
ian@0 2193 return (-1);
ian@0 2194 ofsAddr = moxaTableAddr[port];
ian@0 2195 cflag = termio->c_cflag; /* termio->c_cflag */
ian@0 2196
ian@0 2197 mode = termio->c_cflag & CSIZE;
ian@0 2198 if (mode == CS5)
ian@0 2199 mode = MX_CS5;
ian@0 2200 else if (mode == CS6)
ian@0 2201 mode = MX_CS6;
ian@0 2202 else if (mode == CS7)
ian@0 2203 mode = MX_CS7;
ian@0 2204 else if (mode == CS8)
ian@0 2205 mode = MX_CS8;
ian@0 2206
ian@0 2207 if (termio->c_cflag & CSTOPB) {
ian@0 2208 if (mode == MX_CS5)
ian@0 2209 mode |= MX_STOP15;
ian@0 2210 else
ian@0 2211 mode |= MX_STOP2;
ian@0 2212 } else
ian@0 2213 mode |= MX_STOP1;
ian@0 2214
ian@0 2215 if (termio->c_cflag & PARENB) {
ian@0 2216 if (termio->c_cflag & PARODD)
ian@0 2217 mode |= MX_PARODD;
ian@0 2218 else
ian@0 2219 mode |= MX_PAREVEN;
ian@0 2220 } else
ian@0 2221 mode |= MX_PARNONE;
ian@0 2222
ian@0 2223 moxafunc(ofsAddr, FC_SetDataMode, (ushort) mode);
ian@0 2224
ian@0 2225 cflag &= (CBAUD | CBAUDEX);
ian@0 2226 #ifndef B921600
ian@0 2227 #define B921600 (B460800+1)
ian@0 2228 #endif
ian@0 2229 switch (cflag) {
ian@0 2230 case B921600:
ian@0 2231 baud = 921600L;
ian@0 2232 break;
ian@0 2233 case B460800:
ian@0 2234 baud = 460800L;
ian@0 2235 break;
ian@0 2236 case B230400:
ian@0 2237 baud = 230400L;
ian@0 2238 break;
ian@0 2239 case B115200:
ian@0 2240 baud = 115200L;
ian@0 2241 break;
ian@0 2242 case B57600:
ian@0 2243 baud = 57600L;
ian@0 2244 break;
ian@0 2245 case B38400:
ian@0 2246 baud = 38400L;
ian@0 2247 break;
ian@0 2248 case B19200:
ian@0 2249 baud = 19200L;
ian@0 2250 break;
ian@0 2251 case B9600:
ian@0 2252 baud = 9600L;
ian@0 2253 break;
ian@0 2254 case B4800:
ian@0 2255 baud = 4800L;
ian@0 2256 break;
ian@0 2257 case B2400:
ian@0 2258 baud = 2400L;
ian@0 2259 break;
ian@0 2260 case B1800:
ian@0 2261 baud = 1800L;
ian@0 2262 break;
ian@0 2263 case B1200:
ian@0 2264 baud = 1200L;
ian@0 2265 break;
ian@0 2266 case B600:
ian@0 2267 baud = 600L;
ian@0 2268 break;
ian@0 2269 case B300:
ian@0 2270 baud = 300L;
ian@0 2271 break;
ian@0 2272 case B200:
ian@0 2273 baud = 200L;
ian@0 2274 break;
ian@0 2275 case B150:
ian@0 2276 baud = 150L;
ian@0 2277 break;
ian@0 2278 case B134:
ian@0 2279 baud = 134L;
ian@0 2280 break;
ian@0 2281 case B110:
ian@0 2282 baud = 110L;
ian@0 2283 break;
ian@0 2284 case B75:
ian@0 2285 baud = 75L;
ian@0 2286 break;
ian@0 2287 case B50:
ian@0 2288 baud = 50L;
ian@0 2289 break;
ian@0 2290 default:
ian@0 2291 baud = 0;
ian@0 2292 }
ian@0 2293 if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
ian@0 2294 (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
ian@0 2295 if (baud == 921600L)
ian@0 2296 return (-1);
ian@0 2297 }
ian@0 2298 MoxaPortSetBaud(port, baud);
ian@0 2299
ian@0 2300 if (termio->c_iflag & (IXON | IXOFF | IXANY)) {
ian@0 2301 writeb(termio->c_cc[VSTART], ofsAddr + FuncArg);
ian@0 2302 writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1);
ian@0 2303 writeb(FC_SetXonXoff, ofsAddr + FuncCode);
ian@0 2304 wait_finish(ofsAddr);
ian@0 2305
ian@0 2306 }
ian@0 2307 return (0);
ian@0 2308 }
ian@0 2309
ian@0 2310 int MoxaPortGetLineOut(int port, int *dtrState, int *rtsState)
ian@0 2311 {
ian@0 2312
ian@0 2313 if (!MoxaPortIsValid(port))
ian@0 2314 return (-1);
ian@0 2315 if (dtrState) {
ian@0 2316 if (moxaLineCtrl[port] & DTR_ON)
ian@0 2317 *dtrState = 1;
ian@0 2318 else
ian@0 2319 *dtrState = 0;
ian@0 2320 }
ian@0 2321 if (rtsState) {
ian@0 2322 if (moxaLineCtrl[port] & RTS_ON)
ian@0 2323 *rtsState = 1;
ian@0 2324 else
ian@0 2325 *rtsState = 0;
ian@0 2326 }
ian@0 2327 return (0);
ian@0 2328 }
ian@0 2329
ian@0 2330 void MoxaPortLineCtrl(int port, int dtr, int rts)
ian@0 2331 {
ian@0 2332 void __iomem *ofsAddr;
ian@0 2333 int mode;
ian@0 2334
ian@0 2335 ofsAddr = moxaTableAddr[port];
ian@0 2336 mode = 0;
ian@0 2337 if (dtr)
ian@0 2338 mode |= DTR_ON;
ian@0 2339 if (rts)
ian@0 2340 mode |= RTS_ON;
ian@0 2341 moxaLineCtrl[port] = mode;
ian@0 2342 moxafunc(ofsAddr, FC_LineControl, mode);
ian@0 2343 }
ian@0 2344
ian@0 2345 void MoxaPortFlowCtrl(int port, int rts, int cts, int txflow, int rxflow, int txany)
ian@0 2346 {
ian@0 2347 void __iomem *ofsAddr;
ian@0 2348 int mode;
ian@0 2349
ian@0 2350 ofsAddr = moxaTableAddr[port];
ian@0 2351 mode = 0;
ian@0 2352 if (rts)
ian@0 2353 mode |= RTS_FlowCtl;
ian@0 2354 if (cts)
ian@0 2355 mode |= CTS_FlowCtl;
ian@0 2356 if (txflow)
ian@0 2357 mode |= Tx_FlowCtl;
ian@0 2358 if (rxflow)
ian@0 2359 mode |= Rx_FlowCtl;
ian@0 2360 if (txany)
ian@0 2361 mode |= IXM_IXANY;
ian@0 2362 moxafunc(ofsAddr, FC_SetFlowCtl, mode);
ian@0 2363 }
ian@0 2364
ian@0 2365 int MoxaPortLineStatus(int port)
ian@0 2366 {
ian@0 2367 void __iomem *ofsAddr;
ian@0 2368 int val;
ian@0 2369
ian@0 2370 ofsAddr = moxaTableAddr[port];
ian@0 2371 if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
ian@0 2372 (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
ian@0 2373 moxafunc(ofsAddr, FC_LineStatus, 0);
ian@0 2374 val = readw(ofsAddr + FuncArg);
ian@0 2375 } else {
ian@0 2376 val = readw(ofsAddr + FlagStat) >> 4;
ian@0 2377 }
ian@0 2378 val &= 0x0B;
ian@0 2379 if (val & 8) {
ian@0 2380 val |= 4;
ian@0 2381 if ((moxaDCDState[port] & DCD_oldstate) == 0)
ian@0 2382 moxaDCDState[port] = (DCD_oldstate | DCD_changed);
ian@0 2383 } else {
ian@0 2384 if (moxaDCDState[port] & DCD_oldstate)
ian@0 2385 moxaDCDState[port] = DCD_changed;
ian@0 2386 }
ian@0 2387 val &= 7;
ian@0 2388 return (val);
ian@0 2389 }
ian@0 2390
ian@0 2391 int MoxaPortDCDChange(int port)
ian@0 2392 {
ian@0 2393 int n;
ian@0 2394
ian@0 2395 if (moxaChkPort[port] == 0)
ian@0 2396 return (0);
ian@0 2397 n = moxaDCDState[port];
ian@0 2398 moxaDCDState[port] &= ~DCD_changed;
ian@0 2399 n &= DCD_changed;
ian@0 2400 return (n);
ian@0 2401 }
ian@0 2402
ian@0 2403 int MoxaPortDCDON(int port)
ian@0 2404 {
ian@0 2405 int n;
ian@0 2406
ian@0 2407 if (moxaChkPort[port] == 0)
ian@0 2408 return (0);
ian@0 2409 if (moxaDCDState[port] & DCD_oldstate)
ian@0 2410 n = 1;
ian@0 2411 else
ian@0 2412 n = 0;
ian@0 2413 return (n);
ian@0 2414 }
ian@0 2415
ian@0 2416
ian@0 2417 /*
ian@0 2418 int MoxaDumpMem(int port, unsigned char * buffer, int len)
ian@0 2419 {
ian@0 2420 int i;
ian@0 2421 unsigned long baseAddr,ofsAddr,ofs;
ian@0 2422
ian@0 2423 baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD];
ian@0 2424 ofs = baseAddr + DynPage_addr + pageofs;
ian@0 2425 if (len > 0x2000L)
ian@0 2426 len = 0x2000L;
ian@0 2427 for (i = 0; i < len; i++)
ian@0 2428 buffer[i] = readb(ofs+i);
ian@0 2429 }
ian@0 2430 */
ian@0 2431
ian@0 2432
ian@0 2433 int MoxaPortWriteData(int port, unsigned char * buffer, int len)
ian@0 2434 {
ian@0 2435 int c, total, i;
ian@0 2436 ushort tail;
ian@0 2437 int cnt;
ian@0 2438 ushort head, tx_mask, spage, epage;
ian@0 2439 ushort pageno, pageofs, bufhead;
ian@0 2440 void __iomem *baseAddr, *ofsAddr, *ofs;
ian@0 2441
ian@0 2442 ofsAddr = moxaTableAddr[port];
ian@0 2443 baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD];
ian@0 2444 tx_mask = readw(ofsAddr + TX_mask);
ian@0 2445 spage = readw(ofsAddr + Page_txb);
ian@0 2446 epage = readw(ofsAddr + EndPage_txb);
ian@0 2447 tail = readw(ofsAddr + TXwptr);
ian@0 2448 head = readw(ofsAddr + TXrptr);
ian@0 2449 c = (head > tail) ? (head - tail - 1)
ian@0 2450 : (head - tail + tx_mask);
ian@0 2451 if (c > len)
ian@0 2452 c = len;
ian@0 2453 moxaLog.txcnt[port] += c;
ian@0 2454 total = c;
ian@0 2455 if (spage == epage) {
ian@0 2456 bufhead = readw(ofsAddr + Ofs_txb);
ian@0 2457 writew(spage, baseAddr + Control_reg);
ian@0 2458 while (c > 0) {
ian@0 2459 if (head > tail)
ian@0 2460 len = head - tail - 1;
ian@0 2461 else
ian@0 2462 len = tx_mask + 1 - tail;
ian@0 2463 len = (c > len) ? len : c;
ian@0 2464 ofs = baseAddr + DynPage_addr + bufhead + tail;
ian@0 2465 for (i = 0; i < len; i++)
ian@0 2466 writeb(*buffer++, ofs + i);
ian@0 2467 tail = (tail + len) & tx_mask;
ian@0 2468 c -= len;
ian@0 2469 }
ian@0 2470 writew(tail, ofsAddr + TXwptr);
ian@0 2471 } else {
ian@0 2472 len = c;
ian@0 2473 pageno = spage + (tail >> 13);
ian@0 2474 pageofs = tail & Page_mask;
ian@0 2475 do {
ian@0 2476 cnt = Page_size - pageofs;
ian@0 2477 if (cnt > c)
ian@0 2478 cnt = c;
ian@0 2479 c -= cnt;
ian@0 2480 writeb(pageno, baseAddr + Control_reg);
ian@0 2481 ofs = baseAddr + DynPage_addr + pageofs;
ian@0 2482 for (i = 0; i < cnt; i++)
ian@0 2483 writeb(*buffer++, ofs + i);
ian@0 2484 if (c == 0) {
ian@0 2485 writew((tail + len) & tx_mask, ofsAddr + TXwptr);
ian@0 2486 break;
ian@0 2487 }
ian@0 2488 if (++pageno == epage)
ian@0 2489 pageno = spage;
ian@0 2490 pageofs = 0;
ian@0 2491 } while (1);
ian@0 2492 }
ian@0 2493 writeb(1, ofsAddr + CD180TXirq); /* start to send */
ian@0 2494 return (total);
ian@0 2495 }
ian@0 2496
ian@0 2497 int MoxaPortReadData(int port, struct tty_struct *tty)
ian@0 2498 {
ian@0 2499 register ushort head, pageofs;
ian@0 2500 int i, count, cnt, len, total, remain;
ian@0 2501 ushort tail, rx_mask, spage, epage;
ian@0 2502 ushort pageno, bufhead;
ian@0 2503 void __iomem *baseAddr, *ofsAddr, *ofs;
ian@0 2504
ian@0 2505 ofsAddr = moxaTableAddr[port];
ian@0 2506 baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD];
ian@0 2507 head = readw(ofsAddr + RXrptr);
ian@0 2508 tail = readw(ofsAddr + RXwptr);
ian@0 2509 rx_mask = readw(ofsAddr + RX_mask);
ian@0 2510 spage = readw(ofsAddr + Page_rxb);
ian@0 2511 epage = readw(ofsAddr + EndPage_rxb);
ian@0 2512 count = (tail >= head) ? (tail - head)
ian@0 2513 : (tail - head + rx_mask + 1);
ian@0 2514 if (count == 0)
ian@0 2515 return 0;
ian@0 2516
ian@0 2517 total = count;
ian@0 2518 remain = count - total;
ian@0 2519 moxaLog.rxcnt[port] += total;
ian@0 2520 count = total;
ian@0 2521 if (spage == epage) {
ian@0 2522 bufhead = readw(ofsAddr + Ofs_rxb);
ian@0 2523 writew(spage, baseAddr + Control_reg);
ian@0 2524 while (count > 0) {
ian@0 2525 if (tail >= head)
ian@0 2526 len = tail - head;
ian@0 2527 else
ian@0 2528 len = rx_mask + 1 - head;
ian@0 2529 len = (count > len) ? len : count;
ian@0 2530 ofs = baseAddr + DynPage_addr + bufhead + head;
ian@0 2531 for (i = 0; i < len; i++)
ian@0 2532 tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL);
ian@0 2533 head = (head + len) & rx_mask;
ian@0 2534 count -= len;
ian@0 2535 }
ian@0 2536 writew(head, ofsAddr + RXrptr);
ian@0 2537 } else {
ian@0 2538 len = count;
ian@0 2539 pageno = spage + (head >> 13);
ian@0 2540 pageofs = head & Page_mask;
ian@0 2541 do {
ian@0 2542 cnt = Page_size - pageofs;
ian@0 2543 if (cnt > count)
ian@0 2544 cnt = count;
ian@0 2545 count -= cnt;
ian@0 2546 writew(pageno, baseAddr + Control_reg);
ian@0 2547 ofs = baseAddr + DynPage_addr + pageofs;
ian@0 2548 for (i = 0; i < cnt; i++)
ian@0 2549 tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL);
ian@0 2550 if (count == 0) {
ian@0 2551 writew((head + len) & rx_mask, ofsAddr + RXrptr);
ian@0 2552 break;
ian@0 2553 }
ian@0 2554 if (++pageno == epage)
ian@0 2555 pageno = spage;
ian@0 2556 pageofs = 0;
ian@0 2557 } while (1);
ian@0 2558 }
ian@0 2559 if ((readb(ofsAddr + FlagStat) & Xoff_state) && (remain < LowWater)) {
ian@0 2560 moxaLowWaterChk = 1;
ian@0 2561 moxaLowChkFlag[port] = 1;
ian@0 2562 }
ian@0 2563 return (total);
ian@0 2564 }
ian@0 2565
ian@0 2566
ian@0 2567 int MoxaPortTxQueue(int port)
ian@0 2568 {
ian@0 2569 void __iomem *ofsAddr;
ian@0 2570 ushort rptr, wptr, mask;
ian@0 2571 int len;
ian@0 2572
ian@0 2573 ofsAddr = moxaTableAddr[port];
ian@0 2574 rptr = readw(ofsAddr + TXrptr);
ian@0 2575 wptr = readw(ofsAddr + TXwptr);
ian@0 2576 mask = readw(ofsAddr + TX_mask);
ian@0 2577 len = (wptr - rptr) & mask;
ian@0 2578 return (len);
ian@0 2579 }
ian@0 2580
ian@0 2581 int MoxaPortTxFree(int port)
ian@0 2582 {
ian@0 2583 void __iomem *ofsAddr;
ian@0 2584 ushort rptr, wptr, mask;
ian@0 2585 int len;
ian@0 2586
ian@0 2587 ofsAddr = moxaTableAddr[port];
ian@0 2588 rptr = readw(ofsAddr + TXrptr);
ian@0 2589 wptr = readw(ofsAddr + TXwptr);
ian@0 2590 mask = readw(ofsAddr + TX_mask);
ian@0 2591 len = mask - ((wptr - rptr) & mask);
ian@0 2592 return (len);
ian@0 2593 }
ian@0 2594
ian@0 2595 int MoxaPortRxQueue(int port)
ian@0 2596 {
ian@0 2597 void __iomem *ofsAddr;
ian@0 2598 ushort rptr, wptr, mask;
ian@0 2599 int len;
ian@0 2600
ian@0 2601 ofsAddr = moxaTableAddr[port];
ian@0 2602 rptr = readw(ofsAddr + RXrptr);
ian@0 2603 wptr = readw(ofsAddr + RXwptr);
ian@0 2604 mask = readw(ofsAddr + RX_mask);
ian@0 2605 len = (wptr - rptr) & mask;
ian@0 2606 return (len);
ian@0 2607 }
ian@0 2608
ian@0 2609
ian@0 2610 void MoxaPortTxDisable(int port)
ian@0 2611 {
ian@0 2612 void __iomem *ofsAddr;
ian@0 2613
ian@0 2614 ofsAddr = moxaTableAddr[port];
ian@0 2615 moxafunc(ofsAddr, FC_SetXoffState, Magic_code);
ian@0 2616 }
ian@0 2617
ian@0 2618 void MoxaPortTxEnable(int port)
ian@0 2619 {
ian@0 2620 void __iomem *ofsAddr;
ian@0 2621
ian@0 2622 ofsAddr = moxaTableAddr[port];
ian@0 2623 moxafunc(ofsAddr, FC_SetXonState, Magic_code);
ian@0 2624 }
ian@0 2625
ian@0 2626
ian@0 2627 int MoxaPortResetBrkCnt(int port)
ian@0 2628 {
ian@0 2629 ushort cnt;
ian@0 2630 cnt = moxaBreakCnt[port];
ian@0 2631 moxaBreakCnt[port] = 0;
ian@0 2632 return (cnt);
ian@0 2633 }
ian@0 2634
ian@0 2635
ian@0 2636 void MoxaPortSendBreak(int port, int ms100)
ian@0 2637 {
ian@0 2638 void __iomem *ofsAddr;
ian@0 2639
ian@0 2640 ofsAddr = moxaTableAddr[port];
ian@0 2641 if (ms100) {
ian@0 2642 moxafunc(ofsAddr, FC_SendBreak, Magic_code);
ian@0 2643 moxadelay(ms100 * (HZ / 10));
ian@0 2644 } else {
ian@0 2645 moxafunc(ofsAddr, FC_SendBreak, Magic_code);
ian@0 2646 moxadelay(HZ / 4); /* 250 ms */
ian@0 2647 }
ian@0 2648 moxafunc(ofsAddr, FC_StopBreak, Magic_code);
ian@0 2649 }
ian@0 2650
ian@0 2651 static int moxa_get_serial_info(struct moxa_str *info,
ian@0 2652 struct serial_struct __user *retinfo)
ian@0 2653 {
ian@0 2654 struct serial_struct tmp;
ian@0 2655
ian@0 2656 memset(&tmp, 0, sizeof(tmp));
ian@0 2657 tmp.type = info->type;
ian@0 2658 tmp.line = info->port;
ian@0 2659 tmp.port = 0;
ian@0 2660 tmp.irq = 0;
ian@0 2661 tmp.flags = info->asyncflags;
ian@0 2662 tmp.baud_base = 921600;
ian@0 2663 tmp.close_delay = info->close_delay;
ian@0 2664 tmp.closing_wait = info->closing_wait;
ian@0 2665 tmp.custom_divisor = 0;
ian@0 2666 tmp.hub6 = 0;
ian@0 2667 if(copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
ian@0 2668 return -EFAULT;
ian@0 2669 return (0);
ian@0 2670 }
ian@0 2671
ian@0 2672
ian@0 2673 static int moxa_set_serial_info(struct moxa_str *info,
ian@0 2674 struct serial_struct __user *new_info)
ian@0 2675 {
ian@0 2676 struct serial_struct new_serial;
ian@0 2677
ian@0 2678 if(copy_from_user(&new_serial, new_info, sizeof(new_serial)))
ian@0 2679 return -EFAULT;
ian@0 2680
ian@0 2681 if ((new_serial.irq != 0) ||
ian@0 2682 (new_serial.port != 0) ||
ian@0 2683 // (new_serial.type != info->type) ||
ian@0 2684 (new_serial.custom_divisor != 0) ||
ian@0 2685 (new_serial.baud_base != 921600))
ian@0 2686 return (-EPERM);
ian@0 2687
ian@0 2688 if (!capable(CAP_SYS_ADMIN)) {
ian@0 2689 if (((new_serial.flags & ~ASYNC_USR_MASK) !=
ian@0 2690 (info->asyncflags & ~ASYNC_USR_MASK)))
ian@0 2691 return (-EPERM);
ian@0 2692 } else {
ian@0 2693 info->close_delay = new_serial.close_delay * HZ / 100;
ian@0 2694 info->closing_wait = new_serial.closing_wait * HZ / 100;
ian@0 2695 }
ian@0 2696
ian@0 2697 new_serial.flags = (new_serial.flags & ~ASYNC_FLAGS);
ian@0 2698 new_serial.flags |= (info->asyncflags & ASYNC_FLAGS);
ian@0 2699
ian@0 2700 if (new_serial.type == PORT_16550A) {
ian@0 2701 MoxaSetFifo(info->port, 1);
ian@0 2702 } else {
ian@0 2703 MoxaSetFifo(info->port, 0);
ian@0 2704 }
ian@0 2705
ian@0 2706 info->type = new_serial.type;
ian@0 2707 return (0);
ian@0 2708 }
ian@0 2709
ian@0 2710
ian@0 2711
ian@0 2712 /*****************************************************************************
ian@0 2713 * Static local functions: *
ian@0 2714 *****************************************************************************/
ian@0 2715 /*
ian@0 2716 * moxadelay - delays a specified number ticks
ian@0 2717 */
ian@0 2718 static void moxadelay(int tick)
ian@0 2719 {
ian@0 2720 unsigned long st, et;
ian@0 2721
ian@0 2722 st = jiffies;
ian@0 2723 et = st + tick;
ian@0 2724 while (time_before(jiffies, et));
ian@0 2725 }
ian@0 2726
ian@0 2727 static void moxafunc(void __iomem *ofsAddr, int cmd, ushort arg)
ian@0 2728 {
ian@0 2729
ian@0 2730 writew(arg, ofsAddr + FuncArg);
ian@0 2731 writew(cmd, ofsAddr + FuncCode);
ian@0 2732 wait_finish(ofsAddr);
ian@0 2733 }
ian@0 2734
ian@0 2735 static void wait_finish(void __iomem *ofsAddr)
ian@0 2736 {
ian@0 2737 unsigned long i, j;
ian@0 2738
ian@0 2739 i = jiffies;
ian@0 2740 while (readw(ofsAddr + FuncCode) != 0) {
ian@0 2741 j = jiffies;
ian@0 2742 if ((j - i) > moxaFuncTout) {
ian@0 2743 return;
ian@0 2744 }
ian@0 2745 }
ian@0 2746 }
ian@0 2747
ian@0 2748 static void low_water_check(void __iomem *ofsAddr)
ian@0 2749 {
ian@0 2750 int len;
ian@0 2751 ushort rptr, wptr, mask;
ian@0 2752
ian@0 2753 if (readb(ofsAddr + FlagStat) & Xoff_state) {
ian@0 2754 rptr = readw(ofsAddr + RXrptr);
ian@0 2755 wptr = readw(ofsAddr + RXwptr);
ian@0 2756 mask = readw(ofsAddr + RX_mask);
ian@0 2757 len = (wptr - rptr) & mask;
ian@0 2758 if (len <= Low_water)
ian@0 2759 moxafunc(ofsAddr, FC_SendXon, 0);
ian@0 2760 }
ian@0 2761 }
ian@0 2762
ian@0 2763 static int moxaloadbios(int cardno, unsigned char __user *tmp, int len)
ian@0 2764 {
ian@0 2765 void __iomem *baseAddr;
ian@0 2766 int i;
ian@0 2767
ian@0 2768 if(copy_from_user(moxaBuff, tmp, len))
ian@0 2769 return -EFAULT;
ian@0 2770 baseAddr = moxaBaseAddr[cardno];
ian@0 2771 writeb(HW_reset, baseAddr + Control_reg); /* reset */
ian@0 2772 moxadelay(1); /* delay 10 ms */
ian@0 2773 for (i = 0; i < 4096; i++)
ian@0 2774 writeb(0, baseAddr + i); /* clear fix page */
ian@0 2775 for (i = 0; i < len; i++)
ian@0 2776 writeb(moxaBuff[i], baseAddr + i); /* download BIOS */
ian@0 2777 writeb(0, baseAddr + Control_reg); /* restart */
ian@0 2778 return (0);
ian@0 2779 }
ian@0 2780
ian@0 2781 static int moxafindcard(int cardno)
ian@0 2782 {
ian@0 2783 void __iomem *baseAddr;
ian@0 2784 ushort tmp;
ian@0 2785
ian@0 2786 baseAddr = moxaBaseAddr[cardno];
ian@0 2787 switch (moxa_boards[cardno].boardType) {
ian@0 2788 case MOXA_BOARD_C218_ISA:
ian@0 2789 case MOXA_BOARD_C218_PCI:
ian@0 2790 if ((tmp = readw(baseAddr + C218_key)) != C218_KeyCode) {
ian@0 2791 return (-1);
ian@0 2792 }
ian@0 2793 break;
ian@0 2794 case MOXA_BOARD_CP204J:
ian@0 2795 if ((tmp = readw(baseAddr + C218_key)) != CP204J_KeyCode) {
ian@0 2796 return (-1);
ian@0 2797 }
ian@0 2798 break;
ian@0 2799 default:
ian@0 2800 if ((tmp = readw(baseAddr + C320_key)) != C320_KeyCode) {
ian@0 2801 return (-1);
ian@0 2802 }
ian@0 2803 if ((tmp = readw(baseAddr + C320_status)) != STS_init) {
ian@0 2804 return (-2);
ian@0 2805 }
ian@0 2806 }
ian@0 2807 return (0);
ian@0 2808 }
ian@0 2809
ian@0 2810 static int moxaload320b(int cardno, unsigned char __user *tmp, int len)
ian@0 2811 {
ian@0 2812 void __iomem *baseAddr;
ian@0 2813 int i;
ian@0 2814
ian@0 2815 if(len > sizeof(moxaBuff))
ian@0 2816 return -EINVAL;
ian@0 2817 if(copy_from_user(moxaBuff, tmp, len))
ian@0 2818 return -EFAULT;
ian@0 2819 baseAddr = moxaBaseAddr[cardno];
ian@0 2820 writew(len - 7168 - 2, baseAddr + C320bapi_len);
ian@0 2821 writeb(1, baseAddr + Control_reg); /* Select Page 1 */
ian@0 2822 for (i = 0; i < 7168; i++)
ian@0 2823 writeb(moxaBuff[i], baseAddr + DynPage_addr + i);
ian@0 2824 writeb(2, baseAddr + Control_reg); /* Select Page 2 */
ian@0 2825 for (i = 0; i < (len - 7168); i++)
ian@0 2826 writeb(moxaBuff[i + 7168], baseAddr + DynPage_addr + i);
ian@0 2827 return (0);
ian@0 2828 }
ian@0 2829
ian@0 2830 static int moxaloadcode(int cardno, unsigned char __user *tmp, int len)
ian@0 2831 {
ian@0 2832 void __iomem *baseAddr, *ofsAddr;
ian@0 2833 int retval, port, i;
ian@0 2834
ian@0 2835 if(copy_from_user(moxaBuff, tmp, len))
ian@0 2836 return -EFAULT;
ian@0 2837 baseAddr = moxaBaseAddr[cardno];
ian@0 2838 switch (moxa_boards[cardno].boardType) {
ian@0 2839 case MOXA_BOARD_C218_ISA:
ian@0 2840 case MOXA_BOARD_C218_PCI:
ian@0 2841 case MOXA_BOARD_CP204J:
ian@0 2842 retval = moxaloadc218(cardno, baseAddr, len);
ian@0 2843 if (retval)
ian@0 2844 return (retval);
ian@0 2845 port = cardno * MAX_PORTS_PER_BOARD;
ian@0 2846 for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) {
ian@0 2847 moxaChkPort[port] = 1;
ian@0 2848 moxaCurBaud[port] = 9600L;
ian@0 2849 moxaDCDState[port] = 0;
ian@0 2850 moxaTableAddr[port] = baseAddr + Extern_table + Extern_size * i;
ian@0 2851 ofsAddr = moxaTableAddr[port];
ian@0 2852 writew(C218rx_mask, ofsAddr + RX_mask);
ian@0 2853 writew(C218tx_mask, ofsAddr + TX_mask);
ian@0 2854 writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb);
ian@0 2855 writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb);
ian@0 2856
ian@0 2857 writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb);
ian@0 2858 writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb);
ian@0 2859
ian@0 2860 }
ian@0 2861 break;
ian@0 2862 default:
ian@0 2863 retval = moxaloadc320(cardno, baseAddr, len,
ian@0 2864 &moxa_boards[cardno].numPorts);
ian@0 2865 if (retval)
ian@0 2866 return (retval);
ian@0 2867 port = cardno * MAX_PORTS_PER_BOARD;
ian@0 2868 for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) {
ian@0 2869 moxaChkPort[port] = 1;
ian@0 2870 moxaCurBaud[port] = 9600L;
ian@0 2871 moxaDCDState[port] = 0;
ian@0 2872 moxaTableAddr[port] = baseAddr + Extern_table + Extern_size * i;
ian@0 2873 ofsAddr = moxaTableAddr[port];
ian@0 2874 if (moxa_boards[cardno].numPorts == 8) {
ian@0 2875 writew(C320p8rx_mask, ofsAddr + RX_mask);
ian@0 2876 writew(C320p8tx_mask, ofsAddr + TX_mask);
ian@0 2877 writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb);
ian@0 2878 writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb);
ian@0 2879 writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb);
ian@0 2880 writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb);
ian@0 2881
ian@0 2882 } else if (moxa_boards[cardno].numPorts == 16) {
ian@0 2883 writew(C320p16rx_mask, ofsAddr + RX_mask);
ian@0 2884 writew(C320p16tx_mask, ofsAddr + TX_mask);
ian@0 2885 writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb);
ian@0 2886 writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb);
ian@0 2887 writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb);
ian@0 2888 writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb);
ian@0 2889
ian@0 2890 } else if (moxa_boards[cardno].numPorts == 24) {
ian@0 2891 writew(C320p24rx_mask, ofsAddr + RX_mask);
ian@0 2892 writew(C320p24tx_mask, ofsAddr + TX_mask);
ian@0 2893 writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb);
ian@0 2894 writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb);
ian@0 2895 writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb);
ian@0 2896 writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
ian@0 2897 } else if (moxa_boards[cardno].numPorts == 32) {
ian@0 2898 writew(C320p32rx_mask, ofsAddr + RX_mask);
ian@0 2899 writew(C320p32tx_mask, ofsAddr + TX_mask);
ian@0 2900 writew(C320p32tx_ofs, ofsAddr + Ofs_txb);
ian@0 2901 writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb);
ian@0 2902 writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb);
ian@0 2903 writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb);
ian@0 2904 writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
ian@0 2905 }
ian@0 2906 }
ian@0 2907 break;
ian@0 2908 }
ian@0 2909 loadstat[cardno] = 1;
ian@0 2910 return (0);
ian@0 2911 }
ian@0 2912
ian@0 2913 static int moxaloadc218(int cardno, void __iomem *baseAddr, int len)
ian@0 2914 {
ian@0 2915 char retry;
ian@0 2916 int i, j, len1, len2;
ian@0 2917 ushort usum, *ptr, keycode;
ian@0 2918
ian@0 2919 if (moxa_boards[cardno].boardType == MOXA_BOARD_CP204J)
ian@0 2920 keycode = CP204J_KeyCode;
ian@0 2921 else
ian@0 2922 keycode = C218_KeyCode;
ian@0 2923 usum = 0;
ian@0 2924 len1 = len >> 1;
ian@0 2925 ptr = (ushort *) moxaBuff;
ian@0 2926 for (i = 0; i < len1; i++)
ian@0 2927 usum += le16_to_cpu(*(ptr + i));
ian@0 2928 retry = 0;
ian@0 2929 do {
ian@0 2930 len1 = len >> 1;
ian@0 2931 j = 0;
ian@0 2932 while (len1) {
ian@0 2933 len2 = (len1 > 2048) ? 2048 : len1;
ian@0 2934 len1 -= len2;
ian@0 2935 for (i = 0; i < len2 << 1; i++)
ian@0 2936 writeb(moxaBuff[i + j], baseAddr + C218_LoadBuf + i);
ian@0 2937 j += i;
ian@0 2938
ian@0 2939 writew(len2, baseAddr + C218DLoad_len);
ian@0 2940 writew(0, baseAddr + C218_key);
ian@0 2941 for (i = 0; i < 100; i++) {
ian@0 2942 if (readw(baseAddr + C218_key) == keycode)
ian@0 2943 break;
ian@0 2944 moxadelay(1); /* delay 10 ms */
ian@0 2945 }
ian@0 2946 if (readw(baseAddr + C218_key) != keycode) {
ian@0 2947 return (-1);
ian@0 2948 }
ian@0 2949 }
ian@0 2950 writew(0, baseAddr + C218DLoad_len);
ian@0 2951 writew(usum, baseAddr + C218check_sum);
ian@0 2952 writew(0, baseAddr + C218_key);
ian@0 2953 for (i = 0; i < 100; i++) {
ian@0 2954 if (readw(baseAddr + C218_key) == keycode)
ian@0 2955 break;
ian@0 2956 moxadelay(1); /* delay 10 ms */
ian@0 2957 }
ian@0 2958 retry++;
ian@0 2959 } while ((readb(baseAddr + C218chksum_ok) != 1) && (retry < 3));
ian@0 2960 if (readb(baseAddr + C218chksum_ok) != 1) {
ian@0 2961 return (-1);
ian@0 2962 }
ian@0 2963 writew(0, baseAddr + C218_key);
ian@0 2964 for (i = 0; i < 100; i++) {
ian@0 2965 if (readw(baseAddr + Magic_no) == Magic_code)
ian@0 2966 break;
ian@0 2967 moxadelay(1); /* delay 10 ms */
ian@0 2968 }
ian@0 2969 if (readw(baseAddr + Magic_no) != Magic_code) {
ian@0 2970 return (-1);
ian@0 2971 }
ian@0 2972 writew(1, baseAddr + Disable_IRQ);
ian@0 2973 writew(0, baseAddr + Magic_no);
ian@0 2974 for (i = 0; i < 100; i++) {
ian@0 2975 if (readw(baseAddr + Magic_no) == Magic_code)
ian@0 2976 break;
ian@0 2977 moxadelay(1); /* delay 10 ms */
ian@0 2978 }
ian@0 2979 if (readw(baseAddr + Magic_no) != Magic_code) {
ian@0 2980 return (-1);
ian@0 2981 }
ian@0 2982 moxaCard = 1;
ian@0 2983 moxaIntNdx[cardno] = baseAddr + IRQindex;
ian@0 2984 moxaIntPend[cardno] = baseAddr + IRQpending;
ian@0 2985 moxaIntTable[cardno] = baseAddr + IRQtable;
ian@0 2986 return (0);
ian@0 2987 }
ian@0 2988
ian@0 2989 static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPorts)
ian@0 2990 {
ian@0 2991 ushort usum;
ian@0 2992 int i, j, wlen, len2, retry;
ian@0 2993 ushort *uptr;
ian@0 2994
ian@0 2995 usum = 0;
ian@0 2996 wlen = len >> 1;
ian@0 2997 uptr = (ushort *) moxaBuff;
ian@0 2998 for (i = 0; i < wlen; i++)
ian@0 2999 usum += le16_to_cpu(uptr[i]);
ian@0 3000 retry = 0;
ian@0 3001 j = 0;
ian@0 3002 do {
ian@0 3003 while (wlen) {
ian@0 3004 if (wlen > 2048)
ian@0 3005 len2 = 2048;
ian@0 3006 else
ian@0 3007 len2 = wlen;
ian@0 3008 wlen -= len2;
ian@0 3009 len2 <<= 1;
ian@0 3010 for (i = 0; i < len2; i++)
ian@0 3011 writeb(moxaBuff[j + i], baseAddr + C320_LoadBuf + i);
ian@0 3012 len2 >>= 1;
ian@0 3013 j += i;
ian@0 3014 writew(len2, baseAddr + C320DLoad_len);
ian@0 3015 writew(0, baseAddr + C320_key);
ian@0 3016 for (i = 0; i < 10; i++) {
ian@0 3017 if (readw(baseAddr + C320_key) == C320_KeyCode)
ian@0 3018 break;
ian@0 3019 moxadelay(1);
ian@0 3020 }
ian@0 3021 if (readw(baseAddr + C320_key) != C320_KeyCode)
ian@0 3022 return (-1);
ian@0 3023 }
ian@0 3024 writew(0, baseAddr + C320DLoad_len);
ian@0 3025 writew(usum, baseAddr + C320check_sum);
ian@0 3026 writew(0, baseAddr + C320_key);
ian@0 3027 for (i = 0; i < 10; i++) {
ian@0 3028 if (readw(baseAddr + C320_key) == C320_KeyCode)
ian@0 3029 break;
ian@0 3030 moxadelay(1);
ian@0 3031 }
ian@0 3032 retry++;
ian@0 3033 } while ((readb(baseAddr + C320chksum_ok) != 1) && (retry < 3));
ian@0 3034 if (readb(baseAddr + C320chksum_ok) != 1)
ian@0 3035 return (-1);
ian@0 3036 writew(0, baseAddr + C320_key);
ian@0 3037 for (i = 0; i < 600; i++) {
ian@0 3038 if (readw(baseAddr + Magic_no) == Magic_code)
ian@0 3039 break;
ian@0 3040 moxadelay(1);
ian@0 3041 }
ian@0 3042 if (readw(baseAddr + Magic_no) != Magic_code)
ian@0 3043 return (-100);
ian@0 3044
ian@0 3045 if (moxa_boards[cardno].busType == MOXA_BUS_TYPE_PCI) { /* ASIC board */
ian@0 3046 writew(0x3800, baseAddr + TMS320_PORT1);
ian@0 3047 writew(0x3900, baseAddr + TMS320_PORT2);
ian@0 3048 writew(28499, baseAddr + TMS320_CLOCK);
ian@0 3049 } else {
ian@0 3050 writew(0x3200, baseAddr + TMS320_PORT1);
ian@0 3051 writew(0x3400, baseAddr + TMS320_PORT2);
ian@0 3052 writew(19999, baseAddr + TMS320_CLOCK);
ian@0 3053 }
ian@0 3054 writew(1, baseAddr + Disable_IRQ);
ian@0 3055 writew(0, baseAddr + Magic_no);
ian@0 3056 for (i = 0; i < 500; i++) {
ian@0 3057 if (readw(baseAddr + Magic_no) == Magic_code)
ian@0 3058 break;
ian@0 3059 moxadelay(1);
ian@0 3060 }
ian@0 3061 if (readw(baseAddr + Magic_no) != Magic_code)
ian@0 3062 return (-102);
ian@0 3063
ian@0 3064 j = readw(baseAddr + Module_cnt);
ian@0 3065 if (j <= 0)
ian@0 3066 return (-101);
ian@0 3067 *numPorts = j * 8;
ian@0 3068 writew(j, baseAddr + Module_no);
ian@0 3069 writew(0, baseAddr + Magic_no);
ian@0 3070 for (i = 0; i < 600; i++) {
ian@0 3071 if (readw(baseAddr + Magic_no) == Magic_code)
ian@0 3072 break;
ian@0 3073 moxadelay(1);
ian@0 3074 }
ian@0 3075 if (readw(baseAddr + Magic_no) != Magic_code)
ian@0 3076 return (-102);
ian@0 3077 moxaCard = 1;
ian@0 3078 moxaIntNdx[cardno] = baseAddr + IRQindex;
ian@0 3079 moxaIntPend[cardno] = baseAddr + IRQpending;
ian@0 3080 moxaIntTable[cardno] = baseAddr + IRQtable;
ian@0 3081 return (0);
ian@0 3082 }
ian@0 3083
ian@0 3084 #if 0
ian@0 3085 long MoxaPortGetCurBaud(int port)
ian@0 3086 {
ian@0 3087
ian@0 3088 if (moxaChkPort[port] == 0)
ian@0 3089 return (0);
ian@0 3090 return (moxaCurBaud[port]);
ian@0 3091 }
ian@0 3092 #endif /* 0 */
ian@0 3093
ian@0 3094 static void MoxaSetFifo(int port, int enable)
ian@0 3095 {
ian@0 3096 void __iomem *ofsAddr = moxaTableAddr[port];
ian@0 3097
ian@0 3098 if (!enable) {
ian@0 3099 moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0);
ian@0 3100 moxafunc(ofsAddr, FC_SetTxFIFOCnt, 1);
ian@0 3101 } else {
ian@0 3102 moxafunc(ofsAddr, FC_SetRxFIFOTrig, 3);
ian@0 3103 moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16);
ian@0 3104 }
ian@0 3105 }
ian@0 3106
ian@0 3107 #if 0
ian@0 3108 int MoxaPortSetMode(int port, int databits, int stopbits, int parity)
ian@0 3109 {
ian@0 3110 void __iomem *ofsAddr;
ian@0 3111 int val;
ian@0 3112
ian@0 3113 val = 0;
ian@0 3114 switch (databits) {
ian@0 3115 case 5:
ian@0 3116 val |= 0;
ian@0 3117 break;
ian@0 3118 case 6:
ian@0 3119 val |= 1;
ian@0 3120 break;
ian@0 3121 case 7:
ian@0 3122 val |= 2;
ian@0 3123 break;
ian@0 3124 case 8:
ian@0 3125 val |= 3;
ian@0 3126 break;
ian@0 3127 default:
ian@0 3128 return (-1);
ian@0 3129 }
ian@0 3130 switch (stopbits) {
ian@0 3131 case 0:
ian@0 3132 val |= 0;
ian@0 3133 break; /* stop bits 1.5 */
ian@0 3134 case 1:
ian@0 3135 val |= 0;
ian@0 3136 break;
ian@0 3137 case 2:
ian@0 3138 val |= 4;
ian@0 3139 break;
ian@0 3140 default:
ian@0 3141 return (-1);
ian@0 3142 }
ian@0 3143 switch (parity) {
ian@0 3144 case 0:
ian@0 3145 val |= 0x00;
ian@0 3146 break; /* None */
ian@0 3147 case 1:
ian@0 3148 val |= 0x08;
ian@0 3149 break; /* Odd */
ian@0 3150 case 2:
ian@0 3151 val |= 0x18;
ian@0 3152 break; /* Even */
ian@0 3153 case 3:
ian@0 3154 val |= 0x28;
ian@0 3155 break; /* Mark */
ian@0 3156 case 4:
ian@0 3157 val |= 0x38;
ian@0 3158 break; /* Space */
ian@0 3159 default:
ian@0 3160 return (-1);
ian@0 3161 }
ian@0 3162 ofsAddr = moxaTableAddr[port];
ian@0 3163 moxafunc(ofsAddr, FC_SetMode, val);
ian@0 3164 return (0);
ian@0 3165 }
ian@0 3166
ian@0 3167 int MoxaPortTxBufSize(int port)
ian@0 3168 {
ian@0 3169 void __iomem *ofsAddr;
ian@0 3170 int size;
ian@0 3171
ian@0 3172 ofsAddr = moxaTableAddr[port];
ian@0 3173 size = readw(ofsAddr + TX_mask);
ian@0 3174 return (size);
ian@0 3175 }
ian@0 3176
ian@0 3177 int MoxaPortRxBufSize(int port)
ian@0 3178 {
ian@0 3179 void __iomem *ofsAddr;
ian@0 3180 int size;
ian@0 3181
ian@0 3182 ofsAddr = moxaTableAddr[port];
ian@0 3183 size = readw(ofsAddr + RX_mask);
ian@0 3184 return (size);
ian@0 3185 }
ian@0 3186
ian@0 3187 int MoxaPortRxFree(int port)
ian@0 3188 {
ian@0 3189 void __iomem *ofsAddr;
ian@0 3190 ushort rptr, wptr, mask;
ian@0 3191 int len;
ian@0 3192
ian@0 3193 ofsAddr = moxaTableAddr[port];
ian@0 3194 rptr = readw(ofsAddr + RXrptr);
ian@0 3195 wptr = readw(ofsAddr + RXwptr);
ian@0 3196 mask = readw(ofsAddr + RX_mask);
ian@0 3197 len = mask - ((wptr - rptr) & mask);
ian@0 3198 return (len);
ian@0 3199 }
ian@0 3200 int MoxaPortGetBrkCnt(int port)
ian@0 3201 {
ian@0 3202 return (moxaBreakCnt[port]);
ian@0 3203 }
ian@0 3204
ian@0 3205 void MoxaPortSetXonXoff(int port, int xonValue, int xoffValue)
ian@0 3206 {
ian@0 3207 void __iomem *ofsAddr;
ian@0 3208
ian@0 3209 ofsAddr = moxaTableAddr[port];
ian@0 3210 writew(xonValue, ofsAddr + FuncArg);
ian@0 3211 writew(xoffValue, ofsAddr + FuncArg1);
ian@0 3212 writew(FC_SetXonXoff, ofsAddr + FuncCode);
ian@0 3213 wait_finish(ofsAddr);
ian@0 3214 }
ian@0 3215
ian@0 3216 int MoxaPortIsTxHold(int port)
ian@0 3217 {
ian@0 3218 void __iomem *ofsAddr;
ian@0 3219 int val;
ian@0 3220
ian@0 3221 ofsAddr = moxaTableAddr[port];
ian@0 3222 if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
ian@0 3223 (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
ian@0 3224 moxafunc(ofsAddr, FC_GetCCSR, 0);
ian@0 3225 val = readw(ofsAddr + FuncArg);
ian@0 3226 if (val & 0x04)
ian@0 3227 return (1);
ian@0 3228 } else {
ian@0 3229 if (readw(ofsAddr + FlagStat) & Tx_flowOff)
ian@0 3230 return (1);
ian@0 3231 }
ian@0 3232 return (0);
ian@0 3233 }
ian@0 3234 #endif