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

Cache object: df1f9d03ce3feb58043b3c2ba7b8d204


[ 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.