linux/drivers/char/isicom.c
<<
>>
Prefs
   1/*
   2 *      This program is free software; you can redistribute it and/or
   3 *      modify it under the terms of the GNU General Public License
   4 *      as published by the Free Software Foundation; either version
   5 *      2 of the License, or (at your option) any later version.
   6 *
   7 *      Original driver code supplied by Multi-Tech
   8 *
   9 *      Changes
  10 *      1/9/98  alan@lxorguk.ukuu.org.uk
  11 *                                      Merge to 2.0.x kernel tree
  12 *                                      Obtain and use official major/minors
  13 *                                      Loader switched to a misc device
  14 *                                      (fixed range check bug as a side effect)
  15 *                                      Printk clean up
  16 *      9/12/98 alan@lxorguk.ukuu.org.uk
  17 *                                      Rough port to 2.1.x
  18 *
  19 *      10/6/99 sameer                  Merged the ISA and PCI drivers to
  20 *                                      a new unified driver.
  21 *
  22 *      3/9/99  sameer                  Added support for ISI4616 cards.
  23 *
  24 *      16/9/99 sameer                  We do not force RTS low anymore.
  25 *                                      This is to prevent the firmware
  26 *                                      from getting confused.
  27 *
  28 *      26/10/99 sameer                 Cosmetic changes:The driver now
  29 *                                      dumps the Port Count information
  30 *                                      along with I/O address and IRQ.
  31 *
  32 *      13/12/99 sameer                 Fixed the problem with IRQ sharing.
  33 *
  34 *      10/5/00  sameer                 Fixed isicom_shutdown_board()
  35 *                                      to not lower DTR on all the ports
  36 *                                      when the last port on the card is
  37 *                                      closed.
  38 *
  39 *      10/5/00  sameer                 Signal mask setup command added
  40 *                                      to  isicom_setup_port and
  41 *                                      isicom_shutdown_port.
  42 *
  43 *      24/5/00  sameer                 The driver is now SMP aware.
  44 *
  45 *
  46 *      27/11/00 Vinayak P Risbud       Fixed the Driver Crash Problem
  47 *
  48 *
  49 *      03/01/01  anil .s               Added support for resetting the
  50 *                                      internal modems on ISI cards.
  51 *
  52 *      08/02/01  anil .s               Upgraded the driver for kernel
  53 *                                      2.4.x
  54 *
  55 *      11/04/01  Kevin                 Fixed firmware load problem with
  56 *                                      ISIHP-4X card
  57 *
  58 *      30/04/01  anil .s               Fixed the remote login through
  59 *                                      ISI port problem. Now the link
  60 *                                      does not go down before password
  61 *                                      prompt.
  62 *
  63 *      03/05/01  anil .s               Fixed the problem with IRQ sharing
  64 *                                      among ISI-PCI cards.
  65 *
  66 *      03/05/01  anil .s               Added support to display the version
  67 *                                      info during insmod as well as module
  68 *                                      listing by lsmod.
  69 *
  70 *      10/05/01  anil .s               Done the modifications to the source
  71 *                                      file and Install script so that the
  72 *                                      same installation can be used for
  73 *                                      2.2.x and 2.4.x kernel.
  74 *
  75 *      06/06/01  anil .s               Now we drop both dtr and rts during
  76 *                                      shutdown_port as well as raise them
  77 *                                      during isicom_config_port.
  78 *
  79 *      09/06/01 acme@conectiva.com.br  use capable, not suser, do
  80 *                                      restore_flags on failure in
  81 *                                      isicom_send_break, verify put_user
  82 *                                      result
  83 *
  84 *      11/02/03  ranjeeth              Added support for 230 Kbps and 460 Kbps
  85 *                                      Baud index extended to 21
  86 *
  87 *      20/03/03  ranjeeth              Made to work for Linux Advanced server.
  88 *                                      Taken care of license warning.
  89 *
  90 *      10/12/03  Ravindra              Made to work for Fedora Core 1 of
  91 *                                      Red Hat Distribution
  92 *
  93 *      06/01/05  Alan Cox              Merged the ISI and base kernel strands
  94 *                                      into a single 2.6 driver
  95 *
  96 *      ***********************************************************
  97 *
  98 *      To use this driver you also need the support package. You
  99 *      can find this in RPM format on
 100 *              ftp://ftp.linux.org.uk/pub/linux/alan
 101 *
 102 *      You can find the original tools for this direct from Multitech
 103 *              ftp://ftp.multitech.com/ISI-Cards/
 104 *
 105 *      Having installed the cards the module options (/etc/modprobe.conf)
 106 *
 107 *      options isicom   io=card1,card2,card3,card4 irq=card1,card2,card3,card4
 108 *
 109 *      Omit those entries for boards you don't have installed.
 110 *
 111 *      TODO
 112 *              Merge testing
 113 *              64-bit verification
 114 */
 115
 116#include <linux/module.h>
 117#include <linux/firmware.h>
 118#include <linux/kernel.h>
 119#include <linux/tty.h>
 120#include <linux/tty_flip.h>
 121#include <linux/termios.h>
 122#include <linux/fs.h>
 123#include <linux/sched.h>
 124#include <linux/serial.h>
 125#include <linux/smp_lock.h>
 126#include <linux/mm.h>
 127#include <linux/interrupt.h>
 128#include <linux/timer.h>
 129#include <linux/delay.h>
 130#include <linux/ioport.h>
 131
 132#include <linux/uaccess.h>
 133#include <linux/io.h>
 134#include <asm/system.h>
 135
 136#include <linux/pci.h>
 137
 138#include <linux/isicom.h>
 139
 140#define InterruptTheCard(base) outw(0, (base) + 0xc)
 141#define ClearInterrupt(base) inw((base) + 0x0a)
 142
 143#define pr_dbg(str...) pr_debug("ISICOM: " str)
 144#ifdef DEBUG
 145#define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c))
 146#else
 147#define isicom_paranoia_check(a, b, c) 0
 148#endif
 149
 150static int isicom_probe(struct pci_dev *, const struct pci_device_id *);
 151static void __devexit isicom_remove(struct pci_dev *);
 152
 153static struct pci_device_id isicom_pci_tbl[] = {
 154        { PCI_DEVICE(VENDOR_ID, 0x2028) },
 155        { PCI_DEVICE(VENDOR_ID, 0x2051) },
 156        { PCI_DEVICE(VENDOR_ID, 0x2052) },
 157        { PCI_DEVICE(VENDOR_ID, 0x2053) },
 158        { PCI_DEVICE(VENDOR_ID, 0x2054) },
 159        { PCI_DEVICE(VENDOR_ID, 0x2055) },
 160        { PCI_DEVICE(VENDOR_ID, 0x2056) },
 161        { PCI_DEVICE(VENDOR_ID, 0x2057) },
 162        { PCI_DEVICE(VENDOR_ID, 0x2058) },
 163        { 0 }
 164};
 165MODULE_DEVICE_TABLE(pci, isicom_pci_tbl);
 166
 167static struct pci_driver isicom_driver = {
 168        .name           = "isicom",
 169        .id_table       = isicom_pci_tbl,
 170        .probe          = isicom_probe,
 171        .remove         = __devexit_p(isicom_remove)
 172};
 173
 174static int prev_card = 3;       /*      start servicing isi_card[0]     */
 175static struct tty_driver *isicom_normal;
 176
 177static void isicom_tx(unsigned long _data);
 178static void isicom_start(struct tty_struct *tty);
 179
 180static DEFINE_TIMER(tx, isicom_tx, 0, 0);
 181
 182/*   baud index mappings from linux defns to isi */
 183
 184static signed char linuxb_to_isib[] = {
 185        -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19, 20, 21
 186};
 187
 188struct  isi_board {
 189        unsigned long           base;
 190        int                     irq;
 191        unsigned char           port_count;
 192        unsigned short          status;
 193        unsigned short          port_status; /* each bit for each port */
 194        unsigned short          shift_count;
 195        struct isi_port         *ports;
 196        signed char             count;
 197        spinlock_t              card_lock; /* Card wide lock 11/5/00 -sameer */
 198        unsigned long           flags;
 199        unsigned int            index;
 200};
 201
 202struct  isi_port {
 203        unsigned short          magic;
 204        struct tty_port         port;
 205        u16                     channel;
 206        u16                     status;
 207        struct isi_board        *card;
 208        unsigned char           *xmit_buf;
 209        int                     xmit_head;
 210        int                     xmit_tail;
 211        int                     xmit_cnt;
 212};
 213
 214static struct isi_board isi_card[BOARD_COUNT];
 215static struct isi_port  isi_ports[PORT_COUNT];
 216
 217/*
 218 *      Locking functions for card level locking. We need to own both
 219 *      the kernel lock for the card and have the card in a position that
 220 *      it wants to talk.
 221 */
 222
 223static inline int WaitTillCardIsFree(unsigned long base)
 224{
 225        unsigned int count = 0;
 226        unsigned int a = in_atomic(); /* do we run under spinlock? */
 227
 228        while (!(inw(base + 0xe) & 0x1) && count++ < 100)
 229                if (a)
 230                        mdelay(1);
 231                else
 232                        msleep(1);
 233
 234        return !(inw(base + 0xe) & 0x1);
 235}
 236
 237static int lock_card(struct isi_board *card)
 238{
 239        unsigned long base = card->base;
 240        unsigned int retries, a;
 241
 242        for (retries = 0; retries < 10; retries++) {
 243                spin_lock_irqsave(&card->card_lock, card->flags);
 244                for (a = 0; a < 10; a++) {
 245                        if (inw(base + 0xe) & 0x1)
 246                                return 1;
 247                        udelay(10);
 248                }
 249                spin_unlock_irqrestore(&card->card_lock, card->flags);
 250                msleep(10);
 251        }
 252        printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n",
 253                card->base);
 254
 255        return 0;       /* Failed to acquire the card! */
 256}
 257
 258static void unlock_card(struct isi_board *card)
 259{
 260        spin_unlock_irqrestore(&card->card_lock, card->flags);
 261}
 262
 263/*
 264 *  ISI Card specific ops ...
 265 */
 266
 267/* card->lock HAS to be held */
 268static void raise_dtr(struct isi_port *port)
 269{
 270        struct isi_board *card = port->card;
 271        unsigned long base = card->base;
 272        u16 channel = port->channel;
 273
 274        if (WaitTillCardIsFree(base))
 275                return;
 276
 277        outw(0x8000 | (channel << card->shift_count) | 0x02, base);
 278        outw(0x0504, base);
 279        InterruptTheCard(base);
 280        port->status |= ISI_DTR;
 281}
 282
 283/* card->lock HAS to be held */
 284static inline void drop_dtr(struct isi_port *port)
 285{
 286        struct isi_board *card = port->card;
 287        unsigned long base = card->base;
 288        u16 channel = port->channel;
 289
 290        if (WaitTillCardIsFree(base))
 291                return;
 292
 293        outw(0x8000 | (channel << card->shift_count) | 0x02, base);
 294        outw(0x0404, base);
 295        InterruptTheCard(base);
 296        port->status &= ~ISI_DTR;
 297}
 298
 299/* card->lock HAS to be held */
 300static inline void raise_rts(struct isi_port *port)
 301{
 302        struct isi_board *card = port->card;
 303        unsigned long base = card->base;
 304        u16 channel = port->channel;
 305
 306        if (WaitTillCardIsFree(base))
 307                return;
 308
 309        outw(0x8000 | (channel << card->shift_count) | 0x02, base);
 310        outw(0x0a04, base);
 311        InterruptTheCard(base);
 312        port->status |= ISI_RTS;
 313}
 314
 315/* card->lock HAS to be held */
 316static inline void drop_rts(struct isi_port *port)
 317{
 318        struct isi_board *card = port->card;
 319        unsigned long base = card->base;
 320        u16 channel = port->channel;
 321
 322        if (WaitTillCardIsFree(base))
 323                return;
 324
 325        outw(0x8000 | (channel << card->shift_count) | 0x02, base);
 326        outw(0x0804, base);
 327        InterruptTheCard(base);
 328        port->status &= ~ISI_RTS;
 329}
 330
 331/* card->lock MUST NOT be held */
 332
 333static void isicom_dtr_rts(struct tty_port *port, int on)
 334{
 335        struct isi_port *ip = container_of(port, struct isi_port, port);
 336        struct isi_board *card = ip->card;
 337        unsigned long base = card->base;
 338        u16 channel = ip->channel;
 339
 340        if (!lock_card(card))
 341                return;
 342
 343        if (on) {
 344                outw(0x8000 | (channel << card->shift_count) | 0x02, base);
 345                outw(0x0f04, base);
 346                InterruptTheCard(base);
 347                ip->status |= (ISI_DTR | ISI_RTS);
 348        } else {
 349                outw(0x8000 | (channel << card->shift_count) | 0x02, base);
 350                outw(0x0C04, base);
 351                InterruptTheCard(base);
 352                ip->status &= ~(ISI_DTR | ISI_RTS);
 353        }
 354        unlock_card(card);
 355}
 356
 357/* card->lock HAS to be held */
 358static void drop_dtr_rts(struct isi_port *port)
 359{
 360        struct isi_board *card = port->card;
 361        unsigned long base = card->base;
 362        u16 channel = port->channel;
 363
 364        if (WaitTillCardIsFree(base))
 365                return;
 366
 367        outw(0x8000 | (channel << card->shift_count) | 0x02, base);
 368        outw(0x0c04, base);
 369        InterruptTheCard(base);
 370        port->status &= ~(ISI_RTS | ISI_DTR);
 371}
 372
 373/*
 374 *      ISICOM Driver specific routines ...
 375 *
 376 */
 377
 378static inline int __isicom_paranoia_check(struct isi_port const *port,
 379        char *name, const char *routine)
 380{
 381        if (!port) {
 382                printk(KERN_WARNING "ISICOM: Warning: bad isicom magic for "
 383                        "dev %s in %s.\n", name, routine);
 384                return 1;
 385        }
 386        if (port->magic != ISICOM_MAGIC) {
 387                printk(KERN_WARNING "ISICOM: Warning: NULL isicom port for "
 388                        "dev %s in %s.\n", name, routine);
 389                return 1;
 390        }
 391
 392        return 0;
 393}
 394
 395/*
 396 *      Transmitter.
 397 *
 398 *      We shovel data into the card buffers on a regular basis. The card
 399 *      will do the rest of the work for us.
 400 */
 401
 402static void isicom_tx(unsigned long _data)
 403{
 404        unsigned long flags, base;
 405        unsigned int retries;
 406        short count = (BOARD_COUNT-1), card;
 407        short txcount, wrd, residue, word_count, cnt;
 408        struct isi_port *port;
 409        struct tty_struct *tty;
 410
 411        /*      find next active board  */
 412        card = (prev_card + 1) & 0x0003;
 413        while (count-- > 0) {
 414                if (isi_card[card].status & BOARD_ACTIVE)
 415                        break;
 416                card = (card + 1) & 0x0003;
 417        }
 418        if (!(isi_card[card].status & BOARD_ACTIVE))
 419                goto sched_again;
 420
 421        prev_card = card;
 422
 423        count = isi_card[card].port_count;
 424        port = isi_card[card].ports;
 425        base = isi_card[card].base;
 426
 427        spin_lock_irqsave(&isi_card[card].card_lock, flags);
 428        for (retries = 0; retries < 100; retries++) {
 429                if (inw(base + 0xe) & 0x1)
 430                        break;
 431                udelay(2);
 432        }
 433        if (retries >= 100)
 434                goto unlock;
 435
 436        tty = tty_port_tty_get(&port->port);
 437        if (tty == NULL)
 438                goto put_unlock;
 439
 440        for (; count > 0; count--, port++) {
 441                /* port not active or tx disabled to force flow control */
 442                if (!(port->port.flags & ASYNC_INITIALIZED) ||
 443                                !(port->status & ISI_TXOK))
 444                        continue;
 445
 446                txcount = min_t(short, TX_SIZE, port->xmit_cnt);
 447                if (txcount <= 0 || tty->stopped || tty->hw_stopped)
 448                        continue;
 449
 450                if (!(inw(base + 0x02) & (1 << port->channel)))
 451                        continue;
 452
 453                pr_dbg("txing %d bytes, port%d.\n", txcount,
 454                        port->channel + 1);
 455                outw((port->channel << isi_card[card].shift_count) | txcount,
 456                        base);
 457                residue = NO;
 458                wrd = 0;
 459                while (1) {
 460                        cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE
 461                                        - port->xmit_tail));
 462                        if (residue == YES) {
 463                                residue = NO;
 464                                if (cnt > 0) {
 465                                        wrd |= (port->port.xmit_buf[port->xmit_tail]
 466                                                                        << 8);
 467                                        port->xmit_tail = (port->xmit_tail + 1)
 468                                                & (SERIAL_XMIT_SIZE - 1);
 469                                        port->xmit_cnt--;
 470                                        txcount--;
 471                                        cnt--;
 472                                        outw(wrd, base);
 473                                } else {
 474                                        outw(wrd, base);
 475                                        break;
 476                                }
 477                        }
 478                        if (cnt <= 0)
 479                                break;
 480                        word_count = cnt >> 1;
 481                        outsw(base, port->port.xmit_buf+port->xmit_tail, word_count);
 482                        port->xmit_tail = (port->xmit_tail
 483                                + (word_count << 1)) & (SERIAL_XMIT_SIZE - 1);
 484                        txcount -= (word_count << 1);
 485                        port->xmit_cnt -= (word_count << 1);
 486                        if (cnt & 0x0001) {
 487                                residue = YES;
 488                                wrd = port->port.xmit_buf[port->xmit_tail];
 489                                port->xmit_tail = (port->xmit_tail + 1)
 490                                        & (SERIAL_XMIT_SIZE - 1);
 491                                port->xmit_cnt--;
 492                                txcount--;
 493                        }
 494                }
 495
 496                InterruptTheCard(base);
 497                if (port->xmit_cnt <= 0)
 498                        port->status &= ~ISI_TXOK;
 499                if (port->xmit_cnt <= WAKEUP_CHARS)
 500                        tty_wakeup(tty);
 501        }
 502
 503put_unlock:
 504        tty_kref_put(tty);
 505unlock:
 506        spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
 507        /*      schedule another tx for hopefully in about 10ms */
 508sched_again:
 509        mod_timer(&tx, jiffies + msecs_to_jiffies(10));
 510}
 511
 512/*
 513 *      Main interrupt handler routine
 514 */
 515
 516static irqreturn_t isicom_interrupt(int irq, void *dev_id)
 517{
 518        struct isi_board *card = dev_id;
 519        struct isi_port *port;
 520        struct tty_struct *tty;
 521        unsigned long base;
 522        u16 header, word_count, count, channel;
 523        short byte_count;
 524        unsigned char *rp;
 525
 526        if (!card || !(card->status & FIRMWARE_LOADED))
 527                return IRQ_NONE;
 528
 529        base = card->base;
 530
 531        /* did the card interrupt us? */
 532        if (!(inw(base + 0x0e) & 0x02))
 533                return IRQ_NONE;
 534
 535        spin_lock(&card->card_lock);
 536
 537        /*
 538         * disable any interrupts from the PCI card and lower the
 539         * interrupt line
 540         */
 541        outw(0x8000, base+0x04);
 542        ClearInterrupt(base);
 543
 544        inw(base);              /* get the dummy word out */
 545        header = inw(base);
 546        channel = (header & 0x7800) >> card->shift_count;
 547        byte_count = header & 0xff;
 548
 549        if (channel + 1 > card->port_count) {
 550                printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%lx): "
 551                        "%d(channel) > port_count.\n", base, channel+1);
 552                outw(0x0000, base+0x04); /* enable interrupts */
 553                spin_unlock(&card->card_lock);
 554                return IRQ_HANDLED;
 555        }
 556        port = card->ports + channel;
 557        if (!(port->port.flags & ASYNC_INITIALIZED)) {
 558                outw(0x0000, base+0x04); /* enable interrupts */
 559                spin_unlock(&card->card_lock);
 560                return IRQ_HANDLED;
 561        }
 562
 563        tty = tty_port_tty_get(&port->port);
 564        if (tty == NULL) {
 565                word_count = byte_count >> 1;
 566                while (byte_count > 1) {
 567                        inw(base);
 568                        byte_count -= 2;
 569                }
 570                if (byte_count & 0x01)
 571                        inw(base);
 572                outw(0x0000, base+0x04); /* enable interrupts */
 573                spin_unlock(&card->card_lock);
 574                return IRQ_HANDLED;
 575        }
 576
 577        if (header & 0x8000) {          /* Status Packet */
 578                header = inw(base);
 579                switch (header & 0xff) {
 580                case 0: /* Change in EIA signals */
 581                        if (port->port.flags & ASYNC_CHECK_CD) {
 582                                if (port->status & ISI_DCD) {
 583                                        if (!(header & ISI_DCD)) {
 584                                        /* Carrier has been lost  */
 585                                                pr_dbg("interrupt: DCD->low.\n"
 586                                                        );
 587                                                port->status &= ~ISI_DCD;
 588                                                tty_hangup(tty);
 589                                        }
 590                                } else if (header & ISI_DCD) {
 591                                /* Carrier has been detected */
 592                                        pr_dbg("interrupt: DCD->high.\n");
 593                                        port->status |= ISI_DCD;
 594                                        wake_up_interruptible(&port->port.open_wait);
 595                                }
 596                        } else {
 597                                if (header & ISI_DCD)
 598                                        port->status |= ISI_DCD;
 599                                else
 600                                        port->status &= ~ISI_DCD;
 601                        }
 602
 603                        if (port->port.flags & ASYNC_CTS_FLOW) {
 604                                if (tty->hw_stopped) {
 605                                        if (header & ISI_CTS) {
 606                                                port->port.tty->hw_stopped = 0;
 607                                                /* start tx ing */
 608                                                port->status |= (ISI_TXOK
 609                                                        | ISI_CTS);
 610                                                tty_wakeup(tty);
 611                                        }
 612                                } else if (!(header & ISI_CTS)) {
 613                                        tty->hw_stopped = 1;
 614                                        /* stop tx ing */
 615                                        port->status &= ~(ISI_TXOK | ISI_CTS);
 616                                }
 617                        } else {
 618                                if (header & ISI_CTS)
 619                                        port->status |= ISI_CTS;
 620                                else
 621                                        port->status &= ~ISI_CTS;
 622                        }
 623
 624                        if (header & ISI_DSR)
 625                                port->status |= ISI_DSR;
 626                        else
 627                                port->status &= ~ISI_DSR;
 628
 629                        if (header & ISI_RI)
 630                                port->status |= ISI_RI;
 631                        else
 632                                port->status &= ~ISI_RI;
 633
 634                        break;
 635
 636                case 1: /* Received Break !!! */
 637                        tty_insert_flip_char(tty, 0, TTY_BREAK);
 638                        if (port->port.flags & ASYNC_SAK)
 639                                do_SAK(tty);
 640                        tty_flip_buffer_push(tty);
 641                        break;
 642
 643                case 2: /* Statistics            */
 644                        pr_dbg("isicom_interrupt: stats!!!.\n");
 645                        break;
 646
 647                default:
 648                        pr_dbg("Intr: Unknown code in status packet.\n");
 649                        break;
 650                }
 651        } else {                                /* Data   Packet */
 652
 653                count = tty_prepare_flip_string(tty, &rp, byte_count & ~1);
 654                pr_dbg("Intr: Can rx %d of %d bytes.\n", count, byte_count);
 655                word_count = count >> 1;
 656                insw(base, rp, word_count);
 657                byte_count -= (word_count << 1);
 658                if (count & 0x0001) {
 659                        tty_insert_flip_char(tty,  inw(base) & 0xff,
 660                                TTY_NORMAL);
 661                        byte_count -= 2;
 662                }
 663                if (byte_count > 0) {
 664                        pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping "
 665                                "bytes...\n", base, channel + 1);
 666                /* drain out unread xtra data */
 667                while (byte_count > 0) {
 668                                inw(base);
 669                                byte_count -= 2;
 670                        }
 671                }
 672                tty_flip_buffer_push(tty);
 673        }
 674        outw(0x0000, base+0x04); /* enable interrupts */
 675        spin_unlock(&card->card_lock);
 676        tty_kref_put(tty);
 677
 678        return IRQ_HANDLED;
 679}
 680
 681static void isicom_config_port(struct tty_struct *tty)
 682{
 683        struct isi_port *port = tty->driver_data;
 684        struct isi_board *card = port->card;
 685        unsigned long baud;
 686        unsigned long base = card->base;
 687        u16 channel_setup, channel = port->channel,
 688                shift_count = card->shift_count;
 689        unsigned char flow_ctrl;
 690
 691        /* FIXME: Switch to new tty baud API */
 692        baud = C_BAUD(tty);
 693        if (baud & CBAUDEX) {
 694                baud &= ~CBAUDEX;
 695
 696                /*  if CBAUDEX bit is on and the baud is set to either 50 or 75
 697                 *  then the card is programmed for 57.6Kbps or 115Kbps
 698                 *  respectively.
 699                 */
 700
 701                /* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */
 702                if (baud < 1 || baud > 4)
 703                        tty->termios->c_cflag &= ~CBAUDEX;
 704                else
 705                        baud += 15;
 706        }
 707        if (baud == 15) {
 708
 709                /*  the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set
 710                 *  by the set_serial_info ioctl ... this is done by
 711                 *  the 'setserial' utility.
 712                 */
 713
 714                if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
 715                        baud++; /*  57.6 Kbps */
 716                if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
 717                        baud += 2; /*  115  Kbps */
 718                if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
 719                        baud += 3; /* 230 kbps*/
 720                if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
 721                        baud += 4; /* 460 kbps*/
 722        }
 723        if (linuxb_to_isib[baud] == -1) {
 724                /* hang up */
 725                drop_dtr(port);
 726                return;
 727        } else
 728                raise_dtr(port);
 729
 730        if (WaitTillCardIsFree(base) == 0) {
 731                outw(0x8000 | (channel << shift_count) | 0x03, base);
 732                outw(linuxb_to_isib[baud] << 8 | 0x03, base);
 733                channel_setup = 0;
 734                switch (C_CSIZE(tty)) {
 735                case CS5:
 736                        channel_setup |= ISICOM_CS5;
 737                        break;
 738                case CS6:
 739                        channel_setup |= ISICOM_CS6;
 740                        break;
 741                case CS7:
 742                        channel_setup |= ISICOM_CS7;
 743                        break;
 744                case CS8:
 745                        channel_setup |= ISICOM_CS8;
 746                        break;
 747                }
 748
 749                if (C_CSTOPB(tty))
 750                        channel_setup |= ISICOM_2SB;
 751                if (C_PARENB(tty)) {
 752                        channel_setup |= ISICOM_EVPAR;
 753                        if (C_PARODD(tty))
 754                                channel_setup |= ISICOM_ODPAR;
 755                }
 756                outw(channel_setup, base);
 757                InterruptTheCard(base);
 758        }
 759        if (C_CLOCAL(tty))
 760                port->port.flags &= ~ASYNC_CHECK_CD;
 761        else
 762                port->port.flags |= ASYNC_CHECK_CD;
 763
 764        /* flow control settings ...*/
 765        flow_ctrl = 0;
 766        port->port.flags &= ~ASYNC_CTS_FLOW;
 767        if (C_CRTSCTS(tty)) {
 768                port->port.flags |= ASYNC_CTS_FLOW;
 769                flow_ctrl |= ISICOM_CTSRTS;
 770        }
 771        if (I_IXON(tty))
 772                flow_ctrl |= ISICOM_RESPOND_XONXOFF;
 773        if (I_IXOFF(tty))
 774                flow_ctrl |= ISICOM_INITIATE_XONXOFF;
 775
 776        if (WaitTillCardIsFree(base) == 0) {
 777                outw(0x8000 | (channel << shift_count) | 0x04, base);
 778                outw(flow_ctrl << 8 | 0x05, base);
 779                outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
 780                InterruptTheCard(base);
 781        }
 782
 783        /*      rx enabled -> enable port for rx on the card    */
 784        if (C_CREAD(tty)) {
 785                card->port_status |= (1 << channel);
 786                outw(card->port_status, base + 0x02);
 787        }
 788}
 789
 790/* open et all */
 791
 792static inline void isicom_setup_board(struct isi_board *bp)
 793{
 794        int channel;
 795        struct isi_port *port;
 796        unsigned long flags;
 797
 798        spin_lock_irqsave(&bp->card_lock, flags);
 799        if (bp->status & BOARD_ACTIVE) {
 800                spin_unlock_irqrestore(&bp->card_lock, flags);
 801                return;
 802        }
 803        port = bp->ports;
 804        bp->status |= BOARD_ACTIVE;
 805        for (channel = 0; channel < bp->port_count; channel++, port++)
 806                drop_dtr_rts(port);
 807        spin_unlock_irqrestore(&bp->card_lock, flags);
 808}
 809
 810static int isicom_setup_port(struct tty_struct *tty)
 811{
 812        struct isi_port *port = tty->driver_data;
 813        struct isi_board *card = port->card;
 814        unsigned long flags;
 815
 816        if (port->port.flags & ASYNC_INITIALIZED)
 817                return 0;
 818        if (tty_port_alloc_xmit_buf(&port->port) < 0)
 819                return -ENOMEM;
 820
 821        spin_lock_irqsave(&card->card_lock, flags);
 822        clear_bit(TTY_IO_ERROR, &tty->flags);
 823        if (port->port.count == 1)
 824                card->count++;
 825
 826        port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
 827
 828        /*      discard any residual data       */
 829        if (WaitTillCardIsFree(card->base) == 0) {
 830                outw(0x8000 | (port->channel << card->shift_count) | 0x02,
 831                                card->base);
 832                outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base);
 833                InterruptTheCard(card->base);
 834        }
 835
 836        isicom_config_port(tty);
 837        port->port.flags |= ASYNC_INITIALIZED;
 838        spin_unlock_irqrestore(&card->card_lock, flags);
 839
 840        return 0;
 841}
 842
 843static int isicom_carrier_raised(struct tty_port *port)
 844{
 845        struct isi_port *ip = container_of(port, struct isi_port, port);
 846        return (ip->status & ISI_DCD)?1 : 0;
 847}
 848
 849static struct tty_port *isicom_find_port(struct tty_struct *tty)
 850{
 851        struct isi_port *port;
 852        struct isi_board *card;
 853        unsigned int board;
 854        int line = tty->index;
 855
 856        if (line < 0 || line > PORT_COUNT-1)
 857                return NULL;
 858        board = BOARD(line);
 859        card = &isi_card[board];
 860
 861        if (!(card->status & FIRMWARE_LOADED))
 862                return NULL;
 863
 864        /*  open on a port greater than the port count for the card !!! */
 865        if (line > ((board * 16) + card->port_count - 1))
 866                return NULL;
 867
 868        port = &isi_ports[line];
 869        if (isicom_paranoia_check(port, tty->name, "isicom_open"))
 870                return NULL;
 871
 872        return &port->port;
 873}
 874        
 875static int isicom_open(struct tty_struct *tty, struct file *filp)
 876{
 877        struct isi_port *port;
 878        struct isi_board *card;
 879        struct tty_port *tport;
 880        int error = 0;
 881
 882        tport = isicom_find_port(tty);
 883        if (tport == NULL)
 884                return -ENODEV;
 885        port = container_of(tport, struct isi_port, port);
 886        card = &isi_card[BOARD(tty->index)];
 887        isicom_setup_board(card);
 888
 889        /* FIXME: locking on port.count etc */
 890        port->port.count++;
 891        tty->driver_data = port;
 892        tty_port_tty_set(&port->port, tty);
 893        /* FIXME: Locking on Initialized flag */
 894        if (!test_bit(ASYNCB_INITIALIZED, &tport->flags))
 895                error = isicom_setup_port(tty);
 896        if (error == 0)
 897                error = tty_port_block_til_ready(&port->port, tty, filp);
 898        return error;
 899}
 900
 901/* close et all */
 902
 903static inline void isicom_shutdown_board(struct isi_board *bp)
 904{
 905        if (bp->status & BOARD_ACTIVE)
 906                bp->status &= ~BOARD_ACTIVE;
 907}
 908
 909/* card->lock HAS to be held */
 910static void isicom_shutdown_port(struct isi_port *port)
 911{
 912        struct isi_board *card = port->card;
 913        struct tty_struct *tty;
 914
 915        tty = tty_port_tty_get(&port->port);
 916
 917        if (!(port->port.flags & ASYNC_INITIALIZED)) {
 918                tty_kref_put(tty);
 919                return;
 920        }
 921
 922        tty_port_free_xmit_buf(&port->port);
 923        port->port.flags &= ~ASYNC_INITIALIZED;
 924        /* 3rd October 2000 : Vinayak P Risbud */
 925        tty_port_tty_set(&port->port, NULL);
 926
 927        /*Fix done by Anil .S on 30-04-2001
 928        remote login through isi port has dtr toggle problem
 929        due to which the carrier drops before the password prompt
 930        appears on the remote end. Now we drop the dtr only if the
 931        HUPCL(Hangup on close) flag is set for the tty*/
 932
 933        if (C_HUPCL(tty))
 934                /* drop dtr on this port */
 935                drop_dtr(port);
 936
 937        /* any other port uninits  */
 938        if (tty)
 939                set_bit(TTY_IO_ERROR, &tty->flags);
 940
 941        if (--card->count < 0) {
 942                pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n",
 943                        card->base, card->count);
 944                card->count = 0;
 945        }
 946
 947        /* last port was closed, shutdown that boad too */
 948        if (C_HUPCL(tty)) {
 949                if (!card->count)
 950                        isicom_shutdown_board(card);
 951        }
 952        tty_kref_put(tty);
 953}
 954
 955static void isicom_flush_buffer(struct tty_struct *tty)
 956{
 957        struct isi_port *port = tty->driver_data;
 958        struct isi_board *card = port->card;
 959        unsigned long flags;
 960
 961        if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
 962                return;
 963
 964        spin_lock_irqsave(&card->card_lock, flags);
 965        port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
 966        spin_unlock_irqrestore(&card->card_lock, flags);
 967
 968        tty_wakeup(tty);
 969}
 970
 971static void isicom_close_port(struct tty_port *port)
 972{
 973        struct isi_port *ip = container_of(port, struct isi_port, port);
 974        struct isi_board *card = ip->card;
 975        unsigned long flags;
 976
 977        /* indicate to the card that no more data can be received
 978           on this port */
 979        spin_lock_irqsave(&card->card_lock, flags);
 980        if (port->flags & ASYNC_INITIALIZED) {
 981                card->port_status &= ~(1 << ip->channel);
 982                outw(card->port_status, card->base + 0x02);
 983        }
 984        isicom_shutdown_port(ip);
 985        spin_unlock_irqrestore(&card->card_lock, flags);
 986}
 987
 988static void isicom_close(struct tty_struct *tty, struct file *filp)
 989{
 990        struct isi_port *ip = tty->driver_data;
 991        struct tty_port *port = &ip->port;
 992        if (isicom_paranoia_check(ip, tty->name, "isicom_close"))
 993                return;
 994
 995        if (tty_port_close_start(port, tty, filp) == 0)
 996                return;
 997        isicom_close_port(port);
 998        isicom_flush_buffer(tty);
 999        tty_port_close_end(port, tty);
1000}
1001
1002/* write et all */
1003static int isicom_write(struct tty_struct *tty, const unsigned char *buf,
1004        int count)
1005{
1006        struct isi_port *port = tty->driver_data;
1007        struct isi_board *card = port->card;
1008        unsigned long flags;
1009        int cnt, total = 0;
1010
1011        if (isicom_paranoia_check(port, tty->name, "isicom_write"))
1012                return 0;
1013
1014        spin_lock_irqsave(&card->card_lock, flags);
1015
1016        while (1) {
1017                cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt
1018                                - 1, SERIAL_XMIT_SIZE - port->xmit_head));
1019                if (cnt <= 0)
1020                        break;
1021
1022                memcpy(port->port.xmit_buf + port->xmit_head, buf, cnt);
1023                port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE
1024                        - 1);
1025                port->xmit_cnt += cnt;
1026                buf += cnt;
1027                count -= cnt;
1028                total += cnt;
1029        }
1030        if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
1031                port->status |= ISI_TXOK;
1032        spin_unlock_irqrestore(&card->card_lock, flags);
1033        return total;
1034}
1035
1036/* put_char et all */
1037static int isicom_put_char(struct tty_struct *tty, unsigned char ch)
1038{
1039        struct isi_port *port = tty->driver_data;
1040        struct isi_board *card = port->card;
1041        unsigned long flags;
1042
1043        if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
1044                return 0;
1045
1046        spin_lock_irqsave(&card->card_lock, flags);
1047        if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
1048                spin_unlock_irqrestore(&card->card_lock, flags);
1049                return 0;
1050        }
1051
1052        port->port.xmit_buf[port->xmit_head++] = ch;
1053        port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
1054        port->xmit_cnt++;
1055        spin_unlock_irqrestore(&card->card_lock, flags);
1056        return 1;
1057}
1058
1059/* flush_chars et all */
1060static void isicom_flush_chars(struct tty_struct *tty)
1061{
1062        struct isi_port *port = tty->driver_data;
1063
1064        if (isicom_paranoia_check(port, tty->name, "isicom_flush_chars"))
1065                return;
1066
1067        if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
1068                        !port->port.xmit_buf)
1069                return;
1070
1071        /* this tells the transmitter to consider this port for
1072           data output to the card ... that's the best we can do. */
1073        port->status |= ISI_TXOK;
1074}
1075
1076/* write_room et all */
1077static int isicom_write_room(struct tty_struct *tty)
1078{
1079        struct isi_port *port = tty->driver_data;
1080        int free;
1081
1082        if (isicom_paranoia_check(port, tty->name, "isicom_write_room"))
1083                return 0;
1084
1085        free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
1086        if (free < 0)
1087                free = 0;
1088        return free;
1089}
1090
1091/* chars_in_buffer et all */
1092static int isicom_chars_in_buffer(struct tty_struct *tty)
1093{
1094        struct isi_port *port = tty->driver_data;
1095        if (isicom_paranoia_check(port, tty->name, "isicom_chars_in_buffer"))
1096                return 0;
1097        return port->xmit_cnt;
1098}
1099
1100/* ioctl et all */
1101static int isicom_send_break(struct tty_struct *tty, int length)
1102{
1103        struct isi_port *port = tty->driver_data;
1104        struct isi_board *card = port->card;
1105        unsigned long base = card->base;
1106
1107        if (length == -1)
1108                return -EOPNOTSUPP;
1109
1110        if (!lock_card(card))
1111                return -EINVAL;
1112
1113        outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
1114        outw((length & 0xff) << 8 | 0x00, base);
1115        outw((length & 0xff00), base);
1116        InterruptTheCard(base);
1117
1118        unlock_card(card);
1119        return 0;
1120}
1121
1122static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
1123{
1124        struct isi_port *port = tty->driver_data;
1125        /* just send the port status */
1126        u16 status = port->status;
1127
1128        if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
1129                return -ENODEV;
1130
1131        return  ((status & ISI_RTS) ? TIOCM_RTS : 0) |
1132                ((status & ISI_DTR) ? TIOCM_DTR : 0) |
1133                ((status & ISI_DCD) ? TIOCM_CAR : 0) |
1134                ((status & ISI_DSR) ? TIOCM_DSR : 0) |
1135                ((status & ISI_CTS) ? TIOCM_CTS : 0) |
1136                ((status & ISI_RI ) ? TIOCM_RI  : 0);
1137}
1138
1139static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
1140        unsigned int set, unsigned int clear)
1141{
1142        struct isi_port *port = tty->driver_data;
1143        unsigned long flags;
1144
1145        if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
1146                return -ENODEV;
1147
1148        spin_lock_irqsave(&port->card->card_lock, flags);
1149        if (set & TIOCM_RTS)
1150                raise_rts(port);
1151        if (set & TIOCM_DTR)
1152                raise_dtr(port);
1153
1154        if (clear & TIOCM_RTS)
1155                drop_rts(port);
1156        if (clear & TIOCM_DTR)
1157                drop_dtr(port);
1158        spin_unlock_irqrestore(&port->card->card_lock, flags);
1159
1160        return 0;
1161}
1162
1163static int isicom_set_serial_info(struct tty_struct *tty,
1164                                        struct serial_struct __user *info)
1165{
1166        struct isi_port *port = tty->driver_data;
1167        struct serial_struct newinfo;
1168        int reconfig_port;
1169
1170        if (copy_from_user(&newinfo, info, sizeof(newinfo)))
1171                return -EFAULT;
1172
1173        lock_kernel();
1174
1175        reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) !=
1176                (newinfo.flags & ASYNC_SPD_MASK));
1177
1178        if (!capable(CAP_SYS_ADMIN)) {
1179                if ((newinfo.close_delay != port->port.close_delay) ||
1180                                (newinfo.closing_wait != port->port.closing_wait) ||
1181                                ((newinfo.flags & ~ASYNC_USR_MASK) !=
1182                                (port->port.flags & ~ASYNC_USR_MASK))) {
1183                        unlock_kernel();
1184                        return -EPERM;
1185                }
1186                port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
1187                                (newinfo.flags & ASYNC_USR_MASK));
1188        } else {
1189                port->port.close_delay = newinfo.close_delay;
1190                port->port.closing_wait = newinfo.closing_wait;
1191                port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
1192                                (newinfo.flags & ASYNC_FLAGS));
1193        }
1194        if (reconfig_port) {
1195                unsigned long flags;
1196                spin_lock_irqsave(&port->card->card_lock, flags);
1197                isicom_config_port(tty);
1198                spin_unlock_irqrestore(&port->card->card_lock, flags);
1199        }
1200        unlock_kernel();
1201        return 0;
1202}
1203
1204static int isicom_get_serial_info(struct isi_port *port,
1205        struct serial_struct __user *info)
1206{
1207        struct serial_struct out_info;
1208
1209        lock_kernel();
1210        memset(&out_info, 0, sizeof(out_info));
1211/*      out_info.type = ? */
1212        out_info.line = port - isi_ports;
1213        out_info.port = port->card->base;
1214        out_info.irq = port->card->irq;
1215        out_info.flags = port->port.flags;
1216/*      out_info.baud_base = ? */
1217        out_info.close_delay = port->port.close_delay;
1218        out_info.closing_wait = port->port.closing_wait;
1219        unlock_kernel();
1220        if (copy_to_user(info, &out_info, sizeof(out_info)))
1221                return -EFAULT;
1222        return 0;
1223}
1224
1225static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
1226        unsigned int cmd, unsigned long arg)
1227{
1228        struct isi_port *port = tty->driver_data;
1229        void __user *argp = (void __user *)arg;
1230
1231        if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
1232                return -ENODEV;
1233
1234        switch (cmd) {
1235        case TIOCGSERIAL:
1236                return isicom_get_serial_info(port, argp);
1237
1238        case TIOCSSERIAL:
1239                return isicom_set_serial_info(tty, argp);
1240
1241        default:
1242                return -ENOIOCTLCMD;
1243        }
1244        return 0;
1245}
1246
1247/* set_termios et all */
1248static void isicom_set_termios(struct tty_struct *tty,
1249        struct ktermios *old_termios)
1250{
1251        struct isi_port *port = tty->driver_data;
1252        unsigned long flags;
1253
1254        if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
1255                return;
1256
1257        if (tty->termios->c_cflag == old_termios->c_cflag &&
1258                        tty->termios->c_iflag == old_termios->c_iflag)
1259                return;
1260
1261        spin_lock_irqsave(&port->card->card_lock, flags);
1262        isicom_config_port(tty);
1263        spin_unlock_irqrestore(&port->card->card_lock, flags);
1264
1265        if ((old_termios->c_cflag & CRTSCTS) &&
1266                        !(tty->termios->c_cflag & CRTSCTS)) {
1267                tty->hw_stopped = 0;
1268                isicom_start(tty);
1269        }
1270}
1271
1272/* throttle et all */
1273static void isicom_throttle(struct tty_struct *tty)
1274{
1275        struct isi_port *port = tty->driver_data;
1276        struct isi_board *card = port->card;
1277
1278        if (isicom_paranoia_check(port, tty->name, "isicom_throttle"))
1279                return;
1280
1281        /* tell the card that this port cannot handle any more data for now */
1282        card->port_status &= ~(1 << port->channel);
1283        outw(card->port_status, card->base + 0x02);
1284}
1285
1286/* unthrottle et all */
1287static void isicom_unthrottle(struct tty_struct *tty)
1288{
1289        struct isi_port *port = tty->driver_data;
1290        struct isi_board *card = port->card;
1291
1292        if (isicom_paranoia_check(port, tty->name, "isicom_unthrottle"))
1293                return;
1294
1295        /* tell the card that this port is ready to accept more data */
1296        card->port_status |= (1 << port->channel);
1297        outw(card->port_status, card->base + 0x02);
1298}
1299
1300/* stop et all */
1301static void isicom_stop(struct tty_struct *tty)
1302{
1303        struct isi_port *port = tty->driver_data;
1304
1305        if (isicom_paranoia_check(port, tty->name, "isicom_stop"))
1306                return;
1307
1308        /* this tells the transmitter not to consider this port for
1309           data output to the card. */
1310        port->status &= ~ISI_TXOK;
1311}
1312
1313/* start et all */
1314static void isicom_start(struct tty_struct *tty)
1315{
1316        struct isi_port *port = tty->driver_data;
1317
1318        if (isicom_paranoia_check(port, tty->name, "isicom_start"))
1319                return;
1320
1321        /* this tells the transmitter to consider this port for
1322           data output to the card. */
1323        port->status |= ISI_TXOK;
1324}
1325
1326static void isicom_hangup(struct tty_struct *tty)
1327{
1328        struct isi_port *port = tty->driver_data;
1329        unsigned long flags;
1330
1331        if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
1332                return;
1333
1334        spin_lock_irqsave(&port->card->card_lock, flags);
1335        isicom_shutdown_port(port);
1336        spin_unlock_irqrestore(&port->card->card_lock, flags);
1337
1338        tty_port_hangup(&port->port);
1339}
1340
1341
1342/*
1343 * Driver init and deinit functions
1344 */
1345
1346static const struct tty_operations isicom_ops = {
1347        .open                   = isicom_open,
1348        .close                  = isicom_close,
1349        .write                  = isicom_write,
1350        .put_char               = isicom_put_char,
1351        .flush_chars            = isicom_flush_chars,
1352        .write_room             = isicom_write_room,
1353        .chars_in_buffer        = isicom_chars_in_buffer,
1354        .ioctl                  = isicom_ioctl,
1355        .set_termios            = isicom_set_termios,
1356        .throttle               = isicom_throttle,
1357        .unthrottle             = isicom_unthrottle,
1358        .stop                   = isicom_stop,
1359        .start                  = isicom_start,
1360        .hangup                 = isicom_hangup,
1361        .flush_buffer           = isicom_flush_buffer,
1362        .tiocmget               = isicom_tiocmget,
1363        .tiocmset               = isicom_tiocmset,
1364        .break_ctl              = isicom_send_break,
1365};
1366
1367static const struct tty_port_operations isicom_port_ops = {
1368        .carrier_raised         = isicom_carrier_raised,
1369        .dtr_rts                = isicom_dtr_rts,
1370};
1371
1372static int __devinit reset_card(struct pci_dev *pdev,
1373        const unsigned int card, unsigned int *signature)
1374{
1375        struct isi_board *board = pci_get_drvdata(pdev);
1376        unsigned long base = board->base;
1377        unsigned int sig, portcount = 0;
1378        int retval = 0;
1379
1380        dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1,
1381                base);
1382
1383        inw(base + 0x8);
1384
1385        msleep(10);
1386
1387        outw(0, base + 0x8); /* Reset */
1388
1389        msleep(1000);
1390
1391        sig = inw(base + 0x4) & 0xff;
1392
1393        if (sig != 0xa5 && sig != 0xbb && sig != 0xcc && sig != 0xdd &&
1394                        sig != 0xee) {
1395                dev_warn(&pdev->dev, "ISILoad:Card%u reset failure (Possible "
1396                        "bad I/O Port Address 0x%lx).\n", card + 1, base);
1397                dev_dbg(&pdev->dev, "Sig=0x%x\n", sig);
1398                retval = -EIO;
1399                goto end;
1400        }
1401
1402        msleep(10);
1403
1404        portcount = inw(base + 0x2);
1405        if (!(inw(base + 0xe) & 0x1) || (portcount != 0 && portcount != 4 &&
1406                                portcount != 8 && portcount != 16)) {
1407                dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.\n",
1408                        card + 1);
1409                retval = -EIO;
1410                goto end;
1411        }
1412
1413        switch (sig) {
1414        case 0xa5:
1415        case 0xbb:
1416        case 0xdd:
1417                board->port_count = (portcount == 4) ? 4 : 8;
1418                board->shift_count = 12;
1419                break;
1420        case 0xcc:
1421        case 0xee:
1422                board->port_count = 16;
1423                board->shift_count = 11;
1424                break;
1425        }
1426        dev_info(&pdev->dev, "-Done\n");
1427        *signature = sig;
1428
1429end:
1430        return retval;
1431}
1432
1433static int __devinit load_firmware(struct pci_dev *pdev,
1434        const unsigned int index, const unsigned int signature)
1435{
1436        struct isi_board *board = pci_get_drvdata(pdev);
1437        const struct firmware *fw;
1438        unsigned long base = board->base;
1439        unsigned int a;
1440        u16 word_count, status;
1441        int retval = -EIO;
1442        char *name;
1443        u8 *data;
1444
1445        struct stframe {
1446                u16     addr;
1447                u16     count;
1448                u8      data[0];
1449        } *frame;
1450
1451        switch (signature) {
1452        case 0xa5:
1453                name = "isi608.bin";
1454                break;
1455        case 0xbb:
1456                name = "isi608em.bin";
1457                break;
1458        case 0xcc:
1459                name = "isi616em.bin";
1460                break;
1461        case 0xdd:
1462                name = "isi4608.bin";
1463                break;
1464        case 0xee:
1465                name = "isi4616.bin";
1466                break;
1467        default:
1468                dev_err(&pdev->dev, "Unknown signature.\n");
1469                goto end;
1470        }
1471
1472        retval = request_firmware(&fw, name, &pdev->dev);
1473        if (retval)
1474                goto end;
1475
1476        retval = -EIO;
1477
1478        for (frame = (struct stframe *)fw->data;
1479                        frame < (struct stframe *)(fw->data + fw->size);
1480                        frame = (struct stframe *)((u8 *)(frame + 1) +
1481                                frame->count)) {
1482                if (WaitTillCardIsFree(base))
1483                        goto errrelfw;
1484
1485                outw(0xf0, base);       /* start upload sequence */
1486                outw(0x00, base);
1487                outw(frame->addr, base); /* lsb of address */
1488
1489                word_count = frame->count / 2 + frame->count % 2;
1490                outw(word_count, base);
1491                InterruptTheCard(base);
1492
1493                udelay(100); /* 0x2f */
1494
1495                if (WaitTillCardIsFree(base))
1496                        goto errrelfw;
1497
1498                status = inw(base + 0x4);
1499                if (status != 0) {
1500                        dev_warn(&pdev->dev, "Card%d rejected load header:\n"
1501                                 "Address:0x%x\n"
1502                                 "Count:0x%x\n"
1503                                 "Status:0x%x\n",
1504                                 index + 1, frame->addr, frame->count, status);
1505                        goto errrelfw;
1506                }
1507                outsw(base, frame->data, word_count);
1508
1509                InterruptTheCard(base);
1510
1511                udelay(50); /* 0x0f */
1512
1513                if (WaitTillCardIsFree(base))
1514                        goto errrelfw;
1515
1516                status = inw(base + 0x4);
1517                if (status != 0) {
1518                        dev_err(&pdev->dev, "Card%d got out of sync.Card "
1519                                "Status:0x%x\n", index + 1, status);
1520                        goto errrelfw;
1521                }
1522        }
1523
1524/* XXX: should we test it by reading it back and comparing with original like
1525 * in load firmware package? */
1526        for (frame = (struct stframe *)fw->data;
1527                        frame < (struct stframe *)(fw->data + fw->size);
1528                        frame = (struct stframe *)((u8 *)(frame + 1) +
1529                                frame->count)) {
1530                if (WaitTillCardIsFree(base))
1531                        goto errrelfw;
1532
1533                outw(0xf1, base); /* start download sequence */
1534                outw(0x00, base);
1535                outw(frame->addr, base); /* lsb of address */
1536
1537                word_count = (frame->count >> 1) + frame->count % 2;
1538                outw(word_count + 1, base);
1539                InterruptTheCard(base);
1540
1541                udelay(50); /* 0xf */
1542
1543                if (WaitTillCardIsFree(base))
1544                        goto errrelfw;
1545
1546                status = inw(base + 0x4);
1547                if (status != 0) {
1548                        dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
1549                                 "Address:0x%x\n"
1550                                 "Count:0x%x\n"
1551                                 "Status: 0x%x\n",
1552                                 index + 1, frame->addr, frame->count, status);
1553                        goto errrelfw;
1554                }
1555
1556                data = kmalloc(word_count * 2, GFP_KERNEL);
1557                if (data == NULL) {
1558                        dev_err(&pdev->dev, "Card%d, firmware upload "
1559                                "failed, not enough memory\n", index + 1);
1560                        goto errrelfw;
1561                }
1562                inw(base);
1563                insw(base, data, word_count);
1564                InterruptTheCard(base);
1565
1566                for (a = 0; a < frame->count; a++)
1567                        if (data[a] != frame->data[a]) {
1568                                kfree(data);
1569                                dev_err(&pdev->dev, "Card%d, firmware upload "
1570                                        "failed\n", index + 1);
1571                                goto errrelfw;
1572                        }
1573                kfree(data);
1574
1575                udelay(50); /* 0xf */
1576
1577                if (WaitTillCardIsFree(base))
1578                        goto errrelfw;
1579
1580                status = inw(base + 0x4);
1581                if (status != 0) {
1582                        dev_err(&pdev->dev, "Card%d verify got out of sync. "
1583                                "Card Status:0x%x\n", index + 1, status);
1584                        goto errrelfw;
1585                }
1586        }
1587
1588        /* xfer ctrl */
1589        if (WaitTillCardIsFree(base))
1590                goto errrelfw;
1591
1592        outw(0xf2, base);
1593        outw(0x800, base);
1594        outw(0x0, base);
1595        outw(0x0, base);
1596        InterruptTheCard(base);
1597        outw(0x0, base + 0x4); /* for ISI4608 cards */
1598
1599        board->status |= FIRMWARE_LOADED;
1600        retval = 0;
1601
1602errrelfw:
1603        release_firmware(fw);
1604end:
1605        return retval;
1606}
1607
1608/*
1609 *      Insmod can set static symbols so keep these static
1610 */
1611static unsigned int card_count;
1612
1613static int __devinit isicom_probe(struct pci_dev *pdev,
1614        const struct pci_device_id *ent)
1615{
1616        unsigned int uninitialized_var(signature), index;
1617        int retval = -EPERM;
1618        struct isi_board *board = NULL;
1619
1620        if (card_count >= BOARD_COUNT)
1621                goto err;
1622
1623        retval = pci_enable_device(pdev);
1624        if (retval) {
1625                dev_err(&pdev->dev, "failed to enable\n");
1626                goto err;
1627        }
1628
1629        dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
1630
1631        /* allot the first empty slot in the array */
1632        for (index = 0; index < BOARD_COUNT; index++)
1633                if (isi_card[index].base == 0) {
1634                        board = &isi_card[index];
1635                        break;
1636                }
1637
1638        board->index = index;
1639        board->base = pci_resource_start(pdev, 3);
1640        board->irq = pdev->irq;
1641        card_count++;
1642
1643        pci_set_drvdata(pdev, board);
1644
1645        retval = pci_request_region(pdev, 3, ISICOM_NAME);
1646        if (retval) {
1647                dev_err(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d "
1648                        "will be disabled.\n", board->base, board->base + 15,
1649                        index + 1);
1650                retval = -EBUSY;
1651                goto errdec;
1652        }
1653
1654        retval = request_irq(board->irq, isicom_interrupt,
1655                        IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board);
1656        if (retval < 0) {
1657                dev_err(&pdev->dev, "Could not install handler at Irq %d. "
1658                        "Card%d will be disabled.\n", board->irq, index + 1);
1659                goto errunrr;
1660        }
1661
1662        retval = reset_card(pdev, index, &signature);
1663        if (retval < 0)
1664                goto errunri;
1665
1666        retval = load_firmware(pdev, index, signature);
1667        if (retval < 0)
1668                goto errunri;
1669
1670        for (index = 0; index < board->port_count; index++)
1671                tty_register_device(isicom_normal, board->index * 16 + index,
1672                                &pdev->dev);
1673
1674        return 0;
1675
1676errunri:
1677        free_irq(board->irq, board);
1678errunrr:
1679        pci_release_region(pdev, 3);
1680errdec:
1681        board->base = 0;
1682        card_count--;
1683        pci_disable_device(pdev);
1684err:
1685        return retval;
1686}
1687
1688static void __devexit isicom_remove(struct pci_dev *pdev)
1689{
1690        struct isi_board *board = pci_get_drvdata(pdev);
1691        unsigned int i;
1692
1693        for (i = 0; i < board->port_count; i++)
1694                tty_unregister_device(isicom_normal, board->index * 16 + i);
1695
1696        free_irq(board->irq, board);
1697        pci_release_region(pdev, 3);
1698        board->base = 0;
1699        card_count--;
1700        pci_disable_device(pdev);
1701}
1702
1703static int __init isicom_init(void)
1704{
1705        int retval, idx, channel;
1706        struct isi_port *port;
1707
1708        for (idx = 0; idx < BOARD_COUNT; idx++) {
1709                port = &isi_ports[idx * 16];
1710                isi_card[idx].ports = port;
1711                spin_lock_init(&isi_card[idx].card_lock);
1712                for (channel = 0; channel < 16; channel++, port++) {
1713                        tty_port_init(&port->port);
1714                        port->port.ops = &isicom_port_ops;
1715                        port->magic = ISICOM_MAGIC;
1716                        port->card = &isi_card[idx];
1717                        port->channel = channel;
1718                        port->port.close_delay = 50 * HZ/100;
1719                        port->port.closing_wait = 3000 * HZ/100;
1720                        port->status = 0;
1721                        /*  . . .  */
1722                }
1723                isi_card[idx].base = 0;
1724                isi_card[idx].irq = 0;
1725        }
1726
1727        /* tty driver structure initialization */
1728        isicom_normal = alloc_tty_driver(PORT_COUNT);
1729        if (!isicom_normal) {
1730                retval = -ENOMEM;
1731                goto error;
1732        }
1733
1734        isicom_normal->owner                    = THIS_MODULE;
1735        isicom_normal->name                     = "ttyM";
1736        isicom_normal->major                    = ISICOM_NMAJOR;
1737        isicom_normal->minor_start              = 0;
1738        isicom_normal->type                     = TTY_DRIVER_TYPE_SERIAL;
1739        isicom_normal->subtype                  = SERIAL_TYPE_NORMAL;
1740        isicom_normal->init_termios             = tty_std_termios;
1741        isicom_normal->init_termios.c_cflag     = B9600 | CS8 | CREAD | HUPCL |
1742                CLOCAL;
1743        isicom_normal->flags                    = TTY_DRIVER_REAL_RAW |
1744                TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK;
1745        tty_set_operations(isicom_normal, &isicom_ops);
1746
1747        retval = tty_register_driver(isicom_normal);
1748        if (retval) {
1749                pr_dbg("Couldn't register the dialin driver\n");
1750                goto err_puttty;
1751        }
1752
1753        retval = pci_register_driver(&isicom_driver);
1754        if (retval < 0) {
1755                printk(KERN_ERR "ISICOM: Unable to register pci driver.\n");
1756                goto err_unrtty;
1757        }
1758
1759        mod_timer(&tx, jiffies + 1);
1760
1761        return 0;
1762err_unrtty:
1763        tty_unregister_driver(isicom_normal);
1764err_puttty:
1765        put_tty_driver(isicom_normal);
1766error:
1767        return retval;
1768}
1769
1770static void __exit isicom_exit(void)
1771{
1772        del_timer_sync(&tx);
1773
1774        pci_unregister_driver(&isicom_driver);
1775        tty_unregister_driver(isicom_normal);
1776        put_tty_driver(isicom_normal);
1777}
1778
1779module_init(isicom_init);
1780module_exit(isicom_exit);
1781
1782MODULE_AUTHOR("MultiTech");
1783MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
1784MODULE_LICENSE("GPL");
1785