root/dev/pci/if_lmc_obsd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lmc_pci_probe
  2. lmc_pci_attach
  3. lmc_shutdown
  4. lmc_busdma_allocmem
  5. lmc_busdma_init

    1 /*      $OpenBSD: if_lmc_obsd.c,v 1.19 2005/11/07 00:29:21 brad Exp $ */
    2 /*      $NetBSD: if_lmc_nbsd.c,v 1.1 1999/03/25 03:32:43 explorer Exp $ */
    3 
    4 /*-
    5  * Copyright (c) 1997-1999 LAN Media Corporation (LMC)
    6  * All rights reserved.  www.lanmedia.com
    7  *
    8  * This code is written by Michael Graff <graff@vix.com> for LMC.
    9  * The code is derived from permitted modifications to software created
   10  * by Matt Thomas (matt@3am-software.com).
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above
   18  *    copyright notice, this list of conditions and the following disclaimer
   19  *    in the documentation and/or other materials provided with the
   20  *    distribution.
   21  * 3. All marketing or advertising materials mentioning features or
   22  *    use of this software must display the following acknowledgement:
   23  *      This product includes software developed by LAN Media Corporation
   24  *      and its contributors.
   25  * 4. Neither the name of LAN Media Corporation 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 LAN MEDIA CORPORATION 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
   39  * THE POSSIBILITY OF SUCH DAMAGE.
   40  */
   41 
   42 /*-
   43  * Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com)
   44  * All rights reserved.
   45  *
   46  * Redistribution and use in source and binary forms, with or without
   47  * modification, are permitted provided that the following conditions
   48  * are met:
   49  * 1. Redistributions of source code must retain the above copyright
   50  *    notice, this list of conditions and the following disclaimer.
   51  * 2. The name of the author may not be used to endorse or promote products
   52  *    derived from this software without specific prior written permission
   53  *
   54  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   55  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   56  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   57  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   58  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   59  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   60  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   61  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   62  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   63  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   64  */
   65 
   66 #include "bpfilter.h"
   67 
   68 #include <sys/param.h>
   69 #include <sys/systm.h>
   70 #include <sys/mbuf.h>
   71 #include <sys/socket.h>
   72 #include <sys/ioctl.h>
   73 #include <sys/errno.h>
   74 #include <sys/malloc.h>
   75 #include <sys/kernel.h>
   76 #include <sys/proc.h>   /* only for declaration of wakeup() used by vm.h */
   77 #include <sys/device.h>
   78 
   79 #include <dev/pci/pcidevs.h>
   80 
   81 #include <net/if.h>
   82 #include <net/if_types.h>
   83 #include <net/if_dl.h>
   84 #include <net/netisr.h>
   85 
   86 #if NBPFILTER > 0
   87 #include <net/bpf.h>
   88 #endif
   89 
   90 #include <net/if_sppp.h>
   91 
   92 #include <machine/bus.h>
   93 
   94 #include <dev/pci/pcireg.h>
   95 #include <dev/pci/pcivar.h>
   96 #include <dev/ic/dc21040reg.h>
   97 
   98 #include <dev/pci/if_lmc_types.h>
   99 #include <dev/pci/if_lmcioctl.h>
  100 #include <dev/pci/if_lmcvar.h>
  101 
  102 /*
  103  * This file is INCLUDED (gross, I know, but...)
  104  */
  105 
  106 static void lmc_shutdown(void *arg);
  107 static int lmc_busdma_init(lmc_softc_t * const sc);
  108 static int lmc_busdma_allocmem(lmc_softc_t * const sc, size_t size,
  109         bus_dmamap_t *map_p, lmc_desc_t **desc_p);
  110 
  111 static int
  112 lmc_pci_probe(struct device *parent,
  113                void *match,
  114                void *aux)
  115 {
  116         struct pci_attach_args *pa = (struct pci_attach_args *)aux;
  117         u_int32_t id;
  118 
  119         /*
  120          * check first for the DEC chip we expect to find.  We expect
  121          * 21140A, pass 2.2 or higher.
  122          */
  123         if (PCI_VENDORID(pa->pa_id) != PCI_VENDOR_DEC)
  124                 return 0;
  125         if (PCI_CHIPID(pa->pa_id) != PCI_PRODUCT_DEC_21140)
  126                 return 0;
  127         id = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CFRV) & 0xff;
  128         if (id < 0x22)
  129                 return 0;
  130 
  131         /*
  132          * Next, check the subsystem ID and see if it matches what we
  133          * expect.
  134          */
  135         id = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SSID);
  136         if (PCI_VENDORID(id) != PCI_VENDOR_LMC)
  137                 return 0;
  138         if ((PCI_CHIPID(id) != PCI_PRODUCT_LMC_HSSI)
  139             && (PCI_CHIPID(id) != PCI_PRODUCT_LMC_HSSIC)
  140             && (PCI_CHIPID(id) != PCI_PRODUCT_LMC_DS3)
  141             && (PCI_CHIPID(id) != PCI_PRODUCT_LMC_SSI)
  142             && (PCI_CHIPID(id) != PCI_PRODUCT_LMC_DS1))
  143                 return 0;
  144 
  145         return 20; /* must be > than any other tulip driver */
  146 }
  147 
  148 static void  lmc_pci_attach(struct device * const parent,
  149                              struct device * const self, void * const aux);
  150 
  151 struct cfattach lmc_ca = {
  152     sizeof(lmc_softc_t), lmc_pci_probe, lmc_pci_attach
  153 };
  154 
  155 struct cfdriver lmc_cd = {
  156         0, "lmc", DV_IFNET
  157 };
  158 
  159 static void
  160 lmc_pci_attach(struct device * const parent,
  161                 struct device * const self, void * const aux)
  162 {
  163         u_int32_t revinfo, cfdainfo, id, ssid;
  164         pci_intr_handle_t intrhandle;
  165         const char *intrstr;
  166         unsigned csroffset = LMC_PCI_CSROFFSET;
  167         unsigned csrsize = LMC_PCI_CSRSIZE;
  168         lmc_csrptr_t csr_base;
  169         lmc_spl_t s;
  170         lmc_intrfunc_t (*intr_rtn)(void *) = lmc_intr_normal;
  171         lmc_softc_t * const sc = (lmc_softc_t *) self;
  172         struct pci_attach_args * const pa = (struct pci_attach_args *) aux;
  173         extern lmc_media_t lmc_hssi_media;
  174         extern lmc_media_t lmc_ds3_media;
  175         extern lmc_media_t lmc_t1_media;
  176         extern lmc_media_t lmc_ssi_media;
  177 
  178         revinfo  = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CFRV) & 0xFF;
  179         id       = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CFID);
  180         cfdainfo = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CFDA);
  181         ssid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SSID);
  182 
  183         switch (PCI_CHIPID(ssid)) {
  184         case PCI_PRODUCT_LMC_HSSI:
  185                 printf(": HSSI\n");
  186                 sc->lmc_media = &lmc_hssi_media;
  187                 break;
  188         case PCI_PRODUCT_LMC_HSSIC:
  189                 printf(": HSSIc\n");
  190                 sc->lmc_media = &lmc_hssi_media;
  191                 break;
  192         case PCI_PRODUCT_LMC_DS3:
  193                 printf(": DS3\n");
  194                 sc->lmc_media = &lmc_ds3_media;
  195                 break;
  196         case PCI_PRODUCT_LMC_SSI:
  197                 printf(": SSI\n");
  198                 sc->lmc_media = &lmc_ssi_media;
  199                 break;
  200         case PCI_PRODUCT_LMC_DS1:
  201                 printf(": T1\n");
  202                 sc->lmc_media = &lmc_t1_media;
  203                 break;
  204         }
  205 
  206         sc->lmc_pci_busno = parent;
  207         sc->lmc_pci_devno = pa->pa_device;
  208 
  209         sc->lmc_chipid = LMC_21140A;
  210         sc->lmc_features |= LMC_HAVE_STOREFWD;
  211         if (sc->lmc_chipid == LMC_21140A && revinfo <= 0x22)
  212                 sc->lmc_features |= LMC_HAVE_RXBADOVRFLW;
  213 
  214         if (cfdainfo & (TULIP_CFDA_SLEEP | TULIP_CFDA_SNOOZE)) {
  215                 cfdainfo &= ~(TULIP_CFDA_SLEEP | TULIP_CFDA_SNOOZE);
  216                 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_CFDA, cfdainfo);
  217                 DELAY(11 * 1000);
  218         }
  219 
  220         bcopy(self->dv_xname, sc->lmc_if.if_xname, IFNAMSIZ);
  221         sc->lmc_if.if_softc = sc;
  222         sc->lmc_pc = pa->pa_pc;
  223 
  224         sc->lmc_revinfo = revinfo;
  225         sc->lmc_if.if_softc = sc;
  226 
  227         csr_base = 0;
  228         {
  229                 bus_space_tag_t iot, memt;
  230                 bus_space_handle_t ioh, memh;
  231                 int ioh_valid, memh_valid;
  232 
  233                 ioh_valid = (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO,
  234                     0, &iot, &ioh, NULL, NULL, 0) == 0);
  235                 memh_valid = (pci_mapreg_map(pa, PCI_CBMA,
  236                     PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &memt,
  237                     &memh, NULL, NULL, 0) == 0);
  238 
  239                 if (memh_valid) {
  240                         sc->lmc_bustag = memt;
  241                         sc->lmc_bushandle = memh;
  242                 } else if (ioh_valid) {
  243                         sc->lmc_bustag = iot;
  244                         sc->lmc_bushandle = ioh;
  245                 } else {
  246                         printf("%s: unable to map device registers\n",
  247                                sc->lmc_dev.dv_xname);
  248                         return;
  249                 }
  250         }
  251 
  252         sc->lmc_dmatag = pa->pa_dmat;
  253         if ((lmc_busdma_init(sc)) != 0) {
  254                 printf("error initing bus_dma\n");
  255                 return;
  256         }
  257 
  258         lmc_initcsrs(sc, csr_base + csroffset, csrsize);
  259         lmc_initring(sc, &sc->lmc_rxinfo, sc->lmc_rxdescs,
  260                        LMC_RXDESCS);
  261         lmc_initring(sc, &sc->lmc_txinfo, sc->lmc_txdescs,
  262                        LMC_TXDESCS);
  263 
  264         lmc_gpio_mkinput(sc, 0xff);
  265         sc->lmc_gpio = 0;  /* drive no signals yet */
  266 
  267         sc->lmc_media->defaults(sc);
  268 
  269         sc->lmc_media->set_link_status(sc, LMC_LINK_DOWN); /* down */
  270 
  271         /*
  272          * Make sure there won't be any interrupts or such...
  273          */
  274         LMC_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
  275 
  276         /*
  277          * Wait 10 microseconds (actually 50 PCI cycles but at 
  278          * 33MHz that comes to two microseconds but wait a
  279          * bit longer anyways)
  280          */
  281         DELAY(100);
  282 
  283         lmc_read_macaddr(sc);
  284 
  285         if (pci_intr_map(pa, &intrhandle)) {
  286                  printf("%s: couldn't map interrupt\n",
  287                         sc->lmc_dev.dv_xname);
  288                 return;
  289         }
  290         intrstr = pci_intr_string(pa->pa_pc, intrhandle);
  291 
  292         sc->lmc_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_NET,
  293                                                 intr_rtn, sc, self->dv_xname);
  294 
  295         if (sc->lmc_ih == NULL) {
  296                 printf("%s: couldn't establish interrupt",
  297                        sc->lmc_dev.dv_xname);
  298                 if (intrstr != NULL)
  299                         printf(" at %s", intrstr);
  300                 printf("\n");
  301                 return;
  302         }
  303 
  304         printf("%s: pass %d.%d, serial " LMC_EADDR_FMT ", %s\n",
  305                sc->lmc_dev.dv_xname,
  306                (sc->lmc_revinfo & 0xF0) >> 4, sc->lmc_revinfo & 0x0F,
  307                LMC_EADDR_ARGS(sc->lmc_enaddr), intrstr);
  308 
  309         sc->lmc_ats = shutdownhook_establish(lmc_shutdown, sc);
  310         if (sc->lmc_ats == NULL)
  311                 printf("%s: warning: couldn't establish shutdown hook\n",
  312                        sc->lmc_xname);
  313 
  314         s = LMC_RAISESPL();
  315         lmc_dec_reset(sc);
  316         lmc_reset(sc);
  317         lmc_attach(sc);
  318         LMC_RESTORESPL(s);
  319 }
  320 
  321 static void
  322 lmc_shutdown(void *arg)
  323 {
  324         lmc_softc_t * const sc = arg;
  325         LMC_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
  326         DELAY(10);
  327 
  328         sc->lmc_miireg16 = 0;  /* deassert ready, and all others too */
  329         lmc_led_on(sc, LMC_MII16_LED_ALL);
  330 }
  331 
  332 static int
  333 lmc_busdma_allocmem(
  334     lmc_softc_t * const sc,
  335     size_t size,
  336     bus_dmamap_t *map_p,
  337     lmc_desc_t **desc_p)
  338 {
  339     bus_dma_segment_t segs[1];
  340     int nsegs, error;
  341     error = bus_dmamem_alloc(sc->lmc_dmatag, size, 1, NBPG,
  342                              segs, sizeof(segs)/sizeof(segs[0]),
  343                              &nsegs, BUS_DMA_NOWAIT);
  344     if (error == 0) {
  345         void *desc;
  346         error = bus_dmamem_map(sc->lmc_dmatag, segs, nsegs, size,
  347                                (void *) &desc, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
  348         if (error == 0) {
  349             bus_dmamap_t map;
  350             error = bus_dmamap_create(sc->lmc_dmatag, size, 1, size, 0,
  351                                       BUS_DMA_NOWAIT, &map);
  352             if (error == 0) {
  353                 error = bus_dmamap_load(sc->lmc_dmatag, map, desc,
  354                                         size, NULL, BUS_DMA_NOWAIT);
  355                 if (error)
  356                     bus_dmamap_destroy(sc->lmc_dmatag, map);
  357                 else
  358                     *map_p = map;
  359             }
  360             if (error)
  361                 bus_dmamem_unmap(sc->lmc_dmatag, desc, size);
  362         }
  363         if (error)
  364             bus_dmamem_free(sc->lmc_dmatag, segs, nsegs);
  365         else
  366             *desc_p = desc;
  367     }
  368     return error;
  369 }
  370 
  371 static int
  372 lmc_busdma_init(
  373     lmc_softc_t * const sc)
  374 {
  375     int error = 0;
  376 
  377     /*
  378      * Allocate space and dmamap for transmit ring
  379      */
  380     if (error == 0) {
  381         error = lmc_busdma_allocmem(sc, sizeof(lmc_desc_t) * LMC_TXDESCS,
  382                                       &sc->lmc_txdescmap,
  383                                       &sc->lmc_txdescs);
  384     }
  385 
  386     /*
  387      * Allocate dmamaps for each transmit descriptors
  388      */
  389     if (error == 0) {
  390         while (error == 0 && sc->lmc_txmaps_free < LMC_TXDESCS) {
  391             bus_dmamap_t map;
  392             if ((error = LMC_TXMAP_CREATE(sc, &map)) == 0)
  393                 sc->lmc_txmaps[sc->lmc_txmaps_free++] = map;
  394         }
  395         if (error) {
  396             while (sc->lmc_txmaps_free > 0) 
  397                 bus_dmamap_destroy(sc->lmc_dmatag,
  398                                    sc->lmc_txmaps[--sc->lmc_txmaps_free]);
  399         }
  400     }
  401 
  402     /*
  403      * Allocate space and dmamap for receive ring
  404      */
  405     if (error == 0) {
  406         error = lmc_busdma_allocmem(sc, sizeof(lmc_desc_t) * LMC_RXDESCS,
  407                                       &sc->lmc_rxdescmap,
  408                                       &sc->lmc_rxdescs);
  409     }
  410 
  411     /*
  412      * Allocate dmamaps for each receive descriptors
  413      */
  414     if (error == 0) {
  415         while (error == 0 && sc->lmc_rxmaps_free < LMC_RXDESCS) {
  416             bus_dmamap_t map;
  417             if ((error = LMC_RXMAP_CREATE(sc, &map)) == 0)
  418                 sc->lmc_rxmaps[sc->lmc_rxmaps_free++] = map;
  419         }
  420         if (error) {
  421             while (sc->lmc_rxmaps_free > 0) 
  422                 bus_dmamap_destroy(sc->lmc_dmatag,
  423                                    sc->lmc_rxmaps[--sc->lmc_rxmaps_free]);
  424         }
  425     }
  426 
  427     return error;
  428 }

/* [<][>][^][v][top][bottom][index][help] */