kernel tree reorganization stage 1: Major cvs repository work (not logged as
[dragonfly.git] / sys / net / i4b / capi / iavc / iavc_isa.c
1 /*
2  * Copyright (c) 2001 Hellmuth Michaelis. 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  * $FreeBSD: src/sys/i4b/capi/iavc/iavc_isa.c,v 1.1.2.1 2001/08/10 14:08:34 obrien Exp $
26  * $DragonFly: src/sys/net/i4b/capi/iavc/iavc_isa.c,v 1.3 2003/08/07 21:17:24 dillon Exp $
27  */
28
29 #include "use_iavc.h"
30 #include "use_i4bcapi.h"
31
32 #if (NIAVC > 0) && (NI4BCAPI > 0)
33
34 #include <sys/param.h>
35 #include <sys/kernel.h>
36 #include <sys/systm.h>
37 #include <sys/mbuf.h>
38 #include <sys/socket.h>
39 #include <net/if.h>
40
41 #include <machine/clock.h>
42
43 #include <machine/bus.h>
44 #include <machine/resource.h>
45 #include <sys/bus.h>
46 #include <sys/rman.h>
47 #include <vm/vm.h>
48 #include <vm/pmap.h>
49 #include <bus/isa/isavar.h>
50
51 #include <machine/i4b_debug.h>
52 #include <machine/i4b_ioctl.h>
53 #include <machine/i4b_trace.h>
54
55 #include "../../include/i4b_global.h"
56 #include "../../include/i4b_l3l4.h"
57 #include "../../include/i4b_mbuf.h"
58 #include "../capi.h"
59
60 #include "iavc.h"
61
62 /* ISA driver linkage */
63
64 static void iavc_isa_intr(iavc_softc_t *sc);
65 static int iavc_isa_probe(device_t dev);
66 static int iavc_isa_attach(device_t dev);
67
68 static device_method_t iavc_isa_methods[] =
69 {
70     DEVMETHOD(device_probe,     iavc_isa_probe),
71     DEVMETHOD(device_attach,    iavc_isa_attach),
72     { 0, 0 }
73 };
74
75 static driver_t iavc_isa_driver =
76 {
77     "iavc",
78     iavc_isa_methods,
79     0
80 };
81
82 static devclass_t iavc_isa_devclass;
83
84 DRIVER_MODULE(iavc, isa, iavc_isa_driver, iavc_isa_devclass, 0, 0);
85
86 #define B1_IOLENGTH     0x20
87
88 static int b1_irq_table[] =
89 {0, 0, 0, 192, 32, 160, 96, 224, 0, 64, 80, 208, 48, 0, 0, 112};
90 /*        3    4   5    6   7       9   10  11   12        15 */
91
92 /*---------------------------------------------------------------------------*
93  *      device probe
94  *---------------------------------------------------------------------------*/
95
96 static int
97 iavc_isa_probe(device_t dev)
98 {
99         struct iavc_softc *sc;
100         int ret = ENXIO;
101         int unit = device_get_unit(dev);
102         
103         if(isa_get_vendorid(dev))       /* no PnP probes here */
104                 return ENXIO;
105
106         /* check max unit range */
107         
108         if (unit >= IAVC_MAXUNIT)
109         {
110                 printf("iavc%d: too many units\n", unit);
111                 return(ENXIO);  
112         }
113
114         sc = iavc_find_sc(unit);        /* get softc */ 
115         
116         sc->sc_unit = unit;
117
118         if (!(sc->sc_resources.io_base[0] =
119                 bus_alloc_resource(dev, SYS_RES_IOPORT,
120                         &sc->sc_resources.io_rid[0],
121                         0UL, ~0UL, B1_IOLENGTH, RF_ACTIVE)))
122         {
123                 printf("iavc%d: can't allocate io region\n", unit);
124                 return(ENXIO);                                       
125         }
126
127         sc->sc_iobase = rman_get_start(sc->sc_resources.io_base[0]);
128
129         switch(sc->sc_iobase)
130         {
131                 case 0x150:
132                 case 0x250:
133                 case 0x300:
134                 case 0x340:
135                         break;
136                 default:
137                         printf("iavc%d: ERROR, invalid i/o base addr 0x%x configured!\n", sc->sc_unit, sc->sc_iobase);
138                         bus_release_resource(dev, SYS_RES_IOPORT,
139                                         sc->sc_resources.io_rid[0],
140                                         sc->sc_resources.io_base[0]);
141                 return(ENXIO);
142         }       
143         
144         sc->sc_io_bt = rman_get_bustag(sc->sc_resources.io_base[0]);
145         sc->sc_io_bh = rman_get_bushandle(sc->sc_resources.io_base[0]);
146
147         /* setup characteristics */
148
149         sc->sc_t1 = FALSE;
150         sc->sc_dma = FALSE;
151
152         sc->sc_capi.card_type = CARD_TYPEC_AVM_B1_ISA;
153         sc->sc_capi.sc_nbch = 2;
154
155         b1_reset(sc);
156         DELAY(100);
157
158         ret = b1_detect(sc);
159
160         if(ret)
161         {
162                 printf("iavc%d: no card ? b1_detect returns 0x02x\n", sc->sc_unit, ret);
163                 return(ENXIO);
164         }
165
166         DELAY(100);
167
168         b1_reset(sc);
169         
170         DELAY(100);
171
172         if(bootverbose)
173         {
174                 printf("iavc%d: class = 0x%02x, rev = 0x%02x\n", sc->sc_unit,
175                         iavc_read_port(sc, B1_ANALYSE),
176                         iavc_read_port(sc, B1_REVISION));
177         }
178
179         device_set_desc(dev, "AVM B1 ISA");
180         return(0);
181 }
182
183 /*---------------------------------------------------------------------------*
184  *      attach
185  *---------------------------------------------------------------------------*/
186 static int
187 iavc_isa_attach(device_t dev)
188 {
189         struct iavc_softc *sc;
190         void *ih = 0;
191         int unit = device_get_unit(dev);
192         int irq;
193         
194         sc = iavc_find_sc(unit);        /* get softc */ 
195         
196         sc->sc_resources.irq_rid = 0;
197         
198         if(!(sc->sc_resources.irq =
199                 bus_alloc_resource(dev, SYS_RES_IRQ,
200                         &sc->sc_resources.irq_rid,
201                         0UL, ~0UL, 1, RF_ACTIVE)))
202         {
203                 printf("iavc%d: can't allocate irq\n",unit);
204                 bus_release_resource(dev, SYS_RES_IOPORT,
205                                 sc->sc_resources.io_rid[0],
206                                 sc->sc_resources.io_base[0]);
207                 return(ENXIO);
208         }
209
210         irq = rman_get_start(sc->sc_resources.irq);
211
212         if(b1_irq_table[irq] == 0)
213         {
214                 printf("iavc%d: ERROR, illegal irq %d configured!\n",unit, irq);
215                 bus_release_resource(dev, SYS_RES_IOPORT,
216                                 sc->sc_resources.io_rid[0],
217                                 sc->sc_resources.io_base[0]);
218                 bus_release_resource(dev, SYS_RES_IRQ,
219                                 sc->sc_resources.irq_rid,
220                                 sc->sc_resources.irq);
221                 return(ENXIO);
222         }
223         
224         memset(&sc->sc_txq, 0, sizeof(struct ifqueue));
225         sc->sc_txq.ifq_maxlen = sc->sc_capi.sc_nbch * 4;
226
227 #if defined (__FreeBSD__) && __FreeBSD__ > 4
228         mtx_init(&sc->sc_txq.ifq_mtx, "i4b_ivac_isa", MTX_DEF);
229 #endif
230
231         sc->sc_intr = FALSE;
232         sc->sc_state = IAVC_DOWN;
233         sc->sc_blocked = FALSE;
234
235         /* setup capi link */
236         
237         sc->sc_capi.load = iavc_load;
238         sc->sc_capi.reg_appl = iavc_register;
239         sc->sc_capi.rel_appl = iavc_release;
240         sc->sc_capi.send = iavc_send;
241         sc->sc_capi.ctx = (void*) sc;
242
243         if (capi_ll_attach(&sc->sc_capi))
244         {
245                 printf("iavc%d: capi attach failed\n", unit);
246                 return(ENXIO);
247         }
248
249         /* setup the interrupt */
250
251         if(bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET,
252                       (void(*)(void*))iavc_isa_intr,
253                       sc, &ih))
254         {
255                 printf("iavc%d: irq setup failed\n", unit);
256                 bus_release_resource(dev, SYS_RES_IOPORT,
257                                 sc->sc_resources.io_rid[0],
258                                 sc->sc_resources.io_base[0]);
259                 bus_release_resource(dev, SYS_RES_IRQ,
260                                 sc->sc_resources.irq_rid,
261                                 sc->sc_resources.irq);
262                 return(ENXIO);
263         }
264
265         /* the board is now ready to be loaded */
266
267         return(0);
268 }
269
270 /*---------------------------------------------------------------------------*
271  *      setup interrupt
272  *---------------------------------------------------------------------------*/
273 void
274 b1isa_setup_irq(struct iavc_softc *sc)
275 {
276         int irq = rman_get_start(sc->sc_resources.irq);
277         
278         if(bootverbose)
279                 printf("iavc%d: using irq %d\n", sc->sc_unit, irq);
280
281         /* enable the interrupt */
282
283         b1io_outp(sc, B1_INSTAT, 0x00);
284         b1io_outp(sc, B1_RESET, b1_irq_table[irq]);
285         b1io_outp(sc, B1_INSTAT, 0x02);
286 }       
287
288 /*---------------------------------------------------------------------------*
289  *      IRQ handler
290  *---------------------------------------------------------------------------*/
291 static void
292 iavc_isa_intr(struct iavc_softc *sc)
293 {
294         iavc_handle_intr(sc);
295 }
296
297 #endif