OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [isdn/] [hisax/] [amd7930_fn.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* gerdes_amd7930.c,v 0.99 2001/10/02
2
 *
3
 * gerdes_amd7930.c     Amd 79C30A and 79C32A specific routines
4
 *                      (based on HiSax driver by Karsten Keil)
5
 *
6
 * Author               Christoph Ersfeld <info@formula-n.de>
7
 *                      Formula-n Europe AG (www.formula-n.com)
8
 *                      previously Gerdes AG
9
 *
10
 *
11
 *                      This file is (c) under GNU PUBLIC LICENSE
12
 *
13
 *
14
 * Notes:
15
 * Version 0.99 is the first release of this driver and there are
16
 * certainly a few bugs.
17
 *
18
 * Please don't report any malfunction to me without sending
19
 * (compressed) debug-logs.
20
 * It would be nearly impossible to retrace it.
21
 *
22
 * Log D-channel-processing as follows:
23
 *
24
 * 1. Load hisax with card-specific parameters, this example ist for
25
 *    Formula-n enter:now ISDN PCI and compatible
26
 *    (f.e. Gerdes Power ISDN PCI)
27
 *
28
 *    modprobe hisax type=41 protocol=2 id=gerdes
29
 *
30
 *    if you chose an other value for id, you need to modify the
31
 *    code below, too.
32
 *
33
 * 2. set debug-level
34
 *
35
 *    hisaxctrl gerdes 1 0x3ff
36
 *    hisaxctrl gerdes 11 0x4f
37
 *    cat /dev/isdnctrl >> ~/log &
38
 *
39
 * Please take also a look into /var/log/messages if there is
40
 * anything importand concerning HISAX.
41
 *
42
 *
43
 * Credits:
44
 * Programming the driver for Formula-n enter:now ISDN PCI and
45
 * necessary this driver for the used Amd 7930 D-channel-controller
46
 * was spnsored by Formula-n Europe AG.
47
 * Thanks to Karsten Keil and Petr Novak, who gave me support in
48
 * Hisax-specific questions.
49
 * I want so say special thanks to Carl-Friedrich Braun, who had to
50
 * answer a lot of questions about generally ISDN and about handling
51
 * of the Amd-Chip.
52
 *
53
 */
54
 
55
 
56
#include "hisax.h"
57
#include "isdnl1.h"
58
#include "isac.h"
59
#include "amd7930_fn.h"
60
#include <linux/interrupt.h>
61
#include <linux/init.h>
62
 
63
static void Amd7930_new_ph(struct IsdnCardState *cs);
64
 
65
static WORD initAMD[] = {
66
        0x0100,
67
 
68
        0x00A5, 3, 0x01, 0x40, 0x58,                            // LPR, LMR1, LMR2
69
        0x0086, 1, 0x0B,                                        // DMR1 (D-Buffer TH-Interrupts on)
70
        0x0087, 1, 0xFF,                                        // DMR2
71
        0x0092, 1, 0x03,                                        // EFCR (extended mode d-channel-fifo on)
72
        0x0090, 4, 0xFE, 0xFF, 0x02, 0x0F,                      // FRAR4, SRAR4, DMR3, DMR4 (address recognition )
73
        0x0084, 2, 0x80, 0x00,                                  // DRLR
74
        0x00C0, 1, 0x47,                                        // PPCR1
75
        0x00C8, 1, 0x01,                                        // PPCR2
76
 
77
        0x0102,
78
        0x0107,
79
        0x01A1, 1,
80
        0x0121, 1,
81
        0x0189, 2,
82
 
83
        0x0045, 4, 0x61, 0x72, 0x00, 0x00,                      // MCR1, MCR2, MCR3, MCR4
84
        0x0063, 2, 0x08, 0x08,                                  // GX
85
        0x0064, 2, 0x08, 0x08,                                  // GR
86
        0x0065, 2, 0x99, 0x00,                                  // GER
87
        0x0066, 2, 0x7C, 0x8B,                                  // STG
88
        0x0067, 2, 0x00, 0x00,                                  // FTGR1, FTGR2
89
        0x0068, 2, 0x20, 0x20,                                  // ATGR1, ATGR2
90
        0x0069, 1, 0x4F,                                        // MMR1
91
        0x006A, 1, 0x00,                                        // MMR2
92
        0x006C, 1, 0x40,                                        // MMR3
93
        0x0021, 1, 0x02,                                        // INIT
94
        0x00A3, 1, 0x40,                                        // LMR1
95
 
96
        0xFFFF
97
};
98
 
99
 
100
static void /* macro wWordAMD */
101
WriteWordAmd7930(struct IsdnCardState *cs, BYTE reg, WORD val)
102
{
103
        wByteAMD(cs, 0x00, reg);
104
        wByteAMD(cs, 0x01, LOBYTE(val));
105
        wByteAMD(cs, 0x01, HIBYTE(val));
106
}
107
 
108
static WORD /* macro rWordAMD */
109
ReadWordAmd7930(struct IsdnCardState *cs, BYTE reg)
110
{
111
        WORD res;
112
        /* direct access register */
113
        if(reg < 8) {
114
                res = rByteAMD(cs, reg);
115
                res += 256*rByteAMD(cs, reg);
116
        }
117
        /* indirect access register */
118
        else {
119
                wByteAMD(cs, 0x00, reg);
120
                res = rByteAMD(cs, 0x01);
121
                res += 256*rByteAMD(cs, 0x01);
122
        }
123
        return (res);
124
}
125
 
126
 
127
static void
128
Amd7930_ph_command(struct IsdnCardState *cs, u_char command, char *s)
129
{
130
        if (cs->debug & L1_DEB_ISAC)
131
                debugl1(cs, "AMD7930: %s: ph_command 0x%02X", s, command);
132
 
133
        cs->dc.amd7930.lmr1 = command;
134
        wByteAMD(cs, 0xA3, command);
135
}
136
 
137
 
138
 
139
static BYTE i430States[] = {
140
// to   reset  F3    F4    F5    F6    F7    F8    AR     from
141
        0x01, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x00,   // init
142
        0x01, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x00,   // reset
143
        0x01, 0x02, 0x00, 0x00, 0x00, 0x09, 0x05, 0x04,   // F3
144
        0x01, 0x02, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00,   // F4
145
        0x01, 0x02, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00,   // F5
146
        0x01, 0x03, 0x00, 0x00, 0x00, 0x06, 0x05, 0x00,   // F6
147
        0x11, 0x13, 0x00, 0x00, 0x1B, 0x00, 0x15, 0x00,   // F7
148
        0x01, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,   // F8
149
        0x01, 0x03, 0x00, 0x00, 0x00, 0x09, 0x00, 0x0A};  // AR
150
 
151
 
152
/*                    Row     init    -   reset  F3    F4    F5    F6    F7    F8    AR */
153
static BYTE stateHelper[] = { 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
154
 
155
 
156
 
157
 
158
static void
159
Amd7930_get_state(struct IsdnCardState *cs) {
160
        BYTE lsr = rByteAMD(cs, 0xA1);
161
        cs->dc.amd7930.ph_state = (lsr & 0x7) + 2;
162
        Amd7930_new_ph(cs);
163
}
164
 
165
 
166
 
167
static void
168
Amd7930_new_ph(struct IsdnCardState *cs)
169
{
170
        u_char index = stateHelper[cs->dc.amd7930.old_state]*8 + stateHelper[cs->dc.amd7930.ph_state]-1;
171
        u_char message = i430States[index];
172
 
173
        if (cs->debug & L1_DEB_ISAC)
174
                debugl1(cs, "AMD7930: new_ph %d, old_ph %d, message %d, index %d",
175
                        cs->dc.amd7930.ph_state, cs->dc.amd7930.old_state, message & 0x0f, index);
176
 
177
        cs->dc.amd7930.old_state = cs->dc.amd7930.ph_state;
178
 
179
        /* abort transmit if nessesary */
180
        if ((message & 0xf0) && (cs->tx_skb)) {
181
                wByteAMD(cs, 0x21, 0xC2);
182
                wByteAMD(cs, 0x21, 0x02);
183
        }
184
 
185
        switch (message & 0x0f) {
186
 
187
                case (1):
188
                        l1_msg(cs, HW_RESET | INDICATION, NULL);
189
                        Amd7930_get_state(cs);
190
                        break;
191
                case (2): /* init, Card starts in F3 */
192
                        l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
193
                        break;
194
                case (3):
195
                        l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
196
                        break;
197
                case (4):
198
                        l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
199
                        Amd7930_ph_command(cs, 0x50, "HW_ENABLE REQUEST");
200
                        break;
201
                case (5):
202
                        l1_msg(cs, HW_RSYNC | INDICATION, NULL);
203
                        break;
204
                case (6):
205
                        l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
206
                        break;
207
                case (7): /* init, Card starts in F7 */
208
                        l1_msg(cs, HW_RSYNC | INDICATION, NULL);
209
                        l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
210
                        break;
211
                case (8):
212
                        l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
213
                        /* fall through */
214
                case (9):
215
                        Amd7930_ph_command(cs, 0x40, "HW_ENABLE REQ cleared if set");
216
                        l1_msg(cs, HW_RSYNC | INDICATION, NULL);
217
                        l1_msg(cs, HW_INFO2 | INDICATION, NULL);
218
                        l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
219
                        break;
220
                case (10):
221
                        Amd7930_ph_command(cs, 0x40, "T3 expired, HW_ENABLE REQ cleared");
222
                        cs->dc.amd7930.old_state = 3;
223
                        break;
224
                case (11):
225
                        l1_msg(cs, HW_INFO2 | INDICATION, NULL);
226
                        break;
227
                default:
228
                        break;
229
        }
230
}
231
 
232
 
233
 
234
static void
235
Amd7930_bh(struct work_struct *work)
236
{
237
        struct IsdnCardState *cs =
238
                container_of(work, struct IsdnCardState, tqueue);
239
        struct PStack *stptr;
240
 
241
        if (!cs)
242
                return;
243
        if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
244
                if (cs->debug)
245
                        debugl1(cs, "Amd7930: bh, D-Channel Busy cleared");
246
                stptr = cs->stlist;
247
                while (stptr != NULL) {
248
                        stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
249
                        stptr = stptr->next;
250
                }
251
        }
252
        if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
253
                if (cs->debug & L1_DEB_ISAC)
254
                        debugl1(cs, "AMD7930: bh, D_L1STATECHANGE");
255
                Amd7930_new_ph(cs);
256
        }
257
 
258
        if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) {
259
                if (cs->debug & L1_DEB_ISAC)
260
                        debugl1(cs, "AMD7930: bh, D_RCVBUFREADY");
261
                DChannel_proc_rcv(cs);
262
        }
