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