linux/drivers/isdn/hisax/hfc_2bs0.c
<<
>>
Prefs
   1/* $Id: hfc_2bs0.c,v 1.20.2.6 2004/02/11 13:21:33 keil Exp $
   2 *
   3 * specific routines for CCD's HFC 2BS0
   4 *
   5 * Author       Karsten Keil
   6 * Copyright    by Karsten Keil      <keil@isdn4linux.de>
   7 *
   8 * This software may be used and distributed according to the terms
   9 * of the GNU General Public License, incorporated herein by reference.
  10 *
  11 */
  12
  13#include <linux/init.h>
  14#include "hisax.h"
  15#include "hfc_2bs0.h"
  16#include "isac.h"
  17#include "isdnl1.h"
  18#include <linux/interrupt.h>
  19#include <linux/slab.h>
  20
  21static inline int
  22WaitForBusy(struct IsdnCardState *cs)
  23{
  24        int to = 130;
  25        u_char val;
  26
  27        while (!(cs->BC_Read_Reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) {
  28                val = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2 |
  29                                      (cs->hw.hfc.cip & 3));
  30                udelay(1);
  31                to--;
  32        }
  33        if (!to) {
  34                printk(KERN_WARNING "HiSax: waitforBusy timeout\n");
  35                return (0);
  36        } else
  37                return (to);
  38}
  39
  40static inline int
  41WaitNoBusy(struct IsdnCardState *cs)
  42{
  43        int to = 125;
  44
  45        while ((cs->BC_Read_Reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) {
  46                udelay(1);
  47                to--;
  48        }
  49        if (!to) {
  50                printk(KERN_WARNING "HiSax: waitforBusy timeout\n");
  51                return (0);
  52        } else
  53                return (to);
  54}
  55
  56static int
  57GetFreeFifoBytes(struct BCState *bcs)
  58{
  59        int s;
  60
  61        if (bcs->hw.hfc.f1 == bcs->hw.hfc.f2)
  62                return (bcs->cs->hw.hfc.fifosize);
  63        s = bcs->hw.hfc.send[bcs->hw.hfc.f1] - bcs->hw.hfc.send[bcs->hw.hfc.f2];
  64        if (s <= 0)
  65                s += bcs->cs->hw.hfc.fifosize;
  66        s = bcs->cs->hw.hfc.fifosize - s;
  67        return (s);
  68}
  69
  70static int
  71ReadZReg(struct BCState *bcs, u_char reg)
  72{
  73        int val;
  74
  75        WaitNoBusy(bcs->cs);
  76        val = 256 * bcs->cs->BC_Read_Reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_HIGH);
  77        WaitNoBusy(bcs->cs);
  78        val += bcs->cs->BC_Read_Reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_LOW);
  79        return (val);
  80}
  81
  82static void
  83hfc_clear_fifo(struct BCState *bcs)
  84{
  85        struct IsdnCardState *cs = bcs->cs;
  86        int idx, cnt;
  87        int rcnt, z1, z2;
  88        u_char cip, f1, f2;
  89
  90        if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
  91                debugl1(cs, "hfc_clear_fifo");
  92        cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
  93        if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
  94                cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
  95                WaitForBusy(cs);
  96        }
  97        WaitNoBusy(cs);
  98        f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
  99        cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel);
 100        WaitNoBusy(cs);
 101        f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 102        z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
 103        z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
 104        cnt = 32;
 105        while (((f1 != f2) || (z1 != z2)) && cnt--) {
 106                if (cs->debug & L1_DEB_HSCX)
 107                        debugl1(cs, "hfc clear %d f1(%d) f2(%d)",
 108                                bcs->channel, f1, f2);
 109                rcnt = z1 - z2;
 110                if (rcnt < 0)
 111                        rcnt += cs->hw.hfc.fifosize;
 112                if (rcnt)
 113                        rcnt++;
 114                if (cs->debug & L1_DEB_HSCX)
 115                        debugl1(cs, "hfc clear %d z1(%x) z2(%x) cnt(%d)",
 116                                bcs->channel, z1, z2, rcnt);
 117                cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
 118                idx = 0;
 119                while ((idx < rcnt) && WaitNoBusy(cs)) {
 120                        cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip);
 121                        idx++;
 122                }
 123                if (f1 != f2) {
 124                        WaitNoBusy(cs);
 125                        cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
 126                                        HFC_CHANNEL(bcs->channel));
 127                        WaitForBusy(cs);
 128                }
 129                cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
 130                WaitNoBusy(cs);
 131                f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 132                cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel);
 133                WaitNoBusy(cs);
 134                f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 135                z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
 136                z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
 137        }
 138        return;
 139}
 140
 141
 142static struct sk_buff
 143*
 144hfc_empty_fifo(struct BCState *bcs, int count)
 145{
 146        u_char *ptr;
 147        struct sk_buff *skb;
 148        struct IsdnCardState *cs = bcs->cs;
 149        int idx;
 150        int chksum;
 151        u_char stat, cip;
 152
 153        if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 154                debugl1(cs, "hfc_empty_fifo");
 155        idx = 0;
 156        if (count > HSCX_BUFMAX + 3) {
 157                if (cs->debug & L1_DEB_WARN)
 158                        debugl1(cs, "hfc_empty_fifo: incoming packet too large");
 159                cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
 160                while ((idx++ < count) && WaitNoBusy(cs))
 161                        cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip);
 162                WaitNoBusy(cs);
 163                stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
 164                                       HFC_CHANNEL(bcs->channel));
 165                WaitForBusy(cs);
 166                return (NULL);
 167        }
 168        if ((count < 4) && (bcs->mode != L1_MODE_TRANS)) {
 169                if (cs->debug & L1_DEB_WARN)
 170                        debugl1(cs, "hfc_empty_fifo: incoming packet too small");
 171                cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
 172                while ((idx++ < count) && WaitNoBusy(cs))
 173                        cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip);
 174                WaitNoBusy(cs);
 175                stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
 176                                       HFC_CHANNEL(bcs->channel));
 177                WaitForBusy(cs);
 178#ifdef ERROR_STATISTIC
 179                bcs->err_inv++;
 180#endif
 181                return (NULL);
 182        }
 183        if (bcs->mode == L1_MODE_TRANS)
 184                count -= 1;
 185        else
 186                count -= 3;
 187        if (!(skb = dev_alloc_skb(count)))
 188                printk(KERN_WARNING "HFC: receive out of memory\n");
 189        else {
 190                ptr = skb_put(skb, count);
 191                idx = 0;
 192                cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
 193                while ((idx < count) && WaitNoBusy(cs)) {
 194                        *ptr++ = cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip);
 195                        idx++;
 196                }
 197                if (idx != count) {
 198                        debugl1(cs, "RFIFO BUSY error");
 199                        printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel);
 200                        dev_kfree_skb_any(skb);
 201                        if (bcs->mode != L1_MODE_TRANS) {
 202                                WaitNoBusy(cs);
 203                                stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
 204                                                       HFC_CHANNEL(bcs->channel));
 205                                WaitForBusy(cs);
 206                        }
 207                        return (NULL);
 208                }
 209                if (bcs->mode != L1_MODE_TRANS) {
 210                        WaitNoBusy(cs);
 211                        chksum = (cs->BC_Read_Reg(cs, HFC_DATA, cip) << 8);
 212                        WaitNoBusy(cs);
 213                        chksum += cs->BC_Read_Reg(cs, HFC_DATA, cip);
 214                        WaitNoBusy(cs);
 215                        stat = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 216                        if (cs->debug & L1_DEB_HSCX)
 217                                debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x",
 218                                        bcs->channel, chksum, stat);
 219                        if (stat) {
 220                                debugl1(cs, "FIFO CRC error");
 221                                dev_kfree_skb_any(skb);
 222                                skb = NULL;
 223#ifdef ERROR_STATISTIC
 224                                bcs->err_crc++;
 225#endif
 226                        }
 227                        WaitNoBusy(cs);
 228                        stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
 229                                               HFC_CHANNEL(bcs->channel));
 230                        WaitForBusy(cs);
 231                }
 232        }
 233        return (skb);
 234}
 235
 236static void
 237hfc_fill_fifo(struct BCState *bcs)
 238{
 239        struct IsdnCardState *cs = bcs->cs;
 240        int idx, fcnt;
 241        int count;
 242        int z1, z2;
 243        u_char cip;
 244
 245        if (!bcs->tx_skb)
 246                return;
 247        if (bcs->tx_skb->len <= 0)
 248                return;
 249
 250        cip = HFC_CIP | HFC_F1 | HFC_SEND | HFC_CHANNEL(bcs->channel);
 251        if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
 252                cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
 253                WaitForBusy(cs);
 254        }
 255        WaitNoBusy(cs);
 256        if (bcs->mode != L1_MODE_TRANS) {
 257                bcs->hw.hfc.f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 258                cip = HFC_CIP | HFC_F2 | HFC_SEND | HFC_CHANNEL(bcs->channel);
 259                WaitNoBusy(cs);
 260                bcs->hw.hfc.f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 261                bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(bcs, HFC_Z1 | HFC_SEND | HFC_CHANNEL(bcs->channel));
 262                if (cs->debug & L1_DEB_HSCX)
 263                        debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
 264                                bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2,
 265                                bcs->hw.hfc.send[bcs->hw.hfc.f1]);
 266                fcnt = bcs->hw.hfc.f1 - bcs->hw.hfc.f2;
 267                if (fcnt < 0)
 268                        fcnt += 32;
 269                if (fcnt > 30) {
 270                        if (cs->debug & L1_DEB_HSCX)
 271                                debugl1(cs, "hfc_fill_fifo more as 30 frames");
 272                        return;
 273                }
 274                count = GetFreeFifoBytes(bcs);
 275        }
 276        else {
 277                WaitForBusy(cs);
 278                z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
 279                z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
 280                count = z1 - z2;
 281                if (count < 0)
 282                        count += cs->hw.hfc.fifosize;
 283        } /* L1_MODE_TRANS */
 284        if (cs->debug & L1_DEB_HSCX)
 285                debugl1(cs, "hfc_fill_fifo %d count(%u/%d)",
 286                        bcs->channel, bcs->tx_skb->len,
 287                        count);
 288        if (count < bcs->tx_skb->len) {
 289                if (cs->debug & L1_DEB_HSCX)
 290                        debugl1(cs, "hfc_fill_fifo no fifo mem");
 291                return;
 292        }
 293        cip = HFC_CIP | HFC_FIFO_IN | HFC_SEND | HFC_CHANNEL(bcs->channel);
 294        idx = 0;
 295        while ((idx < bcs->tx_skb->len) && WaitNoBusy(cs))
 296                cs->BC_Write_Reg(cs, HFC_DATA_NODEB, cip, bcs->tx_skb->data[idx++]);
 297        if (idx != bcs->tx_skb->len) {
 298                debugl1(cs, "FIFO Send BUSY error");
 299                printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel);
 300        } else {
 301                count =  bcs->tx_skb->len;
 302                bcs->tx_cnt -= count;
 303                if (PACKET_NOACK == bcs->tx_skb->pkt_type)
 304                        count = -1;
 305                dev_kfree_skb_any(bcs->tx_skb);
 306                bcs->tx_skb = NULL;
 307                if (bcs->mode != L1_MODE_TRANS) {
 308                        WaitForBusy(cs);
 309                        WaitNoBusy(cs);
 310                        cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F1_INC | HFC_SEND | HFC_CHANNEL(bcs->channel));
 311                }
 312                if (test_bit(FLG_LLI_L1WAKEUP, &bcs->st->lli.flag) &&
 313                    (count >= 0)) {
 314                        u_long  flags;
 315                        spin_lock_irqsave(&bcs->aclock, flags);
 316                        bcs->ackcnt += count;
 317                        spin_unlock_irqrestore(&bcs->aclock, flags);
 318                        schedule_event(bcs, B_ACKPENDING);
 319                }
 320                test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 321        }
 322        return;
 323}
 324
 325void
 326main_irq_hfc(struct BCState *bcs)
 327{
 328        struct IsdnCardState *cs = bcs->cs;
 329        int z1, z2, rcnt;
 330        u_char f1, f2, cip;
 331        int receive, transmit, count = 5;
 332        struct sk_buff *skb;
 333
 334Begin:
 335        count--;
 336        cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
 337        if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
 338                cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
 339                WaitForBusy(cs);
 340        }
 341        WaitNoBusy(cs);
 342        receive = 0;
 343        if (bcs->mode == L1_MODE_HDLC) {
 344                f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 345                cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel);
 346                WaitNoBusy(cs);
 347                f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 348                if (f1 != f2) {
 349                        if (cs->debug & L1_DEB_HSCX)
 350                                debugl1(cs, "hfc rec %d f1(%d) f2(%d)",
 351                                        bcs->channel, f1, f2);
 352                        receive = 1;
 353                }
 354        }
 355        if (receive || (bcs->mode == L1_MODE_TRANS)) {
 356                WaitForBusy(cs);
 357                z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
 358                z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
 359                rcnt = z1 - z2;
 360                if (rcnt < 0)
 361                        rcnt += cs->hw.hfc.fifosize;
 362                if ((bcs->mode == L1_MODE_HDLC) || (rcnt)) {
 363                        rcnt++;
 364                        if (cs->debug & L1_DEB_HSCX)
 365                                debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
 366                                        bcs->channel, z1, z2, rcnt);
 367                        /*              sti(); */
 368                        if ((skb = hfc_empty_fifo(bcs, rcnt))) {
 369                                skb_queue_tail(&bcs->rqueue, skb);
 370                                schedule_event(bcs, B_RCVBUFREADY);
 371                        }
 372                }
 373                receive = 1;
 374        }
 375        if (bcs->tx_skb) {
 376                transmit = 1;
 377                test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 378                hfc_fill_fifo(bcs);
 379                if (test_bit(BC_FLG_BUSY, &bcs->Flag))
 380                        transmit = 0;
 381        } else {
 382                if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
 383                        transmit = 1;
 384                        test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 385                        hfc_fill_fifo(bcs);
 386                        if (test_bit(BC_FLG_BUSY, &bcs->Flag))
 387                                transmit = 0;
 388                } else {
 389                        transmit = 0;
 390                        schedule_event(bcs, B_XMTBUFREADY);
 391                }
 392        }
 393        if ((receive || transmit) && count)
 394                goto Begin;
 395        return;
 396}
 397
 398static void
 399mode_hfc(struct BCState *bcs, int mode, int bc)
 400{
 401        struct IsdnCardState *cs = bcs->cs;
 402
 403        if (cs->debug & L1_DEB_HSCX)
 404                debugl1(cs, "HFC 2BS0 mode %d bchan %d/%d",
 405                        mode, bc, bcs->channel);
 406        bcs->mode = mode;
 407        bcs->channel = bc;
 408
 409        switch (mode) {
 410        case (L1_MODE_NULL):
 411                if (bc) {
 412                        cs->hw.hfc.ctmt &= ~1;
 413                        cs->hw.hfc.isac_spcr &= ~0x03;
 414                }
 415                else {
 416                        cs->hw.hfc.ctmt &= ~2;
 417                        cs->hw.hfc.isac_spcr &= ~0x0c;
 418                }
 419                break;
 420        case (L1_MODE_TRANS):
 421                cs->hw.hfc.ctmt &= ~(1 << bc); /* set HDLC mode */
 422                cs->BC_Write_Reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt);
 423                hfc_clear_fifo(bcs); /* complete fifo clear */
 424                if (bc) {
 425                        cs->hw.hfc.ctmt |= 1;
 426                        cs->hw.hfc.isac_spcr &= ~0x03;
 427                        cs->hw.hfc.isac_spcr |= 0x02;
 428                } else {
 429                        cs->hw.hfc.ctmt |= 2;
 430                        cs->hw.hfc.isac_spcr &= ~0x0c;
 431                        cs->hw.hfc.isac_spcr |= 0x08;
 432                }
 433                break;
 434        case (L1_MODE_HDLC):
 435                if (bc) {
 436                        cs->hw.hfc.ctmt &= ~1;
 437                        cs->hw.hfc.isac_spcr &= ~0x03;
 438                        cs->hw.hfc.isac_spcr |= 0x02;
 439                } else {
 440                        cs->hw.hfc.ctmt &= ~2;
 441                        cs->hw.hfc.isac_spcr &= ~0x0c;
 442                        cs->hw.hfc.isac_spcr |= 0x08;
 443                }
 444                break;
 445        }
 446        cs->BC_Write_Reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt);
 447        cs->writeisac(cs, ISAC_SPCR, cs->hw.hfc.isac_spcr);
 448        if (mode == L1_MODE_HDLC)
 449                hfc_clear_fifo(bcs);
 450}
 451
 452static void
 453hfc_l2l1(struct PStack *st, int pr, void *arg)
 454{
 455        struct BCState  *bcs = st->l1.bcs;
 456        struct sk_buff  *skb = arg;
 457        u_long          flags;
 458
 459        switch (pr) {
 460        case (PH_DATA | REQUEST):
 461                spin_lock_irqsave(&bcs->cs->lock, flags);
 462                if (bcs->tx_skb) {
 463                        skb_queue_tail(&bcs->squeue, skb);
 464                } else {
 465                        bcs->tx_skb = skb;
 466                        test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 467                        bcs->cs->BC_Send_Data(bcs);
 468                }
 469                spin_unlock_irqrestore(&bcs->cs->lock, flags);
 470                break;
 471        case (PH_PULL | INDICATION):
 472                spin_lock_irqsave(&bcs->cs->lock, flags);
 473                if (bcs->tx_skb) {
 474                        printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
 475                } else {
 476                        test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 477                        bcs->tx_skb = skb;
 478                        bcs->cs->BC_Send_Data(bcs);
 479                }
 480                spin_unlock_irqrestore(&bcs->cs->lock, flags);
 481                break;
 482        case (PH_PULL | REQUEST):
 483                if (!bcs->tx_skb) {
 484                        test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 485                        st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 486                } else
 487                        test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 488                break;
 489        case (PH_ACTIVATE | REQUEST):
 490                spin_lock_irqsave(&bcs->cs->lock, flags);
 491                test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
 492                mode_hfc(bcs, st->l1.mode, st->l1.bc);
 493                spin_unlock_irqrestore(&bcs->cs->lock, flags);
 494                l1_msg_b(st, pr, arg);
 495                break;
 496        case (PH_DEACTIVATE | REQUEST):
 497                l1_msg_b(st, pr, arg);
 498                break;
 499        case (PH_DEACTIVATE | CONFIRM):
 500                spin_lock_irqsave(&bcs->cs->lock, flags);
 501                test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
 502                test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 503                mode_hfc(bcs, 0, st->l1.bc);
 504                spin_unlock_irqrestore(&bcs->cs->lock, flags);
 505                st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
 506                break;
 507        }
 508}
 509
 510
 511static void
 512close_hfcstate(struct BCState *bcs)
 513{
 514        mode_hfc(bcs, 0, bcs->channel);
 515        if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
 516                skb_queue_purge(&bcs->rqueue);
 517                skb_queue_purge(&bcs->squeue);
 518                if (bcs->tx_skb) {
 519                        dev_kfree_skb_any(bcs->tx_skb);
 520                        bcs->tx_skb = NULL;
 521                        test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 522                }
 523        }
 524        test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
 525}
 526
 527static int
 528open_hfcstate(struct IsdnCardState *cs, struct BCState *bcs)
 529{
 530        if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
 531                skb_queue_head_init(&bcs->rqueue);
 532                skb_queue_head_init(&bcs->squeue);
 533        }
 534        bcs->tx_skb = NULL;
 535        test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 536        bcs->event = 0;
 537        bcs->tx_cnt = 0;
 538        return (0);
 539}
 540
 541static int
 542setstack_hfc(struct PStack *st, struct BCState *bcs)
 543{
 544        bcs->channel = st->l1.bc;
 545        if (open_hfcstate(st->l1.hardware, bcs))
 546                return (-1);
 547        st->l1.bcs = bcs;
 548        st->l2.l2l1 = hfc_l2l1;
 549        setstack_manager(st);
 550        bcs->st = st;
 551        setstack_l1_B(st);
 552        return (0);
 553}
 554
 555static void
 556init_send(struct BCState *bcs)
 557{
 558        int i;
 559
 560        if (!(bcs->hw.hfc.send = kmalloc(32 * sizeof(unsigned int), GFP_ATOMIC))) {
 561                printk(KERN_WARNING
 562                       "HiSax: No memory for hfc.send\n");
 563                return;
 564        }
 565        for (i = 0; i < 32; i++)
 566                bcs->hw.hfc.send[i] = 0x1fff;
 567}
 568
 569void
 570inithfc(struct IsdnCardState *cs)
 571{
 572        init_send(&cs->bcs[0]);
 573        init_send(&cs->bcs[1]);
 574        cs->BC_Send_Data = &hfc_fill_fifo;
 575        cs->bcs[0].BC_SetStack = setstack_hfc;
 576        cs->bcs[1].BC_SetStack = setstack_hfc;
 577        cs->bcs[0].BC_Close = close_hfcstate;
 578        cs->bcs[1].BC_Close = close_hfcstate;
 579        mode_hfc(cs->bcs, 0, 0);
 580        mode_hfc(cs->bcs + 1, 0, 0);
 581}
 582
 583void
 584releasehfc(struct IsdnCardState *cs)
 585{
 586        kfree(cs->bcs[0].hw.hfc.send);
 587        cs->bcs[0].hw.hfc.send = NULL;
 588        kfree(cs->bcs[1].hw.hfc.send);
 589        cs->bcs[1].hw.hfc.send = NULL;
 590}
 591