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

Subversion Repositories test_project

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* $Id: teles0.c,v 2.15.2.4 2004/01/13 23:48:39 keil Exp $
2
 *
3
 * low level stuff for Teles Memory IO isdn cards
4
 *
5
 * Author       Karsten Keil
6
 *              based on the teles driver from Jan den Ouden
7
 * Copyright    by Karsten Keil      <keil@isdn4linux.de>
8
 *
9
 * This software may be used and distributed according to the terms
10
 * of the GNU General Public License, incorporated herein by reference.
11
 *
12
 * Thanks to    Jan den Ouden
13
 *              Fritz Elfert
14
 *              Beat Doebeli
15
 *
16
 */
17
 
18
#include <linux/init.h>
19
#include "hisax.h"
20
#include "isdnl1.h"
21
#include "isac.h"
22
#include "hscx.h"
23
 
24
extern const char *CardType[];
25
 
26
static const char *teles0_revision = "$Revision: 2.15.2.4 $";
27
 
28
#define TELES_IOMEM_SIZE        0x400
29
#define byteout(addr,val) outb(val,addr)
30
#define bytein(addr) inb(addr)
31
 
32
static inline u_char
33
readisac(void __iomem *adr, u_char off)
34
{
35
        return readb(adr + ((off & 1) ? 0x2ff : 0x100) + off);
36
}
37
 
38
static inline void
39
writeisac(void __iomem *adr, u_char off, u_char data)
40
{
41
        writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off); mb();
42
}
43
 
44
 
45
static inline u_char
46
readhscx(void __iomem *adr, int hscx, u_char off)
47
{
48
        return readb(adr + (hscx ? 0x1c0 : 0x180) +
49
                     ((off & 1) ? 0x1ff : 0) + off);
50
}
51
 
52
static inline void
53
writehscx(void __iomem *adr, int hscx, u_char off, u_char data)
54
{
55
        writeb(data, adr + (hscx ? 0x1c0 : 0x180) +
56
               ((off & 1) ? 0x1ff : 0) + off); mb();
57
}
58
 
59
static inline void
60
read_fifo_isac(void __iomem *adr, u_char * data, int size)
61
{
62
        register int i;
63
        register u_char __iomem *ad = adr + 0x100;
64
        for (i = 0; i < size; i++)
65
                data[i] = readb(ad);
66
}
67
 
68
static inline void
69
write_fifo_isac(void __iomem *adr, u_char * data, int size)
70
{
71
        register int i;
72
        register u_char __iomem *ad = adr + 0x100;
73
        for (i = 0; i < size; i++) {
74
                writeb(data[i], ad); mb();
75
        }
76
}
77
 
78
static inline void
79
read_fifo_hscx(void __iomem *adr, int hscx, u_char * data, int size)
80
{
81
        register int i;
82
        register u_char __iomem *ad = adr + (hscx ? 0x1c0 : 0x180);
83
        for (i = 0; i < size; i++)
84
                data[i] = readb(ad);
85
}
86
 
87
static inline void
88
write_fifo_hscx(void __iomem *adr, int hscx, u_char * data, int size)
89
{
90
        int i;
91
        register u_char __iomem *ad = adr + (hscx ? 0x1c0 : 0x180);
92
        for (i = 0; i < size; i++) {
93
                writeb(data[i], ad); mb();
94
        }
95
}
96
 
97
/* Interface functions */
98
 
99
static u_char
100
ReadISAC(struct IsdnCardState *cs, u_char offset)
101
{
102
        return (readisac(cs->hw.teles0.membase, offset));
103
}
104
 
105
static void
106
WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
107
{
108
        writeisac(cs->hw.teles0.membase, offset, value);
109
}
110
 
111
static void
112
ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
113
{
114
        read_fifo_isac(cs->hw.teles0.membase, data, size);
115
}
116
 
117
static void
118
WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
119
{
120
        write_fifo_isac(cs->hw.teles0.membase, data, size);
121
}
122
 
123
static u_char
124
ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
125
{
126
        return (readhscx(cs->hw.teles0.membase, hscx, offset));
127
}
128
 
129
static void
130
WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
131
{
132
        writehscx(cs->hw.teles0.membase, hscx, offset, value);
133
}
134
 
135
/*
136
 * fast interrupt HSCX stuff goes here
137
 */
138
 
