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