linux/drivers/isdn/hardware/mISDN/mISDNipac.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * isac.c   ISAC specific routines
   4 *
   5 * Author       Karsten Keil <keil@isdn4linux.de>
   6 *
   7 * Copyright 2009  by Karsten Keil <keil@isdn4linux.de>
   8 */
   9
  10#include <linux/irqreturn.h>
  11#include <linux/slab.h>
  12#include <linux/module.h>
  13#include <linux/mISDNhw.h>
  14#include "ipac.h"
  15
  16
  17#define DBUSY_TIMER_VALUE       80
  18#define ARCOFI_USE              1
  19
  20#define ISAC_REV                "2.0"
  21
  22MODULE_AUTHOR("Karsten Keil");
  23MODULE_VERSION(ISAC_REV);
  24MODULE_LICENSE("GPL v2");
  25
  26#define ReadISAC(is, o)         (is->read_reg(is->dch.hw, o + is->off))
  27#define WriteISAC(is, o, v)     (is->write_reg(is->dch.hw, o + is->off, v))
  28#define ReadHSCX(h, o)          (h->ip->read_reg(h->ip->hw, h->off + o))
  29#define WriteHSCX(h, o, v)      (h->ip->write_reg(h->ip->hw, h->off + o, v))
  30#define ReadIPAC(ip, o)         (ip->read_reg(ip->hw, o))
  31#define WriteIPAC(ip, o, v)     (ip->write_reg(ip->hw, o, v))
  32
  33static inline void
  34ph_command(struct isac_hw *isac, u8 command)
  35{
  36        pr_debug("%s: ph_command %x\n", isac->name, command);
  37        if (isac->type & IPAC_TYPE_ISACX)
  38                WriteISAC(isac, ISACX_CIX0, (command << 4) | 0xE);
  39        else
  40                WriteISAC(isac, ISAC_CIX0, (command << 2) | 3);
  41}
  42
  43static void
  44isac_ph_state_change(struct isac_hw *isac)
  45{
  46        switch (isac->state) {
  47        case (ISAC_IND_RS):
  48        case (ISAC_IND_EI):
  49                ph_command(isac, ISAC_CMD_DUI);
  50        }
  51        schedule_event(&isac->dch, FLG_PHCHANGE);
  52}
  53
  54static void
  55isac_ph_state_bh(struct dchannel *dch)
  56{
  57        struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
  58
  59        switch (isac->state) {
  60        case ISAC_IND_RS:
  61        case ISAC_IND_EI:
  62                dch->state = 0;
  63                l1_event(dch->l1, HW_RESET_IND);
  64                break;
  65        case ISAC_IND_DID:
  66                dch->state = 3;
  67                l1_event(dch->l1, HW_DEACT_CNF);
  68                break;
  69        case ISAC_IND_DR:
  70        case ISAC_IND_DR6:
  71                dch->state = 3;
  72                l1_event(dch->l1, HW_DEACT_IND);
  73                break;
  74        case ISAC_IND_PU:
  75                dch->state = 4;
  76                l1_event(dch->l1, HW_POWERUP_IND);
  77                break;
  78        case ISAC_IND_RSY:
  79                if (dch->state <= 5) {
  80                        dch->state = 5;
  81                        l1_event(dch->l1, ANYSIGNAL);
  82                } else {
  83                        dch->state = 8;
  84                        l1_event(dch->l1, LOSTFRAMING);
  85                }
  86                break;
  87        case ISAC_IND_ARD:
  88                dch->state = 6;
  89                l1_event(dch->l1, INFO2);
  90                break;
  91        case ISAC_IND_AI8:
  92                dch->state = 7;
  93                l1_event(dch->l1, INFO4_P8);
  94                break;
  95        case ISAC_IND_AI10:
  96                dch->state = 7;
  97                l1_event(dch->l1, INFO4_P10);
  98                break;
  99        }
 100        pr_debug("%s: TE newstate %x\n", isac->name, dch->state);
 101}
 102
 103static void
 104isac_empty_fifo(struct isac_hw *isac, int count)
 105{
 106        u8 *ptr;
 107
 108        pr_debug("%s: %s  %d\n", isac->name, __func__, count);
 109
 110        if (!isac->dch.rx_skb) {
 111                isac->dch.rx_skb = mI_alloc_skb(isac->dch.maxlen, GFP_ATOMIC);
 112                if (!isac->dch.rx_skb) {
 113                        pr_info("%s: D receive out of memory\n", isac->name);
 114                        WriteISAC(isac, ISAC_CMDR, 0x80);
 115                        return;
 116                }
 117        }
 118        if ((isac->dch.rx_skb->len + count) >= isac->dch.maxlen) {
 119                pr_debug("%s: %s overrun %d\n", isac->name, __func__,
 120                         isac->dch.rx_skb->len + count);
 121                WriteISAC(isac, ISAC_CMDR, 0x80);
 122                return;
 123        }
 124        ptr = skb_put(isac->dch.rx_skb, count);
 125        isac->read_fifo(isac->dch.hw, isac->off, ptr, count);
 126        WriteISAC(isac, ISAC_CMDR, 0x80);
 127        if (isac->dch.debug & DEBUG_HW_DFIFO) {
 128                char    pfx[MISDN_MAX_IDLEN + 16];
 129
 130                snprintf(pfx, MISDN_MAX_IDLEN + 15, "D-recv %s %d ",
 131                         isac->name, count);
 132                print_hex_dump_bytes(pfx, DUMP_PREFIX_OFFSET, ptr, count);
 133        }
 134}
 135
 136static void
 137isac_fill_fifo(struct isac_hw *isac)
 138{
 139        int count, more;
 140        u8 *ptr;
 141
 142        if (!isac->dch.tx_skb)
 143                return;
 144        count = isac->dch.tx_skb->len - isac->dch.tx_idx;
 145        if (count <= 0)
 146                return;
 147
 148        more = 0;
 149        if (count > 32) {
 150                more = !0;
 151                count = 32;
 152        }
 153        pr_debug("%s: %s  %d\n", isac->name, __func__, count);
 154        ptr = isac->dch.tx_skb->data + isac->dch.tx_idx;
 155        isac->dch.tx_idx += count;
 156        isac->write_fifo(isac->dch.hw, isac->off, ptr, count);
 157        WriteISAC(isac, ISAC_CMDR, more ? 0x8 : 0xa);
 158        if (test_and_set_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) {
 159                pr_debug("%s: %s dbusytimer running\n", isac->name, __func__);
 160                del_timer(&isac->dch.timer);
 161        }
 162        isac->dch.timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
 163        add_timer(&isac->dch.timer);
 164        if (isac->dch.debug & DEBUG_HW_DFIFO) {
 165                char    pfx[MISDN_MAX_IDLEN + 16];
 166
 167                snprintf(pfx, MISDN_MAX_IDLEN + 15, "D-send %s %d ",
 168                         isac->name, count);
 169                print_hex_dump_bytes(pfx, DUMP_PREFIX_OFFSET, ptr, count);
 170        }
 171}
 172
 173static void
 174isac_rme_irq(struct isac_hw *isac)
 175{
 176        u8 val, count;
 177
 178        val = ReadISAC(isac, ISAC_RSTA);
 179        if ((val & 0x70) != 0x20) {
 180                if (val & 0x40) {
 181                        pr_debug("%s: ISAC RDO\n", isac->name);
 182#ifdef ERROR_STATISTIC
 183                        isac->dch.err_rx++;
 184#endif
 185                }
 186                if (!(val & 0x20)) {
 187                        pr_debug("%s: ISAC CRC error\n", isac->name);
 188#ifdef ERROR_STATISTIC
 189                        isac->dch.err_crc++;
 190#endif
 191                }
 192                WriteISAC(isac, ISAC_CMDR, 0x80);
 193                dev_kfree_skb(isac->dch.rx_skb);
 194                isac->dch.rx_skb = NULL;
 195        } else {
 196                count = ReadISAC(isac, ISAC_RBCL) & 0x1f;
 197                if (count == 0)
 198                        count = 32;
 199                isac_empty_fifo(isac, count);
 200                recv_Dchannel(&isac->dch);
 201        }
 202}
 203
 204static void
 205isac_xpr_irq(struct isac_hw *isac)
 206{
 207        if (test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags))
 208                del_timer(&isac->dch.timer);
 209        if (isac->dch.tx_skb && isac->dch.tx_idx < isac->dch.tx_skb->len) {
 210                isac_fill_fifo(isac);
 211        } else {
 212                dev_kfree_skb(isac->dch.tx_skb);
 213                if (get_next_dframe(&isac->dch))
 214                        isac_fill_fifo(isac);
 215        }
 216}
 217
 218static void
 219isac_retransmit(struct isac_hw *isac)
 220{
 221        if (test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags))
 222                del_timer(&isac->dch.timer);
 223        if (test_bit(FLG_TX_BUSY, &isac->dch.Flags)) {
 224                /* Restart frame */
 225                isac->dch.tx_idx = 0;
 226                isac_fill_fifo(isac);
 227        } else if (isac->dch.tx_skb) { /* should not happen */
 228                pr_info("%s: tx_skb exist but not busy\n", isac->name);
 229                test_and_set_bit(FLG_TX_BUSY, &isac->dch.Flags);
 230                isac->dch.tx_idx = 0;
 231                isac_fill_fifo(isac);
 232        } else {
 233                pr_info("%s: ISAC XDU no TX_BUSY\n", isac->name);
 234                if (get_next_dframe(&isac->dch))
 235                        isac_fill_fifo(isac);
 236        }
 237}
 238
 239static void
 240isac_mos_irq(struct isac_hw *isac)
 241{
 242        u8 val;
 243        int ret;
 244
 245        val = ReadISAC(isac, ISAC_MOSR);
 246        pr_debug("%s: ISAC MOSR %02x\n", isac->name, val);
 247#if ARCOFI_USE
 248        if (val & 0x08) {
 249                if (!isac->mon_rx) {
 250                        isac->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC);
 251                        if (!isac->mon_rx) {
 252                                pr_info("%s: ISAC MON RX out of memory!\n",
 253                                        isac->name);
 254                                isac->mocr &= 0xf0;
 255                                isac->mocr |= 0x0a;
 256                                WriteISAC(isac, ISAC_MOCR, isac->mocr);
 257                                goto afterMONR0;
 258                        } else
 259                                isac->mon_rxp = 0;
 260                }
 261                if (isac->mon_rxp >= MAX_MON_FRAME) {
 262                        isac->mocr &= 0xf0;
 263                        isac->mocr |= 0x0a;
 264                        WriteISAC(isac, ISAC_MOCR, isac->mocr);
 265                        isac->mon_rxp = 0;
 266                        pr_debug("%s: ISAC MON RX overflow!\n", isac->name);
 267                        goto afterMONR0;
 268                }
 269                isac->mon_rx[isac->mon_rxp++] = ReadISAC(isac, ISAC_MOR0);
 270                pr_debug("%s: ISAC MOR0 %02x\n", isac->name,
 271                         isac->mon_rx[isac->mon_rxp - 1]);
 272                if (isac->mon_rxp == 1) {
 273                        isac->mocr |= 0x04;
 274                        WriteISAC(isac, ISAC_MOCR, isac->mocr);
 275                }
 276        }
 277afterMONR0:
 278        if (val & 0x80) {
 279                if (!isac->mon_rx) {
 280                        isac->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC);
 281                        if (!isac->mon_rx) {
 282                                pr_info("%s: ISAC MON RX out of memory!\n",
 283                                        isac->name);
 284                                isac->mocr &= 0x0f;
 285                                isac->mocr |= 0xa0;
 286                                WriteISAC(isac, ISAC_MOCR, isac->mocr);
 287                                goto afterMONR1;
 288                        } else
 289                                isac->mon_rxp = 0;
 290                }
 291                if (isac->mon_rxp >= MAX_MON_FRAME) {
 292                        isac->mocr &= 0x0f;
 293                        isac->mocr |= 0xa0;
 294                        WriteISAC(isac, ISAC_MOCR, isac->mocr);
 295                        isac->mon_rxp = 0;
 296                        pr_debug("%s: ISAC MON RX overflow!\n", isac->name);
 297                        goto afterMONR1;
 298                }
 299                isac->mon_rx[isac->mon_rxp++] = ReadISAC(isac, ISAC_MOR1);
 300                pr_debug("%s: ISAC MOR1 %02x\n", isac->name,
 301                         isac->mon_rx[isac->mon_rxp - 1]);
 302                isac->mocr |= 0x40;
 303                WriteISAC(isac, ISAC_MOCR, isac->mocr);
 304        }
 305afterMONR1:
 306        if (val & 0x04) {
 307                isac->mocr &= 0xf0;
 308                WriteISAC(isac, ISAC_MOCR, isac->mocr);
 309                isac->mocr |= 0x0a;
 310                WriteISAC(isac, ISAC_MOCR, isac->mocr);
 311                if (isac->monitor) {
 312                        ret = isac->monitor(isac->dch.hw, MONITOR_RX_0,
 313                                            isac->mon_rx, isac->mon_rxp);
 314                        if (ret)
 315                                kfree(isac->mon_rx);
 316                } else {
 317                        pr_info("%s: MONITOR 0 received %d but no user\n",
 318                                isac->name, isac->mon_rxp);
 319                        kfree(isac->mon_rx);
 320                }
 321                isac->mon_rx = NULL;
 322                isac->mon_rxp = 0;
 323        }
 324        if (val & 0x40) {
 325                isac->mocr &= 0x0f;
 326                WriteISAC(isac, ISAC_MOCR, isac->mocr);
 327                isac->mocr |= 0xa0;
 328                WriteISAC(isac, ISAC_MOCR, isac->mocr);
 329                if (isac->monitor) {
 330                        ret = isac->monitor(isac->dch.hw, MONITOR_RX_1,
 331                                            isac->mon_rx, isac->mon_rxp);
 332                        if (ret)
 333                                kfree(isac->mon_rx);
 334                } else {
 335                        pr_info("%s: MONITOR 1 received %d but no user\n",
 336                                isac->name, isac->mon_rxp);
 337                        kfree(isac->mon_rx);
 338                }
 339                isac->mon_rx = NULL;
 340                isac->mon_rxp = 0;
 341        }
 342        if (val & 0x02) {
 343                if ((!isac->mon_tx) || (isac->mon_txc &&
 344                                        (isac->mon_txp >= isac->mon_txc) && !(val & 0x08))) {
 345                        isac->mocr &= 0xf0;
 346                        WriteISAC(isac, ISAC_MOCR, isac->mocr);
 347                        isac->mocr |= 0x0a;
 348                        WriteISAC(isac, ISAC_MOCR, isac->mocr);
 349                        if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
 350                                if (isac->monitor)
 351                                        isac->monitor(isac->dch.hw,
 352                                                      MONITOR_TX_0, NULL, 0);
 353                        }
 354                        kfree(isac->mon_tx);
 355                        isac->mon_tx = NULL;
 356                        isac->mon_txc = 0;
 357                        isac->mon_txp = 0;
 358                        goto AfterMOX0;
 359                }
 360                if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
 361                        if (isac->monitor)
 362                                isac->monitor(isac->dch.hw,
 363                                              MONITOR_TX_0, NULL, 0);
 364                        kfree(isac->mon_tx);
 365                        isac->mon_tx = NULL;
 366                        isac->mon_txc = 0;
 367                        isac->mon_txp = 0;
 368                        goto AfterMOX0;
 369                }
 370                WriteISAC(isac, ISAC_MOX0, isac->mon_tx[isac->mon_txp++]);
 371                pr_debug("%s: ISAC %02x -> MOX0\n", isac->name,
 372                         isac->mon_tx[isac->mon_txp - 1]);
 373        }
 374AfterMOX0:
 375        if (val & 0x20) {
 376                if ((!isac->mon_tx) || (isac->mon_txc &&
 377                                        (isac->mon_txp >= isac->mon_txc) && !(val & 0x80))) {
 378                        isac->mocr &= 0x0f;
 379                        WriteISAC(isac, ISAC_MOCR, isac->mocr);
 380                        isac->mocr |= 0xa0;
 381                        WriteISAC(isac, ISAC_MOCR, isac->mocr);
 382                        if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
 383                                if (isac->monitor)
 384                                        isac->monitor(isac->dch.hw,
 385                                                      MONITOR_TX_1, NULL, 0);
 386                        }
 387                        kfree(isac->mon_tx);
 388                        isac->mon_tx = NULL;
 389                        isac->mon_txc = 0;
 390                        isac->mon_txp = 0;
 391                        goto AfterMOX1;
 392                }
 393                if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
 394                        if (isac->monitor)
 395                                isac->monitor(isac->dch.hw,
 396                                              MONITOR_TX_1, NULL, 0);
 397                        kfree(isac->mon_tx);
 398                        isac->mon_tx = NULL;
 399                        isac->mon_txc = 0;
 400                        isac->mon_txp = 0;
 401                        goto AfterMOX1;
 402                }
 403                WriteISAC(isac, ISAC_MOX1, isac->mon_tx[isac->mon_txp++]);
 404                pr_debug("%s: ISAC %02x -> MOX1\n", isac->name,
 405                         isac->mon_tx[isac->mon_txp - 1]);
 406        }
 407AfterMOX1:
 408        val = 0; /* dummy to avoid warning */
 409#endif
 410}
 411
 412static void
 413isac_cisq_irq(struct isac_hw *isac) {
 414        u8 val;
 415
 416        val = ReadISAC(isac, ISAC_CIR0);
 417        pr_debug("%s: ISAC CIR0 %02X\n", isac->name, val);
 418        if (val & 2) {
 419                pr_debug("%s: ph_state change %x->%x\n", isac->name,
 420                         isac->state, (val >> 2) & 0xf);
 421                isac->state = (val >> 2) & 0xf;
 422                isac_ph_state_change(isac);
 423        }
 424        if (val & 1) {
 425                val = ReadISAC(isac, ISAC_CIR1);
 426                pr_debug("%s: ISAC CIR1 %02X\n", isac->name, val);
 427        }
 428}
 429
 430static void
 431isacsx_cic_irq(struct isac_hw *isac)
 432{
 433        u8 val;
 434
 435        val = ReadISAC(isac, ISACX_CIR0);
 436        pr_debug("%s: ISACX CIR0 %02X\n", isac->name, val);
 437        if (val & ISACX_CIR0_CIC0) {
 438                pr_debug("%s: ph_state change %x->%x\n", isac->name,
 439                         isac->state, val >> 4);
 440                isac->state = val >> 4;
 441                isac_ph_state_change(isac);
 442        }
 443}
 444
 445static void
 446isacsx_rme_irq(struct isac_hw *isac)
 447{
 448        int count;
 449        u8 val;
 450
 451        val = ReadISAC(isac, ISACX_RSTAD);
 452        if ((val & (ISACX_RSTAD_VFR |
 453                    ISACX_RSTAD_RDO |
 454                    ISACX_RSTAD_CRC |
 455                    ISACX_RSTAD_RAB))
 456            != (ISACX_RSTAD_VFR | ISACX_RSTAD_CRC)) {
 457                pr_debug("%s: RSTAD %#x, dropped\n", isac->name, val);
 458#ifdef ERROR_STATISTIC
 459                if (val & ISACX_RSTAD_CRC)
 460                        isac->dch.err_rx++;
 461                else
 462                        isac->dch.err_crc++;
 463#endif
 464                WriteISAC(isac, ISACX_CMDRD, ISACX_CMDRD_RMC);
 465                dev_kfree_skb(isac->dch.rx_skb);
 466                isac->dch.rx_skb = NULL;
 467        } else {
 468                count = ReadISAC(isac, ISACX_RBCLD) & 0x1f;
 469                if (count == 0)
 470                        count = 32;
 471                isac_empty_fifo(isac, count);
 472                if (isac->dch.rx_skb) {
 473                        skb_trim(isac->dch.rx_skb, isac->dch.rx_skb->len - 1);
 474                        pr_debug("%s: dchannel received %d\n", isac->name,
 475                                 isac->dch.rx_skb->len);
 476                        recv_Dchannel(&isac->dch);
 477                }
 478        }
 479}
 480
 481irqreturn_t
 482mISDNisac_irq(struct isac_hw *isac, u8 val)
 483{
 484        if (unlikely(!val))
 485                return IRQ_NONE;
 486        pr_debug("%s: ISAC interrupt %02x\n", isac->name, val);
 487        if (isac->type & IPAC_TYPE_ISACX) {
 488                if (val & ISACX__CIC)
 489                        isacsx_cic_irq(isac);
 490                if (val & ISACX__ICD) {
 491                        val = ReadISAC(isac, ISACX_ISTAD);
 492                        pr_debug("%s: ISTAD %02x\n", isac->name, val);
 493                        if (val & ISACX_D_XDU) {
 494                                pr_debug("%s: ISAC XDU\n", isac->name);
 495#ifdef ERROR_STATISTIC
 496                                isac->dch.err_tx++;
 497#endif
 498                                isac_retransmit(isac);
 499                        }
 500                        if (val & ISACX_D_XMR) {
 501                                pr_debug("%s: ISAC XMR\n", isac->name);
 502#ifdef ERROR_STATISTIC
 503                                isac->dch.err_tx++;
 504#endif
 505                                isac_retransmit(isac);
 506                        }
 507                        if (val & ISACX_D_XPR)
 508                                isac_xpr_irq(isac);
 509                        if (val & ISACX_D_RFO) {
 510                                pr_debug("%s: ISAC RFO\n", isac->name);
 511                                WriteISAC(isac, ISACX_CMDRD, ISACX_CMDRD_RMC);
 512                        }
 513                        if (val & ISACX_D_RME)
 514                                isacsx_rme_irq(isac);
 515                        if (val & ISACX_D_RPF)
 516                                isac_empty_fifo(isac, 0x20);
 517                }
 518        } else {
 519                if (val & 0x80) /* RME */
 520                        isac_rme_irq(isac);
 521                if (val & 0x40) /* RPF */
 522                        isac_empty_fifo(isac, 32);
 523                if (val & 0x10) /* XPR */
 524                        isac_xpr_irq(isac);
 525                if (val & 0x04) /* CISQ */
 526                        isac_cisq_irq(isac);
 527                if (val & 0x20) /* RSC - never */
 528                        pr_debug("%s: ISAC RSC interrupt\n", isac->name);
 529                if (val & 0x02) /* SIN - never */
 530                        pr_debug("%s: ISAC SIN interrupt\n", isac->name);
 531                if (val & 0x01) {       /* EXI */
 532                        val = ReadISAC(isac, ISAC_EXIR);
 533                        pr_debug("%s: ISAC EXIR %02x\n", isac->name, val);
 534                        if (val & 0x80) /* XMR */
 535                                pr_debug("%s: ISAC XMR\n", isac->name);
 536                        if (val & 0x40) { /* XDU */
 537                                pr_debug("%s: ISAC XDU\n", isac->name);
 538#ifdef ERROR_STATISTIC
 539                                isac->dch.err_tx++;
 540#endif
 541                                isac_retransmit(isac);
 542                        }
 543                        if (val & 0x04) /* MOS */
 544                                isac_mos_irq(isac);
 545                }
 546        }
 547        return IRQ_HANDLED;
 548}
 549EXPORT_SYMBOL(mISDNisac_irq);
 550
 551static int
 552isac_l1hw(struct mISDNchannel *ch, struct sk_buff *skb)
 553{
 554        struct mISDNdevice      *dev = container_of(ch, struct mISDNdevice, D);
 555        struct dchannel         *dch = container_of(dev, struct dchannel, dev);
 556        struct isac_hw          *isac = container_of(dch, struct isac_hw, dch);
 557        int                     ret = -EINVAL;
 558        struct mISDNhead        *hh = mISDN_HEAD_P(skb);
 559        u32                     id;
 560        u_long                  flags;
 561
 562        switch (hh->prim) {
 563        case PH_DATA_REQ:
 564                spin_lock_irqsave(isac->hwlock, flags);
 565                ret = dchannel_senddata(dch, skb);
 566                if (ret > 0) { /* direct TX */
 567                        id = hh->id; /* skb can be freed */
 568                        isac_fill_fifo(isac);
 569                        ret = 0;
 570                        spin_unlock_irqrestore(isac->hwlock, flags);
 571                        queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
 572                } else
 573                        spin_unlock_irqrestore(isac->hwlock, flags);
 574                return ret;
 575        case PH_ACTIVATE_REQ:
 576                ret = l1_event(dch->l1, hh->prim);
 577                break;
 578        case PH_DEACTIVATE_REQ:
 579                test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags);
 580                ret = l1_event(dch->l1, hh->prim);
 581                break;
 582        }
 583
 584        if (!ret)
 585                dev_kfree_skb(skb);
 586        return ret;
 587}
 588
 589static int
 590isac_ctrl(struct isac_hw *isac, u32 cmd, unsigned long para)
 591{
 592        u8 tl = 0;
 593        unsigned long flags;
 594        int ret = 0;
 595
 596        switch (cmd) {
 597        case HW_TESTLOOP:
 598                spin_lock_irqsave(isac->hwlock, flags);
 599                if (!(isac->type & IPAC_TYPE_ISACX)) {
 600                        /* TODO: implement for IPAC_TYPE_ISACX */
 601                        if (para & 1) /* B1 */
 602                                tl |= 0x0c;
 603                        else if (para & 2) /* B2 */
 604                                tl |= 0x3;
 605                        /* we only support IOM2 mode */
 606                        WriteISAC(isac, ISAC_SPCR, tl);
 607                        if (tl)
 608                                WriteISAC(isac, ISAC_ADF1, 0x8);
 609                        else
 610                                WriteISAC(isac, ISAC_ADF1, 0x0);
 611                }
 612                spin_unlock_irqrestore(isac->hwlock, flags);
 613                break;
 614        case HW_TIMER3_VALUE:
 615                ret = l1_event(isac->dch.l1, HW_TIMER3_VALUE | (para & 0xff));
 616                break;
 617        default:
 618                pr_debug("%s: %s unknown command %x %lx\n", isac->name,
 619                         __func__, cmd, para);
 620                ret = -1;
 621        }
 622        return ret;
 623}
 624
 625static int
 626isac_l1cmd(struct dchannel *dch, u32 cmd)
 627{
 628        struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
 629        u_long flags;
 630
 631        pr_debug("%s: cmd(%x) state(%02x)\n", isac->name, cmd, isac->state);
 632        switch (cmd) {
 633        case INFO3_P8:
 634                spin_lock_irqsave(isac->hwlock, flags);
 635                ph_command(isac, ISAC_CMD_AR8);
 636                spin_unlock_irqrestore(isac->hwlock, flags);
 637                break;
 638        case INFO3_P10:
 639                spin_lock_irqsave(isac->hwlock, flags);
 640                ph_command(isac, ISAC_CMD_AR10);
 641                spin_unlock_irqrestore(isac->hwlock, flags);
 642                break;
 643        case HW_RESET_REQ:
 644                spin_lock_irqsave(isac->hwlock, flags);
 645                if ((isac->state == ISAC_IND_EI) ||
 646                    (isac->state == ISAC_IND_DR) ||
 647                    (isac->state == ISAC_IND_DR6) ||
 648                    (isac->state == ISAC_IND_RS))
 649                        ph_command(isac, ISAC_CMD_TIM);
 650                else
 651                        ph_command(isac, ISAC_CMD_RS);
 652                spin_unlock_irqrestore(isac->hwlock, flags);
 653                break;
 654        case HW_DEACT_REQ:
 655                skb_queue_purge(&dch->squeue);
 656                if (dch->tx_skb) {
 657                        dev_kfree_skb(dch->tx_skb);
 658                        dch->tx_skb = NULL;
 659                }
 660                dch->tx_idx = 0;
 661                if (dch->rx_skb) {
 662                        dev_kfree_skb(dch->rx_skb);
 663                        dch->rx_skb = NULL;
 664                }
 665                test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
 666                if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
 667                        del_timer(&dch->timer);
 668                break;
 669        case HW_POWERUP_REQ:
 670                spin_lock_irqsave(isac->hwlock, flags);
 671                ph_command(isac, ISAC_CMD_TIM);
 672                spin_unlock_irqrestore(isac->hwlock, flags);
 673                break;
 674        case PH_ACTIVATE_IND:
 675                test_and_set_bit(FLG_ACTIVE, &dch->Flags);
 676                _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
 677                            GFP_ATOMIC);
 678                break;
 679        case PH_DEACTIVATE_IND:
 680                test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
 681                _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
 682                            GFP_ATOMIC);
 683                break;
 684        default:
 685                pr_debug("%s: %s unknown command %x\n", isac->name,
 686                         __func__, cmd);
 687                return -1;
 688        }
 689        return 0;
 690}
 691
 692static void
 693isac_release(struct isac_hw *isac)
 694{
 695        if (isac->type & IPAC_TYPE_ISACX)
 696                WriteISAC(isac, ISACX_MASK, 0xff);
 697        else if (isac->type != 0)
 698                WriteISAC(isac, ISAC_MASK, 0xff);
 699        if (isac->dch.timer.function != NULL) {
 700                del_timer(&isac->dch.timer);
 701                isac->dch.timer.function = NULL;
 702        }
 703        kfree(isac->mon_rx);
 704        isac->mon_rx = NULL;
 705        kfree(isac->mon_tx);
 706        isac->mon_tx = NULL;
 707        if (isac->dch.l1)
 708                l1_event(isac->dch.l1, CLOSE_CHANNEL);
 709        mISDN_freedchannel(&isac->dch);
 710}
 711
 712static void
 713dbusy_timer_handler(struct timer_list *t)
 714{
 715        struct isac_hw *isac = from_timer(isac, t, dch.timer);
 716        int rbch, star;
 717        u_long flags;
 718
 719        if (test_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) {
 720                spin_lock_irqsave(isac->hwlock, flags);
 721                rbch = ReadISAC(isac, ISAC_RBCH);
 722                star = ReadISAC(isac, ISAC_STAR);
 723                pr_debug("%s: D-Channel Busy RBCH %02x STAR %02x\n",
 724                         isac->name, rbch, star);
 725                if (rbch & ISAC_RBCH_XAC) /* D-Channel Busy */
 726                        test_and_set_bit(FLG_L1_BUSY, &isac->dch.Flags);
 727                else {
 728                        /* discard frame; reset transceiver */
 729                        test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags);
 730                        if (isac->dch.tx_idx)
 731                                isac->dch.tx_idx = 0;
 732                        else
 733                                pr_info("%s: ISAC D-Channel Busy no tx_idx\n",
 734                                        isac->name);
 735                        /* Transmitter reset */
 736                        WriteISAC(isac, ISAC_CMDR, 0x01);
 737                }
 738                spin_unlock_irqrestore(isac->hwlock, flags);
 739        }
 740}
 741
 742static int
 743open_dchannel_caller(struct isac_hw *isac, struct channel_req *rq, void *caller)
 744{
 745        pr_debug("%s: %s dev(%d) open from %p\n", isac->name, __func__,
 746                 isac->dch.dev.id, caller);
 747        if (rq->protocol != ISDN_P_TE_S0)
 748                return -EINVAL;
 749        if (rq->adr.channel == 1)
 750                /* E-Channel not supported */
 751                return -EINVAL;
 752        rq->ch = &isac->dch.dev.D;
 753        rq->ch->protocol = rq->protocol;
 754        if (isac->dch.state == 7)
 755                _queue_data(rq->ch, PH_ACTIVATE_IND, MISDN_ID_ANY,
 756                            0, NULL, GFP_KERNEL);
 757        return 0;
 758}
 759
 760static int
 761open_dchannel(struct isac_hw *isac, struct channel_req *rq)
 762{
 763        return open_dchannel_caller(isac, rq, __builtin_return_address(0));
 764}
 765
 766static const char *ISACVer[] =
 767{"2086/2186 V1.1", "2085 B1", "2085 B2",
 768 "2085 V2.3"};
 769
 770static int
 771isac_init(struct isac_hw *isac)
 772{
 773        u8 val;
 774        int err = 0;
 775
 776        if (!isac->dch.l1) {
 777                err = create_l1(&isac->dch, isac_l1cmd);
 778                if (err)
 779                        return err;
 780        }
 781        isac->mon_tx = NULL;
 782        isac->mon_rx = NULL;
 783        timer_setup(&isac->dch.timer, dbusy_timer_handler, 0);
 784        isac->mocr = 0xaa;
 785        if (isac->type & IPAC_TYPE_ISACX) {
 786                /* Disable all IRQ */
 787                WriteISAC(isac, ISACX_MASK, 0xff);
 788                val = ReadISAC(isac, ISACX_STARD);
 789                pr_debug("%s: ISACX STARD %x\n", isac->name, val);
 790                val = ReadISAC(isac, ISACX_ISTAD);
 791                pr_debug("%s: ISACX ISTAD %x\n", isac->name, val);
 792                val = ReadISAC(isac, ISACX_ISTA);
 793                pr_debug("%s: ISACX ISTA %x\n", isac->name, val);
 794                /* clear LDD */
 795                WriteISAC(isac, ISACX_TR_CONF0, 0x00);
 796                /* enable transmitter */
 797                WriteISAC(isac, ISACX_TR_CONF2, 0x00);
 798                /* transparent mode 0, RAC, stop/go */
 799                WriteISAC(isac, ISACX_MODED, 0xc9);
 800                /* all HDLC IRQ unmasked */
 801                val = ReadISAC(isac, ISACX_ID);
 802                if (isac->dch.debug & DEBUG_HW)
 803                        pr_notice("%s: ISACX Design ID %x\n",
 804                                  isac->name, val & 0x3f);
 805                val = ReadISAC(isac, ISACX_CIR0);
 806                pr_debug("%s: ISACX CIR0 %02X\n", isac->name, val);
 807                isac->state = val >> 4;
 808                isac_ph_state_change(isac);
 809                ph_command(isac, ISAC_CMD_RS);
 810                WriteISAC(isac, ISACX_MASK, IPACX__ON);
 811                WriteISAC(isac, ISACX_MASKD, 0x00);
 812        } else { /* old isac */
 813                WriteISAC(isac, ISAC_MASK, 0xff);
 814                val = ReadISAC(isac, ISAC_STAR);
 815                pr_debug("%s: ISAC STAR %x\n", isac->name, val);
 816                val = ReadISAC(isac, ISAC_MODE);
 817                pr_debug("%s: ISAC MODE %x\n", isac->name, val);
 818                val = ReadISAC(isac, ISAC_ADF2);
 819                pr_debug("%s: ISAC ADF2 %x\n", isac->name, val);
 820                val = ReadISAC(isac, ISAC_ISTA);
 821                pr_debug("%s: ISAC ISTA %x\n", isac->name, val);
 822                if (val & 0x01) {
 823                        val = ReadISAC(isac, ISAC_EXIR);
 824                        pr_debug("%s: ISAC EXIR %x\n", isac->name, val);
 825                }
 826                val = ReadISAC(isac, ISAC_RBCH);
 827                if (isac->dch.debug & DEBUG_HW)
 828                        pr_notice("%s: ISAC version (%x): %s\n", isac->name,
 829                                  val, ISACVer[(val >> 5) & 3]);
 830                isac->type |= ((val >> 5) & 3);
 831                if (!isac->adf2)
 832                        isac->adf2 = 0x80;
 833                if (!(isac->adf2 & 0x80)) { /* only IOM 2 Mode */
 834                        pr_info("%s: only support IOM2 mode but adf2=%02x\n",
 835                                isac->name, isac->adf2);
 836                        isac_release(isac);
 837                        return -EINVAL;
 838                }
 839                WriteISAC(isac, ISAC_ADF2, isac->adf2);
 840                WriteISAC(isac, ISAC_SQXR, 0x2f);
 841                WriteISAC(isac, ISAC_SPCR, 0x00);
 842                WriteISAC(isac, ISAC_STCR, 0x70);
 843                WriteISAC(isac, ISAC_MODE, 0xc9);
 844                WriteISAC(isac, ISAC_TIMR, 0x00);
 845                WriteISAC(isac, ISAC_ADF1, 0x00);
 846                val = ReadISAC(isac, ISAC_CIR0);
 847                pr_debug("%s: ISAC CIR0 %x\n", isac->name, val);
 848                isac->state = (val >> 2) & 0xf;
 849                isac_ph_state_change(isac);
 850                ph_command(isac, ISAC_CMD_RS);
 851                WriteISAC(isac, ISAC_MASK, 0);
 852        }
 853        return err;
 854}
 855
 856int
 857mISDNisac_init(struct isac_hw *isac, void *hw)
 858{
 859        mISDN_initdchannel(&isac->dch, MAX_DFRAME_LEN_L1, isac_ph_state_bh);
 860        isac->dch.hw = hw;
 861        isac->dch.dev.D.send = isac_l1hw;
 862        isac->init = isac_init;
 863        isac->release = isac_release;
 864        isac->ctrl = isac_ctrl;
 865        isac->open = open_dchannel;
 866        isac->dch.dev.Dprotocols = (1 << ISDN_P_TE_S0);
 867        isac->dch.dev.nrbchan = 2;
 868        return 0;
 869}
 870EXPORT_SYMBOL(mISDNisac_init);
 871
 872static void
 873waitforCEC(struct hscx_hw *hx)
 874{
 875        u8 starb, to = 50;
 876
 877        while (to) {
 878                starb = ReadHSCX(hx, IPAC_STARB);
 879                if (!(starb & 0x04))
 880                        break;
 881                udelay(1);
 882                to--;
 883        }
 884        if (to < 50)
 885                pr_debug("%s: B%1d CEC %d us\n", hx->ip->name, hx->bch.nr,
 886                         50 - to);
 887        if (!to)
 888                pr_info("%s: B%1d CEC timeout\n", hx->ip->name, hx->bch.nr);
 889}
 890
 891
 892static void
 893waitforXFW(struct hscx_hw *hx)
 894{
 895        u8 starb, to = 50;
 896
 897        while (to) {
 898                starb = ReadHSCX(hx, IPAC_STARB);
 899                if ((starb & 0x44) == 0x40)
 900                        break;
 901                udelay(1);
 902                to--;
 903        }
 904        if (to < 50)
 905                pr_debug("%s: B%1d XFW %d us\n", hx->ip->name, hx->bch.nr,
 906                         50 - to);
 907        if (!to)
 908                pr_info("%s: B%1d XFW timeout\n", hx->ip->name, hx->bch.nr);
 909}
 910
 911static void
 912hscx_cmdr(struct hscx_hw *hx, u8 cmd)
 913{
 914        if (hx->ip->type & IPAC_TYPE_IPACX)
 915                WriteHSCX(hx, IPACX_CMDRB, cmd);
 916        else {
 917                waitforCEC(hx);
 918                WriteHSCX(hx, IPAC_CMDRB, cmd);
 919        }
 920}
 921
 922static void
 923hscx_empty_fifo(struct hscx_hw *hscx, u8 count)
 924{
 925        u8 *p;
 926        int maxlen;
 927
 928        pr_debug("%s: B%1d %d\n", hscx->ip->name, hscx->bch.nr, count);
 929        if (test_bit(FLG_RX_OFF, &hscx->bch.Flags)) {
 930                hscx->bch.dropcnt += count;
 931                hscx_cmdr(hscx, 0x80); /* RMC */
 932                return;
 933        }
 934        maxlen = bchannel_get_rxbuf(&hscx->bch, count);
 935        if (maxlen < 0) {
 936                hscx_cmdr(hscx, 0x80); /* RMC */
 937                if (hscx->bch.rx_skb)
 938                        skb_trim(hscx->bch.rx_skb, 0);
 939                pr_warn("%s.B%d: No bufferspace for %d bytes\n",
 940                        hscx->ip->name, hscx->bch.nr, count);
 941                return;
 942        }
 943        p = skb_put(hscx->bch.rx_skb, count);
 944
 945        if (hscx->ip->type & IPAC_TYPE_IPACX)
 946                hscx->ip->read_fifo(hscx->ip->hw,
 947                                    hscx->off + IPACX_RFIFOB, p, count);
 948        else
 949                hscx->ip->read_fifo(hscx->ip->hw,
 950                                    hscx->off, p, count);
 951
 952        hscx_cmdr(hscx, 0x80); /* RMC */
 953
 954        if (hscx->bch.debug & DEBUG_HW_BFIFO) {
 955                snprintf(hscx->log, 64, "B%1d-recv %s %d ",
 956                         hscx->bch.nr, hscx->ip->name, count);
 957                print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count);
 958        }
 959}
 960
 961static void
 962hscx_fill_fifo(struct hscx_hw *hscx)
 963{
 964        int count, more;
 965        u8 *p;
 966
 967        if (!hscx->bch.tx_skb) {
 968                if (!test_bit(FLG_TX_EMPTY, &hscx->bch.Flags))
 969                        return;
 970                count = hscx->fifo_size;
 971                more = 1;
 972                p = hscx->log;
 973                memset(p, hscx->bch.fill[0], count);
 974        } else {
 975                count = hscx->bch.tx_skb->len - hscx->bch.tx_idx;
 976                if (count <= 0)
 977                        return;
 978                p = hscx->bch.tx_skb->data + hscx->bch.tx_idx;
 979
 980                more = test_bit(FLG_TRANSPARENT, &hscx->bch.Flags) ? 1 : 0;
 981                if (count > hscx->fifo_size) {
 982                        count = hscx->fifo_size;
 983                        more = 1;
 984                }
 985                pr_debug("%s: B%1d %d/%d/%d\n", hscx->ip->name, hscx->bch.nr,
 986                         count, hscx->bch.tx_idx, hscx->bch.tx_skb->len);
 987                hscx->bch.tx_idx += count;
 988        }
 989        if (hscx->ip->type & IPAC_TYPE_IPACX)
 990                hscx->ip->write_fifo(hscx->ip->hw,
 991                                     hscx->off + IPACX_XFIFOB, p, count);
 992        else {
 993                waitforXFW(hscx);
 994                hscx->ip->write_fifo(hscx->ip->hw,
 995                                     hscx->off, p, count);
 996        }
 997        hscx_cmdr(hscx, more ? 0x08 : 0x0a);
 998
 999        if (hscx->bch.tx_skb && (hscx->bch.debug & DEBUG_HW_BFIFO)) {
1000                snprintf(hscx->log, 64, "B%1d-send %s %d ",
1001                         hscx->bch.nr, hscx->ip->name, count);
1002                print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count);
1003        }
1004}
1005
1006static void
1007hscx_xpr(struct hscx_hw *hx)
1008{
1009        if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len) {
1010                hscx_fill_fifo(hx);
1011        } else {
1012                dev_kfree_skb(hx->bch.tx_skb);
1013                if (get_next_bframe(&hx->bch)) {
1014                        hscx_fill_fifo(hx);
1015                        test_and_clear_bit(FLG_TX_EMPTY, &hx->bch.Flags);
1016                } else if (test_bit(FLG_TX_EMPTY, &hx->bch.Flags)) {
1017                        hscx_fill_fifo(hx);
1018                }
1019        }
1020}
1021
1022static void
1023ipac_rme(struct hscx_hw *hx)
1024{
1025        int count;
1026        u8 rstab;
1027
1028        if (hx->ip->type & IPAC_TYPE_IPACX)
1029                rstab = ReadHSCX(hx, IPACX_RSTAB);
1030        else
1031                rstab = ReadHSCX(hx, IPAC_RSTAB);
1032        pr_debug("%s: B%1d RSTAB %02x\n", hx->ip->name, hx->bch.nr, rstab);
1033        if ((rstab & 0xf0) != 0xa0) {
1034                /* !(VFR && !RDO && CRC && !RAB) */
1035                if (!(rstab & 0x80)) {
1036                        if (hx->bch.debug & DEBUG_HW_BCHANNEL)
1037                                pr_notice("%s: B%1d invalid frame\n",
1038                                          hx->ip->name, hx->bch.nr);
1039                }
1040                if (rstab & 0x40) {
1041                        if (hx->bch.debug & DEBUG_HW_BCHANNEL)
1042                                pr_notice("%s: B%1d RDO proto=%x\n",
1043                                          hx->ip->name, hx->bch.nr,
1044                                          hx->bch.state);
1045                }
1046                if (!(rstab & 0x20)) {
1047                        if (hx->bch.debug & DEBUG_HW_BCHANNEL)
1048                                pr_notice("%s: B%1d CRC error\n",
1049                                          hx->ip->name, hx->bch.nr);
1050                }
1051                hscx_cmdr(hx, 0x80); /* Do RMC */
1052                return;
1053        }
1054        if (hx->ip->type & IPAC_TYPE_IPACX)
1055                count = ReadHSCX(hx, IPACX_RBCLB);
1056        else
1057                count = ReadHSCX(hx, IPAC_RBCLB);
1058        count &= (hx->fifo_size - 1);
1059        if (count == 0)
1060                count = hx->fifo_size;
1061        hscx_empty_fifo(hx, count);
1062        if (!hx->bch.rx_skb)
1063                return;
1064        if (hx->bch.rx_skb->len < 2) {
1065                pr_debug("%s: B%1d frame to short %d\n",
1066                         hx->ip->name, hx->bch.nr, hx->bch.rx_skb->len);
1067                skb_trim(hx->bch.rx_skb, 0);
1068        } else {
1069                skb_trim(hx->bch.rx_skb, hx->bch.rx_skb->len - 1);
1070                recv_Bchannel(&hx->bch, 0, false);
1071        }
1072}
1073
1074static void
1075ipac_irq(struct hscx_hw *hx, u8 ista)
1076{
1077        u8 istab, m, exirb = 0;
1078
1079        if (hx->ip->type & IPAC_TYPE_IPACX)
1080                istab = ReadHSCX(hx, IPACX_ISTAB);
1081        else if (hx->ip->type & IPAC_TYPE_IPAC) {
1082                istab = ReadHSCX(hx, IPAC_ISTAB);
1083                m = (hx->bch.nr & 1) ? IPAC__EXA : IPAC__EXB;
1084                if (m & ista) {
1085                        exirb = ReadHSCX(hx, IPAC_EXIRB);
1086                        pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
1087                                 hx->bch.nr, exirb);
1088                }
1089        } else if (hx->bch.nr & 2) { /* HSCX B */
1090                if (ista & (HSCX__EXA | HSCX__ICA))
1091                        ipac_irq(&hx->ip->hscx[0], ista);
1092                if (ista & HSCX__EXB) {
1093                        exirb = ReadHSCX(hx, IPAC_EXIRB);
1094                        pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
1095                                 hx->bch.nr, exirb);
1096                }
1097                istab = ista & 0xF8;
1098        } else { /* HSCX A */
1099                istab = ReadHSCX(hx, IPAC_ISTAB);
1100                if (ista & HSCX__EXA) {
1101                        exirb = ReadHSCX(hx, IPAC_EXIRB);
1102                        pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
1103                                 hx->bch.nr, exirb);
1104                }
1105                istab = istab & 0xF8;
1106        }
1107        if (exirb & IPAC_B_XDU)
1108                istab |= IPACX_B_XDU;
1109        if (exirb & IPAC_B_RFO)
1110                istab |= IPACX_B_RFO;
1111        pr_debug("%s: B%1d ISTAB %02x\n", hx->ip->name, hx->bch.nr, istab);
1112
1113        if (!test_bit(FLG_ACTIVE, &hx->bch.Flags))
1114                return;
1115
1116        if (istab & IPACX_B_RME)
1117                ipac_rme(hx);
1118
1119        if (istab & IPACX_B_RPF) {
1120                hscx_empty_fifo(hx, hx->fifo_size);
1121                if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags))
1122                        recv_Bchannel(&hx->bch, 0, false);
1123        }
1124
1125        if (istab & IPACX_B_RFO) {
1126                pr_debug("%s: B%1d RFO error\n", hx->ip->name, hx->bch.nr);
1127                hscx_cmdr(hx, 0x40);    /* RRES */
1128        }
1129
1130        if (istab & IPACX_B_XPR)
1131                hscx_xpr(hx);
1132
1133        if (istab & IPACX_B_XDU) {
1134                if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) {
1135                        if (test_bit(FLG_FILLEMPTY, &hx->bch.Flags))
1136                                test_and_set_bit(FLG_TX_EMPTY, &hx->bch.Flags);
1137                        hscx_xpr(hx);
1138                        return;
1139                }
1140                pr_debug("%s: B%1d XDU error at len %d\n", hx->ip->name,
1141                         hx->bch.nr, hx->bch.tx_idx);
1142                hx->bch.tx_idx = 0;
1143                hscx_cmdr(hx, 0x01);    /* XRES */
1144        }
1145}
1146
1147irqreturn_t
1148mISDNipac_irq(struct ipac_hw *ipac, int maxloop)
1149{
1150        int cnt = maxloop + 1;
1151        u8 ista, istad;
1152        struct isac_hw  *isac = &ipac->isac;
1153
1154        if (ipac->type & IPAC_TYPE_IPACX) {
1155                ista = ReadIPAC(ipac, ISACX_ISTA);
1156                while (ista && --cnt) {
1157                        pr_debug("%s: ISTA %02x\n", ipac->name, ista);
1158                        if (ista & IPACX__ICA)
1159                                ipac_irq(&ipac->hscx[0], ista);
1160                        if (ista & IPACX__ICB)
1161                                ipac_irq(&ipac->hscx[1], ista);
1162                        if (ista & (ISACX__ICD | ISACX__CIC))
1163                                mISDNisac_irq(&ipac->isac, ista);
1164                        ista = ReadIPAC(ipac, ISACX_ISTA);
1165                }
1166        } else if (ipac->type & IPAC_TYPE_IPAC) {
1167                ista = ReadIPAC(ipac, IPAC_ISTA);
1168                while (ista && --cnt) {
1169                        pr_debug("%s: ISTA %02x\n", ipac->name, ista);
1170                        if (ista & (IPAC__ICD | IPAC__EXD)) {
1171                                istad = ReadISAC(isac, ISAC_ISTA);
1172                                pr_debug("%s: ISTAD %02x\n", ipac->name, istad);
1173                                if (istad & IPAC_D_TIN2)
1174                                        pr_debug("%s TIN2 irq\n", ipac->name);
1175                                if (ista & IPAC__EXD)
1176                                        istad |= 1; /* ISAC EXI */
1177                                mISDNisac_irq(isac, istad);
1178                        }
1179                        if (ista & (IPAC__ICA | IPAC__EXA))
1180                                ipac_irq(&ipac->hscx[0], ista);
1181                        if (ista & (IPAC__ICB | IPAC__EXB))
1182                                ipac_irq(&ipac->hscx[1], ista);
1183                        ista = ReadIPAC(ipac, IPAC_ISTA);
1184                }
1185        } else if (ipac->type & IPAC_TYPE_HSCX) {
1186                while (--cnt) {
1187                        ista = ReadIPAC(ipac, IPAC_ISTAB + ipac->hscx[1].off);
1188                        pr_debug("%s: B2 ISTA %02x\n", ipac->name, ista);
1189                        if (ista)
1190                                ipac_irq(&ipac->hscx[1], ista);
1191                        istad = ReadISAC(isac, ISAC_ISTA);
1192                        pr_debug("%s: ISTAD %02x\n", ipac->name, istad);
1193                        if (istad)
1194                                mISDNisac_irq(isac, istad);
1195                        if (0 == (ista | istad))
1196                                break;
1197                }
1198        }
1199        if (cnt > maxloop) /* only for ISAC/HSCX without PCI IRQ test */
1200                return IRQ_NONE;
1201        if (cnt < maxloop)
1202                pr_debug("%s: %d irqloops cpu%d\n", ipac->name,
1203                         maxloop - cnt, smp_processor_id());
1204        if (maxloop && !cnt)
1205                pr_notice("%s: %d IRQ LOOP cpu%d\n", ipac->name,
1206                          maxloop, smp_processor_id());
1207        return IRQ_HANDLED;
1208}
1209EXPORT_SYMBOL(mISDNipac_irq);
1210
1211static int
1212hscx_mode(struct hscx_hw *hscx, u32 bprotocol)
1213{
1214        pr_debug("%s: HSCX %c protocol %x-->%x ch %d\n", hscx->ip->name,
1215                 '@' + hscx->bch.nr, hscx->bch.state, bprotocol, hscx->bch.nr);
1216        if (hscx->ip->type & IPAC_TYPE_IPACX) {
1217                if (hscx->bch.nr & 1) { /* B1 and ICA */
1218                        WriteIPAC(hscx->ip, ISACX_BCHA_TSDP_BC1, 0x80);
1219                        WriteIPAC(hscx->ip, ISACX_BCHA_CR, 0x88);
1220                } else { /* B2 and ICB */
1221                        WriteIPAC(hscx->ip, ISACX_BCHB_TSDP_BC1, 0x81);
1222                        WriteIPAC(hscx->ip, ISACX_BCHB_CR, 0x88);
1223                }
1224                switch (bprotocol) {
1225                case ISDN_P_NONE: /* init */
1226                        WriteHSCX(hscx, IPACX_MODEB, 0xC0);     /* rec off */
1227                        WriteHSCX(hscx, IPACX_EXMB,  0x30);     /* std adj. */
1228                        WriteHSCX(hscx, IPACX_MASKB, 0xFF);     /* ints off */
1229                        hscx_cmdr(hscx, 0x41);
1230                        test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags);
1231                        test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
1232                        break;
1233                case ISDN_P_B_RAW:
1234                        WriteHSCX(hscx, IPACX_MODEB, 0x88);     /* ex trans */
1235                        WriteHSCX(hscx, IPACX_EXMB,  0x00);     /* trans */
1236                        hscx_cmdr(hscx, 0x41);
1237                        WriteHSCX(hscx, IPACX_MASKB, IPACX_B_ON);
1238                        test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
1239                        break;
1240                case ISDN_P_B_HDLC:
1241                        WriteHSCX(hscx, IPACX_MODEB, 0xC0);     /* trans */
1242                        WriteHSCX(hscx, IPACX_EXMB,  0x00);     /* hdlc,crc */
1243                        hscx_cmdr(hscx, 0x41);
1244                        WriteHSCX(hscx, IPACX_MASKB, IPACX_B_ON);
1245                        test_and_set_bit(FLG_HDLC, &hscx->bch.Flags);
1246                        break;
1247                default:
1248                        pr_info("%s: protocol not known %x\n", hscx->ip->name,
1249                                bprotocol);
1250                        return -ENOPROTOOPT;
1251                }
1252        } else if (hscx->ip->type & IPAC_TYPE_IPAC) { /* IPAC */
1253                WriteHSCX(hscx, IPAC_CCR1, 0x82);
1254                WriteHSCX(hscx, IPAC_CCR2, 0x30);
1255                WriteHSCX(hscx, IPAC_XCCR, 0x07);
1256                WriteHSCX(hscx, IPAC_RCCR, 0x07);
1257                WriteHSCX(hscx, IPAC_TSAX, hscx->slot);
1258                WriteHSCX(hscx, IPAC_TSAR, hscx->slot);
1259                switch (bprotocol) {
1260                case ISDN_P_NONE:
1261                        WriteHSCX(hscx, IPAC_TSAX, 0x1F);
1262                        WriteHSCX(hscx, IPAC_TSAR, 0x1F);
1263                        WriteHSCX(hscx, IPAC_MODEB, 0x84);
1264                        WriteHSCX(hscx, IPAC_CCR1, 0x82);
1265                        WriteHSCX(hscx, IPAC_MASKB, 0xFF);      /* ints off */
1266                        test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags);
1267                        test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
1268                        break;
1269                case ISDN_P_B_RAW:
1270                        WriteHSCX(hscx, IPAC_MODEB, 0xe4);      /* ex trans */
1271                        WriteHSCX(hscx, IPAC_CCR1, 0x82);
1272                        hscx_cmdr(hscx, 0x41);
1273                        WriteHSCX(hscx, IPAC_MASKB, 0);
1274                        test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
1275                        break;
1276                case ISDN_P_B_HDLC:
1277                        WriteHSCX(hscx, IPAC_MODEB, 0x8c);
1278                        WriteHSCX(hscx, IPAC_CCR1, 0x8a);
1279                        hscx_cmdr(hscx, 0x41);
1280                        WriteHSCX(hscx, IPAC_MASKB, 0);
1281                        test_and_set_bit(FLG_HDLC, &hscx->bch.Flags);
1282                        break;
1283                default:
1284                        pr_info("%s: protocol not known %x\n", hscx->ip->name,
1285                                bprotocol);
1286                        return -ENOPROTOOPT;
1287                }
1288        } else if (hscx->ip->type & IPAC_TYPE_HSCX) { /* HSCX */
1289                WriteHSCX(hscx, IPAC_CCR1, 0x85);
1290                WriteHSCX(hscx, IPAC_CCR2, 0x30);
1291                WriteHSCX(hscx, IPAC_XCCR, 0x07);
1292                WriteHSCX(hscx, IPAC_RCCR, 0x07);
1293                WriteHSCX(hscx, IPAC_TSAX, hscx->slot);
1294                WriteHSCX(hscx, IPAC_TSAR, hscx->slot);
1295                switch (bprotocol) {
1296                case ISDN_P_NONE:
1297                        WriteHSCX(hscx, IPAC_TSAX, 0x1F);
1298                        WriteHSCX(hscx, IPAC_TSAR, 0x1F);
1299                        WriteHSCX(hscx, IPAC_MODEB, 0x84);
1300                        WriteHSCX(hscx, IPAC_CCR1, 0x85);
1301                        WriteHSCX(hscx, IPAC_MASKB, 0xFF);      /* ints off */
1302                        test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags);
1303                        test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
1304                        break;
1305                case ISDN_P_B_RAW:
1306                        WriteHSCX(hscx, IPAC_MODEB, 0xe4);      /* ex trans */
1307                        WriteHSCX(hscx, IPAC_CCR1, 0x85);
1308                        hscx_cmdr(hscx, 0x41);
1309                        WriteHSCX(hscx, IPAC_MASKB, 0);
1310                        test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
1311                        break;
1312                case ISDN_P_B_HDLC:
1313                        WriteHSCX(hscx, IPAC_MODEB, 0x8c);
1314                        WriteHSCX(hscx, IPAC_CCR1, 0x8d);
1315                        hscx_cmdr(hscx, 0x41);
1316                        WriteHSCX(hscx, IPAC_MASKB, 0);
1317                        test_and_set_bit(FLG_HDLC, &hscx->bch.Flags);
1318                        break;
1319                default:
1320                        pr_info("%s: protocol not known %x\n", hscx->ip->name,
1321                                bprotocol);
1322                        return -ENOPROTOOPT;
1323                }
1324        } else
1325                return -EINVAL;
1326        hscx->bch.state = bprotocol;
1327        return 0;
1328}
1329
1330static int
1331hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
1332{
1333        struct bchannel *bch = container_of(ch, struct bchannel, ch);
1334        struct hscx_hw  *hx = container_of(bch, struct hscx_hw, bch);
1335        int ret = -EINVAL;
1336        struct mISDNhead *hh = mISDN_HEAD_P(skb);
1337        unsigned long flags;
1338
1339        switch (hh->prim) {
1340        case PH_DATA_REQ:
1341                spin_lock_irqsave(hx->ip->hwlock, flags);
1342                ret = bchannel_senddata(bch, skb);
1343                if (ret > 0) { /* direct TX */
1344                        ret = 0;
1345                        hscx_fill_fifo(hx);
1346                }
1347                spin_unlock_irqrestore(hx->ip->hwlock, flags);
1348                return ret;
1349        case PH_ACTIVATE_REQ:
1350                spin_lock_irqsave(hx->ip->hwlock, flags);
1351                if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags))
1352                        ret = hscx_mode(hx, ch->protocol);
1353                else
1354                        ret = 0;
1355                spin_unlock_irqrestore(hx->ip->hwlock, flags);
1356                if (!ret)
1357                        _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
1358                                    NULL, GFP_KERNEL);
1359                break;
1360        case PH_DEACTIVATE_REQ:
1361                spin_lock_irqsave(hx->ip->hwlock, flags);
1362                mISDN_clear_bchannel(bch);
1363                hscx_mode(hx, ISDN_P_NONE);
1364                spin_unlock_irqrestore(hx->ip->hwlock, flags);
1365                _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
1366                            NULL, GFP_KERNEL);
1367                ret = 0;
1368                break;
1369        default:
1370                pr_info("%s: %s unknown prim(%x,%x)\n",
1371                        hx->ip->name, __func__, hh->prim, hh->id);
1372                ret = -EINVAL;
1373        }
1374        if (!ret)
1375                dev_kfree_skb(skb);
1376        return ret;
1377}
1378
1379static int
1380channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
1381{
1382        return mISDN_ctrl_bchannel(bch, cq);
1383}
1384
1385static int
1386hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
1387{
1388        struct bchannel *bch = container_of(ch, struct bchannel, ch);
1389        struct hscx_hw  *hx = container_of(bch, struct hscx_hw, bch);
1390        int ret = -EINVAL;
1391        u_long flags;
1392
1393        pr_debug("%s: %s cmd:%x %p\n", hx->ip->name, __func__, cmd, arg);
1394        switch (cmd) {
1395        case CLOSE_CHANNEL:
1396                test_and_clear_bit(FLG_OPEN, &bch->Flags);
1397                cancel_work_sync(&bch->workq);
1398                spin_lock_irqsave(hx->ip->hwlock, flags);
1399                mISDN_clear_bchannel(bch);
1400                hscx_mode(hx, ISDN_P_NONE);
1401                spin_unlock_irqrestore(hx->ip->hwlock, flags);
1402                ch->protocol = ISDN_P_NONE;
1403                ch->peer = NULL;
1404                module_put(hx->ip->owner);
1405                ret = 0;
1406                break;
1407        case CONTROL_CHANNEL:
1408                ret = channel_bctrl(bch, arg);
1409                break;
1410        default:
1411                pr_info("%s: %s unknown prim(%x)\n",
1412                        hx->ip->name, __func__, cmd);
1413        }
1414        return ret;
1415}
1416
1417static void
1418free_ipac(struct ipac_hw *ipac)
1419{
1420        isac_release(&ipac->isac);
1421}
1422
1423static const char *HSCXVer[] =
1424{"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7",
1425 "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"};
1426
1427
1428
1429static void
1430hscx_init(struct hscx_hw *hx)
1431{
1432        u8 val;
1433
1434        WriteHSCX(hx, IPAC_RAH2, 0xFF);
1435        WriteHSCX(hx, IPAC_XBCH, 0x00);
1436        WriteHSCX(hx, IPAC_RLCR, 0x00);
1437
1438        if (hx->ip->type & IPAC_TYPE_HSCX) {
1439                WriteHSCX(hx, IPAC_CCR1, 0x85);
1440                val = ReadHSCX(hx, HSCX_VSTR);
1441                pr_debug("%s: HSCX VSTR %02x\n", hx->ip->name, val);
1442                if (hx->bch.debug & DEBUG_HW)
1443                        pr_notice("%s: HSCX version %s\n", hx->ip->name,
1444                                  HSCXVer[val & 0x0f]);
1445        } else
1446                WriteHSCX(hx, IPAC_CCR1, 0x82);
1447        WriteHSCX(hx, IPAC_CCR2, 0x30);
1448        WriteHSCX(hx, IPAC_XCCR, 0x07);
1449        WriteHSCX(hx, IPAC_RCCR, 0x07);
1450}
1451
1452static int
1453ipac_init(struct ipac_hw *ipac)
1454{
1455        u8 val;
1456
1457        if (ipac->type & IPAC_TYPE_HSCX) {
1458                hscx_init(&ipac->hscx[0]);
1459                hscx_init(&ipac->hscx[1]);
1460                val = ReadIPAC(ipac, IPAC_ID);
1461        } else if (ipac->type & IPAC_TYPE_IPAC) {
1462                hscx_init(&ipac->hscx[0]);
1463                hscx_init(&ipac->hscx[1]);
1464                WriteIPAC(ipac, IPAC_MASK, IPAC__ON);
1465                val = ReadIPAC(ipac, IPAC_CONF);
1466                /* conf is default 0, but can be overwritten by card setup */
1467                pr_debug("%s: IPAC CONF %02x/%02x\n", ipac->name,
1468                         val, ipac->conf);
1469                WriteIPAC(ipac, IPAC_CONF, ipac->conf);
1470                val = ReadIPAC(ipac, IPAC_ID);
1471                if (ipac->hscx[0].bch.debug & DEBUG_HW)
1472                        pr_notice("%s: IPAC Design ID %02x\n", ipac->name, val);
1473        }
1474        /* nothing special for IPACX to do here */
1475        return isac_init(&ipac->isac);
1476}
1477
1478static int
1479open_bchannel(struct ipac_hw *ipac, struct channel_req *rq)
1480{
1481        struct bchannel         *bch;
1482
1483        if (rq->adr.channel == 0 || rq->adr.channel > 2)
1484                return -EINVAL;
1485        if (rq->protocol == ISDN_P_NONE)
1486                return -EINVAL;
1487        bch = &ipac->hscx[rq->adr.channel - 1].bch;
1488        if (test_and_set_bit(FLG_OPEN, &bch->Flags))
1489                return -EBUSY; /* b-channel can be only open once */
1490        test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
1491        bch->ch.protocol = rq->protocol;
1492        rq->ch = &bch->ch;
1493        return 0;
1494}
1495
1496static int
1497channel_ctrl(struct ipac_hw *ipac, struct mISDN_ctrl_req *cq)
1498{
1499        int     ret = 0;
1500
1501        switch (cq->op) {
1502        case MISDN_CTRL_GETOP:
1503                cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
1504                break;
1505        case MISDN_CTRL_LOOP:
1506                /* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
1507                if (cq->channel < 0 || cq->channel > 3) {
1508                        ret = -EINVAL;
1509                        break;
1510                }
1511                ret = ipac->ctrl(ipac, HW_TESTLOOP, cq->channel);
1512                break;
1513        case MISDN_CTRL_L1_TIMER3:
1514                ret = ipac->isac.ctrl(&ipac->isac, HW_TIMER3_VALUE, cq->p1);
1515                break;
1516        default:
1517                pr_info("%s: unknown CTRL OP %x\n", ipac->name, cq->op);
1518                ret = -EINVAL;
1519                break;
1520        }
1521        return ret;
1522}
1523
1524static int
1525ipac_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
1526{
1527        struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
1528        struct dchannel *dch = container_of(dev, struct dchannel, dev);
1529        struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
1530        struct ipac_hw *ipac = container_of(isac, struct ipac_hw, isac);
1531        struct channel_req *rq;
1532        int err = 0;
1533
1534        pr_debug("%s: DCTRL: %x %p\n", ipac->name, cmd, arg);
1535        switch (cmd) {
1536        case OPEN_CHANNEL:
1537                rq = arg;
1538                if (rq->protocol == ISDN_P_TE_S0)
1539                        err = open_dchannel_caller(isac, rq, __builtin_return_address(0));
1540                else
1541                        err = open_bchannel(ipac, rq);
1542                if (err)
1543                        break;
1544                if (!try_module_get(ipac->owner))
1545                        pr_info("%s: cannot get module\n", ipac->name);
1546                break;
1547        case CLOSE_CHANNEL:
1548                pr_debug("%s: dev(%d) close from %p\n", ipac->name,
1549                         dch->dev.id, __builtin_return_address(0));
1550                module_put(ipac->owner);
1551                break;
1552        case CONTROL_CHANNEL:
1553                err = channel_ctrl(ipac, arg);
1554                break;
1555        default:
1556                pr_debug("%s: unknown DCTRL command %x\n", ipac->name, cmd);
1557                return -EINVAL;
1558        }
1559        return err;
1560}
1561
1562u32
1563mISDNipac_init(struct ipac_hw *ipac, void *hw)
1564{
1565        u32 ret;
1566        u8 i;
1567
1568        ipac->hw = hw;
1569        if (ipac->isac.dch.debug & DEBUG_HW)
1570                pr_notice("%s: ipac type %x\n", ipac->name, ipac->type);
1571        if (ipac->type & IPAC_TYPE_HSCX) {
1572                ipac->isac.type = IPAC_TYPE_ISAC;
1573                ipac->hscx[0].off = 0;
1574                ipac->hscx[1].off = 0x40;
1575                ipac->hscx[0].fifo_size = 32;
1576                ipac->hscx[1].fifo_size = 32;
1577        } else if (ipac->type & IPAC_TYPE_IPAC) {
1578                ipac->isac.type = IPAC_TYPE_IPAC | IPAC_TYPE_ISAC;
1579                ipac->hscx[0].off = 0;
1580                ipac->hscx[1].off = 0x40;
1581                ipac->hscx[0].fifo_size = 64;
1582                ipac->hscx[1].fifo_size = 64;
1583        } else if (ipac->type & IPAC_TYPE_IPACX) {
1584                ipac->isac.type = IPAC_TYPE_IPACX | IPAC_TYPE_ISACX;
1585                ipac->hscx[0].off = IPACX_OFF_ICA;
1586                ipac->hscx[1].off = IPACX_OFF_ICB;
1587                ipac->hscx[0].fifo_size = 64;
1588                ipac->hscx[1].fifo_size = 64;
1589        } else
1590                return 0;
1591
1592        mISDNisac_init(&ipac->isac, hw);
1593
1594        ipac->isac.dch.dev.D.ctrl = ipac_dctrl;
1595
1596        for (i = 0; i < 2; i++) {
1597                ipac->hscx[i].bch.nr = i + 1;
1598                set_channelmap(i + 1, ipac->isac.dch.dev.channelmap);
1599                list_add(&ipac->hscx[i].bch.ch.list,
1600                         &ipac->isac.dch.dev.bchannels);
1601                mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM,
1602                                   ipac->hscx[i].fifo_size);
1603                ipac->hscx[i].bch.ch.nr = i + 1;
1604                ipac->hscx[i].bch.ch.send = &hscx_l2l1;
1605                ipac->hscx[i].bch.ch.ctrl = hscx_bctrl;
1606                ipac->hscx[i].bch.hw = hw;
1607                ipac->hscx[i].ip = ipac;
1608                /* default values for IOM time slots
1609                 * can be overwritten by card */
1610                ipac->hscx[i].slot = (i == 0) ? 0x2f : 0x03;
1611        }
1612
1613        ipac->init = ipac_init;
1614        ipac->release = free_ipac;
1615
1616        ret =   (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
1617                (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
1618        return ret;
1619}
1620EXPORT_SYMBOL(mISDNipac_init);
1621
1622static int __init
1623isac_mod_init(void)
1624{
1625        pr_notice("mISDNipac module version %s\n", ISAC_REV);
1626        return 0;
1627}
1628
1629static void __exit
1630isac_mod_cleanup(void)
1631{
1632        pr_notice("mISDNipac module unloaded\n");
1633}
1634module_init(isac_mod_init);
1635module_exit(isac_mod_cleanup);
1636