linux/drivers/isdn/hisax/w6692.c
<<
>>
Prefs
   1/* $Id: w6692.c,v 1.18.2.4 2004/02/11 13:21:34 keil Exp $
   2 *
   3 * Winbond W6692 specific routines
   4 *
   5 * Author       Petr Novak
   6 * Copyright    by Petr Novak        <petr.novak@i.cz>
   7 *
   8 * This software may be used and distributed according to the terms
   9 * of the GNU General Public License, incorporated herein by reference.
  10 *
  11 */
  12
  13#include <linux/init.h>
  14#include "hisax.h"
  15#include "w6692.h"
  16#include "isdnl1.h"
  17#include <linux/interrupt.h>
  18#include <linux/pci.h>
  19#include <linux/slab.h>
  20
  21/* table entry in the PCI devices list */
  22typedef struct {
  23        int vendor_id;
  24        int device_id;
  25        char *vendor_name;
  26        char *card_name;
  27} PCI_ENTRY;
  28
  29static const PCI_ENTRY id_list[] =
  30{
  31        {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, "Winbond", "W6692"},
  32        {PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, "Dynalink/AsusCom", "IS64PH"},
  33        {0, 0, "U.S.Robotics", "ISDN PCI Card TA"}
  34};
  35
  36#define W6692_SV_USR   0x16ec
  37#define W6692_SD_USR   0x3409
  38#define W6692_WINBOND  0
  39#define W6692_DYNALINK 1
  40#define W6692_USR      2
  41
  42static const char *w6692_revision = "$Revision: 1.18.2.4 $";
  43
  44#define DBUSY_TIMER_VALUE 80
  45
  46static char *W6692Ver[] =
  47{"W6692 V00", "W6692 V01", "W6692 V10",
  48 "W6692 V11"};
  49
  50static void
  51W6692Version(struct IsdnCardState *cs, char *s)
  52{
  53        int val;
  54
  55        val = cs->readW6692(cs, W_D_RBCH);
  56        printk(KERN_INFO "%s Winbond W6692 version (%x): %s\n", s, val, W6692Ver[(val >> 6) & 3]);
  57}
  58
  59static void
  60ph_command(struct IsdnCardState *cs, unsigned int command)
  61{
  62        if (cs->debug & L1_DEB_ISAC)
  63                debugl1(cs, "ph_command %x", command);
  64        cs->writeisac(cs, W_CIX, command);
  65}
  66
  67
  68static void
  69W6692_new_ph(struct IsdnCardState *cs)
  70{
  71        switch (cs->dc.w6692.ph_state) {
  72        case (W_L1CMD_RST):
  73                ph_command(cs, W_L1CMD_DRC);
  74                l1_msg(cs, HW_RESET | INDICATION, NULL);
  75                /* fallthru */
  76        case (W_L1IND_CD):
  77                l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
  78                break;
  79        case (W_L1IND_DRD):
  80                l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
  81                break;
  82        case (W_L1IND_CE):
  83                l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
  84                break;
  85        case (W_L1IND_LD):
  86                l1_msg(cs, HW_RSYNC | INDICATION, NULL);
  87                break;
  88        case (W_L1IND_ARD):
  89                l1_msg(cs, HW_INFO2 | INDICATION, NULL);
  90                break;
  91        case (W_L1IND_AI8):
  92                l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
  93                break;
  94        case (W_L1IND_AI10):
  95                l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL);
  96                break;
  97        default:
  98                break;
  99        }
 100}
 101
 102static void
 103W6692_bh(struct work_struct *work)
 104{
 105        struct IsdnCardState *cs =
 106                container_of(work, struct IsdnCardState, tqueue);
 107        struct PStack *stptr;
 108
 109        if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
 110                if (cs->debug)
 111                        debugl1(cs, "D-Channel Busy cleared");
 112                stptr = cs->stlist;
 113                while (stptr != NULL) {
 114                        stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
 115                        stptr = stptr->next;
 116                }
 117        }
 118        if (test_and_clear_bit(D_L1STATECHANGE, &cs->event))
 119                W6692_new_ph(cs);
 120        if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
 121                DChannel_proc_rcv(cs);
 122        if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
 123                DChannel_proc_xmt(cs);
 124/*
 125  if (test_and_clear_bit(D_RX_MON1, &cs->event))
 126  arcofi_fsm(cs, ARCOFI_RX_END, NULL);
 127  if (test_and_clear_bit(D_TX_MON1, &cs->event))
 128  arcofi_fsm(cs, ARCOFI_TX_END, NULL);
 129*/
 130}
 131
 132static void
 133W6692_empty_fifo(struct IsdnCardState *cs, int count)
 134{
 135        u_char *ptr;
 136
 137        if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
 138                debugl1(cs, "W6692_empty_fifo");
 139
 140        if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
 141                if (cs->debug & L1_DEB_WARN)
 142                        debugl1(cs, "W6692_empty_fifo overrun %d",
 143                                cs->rcvidx + count);
 144                cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK);
 145                cs->rcvidx = 0;
 146                return;
 147        }
 148        ptr = cs->rcvbuf + cs->rcvidx;
 149        cs->rcvidx += count;
 150        cs->readW6692fifo(cs, ptr, count);
 151        cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK);
 152        if (cs->debug & L1_DEB_ISAC_FIFO) {
 153                char *t = cs->dlog;
 154
 155                t += sprintf(t, "W6692_empty_fifo cnt %d", count);
 156                QuickHex(t, ptr, count);
 157                debugl1(cs, "%s", cs->dlog);
 158        }
 159}
 160
 161static void
 162W6692_fill_fifo(struct IsdnCardState *cs)
 163{
 164        int count, more;
 165        u_char *ptr;
 166
 167        if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
 168                debugl1(cs, "W6692_fill_fifo");
 169
 170        if (!cs->tx_skb)
 171                return;
 172
 173        count = cs->tx_skb->len;
 174        if (count <= 0)
 175                return;
 176
 177        more = 0;
 178        if (count > W_D_FIFO_THRESH) {
 179                more = !0;
 180                count = W_D_FIFO_THRESH;
 181        }
 182        ptr = cs->tx_skb->data;
 183        skb_pull(cs->tx_skb, count);
 184        cs->tx_cnt += count;
 185        cs->writeW6692fifo(cs, ptr, count);
 186        cs->writeW6692(cs, W_D_CMDR, more ? W_D_CMDR_XMS : (W_D_CMDR_XMS | W_D_CMDR_XME));
 187        if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
 188                debugl1(cs, "W6692_fill_fifo dbusytimer running");
 189                del_timer(&cs->dbusytimer);
 190        }
 191        init_timer(&cs->dbusytimer);
 192        cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000);
 193        add_timer(&cs->dbusytimer);
 194        if (cs->debug & L1_DEB_ISAC_FIFO) {
 195                char *t = cs->dlog;
 196
 197                t += sprintf(t, "W6692_fill_fifo cnt %d", count);
 198                QuickHex(t, ptr, count);
 199                debugl1(cs, "%s", cs->dlog);
 200        }
 201}
 202
 203static void
 204W6692B_empty_fifo(struct BCState *bcs, int count)
 205{
 206        u_char *ptr;
 207        struct IsdnCardState *cs = bcs->cs;
 208
 209        if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 210                debugl1(cs, "W6692B_empty_fifo");
 211
 212        if (bcs->hw.w6692.rcvidx + count > HSCX_BUFMAX) {
 213                if (cs->debug & L1_DEB_WARN)
 214                        debugl1(cs, "W6692B_empty_fifo: incoming packet too large");
 215                cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
 216                bcs->hw.w6692.rcvidx = 0;
 217                return;
 218        }
 219        ptr = bcs->hw.w6692.rcvbuf + bcs->hw.w6692.rcvidx;
 220        bcs->hw.w6692.rcvidx += count;
 221        READW6692BFIFO(cs, bcs->channel, ptr, count);
 222        cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
 223        if (cs->debug & L1_DEB_HSCX_FIFO) {
 224                char *t = bcs->blog;
 225
 226                t += sprintf(t, "W6692B_empty_fifo %c cnt %d",
 227                             bcs->channel + '1', count);
 228                QuickHex(t, ptr, count);
 229                debugl1(cs, "%s", bcs->blog);
 230        }
 231}
 232
 233static void
 234W6692B_fill_fifo(struct BCState *bcs)
 235{
 236        struct IsdnCardState *cs = bcs->cs;
 237        int more, count;
 238        u_char *ptr;
 239
 240        if (!bcs->tx_skb)
 241                return;
 242        if (bcs->tx_skb->len <= 0)
 243                return;
 244
 245        more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
 246        if (bcs->tx_skb->len > W_B_FIFO_THRESH) {
 247                more = 1;
 248                count = W_B_FIFO_THRESH;
 249        } else
 250                count = bcs->tx_skb->len;
 251
 252        if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 253                debugl1(cs, "W6692B_fill_fifo%s%d", (more ? " " : " last "), count);
 254
 255        ptr = bcs->tx_skb->data;
 256        skb_pull(bcs->tx_skb, count);
 257        bcs->tx_cnt -= count;
 258        bcs->hw.w6692.count += count;
 259        WRITEW6692BFIFO(cs, bcs->channel, ptr, count);
 260        cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACT | W_B_CMDR_XMS | (more ? 0 : W_B_CMDR_XME));
 261        if (cs->debug & L1_DEB_HSCX_FIFO) {
 262                char *t = bcs->blog;
 263
 264                t += sprintf(t, "W6692B_fill_fifo %c cnt %d",
 265                             bcs->channel + '1', count);
 266                QuickHex(t, ptr, count);
 267                debugl1(cs, "%s", bcs->blog);
 268        }
 269}
 270
 271static void
 272W6692B_interrupt(struct IsdnCardState *cs, u_char bchan)
 273{
 274        u_char val;
 275        u_char r;
 276        struct BCState *bcs;
 277        struct sk_buff *skb;
 278        int count;
 279
 280        bcs = (cs->bcs->channel == bchan) ? cs->bcs : (cs->bcs + 1);
 281        val = cs->BC_Read_Reg(cs, bchan, W_B_EXIR);
 282        debugl1(cs, "W6692B chan %d B_EXIR 0x%02X", bchan, val);
 283
 284        if (!test_bit(BC_FLG_INIT, &bcs->Flag)) {
 285                debugl1(cs, "W6692B not INIT yet");
 286                return;
 287        }
 288        if (val & W_B_EXI_RME) {        /* RME */
 289                r = cs->BC_Read_Reg(cs, bchan, W_B_STAR);
 290                if (r & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB)) {
 291                        if (cs->debug & L1_DEB_WARN)
 292                                debugl1(cs, "W6692 B STAR %x", r);
 293                        if ((r & W_B_STAR_RDOV) && bcs->mode)
 294                                if (cs->debug & L1_DEB_WARN)
 295                                        debugl1(cs, "W6692 B RDOV mode=%d",
 296                                                bcs->mode);
 297                        if (r & W_B_STAR_CRCE)
 298                                if (cs->debug & L1_DEB_WARN)
 299                                        debugl1(cs, "W6692 B CRC error");
 300                        cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
 301                } else {
 302                        count = cs->BC_Read_Reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1);
 303                        if (count == 0)
 304                                count = W_B_FIFO_THRESH;
 305                        W6692B_empty_fifo(bcs, count);
 306                        if ((count = bcs->hw.w6692.rcvidx) > 0) {
 307                                if (cs->debug & L1_DEB_HSCX_FIFO)
 308                                        debugl1(cs, "W6692 Bchan Frame %d", count);
 309                                if (!(skb = dev_alloc_skb(count)))
 310                                        printk(KERN_WARNING "W6692: Bchan receive out of memory\n");
 311                                else {
 312                                        skb_put_data(skb,
 313                                                     bcs->hw.w6692.rcvbuf,
 314                                                     count);
 315                                        skb_queue_tail(&bcs->rqueue, skb);
 316                                }
 317                        }
 318                }
 319                bcs->hw.w6692.rcvidx = 0;
 320                schedule_event(bcs, B_RCVBUFREADY);
 321        }
 322        if (val & W_B_EXI_RMR) {        /* RMR */
 323                W6692B_empty_fifo(bcs, W_B_FIFO_THRESH);
 324                r = cs->BC_Read_Reg(cs, bchan, W_B_STAR);
 325                if (r & W_B_STAR_RDOV) {
 326                        if (cs->debug & L1_DEB_WARN)
 327                                debugl1(cs, "W6692 B RDOV(RMR) mode=%d", bcs->mode);
 328                        cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
 329                        if (bcs->mode != L1_MODE_TRANS)
 330                                bcs->hw.w6692.rcvidx = 0;
 331                }
 332                if (bcs->mode == L1_MODE_TRANS) {
 333                        /* receive audio data */
 334                        if (!(skb = dev_alloc_skb(W_B_FIFO_THRESH)))
 335                                printk(KERN_WARNING "HiSax: receive out of memory\n");
 336                        else {
 337                                skb_put_data(skb, bcs->hw.w6692.rcvbuf,
 338                                             W_B_FIFO_THRESH);
 339                                skb_queue_tail(&bcs->rqueue, skb);
 340                        }
 341                        bcs->hw.w6692.rcvidx = 0;
 342                        schedule_event(bcs, B_RCVBUFREADY);
 343                }
 344        }
 345        if (val & W_B_EXI_XDUN) {       /* XDUN */
 346                cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
 347                if (cs->debug & L1_DEB_WARN)
 348                        debugl1(cs, "W6692 B EXIR %x Lost TX", val);
 349                if (bcs->mode == 1)
 350                        W6692B_fill_fifo(bcs);
 351                else {
 352                        /* Here we lost an TX interrupt, so
 353                         * restart transmitting the whole frame.
 354                         */
 355                        if (bcs->tx_skb) {
 356                                skb_push(bcs->tx_skb, bcs->hw.w6692.count);
 357                                bcs->tx_cnt += bcs->hw.w6692.count;
 358                                bcs->hw.w6692.count = 0;
 359                        }
 360                }
 361                return;
 362        }
 363        if (val & W_B_EXI_XFR) {        /* XFR */
 364                r = cs->BC_Read_Reg(cs, bchan, W_B_STAR);
 365                if (r & W_B_STAR_XDOW) {
 366                        if (cs->debug & L1_DEB_WARN)
 367                                debugl1(cs, "W6692 B STAR %x XDOW", r);
 368                        cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
 369                        if (bcs->tx_skb && (bcs->mode != 1)) {
 370                                skb_push(bcs->tx_skb, bcs->hw.w6692.count);
 371                                bcs->tx_cnt += bcs->hw.w6692.count;
 372                                bcs->hw.w6692.count = 0;
 373                        }
 374                }
 375                if (bcs->tx_skb) {
 376                        if (bcs->tx_skb->len) {
 377                                W6692B_fill_fifo(bcs);
 378                                return;
 379                        } else {
 380                                if (test_bit(FLG_LLI_L1WAKEUP, &bcs->st->lli.flag) &&
 381                                    (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
 382                                        u_long flags;
 383                                        spin_lock_irqsave(&bcs->aclock, flags);
 384                                        bcs->ackcnt += bcs->hw.w6692.count;
 385                                        spin_unlock_irqrestore(&bcs->aclock, flags);
 386                                        schedule_event(bcs, B_ACKPENDING);
 387                                }
 388                                dev_kfree_skb_irq(bcs->tx_skb);
 389                                bcs->hw.w6692.count = 0;
 390                                bcs->tx_skb = NULL;
 391                        }
 392                }
 393                if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
 394                        bcs->hw.w6692.count = 0;
 395                        test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 396                        W6692B_fill_fifo(bcs);
 397                } else {
 398                        test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 399                        schedule_event(bcs, B_XMTBUFREADY);
 400                }
 401        }
 402}
 403
 404static irqreturn_t
 405W6692_interrupt(int intno, void *dev_id)
 406{
 407        struct IsdnCardState    *cs = dev_id;
 408        u_char                  val, exval, v1;
 409        struct sk_buff          *skb;
 410        u_int                   count;
 411        u_long                  flags;
 412        int                     icnt = 5;
 413
 414        spin_lock_irqsave(&cs->lock, flags);
 415        val = cs->readW6692(cs, W_ISTA);
 416        if (!val) {
 417                spin_unlock_irqrestore(&cs->lock, flags);
 418                return IRQ_NONE;
 419        }
 420StartW6692:
 421        if (cs->debug & L1_DEB_ISAC)
 422                debugl1(cs, "W6692 ISTA %x", val);
 423
 424        if (val & W_INT_D_RME) {        /* RME */
 425                exval = cs->readW6692(cs, W_D_RSTA);
 426                if (exval & (W_D_RSTA_RDOV | W_D_RSTA_CRCE | W_D_RSTA_RMB)) {
 427                        if (exval & W_D_RSTA_RDOV)
 428                                if (cs->debug & L1_DEB_WARN)
 429                                        debugl1(cs, "W6692 RDOV");
 430                        if (exval & W_D_RSTA_CRCE)
 431                                if (cs->debug & L1_DEB_WARN)
 432                                        debugl1(cs, "W6692 D-channel CRC error");
 433                        if (exval & W_D_RSTA_RMB)
 434                                if (cs->debug & L1_DEB_WARN)
 435                                        debugl1(cs, "W6692 D-channel ABORT");
 436                        cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST);
 437                } else {
 438                        count = cs->readW6692(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1);
 439                        if (count == 0)
 440                                count = W_D_FIFO_THRESH;
 441                        W6692_empty_fifo(cs, count);
 442                        if ((count = cs->rcvidx) > 0) {
 443                                cs->rcvidx = 0;
 444                                if (!(skb = alloc_skb(count, GFP_ATOMIC)))
 445                                        printk(KERN_WARNING "HiSax: D receive out of memory\n");
 446                                else {
 447                                        skb_put_data(skb, cs->rcvbuf, count);
 448                                        skb_queue_tail(&cs->rq, skb);
 449                                }
 450                        }
 451                }
 452                cs->rcvidx = 0;
 453                schedule_event(cs, D_RCVBUFREADY);
 454        }
 455        if (val & W_INT_D_RMR) {        /* RMR */
 456                W6692_empty_fifo(cs, W_D_FIFO_THRESH);
 457        }
 458        if (val & W_INT_D_XFR) {        /* XFR */
 459                if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 460                        del_timer(&cs->dbusytimer);
 461                if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
 462                        schedule_event(cs, D_CLEARBUSY);
 463                if (cs->tx_skb) {
 464                        if (cs->tx_skb->len) {
 465                                W6692_fill_fifo(cs);
 466                                goto afterXFR;
 467                        } else {
 468                                dev_kfree_skb_irq(cs->tx_skb);
 469                                cs->tx_cnt = 0;
 470                                cs->tx_skb = NULL;
 471                        }
 472                }
 473                if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
 474                        cs->tx_cnt = 0;
 475                        W6692_fill_fifo(cs);
 476                } else
 477                        schedule_event(cs, D_XMTBUFREADY);
 478        }
 479afterXFR:
 480        if (val & (W_INT_XINT0 | W_INT_XINT1)) {        /* XINT0/1 - never */
 481                if (cs->debug & L1_DEB_ISAC)
 482                        debugl1(cs, "W6692 spurious XINT!");
 483        }
 484        if (val & W_INT_D_EXI) {        /* EXI */
 485                exval = cs->readW6692(cs, W_D_EXIR);
 486                if (cs->debug & L1_DEB_WARN)
 487                        debugl1(cs, "W6692 D_EXIR %02x", exval);
 488                if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) {    /* Transmit underrun/collision */
 489                        debugl1(cs, "W6692 D-chan underrun/collision");
 490                        printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL\n");
 491                        if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 492                                del_timer(&cs->dbusytimer);
 493                        if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
 494                                schedule_event(cs, D_CLEARBUSY);
 495                        if (cs->tx_skb) {       /* Restart frame */
 496                                skb_push(cs->tx_skb, cs->tx_cnt);
 497                                cs->tx_cnt = 0;
 498                                W6692_fill_fifo(cs);
 499                        } else {
 500                                printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL no skb\n");
 501                                debugl1(cs, "W6692 XDUN/XCOL no skb");
 502                                cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST);
 503                        }
 504                }
 505                if (exval & W_D_EXI_RDOV) {     /* RDOV */
 506                        debugl1(cs, "W6692 D-channel RDOV");
 507                        printk(KERN_WARNING "HiSax: W6692 D-RDOV\n");
 508                        cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST);
 509                }
 510                if (exval & W_D_EXI_TIN2) {     /* TIN2 - never */
 511                        debugl1(cs, "W6692 spurious TIN2 interrupt");
 512                }
 513                if (exval & W_D_EXI_MOC) {      /* MOC - not supported */
 514                        debugl1(cs, "W6692 spurious MOC interrupt");
 515                        v1 = cs->readW6692(cs, W_MOSR);
 516                        debugl1(cs, "W6692 MOSR %02x", v1);
 517                }
 518                if (exval & W_D_EXI_ISC) {      /* ISC - Level1 change */
 519                        v1 = cs->readW6692(cs, W_CIR);
 520                        if (cs->debug & L1_DEB_ISAC)
 521                                debugl1(cs, "W6692 ISC CIR=0x%02X", v1);
 522                        if (v1 & W_CIR_ICC) {
 523                                cs->dc.w6692.ph_state = v1 & W_CIR_COD_MASK;
 524                                if (cs->debug & L1_DEB_ISAC)
 525                                        debugl1(cs, "ph_state_change %x", cs->dc.w6692.ph_state);
 526                                schedule_event(cs, D_L1STATECHANGE);
 527                        }
 528                        if (v1 & W_CIR_SCC) {
 529                                v1 = cs->readW6692(cs, W_SQR);
 530                                debugl1(cs, "W6692 SCC SQR=0x%02X", v1);
 531                        }
 532                }
 533                if (exval & W_D_EXI_WEXP) {
 534                        debugl1(cs, "W6692 spurious WEXP interrupt!");
 535                }
 536                if (exval & W_D_EXI_TEXP) {
 537                        debugl1(cs, "W6692 spurious TEXP interrupt!");
 538                }
 539        }
 540        if (val & W_INT_B1_EXI) {
 541                debugl1(cs, "W6692 B channel 1 interrupt");
 542                W6692B_interrupt(cs, 0);
 543        }
 544        if (val & W_INT_B2_EXI) {
 545                debugl1(cs, "W6692 B channel 2 interrupt");
 546                W6692B_interrupt(cs, 1);
 547        }
 548        val = cs->readW6692(cs, W_ISTA);
 549        if (val && icnt) {
 550                icnt--;
 551                goto StartW6692;
 552        }
 553        if (!icnt) {
 554                printk(KERN_WARNING "W6692 IRQ LOOP\n");
 555                cs->writeW6692(cs, W_IMASK, 0xff);
 556        }
 557        spin_unlock_irqrestore(&cs->lock, flags);
 558        return IRQ_HANDLED;
 559}
 560
 561static void
 562W6692_l1hw(struct PStack *st, int pr, void *arg)
 563{
 564        struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
 565        struct sk_buff *skb = arg;
 566        u_long flags;
 567        int val;
 568
 569        switch (pr) {
 570        case (PH_DATA | REQUEST):
 571                if (cs->debug & DEB_DLOG_HEX)
 572                        LogFrame(cs, skb->data, skb->len);
 573                if (cs->debug & DEB_DLOG_VERBOSE)
 574                        dlogframe(cs, skb, 0);
 575                spin_lock_irqsave(&cs->lock, flags);
 576                if (cs->tx_skb) {
 577                        skb_queue_tail(&cs->sq, skb);
 578#ifdef L2FRAME_DEBUG            /* psa */
 579                        if (cs->debug & L1_DEB_LAPD)
 580                                Logl2Frame(cs, skb, "PH_DATA Queued", 0);
 581#endif
 582                } else {
 583                        cs->tx_skb = skb;
 584                        cs->tx_cnt = 0;
 585#ifdef L2FRAME_DEBUG            /* psa */
 586                        if (cs->debug & L1_DEB_LAPD)
 587                                Logl2Frame(cs, skb, "PH_DATA", 0);
 588#endif
 589                        W6692_fill_fifo(cs);
 590                }
 591                spin_unlock_irqrestore(&cs->lock, flags);
 592                break;
 593        case (PH_PULL | INDICATION):
 594                spin_lock_irqsave(&cs->lock, flags);
 595                if (cs->tx_skb) {
 596                        if (cs->debug & L1_DEB_WARN)
 597                                debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
 598                        skb_queue_tail(&cs->sq, skb);
 599                        spin_unlock_irqrestore(&cs->lock, flags);
 600                        break;
 601                }
 602                if (cs->debug & DEB_DLOG_HEX)
 603                        LogFrame(cs, skb->data, skb->len);
 604                if (cs->debug & DEB_DLOG_VERBOSE)
 605                        dlogframe(cs, skb, 0);
 606                cs->tx_skb = skb;
 607                cs->tx_cnt = 0;
 608#ifdef L2FRAME_DEBUG            /* psa */
 609                if (cs->debug & L1_DEB_LAPD)
 610                        Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
 611#endif
 612                W6692_fill_fifo(cs);
 613                spin_unlock_irqrestore(&cs->lock, flags);
 614                break;
 615        case (PH_PULL | REQUEST):
 616#ifdef L2FRAME_DEBUG            /* psa */
 617                if (cs->debug & L1_DEB_LAPD)
 618                        debugl1(cs, "-> PH_REQUEST_PULL");
 619#endif
 620                if (!cs->tx_skb) {
 621                        test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 622                        st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 623                } else
 624                        test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 625                break;
 626        case (HW_RESET | REQUEST):
 627                spin_lock_irqsave(&cs->lock, flags);
 628                if ((cs->dc.w6692.ph_state == W_L1IND_DRD)) {
 629                        ph_command(cs, W_L1CMD_ECK);
 630                        spin_unlock_irqrestore(&cs->lock, flags);
 631                } else {
 632                        ph_command(cs, W_L1CMD_RST);
 633                        cs->dc.w6692.ph_state = W_L1CMD_RST;
 634                        spin_unlock_irqrestore(&cs->lock, flags);
 635                        W6692_new_ph(cs);
 636                }
 637                break;
 638        case (HW_ENABLE | REQUEST):
 639                spin_lock_irqsave(&cs->lock, flags);
 640                ph_command(cs, W_L1CMD_ECK);
 641                spin_unlock_irqrestore(&cs->lock, flags);
 642                break;
 643        case (HW_INFO3 | REQUEST):
 644                spin_lock_irqsave(&cs->lock, flags);
 645                ph_command(cs, W_L1CMD_AR8);
 646                spin_unlock_irqrestore(&cs->lock, flags);
 647                break;
 648        case (HW_TESTLOOP | REQUEST):
 649                val = 0;
 650                if (1 & (long) arg)
 651                        val |= 0x0c;
 652                if (2 & (long) arg)
 653                        val |= 0x3;
 654                /* !!! not implemented yet */
 655                break;
 656        case (HW_DEACTIVATE | RESPONSE):
 657                skb_queue_purge(&cs->rq);
 658                skb_queue_purge(&cs->sq);
 659                if (cs->tx_skb) {
 660                        dev_kfree_skb_any(cs->tx_skb);
 661                        cs->tx_skb = NULL;
 662                }
 663                if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 664                        del_timer(&cs->dbusytimer);
 665                if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
 666                        schedule_event(cs, D_CLEARBUSY);
 667                break;
 668        default:
 669                if (cs->debug & L1_DEB_WARN)
 670                        debugl1(cs, "W6692_l1hw unknown %04x", pr);
 671                break;
 672        }
 673}
 674
 675static void
 676setstack_W6692(struct PStack *st, struct IsdnCardState *cs)
 677{
 678        st->l1.l1hw = W6692_l1hw;
 679}
 680
 681static void
 682DC_Close_W6692(struct IsdnCardState *cs)
 683{
 684}
 685
 686static void
 687dbusy_timer_handler(struct IsdnCardState *cs)
 688{
 689        struct PStack *stptr;
 690        int rbch, star;
 691        u_long flags;
 692
 693        spin_lock_irqsave(&cs->lock, flags);
 694        if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
 695                rbch = cs->readW6692(cs, W_D_RBCH);
 696                star = cs->readW6692(cs, W_D_STAR);
 697                if (cs->debug)
 698                        debugl1(cs, "D-Channel Busy D_RBCH %02x D_STAR %02x",
 699                                rbch, star);
 700                if (star & W_D_STAR_XBZ) {      /* D-Channel Busy */
 701                        test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
 702                        stptr = cs->stlist;
 703                        while (stptr != NULL) {
 704                                stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
 705                                stptr = stptr->next;
 706                        }
 707                } else {
 708                        /* discard frame; reset transceiver */
 709                        test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags);
 710                        if (cs->tx_skb) {
 711                                dev_kfree_skb_any(cs->tx_skb);
 712                                cs->tx_cnt = 0;
 713                                cs->tx_skb = NULL;
 714                        } else {
 715                                printk(KERN_WARNING "HiSax: W6692 D-Channel Busy no skb\n");
 716                                debugl1(cs, "D-Channel Busy no skb");
 717                        }
 718                        cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST);    /* Transmitter reset */
 719                        spin_unlock_irqrestore(&cs->lock, flags);
 720                        cs->irq_func(cs->irq, cs);
 721                        return;
 722                }
 723        }
 724        spin_unlock_irqrestore(&cs->lock, flags);
 725}
 726
 727static void
 728W6692Bmode(struct BCState *bcs, int mode, int bchan)
 729{
 730        struct IsdnCardState *cs = bcs->cs;
 731
 732        if (cs->debug & L1_DEB_HSCX)
 733                debugl1(cs, "w6692 %c mode %d ichan %d",
 734                        '1' + bchan, mode, bchan);
 735        bcs->mode = mode;
 736        bcs->channel = bchan;
 737        bcs->hw.w6692.bchan = bchan;
 738
 739        switch (mode) {
 740        case (L1_MODE_NULL):
 741                cs->BC_Write_Reg(cs, bchan, W_B_MODE, 0);
 742                break;
 743        case (L1_MODE_TRANS):
 744                cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_MMS);
 745                break;
 746        case (L1_MODE_HDLC):
 747                cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_ITF);
 748                cs->BC_Write_Reg(cs, bchan, W_B_ADM1, 0xff);
 749                cs->BC_Write_Reg(cs, bchan, W_B_ADM2, 0xff);
 750                break;
 751        }
 752        if (mode)
 753                cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RRST |
 754                                 W_B_CMDR_RACT | W_B_CMDR_XRST);
 755        cs->BC_Write_Reg(cs, bchan, W_B_EXIM, 0x00);
 756}
 757
 758static void
 759W6692_l2l1(struct PStack *st, int pr, void *arg)
 760{
 761        struct sk_buff *skb = arg;
 762        struct BCState *bcs = st->l1.bcs;
 763        u_long flags;
 764
 765        switch (pr) {
 766        case (PH_DATA | REQUEST):
 767                spin_lock_irqsave(&bcs->cs->lock, flags);
 768                if (bcs->tx_skb) {
 769                        skb_queue_tail(&bcs->squeue, skb);
 770                } else {
 771                        bcs->tx_skb = skb;
 772                        test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 773                        bcs->hw.w6692.count = 0;
 774                        bcs->cs->BC_Send_Data(bcs);
 775                }
 776                spin_unlock_irqrestore(&bcs->cs->lock, flags);
 777                break;
 778        case (PH_PULL | INDICATION):
 779                if (bcs->tx_skb) {
 780                        printk(KERN_WARNING "W6692_l2l1: this shouldn't happen\n");
 781                        break;
 782                }
 783                spin_lock_irqsave(&bcs->cs->lock, flags);
 784                test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 785                bcs->tx_skb = skb;
 786                bcs->hw.w6692.count = 0;
 787                bcs->cs->BC_Send_Data(bcs);
 788                spin_unlock_irqrestore(&bcs->cs->lock, flags);
 789                break;
 790        case (PH_PULL | REQUEST):
 791                if (!bcs->tx_skb) {
 792                        test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 793                        st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 794                } else
 795                        test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 796                break;
 797        case (PH_ACTIVATE | REQUEST):
 798                spin_lock_irqsave(&bcs->cs->lock, flags);
 799                test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
 800                W6692Bmode(bcs, st->l1.mode, st->l1.bc);
 801                spin_unlock_irqrestore(&bcs->cs->lock, flags);
 802                l1_msg_b(st, pr, arg);
 803                break;
 804        case (PH_DEACTIVATE | REQUEST):
 805                l1_msg_b(st, pr, arg);
 806                break;
 807        case (PH_DEACTIVATE | CONFIRM):
 808                spin_lock_irqsave(&bcs->cs->lock, flags);
 809                test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
 810                test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 811                W6692Bmode(bcs, 0, st->l1.bc);
 812                spin_unlock_irqrestore(&bcs->cs->lock, flags);
 813                st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
 814                break;
 815        }
 816}
 817
 818static void
 819close_w6692state(struct BCState *bcs)
 820{
 821        W6692Bmode(bcs, 0, bcs->channel);
 822        if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
 823                kfree(bcs->hw.w6692.rcvbuf);
 824                bcs->hw.w6692.rcvbuf = NULL;
 825                kfree(bcs->blog);
 826                bcs->blog = NULL;
 827                skb_queue_purge(&bcs->rqueue);
 828                skb_queue_purge(&bcs->squeue);
 829                if (bcs->tx_skb) {
 830                        dev_kfree_skb_any(bcs->tx_skb);
 831                        bcs->tx_skb = NULL;
 832                        test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 833                }
 834        }
 835}
 836
 837static int
 838open_w6692state(struct IsdnCardState *cs, struct BCState *bcs)
 839{
 840        if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
 841                if (!(bcs->hw.w6692.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
 842                        printk(KERN_WARNING
 843                               "HiSax: No memory for w6692.rcvbuf\n");
 844                        test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
 845                        return (1);
 846                }
 847                if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
 848                        printk(KERN_WARNING
 849                               "HiSax: No memory for bcs->blog\n");
 850                        test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
 851                        kfree(bcs->hw.w6692.rcvbuf);
 852                        bcs->hw.w6692.rcvbuf = NULL;
 853                        return (2);
 854                }
 855                skb_queue_head_init(&bcs->rqueue);
 856                skb_queue_head_init(&bcs->squeue);
 857        }
 858        bcs->tx_skb = NULL;
 859        test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 860        bcs->event = 0;
 861        bcs->hw.w6692.rcvidx = 0;
 862        bcs->tx_cnt = 0;
 863        return (0);
 864}
 865
 866static int
 867setstack_w6692(struct PStack *st, struct BCState *bcs)
 868{
 869        bcs->channel = st->l1.bc;
 870        if (open_w6692state(st->l1.hardware, bcs))
 871                return (-1);
 872        st->l1.bcs = bcs;
 873        st->l2.l2l1 = W6692_l2l1;
 874        setstack_manager(st);
 875        bcs->st = st;
 876        setstack_l1_B(st);
 877        return (0);
 878}
 879
 880static void resetW6692(struct IsdnCardState *cs)
 881{
 882        cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST);
 883        mdelay(10);
 884        cs->writeW6692(cs, W_D_CTL, 0x00);
 885        mdelay(10);
 886        cs->writeW6692(cs, W_IMASK, 0xff);
 887        cs->writeW6692(cs, W_D_SAM, 0xff);
 888        cs->writeW6692(cs, W_D_TAM, 0xff);
 889        cs->writeW6692(cs, W_D_EXIM, 0x00);
 890        cs->writeW6692(cs, W_D_MODE, W_D_MODE_RACT);
 891        cs->writeW6692(cs, W_IMASK, 0x18);
 892        if (cs->subtyp == W6692_USR) {
 893                /* seems that USR implemented some power control features
 894                 * Pin 79 is connected to the oscilator circuit so we
 895                 * have to handle it here
 896                 */
 897                cs->writeW6692(cs, W_PCTL, 0x80);
 898                cs->writeW6692(cs, W_XDATA, 0x00);
 899        }
 900}
 901
 902static void initW6692(struct IsdnCardState *cs, int part)
 903{
 904        if (part & 1) {
 905                cs->setstack_d = setstack_W6692;
 906                cs->DC_Close = DC_Close_W6692;
 907                setup_timer(&cs->dbusytimer, (void *)dbusy_timer_handler,
 908                            (long)cs);
 909                resetW6692(cs);
 910                ph_command(cs, W_L1CMD_RST);
 911                cs->dc.w6692.ph_state = W_L1CMD_RST;
 912                W6692_new_ph(cs);
 913                ph_command(cs, W_L1CMD_ECK);
 914
 915                cs->bcs[0].BC_SetStack = setstack_w6692;
 916                cs->bcs[1].BC_SetStack = setstack_w6692;
 917                cs->bcs[0].BC_Close = close_w6692state;
 918                cs->bcs[1].BC_Close = close_w6692state;
 919                W6692Bmode(cs->bcs, 0, 0);
 920                W6692Bmode(cs->bcs + 1, 0, 0);
 921        }
 922        if (part & 2) {
 923                /* Reenable all IRQ */
 924                cs->writeW6692(cs, W_IMASK, 0x18);
 925                cs->writeW6692(cs, W_D_EXIM, 0x00);
 926                cs->BC_Write_Reg(cs, 0, W_B_EXIM, 0x00);
 927                cs->BC_Write_Reg(cs, 1, W_B_EXIM, 0x00);
 928                /* Reset D-chan receiver and transmitter */
 929                cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST);
 930        }
 931}
 932
 933/* Interface functions */
 934
 935static u_char
 936ReadW6692(struct IsdnCardState *cs, u_char offset)
 937{
 938        return (inb(cs->hw.w6692.iobase + offset));
 939}
 940
 941static void
 942WriteW6692(struct IsdnCardState *cs, u_char offset, u_char value)
 943{
 944        outb(value, cs->hw.w6692.iobase + offset);
 945}
 946
 947static void
 948ReadISACfifo(struct IsdnCardState *cs, u_char *data, int size)
 949{
 950        insb(cs->hw.w6692.iobase + W_D_RFIFO, data, size);
 951}
 952
 953static void
 954WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size)
 955{
 956        outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, size);
 957}
 958
 959static u_char
 960ReadW6692B(struct IsdnCardState *cs, int bchan, u_char offset)
 961{
 962        return (inb(cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset));
 963}
 964
 965static void
 966WriteW6692B(struct IsdnCardState *cs, int bchan, u_char offset, u_char value)
 967{
 968        outb(value, cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset);
 969}
 970
 971static int
 972w6692_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 973{
 974        switch (mt) {
 975        case CARD_RESET:
 976                resetW6692(cs);
 977                return (0);
 978        case CARD_RELEASE:
 979                cs->writeW6692(cs, W_IMASK, 0xff);
 980                release_region(cs->hw.w6692.iobase, 256);
 981                if (cs->subtyp == W6692_USR) {
 982                        cs->writeW6692(cs, W_XDATA, 0x04);
 983                }
 984                return (0);
 985        case CARD_INIT:
 986                initW6692(cs, 3);
 987                return (0);
 988        case CARD_TEST:
 989                return (0);
 990        }
 991        return (0);
 992}
 993
 994static int id_idx;
 995
 996static struct pci_dev *dev_w6692 = NULL;
 997
 998int setup_w6692(struct IsdnCard *card)
 999{
1000        struct IsdnCardState *cs = card->cs;
1001        char tmp[64];
1002        u_char found = 0;
1003        u_char pci_irq = 0;
1004        u_int pci_ioaddr = 0;
1005
1006        strcpy(tmp, w6692_revision);
1007        printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp));
1008        if (cs->typ != ISDN_CTYPE_W6692)
1009                return (0);
1010
1011        while (id_list[id_idx].vendor_id) {
1012                dev_w6692 = hisax_find_pci_device(id_list[id_idx].vendor_id,
1013                                                  id_list[id_idx].device_id,
1014                                                  dev_w6692);
1015                if (dev_w6692) {
1016                        if (pci_enable_device(dev_w6692))
1017                                continue;
1018                        cs->subtyp = id_idx;
1019                        break;
1020                }
1021                id_idx++;
1022        }
1023        if (dev_w6692) {
1024                found = 1;
1025                pci_irq = dev_w6692->irq;
1026                /* I think address 0 is allways the configuration area */
1027                /* and address 1 is the real IO space KKe 03.09.99 */
1028                pci_ioaddr = pci_resource_start(dev_w6692, 1);
1029                /* USR ISDN PCI card TA need some special handling */
1030                if (cs->subtyp == W6692_WINBOND) {
1031                        if ((W6692_SV_USR == dev_w6692->subsystem_vendor) &&
1032                            (W6692_SD_USR == dev_w6692->subsystem_device)) {
1033                                cs->subtyp = W6692_USR;
1034                        }
1035                }
1036        }
1037        if (!found) {
1038                printk(KERN_WARNING "W6692: No PCI card found\n");
1039                return (0);
1040        }
1041        cs->irq = pci_irq;
1042        if (!cs->irq) {
1043                printk(KERN_WARNING "W6692: No IRQ for PCI card found\n");
1044                return (0);
1045        }
1046        if (!pci_ioaddr) {
1047                printk(KERN_WARNING "W6692: NO I/O Base Address found\n");
1048                return (0);
1049        }
1050        cs->hw.w6692.iobase = pci_ioaddr;
1051        printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n",
1052               id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,
1053               pci_ioaddr, pci_irq);
1054        if (!request_region(cs->hw.w6692.iobase, 256, id_list[cs->subtyp].card_name)) {
1055                printk(KERN_WARNING
1056                       "HiSax: %s I/O ports %x-%x already in use\n",
1057                       id_list[cs->subtyp].card_name,
1058                       cs->hw.w6692.iobase,
1059                       cs->hw.w6692.iobase + 255);
1060                return (0);
1061        }
1062
1063        printk(KERN_INFO
1064               "HiSax: %s config irq:%d I/O:%x\n",
1065               id_list[cs->subtyp].card_name, cs->irq,
1066               cs->hw.w6692.iobase);
1067
1068        INIT_WORK(&cs->tqueue, W6692_bh);
1069        cs->readW6692 = &ReadW6692;
1070        cs->writeW6692 = &WriteW6692;
1071        cs->readisacfifo = &ReadISACfifo;
1072        cs->writeisacfifo = &WriteISACfifo;
1073        cs->BC_Read_Reg = &ReadW6692B;
1074        cs->BC_Write_Reg = &WriteW6692B;
1075        cs->BC_Send_Data = &W6692B_fill_fifo;
1076        cs->cardmsg = &w6692_card_msg;
1077        cs->irq_func = &W6692_interrupt;
1078        cs->irq_flags |= IRQF_SHARED;
1079        W6692Version(cs, "W6692:");
1080        printk(KERN_INFO "W6692 ISTA=0x%X\n", ReadW6692(cs, W_ISTA));
1081        printk(KERN_INFO "W6692 IMASK=0x%X\n", ReadW6692(cs, W_IMASK));
1082        printk(KERN_INFO "W6692 D_EXIR=0x%X\n", ReadW6692(cs, W_D_EXIR));
1083        printk(KERN_INFO "W6692 D_EXIM=0x%X\n", ReadW6692(cs, W_D_EXIM));
1084        printk(KERN_INFO "W6692 D_RSTA=0x%X\n", ReadW6692(cs, W_D_RSTA));
1085        return (1);
1086}
1087