File: | dev/pci/if_gem_pci.c |
Warning: | line 252, column 3 Value stored to 'gotenaddr' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: if_gem_pci.c,v 1.40 2022/03/11 18:00:45 mpi Exp $ */ |
2 | /* $NetBSD: if_gem_pci.c,v 1.1 2001/09/16 00:11:42 eeh Exp $ */ |
3 | |
4 | /* |
5 | * |
6 | * Copyright (C) 2001 Eduardo Horvath. |
7 | * All rights reserved. |
8 | * |
9 | * |
10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions |
12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. |
18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND |
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 | * SUCH DAMAGE. |
30 | * |
31 | */ |
32 | |
33 | /* |
34 | * PCI bindings for Sun GEM ethernet controllers. |
35 | */ |
36 | |
37 | #include <sys/param.h> |
38 | #include <sys/systm.h> |
39 | #include <sys/malloc.h> |
40 | #include <sys/kernel.h> |
41 | #include <sys/socket.h> |
42 | #include <sys/errno.h> |
43 | #include <sys/device.h> |
44 | #include <sys/endian.h> |
45 | |
46 | #include <net/if.h> |
47 | #include <net/if_media.h> |
48 | |
49 | #include <netinet/in.h> |
50 | #include <netinet/if_ether.h> |
51 | |
52 | #include <machine/bus.h> |
53 | #include <machine/intr.h> |
54 | |
55 | #ifdef __sparc64__ |
56 | #include <dev/ofw/openfirm.h> |
57 | #endif |
58 | |
59 | #include <dev/mii/miivar.h> |
60 | #include <dev/mii/mii_bitbang.h> |
61 | |
62 | #include <dev/ic/gemreg.h> |
63 | #include <dev/ic/gemvar.h> |
64 | |
65 | #include <dev/pci/pcivar.h> |
66 | #include <dev/pci/pcireg.h> |
67 | #include <dev/pci/pcidevs.h> |
68 | |
69 | struct gem_pci_softc { |
70 | struct gem_softc gsc_gem; /* GEM device */ |
71 | bus_space_tag_t gsc_memt; |
72 | bus_space_handle_t gsc_memh; |
73 | bus_size_t gsc_memsize; |
74 | pci_chipset_tag_t gsc_pc; |
75 | }; |
76 | |
77 | int gem_match_pci(struct device *, void *, void *); |
78 | void gem_attach_pci(struct device *, struct device *, void *); |
79 | int gem_detach_pci(struct device *, int); |
80 | int gem_pci_enaddr(struct gem_softc *, struct pci_attach_args *); |
81 | |
82 | const struct cfattach gem_pci_ca = { |
83 | sizeof(struct gem_pci_softc), gem_match_pci, gem_attach_pci, |
84 | gem_detach_pci |
85 | }; |
86 | |
87 | /* |
88 | * Attach routines need to be split out to different bus-specific files. |
89 | */ |
90 | |
91 | const struct pci_matchid gem_pci_devices[] = { |
92 | { PCI_VENDOR_SUN0x108e, PCI_PRODUCT_SUN_ERINETWORK0x1101 }, |
93 | { PCI_VENDOR_SUN0x108e, PCI_PRODUCT_SUN_GEMNETWORK0x2bad }, |
94 | { PCI_VENDOR_APPLE0x106b, PCI_PRODUCT_APPLE_INTREPID2_GMAC0x006b }, |
95 | { PCI_VENDOR_APPLE0x106b, PCI_PRODUCT_APPLE_K2_GMAC0x004c }, |
96 | { PCI_VENDOR_APPLE0x106b, PCI_PRODUCT_APPLE_PANGEA_GMAC0x0024 }, |
97 | { PCI_VENDOR_APPLE0x106b, PCI_PRODUCT_APPLE_SHASTA_GMAC0x0051 }, |
98 | { PCI_VENDOR_APPLE0x106b, PCI_PRODUCT_APPLE_UNINORTHGMAC0x0021 }, |
99 | { PCI_VENDOR_APPLE0x106b, PCI_PRODUCT_APPLE_UNINORTH2GMAC0x0032 }, |
100 | }; |
101 | |
102 | int |
103 | gem_match_pci(struct device *parent, void *cf, void *aux) |
104 | { |
105 | return (pci_matchbyid((struct pci_attach_args *)aux, gem_pci_devices, |
106 | nitems(gem_pci_devices)(sizeof((gem_pci_devices)) / sizeof((gem_pci_devices)[0])))); |
107 | } |
108 | |
109 | #define PROMHDR_PTR_DATA0x18 0x18 |
110 | #define PROMDATA_PTR_VPD0x08 0x08 |
111 | #define PROMDATA_DATA20x0a 0x0a |
112 | |
113 | static const u_int8_t gem_promhdr[] = { 0x55, 0xaa }; |
114 | static const u_int8_t gem_promdat[] = { |
115 | 'P', 'C', 'I', 'R', |
116 | PCI_VENDOR_SUN0x108e & 0xff, PCI_VENDOR_SUN0x108e >> 8, |
117 | PCI_PRODUCT_SUN_GEMNETWORK0x2bad & 0xff, PCI_PRODUCT_SUN_GEMNETWORK0x2bad >> 8 |
118 | }; |
119 | |
120 | static const u_int8_t gem_promdat2[] = { |
121 | 0x18, 0x00, /* structure length */ |
122 | 0x00, /* structure revision */ |
123 | 0x00, /* interface revision */ |
124 | PCI_SUBCLASS_NETWORK_ETHERNET0x00, /* subclass code */ |
125 | PCI_CLASS_NETWORK0x02 /* class code */ |
126 | }; |
127 | |
128 | int |
129 | gem_pci_enaddr(struct gem_softc *sc, struct pci_attach_args *pa) |
130 | { |
131 | struct pci_vpd *vpd; |
132 | bus_space_handle_t romh; |
133 | bus_space_tag_t romt; |
134 | bus_size_t romsize = 0; |
135 | u_int8_t buf[32]; |
136 | pcireg_t address; |
137 | int dataoff, vpdoff; |
138 | int rv = -1; |
139 | |
140 | if (pci_mapreg_map(pa, PCI_ROM_REG0x30, PCI_MAPREG_TYPE_MEM0x00000000, 0, |
141 | &romt, &romh, 0, &romsize, 0)) |
142 | return (-1); |
143 | |
144 | address = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG0x30); |
145 | address |= PCI_ROM_ENABLE0x00000001; |
146 | pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG0x30, address); |
147 | |
148 | bus_space_read_region_1(romt, romh, 0, buf, sizeof(buf))((romt)->read_region_1((romh), (0), (buf), (sizeof(buf)))); |
149 | if (bcmp(buf, gem_promhdr, sizeof(gem_promhdr))) |
150 | goto fail; |
151 | |
152 | dataoff = buf[PROMHDR_PTR_DATA0x18] | (buf[PROMHDR_PTR_DATA0x18 + 1] << 8); |
153 | if (dataoff < 0x1c) |
154 | goto fail; |
155 | |
156 | bus_space_read_region_1(romt, romh, dataoff, buf, sizeof(buf))((romt)->read_region_1((romh), (dataoff), (buf), (sizeof(buf )))); |
157 | if (bcmp(buf, gem_promdat, sizeof(gem_promdat)) || |
158 | bcmp(buf + PROMDATA_DATA20x0a, gem_promdat2, sizeof(gem_promdat2))) |
159 | goto fail; |
160 | |
161 | vpdoff = buf[PROMDATA_PTR_VPD0x08] | (buf[PROMDATA_PTR_VPD0x08 + 1] << 8); |
162 | if (vpdoff < 0x1c) |
163 | goto fail; |
164 | |
165 | bus_space_read_region_1(romt, romh, vpdoff, buf, sizeof(buf))((romt)->read_region_1((romh), (vpdoff), (buf), (sizeof(buf )))); |
166 | |
167 | /* |
168 | * The VPD of gem is not in PCI 2.2 standard format. The length |
169 | * in the resource header is in big endian. |
170 | */ |
171 | vpd = (struct pci_vpd *)(buf + 3); |
172 | if (!PCI_VPDRES_ISLARGE(buf[0])((buf[0]) & 0x80) || |
173 | PCI_VPDRES_LARGE_NAME(buf[0])((buf[0]) & 0x7f) != PCI_VPDRES_TYPE_VPD0x10) |
174 | goto fail; |
175 | if (vpd->vpd_key0 != 'N' || vpd->vpd_key1 != 'A') |
176 | goto fail; |
177 | |
178 | bcopy(buf + 6, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN6); |
179 | rv = 0; |
180 | |
181 | fail: |
182 | if (romsize != 0) |
183 | bus_space_unmap(romt, romh, romsize); |
184 | |
185 | address = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG0x30); |
186 | address &= ~PCI_ROM_ENABLE0x00000001; |
187 | pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG0x30, address); |
188 | |
189 | return (rv); |
190 | } |
191 | |
192 | void |
193 | gem_attach_pci(struct device *parent, struct device *self, void *aux) |
194 | { |
195 | struct pci_attach_args *pa = aux; |
196 | struct gem_pci_softc *gsc = (void *)self; |
197 | struct gem_softc *sc = &gsc->gsc_gem; |
198 | pci_intr_handle_t ih; |
199 | #ifdef __sparc64__ |
200 | /* XXX the following declarations should be elsewhere */ |
201 | extern void myetheraddr(u_char *); |
202 | #endif |
203 | const char *intrstr = NULL((void *)0); |
204 | int type, gotenaddr = 0; |
205 | |
206 | gsc->gsc_pc = pa->pa_pc; |
207 | |
208 | if (pa->pa_memt) { |
209 | type = PCI_MAPREG_TYPE_MEM0x00000000; |
210 | sc->sc_bustag = pa->pa_memt; |
211 | } else { |
212 | type = PCI_MAPREG_TYPE_IO0x00000001; |
213 | sc->sc_bustag = pa->pa_iot; |
214 | } |
215 | |
216 | sc->sc_dmatag = pa->pa_dmat; |
217 | |
218 | sc->sc_pci = 1; /* XXXXX should all be done in bus_dma. */ |
219 | |
220 | switch (PCI_PRODUCT(pa->pa_id)(((pa->pa_id) >> 16) & 0xffff)) { |
221 | case PCI_PRODUCT_SUN_GEMNETWORK0x2bad: |
222 | sc->sc_variant = GEM_SUN_GEM1; |
223 | break; |
224 | case PCI_PRODUCT_SUN_ERINETWORK0x1101: |
225 | sc->sc_variant = GEM_SUN_ERI2; |
226 | break; |
227 | case PCI_PRODUCT_APPLE_K2_GMAC0x004c: |
228 | sc->sc_variant = GEM_APPLE_K2_GMAC4; |
229 | break; |
230 | default: |
231 | sc->sc_variant = GEM_APPLE_GMAC3; |
232 | } |
233 | |
234 | #define PCI_GEM_BASEADDR0x10 0x10 |
235 | if (pci_mapreg_map(pa, PCI_GEM_BASEADDR0x10, type, 0, |
236 | &gsc->gsc_memt, &gsc->gsc_memh, NULL((void *)0), &gsc->gsc_memsize, 0) != 0) { |
237 | printf(": can't map registers\n"); |
238 | return; |
239 | } |
240 | |
241 | sc->sc_bustag = gsc->gsc_memt; |
242 | sc->sc_h1 = gsc->gsc_memh; |
243 | |
244 | if (bus_space_subregion(sc->sc_bustag, sc->sc_h1, |
245 | GEM_PCI_BANK2_OFFSET0x1000, GEM_PCI_BANK2_SIZE0x14, &sc->sc_h2)) { |
246 | printf(": unable to create bank 2 subregion\n"); |
247 | bus_space_unmap(gsc->gsc_memt, gsc->gsc_memh, gsc->gsc_memsize); |
248 | return; |
249 | } |
250 | |
251 | if (gem_pci_enaddr(sc, pa) == 0) |
252 | gotenaddr = 1; |
Value stored to 'gotenaddr' is never read | |
253 | |
254 | #ifdef __sparc64__ |
255 | if (!gotenaddr) { |
256 | if (OF_getprop(PCITAG_NODE(pa->pa_tag), "local-mac-address", |
257 | sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN6) <= 0) |
258 | myetheraddr(sc->sc_arpcom.ac_enaddr); |
259 | gotenaddr = 1; |
260 | } |
261 | #endif |
262 | #ifdef __powerpc__ |
263 | if (!gotenaddr) { |
264 | pci_ether_hw_addr(pa->pa_pc, sc->sc_arpcom.ac_enaddr); |
265 | gotenaddr = 1; |
266 | } |
267 | #endif |
268 | |
269 | sc->sc_burst = 16; /* XXX */ |
270 | |
271 | if (pci_intr_map(pa, &ih) != 0) { |
272 | printf(": couldn't map interrupt\n"); |
273 | bus_space_unmap(gsc->gsc_memt, gsc->gsc_memh, gsc->gsc_memsize); |
274 | return; |
275 | } |
276 | intrstr = pci_intr_string(pa->pa_pc, ih); |
277 | sc->sc_ih = pci_intr_establish(pa->pa_pc, |
278 | ih, IPL_NET0x4 | IPL_MPSAFE0x100, gem_intr, sc, self->dv_xname); |
279 | if (sc->sc_ih == NULL((void *)0)) { |
280 | printf(": couldn't establish interrupt"); |
281 | if (intrstr != NULL((void *)0)) |
282 | printf(" at %s", intrstr); |
283 | printf("\n"); |
284 | bus_space_unmap(gsc->gsc_memt, gsc->gsc_memh, gsc->gsc_memsize); |
285 | return; |
286 | } |
287 | |
288 | printf(": %s", intrstr); |
289 | |
290 | /* |
291 | * call the main configure |
292 | */ |
293 | gem_config(sc); |
294 | } |
295 | |
296 | int |
297 | gem_detach_pci(struct device *self, int flags) |
298 | { |
299 | struct gem_pci_softc *gsc = (void *)self; |
300 | struct gem_softc *sc = &gsc->gsc_gem; |
301 | |
302 | timeout_del(&sc->sc_tick_ch); |
303 | timeout_del(&sc->sc_rx_watchdog); |
304 | |
305 | gem_unconfig(sc); |
306 | pci_intr_disestablish(gsc->gsc_pc, sc->sc_ih); |
307 | bus_space_unmap(gsc->gsc_memt, gsc->gsc_memh, gsc->gsc_memsize); |
308 | |
309 | return (0); |
310 | } |