1418 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * w6692.c mISDN driver for Winbond w6692 based cards4 *5 * Author Karsten Keil <kkeil@suse.de>6 * based on the w6692 I4L driver from Petr Novak <petr.novak@i.cz>7 *8 * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>9 */10 11#include <linux/interrupt.h>12#include <linux/module.h>13#include <linux/pci.h>14#include <linux/delay.h>15#include <linux/mISDNhw.h>16#include <linux/slab.h>17#include "w6692.h"18 19#define W6692_REV "2.0"20 21#define DBUSY_TIMER_VALUE 8022 23enum {24 W6692_ASUS,25 W6692_WINBOND,26 W6692_USR27};28 29/* private data in the PCI devices list */30struct w6692map {31 u_int subtype;32 char *name;33};34 35static const struct w6692map w6692_map[] =36{37 {W6692_ASUS, "Dynalink/AsusCom IS64PH"},38 {W6692_WINBOND, "Winbond W6692"},39 {W6692_USR, "USR W6692"}40};41 42#define PCI_DEVICE_ID_USR_6692 0x340943 44struct w6692_ch {45 struct bchannel bch;46 u32 addr;47 struct timer_list timer;48 u8 b_mode;49};50 51struct w6692_hw {52 struct list_head list;53 struct pci_dev *pdev;54 char name[MISDN_MAX_IDLEN];55 u32 irq;56 u32 irqcnt;57 u32 addr;58 u32 fmask; /* feature mask - bit set per card nr */59 int subtype;60 spinlock_t lock; /* hw lock */61 u8 imask;62 u8 pctl;63 u8 xaddr;64 u8 xdata;65 u8 state;66 struct w6692_ch bc[2];67 struct dchannel dch;68 char log[64];69};70 71static LIST_HEAD(Cards);72static DEFINE_RWLOCK(card_lock); /* protect Cards */73 74static int w6692_cnt;75static int debug;76static u32 led;77static u32 pots;78 79static void80_set_debug(struct w6692_hw *card)81{82 card->dch.debug = debug;83 card->bc[0].bch.debug = debug;84 card->bc[1].bch.debug = debug;85}86 87static int88set_debug(const char *val, const struct kernel_param *kp)89{90 int ret;91 struct w6692_hw *card;92 93 ret = param_set_uint(val, kp);94 if (!ret) {95 read_lock(&card_lock);96 list_for_each_entry(card, &Cards, list)97 _set_debug(card);98 read_unlock(&card_lock);99 }100 return ret;101}102 103MODULE_AUTHOR("Karsten Keil");104MODULE_DESCRIPTION("mISDN driver for Winbond w6692 based cards");105MODULE_LICENSE("GPL v2");106MODULE_VERSION(W6692_REV);107module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);108MODULE_PARM_DESC(debug, "W6692 debug mask");109module_param(led, uint, S_IRUGO | S_IWUSR);110MODULE_PARM_DESC(led, "W6692 LED support bitmask (one bit per card)");111module_param(pots, uint, S_IRUGO | S_IWUSR);112MODULE_PARM_DESC(pots, "W6692 POTS support bitmask (one bit per card)");113 114static inline u8115ReadW6692(struct w6692_hw *card, u8 offset)116{117 return inb(card->addr + offset);118}119 120static inline void121WriteW6692(struct w6692_hw *card, u8 offset, u8 value)122{123 outb(value, card->addr + offset);124}125 126static inline u8127ReadW6692B(struct w6692_ch *bc, u8 offset)128{129 return inb(bc->addr + offset);130}131 132static inline void133WriteW6692B(struct w6692_ch *bc, u8 offset, u8 value)134{135 outb(value, bc->addr + offset);136}137 138static void139enable_hwirq(struct w6692_hw *card)140{141 WriteW6692(card, W_IMASK, card->imask);142}143 144static void145disable_hwirq(struct w6692_hw *card)146{147 WriteW6692(card, W_IMASK, 0xff);148}149 150static const char *W6692Ver[] = {"V00", "V01", "V10", "V11"};151 152static void153W6692Version(struct w6692_hw *card)154{155 int val;156 157 val = ReadW6692(card, W_D_RBCH);158 pr_notice("%s: Winbond W6692 version: %s\n", card->name,159 W6692Ver[(val >> 6) & 3]);160}161 162static void163w6692_led_handler(struct w6692_hw *card, int on)164{165 if ((!(card->fmask & led)) || card->subtype == W6692_USR)166 return;167 if (on) {168 card->xdata &= 0xfb; /* LED ON */169 WriteW6692(card, W_XDATA, card->xdata);170 } else {171 card->xdata |= 0x04; /* LED OFF */172 WriteW6692(card, W_XDATA, card->xdata);173 }174}175 176static void177ph_command(struct w6692_hw *card, u8 cmd)178{179 pr_debug("%s: ph_command %x\n", card->name, cmd);180 WriteW6692(card, W_CIX, cmd);181}182 183static void184W6692_new_ph(struct w6692_hw *card)185{186 if (card->state == W_L1CMD_RST)187 ph_command(card, W_L1CMD_DRC);188 schedule_event(&card->dch, FLG_PHCHANGE);189}190 191static void192W6692_ph_bh(struct dchannel *dch)193{194 struct w6692_hw *card = dch->hw;195 196 switch (card->state) {197 case W_L1CMD_RST:198 dch->state = 0;199 l1_event(dch->l1, HW_RESET_IND);200 break;201 case W_L1IND_CD:202 dch->state = 3;203 l1_event(dch->l1, HW_DEACT_CNF);204 break;205 case W_L1IND_DRD:206 dch->state = 3;207 l1_event(dch->l1, HW_DEACT_IND);208 break;209 case W_L1IND_CE:210 dch->state = 4;211 l1_event(dch->l1, HW_POWERUP_IND);212 break;213 case W_L1IND_LD:214 if (dch->state <= 5) {215 dch->state = 5;216 l1_event(dch->l1, ANYSIGNAL);217 } else {218 dch->state = 8;219 l1_event(dch->l1, LOSTFRAMING);220 }221 break;222 case W_L1IND_ARD:223 dch->state = 6;224 l1_event(dch->l1, INFO2);225 break;226 case W_L1IND_AI8:227 dch->state = 7;228 l1_event(dch->l1, INFO4_P8);229 break;230 case W_L1IND_AI10:231 dch->state = 7;232 l1_event(dch->l1, INFO4_P10);233 break;234 default:235 pr_debug("%s: TE unknown state %02x dch state %02x\n",236 card->name, card->state, dch->state);237 break;238 }239 pr_debug("%s: TE newstate %02x\n", card->name, dch->state);240}241 242static void243W6692_empty_Dfifo(struct w6692_hw *card, int count)244{245 struct dchannel *dch = &card->dch;246 u8 *ptr;247 248 pr_debug("%s: empty_Dfifo %d\n", card->name, count);249 if (!dch->rx_skb) {250 dch->rx_skb = mI_alloc_skb(card->dch.maxlen, GFP_ATOMIC);251 if (!dch->rx_skb) {252 pr_info("%s: D receive out of memory\n", card->name);253 WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);254 return;255 }256 }257 if ((dch->rx_skb->len + count) >= dch->maxlen) {258 pr_debug("%s: empty_Dfifo overrun %d\n", card->name,259 dch->rx_skb->len + count);260 WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);261 return;262 }263 ptr = skb_put(dch->rx_skb, count);264 insb(card->addr + W_D_RFIFO, ptr, count);265 WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);266 if (debug & DEBUG_HW_DFIFO) {267 snprintf(card->log, 63, "D-recv %s %d ",268 card->name, count);269 print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count);270 }271}272 273static void274W6692_fill_Dfifo(struct w6692_hw *card)275{276 struct dchannel *dch = &card->dch;277 int count;278 u8 *ptr;279 u8 cmd = W_D_CMDR_XMS;280 281 pr_debug("%s: fill_Dfifo\n", card->name);282 if (!dch->tx_skb)283 return;284 count = dch->tx_skb->len - dch->tx_idx;285 if (count <= 0)286 return;287 if (count > W_D_FIFO_THRESH)288 count = W_D_FIFO_THRESH;289 else290 cmd |= W_D_CMDR_XME;291 ptr = dch->tx_skb->data + dch->tx_idx;292 dch->tx_idx += count;293 outsb(card->addr + W_D_XFIFO, ptr, count);294 WriteW6692(card, W_D_CMDR, cmd);295 if (test_and_set_bit(FLG_BUSY_TIMER, &dch->Flags)) {296 pr_debug("%s: fill_Dfifo dbusytimer running\n", card->name);297 del_timer(&dch->timer);298 }299 dch->timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000);300 add_timer(&dch->timer);301 if (debug & DEBUG_HW_DFIFO) {302 snprintf(card->log, 63, "D-send %s %d ",303 card->name, count);304 print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count);305 }306}307 308static void309d_retransmit(struct w6692_hw *card)310{311 struct dchannel *dch = &card->dch;312 313 if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))314 del_timer(&dch->timer);315#ifdef FIXME316 if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags))317 dchannel_sched_event(dch, D_CLEARBUSY);318#endif319 if (test_bit(FLG_TX_BUSY, &dch->Flags)) {320 /* Restart frame */321 dch->tx_idx = 0;322 W6692_fill_Dfifo(card);323 } else if (dch->tx_skb) { /* should not happen */324 pr_info("%s: %s without TX_BUSY\n", card->name, __func__);325 test_and_set_bit(FLG_TX_BUSY, &dch->Flags);326 dch->tx_idx = 0;327 W6692_fill_Dfifo(card);328 } else {329 pr_info("%s: XDU no TX_BUSY\n", card->name);330 if (get_next_dframe(dch))331 W6692_fill_Dfifo(card);332 }333}334 335static void336handle_rxD(struct w6692_hw *card) {337 u8 stat;338 int count;339 340 stat = ReadW6692(card, W_D_RSTA);341 if (stat & (W_D_RSTA_RDOV | W_D_RSTA_CRCE | W_D_RSTA_RMB)) {342 if (stat & W_D_RSTA_RDOV) {343 pr_debug("%s: D-channel RDOV\n", card->name);344#ifdef ERROR_STATISTIC345 card->dch.err_rx++;346#endif347 }348 if (stat & W_D_RSTA_CRCE) {349 pr_debug("%s: D-channel CRC error\n", card->name);350#ifdef ERROR_STATISTIC351 card->dch.err_crc++;352#endif353 }354 if (stat & W_D_RSTA_RMB) {355 pr_debug("%s: D-channel ABORT\n", card->name);356#ifdef ERROR_STATISTIC357 card->dch.err_rx++;358#endif359 }360 dev_kfree_skb(card->dch.rx_skb);361 card->dch.rx_skb = NULL;362 WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST);363 } else {364 count = ReadW6692(card, W_D_RBCL) & (W_D_FIFO_THRESH - 1);365 if (count == 0)366 count = W_D_FIFO_THRESH;367 W6692_empty_Dfifo(card, count);368 recv_Dchannel(&card->dch);369 }370}371 372static void373handle_txD(struct w6692_hw *card) {374 if (test_and_clear_bit(FLG_BUSY_TIMER, &card->dch.Flags))375 del_timer(&card->dch.timer);376 if (card->dch.tx_skb && card->dch.tx_idx < card->dch.tx_skb->len) {377 W6692_fill_Dfifo(card);378 } else {379 dev_kfree_skb(card->dch.tx_skb);380 if (get_next_dframe(&card->dch))381 W6692_fill_Dfifo(card);382 }383}384 385static void386handle_statusD(struct w6692_hw *card)387{388 struct dchannel *dch = &card->dch;389 u8 exval, v1, cir;390 391 exval = ReadW6692(card, W_D_EXIR);392 393 pr_debug("%s: D_EXIR %02x\n", card->name, exval);394 if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) {395 /* Transmit underrun/collision */396 pr_debug("%s: D-channel underrun/collision\n", card->name);397#ifdef ERROR_STATISTIC398 dch->err_tx++;399#endif400 d_retransmit(card);401 }402 if (exval & W_D_EXI_RDOV) { /* RDOV */403 pr_debug("%s: D-channel RDOV\n", card->name);404 WriteW6692(card, W_D_CMDR, W_D_CMDR_RRST);405 }406 if (exval & W_D_EXI_TIN2) /* TIN2 - never */407 pr_debug("%s: spurious TIN2 interrupt\n", card->name);408 if (exval & W_D_EXI_MOC) { /* MOC - not supported */409 v1 = ReadW6692(card, W_MOSR);410 pr_debug("%s: spurious MOC interrupt MOSR %02x\n",411 card->name, v1);412 }413 if (exval & W_D_EXI_ISC) { /* ISC - Level1 change */414 cir = ReadW6692(card, W_CIR);415 pr_debug("%s: ISC CIR %02X\n", card->name, cir);416 if (cir & W_CIR_ICC) {417 v1 = cir & W_CIR_COD_MASK;418 pr_debug("%s: ph_state_change %x -> %x\n", card->name,419 dch->state, v1);420 card->state = v1;421 if (card->fmask & led) {422 switch (v1) {423 case W_L1IND_AI8:424 case W_L1IND_AI10:425 w6692_led_handler(card, 1);426 break;427 default:428 w6692_led_handler(card, 0);429 break;430 }431 }432 W6692_new_ph(card);433 }434 if (cir & W_CIR_SCC) {435 v1 = ReadW6692(card, W_SQR);436 pr_debug("%s: SCC SQR %02X\n", card->name, v1);437 }438 }439 if (exval & W_D_EXI_WEXP)440 pr_debug("%s: spurious WEXP interrupt!\n", card->name);441 if (exval & W_D_EXI_TEXP)442 pr_debug("%s: spurious TEXP interrupt!\n", card->name);443}444 445static void446W6692_empty_Bfifo(struct w6692_ch *wch, int count)447{448 struct w6692_hw *card = wch->bch.hw;449 u8 *ptr;450 int maxlen;451 452 pr_debug("%s: empty_Bfifo %d\n", card->name, count);453 if (unlikely(wch->bch.state == ISDN_P_NONE)) {454 pr_debug("%s: empty_Bfifo ISDN_P_NONE\n", card->name);455 WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);456 if (wch->bch.rx_skb)457 skb_trim(wch->bch.rx_skb, 0);458 return;459 }460 if (test_bit(FLG_RX_OFF, &wch->bch.Flags)) {461 wch->bch.dropcnt += count;462 WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);463 return;464 }465 maxlen = bchannel_get_rxbuf(&wch->bch, count);466 if (maxlen < 0) {467 WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);468 if (wch->bch.rx_skb)469 skb_trim(wch->bch.rx_skb, 0);470 pr_warn("%s.B%d: No bufferspace for %d bytes\n",471 card->name, wch->bch.nr, count);472 return;473 }474 ptr = skb_put(wch->bch.rx_skb, count);475 insb(wch->addr + W_B_RFIFO, ptr, count);476 WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);477 if (debug & DEBUG_HW_DFIFO) {478 snprintf(card->log, 63, "B%1d-recv %s %d ",479 wch->bch.nr, card->name, count);480 print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count);481 }482}483 484static void485W6692_fill_Bfifo(struct w6692_ch *wch)486{487 struct w6692_hw *card = wch->bch.hw;488 int count, fillempty = 0;489 u8 *ptr, cmd = W_B_CMDR_RACT | W_B_CMDR_XMS;490 491 pr_debug("%s: fill Bfifo\n", card->name);492 if (!wch->bch.tx_skb) {493 if (!test_bit(FLG_TX_EMPTY, &wch->bch.Flags))494 return;495 ptr = wch->bch.fill;496 count = W_B_FIFO_THRESH;497 fillempty = 1;498 } else {499 count = wch->bch.tx_skb->len - wch->bch.tx_idx;500 if (count <= 0)501 return;502 ptr = wch->bch.tx_skb->data + wch->bch.tx_idx;503 }504 if (count > W_B_FIFO_THRESH)505 count = W_B_FIFO_THRESH;506 else if (test_bit(FLG_HDLC, &wch->bch.Flags))507 cmd |= W_B_CMDR_XME;508 509 pr_debug("%s: fill Bfifo%d/%d\n", card->name,510 count, wch->bch.tx_idx);511 wch->bch.tx_idx += count;512 if (fillempty) {513 while (count > 0) {514 outsb(wch->addr + W_B_XFIFO, ptr, MISDN_BCH_FILL_SIZE);515 count -= MISDN_BCH_FILL_SIZE;516 }517 } else {518 outsb(wch->addr + W_B_XFIFO, ptr, count);519 }520 WriteW6692B(wch, W_B_CMDR, cmd);521 if ((debug & DEBUG_HW_BFIFO) && !fillempty) {522 snprintf(card->log, 63, "B%1d-send %s %d ",523 wch->bch.nr, card->name, count);524 print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count);525 }526}527 528#if 0529static int530setvolume(struct w6692_ch *wch, int mic, struct sk_buff *skb)531{532 struct w6692_hw *card = wch->bch.hw;533 u16 *vol = (u16 *)skb->data;534 u8 val;535 536 if ((!(card->fmask & pots)) ||537 !test_bit(FLG_TRANSPARENT, &wch->bch.Flags))538 return -ENODEV;539 if (skb->len < 2)540 return -EINVAL;541 if (*vol > 7)542 return -EINVAL;543 val = *vol & 7;544 val = 7 - val;545 if (mic) {546 val <<= 3;547 card->xaddr &= 0xc7;548 } else {549 card->xaddr &= 0xf8;550 }551 card->xaddr |= val;552 WriteW6692(card, W_XADDR, card->xaddr);553 return 0;554}555 556static int557enable_pots(struct w6692_ch *wch)558{559 struct w6692_hw *card = wch->bch.hw;560 561 if ((!(card->fmask & pots)) ||562 !test_bit(FLG_TRANSPARENT, &wch->bch.Flags))563 return -ENODEV;564 wch->b_mode |= W_B_MODE_EPCM | W_B_MODE_BSW0;565 WriteW6692B(wch, W_B_MODE, wch->b_mode);566 WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);567 card->pctl |= ((wch->bch.nr & 2) ? W_PCTL_PCX : 0);568 WriteW6692(card, W_PCTL, card->pctl);569 return 0;570}571#endif572 573static int574disable_pots(struct w6692_ch *wch)575{576 struct w6692_hw *card = wch->bch.hw;577 578 if (!(card->fmask & pots))579 return -ENODEV;580 wch->b_mode &= ~(W_B_MODE_EPCM | W_B_MODE_BSW0);581 WriteW6692B(wch, W_B_MODE, wch->b_mode);582 WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT |583 W_B_CMDR_XRST);584 return 0;585}586 587static int588w6692_mode(struct w6692_ch *wch, u32 pr)589{590 struct w6692_hw *card;591 592 card = wch->bch.hw;593 pr_debug("%s: B%d protocol %x-->%x\n", card->name,594 wch->bch.nr, wch->bch.state, pr);595 switch (pr) {596 case ISDN_P_NONE:597 if ((card->fmask & pots) && (wch->b_mode & W_B_MODE_EPCM))598 disable_pots(wch);599 wch->b_mode = 0;600 mISDN_clear_bchannel(&wch->bch);601 WriteW6692B(wch, W_B_MODE, wch->b_mode);602 WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);603 test_and_clear_bit(FLG_HDLC, &wch->bch.Flags);604 test_and_clear_bit(FLG_TRANSPARENT, &wch->bch.Flags);605 break;606 case ISDN_P_B_RAW:607 wch->b_mode = W_B_MODE_MMS;608 WriteW6692B(wch, W_B_MODE, wch->b_mode);609 WriteW6692B(wch, W_B_EXIM, 0);610 WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT |611 W_B_CMDR_XRST);612 test_and_set_bit(FLG_TRANSPARENT, &wch->bch.Flags);613 break;614 case ISDN_P_B_HDLC:615 wch->b_mode = W_B_MODE_ITF;616 WriteW6692B(wch, W_B_MODE, wch->b_mode);617 WriteW6692B(wch, W_B_ADM1, 0xff);618 WriteW6692B(wch, W_B_ADM2, 0xff);619 WriteW6692B(wch, W_B_EXIM, 0);620 WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT |621 W_B_CMDR_XRST);622 test_and_set_bit(FLG_HDLC, &wch->bch.Flags);623 break;624 default:625 pr_info("%s: protocol %x not known\n", card->name, pr);626 return -ENOPROTOOPT;627 }628 wch->bch.state = pr;629 return 0;630}631 632static void633send_next(struct w6692_ch *wch)634{635 if (wch->bch.tx_skb && wch->bch.tx_idx < wch->bch.tx_skb->len) {636 W6692_fill_Bfifo(wch);637 } else {638 dev_kfree_skb(wch->bch.tx_skb);639 if (get_next_bframe(&wch->bch)) {640 W6692_fill_Bfifo(wch);641 test_and_clear_bit(FLG_TX_EMPTY, &wch->bch.Flags);642 } else if (test_bit(FLG_TX_EMPTY, &wch->bch.Flags)) {643 W6692_fill_Bfifo(wch);644 }645 }646}647 648static void649W6692B_interrupt(struct w6692_hw *card, int ch)650{651 struct w6692_ch *wch = &card->bc[ch];652 int count;653 u8 stat, star = 0;654 655 stat = ReadW6692B(wch, W_B_EXIR);656 pr_debug("%s: B%d EXIR %02x\n", card->name, wch->bch.nr, stat);657 if (stat & W_B_EXI_RME) {658 star = ReadW6692B(wch, W_B_STAR);659 if (star & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB)) {660 if ((star & W_B_STAR_RDOV) &&661 test_bit(FLG_ACTIVE, &wch->bch.Flags)) {662 pr_debug("%s: B%d RDOV proto=%x\n", card->name,663 wch->bch.nr, wch->bch.state);664#ifdef ERROR_STATISTIC665 wch->bch.err_rdo++;666#endif667 }668 if (test_bit(FLG_HDLC, &wch->bch.Flags)) {669 if (star & W_B_STAR_CRCE) {670 pr_debug("%s: B%d CRC error\n",671 card->name, wch->bch.nr);672#ifdef ERROR_STATISTIC673 wch->bch.err_crc++;674#endif675 }676 if (star & W_B_STAR_RMB) {677 pr_debug("%s: B%d message abort\n",678 card->name, wch->bch.nr);679#ifdef ERROR_STATISTIC680 wch->bch.err_inv++;681#endif682 }683 }684 WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK |685 W_B_CMDR_RRST | W_B_CMDR_RACT);686 if (wch->bch.rx_skb)687 skb_trim(wch->bch.rx_skb, 0);688 } else {689 count = ReadW6692B(wch, W_B_RBCL) &690 (W_B_FIFO_THRESH - 1);691 if (count == 0)692 count = W_B_FIFO_THRESH;693 W6692_empty_Bfifo(wch, count);694 recv_Bchannel(&wch->bch, 0, false);695 }696 }697 if (stat & W_B_EXI_RMR) {698 if (!(stat & W_B_EXI_RME))699 star = ReadW6692B(wch, W_B_STAR);700 if (star & W_B_STAR_RDOV) {701 pr_debug("%s: B%d RDOV proto=%x\n", card->name,702 wch->bch.nr, wch->bch.state);703#ifdef ERROR_STATISTIC704 wch->bch.err_rdo++;705#endif706 WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK |707 W_B_CMDR_RRST | W_B_CMDR_RACT);708 } else {709 W6692_empty_Bfifo(wch, W_B_FIFO_THRESH);710 if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags))711 recv_Bchannel(&wch->bch, 0, false);712 }713 }714 if (stat & W_B_EXI_RDOV) {715 /* only if it is not handled yet */716 if (!(star & W_B_STAR_RDOV)) {717 pr_debug("%s: B%d RDOV IRQ proto=%x\n", card->name,718 wch->bch.nr, wch->bch.state);719#ifdef ERROR_STATISTIC720 wch->bch.err_rdo++;721#endif722 WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK |723 W_B_CMDR_RRST | W_B_CMDR_RACT);724 }725 }726 if (stat & W_B_EXI_XFR) {727 if (!(stat & (W_B_EXI_RME | W_B_EXI_RMR))) {728 star = ReadW6692B(wch, W_B_STAR);729 pr_debug("%s: B%d star %02x\n", card->name,730 wch->bch.nr, star);731 }732 if (star & W_B_STAR_XDOW) {733 pr_warn("%s: B%d XDOW proto=%x\n", card->name,734 wch->bch.nr, wch->bch.state);735#ifdef ERROR_STATISTIC736 wch->bch.err_xdu++;737#endif738 WriteW6692B(wch, W_B_CMDR, W_B_CMDR_XRST |739 W_B_CMDR_RACT);740 /* resend */741 if (wch->bch.tx_skb) {742 if (!test_bit(FLG_TRANSPARENT, &wch->bch.Flags))743 wch->bch.tx_idx = 0;744 }745 }746 send_next(wch);747 if (star & W_B_STAR_XDOW)748 return; /* handle XDOW only once */749 }750 if (stat & W_B_EXI_XDUN) {751 pr_warn("%s: B%d XDUN proto=%x\n", card->name,752 wch->bch.nr, wch->bch.state);753#ifdef ERROR_STATISTIC754 wch->bch.err_xdu++;755#endif756 /* resend - no XRST needed */757 if (wch->bch.tx_skb) {758 if (!test_bit(FLG_TRANSPARENT, &wch->bch.Flags))759 wch->bch.tx_idx = 0;760 } else if (test_bit(FLG_FILLEMPTY, &wch->bch.Flags)) {761 test_and_set_bit(FLG_TX_EMPTY, &wch->bch.Flags);762 }763 send_next(wch);764 }765}766 767static irqreturn_t768w6692_irq(int intno, void *dev_id)769{770 struct w6692_hw *card = dev_id;771 u8 ista;772 773 spin_lock(&card->lock);774 ista = ReadW6692(card, W_ISTA);775 if ((ista | card->imask) == card->imask) {776 /* possible a shared IRQ reqest */777 spin_unlock(&card->lock);778 return IRQ_NONE;779 }780 card->irqcnt++;781 pr_debug("%s: ista %02x\n", card->name, ista);782 ista &= ~card->imask;783 if (ista & W_INT_B1_EXI)784 W6692B_interrupt(card, 0);785 if (ista & W_INT_B2_EXI)786 W6692B_interrupt(card, 1);787 if (ista & W_INT_D_RME)788 handle_rxD(card);789 if (ista & W_INT_D_RMR)790 W6692_empty_Dfifo(card, W_D_FIFO_THRESH);791 if (ista & W_INT_D_XFR)792 handle_txD(card);793 if (ista & W_INT_D_EXI)794 handle_statusD(card);795 if (ista & (W_INT_XINT0 | W_INT_XINT1)) /* XINT0/1 - never */796 pr_debug("%s: W6692 spurious XINT!\n", card->name);797/* End IRQ Handler */798 spin_unlock(&card->lock);799 return IRQ_HANDLED;800}801 802static void803dbusy_timer_handler(struct timer_list *t)804{805 struct dchannel *dch = from_timer(dch, t, timer);806 struct w6692_hw *card = dch->hw;807 int rbch, star;808 u_long flags;809 810 if (test_bit(FLG_BUSY_TIMER, &dch->Flags)) {811 spin_lock_irqsave(&card->lock, flags);812 rbch = ReadW6692(card, W_D_RBCH);813 star = ReadW6692(card, W_D_STAR);814 pr_debug("%s: D-Channel Busy RBCH %02x STAR %02x\n",815 card->name, rbch, star);816 if (star & W_D_STAR_XBZ) /* D-Channel Busy */817 test_and_set_bit(FLG_L1_BUSY, &dch->Flags);818 else {819 /* discard frame; reset transceiver */820 test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags);821 if (dch->tx_idx)822 dch->tx_idx = 0;823 else824 pr_info("%s: W6692 D-Channel Busy no tx_idx\n",825 card->name);826 /* Transmitter reset */827 WriteW6692(card, W_D_CMDR, W_D_CMDR_XRST);828 }829 spin_unlock_irqrestore(&card->lock, flags);830 }831}832 833static void initW6692(struct w6692_hw *card)834{835 u8 val;836 837 timer_setup(&card->dch.timer, dbusy_timer_handler, 0);838 w6692_mode(&card->bc[0], ISDN_P_NONE);839 w6692_mode(&card->bc[1], ISDN_P_NONE);840 WriteW6692(card, W_D_CTL, 0x00);841 disable_hwirq(card);842 WriteW6692(card, W_D_SAM, 0xff);843 WriteW6692(card, W_D_TAM, 0xff);844 WriteW6692(card, W_D_MODE, W_D_MODE_RACT);845 card->state = W_L1CMD_RST;846 ph_command(card, W_L1CMD_RST);847 ph_command(card, W_L1CMD_ECK);848 /* enable all IRQ but extern */849 card->imask = 0x18;850 WriteW6692(card, W_D_EXIM, 0x00);851 WriteW6692B(&card->bc[0], W_B_EXIM, 0);852 WriteW6692B(&card->bc[1], W_B_EXIM, 0);853 /* Reset D-chan receiver and transmitter */854 WriteW6692(card, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST);855 /* Reset B-chan receiver and transmitter */856 WriteW6692B(&card->bc[0], W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);857 WriteW6692B(&card->bc[1], W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);858 /* enable peripheral */859 if (card->subtype == W6692_USR) {860 /* seems that USR implemented some power control features861 * Pin 79 is connected to the oscilator circuit so we862 * have to handle it here863 */864 card->pctl = 0x80;865 card->xdata = 0;866 WriteW6692(card, W_PCTL, card->pctl);867 WriteW6692(card, W_XDATA, card->xdata);868 } else {869 card->pctl = W_PCTL_OE5 | W_PCTL_OE4 | W_PCTL_OE2 |870 W_PCTL_OE1 | W_PCTL_OE0;871 card->xaddr = 0x00;/* all sw off */872 if (card->fmask & pots)873 card->xdata |= 0x06; /* POWER UP/ LED OFF / ALAW */874 if (card->fmask & led)875 card->xdata |= 0x04; /* LED OFF */876 if ((card->fmask & pots) || (card->fmask & led)) {877 WriteW6692(card, W_PCTL, card->pctl);878 WriteW6692(card, W_XADDR, card->xaddr);879 WriteW6692(card, W_XDATA, card->xdata);880 val = ReadW6692(card, W_XADDR);881 if (debug & DEBUG_HW)882 pr_notice("%s: W_XADDR=%02x\n",883 card->name, val);884 }885 }886}887 888static void889reset_w6692(struct w6692_hw *card)890{891 WriteW6692(card, W_D_CTL, W_D_CTL_SRST);892 mdelay(10);893 WriteW6692(card, W_D_CTL, 0);894}895 896static int897init_card(struct w6692_hw *card)898{899 int cnt = 3;900 u_long flags;901 902 spin_lock_irqsave(&card->lock, flags);903 disable_hwirq(card);904 spin_unlock_irqrestore(&card->lock, flags);905 if (request_irq(card->irq, w6692_irq, IRQF_SHARED, card->name, card)) {906 pr_info("%s: couldn't get interrupt %d\n", card->name,907 card->irq);908 return -EIO;909 }910 while (cnt--) {911 spin_lock_irqsave(&card->lock, flags);912 initW6692(card);913 enable_hwirq(card);914 spin_unlock_irqrestore(&card->lock, flags);915 /* Timeout 10ms */916 msleep_interruptible(10);917 if (debug & DEBUG_HW)918 pr_notice("%s: IRQ %d count %d\n", card->name,919 card->irq, card->irqcnt);920 if (!card->irqcnt) {921 pr_info("%s: IRQ(%d) getting no IRQs during init %d\n",922 card->name, card->irq, 3 - cnt);923 reset_w6692(card);924 } else925 return 0;926 }927 free_irq(card->irq, card);928 return -EIO;929}930 931static int932w6692_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)933{934 struct bchannel *bch = container_of(ch, struct bchannel, ch);935 struct w6692_ch *bc = container_of(bch, struct w6692_ch, bch);936 struct w6692_hw *card = bch->hw;937 int ret = -EINVAL;938 struct mISDNhead *hh = mISDN_HEAD_P(skb);939 unsigned long flags;940 941 switch (hh->prim) {942 case PH_DATA_REQ:943 spin_lock_irqsave(&card->lock, flags);944 ret = bchannel_senddata(bch, skb);945 if (ret > 0) { /* direct TX */946 ret = 0;947 W6692_fill_Bfifo(bc);948 }949 spin_unlock_irqrestore(&card->lock, flags);950 return ret;951 case PH_ACTIVATE_REQ:952 spin_lock_irqsave(&card->lock, flags);953 if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags))954 ret = w6692_mode(bc, ch->protocol);955 else956 ret = 0;957 spin_unlock_irqrestore(&card->lock, flags);958 if (!ret)959 _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,960 NULL, GFP_KERNEL);961 break;962 case PH_DEACTIVATE_REQ:963 spin_lock_irqsave(&card->lock, flags);964 mISDN_clear_bchannel(bch);965 w6692_mode(bc, ISDN_P_NONE);966 spin_unlock_irqrestore(&card->lock, flags);967 _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,968 NULL, GFP_KERNEL);969 ret = 0;970 break;971 default:972 pr_info("%s: %s unknown prim(%x,%x)\n",973 card->name, __func__, hh->prim, hh->id);974 ret = -EINVAL;975 }976 if (!ret)977 dev_kfree_skb(skb);978 return ret;979}980 981static int982channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)983{984 return mISDN_ctrl_bchannel(bch, cq);985}986 987static int988open_bchannel(struct w6692_hw *card, struct channel_req *rq)989{990 struct bchannel *bch;991 992 if (rq->adr.channel == 0 || rq->adr.channel > 2)993 return -EINVAL;994 if (rq->protocol == ISDN_P_NONE)995 return -EINVAL;996 bch = &card->bc[rq->adr.channel - 1].bch;997 if (test_and_set_bit(FLG_OPEN, &bch->Flags))998 return -EBUSY; /* b-channel can be only open once */999 bch->ch.protocol = rq->protocol;1000 rq->ch = &bch->ch;1001 return 0;1002}1003 1004static int1005channel_ctrl(struct w6692_hw *card, struct mISDN_ctrl_req *cq)1006{1007 int ret = 0;1008 1009 switch (cq->op) {1010 case MISDN_CTRL_GETOP:1011 cq->op = MISDN_CTRL_L1_TIMER3;1012 break;1013 case MISDN_CTRL_L1_TIMER3:1014 ret = l1_event(card->dch.l1, HW_TIMER3_VALUE | (cq->p1 & 0xff));1015 break;1016 default:1017 pr_info("%s: unknown CTRL OP %x\n", card->name, cq->op);1018 ret = -EINVAL;1019 break;1020 }1021 return ret;1022}1023 1024static int1025w6692_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)1026{1027 struct bchannel *bch = container_of(ch, struct bchannel, ch);1028 struct w6692_ch *bc = container_of(bch, struct w6692_ch, bch);1029 struct w6692_hw *card = bch->hw;1030 int ret = -EINVAL;1031 u_long flags;1032 1033 pr_debug("%s: %s cmd:%x %p\n", card->name, __func__, cmd, arg);1034 switch (cmd) {1035 case CLOSE_CHANNEL:1036 test_and_clear_bit(FLG_OPEN, &bch->Flags);1037 cancel_work_sync(&bch->workq);1038 spin_lock_irqsave(&card->lock, flags);1039 mISDN_clear_bchannel(bch);1040 w6692_mode(bc, ISDN_P_NONE);1041 spin_unlock_irqrestore(&card->lock, flags);1042 ch->protocol = ISDN_P_NONE;1043 ch->peer = NULL;1044 module_put(THIS_MODULE);1045 ret = 0;1046 break;1047 case CONTROL_CHANNEL:1048 ret = channel_bctrl(bch, arg);1049 break;1050 default:1051 pr_info("%s: %s unknown prim(%x)\n",1052 card->name, __func__, cmd);1053 }1054 return ret;1055}1056 1057static int1058w6692_l2l1D(struct mISDNchannel *ch, struct sk_buff *skb)1059{1060 struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);1061 struct dchannel *dch = container_of(dev, struct dchannel, dev);1062 struct w6692_hw *card = container_of(dch, struct w6692_hw, dch);1063 int ret = -EINVAL;1064 struct mISDNhead *hh = mISDN_HEAD_P(skb);1065 u32 id;1066 u_long flags;1067 1068 switch (hh->prim) {1069 case PH_DATA_REQ:1070 spin_lock_irqsave(&card->lock, flags);1071 ret = dchannel_senddata(dch, skb);1072 if (ret > 0) { /* direct TX */1073 id = hh->id; /* skb can be freed */1074 W6692_fill_Dfifo(card);1075 ret = 0;1076 spin_unlock_irqrestore(&card->lock, flags);1077 queue_ch_frame(ch, PH_DATA_CNF, id, NULL);1078 } else1079 spin_unlock_irqrestore(&card->lock, flags);1080 return ret;1081 case PH_ACTIVATE_REQ:1082 ret = l1_event(dch->l1, hh->prim);1083 break;1084 case PH_DEACTIVATE_REQ:1085 test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags);1086 ret = l1_event(dch->l1, hh->prim);1087 break;1088 }1089 1090 if (!ret)1091 dev_kfree_skb(skb);1092 return ret;1093}1094 1095static int1096w6692_l1callback(struct dchannel *dch, u32 cmd)1097{1098 struct w6692_hw *card = container_of(dch, struct w6692_hw, dch);1099 u_long flags;1100 1101 pr_debug("%s: cmd(%x) state(%02x)\n", card->name, cmd, card->state);1102 switch (cmd) {1103 case INFO3_P8:1104 spin_lock_irqsave(&card->lock, flags);1105 ph_command(card, W_L1CMD_AR8);1106 spin_unlock_irqrestore(&card->lock, flags);1107 break;1108 case INFO3_P10:1109 spin_lock_irqsave(&card->lock, flags);1110 ph_command(card, W_L1CMD_AR10);1111 spin_unlock_irqrestore(&card->lock, flags);1112 break;1113 case HW_RESET_REQ:1114 spin_lock_irqsave(&card->lock, flags);1115 if (card->state != W_L1IND_DRD)1116 ph_command(card, W_L1CMD_RST);1117 ph_command(card, W_L1CMD_ECK);1118 spin_unlock_irqrestore(&card->lock, flags);1119 break;1120 case HW_DEACT_REQ:1121 skb_queue_purge(&dch->squeue);1122 if (dch->tx_skb) {1123 dev_kfree_skb(dch->tx_skb);1124 dch->tx_skb = NULL;1125 }1126 dch->tx_idx = 0;1127 if (dch->rx_skb) {1128 dev_kfree_skb(dch->rx_skb);1129 dch->rx_skb = NULL;1130 }1131 test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);1132 if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))1133 del_timer(&dch->timer);1134 break;1135 case HW_POWERUP_REQ:1136 spin_lock_irqsave(&card->lock, flags);1137 ph_command(card, W_L1CMD_ECK);1138 spin_unlock_irqrestore(&card->lock, flags);1139 break;1140 case PH_ACTIVATE_IND:1141 test_and_set_bit(FLG_ACTIVE, &dch->Flags);1142 _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,1143 GFP_ATOMIC);1144 break;1145 case PH_DEACTIVATE_IND:1146 test_and_clear_bit(FLG_ACTIVE, &dch->Flags);1147 _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,1148 GFP_ATOMIC);1149 break;1150 default:1151 pr_debug("%s: %s unknown command %x\n", card->name,1152 __func__, cmd);1153 return -1;1154 }1155 return 0;1156}1157 1158static int1159open_dchannel(struct w6692_hw *card, struct channel_req *rq, void *caller)1160{1161 pr_debug("%s: %s dev(%d) open from %p\n", card->name, __func__,1162 card->dch.dev.id, caller);1163 if (rq->protocol != ISDN_P_TE_S0)1164 return -EINVAL;1165 if (rq->adr.channel == 1)1166 /* E-Channel not supported */1167 return -EINVAL;1168 rq->ch = &card->dch.dev.D;1169 rq->ch->protocol = rq->protocol;1170 if (card->dch.state == 7)1171 _queue_data(rq->ch, PH_ACTIVATE_IND, MISDN_ID_ANY,1172 0, NULL, GFP_KERNEL);1173 return 0;1174}1175 1176static int1177w6692_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg)1178{1179 struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);1180 struct dchannel *dch = container_of(dev, struct dchannel, dev);1181 struct w6692_hw *card = container_of(dch, struct w6692_hw, dch);1182 struct channel_req *rq;1183 int err = 0;1184 1185 pr_debug("%s: DCTRL: %x %p\n", card->name, cmd, arg);1186 switch (cmd) {1187 case OPEN_CHANNEL:1188 rq = arg;1189 if (rq->protocol == ISDN_P_TE_S0)1190 err = open_dchannel(card, rq, __builtin_return_address(0));1191 else1192 err = open_bchannel(card, rq);1193 if (err)1194 break;1195 if (!try_module_get(THIS_MODULE))1196 pr_info("%s: cannot get module\n", card->name);1197 break;1198 case CLOSE_CHANNEL:1199 pr_debug("%s: dev(%d) close from %p\n", card->name,1200 dch->dev.id, __builtin_return_address(0));1201 module_put(THIS_MODULE);1202 break;1203 case CONTROL_CHANNEL:1204 err = channel_ctrl(card, arg);1205 break;1206 default:1207 pr_debug("%s: unknown DCTRL command %x\n", card->name, cmd);1208 return -EINVAL;1209 }1210 return err;1211}1212 1213static int1214setup_w6692(struct w6692_hw *card)1215{1216 u32 val;1217 1218 if (!request_region(card->addr, 256, card->name)) {1219 pr_info("%s: config port %x-%x already in use\n", card->name,1220 card->addr, card->addr + 255);1221 return -EIO;1222 }1223 W6692Version(card);1224 card->bc[0].addr = card->addr;1225 card->bc[1].addr = card->addr + 0x40;1226 val = ReadW6692(card, W_ISTA);1227 if (debug & DEBUG_HW)1228 pr_notice("%s ISTA=%02x\n", card->name, val);1229 val = ReadW6692(card, W_IMASK);1230 if (debug & DEBUG_HW)1231 pr_notice("%s IMASK=%02x\n", card->name, val);1232 val = ReadW6692(card, W_D_EXIR);1233 if (debug & DEBUG_HW)1234 pr_notice("%s D_EXIR=%02x\n", card->name, val);1235 val = ReadW6692(card, W_D_EXIM);1236 if (debug & DEBUG_HW)1237 pr_notice("%s D_EXIM=%02x\n", card->name, val);1238 val = ReadW6692(card, W_D_RSTA);1239 if (debug & DEBUG_HW)1240 pr_notice("%s D_RSTA=%02x\n", card->name, val);1241 return 0;1242}1243 1244static void1245release_card(struct w6692_hw *card)1246{1247 u_long flags;1248 1249 spin_lock_irqsave(&card->lock, flags);1250 disable_hwirq(card);1251 w6692_mode(&card->bc[0], ISDN_P_NONE);1252 w6692_mode(&card->bc[1], ISDN_P_NONE);1253 if ((card->fmask & led) || card->subtype == W6692_USR) {1254 card->xdata |= 0x04; /* LED OFF */1255 WriteW6692(card, W_XDATA, card->xdata);1256 }1257 spin_unlock_irqrestore(&card->lock, flags);1258 free_irq(card->irq, card);1259 l1_event(card->dch.l1, CLOSE_CHANNEL);1260 mISDN_unregister_device(&card->dch.dev);1261 release_region(card->addr, 256);1262 mISDN_freebchannel(&card->bc[1].bch);1263 mISDN_freebchannel(&card->bc[0].bch);1264 mISDN_freedchannel(&card->dch);1265 write_lock_irqsave(&card_lock, flags);1266 list_del(&card->list);1267 write_unlock_irqrestore(&card_lock, flags);1268 pci_disable_device(card->pdev);1269 pci_set_drvdata(card->pdev, NULL);1270 kfree(card);1271}1272 1273static int1274setup_instance(struct w6692_hw *card)1275{1276 int i, err;1277 u_long flags;1278 1279 snprintf(card->name, MISDN_MAX_IDLEN - 1, "w6692.%d", w6692_cnt + 1);1280 write_lock_irqsave(&card_lock, flags);1281 list_add_tail(&card->list, &Cards);1282 write_unlock_irqrestore(&card_lock, flags);1283 card->fmask = (1 << w6692_cnt);1284 _set_debug(card);1285 spin_lock_init(&card->lock);1286 mISDN_initdchannel(&card->dch, MAX_DFRAME_LEN_L1, W6692_ph_bh);1287 card->dch.dev.Dprotocols = (1 << ISDN_P_TE_S0);1288 card->dch.dev.D.send = w6692_l2l1D;1289 card->dch.dev.D.ctrl = w6692_dctrl;1290 card->dch.dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |1291 (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));1292 card->dch.hw = card;1293 card->dch.dev.nrbchan = 2;1294 for (i = 0; i < 2; i++) {1295 mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM,1296 W_B_FIFO_THRESH);1297 card->bc[i].bch.hw = card;1298 card->bc[i].bch.nr = i + 1;1299 card->bc[i].bch.ch.nr = i + 1;1300 card->bc[i].bch.ch.send = w6692_l2l1B;1301 card->bc[i].bch.ch.ctrl = w6692_bctrl;1302 set_channelmap(i + 1, card->dch.dev.channelmap);1303 list_add(&card->bc[i].bch.ch.list, &card->dch.dev.bchannels);1304 }1305 err = setup_w6692(card);1306 if (err)1307 goto error_setup;1308 err = mISDN_register_device(&card->dch.dev, &card->pdev->dev,1309 card->name);1310 if (err)1311 goto error_reg;1312 err = init_card(card);1313 if (err)1314 goto error_init;1315 err = create_l1(&card->dch, w6692_l1callback);1316 if (!err) {1317 w6692_cnt++;1318 pr_notice("W6692 %d cards installed\n", w6692_cnt);1319 return 0;1320 }1321 1322 free_irq(card->irq, card);1323error_init:1324 mISDN_unregister_device(&card->dch.dev);1325error_reg:1326 release_region(card->addr, 256);1327error_setup:1328 mISDN_freebchannel(&card->bc[1].bch);1329 mISDN_freebchannel(&card->bc[0].bch);1330 mISDN_freedchannel(&card->dch);1331 write_lock_irqsave(&card_lock, flags);1332 list_del(&card->list);1333 write_unlock_irqrestore(&card_lock, flags);1334 kfree(card);1335 return err;1336}1337 1338static int1339w6692_probe(struct pci_dev *pdev, const struct pci_device_id *ent)1340{1341 int err = -ENOMEM;1342 struct w6692_hw *card;1343 struct w6692map *m = (struct w6692map *)ent->driver_data;1344 1345 card = kzalloc(sizeof(struct w6692_hw), GFP_KERNEL);1346 if (!card) {1347 pr_info("No kmem for w6692 card\n");1348 return err;1349 }1350 card->pdev = pdev;1351 card->subtype = m->subtype;1352 err = pci_enable_device(pdev);1353 if (err) {1354 kfree(card);1355 return err;1356 }1357 1358 printk(KERN_INFO "mISDN_w6692: found adapter %s at %s\n",1359 m->name, pci_name(pdev));1360 1361 card->addr = pci_resource_start(pdev, 1);1362 card->irq = pdev->irq;1363 pci_set_drvdata(pdev, card);1364 err = setup_instance(card);1365 if (err)1366 pci_set_drvdata(pdev, NULL);1367 return err;1368}1369 1370static void1371w6692_remove_pci(struct pci_dev *pdev)1372{1373 struct w6692_hw *card = pci_get_drvdata(pdev);1374 1375 if (card)1376 release_card(card);1377 else1378 if (debug)1379 pr_notice("%s: drvdata already removed\n", __func__);1380}1381 1382static const struct pci_device_id w6692_ids[] = {1383 { PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH,1384 PCI_ANY_ID, PCI_ANY_ID, 0, 0, (ulong)&w6692_map[0]},1385 { PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692,1386 PCI_VENDOR_ID_USR, PCI_DEVICE_ID_USR_6692, 0, 0,1387 (ulong)&w6692_map[2]},1388 { PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692,1389 PCI_ANY_ID, PCI_ANY_ID, 0, 0, (ulong)&w6692_map[1]},1390 { }1391};1392MODULE_DEVICE_TABLE(pci, w6692_ids);1393 1394static struct pci_driver w6692_driver = {1395 .name = "w6692",1396 .probe = w6692_probe,1397 .remove = w6692_remove_pci,1398 .id_table = w6692_ids,1399};1400 1401static int __init w6692_init(void)1402{1403 int err;1404 1405 pr_notice("Winbond W6692 PCI driver Rev. %s\n", W6692_REV);1406 1407 err = pci_register_driver(&w6692_driver);1408 return err;1409}1410 1411static void __exit w6692_cleanup(void)1412{1413 pci_unregister_driver(&w6692_driver);1414}1415 1416module_init(w6692_init);1417module_exit(w6692_cleanup);1418