1 /* $NetBSD: iavc_pci.c,v 1.12 2009/11/26 15:17:09 njoly Exp $ */
4 * Copyright (c) 2001-2003 Cubical Solutions Ltd.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * capi/iavc/iavc_pci.c
29 * The AVM ISDN controllers' PCI bus attachment handling.
31 * $FreeBSD: src/sys/i4b/capi/iavc/iavc_pci.c,v 1.1.2.1 2001/08/10 14:08:34 obrien Exp $
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: iavc_pci.c,v 1.12 2009/11/26 15:17:09 njoly Exp $");
37 #include <sys/param.h>
38 #include <sys/kernel.h>
39 #include <sys/systm.h>
41 #include <sys/callout.h>
42 #include <sys/socket.h>
43 #include <sys/device.h>
48 #include <dev/pci/pcireg.h>
49 #include <dev/pci/pcivar.h>
50 #include <dev/pci/pcidevs.h>
52 #include <netisdn/i4b_ioctl.h>
53 #include <netisdn/i4b_l3l4.h>
54 #include <netisdn/i4b_capi.h>
56 #include <dev/ic/iavcvar.h>
57 #include <dev/ic/iavcreg.h>
59 struct iavc_pci_softc
{
60 struct iavc_softc sc_iavc
;
67 pci_chipset_tag_t sc_pc
;
69 void *sc_ih
; /* interrupt handler */
71 #define IAVC_PCI_IOBA 0x14
72 #define IAVC_PCI_MMBA 0x10
74 /* PCI driver linkage */
76 static const struct iavc_pci_product
*find_cardname(struct pci_attach_args
*);
78 static int iavc_pci_probe(device_t
, cfdata_t
, void *);
79 static void iavc_pci_attach(device_t
, device_t
, void *);
81 int iavc_pci_intr(void *);
83 CFATTACH_DECL(iavc_pci
, sizeof(struct iavc_pci_softc
),
84 iavc_pci_probe
, iavc_pci_attach
, NULL
, NULL
);
86 static const struct iavc_pci_product
{
87 pci_vendor_id_t npp_vendor
;
88 pci_product_id_t npp_product
;
90 } iavc_pci_products
[] = {
91 { PCI_VENDOR_AVM
, PCI_PRODUCT_AVM_B1
, "AVM B1 PCI" },
92 { PCI_VENDOR_AVM
, PCI_PRODUCT_AVM_T1
, "AVM T1 PCI" },
96 static const struct iavc_pci_product
*
97 find_cardname(struct pci_attach_args
* pa
)
99 const struct iavc_pci_product
*pp
= NULL
;
101 for (pp
= iavc_pci_products
; pp
->npp_vendor
; pp
++) {
102 if (PCI_VENDOR(pa
->pa_id
) == pp
->npp_vendor
&&
103 PCI_PRODUCT(pa
->pa_id
) == pp
->npp_product
)
111 iavc_pci_probe(device_t parent
, cfdata_t match
, void *aux
)
113 struct pci_attach_args
*pa
= aux
;
115 if (find_cardname(pa
))
122 iavc_pci_attach(device_t parent
, device_t self
, void *aux
)
124 struct iavc_pci_softc
*psc
= device_private(self
);
125 struct iavc_softc
*sc
= &psc
->sc_iavc
;
126 struct pci_attach_args
*pa
= aux
;
127 pci_chipset_tag_t pc
= pa
->pa_pc
;
128 const struct iavc_pci_product
*pp
;
129 pci_intr_handle_t ih
;
133 pp
= find_cardname(pa
);
139 sc
->dmat
= pa
->pa_dmat
;
141 iavc_b1dma_reset(sc
);
143 if (pci_mapreg_map(pa
, IAVC_PCI_IOBA
, PCI_MAPREG_TYPE_IO
, 0,
144 &sc
->sc_io_bt
, &sc
->sc_io_bh
, &psc
->io_base
, &psc
->io_size
)) {
145 aprint_error(": unable to map i/o registers\n");
149 if (pci_mapreg_map(pa
, IAVC_PCI_MMBA
, PCI_MAPREG_TYPE_MEM
, 0,
150 &sc
->sc_mem_bt
, &sc
->sc_mem_bh
, &psc
->mem_base
, &psc
->mem_size
)) {
151 aprint_error(": unable to map mem registers\n");
154 aprint_normal(": %s\n", pp
->name
);
156 if (pp
->npp_product
== PCI_PRODUCT_AVM_T1
) {
157 aprint_error_dev(&sc
->sc_dev
, "sorry, PRI not yet supported\n");
161 sc
->sc_capi
.card_type
= CARD_TYPEC_AVM_T1_PCI
;
162 sc
->sc_capi
.sc_nbch
= NBCH_PRI
;
163 ret
= iavc_t1_detect(sc
);
166 aprint_error_dev(&sc
->sc_dev
, "no card detected?\n");
168 aprint_error_dev(&sc
->sc_dev
, "black box not on\n");
177 } else if (pp
->npp_product
== PCI_PRODUCT_AVM_B1
) {
178 sc
->sc_capi
.card_type
= CARD_TYPEC_AVM_B1_PCI
;
179 sc
->sc_capi
.sc_nbch
= NBCH_BRI
;
180 ret
= iavc_b1dma_detect(sc
);
182 ret
= iavc_b1_detect(sc
);
184 aprint_error_dev(&sc
->sc_dev
, "no card detected?\n");
192 iavc_b1dma_reset(sc
);
196 * XXX: should really be done this way, but this freezes the card
204 if (pci_intr_map(pa
, &ih
)) {
205 aprint_error_dev(&sc
->sc_dev
, "couldn't map interrupt\n");
209 intrstr
= pci_intr_string(pc
, ih
);
210 psc
->sc_ih
= pci_intr_establish(pc
, ih
, IPL_NET
, iavc_pci_intr
, psc
);
211 if (psc
->sc_ih
== NULL
) {
212 aprint_error_dev(&sc
->sc_dev
, "couldn't establish interrupt");
214 aprint_error(" at %s", intrstr
);
219 aprint_normal("%s: interrupting at %s\n", device_xname(&sc
->sc_dev
), intrstr
);
221 memset(&sc
->sc_txq
, 0, sizeof(struct ifqueue
));
222 sc
->sc_txq
.ifq_maxlen
= sc
->sc_capi
.sc_nbch
* 4;
225 sc
->sc_state
= IAVC_DOWN
;
228 /* setup capi link */
229 sc
->sc_capi
.load
= iavc_load
;
230 sc
->sc_capi
.reg_appl
= iavc_register
;
231 sc
->sc_capi
.rel_appl
= iavc_release
;
232 sc
->sc_capi
.send
= iavc_send
;
233 sc
->sc_capi
.ctx
= (void *) sc
;
235 /* lock & load DMA for TX */
236 if ((ret
= bus_dmamem_alloc(sc
->dmat
, IAVC_DMA_SIZE
, PAGE_SIZE
, 0,
237 &sc
->txseg
, 1, &sc
->ntxsegs
, BUS_DMA_ALLOCNOW
)) != 0) {
238 aprint_error_dev(&sc
->sc_dev
, "can't allocate tx DMA memory, error = %d\n",
243 if ((ret
= bus_dmamem_map(sc
->dmat
, &sc
->txseg
, sc
->ntxsegs
,
244 IAVC_DMA_SIZE
, &sc
->sc_sendbuf
, BUS_DMA_NOWAIT
)) != 0) {
245 aprint_error_dev(&sc
->sc_dev
, "can't map tx DMA memory, error = %d\n",
250 if ((ret
= bus_dmamap_create(sc
->dmat
, IAVC_DMA_SIZE
, 1,
251 IAVC_DMA_SIZE
, 0, BUS_DMA_ALLOCNOW
| BUS_DMA_NOWAIT
,
252 &sc
->tx_map
)) != 0) {
253 aprint_error_dev(&sc
->sc_dev
, "can't create tx DMA map, error = %d\n",
258 if ((ret
= bus_dmamap_load(sc
->dmat
, sc
->tx_map
, sc
->sc_sendbuf
,
259 IAVC_DMA_SIZE
, NULL
, BUS_DMA_WRITE
| BUS_DMA_NOWAIT
)) != 0) {
260 aprint_error_dev(&sc
->sc_dev
, "can't load tx DMA map, error = %d\n",
265 /* do the same for RX */
266 if ((ret
= bus_dmamem_alloc(sc
->dmat
, IAVC_DMA_SIZE
, PAGE_SIZE
, 0,
267 &sc
->rxseg
, 1, &sc
->nrxsegs
, BUS_DMA_ALLOCNOW
)) != 0) {
268 aprint_error_dev(&sc
->sc_dev
, "can't allocate rx DMA memory, error = %d\n",
273 if ((ret
= bus_dmamem_map(sc
->dmat
, &sc
->rxseg
, sc
->nrxsegs
,
274 IAVC_DMA_SIZE
, &sc
->sc_recvbuf
, BUS_DMA_NOWAIT
)) != 0) {
275 aprint_error_dev(&sc
->sc_dev
, "can't map rx DMA memory, error = %d\n",
280 if ((ret
= bus_dmamap_create(sc
->dmat
, IAVC_DMA_SIZE
, 1, IAVC_DMA_SIZE
,
281 0, BUS_DMA_ALLOCNOW
| BUS_DMA_NOWAIT
, &sc
->rx_map
)) != 0) {
282 aprint_error_dev(&sc
->sc_dev
, "can't create rx DMA map, error = %d\n",
287 if ((ret
= bus_dmamap_load(sc
->dmat
, sc
->rx_map
, sc
->sc_recvbuf
,
288 IAVC_DMA_SIZE
, NULL
, BUS_DMA_READ
| BUS_DMA_NOWAIT
)) != 0) {
289 aprint_error_dev(&sc
->sc_dev
, "can't load rx DMA map, error = %d\n",
294 if (capi_ll_attach(&sc
->sc_capi
, device_xname(&sc
->sc_dev
), pp
->name
)) {
295 aprint_error_dev(&sc
->sc_dev
, "capi attach failed\n");
300 /* release resources in case of failed attach */
302 bus_dmamap_unload(sc
->dmat
, sc
->rx_map
);
304 bus_dmamap_destroy(sc
->dmat
, sc
->rx_map
);
306 bus_dmamem_unmap(sc
->dmat
, sc
->sc_recvbuf
, IAVC_DMA_SIZE
);
308 bus_dmamem_free(sc
->dmat
, &sc
->rxseg
, sc
->nrxsegs
);
310 bus_dmamap_unload(sc
->dmat
, sc
->tx_map
);
312 bus_dmamap_destroy(sc
->dmat
, sc
->tx_map
);
314 bus_dmamem_unmap(sc
->dmat
, sc
->sc_sendbuf
, IAVC_DMA_SIZE
);
316 bus_dmamem_free(sc
->dmat
, &sc
->txseg
, sc
->ntxsegs
);
318 pci_intr_disestablish(psc
->sc_pc
, psc
->sc_ih
);
324 iavc_pci_intr(void *arg
)
326 struct iavc_softc
*sc
= arg
;
328 return iavc_handle_intr(sc
);
333 iavc_pci_detach(device_t self
, int flags
)
335 struct iavc_pci_softc
*psc
= device_private(self
);
337 bus_space_unmap(psc
->sc_iavc
.sc_mem_bt
, psc
->sc_iavc
.sc_mem_bh
,
339 bus_space_free(psc
->sc_iavc
.sc_mem_bt
, psc
->sc_iavc
.sc_mem_bh
,
341 bus_space_unmap(psc
->sc_iavc
.sc_io_bt
, psc
->sc_iavc
.sc_io_bh
,
343 bus_space_free(psc
->sc_iavc
.sc_io_bt
, psc
->sc_iavc
.sc_io_bh
,
346 pci_intr_disestablish(psc
->sc_pc
, psc
->sc_ih
);
348 /* XXX: capi detach?!? */