Deleted Added
full compact
if_gem_pci.c (169269) if_gem_pci.c (172334)
1/*-
2 * Copyright (C) 2001 Eduardo Horvath.
3 * All rights reserved.
4 *
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 11 unchanged lines hidden (view full) ---

20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * from: NetBSD: if_gem_pci.c,v 1.7 2001/10/18 15:09:15 thorpej Exp
1/*-
2 * Copyright (C) 2001 Eduardo Horvath.
3 * All rights reserved.
4 *
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 11 unchanged lines hidden (view full) ---

20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * from: NetBSD: if_gem_pci.c,v 1.7 2001/10/18 15:09:15 thorpej Exp
28 *
29 */
30
31#include <sys/cdefs.h>
28 */
29
30#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/gem/if_gem_pci.c 169269 2007-05-04 19:15:28Z phk $");
31__FBSDID("$FreeBSD: head/sys/dev/gem/if_gem_pci.c 172334 2007-09-26 21:14:18Z marius $");
33
34/*
32
33/*
35 * PCI bindings for Sun GEM ethernet controllers.
34 * PCI bindings for Apple GMAC, Sun ERI and Sun GEM Ethernet controllers
36 */
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/bus.h>
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/bus.h>
41#include <sys/malloc.h>
42#include <sys/kernel.h>
43#include <sys/lock.h>
44#include <sys/module.h>
45#include <sys/mutex.h>
46#include <sys/resource.h>
40#include <sys/kernel.h>
41#include <sys/lock.h>
42#include <sys/module.h>
43#include <sys/mutex.h>
44#include <sys/resource.h>
45#include <sys/rman.h>
47#include <sys/socket.h>
48
46#include <sys/socket.h>
47
49#include <machine/endian.h>
50
51#include <net/ethernet.h>
52#include <net/if.h>
48#include <net/ethernet.h>
49#include <net/if.h>
53#include <net/if_arp.h>
54#include <net/if_dl.h>
55#include <net/if_media.h>
56
57#include <machine/bus.h>
50
51#include <machine/bus.h>
58#include <machine/resource.h>
52#if defined(__powerpc__) || defined(__sparc64__)
59#include <dev/ofw/openfirm.h>
60#include <machine/ofw_machdep.h>
53#include <dev/ofw/openfirm.h>
54#include <machine/ofw_machdep.h>
55#endif
56#include <machine/resource.h>
61
57
62#include <sys/rman.h>
63
64#include <dev/mii/mii.h>
65#include <dev/mii/miivar.h>
66
67#include <dev/gem/if_gemreg.h>
68#include <dev/gem/if_gemvar.h>
69
58#include <dev/gem/if_gemreg.h>
59#include <dev/gem/if_gemvar.h>
60
70#include <dev/pci/pcivar.h>
71#include <dev/pci/pcireg.h>
61#include <dev/pci/pcireg.h>
62#include <dev/pci/pcivar.h>
72
73#include "miibus_if.h"
74
75static int gem_pci_probe(device_t);
76static int gem_pci_attach(device_t);
77static int gem_pci_detach(device_t);
78static int gem_pci_suspend(device_t);
79static int gem_pci_resume(device_t);

--- 21 unchanged lines hidden (view full) ---

101};
102
103static driver_t gem_pci_driver = {
104 "gem",
105 gem_pci_methods,
106 sizeof(struct gem_softc)
107};
108
63
64#include "miibus_if.h"
65
66static int gem_pci_probe(device_t);
67static int gem_pci_attach(device_t);
68static int gem_pci_detach(device_t);
69static int gem_pci_suspend(device_t);
70static int gem_pci_resume(device_t);

--- 21 unchanged lines hidden (view full) ---

