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/netif/lnc/if_lnc_pci.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 /*      $NetBSD: if_le_pci.c,v 1.43 2005/12/11 12:22:49 christos Exp $  */
    2 /*      $FreeBSD: src/sys/dev/le/if_le_pci.c,v 1.4 2006/06/05 15:14:14 marius Exp $     */
    3 
    4 
    5 /*-
    6  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
    7  * All rights reserved.
    8  *
    9  * This code is derived from software contributed to The NetBSD Foundation
   10  * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
   11  * Simulation Facility, NASA Ames Research Center.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 3. All advertising materials mentioning features or use of this software
   22  *    must display the following acknowledgement:
   23  *      This product includes software developed by the NetBSD
   24  *      Foundation, Inc. and its contributors.
   25  * 4. Neither the name of The NetBSD Foundation nor the names of its
   26  *    contributors may be used to endorse or promote products derived
   27  *    from this software without specific prior written permission.
   28  *
   29  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   30  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   31  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   32  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   33  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   34  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   35  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   36  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   37  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   38  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   39  * POSSIBILITY OF SUCH DAMAGE.
   40  */
   41 
   42 /*-
   43  * Copyright (c) 1992, 1993
   44  *      The Regents of the University of California.  All rights reserved.
   45  *
   46  * This code is derived from software contributed to Berkeley by
   47  * Ralph Campbell and Rick Macklem.
   48  *
   49  * Redistribution and use in source and binary forms, with or without
   50  * modification, are permitted provided that the following conditions
   51  * are met:
   52  * 1. Redistributions of source code must retain the above copyright
   53  *    notice, this list of conditions and the following disclaimer.
   54  * 2. Redistributions in binary form must reproduce the above copyright
   55  *    notice, this list of conditions and the following disclaimer in the
   56  *    documentation and/or other materials provided with the distribution.
   57  * 3. Neither the name of the University nor the names of its contributors
   58  *    may be used to endorse or promote products derived from this software
   59  *    without specific prior written permission.
   60  *
   61  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   62  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   63  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   64  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   65  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   66  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   67  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   68  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   69  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   70  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   71  * SUCH DAMAGE.
   72  *
   73  *      @(#)if_le.c     8.2 (Berkeley) 11/16/93
   74  */
   75 
   76 #include <sys/param.h>
   77 #include <sys/systm.h>
   78 #include <sys/bus.h>
   79 #include <sys/endian.h>
   80 #include <sys/kernel.h>
   81 #include <sys/interrupt.h>
   82 #include <sys/lock.h>
   83 #include <sys/module.h>
   84 #include <sys/resource.h>
   85 #include <sys/rman.h>
   86 #include <sys/socket.h>
   87 
   88 #include <net/ethernet.h>
   89 #include <net/if.h>
   90 #include <net/if_media.h>
   91 #include <net/if_arp.h>
   92 #include <net/ifq_var.h>
   93 
   94 #include <bus/pci/pcireg.h>
   95 #include <bus/pci/pcivar.h>
   96 
   97 #include <dev/netif/lnc/lancereg.h>
   98 #include <dev/netif/lnc/lancevar.h>
   99 #include <dev/netif/lnc/am79900var.h>
  100 
  101 #define AMD_VENDOR      0x1022
  102 #define AMD_PCNET_PCI   0x2000
  103 #define AMD_PCNET_HOME  0x2001
  104 #define PCNET_MEMSIZE   (32*1024)
  105 #define PCNET_PCI_RDP   0x10
  106 #define PCNET_PCI_RAP   0x12
  107 #define PCNET_PCI_BDP   0x16
  108 
  109 #define LNC_PROBE_PRIORITY -100
  110 
  111 struct le_pci_softc {
  112         struct am79900_softc    sc_am79900;     /* glue to MI code */
  113 
  114         int                     sc_rrid;
  115         struct resource         *sc_rres;
  116         bus_space_tag_t         sc_regt;
  117         bus_space_handle_t      sc_regh;
  118 
  119         int                     sc_irid;
  120         struct resource         *sc_ires;
  121         void                    *sc_ih;
  122 
  123         bus_dma_tag_t           sc_pdmat;
  124         bus_dma_tag_t           sc_dmat;
  125         bus_dmamap_t            sc_dmam;
  126 };
  127 
  128 static device_probe_t le_pci_probe;
  129 static device_attach_t le_pci_attach;
  130 static device_detach_t le_pci_detach;
  131 static device_resume_t le_pci_resume;
  132 static device_suspend_t le_pci_suspend;
  133 
  134 static device_method_t le_pci_methods[] = {
  135         /* Device interface */
  136         DEVMETHOD(device_probe,         le_pci_probe),
  137         DEVMETHOD(device_attach,        le_pci_attach),
  138         DEVMETHOD(device_detach,        le_pci_detach),
  139         /* We can just use the suspend method here. */
  140         DEVMETHOD(device_shutdown,      le_pci_suspend),
  141         DEVMETHOD(device_suspend,       le_pci_suspend),
  142         DEVMETHOD(device_resume,        le_pci_resume),
  143 
  144         DEVMETHOD_END
  145 };
  146 
  147 DEFINE_CLASS_0(lnc, le_pci_driver, le_pci_methods, sizeof(struct le_pci_softc));
  148 DRIVER_MODULE(lnc, pci, le_pci_driver, le_devclass, NULL, NULL);
  149 MODULE_DEPEND(lnc, ether, 1, 1, 1);
  150 
  151 static const int le_home_supmedia[] = {
  152         IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0, 0)
  153 };
  154 
  155 static const int le_pci_supmedia[] = {
  156         IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0),
  157         IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, IFM_FDX, 0),
  158         IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0),
  159         IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, 0),
  160         IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, 0),
  161         IFM_MAKEWORD(IFM_ETHER, IFM_10_5, IFM_FDX, 0)
  162 };
  163 
  164 static void le_pci_wrbcr(struct lance_softc *, uint16_t, uint16_t);
  165 static uint16_t le_pci_rdbcr(struct lance_softc *, uint16_t);
  166 static void le_pci_wrcsr(struct lance_softc *, uint16_t, uint16_t);
  167 static uint16_t le_pci_rdcsr(struct lance_softc *, uint16_t);
  168 static int le_pci_mediachange(struct lance_softc *);
  169 static void le_pci_hwreset(struct lance_softc *);
  170 static bus_dmamap_callback_t le_pci_dma_callback;
  171 
  172 static void
  173 le_pci_wrbcr(struct lance_softc *sc, uint16_t port, uint16_t val)
  174 {
  175         struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
  176 
  177         bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
  178         bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
  179             BUS_SPACE_BARRIER_WRITE);
  180         bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_BDP, val);
  181 }
  182 
  183 static uint16_t
  184 le_pci_rdbcr(struct lance_softc *sc, uint16_t port)
  185 {
  186         struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
  187 
  188         bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
  189         bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
  190             BUS_SPACE_BARRIER_WRITE);
  191         return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_BDP));
  192 }
  193 
  194 static void
  195 le_pci_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val)
  196 {
  197         struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
  198 
  199         bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
  200         bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
  201             BUS_SPACE_BARRIER_WRITE);
  202         bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RDP, val);
  203 }
  204 
  205 static uint16_t
  206 le_pci_rdcsr(struct lance_softc *sc, uint16_t port)
  207 {
  208         struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
  209 
  210         bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
  211         bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
  212             BUS_SPACE_BARRIER_WRITE);
  213         return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RDP));
  214 }
  215 
  216 static int
  217 le_pci_mediachange(struct lance_softc *sc)
  218 {
  219         struct ifmedia *ifm = &sc->sc_media;
  220         uint16_t reg;
  221 
  222         if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
  223                 return (EINVAL);
  224 
  225         if (IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1)
  226                 le_pci_wrbcr(sc, LE_BCR49,
  227                     (le_pci_rdbcr(sc, LE_BCR49) & ~LE_B49_PHYSEL) | 0x1);
  228         else if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO)
  229                 le_pci_wrbcr(sc, LE_BCR2,
  230                     le_pci_rdbcr(sc, LE_BCR2) | LE_B2_ASEL);
  231         else {
  232                 le_pci_wrbcr(sc, LE_BCR2,
  233                     le_pci_rdbcr(sc, LE_BCR2) & ~LE_B2_ASEL);
  234 
  235                 reg = le_pci_rdcsr(sc, LE_CSR15);
  236                 reg &= ~LE_C15_PORTSEL(LE_PORTSEL_MASK);
  237                 if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_T)
  238                         reg |= LE_C15_PORTSEL(LE_PORTSEL_10T);
  239                 else
  240                         reg |= LE_C15_PORTSEL(LE_PORTSEL_AUI);
  241                 le_pci_wrcsr(sc, LE_CSR15, reg);
  242         }
  243 
  244         reg = le_pci_rdbcr(sc, LE_BCR9);
  245         if (IFM_OPTIONS(ifm->ifm_media) & IFM_FDX) {
  246                 reg |= LE_B9_FDEN;
  247                 /*
  248                  * Allow FDX on AUI only if explicitly chosen,
  249                  * not in autoselect mode.
  250                  */
  251                 if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_5)
  252                         reg |= LE_B9_AUIFD;
  253                 else
  254                         reg &= ~LE_B9_AUIFD;
  255         } else
  256                 reg &= ~LE_B9_FDEN;
  257         le_pci_wrbcr(sc, LE_BCR9, reg);
  258 
  259         return (0);
  260 }
  261 
  262 static void
  263 le_pci_hwreset(struct lance_softc *sc)
  264 {
  265 
  266         /*
  267          * Chip is stopped. Set software style to PCnet-PCI (32-bit).
  268          * Actually, am79900.c implements ILACC support (hence its
  269          * name) but unfortunately VMware does not. As far as this
  270          * driver is concerned that should not make a difference
  271          * though, as the settings used have the same meaning for
  272          * both, ILACC and PCnet-PCI (note that there would be a
  273          * difference for the ADD_FCS/NO_FCS bit if used).
  274          */
  275         le_pci_wrbcr(sc, LE_BCR20, LE_B20_SSTYLE_PCNETPCI2);
  276 }
  277 
  278 static void
  279 le_pci_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
  280 {
  281         struct lance_softc *sc = (struct lance_softc *)xsc;
  282 
  283         if (error != 0)
  284                 return;
  285         KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__));
  286         sc->sc_addr = segs[0].ds_addr;
  287 }
  288 
  289 static int
  290 le_pci_probe(device_t dev)
  291 {
  292 
  293         if (pci_get_vendor(dev) != AMD_VENDOR)
  294                 return (ENXIO);
  295 
  296         switch (pci_get_device(dev)) {
  297         case AMD_PCNET_PCI:
  298                 device_set_desc(dev, "AMD PCnet-PCI");
  299                 /* Let pcn(4) win. */
  300                 return (LNC_PROBE_PRIORITY);
  301         case AMD_PCNET_HOME:
  302                 device_set_desc(dev, "AMD PCnet-Home");
  303                 /* Let pcn(4) win. */
  304                 return (LNC_PROBE_PRIORITY);
  305         default:
  306                 return (ENXIO);
  307         }
  308 }
  309 
  310 static int
  311 le_pci_attach(device_t dev)
  312 {
  313         struct le_pci_softc *lesc;
  314         struct lance_softc *sc;
  315         int error, i;
  316 
  317         lesc = device_get_softc(dev);
  318         sc = &lesc->sc_am79900.lsc;
  319 
  320         pci_enable_busmaster(dev);
  321         pci_enable_io(dev, PCIM_CMD_PORTEN);
  322 
  323         lesc->sc_rrid = PCIR_BAR(0);
  324         lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
  325             &lesc->sc_rrid, RF_ACTIVE);
  326         if (lesc->sc_rres == NULL) {
  327                 device_printf(dev, "cannot allocate registers\n");
  328                 error = ENXIO;
  329                 goto fail_mtx;
  330         }
  331         lesc->sc_regt = rman_get_bustag(lesc->sc_rres);
  332         lesc->sc_regh = rman_get_bushandle(lesc->sc_rres);
  333 
  334         lesc->sc_irid = 0;
  335         if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
  336             &lesc->sc_irid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
  337                 device_printf(dev, "cannot allocate interrupt\n");
  338                 error = ENXIO;
  339                 goto fail_rres;
  340         }
  341 
  342         error = bus_dma_tag_create(
  343             NULL,                       /* parent */
  344             1, 0,                       /* alignment, boundary */
  345             BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
  346             BUS_SPACE_MAXADDR,          /* highaddr */
  347             NULL, NULL,                 /* filter, filterarg */
  348             BUS_SPACE_MAXSIZE_32BIT,    /* maxsize */
  349             0,                          /* nsegments */
  350             BUS_SPACE_MAXSIZE_32BIT,    /* maxsegsize */
  351             BUS_DMA_WAITOK,             /* flags */
  352             &lesc->sc_pdmat);
  353         if (error != 0) {
  354                 device_printf(dev, "cannot allocate parent DMA tag\n");
  355                 goto fail_ires;
  356         }
  357 
  358         sc->sc_memsize = PCNET_MEMSIZE;
  359         /*
  360          * For Am79C970A, Am79C971 and Am79C978 the init block must be 2-byte
  361          * aligned and the ring descriptors must be 16-byte aligned when using
  362          * a 32-bit software style.
  363          */
  364         error = bus_dma_tag_create(
  365             lesc->sc_pdmat,             /* parent */
  366             16, 0,                      /* alignment, boundary */
  367             BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
  368             BUS_SPACE_MAXADDR,          /* highaddr */
  369             NULL, NULL,                 /* filter, filterarg */
  370             sc->sc_memsize,             /* maxsize */
  371             1,                          /* nsegments */
  372             sc->sc_memsize,             /* maxsegsize */
  373             BUS_DMA_WAITOK,             /* flags */
  374             &lesc->sc_dmat);
  375         if (error != 0) {
  376                 device_printf(dev, "cannot allocate buffer DMA tag\n");
  377                 goto fail_pdtag;
  378         }
  379 
  380         error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem,
  381             BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam);
  382         if (error != 0) {
  383                 device_printf(dev, "cannot allocate DMA buffer memory\n");
  384                 goto fail_dtag;
  385         }
  386 
  387         sc->sc_addr = 0;
  388         error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem,
  389             sc->sc_memsize, le_pci_dma_callback, sc, 0);
  390         if (error != 0 || sc->sc_addr == 0) {
  391                 device_printf(dev, "cannot load DMA buffer map\n");
  392                 goto fail_dmem;
  393         }
  394 
  395         sc->sc_flags = LE_BSWAP;
  396         sc->sc_conf3 = 0;
  397 
  398         sc->sc_mediastatus = NULL;
  399         switch (pci_get_device(dev)) {
  400         case AMD_PCNET_HOME:
  401                 sc->sc_mediachange = le_pci_mediachange;
  402                 sc->sc_supmedia = le_home_supmedia;
  403                 sc->sc_nsupmedia = sizeof(le_home_supmedia) / sizeof(int);
  404                 sc->sc_defaultmedia = le_home_supmedia[0];
  405                 break;
  406         default:
  407                 sc->sc_mediachange = le_pci_mediachange;
  408                 sc->sc_supmedia = le_pci_supmedia;
  409                 sc->sc_nsupmedia = sizeof(le_pci_supmedia) / sizeof(int);
  410                 sc->sc_defaultmedia = le_pci_supmedia[0];
  411         }
  412 
  413         /*
  414          * Extract the physical MAC address from the ROM.
  415          */
  416         for (i = 0; i < sizeof(sc->sc_enaddr); i++)
  417                 sc->sc_enaddr[i] =
  418                     bus_space_read_1(lesc->sc_regt, lesc->sc_regh, i);
  419 
  420         sc->sc_copytodesc = lance_copytobuf_contig;
  421         sc->sc_copyfromdesc = lance_copyfrombuf_contig;
  422         sc->sc_copytobuf = lance_copytobuf_contig;
  423         sc->sc_copyfrombuf = lance_copyfrombuf_contig;
  424         sc->sc_zerobuf = lance_zerobuf_contig;
  425 
  426         sc->sc_rdcsr = le_pci_rdcsr;
  427         sc->sc_wrcsr = le_pci_wrcsr;
  428         sc->sc_hwreset = le_pci_hwreset;
  429         sc->sc_hwinit = NULL;
  430         sc->sc_hwintr = NULL;
  431         sc->sc_nocarrier = NULL;
  432 
  433         error = am79900_config(&lesc->sc_am79900, device_get_name(dev),
  434             device_get_unit(dev));
  435         if (error != 0) {
  436                 device_printf(dev, "cannot attach Am79900\n");
  437                 goto fail_dmap;
  438         }
  439 
  440         ifq_set_cpuid(&sc->ifp->if_snd, rman_get_cpuid(lesc->sc_ires));
  441 
  442         error = bus_setup_intr(dev, lesc->sc_ires, INTR_MPSAFE,
  443             am79900_intr, sc, &lesc->sc_ih, sc->ifp->if_serializer);
  444         if (error != 0) {
  445                 device_printf(dev, "cannot set up interrupt\n");
  446                 goto fail_am79900;
  447         }
  448 
  449         return (0);
  450 
  451  fail_am79900:
  452         am79900_detach(&lesc->sc_am79900);
  453  fail_dmap:
  454         bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam);
  455  fail_dmem:
  456         bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam);
  457  fail_dtag:
  458         bus_dma_tag_destroy(lesc->sc_dmat);
  459  fail_pdtag:
  460         bus_dma_tag_destroy(lesc->sc_pdmat);
  461  fail_ires:
  462         bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires);
  463  fail_rres:
  464         bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres);
  465  fail_mtx:
  466         return (error);
  467 }
  468 
  469 static int
  470 le_pci_detach(device_t dev)
  471 {
  472         struct le_pci_softc *lesc;
  473         struct lance_softc *sc;
  474 
  475         lesc = device_get_softc(dev);
  476         sc = &lesc->sc_am79900.lsc;
  477 
  478         if (device_is_attached(dev)) {
  479                 lwkt_serialize_enter(sc->ifp->if_serializer);
  480                 lance_stop(sc);
  481                 bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih);
  482                 lwkt_serialize_exit(sc->ifp->if_serializer);
  483 
  484                 am79900_detach(&lesc->sc_am79900);
  485         }
  486 
  487         if (lesc->sc_ires)
  488                 bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires);
  489         if (lesc->sc_rres)
  490                 bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres);
  491         if (lesc->sc_dmam) {
  492                 bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam);
  493                 bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam);
  494         }
  495         if (lesc->sc_dmat)
  496                 bus_dma_tag_destroy(lesc->sc_dmat);
  497         if (lesc->sc_pdmat)
  498                 bus_dma_tag_destroy(lesc->sc_pdmat);
  499 
  500         return (0);
  501 }
  502 
  503 static int
  504 le_pci_suspend(device_t dev)
  505 {
  506         struct le_pci_softc *lesc;
  507 
  508         lesc = device_get_softc(dev);
  509 
  510         lance_suspend(&lesc->sc_am79900.lsc);
  511 
  512         return (0);
  513 }
  514 
  515 static int
  516 le_pci_resume(device_t dev)
  517 {
  518         struct le_pci_softc *lesc;
  519 
  520         lesc = device_get_softc(dev);
  521 
  522         lance_resume(&lesc->sc_am79900.lsc);
  523 
  524         return (0);
  525 }

Cache object: 30946b5a3984c4911f2ebd4303f7671e


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