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