263
 
264
        if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) {
265
                if (cs->debug & L1_DEB_ISAC)
266
                        debugl1(cs, "AMD7930: bh, D_XMTBUFREADY");
267
                DChannel_proc_xmt(cs);
268
        }
269
}
270
 
271
static void
272
Amd7930_empty_Dfifo(struct IsdnCardState *cs, int flag)
273
{
274
 
275
        BYTE stat, der;
276
        BYTE *ptr;
277
        struct sk_buff *skb;
278
 
279
 
280
        if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
281
                debugl1(cs, "Amd7930: empty_Dfifo");
282
 
283
 
284
        ptr = cs->rcvbuf + cs->rcvidx;
285
 
286
        /* AMD interrupts off */
287
        AmdIrqOff(cs);
288
 
289
        /* read D-Channel-Fifo*/
290
        stat = rByteAMD(cs, 0x07); // DSR2
291
 
292
                /* while Data in Fifo ... */
293
                while ( (stat & 2) && ((ptr-cs->rcvbuf) < MAX_DFRAME_LEN_L1) ) {
294
                        *ptr = rByteAMD(cs, 0x04); // DCRB
295
                        ptr++;
296
                        stat = rByteAMD(cs, 0x07); // DSR2
297
                        cs->rcvidx = ptr - cs->rcvbuf;
298
 
299
                        /* Paket ready? */
300
                        if (stat & 1) {
301
 
302
                                der = rWordAMD(cs, 0x03);
303
 
304
                                /* no errors, packet ok */
305
                                if(!der && !flag) {
306
                                        rWordAMD(cs, 0x89); // clear DRCR
307
 
308
                                        if ((cs->rcvidx) > 0) {
309
                                                if (!(skb = alloc_skb(cs->rcvidx, GFP_ATOMIC)))
310
                                                        printk(KERN_WARNING "HiSax: Amd7930: empty_Dfifo, D receive out of memory!\n");
311
                                                else {
312
                                                        /* Debugging */
313
                                                        if (cs->debug & L1_DEB_ISAC_FIFO) {
314
                                                                char *t = cs->dlog;
315
 
316
                                                                t += sprintf(t, "Amd7930: empty_Dfifo cnt: %d |", cs->rcvidx);
317
                                                                QuickHex(t, cs->rcvbuf, cs->rcvidx);
318
                                                                debugl1(cs, cs->dlog);
319
                                                        }
320
                                                        /* moves received data in sk-buffer */
321
                                                        memcpy(skb_put(skb, cs->rcvidx), cs->rcvbuf, cs->rcvidx);
322
                                                        skb_queue_tail(&cs->rq, skb);
323
                                                }
324
                                        }
325
 
326
                                }
327
                                /* throw damaged packets away, reset receive-buffer, indicate RX */
328
                                ptr = cs->rcvbuf;
329
                                cs->rcvidx = 0;
330
                                schedule_event(cs, D_RCVBUFREADY);
331
                        }
332
                }
333
                /* Packet to long, overflow */
334
                if(cs->rcvidx >= MAX_DFRAME_LEN_L1) {
335
                        if (cs->debug & L1_DEB_WARN)
336
                                debugl1(cs, "AMD7930: empty_Dfifo L2-Framelength overrun");
337
                        cs->rcvidx = 0;
338
                        return;
339
                }
340
        /* AMD interrupts on */
341
        AmdIrqOn(cs);
342
}
343
 