139
#define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg)
140
#define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data)
141
#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
142
#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
143
 
144
#include "hscx_irq.c"
145
 
146
static irqreturn_t
147
teles0_interrupt(int intno, void *dev_id)
148
{
149
        struct IsdnCardState *cs = dev_id;
150
        u_char val;
151
        u_long flags;
152
        int count = 0;
153
 
154
        spin_lock_irqsave(&cs->lock, flags);
155
        val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
156
      Start_HSCX:
157
        if (val)
158
                hscx_int_main(cs, val);
159
        val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
160
      Start_ISAC:
161
        if (val)
162
                isac_interrupt(cs, val);
163
        count++;
164
        val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
165
        if (val && count < 5) {
166
                if (cs->debug & L1_DEB_HSCX)
167
                        debugl1(cs, "HSCX IntStat after IntRoutine");
168
                goto Start_HSCX;
169
        }
170
        val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
171
        if (val && count < 5) {
172
                if (cs->debug & L1_DEB_ISAC)
173
                        debugl1(cs, "ISAC IntStat after IntRoutine");
174
                goto Start_ISAC;
175
        }
176
        writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
177
        writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
178
        writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
179
        writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
180
        writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
181
        writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
182
        spin_unlock_irqrestore(&cs->lock, flags);
183
        return IRQ_HANDLED;
184
}
185
 
186
static void
187
release_io_teles0(struct IsdnCardState *cs)
188
{
189
        if (cs->hw.teles0.cfg_reg)
190
                release_region(cs->hw.teles0.cfg_reg, 8);
191
        iounmap(cs->hw.teles0.membase);
192
        release_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE);
193
}
194
 
195
static int
196
reset_teles0(struct IsdnCardState *cs)
197
{
198
        u_char cfval;
199
 
200
        if (cs->hw.teles0.cfg_reg) {
201
                switch (cs->irq) {
202
                        case 2:
203
                        case 9:
204
                                cfval = 0x00;
205
                                break;
206
                        case 3:
207
                                cfval = 0x02;
208
                                break;
209
                        case 4:
210
                                cfval = 0x04;
211
                                break;
212
                        case 5:
213
                                cfval = 0x06;
214
                                break;
215
                        case 10:
216
                                cfval = 0x08;
217
                                break;
218
                        case 11:
219
                                cfval = 0x0A;
220
                                break;
221
                        case 12:
222
                                cfval = 0x0C;
223
                                break;
224
                        case 15:
225
                                cfval = 0x0E;
226
                                break;
227
                        default:
228
                                return(1);
229
                }
230
                cfval |= ((cs->hw.teles0.phymem >> 9) & 0xF0);
231
                byteout(cs->hw.teles0.cfg_reg + 4, cfval);
232
                HZDELAY(HZ / 10 + 1);
233
                byteout(cs->hw.teles0.cfg_reg + 4, cfval | 1);
234
                HZDELAY(HZ / 10 + 1);
235
        }
236
        writeb(0, cs->hw.teles0.membase + 0x80); mb();
237
        HZDELAY(HZ / 5 + 1);
238
        writeb(1, cs->hw.teles0.membase + 0x80); mb();
239
        HZDELAY(HZ / 5 + 1);
240
        return(0);
241
}
242
 
243
static int
244
Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
245
{
246
        u_long flags;
247
 
248
        switch (mt) {
249
                case CARD_RESET:
250
                        spin_lock_irqsave(&cs->lock, flags);
251
                        reset_teles0(cs);
252
                        spin_unlock_irqrestore(&cs->lock, flags);
253
                        return(0);
254
                case CARD_RELEASE:
255
                        release_io_teles0(cs);
256
                        return(0);
257
                case CARD_INIT:
258
                        spin_lock_irqsave(&cs->lock, flags);
259
                        inithscxisac(cs, 3);
260
                        spin_unlock_irqrestore(&cs->lock, flags);
261
                        return(0);
262
                case CARD_TEST:
263
                        return(0);
264
        }
265
        return(0);
266
}
267
 
