xref: /openbsd-src/sys/dev/pci/if_ral_pci.c (revision daf88648c0e349d5c02e1504293082072c981640)
1 /*	$OpenBSD: if_ral_pci.c,v 1.8 2006/11/18 20:44:40 grange Exp $  */
2 
3 /*-
4  * Copyright (c) 2005, 2006
5  *	Damien Bergamini <damien.bergamini@free.fr>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * PCI front-end for the Ralink RT2560/RT2561/RT2561S/RT2661 driver.
22  */
23 
24 #include "bpfilter.h"
25 
26 #include <sys/param.h>
27 #include <sys/sockio.h>
28 #include <sys/mbuf.h>
29 #include <sys/kernel.h>
30 #include <sys/socket.h>
31 #include <sys/systm.h>
32 #include <sys/malloc.h>
33 #include <sys/timeout.h>
34 #include <sys/device.h>
35 
36 #include <machine/bus.h>
37 #include <machine/intr.h>
38 
39 #include <net/if.h>
40 #include <net/if_dl.h>
41 #include <net/if_media.h>
42 
43 #include <netinet/in.h>
44 #include <netinet/if_ether.h>
45 
46 #include <net80211/ieee80211_var.h>
47 #include <net80211/ieee80211_amrr.h>
48 #include <net80211/ieee80211_radiotap.h>
49 
50 #include <dev/ic/rt2560var.h>
51 #include <dev/ic/rt2661var.h>
52 
53 #include <dev/pci/pcireg.h>
54 #include <dev/pci/pcivar.h>
55 #include <dev/pci/pcidevs.h>
56 
57 static struct ral_opns {
58 	int	(*attach)(void *, int);
59 	int	(*detach)(void *);
60 	int	(*intr)(void *);
61 
62 }  ral_rt2560_opns = {
63 	rt2560_attach,
64 	rt2560_detach,
65 	rt2560_intr
66 
67 }, ral_rt2661_opns = {
68 	rt2661_attach,
69 	rt2661_detach,
70 	rt2661_intr
71 };
72 
73 struct ral_pci_softc {
74 	union {
75 		struct rt2560_softc	sc_rt2560;
76 		struct rt2661_softc	sc_rt2661;
77 	} u;
78 #define sc_sc	u.sc_rt2560
79 
80 	/* PCI specific goo */
81 	struct ral_opns		*sc_opns;
82 	pci_chipset_tag_t	sc_pc;
83 	void			*sc_ih;
84 	bus_size_t		sc_mapsize;
85 };
86 
87 /* Base Address Register */
88 #define RAL_PCI_BAR0	0x10
89 
90 int	ral_pci_match(struct device *, void *, void *);
91 void	ral_pci_attach(struct device *, struct device *, void *);
92 int	ral_pci_detach(struct device *, int);
93 
94 struct cfattach ral_pci_ca = {
95 	sizeof (struct ral_pci_softc), ral_pci_match, ral_pci_attach,
96 	ral_pci_detach
97 };
98 
99 const struct pci_matchid ral_pci_devices[] = {
100 	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2560  },
101 	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2561  },
102 	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2561S },
103 	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2661  }
104 };
105 
106 int
107 ral_pci_match(struct device *parent, void *match, void *aux)
108 {
109 	return (pci_matchbyid((struct pci_attach_args *)aux, ral_pci_devices,
110 	    sizeof (ral_pci_devices) / sizeof (ral_pci_devices[0])));
111 }
112 
113 void
114 ral_pci_attach(struct device *parent, struct device *self, void *aux)
115 {
116 	struct ral_pci_softc *psc = (struct ral_pci_softc *)self;
117 	struct rt2560_softc *sc = &psc->sc_sc;
118 	struct pci_attach_args *pa = aux;
119 	const char *intrstr;
120 	pci_intr_handle_t ih;
121 	int error;
122 
123 	psc->sc_opns = (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RALINK_RT2560) ?
124 	    &ral_rt2560_opns : &ral_rt2661_opns;
125 
126 	sc->sc_dmat = pa->pa_dmat;
127 	psc->sc_pc = pa->pa_pc;
128 
129 	/* map control/status registers */
130 	error = pci_mapreg_map(pa, RAL_PCI_BAR0, PCI_MAPREG_TYPE_MEM |
131 	    PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->sc_st, &sc->sc_sh, NULL,
132 	    &psc->sc_mapsize, 0);
133 	if (error != 0) {
134 		printf(": could not map memory space\n");
135 		return;
136 	}
137 
138 	if (pci_intr_map(pa, &ih) != 0) {
139 		printf(": could not map interrupt\n");
140 		return;
141 	}
142 
143 	intrstr = pci_intr_string(psc->sc_pc, ih);
144 	psc->sc_ih = pci_intr_establish(psc->sc_pc, ih, IPL_NET,
145 	    psc->sc_opns->intr, sc, sc->sc_dev.dv_xname);
146 	if (psc->sc_ih == NULL) {
147 		printf(": could not establish interrupt");
148 		if (intrstr != NULL)
149 			printf(" at %s", intrstr);
150 		printf("\n");
151 		return;
152 	}
153 	printf(": %s", intrstr);
154 
155 	(*psc->sc_opns->attach)(sc, PCI_PRODUCT(pa->pa_id));
156 }
157 
158 int
159 ral_pci_detach(struct device *self, int flags)
160 {
161 	struct ral_pci_softc *psc = (struct ral_pci_softc *)self;
162 	struct rt2560_softc *sc = &psc->sc_sc;
163 
164 	(*psc->sc_opns->detach)(sc);
165 	pci_intr_disestablish(psc->sc_pc, psc->sc_ih);
166 
167 	return 0;
168 }
169