344
 
345
static void
346
Amd7930_fill_Dfifo(struct IsdnCardState *cs)
347
{
348
 
349
        WORD dtcrr, dtcrw, len, count;
350
        BYTE txstat, dmr3;
351
        BYTE *ptr, *deb_ptr;
352
 
353
        if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
354
                debugl1(cs, "Amd7930: fill_Dfifo");
355
 
356
        if ((!cs->tx_skb) || (cs->tx_skb->len <= 0))
357
                return;
358
 
359
        dtcrw = 0;
360
        if(!cs->dc.amd7930.tx_xmtlen)
361
                /* new Frame */
362
                len = dtcrw = cs->tx_skb->len;
363
        /* continue frame */
364
        else len = cs->dc.amd7930.tx_xmtlen;
365
 
366
 
367
        /* AMD interrupts off */
368
        AmdIrqOff(cs);
369
 
370
        deb_ptr = ptr = cs->tx_skb->data;
371
 
372
        /* while free place in tx-fifo available and data in sk-buffer */
373
        txstat = 0x10;
374
        while((txstat & 0x10) && (cs->tx_cnt < len)) {
375
                wByteAMD(cs, 0x04, *ptr);
376
                ptr++;
377
                cs->tx_cnt++;
378
                txstat= rByteAMD(cs, 0x07);
379
        }
380
        count = ptr - cs->tx_skb->data;
381
        skb_pull(cs->tx_skb, count);
382
 
383
 
384
        dtcrr = rWordAMD(cs, 0x85); // DTCR
385
        dmr3  = rByteAMD(cs, 0x8E);
386
 
387
        if (cs->debug & L1_DEB_ISAC) {
388
                debugl1(cs, "Amd7930: fill_Dfifo, DMR3: 0x%02X, DTCR read: 0x%04X write: 0x%02X 0x%02X", dmr3, dtcrr, LOBYTE(dtcrw), HIBYTE(dtcrw));
389
        }
390
 
391
        /* writeing of dtcrw starts transmit */
392
        if(!cs->dc.amd7930.tx_xmtlen) {
393
                wWordAMD(cs, 0x85, dtcrw);
394
                cs->dc.amd7930.tx_xmtlen = dtcrw;
395
        }
396
 
397
        if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
398
                debugl1(cs, "Amd7930: fill_Dfifo dbusytimer running");
399
                del_timer(&cs->dbusytimer);
400
        }
