linux/drivers/char/ip2/ip2main.c
<<
>>
Prefs
   1/*
   2*
   3*   (c) 1999 by Computone Corporation
   4*
   5********************************************************************************
   6*
   7*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
   8*                serial I/O controllers.
   9*
  10*   DESCRIPTION: Mainline code for the device driver
  11*
  12*******************************************************************************/
  13// ToDo:
  14//
  15// Fix the immediate DSS_NOW problem.
  16// Work over the channel stats return logic in ip2_ipl_ioctl so they
  17//      make sense for all 256 possible channels and so the user space
  18//      utilities will compile and work properly.
  19//
  20// Done:
  21//
  22// 1.2.14       /\/\|=mhw=|\/\/
  23// Added bounds checking to ip2_ipl_ioctl to avoid potential terroristic acts.
  24// Changed the definition of ip2trace to be more consistent with kernel style
  25//      Thanks to Andreas Dilger <adilger@turbolabs.com> for these updates
  26//
  27// 1.2.13       /\/\|=mhw=|\/\/
  28// DEVFS: Renamed ttf/{n} to tts/F{n} and cuf/{n} to cua/F{n} to conform
  29//      to agreed devfs serial device naming convention.
  30//
  31// 1.2.12       /\/\|=mhw=|\/\/
  32// Cleaned up some remove queue cut and paste errors
  33//
  34// 1.2.11       /\/\|=mhw=|\/\/
  35// Clean up potential NULL pointer dereferences
  36// Clean up devfs registration
  37// Add kernel command line parsing for io and irq
  38//      Compile defaults for io and irq are now set in ip2.c not ip2.h!
  39// Reworked poll_only hack for explicit parameter setting
  40//      You must now EXPLICITLY set poll_only = 1 or set all irqs to 0
  41// Merged ip2_loadmain and old_ip2_init
  42// Converted all instances of interruptible_sleep_on into queue calls
  43//      Most of these had no race conditions but better to clean up now
  44//
  45// 1.2.10       /\/\|=mhw=|\/\/
  46// Fixed the bottom half interrupt handler and enabled USE_IQI
  47//      to split the interrupt handler into a formal top-half / bottom-half
  48// Fixed timing window on high speed processors that queued messages to
  49//      the outbound mail fifo faster than the board could handle.
  50//
  51// 1.2.9
  52// Four box EX was barfing on >128k kmalloc, made structure smaller by
  53// reducing output buffer size
  54//
  55// 1.2.8
  56// Device file system support (MHW)
  57//
  58// 1.2.7 
  59// Fixed
  60// Reload of ip2 without unloading ip2main hangs system on cat of /proc/modules
  61//
  62// 1.2.6
  63//Fixes DCD problems
  64//      DCD was not reported when CLOCAL was set on call to TIOCMGET
  65//
  66//Enhancements:
  67//      TIOCMGET requests and waits for status return
  68//      No DSS interrupts enabled except for DCD when needed
  69//
  70// For internal use only
  71//
  72//#define IP2DEBUG_INIT
  73//#define IP2DEBUG_OPEN
  74//#define IP2DEBUG_WRITE
  75//#define IP2DEBUG_READ
  76//#define IP2DEBUG_IOCTL
  77//#define IP2DEBUG_IPL
  78
  79//#define IP2DEBUG_TRACE
  80//#define DEBUG_FIFO
  81
  82/************/
  83/* Includes */
  84/************/
  85
  86#include <linux/ctype.h>
  87#include <linux/string.h>
  88#include <linux/fcntl.h>
  89#include <linux/errno.h>
  90#include <linux/module.h>
  91#include <linux/signal.h>
  92#include <linux/sched.h>
  93#include <linux/timer.h>
  94#include <linux/interrupt.h>
  95#include <linux/pci.h>
  96#include <linux/mm.h>
  97#include <linux/slab.h>
  98#include <linux/major.h>
  99#include <linux/wait.h>
 100#include <linux/device.h>
 101#include <linux/smp_lock.h>
 102#include <linux/firmware.h>
 103#include <linux/platform_device.h>
 104
 105#include <linux/tty.h>
 106#include <linux/tty_flip.h>
 107#include <linux/termios.h>
 108#include <linux/tty_driver.h>
 109#include <linux/serial.h>
 110#include <linux/ptrace.h>
 111#include <linux/ioport.h>
 112
 113#include <linux/cdk.h>
 114#include <linux/comstats.h>
 115#include <linux/delay.h>
 116#include <linux/bitops.h>
 117
 118#include <asm/system.h>
 119#include <asm/io.h>
 120#include <asm/irq.h>
 121
 122#include <linux/vmalloc.h>
 123#include <linux/init.h>
 124
 125#include <asm/uaccess.h>
 126
 127#include "ip2types.h"
 128#include "ip2trace.h"
 129#include "ip2ioctl.h"
 130#include "ip2.h"
 131#include "i2ellis.h"
 132#include "i2lib.h"
 133
 134/*****************
 135 * /proc/ip2mem  *
 136 *****************/
 137
 138#include <linux/proc_fs.h>
 139#include <linux/seq_file.h>
 140
 141static const struct file_operations ip2mem_proc_fops;
 142static const struct file_operations ip2_proc_fops;
 143
 144/********************/
 145/* Type Definitions */
 146/********************/
 147
 148/*************/
 149/* Constants */
 150/*************/
 151
 152/* String constants to identify ourselves */
 153static const char pcName[] = "Computone IntelliPort Plus multiport driver";
 154static const char pcVersion[] = "1.2.14";
 155
 156/* String constants for port names */
 157static const char pcDriver_name[] = "ip2";
 158static const char pcIpl[] = "ip2ipl";
 159
 160/***********************/
 161/* Function Prototypes */
 162/***********************/
 163
 164/* Global module entry functions */
 165
 166/* Private (static) functions */
 167static int  ip2_open(PTTY, struct file *);
 168static void ip2_close(PTTY, struct file *);
 169static int  ip2_write(PTTY, const unsigned char *, int);
 170static int  ip2_putchar(PTTY, unsigned char);
 171static void ip2_flush_chars(PTTY);
 172static int  ip2_write_room(PTTY);
 173static int  ip2_chars_in_buf(PTTY);
 174static void ip2_flush_buffer(PTTY);
 175static int  ip2_ioctl(PTTY, struct file *, UINT, ULONG);
 176static void ip2_set_termios(PTTY, struct ktermios *);
 177static void ip2_set_line_discipline(PTTY);
 178static void ip2_throttle(PTTY);
 179static void ip2_unthrottle(PTTY);
 180static void ip2_stop(PTTY);
 181static void ip2_start(PTTY);
 182static void ip2_hangup(PTTY);
 183static int  ip2_tiocmget(struct tty_struct *tty, struct file *file);
 184static int  ip2_tiocmset(struct tty_struct *tty, struct file *file,
 185                         unsigned int set, unsigned int clear);
 186
 187static void set_irq(int, int);
 188static void ip2_interrupt_bh(struct work_struct *work);
 189static irqreturn_t ip2_interrupt(int irq, void *dev_id);
 190static void ip2_poll(unsigned long arg);
 191static inline void service_all_boards(void);
 192static void do_input(struct work_struct *);
 193static void do_status(struct work_struct *);
 194
 195static void ip2_wait_until_sent(PTTY,int);
 196
 197static void set_params (i2ChanStrPtr, struct ktermios *);
 198static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *);
 199static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *);
 200
 201static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *);
 202static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *);
 203static long ip2_ipl_ioctl(struct file *, UINT, ULONG);
 204static int ip2_ipl_open(struct inode *, struct file *);
 205
 206static int DumpTraceBuffer(char __user *, int);
 207static int DumpFifoBuffer( char __user *, int);
 208
 209static void ip2_init_board(int, const struct firmware *);
 210static unsigned short find_eisa_board(int);
 211
 212/***************/
 213/* Static Data */
 214/***************/
 215
 216static struct tty_driver *ip2_tty_driver;
 217
 218/* Here, then is a table of board pointers which the interrupt routine should
 219 * scan through to determine who it must service.
 220 */
 221static unsigned short i2nBoards; // Number of boards here
 222
 223static i2eBordStrPtr i2BoardPtrTable[IP2_MAX_BOARDS];
 224
 225static i2ChanStrPtr  DevTable[IP2_MAX_PORTS];
 226//DevTableMem just used to save addresses for kfree
 227static void  *DevTableMem[IP2_MAX_BOARDS];
 228
 229/* This is the driver descriptor for the ip2ipl device, which is used to
 230 * download the loadware to the boards.
 231 */
 232static const struct file_operations ip2_ipl = {
 233        .owner          = THIS_MODULE,
 234        .read           = ip2_ipl_read,
 235        .write          = ip2_ipl_write,
 236        .unlocked_ioctl = ip2_ipl_ioctl,
 237        .open           = ip2_ipl_open,
 238}; 
 239
 240static unsigned long irq_counter;
 241static unsigned long bh_counter;
 242
 243// Use immediate queue to service interrupts
 244#define USE_IQI
 245//#define USE_IQ        // PCI&2.2 needs work
 246
 247/* The timer_list entry for our poll routine. If interrupt operation is not
 248 * selected, the board is serviced periodically to see if anything needs doing.
 249 */
 250#define  POLL_TIMEOUT   (jiffies + 1)
 251static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0);
 252
 253#ifdef IP2DEBUG_TRACE
 254/* Trace (debug) buffer data */
 255#define TRACEMAX  1000
 256static unsigned long tracebuf[TRACEMAX];
 257static int tracestuff;
 258static int tracestrip;
 259static int tracewrap;
 260#endif
 261
 262/**********/
 263/* Macros */
 264/**********/
 265
 266#if defined(MODULE) && defined(IP2DEBUG_OPEN)
 267#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \
 268                    tty->name,(pCh->flags), \
 269                    tty->count,/*GET_USE_COUNT(module)*/0,s)
 270#else
 271#define DBG_CNT(s)
 272#endif
 273
 274/********/
 275/* Code */
 276/********/
 277
 278#include "i2ellis.c"    /* Extremely low-level interface services */
 279#include "i2cmd.c"      /* Standard loadware command definitions */
 280#include "i2lib.c"      /* High level interface services */
 281
 282/* Configuration area for modprobe */
 283
 284MODULE_AUTHOR("Doug McNash");
 285MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
 286MODULE_LICENSE("GPL");
 287
 288static int poll_only;
 289
 290static int Eisa_irq;
 291static int Eisa_slot;
 292
 293static int iindx;
 294static char rirqs[IP2_MAX_BOARDS];
 295static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
 296
 297/* Note: Add compiled in defaults to these arrays, not to the structure
 298        in ip2.h any longer.  That structure WILL get overridden
 299        by these values, or command line values, or insmod values!!!  =mhw=
 300*/
 301static int io[IP2_MAX_BOARDS];
 302static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 };
 303
 304MODULE_AUTHOR("Doug McNash");
 305MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
 306module_param_array(irq, int, NULL, 0);
 307MODULE_PARM_DESC(irq, "Interrupts for IntelliPort Cards");
 308module_param_array(io, int, NULL, 0);
 309MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards");
 310module_param(poll_only, bool, 0);
 311MODULE_PARM_DESC(poll_only, "Do not use card interrupts");
 312
 313/* for sysfs class support */
 314static struct class *ip2_class;
 315
 316/* Some functions to keep track of what irqs we have */
 317
 318static int __init is_valid_irq(int irq)
 319{
 320        int *i = Valid_Irqs;
 321        
 322        while (*i != 0 && *i != irq)
 323                i++;
 324
 325        return *i;
 326}
 327
 328static void __init mark_requested_irq(char irq)
 329{
 330        rirqs[iindx++] = irq;
 331}
 332
 333static int __exit clear_requested_irq(char irq)
 334{
 335        int i;
 336        for (i = 0; i < IP2_MAX_BOARDS; ++i) {
 337                if (rirqs[i] == irq) {
 338                        rirqs[i] = 0;
 339                        return 1;
 340                }
 341        }
 342        return 0;
 343}
 344
 345static int have_requested_irq(char irq)
 346{
 347        /* array init to zeros so 0 irq will not be requested as a side
 348         * effect */
 349        int i;
 350        for (i = 0; i < IP2_MAX_BOARDS; ++i)
 351                if (rirqs[i] == irq)
 352                        return 1;
 353        return 0;
 354}
 355
 356/******************************************************************************/
 357/* Function:   cleanup_module()                                               */
 358/* Parameters: None                                                           */
 359/* Returns:    Nothing                                                        */
 360/*                                                                            */
 361/* Description:                                                               */
 362/* This is a required entry point for an installable module. It has to return */
 363/* the device and the driver to a passive state. It should not be necessary   */
 364/* to reset the board fully, especially as the loadware is downloaded         */
 365/* externally rather than in the driver. We just want to disable the board    */
 366/* and clear the loadware to a reset state. To allow this there has to be a   */
 367/* way to detect whether the board has the loadware running at init time to   */
 368/* handle subsequent installations of the driver. All memory allocated by the */
 369/* driver should be returned since it may be unloaded from memory.            */
 370/******************************************************************************/
 371static void __exit ip2_cleanup_module(void)
 372{
 373        int err;
 374        int i;
 375
 376        del_timer_sync(&PollTimer);
 377
 378        /* Reset the boards we have. */
 379        for (i = 0; i < IP2_MAX_BOARDS; i++)
 380                if (i2BoardPtrTable[i])
 381                        iiReset(i2BoardPtrTable[i]);
 382
 383        /* The following is done at most once, if any boards were installed. */
 384        for (i = 0; i < IP2_MAX_BOARDS; i++) {
 385                if (i2BoardPtrTable[i]) {
 386                        iiResetDelay(i2BoardPtrTable[i]);
 387                        /* free io addresses and Tibet */
 388                        release_region(ip2config.addr[i], 8);
 389                        device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
 390                        device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR,
 391                                                4 * i + 1));
 392                }
 393                /* Disable and remove interrupt handler. */
 394                if (ip2config.irq[i] > 0 &&
 395                                have_requested_irq(ip2config.irq[i])) {
 396                        free_irq(ip2config.irq[i], (void *)&pcName);
 397                        clear_requested_irq(ip2config.irq[i]);
 398                }
 399        }
 400        class_destroy(ip2_class);
 401        err = tty_unregister_driver(ip2_tty_driver);
 402        if (err)
 403                printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n",
 404                                err);
 405        put_tty_driver(ip2_tty_driver);
 406        unregister_chrdev(IP2_IPL_MAJOR, pcIpl);
 407        remove_proc_entry("ip2mem", NULL);
 408
 409        /* free memory */
 410        for (i = 0; i < IP2_MAX_BOARDS; i++) {
 411                void *pB;
 412#ifdef CONFIG_PCI
 413                if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) {
 414                        pci_disable_device(ip2config.pci_dev[i]);
 415                        pci_dev_put(ip2config.pci_dev[i]);
 416                        ip2config.pci_dev[i] = NULL;
 417                }
 418#endif
 419                pB = i2BoardPtrTable[i];
 420                if (pB != NULL) {
 421                        kfree(pB);
 422                        i2BoardPtrTable[i] = NULL;
 423                }
 424                if (DevTableMem[i] != NULL) {
 425                        kfree(DevTableMem[i]);
 426                        DevTableMem[i] = NULL;
 427                }
 428        }
 429}
 430module_exit(ip2_cleanup_module);
 431
 432static const struct tty_operations ip2_ops = {
 433        .open            = ip2_open,
 434        .close           = ip2_close,
 435        .write           = ip2_write,
 436        .put_char        = ip2_putchar,
 437        .flush_chars     = ip2_flush_chars,
 438        .write_room      = ip2_write_room,
 439        .chars_in_buffer = ip2_chars_in_buf,
 440        .flush_buffer    = ip2_flush_buffer,
 441        .ioctl           = ip2_ioctl,
 442        .throttle        = ip2_throttle,
 443        .unthrottle      = ip2_unthrottle,
 444        .set_termios     = ip2_set_termios,
 445        .set_ldisc       = ip2_set_line_discipline,
 446        .stop            = ip2_stop,
 447        .start           = ip2_start,
 448        .hangup          = ip2_hangup,
 449        .tiocmget        = ip2_tiocmget,
 450        .tiocmset        = ip2_tiocmset,
 451        .proc_fops       = &ip2_proc_fops,
 452};
 453
 454/******************************************************************************/
 455/* Function:   ip2_loadmain()                                                 */
 456/* Parameters: irq, io from command line of insmod et. al.                    */
 457/*              pointer to fip firmware and firmware size for boards          */
 458/* Returns:    Success (0)                                                    */
 459/*                                                                            */
 460/* Description:                                                               */
 461/* This was the required entry point for all drivers (now in ip2.c)           */
 462/* It performs all                                                            */
 463/* initialisation of the devices and driver structures, and registers itself  */
 464/* with the relevant kernel modules.                                          */
 465/******************************************************************************/
 466/* IRQF_DISABLED - if set blocks all interrupts else only this line */
 467/* IRQF_SHARED    - for shared irq PCI or maybe EISA only */
 468/* SA_RANDOM   - can be source for cert. random number generators */
 469#define IP2_SA_FLAGS    0
 470
 471
 472static const struct firmware *ip2_request_firmware(void)
 473{
 474        struct platform_device *pdev;
 475        const struct firmware *fw;
 476
 477        pdev = platform_device_register_simple("ip2", 0, NULL, 0);
 478        if (IS_ERR(pdev)) {
 479                printk(KERN_ERR "Failed to register platform device for ip2\n");
 480                return NULL;
 481        }
 482        if (request_firmware(&fw, "intelliport2.bin", &pdev->dev)) {
 483                printk(KERN_ERR "Failed to load firmware 'intelliport2.bin'\n");
 484                fw = NULL;
 485        }
 486        platform_device_unregister(pdev);
 487        return fw;
 488}
 489
 490#ifndef MODULE
 491/******************************************************************************
 492 *      ip2_setup:
 493 *              str: kernel command line string
 494 *
 495 *      Can't autoprobe the boards so user must specify configuration on
 496 *      kernel command line.  Sane people build it modular but the others
 497 *      come here.
 498 *
 499 *      Alternating pairs of io,irq for up to 4 boards.
 500 *              ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
 501 *
 502 *              io=0 => No board
 503 *              io=1 => PCI
 504 *              io=2 => EISA
 505 *              else => ISA I/O address
 506 *
 507 *              irq=0 or invalid for ISA will revert to polling mode
 508 *
 509 *              Any value = -1, do not overwrite compiled in value.
 510 *
 511 ******************************************************************************/
 512static int __init ip2_setup(char *str)
 513{
 514        int j, ints[10];        /* 4 boards, 2 parameters + 2 */
 515        unsigned int i;
 516
 517        str = get_options(str, ARRAY_SIZE(ints), ints);
 518
 519        for (i = 0, j = 1; i < 4; i++) {
 520                if (j > ints[0])
 521                        break;
 522                if (ints[j] >= 0)
 523                        io[i] = ints[j];
 524                j++;
 525                if (j > ints[0])
 526                        break;
 527                if (ints[j] >= 0)
 528                        irq[i] = ints[j];
 529                j++;
 530        }
 531        return 1;
 532}
 533__setup("ip2=", ip2_setup);
 534#endif /* !MODULE */
 535
 536static int __init ip2_loadmain(void)
 537{
 538        int i, j, box;
 539        int err = 0;
 540        i2eBordStrPtr pB = NULL;
 541        int rc = -1;
 542        struct pci_dev *pdev = NULL;
 543        const struct firmware *fw = NULL;
 544
 545        if (poll_only) {
 546                /* Hard lock the interrupts to zero */
 547                irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0;
 548        }
 549
 550        ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0);
 551
 552        /* process command line arguments to modprobe or
 553                insmod i.e. iop & irqp */
 554        /* irqp and iop should ALWAYS be specified now...  But we check
 555                them individually just to be sure, anyways... */
 556        for (i = 0; i < IP2_MAX_BOARDS; ++i) {
 557                ip2config.addr[i] = io[i];
 558                if (irq[i] >= 0)
 559                        ip2config.irq[i] = irq[i];
 560                else
 561                        ip2config.irq[i] = 0;
 562        /* This is a little bit of a hack.  If poll_only=1 on command
 563           line back in ip2.c OR all IRQs on all specified boards are
 564           explicitly set to 0, then drop to poll only mode and override
 565           PCI or EISA interrupts.  This superceeds the old hack of
 566           triggering if all interrupts were zero (like da default).
 567           Still a hack but less prone to random acts of terrorism.
 568
 569           What we really should do, now that the IRQ default is set
 570           to -1, is to use 0 as a hard coded, do not probe.
 571
 572                /\/\|=mhw=|\/\/
 573        */
 574                poll_only |= irq[i];
 575        }
 576        poll_only = !poll_only;
 577
 578        /* Announce our presence */
 579        printk(KERN_INFO "%s version %s\n", pcName, pcVersion);
 580
 581        ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS);
 582        if (!ip2_tty_driver)
 583                return -ENOMEM;
 584
 585        /* Initialise all the boards we can find (up to the maximum). */
 586        for (i = 0; i < IP2_MAX_BOARDS; ++i) {
 587                switch (ip2config.addr[i]) {
 588                case 0: /* skip this slot even if card is present */
 589                        break;
 590                default: /* ISA */
 591                   /* ISA address must be specified */
 592                        if (ip2config.addr[i] < 0x100 ||
 593                                        ip2config.addr[i] > 0x3f8) {
 594                                printk(KERN_ERR "IP2: Bad ISA board %d "
 595                                                "address %x\n", i,
 596                                                ip2config.addr[i]);
 597                                ip2config.addr[i] = 0;
 598                                break;
 599                        }
 600                        ip2config.type[i] = ISA;
 601
 602                        /* Check for valid irq argument, set for polling if
 603                         * invalid */
 604                        if (ip2config.irq[i] &&
 605                                        !is_valid_irq(ip2config.irq[i])) {
 606                                printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",
 607                                                ip2config.irq[i]);
 608                                /* 0 is polling and is valid in that sense */
 609                                ip2config.irq[i] = 0;
 610                        }
 611                        break;
 612                case PCI:
 613#ifdef CONFIG_PCI
 614                {
 615                        u32 addr;
 616                        int status;
 617
 618                        pdev = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
 619                                        PCI_DEVICE_ID_COMPUTONE_IP2EX, pdev);
 620                        if (pdev == NULL) {
 621                                ip2config.addr[i] = 0;
 622                                printk(KERN_ERR "IP2: PCI board %d not "
 623                                                "found\n", i);
 624                                break;
 625                        }
 626
 627                        if (pci_enable_device(pdev)) {
 628                                dev_err(&pdev->dev, "can't enable device\n");
 629                                break;
 630                        }
 631                        ip2config.type[i] = PCI;
 632                        ip2config.pci_dev[i] = pci_dev_get(pdev);
 633                        status = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1,
 634                                        &addr);
 635                        if (addr & 1)
 636                                ip2config.addr[i] = (USHORT)(addr & 0xfffe);
 637                        else
 638                                dev_err(&pdev->dev, "I/O address error\n");
 639
 640                        ip2config.irq[i] = pdev->irq;
 641                }
 642#else
 643                        printk(KERN_ERR "IP2: PCI card specified but PCI "
 644                                        "support not enabled.\n");
 645                        printk(KERN_ERR "IP2: Recompile kernel with CONFIG_PCI "
 646                                        "defined!\n");
 647#endif /* CONFIG_PCI */
 648                        break;
 649                case EISA:
 650                        ip2config.addr[i] = find_eisa_board(Eisa_slot + 1);
 651                        if (ip2config.addr[i] != 0) {
 652                                /* Eisa_irq set as side effect, boo */
 653                                ip2config.type[i] = EISA;
 654                        } 
 655                        ip2config.irq[i] = Eisa_irq;
 656                        break;
 657                }       /* switch */
 658        }       /* for */
 659        pci_dev_put(pdev);
 660
 661        for (i = 0; i < IP2_MAX_BOARDS; ++i) {
 662                if (ip2config.addr[i]) {
 663                        pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL);
 664                        if (pB) {
 665                                i2BoardPtrTable[i] = pB;
 666                                iiSetAddress(pB, ip2config.addr[i],
 667                                                ii2DelayTimer);
 668                                iiReset(pB);
 669                        } else
 670                                printk(KERN_ERR "IP2: board memory allocation "
 671                                                "error\n");
 672                }
 673        }
 674        for (i = 0; i < IP2_MAX_BOARDS; ++i) {
 675                pB = i2BoardPtrTable[i];
 676                if (pB != NULL) {
 677                        iiResetDelay(pB);
 678                        break;
 679                }
 680        }
 681        for (i = 0; i < IP2_MAX_BOARDS; ++i) {
 682                /* We don't want to request the firmware unless we have at
 683                   least one board */
 684                if (i2BoardPtrTable[i] != NULL) {
 685                        if (!fw)
 686                                fw = ip2_request_firmware();
 687                        if (!fw)
 688                                break;
 689                        ip2_init_board(i, fw);
 690                }
 691        }
 692        if (fw)
 693                release_firmware(fw);
 694
 695        ip2trace(ITRC_NO_PORT, ITRC_INIT, 2, 0);
 696
 697        ip2_tty_driver->owner               = THIS_MODULE;
 698        ip2_tty_driver->name                 = "ttyF";
 699        ip2_tty_driver->driver_name          = pcDriver_name;
 700        ip2_tty_driver->major                = IP2_TTY_MAJOR;
 701        ip2_tty_driver->minor_start          = 0;
 702        ip2_tty_driver->type                 = TTY_DRIVER_TYPE_SERIAL;
 703        ip2_tty_driver->subtype              = SERIAL_TYPE_NORMAL;
 704        ip2_tty_driver->init_termios         = tty_std_termios;
 705        ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
 706        ip2_tty_driver->flags                = TTY_DRIVER_REAL_RAW |
 707                TTY_DRIVER_DYNAMIC_DEV;
 708        tty_set_operations(ip2_tty_driver, &ip2_ops);
 709
 710        ip2trace(ITRC_NO_PORT, ITRC_INIT, 3, 0);
 711
 712        err = tty_register_driver(ip2_tty_driver);
 713        if (err) {
 714                printk(KERN_ERR "IP2: failed to register tty driver\n");
 715                put_tty_driver(ip2_tty_driver);
 716                return err; /* leaking resources */
 717        }
 718
 719        err = register_chrdev(IP2_IPL_MAJOR, pcIpl, &ip2_ipl);
 720        if (err) {
 721                printk(KERN_ERR "IP2: failed to register IPL device (%d)\n",
 722                                err);
 723        } else {
 724                /* create the sysfs class */
 725                ip2_class = class_create(THIS_MODULE, "ip2");
 726                if (IS_ERR(ip2_class)) {
 727                        err = PTR_ERR(ip2_class);
 728                        goto out_chrdev;        
 729                }
 730        }
 731        /* Register the read_procmem thing */
 732        if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) {
 733                printk(KERN_ERR "IP2: failed to register read_procmem\n");
 734                return -EIO; /* leaking resources */
 735        }
 736
 737        ip2trace(ITRC_NO_PORT, ITRC_INIT, 4, 0);
 738        /* Register the interrupt handler or poll handler, depending upon the
 739         * specified interrupt.
 740         */
 741
 742        for (i = 0; i < IP2_MAX_BOARDS; ++i) {
 743                if (ip2config.addr[i] == 0)
 744                        continue;
 745
 746                pB = i2BoardPtrTable[i];
 747                if (pB != NULL) {
 748                        device_create(ip2_class, NULL,
 749                                      MKDEV(IP2_IPL_MAJOR, 4 * i),
 750                                      NULL, "ipl%d", i);
 751                        device_create(ip2_class, NULL,
 752                                      MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
 753                                      NULL, "stat%d", i);
 754
 755                        for (box = 0; box < ABS_MAX_BOXES; box++)
 756                                for (j = 0; j < ABS_BIGGEST_BOX; j++)
 757                                        if (pB->i2eChannelMap[box] & (1 << j))
 758                                                tty_register_device(
 759                                                        ip2_tty_driver,
 760                                                        j + ABS_BIGGEST_BOX *
 761                                                        (box+i*ABS_MAX_BOXES),
 762                                                        NULL);
 763                }
 764
 765                if (poll_only) {
 766                        /* Poll only forces driver to only use polling and
 767                           to ignore the probed PCI or EISA interrupts. */
 768                        ip2config.irq[i] = CIR_POLL;
 769                }
 770                if (ip2config.irq[i] == CIR_POLL) {
 771retry:
 772                        if (!timer_pending(&PollTimer)) {
 773                                mod_timer(&PollTimer, POLL_TIMEOUT);
 774                                printk(KERN_INFO "IP2: polling\n");
 775                        }
 776                } else {
 777                        if (have_requested_irq(ip2config.irq[i]))
 778                                continue;
 779                        rc = request_irq(ip2config.irq[i], ip2_interrupt,
 780                                IP2_SA_FLAGS |
 781                                (ip2config.type[i] == PCI ? IRQF_SHARED : 0),
 782                                pcName, i2BoardPtrTable[i]);
 783                        if (rc) {
 784                                printk(KERN_ERR "IP2: request_irq failed: "
 785                                                "error %d\n", rc);
 786                                ip2config.irq[i] = CIR_POLL;
 787                                printk(KERN_INFO "IP2: Polling %ld/sec.\n",
 788                                                (POLL_TIMEOUT - jiffies));
 789                                goto retry;
 790                        }
 791                        mark_requested_irq(ip2config.irq[i]);
 792                        /* Initialise the interrupt handler bottom half
 793                         * (aka slih). */
 794                }
 795        }
 796
 797        for (i = 0; i < IP2_MAX_BOARDS; ++i) {
 798                if (i2BoardPtrTable[i]) {
 799                        /* set and enable board interrupt */
 800                        set_irq(i, ip2config.irq[i]);
 801                }
 802        }
 803
 804        ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0);
 805
 806        return 0;
 807
 808out_chrdev:
 809        unregister_chrdev(IP2_IPL_MAJOR, "ip2");
 810        /* unregister and put tty here */
 811        return err;
 812}
 813module_init(ip2_loadmain);
 814
 815/******************************************************************************/
 816/* Function:   ip2_init_board()                                               */
 817/* Parameters: Index of board in configuration structure                      */
 818/* Returns:    Success (0)                                                    */
 819/*                                                                            */
 820/* Description:                                                               */
 821/* This function initializes the specified board. The loadware is copied to   */
 822/* the board, the channel structures are initialized, and the board details   */
 823/* are reported on the console.                                               */
 824/******************************************************************************/
 825static void
 826ip2_init_board(int boardnum, const struct firmware *fw)
 827{
 828        int i;
 829        int nports = 0, nboxes = 0;
 830        i2ChanStrPtr pCh;
 831        i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
 832
 833        if ( !iiInitialize ( pB ) ) {
 834                printk ( KERN_ERR "IP2: Failed to initialize board at 0x%x, error %d\n",
 835                         pB->i2eBase, pB->i2eError );
 836                goto err_initialize;
 837        }
 838        printk(KERN_INFO "IP2: Board %d: addr=0x%x irq=%d\n", boardnum + 1,
 839               ip2config.addr[boardnum], ip2config.irq[boardnum] );
 840
 841        if (!request_region( ip2config.addr[boardnum], 8, pcName )) {
 842                printk(KERN_ERR "IP2: bad addr=0x%x\n", ip2config.addr[boardnum]);
 843                goto err_initialize;
 844        }
 845
 846        if ( iiDownloadAll ( pB, (loadHdrStrPtr)fw->data, 1, fw->size )
 847            != II_DOWN_GOOD ) {
 848                printk ( KERN_ERR "IP2: failed to download loadware\n" );
 849                goto err_release_region;
 850        } else {
 851                printk ( KERN_INFO "IP2: fv=%d.%d.%d lv=%d.%d.%d\n",
 852                         pB->i2ePom.e.porVersion,
 853                         pB->i2ePom.e.porRevision,
 854                         pB->i2ePom.e.porSubRev, pB->i2eLVersion,
 855                         pB->i2eLRevision, pB->i2eLSub );
 856        }
 857
 858        switch ( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) {
 859
 860        default:
 861                printk( KERN_ERR "IP2: Unknown board type, ID = %x\n",
 862                                pB->i2ePom.e.porID );
 863                nports = 0;
 864                goto err_release_region;
 865                break;
 866
 867        case POR_ID_II_4: /* IntelliPort-II, ISA-4 (4xRJ45) */
 868                printk ( KERN_INFO "IP2: ISA-4\n" );
 869                nports = 4;
 870                break;
 871
 872        case POR_ID_II_8: /* IntelliPort-II, 8-port using standard brick. */
 873                printk ( KERN_INFO "IP2: ISA-8 std\n" );
 874                nports = 8;
 875                break;
 876
 877        case POR_ID_II_8R: /* IntelliPort-II, 8-port using RJ11's (no CTS) */
 878                printk ( KERN_INFO "IP2: ISA-8 RJ11\n" );
 879                nports = 8;
 880                break;
 881
 882        case POR_ID_FIIEX: /* IntelliPort IIEX */
 883        {
 884                int portnum = IP2_PORTS_PER_BOARD * boardnum;
 885                int            box;
 886
 887                for( box = 0; box < ABS_MAX_BOXES; ++box ) {
 888                        if ( pB->i2eChannelMap[box] != 0 ) {
 889                                ++nboxes;
 890                        }
 891                        for( i = 0; i < ABS_BIGGEST_BOX; ++i ) {
 892                                if ( pB->i2eChannelMap[box] & 1<< i ) {
 893                                        ++nports;
 894                                }
 895                        }
 896                }
 897                DevTableMem[boardnum] = pCh =
 898                        kmalloc( sizeof(i2ChanStr) * nports, GFP_KERNEL );
 899                if ( !pCh ) {
 900                        printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n");
 901                        goto err_release_region;
 902                }
 903                if ( !i2InitChannels( pB, nports, pCh ) ) {
 904                        printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError);
 905                        kfree ( pCh );
 906                        goto err_release_region;
 907                }
 908                pB->i2eChannelPtr = &DevTable[portnum];
 909                pB->i2eChannelCnt = ABS_MOST_PORTS;
 910
 911                for( box = 0; box < ABS_MAX_BOXES; ++box, portnum += ABS_BIGGEST_BOX ) {
 912                        for( i = 0; i < ABS_BIGGEST_BOX; ++i ) {
 913                                if ( pB->i2eChannelMap[box] & (1 << i) ) {
 914                                        DevTable[portnum + i] = pCh;
 915                                        pCh->port_index = portnum + i;
 916                                        pCh++;
 917                                }
 918                        }
 919                }
 920                printk(KERN_INFO "IP2: EX box=%d ports=%d %d bit\n",
 921                        nboxes, nports, pB->i2eDataWidth16 ? 16 : 8 );
 922                }
 923                goto ex_exit;
 924        }
 925        DevTableMem[boardnum] = pCh =
 926                kmalloc ( sizeof (i2ChanStr) * nports, GFP_KERNEL );
 927        if ( !pCh ) {
 928                printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n");
 929                goto err_release_region;
 930        }
 931        pB->i2eChannelPtr = pCh;
 932        pB->i2eChannelCnt = nports;
 933        if ( !i2InitChannels( pB, nports, pCh ) ) {
 934                printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError);
 935                kfree ( pCh );
 936                goto err_release_region;
 937        }
 938        pB->i2eChannelPtr = &DevTable[IP2_PORTS_PER_BOARD * boardnum];
 939
 940        for( i = 0; i < pB->i2eChannelCnt; ++i ) {
 941                DevTable[IP2_PORTS_PER_BOARD * boardnum + i] = pCh;
 942                pCh->port_index = (IP2_PORTS_PER_BOARD * boardnum) + i;
 943                pCh++;
 944        }
 945ex_exit:
 946        INIT_WORK(&pB->tqueue_interrupt, ip2_interrupt_bh);
 947        return;
 948
 949err_release_region:
 950        release_region(ip2config.addr[boardnum], 8);
 951err_initialize:
 952        kfree ( pB );
 953        i2BoardPtrTable[boardnum] = NULL;
 954        return;
 955}
 956
 957/******************************************************************************/
 958/* Function:   find_eisa_board ( int start_slot )                             */
 959/* Parameters: First slot to check                                            */
 960/* Returns:    Address of EISA IntelliPort II controller                      */
 961/*                                                                            */
 962/* Description:                                                               */
 963/* This function searches for an EISA IntelliPort controller, starting        */
 964/* from the specified slot number. If the motherboard is not identified as an */
 965/* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */
 966/* it returns the base address of the controller.                             */
 967/******************************************************************************/
 968static unsigned short
 969find_eisa_board( int start_slot )
 970{
 971        int i, j;
 972        unsigned int idm = 0;
 973        unsigned int idp = 0;
 974        unsigned int base = 0;
 975        unsigned int value;
 976        int setup_address;
 977        int setup_irq;
 978        int ismine = 0;
 979
 980        /*
 981         * First a check for an EISA motherboard, which we do by comparing the
 982         * EISA ID registers for the system board and the first couple of slots.
 983         * No slot ID should match the system board ID, but on an ISA or PCI
 984         * machine the odds are that an empty bus will return similar values for
 985         * each slot.
 986         */
 987        i = 0x0c80;
 988        value = (inb(i) << 24) + (inb(i+1) << 16) + (inb(i+2) << 8) + inb(i+3);
 989        for( i = 0x1c80; i <= 0x4c80; i += 0x1000 ) {
 990                j = (inb(i)<<24)+(inb(i+1)<<16)+(inb(i+2)<<8)+inb(i+3);
 991                if ( value == j )
 992                        return 0;
 993        }
 994
 995        /*
 996         * OK, so we are inclined to believe that this is an EISA machine. Find
 997         * an IntelliPort controller.
 998         */
 999        for( i = start_slot; i < 16; i++ ) {
1000                base = i << 12;
1001                idm = (inb(base + 0xc80) << 8) | (inb(base + 0xc81) & 0xff);
1002                idp = (inb(base + 0xc82) << 8) | (inb(base + 0xc83) & 0xff);
1003                ismine = 0;
1004                if ( idm == 0x0e8e ) {
1005                        if ( idp == 0x0281 || idp == 0x0218 ) {
1006                                ismine = 1;
1007                        } else if ( idp == 0x0282 || idp == 0x0283 ) {
1008                                ismine = 3;     /* Can do edge-trigger */
1009                        }
1010                        if ( ismine ) {
1011                                Eisa_slot = i;
1012                                break;
1013                        }
1014                }
1015        }
1016        if ( !ismine )
1017                return 0;
1018
1019        /* It's some sort of EISA card, but at what address is it configured? */
1020
1021        setup_address = base + 0xc88;
1022        value = inb(base + 0xc86);
1023        setup_irq = (value & 8) ? Valid_Irqs[value & 7] : 0;
1024
1025        if ( (ismine & 2) && !(value & 0x10) ) {
1026                ismine = 1;     /* Could be edging, but not */
1027        }
1028
1029        if ( Eisa_irq == 0 ) {
1030                Eisa_irq = setup_irq;
1031        } else if ( Eisa_irq != setup_irq ) {
1032                printk ( KERN_ERR "IP2: EISA irq mismatch between EISA controllers\n" );
1033        }
1034
1035#ifdef IP2DEBUG_INIT
1036printk(KERN_DEBUG "Computone EISA board in slot %d, I.D. 0x%x%x, Address 0x%x",
1037               base >> 12, idm, idp, setup_address);
1038        if ( Eisa_irq ) {
1039                printk(KERN_DEBUG ", Interrupt %d %s\n",
1040                       setup_irq, (ismine & 2) ? "(edge)" : "(level)");
1041        } else {
1042                printk(KERN_DEBUG ", (polled)\n");
1043        }
1044#endif
1045        return setup_address;
1046}
1047
1048/******************************************************************************/
1049/* Function:   set_irq()                                                      */
1050/* Parameters: index to board in board table                                  */
1051/*             IRQ to use                                                     */
1052/* Returns:    Success (0)                                                    */
1053/*                                                                            */
1054/* Description:                                                               */
1055/******************************************************************************/
1056static void
1057set_irq( int boardnum, int boardIrq )
1058{
1059        unsigned char tempCommand[16];
1060        i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
1061        unsigned long flags;
1062
1063        /*
1064         * Notify the boards they may generate interrupts. This is done by
1065         * sending an in-line command to channel 0 on each board. This is why
1066         * the channels have to be defined already. For each board, if the
1067         * interrupt has never been defined, we must do so NOW, directly, since
1068         * board will not send flow control or even give an interrupt until this
1069         * is done.  If polling we must send 0 as the interrupt parameter.
1070         */
1071
1072        // We will get an interrupt here at the end of this function
1073
1074        iiDisableMailIrq(pB);
1075
1076        /* We build up the entire packet header. */
1077        CHANNEL_OF(tempCommand) = 0;
1078        PTYPE_OF(tempCommand) = PTYPE_INLINE;
1079        CMD_COUNT_OF(tempCommand) = 2;
1080        (CMD_OF(tempCommand))[0] = CMDVALUE_IRQ;
1081        (CMD_OF(tempCommand))[1] = boardIrq;
1082        /*
1083         * Write to FIFO; don't bother to adjust fifo capacity for this, since
1084         * board will respond almost immediately after SendMail hit.
1085         */
1086        write_lock_irqsave(&pB->write_fifo_spinlock, flags);
1087        iiWriteBuf(pB, tempCommand, 4);
1088        write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
1089        pB->i2eUsingIrq = boardIrq;
1090        pB->i2eOutMailWaiting |= MB_OUT_STUFFED;
1091
1092        /* Need to update number of boards before you enable mailbox int */
1093        ++i2nBoards;
1094
1095        CHANNEL_OF(tempCommand) = 0;
1096        PTYPE_OF(tempCommand) = PTYPE_BYPASS;
1097        CMD_COUNT_OF(tempCommand) = 6;
1098        (CMD_OF(tempCommand))[0] = 88;  // SILO
1099        (CMD_OF(tempCommand))[1] = 64;  // chars
1100        (CMD_OF(tempCommand))[2] = 32;  // ms
1101
1102        (CMD_OF(tempCommand))[3] = 28;  // MAX_BLOCK
1103        (CMD_OF(tempCommand))[4] = 64;  // chars
1104
1105        (CMD_OF(tempCommand))[5] = 87;  // HW_TEST
1106        write_lock_irqsave(&pB->write_fifo_spinlock, flags);
1107        iiWriteBuf(pB, tempCommand, 8);
1108        write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
1109
1110        CHANNEL_OF(tempCommand) = 0;
1111        PTYPE_OF(tempCommand) = PTYPE_BYPASS;
1112        CMD_COUNT_OF(tempCommand) = 1;
1113        (CMD_OF(tempCommand))[0] = 84;  /* get BOX_IDS */
1114        iiWriteBuf(pB, tempCommand, 3);
1115
1116#ifdef XXX
1117        // enable heartbeat for test porpoises
1118        CHANNEL_OF(tempCommand) = 0;
1119        PTYPE_OF(tempCommand) = PTYPE_BYPASS;
1120        CMD_COUNT_OF(tempCommand) = 2;
1121        (CMD_OF(tempCommand))[0] = 44;  /* get ping */
1122        (CMD_OF(tempCommand))[1] = 200; /* 200 ms */
1123        write_lock_irqsave(&pB->write_fifo_spinlock, flags);
1124        iiWriteBuf(pB, tempCommand, 4);
1125        write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
1126#endif
1127
1128        iiEnableMailIrq(pB);
1129        iiSendPendingMail(pB);
1130}
1131
1132/******************************************************************************/
1133/* Interrupt Handler Section                                                  */
1134/******************************************************************************/
1135
1136static inline void
1137service_all_boards(void)
1138{
1139        int i;
1140        i2eBordStrPtr  pB;
1141
1142        /* Service every board on the list */
1143        for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
1144                pB = i2BoardPtrTable[i];
1145                if ( pB ) {
1146                        i2ServiceBoard( pB );
1147                }
1148        }
1149}
1150
1151
1152/******************************************************************************/
1153/* Function:   ip2_interrupt_bh(work)                                         */
1154/* Parameters: work - pointer to the board structure                          */
1155/* Returns:    Nothing                                                        */
1156/*                                                                            */
1157/* Description:                                                               */
1158/*      Service the board in a bottom half interrupt handler and then         */
1159/*      reenable the board's interrupts if it has an IRQ number               */
1160/*                                                                            */
1161/******************************************************************************/
1162static void
1163ip2_interrupt_bh(struct work_struct *work)
1164{
1165        i2eBordStrPtr pB = container_of(work, i2eBordStr, tqueue_interrupt);
1166//      pB better well be set or we have a problem!  We can only get
1167//      here from the IMMEDIATE queue.  Here, we process the boards.
1168//      Checking pB doesn't cost much and it saves us from the sanity checkers.
1169
1170        bh_counter++; 
1171
1172        if ( pB ) {
1173                i2ServiceBoard( pB );
1174                if( pB->i2eUsingIrq ) {
1175//                      Re-enable his interrupts
1176                        iiEnableMailIrq(pB);
1177                }
1178        }
1179}
1180
1181
1182/******************************************************************************/
1183/* Function:   ip2_interrupt(int irq, void *dev_id)    */
1184/* Parameters: irq - interrupt number                                         */
1185/*             pointer to optional device ID structure                        */
1186/* Returns:    Nothing                                                        */
1187/*                                                                            */
1188/* Description:                                                               */
1189/*                                                                            */
1190/*      Our task here is simply to identify each board which needs servicing. */
1191/*      If we are queuing then, queue it to be serviced, and disable its irq  */
1192/*      mask otherwise process the board directly.                            */
1193/*                                                                            */
1194/*      We could queue by IRQ but that just complicates things on both ends   */
1195/*      with very little gain in performance (how many instructions does      */
1196/*      it take to iterate on the immediate queue).                           */
1197/*                                                                            */
1198/*                                                                            */
1199/******************************************************************************/
1200static void
1201ip2_irq_work(i2eBordStrPtr pB)
1202{
1203#ifdef USE_IQI
1204        if (NO_MAIL_HERE != ( pB->i2eStartMail = iiGetMail(pB))) {
1205//              Disable his interrupt (will be enabled when serviced)
1206//              This is mostly to protect from reentrancy.
1207                iiDisableMailIrq(pB);
1208
1209//              Park the board on the immediate queue for processing.
1210                schedule_work(&pB->tqueue_interrupt);
1211
1212//              Make sure the immediate queue is flagged to fire.
1213        }
1214#else
1215
1216//      We are using immediate servicing here.  This sucks and can
1217//      cause all sorts of havoc with ppp and others.  The failsafe
1218//      check on iiSendPendingMail could also throw a hairball.
1219
1220        i2ServiceBoard( pB );
1221
1222#endif /* USE_IQI */
1223}
1224
1225static void
1226ip2_polled_interrupt(void)
1227{
1228        int i;
1229        i2eBordStrPtr  pB;
1230
1231        ip2trace(ITRC_NO_PORT, ITRC_INTR, 99, 1, 0);
1232
1233        /* Service just the boards on the list using this irq */
1234        for( i = 0; i < i2nBoards; ++i ) {
1235                pB = i2BoardPtrTable[i];
1236
1237//              Only process those boards which match our IRQ.
1238//                      IRQ = 0 for polled boards, we won't poll "IRQ" boards
1239
1240                if (pB && pB->i2eUsingIrq == 0)
1241                        ip2_irq_work(pB);
1242        }
1243
1244        ++irq_counter;
1245
1246        ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
1247}
1248
1249static irqreturn_t
1250ip2_interrupt(int irq, void *dev_id)
1251{
1252        i2eBordStrPtr pB = dev_id;
1253
1254        ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, pB->i2eUsingIrq );
1255
1256        ip2_irq_work(pB);
1257
1258        ++irq_counter;
1259
1260        ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
1261        return IRQ_HANDLED;
1262}
1263
1264/******************************************************************************/
1265/* Function:   ip2_poll(unsigned long arg)                                    */
1266/* Parameters: ?                                                              */
1267/* Returns:    Nothing                                                        */
1268/*                                                                            */
1269/* Description:                                                               */
1270/* This function calls the library routine i2ServiceBoard for each board in   */
1271/* the board table. This is used instead of the interrupt routine when polled */
1272/* mode is specified.                                                         */
1273/******************************************************************************/
1274static void
1275ip2_poll(unsigned long arg)
1276{
1277        ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 );
1278
1279        // Just polled boards, IRQ = 0 will hit all non-interrupt boards.
1280        // It will NOT poll boards handled by hard interrupts.
1281        // The issue of queued BH interrupts is handled in ip2_interrupt().
1282        ip2_polled_interrupt();
1283
1284        mod_timer(&PollTimer, POLL_TIMEOUT);
1285
1286        ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
1287}
1288
1289static void do_input(struct work_struct *work)
1290{
1291        i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_input);
1292        unsigned long flags;
1293
1294        ip2trace(CHANN, ITRC_INPUT, 21, 0 );
1295
1296        // Data input
1297        if ( pCh->pTTY != NULL ) {
1298                read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
1299                if (!pCh->throttled && (pCh->Ibuf_stuff != pCh->Ibuf_strip)) {
1300                        read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
1301                        i2Input( pCh );
1302                } else
1303                        read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
1304        } else {
1305                ip2trace(CHANN, ITRC_INPUT, 22, 0 );
1306
1307                i2InputFlush( pCh );
1308        }
1309}
1310
1311// code duplicated from n_tty (ldisc)
1312static inline void  isig(int sig, struct tty_struct *tty, int flush)
1313{
1314        /* FIXME: This is completely bogus */
1315        if (tty->pgrp)
1316                kill_pgrp(tty->pgrp, sig, 1);
1317        if (flush || !L_NOFLSH(tty)) {
1318                if ( tty->ldisc->ops->flush_buffer )  
1319                        tty->ldisc->ops->flush_buffer(tty);
1320                i2InputFlush( tty->driver_data );
1321        }
1322}
1323
1324static void do_status(struct work_struct *work)
1325{
1326        i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_status);
1327        int status;
1328
1329        status =  i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) );
1330
1331        ip2trace (CHANN, ITRC_STATUS, 21, 1, status );
1332
1333        if (pCh->pTTY && (status & (I2_BRK|I2_PAR|I2_FRA|I2_OVR)) ) {
1334                if ( (status & I2_BRK) ) {
1335                        // code duplicated from n_tty (ldisc)
1336                        if (I_IGNBRK(pCh->pTTY))
1337                                goto skip_this;
1338                        if (I_BRKINT(pCh->pTTY)) {
1339                                isig(SIGINT, pCh->pTTY, 1);
1340                                goto skip_this;
1341                        }
1342                        wake_up_interruptible(&pCh->pTTY->read_wait);
1343                }
1344#ifdef NEVER_HAPPENS_AS_SETUP_XXX
1345        // and can't work because we don't know the_char
1346        // as the_char is reported on a separate path
1347        // The intelligent board does this stuff as setup
1348        {
1349        char brkf = TTY_NORMAL;
1350        unsigned char brkc = '\0';
1351        unsigned char tmp;
1352                if ( (status & I2_BRK) ) {
1353                        brkf = TTY_BREAK;
1354                        brkc = '\0';
1355                } 
1356                else if (status & I2_PAR) {
1357                        brkf = TTY_PARITY;
1358                        brkc = the_char;
1359                } else if (status & I2_FRA) {
1360                        brkf = TTY_FRAME;
1361                        brkc = the_char;
1362                } else if (status & I2_OVR) {
1363                        brkf = TTY_OVERRUN;
1364                        brkc = the_char;
1365                }
1366                tmp = pCh->pTTY->real_raw;
1367                pCh->pTTY->real_raw = 0;
1368                pCh->pTTY->ldisc->ops.receive_buf( pCh->pTTY, &brkc, &brkf, 1 );
1369                pCh->pTTY->real_raw = tmp;
1370        }
1371#endif /* NEVER_HAPPENS_AS_SETUP_XXX */
1372        }
1373skip_this:
1374
1375        if ( status & (I2_DDCD | I2_DDSR | I2_DCTS | I2_DRI) ) {
1376                wake_up_interruptible(&pCh->delta_msr_wait);
1377
1378                if ( (pCh->flags & ASYNC_CHECK_CD) && (status & I2_DDCD) ) {
1379                        if ( status & I2_DCD ) {
1380                                if ( pCh->wopen ) {
1381                                        wake_up_interruptible ( &pCh->open_wait );
1382                                }
1383                        } else {
1384                                if (pCh->pTTY &&  (!(pCh->pTTY->termios->c_cflag & CLOCAL)) ) {
1385                                        tty_hangup( pCh->pTTY );
1386                                }
1387                        }
1388                }
1389        }
1390
1391        ip2trace (CHANN, ITRC_STATUS, 26, 0 );
1392}
1393
1394/******************************************************************************/
1395/* Device Open/Close/Ioctl Entry Point Section                                */
1396/******************************************************************************/
1397
1398/******************************************************************************/
1399/* Function:   open_sanity_check()                                            */
1400/* Parameters: Pointer to tty structure                                       */
1401/*             Pointer to file structure                                      */
1402/* Returns:    Success or failure                                             */
1403/*                                                                            */
1404/* Description:                                                               */
1405/* Verifies the structure magic numbers and cross links.                      */
1406/******************************************************************************/
1407#ifdef IP2DEBUG_OPEN
1408static void 
1409open_sanity_check( i2ChanStrPtr pCh, i2eBordStrPtr pBrd )
1410{
1411        if ( pBrd->i2eValid != I2E_MAGIC ) {
1412                printk(KERN_ERR "IP2: invalid board structure\n" );
1413        } else if ( pBrd != pCh->pMyBord ) {
1414                printk(KERN_ERR "IP2: board structure pointer mismatch (%p)\n",
1415                         pCh->pMyBord );
1416        } else if ( pBrd->i2eChannelCnt < pCh->port_index ) {
1417                printk(KERN_ERR "IP2: bad device index (%d)\n", pCh->port_index );
1418        } else if (&((i2ChanStrPtr)pBrd->i2eChannelPtr)[pCh->port_index] != pCh) {
1419        } else {
1420                printk(KERN_INFO "IP2: all pointers check out!\n" );
1421        }
1422}
1423#endif
1424
1425
1426/******************************************************************************/
1427/* Function:   ip2_open()                                                     */
1428/* Parameters: Pointer to tty structure                                       */
1429/*             Pointer to file structure                                      */
1430/* Returns:    Success or failure                                             */
1431/*                                                                            */
1432/* Description: (MANDATORY)                                                   */
1433/* A successful device open has to run a gauntlet of checks before it         */
1434/* completes. After some sanity checking and pointer setup, the function      */
1435/* blocks until all conditions are satisfied. It then initialises the port to */
1436/* the default characteristics and returns.                                   */
1437/******************************************************************************/
1438static int
1439ip2_open( PTTY tty, struct file *pFile )
1440{
1441        wait_queue_t wait;
1442        int rc = 0;
1443        int do_clocal = 0;
1444        i2ChanStrPtr  pCh = DevTable[tty->index];
1445
1446        ip2trace (tty->index, ITRC_OPEN, ITRC_ENTER, 0 );
1447
1448        if ( pCh == NULL ) {
1449                return -ENODEV;
1450        }
1451        /* Setup pointer links in device and tty structures */
1452        pCh->pTTY = tty;
1453        tty->driver_data = pCh;
1454
1455#ifdef IP2DEBUG_OPEN
1456        printk(KERN_DEBUG \
1457                        "IP2:open(tty=%p,pFile=%p):dev=%s,ch=%d,idx=%d\n",
1458               tty, pFile, tty->name, pCh->infl.hd.i2sChannel, pCh->port_index);
1459        open_sanity_check ( pCh, pCh->pMyBord );
1460#endif
1461
1462        i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, CMD_DTRUP,CMD_RTSUP,CMD_DCD_REP);
1463        pCh->dataSetOut |= (I2_DTR | I2_RTS);
1464        serviceOutgoingFifo( pCh->pMyBord );
1465
1466        /* Block here until the port is ready (per serial and istallion) */
1467        /*
1468         * 1. If the port is in the middle of closing wait for the completion
1469         *    and then return the appropriate error.
1470         */
1471        init_waitqueue_entry(&wait, current);
1472        add_wait_queue(&pCh->close_wait, &wait);
1473        set_current_state( TASK_INTERRUPTIBLE );
1474
1475        if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) {
1476                if ( pCh->flags & ASYNC_CLOSING ) {
1477                        schedule();
1478                }
1479                if ( tty_hung_up_p(pFile) ) {
1480                        set_current_state( TASK_RUNNING );
1481                        remove_wait_queue(&pCh->close_wait, &wait);
1482                        return( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS;
1483                }
1484        }
1485        set_current_state( TASK_RUNNING );
1486        remove_wait_queue(&pCh->close_wait, &wait);
1487
1488        /*
1489         * 3. Handle a non-blocking open of a normal port.
1490         */
1491        if ( (pFile->f_flags & O_NONBLOCK) || (tty->flags & (1<<TTY_IO_ERROR) )) {
1492                pCh->flags |= ASYNC_NORMAL_ACTIVE;
1493                goto noblock;
1494        }
1495        /*
1496         * 4. Now loop waiting for the port to be free and carrier present
1497         *    (if required).
1498         */
1499        if ( tty->termios->c_cflag & CLOCAL )
1500                do_clocal = 1;
1501
1502#ifdef IP2DEBUG_OPEN
1503        printk(KERN_DEBUG "OpenBlock: do_clocal = %d\n", do_clocal);
1504#endif
1505
1506        ++pCh->wopen;
1507
1508        init_waitqueue_entry(&wait, current);
1509        add_wait_queue(&pCh->open_wait, &wait);
1510
1511        for(;;) {
1512                i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
1513                pCh->dataSetOut |= (I2_DTR | I2_RTS);
1514                set_current_state( TASK_INTERRUPTIBLE );
1515                serviceOutgoingFifo( pCh->pMyBord );
1516                if ( tty_hung_up_p(pFile) ) {
1517                        set_current_state( TASK_RUNNING );
1518                        remove_wait_queue(&pCh->open_wait, &wait);
1519                        return ( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EBUSY : -ERESTARTSYS;
1520                }
1521                if (!(pCh->flags & ASYNC_CLOSING) && 
1522                                (do_clocal || (pCh->dataSetIn & I2_DCD) )) {
1523                        rc = 0;
1524                        break;
1525                }
1526
1527#ifdef IP2DEBUG_OPEN
1528                printk(KERN_DEBUG "ASYNC_CLOSING = %s\n",
1529                        (pCh->flags & ASYNC_CLOSING)?"True":"False");
1530                printk(KERN_DEBUG "OpenBlock: waiting for CD or signal\n");
1531#endif
1532                ip2trace (CHANN, ITRC_OPEN, 3, 2, 0,
1533                                (pCh->flags & ASYNC_CLOSING) );
1534                /* check for signal */
1535                if (signal_pending(current)) {
1536                        rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS);
1537                        break;
1538                }
1539                schedule();
1540        }
1541        set_current_state( TASK_RUNNING );
1542        remove_wait_queue(&pCh->open_wait, &wait);
1543
1544        --pCh->wopen; //why count?
1545
1546        ip2trace (CHANN, ITRC_OPEN, 4, 0 );
1547
1548        if (rc != 0 ) {
1549                return rc;
1550        }
1551        pCh->flags |= ASYNC_NORMAL_ACTIVE;
1552
1553noblock:
1554
1555        /* first open - Assign termios structure to port */
1556        if ( tty->count == 1 ) {
1557                i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
1558                /* Now we must send the termios settings to the loadware */
1559                set_params( pCh, NULL );
1560        }
1561
1562        /*
1563         * Now set any i2lib options. These may go away if the i2lib code ends
1564         * up rolled into the mainline.
1565         */
1566        pCh->channelOptions |= CO_NBLOCK_WRITE;
1567
1568#ifdef IP2DEBUG_OPEN
1569        printk (KERN_DEBUG "IP2: open completed\n" );
1570#endif
1571        serviceOutgoingFifo( pCh->pMyBord );
1572
1573        ip2trace (CHANN, ITRC_OPEN, ITRC_RETURN, 0 );
1574
1575        return 0;
1576}
1577
1578/******************************************************************************/
1579/* Function:   ip2_close()                                                    */
1580/* Parameters: Pointer to tty structure                                       */
1581/*             Pointer to file structure                                      */
1582/* Returns:    Nothing                                                        */
1583/*                                                                            */
1584/* Description:                                                               */
1585/*                                                                            */
1586/*                                                                            */
1587/******************************************************************************/
1588static void
1589ip2_close( PTTY tty, struct file *pFile )
1590{
1591        i2ChanStrPtr  pCh = tty->driver_data;
1592
1593        if ( !pCh ) {
1594                return;
1595        }
1596
1597        ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 );
1598
1599#ifdef IP2DEBUG_OPEN
1600        printk(KERN_DEBUG "IP2:close %s:\n",tty->name);
1601#endif
1602
1603        if ( tty_hung_up_p ( pFile ) ) {
1604
1605                ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 );
1606
1607                return;
1608        }
1609        if ( tty->count > 1 ) { /* not the last close */
1610
1611                ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 );
1612
1613                return;
1614        }
1615        pCh->flags |= ASYNC_CLOSING;    // last close actually
1616
1617        tty->closing = 1;
1618
1619        if (pCh->ClosingWaitTime != ASYNC_CLOSING_WAIT_NONE) {
1620                /*
1621                 * Before we drop DTR, make sure the transmitter has completely drained.
1622                 * This uses an timeout, after which the close
1623                 * completes.
1624                 */
1625                ip2_wait_until_sent(tty, pCh->ClosingWaitTime );
1626        }
1627        /*
1628         * At this point we stop accepting input. Here we flush the channel
1629         * input buffer which will allow the board to send up more data. Any
1630         * additional input is tossed at interrupt/poll time.
1631         */
1632        i2InputFlush( pCh );
1633
1634        /* disable DSS reporting */
1635        i2QueueCommands(PTYPE_INLINE, pCh, 100, 4,
1636                                CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
1637        if ( !tty || (tty->termios->c_cflag & HUPCL) ) {
1638                i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
1639                pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
1640                i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
1641        }
1642
1643        serviceOutgoingFifo ( pCh->pMyBord );
1644
1645        tty_ldisc_flush(tty);
1646        tty_driver_flush_buffer(tty);
1647        tty->closing = 0;
1648        
1649        pCh->pTTY = NULL;
1650
1651        if (pCh->wopen) {
1652                if (pCh->ClosingDelay) {
1653                        msleep_interruptible(jiffies_to_msecs(pCh->ClosingDelay));
1654                }
1655                wake_up_interruptible(&pCh->open_wait);
1656        }
1657
1658        pCh->flags &=~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1659        wake_up_interruptible(&pCh->close_wait);
1660
1661#ifdef IP2DEBUG_OPEN
1662        DBG_CNT("ip2_close: after wakeups--");
1663#endif
1664
1665
1666        ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 );
1667
1668        return;
1669}
1670
1671/******************************************************************************/
1672/* Function:   ip2_hangup()                                                   */
1673/* Parameters: Pointer to tty structure                                       */
1674/* Returns:    Nothing                                                        */
1675/*                                                                            */
1676/* Description:                                                               */
1677/*                                                                            */
1678/*                                                                            */
1679/******************************************************************************/
1680static void
1681ip2_hangup ( PTTY tty )
1682{
1683        i2ChanStrPtr  pCh = tty->driver_data;
1684
1685        if( !pCh ) {
1686                return;
1687        }
1688
1689        ip2trace (CHANN, ITRC_HANGUP, ITRC_ENTER, 0 );
1690
1691        ip2_flush_buffer(tty);
1692
1693        /* disable DSS reporting */
1694
1695        i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_DCD_NREP);
1696        i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
1697        if ( (tty->termios->c_cflag & HUPCL) ) {
1698                i2QueueCommands(PTYPE_BYPASS, pCh, 0, 2, CMD_RTSDN, CMD_DTRDN);
1699                pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
1700                i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
1701        }
1702        i2QueueCommands(PTYPE_INLINE, pCh, 1, 3, 
1703                                CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
1704        serviceOutgoingFifo ( pCh->pMyBord );
1705
1706        wake_up_interruptible ( &pCh->delta_msr_wait );
1707
1708        pCh->flags &= ~ASYNC_NORMAL_ACTIVE;
1709        pCh->pTTY = NULL;
1710        wake_up_interruptible ( &pCh->open_wait );
1711
1712        ip2trace (CHANN, ITRC_HANGUP, ITRC_RETURN, 0 );
1713}
1714
1715/******************************************************************************/
1716/******************************************************************************/
1717/* Device Output Section                                                      */
1718/******************************************************************************/
1719/******************************************************************************/
1720
1721/******************************************************************************/
1722/* Function:   ip2_write()                                                    */
1723/* Parameters: Pointer to tty structure                                       */
1724/*             Flag denoting data is in user (1) or kernel (0) space          */
1725/*             Pointer to data                                                */
1726/*             Number of bytes to write                                       */
1727/* Returns:    Number of bytes actually written                               */
1728/*                                                                            */
1729/* Description: (MANDATORY)                                                   */
1730/*                                                                            */
1731/*                                                                            */
1732/******************************************************************************/
1733static int
1734ip2_write( PTTY tty, const unsigned char *pData, int count)
1735{
1736        i2ChanStrPtr  pCh = tty->driver_data;
1737        int bytesSent = 0;
1738        unsigned long flags;
1739
1740        ip2trace (CHANN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 );
1741
1742        /* Flush out any buffered data left over from ip2_putchar() calls. */
1743        ip2_flush_chars( tty );
1744
1745        /* This is the actual move bit. Make sure it does what we need!!!!! */
1746        write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
1747        bytesSent = i2Output( pCh, pData, count);
1748        write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
1749
1750        ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent );
1751
1752        return bytesSent > 0 ? bytesSent : 0;
1753}
1754
1755/******************************************************************************/
1756/* Function:   ip2_putchar()                                                  */
1757/* Parameters: Pointer to tty structure                                       */
1758/*             Character to write                                             */
1759/* Returns:    Nothing                                                        */
1760/*                                                                            */
1761/* Description:                                                               */
1762/*                                                                            */
1763/*                                                                            */
1764/******************************************************************************/
1765static int
1766ip2_putchar( PTTY tty, unsigned char ch )
1767{
1768        i2ChanStrPtr  pCh = tty->driver_data;
1769        unsigned long flags;
1770
1771//      ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch );
1772
1773        write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
1774        pCh->Pbuf[pCh->Pbuf_stuff++] = ch;
1775        if ( pCh->Pbuf_stuff == sizeof pCh->Pbuf ) {
1776                write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
1777                ip2_flush_chars( tty );
1778        } else
1779                write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
1780        return 1;
1781
1782//      ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch );
1783}
1784
1785/******************************************************************************/
1786/* Function:   ip2_flush_chars()                                              */
1787/* Parameters: Pointer to tty structure                                       */
1788/* Returns:    Nothing                                                        */
1789/*                                                                            */
1790/* Description:                                                               */
1791/*                                                                            */
1792/******************************************************************************/
1793static void
1794ip2_flush_chars( PTTY tty )
1795{
1796        int   strip;
1797        i2ChanStrPtr  pCh = tty->driver_data;
1798        unsigned long flags;
1799
1800        write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
1801        if ( pCh->Pbuf_stuff ) {
1802
1803//              ip2trace (CHANN, ITRC_PUTC, 10, 1, strip );
1804
1805                //
1806                // We may need to restart i2Output if it does not fullfill this request
1807                //
1808                strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff);
1809                if ( strip != pCh->Pbuf_stuff ) {
1810                        memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip );
1811                }
1812                pCh->Pbuf_stuff -= strip;
1813        }
1814        write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
1815}
1816
1817/******************************************************************************/
1818/* Function:   ip2_write_room()                                               */
1819/* Parameters: Pointer to tty structure                                       */
1820/* Returns:    Number of bytes that the driver can accept                     */
1821/*                                                                            */
1822/* Description:                                                               */
1823/*                                                                            */
1824/******************************************************************************/
1825static int
1826ip2_write_room ( PTTY tty )
1827{
1828        int bytesFree;
1829        i2ChanStrPtr  pCh = tty->driver_data;
1830        unsigned long flags;
1831
1832        read_lock_irqsave(&pCh->Pbuf_spinlock, flags);
1833        bytesFree = i2OutputFree( pCh ) - pCh->Pbuf_stuff;
1834        read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
1835
1836        ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree );
1837
1838        return ((bytesFree > 0) ? bytesFree : 0);
1839}
1840
1841/******************************************************************************/
1842/* Function:   ip2_chars_in_buf()                                             */
1843/* Parameters: Pointer to tty structure                                       */
1844/* Returns:    Number of bytes queued for transmission                        */
1845/*                                                                            */
1846/* Description:                                                               */
1847/*                                                                            */
1848/*                                                                            */
1849/******************************************************************************/
1850static int
1851ip2_chars_in_buf ( PTTY tty )
1852{
1853        i2ChanStrPtr  pCh = tty->driver_data;
1854        int rc;
1855        unsigned long flags;
1856
1857        ip2trace (CHANN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff );
1858
1859#ifdef IP2DEBUG_WRITE
1860        printk (KERN_DEBUG "IP2: chars in buffer = %d (%d,%d)\n",
1861                                 pCh->Obuf_char_count + pCh->Pbuf_stuff,
1862                                 pCh->Obuf_char_count, pCh->Pbuf_stuff );
1863#endif
1864        read_lock_irqsave(&pCh->Obuf_spinlock, flags);
1865        rc =  pCh->Obuf_char_count;
1866        read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
1867        read_lock_irqsave(&pCh->Pbuf_spinlock, flags);
1868        rc +=  pCh->Pbuf_stuff;
1869        read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
1870        return rc;
1871}
1872
1873/******************************************************************************/
1874/* Function:   ip2_flush_buffer()                                             */
1875/* Parameters: Pointer to tty structure                                       */
1876/* Returns:    Nothing                                                        */
1877/*                                                                            */
1878/* Description:                                                               */
1879/*                                                                            */
1880/*                                                                            */
1881/******************************************************************************/
1882static void
1883ip2_flush_buffer( PTTY tty )
1884{
1885        i2ChanStrPtr  pCh = tty->driver_data;
1886        unsigned long flags;
1887
1888        ip2trace (CHANN, ITRC_FLUSH, ITRC_ENTER, 0 );
1889
1890#ifdef IP2DEBUG_WRITE
1891        printk (KERN_DEBUG "IP2: flush buffer\n" );
1892#endif
1893        write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
1894        pCh->Pbuf_stuff = 0;
1895        write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
1896        i2FlushOutput( pCh );
1897        ip2_owake(tty);
1898
1899        ip2trace (CHANN, ITRC_FLUSH, ITRC_RETURN, 0 );
1900
1901}
1902
1903/******************************************************************************/
1904/* Function:   ip2_wait_until_sent()                                          */
1905/* Parameters: Pointer to tty structure                                       */
1906/*             Timeout for wait.                                              */
1907/* Returns:    Nothing                                                        */
1908/*                                                                            */
1909/* Description:                                                               */
1910/* This function is used in place of the normal tty_wait_until_sent, which    */
1911/* only waits for the driver buffers to be empty (or rather, those buffers    */
1912/* reported by chars_in_buffer) which doesn't work for IP2 due to the         */
1913/* indeterminate number of bytes buffered on the board.                       */
1914/******************************************************************************/
1915static void
1916ip2_wait_until_sent ( PTTY tty, int timeout )
1917{
1918        int i = jiffies;
1919        i2ChanStrPtr  pCh = tty->driver_data;
1920
1921        tty_wait_until_sent(tty, timeout );
1922        if ( (i = timeout - (jiffies -i)) > 0)
1923                i2DrainOutput( pCh, i );
1924}
1925
1926/******************************************************************************/
1927/******************************************************************************/
1928/* Device Input Section                                                       */
1929/******************************************************************************/
1930/******************************************************************************/
1931
1932/******************************************************************************/
1933/* Function:   ip2_throttle()                                                 */
1934/* Parameters: Pointer to tty structure                                       */
1935/* Returns:    Nothing                                                        */
1936/*                                                                            */
1937/* Description:                                                               */
1938/*                                                                            */
1939/*                                                                            */
1940/******************************************************************************/
1941static void
1942ip2_throttle ( PTTY tty )
1943{
1944        i2ChanStrPtr  pCh = tty->driver_data;
1945
1946#ifdef IP2DEBUG_READ
1947        printk (KERN_DEBUG "IP2: throttle\n" );
1948#endif
1949        /*
1950         * Signal the poll/interrupt handlers not to forward incoming data to
1951         * the line discipline. This will cause the buffers to fill up in the
1952         * library and thus cause the library routines to send the flow control
1953         * stuff.
1954         */
1955        pCh->throttled = 1;
1956}
1957
1958/******************************************************************************/
1959/* Function:   ip2_unthrottle()                                               */
1960/* Parameters: Pointer to tty structure                                       */
1961/* Returns:    Nothing                                                        */
1962/*                                                                            */
1963/* Description:                                                               */
1964/*                                                                            */
1965/*                                                                            */
1966/******************************************************************************/
1967static void
1968ip2_unthrottle ( PTTY tty )
1969{
1970        i2ChanStrPtr  pCh = tty->driver_data;
1971        unsigned long flags;
1972
1973#ifdef IP2DEBUG_READ
1974        printk (KERN_DEBUG "IP2: unthrottle\n" );
1975#endif
1976
1977        /* Pass incoming data up to the line discipline again. */
1978        pCh->throttled = 0;
1979        i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
1980        serviceOutgoingFifo( pCh->pMyBord );
1981        read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
1982        if ( pCh->Ibuf_stuff != pCh->Ibuf_strip ) {
1983                read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
1984#ifdef IP2DEBUG_READ
1985                printk (KERN_DEBUG "i2Input called from unthrottle\n" );
1986#endif
1987                i2Input( pCh );
1988        } else
1989                read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
1990}
1991
1992static void
1993ip2_start ( PTTY tty )
1994{
1995        i2ChanStrPtr  pCh = DevTable[tty->index];
1996
1997        i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
1998        i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_UNSUSPEND);
1999        i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_RESUME);
2000#ifdef IP2DEBUG_WRITE
2001        printk (KERN_DEBUG "IP2: start tx\n" );
2002#endif
2003}
2004
2005static void
2006ip2_stop ( PTTY tty )
2007{
2008        i2ChanStrPtr  pCh = DevTable[tty->index];
2009
2010        i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_SUSPEND);
2011#ifdef IP2DEBUG_WRITE
2012        printk (KERN_DEBUG "IP2: stop tx\n" );
2013#endif
2014}
2015
2016/******************************************************************************/
2017/* Device Ioctl Section                                                       */
2018/******************************************************************************/
2019
2020static int ip2_tiocmget(struct tty_struct *tty, struct file *file)
2021{
2022        i2ChanStrPtr pCh = DevTable[tty->index];
2023#ifdef  ENABLE_DSSNOW
2024        wait_queue_t wait;
2025#endif
2026
2027        if (pCh == NULL)
2028                return -ENODEV;
2029
2030/*
2031        FIXME - the following code is causing a NULL pointer dereference in
2032        2.3.51 in an interrupt handler.  It's suppose to prompt the board
2033        to return the DSS signal status immediately.  Why doesn't it do
2034        the same thing in 2.2.14?
2035*/
2036
2037/*      This thing is still busted in the 1.2.12 driver on 2.4.x
2038        and even hoses the serial console so the oops can be trapped.
2039                /\/\|=mhw=|\/\/                 */
2040
2041#ifdef  ENABLE_DSSNOW
2042        i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW);
2043
2044        init_waitqueue_entry(&wait, current);
2045        add_wait_queue(&pCh->dss_now_wait, &wait);
2046        set_current_state( TASK_INTERRUPTIBLE );
2047
2048        serviceOutgoingFifo( pCh->pMyBord );
2049
2050        schedule();
2051
2052        set_current_state( TASK_RUNNING );
2053        remove_wait_queue(&pCh->dss_now_wait, &wait);
2054
2055        if (signal_pending(current)) {
2056                return -EINTR;
2057        }
2058#endif
2059        return  ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
2060              | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
2061              | ((pCh->dataSetIn  & I2_DCD) ? TIOCM_CAR : 0)
2062              | ((pCh->dataSetIn  & I2_RI)  ? TIOCM_RNG : 0)
2063              | ((pCh->dataSetIn  & I2_DSR) ? TIOCM_DSR : 0)
2064              | ((pCh->dataSetIn  & I2_CTS) ? TIOCM_CTS : 0);
2065}
2066
2067static int ip2_tiocmset(struct tty_struct *tty, struct file *file,
2068                        unsigned int set, unsigned int clear)
2069{
2070        i2ChanStrPtr pCh = DevTable[tty->index];
2071
2072        if (pCh == NULL)
2073                return -ENODEV;
2074
2075        if (set & TIOCM_RTS) {
2076                i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
2077                pCh->dataSetOut |= I2_RTS;
2078        }
2079        if (set & TIOCM_DTR) {
2080                i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
2081                pCh->dataSetOut |= I2_DTR;
2082        }
2083
2084        if (clear & TIOCM_RTS) {
2085                i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
2086                pCh->dataSetOut &= ~I2_RTS;
2087        }
2088        if (clear & TIOCM_DTR) {
2089                i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
2090                pCh->dataSetOut &= ~I2_DTR;
2091        }
2092        serviceOutgoingFifo( pCh->pMyBord );
2093        return 0;
2094}
2095
2096/******************************************************************************/
2097/* Function:   ip2_ioctl()                                                    */
2098/* Parameters: Pointer to tty structure                                       */
2099/*             Pointer to file structure                                      */
2100/*             Command                                                        */
2101/*             Argument                                                       */
2102/* Returns:    Success or failure                                             */
2103/*                                                                            */
2104/* Description:                                                               */
2105/*                                                                            */
2106/*                                                                            */
2107/******************************************************************************/
2108static int
2109ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
2110{
2111        wait_queue_t wait;
2112        i2ChanStrPtr pCh = DevTable[tty->index];
2113        i2eBordStrPtr pB;
2114        struct async_icount cprev, cnow;        /* kernel counter temps */
2115        struct serial_icounter_struct __user *p_cuser;
2116        int rc = 0;
2117        unsigned long flags;
2118        void __user *argp = (void __user *)arg;
2119
2120        if ( pCh == NULL )
2121                return -ENODEV;
2122
2123        pB = pCh->pMyBord;
2124
2125        ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg );
2126
2127#ifdef IP2DEBUG_IOCTL
2128        printk(KERN_DEBUG "IP2: ioctl cmd (%x), arg (%lx)\n", cmd, arg );
2129#endif
2130
2131        switch(cmd) {
2132        case TIOCGSERIAL:
2133
2134                ip2trace (CHANN, ITRC_IOCTL, 2, 1, rc );
2135
2136                rc = get_serial_info(pCh, argp);
2137                if (rc)
2138                        return rc;
2139                break;
2140
2141        case TIOCSSERIAL:
2142
2143                ip2trace (CHANN, ITRC_IOCTL, 3, 1, rc );
2144
2145                rc = set_serial_info(pCh, argp);
2146                if (rc)
2147                        return rc;
2148                break;
2149
2150        case TCXONC:
2151                rc = tty_check_change(tty);
2152                if (rc)
2153                        return rc;
2154                switch (arg) {
2155                case TCOOFF:
2156                        //return  -ENOIOCTLCMD;
2157                        break;
2158                case TCOON:
2159                        //return  -ENOIOCTLCMD;
2160                        break;
2161                case TCIOFF:
2162                        if (STOP_CHAR(tty) != __DISABLED_CHAR) {
2163                                i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1,
2164                                                CMD_XMIT_NOW(STOP_CHAR(tty)));
2165                        }
2166                        break;
2167                case TCION:
2168                        if (START_CHAR(tty) != __DISABLED_CHAR) {
2169                                i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1,
2170                                                CMD_XMIT_NOW(START_CHAR(tty)));
2171                        }
2172                        break;
2173                default:
2174                        return -EINVAL;
2175                }
2176                return 0;
2177
2178        case TCSBRK:   /* SVID version: non-zero arg --> no break */
2179                rc = tty_check_change(tty);
2180
2181                ip2trace (CHANN, ITRC_IOCTL, 4, 1, rc );
2182
2183                if (!rc) {
2184                        ip2_wait_until_sent(tty,0);
2185                        if (!arg) {
2186                                i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SEND_BRK(250));
2187                                serviceOutgoingFifo( pCh->pMyBord );
2188                        }
2189                }
2190                break;
2191
2192        case TCSBRKP:  /* support for POSIX tcsendbreak() */
2193                rc = tty_check_change(tty);
2194
2195                ip2trace (CHANN, ITRC_IOCTL, 5, 1, rc );
2196
2197                if (!rc) {
2198                        ip2_wait_until_sent(tty,0);
2199                        i2QueueCommands(PTYPE_INLINE, pCh, 100, 1,
2200                                CMD_SEND_BRK(arg ? arg*100 : 250));
2201                        serviceOutgoingFifo ( pCh->pMyBord );   
2202                }
2203                break;
2204
2205        case TIOCGSOFTCAR:
2206
2207                ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc );
2208
2209                        rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp);
2210                if (rc) 
2211                        return rc;
2212        break;
2213
2214        case TIOCSSOFTCAR:
2215
2216                ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc );
2217
2218                rc = get_user(arg,(unsigned long __user *) argp);
2219                if (rc) 
2220                        return rc;
2221                tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL)
2222                                         | (arg ? CLOCAL : 0));
2223                
2224                break;
2225
2226        /*
2227         * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask
2228         * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS
2229         * for masking). Caller should use TIOCGICOUNT to see which one it was
2230         */
2231        case TIOCMIWAIT:
2232                write_lock_irqsave(&pB->read_fifo_spinlock, flags);
2233                cprev = pCh->icount;     /* note the counters on entry */
2234                write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
2235                i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4, 
2236                                                CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP);
2237                init_waitqueue_entry(&wait, current);
2238                add_wait_queue(&pCh->delta_msr_wait, &wait);
2239                set_current_state( TASK_INTERRUPTIBLE );
2240
2241                serviceOutgoingFifo( pCh->pMyBord );
2242                for(;;) {
2243                        ip2trace (CHANN, ITRC_IOCTL, 10, 0 );
2244
2245                        schedule();
2246
2247                        ip2trace (CHANN, ITRC_IOCTL, 11, 0 );
2248
2249                        /* see if a signal did it */
2250                        if (signal_pending(current)) {
2251                                rc = -ERESTARTSYS;
2252                                break;
2253                        }
2254                        write_lock_irqsave(&pB->read_fifo_spinlock, flags);
2255                        cnow = pCh->icount; /* atomic copy */
2256                        write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
2257                        if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
2258                                cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
2259                                rc =  -EIO; /* no change => rc */
2260                                break;
2261                        }
2262                        if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
2263                            ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
2264                            ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
2265                            ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
2266                                rc =  0;
2267                                break;
2268                        }
2269                        cprev = cnow;
2270                }
2271                set_current_state( TASK_RUNNING );
2272                remove_wait_queue(&pCh->delta_msr_wait, &wait);
2273
2274                i2QueueCommands(PTYPE_BYPASS, pCh, 100, 3, 
2275                                                 CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
2276                if ( ! (pCh->flags      & ASYNC_CHECK_CD)) {
2277                        i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DCD_NREP);
2278                }
2279                serviceOutgoingFifo( pCh->pMyBord );
2280                return rc;
2281                break;
2282
2283        /*
2284         * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
2285         * Return: write counters to the user passed counter struct
2286         * NB: both 1->0 and 0->1 transitions are counted except for RI where
2287         * only 0->1 is counted. The controller is quite capable of counting
2288         * both, but this done to preserve compatibility with the standard
2289         * serial driver.
2290         */
2291        case TIOCGICOUNT:
2292                ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
2293
2294                write_lock_irqsave(&pB->read_fifo_spinlock, flags);
2295                cnow = pCh->icount;
2296                write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
2297                p_cuser = argp;
2298                rc = put_user(cnow.cts, &p_cuser->cts);
2299                rc = put_user(cnow.dsr, &p_cuser->dsr);
2300                rc = put_user(cnow.rng, &p_cuser->rng);
2301                rc = put_user(cnow.dcd, &p_cuser->dcd);
2302                rc = put_user(cnow.rx, &p_cuser->rx);
2303                rc = put_user(cnow.tx, &p_cuser->tx);
2304                rc = put_user(cnow.frame, &p_cuser->frame);
2305                rc = put_user(cnow.overrun, &p_cuser->overrun);
2306                rc = put_user(cnow.parity, &p_cuser->parity);
2307                rc = put_user(cnow.brk, &p_cuser->brk);
2308                rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
2309                break;
2310
2311        /*
2312         * The rest are not supported by this driver. By returning -ENOIOCTLCMD they
2313         * will be passed to the line discipline for it to handle.
2314         */
2315        case TIOCSERCONFIG:
2316        case TIOCSERGWILD:
2317        case TIOCSERGETLSR:
2318        case TIOCSERSWILD:
2319        case TIOCSERGSTRUCT:
2320        case TIOCSERGETMULTI:
2321        case TIOCSERSETMULTI:
2322
2323        default:
2324                ip2trace (CHANN, ITRC_IOCTL, 12, 0 );
2325
2326                rc =  -ENOIOCTLCMD;
2327                break;
2328        }
2329
2330        ip2trace (CHANN, ITRC_IOCTL, ITRC_RETURN, 0 );
2331
2332        return rc;
2333}
2334
2335/******************************************************************************/
2336/* Function:   GetSerialInfo()                                                */
2337/* Parameters: Pointer to channel structure                                   */
2338/*             Pointer to old termios structure                               */
2339/* Returns:    Nothing                                                        */
2340/*                                                                            */
2341/* Description:                                                               */
2342/* This is to support the setserial command, and requires processing of the   */
2343/* standard Linux serial structure.                                           */
2344/******************************************************************************/
2345static int
2346get_serial_info ( i2ChanStrPtr pCh, struct serial_struct __user *retinfo )
2347{
2348        struct serial_struct tmp;
2349
2350        memset ( &tmp, 0, sizeof(tmp) );
2351        tmp.type = pCh->pMyBord->channelBtypes.bid_value[(pCh->port_index & (IP2_PORTS_PER_BOARD-1))/16];
2352        if (BID_HAS_654(tmp.type)) {
2353                tmp.type = PORT_16650;
2354        } else {
2355                tmp.type = PORT_CIRRUS;
2356        }
2357        tmp.line = pCh->port_index;
2358        tmp.port = pCh->pMyBord->i2eBase;
2359        tmp.irq  = ip2config.irq[pCh->port_index/64];
2360        tmp.flags = pCh->flags;
2361        tmp.baud_base = pCh->BaudBase;
2362        tmp.close_delay = pCh->ClosingDelay;
2363        tmp.closing_wait = pCh->ClosingWaitTime;
2364        tmp.custom_divisor = pCh->BaudDivisor;
2365        return copy_to_user(retinfo,&tmp,sizeof(*retinfo));
2366}
2367
2368/******************************************************************************/
2369/* Function:   SetSerialInfo()                                                */
2370/* Parameters: Pointer to channel structure                                   */
2371/*             Pointer to old termios structure                               */
2372/* Returns:    Nothing                                                        */
2373/*                                                                            */
2374/* Description:                                                               */
2375/* This function provides support for setserial, which uses the TIOCSSERIAL   */
2376/* ioctl. Not all setserial parameters are relevant. If the user attempts to  */
2377/* change the IRQ, address or type of the port the ioctl fails.               */
2378/******************************************************************************/
2379static int
2380set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info )
2381{
2382        struct serial_struct ns;
2383        int   old_flags, old_baud_divisor;
2384
2385        if (copy_from_user(&ns, new_info, sizeof (ns)))
2386                return -EFAULT;
2387
2388        /*
2389         * We don't allow setserial to change IRQ, board address, type or baud
2390         * base. Also line nunber as such is meaningless but we use it for our
2391         * array index so it is fixed also.
2392         */
2393        if ( (ns.irq        != ip2config.irq[pCh->port_index])
2394            || ((int) ns.port      != ((int) (pCh->pMyBord->i2eBase)))
2395            || (ns.baud_base != pCh->BaudBase)
2396            || (ns.line      != pCh->port_index) ) {
2397                return -EINVAL;
2398        }
2399
2400        old_flags = pCh->flags;
2401        old_baud_divisor = pCh->BaudDivisor;
2402
2403        if ( !capable(CAP_SYS_ADMIN) ) {
2404                if ( ( ns.close_delay != pCh->ClosingDelay ) ||
2405                    ( (ns.flags & ~ASYNC_USR_MASK) !=
2406                      (pCh->flags & ~ASYNC_USR_MASK) ) ) {
2407                        return -EPERM;
2408                }
2409
2410                pCh->flags = (pCh->flags & ~ASYNC_USR_MASK) |
2411                               (ns.flags & ASYNC_USR_MASK);
2412                pCh->BaudDivisor = ns.custom_divisor;
2413        } else {
2414                pCh->flags = (pCh->flags & ~ASYNC_FLAGS) |
2415                               (ns.flags & ASYNC_FLAGS);
2416                pCh->BaudDivisor = ns.custom_divisor;
2417                pCh->ClosingDelay = ns.close_delay * HZ/100;
2418                pCh->ClosingWaitTime = ns.closing_wait * HZ/100;
2419        }
2420
2421        if ( ( (old_flags & ASYNC_SPD_MASK) != (pCh->flags & ASYNC_SPD_MASK) )
2422            || (old_baud_divisor != pCh->BaudDivisor) ) {
2423                // Invalidate speed and reset parameters
2424                set_params( pCh, NULL );
2425        }
2426
2427        return 0;
2428}
2429
2430/******************************************************************************/
2431/* Function:   ip2_set_termios()                                              */
2432/* Parameters: Pointer to tty structure                                       */
2433/*             Pointer to old termios structure                               */
2434/* Returns:    Nothing                                                        */
2435/*                                                                            */
2436/* Description:                                                               */
2437/*                                                                            */
2438/*                                                                            */
2439/******************************************************************************/
2440static void
2441ip2_set_termios( PTTY tty, struct ktermios *old_termios )
2442{
2443        i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data;
2444
2445#ifdef IP2DEBUG_IOCTL
2446        printk (KERN_DEBUG "IP2: set termios %p\n", old_termios );
2447#endif
2448
2449        set_params( pCh, old_termios );
2450}
2451
2452/******************************************************************************/
2453/* Function:   ip2_set_line_discipline()                                      */
2454/* Parameters: Pointer to tty structure                                       */
2455/* Returns:    Nothing                                                        */
2456/*                                                                            */
2457/* Description:  Does nothing                                                 */
2458/*                                                                            */
2459/*                                                                            */
2460/******************************************************************************/
2461static void
2462ip2_set_line_discipline ( PTTY tty )
2463{
2464#ifdef IP2DEBUG_IOCTL
2465        printk (KERN_DEBUG "IP2: set line discipline\n" );
2466#endif
2467
2468        ip2trace (((i2ChanStrPtr)tty->driver_data)->port_index, ITRC_IOCTL, 16, 0 );
2469
2470}
2471
2472/******************************************************************************/
2473/* Function:   SetLine Characteristics()                                      */
2474/* Parameters: Pointer to channel structure                                   */
2475/* Returns:    Nothing                                                        */
2476/*                                                                            */
2477/* Description:                                                               */
2478/* This routine is called to update the channel structure with the new line   */
2479/* characteristics, and send the appropriate commands to the board when they  */
2480/* change.                                                                    */
2481/******************************************************************************/
2482static void
2483set_params( i2ChanStrPtr pCh, struct ktermios *o_tios )
2484{
2485        tcflag_t cflag, iflag, lflag;
2486        char stop_char, start_char;
2487        struct ktermios dummy;
2488
2489        lflag = pCh->pTTY->termios->c_lflag;
2490        cflag = pCh->pTTY->termios->c_cflag;
2491        iflag = pCh->pTTY->termios->c_iflag;
2492
2493        if (o_tios == NULL) {
2494                dummy.c_lflag = ~lflag;
2495                dummy.c_cflag = ~cflag;
2496                dummy.c_iflag = ~iflag;
2497                o_tios = &dummy;
2498        }
2499
2500        {
2501                switch ( cflag & CBAUD ) {
2502                case B0:
2503                        i2QueueCommands( PTYPE_BYPASS, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
2504                        pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
2505                        i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
2506                        pCh->pTTY->termios->c_cflag |= (CBAUD & o_tios->c_cflag);
2507                        goto service_it;
2508                        break;
2509                case B38400:
2510                        /*
2511                         * This is the speed that is overloaded with all the other high
2512                         * speeds, depending upon the flag settings.
2513                         */
2514                        if ( ( pCh->flags & ASYNC_SPD_MASK ) == ASYNC_SPD_HI ) {
2515                                pCh->speed = CBR_57600;
2516                        } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI ) {
2517                                pCh->speed = CBR_115200;
2518                        } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST ) {
2519                                pCh->speed = CBR_C1;
2520                        } else {
2521                                pCh->speed = CBR_38400;
2522                        }
2523                        break;
2524                case B50:      pCh->speed = CBR_50;      break;
2525                case B75:      pCh->speed = CBR_75;      break;
2526                case B110:     pCh->speed = CBR_110;     break;
2527                case B134:     pCh->speed = CBR_134;     break;
2528                case B150:     pCh->speed = CBR_150;     break;
2529                case B200:     pCh->speed = CBR_200;     break;
2530                case B300:     pCh->speed = CBR_300;     break;
2531                case B600:     pCh->speed = CBR_600;     break;
2532                case B1200:    pCh->speed = CBR_1200;    break;
2533                case B1800:    pCh->speed = CBR_1800;    break;
2534                case B2400:    pCh->speed = CBR_2400;    break;
2535                case B4800:    pCh->speed = CBR_4800;    break;
2536                case B9600:    pCh->speed = CBR_9600;    break;
2537                case B19200:   pCh->speed = CBR_19200;   break;
2538                case B57600:   pCh->speed = CBR_57600;   break;
2539                case B115200:  pCh->speed = CBR_115200;  break;
2540                case B153600:  pCh->speed = CBR_153600;  break;
2541                case B230400:  pCh->speed = CBR_230400;  break;
2542                case B307200:  pCh->speed = CBR_307200;  break;
2543                case B460800:  pCh->speed = CBR_460800;  break;
2544                case B921600:  pCh->speed = CBR_921600;  break;
2545                default:       pCh->speed = CBR_9600;    break;
2546                }
2547                if ( pCh->speed == CBR_C1 ) {
2548                        // Process the custom speed parameters.
2549                        int bps = pCh->BaudBase / pCh->BaudDivisor;
2550                        if ( bps == 921600 ) {
2551                                pCh->speed = CBR_921600;
2552                        } else {
2553                                bps = bps/10;
2554                                i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_BAUD_DEF1(bps) );
2555                        }
2556                }
2557                i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_SETBAUD(pCh->speed));
2558                
2559                i2QueueCommands ( PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
2560                pCh->dataSetOut |= (I2_DTR | I2_RTS);
2561        }
2562        if ( (CSTOPB & cflag) ^ (CSTOPB & o_tios->c_cflag)) 
2563        {
2564                i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, 
2565                        CMD_SETSTOP( ( cflag & CSTOPB ) ? CST_2 : CST_1));
2566        }
2567        if (((PARENB|PARODD) & cflag) ^ ((PARENB|PARODD) & o_tios->c_cflag)) 
2568        {
2569                i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1,
2570                        CMD_SETPAR( 
2571                                (cflag & PARENB ?  (cflag & PARODD ? CSP_OD : CSP_EV) : CSP_NP)
2572                        )
2573                );
2574        }
2575        /* byte size and parity */
2576        if ( (CSIZE & cflag)^(CSIZE & o_tios->c_cflag)) 
2577        {
2578                int datasize;
2579                switch ( cflag & CSIZE ) {
2580                case CS5: datasize = CSZ_5; break;
2581                case CS6: datasize = CSZ_6; break;
2582                case CS7: datasize = CSZ_7; break;
2583                case CS8: datasize = CSZ_8; break;
2584                default:  datasize = CSZ_5; break;      /* as per serial.c */
2585                }
2586                i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, CMD_SETBITS(datasize) );
2587        }
2588        /* Process CTS flow control flag setting */
2589        if ( (cflag & CRTSCTS) ) {
2590                i2QueueCommands(PTYPE_INLINE, pCh, 100,
2591                                                2, CMD_CTSFL_ENAB, CMD_RTSFL_ENAB);
2592        } else {
2593                i2QueueCommands(PTYPE_INLINE, pCh, 100,
2594                                                2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
2595        }
2596        //
2597        // Process XON/XOFF flow control flags settings
2598        //
2599        stop_char = STOP_CHAR(pCh->pTTY);
2600        start_char = START_CHAR(pCh->pTTY);
2601
2602        //////////// can't be \000
2603        if (stop_char == __DISABLED_CHAR ) 
2604        {
2605                stop_char = ~__DISABLED_CHAR; 
2606        }
2607        if (start_char == __DISABLED_CHAR ) 
2608        {
2609                start_char = ~__DISABLED_CHAR;
2610        }
2611        /////////////////////////////////
2612
2613        if ( o_tios->c_cc[VSTART] != start_char ) 
2614        {
2615                i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXON(start_char));
2616                i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXON(start_char));
2617        }
2618        if ( o_tios->c_cc[VSTOP] != stop_char ) 
2619        {
2620                 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXOFF(stop_char));
2621                 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXOFF(stop_char));
2622        }
2623        if (stop_char == __DISABLED_CHAR ) 
2624        {
2625                stop_char = ~__DISABLED_CHAR;  //TEST123
2626                goto no_xoff;
2627        }
2628        if ((iflag & (IXOFF))^(o_tios->c_iflag & (IXOFF))) 
2629        {
2630                if ( iflag & IXOFF ) {  // Enable XOFF output flow control
2631                        i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_XON));
2632                } else {        // Disable XOFF output flow control
2633no_xoff:
2634                        i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_NONE));
2635                }
2636        }
2637        if (start_char == __DISABLED_CHAR ) 
2638        {
2639                goto no_xon;
2640        }
2641        if ((iflag & (IXON|IXANY)) ^ (o_tios->c_iflag & (IXON|IXANY))) 
2642        {
2643                if ( iflag & IXON ) {
2644                        if ( iflag & IXANY ) { // Enable XON/XANY output flow control
2645                                i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XANY));
2646                        } else { // Enable XON output flow control
2647                                i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XON));
2648                        }
2649                } else { // Disable XON output flow control
2650no_xon:
2651                        i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_NONE));
2652                }
2653        }
2654        if ( (iflag & ISTRIP) ^ ( o_tios->c_iflag & (ISTRIP)) ) 
2655        {
2656                i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, 
2657                                CMD_ISTRIP_OPT((iflag & ISTRIP ? 1 : 0)));
2658        }
2659        if ( (iflag & INPCK) ^ ( o_tios->c_iflag & (INPCK)) ) 
2660        {
2661                i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, 
2662                                CMD_PARCHK((iflag & INPCK) ? CPK_ENAB : CPK_DSAB));
2663        }
2664
2665        if ( (iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) 
2666                        ^       ( o_tios->c_iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) ) 
2667        {
2668                char brkrpt = 0;
2669                char parrpt = 0;
2670
2671                if ( iflag & IGNBRK ) { /* Ignore breaks altogether */
2672                        /* Ignore breaks altogether */
2673                        i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_NREP);
2674                } else {
2675                        if ( iflag & BRKINT ) {
2676                                if ( iflag & PARMRK ) {
2677                                        brkrpt = 0x0a;  // exception an inline triple
2678                                } else {
2679                                        brkrpt = 0x1a;  // exception and NULL
2680                                }
2681                                brkrpt |= 0x04; // flush input
2682                        } else {
2683                                if ( iflag & PARMRK ) {
2684                                        brkrpt = 0x0b;  //POSIX triple \0377 \0 \0
2685                                } else {
2686                                        brkrpt = 0x01;  // Null only
2687                                }
2688                        }
2689                        i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_REP(brkrpt));
2690                } 
2691
2692                if (iflag & IGNPAR) {
2693                        parrpt = 0x20;
2694                                                                                                        /* would be 2 for not cirrus bug */
2695                                                                                                        /* would be 0x20 cept for cirrus bug */
2696                } else {
2697                        if ( iflag & PARMRK ) {
2698                                /*
2699                                 * Replace error characters with 3-byte sequence (\0377,\0,char)
2700                                 */
2701                                parrpt = 0x04 ;
2702                                i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_ISTRIP_OPT((char)0));
2703                        } else {
2704                                parrpt = 0x03;
2705                        } 
2706                }
2707                i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SET_ERROR(parrpt));
2708        }
2709        if (cflag & CLOCAL) {
2710                // Status reporting fails for DCD if this is off
2711                i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_NREP);
2712                pCh->flags &= ~ASYNC_CHECK_CD;
2713        } else {
2714                i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_REP);
2715                pCh->flags      |= ASYNC_CHECK_CD;
2716        }
2717
2718service_it:
2719        i2DrainOutput( pCh, 100 );              
2720}
2721
2722/******************************************************************************/
2723/* IPL Device Section                                                         */
2724/******************************************************************************/
2725
2726/******************************************************************************/
2727/* Function:   ip2_ipl_read()                                                  */
2728/* Parameters: Pointer to device inode                                        */
2729/*             Pointer to file structure                                      */
2730/*             Pointer to data                                                */
2731/*             Number of bytes to read                                        */
2732/* Returns:    Success or failure                                             */
2733/*                                                                            */
2734/* Description:   Ugly                                                        */
2735/*                                                                            */
2736/*                                                                            */
2737/******************************************************************************/
2738
2739static 
2740ssize_t
2741ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off )
2742{
2743        unsigned int minor = iminor(pFile->f_path.dentry->d_inode);
2744        int rc = 0;
2745
2746#ifdef IP2DEBUG_IPL
2747        printk (KERN_DEBUG "IP2IPL: read %p, %d bytes\n", pData, count );
2748#endif
2749
2750        switch( minor ) {
2751        case 0:     // IPL device
2752                rc = -EINVAL;
2753                break;
2754        case 1:     // Status dump
2755                rc = -EINVAL;
2756                break;
2757        case 2:     // Ping device
2758                rc = -EINVAL;
2759                break;
2760        case 3:     // Trace device
2761                rc = DumpTraceBuffer ( pData, count );
2762                break;
2763        case 4:     // Trace device
2764                rc = DumpFifoBuffer ( pData, count );
2765                break;
2766        default:
2767                rc = -ENODEV;
2768                break;
2769        }
2770        return rc;
2771}
2772
2773static int
2774DumpFifoBuffer ( char __user *pData, int count )
2775{
2776#ifdef DEBUG_FIFO
2777        int rc;
2778        rc = copy_to_user(pData, DBGBuf, count);
2779
2780        printk(KERN_DEBUG "Last index %d\n", I );
2781
2782        return count;
2783#endif  /* DEBUG_FIFO */
2784        return 0;
2785}
2786
2787static int
2788DumpTraceBuffer ( char __user *pData, int count )
2789{
2790#ifdef IP2DEBUG_TRACE
2791        int rc;
2792        int dumpcount;
2793        int chunk;
2794        int *pIndex = (int __user *)pData;
2795
2796        if ( count < (sizeof(int) * 6) ) {
2797                return -EIO;
2798        }
2799        rc = put_user(tracewrap, pIndex );
2800        rc = put_user(TRACEMAX, ++pIndex );
2801        rc = put_user(tracestrip, ++pIndex );
2802        rc = put_user(tracestuff, ++pIndex );
2803        pData += sizeof(int) * 6;
2804        count -= sizeof(int) * 6;
2805
2806        dumpcount = tracestuff - tracestrip;
2807        if ( dumpcount < 0 ) {
2808                dumpcount += TRACEMAX;
2809        }
2810        if ( dumpcount > count ) {
2811                dumpcount = count;
2812        }
2813        chunk = TRACEMAX - tracestrip;
2814        if ( dumpcount > chunk ) {
2815                rc = copy_to_user(pData, &tracebuf[tracestrip],
2816                              chunk * sizeof(tracebuf[0]) );
2817                pData += chunk * sizeof(tracebuf[0]);
2818                tracestrip = 0;
2819                chunk = dumpcount - chunk;
2820        } else {
2821                chunk = dumpcount;
2822        }
2823        rc = copy_to_user(pData, &tracebuf[tracestrip],
2824                      chunk * sizeof(tracebuf[0]) );
2825        tracestrip += chunk;
2826        tracewrap = 0;
2827
2828        rc = put_user(tracestrip, ++pIndex );
2829        rc = put_user(tracestuff, ++pIndex );
2830
2831        return dumpcount;
2832#else
2833        return 0;
2834#endif
2835}
2836
2837/******************************************************************************/
2838/* Function:   ip2_ipl_write()                                                 */
2839/* Parameters:                                                                */
2840/*             Pointer to file structure                                      */
2841/*             Pointer to data                                                */
2842/*             Number of bytes to write                                       */
2843/* Returns:    Success or failure                                             */
2844/*                                                                            */
2845/* Description:                                                               */
2846/*                                                                            */
2847/*                                                                            */
2848/******************************************************************************/
2849static ssize_t
2850ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t *off)
2851{
2852#ifdef IP2DEBUG_IPL
2853        printk (KERN_DEBUG "IP2IPL: write %p, %d bytes\n", pData, count );
2854#endif
2855        return 0;
2856}
2857
2858/******************************************************************************/
2859/* Function:   ip2_ipl_ioctl()                                                */
2860/* Parameters: Pointer to device inode                                        */
2861/*             Pointer to file structure                                      */
2862/*             Command                                                        */
2863/*             Argument                                                       */
2864/* Returns:    Success or failure                                             */
2865/*                                                                            */
2866/* Description:                                                               */
2867/*                                                                            */
2868/*                                                                            */
2869/******************************************************************************/
2870static long
2871ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
2872{
2873        unsigned int iplminor = iminor(pFile->f_path.dentry->d_inode);
2874        int rc = 0;
2875        void __user *argp = (void __user *)arg;
2876        ULONG __user *pIndex = argp;
2877        i2eBordStrPtr pB = i2BoardPtrTable[iplminor / 4];
2878        i2ChanStrPtr pCh;
2879
2880#ifdef IP2DEBUG_IPL
2881        printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg );
2882#endif
2883
2884        lock_kernel();
2885
2886        switch ( iplminor ) {
2887        case 0:     // IPL device
2888                rc = -EINVAL;
2889                break;
2890        case 1:     // Status dump
2891        case 5:
2892        case 9:
2893        case 13:
2894                switch ( cmd ) {
2895                case 64:        /* Driver - ip2stat */
2896                        rc = put_user(-1, pIndex++ );
2897                        rc = put_user(irq_counter, pIndex++  );
2898                        rc = put_user(bh_counter, pIndex++  );
2899                        break;
2900
2901                case 65:        /* Board  - ip2stat */
2902                        if ( pB ) {
2903                                rc = copy_to_user(argp, pB, sizeof(i2eBordStr));
2904                                rc = put_user(inb(pB->i2eStatus),
2905                                        (ULONG __user *)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) );
2906                        } else {
2907                                rc = -ENODEV;
2908                        }
2909                        break;
2910
2911                default:
2912                        if (cmd < IP2_MAX_PORTS) {
2913                                pCh = DevTable[cmd];
2914                                if ( pCh )
2915                                {
2916                                        rc = copy_to_user(argp, pCh, sizeof(i2ChanStr));
2917                                } else {
2918                                        rc = -ENODEV;
2919                                }
2920                        } else {
2921                                rc = -EINVAL;
2922                        }
2923                }
2924                break;
2925
2926        case 2:     // Ping device
2927                rc = -EINVAL;
2928                break;
2929        case 3:     // Trace device
2930                /*
2931                 * akpm: This used to write a whole bunch of function addresses
2932                 * to userspace, which generated lots of put_user() warnings.
2933                 * I killed it all.  Just return "success" and don't do
2934                 * anything.
2935                 */
2936                if (cmd == 1)
2937                        rc = 0;
2938                else
2939                        rc = -EINVAL;
2940                break;
2941
2942        default:
2943                rc = -ENODEV;
2944                break;
2945        }
2946        unlock_kernel();
2947        return rc;
2948}
2949
2950/******************************************************************************/
2951/* Function:   ip2_ipl_open()                                                 */
2952/* Parameters: Pointer to device inode                                        */
2953/*             Pointer to file structure                                      */
2954/* Returns:    Success or failure                                             */
2955/*                                                                            */
2956/* Description:                                                               */
2957/*                                                                            */
2958/*                                                                            */
2959/******************************************************************************/
2960static int
2961ip2_ipl_open( struct inode *pInode, struct file *pFile )
2962{
2963
2964#ifdef IP2DEBUG_IPL
2965        printk (KERN_DEBUG "IP2IPL: open\n" );
2966#endif
2967        cycle_kernel_lock();
2968        return 0;
2969}
2970
2971static int
2972proc_ip2mem_show(struct seq_file *m, void *v)
2973{
2974        i2eBordStrPtr  pB;
2975        i2ChanStrPtr  pCh;
2976        PTTY tty;
2977        int i;
2978
2979#define FMTLINE "%3d: 0x%08x 0x%08x 0%011o 0%011o\n"
2980#define FMTLIN2 "     0x%04x 0x%04x tx flow 0x%x\n"
2981#define FMTLIN3 "     0x%04x 0x%04x rc flow\n"
2982
2983        seq_printf(m,"\n");
2984
2985        for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
2986                pB = i2BoardPtrTable[i];
2987                if ( pB ) {
2988                        seq_printf(m,"board %d:\n",i);
2989                        seq_printf(m,"\tFifo rem: %d mty: %x outM %x\n",
2990                                pB->i2eFifoRemains,pB->i2eWaitingForEmptyFifo,pB->i2eOutMailWaiting);
2991                }
2992        }
2993
2994        seq_printf(m,"#: tty flags, port flags,     cflags,     iflags\n");
2995        for (i=0; i < IP2_MAX_PORTS; i++) {
2996                pCh = DevTable[i];
2997                if (pCh) {
2998                        tty = pCh->pTTY;
2999                        if (tty && tty->count) {
3000                                seq_printf(m,FMTLINE,i,(int)tty->flags,pCh->flags,
3001                                                                        tty->termios->c_cflag,tty->termios->c_iflag);
3002
3003                                seq_printf(m,FMTLIN2,
3004                                                pCh->outfl.asof,pCh->outfl.room,pCh->channelNeeds);
3005                                seq_printf(m,FMTLIN3,pCh->infl.asof,pCh->infl.room);
3006                        }
3007                }
3008        }
3009        return 0;
3010}
3011
3012static int proc_ip2mem_open(struct inode *inode, struct file *file)
3013{
3014        return single_open(file, proc_ip2mem_show, NULL);
3015}
3016
3017static const struct file_operations ip2mem_proc_fops = {
3018        .owner          = THIS_MODULE,
3019        .open           = proc_ip2mem_open,
3020        .read           = seq_read,
3021        .llseek         = seq_lseek,
3022        .release        = single_release,
3023};
3024
3025/*
3026 * This is the handler for /proc/tty/driver/ip2
3027 *
3028 * This stretch of code has been largely plagerized from at least three
3029 * different sources including ip2mkdev.c and a couple of other drivers.
3030 * The bugs are all mine.  :-)  =mhw=
3031 */
3032static int ip2_proc_show(struct seq_file *m, void *v)
3033{
3034        int     i, j, box;
3035        int     boxes = 0;
3036        int     ports = 0;
3037        int     tports = 0;
3038        i2eBordStrPtr  pB;
3039        char *sep;
3040
3041        seq_printf(m, "ip2info: 1.0 driver: %s\n", pcVersion);
3042        seq_printf(m, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n",
3043                        IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR,
3044                        IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX);
3045
3046        for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
3047                /* This need to be reset for a board by board count... */
3048                boxes = 0;
3049                pB = i2BoardPtrTable[i];
3050                if( pB ) {
3051                        switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) 
3052                        {
3053                        case POR_ID_FIIEX:
3054                                seq_printf(m, "Board %d: EX ports=", i);
3055                                sep = "";
3056                                for( box = 0; box < ABS_MAX_BOXES; ++box )
3057                                {
3058                                        ports = 0;
3059
3060                                        if( pB->i2eChannelMap[box] != 0 ) ++boxes;
3061                                        for( j = 0; j < ABS_BIGGEST_BOX; ++j ) 
3062                                        {
3063                                                if( pB->i2eChannelMap[box] & 1<< j ) {
3064                                                        ++ports;
3065                                                }
3066                                        }
3067                                        seq_printf(m, "%s%d", sep, ports);
3068                                        sep = ",";
3069                                        tports += ports;
3070                                }
3071                                seq_printf(m, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8);
3072                                break;
3073
3074                        case POR_ID_II_4:
3075                                seq_printf(m, "Board %d: ISA-4 ports=4 boxes=1", i);
3076                                tports = ports = 4;
3077                                break;
3078
3079                        case POR_ID_II_8:
3080                                seq_printf(m, "Board %d: ISA-8-std ports=8 boxes=1", i);
3081                                tports = ports = 8;
3082                                break;
3083
3084                        case POR_ID_II_8R:
3085                                seq_printf(m, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i);
3086                                tports = ports = 8;
3087                                break;
3088
3089                        default:
3090                                seq_printf(m, "Board %d: unknown", i);
3091                                /* Don't try and probe for minor numbers */
3092                                tports = ports = 0;
3093                        }
3094
3095                } else {
3096                        /* Don't try and probe for minor numbers */
3097                        seq_printf(m, "Board %d: vacant", i);
3098                        tports = ports = 0;
3099                }
3100
3101                if( tports ) {
3102                        seq_puts(m, " minors=");
3103                        sep = "";
3104                        for ( box = 0; box < ABS_MAX_BOXES; ++box )
3105                        {
3106                                for ( j = 0; j < ABS_BIGGEST_BOX; ++j )
3107                                {
3108                                        if ( pB->i2eChannelMap[box] & (1 << j) )
3109                                        {
3110                                                seq_printf(m, "%s%d", sep,
3111                                                        j + ABS_BIGGEST_BOX *
3112                                                        (box+i*ABS_MAX_BOXES));
3113                                                sep = ",";
3114                                        }
3115                                }
3116                        }
3117                }
3118                seq_putc(m, '\n');
3119        }
3120        return 0;
3121 }
3122
3123static int ip2_proc_open(struct inode *inode, struct file *file)
3124{
3125        return single_open(file, ip2_proc_show, NULL);
3126}
3127
3128static const struct file_operations ip2_proc_fops = {
3129        .owner          = THIS_MODULE,
3130        .open           = ip2_proc_open,
3131        .read           = seq_read,
3132        .llseek         = seq_lseek,
3133        .release        = single_release,
3134};
3135 
3136/******************************************************************************/
3137/* Function:   ip2trace()                                                     */
3138/* Parameters: Value to add to trace buffer                                   */
3139/* Returns:    Nothing                                                        */
3140/*                                                                            */
3141/* Description:                                                               */
3142/*                                                                            */
3143/*                                                                            */
3144/******************************************************************************/
3145#ifdef IP2DEBUG_TRACE
3146void
3147ip2trace (unsigned short pn, unsigned char cat, unsigned char label, unsigned long codes, ...)
3148{
3149        long flags;
3150        unsigned long *pCode = &codes;
3151        union ip2breadcrumb bc;
3152        i2ChanStrPtr  pCh;
3153
3154
3155        tracebuf[tracestuff++] = jiffies;
3156        if ( tracestuff == TRACEMAX ) {
3157                tracestuff = 0;
3158        }
3159        if ( tracestuff == tracestrip ) {
3160                if ( ++tracestrip == TRACEMAX ) {
3161                        tracestrip = 0;
3162                }
3163                ++tracewrap;
3164        }
3165
3166        bc.hdr.port  = 0xff & pn;
3167        bc.hdr.cat   = cat;
3168        bc.hdr.codes = (unsigned char)( codes & 0xff );
3169        bc.hdr.label = label;
3170        tracebuf[tracestuff++] = bc.value;
3171
3172        for (;;) {
3173                if ( tracestuff == TRACEMAX ) {
3174                        tracestuff = 0;
3175                }
3176                if ( tracestuff == tracestrip ) {
3177                        if ( ++tracestrip == TRACEMAX ) {
3178                                tracestrip = 0;
3179                        }
3180                        ++tracewrap;
3181                }
3182
3183                if ( !codes-- )
3184                        break;
3185
3186                tracebuf[tracestuff++] = *++pCode;
3187        }
3188}
3189#endif
3190
3191
3192MODULE_LICENSE("GPL");
3193
3194static struct pci_device_id ip2main_pci_tbl[] __devinitdata = {
3195        { PCI_DEVICE(PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_IP2EX) },
3196        { }
3197};
3198
3199MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl);
3200