File: | dev/pci/if_hme_pci.c |
Warning: | line 260, column 3 Value stored to 'gotenaddr' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: if_hme_pci.c,v 1.23 2021/03/05 12:40:13 jsg Exp $ */ |
2 | /* $NetBSD: if_hme_pci.c,v 1.3 2000/12/28 22:59:13 sommerfeld Exp $ */ |
3 | |
4 | /* |
5 | * Copyright (c) 2000 Matthew R. Green |
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 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
22 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
24 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
25 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
27 | * SUCH DAMAGE. |
28 | */ |
29 | |
30 | /* |
31 | * PCI front-end device driver for the HME ethernet device. |
32 | */ |
33 | |
34 | #include <sys/param.h> |
35 | #include <sys/systm.h> |
36 | #include <sys/syslog.h> |
37 | #include <sys/device.h> |
38 | #include <sys/malloc.h> |
39 | #include <sys/socket.h> |
40 | |
41 | #include <net/if.h> |
42 | #include <net/if_media.h> |
43 | |
44 | #include <netinet/in.h> |
45 | #include <netinet/if_ether.h> |
46 | |
47 | #include <dev/mii/miivar.h> |
48 | |
49 | #ifdef __sparc64__ |
50 | #include <machine/autoconf.h> |
51 | #include <dev/ofw/openfirm.h> |
52 | #endif |
53 | #include <machine/cpu.h> |
54 | |
55 | #include <dev/pci/pcivar.h> |
56 | #include <dev/pci/pcireg.h> |
57 | #include <dev/pci/pcidevs.h> |
58 | |
59 | #include <dev/ic/hmevar.h> |
60 | |
61 | struct hme_pci_softc { |
62 | struct hme_softc hsc_hme; /* HME device */ |
63 | bus_space_tag_t hsc_memt; |
64 | bus_space_handle_t hsc_memh; |
65 | bus_size_t hsc_memsize; |
66 | void *hsc_ih; |
67 | pci_chipset_tag_t hsc_pc; |
68 | }; |
69 | |
70 | int hmematch_pci(struct device *, void *, void *); |
71 | void hmeattach_pci(struct device *, struct device *, void *); |
72 | int hmedetach_pci(struct device *, int); |
73 | int hme_pci_enaddr(struct hme_softc *, struct pci_attach_args *); |
74 | |
75 | struct cfattach hme_pci_ca = { |
76 | sizeof(struct hme_pci_softc), hmematch_pci, hmeattach_pci, hmedetach_pci |
77 | }; |
78 | |
79 | int |
80 | hmematch_pci(struct device *parent, void *vcf, void *aux) |
81 | { |
82 | struct pci_attach_args *pa = aux; |
83 | |
84 | if (PCI_VENDOR(pa->pa_id)(((pa->pa_id) >> 0) & 0xffff) == PCI_VENDOR_SUN0x108e && |
85 | PCI_PRODUCT(pa->pa_id)(((pa->pa_id) >> 16) & 0xffff) == PCI_PRODUCT_SUN_HME0x1001) |
86 | return (1); |
87 | |
88 | return (0); |
89 | } |
90 | |
91 | #define PCI_EBUS2_BOOTROM0x10 0x10 |
92 | #define PCI_EBUS2_BOOTROM_SIZE0x20000 0x20000 |
93 | #define PROMHDR_PTR_DATA0x18 0x18 |
94 | #define PROMDATA_PTR_VPD0x08 0x08 |
95 | #define PROMDATA_LENGTH0x0a 0x0a |
96 | #define PROMDATA_REVISION0x0c 0x0c |
97 | #define PROMDATA_SUBCLASS0x0e 0x0e |
98 | #define PROMDATA_CLASS0x0f 0x0f |
99 | |
100 | static const u_int8_t hme_promhdr[] = { 0x55, 0xaa }; |
101 | static const u_int8_t hme_promdat[] = { |
102 | 'P', 'C', 'I', 'R', |
103 | PCI_VENDOR_SUN0x108e & 0xff, PCI_VENDOR_SUN0x108e >> 8, |
104 | PCI_PRODUCT_SUN_HME0x1001 & 0xff, PCI_PRODUCT_SUN_HME0x1001 >> 8 |
105 | }; |
106 | |
107 | int |
108 | hme_pci_enaddr(struct hme_softc *sc, struct pci_attach_args *hpa) |
109 | { |
110 | struct pci_attach_args epa; |
111 | struct pci_vpd *vpd; |
112 | pcireg_t cl, id; |
113 | bus_space_handle_t romh; |
114 | bus_space_tag_t romt; |
115 | bus_size_t romsize = 0; |
116 | u_int8_t buf[32]; |
117 | int dataoff, vpdoff, length; |
118 | |
119 | /* |
120 | * Dig out VPD (vital product data) and acquire Ethernet address. |
121 | * The VPD of hme resides in the Boot PROM (PCI FCode) attached |
122 | * to the EBus interface. |
123 | * ``Writing FCode 3.x Programs'' (newer ones, dated 1997 and later) |
124 | * chapter 2 describes the data structure. |
125 | */ |
126 | |
127 | /* get a PCI tag for the EBus bridge (function 0 of the same device) */ |
128 | epa = *hpa; |
129 | epa.pa_tag = pci_make_tag(hpa->pa_pc, hpa->pa_bus, hpa->pa_device, 0); |
130 | cl = pci_conf_read(epa.pa_pc, epa.pa_tag, PCI_CLASS_REG0x08); |
131 | id = pci_conf_read(epa.pa_pc, epa.pa_tag, PCI_ID_REG0x00); |
132 | |
133 | if (PCI_CLASS(cl)(((cl) >> 24) & 0xff) != PCI_CLASS_BRIDGE0x06 || |
134 | PCI_PRODUCT(id)(((id) >> 16) & 0xffff) != PCI_PRODUCT_SUN_EBUS0x1000) |
135 | goto fail; |
136 | |
137 | if (pci_mapreg_map(&epa, PCI_EBUS2_BOOTROM0x10, PCI_MAPREG_TYPE_MEM0x00000000, 0, |
138 | &romt, &romh, 0, &romsize, PCI_EBUS2_BOOTROM_SIZE0x20000)) |
139 | goto fail; |
140 | |
141 | bus_space_read_region_1(romt, romh, 0, buf, sizeof(buf))((romt)->read_region_1((romh), (0), (buf), (sizeof(buf)))); |
142 | if (bcmp(buf, hme_promhdr, sizeof(hme_promhdr))) |
143 | goto fail; |
144 | |
145 | dataoff = buf[PROMHDR_PTR_DATA0x18] | (buf[PROMHDR_PTR_DATA0x18 + 1] << 8); |
146 | if (dataoff < 0x1c) |
147 | goto fail; |
148 | |
149 | bus_space_read_region_1(romt, romh, dataoff, buf, sizeof(buf))((romt)->read_region_1((romh), (dataoff), (buf), (sizeof(buf )))); |
150 | if (bcmp(buf, hme_promdat, sizeof(hme_promdat))) |
151 | goto fail; |
152 | |
153 | /* |
154 | * Don't check the interface part of the class code, since |
155 | * some cards have a bogus value there. |
156 | */ |
157 | length = buf[PROMDATA_LENGTH0x0a] | (buf[PROMDATA_LENGTH0x0a + 1] << 8); |
158 | if (length != 0x18 || buf[PROMDATA_REVISION0x0c] != 0x00 || |
159 | buf[PROMDATA_SUBCLASS0x0e] != PCI_SUBCLASS_NETWORK_ETHERNET0x00 || |
160 | buf[PROMDATA_CLASS0x0f] != PCI_CLASS_NETWORK0x02) |
161 | goto fail; |
162 | |
163 | vpdoff = buf[PROMDATA_PTR_VPD0x08] | (buf[PROMDATA_PTR_VPD0x08 + 1] << 8); |
164 | if (vpdoff < 0x1c) |
165 | goto fail; |
166 | |
167 | /* |
168 | * The VPD of hme is not in PCI 2.2 standard format. The length |
169 | * in the resource header is in big endian, and resources are not |
170 | * properly terminated (only one resource and no end tag). |
171 | */ |
172 | bus_space_read_region_1(romt, romh, vpdoff, buf, sizeof(buf))((romt)->read_region_1((romh), (vpdoff), (buf), (sizeof(buf )))); |
173 | |
174 | /* XXX TODO: Get the data from VPD */ |
175 | vpd = (struct pci_vpd *)(buf + 3); |
176 | if (!PCI_VPDRES_ISLARGE(buf[0])((buf[0]) & 0x80) || |
177 | PCI_VPDRES_LARGE_NAME(buf[0])((buf[0]) & 0x7f) != PCI_VPDRES_TYPE_VPD0x10) |
178 | goto fail; |
179 | if (vpd->vpd_key0 != 'N' || vpd->vpd_key1 != 'A') |
180 | goto fail; |
181 | |
182 | bcopy(buf + 6, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN6); |
183 | sc->sc_arpcom.ac_enaddr[5] += hpa->pa_device; |
184 | bus_space_unmap(romt, romh, romsize); |
185 | return (0); |
186 | |
187 | fail: |
188 | if (romsize != 0) |
189 | bus_space_unmap(romt, romh, romsize); |
190 | return (-1); |
191 | } |
192 | |
193 | void |
194 | hmeattach_pci(struct device *parent, struct device *self, void *aux) |
195 | { |
196 | struct pci_attach_args *pa = aux; |
197 | struct hme_pci_softc *hsc = (void *)self; |
198 | struct hme_softc *sc = &hsc->hsc_hme; |
199 | pci_intr_handle_t ih; |
200 | /* XXX the following declarations should be elsewhere */ |
201 | extern void myetheraddr(u_char *); |
202 | pcireg_t csr; |
203 | const char *intrstr = NULL((void *)0); |
204 | int type, gotenaddr = 0; |
205 | |
206 | hsc->hsc_pc = pa->pa_pc; |
207 | |
208 | /* |
209 | * enable io/memory-space accesses. this is kinda of gross; but |
210 | * the hme comes up with neither IO space enabled, or memory space. |
211 | */ |
212 | if (pa->pa_memt) |
213 | pa->pa_flags |= PCI_FLAGS_MEM_ENABLED0x02; |
214 | if (pa->pa_iot) |
215 | pa->pa_flags |= PCI_FLAGS_IO_ENABLED0x01; |
216 | csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG0x04); |
217 | if (pa->pa_memt) { |
218 | type = PCI_MAPREG_TYPE_MEM0x00000000; |
219 | csr |= PCI_COMMAND_MEM_ENABLE0x00000002; |
220 | sc->sc_bustag = pa->pa_memt; |
221 | } else { |
222 | type = PCI_MAPREG_TYPE_IO0x00000001; |
223 | csr |= PCI_COMMAND_IO_ENABLE0x00000001; |
224 | sc->sc_bustag = pa->pa_iot; |
225 | } |
226 | pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG0x04, |
227 | csr | PCI_COMMAND_MEM_ENABLE0x00000002); |
228 | |
229 | sc->sc_dmatag = pa->pa_dmat; |
230 | |
231 | sc->sc_pci = 1; /* XXXXX should all be done in bus_dma. */ |
232 | /* |
233 | * Map five register banks: |
234 | * |
235 | * bank 0: HME SEB registers: +0x0000 |
236 | * bank 1: HME ETX registers: +0x2000 |
237 | * bank 2: HME ERX registers: +0x4000 |
238 | * bank 3: HME MAC registers: +0x6000 |
239 | * bank 4: HME MIF registers: +0x7000 |
240 | * |
241 | */ |
242 | |
243 | #define PCI_HME_BASEADDR0x10 0x10 |
244 | if (pci_mapreg_map(pa, PCI_HME_BASEADDR0x10, type, 0, |
245 | &hsc->hsc_memt, &hsc->hsc_memh, NULL((void *)0), &hsc->hsc_memsize, 0) != 0) { |
246 | printf(": can't map registers\n"); |
247 | return; |
248 | } |
249 | sc->sc_seb = hsc->hsc_memh; |
250 | bus_space_subregion(sc->sc_bustag, hsc->hsc_memh, 0x2000, 0x2000, |
251 | &sc->sc_etx); |
252 | bus_space_subregion(sc->sc_bustag, hsc->hsc_memh, 0x4000, 0x2000, |
253 | &sc->sc_erx); |
254 | bus_space_subregion(sc->sc_bustag, hsc->hsc_memh, 0x6000, 0x1000, |
255 | &sc->sc_mac); |
256 | bus_space_subregion(sc->sc_bustag, hsc->hsc_memh, 0x7000, 0x1000, |
257 | &sc->sc_mif); |
258 | |
259 | if (hme_pci_enaddr(sc, pa) == 0) |
260 | gotenaddr = 1; |
Value stored to 'gotenaddr' is never read | |
261 | |
262 | #ifdef __sparc64__ |
263 | if (!gotenaddr) { |
264 | if (OF_getprop(PCITAG_NODE(pa->pa_tag), "local-mac-address", |
265 | sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN6) <= 0) |
266 | myetheraddr(sc->sc_arpcom.ac_enaddr); |
267 | gotenaddr = 1; |
268 | } |
269 | #endif |
270 | #ifdef __powerpc__ |
271 | if (!gotenaddr) { |
272 | pci_ether_hw_addr(pa->pa_pc, sc->sc_arpcom.ac_enaddr); |
273 | gotenaddr = 1; |
274 | } |
275 | #endif |
276 | |
277 | sc->sc_burst = 16; /* XXX */ |
278 | |
279 | if (pci_intr_map(pa, &ih) != 0) { |
280 | printf(": couldn't map interrupt\n"); |
281 | bus_space_unmap(hsc->hsc_memt, hsc->hsc_memh, hsc->hsc_memsize); |
282 | return; |
283 | } |
284 | intrstr = pci_intr_string(pa->pa_pc, ih); |
285 | hsc->hsc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET0x7, |
286 | hme_intr, sc, self->dv_xname); |
287 | if (hsc->hsc_ih == NULL((void *)0)) { |
288 | printf(": couldn't establish interrupt"); |
289 | if (intrstr != NULL((void *)0)) |
290 | printf(" at %s", intrstr); |
291 | printf("\n"); |
292 | bus_space_unmap(hsc->hsc_memt, hsc->hsc_memh, hsc->hsc_memsize); |
293 | return; |
294 | } |
295 | |
296 | printf(": %s", intrstr); |
297 | |
298 | /* |
299 | * call the main configure |
300 | */ |
301 | hme_config(sc); |
302 | } |
303 | |
304 | int |
305 | hmedetach_pci(struct device *self, int flags) |
306 | { |
307 | struct hme_pci_softc *hsc = (void *)self; |
308 | struct hme_softc *sc = &hsc->hsc_hme; |
309 | |
310 | timeout_del(&sc->sc_tick_ch); |
311 | pci_intr_disestablish(hsc->hsc_pc, hsc->hsc_ih); |
312 | |
313 | hme_unconfig(sc); |
314 | bus_space_unmap(hsc->hsc_memt, hsc->hsc_memh, hsc->hsc_memsize); |
315 | return (0); |
316 | } |