401
        init_timer(&cs->dbusytimer);
402
        cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000);
403
        add_timer(&cs->dbusytimer);
404
 
405
        if (cs->debug & L1_DEB_ISAC_FIFO) {
406
                char *t = cs->dlog;
407
 
408
                t += sprintf(t, "Amd7930: fill_Dfifo cnt: %d |", count);
409
                QuickHex(t, deb_ptr, count);
410
                debugl1(cs, cs->dlog);
411
        }
412
        /* AMD interrupts on */
413
        AmdIrqOn(cs);
414
}
415
 
416
 
417
void Amd7930_interrupt(struct IsdnCardState *cs, BYTE irflags)
418
{
419
        BYTE dsr1, dsr2, lsr;
420
        WORD der;
421
 
422
 while (irflags)
423
 {
424
 
425
        dsr1 = rByteAMD(cs, 0x02);
426
        der  = rWordAMD(cs, 0x03);
427
        dsr2 = rByteAMD(cs, 0x07);
428
        lsr  = rByteAMD(cs, 0xA1);
429
 
430
        if (cs->debug & L1_DEB_ISAC)
431
                debugl1(cs, "Amd7930: interrupt: flags: 0x%02X, DSR1: 0x%02X, DSR2: 0x%02X, LSR: 0x%02X, DER=0x%04X", irflags, dsr1, dsr2, lsr, der);
432
 
433
        /* D error -> read DER and DSR2 bit 2 */
434
        if (der || (dsr2 & 4)) {
435
 
436
                if (cs->debug & L1_DEB_WARN)
437
                        debugl1(cs, "Amd7930: interrupt: D error DER=0x%04X", der);
438
 
439
                /* RX, TX abort if collision detected */
440
                if (der & 2) {
441
                        wByteAMD(cs, 0x21, 0xC2);
442
                        wByteAMD(cs, 0x21, 0x02);
443
                        if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
444
                                del_timer(&cs->dbusytimer);
445
                        if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
446
                                schedule_event(cs, D_CLEARBUSY);
447
                        /* restart frame */
448
                        if (cs->tx_skb) {
449
                                skb_push(cs->tx_skb, cs->tx_cnt);
450
                                cs->tx_cnt = 0;
451
                                cs->dc.amd7930.tx_xmtlen = 0;
452
                                Amd7930_fill_Dfifo(cs);
453
                        } else {
454
                                printk(KERN_WARNING "HiSax: Amd7930 D-Collision, no skb\n");
455
                                debugl1(cs, "Amd7930: interrupt: D-Collision, no skb");
456
                        }
457
                }
458
                /* remove damaged data from fifo */
459
                Amd7930_empty_Dfifo(cs, 1);
460
 
461
                if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
462
                        del_timer(&cs->dbusytimer);
463
                if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
464
                        schedule_event(cs, D_CLEARBUSY);
465
                /* restart TX-Frame */
466
                if (cs->tx_skb) {
467
                        skb_push(cs->tx_skb, cs->tx_cnt);
468
                        cs->tx_cnt = 0;
469
                        cs->dc.amd7930.tx_xmtlen = 0;
470
                        Amd7930_fill_Dfifo(cs);
471
                }
472
        }
473
 
474
        /* D TX FIFO empty -> fill */
475
        if (irflags & 1) {
476
                if (cs->debug & L1_DEB_ISAC)
477
                        debugl1(cs, "Amd7930: interrupt: clear Timer and fill D-TX-FIFO if data");
478
 
479
                /* AMD interrupts off */
480
                AmdIrqOff(cs);
481
 
482
                if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
483
                        del_timer(&cs->dbusytimer);
484
                if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
485
                        schedule_event(cs, D_CLEARBUSY);
486
                if (cs->tx_skb) {
487
                        if (cs->tx_skb->len)
488
                                Amd7930_fill_Dfifo(cs);
489
                }
490
                /* AMD interrupts on */
491
                AmdIrqOn(cs);
492
        }
493
 
494
 
495
        /* D RX FIFO full or tiny packet in Fifo -> empty */
496
        if ((irflags & 2) || (dsr1 & 2)) {
497
                if (cs->debug & L1_DEB_ISAC)
498
                        debugl1(cs, "Amd7930: interrupt: empty D-FIFO");
499
                Amd7930_empty_Dfifo(cs, 0);
500
        }
501
 
502
 
503
        /* D-Frame transmit complete */
504
        if (dsr1 & 64) {
505
                if (cs->debug & L1_DEB_ISAC) {
506
                        debugl1(cs, "Amd7930: interrupt: transmit packet ready");
507
                }
508
                /* AMD interrupts off */
509
                AmdIrqOff(cs);
510
 
511
                if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
512
                        del_timer(&cs->dbusytimer);
513
                if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
514
                        schedule_event(cs, D_CLEARBUSY);
515
 
516
                if (cs->tx_skb) {
517
                        if (cs->debug & L1_DEB_ISAC)
518
                                debugl1(cs, "Amd7930: interrupt: TX-Packet ready, freeing skb");
519
                        dev_kfree_skb_irq(cs->tx_skb);
520
                        cs->tx_cnt = 0;
521
                        cs->dc.amd7930.tx_xmtlen=0;
522
                        cs->tx_skb = NULL;
523
                }
524
                if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
525
                        if (cs->debug & L1_DEB_ISAC)
526
                                debugl1(cs, "Amd7930: interrupt: TX-Packet ready, next packet dequeued");
527
                        cs->tx_cnt = 0;
528
                        cs->dc.amd7930.tx_xmtlen=0;
529
                        Amd7930_fill_Dfifo(cs);
530
                }
531
                else
532
                        schedule_event(cs, D_XMTBUFREADY);
533
                /* AMD interrupts on */
534
                AmdIrqOn(cs);
535
        }
536
 
537
        /* LIU status interrupt -> read LSR, check statechanges */
538
        if (lsr & 0x38) {
539
                /* AMD interrupts off */
540
                AmdIrqOff(cs);
541
 
542
                if (cs->debug & L1_DEB_ISAC)
543
                        debugl1(cs, "Amd: interrupt: LSR=0x%02X, LIU is in state %d", lsr, ((lsr & 0x7) +2));
544
 
545
                cs->dc.amd7930.ph_state = (lsr & 0x7) + 2;
546
 
547
                schedule_event(cs, D_L1STATECHANGE);
548
                /* AMD interrupts on */
549
                AmdIrqOn(cs);
550
        }
551
 
552
        /* reads Interrupt-Register again. If there is a new interrupt-flag: restart handler */
553
        irflags = rByteAMD(cs, 0x00);
554
 }
