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