pre-2.3.4..
[davej-history.git] / drivers / isdn / hisax / sportster.c
blob655abfadc534cd3be218f994826198f874e17b6e
1 /* $Id: sportster.c,v 1.7 1998/11/15 23:55:22 keil Exp $
3 * sportster.c low level stuff for USR Sportster internal TA
5 * Author Karsten Keil (keil@temic-ech.spacenet.de)
7 * Thanks to Christian "naddy" Weisgerber (3Com, US Robotics) for documentation
9 * $Log: sportster.c,v $
10 * Revision 1.7 1998/11/15 23:55:22 keil
11 * changes from 2.0
13 * Revision 1.6 1998/04/15 16:44:35 keil
14 * new init code
16 * Revision 1.5 1998/02/02 13:29:46 keil
17 * fast io
19 * Revision 1.4 1997/11/08 21:35:52 keil
20 * new l1 init
22 * Revision 1.3 1997/11/06 17:09:29 keil
23 * New 2.1 init code
25 * Revision 1.2 1997/10/29 18:51:18 keil
26 * New files
28 * Revision 1.1.2.1 1997/10/17 22:10:58 keil
29 * new files on 2.0
32 #define __NO_VERSION__
33 #include "hisax.h"
34 #include "isac.h"
35 #include "hscx.h"
36 #include "isdnl1.h"
38 extern const char *CardType[];
39 const char *sportster_revision = "$Revision: 1.7 $";
41 #define byteout(addr,val) outb(val,addr)
42 #define bytein(addr) inb(addr)
44 #define SPORTSTER_ISAC 0xC000
45 #define SPORTSTER_HSCXA 0x0000
46 #define SPORTSTER_HSCXB 0x4000
47 #define SPORTSTER_RES_IRQ 0x8000
48 #define SPORTSTER_RESET 0x80
49 #define SPORTSTER_INTE 0x40
51 static inline int
52 calc_off(unsigned int base, unsigned int off)
54 return(base + ((off & 0xfc)<<8) + ((off & 3)<<1));
57 static inline void
58 read_fifo(unsigned int adr, u_char * data, int size)
60 insb(adr, data, size);
63 static void
64 write_fifo(unsigned int adr, u_char * data, int size)
66 outsb(adr, data, size);
69 /* Interface functions */
71 static u_char
72 ReadISAC(struct IsdnCardState *cs, u_char offset)
74 return (bytein(calc_off(cs->hw.spt.isac, offset)));
77 static void
78 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
80 byteout(calc_off(cs->hw.spt.isac, offset), value);
83 static void
84 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
86 read_fifo(cs->hw.spt.isac, data, size);
89 static void
90 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
92 write_fifo(cs->hw.spt.isac, data, size);
95 static u_char
96 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
98 return (bytein(calc_off(cs->hw.spt.hscx[hscx], offset)));
101 static void
102 WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
104 byteout(calc_off(cs->hw.spt.hscx[hscx], offset), value);
108 * fast interrupt HSCX stuff goes here
111 #define READHSCX(cs, nr, reg) bytein(calc_off(cs->hw.spt.hscx[nr], reg))
112 #define WRITEHSCX(cs, nr, reg, data) byteout(calc_off(cs->hw.spt.hscx[nr], reg), data)
113 #define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.spt.hscx[nr], ptr, cnt)
114 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.spt.hscx[nr], ptr, cnt)
116 #include "hscx_irq.c"
118 static void
119 sportster_interrupt(int intno, void *dev_id, struct pt_regs *regs)
121 struct IsdnCardState *cs = dev_id;
122 u_char val;
124 if (!cs) {
125 printk(KERN_WARNING "Sportster: Spurious interrupt!\n");
126 return;
128 val = READHSCX(cs, 1, HSCX_ISTA);
129 Start_HSCX:
130 if (val)
131 hscx_int_main(cs, val);
132 val = ReadISAC(cs, ISAC_ISTA);
133 Start_ISAC:
134 if (val)
135 isac_interrupt(cs, val);
136 val = READHSCX(cs, 1, HSCX_ISTA);
137 if (val) {
138 if (cs->debug & L1_DEB_HSCX)
139 debugl1(cs, "HSCX IntStat after IntRoutine");
140 goto Start_HSCX;
142 val = ReadISAC(cs, ISAC_ISTA);
143 if (val) {
144 if (cs->debug & L1_DEB_ISAC)
145 debugl1(cs, "ISAC IntStat after IntRoutine");
146 goto Start_ISAC;
148 /* get a new irq impulse if there any pending */
149 bytein(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ +1);
152 void
153 release_io_sportster(struct IsdnCardState *cs)
155 int i, adr;
157 byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, 0);
158 for (i=0; i<64; i++) {
159 adr = cs->hw.spt.cfg_reg + i *1024;
160 release_region(adr, 8);
164 void
165 reset_sportster(struct IsdnCardState *cs)
167 long flags;
169 cs->hw.spt.res_irq |= SPORTSTER_RESET; /* Reset On */
170 byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
171 save_flags(flags);
172 sti();
173 current->state = TASK_INTERRUPTIBLE;
174 schedule_timeout(1);
175 cs->hw.spt.res_irq &= ~SPORTSTER_RESET; /* Reset Off */
176 byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
177 current->state = TASK_INTERRUPTIBLE;
178 schedule_timeout(1);
179 restore_flags(flags);
182 static int
183 Sportster_card_msg(struct IsdnCardState *cs, int mt, void *arg)
185 switch (mt) {
186 case CARD_RESET:
187 reset_sportster(cs);
188 return(0);
189 case CARD_RELEASE:
190 release_io_sportster(cs);
191 return(0);
192 case CARD_SETIRQ:
193 return(request_irq(cs->irq, &sportster_interrupt,
194 I4L_IRQ_FLAG, "HiSax", cs));
195 case CARD_INIT:
196 inithscxisac(cs, 1);
197 cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */
198 byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
199 inithscxisac(cs, 2);
200 return(0);
201 case CARD_TEST:
202 return(0);
204 return(0);
207 __initfunc(int
208 get_io_range(struct IsdnCardState *cs))
210 int i, j, adr;
212 for (i=0;i<64;i++) {
213 adr = cs->hw.spt.cfg_reg + i *1024;
214 if (check_region(adr, 8)) {
215 printk(KERN_WARNING
216 "HiSax: %s config port %x-%x already in use\n",
217 CardType[cs->typ], adr, adr + 8);
218 break;
219 } else
220 request_region(adr, 8, "sportster");
222 if (i==64)
223 return(1);
224 else {
225 for (j=0; j<i; j++) {
226 adr = cs->hw.spt.cfg_reg + j *1024;
227 release_region(adr, 8);
229 return(0);
233 __initfunc(int
234 setup_sportster(struct IsdnCard *card))
236 struct IsdnCardState *cs = card->cs;
237 char tmp[64];
239 strcpy(tmp, sportster_revision);
240 printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", HiSax_getrev(tmp));
241 if (cs->typ != ISDN_CTYPE_SPORTSTER)
242 return (0);
244 cs->hw.spt.cfg_reg = card->para[1];
245 cs->irq = card->para[0];
246 if (!get_io_range(cs))
247 return (0);
248 cs->hw.spt.isac = cs->hw.spt.cfg_reg + SPORTSTER_ISAC;
249 cs->hw.spt.hscx[0] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXA;
250 cs->hw.spt.hscx[1] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXB;
252 switch(cs->irq) {
253 case 5: cs->hw.spt.res_irq = 1;
254 break;
255 case 7: cs->hw.spt.res_irq = 2;
256 break;
257 case 10:cs->hw.spt.res_irq = 3;
258 break;
259 case 11:cs->hw.spt.res_irq = 4;
260 break;
261 case 12:cs->hw.spt.res_irq = 5;
262 break;
263 case 14:cs->hw.spt.res_irq = 6;
264 break;
265 case 15:cs->hw.spt.res_irq = 7;
266 break;
267 default:release_io_sportster(cs);
268 printk(KERN_WARNING "Sportster: wrong IRQ\n");
269 return(0);
271 reset_sportster(cs);
272 printk(KERN_INFO
273 "HiSax: %s config irq:%d cfg:0x%X\n",
274 CardType[cs->typ], cs->irq,
275 cs->hw.spt.cfg_reg);
277 cs->readisac = &ReadISAC;
278 cs->writeisac = &WriteISAC;
279 cs->readisacfifo = &ReadISACfifo;
280 cs->writeisacfifo = &WriteISACfifo;
281 cs->BC_Read_Reg = &ReadHSCX;
282 cs->BC_Write_Reg = &WriteHSCX;
283 cs->BC_Send_Data = &hscx_fill_fifo;
284 cs->cardmsg = &Sportster_card_msg;
285 ISACVersion(cs, "Sportster:");
286 if (HscxVersion(cs, "Sportster:")) {
287 printk(KERN_WARNING
288 "Sportster: wrong HSCX versions check IO address\n");
289 release_io_sportster(cs);
290 return (0);
292 return (1);