if_ral_pci.c revision 156321
1145247Sdamien/*	$FreeBSD: head/sys/dev/ral/if_ral_pci.c 156321 2006-03-05 20:36:56Z damien $	*/
2145247Sdamien
3145247Sdamien/*-
4156321Sdamien * Copyright (c) 2005, 2006
5145247Sdamien *	Damien Bergamini <damien.bergamini@free.fr>
6145247Sdamien *
7145247Sdamien * Permission to use, copy, modify, and distribute this software for any
8145247Sdamien * purpose with or without fee is hereby granted, provided that the above
9145247Sdamien * copyright notice and this permission notice appear in all copies.
10145247Sdamien *
11145247Sdamien * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12145247Sdamien * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13145247Sdamien * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14145247Sdamien * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15145247Sdamien * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16145247Sdamien * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17145247Sdamien * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18145247Sdamien */
19145247Sdamien
20145247Sdamien#include <sys/cdefs.h>
21145247Sdamien__FBSDID("$FreeBSD: head/sys/dev/ral/if_ral_pci.c 156321 2006-03-05 20:36:56Z damien $");
22145247Sdamien
23145247Sdamien/*
24156321Sdamien * PCI/Cardbus front-end for the Ralink RT2560/RT2561/RT2561S/RT2661 driver.
25145247Sdamien */
26145247Sdamien
27145247Sdamien#include <sys/param.h>
28145247Sdamien#include <sys/sysctl.h>
29145247Sdamien#include <sys/sockio.h>
30145247Sdamien#include <sys/mbuf.h>
31145247Sdamien#include <sys/kernel.h>
32145247Sdamien#include <sys/socket.h>
33145247Sdamien#include <sys/systm.h>
34145247Sdamien#include <sys/malloc.h>
35145247Sdamien#include <sys/module.h>
36145247Sdamien#include <sys/bus.h>
37145247Sdamien#include <sys/endian.h>
38145247Sdamien
39145247Sdamien#include <machine/bus.h>
40145247Sdamien#include <machine/resource.h>
41145247Sdamien#include <machine/clock.h>
42145247Sdamien#include <sys/rman.h>
43145247Sdamien
44145247Sdamien#include <net/bpf.h>
45145247Sdamien#include <net/if.h>
46145247Sdamien#include <net/if_arp.h>
47145247Sdamien#include <net/ethernet.h>
48145247Sdamien#include <net/if_dl.h>
49145247Sdamien#include <net/if_media.h>
50145247Sdamien#include <net/if_types.h>
51145247Sdamien
52145247Sdamien#include <net80211/ieee80211_var.h>
53145247Sdamien#include <net80211/ieee80211_radiotap.h>
54145247Sdamien
55145247Sdamien#include <dev/pci/pcireg.h>
56145247Sdamien#include <dev/pci/pcivar.h>
57145247Sdamien
58156321Sdamien#include <dev/rt61/if_ralrate.h>
59156321Sdamien#include <dev/rt61/rt2560var.h>
60156321Sdamien#include <dev/rt61/rt2661var.h>
61145247Sdamien
62145247SdamienMODULE_DEPEND(ral, pci, 1, 1, 1);
63145247SdamienMODULE_DEPEND(ral, wlan, 1, 1, 1);
64145247Sdamien
65145247Sdamienstruct ral_pci_ident {
66145247Sdamien	uint16_t	vendor;
67145247Sdamien	uint16_t	device;
68145247Sdamien	const char	*name;
69145247Sdamien};
70145247Sdamien
71145247Sdamienstatic const struct ral_pci_ident ral_pci_ids[] = {
72156321Sdamien	{ 0x1814, 0x0201, "Ralink Technology RT2560" },
73156321Sdamien	{ 0x1814, 0x0301, "Ralink Technology RT2561S" },
74156321Sdamien	{ 0x1814, 0x0302, "Ralink Technology RT2561" },
75156321Sdamien	{ 0x1814, 0x0401, "Ralink Technology RT2661" },
76145247Sdamien
77145247Sdamien	{ 0, 0, NULL }
78145247Sdamien};
79145247Sdamien
80156321Sdamienstatic struct ral_opns {
81156321Sdamien	int	(*attach)(device_t, int);
82156321Sdamien	int	(*detach)(void *);
83156321Sdamien	void	(*shutdown)(void *);
84156321Sdamien	void	(*suspend)(void *);
85156321Sdamien	void	(*resume)(void *);
86156321Sdamien	void	(*intr)(void *);
87156321Sdamien
88156321Sdamien}  ral_rt2560_opns = {
89156321Sdamien	rt2560_attach,
90156321Sdamien	rt2560_detach,
91156321Sdamien	rt2560_shutdown,
92156321Sdamien	rt2560_suspend,
93156321Sdamien	rt2560_resume,
94156321Sdamien	rt2560_intr
95156321Sdamien
96156321Sdamien}, ral_rt2661_opns = {
97156321Sdamien	rt2661_attach,
98156321Sdamien	rt2661_detach,
99156321Sdamien	rt2661_shutdown,
100156321Sdamien	rt2661_suspend,
101156321Sdamien	rt2661_resume,
102156321Sdamien	rt2661_intr
103156321Sdamien};
104156321Sdamien
105156321Sdamienstruct ral_pci_softc {
106156321Sdamien	union {
107156321Sdamien		struct rt2560_softc sc_rt2560;
108156321Sdamien		struct rt2661_softc sc_rt2661;
109156321Sdamien	} u;
110156321Sdamien
111156321Sdamien	struct ral_opns		*sc_opns;
112156321Sdamien	int			irq_rid;
113156321Sdamien	int			mem_rid;
114156321Sdamien	struct resource		*irq;
115156321Sdamien	struct resource		*mem;
116156321Sdamien	void			*sc_ih;
117156321Sdamien};
118156321Sdamien
119145247Sdamienstatic int ral_pci_probe(device_t);
120145247Sdamienstatic int ral_pci_attach(device_t);
121156321Sdamienstatic int ral_pci_detach(device_t);
122156321Sdamienstatic int ral_pci_shutdown(device_t);
123145247Sdamienstatic int ral_pci_suspend(device_t);
124145247Sdamienstatic int ral_pci_resume(device_t);
125145247Sdamien
126145247Sdamienstatic device_method_t ral_pci_methods[] = {
127145247Sdamien	/* Device interface */
128145247Sdamien	DEVMETHOD(device_probe,		ral_pci_probe),
129145247Sdamien	DEVMETHOD(device_attach,	ral_pci_attach),
130156321Sdamien	DEVMETHOD(device_detach,	ral_pci_detach),
131156321Sdamien	DEVMETHOD(device_shutdown,	ral_pci_shutdown),
132145247Sdamien	DEVMETHOD(device_suspend,	ral_pci_suspend),
133145247Sdamien	DEVMETHOD(device_resume,	ral_pci_resume),
134145247Sdamien
135145247Sdamien	{ 0, 0 }
136145247Sdamien};
137145247Sdamien
138145247Sdamienstatic driver_t ral_pci_driver = {
139145247Sdamien	"ral",
140145247Sdamien	ral_pci_methods,
141156321Sdamien	sizeof (struct ral_pci_softc)
142145247Sdamien};
143145247Sdamien
144156321Sdamienstatic devclass_t ral_devclass;
145156321Sdamien
146145247SdamienDRIVER_MODULE(ral, pci, ral_pci_driver, ral_devclass, 0, 0);
147145247SdamienDRIVER_MODULE(ral, cardbus, ral_pci_driver, ral_devclass, 0, 0);
148145247Sdamien
149145247Sdamienstatic int
150145247Sdamienral_pci_probe(device_t dev)
151145247Sdamien{
152145247Sdamien	const struct ral_pci_ident *ident;
153145247Sdamien
154145247Sdamien	for (ident = ral_pci_ids; ident->name != NULL; ident++) {
155145247Sdamien		if (pci_get_vendor(dev) == ident->vendor &&
156145247Sdamien		    pci_get_device(dev) == ident->device) {
157145247Sdamien			device_set_desc(dev, ident->name);
158145247Sdamien			return 0;
159145247Sdamien		}
160145247Sdamien	}
161145247Sdamien	return ENXIO;
162145247Sdamien}
163145247Sdamien
164145247Sdamien/* Base Address Register */
165145247Sdamien#define RAL_PCI_BAR0	0x10
166145247Sdamien
167145247Sdamienstatic int
168145247Sdamienral_pci_attach(device_t dev)
169145247Sdamien{
170156321Sdamien	struct ral_pci_softc *psc = device_get_softc(dev);
171156321Sdamien	struct rt2560_softc *sc = &psc->u.sc_rt2560;
172145247Sdamien	int error;
173145247Sdamien
174145247Sdamien	if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
175145247Sdamien		device_printf(dev, "chip is in D%d power mode "
176145247Sdamien		    "-- setting to D0\n", pci_get_powerstate(dev));
177145247Sdamien		pci_set_powerstate(dev, PCI_POWERSTATE_D0);
178145247Sdamien	}
179145247Sdamien
180145247Sdamien	/* enable bus-mastering */
181145247Sdamien	pci_enable_busmaster(dev);
182145247Sdamien
183156321Sdamien	psc->sc_opns = (pci_get_device(dev) == 0x0201) ? &ral_rt2560_opns :
184156321Sdamien	    &ral_rt2661_opns;
185156321Sdamien
186156321Sdamien	psc->mem_rid = RAL_PCI_BAR0;
187156321Sdamien	psc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &psc->mem_rid,
188156321Sdamien	    RF_ACTIVE);
189156321Sdamien	if (psc->mem == NULL) {
190156321Sdamien		device_printf(dev, "could not allocate memory resource\n");
191156321Sdamien		return ENXIO;
192156321Sdamien	}
193156321Sdamien
194156321Sdamien	sc->sc_st = rman_get_bustag(psc->mem);
195156321Sdamien	sc->sc_sh = rman_get_bushandle(psc->mem);
196156321Sdamien
197156321Sdamien	psc->irq_rid = 0;
198156321Sdamien	psc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &psc->irq_rid,
199156321Sdamien	    RF_ACTIVE | RF_SHAREABLE);
200156321Sdamien	if (psc->irq == NULL) {
201156321Sdamien		device_printf(dev, "could not allocate interrupt resource\n");
202156321Sdamien		return ENXIO;
203156321Sdamien	}
204156321Sdamien
205156321Sdamien	error = (*psc->sc_opns->attach)(dev, pci_get_device(dev));
206145247Sdamien	if (error != 0)
207145247Sdamien		return error;
208145247Sdamien
209156321Sdamien	/*
210156321Sdamien	 * Hook our interrupt after all initialization is complete.
211156321Sdamien	 */
212156321Sdamien	error = bus_setup_intr(dev, psc->irq, INTR_TYPE_NET | INTR_MPSAFE,
213156321Sdamien	    psc->sc_opns->intr, psc, &psc->sc_ih);
214156321Sdamien	if (error != 0) {
215156321Sdamien		device_printf(dev, "could not set up interrupt\n");
216156321Sdamien		return error;
217156321Sdamien	}
218145247Sdamien
219156321Sdamien	return 0;
220145247Sdamien}
221145247Sdamien
222145247Sdamienstatic int
223156321Sdamienral_pci_detach(device_t dev)
224156321Sdamien{
225156321Sdamien	struct ral_pci_softc *psc = device_get_softc(dev);
226156321Sdamien
227156321Sdamien	(*psc->sc_opns->detach)(psc);
228156321Sdamien
229156321Sdamien	bus_generic_detach(dev);
230156321Sdamien	bus_teardown_intr(dev, psc->irq, psc->sc_ih);
231156321Sdamien	bus_release_resource(dev, SYS_RES_IRQ, psc->irq_rid, psc->irq);
232156321Sdamien
233156321Sdamien	bus_release_resource(dev, SYS_RES_MEMORY, psc->mem_rid, psc->mem);
234156321Sdamien
235156321Sdamien	return 0;
236156321Sdamien}
237156321Sdamien
238156321Sdamienstatic int
239156321Sdamienral_pci_shutdown(device_t dev)
240156321Sdamien{
241156321Sdamien	struct ral_pci_softc *psc = device_get_softc(dev);
242156321Sdamien
243156321Sdamien	(*psc->sc_opns->shutdown)(psc);
244156321Sdamien
245156321Sdamien	return 0;
246156321Sdamien}
247156321Sdamien
248156321Sdamienstatic int
249145247Sdamienral_pci_suspend(device_t dev)
250145247Sdamien{
251156321Sdamien	struct ral_pci_softc *psc = device_get_softc(dev);
252145247Sdamien
253156321Sdamien	(*psc->sc_opns->suspend)(psc);
254145247Sdamien
255145247Sdamien	return 0;
256145247Sdamien}
257145247Sdamien
258145247Sdamienstatic int
259145247Sdamienral_pci_resume(device_t dev)
260145247Sdamien{
261156321Sdamien	struct ral_pci_softc *psc = device_get_softc(dev);
262145247Sdamien
263156321Sdamien	(*psc->sc_opns->resume)(psc);
264145247Sdamien
265145247Sdamien	return 0;
266145247Sdamien}
267