| 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.24 2022/03/11 18:00:45 mpi 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 | const 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_NET0x4, |
| 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 | } |