linux/drivers/char/isicom.c History
<<
>>
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 int isicom_open(struct tty_struct *tty, struct file *filp)
 850{
 851        struct isi_port *port;
 852        struct isi_board *card;
 853        unsigned int board;
 854        int error, line;
 855
 856        line = tty->index;
 857        if (line < 0 || line > PORT_COUNT-1)
 858                return -ENODEV;
 859        board = BOARD(line);
 860        card = &isi_card[board];
 861
 862        if (!(card->status & FIRMWARE_LOADED))
 863                return -ENODEV;
 864
 865        /*  open on a port greater than the port count for the card !!! */
 866        if (line > ((board * 16) + card->port_count - 1))
 867                return -ENODEV;
 868
 869        port = &isi_ports[line];
 870        if (isicom_paranoia_check(port, tty->name, "isicom_open"))
 871                return -ENODEV;
 872
 873        isicom_setup_board(card);
 874
 875        /* FIXME: locking on port.count etc */
 876        port->port.count++;
 877        tty->driver_data = port;
 878        tty_port_tty_set(&port->port, tty);
 879        error = isicom_setup_port(tty);
 880        if (error == 0)
 881                error = tty_port_block_til_ready(&port->port, tty, filp);
 882        return error;
 883}
 884
 885/* close et all */
 886
 887static inline void isicom_shutdown_board(struct isi_board *bp)
 888{
 889        if (bp->status & BOARD_ACTIVE)
 890                bp->status &= ~BOARD_ACTIVE;
 891}
 892
 893/* card->lock HAS to be held */
 894static void isicom_shutdown_port(struct isi_port *port)
 895{
 896        struct isi_board *card = port->card;
 897        struct tty_struct *tty;
 898
 899        tty = tty_port_tty_get(&port->port);
 900
 901        if (!(port->port.flags & ASYNC_INITIALIZED)) {
 902                tty_kref_put(tty);
 903                return;
 904        }
 905
 906        tty_port_free_xmit_buf(&port->port);
 907        port->port.flags &= ~ASYNC_INITIALIZED;
 908        /* 3rd October 2000 : Vinayak P Risbud */
 909        tty_port_tty_set(&port->port, NULL);
 910
 911        /*Fix done by Anil .S on 30-04-2001
 912        remote login through isi port has dtr toggle problem
 913        due to which the carrier drops before the password prompt
 914        appears on the remote end. Now we drop the dtr only if the
 915        HUPCL(Hangup on close) flag is set for the tty*/
 916
 917        if (C_HUPCL(tty))
 918                /* drop dtr on this port */
 919                drop_dtr(port);
 920
 921        /* any other port uninits  */
 922        if (tty)
 923                set_bit(TTY_IO_ERROR, &tty->flags);
 924
 925        if (--card->count < 0) {
 926                pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n",
 927                        card->base, card->count);
 928                card->count = 0;
 929        }
 930
 931        /* last port was closed, shutdown that boad too */
 932        if (C_HUPCL(tty)) {
 933                if (!card->count)
 934                        isicom_shutdown_board(card);
 935        }
 936        tty_kref_put(tty);
 937}
 938
 939static void isicom_flush_buffer(struct tty_struct *tty)
 940{
 941        struct isi_port *port = tty->driver_data;
 942        struct isi_board *card = port->card;
 943        unsigned long flags;
 944
 945        if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
 946                return;
 947
 948        spin_lock_irqsave(&card->card_lock, flags);
 949        port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
 950        spin_unlock_irqrestore(&card->card_lock, flags);
 951
 952        tty_wakeup(tty);
 953}
 954
 955static void isicom_close(struct tty_struct *tty, struct file *filp)
 956{
 957        struct isi_port *ip = tty->driver_data;
 958        struct tty_port *port = &ip->port;
 959        struct isi_board *card;
 960        unsigned long flags;
 961
 962        BUG_ON(!ip);
 963
 964        card = ip->card;
 965        if (isicom_paranoia_check(ip, tty->name, "isicom_close"))
 966                return;
 967
 968        /* indicate to the card that no more data can be received
 969           on this port */
 970        spin_lock_irqsave(&card->card_lock, flags);
 971        if (port->flags & ASYNC_INITIALIZED) {
 972                card->port_status &= ~(1 << ip->channel);
 973                outw(card->port_status, card->base + 0x02);
 974        }
 975        isicom_shutdown_port(ip);
 976        spin_unlock_irqrestore(&card->card_lock, flags);
 977
 978        isicom_flush_buffer(tty);
 979        
 980        tty_port_close_end(port, tty);
 981}
 982
 983/* write et all */
 984static int isicom_write(struct tty_struct *tty, const unsigned char *buf,
 985        int count)
 986{
 987        struct isi_port *port = tty->driver_data;
 988        struct isi_board *card = port->card;
 989        unsigned long flags;
 990        int cnt, total = 0;
 991
 992        if (isicom_paranoia_check(port, tty->name, "isicom_write"))
 993                return 0;
 994
 995        spin_lock_irqsave(&card->card_lock, flags);
 996
 997        while (1) {
 998                cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt
 999                                - 1, SERIAL_XMIT_SIZE - port->xmit_head));
