linux/drivers/isdn/hisax/elsa_ser.c
<<
>>
Prefs
   1/* $Id: elsa_ser.c,v 2.14.2.3 2004/02/11 13:21:33 keil Exp $
   2 *
   3 * stuff for the serial modem on ELSA cards
   4 *
   5 * This software may be used and distributed according to the terms
   6 * of the GNU General Public License, incorporated herein by reference.
   7 *
   8 */
   9
  10#include <linux/serial.h>
  11#include <linux/serial_reg.h>
  12#include <linux/slab.h>
  13
  14#define MAX_MODEM_BUF   256
  15#define WAKEUP_CHARS    (MAX_MODEM_BUF/2)
  16#define RS_ISR_PASS_LIMIT 256
  17#define BASE_BAUD ( 1843200 / 16 )
  18
  19//#define SERIAL_DEBUG_OPEN 1
  20//#define SERIAL_DEBUG_INTR 1
  21//#define SERIAL_DEBUG_FLOW 1
  22#undef SERIAL_DEBUG_OPEN
  23#undef SERIAL_DEBUG_INTR
  24#undef SERIAL_DEBUG_FLOW
  25#undef SERIAL_DEBUG_REG
  26//#define SERIAL_DEBUG_REG 1
  27
  28#ifdef SERIAL_DEBUG_REG
  29static u_char deb[32];
  30const char *ModemIn[] = {"RBR","IER","IIR","LCR","MCR","LSR","MSR","SCR"};
  31const char *ModemOut[] = {"THR","IER","FCR","LCR","MCR","LSR","MSR","SCR"};
  32#endif
  33
  34static char *MInit_1 = "AT&F&C1E0&D2\r\0";
  35static char *MInit_2 = "ATL2M1S64=13\r\0";
  36static char *MInit_3 = "AT+FCLASS=0\r\0";
  37static char *MInit_4 = "ATV1S2=128X1\r\0";
  38static char *MInit_5 = "AT\\V8\\N3\r\0";
  39static char *MInit_6 = "ATL0M0&G0%E1\r\0";
  40static char *MInit_7 = "AT%L1%M0%C3\r\0";
  41
  42static char *MInit_speed28800 = "AT%G0%B28800\r\0";
  43
  44static char *MInit_dialout = "ATs7=60 x1 d\r\0";
  45static char *MInit_dialin = "ATs7=60 x1 a\r\0";
  46
  47
  48static inline unsigned int serial_in(struct IsdnCardState *cs, int offset)
  49{
  50#ifdef SERIAL_DEBUG_REG
  51        u_int val = inb(cs->hw.elsa.base + 8 + offset);
  52        debugl1(cs,"in   %s %02x",ModemIn[offset], val);
  53        return(val);
  54#else
  55        return inb(cs->hw.elsa.base + 8 + offset);
  56#endif
  57}
  58
  59static inline unsigned int serial_inp(struct IsdnCardState *cs, int offset)
  60{
  61#ifdef SERIAL_DEBUG_REG
  62#ifdef ELSA_SERIAL_NOPAUSE_IO
  63        u_int val = inb(cs->hw.elsa.base + 8 + offset);
  64        debugl1(cs,"inp  %s %02x",ModemIn[offset], val);
  65#else
  66        u_int val = inb_p(cs->hw.elsa.base + 8 + offset);
  67        debugl1(cs,"inP  %s %02x",ModemIn[offset], val);
  68#endif
  69        return(val);
  70#else
  71#ifdef ELSA_SERIAL_NOPAUSE_IO
  72        return inb(cs->hw.elsa.base + 8 + offset);
  73#else
  74        return inb_p(cs->hw.elsa.base + 8 + offset);
  75#endif
  76#endif
  77}
  78
  79static inline void serial_out(struct IsdnCardState *cs, int offset, int value)
  80{
  81#ifdef SERIAL_DEBUG_REG
  82        debugl1(cs,"out  %s %02x",ModemOut[offset], value);
  83#endif
  84        outb(value, cs->hw.elsa.base + 8 + offset);
  85}
  86
  87static inline void serial_outp(struct IsdnCardState *cs, int offset,
  88                               int value)
  89{
  90#ifdef SERIAL_DEBUG_REG
  91#ifdef ELSA_SERIAL_NOPAUSE_IO
  92        debugl1(cs,"outp %s %02x",ModemOut[offset], value);
  93#else
  94        debugl1(cs,"outP %s %02x",ModemOut[offset], value);
  95#endif
  96#endif
  97#ifdef ELSA_SERIAL_NOPAUSE_IO
  98        outb(value, cs->hw.elsa.base + 8 + offset);
  99#else
 100        outb_p(value, cs->hw.elsa.base + 8 + offset);
 101#endif
 102}
 103
 104/*
 105 * This routine is called to set the UART divisor registers to match
 106 * the specified baud rate for a serial port.
 107 */
 108static void change_speed(struct IsdnCardState *cs, int baud)
 109{
 110        int     quot = 0, baud_base;
 111        unsigned cval, fcr = 0;
 112        int     bits;
 113
 114
 115        /* byte size and parity */
 116        cval = 0x03; bits = 10;
 117        /* Determine divisor based on baud rate */
 118        baud_base = BASE_BAUD;
 119        quot = baud_base / baud;
 120        /* If the quotient is ever zero, default to 9600 bps */
 121        if (!quot)
 122                quot = baud_base / 9600;
 123
 124        /* Set up FIFO's */
 125        if ((baud_base / quot) < 2400)
 126                fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
 127        else
 128                fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
 129        serial_outp(cs, UART_FCR, fcr);
 130        /* CTS flow control flag and modem status interrupts */
 131        cs->hw.elsa.IER &= ~UART_IER_MSI;
 132        cs->hw.elsa.IER |= UART_IER_MSI;
 133        serial_outp(cs, UART_IER, cs->hw.elsa.IER);
 134
 135        debugl1(cs,"modem quot=0x%x", quot);
 136        serial_outp(cs, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
 137        serial_outp(cs, UART_DLL, quot & 0xff);         /* LS of divisor */
 138        serial_outp(cs, UART_DLM, quot >> 8);           /* MS of divisor */
 139        serial_outp(cs, UART_LCR, cval);                /* reset DLAB */
 140        serial_inp(cs, UART_RX);
 141}
 142
 143static int mstartup(struct IsdnCardState *cs)
 144{
 145        int     retval=0;
 146
 147        /*
 148         * Clear the FIFO buffers and disable them
 149         * (they will be reenabled in change_speed())
 150         */
 151        serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT));
 152
 153        /*
 154         * At this point there's no way the LSR could still be 0xFF;
 155         * if it is, then bail out, because there's likely no UART
 156         * here.
 157         */
 158        if (serial_inp(cs, UART_LSR) == 0xff) {
 159                retval = -ENODEV;
 160                goto errout;
 161        }
 162        
 163        /*
 164         * Clear the interrupt registers.
 165         */
 166        (void) serial_inp(cs, UART_RX);
 167        (void) serial_inp(cs, UART_IIR);
 168        (void) serial_inp(cs, UART_MSR);
 169
 170        /*
 171         * Now, initialize the UART 
 172         */
 173        serial_outp(cs, UART_LCR, UART_LCR_WLEN8);      /* reset DLAB */
 174
 175        cs->hw.elsa.MCR = 0;
 176        cs->hw.elsa.MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
 177        serial_outp(cs, UART_MCR, cs->hw.elsa.MCR);
 178        
 179        /*
 180         * Finally, enable interrupts
 181         */
 182        cs->hw.elsa.IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
 183        serial_outp(cs, UART_IER, cs->hw.elsa.IER);     /* enable interrupts */
 184        
 185        /*
 186         * And clear the interrupt registers again for luck.
 187         */
 188        (void)serial_inp(cs, UART_LSR);
 189        (void)serial_inp(cs, UART_RX);
 190        (void)serial_inp(cs, UART_IIR);
 191        (void)serial_inp(cs, UART_MSR);
 192
 193        cs->hw.elsa.transcnt = cs->hw.elsa.transp = 0;
 194        cs->hw.elsa.rcvcnt = cs->hw.elsa.rcvp =0;
 195
 196        /*
 197         * and set the speed of the serial port
 198         */
 199        change_speed(cs, BASE_BAUD);
 200        cs->hw.elsa.MFlag = 1;
 201errout:
 202        return retval;
 203}
 204
 205/*
 206 * This routine will shutdown a serial port; interrupts are disabled, and
 207 * DTR is dropped if the hangup on close termio flag is on.
 208 */
 209static void mshutdown(struct IsdnCardState *cs)
 210{
 211
 212#ifdef SERIAL_DEBUG_OPEN
 213        printk(KERN_DEBUG"Shutting down serial ....");
 214#endif
 215        
 216        /*
 217         * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
 218         * here so the queue might never be waken up
 219         */
 220
 221        cs->hw.elsa.IER = 0;
 222        serial_outp(cs, UART_IER, 0x00);        /* disable all intrs */
 223        cs->hw.elsa.MCR &= ~UART_MCR_OUT2;
 224        
 225        /* disable break condition */
 226        serial_outp(cs, UART_LCR, serial_inp(cs, UART_LCR) & ~UART_LCR_SBC);
 227        
 228        cs->hw.elsa.MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
 229        serial_outp(cs, UART_MCR, cs->hw.elsa.MCR);
 230
 231        /* disable FIFO's */    
 232        serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT));
 233        serial_inp(cs, UART_RX);    /* read data port to reset things */
 234        
 235#ifdef SERIAL_DEBUG_OPEN
 236        printk(" done\n");
 237#endif
 238}
 239
 240static inline int
 241write_modem(struct BCState *bcs) {
 242        int ret=0;
 243        struct IsdnCardState *cs = bcs->cs;
 244        int count, len, fp;
 245        
 246        if (!bcs->tx_skb)
 247                return 0;
 248        if (bcs->tx_skb->len <= 0)
 249                return 0;
 250        len = bcs->tx_skb->len;
 251        if (len > MAX_MODEM_BUF - cs->hw.elsa.transcnt)
 252                len = MAX_MODEM_BUF - cs->hw.elsa.transcnt;
 253        fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp;
 254        fp &= (MAX_MODEM_BUF -1);
 255        count = len;
 256        if (count > MAX_MODEM_BUF - fp) {
 257                count = MAX_MODEM_BUF - fp;
 258                skb_copy_from_linear_data(bcs->tx_skb,
 259                                          cs->hw.elsa.transbuf + fp, count);
 260                skb_pull(bcs->tx_skb, count);
 261                cs->hw.elsa.transcnt += count;
 262                ret = count;
 263                count = len - count;
 264                fp = 0;
 265        }
 266        skb_copy_from_linear_data(bcs->tx_skb,
 267                                  cs->hw.elsa.transbuf + fp, count);
 268        skb_pull(bcs->tx_skb, count);
 269        cs->hw.elsa.transcnt += count;
 270        ret += count;
 271        
 272        if (cs->hw.elsa.transcnt && 
 273            !(cs->hw.elsa.IER & UART_IER_THRI)) {
 274                        cs->hw.elsa.IER |= UART_IER_THRI;
 275                serial_outp(cs, UART_IER, cs->hw.elsa.IER);
 276        }
 277        return(ret);
 278}
 279
 280static inline void
 281modem_fill(struct BCState *bcs) {
 282                
 283        if (bcs->tx_skb) {
 284                if (bcs->tx_skb->len) {
 285                        write_modem(bcs);
 286                        return;
 287                } else {
 288                        if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
 289                                (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
 290                                u_long  flags;
 291                                spin_lock_irqsave(&bcs->aclock, flags);
 292                                bcs->ackcnt += bcs->hw.hscx.count;
 293                                spin_unlock_irqrestore(&bcs->aclock, flags);
 294                                schedule_event(bcs, B_ACKPENDING);
 295                        }
 296                        dev_kfree_skb_any(bcs->tx_skb);
 297                        bcs->tx_skb = NULL;
 298                }
 299        }
 300        if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
 301                bcs->hw.hscx.count = 0;
 302                test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 303                write_modem(bcs);
 304        } else {
 305                test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 306                schedule_event(bcs, B_XMTBUFREADY);
 307        }
 308}
 309
 310static inline void receive_chars(struct IsdnCardState *cs,
 311                                 int *status)
 312{
 313        unsigned char ch;
 314        struct sk_buff *skb;
 315
 316        do {
 317                ch = serial_in(cs, UART_RX);
 318                if (cs->hw.elsa.rcvcnt >= MAX_MODEM_BUF)
 319                        break;
 320                cs->hw.elsa.rcvbuf[cs->hw.elsa.rcvcnt++] = ch;
 321#ifdef SERIAL_DEBUG_INTR
 322                printk("DR%02x:%02x...", ch, *status);
 323#endif
 324                if (*status & (UART_LSR_BI | UART_LSR_PE |
 325                               UART_LSR_FE | UART_LSR_OE)) {
 326                                        
 327#ifdef SERIAL_DEBUG_INTR
 328                        printk("handling exept....");
 329#endif
 330                }
 331                *status = serial_inp(cs, UART_LSR);
 332        } while (*status & UART_LSR_DR);
 333        if (cs->hw.elsa.MFlag == 2) {
 334                if (!(skb = dev_alloc_skb(cs->hw.elsa.rcvcnt)))
 335                        printk(KERN_WARNING "ElsaSER: receive out of memory\n");
 336                else {
 337                        memcpy(skb_put(skb, cs->hw.elsa.rcvcnt), cs->hw.elsa.rcvbuf, 
 338                                cs->hw.elsa.rcvcnt);
 339                        skb_queue_tail(& cs->hw.elsa.bcs->rqueue, skb);
 340                }
 341                schedule_event(cs->hw.elsa.bcs, B_RCVBUFREADY);
 342        } else {
 343                char tmp[128];
 344                char *t = tmp;
 345
 346                t += sprintf(t, "modem read cnt %d", cs->hw.elsa.rcvcnt);
 347                QuickHex(t, cs->hw.elsa.rcvbuf, cs->hw.elsa.rcvcnt);
 348                debugl1(cs, tmp);
 349        }
 350        cs->hw.elsa.rcvcnt = 0;
 351}
 352
 353static inline void transmit_chars(struct IsdnCardState *cs, int *intr_done)
 354{
 355        int count;
 356        
 357        debugl1(cs, "transmit_chars: p(%x) cnt(%x)", cs->hw.elsa.transp, 
 358                cs->hw.elsa.transcnt);
 359        
 360        if (cs->hw.elsa.transcnt <= 0) {
 361                cs->hw.elsa.IER &= ~UART_IER_THRI;
 362                serial_out(cs, UART_IER, cs->hw.elsa.IER);
 363                return;
 364        }
 365        count = 16;
 366        do {
 367                serial_outp(cs, UART_TX, cs->hw.elsa.transbuf[cs->hw.elsa.transp++]);
 368                if (cs->hw.elsa.transp >= MAX_MODEM_BUF)
 369                        cs->hw.elsa.transp=0;
 370                if (--cs->hw.elsa.transcnt <= 0)
 371                        break;
 372        } while (--count > 0);
 373        if ((cs->hw.elsa.transcnt < WAKEUP_CHARS) && (cs->hw.elsa.MFlag==2))
 374                modem_fill(cs->hw.elsa.bcs);
 375
 376#ifdef SERIAL_DEBUG_INTR
 377        printk("THRE...");
 378#endif
 379        if (intr_done)
 380                *intr_done = 0;
 381        if (cs->hw.elsa.transcnt <= 0) {
 382                cs->hw.elsa.IER &= ~UART_IER_THRI;
 383                serial_outp(cs, UART_IER, cs->hw.elsa.IER);
 384        }
 385}
 386
 387
 388static void rs_interrupt_elsa(struct IsdnCardState *cs)
 389{
 390        int status, iir, msr;
 391        int pass_counter = 0;
 392        
 393#ifdef SERIAL_DEBUG_INTR
 394        printk(KERN_DEBUG "rs_interrupt_single(%d)...", cs->irq);
 395#endif
 396
 397        do {
 398                status = serial_inp(cs, UART_LSR);
 399                debugl1(cs,"rs LSR %02x", status);
 400#ifdef SERIAL_DEBUG_INTR
 401                printk("status = %x...", status);
 402#endif
 403                if (status & UART_LSR_DR)
 404                        receive_chars(cs, &status);
 405                if (status & UART_LSR_THRE)
 406                        transmit_chars(cs, NULL);
 407                if (pass_counter++ > RS_ISR_PASS_LIMIT) {
 408                        printk("rs_single loop break.\n");
 409                        break;
 410                }
 411                iir = serial_inp(cs, UART_IIR);
 412                debugl1(cs,"rs IIR %02x", iir);
 413                if ((iir & 0xf) == 0) {
 414                        msr = serial_inp(cs, UART_MSR);
 415                        debugl1(cs,"rs MSR %02x", msr);
 416                }
 417        } while (!(iir & UART_IIR_NO_INT));
 418#ifdef SERIAL_DEBUG_INTR
 419        printk("end.\n");
 420#endif
 421}
 422
 423extern int open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs);
 424extern void modehscx(struct BCState *bcs, int mode, int bc);
 425extern void hscx_l2l1(struct PStack *st, int pr, void *arg);
 426
 427static void
 428close_elsastate(struct BCState *bcs)
 429{
 430        modehscx(bcs, 0, bcs->channel);
 431        if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
 432                if (bcs->hw.hscx.rcvbuf) {
 433                        if (bcs->mode != L1_MODE_MODEM)
 434                                kfree(bcs->hw.hscx.rcvbuf);
 435                        bcs->hw.hscx.rcvbuf = NULL;
 436                }
 437                skb_queue_purge(&bcs->rqueue);
 438                skb_queue_purge(&bcs->squeue);
 439                if (bcs->tx_skb) {
 440                        dev_kfree_skb_any(bcs->tx_skb);
 441                        bcs->tx_skb = NULL;
 442                        test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 443                }
 444        }
 445}
 446
 447static void
 448modem_write_cmd(struct IsdnCardState *cs, u_char *buf, int len) {
 449        int count, fp;
 450        u_char *msg = buf;
 451        
 452        if (!len)
 453                return;
 454        if (len > (MAX_MODEM_BUF - cs->hw.elsa.transcnt)) {
 455                return;
 456        }
 457        fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp;
 458        fp &= (MAX_MODEM_BUF -1);
 459        count = len;
 460        if (count > MAX_MODEM_BUF - fp) {
 461                count = MAX_MODEM_BUF - fp;
 462                memcpy(cs->hw.elsa.transbuf + fp, msg, count);
 463                cs->hw.elsa.transcnt += count;
 464                msg += count;
 465                count = len - count;
 466                fp = 0;
 467        }
 468        memcpy(cs->hw.elsa.transbuf + fp, msg, count);
 469        cs->hw.elsa.transcnt += count;
 470        if (cs->hw.elsa.transcnt && 
 471            !(cs->hw.elsa.IER & UART_IER_THRI)) {
 472                cs->hw.elsa.IER |= UART_IER_THRI;
 473                serial_outp(cs, UART_IER, cs->hw.elsa.IER);
 474        }
 475}
 476
 477static void
 478modem_set_init(struct IsdnCardState *cs) {
 479        int timeout;
 480
 481#define RCV_DELAY 20
 482        modem_write_cmd(cs, MInit_1, strlen(MInit_1));
 483        timeout = 1000;
 484        while(timeout-- && cs->hw.elsa.transcnt)
 485                udelay(1000);
 486        debugl1(cs, "msi tout=%d", timeout);
 487        mdelay(RCV_DELAY);
 488        modem_write_cmd(cs, MInit_2, strlen(MInit_2));
 489        timeout = 1000;
 490        while(timeout-- && cs->hw.elsa.transcnt)
 491                udelay(1000);
 492        debugl1(cs, "msi tout=%d", timeout);
 493        mdelay(RCV_DELAY);
 494        modem_write_cmd(cs, MInit_3, strlen(MInit_3));
 495        timeout = 1000;
 496        while(timeout-- && cs->hw.elsa.transcnt)
 497                udelay(1000);
 498        debugl1(cs, "msi tout=%d", timeout);
 499        mdelay(RCV_DELAY);
 500        modem_write_cmd(cs, MInit_4, strlen(MInit_4));
 501        timeout = 1000;
 502        while(timeout-- && cs->hw.elsa.transcnt)
 503                udelay(1000);
 504        debugl1(cs, "msi tout=%d", timeout);
 505        mdelay(RCV_DELAY);
 506        modem_write_cmd(cs, MInit_5, strlen(MInit_5));
 507        timeout = 1000;
 508        while(timeout-- && cs->hw.elsa.transcnt)
 509                udelay(1000);
 510        debugl1(cs, "msi tout=%d", timeout);
 511        mdelay(RCV_DELAY);
 512        modem_write_cmd(cs, MInit_6, strlen(MInit_6));
 513        timeout = 1000;
 514        while(timeout-- && cs->hw.elsa.transcnt)
 515                udelay(1000);
 516        debugl1(cs, "msi tout=%d", timeout);
 517        mdelay(RCV_DELAY);
 518        modem_write_cmd(cs, MInit_7, strlen(MInit_7));
 519        timeout = 1000;
 520        while(timeout-- && cs->hw.elsa.transcnt)
 521                udelay(1000);
 522        debugl1(cs, "msi tout=%d", timeout);
 523        mdelay(RCV_DELAY);
 524}
 525
 526static void
 527modem_set_dial(struct IsdnCardState *cs, int outgoing) {
 528        int timeout;
 529#define RCV_DELAY 20
 530
 531        modem_write_cmd(cs, MInit_speed28800, strlen(MInit_speed28800));
 532        timeout = 1000;
 533        while(timeout-- && cs->hw.elsa.transcnt)
 534                udelay(1000);
 535        debugl1(cs, "msi tout=%d", timeout);
 536        mdelay(RCV_DELAY);
 537        if (outgoing)
 538                modem_write_cmd(cs, MInit_dialout, strlen(MInit_dialout));
 539        else
 540                modem_write_cmd(cs, MInit_dialin, strlen(MInit_dialin));
 541        timeout = 1000;
 542        while(timeout-- && cs->hw.elsa.transcnt)
 543                udelay(1000);
 544        debugl1(cs, "msi tout=%d", timeout);
 545        mdelay(RCV_DELAY);
 546}
 547
 548static void
 549modem_l2l1(struct PStack *st, int pr, void *arg)
 550{
 551        struct BCState *bcs = st->l1.bcs;
 552        struct sk_buff *skb = arg;
 553        u_long flags;
 554
 555        if (pr == (PH_DATA | REQUEST)) {
 556                spin_lock_irqsave(&bcs->cs->lock, flags);
 557                if (bcs->tx_skb) {
 558                        skb_queue_tail(&bcs->squeue, skb);
 559                } else {
 560                        bcs->tx_skb = skb;
 561                        test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 562                        bcs->hw.hscx.count = 0;
 563                        write_modem(bcs);
 564                }
 565                spin_unlock_irqrestore(&bcs->cs->lock, flags);
 566        } else if (pr == (PH_ACTIVATE | REQUEST)) {
 567                test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
 568                st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
 569                set_arcofi(bcs->cs, st->l1.bc);
 570                mstartup(bcs->cs);
 571                modem_set_dial(bcs->cs, test_bit(FLG_ORIG, &st->l2.flag));
 572                bcs->cs->hw.elsa.MFlag=2;
 573        } else if (pr == (PH_DEACTIVATE | REQUEST)) {
 574                test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
 575                bcs->cs->dc.isac.arcofi_bc = st->l1.bc;
 576                arcofi_fsm(bcs->cs, ARCOFI_START, &ARCOFI_XOP_0);
 577                interruptible_sleep_on(&bcs->cs->dc.isac.arcofi_wait);
 578                bcs->cs->hw.elsa.MFlag=1;
 579        } else {
 580                printk(KERN_WARNING"ElsaSer: unknown pr %x\n", pr);
 581        }
 582}
 583
 584static int
 585setstack_elsa(struct PStack *st, struct BCState *bcs)
 586{
 587
 588        bcs->channel = st->l1.bc;
 589        switch (st->l1.mode) {
 590                case L1_MODE_HDLC:
 591                case L1_MODE_TRANS:
 592                        if (open_hscxstate(st->l1.hardware, bcs))
 593                                return (-1);
 594                        st->l2.l2l1 = hscx_l2l1;
 595                        break;
 596                case L1_MODE_MODEM:
 597                        bcs->mode = L1_MODE_MODEM;
 598                        if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
 599                                bcs->hw.hscx.rcvbuf = bcs->cs->hw.elsa.rcvbuf;
 600                                skb_queue_head_init(&bcs->rqueue);
 601                                skb_queue_head_init(&bcs->squeue);
 602                        }
 603                        bcs->tx_skb = NULL;
 604                        test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 605                        bcs->event = 0;
 606                        bcs->hw.hscx.rcvidx = 0;
 607                        bcs->tx_cnt = 0;
 608                        bcs->cs->hw.elsa.bcs = bcs;
 609                        st->l2.l2l1 = modem_l2l1;
 610                        break;
 611        }
 612        st->l1.bcs = bcs;
 613        setstack_manager(st);
 614        bcs->st = st;
 615        setstack_l1_B(st);
 616        return (0);
 617}
 618
 619static void
 620init_modem(struct IsdnCardState *cs) {
 621
 622        cs->bcs[0].BC_SetStack = setstack_elsa;
 623        cs->bcs[1].BC_SetStack = setstack_elsa;
 624        cs->bcs[0].BC_Close = close_elsastate;
 625        cs->bcs[1].BC_Close = close_elsastate;
 626        if (!(cs->hw.elsa.rcvbuf = kmalloc(MAX_MODEM_BUF,
 627                GFP_ATOMIC))) {
 628                printk(KERN_WARNING
 629                        "Elsa: No modem mem hw.elsa.rcvbuf\n");
 630                return;
 631        }
 632        if (!(cs->hw.elsa.transbuf = kmalloc(MAX_MODEM_BUF,
 633                GFP_ATOMIC))) {
 634                printk(KERN_WARNING
 635                        "Elsa: No modem mem hw.elsa.transbuf\n");
 636                kfree(cs->hw.elsa.rcvbuf);
 637                cs->hw.elsa.rcvbuf = NULL;
 638                return;
 639        }
 640        if (mstartup(cs)) {
 641                printk(KERN_WARNING "Elsa: problem startup modem\n");
 642        }
 643        modem_set_init(cs);
 644}
 645
 646static void
 647release_modem(struct IsdnCardState *cs) {
 648
 649        cs->hw.elsa.MFlag = 0;
 650        if (cs->hw.elsa.transbuf) {
 651                if (cs->hw.elsa.rcvbuf) {
 652                        mshutdown(cs);
 653                        kfree(cs->hw.elsa.rcvbuf);
 654                        cs->hw.elsa.rcvbuf = NULL;
 655                }
 656                kfree(cs->hw.elsa.transbuf);
 657                cs->hw.elsa.transbuf = NULL;
 658        }
 659}
 660