Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pci / iavc_pci.c
blob47d6ff70acbc4ac6cb224fa922396199960c3597
1 /* $NetBSD: iavc_pci.c,v 1.12 2009/11/26 15:17:09 njoly Exp $ */
3 /*
4 * Copyright (c) 2001-2003 Cubical Solutions Ltd.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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
26 * SUCH DAMAGE.
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>
40 #include <sys/mbuf.h>
41 #include <sys/callout.h>
42 #include <sys/socket.h>
43 #include <sys/device.h>
44 #include <net/if.h>
46 #include <sys/bus.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;
62 bus_addr_t mem_base;
63 bus_size_t mem_size;
64 bus_addr_t io_base;
65 bus_size_t io_size;
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;
89 const char *name;
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" },
93 { 0, 0, NULL },
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)
104 return pp;
107 return NULL;
110 static int
111 iavc_pci_probe(device_t parent, cfdata_t match, void *aux)
113 struct pci_attach_args *pa = aux;
115 if (find_cardname(pa))
116 return 1;
118 return 0;
121 static void
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;
130 const char *intrstr;
131 int ret;
133 pp = find_cardname(pa);
134 if (pp == NULL)
135 return;
137 sc->sc_t1 = 0;
138 sc->sc_dma = 0;
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");
146 return;
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");
152 return;
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");
158 return;
160 #if 0
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);
164 if (ret) {
165 if (ret < 6) {
166 aprint_error_dev(&sc->sc_dev, "no card detected?\n");
167 } else {
168 aprint_error_dev(&sc->sc_dev, "black box not on\n");
170 return;
171 } else {
172 sc->sc_dma = 1;
173 sc->sc_t1 = 1;
175 #endif
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);
181 if (ret) {
182 ret = iavc_b1_detect(sc);
183 if (ret) {
184 aprint_error_dev(&sc->sc_dev, "no card detected?\n");
185 return;
187 } else {
188 sc->sc_dma = 1;
191 if (sc->sc_dma)
192 iavc_b1dma_reset(sc);
194 #if 0
196 * XXX: should really be done this way, but this freezes the card
198 if (sc->sc_t1)
199 iavc_t1_reset(sc);
200 else
201 iavc_b1_reset(sc);
202 #endif
204 if (pci_intr_map(pa, &ih)) {
205 aprint_error_dev(&sc->sc_dev, "couldn't map interrupt\n");
206 return;
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");
213 if (intrstr != NULL)
214 aprint_error(" at %s", intrstr);
215 aprint_error("\n");
216 return;
218 psc->sc_pc = pc;
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;
224 sc->sc_intr = 0;
225 sc->sc_state = IAVC_DOWN;
226 sc->sc_blocked = 0;
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",
239 ret);
240 goto fail1;
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",
246 ret);
247 goto fail2;
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",
254 ret);
255 goto fail3;
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",
261 ret);
262 goto fail4;
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",
269 ret);
270 goto fail5;
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",
276 ret);
277 goto fail6;
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",
283 ret);
284 goto fail7;
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",
290 ret);
291 goto fail8;
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");
296 goto fail9;
298 return;
300 /* release resources in case of failed attach */
301 fail9:
302 bus_dmamap_unload(sc->dmat, sc->rx_map);
303 fail8:
304 bus_dmamap_destroy(sc->dmat, sc->rx_map);
305 fail7:
306 bus_dmamem_unmap(sc->dmat, sc->sc_recvbuf, IAVC_DMA_SIZE);
307 fail6:
308 bus_dmamem_free(sc->dmat, &sc->rxseg, sc->nrxsegs);
309 fail5:
310 bus_dmamap_unload(sc->dmat, sc->tx_map);
311 fail4:
312 bus_dmamap_destroy(sc->dmat, sc->tx_map);
313 fail3:
314 bus_dmamem_unmap(sc->dmat, sc->sc_sendbuf, IAVC_DMA_SIZE);
315 fail2:
316 bus_dmamem_free(sc->dmat, &sc->txseg, sc->ntxsegs);
317 fail1:
318 pci_intr_disestablish(psc->sc_pc, psc->sc_ih);
320 return;
324 iavc_pci_intr(void *arg)
326 struct iavc_softc *sc = arg;
328 return iavc_handle_intr(sc);
331 #if 0
332 static int
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,
338 psc->mem_size);
339 bus_space_free(psc->sc_iavc.sc_mem_bt, psc->sc_iavc.sc_mem_bh,
340 psc->mem_size);
341 bus_space_unmap(psc->sc_iavc.sc_io_bt, psc->sc_iavc.sc_io_bh,
342 psc->io_size);
343 bus_space_free(psc->sc_iavc.sc_io_bt, psc->sc_iavc.sc_io_bh,
344 psc->io_size);
346 pci_intr_disestablish(psc->sc_pc, psc->sc_ih);
348 /* XXX: capi detach?!? */
350 return 0;
352 #endif