xref: /openbsd-src/sys/dev/pci/if_ath_pci.c (revision daf88648c0e349d5c02e1504293082072c981640)
1 /*      $OpenBSD: if_ath_pci.c,v 1.13 2006/08/03 02:29:33 brad Exp $   */
2 /*	$NetBSD: if_ath_pci.c,v 1.7 2004/06/30 05:58:17 mycroft Exp $	*/
3 
4 /*-
5  * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer,
13  *    without modification.
14  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
15  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
16  *    redistribution must be conditioned upon including a substantially
17  *    similar Disclaimer requirement for further binary redistribution.
18  * 3. Neither the names of the above-listed copyright holders nor the names
19  *    of any contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  * Alternatively, this software may be distributed under the terms of the
23  * GNU General Public License ("GPL") version 2 as published by the Free
24  * Software Foundation.
25  *
26  * NO WARRANTY
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
30  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
31  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
32  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
35  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37  * THE POSSIBILITY OF SUCH DAMAGES.
38  */
39 
40 /*
41  * PCI front-end for the Atheros Wireless LAN controller driver.
42  */
43 
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/mbuf.h>
47 #include <sys/malloc.h>
48 #include <sys/kernel.h>
49 #include <sys/lock.h>
50 #include <sys/socket.h>
51 #include <sys/sockio.h>
52 #include <sys/errno.h>
53 #include <sys/device.h>
54 #include <sys/gpio.h>
55 
56 #include <machine/bus.h>
57 
58 #include <net/if.h>
59 #include <net/if_dl.h>
60 #include <net/if_media.h>
61 #include <net/if_llc.h>
62 #include <net/if_arp.h>
63 #ifdef INET
64 #include <netinet/in.h>
65 #include <netinet/if_ether.h>
66 #endif
67 
68 #include <net80211/ieee80211_var.h>
69 #include <net80211/ieee80211_rssadapt.h>
70 
71 #include <dev/gpio/gpiovar.h>
72 
73 #include <dev/pci/pcivar.h>
74 #include <dev/pci/pcireg.h>
75 #include <dev/pci/pcidevs.h>
76 
77 #include <dev/ic/athvar.h>
78 
79 /*
80  * PCI glue.
81  */
82 
83 struct ath_pci_softc {
84 	struct ath_softc	sc_sc;
85 
86 	pci_chipset_tag_t	sc_pc;
87 	pcitag_t		sc_pcitag;
88 
89 	void			*sc_ih;		/* interrupt handler */
90 };
91 
92 /* Base Address Register */
93 #define ATH_BAR0	0x10
94 
95 int	 ath_pci_match(struct device *, void *, void *);
96 void	 ath_pci_attach(struct device *, struct device *, void *);
97 void	 ath_pci_shutdown(void *);
98 int	 ath_pci_detach(struct device *, int);
99 
100 struct cfattach ath_pci_ca = {
101 	sizeof(struct ath_pci_softc),
102 	ath_pci_match,
103 	ath_pci_attach,
104 	ath_pci_detach
105 };
106 
107 int
108 ath_pci_match(struct device *parent, void *match, void *aux)
109 {
110 	const char* devname;
111 	struct pci_attach_args *pa = aux;
112 	pci_vendor_id_t vendor;
113 
114 	vendor = PCI_VENDOR(pa->pa_id);
115 	if (vendor == 0x128c)
116 		vendor = PCI_VENDOR_ATHEROS;
117 	devname = ath_hal_probe(vendor, PCI_PRODUCT(pa->pa_id));
118 	if (devname)
119 		return 1;
120 
121 	return 0;
122 }
123 
124 void
125 ath_pci_attach(struct device *parent, struct device *self, void *aux)
126 {
127 	struct ath_pci_softc *psc = (struct ath_pci_softc *)self;
128 	struct ath_softc *sc = &psc->sc_sc;
129 	struct pci_attach_args *pa = aux;
130 	pci_chipset_tag_t pc = pa->pa_pc;
131 	pcitag_t pt = pa->pa_tag;
132 	bus_space_tag_t iot;
133 	bus_space_handle_t ioh;
134 	pci_intr_handle_t ih;
135 	pcireg_t mem_type;
136 	void *hook;
137 	const char *intrstr = NULL;
138 
139 	psc->sc_pc = pc;
140 	psc->sc_pcitag = pt;
141 
142 	/*
143 	 * Setup memory-mapping of PCI registers.
144 	 */
145 	mem_type = pci_mapreg_type(pc, pa->pa_tag, ATH_BAR0);
146 	if (mem_type != PCI_MAPREG_TYPE_MEM &&
147 	    mem_type != PCI_MAPREG_MEM_TYPE_64BIT) {
148 		printf(": bad PCI register type %d\n", (int)mem_type);
149 		goto bad;
150 	}
151 	if (pci_mapreg_map(pa, ATH_BAR0, mem_type, 0, &iot, &ioh,
152 	    NULL, NULL, 0)) {
153 		printf(": cannot map register space\n");
154 		goto bad;
155 	}
156 	sc->sc_st = iot;
157 	sc->sc_sh = ioh;
158 
159 	sc->sc_invalid = 1;
160 
161 	/*
162 	 * Arrange interrupt line.
163 	 */
164 	if (pci_intr_map(pa, &ih)) {
165 		printf(": couldn't map interrupt\n");
166 		goto bad1;
167 	}
168 
169 	intrstr = pci_intr_string(pc, ih);
170 	psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, ath_intr, sc,
171 	    sc->sc_dev.dv_xname);
172 	if (psc->sc_ih == NULL) {
173 		printf(": couldn't map interrupt\n");
174 		goto bad2;
175 	}
176 
177 	printf(": %s\n", intrstr);
178 
179 	sc->sc_dmat = pa->pa_dmat;
180 
181 	hook = shutdownhook_establish(ath_pci_shutdown, psc);
182 	if (hook == NULL) {
183 		printf(": couldn't make shutdown hook\n");
184 		goto bad3;
185 	}
186 
187 	if (ath_attach(PCI_PRODUCT(pa->pa_id), sc) == 0)
188 		return;
189 
190 	shutdownhook_disestablish(hook);
191 
192 bad3:	pci_intr_disestablish(pc, psc->sc_ih);
193 bad2:	/* XXX */
194 bad1:	/* XXX */
195 bad:
196 	return;
197 }
198 
199 int
200 ath_pci_detach(struct device *self, int flags)
201 {
202 	struct ath_pci_softc *psc = (struct ath_pci_softc *)self;
203 
204 	ath_detach(&psc->sc_sc, flags);
205 	pci_intr_disestablish(psc->sc_pc, psc->sc_ih);
206 
207 	return (0);
208 }
209 
210 void
211 ath_pci_shutdown(void *self)
212 {
213 	struct ath_pci_softc *psc = (struct ath_pci_softc *)self;
214 
215 	ath_shutdown(&psc->sc_sc);
216 }
217