more debug output
[linux-2.4.git] / drivers / isdn / hisax / s0box.c
1 /* $Id: s0box.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
2  *
3  * low level stuff for Creatix S0BOX
4  *
5  * Author       Enrik Berkhan
6  * Copyright    by Enrik Berkhan <enrik@starfleet.inka.de>
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 #define __NO_VERSION__
14 #include <linux/init.h>
15 #include "hisax.h"
16 #include "isac.h"
17 #include "hscx.h"
18 #include "isdnl1.h"
19
20 extern const char *CardType[];
21 const char *s0box_revision = "$Revision: 1.1.4.1 $";
22
23 static inline void
24 writereg(unsigned int padr, signed int addr, u_char off, u_char val) {
25         unsigned long flags;
26
27         save_flags(flags);
28         cli();
29         outb_p(0x1c,padr+2);
30         outb_p(0x14,padr+2);
31         outb_p((addr+off)&0x7f,padr);
32         outb_p(0x16,padr+2);
33         outb_p(val,padr);
34         outb_p(0x17,padr+2);
35         outb_p(0x14,padr+2);
36         outb_p(0x1c,padr+2);
37         restore_flags(flags);
38 }
39
40 static u_char nibtab[] = { 1, 9, 5, 0xd, 3, 0xb, 7, 0xf,
41                          0, 0, 0, 0, 0, 0, 0, 0,
42                          0, 8, 4, 0xc, 2, 0xa, 6, 0xe } ;
43
44 static inline u_char
45 readreg(unsigned int padr, signed int addr, u_char off) {
46         register u_char n1, n2;
47         unsigned long flags;
48
49         save_flags(flags);
50         cli();
51         outb_p(0x1c,padr+2);
52         outb_p(0x14,padr+2);
53         outb_p((addr+off)|0x80,padr);
54         outb_p(0x16,padr+2);
55         outb_p(0x17,padr+2);
56         n1 = (inb_p(padr+1) >> 3) & 0x17;
57         outb_p(0x16,padr+2);
58         n2 = (inb_p(padr+1) >> 3) & 0x17;
59         outb_p(0x14,padr+2);
60         outb_p(0x1c,padr+2);
61         restore_flags(flags);
62         return nibtab[n1] | (nibtab[n2] << 4);
63 }
64
65 static inline void
66 read_fifo(unsigned int padr, signed int adr, u_char * data, int size)
67 {
68         int i;
69         register u_char n1, n2;
70         
71         outb_p(0x1c, padr+2);
72         outb_p(0x14, padr+2);
73         outb_p(adr|0x80, padr);
74         outb_p(0x16, padr+2);
75         for (i=0; i<size; i++) {
76                 outb_p(0x17, padr+2);
77                 n1 = (inb_p(padr+1) >> 3) & 0x17;
78                 outb_p(0x16,padr+2);
79                 n2 = (inb_p(padr+1) >> 3) & 0x17;
80                 *(data++)=nibtab[n1] | (nibtab[n2] << 4);
81         }
82         outb_p(0x14,padr+2);
83         outb_p(0x1c,padr+2);
84         return;
85 }
86
87 static inline void
88 write_fifo(unsigned int padr, signed int adr, u_char * data, int size)
89 {
90         int i;
91         outb_p(0x1c, padr+2);
92         outb_p(0x14, padr+2);
93         outb_p(adr&0x7f, padr);
94         for (i=0; i<size; i++) {
95                 outb_p(0x16, padr+2);
96                 outb_p(*(data++), padr);
97                 outb_p(0x17, padr+2);
98         }
99         outb_p(0x14,padr+2);
100         outb_p(0x1c,padr+2);
101         return;
102 }
103
104 /* Interface functions */
105
106 static u_char
107 ReadISAC(struct IsdnCardState *cs, u_char offset)
108 {
109         return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset));
110 }
111
112 static void
113 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
114 {
115         writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset, value);
116 }
117
118 static void
119 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
120 {
121         read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size);
122 }
123
124 static void
125 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
126 {
127         write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size);
128 }
129
130 static u_char
131 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
132 {
133         return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset));
134 }
135
136 static void
137 WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
138 {
139         writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset, value);
140 }
141
142 /*
143  * fast interrupt HSCX stuff goes here
144  */
145
146 #define READHSCX(cs, nr, reg) readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg)
147 #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg, data)
148 #define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt)
149 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt)
150
151 #include "hscx_irq.c"
152
153 static void
154 s0box_interrupt(int intno, void *dev_id, struct pt_regs *regs)
155 {
156 #define MAXCOUNT 5
157         struct IsdnCardState *cs = dev_id;
158         u_char val;
159         int count = 0;
160
161         if (!cs) {
162                 printk(KERN_WARNING "Teles: Spurious interrupt!\n");
163                 return;
164         }
165         val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA);
166       Start_HSCX:
167         if (val)
168                 hscx_int_main(cs, val);
169         val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA);
170       Start_ISAC:
171         if (val)
172                 isac_interrupt(cs, val);
173         count++;
174         val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA);
175         if (val && count < MAXCOUNT) {
176                 if (cs->debug & L1_DEB_HSCX)
177                         debugl1(cs, "HSCX IntStat after IntRoutine");
178                 goto Start_HSCX;
179         }
180         val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA);
181         if (val && count < MAXCOUNT) {
182                 if (cs->debug & L1_DEB_ISAC)
183                         debugl1(cs, "ISAC IntStat after IntRoutine");
184                 goto Start_ISAC;
185         }
186         if (count >= MAXCOUNT)
187                 printk(KERN_WARNING "S0Box: more than %d loops in s0box_interrupt\n", count);
188         writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF);
189         writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF);
190         writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0xFF);
191         writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0x0);
192         writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
193         writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
194 }
195
196 void
197 release_io_s0box(struct IsdnCardState *cs)
198 {
199         release_region(cs->hw.teles3.cfg_reg, 8);
200 }
201
202 static int
203 S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg)
204 {
205         switch (mt) {
206                 case CARD_RESET:
207                         break;
208                 case CARD_RELEASE:
209                         release_io_s0box(cs);
210                         break;
211                 case CARD_INIT:
212                         inithscxisac(cs, 3);
213                         break;
214                 case CARD_TEST:
215                         break;
216         }
217         return(0);
218 }
219
220 int __init
221 setup_s0box(struct IsdnCard *card)
222 {
223         struct IsdnCardState *cs = card->cs;
224         char tmp[64];
225
226         strcpy(tmp, s0box_revision);
227         printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp));
228         if (cs->typ != ISDN_CTYPE_S0BOX)
229                 return (0);
230
231         cs->hw.teles3.cfg_reg = card->para[1];
232         cs->hw.teles3.hscx[0] = -0x20;
233         cs->hw.teles3.hscx[1] = 0x0;
234         cs->hw.teles3.isac = 0x20;
235         cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
236         cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
237         cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
238         cs->irq = card->para[0];
239         if (check_region(cs->hw.teles3.cfg_reg,8)) {
240                 printk(KERN_WARNING
241                        "HiSax: %s ports %x-%x already in use\n",
242                        CardType[cs->typ],
243                        cs->hw.teles3.cfg_reg,
244                        cs->hw.teles3.cfg_reg + 7);
245                 return 0;
246         } else
247                 request_region(cs->hw.teles3.cfg_reg, 8, "S0Box parallel I/O");
248         printk(KERN_INFO
249                "HiSax: %s config irq:%d isac:0x%x  cfg:0x%x\n",
250                CardType[cs->typ], cs->irq,
251                cs->hw.teles3.isac, cs->hw.teles3.cfg_reg);
252         printk(KERN_INFO
253                "HiSax: hscx A:0x%x  hscx B:0x%x\n",
254                cs->hw.teles3.hscx[0], cs->hw.teles3.hscx[1]);
255         cs->readisac = &ReadISAC;
256         cs->writeisac = &WriteISAC;
257         cs->readisacfifo = &ReadISACfifo;
258         cs->writeisacfifo = &WriteISACfifo;
259         cs->BC_Read_Reg = &ReadHSCX;
260         cs->BC_Write_Reg = &WriteHSCX;
261         cs->BC_Send_Data = &hscx_fill_fifo;
262         cs->cardmsg = &S0Box_card_msg;
263         cs->irq_func = &s0box_interrupt;
264         ISACVersion(cs, "S0Box:");
265         if (HscxVersion(cs, "S0Box:")) {
266                 printk(KERN_WARNING
267                        "S0Box: wrong HSCX versions check IO address\n");
268                 release_io_s0box(cs);
269                 return (0);
270         }
271         return (1);
272 }