* Remove (void) casts for discarded return values.
[dragonfly.git] / sys / net / i4b / capi / iavc / iavc_card.c
1 /*
2  * Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  * capi/iavc/iavc_card.c
26  *              The AVM ISDN controllers' card specific support routines.
27  *
28  * $FreeBSD: src/sys/i4b/capi/iavc/iavc_card.c,v 1.1.2.1 2001/08/10 14:08:34 obrien Exp $
29  * $DragonFly: src/sys/net/i4b/capi/iavc/iavc_card.c,v 1.7 2006/01/14 11:05:17 swildner Exp $
30  */
31
32 #include <sys/param.h>
33 #include <sys/kernel.h>
34 #include <sys/systm.h>
35 #include <sys/mbuf.h>
36 #include <sys/socket.h>
37 #include <net/if.h>
38
39 #include <machine/clock.h>
40
41 #include <machine/bus.h>
42 #include <machine/resource.h>
43 #include <sys/bus.h>
44 #include <sys/rman.h>
45 #include <sys/thread2.h>
46
47 #include <net/i4b/include/machine/i4b_debug.h>
48 #include <net/i4b/include/machine/i4b_ioctl.h>
49 #include <net/i4b/include/machine/i4b_trace.h>
50
51 #include "../../include/i4b_global.h"
52 #include "../../include/i4b_l3l4.h"
53 #include "../../include/i4b_mbuf.h"
54 #include "../capi.h"
55
56 #include "iavc.h"
57
58 /*
59 //  AVM B1 (active BRI, PIO mode)
60 */
61
62 int
63 b1_detect(iavc_softc_t *sc)
64 {
65     if ((iavc_read_port(sc, B1_INSTAT) & 0xfc) ||
66         (iavc_read_port(sc, B1_OUTSTAT) & 0xfc))
67         return (1);
68
69     b1io_outp(sc, B1_INSTAT, 0x02);
70     b1io_outp(sc, B1_OUTSTAT, 0x02);
71     if ((iavc_read_port(sc, B1_INSTAT) & 0xfe) != 2 ||
72         (iavc_read_port(sc, B1_OUTSTAT) & 0xfe) != 2)
73         return (2);
74
75     b1io_outp(sc, B1_INSTAT, 0x00);
76     b1io_outp(sc, B1_OUTSTAT, 0x00);
77     if ((iavc_read_port(sc, B1_INSTAT) & 0xfe) ||
78         (iavc_read_port(sc, B1_OUTSTAT) & 0xfe))
79         return (3);
80
81     return (0); /* found */
82 }
83
84 void
85 b1_disable_irq(iavc_softc_t *sc)
86 {
87     b1io_outp(sc, B1_INSTAT, 0x00);
88 }
89
90 void
91 b1_reset(iavc_softc_t *sc)
92 {
93     b1io_outp(sc, B1_RESET, 0);
94     DELAY(55*2*1000);
95
96     b1io_outp(sc, B1_RESET, 1);
97     DELAY(55*2*1000);
98
99     b1io_outp(sc, B1_RESET, 0);
100     DELAY(55*2*1000);
101 }
102
103 /*
104 //  Newer PCI-based B1's, and T1's, supports DMA
105 */
106
107 int
108 b1dma_detect(iavc_softc_t *sc)
109 {
110     AMCC_WRITE(sc, AMCC_MCSR, 0);
111     DELAY(10*1000);
112     AMCC_WRITE(sc, AMCC_MCSR, 0x0f000000);
113     DELAY(10*1000);
114     AMCC_WRITE(sc, AMCC_MCSR, 0);
115     DELAY(42*1000);
116
117     AMCC_WRITE(sc, AMCC_RXLEN, 0);
118     AMCC_WRITE(sc, AMCC_TXLEN, 0);
119     sc->sc_csr = 0;
120     AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
121
122     if (AMCC_READ(sc, AMCC_INTCSR) != 0)
123         return 1;
124
125     AMCC_WRITE(sc, AMCC_RXPTR, 0xffffffff);
126     AMCC_WRITE(sc, AMCC_TXPTR, 0xffffffff);
127     if ((AMCC_READ(sc, AMCC_RXPTR) != 0xfffffffc) ||
128         (AMCC_READ(sc, AMCC_TXPTR) != 0xfffffffc))
129         return 2;
130
131     AMCC_WRITE(sc, AMCC_RXPTR, 0);
132     AMCC_WRITE(sc, AMCC_TXPTR, 0);
133     if ((AMCC_READ(sc, AMCC_RXPTR) != 0) ||
134         (AMCC_READ(sc, AMCC_TXPTR) != 0))
135         return 3;
136
137     iavc_write_port(sc, 0x10, 0x00);
138     iavc_write_port(sc, 0x07, 0x00);
139
140     iavc_write_port(sc, 0x02, 0x02);
141     iavc_write_port(sc, 0x03, 0x02);
142
143     if (((iavc_read_port(sc, 0x02) & 0xfe) != 0x02) ||
144         (iavc_read_port(sc, 0x03) != 0x03))
145         return 4;
146
147     iavc_write_port(sc, 0x02, 0x00);
148     iavc_write_port(sc, 0x03, 0x00);
149
150     if (((iavc_read_port(sc, 0x02) & 0xfe) != 0x00) ||
151         (iavc_read_port(sc, 0x03) != 0x01))
152         return 5;
153
154     return (0); /* found */
155 }
156
157 void
158 b1dma_reset(iavc_softc_t *sc)
159 {
160     crit_enter();
161     sc->sc_csr = 0;
162     AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
163     AMCC_WRITE(sc, AMCC_MCSR, 0);
164     AMCC_WRITE(sc, AMCC_RXLEN, 0);
165     AMCC_WRITE(sc, AMCC_TXLEN, 0);
166
167     iavc_write_port(sc, 0x10, 0x00); /* XXX magic numbers from */
168     iavc_write_port(sc, 0x07, 0x00); /* XXX the linux driver */
169
170     crit_exit();
171
172     AMCC_WRITE(sc, AMCC_MCSR, 0);
173     DELAY(10 * 1000);
174     AMCC_WRITE(sc, AMCC_MCSR, 0x0f000000);
175     DELAY(10 * 1000);
176     AMCC_WRITE(sc, AMCC_MCSR, 0);
177     DELAY(42 * 1000);
178 }
179
180 /*
181 //  AVM T1 (active PRI)
182 */
183
184 /* XXX how do these differ from b1io_{read,write}_reg()? XXX */
185
186 static int
187 b1dma_tx_empty(int iobase)
188 {
189         return inb(iobase + 3) & 1;
190 }
191
192 static int
193 b1dma_rx_full(int iobase)
194 {
195         return inb(iobase + 2) & 1;
196 }
197
198 static int
199 b1dma_tolink(iavc_softc_t *sc, void *buf, int len)
200 {
201     volatile int spin;
202     char *s = (char*) buf;
203     while (len--) {
204         spin = 0;
205         while (!b1dma_tx_empty(sc->sc_iobase) && spin < 100000)
206             spin++;
207         if (!b1dma_tx_empty(sc->sc_iobase))
208             return -1;
209         t1io_outp(sc, 1, *s++);
210     }
211     return 0;
212 }
213
214 static int
215 b1dma_fromlink(iavc_softc_t *sc, void *buf, int len)
216 {
217     volatile int spin;
218     char *s = (char*) buf;
219     while (len--) {
220         spin = 0;
221         while (!b1dma_rx_full(sc->sc_iobase) && spin < 100000)
222             spin++;
223         if (!b1dma_rx_full(sc->sc_iobase))
224             return -1;
225         *s++ = t1io_inp(sc, 0);
226     }
227     return 0;
228 }
229
230 static int
231 WriteReg(iavc_softc_t *sc, u_int32_t reg, u_int8_t val)
232 {
233     u_int8_t cmd = 0;
234     if (b1dma_tolink(sc, &cmd, 1) == 0 &&
235         b1dma_tolink(sc, &reg, 4) == 0) {
236         u_int32_t tmp = val;
237         return b1dma_tolink(sc, &tmp, 4);
238     }
239     return -1;
240 }
241
242 static u_int8_t
243 ReadReg(iavc_softc_t *sc, u_int32_t reg)
244 {
245     u_int8_t cmd = 1;
246     if (b1dma_tolink(sc, &cmd, 1) == 0 &&
247         b1dma_tolink(sc, &reg, 4) == 0) {
248         u_int32_t tmp;
249         if (b1dma_fromlink(sc, &tmp, 4) == 0)
250             return (u_int8_t) tmp;
251     }
252     return 0xff;
253 }
254
255 int
256 t1_detect(iavc_softc_t *sc)
257 {
258     int ret = b1dma_detect(sc);
259     if (ret) return ret;
260
261     if ((WriteReg(sc, 0x80001000, 0x11) != 0) ||
262         (WriteReg(sc, 0x80101000, 0x22) != 0) ||
263         (WriteReg(sc, 0x80201000, 0x33) != 0) ||
264         (WriteReg(sc, 0x80301000, 0x44) != 0))
265         return 6;
266
267     if ((ReadReg(sc, 0x80001000) != 0x11) ||
268         (ReadReg(sc, 0x80101000) != 0x22) ||
269         (ReadReg(sc, 0x80201000) != 0x33) ||
270         (ReadReg(sc, 0x80301000) != 0x44))
271         return 7;
272
273     if ((WriteReg(sc, 0x80001000, 0x55) != 0) ||
274         (WriteReg(sc, 0x80101000, 0x66) != 0) ||
275         (WriteReg(sc, 0x80201000, 0x77) != 0) ||
276         (WriteReg(sc, 0x80301000, 0x88) != 0))
277         return 8;
278
279     if ((ReadReg(sc, 0x80001000) != 0x55) ||
280         (ReadReg(sc, 0x80101000) != 0x66) ||
281         (ReadReg(sc, 0x80201000) != 0x77) ||
282         (ReadReg(sc, 0x80301000) != 0x88))
283         return 9;
284
285     return 0; /* found */
286 }
287
288 void
289 t1_disable_irq(iavc_softc_t *sc)
290 {
291     iavc_write_port(sc, T1_IRQMASTER, 0x00);
292 }
293
294 void
295 t1_reset(iavc_softc_t *sc)
296 {
297     b1_reset(sc);
298     iavc_write_port(sc, B1_INSTAT, 0x00);
299     iavc_write_port(sc, B1_OUTSTAT, 0x00);
300     iavc_write_port(sc, T1_IRQMASTER, 0x00);
301     iavc_write_port(sc, T1_RESETBOARD, 0x0f);
302 }