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/patm/if_patm_attach.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) 2003
    3  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
    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  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  * Author: Hartmut Brandt <harti@freebsd.org>
   28  *
   29  * Driver for IDT77252 based cards like ProSum's.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD: releng/6.0/sys/dev/patm/if_patm_attach.c 151143 2005-10-09 04:18:18Z delphij $");
   34 
   35 #include "opt_inet.h"
   36 #include "opt_natm.h"
   37 
   38 #include <sys/types.h>
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/malloc.h>
   42 #include <sys/kernel.h>
   43 #include <sys/bus.h>
   44 #include <sys/errno.h>
   45 #include <sys/conf.h>
   46 #include <sys/module.h>
   47 #include <sys/lock.h>
   48 #include <sys/mutex.h>
   49 #include <sys/sysctl.h>
   50 #include <sys/queue.h>
   51 #include <sys/condvar.h>
   52 #include <vm/uma.h>
   53 
   54 #include <sys/sockio.h>
   55 #include <sys/mbuf.h>
   56 #include <sys/socket.h>
   57 
   58 #include <net/if.h>
   59 #include <net/if_media.h>
   60 #include <net/if_types.h>
   61 #include <net/if_atm.h>
   62 #include <net/route.h>
   63 #ifdef ENABLE_BPF
   64 #include <net/bpf.h>
   65 #endif
   66 #include <netinet/in.h>
   67 #include <netinet/if_atm.h>
   68 
   69 #include <machine/bus.h>
   70 #include <machine/resource.h>
   71 #include <sys/bus.h>
   72 #include <sys/rman.h>
   73 #include <sys/mbpool.h>
   74 #include <dev/pci/pcireg.h>
   75 #include <dev/pci/pcivar.h>
   76 
   77 #include <dev/utopia/utopia.h>
   78 #include <dev/patm/idt77252reg.h>
   79 #include <dev/patm/if_patmvar.h>
   80 
   81 MODULE_DEPEND(patm, utopia, 1, 1, 1);
   82 MODULE_DEPEND(patm, pci, 1, 1, 1);
   83 MODULE_DEPEND(patm, atm, 1, 1, 1);
   84 MODULE_DEPEND(patm, libmbpool, 1, 1, 1);
   85 
   86 devclass_t patm_devclass;
   87 
   88 static int patm_probe(device_t dev);
   89 static int patm_attach(device_t dev);
   90 static int patm_detach(device_t dev);
   91 static device_method_t patm_methods[] = {
   92         DEVMETHOD(device_probe,         patm_probe),
   93         DEVMETHOD(device_attach,        patm_attach),
   94         DEVMETHOD(device_detach,        patm_detach),
   95         {0,0}
   96 };
   97 static driver_t patm_driver = {
   98         "patm",
   99         patm_methods,
  100         sizeof(struct patm_softc),
  101 };
  102 DRIVER_MODULE(patm, pci, patm_driver, patm_devclass, NULL, 0);
  103 
  104 static const struct {
  105         u_int   devid;
  106         const char *desc;
  107 } devs[] = {
  108         { PCI_DEVICE_IDT77252,  "NICStAR (77222/77252) ATM adapter" },
  109         { PCI_DEVICE_IDT77v252, "NICStAR (77v252) ATM adapter" },
  110         { PCI_DEVICE_IDT77v222, "NICStAR (77v222) ATM adapter" },
  111         { 0, NULL }
  112 };
  113 
  114 SYSCTL_DECL(_hw_atm);
  115 
  116 static int patm_phy_readregs(struct ifatm *, u_int, uint8_t *, u_int *);
  117 static int patm_phy_writereg(struct ifatm *, u_int, u_int, u_int);
  118 static const struct utopia_methods patm_utopia_methods = {
  119         patm_phy_readregs,
  120         patm_phy_writereg
  121 };
  122 
  123 static void patm_destroy(struct patm_softc *sc);
  124 
  125 static int patm_sysctl_istats(SYSCTL_HANDLER_ARGS);
  126 static int patm_sysctl_eeprom(SYSCTL_HANDLER_ARGS);
  127 
  128 static void patm_read_eeprom(struct patm_softc *sc);
  129 static int patm_sq_init(struct patm_softc *sc);
  130 static int patm_rbuf_init(struct patm_softc *sc);
  131 static int patm_txmap_init(struct patm_softc *sc);
  132 
  133 static void patm_env_getuint(struct patm_softc *, u_int *, const char *);
  134 
  135 #ifdef PATM_DEBUG
  136 static int patm_sysctl_regs(SYSCTL_HANDLER_ARGS);
  137 static int patm_sysctl_tsq(SYSCTL_HANDLER_ARGS);
  138 int patm_dump_vc(u_int unit, u_int vc) __unused;
  139 int patm_dump_regs(u_int unit) __unused;
  140 int patm_dump_sram(u_int unit, u_int from, u_int words) __unused;
  141 #endif
  142 
  143 /*
  144  * Probe for a IDT77252 controller
  145  */
  146 static int
  147 patm_probe(device_t dev)
  148 {
  149         u_int i;
  150 
  151         if (pci_get_vendor(dev) == PCI_VENDOR_IDT) {
  152                 for (i = 0; devs[i].desc != NULL; i++)
  153                         if (pci_get_device(dev) == devs[i].devid) {
  154                                 device_set_desc(dev, devs[i].desc);
  155                                 return (BUS_PROBE_DEFAULT);
  156                         }
  157         }
  158         return (ENXIO);
  159 }
  160 
  161 /*
  162  * Attach
  163  */
  164 static int
  165 patm_attach(device_t dev)
  166 {
  167         struct patm_softc *sc;
  168         int error;
  169         struct ifnet *ifp;
  170         int rid;
  171         u_int a;
  172 
  173         static const struct idt_mmap idt_mmap[4] = IDT_MMAP;
  174 
  175         sc = device_get_softc(dev);
  176 
  177         sc->dev = dev;
  178 #ifdef IATM_DEBUG
  179         sc->debug = IATM_DEBUG;
  180 #endif
  181         ifp = sc->ifp = if_alloc(IFT_ATM);
  182         if (ifp == NULL) {
  183                 return (ENOSPC);
  184         }
  185 
  186         IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_IDTABR25;
  187         IFP2IFATM(sc->ifp)->mib.serial = 0;
  188         IFP2IFATM(sc->ifp)->mib.hw_version = 0;
  189         IFP2IFATM(sc->ifp)->mib.sw_version = 0;
  190         IFP2IFATM(sc->ifp)->mib.vpi_bits = PATM_VPI_BITS;
  191         IFP2IFATM(sc->ifp)->mib.vci_bits = 0;   /* set below */;
  192         IFP2IFATM(sc->ifp)->mib.max_vpcs = 0;
  193         IFP2IFATM(sc->ifp)->mib.max_vccs = 0;   /* set below */
  194         IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_UNKNOWN;
  195         IFP2IFATM(sc->ifp)->phy = &sc->utopia;
  196 
  197         ifp->if_softc = sc;
  198         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
  199         ifp->if_flags = IFF_SIMPLEX;
  200         ifp->if_watchdog = NULL;
  201         ifp->if_init = patm_init;
  202         ifp->if_ioctl = patm_ioctl;
  203         ifp->if_start = patm_start;
  204         ifp->if_watchdog = NULL;
  205 
  206         /* do this early so we can destroy unconditionally */
  207         mtx_init(&sc->mtx, device_get_nameunit(dev),
  208             MTX_NETWORK_LOCK, MTX_DEF);
  209         mtx_init(&sc->tst_lock, "tst lock", NULL, MTX_DEF);
  210         cv_init(&sc->vcc_cv, "vcc_close");
  211 
  212         callout_init(&sc->tst_callout, CALLOUT_MPSAFE);
  213 
  214         sysctl_ctx_init(&sc->sysctl_ctx);
  215 
  216         /*
  217          * Get revision
  218          */
  219         sc->revision = pci_read_config(dev, PCIR_REVID, 4) & 0xf;
  220 
  221         /*
  222          * Enable PCI bus master and memory
  223          */
  224         pci_enable_busmaster(dev);
  225 
  226         rid = IDT_PCI_REG_MEMBASE;
  227         sc->memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  228             RF_ACTIVE);
  229         if (sc->memres == NULL) {
  230                 patm_printf(sc, "could not map memory\n");
  231                 error = ENXIO;
  232                 goto fail;
  233         }
  234         sc->memh = rman_get_bushandle(sc->memres);
  235         sc->memt = rman_get_bustag(sc->memres);
  236 
  237         /*
  238          * Allocate the interrupt (enable it later)
  239          */
  240         sc->irqid = 0;
  241         sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
  242             RF_SHAREABLE | RF_ACTIVE);
  243         if (sc->irqres == 0) {
  244                 patm_printf(sc, "could not allocate irq\n");
  245                 error = ENXIO;
  246                 goto fail;
  247         }
  248 
  249         /*
  250          * Construct the sysctl tree
  251          */
  252         error = ENOMEM;
  253         if ((sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
  254             SYSCTL_STATIC_CHILDREN(_hw_atm), OID_AUTO,
  255             device_get_nameunit(dev), CTLFLAG_RD, 0, "")) == NULL)
  256                 goto fail;
  257 
  258         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
  259             OID_AUTO, "istats", CTLFLAG_RD, sc, 0, patm_sysctl_istats,
  260             "S", "internal statistics") == NULL)
  261                 goto fail;
  262 
  263         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
  264             OID_AUTO, "eeprom", CTLFLAG_RD, sc, 0, patm_sysctl_eeprom,
  265             "S", "EEPROM contents") == NULL)
  266                 goto fail;
  267 
  268         if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
  269             OID_AUTO, "lbuf_max", CTLFLAG_RD, &sc->lbuf_max,
  270             0, "maximum number of large receive buffers") == NULL)
  271                 goto fail;
  272         patm_env_getuint(sc, &sc->lbuf_max, "lbuf_max");
  273 
  274         if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
  275             OID_AUTO, "max_txmaps", CTLFLAG_RW, &sc->tx_maxmaps,
  276             0, "maximum number of TX DMA maps") == NULL)
  277                 goto fail;
  278         patm_env_getuint(sc, &sc->tx_maxmaps, "tx_maxmaps");
  279 
  280 #ifdef PATM_DEBUG
  281         if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
  282             OID_AUTO, "debug", CTLFLAG_RW, &sc->debug,
  283             0, "debug flags") == NULL)
  284                 goto fail;
  285         sc->debug = PATM_DEBUG;
  286         patm_env_getuint(sc, &sc->debug, "debug");
  287 
  288         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
  289             OID_AUTO, "regs", CTLFLAG_RD, sc, 0, patm_sysctl_regs,
  290             "S", "registers") == NULL)
  291                 goto fail;
  292 
  293         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
  294             OID_AUTO, "tsq", CTLFLAG_RD, sc, 0, patm_sysctl_tsq,
  295             "S", "TSQ") == NULL)
  296                 goto fail;
  297 #endif
  298 
  299         patm_reset(sc);
  300 
  301         /*
  302          * Detect and attach the phy.
  303          */
  304         patm_debug(sc, ATTACH, "attaching utopia");
  305         IFP2IFATM(sc->ifp)->phy = &sc->utopia;
  306         utopia_attach(&sc->utopia, IFP2IFATM(sc->ifp), &sc->media, &sc->mtx,
  307             &sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
  308             &patm_utopia_methods);
  309 
  310         /*
  311          * Start the PHY because we need the autodetection
  312          */
  313         patm_debug(sc, ATTACH, "starting utopia");
  314         mtx_lock(&sc->mtx);
  315         utopia_start(&sc->utopia);
  316         utopia_reset(&sc->utopia);
  317         mtx_unlock(&sc->mtx);
  318 
  319         /* Read EEPROM */
  320         patm_read_eeprom(sc);
  321 
  322         /* analyze it */
  323         if (strncmp(sc->eeprom + PATM_PROATM_NAME_OFFSET, PATM_PROATM_NAME,
  324             strlen(PATM_PROATM_NAME)) == 0) {
  325                 if (sc->utopia.chip->type == UTP_TYPE_IDT77105) {
  326                         IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_PROATM25;
  327                         IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_25_6M;
  328                         IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_UTP_25;
  329                         sc->flags |= PATM_25M;
  330                         patm_printf(sc, "ProATM 25 interface; ");
  331 
  332                 } else {
  333                         /* cannot really know which media */
  334                         IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_PROATM155;
  335                         IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_155M;
  336                         IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_MM_155;
  337                         patm_printf(sc, "ProATM 155 interface; ");
  338                 }
  339 
  340                 bcopy(sc->eeprom + PATM_PROATM_MAC_OFFSET, IFP2IFATM(sc->ifp)->mib.esi,
  341                     sizeof(IFP2IFATM(sc->ifp)->mib.esi));
  342 
  343         } else {
  344                 if (sc->utopia.chip->type == UTP_TYPE_IDT77105) {
  345                         IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_IDTABR25;
  346                         IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_25_6M;
  347                         IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_UTP_25;
  348                         sc->flags |= PATM_25M;
  349                         patm_printf(sc, "IDT77252 25MBit interface; ");
  350 
  351                 } else {
  352                         /* cannot really know which media */
  353                         IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_IDTABR155;
  354                         IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_155M;
  355                         IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_MM_155;
  356                         patm_printf(sc, "IDT77252 155MBit interface; ");
  357                 }
  358 
  359                 bcopy(sc->eeprom + PATM_IDT_MAC_OFFSET, IFP2IFATM(sc->ifp)->mib.esi,
  360                     sizeof(IFP2IFATM(sc->ifp)->mib.esi));
  361         }
  362         printf("idt77252 Rev. %c; %s PHY\n", 'A' + sc->revision,
  363             sc->utopia.chip->name);
  364 
  365         utopia_reset_media(&sc->utopia);
  366         utopia_init_media(&sc->utopia);
  367 
  368         /*
  369          * Determine RAM size
  370          */
  371         for (a = 0; a < 0x20000; a++)
  372                 patm_sram_write(sc, a, 0);
  373         patm_sram_write(sc, 0, 0xdeadbeef);
  374         if (patm_sram_read(sc, 0x4004) == 0xdeadbeef)
  375                 sc->mmap = &idt_mmap[0];
  376         else if (patm_sram_read(sc, 0x8000) == 0xdeadbeef)
  377                 sc->mmap = &idt_mmap[1];
  378         else if (patm_sram_read(sc, 0x20000) == 0xdeadbeef)
  379                 sc->mmap = &idt_mmap[2];
  380         else
  381                 sc->mmap = &idt_mmap[3];
  382 
  383         IFP2IFATM(sc->ifp)->mib.vci_bits = sc->mmap->vcbits - IFP2IFATM(sc->ifp)->mib.vpi_bits;
  384         IFP2IFATM(sc->ifp)->mib.max_vccs = sc->mmap->max_conn;
  385         patm_sram_write(sc, 0, 0);
  386         patm_printf(sc, "%uK x 32 SRAM; %u connections\n", sc->mmap->sram,
  387             sc->mmap->max_conn);
  388 
  389         /* initialize status queues */
  390         error = patm_sq_init(sc);
  391         if (error != 0)
  392                 goto fail;
  393 
  394         /* get TST */
  395         sc->tst_soft = malloc(sizeof(uint32_t) * sc->mmap->tst_size,
  396             M_DEVBUF, M_WAITOK);
  397 
  398         /* allocate all the receive buffer stuff */
  399         error = patm_rbuf_init(sc);
  400         if (error != 0)
  401                 goto fail;
  402 
  403         /*
  404          * Allocate SCD tag
  405          *
  406          * Don't use BUS_DMA_ALLOCNOW, because we never need bouncing with
  407          * bus_dmamem_alloc()
  408          */
  409         error = bus_dma_tag_create(NULL, PAGE_SIZE, 0,
  410             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
  411             NULL, NULL, sizeof(struct patm_scd), 1,
  412             sizeof(struct patm_scd), 0, NULL, NULL, &sc->scd_tag);
  413         if (error) {
  414                 patm_printf(sc, "SCD DMA tag create %d\n", error);
  415                 goto fail;
  416         }
  417         LIST_INIT(&sc->scd_list);
  418 
  419         /* allocate VCC zone and pointers */
  420         if ((sc->vcc_zone = uma_zcreate("PATM vccs", sizeof(struct patm_vcc),
  421             NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0)) == NULL) {
  422                 patm_printf(sc, "cannot allocate zone for vccs\n");
  423                 goto fail;
  424         }
  425         sc->vccs = malloc(sizeof(sc->vccs[0]) * sc->mmap->max_conn,
  426             M_DEVBUF, M_WAITOK | M_ZERO);
  427 
  428         /* allocate transmission resources */
  429         error = patm_txmap_init(sc);
  430         if (error != 0)
  431                 goto fail;
  432 
  433         /* poll while we are not running */
  434         sc->utopia.flags |= UTP_FL_POLL_CARRIER;
  435 
  436         patm_debug(sc, ATTACH, "attaching interface");
  437         atm_ifattach(ifp);
  438 
  439 #ifdef ENABLE_BPF
  440         bpfattach(ifp, DLT_ATM_RFC1483, sizeof(struct atmllc));
  441 #endif
  442 
  443         patm_debug(sc, ATTACH, "attaching interrupt handler");
  444         error = bus_setup_intr(dev, sc->irqres, INTR_TYPE_NET, patm_intr,
  445             sc, &sc->ih);
  446         if (error != 0) {
  447                 patm_printf(sc, "could not setup interrupt\n");
  448                 atm_ifdetach(sc->ifp);
  449                 if_free(sc->ifp);
  450                 goto fail;
  451         }
  452 
  453         return (0);
  454 
  455   fail:
  456         patm_destroy(sc);
  457         return (error);
  458 }
  459 
  460 /*
  461  * Detach
  462  */
  463 static int
  464 patm_detach(device_t dev)
  465 {
  466         struct patm_softc *sc;
  467 
  468         sc = device_get_softc(dev);
  469 
  470         mtx_lock(&sc->mtx);
  471         patm_stop(sc);
  472         if (sc->utopia.state & UTP_ST_ATTACHED) {
  473                 patm_debug(sc, ATTACH, "detaching utopia");
  474                 utopia_stop(&sc->utopia);
  475                 utopia_detach(&sc->utopia);
  476         }
  477         mtx_unlock(&sc->mtx);
  478 
  479         atm_ifdetach(sc->ifp);
  480 
  481         patm_destroy(sc);
  482 
  483         return (0);
  484 }
  485 
  486 /*
  487  * Destroy everything. Assume we are stopped.
  488  */
  489 static void
  490 patm_destroy(struct patm_softc *sc)
  491 {
  492         u_int i;
  493         struct patm_txmap *map;
  494 
  495         if (sc->ih != NULL)
  496                 bus_teardown_intr(sc->dev, sc->irqres, sc->ih);
  497 
  498         if (sc->tx_mapzone != NULL) {
  499                 /* all maps must be free */
  500                 while ((map = SLIST_FIRST(&sc->tx_maps_free)) != NULL) {
  501                         bus_dmamap_destroy(sc->tx_tag, map->map);
  502                         SLIST_REMOVE_HEAD(&sc->tx_maps_free, link);
  503                         uma_zfree(sc->tx_mapzone, map);
  504                 }
  505                 uma_zdestroy(sc->tx_mapzone);
  506         }
  507 
  508         if (sc->scd_tag != NULL)
  509                 bus_dma_tag_destroy(sc->scd_tag);
  510 
  511         if (sc->tx_tag != NULL)
  512                 bus_dma_tag_destroy(sc->scd_tag);
  513 
  514         if (sc->vccs != NULL) {
  515                 for (i = 0; i < sc->mmap->max_conn; i++)
  516                         if (sc->vccs[i] != NULL)
  517                                 uma_zfree(sc->vcc_zone, sc->vccs[i]);
  518                 free(sc->vccs, M_DEVBUF);
  519         }
  520         if (sc->vcc_zone != NULL)
  521                 uma_zdestroy(sc->vcc_zone);
  522 
  523         if (sc->lbufs != NULL) {
  524                 for (i = 0; i < sc->lbuf_max; i++)
  525                         bus_dmamap_destroy(sc->lbuf_tag, sc->lbufs[i].map);
  526                 free(sc->lbufs, M_DEVBUF);
  527         }
  528 
  529         if (sc->lbuf_tag != NULL)
  530                 bus_dma_tag_destroy(sc->lbuf_tag);
  531 
  532         if (sc->sbuf_pool != NULL)
  533                 mbp_destroy(sc->sbuf_pool);
  534         if (sc->vbuf_pool != NULL)
  535                 mbp_destroy(sc->vbuf_pool);
  536 
  537         if (sc->sbuf_tag != NULL)
  538                 bus_dma_tag_destroy(sc->sbuf_tag);
  539 
  540         if (sc->tst_soft != NULL)
  541                 free(sc->tst_soft, M_DEVBUF);
  542 
  543         /*
  544          * Free all status queue memory resources
  545          */
  546         if (sc->tsq != NULL) {
  547                 bus_dmamap_unload(sc->sq_tag, sc->sq_map);
  548                 bus_dmamem_free(sc->sq_tag, sc->tsq, sc->sq_map);
  549                 bus_dma_tag_destroy(sc->sq_tag);
  550         }
  551 
  552         if (sc->irqres != NULL)
  553                 bus_release_resource(sc->dev, SYS_RES_IRQ,
  554                     sc->irqid, sc->irqres);
  555         if (sc->memres != NULL)
  556                 bus_release_resource(sc->dev, SYS_RES_MEMORY,
  557                     IDT_PCI_REG_MEMBASE, sc->memres);
  558 
  559         /* this was initialize unconditionally */
  560         sysctl_ctx_free(&sc->sysctl_ctx);
  561         cv_destroy(&sc->vcc_cv);
  562         mtx_destroy(&sc->tst_lock);
  563         mtx_destroy(&sc->mtx);
  564 
  565         if (sc->ifp != NULL)
  566                 if_free(sc->ifp);
  567 }
  568 
  569 /*
  570  * Try to find a variable in the environment and parse it as an unsigned
  571  * integer.
  572  */
  573 static void
  574 patm_env_getuint(struct patm_softc *sc, u_int *var, const char *name)
  575 {
  576         char full[IFNAMSIZ + 3 + 20];
  577         char *val, *end;
  578         u_long u;
  579 
  580         snprintf(full, sizeof(full), "hw.%s.%s",
  581             device_get_nameunit(sc->dev), name);
  582 
  583         if ((val = getenv(full)) != NULL) {
  584                 u = strtoul(val, &end, 0);
  585                 if (end > val && *end == '\0') {
  586                         if (bootverbose)
  587                                 patm_printf(sc, "%s=%lu\n", full, u);
  588                         *var = u;
  589                 }
  590                 freeenv(val);
  591         }
  592 }
  593 
  594 /*
  595  * Sysctl handler for internal statistics
  596  *
  597  * LOCK: unlocked, needed
  598  */
  599 static int
  600 patm_sysctl_istats(SYSCTL_HANDLER_ARGS)
  601 {
  602         struct patm_softc *sc = arg1;
  603         uint32_t *ret;
  604         int error;
  605 
  606         ret = malloc(sizeof(sc->stats), M_TEMP, M_WAITOK);
  607 
  608         mtx_lock(&sc->mtx);
  609         bcopy(&sc->stats, ret, sizeof(sc->stats));
  610         mtx_unlock(&sc->mtx);
  611 
  612         error = SYSCTL_OUT(req, ret, sizeof(sc->stats));
  613         free(ret, M_TEMP);
  614 
  615         return (error);
  616 }
  617 
  618 /*
  619  * Sysctl handler for EEPROM
  620  *
  621  * LOCK: unlocked, needed
  622  */
  623 static int
  624 patm_sysctl_eeprom(SYSCTL_HANDLER_ARGS)
  625 {
  626         struct patm_softc *sc = arg1;
  627         void *ret;
  628         int error;
  629 
  630         ret = malloc(sizeof(sc->eeprom), M_TEMP, M_WAITOK);
  631 
  632         mtx_lock(&sc->mtx);
  633         bcopy(sc->eeprom, ret, sizeof(sc->eeprom));
  634         mtx_unlock(&sc->mtx);
  635 
  636         error = SYSCTL_OUT(req, ret, sizeof(sc->eeprom));
  637         free(ret, M_TEMP);
  638 
  639         return (error);
  640 }
  641 
  642 /*
  643  * Read the EEPROM. We assume that this is a XIRCOM 25020
  644  */
  645 static void
  646 patm_read_eeprom(struct patm_softc *sc)
  647 {
  648         u_int gp;
  649         uint8_t byte;
  650         int i, addr;
  651 
  652         static const uint32_t tab[] = {
  653                 /* CS transition to reset the chip */
  654                 IDT_GP_EECS | IDT_GP_EESCLK,    0,
  655                 /* read command 0x03 */
  656                 IDT_GP_EESCLK,                  0,
  657                 IDT_GP_EESCLK,                  0,
  658                 IDT_GP_EESCLK,                  0,
  659                 IDT_GP_EESCLK,                  0,
  660                 IDT_GP_EESCLK,                  0,
  661                 IDT_GP_EESCLK,                  IDT_GP_EEDO,
  662                 IDT_GP_EESCLK | IDT_GP_EEDO,    IDT_GP_EEDO,
  663                 IDT_GP_EESCLK | IDT_GP_EEDO,    0,
  664                 /* address 0x00 */
  665                 IDT_GP_EESCLK,                  0,
  666                 IDT_GP_EESCLK,                  0,
  667                 IDT_GP_EESCLK,                  0,
  668                 IDT_GP_EESCLK,                  0,
  669                 IDT_GP_EESCLK,                  0,
  670                 IDT_GP_EESCLK,                  0,
  671                 IDT_GP_EESCLK,                  0,
  672                 IDT_GP_EESCLK,                  0,
  673         };
  674 
  675         /* go to a known state (chip enabled) */
  676         gp = patm_nor_read(sc, IDT_NOR_GP);
  677         gp &= ~(IDT_GP_EESCLK | IDT_GP_EECS | IDT_GP_EEDO);
  678 
  679         for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
  680                 patm_nor_write(sc, IDT_NOR_GP, gp | tab[i]);
  681                 DELAY(40);
  682         }
  683 
  684         /* read out the prom */
  685         for (addr = 0; addr < 256; addr++) {
  686                 byte = 0;
  687                 for (i = 0; i < 8; i++) {
  688                         byte <<= 1;
  689                         if (patm_nor_read(sc, IDT_NOR_GP) & IDT_GP_EEDI)
  690                                 byte |= 1;
  691                         /* rising CLK */
  692                         patm_nor_write(sc, IDT_NOR_GP, gp | IDT_GP_EESCLK);
  693                         DELAY(40);
  694                         /* falling clock */
  695                         patm_nor_write(sc, IDT_NOR_GP, gp);
  696                         DELAY(40);
  697                 }
  698                 sc->eeprom[addr] = byte;
  699         }
  700 }
  701 
  702 /*
  703  * PHY access read
  704  */
  705 static int
  706 patm_phy_readregs(struct ifatm *ifatm, u_int reg, uint8_t *val, u_int *n)
  707 {
  708         struct patm_softc *sc = ifatm->ifp->if_softc;
  709         u_int cnt = *n;
  710 
  711         if (reg >= 0x100)
  712                 return (EINVAL);
  713 
  714         patm_cmd_wait(sc);
  715         while (reg < 0x100 && cnt > 0) {
  716                 patm_nor_write(sc, IDT_NOR_CMD, IDT_MKCMD_RUTIL(1, 0, reg));
  717                 patm_cmd_wait(sc);
  718                 *val = patm_nor_read(sc, IDT_NOR_D0);
  719                 patm_debug(sc, PHY, "phy(%02x)=%02x", reg, *val);
  720                 val++;
  721                 reg++;
  722                 cnt--;
  723         }
  724         *n = *n - cnt;
  725         return (0);
  726 }
  727 
  728 /*
  729  * Write PHY reg
  730  */
  731 static int
  732 patm_phy_writereg(struct ifatm *ifatm, u_int reg, u_int mask, u_int val)
  733 {
  734         struct patm_softc *sc = ifatm->ifp->if_softc;
  735         u_int old, new;
  736 
  737         if (reg >= 0x100)
  738                 return (EINVAL);
  739 
  740         patm_cmd_wait(sc);
  741         patm_nor_write(sc, IDT_NOR_CMD, IDT_MKCMD_RUTIL(1, 0, reg));
  742         patm_cmd_wait(sc);
  743 
  744         old = patm_nor_read(sc, IDT_NOR_D0);
  745         new = (old & ~mask) | (val & mask);
  746         patm_debug(sc, PHY, "phy(%02x) %02x -> %02x", reg, old, new);
  747             
  748         patm_nor_write(sc, IDT_NOR_D0, new);
  749         patm_nor_write(sc, IDT_NOR_CMD, IDT_MKCMD_WUTIL(1, 0, reg));
  750         patm_cmd_wait(sc);
  751 
  752         return (0);
  753 }
  754 
  755 /*
  756  * Allocate a large chunk of DMA able memory for the transmit
  757  * and receive status queues. We align this to a page boundary
  758  * to ensure the alignment.
  759  */
  760 static int
  761 patm_sq_init(struct patm_softc *sc)
  762 {
  763         int error;
  764         void *p;
  765 
  766         /* compute size of the two queues */
  767         sc->sq_size = IDT_TSQ_SIZE * IDT_TSQE_SIZE +
  768             PATM_RSQ_SIZE * IDT_RSQE_SIZE +
  769             IDT_RAWHND_SIZE;
  770 
  771         patm_debug(sc, ATTACH,
  772             "allocating status queues (%zu) ...", sc->sq_size);
  773 
  774         /*
  775          * allocate tag
  776          * Don't use BUS_DMA_ALLOCNOW, because we never need bouncing with
  777          * bus_dmamem_alloc()
  778          */
  779         error = bus_dma_tag_create(NULL, PATM_SQ_ALIGNMENT, 0,
  780             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
  781             NULL, NULL, sc->sq_size, 1, sc->sq_size,
  782             0, NULL, NULL, &sc->sq_tag);
  783         if (error) {
  784                 patm_printf(sc, "memory DMA tag create %d\n", error);
  785                 return (error);
  786         }
  787 
  788         /* allocate memory */
  789         error = bus_dmamem_alloc(sc->sq_tag, &p, 0, &sc->sq_map);
  790         if (error) {
  791                 patm_printf(sc, "memory DMA alloc %d\n", error);
  792                 bus_dma_tag_destroy(sc->sq_tag);
  793                 return (error);
  794         }
  795 
  796         /* map it */
  797         sc->tsq_phy = 0x1fff;
  798         error = bus_dmamap_load(sc->sq_tag, sc->sq_map, p,
  799             sc->sq_size, patm_load_callback, &sc->tsq_phy, BUS_DMA_NOWAIT);
  800         if (error) {
  801                 patm_printf(sc, "memory DMA map load %d\n", error);
  802                 bus_dmamem_free(sc->sq_tag, p, sc->sq_map);
  803                 bus_dma_tag_destroy(sc->sq_tag);
  804                 return (error);
  805         }
  806 
  807         /* set queue start */
  808         sc->tsq = p;
  809         sc->rsq = (void *)((char *)p + IDT_TSQ_SIZE * IDT_TSQE_SIZE);
  810         sc->rsq_phy = sc->tsq_phy + IDT_TSQ_SIZE * IDT_TSQE_SIZE;
  811         sc->rawhnd = (void *)((char *)sc->rsq + PATM_RSQ_SIZE * IDT_RSQE_SIZE);
  812         sc->rawhnd_phy = sc->rsq_phy + PATM_RSQ_SIZE * IDT_RSQE_SIZE;
  813 
  814         return (0);
  815 }
  816 
  817 /*
  818  * Initialize all receive buffer stuff
  819  */
  820 static int
  821 patm_rbuf_init(struct patm_softc *sc)
  822 {
  823         u_int i;
  824         int error;
  825 
  826         patm_debug(sc, ATTACH, "allocating Rx buffer resources ...");
  827         /*
  828          * Create a tag for small buffers. We allocate these page wise.
  829          * Don't use BUS_DMA_ALLOCNOW, because we never need bouncing with
  830          * bus_dmamem_alloc()
  831          */
  832         if ((error = bus_dma_tag_create(NULL, PAGE_SIZE, 0,
  833             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
  834             SMBUF_PAGE_SIZE, 1, SMBUF_PAGE_SIZE, 0,
  835             NULL, NULL, &sc->sbuf_tag)) != 0) {
  836                 patm_printf(sc, "sbuf DMA tag create %d\n", error);
  837                 return (error);
  838         }
  839 
  840         error = mbp_create(&sc->sbuf_pool, "patm sbufs", sc->sbuf_tag,
  841             SMBUF_MAX_PAGES, SMBUF_PAGE_SIZE, SMBUF_CHUNK_SIZE);
  842         if (error != 0) {
  843                 patm_printf(sc, "smbuf pool create %d\n", error);
  844                 return (error);
  845         }
  846 
  847         error = mbp_create(&sc->vbuf_pool, "patm vbufs", sc->sbuf_tag,
  848             VMBUF_MAX_PAGES, SMBUF_PAGE_SIZE, VMBUF_CHUNK_SIZE);
  849         if (error != 0) {
  850                 patm_printf(sc, "vmbuf pool create %d\n", error);
  851                 return (error);
  852         }
  853 
  854         /*
  855          * Create a tag for large buffers.
  856          * Don't use BUS_DMA_ALLOCNOW, because it makes no sense with multiple
  857          * maps using one tag. Rather use BUS_DMA_NOWAIT when loading the map
  858          * to prevent EINPROGRESS.
  859          */
  860         if ((error = bus_dma_tag_create(NULL, 4, 0,
  861             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
  862             MCLBYTES, 1, MCLBYTES, 0, 
  863             NULL, NULL, &sc->lbuf_tag)) != 0) {
  864                 patm_printf(sc, "lbuf DMA tag create %d\n", error);
  865                 return (error);
  866         }
  867 
  868         if (sc->lbuf_max < IDT_FBQ_SIZE)
  869                 sc->lbuf_max = LMBUF_MAX;
  870         sc->lbufs = malloc(sizeof(sc->lbufs[0]) * sc->lbuf_max,
  871             M_DEVBUF, M_ZERO | M_WAITOK);
  872 
  873         SLIST_INIT(&sc->lbuf_free_list);
  874         for (i = 0; i < sc->lbuf_max; i++) {
  875                 struct lmbuf *b = &sc->lbufs[i];
  876 
  877                 error = bus_dmamap_create(sc->lbuf_tag, 0, &b->map);
  878                 if (error) {
  879                         /* must deallocate here, because a test for NULL
  880                          * does not work on most archs */
  881                         while (i-- > 0)
  882                                 bus_dmamap_destroy(sc->lbuf_tag,
  883                                     sc->lbufs[i].map);
  884                         free(sc->lbufs, M_DEVBUF);
  885                         sc->lbufs = NULL;
  886                         return (error);
  887                 }
  888                 b->handle = i;
  889                 SLIST_INSERT_HEAD(&sc->lbuf_free_list, b, link);
  890         }
  891 
  892         return (0);
  893 }
  894 
  895 /*
  896  * Allocate everything needed for the transmission maps.
  897  */
  898 static int
  899 patm_txmap_init(struct patm_softc *sc)
  900 {
  901         int error;
  902         struct patm_txmap *map;
  903 
  904         /* get transmission tag */
  905         error = bus_dma_tag_create(NULL, 1, 0,
  906             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
  907             NULL, NULL, 65536, IDT_SCQ_SIZE - 1, 65536,
  908             0, NULL, NULL, &sc->tx_tag);
  909         if (error) {
  910                 patm_printf(sc, "cannot allocate TX tag %d\n", error);
  911                 return (error);
  912         }
  913 
  914         if ((sc->tx_mapzone = uma_zcreate("PATM tx maps",
  915             sizeof(struct patm_txmap), NULL, NULL, NULL, NULL,
  916             UMA_ALIGN_PTR, 0)) == NULL)
  917                 return (ENOMEM);
  918 
  919         if (sc->tx_maxmaps < PATM_CFG_TXMAPS_MAX)
  920                 sc->tx_maxmaps = PATM_CFG_TXMAPS_MAX;
  921         sc->tx_nmaps = PATM_CFG_TXMAPS_INIT;
  922 
  923         for (sc->tx_nmaps = 0; sc->tx_nmaps < PATM_CFG_TXMAPS_INIT;
  924             sc->tx_nmaps++) {
  925                 map = uma_zalloc(sc->tx_mapzone, M_WAITOK);
  926                 error = bus_dmamap_create(sc->tx_tag, 0, &map->map);
  927                 if (error) {
  928                         uma_zfree(sc->tx_mapzone, map);
  929                         return (ENOMEM);
  930                 }
  931                 SLIST_INSERT_HEAD(&sc->tx_maps_free, map, link);
  932         }
  933 
  934         return (0);
  935 }
  936 
  937 #ifdef PATM_DEBUG
  938 
  939 /*
  940  * Sysctl handler for REGS
  941  *
  942  * LOCK: unlocked, needed
  943  */
  944 static int
  945 patm_sysctl_regs(SYSCTL_HANDLER_ARGS)
  946 {
  947         struct patm_softc *sc = arg1;
  948         uint32_t *ret;
  949         int error, i;
  950 
  951         ret = malloc(IDT_NOR_END, M_TEMP, M_WAITOK);
  952 
  953         mtx_lock(&sc->mtx);
  954         for (i = 0; i < IDT_NOR_END; i += 4)
  955                 ret[i / 4] = patm_nor_read(sc, i);
  956         mtx_unlock(&sc->mtx);
  957 
  958         error = SYSCTL_OUT(req, ret, IDT_NOR_END);
  959         free(ret, M_TEMP);
  960 
  961         return (error);
  962 }
  963 
  964 /*
  965  * Sysctl handler for TSQ
  966  *
  967  * LOCK: unlocked, needed
  968  */
  969 static int
  970 patm_sysctl_tsq(SYSCTL_HANDLER_ARGS)
  971 {
  972         struct patm_softc *sc = arg1;
  973         void *ret;
  974         int error;
  975 
  976         ret = malloc(IDT_TSQ_SIZE * IDT_TSQE_SIZE, M_TEMP, M_WAITOK);
  977 
  978         mtx_lock(&sc->mtx);
  979         memcpy(ret, sc->tsq, IDT_TSQ_SIZE * IDT_TSQE_SIZE);
  980         mtx_unlock(&sc->mtx);
  981 
  982         error = SYSCTL_OUT(req, ret, IDT_TSQ_SIZE * IDT_TSQE_SIZE);
  983         free(ret, M_TEMP);
  984 
  985         return (error);
  986 }
  987 
  988 /*
  989  * debugging
  990  */
  991 static struct patm_softc *
  992 patm_dump_unit(u_int unit)
  993 {
  994         devclass_t dc;
  995         struct patm_softc *sc;
  996 
  997         dc = devclass_find("patm");
  998         if (dc == NULL) {
  999                 printf("%s: can't find devclass\n", __func__);
 1000                 return (NULL);
 1001         }
 1002         sc = devclass_get_softc(dc, unit);
 1003         if (sc == NULL) {
 1004                 printf("%s: invalid unit number: %d\n", __func__, unit);
 1005                 return (NULL);
 1006         }
 1007         return (sc);
 1008 }
 1009 
 1010 int
 1011 patm_dump_vc(u_int unit, u_int vc)
 1012 {
 1013         struct patm_softc *sc;
 1014         uint32_t tct[8];
 1015         uint32_t rct[4];
 1016         uint32_t scd[12];
 1017         u_int i;
 1018 
 1019         if ((sc = patm_dump_unit(unit)) == NULL)
 1020                 return (0);
 1021 
 1022         for (i = 0; i < 8; i++)
 1023                 tct[i] = patm_sram_read(sc, vc * 8 + i);
 1024         for (i = 0; i < 4; i++)
 1025                 rct[i] = patm_sram_read(sc, sc->mmap->rct + vc * 4 + i);
 1026         for (i = 0; i < 12; i++)
 1027                 scd[i] = patm_sram_read(sc, (tct[0] & 0x7ffff) + i);
 1028 
 1029         printf("TCT%3u: %08x %08x %08x %08x  %08x %08x %08x %08x\n", vc,
 1030             tct[0], tct[1], tct[2], tct[3], tct[4], tct[5], tct[6], tct[7]);
 1031         printf("RCT%3u: %08x %08x %08x %08x\n", vc,
 1032             rct[0], rct[1], rct[2], rct[3]);
 1033         printf("SCD%3u: %08x %08x %08x %08x  %08x %08x %08x %08x\n", vc,
 1034             scd[0], scd[1], scd[2], scd[3], scd[4], scd[5], scd[6], scd[7]);
 1035         printf("        %08x %08x %08x %08x\n",
 1036             scd[8], scd[9], scd[10], scd[11]);
 1037 
 1038         return (0);
 1039 }
 1040 
 1041 int
 1042 patm_dump_regs(u_int unit)
 1043 {
 1044         struct patm_softc *sc;
 1045         u_int i;
 1046 
 1047         if ((sc = patm_dump_unit(unit)) == NULL)
 1048                 return (0);
 1049 
 1050         for (i = 0; i <= IDT_NOR_DNOW; i += 4)
 1051                 printf("%x: %08x\n", i, patm_nor_read(sc, i));
 1052 
 1053         return (0);
 1054 }
 1055 
 1056 int
 1057 patm_dump_sram(u_int unit, u_int from, u_int words)
 1058 {
 1059         struct patm_softc *sc;
 1060         u_int i;
 1061 
 1062         if ((sc = patm_dump_unit(unit)) == NULL)
 1063                 return (0);
 1064 
 1065         for (i = 0; i < words; i++) {
 1066                 if (i % 8 == 0)
 1067                         printf("%05x:", from + i);
 1068                 printf(" %08x", patm_sram_read(sc, from + i));
 1069                 if (i % 8 == 7)
 1070                         printf("\n");
 1071         }
 1072         if (i % 8 != 0)
 1073                 printf("\n");
 1074         return (0);
 1075 }
 1076 #endif

Cache object: cd391716e02006e2f48f4e0ac3514cc2


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