linux/drivers/staging/i4l/icn/icn.c
<<
>>
Prefs
   1/* $Id: icn.c,v 1.65.6.8 2001/09/23 22:24:55 kai Exp $
   2 *
   3 * ISDN low-level module for the ICN active ISDN-Card.
   4 *
   5 * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de)
   6 *
   7 * This software may be used and distributed according to the terms
   8 * of the GNU General Public License, incorporated herein by reference.
   9 *
  10 */
  11
  12#include "icn.h"
  13#include <linux/module.h>
  14#include <linux/init.h>
  15#include <linux/slab.h>
  16#include <linux/sched.h>
  17
  18static int portbase = ICN_BASEADDR;
  19static unsigned long membase = ICN_MEMADDR;
  20static char *icn_id = "\0";
  21static char *icn_id2 = "\0";
  22
  23MODULE_DESCRIPTION("ISDN4Linux: Driver for ICN active ISDN card");
  24MODULE_AUTHOR("Fritz Elfert");
  25MODULE_LICENSE("GPL");
  26module_param(portbase, int, 0);
  27MODULE_PARM_DESC(portbase, "Port address of first card");
  28module_param(membase, ulong, 0);
  29MODULE_PARM_DESC(membase, "Shared memory address of all cards");
  30module_param(icn_id, charp, 0);
  31MODULE_PARM_DESC(icn_id, "ID-String of first card");
  32module_param(icn_id2, charp, 0);
  33MODULE_PARM_DESC(icn_id2, "ID-String of first card, second S0 (4B only)");
  34
  35/*
  36 * Verbose bootcode- and protocol-downloading.
  37 */
  38#undef BOOT_DEBUG
  39
  40/*
  41 * Verbose Shmem-Mapping.
  42 */
  43#undef MAP_DEBUG
  44
  45static char
  46*revision = "$Revision: 1.65.6.8 $";
  47
  48static int icn_addcard(int, char *, char *);
  49
  50/*
  51 * Free send-queue completely.
  52 * Parameter:
  53 *   card   = pointer to card struct
  54 *   channel = channel number
  55 */
  56static void
  57icn_free_queue(icn_card *card, int channel)
  58{
  59        struct sk_buff_head *queue = &card->spqueue[channel];
  60        struct sk_buff *skb;
  61
  62        skb_queue_purge(queue);
  63        card->xlen[channel] = 0;
  64        card->sndcount[channel] = 0;
  65        if ((skb = card->xskb[channel])) {
  66                card->xskb[channel] = NULL;
  67                dev_kfree_skb(skb);
  68        }
  69}
  70
  71/* Put a value into a shift-register, highest bit first.
  72 * Parameters:
  73 *            port     = port for output (bit 0 is significant)
  74 *            val      = value to be output
  75 *            firstbit = Bit-Number of highest bit
  76 *            bitcount = Number of bits to output
  77 */
  78static inline void
  79icn_shiftout(unsigned short port,
  80             unsigned long val,
  81             int firstbit,
  82             int bitcount)
  83{
  84
  85        register u_char s;
  86        register u_char c;
  87
  88        for (s = firstbit, c = bitcount; c > 0; s--, c--)
  89                OUTB_P((u_char) ((val >> s) & 1) ? 0xff : 0, port);
  90}
  91
  92/*
  93 * disable a cards shared memory
  94 */
  95static inline void
  96icn_disable_ram(icn_card *card)
  97{
  98        OUTB_P(0, ICN_MAPRAM);
  99}
 100
 101/*
 102 * enable a cards shared memory
 103 */
 104static inline void
 105icn_enable_ram(icn_card *card)
 106{
 107        OUTB_P(0xff, ICN_MAPRAM);
 108}
 109
 110/*
 111 * Map a cards channel0 (Bank0/Bank8) or channel1 (Bank4/Bank12)
 112 *
 113 * must called with holding the devlock
 114 */
 115static inline void
 116icn_map_channel(icn_card *card, int channel)
 117{
 118#ifdef MAP_DEBUG
 119        printk(KERN_DEBUG "icn_map_channel %d %d\n", dev.channel, channel);
 120#endif
 121        if ((channel == dev.channel) && (card == dev.mcard))
 122                return;
 123        if (dev.mcard)
 124                icn_disable_ram(dev.mcard);
 125        icn_shiftout(ICN_BANK, chan2bank[channel], 3, 4);       /* Select Bank          */
 126        icn_enable_ram(card);
 127        dev.mcard = card;
 128        dev.channel = channel;
 129#ifdef MAP_DEBUG
 130        printk(KERN_DEBUG "icn_map_channel done\n");
 131#endif
 132}
 133
 134/*
 135 * Lock a cards channel.
 136 * Return 0 if requested card/channel is unmapped (failure).
 137 * Return 1 on success.
 138 *
 139 * must called with holding the devlock
 140 */
 141static inline int
 142icn_lock_channel(icn_card *card, int channel)
 143{
 144        register int retval;
 145
 146#ifdef MAP_DEBUG
 147        printk(KERN_DEBUG "icn_lock_channel %d\n", channel);
 148#endif
 149        if ((dev.channel == channel) && (card == dev.mcard)) {
 150                dev.chanlock++;
 151                retval = 1;
 152#ifdef MAP_DEBUG
 153                printk(KERN_DEBUG "icn_lock_channel %d OK\n", channel);
 154#endif
 155        } else {
 156                retval = 0;
 157#ifdef MAP_DEBUG
 158                printk(KERN_DEBUG "icn_lock_channel %d FAILED, dc=%d\n", channel, dev.channel);
 159#endif
 160        }
 161        return retval;
 162}
 163
 164/*
 165 * Release current card/channel lock
 166 *
 167 * must called with holding the devlock
 168 */
 169static inline void
 170__icn_release_channel(void)
 171{
 172#ifdef MAP_DEBUG
 173        printk(KERN_DEBUG "icn_release_channel l=%d\n", dev.chanlock);
 174#endif
 175        if (dev.chanlock > 0)
 176                dev.chanlock--;
 177}
 178
 179/*
 180 * Release current card/channel lock
 181 */
 182static inline void
 183icn_release_channel(void)
 184{
 185        ulong flags;
 186
 187        spin_lock_irqsave(&dev.devlock, flags);
 188        __icn_release_channel();
 189        spin_unlock_irqrestore(&dev.devlock, flags);
 190}
 191
 192/*
 193 * Try to map and lock a cards channel.
 194 * Return 1 on success, 0 on failure.
 195 */
 196static inline int
 197icn_trymaplock_channel(icn_card *card, int channel)
 198{
 199        ulong flags;
 200
 201#ifdef MAP_DEBUG
 202        printk(KERN_DEBUG "trymaplock c=%d dc=%d l=%d\n", channel, dev.channel,
 203               dev.chanlock);
 204#endif
 205        spin_lock_irqsave(&dev.devlock, flags);
 206        if ((!dev.chanlock) ||
 207            ((dev.channel == channel) && (dev.mcard == card))) {
 208                dev.chanlock++;
 209                icn_map_channel(card, channel);
 210                spin_unlock_irqrestore(&dev.devlock, flags);
 211#ifdef MAP_DEBUG
 212                printk(KERN_DEBUG "trymaplock %d OK\n", channel);
 213#endif
 214                return 1;
 215        }
 216        spin_unlock_irqrestore(&dev.devlock, flags);
 217#ifdef MAP_DEBUG
 218        printk(KERN_DEBUG "trymaplock %d FAILED\n", channel);
 219#endif
 220        return 0;
 221}
 222
 223/*
 224 * Release current card/channel lock,
 225 * then map same or other channel without locking.
 226 */
 227static inline void
 228icn_maprelease_channel(icn_card *card, int channel)
 229{
 230        ulong flags;
 231
 232#ifdef MAP_DEBUG
 233        printk(KERN_DEBUG "map_release c=%d l=%d\n", channel, dev.chanlock);
 234#endif
 235        spin_lock_irqsave(&dev.devlock, flags);
 236        if (dev.chanlock > 0)
 237                dev.chanlock--;
 238        if (!dev.chanlock)
 239                icn_map_channel(card, channel);
 240        spin_unlock_irqrestore(&dev.devlock, flags);
 241}
 242
 243/* Get Data from the B-Channel, assemble fragmented packets and put them
 244 * into receive-queue. Wake up any B-Channel-reading processes.
 245 * This routine is called via timer-callback from icn_pollbchan().
 246 */
 247
 248static void
 249icn_pollbchan_receive(int channel, icn_card *card)
 250{
 251        int mch = channel + ((card->secondhalf) ? 2 : 0);
 252        int eflag;
 253        int cnt;
 254        struct sk_buff *skb;
 255
 256        if (icn_trymaplock_channel(card, mch)) {
 257                while (rbavl) {
 258                        cnt = readb(&rbuf_l);
 259                        if ((card->rcvidx[channel] + cnt) > 4000) {
 260                                printk(KERN_WARNING
 261                                       "icn: (%s) bogus packet on ch%d, dropping.\n",
 262                                       CID,
 263                                       channel + 1);
 264                                card->rcvidx[channel] = 0;
 265                                eflag = 0;
 266                        } else {
 267                                memcpy_fromio(&card->rcvbuf[channel][card->rcvidx[channel]],
 268                                              &rbuf_d, cnt);
 269                                card->rcvidx[channel] += cnt;
 270                                eflag = readb(&rbuf_f);
 271                        }
 272                        rbnext;
 273                        icn_maprelease_channel(card, mch & 2);
 274                        if (!eflag) {
 275                                if ((cnt = card->rcvidx[channel])) {
 276                                        if (!(skb = dev_alloc_skb(cnt))) {
 277                                                printk(KERN_WARNING "icn: receive out of memory\n");
 278                                                break;
 279                                        }
 280                                        memcpy(skb_put(skb, cnt), card->rcvbuf[channel], cnt);
 281                                        card->rcvidx[channel] = 0;
 282                                        card->interface.rcvcallb_skb(card->myid, channel, skb);
 283                                }
 284                        }
 285                        if (!icn_trymaplock_channel(card, mch))
 286                                break;
 287                }
 288                icn_maprelease_channel(card, mch & 2);
 289        }
 290}
 291
 292/* Send data-packet to B-Channel, split it up into fragments of
 293 * ICN_FRAGSIZE length. If last fragment is sent out, signal
 294 * success to upper layers via statcallb with ISDN_STAT_BSENT argument.
 295 * This routine is called via timer-callback from icn_pollbchan() or
 296 * directly from icn_sendbuf().
 297 */
 298
 299static void
 300icn_pollbchan_send(int channel, icn_card *card)
 301{
 302        int mch = channel + ((card->secondhalf) ? 2 : 0);
 303        int cnt;
 304        unsigned long flags;
 305        struct sk_buff *skb;
 306        isdn_ctrl cmd;
 307
 308        if (!(card->sndcount[channel] || card->xskb[channel] ||
 309              !skb_queue_empty(&card->spqueue[channel])))
 310                return;
 311        if (icn_trymaplock_channel(card, mch)) {
 312                while (sbfree &&
 313                       (card->sndcount[channel] ||
 314                        !skb_queue_empty(&card->spqueue[channel]) ||
 315                        card->xskb[channel])) {
 316                        spin_lock_irqsave(&card->lock, flags);
 317                        if (card->xmit_lock[channel]) {
 318                                spin_unlock_irqrestore(&card->lock, flags);
 319                                break;
 320                        }
 321                        card->xmit_lock[channel]++;
 322                        spin_unlock_irqrestore(&card->lock, flags);
 323                        skb = card->xskb[channel];
 324                        if (!skb) {
 325                                skb = skb_dequeue(&card->spqueue[channel]);
 326                                if (skb) {
 327                                        /* Pop ACK-flag off skb.
 328                                         * Store length to xlen.
 329                                         */
 330                                        if (*(skb_pull(skb, 1)))
 331                                                card->xlen[channel] = skb->len;
 332                                        else
 333                                                card->xlen[channel] = 0;
 334                                }
 335                        }
 336                        if (!skb)
 337                                break;
 338                        if (skb->len > ICN_FRAGSIZE) {
 339                                writeb(0xff, &sbuf_f);
 340                                cnt = ICN_FRAGSIZE;
 341                        } else {
 342                                writeb(0x0, &sbuf_f);
 343                                cnt = skb->len;
 344                        }
 345                        writeb(cnt, &sbuf_l);
 346                        memcpy_toio(&sbuf_d, skb->data, cnt);
 347                        skb_pull(skb, cnt);
 348                        sbnext; /* switch to next buffer        */
 349                        icn_maprelease_channel(card, mch & 2);
 350                        spin_lock_irqsave(&card->lock, flags);
 351                        card->sndcount[channel] -= cnt;
 352                        if (!skb->len) {
 353                                if (card->xskb[channel])
 354                                        card->xskb[channel] = NULL;
 355                                card->xmit_lock[channel] = 0;
 356                                spin_unlock_irqrestore(&card->lock, flags);
 357                                dev_kfree_skb(skb);
 358                                if (card->xlen[channel]) {
 359                                        cmd.command = ISDN_STAT_BSENT;
 360                                        cmd.driver = card->myid;
 361                                        cmd.arg = channel;
 362                                        cmd.parm.length = card->xlen[channel];
 363                                        card->interface.statcallb(&cmd);
 364                                }
 365                        } else {
 366                                card->xskb[channel] = skb;
 367                                card->xmit_lock[channel] = 0;
 368                                spin_unlock_irqrestore(&card->lock, flags);
 369                        }
 370                        if (!icn_trymaplock_channel(card, mch))
 371                                break;
 372                }
 373                icn_maprelease_channel(card, mch & 2);
 374        }
 375}
 376
 377/* Send/Receive Data to/from the B-Channel.
 378 * This routine is called via timer-callback.
 379 * It schedules itself while any B-Channel is open.
 380 */
 381
 382static void
 383icn_pollbchan(unsigned long data)
 384{
 385        icn_card *card = (icn_card *) data;
 386        unsigned long flags;
 387
 388        if (card->flags & ICN_FLAGS_B1ACTIVE) {
 389                icn_pollbchan_receive(0, card);
 390                icn_pollbchan_send(0, card);
 391        }
 392        if (card->flags & ICN_FLAGS_B2ACTIVE) {
 393                icn_pollbchan_receive(1, card);
 394                icn_pollbchan_send(1, card);
 395        }
 396        if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE)) {
 397                /* schedule b-channel polling again */
 398                spin_lock_irqsave(&card->lock, flags);
 399                mod_timer(&card->rb_timer, jiffies + ICN_TIMER_BCREAD);
 400                card->flags |= ICN_FLAGS_RBTIMER;
 401                spin_unlock_irqrestore(&card->lock, flags);
 402        } else
 403                card->flags &= ~ICN_FLAGS_RBTIMER;
 404}
 405
 406typedef struct icn_stat {
 407        char *statstr;
 408        int command;
 409        int action;
 410} icn_stat;
 411/* *INDENT-OFF* */
 412static icn_stat icn_stat_table[] =
 413{
 414        {"BCON_",          ISDN_STAT_BCONN, 1}, /* B-Channel connected        */
 415        {"BDIS_",          ISDN_STAT_BHUP,  2}, /* B-Channel disconnected     */
 416        /*
 417        ** add d-channel connect and disconnect support to link-level
 418        */
 419        {"DCON_",          ISDN_STAT_DCONN, 10},        /* D-Channel connected        */
 420        {"DDIS_",          ISDN_STAT_DHUP,  11},        /* D-Channel disconnected     */
 421        {"DCAL_I",         ISDN_STAT_ICALL, 3}, /* Incoming call dialup-line  */
 422        {"DSCA_I",         ISDN_STAT_ICALL, 3}, /* Incoming call 1TR6-SPV     */
 423        {"FCALL",          ISDN_STAT_ICALL, 4}, /* Leased line connection up  */
 424        {"CIF",            ISDN_STAT_CINF,  5}, /* Charge-info, 1TR6-type     */
 425        {"AOC",            ISDN_STAT_CINF,  6}, /* Charge-info, DSS1-type     */
 426        {"CAU",            ISDN_STAT_CAUSE, 7}, /* Cause code                 */
 427        {"TEI OK",         ISDN_STAT_RUN,   0}, /* Card connected to wallplug */
 428        {"E_L1: ACT FAIL", ISDN_STAT_BHUP,  8}, /* Layer-1 activation failed  */
 429        {"E_L2: DATA LIN", ISDN_STAT_BHUP,  8}, /* Layer-2 data link lost     */
 430        {"E_L1: ACTIVATION FAILED",
 431         ISDN_STAT_BHUP,  8},   /* Layer-1 activation failed  */
 432        {NULL, 0, -1}
 433};
 434/* *INDENT-ON* */
 435
 436
 437/*
 438 * Check Statusqueue-Pointer from isdn-cards.
 439 * If there are new status-replies from the interface, check
 440 * them against B-Channel-connects/disconnects and set flags accordingly.
 441 * Wake-Up any processes, who are reading the status-device.
 442 * If there are B-Channels open, initiate a timer-callback to
 443 * icn_pollbchan().
 444 * This routine is called periodically via timer.
 445 */
 446
 447static void
 448icn_parse_status(u_char *status, int channel, icn_card *card)
 449{
 450        icn_stat *s = icn_stat_table;
 451        int action = -1;
 452        unsigned long flags;
 453        isdn_ctrl cmd;
 454
 455        while (s->statstr) {
 456                if (!strncmp(status, s->statstr, strlen(s->statstr))) {
 457                        cmd.command = s->command;
 458                        action = s->action;
 459                        break;
 460                }
 461                s++;
 462        }
 463        if (action == -1)
 464                return;
 465        cmd.driver = card->myid;
 466        cmd.arg = channel;
 467        switch (action) {
 468        case 11:
 469                spin_lock_irqsave(&card->lock, flags);
 470                icn_free_queue(card, channel);
 471                card->rcvidx[channel] = 0;
 472
 473                if (card->flags &
 474                    ((channel) ? ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE)) {
 475
 476                        isdn_ctrl ncmd;
 477
 478                        card->flags &= ~((channel) ?
 479                                         ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE);
 480
 481                        memset(&ncmd, 0, sizeof(ncmd));
 482
 483                        ncmd.driver = card->myid;
 484                        ncmd.arg = channel;
 485                        ncmd.command = ISDN_STAT_BHUP;
 486                        spin_unlock_irqrestore(&card->lock, flags);
 487                        card->interface.statcallb(&cmd);
 488                } else
 489                        spin_unlock_irqrestore(&card->lock, flags);
 490                break;
 491        case 1:
 492                spin_lock_irqsave(&card->lock, flags);
 493                icn_free_queue(card, channel);
 494                card->flags |= (channel) ?
 495                        ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE;
 496                spin_unlock_irqrestore(&card->lock, flags);
 497                break;
 498        case 2:
 499                spin_lock_irqsave(&card->lock, flags);
 500                card->flags &= ~((channel) ?
 501                                 ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE);
 502                icn_free_queue(card, channel);
 503                card->rcvidx[channel] = 0;
 504                spin_unlock_irqrestore(&card->lock, flags);
 505                break;
 506        case 3:
 507        {
 508                char *t = status + 6;
 509                char *s = strchr(t, ',');
 510
 511                *s++ = '\0';
 512                strlcpy(cmd.parm.setup.phone, t,
 513                        sizeof(cmd.parm.setup.phone));
 514                s = strchr(t = s, ',');
 515                *s++ = '\0';
 516                if (!strlen(t))
 517                        cmd.parm.setup.si1 = 0;
 518                else
 519                        cmd.parm.setup.si1 =
 520                                simple_strtoul(t, NULL, 10);
 521                s = strchr(t = s, ',');
 522                *s++ = '\0';
 523                if (!strlen(t))
 524                        cmd.parm.setup.si2 = 0;
 525                else
 526                        cmd.parm.setup.si2 =
 527                                simple_strtoul(t, NULL, 10);
 528                strlcpy(cmd.parm.setup.eazmsn, s,
 529                        sizeof(cmd.parm.setup.eazmsn));
 530        }
 531        cmd.parm.setup.plan = 0;
 532        cmd.parm.setup.screen = 0;
 533        break;
 534        case 4:
 535                sprintf(cmd.parm.setup.phone, "LEASED%d", card->myid);
 536                sprintf(cmd.parm.setup.eazmsn, "%d", channel + 1);
 537                cmd.parm.setup.si1 = 7;
 538                cmd.parm.setup.si2 = 0;
 539                cmd.parm.setup.plan = 0;
 540                cmd.parm.setup.screen = 0;
 541                break;
 542        case 5:
 543                strlcpy(cmd.parm.num, status + 3, sizeof(cmd.parm.num));
 544                break;
 545        case 6:
 546                snprintf(cmd.parm.num, sizeof(cmd.parm.num), "%d",
 547                         (int) simple_strtoul(status + 7, NULL, 16));
 548                break;
 549        case 7:
 550                status += 3;
 551                if (strlen(status) == 4)
 552                        snprintf(cmd.parm.num, sizeof(cmd.parm.num), "%s%c%c",
 553                                 status + 2, *status, *(status + 1));
 554                else
 555                        strlcpy(cmd.parm.num, status + 1, sizeof(cmd.parm.num));
 556                break;
 557        case 8:
 558                spin_lock_irqsave(&card->lock, flags);
 559                card->flags &= ~ICN_FLAGS_B1ACTIVE;
 560                icn_free_queue(card, 0);
 561                card->rcvidx[0] = 0;
 562                spin_unlock_irqrestore(&card->lock, flags);
 563                cmd.arg = 0;
 564                cmd.driver = card->myid;
 565                card->interface.statcallb(&cmd);
 566                cmd.command = ISDN_STAT_DHUP;
 567                cmd.arg = 0;
 568                cmd.driver = card->myid;
 569                card->interface.statcallb(&cmd);
 570                cmd.command = ISDN_STAT_BHUP;
 571                spin_lock_irqsave(&card->lock, flags);
 572                card->flags &= ~ICN_FLAGS_B2ACTIVE;
 573                icn_free_queue(card, 1);
 574                card->rcvidx[1] = 0;
 575                spin_unlock_irqrestore(&card->lock, flags);
 576                cmd.arg = 1;
 577                cmd.driver = card->myid;
 578                card->interface.statcallb(&cmd);
 579                cmd.command = ISDN_STAT_DHUP;
 580                cmd.arg = 1;
 581                cmd.driver = card->myid;
 582                break;
 583        }
 584        card->interface.statcallb(&cmd);
 585        return;
 586}
 587
 588static void
 589icn_putmsg(icn_card *card, unsigned char c)
 590{
 591        ulong flags;
 592
 593        spin_lock_irqsave(&card->lock, flags);
 594        *card->msg_buf_write++ = (c == 0xff) ? '\n' : c;
 595        if (card->msg_buf_write == card->msg_buf_read) {
 596                if (++card->msg_buf_read > card->msg_buf_end)
 597                        card->msg_buf_read = card->msg_buf;
 598        }
 599        if (card->msg_buf_write > card->msg_buf_end)
 600                card->msg_buf_write = card->msg_buf;
 601        spin_unlock_irqrestore(&card->lock, flags);
 602}
 603
 604static void
 605icn_polldchan(unsigned long data)
 606{
 607        icn_card *card = (icn_card *) data;
 608        int mch = card->secondhalf ? 2 : 0;
 609        int avail = 0;
 610        int left;
 611        u_char c;
 612        int ch;
 613        unsigned long flags;
 614        int i;
 615        u_char *p;
 616        isdn_ctrl cmd;
 617
 618        if (icn_trymaplock_channel(card, mch)) {
 619                avail = msg_avail;
 620                for (left = avail, i = readb(&msg_o); left > 0; i++, left--) {
 621                        c = readb(&dev.shmem->comm_buffers.iopc_buf[i & 0xff]);
 622                        icn_putmsg(card, c);
 623                        if (c == 0xff) {
 624                                card->imsg[card->iptr] = 0;
 625                                card->iptr = 0;
 626                                if (card->imsg[0] == '0' && card->imsg[1] >= '0' &&
 627                                    card->imsg[1] <= '2' && card->imsg[2] == ';') {
 628                                        ch = (card->imsg[1] - '0') - 1;
 629                                        p = &card->imsg[3];
 630                                        icn_parse_status(p, ch, card);
 631                                } else {
 632                                        p = card->imsg;
 633                                        if (!strncmp(p, "DRV1.", 5)) {
 634                                                u_char vstr[10];
 635                                                u_char *q = vstr;
 636
 637                                                printk(KERN_INFO "icn: (%s) %s\n", CID, p);
 638                                                if (!strncmp(p + 7, "TC", 2)) {
 639                                                        card->ptype = ISDN_PTYPE_1TR6;
 640                                                        card->interface.features |= ISDN_FEATURE_P_1TR6;
 641                                                        printk(KERN_INFO
 642                                                               "icn: (%s) 1TR6-Protocol loaded and running\n", CID);
 643                                                }
 644                                                if (!strncmp(p + 7, "EC", 2)) {
 645                                                        card->ptype = ISDN_PTYPE_EURO;
 646                                                        card->interface.features |= ISDN_FEATURE_P_EURO;
 647                                                        printk(KERN_INFO
 648                                                               "icn: (%s) Euro-Protocol loaded and running\n", CID);
 649                                                }
 650                                                p = strstr(card->imsg, "BRV") + 3;
 651                                                while (*p) {
 652                                                        if (*p >= '0' && *p <= '9')
 653                                                                *q++ = *p;
 654                                                        p++;
 655                                                }
 656                                                *q = '\0';
 657                                                strcat(vstr, "000");
 658                                                vstr[3] = '\0';
 659                                                card->fw_rev = (int) simple_strtoul(vstr, NULL, 10);
 660                                                continue;
 661
 662                                        }
 663                                }
 664                        } else {
 665                                card->imsg[card->iptr] = c;
 666                                if (card->iptr < 59)
 667                                        card->iptr++;
 668                        }
 669                }
 670                writeb((readb(&msg_o) + avail) & 0xff, &msg_o);
 671                icn_release_channel();
 672        }
 673        if (avail) {
 674                cmd.command = ISDN_STAT_STAVAIL;
 675                cmd.driver = card->myid;
 676                cmd.arg = avail;
 677                card->interface.statcallb(&cmd);
 678        }
 679        spin_lock_irqsave(&card->lock, flags);
 680        if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE))
 681                if (!(card->flags & ICN_FLAGS_RBTIMER)) {
 682                        /* schedule b-channel polling */
 683                        card->flags |= ICN_FLAGS_RBTIMER;
 684                        del_timer(&card->rb_timer);
 685                        card->rb_timer.function = icn_pollbchan;
 686                        card->rb_timer.data = (unsigned long) card;
 687                        card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD;
 688                        add_timer(&card->rb_timer);
 689                }
 690        /* schedule again */
 691        mod_timer(&card->st_timer, jiffies + ICN_TIMER_DCREAD);
 692        spin_unlock_irqrestore(&card->lock, flags);
 693}
 694
 695/* Append a packet to the transmit buffer-queue.
 696 * Parameters:
 697 *   channel = Number of B-channel
 698 *   skb     = pointer to sk_buff
 699 *   card    = pointer to card-struct
 700 * Return:
 701 *   Number of bytes transferred, -E??? on error
 702 */
 703
 704static int
 705icn_sendbuf(int channel, int ack, struct sk_buff *skb, icn_card *card)
 706{
 707        int len = skb->len;
 708        unsigned long flags;
 709        struct sk_buff *nskb;
 710
 711        if (len > 4000) {
 712                printk(KERN_WARNING
 713                       "icn: Send packet too large\n");
 714                return -EINVAL;
 715        }
 716        if (len) {
 717                if (!(card->flags & (channel) ? ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE))
 718                        return 0;
 719                if (card->sndcount[channel] > ICN_MAX_SQUEUE)
 720                        return 0;
 721                /* TODO test headroom or use skb->nb to flag ACK */
 722                nskb = skb_clone(skb, GFP_ATOMIC);
 723                if (nskb) {
 724                        /* Push ACK flag as one
 725                         * byte in front of data.
 726                         */
 727                        *(skb_push(nskb, 1)) = ack ? 1 : 0;
 728                        skb_queue_tail(&card->spqueue[channel], nskb);
 729                        dev_kfree_skb(skb);
 730                } else
 731                        len = 0;
 732                spin_lock_irqsave(&card->lock, flags);
 733                card->sndcount[channel] += len;
 734                spin_unlock_irqrestore(&card->lock, flags);
 735        }
 736        return len;
 737}
 738
 739/*
 740 * Check card's status after starting the bootstrap loader.
 741 * On entry, the card's shared memory has already to be mapped.
 742 * Return:
 743 *   0 on success (Boot loader ready)
 744 *   -EIO on failure (timeout)
 745 */
 746static int
 747icn_check_loader(int cardnumber)
 748{
 749        int timer = 0;
 750
 751        while (1) {
 752#ifdef BOOT_DEBUG
 753                printk(KERN_DEBUG "Loader %d ?\n", cardnumber);
 754#endif
 755                if (readb(&dev.shmem->data_control.scns) ||
 756                    readb(&dev.shmem->data_control.scnr)) {
 757                        if (timer++ > 5) {
 758                                printk(KERN_WARNING
 759                                       "icn: Boot-Loader %d timed out.\n",
 760                                       cardnumber);
 761                                icn_release_channel();
 762                                return -EIO;
 763                        }
 764#ifdef BOOT_DEBUG
 765                        printk(KERN_DEBUG "Loader %d TO?\n", cardnumber);
 766#endif
 767                        msleep_interruptible(ICN_BOOT_TIMEOUT1);
 768                } else {
 769#ifdef BOOT_DEBUG
 770                        printk(KERN_DEBUG "Loader %d OK\n", cardnumber);
 771#endif
 772                        icn_release_channel();
 773                        return 0;
 774                }
 775        }
 776}
 777
 778/* Load the boot-code into the interface-card's memory and start it.
 779 * Always called from user-process.
 780 *
 781 * Parameters:
 782 *            buffer = pointer to packet
 783 * Return:
 784 *        0 if successfully loaded
 785 */
 786
 787#ifdef BOOT_DEBUG
 788#define SLEEP(sec) {                                            \
 789                int slsec = sec;                                \
 790                printk(KERN_DEBUG "SLEEP(%d)\n", slsec);        \
 791                while (slsec) {                                 \
 792                        msleep_interruptible(1000);             \
 793                        slsec--;                                \
 794                }                                               \
 795        }
 796#else
 797#define SLEEP(sec)
 798#endif
 799
 800static int
 801icn_loadboot(u_char __user *buffer, icn_card *card)
 802{
 803        int ret;
 804        u_char *codebuf;
 805        unsigned long flags;
 806
 807#ifdef BOOT_DEBUG
 808        printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong) buffer);
 809#endif
 810        if (!(codebuf = kmalloc(ICN_CODE_STAGE1, GFP_KERNEL))) {
 811                printk(KERN_WARNING "icn: Could not allocate code buffer\n");
 812                ret = -ENOMEM;
 813                goto out;
 814        }
 815        if (copy_from_user(codebuf, buffer, ICN_CODE_STAGE1)) {
 816                ret = -EFAULT;
 817                goto out_kfree;
 818        }
 819        if (!card->rvalid) {
 820                if (!request_region(card->port, ICN_PORTLEN, card->regname)) {
 821                        printk(KERN_WARNING
 822                               "icn: (%s) ports 0x%03x-0x%03x in use.\n",
 823                               CID,
 824                               card->port,
 825                               card->port + ICN_PORTLEN);
 826                        ret = -EBUSY;
 827                        goto out_kfree;
 828                }
 829                card->rvalid = 1;
 830                if (card->doubleS0)
 831                        card->other->rvalid = 1;
 832        }
 833        if (!dev.mvalid) {
 834                if (!request_mem_region(dev.memaddr, 0x4000, "icn-isdn (all cards)")) {
 835                        printk(KERN_WARNING
 836                               "icn: memory at 0x%08lx in use.\n", dev.memaddr);
 837                        ret = -EBUSY;
 838                        goto out_kfree;
 839                }
 840                dev.shmem = ioremap(dev.memaddr, 0x4000);
 841                dev.mvalid = 1;
 842        }
 843        OUTB_P(0, ICN_RUN);     /* Reset Controller */
 844        OUTB_P(0, ICN_MAPRAM);  /* Disable RAM      */
 845        icn_shiftout(ICN_CFG, 0x0f, 3, 4);      /* Windowsize= 16k  */
 846        icn_shiftout(ICN_CFG, dev.memaddr, 23, 10);     /* Set RAM-Addr.    */
 847#ifdef BOOT_DEBUG
 848        printk(KERN_DEBUG "shmem=%08lx\n", dev.memaddr);
 849#endif
 850        SLEEP(1);
 851#ifdef BOOT_DEBUG
 852        printk(KERN_DEBUG "Map Bank 0\n");
 853#endif
 854        spin_lock_irqsave(&dev.devlock, flags);
 855        icn_map_channel(card, 0);       /* Select Bank 0    */
 856        icn_lock_channel(card, 0);      /* Lock Bank 0      */
 857        spin_unlock_irqrestore(&dev.devlock, flags);
 858        SLEEP(1);
 859        memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1);       /* Copy code        */
 860#ifdef BOOT_DEBUG
 861        printk(KERN_DEBUG "Bootloader transferred\n");
 862#endif
 863        if (card->doubleS0) {
 864                SLEEP(1);
 865#ifdef BOOT_DEBUG
 866                printk(KERN_DEBUG "Map Bank 8\n");
 867#endif
 868                spin_lock_irqsave(&dev.devlock, flags);
 869                __icn_release_channel();
 870                icn_map_channel(card, 2);       /* Select Bank 8   */
 871                icn_lock_channel(card, 2);      /* Lock Bank 8     */
 872                spin_unlock_irqrestore(&dev.devlock, flags);
 873                SLEEP(1);
 874                memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1);       /* Copy code        */
 875#ifdef BOOT_DEBUG
 876                printk(KERN_DEBUG "Bootloader transferred\n");
 877#endif
 878        }
 879        SLEEP(1);
 880        OUTB_P(0xff, ICN_RUN);  /* Start Boot-Code */
 881        if ((ret = icn_check_loader(card->doubleS0 ? 2 : 1))) {
 882                goto out_kfree;
 883        }
 884        if (!card->doubleS0) {
 885                ret = 0;
 886                goto out_kfree;
 887        }
 888        /* reached only, if we have a Double-S0-Card */
 889#ifdef BOOT_DEBUG
 890        printk(KERN_DEBUG "Map Bank 0\n");
 891#endif
 892        spin_lock_irqsave(&dev.devlock, flags);
 893        icn_map_channel(card, 0);       /* Select Bank 0   */
 894        icn_lock_channel(card, 0);      /* Lock Bank 0     */
 895        spin_unlock_irqrestore(&dev.devlock, flags);
 896        SLEEP(1);
 897        ret = (icn_check_loader(1));
 898
 899out_kfree:
 900        kfree(codebuf);
 901out:
 902        return ret;
 903}
 904
 905static int
 906icn_loadproto(u_char __user *buffer, icn_card *card)
 907{
 908        register u_char __user *p = buffer;
 909        u_char codebuf[256];
 910        uint left = ICN_CODE_STAGE2;
 911        uint cnt;
 912        int timer;
 913        unsigned long flags;
 914
 915#ifdef BOOT_DEBUG
 916        printk(KERN_DEBUG "icn_loadproto called\n");
 917#endif
 918        if (!access_ok(VERIFY_READ, buffer, ICN_CODE_STAGE2))
 919                return -EFAULT;
 920        timer = 0;
 921        spin_lock_irqsave(&dev.devlock, flags);
 922        if (card->secondhalf) {
 923                icn_map_channel(card, 2);
 924                icn_lock_channel(card, 2);
 925        } else {
 926                icn_map_channel(card, 0);
 927                icn_lock_channel(card, 0);
 928        }
 929        spin_unlock_irqrestore(&dev.devlock, flags);
 930        while (left) {
 931                if (sbfree) {   /* If there is a free buffer...  */
 932                        cnt = left;
 933                        if (cnt > 256)
 934                                cnt = 256;
 935                        if (copy_from_user(codebuf, p, cnt)) {
 936                                icn_maprelease_channel(card, 0);
 937                                return -EFAULT;
 938                        }
 939                        memcpy_toio(&sbuf_l, codebuf, cnt);     /* copy data                     */
 940                        sbnext; /* switch to next buffer         */
 941                        p += cnt;
 942                        left -= cnt;
 943                        timer = 0;
 944                } else {
 945#ifdef BOOT_DEBUG
 946                        printk(KERN_DEBUG "boot 2 !sbfree\n");
 947#endif
 948                        if (timer++ > 5) {
 949                                icn_maprelease_channel(card, 0);
 950                                return -EIO;
 951                        }
 952                        schedule_timeout_interruptible(10);
 953                }
 954        }
 955        writeb(0x20, &sbuf_n);
 956        timer = 0;
 957        while (1) {
 958                if (readb(&cmd_o) || readb(&cmd_i)) {
 959#ifdef BOOT_DEBUG
 960                        printk(KERN_DEBUG "Proto?\n");
 961#endif
 962                        if (timer++ > 5) {
 963                                printk(KERN_WARNING
 964                                       "icn: (%s) Protocol timed out.\n",
 965                                       CID);
 966#ifdef BOOT_DEBUG
 967                                printk(KERN_DEBUG "Proto TO!\n");
 968#endif
 969                                icn_maprelease_channel(card, 0);
 970                                return -EIO;
 971                        }
 972#ifdef BOOT_DEBUG
 973                        printk(KERN_DEBUG "Proto TO?\n");
 974#endif
 975                        msleep_interruptible(ICN_BOOT_TIMEOUT1);
 976                } else {
 977                        if ((card->secondhalf) || (!card->doubleS0)) {
 978#ifdef BOOT_DEBUG
 979                                printk(KERN_DEBUG "Proto loaded, install poll-timer %d\n",
 980                                       card->secondhalf);
 981#endif
 982                                spin_lock_irqsave(&card->lock, flags);
 983                                init_timer(&card->st_timer);
 984                                card->st_timer.expires = jiffies + ICN_TIMER_DCREAD;
 985                                card->st_timer.function = icn_polldchan;
 986                                card->st_timer.data = (unsigned long) card;
 987                                add_timer(&card->st_timer);
 988                                card->flags |= ICN_FLAGS_RUNNING;
 989                                if (card->doubleS0) {
 990                                        init_timer(&card->other->st_timer);
 991                                        card->other->st_timer.expires = jiffies + ICN_TIMER_DCREAD;
 992                                        card->other->st_timer.function = icn_polldchan;
 993                                        card->other->st_timer.data = (unsigned long) card->other;
 994                                        add_timer(&card->other->st_timer);
 995                                        card->other->flags |= ICN_FLAGS_RUNNING;
 996                                }
 997                                spin_unlock_irqrestore(&card->lock, flags);
 998                        }
 999                        icn_maprelease_channel(card, 0);
1000                        return 0;
1001                }
1002        }
1003}
1004
1005/* Read the Status-replies from the Interface */
1006static int
1007icn_readstatus(u_char __user *buf, int len, icn_card *card)
1008{
1009        int count;
1010        u_char __user *p;
1011
1012        for (p = buf, count = 0; count < len; p++, count++) {
1013                if (card->msg_buf_read == card->msg_buf_write)
1014                        return count;
1015                if (put_user(*card->msg_buf_read++, p))
1016                        return -EFAULT;
1017                if (card->msg_buf_read > card->msg_buf_end)
1018                        card->msg_buf_read = card->msg_buf;
1019        }
1020        return count;
1021}
1022
1023/* Put command-strings into the command-queue of the Interface */
1024static int
1025icn_writecmd(const u_char *buf, int len, int user, icn_card *card)
1026{
1027        int mch = card->secondhalf ? 2 : 0;
1028        int pp;
1029        int i;
1030        int count;
1031        int xcount;
1032        int ocount;
1033        int loop;
1034        unsigned long flags;
1035        int lastmap_channel;
1036        struct icn_card *lastmap_card;
1037        u_char *p;
1038        isdn_ctrl cmd;
1039        u_char msg[0x100];
1040
1041        ocount = 1;
1042        xcount = loop = 0;
1043        while (len) {
1044                count = cmd_free;
1045                if (count > len)
1046                        count = len;
1047                if (user) {
1048                        if (copy_from_user(msg, buf, count))
1049                                return -EFAULT;
1050                } else
1051                        memcpy(msg, buf, count);
1052
1053                spin_lock_irqsave(&dev.devlock, flags);
1054                lastmap_card = dev.mcard;
1055                lastmap_channel = dev.channel;
1056                icn_map_channel(card, mch);
1057
1058                icn_putmsg(card, '>');
1059                for (p = msg, pp = readb(&cmd_i), i = count; i > 0; i--, p++, pp
1060                             ++) {
1061                        writeb((*p == '\n') ? 0xff : *p,
1062                               &dev.shmem->comm_buffers.pcio_buf[pp & 0xff]);
1063                        len--;
1064                        xcount++;
1065                        icn_putmsg(card, *p);
1066                        if ((*p == '\n') && (i > 1)) {
1067                                icn_putmsg(card, '>');
1068                                ocount++;
1069                        }
1070                        ocount++;
1071                }
1072                writeb((readb(&cmd_i) + count) & 0xff, &cmd_i);
1073                if (lastmap_card)
1074                        icn_map_channel(lastmap_card, lastmap_channel);
1075                spin_unlock_irqrestore(&dev.devlock, flags);
1076                if (len) {
1077                        mdelay(1);
1078                        if (loop++ > 20)
1079                                break;
1080                } else
1081                        break;
1082        }
1083        if (len && (!user))
1084                printk(KERN_WARNING "icn: writemsg incomplete!\n");
1085        cmd.command = ISDN_STAT_STAVAIL;
1086        cmd.driver = card->myid;
1087        cmd.arg = ocount;
1088        card->interface.statcallb(&cmd);
1089        return xcount;
1090}
1091
1092/*
1093 * Delete card's pending timers, send STOP to linklevel
1094 */
1095static void
1096icn_stopcard(icn_card *card)
1097{
1098        unsigned long flags;
1099        isdn_ctrl cmd;
1100
1101        spin_lock_irqsave(&card->lock, flags);
1102        if (card->flags & ICN_FLAGS_RUNNING) {
1103                card->flags &= ~ICN_FLAGS_RUNNING;
1104                del_timer(&card->st_timer);
1105                del_timer(&card->rb_timer);
1106                spin_unlock_irqrestore(&card->lock, flags);
1107                cmd.command = ISDN_STAT_STOP;
1108                cmd.driver = card->myid;
1109                card->interface.statcallb(&cmd);
1110                if (card->doubleS0)
1111                        icn_stopcard(card->other);
1112        } else
1113                spin_unlock_irqrestore(&card->lock, flags);
1114}
1115
1116static void
1117icn_stopallcards(void)
1118{
1119        icn_card *p = cards;
1120
1121        while (p) {
1122                icn_stopcard(p);
1123                p = p->next;
1124        }
1125}
1126
1127/*
1128 * Unmap all cards, because some of them may be mapped accidetly during
1129 * autoprobing of some network drivers (SMC-driver?)
1130 */
1131static void
1132icn_disable_cards(void)
1133{
1134        icn_card *card = cards;
1135
1136        while (card) {
1137                if (!request_region(card->port, ICN_PORTLEN, "icn-isdn")) {
1138                        printk(KERN_WARNING
1139                               "icn: (%s) ports 0x%03x-0x%03x in use.\n",
1140                               CID,
1141                               card->port,
1142                               card->port + ICN_PORTLEN);
1143                } else {
1144                        OUTB_P(0, ICN_RUN);     /* Reset Controller     */
1145                        OUTB_P(0, ICN_MAPRAM);  /* Disable RAM          */
1146                        release_region(card->port, ICN_PORTLEN);
1147                }
1148                card = card->next;
1149        }
1150}
1151
1152static int
1153icn_command(isdn_ctrl *c, icn_card *card)
1154{
1155        ulong a;
1156        ulong flags;
1157        int i;
1158        char cbuf[80];
1159        isdn_ctrl cmd;
1160        icn_cdef cdef;
1161        char __user *arg;
1162
1163        switch (c->command) {
1164        case ISDN_CMD_IOCTL:
1165                memcpy(&a, c->parm.num, sizeof(ulong));
1166                arg = (char __user *)a;
1167                switch (c->arg) {
1168                case ICN_IOCTL_SETMMIO:
1169                        if (dev.memaddr != (a & 0x0ffc000)) {
1170                                if (!request_mem_region(a & 0x0ffc000, 0x4000, "icn-isdn (all cards)")) {
1171                                        printk(KERN_WARNING
1172                                               "icn: memory at 0x%08lx in use.\n",
1173                                               a & 0x0ffc000);
1174                                        return -EINVAL;
1175                                }
1176                                release_mem_region(a & 0x0ffc000, 0x4000);
1177                                icn_stopallcards();
1178                                spin_lock_irqsave(&card->lock, flags);
1179                                if (dev.mvalid) {
1180                                        iounmap(dev.shmem);
1181                                        release_mem_region(dev.memaddr, 0x4000);
1182                                }
1183                                dev.mvalid = 0;
1184                                dev.memaddr = a & 0x0ffc000;
1185                                spin_unlock_irqrestore(&card->lock, flags);
1186                                printk(KERN_INFO
1187                                       "icn: (%s) mmio set to 0x%08lx\n",
1188                                       CID,
1189                                       dev.memaddr);
1190                        }
1191                        break;
1192                case ICN_IOCTL_GETMMIO:
1193                        return (long) dev.memaddr;
1194                case ICN_IOCTL_SETPORT:
1195                        if (a == 0x300 || a == 0x310 || a == 0x320 || a == 0x330
1196                            || a == 0x340 || a == 0x350 || a == 0x360 ||
1197                            a == 0x308 || a == 0x318 || a == 0x328 || a == 0x338
1198                            || a == 0x348 || a == 0x358 || a == 0x368) {
1199                                if (card->port != (unsigned short) a) {
1200                                        if (!request_region((unsigned short) a, ICN_PORTLEN, "icn-isdn")) {
1201                                                printk(KERN_WARNING
1202                                                       "icn: (%s) ports 0x%03x-0x%03x in use.\n",
1203                                                       CID, (int) a, (int) a + ICN_PORTLEN);
1204                                                return -EINVAL;
1205                                        }
1206                                        release_region((unsigned short) a, ICN_PORTLEN);
1207                                        icn_stopcard(card);
1208                                        spin_lock_irqsave(&card->lock, flags);
1209                                        if (card->rvalid)
1210                                                release_region(card->port, ICN_PORTLEN);
1211                                        card->port = (unsigned short) a;
1212                                        card->rvalid = 0;
1213                                        if (card->doubleS0) {
1214                                                card->other->port = (unsigned short) a;
1215                                                card->other->rvalid = 0;
1216                                        }
1217                                        spin_unlock_irqrestore(&card->lock, flags);
1218                                        printk(KERN_INFO
1219                                               "icn: (%s) port set to 0x%03x\n",
1220                                               CID, card->port);
1221                                }
1222                        } else
1223                                return -EINVAL;
1224                        break;
1225                case ICN_IOCTL_GETPORT:
1226                        return (int) card->port;
1227                case ICN_IOCTL_GETDOUBLE:
1228                        return (int) card->doubleS0;
1229                case ICN_IOCTL_DEBUGVAR:
1230                        if (copy_to_user(arg,
1231                                         &card,
1232                                         sizeof(ulong)))
1233                                return -EFAULT;
1234                        a += sizeof(ulong);
1235                        {
1236                                ulong l = (ulong)&dev;
1237                                if (copy_to_user(arg,
1238                                                 &l,
1239                                                 sizeof(ulong)))
1240                                        return -EFAULT;
1241                        }
1242                        return 0;
1243                case ICN_IOCTL_LOADBOOT:
1244                        if (dev.firstload) {
1245                                icn_disable_cards();
1246                                dev.firstload = 0;
1247                        }
1248                        icn_stopcard(card);
1249                        return (icn_loadboot(arg, card));
1250                case ICN_IOCTL_LOADPROTO:
1251                        icn_stopcard(card);
1252                        if ((i = (icn_loadproto(arg, card))))
1253                                return i;
1254                        if (card->doubleS0)
1255                                i = icn_loadproto(arg + ICN_CODE_STAGE2, card->other);
1256                        return i;
1257                        break;
1258                case ICN_IOCTL_ADDCARD:
1259                        if (!dev.firstload)
1260                                return -EBUSY;
1261                        if (copy_from_user(&cdef,
1262                                           arg,
1263                                           sizeof(cdef)))
1264                                return -EFAULT;
1265                        return (icn_addcard(cdef.port, cdef.id1, cdef.id2));
1266                        break;
1267                case ICN_IOCTL_LEASEDCFG:
1268                        if (a) {
1269                                if (!card->leased) {
1270                                        card->leased = 1;
1271                                        while (card->ptype == ISDN_PTYPE_UNKNOWN) {
1272                                                msleep_interruptible(ICN_BOOT_TIMEOUT1);
1273                                        }
1274                                        msleep_interruptible(ICN_BOOT_TIMEOUT1);
1275                                        sprintf(cbuf, "00;FV2ON\n01;EAZ%c\n02;EAZ%c\n",
1276                                                (a & 1) ? '1' : 'C', (a & 2) ? '2' : 'C');
1277                                        i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1278                                        printk(KERN_INFO
1279                                               "icn: (%s) Leased-line mode enabled\n",
1280                                               CID);
1281                                        cmd.command = ISDN_STAT_RUN;
1282                                        cmd.driver = card->myid;
1283                                        cmd.arg = 0;
1284                                        card->interface.statcallb(&cmd);
1285                                }
1286                        } else {
1287                                if (card->leased) {
1288                                        card->leased = 0;
1289                                        sprintf(cbuf, "00;FV2OFF\n");
1290                                        i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1291                                        printk(KERN_INFO
1292                                               "icn: (%s) Leased-line mode disabled\n",
1293                                               CID);
1294                                        cmd.command = ISDN_STAT_RUN;
1295                                        cmd.driver = card->myid;
1296                                        cmd.arg = 0;
1297                                        card->interface.statcallb(&cmd);
1298                                }
1299                        }
1300                        return 0;
1301                default:
1302                        return -EINVAL;
1303                }
1304                break;
1305        case ISDN_CMD_DIAL:
1306                if (!(card->flags & ICN_FLAGS_RUNNING))
1307                        return -ENODEV;
1308                if (card->leased)
1309                        break;
1310                if ((c->arg & 255) < ICN_BCH) {
1311                        char *p;
1312                        char dcode[4];
1313
1314                        a = c->arg;
1315                        p = c->parm.setup.phone;
1316                        if (*p == 's' || *p == 'S') {
1317                                /* Dial for SPV */
1318                                p++;
1319                                strcpy(dcode, "SCA");
1320                        } else
1321                                /* Normal Dial */
1322                                strcpy(dcode, "CAL");
1323                        snprintf(cbuf, sizeof(cbuf),
1324                                 "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
1325                                 dcode, p, c->parm.setup.si1,
1326                                 c->parm.setup.si2, c->parm.setup.eazmsn);
1327                        i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1328                }
1329                break;
1330        case ISDN_CMD_ACCEPTD:
1331                if (!(card->flags & ICN_FLAGS_RUNNING))
1332                        return -ENODEV;
1333                if (c->arg < ICN_BCH) {
1334                        a = c->arg + 1;
1335                        if (card->fw_rev >= 300) {
1336                                switch (card->l2_proto[a - 1]) {
1337                                case ISDN_PROTO_L2_X75I:
1338                                        sprintf(cbuf, "%02d;BX75\n", (int) a);
1339                                        break;
1340                                case ISDN_PROTO_L2_HDLC:
1341                                        sprintf(cbuf, "%02d;BTRA\n", (int) a);
1342                                        break;
1343                                }
1344                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1345                        }
1346                        sprintf(cbuf, "%02d;DCON_R\n", (int) a);
1347                        i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1348                }
1349                break;
1350        case ISDN_CMD_ACCEPTB:
1351                if (!(card->flags & ICN_FLAGS_RUNNING))
1352                        return -ENODEV;
1353                if (c->arg < ICN_BCH) {
1354                        a = c->arg + 1;
1355                        if (card->fw_rev >= 300)
1356                                switch (card->l2_proto[a - 1]) {
1357                                case ISDN_PROTO_L2_X75I:
1358                                        sprintf(cbuf, "%02d;BCON_R,BX75\n", (int) a);
1359                                        break;
1360                                case ISDN_PROTO_L2_HDLC:
1361                                        sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int) a);
1362                                        break;
1363                                } else
1364                                sprintf(cbuf, "%02d;BCON_R\n", (int) a);
1365                        i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1366                }
1367                break;
1368        case ISDN_CMD_HANGUP:
1369                if (!(card->flags & ICN_FLAGS_RUNNING))
1370                        return -ENODEV;
1371                if (c->arg < ICN_BCH) {
1372                        a = c->arg + 1;
1373                        sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a);
1374                        i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1375                }
1376                break;
1377        case ISDN_CMD_SETEAZ:
1378                if (!(card->flags & ICN_FLAGS_RUNNING))
1379                        return -ENODEV;
1380                if (card->leased)
1381                        break;
1382                if (c->arg < ICN_BCH) {
1383                        a = c->arg + 1;
1384                        if (card->ptype == ISDN_PTYPE_EURO) {
1385                                sprintf(cbuf, "%02d;MS%s%s\n", (int) a,
1386                                        c->parm.num[0] ? "N" : "ALL", c->parm.num);
1387                        } else
1388                                sprintf(cbuf, "%02d;EAZ%s\n", (int) a,
1389                                        c->parm.num[0] ? (char *)(c->parm.num) : "0123456789");
1390                        i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1391                }
1392                break;
1393        case ISDN_CMD_CLREAZ:
1394                if (!(card->flags & ICN_FLAGS_RUNNING))
1395                        return -ENODEV;
1396                if (card->leased)
1397                        break;
1398                if (c->arg < ICN_BCH) {
1399                        a = c->arg + 1;
1400                        if (card->ptype == ISDN_PTYPE_EURO)
1401                                sprintf(cbuf, "%02d;MSNC\n", (int) a);
1402                        else
1403                                sprintf(cbuf, "%02d;EAZC\n", (int) a);
1404                        i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1405                }
1406                break;
1407        case ISDN_CMD_SETL2:
1408                if (!(card->flags & ICN_FLAGS_RUNNING))
1409                        return -ENODEV;
1410                if ((c->arg & 255) < ICN_BCH) {
1411                        a = c->arg;
1412                        switch (a >> 8) {
1413                        case ISDN_PROTO_L2_X75I:
1414                                sprintf(cbuf, "%02d;BX75\n", (int) (a & 255) + 1);
1415                                break;
1416                        case ISDN_PROTO_L2_HDLC:
1417                                sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1);
1418                                break;
1419                        default:
1420                                return -EINVAL;
1421                        }
1422                        i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
1423                        card->l2_proto[a & 255] = (a >> 8);
1424                }
1425                break;
1426        case ISDN_CMD_SETL3:
1427                if (!(card->flags & ICN_FLAGS_RUNNING))
1428                        return -ENODEV;
1429                return 0;
1430        default:
1431                return -EINVAL;
1432        }
1433        return 0;
1434}
1435
1436/*
1437 * Find card with given driverId
1438 */
1439static inline icn_card *
1440icn_findcard(int driverid)
1441{
1442        icn_card *p = cards;
1443
1444        while (p) {
1445                if (p->myid == driverid)
1446                        return p;
1447                p = p->next;
1448        }
1449        return (icn_card *) 0;
1450}
1451
1452/*
1453 * Wrapper functions for interface to linklevel
1454 */
1455static int
1456if_command(isdn_ctrl *c)
1457{
1458        icn_card *card = icn_findcard(c->driver);
1459
1460        if (card)
1461                return (icn_command(c, card));
1462        printk(KERN_ERR
1463               "icn: if_command %d called with invalid driverId %d!\n",
1464               c->command, c->driver);
1465        return -ENODEV;
1466}
1467
1468static int
1469if_writecmd(const u_char __user *buf, int len, int id, int channel)
1470{
1471        icn_card *card = icn_findcard(id);
1472
1473        if (card) {
1474                if (!(card->flags & ICN_FLAGS_RUNNING))
1475                        return -ENODEV;
1476                return (icn_writecmd(buf, len, 1, card));
1477        }
1478        printk(KERN_ERR
1479               "icn: if_writecmd called with invalid driverId!\n");
1480        return -ENODEV;
1481}
1482
1483static int
1484if_readstatus(u_char __user *buf, int len, int id, int channel)
1485{
1486        icn_card *card = icn_findcard(id);
1487
1488        if (card) {
1489                if (!(card->flags & ICN_FLAGS_RUNNING))
1490                        return -ENODEV;
1491                return (icn_readstatus(buf, len, card));
1492        }
1493        printk(KERN_ERR
1494               "icn: if_readstatus called with invalid driverId!\n");
1495        return -ENODEV;
1496}
1497
1498static int
1499if_sendbuf(int id, int channel, int ack, struct sk_buff *skb)
1500{
1501        icn_card *card = icn_findcard(id);
1502
1503        if (card) {
1504                if (!(card->flags & ICN_FLAGS_RUNNING))
1505                        return -ENODEV;
1506                return (icn_sendbuf(channel, ack, skb, card));
1507        }
1508        printk(KERN_ERR
1509               "icn: if_sendbuf called with invalid driverId!\n");
1510        return -ENODEV;
1511}
1512
1513/*
1514 * Allocate a new card-struct, initialize it
1515 * link it into cards-list and register it at linklevel.
1516 */
1517static icn_card *
1518icn_initcard(int port, char *id)
1519{
1520        icn_card *card;
1521        int i;
1522
1523        if (!(card = kzalloc(sizeof(icn_card), GFP_KERNEL))) {
1524                printk(KERN_WARNING
1525                       "icn: (%s) Could not allocate card-struct.\n", id);
1526                return (icn_card *) 0;
1527        }
1528        spin_lock_init(&card->lock);
1529        card->port = port;
1530        card->interface.owner = THIS_MODULE;
1531        card->interface.hl_hdrlen = 1;
1532        card->interface.channels = ICN_BCH;
1533        card->interface.maxbufsize = 4000;
1534        card->interface.command = if_command;
1535        card->interface.writebuf_skb = if_sendbuf;
1536        card->interface.writecmd = if_writecmd;
1537        card->interface.readstat = if_readstatus;
1538        card->interface.features = ISDN_FEATURE_L2_X75I |
1539                ISDN_FEATURE_L2_HDLC |
1540                ISDN_FEATURE_L3_TRANS |
1541                ISDN_FEATURE_P_UNKNOWN;
1542        card->ptype = ISDN_PTYPE_UNKNOWN;
1543        strlcpy(card->interface.id, id, sizeof(card->interface.id));
1544        card->msg_buf_write = card->msg_buf;
1545        card->msg_buf_read = card->msg_buf;
1546        card->msg_buf_end = &card->msg_buf[sizeof(card->msg_buf) - 1];
1547        for (i = 0; i < ICN_BCH; i++) {
1548                card->l2_proto[i] = ISDN_PROTO_L2_X75I;
1549                skb_queue_head_init(&card->spqueue[i]);
1550        }
1551        card->next = cards;
1552        cards = card;
1553        if (!register_isdn(&card->interface)) {
1554                cards = cards->next;
1555                printk(KERN_WARNING
1556                       "icn: Unable to register %s\n", id);
1557                kfree(card);
1558                return (icn_card *) 0;
1559        }
1560        card->myid = card->interface.channels;
1561        sprintf(card->regname, "icn-isdn (%s)", card->interface.id);
1562        return card;
1563}
1564
1565static int
1566icn_addcard(int port, char *id1, char *id2)
1567{
1568        icn_card *card;
1569        icn_card *card2;
1570
1571        if (!(card = icn_initcard(port, id1))) {
1572                return -EIO;
1573        }
1574        if (!strlen(id2)) {
1575                printk(KERN_INFO
1576                       "icn: (%s) ICN-2B, port 0x%x added\n",
1577                       card->interface.id, port);
1578                return 0;
1579        }
1580        if (!(card2 = icn_initcard(port, id2))) {
1581                printk(KERN_INFO
1582                       "icn: (%s) half ICN-4B, port 0x%x added\n", id2, port);
1583                return 0;
1584        }
1585        card->doubleS0 = 1;
1586        card->secondhalf = 0;
1587        card->other = card2;
1588        card2->doubleS0 = 1;
1589        card2->secondhalf = 1;
1590        card2->other = card;
1591        printk(KERN_INFO
1592               "icn: (%s and %s) ICN-4B, port 0x%x added\n",
1593               card->interface.id, card2->interface.id, port);
1594        return 0;
1595}
1596
1597#ifndef MODULE
1598static int __init
1599icn_setup(char *line)
1600{
1601        char *p, *str;
1602        int     ints[3];
1603        static char sid[20];
1604        static char sid2[20];
1605
1606        str = get_options(line, 2, ints);
1607        if (ints[0])
1608                portbase = ints[1];
1609        if (ints[0] > 1)
1610                membase = (unsigned long)ints[2];
1611        if (str && *str) {
1612                strlcpy(sid, str, sizeof(sid));
1613                icn_id = sid;
1614                if ((p = strchr(sid, ','))) {
1615                        *p++ = 0;
1616                        strcpy(sid2, p);
1617                        icn_id2 = sid2;
1618                }
1619        }
1620        return (1);
1621}
1622__setup("icn=", icn_setup);
1623#endif /* MODULE */
1624
1625static int __init icn_init(void)
1626{
1627        char *p;
1628        char rev[21];
1629
1630        memset(&dev, 0, sizeof(icn_dev));
1631        dev.memaddr = (membase & 0x0ffc000);
1632        dev.channel = -1;
1633        dev.mcard = NULL;
1634        dev.firstload = 1;
1635        spin_lock_init(&dev.devlock);
1636
1637        if ((p = strchr(revision, ':'))) {
1638                strncpy(rev, p + 1, 20);
1639                rev[20] = '\0';
1640                p = strchr(rev, '$');
1641                if (p)
1642                        *p = 0;
1643        } else
1644                strcpy(rev, " ??? ");
1645        printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08lx\n", rev,
1646               dev.memaddr);
1647        return (icn_addcard(portbase, icn_id, icn_id2));
1648}
1649
1650static void __exit icn_exit(void)
1651{
1652        isdn_ctrl cmd;
1653        icn_card *card = cards;
1654        icn_card *last, *tmpcard;
1655        int i;
1656        unsigned long flags;
1657
1658        icn_stopallcards();
1659        while (card) {
1660                cmd.command = ISDN_STAT_UNLOAD;
1661                cmd.driver = card->myid;
1662                card->interface.statcallb(&cmd);
1663                spin_lock_irqsave(&card->lock, flags);
1664                if (card->rvalid) {
1665                        OUTB_P(0, ICN_RUN);     /* Reset Controller     */
1666                        OUTB_P(0, ICN_MAPRAM);  /* Disable RAM          */
1667                        if (card->secondhalf || (!card->doubleS0)) {
1668                                release_region(card->port, ICN_PORTLEN);
1669                                card->rvalid = 0;
1670                        }
1671                        for (i = 0; i < ICN_BCH; i++)
1672                                icn_free_queue(card, i);
1673                }
1674                tmpcard = card->next;
1675                spin_unlock_irqrestore(&card->lock, flags);
1676                card = tmpcard;
1677        }
1678        card = cards;
1679        cards = NULL;
1680        while (card) {
1681                last = card;
1682                card = card->next;
1683                kfree(last);
1684        }
1685        if (dev.mvalid) {
1686                iounmap(dev.shmem);
1687                release_mem_region(dev.memaddr, 0x4000);
1688        }
1689        printk(KERN_NOTICE "ICN-ISDN-driver unloaded\n");
1690}
1691
1692module_init(icn_init);
1693module_exit(icn_exit);
1694