1/*- 2 * Copyright (c) 2000 Matthew R. Green 3 * Copyright (c) 2007 Marius Strobl <marius@FreeBSD.org> 4 * All rights reserved. 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: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 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 * from: NetBSD: if_hme_pci.c,v 1.14 2004/03/17 08:58:23 martin Exp 30 */ 31 32#include <sys/cdefs.h> 33__FBSDID("$FreeBSD: releng/10.2/sys/dev/hme/if_hme_pci.c 227843 2011-11-22 21:28:20Z marius $"); 34 35/* 36 * PCI front-end device driver for the HME ethernet device. 37 */ 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/bus.h> 42#include <sys/kernel.h> 43#include <sys/module.h> 44#include <sys/resource.h> 45#include <sys/socket.h> 46 47#include <machine/bus.h> 48#if defined(__powerpc__) || defined(__sparc64__) 49#include <dev/ofw/openfirm.h> 50#include <machine/ofw_machdep.h> 51#endif 52#include <machine/resource.h> 53 54#include <sys/rman.h> 55 56#include <net/ethernet.h> 57#include <net/if.h> 58#include <net/if_arp.h> 59#include <net/if_dl.h> 60#include <net/if_media.h> 61 62#include <dev/mii/mii.h> 63#include <dev/mii/miivar.h> 64 65#include <dev/pci/pcivar.h> 66#include <dev/pci/pcireg.h> 67 68#include <dev/hme/if_hmereg.h> 69#include <dev/hme/if_hmevar.h> 70 71#include "miibus_if.h" 72 73struct hme_pci_softc { 74 struct hme_softc hsc_hme; /* HME device */ 75 struct resource *hsc_sres; 76 struct resource *hsc_ires; 77 void *hsc_ih; 78}; 79 80static int hme_pci_probe(device_t); 81static int hme_pci_attach(device_t); 82static int hme_pci_detach(device_t); 83static int hme_pci_suspend(device_t); 84static int hme_pci_resume(device_t); 85 86static device_method_t hme_pci_methods[] = { 87 /* Device interface */ 88 DEVMETHOD(device_probe, hme_pci_probe), 89 DEVMETHOD(device_attach, hme_pci_attach), 90 DEVMETHOD(device_detach, hme_pci_detach), 91 DEVMETHOD(device_suspend, hme_pci_suspend), 92 DEVMETHOD(device_resume, hme_pci_resume), 93 /* Can just use the suspend method here. */ 94 DEVMETHOD(device_shutdown, hme_pci_suspend), 95 96 /* MII interface */ 97 DEVMETHOD(miibus_readreg, hme_mii_readreg), 98 DEVMETHOD(miibus_writereg, hme_mii_writereg), 99 DEVMETHOD(miibus_statchg, hme_mii_statchg), 100 101 DEVMETHOD_END 102}; 103 104static driver_t hme_pci_driver = { 105 "hme", 106 hme_pci_methods, 107 sizeof(struct hme_pci_softc) 108}; 109 110DRIVER_MODULE(hme, pci, hme_pci_driver, hme_devclass, 0, 0); 111MODULE_DEPEND(hme, pci, 1, 1, 1); 112MODULE_DEPEND(hme, ether, 1, 1, 1); 113 114#define PCI_VENDOR_SUN 0x108e 115#define PCI_PRODUCT_SUN_EBUS 0x1000 116#define PCI_PRODUCT_SUN_HMENETWORK 0x1001 117 118int 119hme_pci_probe(device_t dev) 120{ 121 122 if (pci_get_vendor(dev) == PCI_VENDOR_SUN && 123 pci_get_device(dev) == PCI_PRODUCT_SUN_HMENETWORK) { 124 device_set_desc(dev, "Sun HME 10/100 Ethernet"); 125 return (BUS_PROBE_DEFAULT); 126 } 127 return (ENXIO); 128} 129 130int 131hme_pci_attach(device_t dev) 132{ 133 struct hme_pci_softc *hsc; 134 struct hme_softc *sc; 135 bus_space_tag_t memt; 136 bus_space_handle_t memh; 137 int i, error = 0; 138#if !(defined(__powerpc__) || defined(__sparc64__)) 139 device_t *children, ebus_dev; 140 struct resource *ebus_rres; 141 int j, slot; 142#endif 143 144 pci_enable_busmaster(dev); 145 /* 146 * Some Sun HMEs do have their intpin register bogusly set to 0, 147 * although it should be 1. Correct that. 148 */ 149 if (pci_get_intpin(dev) == 0) 150 pci_set_intpin(dev, 1); 151 152 hsc = device_get_softc(dev); 153 sc = &hsc->hsc_hme; 154 sc->sc_dev = dev; 155 sc->sc_flags |= HME_PCI; 156 mtx_init(&sc->sc_lock, device_get_nameunit(dev), MTX_NETWORK_LOCK, 157 MTX_DEF); 158 159 /* 160 * Map five register banks: 161 * 162 * bank 0: HME SEB registers: +0x0000 163 * bank 1: HME ETX registers: +0x2000 164 * bank 2: HME ERX registers: +0x4000 165 * bank 3: HME MAC registers: +0x6000 166 * bank 4: HME MIF registers: +0x7000 167 * 168 */ 169 i = PCIR_BAR(0); 170 hsc->hsc_sres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 171 &i, RF_ACTIVE); 172 if (hsc->hsc_sres == NULL) { 173 device_printf(dev, "could not map device registers\n"); 174 error = ENXIO; 175 goto fail_mtx; 176 } 177 i = 0; 178 hsc->hsc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, 179 &i, RF_SHAREABLE | RF_ACTIVE); 180 if (hsc->hsc_ires == NULL) { 181 device_printf(dev, "could not allocate interrupt\n"); 182 error = ENXIO; 183 goto fail_sres; 184 } 185 memt = rman_get_bustag(hsc->hsc_sres); 186 memh = rman_get_bushandle(hsc->hsc_sres); 187 sc->sc_sebt = sc->sc_etxt = sc->sc_erxt = sc->sc_mact = sc->sc_mift = 188 memt; 189 bus_space_subregion(memt, memh, 0x0000, 0x1000, &sc->sc_sebh); 190 bus_space_subregion(memt, memh, 0x2000, 0x1000, &sc->sc_etxh); 191 bus_space_subregion(memt, memh, 0x4000, 0x1000, &sc->sc_erxh); 192 bus_space_subregion(memt, memh, 0x6000, 0x1000, &sc->sc_mach); 193 bus_space_subregion(memt, memh, 0x7000, 0x1000, &sc->sc_mifh); 194 195#if defined(__powerpc__) || defined(__sparc64__) 196 OF_getetheraddr(dev, sc->sc_enaddr); 197#else 198 /* 199 * Dig out VPD (vital product data) and read NA (network address). 200 * 201 * The PCI HME is a PCIO chip, which is composed of two functions: 202 * function 0: PCI-EBus2 bridge, and 203 * function 1: HappyMeal Ethernet controller. 204 * 205 * The VPD of HME resides in the Boot PROM (PCI FCode) attached 206 * to the EBus bridge and can't be accessed via the PCI capability 207 * pointer. 208 * ``Writing FCode 3.x Programs'' (newer ones, dated 1997 and later) 209 * chapter 2 describes the data structure. 210 * 211 * We don't have a MI EBus driver since no EBus device exists 212 * (besides the FCode PROM) on add-on HME boards. The ``no driver 213 * attached'' message for function 0 therefore is what is expected. 214 */ 215 216#define PCI_ROMHDR_SIZE 0x1c 217#define PCI_ROMHDR_SIG 0x00 218#define PCI_ROMHDR_SIG_MAGIC 0xaa55 /* little endian */ 219#define PCI_ROMHDR_PTR_DATA 0x18 220#define PCI_ROM_SIZE 0x18 221#define PCI_ROM_SIG 0x00 222#define PCI_ROM_SIG_MAGIC 0x52494350 /* "PCIR", endian */ 223 /* reversed */ 224#define PCI_ROM_VENDOR 0x04 225#define PCI_ROM_DEVICE 0x06 226#define PCI_ROM_PTR_VPD 0x08 227#define PCI_VPDRES_BYTE0 0x00 228#define PCI_VPDRES_ISLARGE(x) ((x) & 0x80) 229#define PCI_VPDRES_LARGE_NAME(x) ((x) & 0x7f) 230#define PCI_VPDRES_TYPE_VPD 0x10 /* large */ 231#define PCI_VPDRES_LARGE_LEN_LSB 0x01 232#define PCI_VPDRES_LARGE_LEN_MSB 0x02 233#define PCI_VPDRES_LARGE_DATA 0x03 234#define PCI_VPD_SIZE 0x03 235#define PCI_VPD_KEY0 0x00 236#define PCI_VPD_KEY1 0x01 237#define PCI_VPD_LEN 0x02 238#define PCI_VPD_DATA 0x03 239 240#define HME_ROM_READ_N(n, offs) bus_space_read_ ## n (memt, memh, (offs)) 241#define HME_ROM_READ_1(offs) HME_ROM_READ_N(1, (offs)) 242#define HME_ROM_READ_2(offs) HME_ROM_READ_N(2, (offs)) 243#define HME_ROM_READ_4(offs) HME_ROM_READ_N(4, (offs)) 244 245 /* Search accompanying EBus bridge. */ 246 slot = pci_get_slot(dev); 247 if (device_get_children(device_get_parent(dev), &children, &i) != 0) { 248 device_printf(dev, "could not get children\n"); 249 error = ENXIO; 250 goto fail_sres; 251 } 252 ebus_dev = NULL; 253 for (j = 0; j < i; j++) { 254 if (pci_get_class(children[j]) == PCIC_BRIDGE && 255 pci_get_vendor(children[j]) == PCI_VENDOR_SUN && 256 pci_get_device(children[j]) == PCI_PRODUCT_SUN_EBUS && 257 pci_get_slot(children[j]) == slot) { 258 ebus_dev = children[j]; 259 break; 260 } 261 } 262 if (ebus_dev == NULL) { 263 device_printf(dev, "could not find EBus bridge\n"); 264 error = ENXIO; 265 goto fail_children; 266 } 267 268 /* Map EBus bridge PROM registers. */ 269 i = PCIR_BAR(0); 270 if ((ebus_rres = bus_alloc_resource_any(ebus_dev, SYS_RES_MEMORY, 271 &i, RF_ACTIVE)) == NULL) { 272 device_printf(dev, "could not map PROM registers\n"); 273 error = ENXIO; 274 goto fail_children; 275 } 276 memt = rman_get_bustag(ebus_rres); 277 memh = rman_get_bushandle(ebus_rres); 278 279 /* Read PCI Expansion ROM header. */ 280 if (HME_ROM_READ_2(PCI_ROMHDR_SIG) != PCI_ROMHDR_SIG_MAGIC || 281 (i = HME_ROM_READ_2(PCI_ROMHDR_PTR_DATA)) < PCI_ROMHDR_SIZE) { 282 device_printf(dev, "unexpected PCI Expansion ROM header\n"); 283 error = ENXIO; 284 goto fail_rres; 285 } 286 287 /* Read PCI Expansion ROM data. */ 288 if (HME_ROM_READ_4(i + PCI_ROM_SIG) != PCI_ROM_SIG_MAGIC || 289 HME_ROM_READ_2(i + PCI_ROM_VENDOR) != pci_get_vendor(dev) || 290 HME_ROM_READ_2(i + PCI_ROM_DEVICE) != pci_get_device(dev) || 291 (j = HME_ROM_READ_2(i + PCI_ROM_PTR_VPD)) < i + PCI_ROM_SIZE) { 292 device_printf(dev, "unexpected PCI Expansion ROM data\n"); 293 error = ENXIO; 294 goto fail_rres; 295 } 296 297 /* 298 * Read PCI VPD. 299 * SUNW,hme cards have a single large resource VPD-R tag 300 * containing one NA. SUNW,qfe cards have four large resource 301 * VPD-R tags containing one NA each (all four HME chips share 302 * the same PROM). 303 * The VPD used on both cards is not in PCI 2.2 standard format 304 * however. The length in the resource header is in big endian 305 * and the end tag is non-standard (0x79) and followed by an 306 * all-zero "checksum" byte. Sun calls this a "Fresh Choice 307 * Ethernet" VPD... 308 */ 309 /* Look at the end tag to determine whether this is a VPD with 4 NAs. */ 310 if (HME_ROM_READ_1(j + PCI_VPDRES_LARGE_DATA + PCI_VPD_SIZE + 311 ETHER_ADDR_LEN) != 0x79 && 312 HME_ROM_READ_1(j + 4 * (PCI_VPDRES_LARGE_DATA + PCI_VPD_SIZE + 313 ETHER_ADDR_LEN)) == 0x79) 314 /* Use the Nth NA for the Nth HME on this SUNW,qfe. */ 315 j += slot * (PCI_VPDRES_LARGE_DATA + PCI_VPD_SIZE + 316 ETHER_ADDR_LEN); 317 if (PCI_VPDRES_ISLARGE(HME_ROM_READ_1(j + PCI_VPDRES_BYTE0)) == 0 || 318 PCI_VPDRES_LARGE_NAME(HME_ROM_READ_1(j + PCI_VPDRES_BYTE0)) != 319 PCI_VPDRES_TYPE_VPD || 320 (HME_ROM_READ_1(j + PCI_VPDRES_LARGE_LEN_LSB) << 8 | 321 HME_ROM_READ_1(j + PCI_VPDRES_LARGE_LEN_MSB)) != 322 PCI_VPD_SIZE + ETHER_ADDR_LEN || 323 HME_ROM_READ_1(j + PCI_VPDRES_LARGE_DATA + PCI_VPD_KEY0) != 324 0x4e /* N */ || 325 HME_ROM_READ_1(j + PCI_VPDRES_LARGE_DATA + PCI_VPD_KEY1) != 326 0x41 /* A */ || 327 HME_ROM_READ_1(j + PCI_VPDRES_LARGE_DATA + PCI_VPD_LEN) != 328 ETHER_ADDR_LEN) { 329 device_printf(dev, "unexpected PCI VPD\n"); 330 error = ENXIO; 331 goto fail_rres; 332 } 333 bus_space_read_region_1(memt, memh, j + PCI_VPDRES_LARGE_DATA + 334 PCI_VPD_DATA, sc->sc_enaddr, ETHER_ADDR_LEN); 335 336fail_rres: 337 bus_release_resource(ebus_dev, SYS_RES_MEMORY, 338 rman_get_rid(ebus_rres), ebus_rres); 339fail_children: 340 free(children, M_TEMP); 341 if (error != 0) 342 goto fail_sres; 343#endif 344 345 sc->sc_burst = 64; /* XXX */ 346 347 /* 348 * call the main configure 349 */ 350 if ((error = hme_config(sc)) != 0) { 351 device_printf(dev, "could not be configured\n"); 352 goto fail_ires; 353 } 354 355 if ((error = bus_setup_intr(dev, hsc->hsc_ires, INTR_TYPE_NET | 356 INTR_MPSAFE, NULL, hme_intr, sc, &hsc->hsc_ih)) != 0) { 357 device_printf(dev, "couldn't establish interrupt\n"); 358 hme_detach(sc); 359 goto fail_ires; 360 } 361 return (0); 362 363fail_ires: 364 bus_release_resource(dev, SYS_RES_IRQ, 365 rman_get_rid(hsc->hsc_ires), hsc->hsc_ires); 366fail_sres: 367 bus_release_resource(dev, SYS_RES_MEMORY, 368 rman_get_rid(hsc->hsc_sres), hsc->hsc_sres); 369fail_mtx: 370 mtx_destroy(&sc->sc_lock); 371 return (error); 372} 373 374static int 375hme_pci_detach(device_t dev) 376{ 377 struct hme_pci_softc *hsc; 378 struct hme_softc *sc; 379 380 hsc = device_get_softc(dev); 381 sc = &hsc->hsc_hme; 382 bus_teardown_intr(dev, hsc->hsc_ires, hsc->hsc_ih); 383 hme_detach(sc); 384 bus_release_resource(dev, SYS_RES_IRQ, 385 rman_get_rid(hsc->hsc_ires), hsc->hsc_ires); 386 bus_release_resource(dev, SYS_RES_MEMORY, 387 rman_get_rid(hsc->hsc_sres), hsc->hsc_sres); 388 mtx_destroy(&sc->sc_lock); 389 return (0); 390} 391 392static int 393hme_pci_suspend(device_t dev) 394{ 395 struct hme_pci_softc *hsc; 396 397 hsc = device_get_softc(dev); 398 hme_suspend(&hsc->hsc_hme); 399 return (0); 400} 401 402static int 403hme_pci_resume(device_t dev) 404{ 405 struct hme_pci_softc *hsc; 406 407 hsc = device_get_softc(dev); 408 hme_resume(&hsc->hsc_hme); 409 return (0); 410} 411