Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / sys / net / i4b / capi / iavc / iavc_pci.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_pci.c
26  *              The AVM ISDN controllers' PCI bus attachment handling.
27  *
28  * $FreeBSD: src/sys/i4b/capi/iavc/iavc_pci.c,v 1.1.2.1 2001/08/10 14:08:34 obrien Exp $
29  * $DragonFly: src/sys/net/i4b/capi/iavc/iavc_pci.c,v 1.2 2003/06/17 04:28:39 dillon Exp $
30  */
31
32 #include "iavc.h"
33 #include "i4bcapi.h"
34 #include "pci.h"
35
36 #if (NIAVC > 0) && (NI4BCAPI > 0) && (NPCI > 0)
37
38 #include <sys/param.h>
39 #include <sys/kernel.h>
40 #include <sys/systm.h>
41 #include <sys/mbuf.h>
42 #include <sys/socket.h>
43 #include <net/if.h>
44
45 #include <machine/clock.h>
46
47 #include <machine/bus.h>
48 #include <machine/resource.h>
49 #include <sys/bus.h>
50 #include <sys/rman.h>
51 #include <vm/vm.h>
52 #include <vm/pmap.h>
53
54 #include <pci/pcireg.h>
55 #include <pci/pcivar.h>
56
57 #include <machine/i4b_debug.h>
58 #include <machine/i4b_ioctl.h>
59 #include <machine/i4b_trace.h>
60
61 #include <i4b/include/i4b_global.h>
62 #include <i4b/include/i4b_l3l4.h>
63 #include <i4b/include/i4b_mbuf.h>
64
65 #include <i4b/capi/capi.h>
66
67 #include <i4b/capi/iavc/iavc.h>
68
69 /* PCI device ids */
70
71 #define PCI_AVM_VID   0x1244
72 #define PCI_AVMT1_DID 0x1200
73 #define PCI_AVMB1_DID 0x0700
74
75 /* PCI driver linkage */
76
77 static void iavc_pci_intr(iavc_softc_t *sc);
78 static int iavc_pci_probe(device_t dev);
79 static int iavc_pci_attach(device_t dev);
80
81 static device_method_t iavc_pci_methods[] =
82 {
83     DEVMETHOD(device_probe,     iavc_pci_probe),
84     DEVMETHOD(device_attach,    iavc_pci_attach),
85     { 0, 0 }
86 };
87
88 static driver_t iavc_pci_driver =
89 {
90     "iavc",
91     iavc_pci_methods,
92     0
93 };
94
95 static devclass_t iavc_pci_devclass;
96
97 DRIVER_MODULE(iavc, pci, iavc_pci_driver, iavc_pci_devclass, 0, 0);
98
99 /* Driver soft contexts */
100
101 iavc_softc_t iavc_sc[IAVC_MAXUNIT];
102
103 /*---------------------------------------------------------------------------*
104  *
105  *---------------------------------------------------------------------------*/
106
107 static int
108 iavc_pci_probe(device_t dev)
109 {
110     u_int16_t did = pci_get_device(dev);
111     u_int16_t vid = pci_get_vendor(dev);
112
113     if ((vid == PCI_AVM_VID) && (did == PCI_AVMT1_DID)) {
114         device_set_desc(dev, "AVM T1 PCI");
115     } else if ((vid == PCI_AVM_VID) && (did == PCI_AVMB1_DID)) {
116         device_set_desc(dev, "AVM B1 PCI");
117     } else {
118         return(ENXIO);
119     }
120
121     return(0);
122 }
123
124 /*---------------------------------------------------------------------------*
125  *
126  *---------------------------------------------------------------------------*/
127
128 static int
129 iavc_pci_attach(device_t dev)
130 {
131     struct iavc_softc *sc;
132     void *ih = 0;
133     u_int16_t did = pci_get_device(dev);
134     int unit = device_get_unit(dev), ret;
135         
136     /* check max unit range */
137         
138     if (unit >= IAVC_MAXUNIT) {
139         printf("iavc%d: too many units\n", unit);
140         return(ENXIO);  
141     }   
142
143     sc = iavc_find_sc(unit);    /* get softc */ 
144         
145     sc->sc_unit = unit;
146
147     /* use the i/o mapped base address */
148         
149     sc->sc_resources.io_rid[0] = 0x14;
150         
151     if (!(sc->sc_resources.io_base[0] =
152          bus_alloc_resource(dev, SYS_RES_IOPORT,
153                             &sc->sc_resources.io_rid[0],
154                             0UL, ~0UL, 1, RF_ACTIVE))) {
155         printf("iavc%d: can't allocate io region\n", unit);
156         return(ENXIO);                                       
157     }
158
159     sc->sc_iobase = rman_get_start(sc->sc_resources.io_base[0]);
160     sc->sc_io_bt = rman_get_bustag(sc->sc_resources.io_base[0]);
161     sc->sc_io_bh = rman_get_bushandle(sc->sc_resources.io_base[0]);
162
163     /* use the memory mapped DMA controller */
164         
165     sc->sc_resources.mem_rid = 0x10;
166         
167     if (!(sc->sc_resources.mem =
168          bus_alloc_resource(dev, SYS_RES_MEMORY,
169                             &sc->sc_resources.mem_rid,
170                             0UL, ~0UL, 1, RF_ACTIVE))) {
171         printf("iavc%d: can't allocate memory region\n", unit);
172         return(ENXIO);                                       
173     }
174
175     sc->sc_membase = rman_get_start(sc->sc_resources.mem);
176     sc->sc_mem_bt = rman_get_bustag(sc->sc_resources.mem);
177     sc->sc_mem_bh = rman_get_bushandle(sc->sc_resources.mem);
178
179     /* do some detection */
180
181     sc->sc_t1 = FALSE;
182     sc->sc_dma = FALSE;
183     b1dma_reset(sc);
184
185     if (did == PCI_AVMT1_DID) {
186         sc->sc_capi.card_type = CARD_TYPEC_AVM_T1_PCI;
187         sc->sc_capi.sc_nbch = 30;
188         ret = t1_detect(sc);
189         if (ret) {
190             if (ret < 6) {
191                 printf("iavc%d: no card detected?\n", sc->sc_unit);
192             } else {
193                 printf("iavc%d: black box not on\n", sc->sc_unit);
194             }
195             return(ENXIO);
196         } else {
197             sc->sc_dma = TRUE;
198             sc->sc_t1 = TRUE;
199         }
200
201     } else if (did == PCI_AVMB1_DID) {
202         sc->sc_capi.card_type = CARD_TYPEC_AVM_B1_PCI;
203         sc->sc_capi.sc_nbch = 2;
204         ret = b1dma_detect(sc);
205         if (ret) {
206             ret = b1_detect(sc);
207             if (ret) {
208                 printf("iavc%d: no card detected?\n", sc->sc_unit);
209                 return(ENXIO);
210             }
211         } else {
212             sc->sc_dma = TRUE;
213         }
214     }
215
216     if (sc->sc_dma) b1dma_reset(sc);
217 #if 0
218     if (sc->sc_t1) t1_reset(sc);
219     else b1_reset(sc);
220 #endif
221
222     /* of course we need an interrupt */
223     
224     sc->sc_resources.irq_rid = 0x00;
225         
226     if(!(sc->sc_resources.irq =
227          bus_alloc_resource(dev, SYS_RES_IRQ,
228                             &sc->sc_resources.irq_rid,
229                             0UL, ~0UL, 1, RF_SHAREABLE|RF_ACTIVE))) {
230         printf("iavc%d: can't allocate irq\n",unit);
231         return(ENXIO);
232     }
233
234     /* finalize our own context */
235
236     memset(&sc->sc_txq, 0, sizeof(struct ifqueue));
237     sc->sc_txq.ifq_maxlen = sc->sc_capi.sc_nbch * 4;
238
239 #if defined (__FreeBSD__) && __FreeBSD__ > 4
240     mtx_init(&sc->sc_txq.ifq_mtx, "i4b_ivac_pci", MTX_DEF);
241 #endif
242     
243     sc->sc_intr = FALSE;
244     sc->sc_state = IAVC_DOWN;
245     sc->sc_blocked = FALSE;
246
247     /* setup capi link */
248         
249     sc->sc_capi.load = iavc_load;
250     sc->sc_capi.reg_appl = iavc_register;
251     sc->sc_capi.rel_appl = iavc_release;
252     sc->sc_capi.send = iavc_send;
253     sc->sc_capi.ctx = (void*) sc;
254
255     if (capi_ll_attach(&sc->sc_capi)) {
256         printf("iavc%d: capi attach failed\n", unit);
257         return(ENXIO);
258     }
259
260     /* setup the interrupt */
261
262     if(bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET,
263                       (void(*)(void*))iavc_pci_intr,
264                       sc, &ih)) {
265         printf("iavc%d: irq setup failed\n", unit);
266         return(ENXIO);
267     }
268
269     /* the board is now ready to be loaded */
270
271     return(0);
272 }
273
274 /*---------------------------------------------------------------------------*
275  *      IRQ handler
276  *---------------------------------------------------------------------------*/
277
278 static void
279 iavc_pci_intr(struct iavc_softc *sc)
280 {
281     iavc_handle_intr(sc);
282 }
283
284 #endif