linux/drivers/isdn/hardware/avm/b1.c
<<
>>
Prefs
   1/* $Id: b1.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
   2 * 
   3 * Common module for AVM B1 cards.
   4 * 
   5 * Copyright 1999 by Carsten Paeth <calle@calle.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 <linux/module.h>
  13#include <linux/kernel.h>
  14#include <linux/pci.h>
  15#include <linux/skbuff.h>
  16#include <linux/delay.h>
  17#include <linux/mm.h>
  18#include <linux/interrupt.h>
  19#include <linux/ioport.h>
  20#include <linux/capi.h>
  21#include <linux/kernelcapi.h>
  22#include <asm/io.h>
  23#include <linux/init.h>
  24#include <asm/uaccess.h>
  25#include <linux/netdevice.h>
  26#include <linux/isdn/capilli.h>
  27#include "avmcard.h"
  28#include <linux/isdn/capicmd.h>
  29#include <linux/isdn/capiutil.h>
  30
  31static char *revision = "$Revision: 1.1.2.2 $";
  32
  33/* ------------------------------------------------------------- */
  34
  35MODULE_DESCRIPTION("CAPI4Linux: Common support for active AVM cards");
  36MODULE_AUTHOR("Carsten Paeth");
  37MODULE_LICENSE("GPL");
  38
  39/* ------------------------------------------------------------- */
  40
  41int b1_irq_table[16] =
  42{0,
  43 0,
  44 0,
  45 192,                           /* irq 3 */
  46 32,                            /* irq 4 */
  47 160,                           /* irq 5 */
  48 96,                            /* irq 6 */
  49 224,                           /* irq 7 */
  50 0,
  51 64,                            /* irq 9 */
  52 80,                            /* irq 10 */
  53 208,                           /* irq 11 */
  54 48,                            /* irq 12 */
  55 0,
  56 0,
  57 112,                           /* irq 15 */
  58};
  59
  60/* ------------------------------------------------------------- */     
  61
  62avmcard *b1_alloc_card(int nr_controllers)
  63{
  64        avmcard *card;
  65        avmctrl_info *cinfo;
  66        int i;
  67
  68        card = kzalloc(sizeof(*card), GFP_KERNEL);
  69        if (!card)
  70                return NULL;
  71
  72        cinfo = kzalloc(sizeof(*cinfo) * nr_controllers, GFP_KERNEL);
  73        if (!cinfo) {
  74                kfree(card);
  75                return NULL;
  76        }
  77
  78        card->ctrlinfo = cinfo;
  79        for (i = 0; i < nr_controllers; i++) {
  80                INIT_LIST_HEAD(&cinfo[i].ncci_head);
  81                cinfo[i].card = card;
  82        }
  83        spin_lock_init(&card->lock);
  84        card->nr_controllers = nr_controllers;
  85
  86        return card;
  87}
  88
  89/* ------------------------------------------------------------- */
  90
  91void b1_free_card(avmcard *card)
  92{
  93        kfree(card->ctrlinfo);
  94        kfree(card);
  95}
  96
  97/* ------------------------------------------------------------- */
  98
  99int b1_detect(unsigned int base, enum avmcardtype cardtype)
 100{
 101        int onoff, i;
 102
 103        /*
 104         * Statusregister 0000 00xx 
 105         */
 106        if ((inb(base + B1_INSTAT) & 0xfc)
 107            || (inb(base + B1_OUTSTAT) & 0xfc))
 108                return 1;
 109        /*
 110         * Statusregister 0000 001x 
 111         */
 112        b1outp(base, B1_INSTAT, 0x2);   /* enable irq */
 113        /* b1outp(base, B1_OUTSTAT, 0x2); */
 114        if ((inb(base + B1_INSTAT) & 0xfe) != 0x2
 115            /* || (inb(base + B1_OUTSTAT) & 0xfe) != 0x2 */)
 116                return 2;
 117        /*
 118         * Statusregister 0000 000x 
 119         */
 120        b1outp(base, B1_INSTAT, 0x0);   /* disable irq */
 121        b1outp(base, B1_OUTSTAT, 0x0);
 122        if ((inb(base + B1_INSTAT) & 0xfe)
 123            || (inb(base + B1_OUTSTAT) & 0xfe))
 124                return 3;
 125        
 126        for (onoff = !0, i= 0; i < 10 ; i++) {
 127                b1_set_test_bit(base, cardtype, onoff);
 128                if (b1_get_test_bit(base, cardtype) != onoff)
 129                   return 4;
 130                onoff = !onoff;
 131        }
 132
 133        if (cardtype == avm_m1)
 134           return 0;
 135
 136        if ((b1_rd_reg(base, B1_STAT1(cardtype)) & 0x0f) != 0x01)
 137           return 5;
 138
 139        return 0;
 140}
 141
 142void b1_getrevision(avmcard *card)
 143{
 144    card->class = inb(card->port + B1_ANALYSE);
 145    card->revision = inb(card->port + B1_REVISION);
 146}
 147
 148#define FWBUF_SIZE      256
 149int b1_load_t4file(avmcard *card, capiloaddatapart * t4file)
 150{
 151        unsigned char buf[FWBUF_SIZE];
 152        unsigned char *dp;
 153        int i, left;
 154        unsigned int base = card->port;
 155
 156        dp = t4file->data;
 157        left = t4file->len;
 158        while (left > FWBUF_SIZE) {
 159                if (t4file->user) {
 160                        if (copy_from_user(buf, dp, FWBUF_SIZE))
 161                                return -EFAULT;
 162                } else {
 163                        memcpy(buf, dp, FWBUF_SIZE);
 164                }
 165                for (i = 0; i < FWBUF_SIZE; i++)
 166                        if (b1_save_put_byte(base, buf[i]) < 0) {
 167                                printk(KERN_ERR "%s: corrupted firmware file ?\n",
 168                                                card->name);
 169                                return -EIO;
 170                        }
 171                left -= FWBUF_SIZE;
 172                dp += FWBUF_SIZE;
 173        }
 174        if (left) {
 175                if (t4file->user) {
 176                        if (copy_from_user(buf, dp, left))
 177                                return -EFAULT;
 178                } else {
 179                        memcpy(buf, dp, left);
 180                }
 181                for (i = 0; i < left; i++)
 182                        if (b1_save_put_byte(base, buf[i]) < 0) {
 183                                printk(KERN_ERR "%s: corrupted firmware file ?\n",
 184                                                card->name);
 185                                return -EIO;
 186                        }
 187        }
 188        return 0;
 189}
 190
 191int b1_load_config(avmcard *card, capiloaddatapart * config)
 192{
 193        unsigned char buf[FWBUF_SIZE];
 194        unsigned char *dp;
 195        unsigned int base = card->port;
 196        int i, j, left;
 197
 198        dp = config->data;
 199        left = config->len;
 200        if (left) {
 201                b1_put_byte(base, SEND_CONFIG);
 202                b1_put_word(base, 1);
 203                b1_put_byte(base, SEND_CONFIG);
 204                b1_put_word(base, left);
 205        }
 206        while (left > FWBUF_SIZE) {
 207                if (config->user) {
 208                        if (copy_from_user(buf, dp, FWBUF_SIZE))
 209                                return -EFAULT;
 210                } else {
 211                        memcpy(buf, dp, FWBUF_SIZE);
 212                }
 213                for (i = 0; i < FWBUF_SIZE; ) {
 214                        b1_put_byte(base, SEND_CONFIG);
 215                        for (j=0; j < 4; j++) {
 216                                b1_put_byte(base, buf[i++]);
 217                        }
 218                }
 219                left -= FWBUF_SIZE;
 220                dp += FWBUF_SIZE;
 221        }
 222        if (left) {
 223                if (config->user) {
 224                        if (copy_from_user(buf, dp, left))
 225                                return -EFAULT;
 226                } else {
 227                        memcpy(buf, dp, left);
 228                }
 229                for (i = 0; i < left; ) {
 230                        b1_put_byte(base, SEND_CONFIG);
 231                        for (j=0; j < 4; j++) {
 232                                if (i < left)
 233                                        b1_put_byte(base, buf[i++]);
 234                                else
 235                                        b1_put_byte(base, 0);
 236                        }
 237                }
 238        }
 239        return 0;
 240}
 241
 242int b1_loaded(avmcard *card)
 243{
 244        unsigned int base = card->port;
 245        unsigned long stop;
 246        unsigned char ans;
 247        unsigned long tout = 2;
 248
 249        for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
 250                if (b1_tx_empty(base))
 251                        break;
 252        }
 253        if (!b1_tx_empty(base)) {
 254                printk(KERN_ERR "%s: b1_loaded: tx err, corrupted t4 file ?\n",
 255                                card->name);
 256                return 0;
 257        }
 258        b1_put_byte(base, SEND_POLL);
 259        for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
 260                if (b1_rx_full(base)) {
 261                        if ((ans = b1_get_byte(base)) == RECEIVE_POLL) {
 262                                return 1;
 263                        }
 264                        printk(KERN_ERR "%s: b1_loaded: got 0x%x, firmware not running\n",
 265                                        card->name, ans);
 266                        return 0;
 267                }
 268        }
 269        printk(KERN_ERR "%s: b1_loaded: firmware not running\n", card->name);
 270        return 0;
 271}
 272
 273/* ------------------------------------------------------------- */
 274
 275int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
 276{
 277        avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
 278        avmcard *card = cinfo->card;
 279        unsigned int port = card->port;
 280        unsigned long flags;
 281        int retval;
 282
 283        b1_reset(port);
 284
 285        if ((retval = b1_load_t4file(card, &data->firmware))) {
 286                b1_reset(port);
 287                printk(KERN_ERR "%s: failed to load t4file!!\n",
 288                                        card->name);
 289                return retval;
 290        }
 291
 292        b1_disable_irq(port);
 293
 294        if (data->configuration.len > 0 && data->configuration.data) {
 295                if ((retval = b1_load_config(card, &data->configuration))) {
 296                        b1_reset(port);
 297                        printk(KERN_ERR "%s: failed to load config!!\n",
 298                                        card->name);
 299                        return retval;
 300                }
 301        }
 302
 303        if (!b1_loaded(card)) {
 304                printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
 305                return -EIO;
 306        }
 307
 308        spin_lock_irqsave(&card->lock, flags);
 309        b1_setinterrupt(port, card->irq, card->cardtype);
 310        b1_put_byte(port, SEND_INIT);
 311        b1_put_word(port, CAPI_MAXAPPL);
 312        b1_put_word(port, AVM_NCCI_PER_CHANNEL*2);
 313        b1_put_word(port, ctrl->cnr - 1);
 314        spin_unlock_irqrestore(&card->lock, flags);
 315
 316        return 0;
 317}
 318
 319void b1_reset_ctr(struct capi_ctr *ctrl)
 320{
 321        avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
 322        avmcard *card = cinfo->card;
 323        unsigned int port = card->port;
 324        unsigned long flags;
 325
 326        b1_reset(port);
 327        b1_reset(port);
 328
 329        memset(cinfo->version, 0, sizeof(cinfo->version));
 330        spin_lock_irqsave(&card->lock, flags);
 331        capilib_release(&cinfo->ncci_head);
 332        spin_unlock_irqrestore(&card->lock, flags);
 333        capi_ctr_down(ctrl);
 334}
 335
 336void b1_register_appl(struct capi_ctr *ctrl,
 337                                u16 appl,
 338                                capi_register_params *rp)
 339{
 340        avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
 341        avmcard *card = cinfo->card;
 342        unsigned int port = card->port;
 343        unsigned long flags;
 344        int nconn, want = rp->level3cnt;
 345
 346        if (want > 0) nconn = want;
 347        else nconn = ctrl->profile.nbchannel * -want;
 348        if (nconn == 0) nconn = ctrl->profile.nbchannel;
 349
 350        spin_lock_irqsave(&card->lock, flags);
 351        b1_put_byte(port, SEND_REGISTER);
 352        b1_put_word(port, appl);
 353        b1_put_word(port, 1024 * (nconn+1));
 354        b1_put_word(port, nconn);
 355        b1_put_word(port, rp->datablkcnt);
 356        b1_put_word(port, rp->datablklen);
 357        spin_unlock_irqrestore(&card->lock, flags);
 358}
 359
 360void b1_release_appl(struct capi_ctr *ctrl, u16 appl)
 361{
 362        avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
 363        avmcard *card = cinfo->card;
 364        unsigned int port = card->port;
 365        unsigned long flags;
 366
 367        spin_lock_irqsave(&card->lock, flags);
 368        capilib_release_appl(&cinfo->ncci_head, appl);
 369        b1_put_byte(port, SEND_RELEASE);
 370        b1_put_word(port, appl);
 371        spin_unlock_irqrestore(&card->lock, flags);
 372}
 373
 374u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 375{
 376        avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
 377        avmcard *card = cinfo->card;
 378        unsigned int port = card->port;
 379        unsigned long flags;
 380        u16 len = CAPIMSG_LEN(skb->data);
 381        u8 cmd = CAPIMSG_COMMAND(skb->data);
 382        u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
 383        u16 dlen, retval;
 384
 385        spin_lock_irqsave(&card->lock, flags);
 386        if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
 387                retval = capilib_data_b3_req(&cinfo->ncci_head,
 388                                             CAPIMSG_APPID(skb->data),
 389                                             CAPIMSG_NCCI(skb->data),
 390                                             CAPIMSG_MSGID(skb->data));
 391                if (retval != CAPI_NOERROR) {
 392                        spin_unlock_irqrestore(&card->lock, flags);
 393                        return retval;
 394                }
 395
 396                dlen = CAPIMSG_DATALEN(skb->data);
 397
 398                b1_put_byte(port, SEND_DATA_B3_REQ);
 399                b1_put_slice(port, skb->data, len);
 400                b1_put_slice(port, skb->data + len, dlen);
 401        } else {
 402                b1_put_byte(port, SEND_MESSAGE);
 403                b1_put_slice(port, skb->data, len);
 404        }
 405        spin_unlock_irqrestore(&card->lock, flags);
 406
 407        dev_kfree_skb_any(skb);
 408        return CAPI_NOERROR;
 409}
 410
 411/* ------------------------------------------------------------- */
 412
 413void b1_parse_version(avmctrl_info *cinfo)
 414{
 415        struct capi_ctr *ctrl = &cinfo->capi_ctrl;
 416        avmcard *card = cinfo->card;
 417        capi_profile *profp;
 418        u8 *dversion;
 419        u8 flag;
 420        int i, j;
 421
 422        for (j = 0; j < AVM_MAXVERSION; j++)
 423                cinfo->version[j] = "\0\0" + 1;
 424        for (i = 0, j = 0;
 425             j < AVM_MAXVERSION && i < cinfo->versionlen;
 426             j++, i += cinfo->versionbuf[i] + 1)
 427                cinfo->version[j] = &cinfo->versionbuf[i + 1];
 428
 429        strlcpy(ctrl->serial, cinfo->version[VER_SERIAL], sizeof(ctrl->serial));
 430        memcpy(&ctrl->profile, cinfo->version[VER_PROFILE],sizeof(capi_profile));
 431        strlcpy(ctrl->manu, "AVM GmbH", sizeof(ctrl->manu));
 432        dversion = cinfo->version[VER_DRIVER];
 433        ctrl->version.majorversion = 2;
 434        ctrl->version.minorversion = 0;
 435        ctrl->version.majormanuversion = (((dversion[0] - '0') & 0xf) << 4);
 436        ctrl->version.majormanuversion |= ((dversion[2] - '0') & 0xf);
 437        ctrl->version.minormanuversion = (dversion[3] - '0') << 4;
 438        ctrl->version.minormanuversion |=
 439                        (dversion[5] - '0') * 10 + ((dversion[6] - '0') & 0xf);
 440
 441        profp = &ctrl->profile;
 442
 443        flag = ((u8 *)(profp->manu))[1];
 444        switch (flag) {
 445        case 0: if (cinfo->version[VER_CARDTYPE])
 446                   strcpy(cinfo->cardname, cinfo->version[VER_CARDTYPE]);
 447                else strcpy(cinfo->cardname, "B1");
 448                break;
 449        case 3: strcpy(cinfo->cardname,"PCMCIA B"); break;
 450        case 4: strcpy(cinfo->cardname,"PCMCIA M1"); break;
 451        case 5: strcpy(cinfo->cardname,"PCMCIA M2"); break;
 452        case 6: strcpy(cinfo->cardname,"B1 V3.0"); break;
 453        case 7: strcpy(cinfo->cardname,"B1 PCI"); break;
 454        default: sprintf(cinfo->cardname, "AVM?%u", (unsigned int)flag); break;
 455        }
 456        printk(KERN_NOTICE "%s: card %d \"%s\" ready.\n",
 457                                card->name, ctrl->cnr, cinfo->cardname);
 458
 459        flag = ((u8 *)(profp->manu))[3];
 460        if (flag)
 461                printk(KERN_NOTICE "%s: card %d Protocol:%s%s%s%s%s%s%s\n",
 462                        card->name,
 463                        ctrl->cnr,
 464                        (flag & 0x01) ? " DSS1" : "",
 465                        (flag & 0x02) ? " CT1" : "",
 466                        (flag & 0x04) ? " VN3" : "",
 467                        (flag & 0x08) ? " NI1" : "",
 468                        (flag & 0x10) ? " AUSTEL" : "",
 469                        (flag & 0x20) ? " ESS" : "",
 470                        (flag & 0x40) ? " 1TR6" : ""
 471                        );
 472
 473        flag = ((u8 *)(profp->manu))[5];
 474        if (flag)
 475                printk(KERN_NOTICE "%s: card %d Linetype:%s%s%s%s\n",
 476                        card->name,
 477                        ctrl->cnr,
 478                        (flag & 0x01) ? " point to point" : "",
 479                        (flag & 0x02) ? " point to multipoint" : "",
 480                        (flag & 0x08) ? " leased line without D-channel" : "",
 481                        (flag & 0x04) ? " leased line with D-channel" : ""
 482                        );
 483}
 484
 485/* ------------------------------------------------------------- */
 486
 487irqreturn_t b1_interrupt(int interrupt, void *devptr)
 488{
 489        avmcard *card = devptr;
 490        avmctrl_info *cinfo = &card->ctrlinfo[0];
 491        struct capi_ctr *ctrl = &cinfo->capi_ctrl;
 492        unsigned char b1cmd;
 493        struct sk_buff *skb;
 494
 495        unsigned ApplId;
 496        unsigned MsgLen;
 497        unsigned DataB3Len;
 498        unsigned NCCI;
 499        unsigned WindowSize;
 500        unsigned long flags;
 501
 502        spin_lock_irqsave(&card->lock, flags);
 503
 504        if (!b1_rx_full(card->port)) {
 505                spin_unlock_irqrestore(&card->lock, flags);
 506                return IRQ_NONE;
 507        }
 508
 509        b1cmd = b1_get_byte(card->port);
 510
 511        switch (b1cmd) {
 512
 513        case RECEIVE_DATA_B3_IND:
 514
 515                ApplId = (unsigned) b1_get_word(card->port);
 516                MsgLen = b1_get_slice(card->port, card->msgbuf);
 517                DataB3Len = b1_get_slice(card->port, card->databuf);
 518                spin_unlock_irqrestore(&card->lock, flags);
 519
 520                if (MsgLen < 30) { /* not CAPI 64Bit */
 521                        memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
 522                        MsgLen = 30;
 523                        CAPIMSG_SETLEN(card->msgbuf, 30);
 524                }
 525                if (!(skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC))) {
 526                        printk(KERN_ERR "%s: incoming packet dropped\n",
 527                                        card->name);
 528                } else {
 529                        memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
 530                        memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
 531                        capi_ctr_handle_message(ctrl, ApplId, skb);
 532                }
 533                break;
 534
 535        case RECEIVE_MESSAGE:
 536
 537                ApplId = (unsigned) b1_get_word(card->port);
 538                MsgLen = b1_get_slice(card->port, card->msgbuf);
 539                if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
 540                        printk(KERN_ERR "%s: incoming packet dropped\n",
 541                                        card->name);
 542                        spin_unlock_irqrestore(&card->lock, flags);
 543                } else {
 544                        memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
 545                        if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF)
 546                                capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
 547                                                     CAPIMSG_NCCI(skb->data),
 548                                                     CAPIMSG_MSGID(skb->data));
 549                        spin_unlock_irqrestore(&card->lock, flags);
 550                        capi_ctr_handle_message(ctrl, ApplId, skb);
 551                }
 552                break;
 553
 554        case RECEIVE_NEW_NCCI:
 555
 556                ApplId = b1_get_word(card->port);
 557                NCCI = b1_get_word(card->port);
 558                WindowSize = b1_get_word(card->port);
 559                capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
 560                spin_unlock_irqrestore(&card->lock, flags);
 561                break;
 562
 563        case RECEIVE_FREE_NCCI:
 564
 565                ApplId = b1_get_word(card->port);
 566                NCCI = b1_get_word(card->port);
 567                if (NCCI != 0xffffffff)
 568                        capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
 569                spin_unlock_irqrestore(&card->lock, flags);
 570                break;
 571
 572        case RECEIVE_START:
 573                /* b1_put_byte(card->port, SEND_POLLACK); */
 574                spin_unlock_irqrestore(&card->lock, flags);
 575                capi_ctr_resume_output(ctrl);
 576                break;
 577
 578        case RECEIVE_STOP:
 579                spin_unlock_irqrestore(&card->lock, flags);
 580                capi_ctr_suspend_output(ctrl);
 581                break;
 582
 583        case RECEIVE_INIT:
 584
 585                cinfo->versionlen = b1_get_slice(card->port, cinfo->versionbuf);
 586                spin_unlock_irqrestore(&card->lock, flags);
 587                b1_parse_version(cinfo);
 588                printk(KERN_INFO "%s: %s-card (%s) now active\n",
 589                       card->name,
 590                       cinfo->version[VER_CARDTYPE],
 591                       cinfo->version[VER_DRIVER]);
 592                capi_ctr_ready(ctrl);
 593                break;
 594
 595        case RECEIVE_TASK_READY:
 596                ApplId = (unsigned) b1_get_word(card->port);
 597                MsgLen = b1_get_slice(card->port, card->msgbuf);
 598                spin_unlock_irqrestore(&card->lock, flags);
 599                card->msgbuf[MsgLen] = 0;
 600                while (    MsgLen > 0
 601                       && (   card->msgbuf[MsgLen-1] == '\n'
 602                           || card->msgbuf[MsgLen-1] == '\r')) {
 603                        card->msgbuf[MsgLen-1] = 0;
 604                        MsgLen--;
 605                }
 606                printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
 607                                card->name, ApplId, card->msgbuf);
 608                break;
 609
 610        case RECEIVE_DEBUGMSG:
 611                MsgLen = b1_get_slice(card->port, card->msgbuf);
 612                spin_unlock_irqrestore(&card->lock, flags);
 613                card->msgbuf[MsgLen] = 0;
 614                while (    MsgLen > 0
 615                       && (   card->msgbuf[MsgLen-1] == '\n'
 616                           || card->msgbuf[MsgLen-1] == '\r')) {
 617                        card->msgbuf[MsgLen-1] = 0;
 618                        MsgLen--;
 619                }
 620                printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
 621                break;
 622
 623        case 0xff:
 624                spin_unlock_irqrestore(&card->lock, flags);
 625                printk(KERN_ERR "%s: card removed ?\n", card->name);
 626                return IRQ_NONE;
 627        default:
 628                spin_unlock_irqrestore(&card->lock, flags);
 629                printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n",
 630                                card->name, b1cmd);
 631                return IRQ_HANDLED;
 632        }
 633        return IRQ_HANDLED;
 634}
 635
 636/* ------------------------------------------------------------- */
 637int b1ctl_read_proc(char *page, char **start, off_t off,
 638                        int count, int *eof, struct capi_ctr *ctrl)
 639{
 640        avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
 641        avmcard *card = cinfo->card;
 642        u8 flag;
 643        int len = 0;
 644        char *s;
 645
 646        len += sprintf(page+len, "%-16s %s\n", "name", card->name);
 647        len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
 648        len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
 649        switch (card->cardtype) {
 650        case avm_b1isa: s = "B1 ISA"; break;
 651        case avm_b1pci: s = "B1 PCI"; break;
 652        case avm_b1pcmcia: s = "B1 PCMCIA"; break;
 653        case avm_m1: s = "M1"; break;
 654        case avm_m2: s = "M2"; break;
 655        case avm_t1isa: s = "T1 ISA (HEMA)"; break;
 656        case avm_t1pci: s = "T1 PCI"; break;
 657        case avm_c4: s = "C4"; break;
 658        case avm_c2: s = "C2"; break;
 659        default: s = "???"; break;
 660        }
 661        len += sprintf(page+len, "%-16s %s\n", "type", s);
 662        if (card->cardtype == avm_t1isa)
 663           len += sprintf(page+len, "%-16s %d\n", "cardnr", card->cardnr);
 664        if ((s = cinfo->version[VER_DRIVER]) != NULL)
 665           len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
 666        if ((s = cinfo->version[VER_CARDTYPE]) != NULL)
 667           len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
 668        if ((s = cinfo->version[VER_SERIAL]) != NULL)
 669           len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
 670
 671        if (card->cardtype != avm_m1) {
 672                flag = ((u8 *)(ctrl->profile.manu))[3];
 673                if (flag)
 674                        len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n",
 675                        "protocol",
 676                        (flag & 0x01) ? " DSS1" : "",
 677                        (flag & 0x02) ? " CT1" : "",
 678                        (flag & 0x04) ? " VN3" : "",
 679                        (flag & 0x08) ? " NI1" : "",
 680                        (flag & 0x10) ? " AUSTEL" : "",
 681                        (flag & 0x20) ? " ESS" : "",
 682                        (flag & 0x40) ? " 1TR6" : ""
 683                        );
 684        }
 685        if (card->cardtype != avm_m1) {
 686                flag = ((u8 *)(ctrl->profile.manu))[5];
 687                if (flag)
 688                        len += sprintf(page+len, "%-16s%s%s%s%s\n",
 689                        "linetype",
 690                        (flag & 0x01) ? " point to point" : "",
 691                        (flag & 0x02) ? " point to multipoint" : "",
 692                        (flag & 0x08) ? " leased line without D-channel" : "",
 693                        (flag & 0x04) ? " leased line with D-channel" : ""
 694                        );
 695        }
 696        len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
 697
 698        if (off+count >= len)
 699           *eof = 1;
 700        if (len < off)
 701           return 0;
 702        *start = page + off;
 703        return ((count < len-off) ? count : len-off);
 704}
 705
 706/* ------------------------------------------------------------- */
 707
 708#ifdef CONFIG_PCI
 709
 710avmcard_dmainfo *
 711avmcard_dma_alloc(char *name, struct pci_dev *pdev, long rsize, long ssize)
 712{
 713        avmcard_dmainfo *p;
 714        void *buf;
 715
 716        p = kzalloc(sizeof(avmcard_dmainfo), GFP_KERNEL);
 717        if (!p) {
 718                printk(KERN_WARNING "%s: no memory.\n", name);
 719                goto err;
 720        }
 721
 722        p->recvbuf.size = rsize;
 723        buf = pci_alloc_consistent(pdev, rsize, &p->recvbuf.dmaaddr);
 724        if (!buf) {
 725                printk(KERN_WARNING "%s: allocation of receive dma buffer failed.\n", name);
 726                goto err_kfree;
 727        }
 728        p->recvbuf.dmabuf = buf;
 729
 730        p->sendbuf.size = ssize;
 731        buf = pci_alloc_consistent(pdev, ssize, &p->sendbuf.dmaaddr);
 732        if (!buf) {
 733                printk(KERN_WARNING "%s: allocation of send dma buffer failed.\n", name);
 734                goto err_free_consistent;
 735        }
 736
 737        p->sendbuf.dmabuf = buf;
 738        skb_queue_head_init(&p->send_queue);
 739
 740        return p;
 741
 742 err_free_consistent:
 743        pci_free_consistent(p->pcidev, p->recvbuf.size,
 744                            p->recvbuf.dmabuf, p->recvbuf.dmaaddr);
 745 err_kfree:
 746        kfree(p);
 747 err:
 748        return NULL;
 749}
 750
 751void avmcard_dma_free(avmcard_dmainfo *p)
 752{
 753        pci_free_consistent(p->pcidev, p->recvbuf.size,
 754                            p->recvbuf.dmabuf, p->recvbuf.dmaaddr);
 755        pci_free_consistent(p->pcidev, p->sendbuf.size,
 756                            p->sendbuf.dmabuf, p->sendbuf.dmaaddr);
 757        skb_queue_purge(&p->send_queue);
 758        kfree(p);
 759}
 760
 761EXPORT_SYMBOL(avmcard_dma_alloc);
 762EXPORT_SYMBOL(avmcard_dma_free);
 763
 764#endif
 765
 766EXPORT_SYMBOL(b1_irq_table);
 767
 768EXPORT_SYMBOL(b1_alloc_card);
 769EXPORT_SYMBOL(b1_free_card);
 770EXPORT_SYMBOL(b1_detect);
 771EXPORT_SYMBOL(b1_getrevision);
 772EXPORT_SYMBOL(b1_load_t4file);
 773EXPORT_SYMBOL(b1_load_config);
 774EXPORT_SYMBOL(b1_loaded);
 775EXPORT_SYMBOL(b1_load_firmware);
 776EXPORT_SYMBOL(b1_reset_ctr);
 777EXPORT_SYMBOL(b1_register_appl);
 778EXPORT_SYMBOL(b1_release_appl);
 779EXPORT_SYMBOL(b1_send_message);
 780
 781EXPORT_SYMBOL(b1_parse_version);
 782EXPORT_SYMBOL(b1_interrupt);
 783
 784EXPORT_SYMBOL(b1ctl_read_proc);
 785
 786static int __init b1_init(void)
 787{
 788        char *p;
 789        char rev[32];
 790
 791        if ((p = strchr(revision, ':')) != NULL && p[1]) {
 792                strlcpy(rev, p + 2, 32);
 793                if ((p = strchr(rev, '$')) != NULL && p > rev)
 794                   *(p-1) = 0;
 795        } else
 796                strcpy(rev, "1.0");
 797
 798        printk(KERN_INFO "b1: revision %s\n", rev);
 799
 800        return 0;
 801}
 802
 803static void __exit b1_exit(void)
 804{
 805}
 806
 807module_init(b1_init);
 808module_exit(b1_exit);
 809
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.