1000                if (cnt <= 0)
1001                        break;
1002
1003                memcpy(port->port.xmit_buf + port->xmit_head, buf, cnt);
1004                port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE
1005                        - 1);
1006                port->xmit_cnt += cnt;
1007                buf += cnt;
1008                count -= cnt;
1009                total += cnt;
1010        }
1011        if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
1012                port->status |= ISI_TXOK;
1013        spin_unlock_irqrestore(&card->card_lock, flags);
1014        return total;
1015}
1016
1017/* put_char et all */
1018static int isicom_put_char(struct tty_struct *tty, unsigned char ch)
1019{
1020        struct isi_port *port = tty->driver_data;
1021        struct isi_board *card = port->card;
1022        unsigned long flags;
1023
1024        if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
1025                return 0;
1026
1027        spin_lock_irqsave(&card->card_lock, flags);
1028        if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
1029                spin_unlock_irqrestore(&card->card_lock, flags);
1030                return 0;
1031        }
1032
1033        port->port.xmit_buf[port->xmit_head++] = ch;
1034        port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
1035        port->xmit_cnt++;
1036        spin_unlock_irqrestore(&card->card_lock, flags);
1037        return 1;
1038}
1039
1040/* flush_chars et all */
1041static void isicom_flush_chars(struct tty_struct *tty)
1042{
1043        struct isi_port *port = tty->driver_data;
1044
1045        if (isicom_paranoia_check(port, tty->name, "isicom_flush_chars"))
1046                return;
1047
1048        if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
1049                        !port->port.xmit_buf)
1050                return;
1051
1052        /* this tells the transmitter to consider this port for
1053           data output to the card ... that's the best we can do. */
1054        port->status |= ISI_TXOK;
1055}
1056
1057/* write_room et all */
1058static int isicom_write_room(struct tty_struct *tty)
1059{
1060        struct isi_port *port = tty->driver_data;
1061        int free;
1062
1063        if (isicom_paranoia_check(port, tty->name, "isicom_write_room"))
1064                return 0;
1065
1066        free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
1067        if (free < 0)
1068                free = 0;
1069        return free;
1070}
1071
1072/* chars_in_buffer et all */
1073static int isicom_chars_in_buffer(struct tty_struct *tty)
1074{
1075        struct isi_port *port = tty->driver_data;
1076        if (isicom_paranoia_check(port, tty->name, "isicom_chars_in_buffer"))
1077                return 0;
1078        return port->xmit_cnt;
1079}
1080
1081/* ioctl et all */
1082static int isicom_send_break(struct tty_struct *tty, int length)
1083{
1084        struct isi_port *port = tty->driver_data;
1085        struct isi_board *card = port->card;
1086        unsigned long base = card->base;
1087
1088        if (length == -1)
1089                return -EOPNOTSUPP;
1090
1091        if (!lock_card(card))
1092                return -EINVAL;
1093
1094        outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
1095        outw((length & 0xff) << 8 | 0x00, base);
1096        outw((length & 0xff00), base);
1097        InterruptTheCard(base);
1098
1099        unlock_card(card);
1100        return 0;
1101}
1102
1103static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
1104{
1105        struct isi_port *port = tty->driver_data;
1106        /* just send the port status */
1107        u16 status = port->status;
1108
1109        if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
1110                return -ENODEV;
1111
1112        return  ((status & ISI_RTS) ? TIOCM_RTS : 0) |
1113                ((status & ISI_DTR) ? TIOCM_DTR : 0) |
1114                ((status & ISI_DCD) ? TIOCM_CAR : 0) |
1115                ((status & ISI_DSR) ? TIOCM_DSR : 0) |
1116                ((status & ISI_CTS) ? TIOCM_CTS : 0) |
1117                ((status & ISI_RI ) ? TIOCM_RI  : 0);
1118}
1119
1120static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
1121        unsigned int set, unsigned int clear)
1122{
1123        struct isi_port *port = tty->driver_data;
1124        unsigned long flags;
1125
1126        if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
1127                return -ENODEV;
1128
1129        spin_lock_irqsave(&port->card->card_lock, flags);
1130        if (set & TIOCM_RTS)
1131                raise_rts(port);
1132        if (set & TIOCM_DTR)
1133                raise_dtr(port);
1134
1135        if (clear & TIOCM_RTS)
1136                drop_rts(port);
1137        if (clear & TIOCM_DTR)
1138                drop_dtr(port);
1139        spin_unlock_irqrestore(&port->card->card_lock, flags);
1140
1141        return 0;
1142}
1143
1144static int isicom_set_serial_info(struct tty_struct *tty,
1145                                        struct serial_struct __user *info)
1146{
1147        struct isi_port *port = tty->driver_data;
1148        struct serial_struct newinfo;
1149        int reconfig_port;
1150
1151        if (copy_from_user(&newinfo, info, sizeof(newinfo)))
1152                return -EFAULT;
1153
1154        lock_kernel();
1155
1156        reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) !=
1157                (newinfo.flags & ASYNC_SPD_MASK));
1158
1159        if (!capable(CAP_SYS_ADMIN)) {
1160                if ((newinfo.close_delay != port->port.close_delay) ||
1161                                (newinfo.closing_wait != port->port.closing_wait) ||
1162                                ((newinfo.flags & ~ASYNC_USR_MASK) !=
1163                                (port->port.flags & ~ASYNC_USR_MASK))) {
1164                        unlock_kernel();
1165                        return -EPERM;
1166                }
1167                port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
1168                                (newinfo.flags & ASYNC_USR_MASK));
1169        } else {
1170                port->port.close_delay = newinfo.close_delay;
1171                port->port.closing_wait = newinfo.closing_wait;
1172                port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
1173                                (newinfo.flags & ASYNC_FLAGS));
1174        }
1175        if (reconfig_port) {
1176                unsigned long flags;
1177                spin_lock_irqsave(&port->card->card_lock, flags);
1178                isicom_config_port(tty);
1179                spin_unlock_irqrestore(&port->card->card_lock, flags);
1180        }
1181        unlock_kernel();
1182        return 0;
1183}
1184
1185static int isicom_get_serial_info(struct isi_port *port,
1186        struct serial_struct __user *info)
1187{
1188        struct serial_struct out_info;
1189
1190        lock_kernel();
1191        memset(&out_info, 0, sizeof(out_info));
1192/*      out_info.type = ? */
1193        out_info.line = port - isi_ports;
1194        out_info.port = port->card->base;
1195        out_info.irq = port->card->irq;
1196        out_info.flags = port->port.flags;
1197/*      out_info.baud_base = ? */
1198        out_info.close_delay = port->port.close_delay;
1199        out_info.closing_wait = port->port.closing_wait;
1200        unlock_kernel();
1201        if (copy_to_user(info, &out_info, sizeof(out_info)))
1202                return -EFAULT;
1203        return 0;
1204}
1205
1206static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
1207        unsigned int cmd, unsigned long arg)
1208{
1209        struct isi_port *port = tty->driver_data;
1210        void __user *argp = (void __user *)arg;
1211
1212        if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
1213                return -ENODEV;
1214
1215        switch (cmd) {
1216        case TIOCGSERIAL:
1217                return isicom_get_serial_info(port, argp);
1218
1219        case TIOCSSERIAL:
1220                return isicom_set_serial_info(tty, argp);
1221
1222        default:
1223                return -ENOIOCTLCMD;
1224        }
1225        return 0;
1226}
1227
1228/* set_termios et all */
1229static void isicom_set_termios(struct tty_struct *tty,
1230        struct ktermios *old_termios)
1231{
1232        struct isi_port *port = tty->driver_data;
1233        unsigned long flags;
1234
1235        if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
1236                return;
1237
1238        if (tty->termios->c_cflag == old_termios->c_cflag &&
1239                        tty->termios->c_iflag == old_termios->c_iflag)
1240                return;
1241
1242        spin_lock_irqsave(&port->card->card_lock, flags);
1243        isicom_config_port(tty);
1244        spin_unlock_irqrestore(&port->card->card_lock, flags);
1245
1246        if ((old_termios->c_cflag & CRTSCTS) &&
1247                        !(tty->termios->c_cflag & CRTSCTS)) {
1248                tty->hw_stopped = 0;
1249                isicom_start(tty);
1250        }
1251}
1252
1253/* throttle et all */
1254static void isicom_throttle(struct tty_struct *tty)
1255{
1256        struct isi_port *port = tty->driver_data;
1257        struct isi_board *card = port->card;
1258
1259        if (isicom_paranoia_check(port, tty->name, "isicom_throttle"))
1260                return;
1261
1262        /* tell the card that this port cannot handle any more data for now */
1263        card->port_status &= ~(1 << port->channel);
1264        outw(card->port_status, card->base + 0x02);
1265}
1266
1267/* unthrottle et all */
1268static void isicom_unthrottle(struct tty_struct *tty)
1269{
1270        struct isi_port *port = tty->driver_data;
1271        struct isi_board *card = port->card;
1272
1273        if (isicom_paranoia_check(port, tty->name, "isicom_unthrottle"))
1274                return;
1275
1276        /* tell the card that this port is ready to accept more data */
1277        card->port_status |= (1 << port->channel);
1278        outw(card->port_status, card->base + 0x02);
1279}
1280
1281/* stop et all */
1282static void isicom_stop(struct tty_struct *tty)
1283{
1284        struct isi_port *port = tty->driver_data;
1285
1286        if (isicom_paranoia_check(port, tty->name, "isicom_stop"))
1287                return;
1288
1289        /* this tells the transmitter not to consider this port for
1290           data output to the card. */
1291        port->status &= ~ISI_TXOK;
1292}
1293
1294/* start et all */
1295static void isicom_start(struct tty_struct *tty)
1296{
1297        struct isi_port *port = tty->driver_data;
1298
1299        if (isicom_paranoia_check(port, tty->name, "isicom_start"))
1300                return;
1301
1302        /* this tells the transmitter to consider this port for
1303           data output to the card. */
1304        port->status |= ISI_TXOK;
1305}
1306
1307static void isicom_hangup(struct tty_struct *tty)
1308{
1309        struct isi_port *port = tty->driver_data;
1310        unsigned long flags;
1311
1312        if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
1313                return;
1314
1315        spin_lock_irqsave(&port->card->card_lock, flags);
1316        isicom_shutdown_port(port);
1317        spin_unlock_irqrestore(&port->card->card_lock, flags);
1318
1319        tty_port_hangup(&port->port);
1320}
1321
1322
1323/*
1324 * Driver init and deinit functions
1325 */
1326
1327static const struct tty_operations isicom_ops = {
1328        .open                   = isicom_open,
1329        .close                  = isicom_close,
1330        .write                  = isicom_write,
1331        .put_char               = isicom_put_char,
1332        .flush_chars            = isicom_flush_chars,
1333        .write_room             = isicom_write_room,
1334        .chars_in_buffer        = isicom_chars_in_buffer,
1335        .ioctl                  = isicom_ioctl,
1336        .set_termios            = isicom_set_termios,
1337        .throttle               = isicom_throttle,
1338        .unthrottle             = isicom_unthrottle,
1339        .stop                   = isicom_stop,
1340        .start                  = isicom_start,
1341        .hangup                 = isicom_hangup,
1342        .flush_buffer           = isicom_flush_buffer,
1343        .tiocmget               = isicom_tiocmget,
1344        .tiocmset               = isicom_tiocmset,
1345        .break_ctl              = isicom_send_break,
1346};
1347
1348static const struct tty_port_operations isicom_port_ops = {
1349        .carrier_raised         = isicom_carrier_raised,
1350        .dtr_rts                = isicom_dtr_rts,
1351};
1352
1353static int __devinit reset_card(struct pci_dev *pdev,
1354        const unsigned int card, unsigned int *signature)
1355{
1356        struct isi_board *board = pci_get_drvdata(pdev);
1357        unsigned long base = board->base;
1358        unsigned int sig, portcount = 0;
1359        int retval = 0;
1360
1361        dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1,
1362                base);
1363
1364        inw(base + 0x8);
1365
1366        msleep(10);
1367
1368        outw(0, base + 0x8); /* Reset */
1369
1370        msleep(1000);
1371
1372        sig = inw(base + 0x4) & 0xff;
1373
1374        if (sig != 0xa5 && sig != 0xbb && sig != 0xcc && sig != 0xdd &&
1375                        sig != 0xee) {
1376                dev_warn(&pdev->dev, "ISILoad:Card%u reset failure (Possible "
1377                        "bad I/O Port Address 0x%lx).\n", card + 1, base);
1378                dev_dbg(&pdev->dev, "Sig=0x%x\n", sig);
1379                retval = -EIO;
1380                goto end;
1381        }
1382
1383        msleep(10);
1384
1385        portcount = inw(base + 0x2);
1386        if (!(inw(base + 0xe) & 0x1) || (portcount != 0 && portcount != 4 &&
1387                                portcount != 8 && portcount != 16)) {
1388                dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.\n",
1389                        card + 1);
1390                retval = -EIO;
1391                goto end;
1392        }
1393
1394        switch (sig) {
1395        case 0xa5:
1396        case 0xbb:
1397        case 0xdd:
1398                board->port_count = (portcount == 4) ? 4 : 8;
1399                board->shift_count = 12;
1400                break;
1401        case 0xcc:
1402        case 0xee:
1403                board->port_count = 16;
1404                board->shift_count = 11;
1405                break;
1406        }
1407        dev_info(&pdev->dev, "-Done\n");
1408        *signature = sig;
1409
1410end:
1411        return retval;
1412}
1413
1414static int __devinit load_firmware(struct pci_dev *pdev,
1415        const unsigned int index, const unsigned int signature)
1416{
1417        struct isi_board *board = pci_get_drvdata(pdev);
1418        const struct firmware *fw;
1419        unsigned long base = board->base;
1420        unsigned int a;
1421        u16 word_count, status;
1422        int retval = -EIO;
1423        char *name;
1424        u8 *data;
1425
1426        struct stframe {
1427                u16     addr;
1428                u16     count;
1429                u8      data[0];
1430        } *frame;
1431
1432        switch (signature) {
1433        case 0xa5:
1434                name = "isi608.bin";
1435                break;
1436        case 0xbb:
1437                name = "isi608em.bin";
1438                break;
1439        case 0xcc:
1440                name = "isi616em.bin";
1441                break;
1442        case 0xdd:
1443                name = "isi4608.bin";
1444                break;
1445        case 0xee:
1446                name = "isi4616.bin";
1447                break;
1448        default:
1449                dev_err(&pdev->dev, "Unknown signature.\n");
1450                goto end;
1451        }
1452
1453        retval = request_firmware(&fw, name, &pdev->dev);
1454        if (retval)
1455                goto end;
1456
1457        retval = -EIO;
1458
1459        for (frame = (struct stframe *)fw->data;
1460                        frame < (struct stframe *)(fw->data + fw->size);
1461                        frame = (struct stframe *)((u8 *)(frame + 1) +
1462                                frame->count)) {
1463                if (WaitTillCardIsFree(base))
1464                        goto errrelfw;
1465
1466                outw(0xf0, base);       /* start upload sequence */
1467                outw(0x00, base);
1468                outw(frame->addr, base); /* lsb of address */
1469
1470                word_count = frame->count / 2 + frame->count % 2;
1471                outw(word_count, base);
1472                InterruptTheCard(base);
1473
1474                udelay(100); /* 0x2f */
1475
1476                if (WaitTillCardIsFree(base))
1477                        goto errrelfw;
1478
1479                status = inw(base + 0x4);
1480                if (status != 0) {
1481                        dev_warn(&pdev->dev, "Card%d rejected load header:\n"
1482                                 "Address:0x%x\n"
1483                                 "Count:0x%x\n"
1484                                 "Status:0x%x\n",
1485                                 index + 1, frame->addr, frame->count, status);
1486                        goto errrelfw;
1487                }
1488                outsw(base, frame->data, word_count);
1489
1490                InterruptTheCard(base);
1491
1492                udelay(50); /* 0x0f */
1493
1494                if (WaitTillCardIsFree(base))
1495                        goto errrelfw;
1496
1497                status = inw(base + 0x4);
1498                if (status != 0) {
1499                        dev_err(&pdev->dev, "Card%d got out of sync.Card "
1500                                "Status:0x%x\n", index + 1, status);
1501                        goto errrelfw;
1502                }
1503        }
1504
1505/* XXX: should we test it by reading it back and comparing with original like
1506 * in load firmware package? */
1507        for (frame = (struct stframe *)fw->data;
1508                        frame < (struct stframe *)(fw->data + fw->size);
1509                        frame = (struct stframe *)((u8 *)(frame + 1) +
1510                                frame->count)) {
1511                if (WaitTillCardIsFree(base))
1512                        goto errrelfw;
1513
1514                outw(0xf1, base); /* start download sequence */
1515                outw(0x00, base);
1516                outw(frame->addr, base); /* lsb of address */
1517
1518                word_count = (frame->count >> 1) + frame->count % 2;
1519                outw(word_count + 1, base);
1520                InterruptTheCard(base);
1521
1522                udelay(50); /* 0xf */
1523
1524                if (WaitTillCardIsFree(base))
1525                        goto errrelfw;
1526
1527                status = inw(base + 0x4);
1528                if (status != 0) {
1529                        dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
1530                                 "Address:0x%x\n"
1531                                 "Count:0x%x\n"
1532                                 "Status: 0x%x\n",
1533                                 index + 1, frame->addr, frame->count, status);
1534                        goto errrelfw;
1535                }
1536
1537                data = kmalloc(word_count * 2, GFP_KERNEL);
1538                if (data == NULL) {
1539                        dev_err(&pdev->dev, "Card%d, firmware upload "
1540                                "failed, not enough memory\n", index + 1);
1541                        goto errrelfw;
1542                }
1543                inw(base);
1544                insw(base, data, word_count);
1545                InterruptTheCard(base);
1546
1547                for (a = 0; a < frame->count; a++)
1548                        if (data[a] != frame->data[a]) {
1549                                kfree(data);
1550                                dev_err(&pdev->dev, "Card%d, firmware upload "
1551                                        "failed\n", index + 1);
1552                                goto errrelfw;
1553                        }
1554                kfree(data);
1555
1556                udelay(50); /* 0xf */
1557
1558                if (WaitTillCardIsFree(base))
1559                        goto errrelfw;
1560
1561                status = inw(base + 0x4);
1562                if (status != 0) {
1563                        dev_err(&pdev->dev, "Card%d verify got out of sync. "
1564                                "Card Status:0x%x\n", index + 1, status);
1565                        goto errrelfw;
1566                }
1567        }
1568
1569        /* xfer ctrl */
1570        if (WaitTillCardIsFree(base))
1571                goto errrelfw;
1572
1573        outw(0xf2, base);
1574        outw(0x800, base);
1575        outw(0x0, base);
1576        outw(0x0, base);
1577        InterruptTheCard(base);
1578        outw(0x0, base + 0x4); /* for ISI4608 cards */
1579
1580        board->status |= FIRMWARE_LOADED;
1581        retval = 0;
1582
1583errrelfw:
1584        release_firmware(fw);
1585end:
1586        return retval;
1587}
1588
1589/*
1590 *      Insmod can set static symbols so keep these static
1591 */
1592static unsigned int card_count;
1593
1594static int __devinit isicom_probe(struct pci_dev *pdev,
1595        const struct pci_device_id *ent)
1596{
1597        unsigned int uninitialized_var(signature), index;
1598        int retval = -EPERM;
1599        struct isi_board *board = NULL;
1600
1601        if (card_count >= BOARD_COUNT)
1602                goto err;
1603
1604        retval = pci_enable_device(pdev);
1605        if (retval) {
1606                dev_err(&pdev->dev, "failed to enable\n");
1607                goto err;
1608        }
1609
1610        dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
1611
1612        /* allot the first empty slot in the array */
1613        for (index = 0; index < BOARD_COUNT; index++)
1614                if (isi_card[index].base == 0) {
1615                        board = &isi_card[index];
1616                        break;
1617                }
1618
1619        board->index = index;
1620        board->base = pci_resource_start(pdev, 3);
1621        board->irq = pdev->irq;
1622        card_count++;
1623
1624        pci_set_drvdata(pdev, board);
1625
1626        retval = pci_request_region(pdev, 3, ISICOM_NAME);
1627        if (retval) {
1628                dev_err(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d "
1629                        "will be disabled.\n", board->base, board->base + 15,
1630                        index + 1);
1631                retval = -EBUSY;
1632                goto errdec;
1633        }
1634
1635        retval = request_irq(board->irq, isicom_interrupt,
1636                        IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board);
1637        if (retval < 0) {
1638                dev_err(&pdev->dev, "Could not install handler at Irq %d. "
1639                        "Card%d will be disabled.\n", board->irq, index + 1);
1640                goto errunrr;
1641        }
1642
1643        retval = reset_card(pdev, index, &signature);
1644        if (retval < 0)
1645                goto errunri;
1646
1647        retval = load_firmware(pdev, index, signature);
1648        if (retval < 0)
1649                goto errunri;
1650
1651        for (index = 0; index < board->port_count; index++)
1652                tty_register_device(isicom_normal, board->index * 16 + index,
1653                                &pdev->dev);
1654
1655        return 0;
1656
1657errunri:
1658        free_irq(board->irq, board);
1659errunrr:
1660        pci_release_region(pdev, 3);
1661errdec:
1662        board->base = 0;
1663        card_count--;
1664        pci_disable_device(pdev);
1665err:
1666        return retval;
1667}
1668
1669static void __devexit isicom_remove(struct pci_dev *pdev)
1670{
1671        struct isi_board *board = pci_get_drvdata(pdev);
1672        unsigned int i;
1673
1674        for (i = 0; i < board->port_count; i++)
1675                tty_unregister_device(isicom_normal, board->index * 16 + i);
1676
1677        free_irq(board->irq, board);
1678        pci_release_region(pdev, 3);
1679        board->base = 0;
1680        card_count--;
1681        pci_disable_device(pdev);
1682}
1683
1684static int __init isicom_init(void)
1685{
1686        int retval, idx, channel;
1687        struct isi_port *port;
1688
1689        for (idx = 0; idx < BOARD_COUNT; idx++) {
1690                port = &isi_ports[idx * 16];
1691                isi_card[idx].ports = port;
1692                spin_lock_init(&isi_card[idx].card_lock);
1693                for (channel = 0; channel < 16; channel++, port++) {
1694                        tty_port_init(&port->port);
1695                        port->port.ops = &isicom_port_ops;
1696                        port->magic = ISICOM_MAGIC;
1697                        port->card = &isi_card[idx];
1698                        port->channel = channel;
1699                        port->port.close_delay = 50 * HZ/100;
1700                        port->port.closing_wait = 3000 * HZ/100;
1701                        port->status = 0;
1702                        /*  . . .  */
1703                }
1704                isi_card[idx].base = 0;
1705                isi_card[idx].irq = 0;
1706        }
1707
1708        /* tty driver structure initialization */
1709        isicom_normal = alloc_tty_driver(PORT_COUNT);
1710        if (!isicom_normal) {
1711                retval = -ENOMEM;
1712                goto error;
1713        }
1714
1715        isicom_normal->owner                    = THIS_MODULE;
1716        isicom_normal->name                     = "ttyM";
1717        isicom_normal->major                    = ISICOM_NMAJOR;
1718        isicom_normal->minor_start              = 0;
1719        isicom_normal->type                     = TTY_DRIVER_TYPE_SERIAL;
1720        isicom_normal->subtype                  = SERIAL_TYPE_NORMAL;
1721        isicom_normal->init_termios             = tty_std_termios;
1722        isicom_normal->init_termios.c_cflag     = B9600 | CS8 | CREAD | HUPCL |
1723                CLOCAL;
1724        isicom_normal->flags                    = TTY_DRIVER_REAL_RAW |
1725                TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK;
1726        tty_set_operations(isicom_normal, &isicom_ops);
1727
1728        retval = tty_register_driver(isicom_normal);
1729        if (retval) {
1730                pr_dbg("Couldn't register the dialin driver\n");
1731                goto err_puttty;
1732        }
1733
1734        retval = pci_register_driver(&isicom_driver);
1735        if (retval < 0) {
1736                printk(KERN_ERR "ISICOM: Unable to register pci driver.\n");
1737                goto err_unrtty;
1738        }
1739
1740        mod_timer(&tx, jiffies + 1);
1741
1742        return 0;
1743err_unrtty:
1744        tty_unregister_driver(isicom_normal);
1745err_puttty:
1746        put_tty_driver(isicom_normal);
1747error:
1748        return retval;
1749}
1750
1751static void __exit isicom_exit(void)
1752{
1753        del_timer_sync(&tx);
1754
1755        pci_unregister_driver(&isicom_driver);
1756        tty_unregister_driver(isicom_normal);
1757        put_tty_driver(isicom_normal);
1758}
1759
1760module_init(isicom_init);
1761module_exit(isicom_exit);
1762
1763MODULE_AUTHOR("MultiTech");
1764MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
1765MODULE_LICENSE("GPL");
1766
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.