The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/hme/if_hme_sbus.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 1999 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Paul Kranenburg.
    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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  *
   31  *      from: NetBSD: if_hme_sbus.c,v 1.19 2004/03/17 17:04:58 pk Exp
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD: releng/12.0/sys/dev/hme/if_hme_sbus.c 326255 2017-11-27 14:52:40Z pfg $");
   36 
   37 /*
   38  * SBus front-end device driver for the HME ethernet device.
   39  */
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/bus.h>
   44 #include <sys/lock.h>
   45 #include <sys/kernel.h>
   46 #include <sys/module.h>
   47 #include <sys/mutex.h>
   48 #include <sys/resource.h>
   49 #include <sys/socket.h>
   50 
   51 #include <dev/ofw/ofw_bus.h>
   52 
   53 #include <machine/bus.h>
   54 #include <machine/ofw_machdep.h>
   55 #include <machine/resource.h>
   56 
   57 #include <sys/rman.h>
   58 
   59 #include <net/if.h>
   60 #include <net/if_media.h>
   61 #include <net/ethernet.h>
   62 
   63 #include <dev/mii/mii.h>
   64 #include <dev/mii/miivar.h>
   65 
   66 #include <sparc64/sbus/sbusvar.h>
   67 
   68 #include <dev/hme/if_hmereg.h>
   69 #include <dev/hme/if_hmevar.h>
   70 
   71 #include "miibus_if.h"
   72 
   73 struct hme_sbus_softc {
   74         struct  hme_softc       hsc_hme;        /* HME device */
   75         struct  resource        *hsc_seb_res;
   76         struct  resource        *hsc_etx_res;
   77         struct  resource        *hsc_erx_res;
   78         struct  resource        *hsc_mac_res;
   79         struct  resource        *hsc_mif_res;
   80         struct  resource        *hsc_ires;
   81         void                    *hsc_ih;
   82 };
   83 
   84 static int hme_sbus_probe(device_t);
   85 static int hme_sbus_attach(device_t);
   86 static int hme_sbus_detach(device_t);
   87 static int hme_sbus_suspend(device_t);
   88 static int hme_sbus_resume(device_t);
   89 
   90 static device_method_t hme_sbus_methods[] = {
   91         /* Device interface */
   92         DEVMETHOD(device_probe,         hme_sbus_probe),
   93         DEVMETHOD(device_attach,        hme_sbus_attach),
   94         DEVMETHOD(device_detach,        hme_sbus_detach),
   95         DEVMETHOD(device_suspend,       hme_sbus_suspend),
   96         DEVMETHOD(device_resume,        hme_sbus_resume),
   97         /* Can just use the suspend method here. */
   98         DEVMETHOD(device_shutdown,      hme_sbus_suspend),
   99 
  100         /* MII interface */
  101         DEVMETHOD(miibus_readreg,       hme_mii_readreg),
  102         DEVMETHOD(miibus_writereg,      hme_mii_writereg),
  103         DEVMETHOD(miibus_statchg,       hme_mii_statchg),
  104 
  105         DEVMETHOD_END
  106 };
  107 
  108 static driver_t hme_sbus_driver = {
  109         "hme",
  110         hme_sbus_methods,
  111         sizeof(struct hme_sbus_softc)
  112 };
  113 
  114 DRIVER_MODULE(hme, sbus, hme_sbus_driver, hme_devclass, 0, 0);
  115 MODULE_DEPEND(hme, sbus, 1, 1, 1);
  116 MODULE_DEPEND(hme, ether, 1, 1, 1);
  117 
  118 static int
  119 hme_sbus_probe(device_t dev)
  120 {
  121         const char *name;
  122 
  123         name = ofw_bus_get_name(dev);
  124         if (strcmp(name, "SUNW,qfe") == 0 ||
  125             strcmp(name, "SUNW,hme") == 0) {
  126                 device_set_desc(dev, "Sun HME 10/100 Ethernet");
  127                 return (0);
  128         }
  129         return (ENXIO);
  130 }
  131 
  132 static int
  133 hme_sbus_attach(device_t dev)
  134 {
  135         struct hme_sbus_softc *hsc;
  136         struct hme_softc *sc;
  137         u_long start, count;
  138         uint32_t burst;
  139         int i, error = 0;
  140 
  141         hsc = device_get_softc(dev);
  142         sc = &hsc->hsc_hme;
  143         mtx_init(&sc->sc_lock, device_get_nameunit(dev), MTX_NETWORK_LOCK,
  144             MTX_DEF);
  145         /*
  146          * Map five register banks:
  147          *
  148          *      bank 0: HME SEB registers
  149          *      bank 1: HME ETX registers
  150          *      bank 2: HME ERX registers
  151          *      bank 3: HME MAC registers
  152          *      bank 4: HME MIF registers
  153          *
  154          */
  155         i = 0;
  156         hsc->hsc_seb_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  157             &i, RF_ACTIVE);
  158         if (hsc->hsc_seb_res == NULL) {
  159                 device_printf(dev, "cannot map SEB registers\n");
  160                 error = ENXIO;
  161                 goto fail_mtx_res;
  162         }
  163         sc->sc_sebt = rman_get_bustag(hsc->hsc_seb_res);
  164         sc->sc_sebh = rman_get_bushandle(hsc->hsc_seb_res);
  165 
  166         i = 1;
  167         hsc->hsc_etx_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  168             &i, RF_ACTIVE);
  169         if (hsc->hsc_etx_res == NULL) {
  170                 device_printf(dev, "cannot map ETX registers\n");
  171                 error = ENXIO;
  172                 goto fail_seb_res;
  173         }
  174         sc->sc_etxt = rman_get_bustag(hsc->hsc_etx_res);
  175         sc->sc_etxh = rman_get_bushandle(hsc->hsc_etx_res);
  176 
  177         i = 2;
  178         hsc->hsc_erx_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  179             &i, RF_ACTIVE);
  180         if (hsc->hsc_erx_res == NULL) {
  181                 device_printf(dev, "cannot map ERX registers\n");
  182                 error = ENXIO;
  183                 goto fail_etx_res;
  184         }
  185         sc->sc_erxt = rman_get_bustag(hsc->hsc_erx_res);
  186         sc->sc_erxh = rman_get_bushandle(hsc->hsc_erx_res);
  187 
  188         i = 3;
  189         hsc->hsc_mac_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  190             &i, RF_ACTIVE);
  191         if (hsc->hsc_mac_res == NULL) {
  192                 device_printf(dev, "cannot map MAC registers\n");
  193                 error = ENXIO;
  194                 goto fail_erx_res;
  195         }
  196         sc->sc_mact = rman_get_bustag(hsc->hsc_mac_res);
  197         sc->sc_mach = rman_get_bushandle(hsc->hsc_mac_res);
  198 
  199         /*
  200          * At least on some HMEs, the MIF registers seem to be inside the MAC
  201          * range, so try to kludge around it.
  202          */
  203         i = 4;
  204         hsc->hsc_mif_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  205             &i, RF_ACTIVE);
  206         if (hsc->hsc_mif_res == NULL) {
  207                 if (bus_get_resource(dev, SYS_RES_MEMORY, i,
  208                     &start, &count) != 0) {
  209                         device_printf(dev, "cannot get MIF registers\n");
  210                         error = ENXIO;
  211                         goto fail_mac_res;
  212                 }
  213                 if (start < rman_get_start(hsc->hsc_mac_res) ||
  214                     start + count - 1 > rman_get_end(hsc->hsc_mac_res)) {
  215                         device_printf(dev, "cannot move MIF registers to MAC "
  216                             "bank\n");
  217                         error = ENXIO;
  218                         goto fail_mac_res;
  219                 }
  220                 sc->sc_mift = sc->sc_mact;
  221                 bus_space_subregion(sc->sc_mact, sc->sc_mach,
  222                     start - rman_get_start(hsc->hsc_mac_res), count,
  223                     &sc->sc_mifh);
  224         } else {
  225                 sc->sc_mift = rman_get_bustag(hsc->hsc_mif_res);
  226                 sc->sc_mifh = rman_get_bushandle(hsc->hsc_mif_res);
  227         }
  228 
  229         i = 0;
  230         hsc->hsc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
  231             &i, RF_SHAREABLE | RF_ACTIVE);
  232         if (hsc->hsc_ires == NULL) {
  233                 device_printf(dev, "could not allocate interrupt\n");
  234                 error = ENXIO;
  235                 goto fail_mif_res;
  236         }
  237 
  238         OF_getetheraddr(dev, sc->sc_enaddr);
  239 
  240         burst = sbus_get_burstsz(dev);
  241         /* Translate into plain numerical format */
  242         if ((burst & SBUS_BURST_64))
  243                 sc->sc_burst = 64;
  244         else if ((burst & SBUS_BURST_32))
  245                 sc->sc_burst = 32;
  246         else if ((burst & SBUS_BURST_16))
  247                 sc->sc_burst = 16;
  248         else
  249                  sc->sc_burst = 0;
  250 
  251         sc->sc_dev = dev;
  252         sc->sc_flags = 0;
  253 
  254         if ((error = hme_config(sc)) != 0) {
  255                 device_printf(dev, "could not be configured\n");
  256                 goto fail_ires;
  257         }
  258 
  259         if ((error = bus_setup_intr(dev, hsc->hsc_ires, INTR_TYPE_NET |
  260             INTR_MPSAFE, NULL, hme_intr, sc, &hsc->hsc_ih)) != 0) {
  261                 device_printf(dev, "couldn't establish interrupt\n");
  262                 hme_detach(sc);
  263                 goto fail_ires;
  264         }
  265         return (0);
  266 
  267 fail_ires:
  268         bus_release_resource(dev, SYS_RES_IRQ,
  269             rman_get_rid(hsc->hsc_ires), hsc->hsc_ires);
  270 fail_mif_res:
  271         if (hsc->hsc_mif_res != NULL) {
  272                 bus_release_resource(dev, SYS_RES_MEMORY,
  273                     rman_get_rid(hsc->hsc_mif_res), hsc->hsc_mif_res);
  274         }
  275 fail_mac_res:
  276         bus_release_resource(dev, SYS_RES_MEMORY,
  277             rman_get_rid(hsc->hsc_mac_res), hsc->hsc_mac_res);
  278 fail_erx_res:
  279         bus_release_resource(dev, SYS_RES_MEMORY,
  280             rman_get_rid(hsc->hsc_erx_res), hsc->hsc_erx_res);
  281 fail_etx_res:
  282         bus_release_resource(dev, SYS_RES_MEMORY,
  283             rman_get_rid(hsc->hsc_etx_res), hsc->hsc_etx_res);
  284 fail_seb_res:
  285         bus_release_resource(dev, SYS_RES_MEMORY,
  286             rman_get_rid(hsc->hsc_seb_res), hsc->hsc_seb_res);
  287 fail_mtx_res:
  288         mtx_destroy(&sc->sc_lock);
  289         return (error);
  290 }
  291 
  292 static int
  293 hme_sbus_detach(device_t dev)
  294 {
  295         struct hme_sbus_softc *hsc;
  296         struct hme_softc *sc;
  297 
  298         hsc = device_get_softc(dev);
  299         sc = &hsc->hsc_hme;
  300         bus_teardown_intr(dev, hsc->hsc_ires, hsc->hsc_ih);
  301         hme_detach(sc);
  302         bus_release_resource(dev, SYS_RES_IRQ,
  303             rman_get_rid(hsc->hsc_ires), hsc->hsc_ires);
  304         if (hsc->hsc_mif_res != NULL) {
  305                 bus_release_resource(dev, SYS_RES_MEMORY,
  306                     rman_get_rid(hsc->hsc_mif_res), hsc->hsc_mif_res);
  307         }
  308         bus_release_resource(dev, SYS_RES_MEMORY,
  309             rman_get_rid(hsc->hsc_mac_res), hsc->hsc_mac_res);
  310         bus_release_resource(dev, SYS_RES_MEMORY,
  311             rman_get_rid(hsc->hsc_erx_res), hsc->hsc_erx_res);
  312         bus_release_resource(dev, SYS_RES_MEMORY,
  313             rman_get_rid(hsc->hsc_etx_res), hsc->hsc_etx_res);
  314         bus_release_resource(dev, SYS_RES_MEMORY,
  315             rman_get_rid(hsc->hsc_seb_res), hsc->hsc_seb_res);
  316         mtx_destroy(&sc->sc_lock);
  317         return (0);
  318 }
  319 
  320 static int
  321 hme_sbus_suspend(device_t dev)
  322 {
  323         struct hme_sbus_softc *hsc;
  324 
  325         hsc = device_get_softc(dev);
  326         hme_suspend(&hsc->hsc_hme);
  327         return (0);
  328 }
  329 
  330 static int
  331 hme_sbus_resume(device_t dev)
  332 {
  333         struct hme_sbus_softc *hsc;
  334 
  335         hsc = device_get_softc(dev);
  336         hme_resume(&hsc->hsc_hme);
  337         return (0);
  338 }

Cache object: d056a0ef1e6216b0f5040cba84cb254c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.