2 * Copyright (c) 1997, 1998, 1999
3 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
32 * $FreeBSD: src/sys/dev/an/if_an_pci.c,v 1.2.2.8 2003/02/11 03:32:48 ambrisko Exp $
33 * $DragonFly: src/sys/dev/netif/an/if_an_pci.c,v 1.20 2006/10/25 20:55:55 dillon Exp $
37 * This is a PCI shim for the Aironet PC4500/4800 wireless network
38 * driver. Aironet makes PCMCIA, ISA and PCI versions of these devices,
39 * which all have basically the same interface. The ISA and PCI cards
40 * are actually bridge adapters with PCMCIA cards inserted into them,
41 * however they appear as normal PCI or ISA devices to the host.
43 * All we do here is handle the PCI probe and attach and set up an
44 * interrupt handler entry point. The PCI version of the card uses
45 * a PLX 9050 PCI to "dumb bus" bridge chip, which provides us with
46 * multiple PCI address space mappings. The primary mapping at PCI
47 * register 0x14 is for the PLX chip itself, *NOT* the Aironet card.
48 * The I/O address of the Aironet is actually at register 0x18, which
49 * is the local bus mapping register for bus space 0. There are also
50 * registers for additional register spaces at registers 0x1C and
51 * 0x20, but these are unused in the Aironet devices. To find out
52 * more, you need a datasheet for the 9050 from PLX, but you have
53 * to go through their sales office to get it. Bleh.
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/sockio.h>
66 #include <sys/malloc.h>
67 #include <sys/kernel.h>
68 #include <sys/socket.h>
70 #include <sys/module.h>
75 #include <net/if_arp.h>
76 #include <net/ethernet.h>
77 #include <net/if_dl.h>
78 #include <net/if_media.h>
80 #include <bus/pci/pcidevs.h>
81 #include <bus/pci/pcireg.h>
82 #include <bus/pci/pcivar.h>
84 #include "if_aironet_ieee.h"
94 static const struct an_type an_devs
[] = {
95 { PCI_VENDOR_AIRONET
, PCI_PRODUCT_AIRONET_350
,
96 PCIR_BAR(2), "Cisco Aironet 350 Series" },
97 { PCI_VENDOR_AIRONET
, PCI_PRODUCT_AIRONET_PC4500
,
98 PCIR_BAR(2), "Aironet PCI4500" },
99 { PCI_VENDOR_AIRONET
, PCI_PRODUCT_AIRONET_PC4800
,
100 PCIR_BAR(2), "Aironet PCI4800" },
101 { PCI_VENDOR_AIRONET
, PCI_PRODUCT_AIRONET_PC4xxx
,
102 PCIR_BAR(2), "Aironet PCI4500/PCI4800" },
103 { PCI_VENDOR_AIRONET
, PCI_PRODUCT_AIRONET_MPI350
,
104 PCIR_BAR(0), "Cisco Aironet MPI350" },
108 static int an_probe_pci (device_t
);
109 static int an_attach_pci (device_t
);
110 static int an_suspend_pci (device_t
);
111 static int an_resume_pci (device_t
);
114 an_probe_pci(device_t dev
)
116 const struct an_type
*t
;
119 vid
= pci_get_vendor(dev
);
120 did
= pci_get_device(dev
);
121 for (t
= an_devs
; t
->an_name
!= NULL
; ++t
) {
122 if (vid
== t
->an_vid
&& did
== t
->an_did
) {
125 sc
= device_get_softc(dev
);
126 sc
->port_rid
= t
->an_port_rid
;
127 if (vid
== PCI_VENDOR_AIRONET
&&
128 did
== PCI_PRODUCT_AIRONET_MPI350
)
131 device_set_desc(dev
, t
->an_name
);
139 an_attach_pci(device_t dev
)
144 sc
= device_get_softc(dev
);
145 flags
= device_get_flags(dev
);
147 error
= an_alloc_port(dev
, sc
->port_rid
, 1);
149 device_printf(dev
, "couldn't map ports\n");
153 sc
->an_btag
= rman_get_bustag(sc
->port_res
);
154 sc
->an_bhandle
= rman_get_bushandle(sc
->port_res
);
156 /* Allocate memory for MPI350 */
158 /* Allocate memory */
159 sc
->mem_rid
= PCIR_MAPS
+ 4;
160 error
= an_alloc_memory(dev
, sc
->mem_rid
, 1);
162 device_printf(dev
, "couldn't map memory\n");
165 sc
->an_mem_btag
= rman_get_bustag(sc
->mem_res
);
166 sc
->an_mem_bhandle
= rman_get_bushandle(sc
->mem_res
);
168 /* Allocate aux. memory */
169 sc
->mem_aux_rid
= PCIR_MAPS
+ 8;
170 error
= an_alloc_aux_memory(dev
, sc
->mem_aux_rid
,
173 device_printf(dev
, "couldn't map aux memory\n");
176 sc
->an_mem_aux_btag
= rman_get_bustag(sc
->mem_aux_res
);
177 sc
->an_mem_aux_bhandle
= rman_get_bushandle(sc
->mem_aux_res
);
179 /* Allocate DMA region */
180 error
= bus_dma_tag_create(NULL
, /* parent */
181 1, 0, /* alignment, bounds */
182 BUS_SPACE_MAXADDR_32BIT
, /* lowaddr */
183 BUS_SPACE_MAXADDR
, /* highaddr */
184 NULL
, NULL
, /* filter, filterarg */
185 0x3ffff, /* maxsize XXX */
187 0xffff, /* maxsegsize XXX */
188 BUS_DMA_ALLOCNOW
, /* flags */
191 device_printf(dev
, "couldn't get DMA region\n");
196 /* Allocate interrupt */
197 error
= an_alloc_irq(dev
, 0, RF_SHAREABLE
);
201 error
= an_attach(sc
, dev
, flags
);
205 error
= bus_setup_intr(dev
, sc
->irq_res
, INTR_NETSAFE
,
206 an_intr
, sc
, &sc
->irq_handle
,
207 sc
->arpcom
.ac_if
.if_serializer
);
209 ifmedia_removeall(&sc
->an_ifmedia
);
210 ether_ifdetach(&sc
->arpcom
.ac_if
);
217 an_release_resources(dev
);
222 an_suspend_pci(device_t dev
)
230 an_resume_pci(device_t dev
)
237 static device_method_t an_pci_methods
[] = {
238 /* Device interface */
239 DEVMETHOD(device_probe
, an_probe_pci
),
240 DEVMETHOD(device_attach
, an_attach_pci
),
241 DEVMETHOD(device_detach
, an_detach
),
242 DEVMETHOD(device_shutdown
, an_shutdown
),
243 DEVMETHOD(device_suspend
, an_suspend_pci
),
244 DEVMETHOD(device_resume
, an_resume_pci
),
248 static driver_t an_pci_driver
= {
251 sizeof(struct an_softc
),
254 static devclass_t an_devclass
;
256 DRIVER_MODULE(if_an
, pci
, an_pci_driver
, an_devclass
, 0, 0);