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