555
 
556
}
557
 
558
static void
559
Amd7930_l1hw(struct PStack *st, int pr, void *arg)
560
{
561
        struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
562
        struct sk_buff *skb = arg;
563
        u_long flags;
564
 
565
        if (cs->debug & L1_DEB_ISAC)
566
                debugl1(cs, "Amd7930: l1hw called, pr: 0x%04X", pr);
567
 
568
        switch (pr) {
569
                case (PH_DATA | REQUEST):
570
                        if (cs->debug & DEB_DLOG_HEX)
571
                                LogFrame(cs, skb->data, skb->len);
572
                        if (cs->debug & DEB_DLOG_VERBOSE)
573
                                dlogframe(cs, skb, 0);
574
                        spin_lock_irqsave(&cs->lock, flags);
575
                        if (cs->tx_skb) {
576
                                skb_queue_tail(&cs->sq, skb);
577
#ifdef L2FRAME_DEBUG            /* psa */
578
                                if (cs->debug & L1_DEB_LAPD)
579
                                        Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA Queued", 0);
580
#endif
581
                        } else {
582
                                cs->tx_skb = skb;
583
                                cs->tx_cnt = 0;
584
                                cs->dc.amd7930.tx_xmtlen=0;
585
#ifdef L2FRAME_DEBUG            /* psa */
586
                                if (cs->debug & L1_DEB_LAPD)
587
                                        Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA", 0);
588
#endif
589
                                Amd7930_fill_Dfifo(cs);
590
                        }
591
                        spin_unlock_irqrestore(&cs->lock, flags);
592
                        break;
593
                case (PH_PULL | INDICATION):
594
                        spin_lock_irqsave(&cs->lock, flags);
595
                        if (cs->tx_skb) {
596
                                if (cs->debug & L1_DEB_WARN)
597
                                        debugl1(cs, "Amd7930: l1hw: l2l1 tx_skb exist this shouldn't happen");
598
                                skb_queue_tail(&cs->sq, skb);
599
                                break;
600
                        }
601
                        if (cs->debug & DEB_DLOG_HEX)
602
                                LogFrame(cs, skb->data, skb->len);
603
                        if (cs->debug & DEB_DLOG_VERBOSE)
604
                                dlogframe(cs, skb, 0);
605
                        cs->tx_skb = skb;
606
                        cs->tx_cnt = 0;
607
                        cs->dc.amd7930.tx_xmtlen=0;
608
#ifdef L2FRAME_DEBUG            /* psa */
609
                        if (cs->debug & L1_DEB_LAPD)
610
                                Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA_PULLED", 0);
611
#endif
612
                        Amd7930_fill_Dfifo(cs);
613
                        spin_unlock_irqrestore(&cs->lock, flags);
614
                        break;
615
                case (PH_PULL | REQUEST):
616
#ifdef L2FRAME_DEBUG            /* psa */
617
                        if (cs->debug & L1_DEB_LAPD)
618
                                debugl1(cs, "Amd7930: l1hw: -> PH_REQUEST_PULL, skb: %s", (cs->tx_skb)? "yes":"no");
619
#endif
620
                        if (!cs->tx_skb) {
621
                                test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
622
                                st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
623
                        } else
624
                                test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
625
                        break;
626
                case (HW_RESET | REQUEST):
627
                        spin_lock_irqsave(&cs->lock, flags);
628
                        if ((cs->dc.amd7930.ph_state == 8)) {
629
                                /* b-channels off, PH-AR cleared
630
                                 * change to F3 */
631
                                Amd7930_ph_command(cs, 0x20, "HW_RESET REQEST"); //LMR1 bit 5
632
                                spin_unlock_irqrestore(&cs->lock, flags);
633
                        } else {
634
                                Amd7930_ph_command(cs, 0x40, "HW_RESET REQUEST");
635
                                cs->dc.amd7930.ph_state = 2;
636
                                spin_unlock_irqrestore(&cs->lock, flags);
637
                                Amd7930_new_ph(cs);
638
                        }
639
                        break;
640
                case (HW_ENABLE | REQUEST):
641
                        cs->dc.amd7930.ph_state = 9;
642
                        Amd7930_new_ph(cs);
643
                        break;
644
                case (HW_INFO3 | REQUEST):
645
                        // automatic
646
                        break;
647
                case (HW_TESTLOOP | REQUEST):
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(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
                                schedule_event(cs, D_CLEARBUSY);
661
                        break;
662
                default:
663
                        if (cs->debug & L1_DEB_WARN)
664
                                debugl1(cs, "Amd7930: l1hw: unknown %04x", pr);
665
                        break;
666
        }
667
}
668
 
669
static void
670
setstack_Amd7930(struct PStack *st, struct IsdnCardState *cs)
671
{
672
 
673
        if (cs->debug & L1_DEB_ISAC)
674
                debugl1(cs, "Amd7930: setstack called");
675
 
676
        st->l1.l1hw = Amd7930_l1hw;
677
}
678
 
679
 
680
static void
681
DC_Close_Amd7930(struct IsdnCardState *cs) {
682
        if (cs->debug & L1_DEB_ISAC)
683
                debugl1(cs, "Amd7930: DC_Close called");
684
}
685
 
686
 
687
static void
688
dbusy_timer_handler(struct IsdnCardState *cs)
689
{
690
        u_long flags;
691
        struct PStack *stptr;
692
        WORD dtcr, der;
693
        BYTE dsr1, dsr2;
694
 
695
 
696
        if (cs->debug & L1_DEB_ISAC)
697
                debugl1(cs, "Amd7930: dbusy_timer expired!");
698
 
699
        if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
700
                spin_lock_irqsave(&cs->lock, flags);
701
                /* D Transmit Byte Count Register:
702
                 * Counts down packet's number of Bytes, 0 if packet ready */
703
                dtcr = rWordAMD(cs, 0x85);
704
                dsr1 = rByteAMD(cs, 0x02);
705
                dsr2 = rByteAMD(cs, 0x07);
706
                der  = rWordAMD(cs, 0x03);
707
 
708
                if (cs->debug & L1_DEB_ISAC)
709
                        debugl1(cs, "Amd7930: dbusy_timer_handler: DSR1=0x%02X, DSR2=0x%02X, DER=0x%04X, cs->tx_skb->len=%u, tx_stat=%u, dtcr=%u, cs->tx_cnt=%u", dsr1, dsr2, der, cs->tx_skb->len, cs->dc.amd7930.tx_xmtlen, dtcr, cs->tx_cnt);
710
 
711
                if ((cs->dc.amd7930.tx_xmtlen - dtcr) < cs->tx_cnt) {   /* D-Channel Busy */
712
                        test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
713
                        stptr = cs->stlist;
714
                        spin_unlock_irqrestore(&cs->lock, flags);
715
                        while (stptr != NULL) {
716
                                stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
717
                                stptr = stptr->next;
718
                        }
719
 
720
                } else {
721
                        /* discard frame; reset transceiver */
722
                        test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags);
723
                        if (cs->tx_skb) {
724
                                dev_kfree_skb_any(cs->tx_skb);
725
                                cs->tx_cnt = 0;
726
                                cs->tx_skb = NULL;
727
                                cs->dc.amd7930.tx_xmtlen = 0;
728
                        } else {
729
                                printk(KERN_WARNING "HiSax: Amd7930: D-Channel Busy no skb\n");
730
                                debugl1(cs, "Amd7930: D-Channel Busy no skb");
731
 
732
                        }
733
                        /* Transmitter reset, abort transmit */
734
                        wByteAMD(cs, 0x21, 0x82);
735
                        wByteAMD(cs, 0x21, 0x02);
736
                        spin_unlock_irqrestore(&cs->lock, flags);
737
                        cs->irq_func(cs->irq, cs);
738
 
739
                        if (cs->debug & L1_DEB_ISAC)
740
                                debugl1(cs, "Amd7930: dbusy_timer_handler: Transmitter reset");
741
                }
742
        }