92};
93
94static driver_t gem_pci_driver = {
95 "gem",
96 gem_pci_methods,
97 sizeof(struct gem_softc)
98};
99
109
110DRIVER_MODULE(gem, pci, gem_pci_driver, gem_devclass, 0, 0);
111MODULE_DEPEND(gem, pci, 1, 1, 1);
112MODULE_DEPEND(gem, ether, 1, 1, 1);
113
100DRIVER_MODULE(gem, pci, gem_pci_driver, gem_devclass, 0, 0);
101MODULE_DEPEND(gem, pci, 1, 1, 1);
102MODULE_DEPEND(gem, ether, 1, 1, 1);
103
114struct gem_pci_dev {
115 u_int32_t gpd_devid;
116 int gpd_variant;
117 char *gpd_desc;
104static const struct gem_pci_dev {
105 uint32_t gpd_devid;
106 int gpd_variant;
107 const char *gpd_desc;
118} gem_pci_devlist[] = {
108} gem_pci_devlist[] = {
119 { 0x1101108e, GEM_SUN_GEM, "Sun ERI 10/100 Ethernet Adaptor" },
120 { 0x2bad108e, GEM_SUN_GEM, "Sun GEM Gigabit Ethernet Adaptor" },
121 { 0x0021106b, GEM_APPLE_GMAC, "Apple GMAC Ethernet Adaptor" },
122 { 0x0024106b, GEM_APPLE_GMAC, "Apple GMAC2 Ethernet Adaptor" },
123 { 0x0032106b, GEM_APPLE_GMAC, "Apple GMAC3 Ethernet Adaptor" },
109 { 0x1101108e, GEM_SUN_ERI, "Sun ERI 10/100 Ethernet" },
110 { 0x2bad108e, GEM_SUN_GEM, "Sun GEM Gigabit Ethernet" },
111 { 0x0021106b, GEM_APPLE_GMAC, "Apple UniNorth GMAC Ethernet" },
112 { 0x0024106b, GEM_APPLE_GMAC, "Apple Pangea GMAC Ethernet" },
113 { 0x0032106b, GEM_APPLE_GMAC, "Apple UniNorth2 GMAC Ethernet" },
114 { 0x004c106b, GEM_APPLE_K2_GMAC,"Apple K2 GMAC Ethernet" },
115 { 0x0051106b, GEM_APPLE_GMAC, "Apple Shasta GMAC Ethernet" },
116 { 0x006b106b, GEM_APPLE_GMAC, "Apple Intrepid 2 GMAC Ethernet" },
124 { 0, 0, NULL }
125};
126
117 { 0, 0, NULL }
118};
119
127/*
128 * Attach routines need to be split out to different bus-specific files.
129 */
130static int
131gem_pci_probe(dev)
132 device_t dev;
133{
134 int i;
120static int
121gem_pci_probe(dev)
122 device_t dev;
123{
124 int i;
135 u_int32_t devid;
136 struct gem_softc *sc;
137
125
138 devid = pci_get_devid(dev);
139 for (i = 0; gem_pci_devlist[i].gpd_desc != NULL; i++) {
126 for (i = 0; gem_pci_devlist[i].gpd_desc != NULL; i++) {
140 if (devid == gem_pci_devlist[i].gpd_devid) {
127 if (pci_get_devid(dev) == gem_pci_devlist[i].gpd_devid) {
141 device_set_desc(dev, gem_pci_devlist[i].gpd_desc);
128 device_set_desc(dev, gem_pci_devlist[i].gpd_desc);
142 sc = device_get_softc(dev);
143 sc->sc_variant = gem_pci_devlist[i].gpd_variant;
144 return (BUS_PROBE_DEFAULT);
145 }
146 }
147
148 return (ENXIO);
149}
150
151static struct resource_spec gem_pci_res_spec[] = {
129 return (BUS_PROBE_DEFAULT);
130 }
131 }
132
133 return (ENXIO);
134}
135
136static struct resource_spec gem_pci_res_spec[] = {
152 { SYS_RES_MEMORY, PCI_GEM_BASEADDR, RF_ACTIVE },
137 { SYS_RES_MEMORY, PCIR_BAR(0), RF_ACTIVE },
153 { SYS_RES_IRQ, 0, RF_SHAREABLE | RF_ACTIVE },
154 { -1, 0 }
155};
156
157static int
158gem_pci_attach(dev)
159 device_t dev;
160{
138 { SYS_RES_IRQ, 0, RF_SHAREABLE | RF_ACTIVE },
139 { -1, 0 }
140};
141
142static int
143gem_pci_attach(dev)
144 device_t dev;
145{
161 struct gem_softc *sc = device_get_softc(dev);
146 struct gem_softc *sc;
147 int i;
148#if !(defined(__powerpc__) || defined(__sparc64__))
149 int j;
150#endif
162
151
152 sc = device_get_softc(dev);
153 sc->sc_variant = GEM_UNKNOWN;
154 for (i = 0; gem_pci_devlist[i].gpd_desc != NULL; i++) {
155 if (pci_get_devid(dev) == gem_pci_devlist[i].gpd_devid) {
156 sc->sc_variant = gem_pci_devlist[i].gpd_variant;
157 break;
158 }
159 }
160 if (sc->sc_variant == GEM_UNKNOWN) {
161 device_printf(dev, "unknown adaptor\n");
162 return (ENXIO);
163 }
164
163 pci_enable_busmaster(dev);
164
165 /*
166 * Some Sun GEMs/ERIs do have their intpin register bogusly set to 0,
167 * although it should be 1. correct that.
168 */
169 if (pci_get_intpin(dev) == 0)
170 pci_set_intpin(dev, 1);
171
172 sc->sc_dev = dev;
165 pci_enable_busmaster(dev);
166
167 /*
168 * Some Sun GEMs/ERIs do have their intpin register bogusly set to 0,
169 * although it should be 1. correct that.
170 */
171 if (pci_get_intpin(dev) == 0)
172 pci_set_intpin(dev, 1);
173
174 sc->sc_dev = dev;
173 sc->sc_pci = 1; /* XXX */
175 sc->sc_flags |= GEM_PCI; /* XXX */
174
175 if (bus_alloc_resources(dev, gem_pci_res_spec, sc->sc_res)) {
176 device_printf(dev, "failed to allocate resources\n");
177 bus_release_resources(dev, gem_pci_res_spec, sc->sc_res);
178 return (ENXIO);
179 }
180
181 GEM_LOCK_INIT(sc, device_get_nameunit(dev));
182
176
177 if (bus_alloc_resources(dev, gem_pci_res_spec, sc->sc_res)) {
178 device_printf(dev, "failed to allocate resources\n");
179 bus_release_resources(dev, gem_pci_res_spec, sc->sc_res);
180 return (ENXIO);
181 }
182
183 GEM_LOCK_INIT(sc, device_get_nameunit(dev));
184
183 /* All platform that this driver is used on must provide this. */
185#if defined(__powerpc__) || defined(__sparc64__)
184 OF_getetheraddr(dev, sc->sc_enaddr);
186 OF_getetheraddr(dev, sc->sc_enaddr);
187#else
188 /*
189 * Dig out VPD (vital product data) and read NA (network address).
190 * The VPD of GEM resides in the PCI Expansion ROM (PCI FCode) and
191 * can't be accessed via the PCI capability pointer.
192 * ``Writing FCode 3.x Programs'' (newer ones, dated 1997 and later)
193 * chapter 2 describes the data structure.
194 */
185
195
196#define PCI_ROMHDR_SIZE 0x1c
197#define PCI_ROMHDR_SIG 0x00
198#define PCI_ROMHDR_SIG_MAGIC 0xaa55 /* little endian */
199#define PCI_ROMHDR_PTR_DATA 0x18
200#define PCI_ROM_SIZE 0x18
201#define PCI_ROM_SIG 0x00
202#define PCI_ROM_SIG_MAGIC 0x52494350 /* "PCIR", endian */
203 /* reversed */
204#define PCI_ROM_VENDOR 0x04
205#define PCI_ROM_DEVICE 0x06
206#define PCI_ROM_PTR_VPD 0x08
207#define PCI_VPDRES_BYTE0 0x00
208#define PCI_VPDRES_ISLARGE(x) ((x) & 0x80)
209#define PCI_VPDRES_LARGE_NAME(x) ((x) & 0x7f)
210#define PCI_VPDRES_TYPE_VPD 0x10 /* large */
211#define PCI_VPDRES_LARGE_LEN_LSB 0x01
212#define PCI_VPDRES_LARGE_LEN_MSB 0x02
213#define PCI_VPDRES_LARGE_DATA 0x03
214#define PCI_VPD_SIZE 0x03
215#define PCI_VPD_KEY0 0x00
216#define PCI_VPD_KEY1 0x01
217#define PCI_VPD_LEN 0x02
218#define PCI_VPD_DATA 0x03
219
220#define GEM_ROM_READ_N(n, sc, offs) \
221 bus_read_ ## n ((sc)->sc_res[0], GEM_PCI_ROM_OFFSET + (offs))
222#define GEM_ROM_READ_1(sc, offs) GEM_ROM_READ_N(1, (sc), (offs))
223#define GEM_ROM_READ_2(sc, offs) GEM_ROM_READ_N(2, (sc), (offs))
224#define GEM_ROM_READ_4(sc, offs) GEM_ROM_READ_N(4, (sc), (offs))
225
226 /* Read PCI Expansion ROM header. */
227 if (GEM_ROM_READ_2(sc, PCI_ROMHDR_SIG) != PCI_ROMHDR_SIG_MAGIC ||
228 (i = GEM_ROM_READ_2(sc, PCI_ROMHDR_PTR_DATA)) < PCI_ROMHDR_SIZE) {
229 device_printf(dev, "unexpected PCI Expansion ROM header\n");
230 goto fail;
231 }
232
233 /* Read PCI Expansion ROM data. */
234 if (GEM_ROM_READ_4(sc, i + PCI_ROM_SIG) != PCI_ROM_SIG_MAGIC ||
235 GEM_ROM_READ_2(sc, i + PCI_ROM_VENDOR) != pci_get_vendor(dev) ||
236 GEM_ROM_READ_2(sc, i + PCI_ROM_DEVICE) != pci_get_device(dev) ||
237 (j = GEM_ROM_READ_2(sc, i + PCI_ROM_PTR_VPD)) < i + PCI_ROM_SIZE) {
238 device_printf(dev, "unexpected PCI Expansion ROM data\n");
239 goto fail;
240 }
241
186 /*
242 /*
243 * Read PCI VPD.
244 * SUNW,pci-gem cards have a single large resource VPD-R tag
245 * containing one NA. The VPD used is not in PCI 2.2 standard
246 * format however. The length in the resource header is in big
247 * endian and the end tag is non-standard (0x79) and followed
248 * by an all-zero "checksum" byte. Sun calls this a "Fresh
249 * Choice Ethernet" VPD...
250 */
251 if (PCI_VPDRES_ISLARGE(GEM_ROM_READ_1(sc, j + PCI_VPDRES_BYTE0)) == 0 ||
252 PCI_VPDRES_LARGE_NAME(GEM_ROM_READ_1(sc, j + PCI_VPDRES_BYTE0)) !=
253 PCI_VPDRES_TYPE_VPD ||
254 (GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_LEN_LSB) << 8 |
255 GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_LEN_MSB)) !=
256 PCI_VPD_SIZE + ETHER_ADDR_LEN ||
257 GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_DATA + PCI_VPD_KEY0) !=
258 0x4e /* N */ ||
259 GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_DATA + PCI_VPD_KEY1) !=
260 0x41 /* A */ ||
261 GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_DATA + PCI_VPD_LEN) !=
262 ETHER_ADDR_LEN ||
263 GEM_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_DATA + PCI_VPD_DATA +
264 ETHER_ADDR_LEN) != 0x79) {
265 device_printf(dev, "unexpected PCI VPD\n");
266 goto fail;
267 }
268 bus_read_region_1(sc->sc_res[0], GEM_PCI_ROM_OFFSET + j +
269 PCI_VPDRES_LARGE_DATA + PCI_VPD_DATA, sc->sc_enaddr,
270 ETHER_ADDR_LEN);
271#endif
272
273 /*
187 * call the main configure
188 */
189 if (gem_attach(sc) != 0) {
190 device_printf(dev, "could not be configured\n");
191 goto fail;
192 }
193
194 if (bus_setup_intr(dev, sc->sc_res[1], INTR_TYPE_NET | INTR_MPSAFE,
195 NULL, gem_intr, sc, &sc->sc_ih) != 0) {
196 device_printf(dev, "failed to set up interrupt\n");
197 gem_detach(sc);
198 goto fail;
199 }
200 return (0);
201
202fail:
274 * call the main configure
275 */
276 if (gem_attach(sc) != 0) {
277 device_printf(dev, "could not be configured\n");
278 goto fail;
279 }
280
281 if (bus_setup_intr(dev, sc->sc_res[1], INTR_TYPE_NET | INTR_MPSAFE,
282 NULL, gem_intr, sc, &sc->sc_ih) != 0) {
283 device_printf(dev, "failed to set up interrupt\n");
284 gem_detach(sc);
285 goto fail;
286 }
287 return (0);
288
289fail:
203 bus_release_resources(dev, gem_pci_res_spec, sc->sc_res);
204 GEM_LOCK_DESTROY(sc);
290 GEM_LOCK_DESTROY(sc);
291 bus_release_resources(dev, gem_pci_res_spec, sc->sc_res);
205 return (ENXIO);
206}
207
208static int
209gem_pci_detach(dev)
210 device_t dev;
211{
212 struct gem_softc *sc = device_get_softc(dev);

--- 27 unchanged lines hidden ---
292 return (ENXIO);
293}
294
295static int
296gem_pci_detach(dev)
297 device_t dev;
298{
299 struct gem_softc *sc = device_get_softc(dev);

--- 27 unchanged lines hidden ---