1 /* $Id: w6692.c,v 1.7 2000/06/26 08:59:15 keil Exp $
3 * w6692.c Winbond W6692 specific routines
5 * Author Petr Novak <petr.novak@i.cz>
6 * (based on HiSax driver by Karsten Keil)
8 * This file is (c) under GNU PUBLIC LICENSE
12 #include <linux/config.h>
13 #define __NO_VERSION__
17 #include <linux/interrupt.h>
18 #include <linux/pci.h>
20 #ifndef PCI_VENDOR_ID_ASUSCOM
21 #define PCI_VENDOR_ID_ASUSCOM 0x675
23 #ifndef PCI_DEVICE_ID_ASUSCOM_TA1
24 #define PCI_DEVICE_ID_ASUSCOM_TA1 0x1702
26 #ifndef PCI_VENDOR_ID_WINBOND2
27 #define PCI_VENDOR_ID_WINBOND2 0x1050
29 #ifndef PCI_DEVICE_ID_WINBOND_6692
30 #define PCI_DEVICE_ID_WINBOND_6692 0x6692
32 /* table entry in the PCI devices list */
40 static const PCI_ENTRY id_list
[] =
42 {PCI_VENDOR_ID_ASUSCOM
, PCI_DEVICE_ID_ASUSCOM_TA1
, "AsusCom", "TA XXX"},
43 {PCI_VENDOR_ID_WINBOND2
, PCI_DEVICE_ID_WINBOND_6692
, "Winbond", "W6692"},
47 extern const char *CardType
[];
49 const char *w6692_revision
= "$Revision: 1.7 $";
51 #define DBUSY_TIMER_VALUE 80
53 static char *W6692Ver
[] HISAX_INITDATA
=
54 {"W6692 V00", "W6692 V01", "W6692 V10",
58 W6692Version(struct IsdnCardState
*cs
, char *s
)
62 val
= cs
->readW6692(cs
, W_D_RBCH
);
63 printk(KERN_INFO
"%s Winbond W6692 version (%x): %s\n", s
, val
, W6692Ver
[(val
>> 6) & 3]);
67 ph_command(struct IsdnCardState
*cs
, unsigned int command
)
69 if (cs
->debug
& L1_DEB_ISAC
)
70 debugl1(cs
, "ph_command %x", command
);
71 cs
->writeisac(cs
, W_CIX
, command
);
76 W6692_new_ph(struct IsdnCardState
*cs
)
78 switch (cs
->dc
.w6692
.ph_state
) {
80 ph_command(cs
, W_L1CMD_DRC
);
81 l1_msg(cs
, HW_RESET
| INDICATION
, NULL
);
84 l1_msg(cs
, HW_DEACTIVATE
| CONFIRM
, NULL
);
87 l1_msg(cs
, HW_DEACTIVATE
| INDICATION
, NULL
);
90 l1_msg(cs
, HW_POWERUP
| CONFIRM
, NULL
);
93 l1_msg(cs
, HW_RSYNC
| INDICATION
, NULL
);
96 l1_msg(cs
, HW_INFO2
| INDICATION
, NULL
);
99 l1_msg(cs
, HW_INFO4_P8
| INDICATION
, NULL
);
102 l1_msg(cs
, HW_INFO4_P10
| INDICATION
, NULL
);
110 W6692_bh(struct IsdnCardState
*cs
)
112 struct PStack
*stptr
;
116 if (test_and_clear_bit(D_CLEARBUSY
, &cs
->event
)) {
118 debugl1(cs
, "D-Channel Busy cleared");
120 while (stptr
!= NULL
) {
121 stptr
->l1
.l1l2(stptr
, PH_PAUSE
| CONFIRM
, NULL
);
125 if (test_and_clear_bit(D_L1STATECHANGE
, &cs
->event
))
127 if (test_and_clear_bit(D_RCVBUFREADY
, &cs
->event
))
128 DChannel_proc_rcv(cs
);
129 if (test_and_clear_bit(D_XMTBUFREADY
, &cs
->event
))
130 DChannel_proc_xmt(cs
);
132 if (test_and_clear_bit(D_RX_MON1, &cs->event))
133 arcofi_fsm(cs, ARCOFI_RX_END, NULL);
134 if (test_and_clear_bit(D_TX_MON1, &cs->event))
135 arcofi_fsm(cs, ARCOFI_TX_END, NULL);
140 W6692_sched_event(struct IsdnCardState
*cs
, int event
)
142 test_and_set_bit(event
, &cs
->event
);
143 queue_task(&cs
->tqueue
, &tq_immediate
);
144 mark_bh(IMMEDIATE_BH
);
148 W6692B_sched_event(struct BCState
*bcs
, int event
)
150 bcs
->event
|= 1 << event
;
151 queue_task(&bcs
->tqueue
, &tq_immediate
);
152 mark_bh(IMMEDIATE_BH
);
156 W6692_empty_fifo(struct IsdnCardState
*cs
, int count
)
161 if ((cs
->debug
& L1_DEB_ISAC
) && !(cs
->debug
& L1_DEB_ISAC_FIFO
))
162 debugl1(cs
, "W6692_empty_fifo");
164 if ((cs
->rcvidx
+ count
) >= MAX_DFRAME_LEN_L1
) {
165 if (cs
->debug
& L1_DEB_WARN
)
166 debugl1(cs
, "W6692_empty_fifo overrun %d",
168 cs
->writeW6692(cs
, W_D_CMDR
, W_D_CMDR_RACK
);
172 ptr
= cs
->rcvbuf
+ cs
->rcvidx
;
176 cs
->readW6692fifo(cs
, ptr
, count
);
177 cs
->writeW6692(cs
, W_D_CMDR
, W_D_CMDR_RACK
);
178 restore_flags(flags
);
179 if (cs
->debug
& L1_DEB_ISAC_FIFO
) {
182 t
+= sprintf(t
, "W6692_empty_fifo cnt %d", count
);
183 QuickHex(t
, ptr
, count
);
184 debugl1(cs
, cs
->dlog
);
189 W6692_fill_fifo(struct IsdnCardState
*cs
)
195 if ((cs
->debug
& L1_DEB_ISAC
) && !(cs
->debug
& L1_DEB_ISAC_FIFO
))
196 debugl1(cs
, "W6692_fill_fifo");
201 count
= cs
->tx_skb
->len
;
206 if (count
> W_D_FIFO_THRESH
) {
208 count
= W_D_FIFO_THRESH
;
212 ptr
= cs
->tx_skb
->data
;
213 skb_pull(cs
->tx_skb
, count
);
215 cs
->writeW6692fifo(cs
, ptr
, count
);
216 cs
->writeW6692(cs
, W_D_CMDR
, more
? W_D_CMDR_XMS
: (W_D_CMDR_XMS
| W_D_CMDR_XME
));
217 restore_flags(flags
);
218 if (test_and_set_bit(FLG_DBUSY_TIMER
, &cs
->HW_Flags
)) {
219 debugl1(cs
, "W6692_fill_fifo dbusytimer running");
220 del_timer(&cs
->dbusytimer
);
222 init_timer(&cs
->dbusytimer
);
223 cs
->dbusytimer
.expires
= jiffies
+ ((DBUSY_TIMER_VALUE
* HZ
) / 1000);
224 add_timer(&cs
->dbusytimer
);
225 if (cs
->debug
& L1_DEB_ISAC_FIFO
) {
228 t
+= sprintf(t
, "W6692_fill_fifo cnt %d", count
);
229 QuickHex(t
, ptr
, count
);
230 debugl1(cs
, cs
->dlog
);
235 W6692B_empty_fifo(struct BCState
*bcs
, int count
)
238 struct IsdnCardState
*cs
= bcs
->cs
;
241 if ((cs
->debug
& L1_DEB_HSCX
) && !(cs
->debug
& L1_DEB_HSCX_FIFO
))
242 debugl1(cs
, "W6692B_empty_fifo");
244 if (bcs
->hw
.w6692
.rcvidx
+ count
> HSCX_BUFMAX
) {
245 if (cs
->debug
& L1_DEB_WARN
)
246 debugl1(cs
, "W6692B_empty_fifo: incoming packet too large");
247 cs
->BC_Write_Reg(cs
, bcs
->channel
, W_B_CMDR
, W_B_CMDR_RACK
| W_B_CMDR_RACT
);
248 bcs
->hw
.w6692
.rcvidx
= 0;
251 ptr
= bcs
->hw
.w6692
.rcvbuf
+ bcs
->hw
.w6692
.rcvidx
;
252 bcs
->hw
.w6692
.rcvidx
+= count
;
255 READW6692BFIFO(cs
, bcs
->channel
, ptr
, count
);
256 cs
->BC_Write_Reg(cs
, bcs
->channel
, W_B_CMDR
, W_B_CMDR_RACK
| W_B_CMDR_RACT
);
257 restore_flags(flags
);
258 if (cs
->debug
& L1_DEB_HSCX_FIFO
) {
261 t
+= sprintf(t
, "W6692B_empty_fifo %c cnt %d",
262 bcs
->channel
+ '1', count
);
263 QuickHex(t
, ptr
, count
);
264 debugl1(cs
, bcs
->blog
);
269 W6692B_fill_fifo(struct BCState
*bcs
)
271 struct IsdnCardState
*cs
= bcs
->cs
;
277 if ((cs
->debug
& L1_DEB_HSCX
) && !(cs
->debug
& L1_DEB_HSCX_FIFO
))
278 debugl1(cs
, "W6692B_fill_fifo");
282 if (bcs
->tx_skb
->len
<= 0)
285 more
= (bcs
->mode
== L1_MODE_TRANS
) ? 1 : 0;
286 if (bcs
->tx_skb
->len
> W_B_FIFO_THRESH
) {
288 count
= W_B_FIFO_THRESH
;
290 count
= bcs
->tx_skb
->len
;
294 ptr
= bcs
->tx_skb
->data
;
295 skb_pull(bcs
->tx_skb
, count
);
296 bcs
->tx_cnt
-= count
;
297 bcs
->hw
.w6692
.count
+= count
;
298 WRITEW6692BFIFO(cs
, bcs
->channel
, ptr
, count
);
299 cs
->BC_Write_Reg(cs
, bcs
->channel
, W_B_CMDR
, W_B_CMDR_RACT
| W_B_CMDR_XMS
| (more
? 0 : W_B_CMDR_XME
));
300 restore_flags(flags
);
301 if (cs
->debug
& L1_DEB_HSCX_FIFO
) {
304 t
+= sprintf(t
, "W6692B_fill_fifo %c cnt %d",
305 bcs
->channel
+ '1', count
);
306 QuickHex(t
, ptr
, count
);
307 debugl1(cs
, bcs
->blog
);
312 W6692B_interrupt(struct IsdnCardState
*cs
, u_char bchan
)
320 bcs
= (cs
->bcs
->channel
== bchan
) ? cs
->bcs
: (cs
->bcs
+1);
321 val
= cs
->BC_Read_Reg(cs
, bchan
, W_B_EXIR
);
322 debugl1(cs
, "W6692B chan %d B_EXIR 0x%02X", bchan
, val
);
324 if (!test_bit(BC_FLG_INIT
, &bcs
->Flag
)) {
325 debugl1(cs
, "W6692B not INIT yet");
328 if (val
& W_B_EXI_RME
) { /* RME */
329 r
= cs
->BC_Read_Reg(cs
, bchan
, W_B_STAR
);
330 if (r
& (W_B_STAR_RDOV
| W_B_STAR_CRCE
| W_B_STAR_RMB
| W_B_STAR_XDOW
)) {
331 if ((r
& W_B_STAR_RDOV
) && bcs
->mode
)
332 if (cs
->debug
& L1_DEB_WARN
)
333 debugl1(cs
, "W6692 B RDOV mode=%d",
335 if (r
& W_B_STAR_CRCE
)
336 if (cs
->debug
& L1_DEB_WARN
)
337 debugl1(cs
, "W6692 B CRC error");
338 cs
->BC_Write_Reg(cs
, bchan
, W_B_CMDR
, W_B_CMDR_RACK
| W_B_CMDR_RRST
| W_B_CMDR_RACT
);
340 count
= cs
->BC_Read_Reg(cs
, bchan
, W_B_RBCL
) & (W_B_FIFO_THRESH
- 1);
342 count
= W_B_FIFO_THRESH
;
343 W6692B_empty_fifo(bcs
, count
);
344 if ((count
= bcs
->hw
.w6692
.rcvidx
) > 0) {
345 if (cs
->debug
& L1_DEB_HSCX_FIFO
)
346 debugl1(cs
, "W6692 Bchan Frame %d", count
);
347 if (!(skb
= dev_alloc_skb(count
)))
348 printk(KERN_WARNING
"W6692: Bchan receive out of memory\n");
350 memcpy(skb_put(skb
, count
), bcs
->hw
.w6692
.rcvbuf
, count
);
351 skb_queue_tail(&bcs
->rqueue
, skb
);
355 bcs
->hw
.w6692
.rcvidx
= 0;
356 W6692B_sched_event(bcs
, B_RCVBUFREADY
);
358 if (val
& W_B_EXI_RMR
) { /* RMR */
359 W6692B_empty_fifo(bcs
, W_B_FIFO_THRESH
);
360 if (bcs
->mode
== L1_MODE_TRANS
) {
361 /* receive audio data */
362 if (!(skb
= dev_alloc_skb(W_B_FIFO_THRESH
)))
363 printk(KERN_WARNING
"HiSax: receive out of memory\n");
365 memcpy(skb_put(skb
, W_B_FIFO_THRESH
), bcs
->hw
.w6692
.rcvbuf
, W_B_FIFO_THRESH
);
366 skb_queue_tail(&bcs
->rqueue
, skb
);
368 bcs
->hw
.w6692
.rcvidx
= 0;
369 W6692B_sched_event(bcs
, B_RCVBUFREADY
);
372 if (val
& W_B_EXI_XFR
) { /* XFR */
374 if (bcs
->tx_skb
->len
) {
375 W6692B_fill_fifo(bcs
);
378 if (bcs
->st
->lli
.l1writewakeup
&&
379 (PACKET_NOACK
!= bcs
->tx_skb
->pkt_type
))
380 bcs
->st
->lli
.l1writewakeup(bcs
->st
, bcs
->hw
.w6692
.count
);
381 dev_kfree_skb_irq(bcs
->tx_skb
);
382 bcs
->hw
.w6692
.count
= 0;
386 if ((bcs
->tx_skb
= skb_dequeue(&bcs
->squeue
))) {
387 bcs
->hw
.w6692
.count
= 0;
388 test_and_set_bit(BC_FLG_BUSY
, &bcs
->Flag
);
389 W6692B_fill_fifo(bcs
);
391 test_and_clear_bit(BC_FLG_BUSY
, &bcs
->Flag
);
392 W6692B_sched_event(bcs
, B_XMTBUFREADY
);
395 if (val
& W_B_EXI_XDUN
) { /* XDUN */
397 W6692B_fill_fifo(bcs
);
399 /* Here we lost an TX interrupt, so
400 * restart transmitting the whole frame.
403 skb_push(bcs
->tx_skb
, bcs
->hw
.w6692
.count
);
404 bcs
->tx_cnt
+= bcs
->hw
.w6692
.count
;
405 bcs
->hw
.w6692
.count
= 0;
407 cs
->BC_Write_Reg(cs
, bchan
, W_B_CMDR
, W_B_CMDR_XRST
| W_B_CMDR_RACT
);
408 if (cs
->debug
& L1_DEB_WARN
)
409 debugl1(cs
, "W6692 B EXIR %x Lost TX", val
);
415 W6692_interrupt(int intno
, void *dev_id
, struct pt_regs
*regs
)
417 struct IsdnCardState
*cs
= dev_id
;
418 u_char val
, exval
, v1
;
425 printk(KERN_WARNING
"W6692: Spurious interrupt!\n");
428 val
= cs
->readW6692(cs
, W_ISTA
);
431 if (cs
->debug
& L1_DEB_ISAC
)
432 debugl1(cs
, "W6692 ISTA %x", val
);
434 if (val
& W_INT_D_RME
) { /* RME */
435 exval
= cs
->readW6692(cs
, W_D_RSTA
);
436 if (exval
& (W_D_RSTA_RDOV
| W_D_RSTA_CRCE
| W_D_RSTA_RMB
)) {
437 if (exval
& W_D_RSTA_RDOV
)
438 if (cs
->debug
& L1_DEB_WARN
)
439 debugl1(cs
, "W6692 RDOV");
440 if (exval
& W_D_RSTA_CRCE
)
441 if (cs
->debug
& L1_DEB_WARN
)
442 debugl1(cs
, "W6692 D-channel CRC error");
443 if (exval
& W_D_RSTA_RMB
)
444 if (cs
->debug
& L1_DEB_WARN
)
445 debugl1(cs
, "W6692 D-channel ABORT");
446 cs
->writeW6692(cs
, W_D_CMDR
, W_D_CMDR_RACK
| W_D_CMDR_RRST
);
448 count
= cs
->readW6692(cs
, W_D_RBCL
) & (W_D_FIFO_THRESH
- 1);
450 count
= W_D_FIFO_THRESH
;
451 W6692_empty_fifo(cs
, count
);
454 if ((count
= cs
->rcvidx
) > 0) {
456 if (!(skb
= alloc_skb(count
, GFP_ATOMIC
)))
457 printk(KERN_WARNING
"HiSax: D receive out of memory\n");
459 memcpy(skb_put(skb
, count
), cs
->rcvbuf
, count
);
460 skb_queue_tail(&cs
->rq
, skb
);
463 restore_flags(flags
);
466 W6692_sched_event(cs
, D_RCVBUFREADY
);
468 if (val
& W_INT_D_RMR
) { /* RMR */
469 W6692_empty_fifo(cs
, W_D_FIFO_THRESH
);
471 if (val
& W_INT_D_XFR
) { /* XFR */
472 if (test_and_clear_bit(FLG_DBUSY_TIMER
, &cs
->HW_Flags
))
473 del_timer(&cs
->dbusytimer
);
474 if (test_and_clear_bit(FLG_L1_DBUSY
, &cs
->HW_Flags
))
475 W6692_sched_event(cs
, D_CLEARBUSY
);
477 if (cs
->tx_skb
->len
) {
481 dev_kfree_skb_irq(cs
->tx_skb
);
486 if ((cs
->tx_skb
= skb_dequeue(&cs
->sq
))) {
490 W6692_sched_event(cs
, D_XMTBUFREADY
);
493 if (val
& (W_INT_XINT0
| W_INT_XINT1
)) { /* XINT0/1 - never */
494 if (cs
->debug
& L1_DEB_ISAC
)
495 debugl1(cs
, "W6692 spurious XINT!");
497 if (val
& W_INT_D_EXI
) { /* EXI */
498 exval
= cs
->readW6692(cs
, W_D_EXIR
);
499 if (cs
->debug
& L1_DEB_WARN
)
500 debugl1(cs
, "W6692 D_EXIR %02x", exval
);
501 if (exval
& (W_D_EXI_XDUN
| W_D_EXI_XCOL
)) { /* Transmit underrun/collision */
502 debugl1(cs
, "W6692 D-chan underrun/collision");
503 printk(KERN_WARNING
"HiSax: W6692 XDUN/XCOL\n");
504 if (test_and_clear_bit(FLG_DBUSY_TIMER
, &cs
->HW_Flags
))
505 del_timer(&cs
->dbusytimer
);
506 if (test_and_clear_bit(FLG_L1_DBUSY
, &cs
->HW_Flags
))
507 W6692_sched_event(cs
, D_CLEARBUSY
);
508 if (cs
->tx_skb
) { /* Restart frame */
509 skb_push(cs
->tx_skb
, cs
->tx_cnt
);
513 printk(KERN_WARNING
"HiSax: W6692 XDUN/XCOL no skb\n");
514 debugl1(cs
, "W6692 XDUN/XCOL no skb");
515 cs
->writeW6692(cs
, W_D_CMDR
, W_D_CMDR_XRST
);
518 if (exval
& W_D_EXI_RDOV
) { /* RDOV */
519 debugl1(cs
, "W6692 D-channel RDOV");
520 printk(KERN_WARNING
"HiSax: W6692 D-RDOV\n");
521 cs
->writeW6692(cs
, W_D_CMDR
, W_D_CMDR_RRST
);
523 if (exval
& W_D_EXI_TIN2
) { /* TIN2 - never */
524 debugl1(cs
, "W6692 spurious TIN2 interrupt");
526 if (exval
& W_D_EXI_MOC
) { /* MOC - not supported */
527 debugl1(cs
, "W6692 spurious MOC interrupt");
528 v1
= cs
->readW6692(cs
, W_MOSR
);
529 debugl1(cs
, "W6692 MOSR %02x", v1
);
531 if (exval
& W_D_EXI_ISC
) { /* ISC - Level1 change */
532 v1
= cs
->readW6692(cs
, W_CIR
);
533 if (cs
->debug
& L1_DEB_ISAC
)
534 debugl1(cs
, "W6692 ISC CIR=0x%02X", v1
);
535 if (v1
& W_CIR_ICC
) {
536 cs
->dc
.w6692
.ph_state
= v1
& W_CIR_COD_MASK
;
537 if (cs
->debug
& L1_DEB_ISAC
)
538 debugl1(cs
, "ph_state_change %x", cs
->dc
.w6692
.ph_state
);
539 W6692_sched_event(cs
, D_L1STATECHANGE
);
541 if (v1
& W_CIR_SCC
) {
542 v1
= cs
->readW6692(cs
, W_SQR
);
543 debugl1(cs
, "W6692 SCC SQR=0x%02X", v1
);
546 if (exval
& W_D_EXI_WEXP
) {
547 debugl1(cs
, "W6692 spurious WEXP interrupt!");
549 if (exval
& W_D_EXI_TEXP
) {
550 debugl1(cs
, "W6692 spurious TEXP interrupt!");
553 if (val
& W_INT_B1_EXI
) {
554 debugl1(cs
, "W6692 B channel 1 interrupt");
555 W6692B_interrupt(cs
, 0);
557 if (val
& W_INT_B2_EXI
) {
558 debugl1(cs
, "W6692 B channel 2 interrupt");
559 W6692B_interrupt(cs
, 1);
561 val
= cs
->readW6692(cs
, W_ISTA
);
567 printk(KERN_WARNING
"W6692 IRQ LOOP\n");
568 cs
->writeW6692(cs
, W_IMASK
, 0xff);
573 W6692_l1hw(struct PStack
*st
, int pr
, void *arg
)
575 struct IsdnCardState
*cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
576 struct sk_buff
*skb
= arg
;
580 case (PH_DATA
| REQUEST
):
581 if (cs
->debug
& DEB_DLOG_HEX
)
582 LogFrame(cs
, skb
->data
, skb
->len
);
583 if (cs
->debug
& DEB_DLOG_VERBOSE
)
584 dlogframe(cs
, skb
, 0);
586 skb_queue_tail(&cs
->sq
, skb
);
587 #ifdef L2FRAME_DEBUG /* psa */
588 if (cs
->debug
& L1_DEB_LAPD
)
589 Logl2Frame(cs
, skb
, "PH_DATA Queued", 0);
594 #ifdef L2FRAME_DEBUG /* psa */
595 if (cs
->debug
& L1_DEB_LAPD
)
596 Logl2Frame(cs
, skb
, "PH_DATA", 0);
601 case (PH_PULL
| INDICATION
):
603 if (cs
->debug
& L1_DEB_WARN
)
604 debugl1(cs
, " l2l1 tx_skb exist this shouldn't happen");
605 skb_queue_tail(&cs
->sq
, skb
);
608 if (cs
->debug
& DEB_DLOG_HEX
)
609 LogFrame(cs
, skb
->data
, skb
->len
);
610 if (cs
->debug
& DEB_DLOG_VERBOSE
)
611 dlogframe(cs
, skb
, 0);
614 #ifdef L2FRAME_DEBUG /* psa */
615 if (cs
->debug
& L1_DEB_LAPD
)
616 Logl2Frame(cs
, skb
, "PH_DATA_PULLED", 0);
620 case (PH_PULL
| REQUEST
):
621 #ifdef L2FRAME_DEBUG /* psa */
622 if (cs
->debug
& L1_DEB_LAPD
)
623 debugl1(cs
, "-> PH_REQUEST_PULL");
626 test_and_clear_bit(FLG_L1_PULL_REQ
, &st
->l1
.Flags
);
627 st
->l1
.l1l2(st
, PH_PULL
| CONFIRM
, NULL
);
629 test_and_set_bit(FLG_L1_PULL_REQ
, &st
->l1
.Flags
);
631 case (HW_RESET
| REQUEST
):
632 if ((cs
->dc
.w6692
.ph_state
== W_L1IND_DRD
))
633 ph_command(cs
, W_L1CMD_ECK
);
635 ph_command(cs
, W_L1CMD_RST
);
636 cs
->dc
.w6692
.ph_state
= W_L1CMD_RST
;
640 case (HW_ENABLE
| REQUEST
):
641 ph_command(cs
, W_L1CMD_ECK
);
643 case (HW_INFO3
| REQUEST
):
644 ph_command(cs
, W_L1CMD_AR8
);
646 case (HW_TESTLOOP
| REQUEST
):
652 /* !!! not implemented yet */
654 case (HW_DEACTIVATE
| RESPONSE
):
655 discard_queue(&cs
->rq
);
656 discard_queue(&cs
->sq
);
658 dev_kfree_skb_any(cs
->tx_skb
);
661 if (test_and_clear_bit(FLG_DBUSY_TIMER
, &cs
->HW_Flags
))
662 del_timer(&cs
->dbusytimer
);
663 if (test_and_clear_bit(FLG_L1_DBUSY
, &cs
->HW_Flags
))
664 W6692_sched_event(cs
, D_CLEARBUSY
);
667 if (cs
->debug
& L1_DEB_WARN
)
668 debugl1(cs
, "W6692_l1hw unknown %04x", pr
);
674 setstack_W6692(struct PStack
*st
, struct IsdnCardState
*cs
)
676 st
->l1
.l1hw
= W6692_l1hw
;
680 DC_Close_W6692(struct IsdnCardState
*cs
)
685 dbusy_timer_handler(struct IsdnCardState
*cs
)
687 struct PStack
*stptr
;
690 if (test_bit(FLG_DBUSY_TIMER
, &cs
->HW_Flags
)) {
691 rbch
= cs
->readW6692(cs
, W_D_RBCH
);
692 star
= cs
->readW6692(cs
, W_D_STAR
);
694 debugl1(cs
, "D-Channel Busy D_RBCH %02x D_STAR %02x",
696 if (star
& W_D_STAR_XBZ
) { /* D-Channel Busy */
697 test_and_set_bit(FLG_L1_DBUSY
, &cs
->HW_Flags
);
699 while (stptr
!= NULL
) {
700 stptr
->l1
.l1l2(stptr
, PH_PAUSE
| INDICATION
, NULL
);
704 /* discard frame; reset transceiver */
705 test_and_clear_bit(FLG_DBUSY_TIMER
, &cs
->HW_Flags
);
707 dev_kfree_skb_any(cs
->tx_skb
);
711 printk(KERN_WARNING
"HiSax: W6692 D-Channel Busy no skb\n");
712 debugl1(cs
, "D-Channel Busy no skb");
714 cs
->writeW6692(cs
, W_D_CMDR
, W_D_CMDR_XRST
); /* Transmitter reset */
715 cs
->irq_func(cs
->irq
, cs
, NULL
);
721 W6692Bmode(struct BCState
*bcs
, int mode
, int bchan
)
723 struct IsdnCardState
*cs
= bcs
->cs
;
725 if (cs
->debug
& L1_DEB_HSCX
)
726 debugl1(cs
, "w6692 %c mode %d ichan %d",
727 '1' + bchan
, mode
, bchan
);
729 bcs
->channel
= bchan
;
730 bcs
->hw
.w6692
.bchan
= bchan
;
734 cs
->BC_Write_Reg(cs
, bchan
, W_B_MODE
, 0);
736 case (L1_MODE_TRANS
):
737 cs
->BC_Write_Reg(cs
, bchan
, W_B_MODE
, W_B_MODE_MMS
);
740 cs
->BC_Write_Reg(cs
, bchan
, W_B_MODE
, W_B_MODE_ITF
);
741 cs
->BC_Write_Reg(cs
, bchan
, W_B_ADM1
, 0xff);
742 cs
->BC_Write_Reg(cs
, bchan
, W_B_ADM2
, 0xff);
746 cs
->BC_Write_Reg(cs
, bchan
, W_B_CMDR
, W_B_CMDR_RRST
|
747 W_B_CMDR_RACT
| W_B_CMDR_XRST
);
748 cs
->BC_Write_Reg(cs
, bchan
, W_B_EXIM
, 0x00);
752 W6692_l2l1(struct PStack
*st
, int pr
, void *arg
)
754 struct sk_buff
*skb
= arg
;
758 case (PH_DATA
| REQUEST
):
761 if (st
->l1
.bcs
->tx_skb
) {
762 skb_queue_tail(&st
->l1
.bcs
->squeue
, skb
);
763 restore_flags(flags
);
765 st
->l1
.bcs
->tx_skb
= skb
;
766 test_and_set_bit(BC_FLG_BUSY
, &st
->l1
.bcs
->Flag
);
767 st
->l1
.bcs
->hw
.w6692
.count
= 0;
768 restore_flags(flags
);
769 st
->l1
.bcs
->cs
->BC_Send_Data(st
->l1
.bcs
);
772 case (PH_PULL
| INDICATION
):
773 if (st
->l1
.bcs
->tx_skb
) {
774 printk(KERN_WARNING
"W6692_l2l1: this shouldn't happen\n");
777 test_and_set_bit(BC_FLG_BUSY
, &st
->l1
.bcs
->Flag
);
778 st
->l1
.bcs
->tx_skb
= skb
;
779 st
->l1
.bcs
->hw
.w6692
.count
= 0;
780 st
->l1
.bcs
->cs
->BC_Send_Data(st
->l1
.bcs
);
782 case (PH_PULL
| REQUEST
):
783 if (!st
->l1
.bcs
->tx_skb
) {
784 test_and_clear_bit(FLG_L1_PULL_REQ
, &st
->l1
.Flags
);
785 st
->l1
.l1l2(st
, PH_PULL
| CONFIRM
, NULL
);
787 test_and_set_bit(FLG_L1_PULL_REQ
, &st
->l1
.Flags
);
789 case (PH_ACTIVATE
| REQUEST
):
790 test_and_set_bit(BC_FLG_ACTIV
, &st
->l1
.bcs
->Flag
);
791 W6692Bmode(st
->l1
.bcs
, st
->l1
.mode
, st
->l1
.bc
);
792 l1_msg_b(st
, pr
, arg
);
794 case (PH_DEACTIVATE
| REQUEST
):
795 l1_msg_b(st
, pr
, arg
);
797 case (PH_DEACTIVATE
| CONFIRM
):
798 test_and_clear_bit(BC_FLG_ACTIV
, &st
->l1
.bcs
->Flag
);
799 test_and_clear_bit(BC_FLG_BUSY
, &st
->l1
.bcs
->Flag
);
800 W6692Bmode(st
->l1
.bcs
, 0, st
->l1
.bc
);
801 st
->l1
.l1l2(st
, PH_DEACTIVATE
| CONFIRM
, NULL
);
807 close_w6692state(struct BCState
*bcs
)
809 W6692Bmode(bcs
, 0, bcs
->channel
);
810 if (test_and_clear_bit(BC_FLG_INIT
, &bcs
->Flag
)) {
811 if (bcs
->hw
.w6692
.rcvbuf
) {
812 kfree(bcs
->hw
.w6692
.rcvbuf
);
813 bcs
->hw
.w6692
.rcvbuf
= NULL
;
819 discard_queue(&bcs
->rqueue
);
820 discard_queue(&bcs
->squeue
);
822 dev_kfree_skb_any(bcs
->tx_skb
);
824 test_and_clear_bit(BC_FLG_BUSY
, &bcs
->Flag
);
830 open_w6692state(struct IsdnCardState
*cs
, struct BCState
*bcs
)
832 if (!test_and_set_bit(BC_FLG_INIT
, &bcs
->Flag
)) {
833 if (!(bcs
->hw
.w6692
.rcvbuf
= kmalloc(HSCX_BUFMAX
, GFP_ATOMIC
))) {
835 "HiSax: No memory for w6692.rcvbuf\n");
836 test_and_clear_bit(BC_FLG_INIT
, &bcs
->Flag
);
839 if (!(bcs
->blog
= kmalloc(MAX_BLOG_SPACE
, GFP_ATOMIC
))) {
841 "HiSax: No memory for bcs->blog\n");
842 test_and_clear_bit(BC_FLG_INIT
, &bcs
->Flag
);
843 kfree(bcs
->hw
.w6692
.rcvbuf
);
844 bcs
->hw
.w6692
.rcvbuf
= NULL
;
847 skb_queue_head_init(&bcs
->rqueue
);
848 skb_queue_head_init(&bcs
->squeue
);
851 test_and_clear_bit(BC_FLG_BUSY
, &bcs
->Flag
);
853 bcs
->hw
.w6692
.rcvidx
= 0;
859 setstack_w6692(struct PStack
*st
, struct BCState
*bcs
)
861 bcs
->channel
= st
->l1
.bc
;
862 if (open_w6692state(st
->l1
.hardware
, bcs
))
865 st
->l2
.l2l1
= W6692_l2l1
;
866 setstack_manager(st
);
872 HISAX_INITFUNC(void initW6692(struct IsdnCardState
*cs
, int part
))
875 cs
->tqueue
.routine
= (void *) (void *) W6692_bh
;
876 cs
->setstack_d
= setstack_W6692
;
877 cs
->DC_Close
= DC_Close_W6692
;
878 cs
->dbusytimer
.function
= (void *) dbusy_timer_handler
;
879 cs
->dbusytimer
.data
= (long) cs
;
880 init_timer(&cs
->dbusytimer
);
882 cs
->writeW6692(cs
, W_D_CTL
, W_D_CTL_SRST
);
883 cs
->writeW6692(cs
, W_D_CTL
, 0x00);
884 cs
->writeW6692(cs
, W_IMASK
, 0xff);
885 cs
->writeW6692(cs
, W_D_SAM
, 0xff);
886 cs
->writeW6692(cs
, W_D_TAM
, 0xff);
887 cs
->writeW6692(cs
, W_D_EXIM
, 0x00);
888 cs
->writeW6692(cs
, W_D_MODE
, W_D_MODE_RACT
);
889 cs
->writeW6692(cs
, W_IMASK
, 0x18);
890 ph_command(cs
, W_L1CMD_RST
);
891 cs
->dc
.w6692
.ph_state
= W_L1CMD_RST
;
893 ph_command(cs
, W_L1CMD_ECK
);
895 cs
->bcs
[0].BC_SetStack
= setstack_w6692
;
896 cs
->bcs
[1].BC_SetStack
= setstack_w6692
;
897 cs
->bcs
[0].BC_Close
= close_w6692state
;
898 cs
->bcs
[1].BC_Close
= close_w6692state
;
899 W6692Bmode(cs
->bcs
, 0, 0);
900 W6692Bmode(cs
->bcs
+ 1, 0, 0);
903 /* Reenable all IRQ */
904 cs
->writeW6692(cs
, W_IMASK
, 0x18);
905 cs
->writeW6692(cs
, W_D_EXIM
, 0x00);
906 cs
->BC_Write_Reg(cs
, 0, W_B_EXIM
, 0x00);
907 cs
->BC_Write_Reg(cs
, 1, W_B_EXIM
, 0x00);
908 /* Reset D-chan receiver and transmitter */
909 cs
->writeW6692(cs
, W_D_CMDR
, W_D_CMDR_RRST
| W_D_CMDR_XRST
);
913 /* Interface functions */
916 ReadW6692(struct IsdnCardState
*cs
, u_char offset
)
918 return (inb(cs
->hw
.w6692
.iobase
+ offset
));
922 WriteW6692(struct IsdnCardState
*cs
, u_char offset
, u_char value
)
924 outb(value
, cs
->hw
.w6692
.iobase
+ offset
);
928 ReadISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
930 insb(cs
->hw
.w6692
.iobase
+ W_D_RFIFO
, data
, size
);
934 WriteISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
936 outsb(cs
->hw
.w6692
.iobase
+ W_D_XFIFO
, data
, size
);
940 ReadW6692B(struct IsdnCardState
*cs
, int bchan
, u_char offset
)
942 return (inb(cs
->hw
.w6692
.iobase
+ (bchan
? 0x40 : 0) + offset
));
946 WriteW6692B(struct IsdnCardState
*cs
, int bchan
, u_char offset
, u_char value
)
948 outb(value
, cs
->hw
.w6692
.iobase
+ (bchan
? 0x40 : 0) + offset
);
952 w6692_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
958 release_region(cs
->hw
.w6692
.iobase
, 256);
969 static int id_idx
= 0;
971 static struct pci_dev
*dev_w6692 __initdata
= NULL
;
973 __initfunc(int setup_w6692(struct IsdnCard
*card
))
975 struct IsdnCardState
*cs
= card
->cs
;
979 u_int pci_ioaddr
= 0;
982 #error "not running on big endian machines now"
984 strcpy(tmp
, w6692_revision
);
985 printk(KERN_INFO
"HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp
));
986 if (cs
->typ
!= ISDN_CTYPE_W6692
)
989 if (!pci_present()) {
990 printk(KERN_ERR
"W6692: no PCI bus present\n");
993 while (id_list
[id_idx
].vendor_id
) {
994 dev_w6692
= pci_find_device(id_list
[id_idx
].vendor_id
,
995 id_list
[id_idx
].device_id
,
998 if (pci_enable_device(dev_w6692
))
1006 pci_irq
= dev_w6692
->irq
;
1007 /* I think address 0 is allways the configuration area */
1008 /* and address 1 is the real IO space KKe 03.09.99 */
1009 pci_ioaddr
= pci_resource_start(dev_w6692
, 1);
1012 printk(KERN_WARNING
"W6692: No PCI card found\n");
1017 printk(KERN_WARNING
"W6692: No IRQ for PCI card found\n");
1021 printk(KERN_WARNING
"W6692: NO I/O Base Address found\n");
1024 cs
->hw
.w6692
.iobase
= pci_ioaddr
;
1025 printk(KERN_INFO
"Found: %s %s, I/O base: 0x%x, irq: %d\n",
1026 id_list
[id_idx
].vendor_name
, id_list
[id_idx
].card_name
,
1027 pci_ioaddr
, dev_w6692
->irq
);
1028 if (check_region((cs
->hw
.w6692
.iobase
), 256)) {
1030 "HiSax: %s I/O ports %x-%x already in use\n",
1031 id_list
[id_idx
].card_name
,
1032 cs
->hw
.w6692
.iobase
,
1033 cs
->hw
.w6692
.iobase
+ 255);
1036 request_region(cs
->hw
.w6692
.iobase
, 256,
1037 id_list
[id_idx
].card_name
);
1040 printk(KERN_WARNING
"HiSax: W6692 and NO_PCI_BIOS\n");
1041 printk(KERN_WARNING
"HiSax: W6692 unable to config\n");
1043 #endif /* CONFIG_PCI */
1046 "HiSax: %s config irq:%d I/O:%x\n",
1047 id_list
[id_idx
].card_name
, cs
->irq
,
1048 cs
->hw
.w6692
.iobase
);
1050 cs
->readW6692
= &ReadW6692
;
1051 cs
->writeW6692
= &WriteW6692
;
1052 cs
->readisacfifo
= &ReadISACfifo
;
1053 cs
->writeisacfifo
= &WriteISACfifo
;
1054 cs
->BC_Read_Reg
= &ReadW6692B
;
1055 cs
->BC_Write_Reg
= &WriteW6692B
;
1056 cs
->BC_Send_Data
= &W6692B_fill_fifo
;
1057 cs
->cardmsg
= &w6692_card_msg
;
1058 cs
->irq_func
= &W6692_interrupt
;
1059 W6692Version(cs
, "W6692:");
1060 printk(KERN_INFO
"W6692 ISTA=0x%X\n", ReadW6692(cs
, W_ISTA
));
1061 printk(KERN_INFO
"W6692 IMASK=0x%X\n", ReadW6692(cs
, W_IMASK
));
1062 printk(KERN_INFO
"W6692 D_EXIR=0x%X\n", ReadW6692(cs
, W_D_EXIR
));
1063 printk(KERN_INFO
"W6692 D_EXIM=0x%X\n", ReadW6692(cs
, W_D_EXIM
));
1064 printk(KERN_INFO
"W6692 D_RSTA=0x%X\n", ReadW6692(cs
, W_D_RSTA
));