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
13 * Revision 1.6 1998/04/15 16:44:35 keil
16 * Revision 1.5 1998/02/02 13:29:46 keil
19 * Revision 1.4 1997/11/08 21:35:52 keil
22 * Revision 1.3 1997/11/06 17:09:29 keil
25 * Revision 1.2 1997/10/29 18:51:18 keil
28 * Revision 1.1.2.1 1997/10/17 22:10:58 keil
32 #define __NO_VERSION__
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
52 calc_off(unsigned int base
, unsigned int off
)
54 return(base
+ ((off
& 0xfc)<<8) + ((off
& 3)<<1));
58 read_fifo(unsigned int adr
, u_char
* data
, int size
)
60 insb(adr
, data
, size
);
64 write_fifo(unsigned int adr
, u_char
* data
, int size
)
66 outsb(adr
, data
, size
);
69 /* Interface functions */
72 ReadISAC(struct IsdnCardState
*cs
, u_char offset
)
74 return (bytein(calc_off(cs
->hw
.spt
.isac
, offset
)));
78 WriteISAC(struct IsdnCardState
*cs
, u_char offset
, u_char value
)
80 byteout(calc_off(cs
->hw
.spt
.isac
, offset
), value
);
84 ReadISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
86 read_fifo(cs
->hw
.spt
.isac
, data
, size
);
90 WriteISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
92 write_fifo(cs
->hw
.spt
.isac
, data
, size
);
96 ReadHSCX(struct IsdnCardState
*cs
, int hscx
, u_char offset
)
98 return (bytein(calc_off(cs
->hw
.spt
.hscx
[hscx
], offset
)));
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"
119 sportster_interrupt(int intno
, void *dev_id
, struct pt_regs
*regs
)
121 struct IsdnCardState
*cs
= dev_id
;
125 printk(KERN_WARNING
"Sportster: Spurious interrupt!\n");
128 val
= READHSCX(cs
, 1, HSCX_ISTA
);
131 hscx_int_main(cs
, val
);
132 val
= ReadISAC(cs
, ISAC_ISTA
);
135 isac_interrupt(cs
, val
);
136 val
= READHSCX(cs
, 1, HSCX_ISTA
);
138 if (cs
->debug
& L1_DEB_HSCX
)
139 debugl1(cs
, "HSCX IntStat after IntRoutine");
142 val
= ReadISAC(cs
, ISAC_ISTA
);
144 if (cs
->debug
& L1_DEB_ISAC
)
145 debugl1(cs
, "ISAC IntStat after IntRoutine");
148 /* get a new irq impulse if there any pending */
149 bytein(cs
->hw
.spt
.cfg_reg
+ SPORTSTER_RES_IRQ
+1);
153 release_io_sportster(struct IsdnCardState
*cs
)
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);
165 reset_sportster(struct IsdnCardState
*cs
)
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
);
173 current
->state
= TASK_INTERRUPTIBLE
;
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
;
179 restore_flags(flags
);
183 Sportster_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
190 release_io_sportster(cs
);
193 return(request_irq(cs
->irq
, &sportster_interrupt
,
194 I4L_IRQ_FLAG
, "HiSax", cs
));
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
);
208 get_io_range(struct IsdnCardState
*cs
))
213 adr
= cs
->hw
.spt
.cfg_reg
+ i
*1024;
214 if (check_region(adr
, 8)) {
216 "HiSax: %s config port %x-%x already in use\n",
217 CardType
[cs
->typ
], adr
, adr
+ 8);
220 request_region(adr
, 8, "sportster");
225 for (j
=0; j
<i
; j
++) {
226 adr
= cs
->hw
.spt
.cfg_reg
+ j
*1024;
227 release_region(adr
, 8);
234 setup_sportster(struct IsdnCard
*card
))
236 struct IsdnCardState
*cs
= card
->cs
;
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
)
244 cs
->hw
.spt
.cfg_reg
= card
->para
[1];
245 cs
->irq
= card
->para
[0];
246 if (!get_io_range(cs
))
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
;
253 case 5: cs
->hw
.spt
.res_irq
= 1;
255 case 7: cs
->hw
.spt
.res_irq
= 2;
257 case 10:cs
->hw
.spt
.res_irq
= 3;
259 case 11:cs
->hw
.spt
.res_irq
= 4;
261 case 12:cs
->hw
.spt
.res_irq
= 5;
263 case 14:cs
->hw
.spt
.res_irq
= 6;
265 case 15:cs
->hw
.spt
.res_irq
= 7;
267 default:release_io_sportster(cs
);
268 printk(KERN_WARNING
"Sportster: wrong IRQ\n");
273 "HiSax: %s config irq:%d cfg:0x%X\n",
274 CardType
[cs
->typ
], cs
->irq
,
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:")) {
288 "Sportster: wrong HSCX versions check IO address\n");
289 release_io_sportster(cs
);