743
}
744
 
745
 
746
 
747
void __devinit
748
Amd7930_init(struct IsdnCardState *cs)
749
{
750
    WORD *ptr;
751
    BYTE cmd, cnt;
752
 
753
        if (cs->debug & L1_DEB_ISAC)
754
                debugl1(cs, "Amd7930: initamd called");
755
 
756
        cs->dc.amd7930.tx_xmtlen = 0;
757
        cs->dc.amd7930.old_state = 0;
758
        cs->dc.amd7930.lmr1 = 0x40;
759
        cs->dc.amd7930.ph_command = Amd7930_ph_command;
760
        cs->setstack_d = setstack_Amd7930;
761
        cs->DC_Close = DC_Close_Amd7930;
762
 
763
        /* AMD Initialisation */
764
        for (ptr = initAMD; *ptr != 0xFFFF; ) {
765
                cmd = LOBYTE(*ptr);
766
 
767
                /* read */
768
                if (*ptr++ >= 0x100) {
769
                        if (cmd < 8)
770
                                /* reset register */
771
                                rByteAMD(cs, cmd);
772
                        else {
773
                                wByteAMD(cs, 0x00, cmd);
774
                                for (cnt = *ptr++; cnt > 0; cnt--)
775
                                        rByteAMD(cs, 0x01);
776
                        }
777
                }
778
                /* write */
779
                else if (cmd < 8)
780
                        wByteAMD(cs, cmd, LOBYTE(*ptr++));
781
 
782
                else {
783
                        wByteAMD(cs, 0x00, cmd);
784
                        for (cnt = *ptr++; cnt > 0; cnt--)
785
                                wByteAMD(cs, 0x01, LOBYTE(*ptr++));
786
                }
787
        }
788
}
789
 
790
void __devinit
791
setup_Amd7930(struct IsdnCardState *cs)
792
{
793
        INIT_WORK(&cs->tqueue, Amd7930_bh);
794
        cs->dbusytimer.function = (void *) dbusy_timer_handler;
795
        cs->dbusytimer.data = (long) cs;
796
        init_timer(&cs->dbusytimer);
797
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.