268
int __devinit
269
setup_teles0(struct IsdnCard *card)
270
{
271
        u_char val;
272
        struct IsdnCardState *cs = card->cs;
273
        char tmp[64];
274
 
275
        strcpy(tmp, teles0_revision);
276
        printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", HiSax_getrev(tmp));
277
        if ((cs->typ != ISDN_CTYPE_16_0) && (cs->typ != ISDN_CTYPE_8_0))
278
                return (0);
279
 
280
        if (cs->typ == ISDN_CTYPE_16_0)
281
                cs->hw.teles0.cfg_reg = card->para[2];
282
        else                    /* 8.0 */
283
                cs->hw.teles0.cfg_reg = 0;
284
 
285
        if (card->para[1] < 0x10000) {
286
                card->para[1] <<= 4;
287
                printk(KERN_INFO
288
                   "Teles0: membase configured DOSish, assuming 0x%lx\n",
289
                       (unsigned long) card->para[1]);
290
        }
291
        cs->irq = card->para[0];
292
        if (cs->hw.teles0.cfg_reg) {
293
                if (!request_region(cs->hw.teles0.cfg_reg, 8, "teles cfg")) {
294
                        printk(KERN_WARNING
295
                          "HiSax: %s config port %x-%x already in use\n",
296
                               CardType[card->typ],
297
                               cs->hw.teles0.cfg_reg,
298
                               cs->hw.teles0.cfg_reg + 8);
299
                        return (0);
300
                }
301
        }
302
        if (cs->hw.teles0.cfg_reg) {
303
                if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) {
304
                        printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
305
                               cs->hw.teles0.cfg_reg + 0, val);
306
                        release_region(cs->hw.teles0.cfg_reg, 8);
307
                        return (0);
308
                }
309
                if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) {
310
                        printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
311
                               cs->hw.teles0.cfg_reg + 1, val);
312
                        release_region(cs->hw.teles0.cfg_reg, 8);
313
                        return (0);
314
                }
315
                val = bytein(cs->hw.teles0.cfg_reg + 2);        /* 0x1e=without AB
316
                                                                   * 0x1f=with AB
317
                                                                   * 0x1c 16.3 ???
318
                                                                 */
319
                if (val != 0x1e && val != 0x1f) {
320
                        printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
321
                               cs->hw.teles0.cfg_reg + 2, val);
322
                        release_region(cs->hw.teles0.cfg_reg, 8);
323
                        return (0);
324
                }
325
        }
326
        /* 16.0 and 8.0 designed for IOM1 */
327
        test_and_set_bit(HW_IOM1, &cs->HW_Flags);
328
        cs->hw.teles0.phymem = card->para[1];
329
        if (!request_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE, "teles iomem")) {
330
                printk(KERN_WARNING
331
                        "HiSax: %s memory region %lx-%lx already in use\n",
332
                        CardType[card->typ],
333
                        cs->hw.teles0.phymem,
334
                        cs->hw.teles0.phymem + TELES_IOMEM_SIZE);
335
                if (cs->hw.teles0.cfg_reg)
336
                        release_region(cs->hw.teles0.cfg_reg, 8);
337
                return (0);
338
        }
339
        cs->hw.teles0.membase = ioremap(cs->hw.teles0.phymem, TELES_IOMEM_SIZE);
340
        printk(KERN_INFO
341
               "HiSax: %s config irq:%d mem:%p cfg:0x%X\n",
342
               CardType[cs->typ], cs->irq,
343
               cs->hw.teles0.membase, cs->hw.teles0.cfg_reg);
344
        if (reset_teles0(cs)) {
345
                printk(KERN_WARNING "Teles0: wrong IRQ\n");
346
                release_io_teles0(cs);
347
                return (0);
348
        }
349
        setup_isac(cs);
350
        cs->readisac = &ReadISAC;
351
        cs->writeisac = &WriteISAC;
352
        cs->readisacfifo = &ReadISACfifo;
353
        cs->writeisacfifo = &WriteISACfifo;
354
        cs->BC_Read_Reg = &ReadHSCX;
355
        cs->BC_Write_Reg = &WriteHSCX;
356
        cs->BC_Send_Data = &hscx_fill_fifo;
357
        cs->cardmsg = &Teles_card_msg;
358
        cs->irq_func = &teles0_interrupt;
359
        ISACVersion(cs, "Teles0:");
360
        if (HscxVersion(cs, "Teles0:")) {
361
                printk(KERN_WARNING
362
                 "Teles0: wrong HSCX versions check IO/MEM addresses\n");
363
                release_io_teles0(cs);
364
                return (0);
365
        }
366
        return (1);
367
}

powered by: WebSVN 2.1.0

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