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/hatm/if_hatm.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) 2001-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  * ForeHE driver.
   30  *
   31  * This file contains the module and driver infrastructure stuff as well
   32  * as a couple of utility functions and the entire initialisation.
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD$");
   37 
   38 #include "opt_inet.h"
   39 #include "opt_natm.h"
   40 
   41 #include <sys/types.h>
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/malloc.h>
   45 #include <sys/kernel.h>
   46 #include <sys/bus.h>
   47 #include <sys/errno.h>
   48 #include <sys/conf.h>
   49 #include <sys/module.h>
   50 #include <sys/queue.h>
   51 #include <sys/syslog.h>
   52 #include <sys/lock.h>
   53 #include <sys/mutex.h>
   54 #include <sys/condvar.h>
   55 #include <sys/sysctl.h>
   56 #include <vm/uma.h>
   57 
   58 #include <sys/sockio.h>
   59 #include <sys/mbuf.h>
   60 #include <sys/socket.h>
   61 
   62 #include <net/if.h>
   63 #include <net/if_media.h>
   64 #include <net/if_atm.h>
   65 #include <net/if_types.h>
   66 #include <net/route.h>
   67 #ifdef ENABLE_BPF
   68 #include <net/bpf.h>
   69 #endif
   70 #include <netinet/in.h>
   71 #include <netinet/if_atm.h>
   72 
   73 #include <machine/bus.h>
   74 #include <machine/resource.h>
   75 #include <sys/bus.h>
   76 #include <sys/rman.h>
   77 #include <dev/pci/pcireg.h>
   78 #include <dev/pci/pcivar.h>
   79 
   80 #include <dev/utopia/utopia.h>
   81 #include <dev/hatm/if_hatmconf.h>
   82 #include <dev/hatm/if_hatmreg.h>
   83 #include <dev/hatm/if_hatmvar.h>
   84 
   85 static const struct {
   86         uint16_t        vid;
   87         uint16_t        did;
   88         const char      *name;
   89 } hatm_devs[] = {
   90         { 0x1127, 0x400,
   91           "FORE HE" },
   92         { 0, 0, NULL }
   93 };
   94 
   95 SYSCTL_DECL(_hw_atm);
   96 
   97 MODULE_DEPEND(hatm, utopia, 1, 1, 1);
   98 MODULE_DEPEND(hatm, pci, 1, 1, 1);
   99 MODULE_DEPEND(hatm, atm, 1, 1, 1);
  100 
  101 #define EEPROM_DELAY    400 /* microseconds */
  102 
  103 /* Read from EEPROM 0000 0011b */
  104 static const uint32_t readtab[] = {
  105         HE_REGM_HOST_PROM_SEL | HE_REGM_HOST_PROM_CLOCK,
  106         0,
  107         HE_REGM_HOST_PROM_CLOCK,
  108         0,                              /* 0 */
  109         HE_REGM_HOST_PROM_CLOCK,        
  110         0,                              /* 0 */
  111         HE_REGM_HOST_PROM_CLOCK,
  112         0,                              /* 0 */
  113         HE_REGM_HOST_PROM_CLOCK,
  114         0,                              /* 0 */
  115         HE_REGM_HOST_PROM_CLOCK,
  116         0,                              /* 0 */
  117         HE_REGM_HOST_PROM_CLOCK,
  118         HE_REGM_HOST_PROM_DATA_IN,      /* 0 */
  119         HE_REGM_HOST_PROM_CLOCK | HE_REGM_HOST_PROM_DATA_IN,
  120         HE_REGM_HOST_PROM_DATA_IN,      /* 1 */
  121         HE_REGM_HOST_PROM_CLOCK | HE_REGM_HOST_PROM_DATA_IN,
  122         HE_REGM_HOST_PROM_DATA_IN,      /* 1 */
  123 };
  124 static const uint32_t clocktab[] = {
  125         0, HE_REGM_HOST_PROM_CLOCK,
  126         0, HE_REGM_HOST_PROM_CLOCK,
  127         0, HE_REGM_HOST_PROM_CLOCK,
  128         0, HE_REGM_HOST_PROM_CLOCK,
  129         0, HE_REGM_HOST_PROM_CLOCK,
  130         0, HE_REGM_HOST_PROM_CLOCK,
  131         0, HE_REGM_HOST_PROM_CLOCK,
  132         0, HE_REGM_HOST_PROM_CLOCK,
  133         0
  134 };
  135 
  136 /*
  137  * Convert cell rate to ATM Forum format
  138  */
  139 u_int
  140 hatm_cps2atmf(uint32_t pcr)
  141 {
  142         u_int e;
  143 
  144         if (pcr == 0)
  145                 return (0);
  146         pcr <<= 9;
  147         e = 0;
  148         while (pcr > (1024 - 1)) {
  149                 e++;
  150                 pcr >>= 1;
  151         }
  152         return ((1 << 14) | (e << 9) | (pcr & 0x1ff));
  153 }
  154 u_int
  155 hatm_atmf2cps(uint32_t fcr)
  156 {
  157         fcr &= 0x7fff;
  158 
  159         return ((1 << ((fcr >> 9) & 0x1f)) * (512 + (fcr & 0x1ff)) / 512
  160           * (fcr >> 14));
  161 }
  162 
  163 /************************************************************
  164  *
  165  * Initialisation
  166  */
  167 /*
  168  * Probe for a HE controller
  169  */
  170 static int
  171 hatm_probe(device_t dev)
  172 {
  173         int i;
  174 
  175         for (i = 0; hatm_devs[i].name; i++)
  176                 if (pci_get_vendor(dev) == hatm_devs[i].vid &&
  177                     pci_get_device(dev) == hatm_devs[i].did) {
  178                         device_set_desc(dev, hatm_devs[i].name);
  179                         return (BUS_PROBE_DEFAULT);
  180                 }
  181         return (ENXIO);
  182 }
  183 
  184 /*
  185  * Allocate and map DMA-able memory. We support only contiguous mappings.
  186  */
  187 static void
  188 dmaload_helper(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
  189 {
  190         if (error)
  191                 return;
  192         KASSERT(nsegs == 1, ("too many segments for DMA: %d", nsegs));
  193         KASSERT(segs[0].ds_addr <= 0xffffffffUL,
  194             ("phys addr too large %lx", (u_long)segs[0].ds_addr));
  195 
  196         *(bus_addr_t *)arg = segs[0].ds_addr;
  197 }
  198 static int
  199 hatm_alloc_dmamem(struct hatm_softc *sc, const char *what, struct dmamem *mem)
  200 {
  201         int error;
  202 
  203         mem->base = NULL;
  204 
  205         /*
  206          * Alignement does not work in the bus_dmamem_alloc function below
  207          * on FreeBSD. malloc seems to align objects at least to the object
  208          * size so increase the size to the alignment if the size is lesser
  209          * than the alignemnt.
  210          * XXX on sparc64 this is (probably) not needed.
  211          */
  212         if (mem->size < mem->align)
  213                 mem->size = mem->align;
  214 
  215         error = bus_dma_tag_create(sc->parent_tag, mem->align, 0,
  216             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
  217             NULL, NULL, mem->size, 1,
  218             BUS_SPACE_MAXSIZE_32BIT, BUS_DMA_ALLOCNOW,
  219             NULL, NULL, &mem->tag);
  220         if (error) {
  221                 if_printf(sc->ifp, "DMA tag create (%s)\n", what);
  222                 return (error);
  223         }
  224 
  225         error = bus_dmamem_alloc(mem->tag, &mem->base, 0, &mem->map);
  226         if (error) {
  227                 if_printf(sc->ifp, "DMA mem alloc (%s): %d\n",
  228                     what, error);
  229                 bus_dma_tag_destroy(mem->tag);
  230                 mem->base = NULL;
  231                 return (error);
  232         }
  233 
  234         error = bus_dmamap_load(mem->tag, mem->map, mem->base, mem->size,
  235             dmaload_helper, &mem->paddr, BUS_DMA_NOWAIT);
  236         if (error) {
  237                 if_printf(sc->ifp, "DMA map load (%s): %d\n",
  238                     what, error);
  239                 bus_dmamem_free(mem->tag, mem->base, mem->map);
  240                 bus_dma_tag_destroy(mem->tag);
  241                 mem->base = NULL;
  242                 return (error);
  243         }
  244 
  245         DBG(sc, DMA, ("%s S/A/V/P 0x%x 0x%x %p 0x%lx", what, mem->size,
  246             mem->align, mem->base, (u_long)mem->paddr));
  247 
  248         return (0);
  249 }
  250 
  251 /*
  252  * Destroy all the resources of an DMA-able memory region.
  253  */
  254 static void
  255 hatm_destroy_dmamem(struct dmamem *mem)
  256 {
  257         if (mem->base != NULL) {
  258                 bus_dmamap_unload(mem->tag, mem->map);
  259                 bus_dmamem_free(mem->tag, mem->base, mem->map);
  260                 (void)bus_dma_tag_destroy(mem->tag);
  261                 mem->base = NULL;
  262         }
  263 }
  264 
  265 /*
  266  * Initialize/destroy DMA maps for the large pool 0
  267  */
  268 static void
  269 hatm_destroy_rmaps(struct hatm_softc *sc)
  270 {
  271         u_int b;
  272 
  273         DBG(sc, ATTACH, ("destroying rmaps and lbuf pointers..."));
  274         if (sc->rmaps != NULL) {
  275                 for (b = 0; b < sc->lbufs_size; b++)
  276                         bus_dmamap_destroy(sc->mbuf_tag, sc->rmaps[b]);
  277                 free(sc->rmaps, M_DEVBUF);
  278         }
  279         if (sc->lbufs != NULL)
  280                 free(sc->lbufs, M_DEVBUF);
  281 }
  282 
  283 static void
  284 hatm_init_rmaps(struct hatm_softc *sc)
  285 {
  286         u_int b;
  287         int err;
  288 
  289         DBG(sc, ATTACH, ("allocating rmaps and lbuf pointers..."));
  290         sc->lbufs = malloc(sizeof(sc->lbufs[0]) * sc->lbufs_size,
  291             M_DEVBUF, M_ZERO | M_WAITOK);
  292 
  293         /* allocate and create the DMA maps for the large pool */
  294         sc->rmaps = malloc(sizeof(sc->rmaps[0]) * sc->lbufs_size,
  295             M_DEVBUF, M_WAITOK);
  296         for (b = 0; b < sc->lbufs_size; b++) {
  297                 err = bus_dmamap_create(sc->mbuf_tag, 0, &sc->rmaps[b]);
  298                 if (err != 0)
  299                         panic("bus_dmamap_create: %d\n", err);
  300         }
  301 }
  302 
  303 /*
  304  * Initialize and destroy small mbuf page pointers and pages
  305  */
  306 static void
  307 hatm_destroy_smbufs(struct hatm_softc *sc)
  308 {
  309         u_int i, b;
  310         struct mbuf_page *pg;
  311         struct mbuf_chunk_hdr *h;
  312 
  313         if (sc->mbuf_pages != NULL) {
  314                 for (i = 0; i < sc->mbuf_npages; i++) {
  315                         pg = sc->mbuf_pages[i];
  316                         for (b = 0; b < pg->hdr.nchunks; b++) {
  317                                 h = (struct mbuf_chunk_hdr *) ((char *)pg +
  318                                     b * pg->hdr.chunksize + pg->hdr.hdroff);
  319                                 if (h->flags & MBUF_CARD)
  320                                         if_printf(sc->ifp,
  321                                             "%s -- mbuf page=%u card buf %u\n",
  322                                             __func__, i, b);
  323                                 if (h->flags & MBUF_USED)
  324                                         if_printf(sc->ifp,
  325                                             "%s -- mbuf page=%u used buf %u\n",
  326                                             __func__, i, b);
  327                         }
  328                         bus_dmamap_unload(sc->mbuf_tag, pg->hdr.map);
  329                         bus_dmamap_destroy(sc->mbuf_tag, pg->hdr.map);
  330                         free(pg, M_DEVBUF);
  331                 }
  332                 free(sc->mbuf_pages, M_DEVBUF);
  333         }
  334 }
  335 
  336 static void
  337 hatm_init_smbufs(struct hatm_softc *sc)
  338 {
  339         sc->mbuf_pages = malloc(sizeof(sc->mbuf_pages[0]) *
  340             sc->mbuf_max_pages, M_DEVBUF, M_WAITOK);
  341         sc->mbuf_npages = 0;
  342 }
  343 
  344 /*
  345  * Initialize/destroy TPDs. This is called from attach/detach.
  346  */
  347 static void
  348 hatm_destroy_tpds(struct hatm_softc *sc)
  349 {
  350         struct tpd *t;
  351 
  352         if (sc->tpds.base == NULL)
  353                 return;
  354 
  355         DBG(sc, ATTACH, ("releasing TPDs ..."));
  356         if (sc->tpd_nfree != sc->tpd_total)
  357                 if_printf(sc->ifp, "%u tpds still in use from %u\n",
  358                     sc->tpd_total - sc->tpd_nfree, sc->tpd_total);
  359         while ((t = SLIST_FIRST(&sc->tpd_free)) != NULL) {
  360                 SLIST_REMOVE_HEAD(&sc->tpd_free, link);
  361                 bus_dmamap_destroy(sc->tx_tag, t->map);
  362         }
  363         hatm_destroy_dmamem(&sc->tpds);
  364         free(sc->tpd_used, M_DEVBUF);
  365         DBG(sc, ATTACH, ("... done"));
  366 }
  367 static int
  368 hatm_init_tpds(struct hatm_softc *sc)
  369 {
  370         int error;
  371         u_int i;
  372         struct tpd *t;
  373 
  374         DBG(sc, ATTACH, ("allocating %u TPDs and maps ...", sc->tpd_total));
  375         error = hatm_alloc_dmamem(sc, "TPD memory", &sc->tpds);
  376         if (error != 0) {
  377                 DBG(sc, ATTACH, ("... dmamem error=%d", error));
  378                 return (error);
  379         }
  380 
  381         /* put all the TPDs on the free list and allocate DMA maps */
  382         for (i = 0; i < sc->tpd_total; i++) {
  383                 t = TPD_ADDR(sc, i);
  384                 t->no = i;
  385                 t->mbuf = NULL;
  386                 error = bus_dmamap_create(sc->tx_tag, 0, &t->map);
  387                 if (error != 0) {
  388                         DBG(sc, ATTACH, ("... dmamap error=%d", error));
  389                         while ((t = SLIST_FIRST(&sc->tpd_free)) != NULL) {
  390                                 SLIST_REMOVE_HEAD(&sc->tpd_free, link);
  391                                 bus_dmamap_destroy(sc->tx_tag, t->map);
  392                         }
  393                         hatm_destroy_dmamem(&sc->tpds);
  394                         return (error);
  395                 }
  396 
  397                 SLIST_INSERT_HEAD(&sc->tpd_free, t, link);
  398         }
  399 
  400         /* allocate and zero bitmap */
  401         sc->tpd_used = malloc(sizeof(uint8_t) * (sc->tpd_total + 7) / 8,
  402             M_DEVBUF, M_ZERO | M_WAITOK);
  403         sc->tpd_nfree = sc->tpd_total;
  404 
  405         DBG(sc, ATTACH, ("... done"));
  406 
  407         return (0);
  408 }
  409 
  410 /*
  411  * Free all the TPDs that where given to the card. 
  412  * An mbuf chain may be attached to a TPD - free it also and
  413  * unload its associated DMA map.
  414  */
  415 static void
  416 hatm_stop_tpds(struct hatm_softc *sc)
  417 {
  418         u_int i;
  419         struct tpd *t;
  420 
  421         DBG(sc, ATTACH, ("free TPDs ..."));
  422         for (i = 0; i < sc->tpd_total; i++) {
  423                 if (TPD_TST_USED(sc, i)) {
  424                         t = TPD_ADDR(sc, i);
  425                         if (t->mbuf) {
  426                                 m_freem(t->mbuf);
  427                                 t->mbuf = NULL;
  428                                 bus_dmamap_unload(sc->tx_tag, t->map);
  429                         }
  430                         TPD_CLR_USED(sc, i);
  431                         SLIST_INSERT_HEAD(&sc->tpd_free, t, link);
  432                         sc->tpd_nfree++;
  433                 }
  434         }
  435 }
  436 
  437 /*
  438  * This frees ALL resources of this interface and leaves the structure
  439  * in an indeterminate state. This is called just before detaching or
  440  * on a failed attach. No lock should be held.
  441  */
  442 static void
  443 hatm_destroy(struct hatm_softc *sc)
  444 {
  445         u_int cid;
  446 
  447         bus_teardown_intr(sc->dev, sc->irqres, sc->ih);
  448 
  449         hatm_destroy_rmaps(sc);
  450         hatm_destroy_smbufs(sc);
  451         hatm_destroy_tpds(sc);
  452 
  453         if (sc->vcc_zone != NULL) {
  454                 for (cid = 0; cid < HE_MAX_VCCS; cid++)
  455                         if (sc->vccs[cid] != NULL)
  456                                 uma_zfree(sc->vcc_zone, sc->vccs[cid]);
  457                 uma_zdestroy(sc->vcc_zone);
  458         }
  459 
  460         /*
  461          * Release all memory allocated to the various queues and
  462          * Status pages. These have there own flag which shows whether
  463          * they are really allocated.
  464          */
  465         hatm_destroy_dmamem(&sc->irq_0.mem);
  466         hatm_destroy_dmamem(&sc->rbp_s0.mem);
  467         hatm_destroy_dmamem(&sc->rbp_l0.mem);
  468         hatm_destroy_dmamem(&sc->rbp_s1.mem);
  469         hatm_destroy_dmamem(&sc->rbrq_0.mem);
  470         hatm_destroy_dmamem(&sc->rbrq_1.mem);
  471         hatm_destroy_dmamem(&sc->tbrq.mem);
  472         hatm_destroy_dmamem(&sc->tpdrq.mem);
  473         hatm_destroy_dmamem(&sc->hsp_mem);
  474 
  475         if (sc->irqres != NULL)
  476                 bus_release_resource(sc->dev, SYS_RES_IRQ,
  477                     sc->irqid, sc->irqres);
  478 
  479         if (sc->tx_tag != NULL)
  480                 if (bus_dma_tag_destroy(sc->tx_tag))
  481                         if_printf(sc->ifp, "mbuf DMA tag busy\n");
  482 
  483         if (sc->mbuf_tag != NULL)
  484                 if (bus_dma_tag_destroy(sc->mbuf_tag))
  485                         if_printf(sc->ifp, "mbuf DMA tag busy\n");
  486 
  487         if (sc->parent_tag != NULL)
  488                 if (bus_dma_tag_destroy(sc->parent_tag))
  489                         if_printf(sc->ifp, "parent DMA tag busy\n");
  490 
  491         if (sc->memres != NULL)
  492                 bus_release_resource(sc->dev, SYS_RES_MEMORY,
  493                     sc->memid, sc->memres);
  494 
  495         sysctl_ctx_free(&sc->sysctl_ctx);
  496 
  497         cv_destroy(&sc->cv_rcclose);
  498         cv_destroy(&sc->vcc_cv);
  499         mtx_destroy(&sc->mtx);
  500 
  501         if (sc->ifp != NULL)
  502                 if_free(sc->ifp);
  503 }
  504 
  505 /*
  506  * 4.4 Card reset
  507  */
  508 static int
  509 hatm_reset(struct hatm_softc *sc)
  510 {
  511         u_int v, count;
  512 
  513         WRITE4(sc, HE_REGO_RESET_CNTL, 0x00);
  514         BARRIER_W(sc);
  515         WRITE4(sc, HE_REGO_RESET_CNTL, 0xff);
  516         BARRIER_RW(sc);
  517         count = 0;
  518         while (((v = READ4(sc, HE_REGO_RESET_CNTL)) & HE_REGM_RESET_STATE) == 0) {
  519                 BARRIER_R(sc);
  520                 if (++count == 100) {
  521                         if_printf(sc->ifp, "reset failed\n");
  522                         return (ENXIO);
  523                 }
  524                 DELAY(1000);
  525         }
  526         return (0);
  527 }
  528 
  529 /*
  530  * 4.5 Set Bus Width
  531  */
  532 static void
  533 hatm_init_bus_width(struct hatm_softc *sc)
  534 {
  535         uint32_t v, v1;
  536 
  537         v = READ4(sc, HE_REGO_HOST_CNTL);
  538         BARRIER_R(sc);
  539         if (v & HE_REGM_HOST_BUS64) {
  540                 sc->pci64 = 1;
  541                 v1 = pci_read_config(sc->dev, HE_PCIR_GEN_CNTL_0, 4);
  542                 v1 |= HE_PCIM_CTL0_64BIT;
  543                 pci_write_config(sc->dev, HE_PCIR_GEN_CNTL_0, v1, 4);
  544 
  545                 v |= HE_REGM_HOST_DESC_RD64
  546                     | HE_REGM_HOST_DATA_RD64
  547                     | HE_REGM_HOST_DATA_WR64;
  548                 WRITE4(sc, HE_REGO_HOST_CNTL, v);
  549                 BARRIER_W(sc);
  550         } else {
  551                 sc->pci64 = 0;
  552                 v = pci_read_config(sc->dev, HE_PCIR_GEN_CNTL_0, 4);
  553                 v &= ~HE_PCIM_CTL0_64BIT;
  554                 pci_write_config(sc->dev, HE_PCIR_GEN_CNTL_0, v, 4);
  555         }
  556 }
  557 
  558 /*
  559  * 4.6 Set Host Endianess
  560  */
  561 static void
  562 hatm_init_endianess(struct hatm_softc *sc)
  563 {
  564         uint32_t v;
  565 
  566         v = READ4(sc, HE_REGO_LB_SWAP);
  567         BARRIER_R(sc);
  568 #if BYTE_ORDER == BIG_ENDIAN
  569         v |= HE_REGM_LBSWAP_INTR_SWAP |
  570             HE_REGM_LBSWAP_DESC_WR_SWAP |
  571             HE_REGM_LBSWAP_BIG_ENDIAN;
  572         v &= ~(HE_REGM_LBSWAP_DATA_WR_SWAP |
  573             HE_REGM_LBSWAP_DESC_RD_SWAP |
  574             HE_REGM_LBSWAP_DATA_RD_SWAP);
  575 #else
  576         v &= ~(HE_REGM_LBSWAP_DATA_WR_SWAP |
  577             HE_REGM_LBSWAP_DESC_RD_SWAP |
  578             HE_REGM_LBSWAP_DATA_RD_SWAP |
  579             HE_REGM_LBSWAP_INTR_SWAP |
  580             HE_REGM_LBSWAP_DESC_WR_SWAP |
  581             HE_REGM_LBSWAP_BIG_ENDIAN);
  582 #endif
  583 
  584         if (sc->he622)
  585                 v |= HE_REGM_LBSWAP_XFER_SIZE;
  586 
  587         WRITE4(sc, HE_REGO_LB_SWAP, v);
  588         BARRIER_W(sc);
  589 }
  590 
  591 /*
  592  * 4.7 Read EEPROM
  593  */
  594 static uint8_t
  595 hatm_read_prom_byte(struct hatm_softc *sc, u_int addr)
  596 {
  597         uint32_t val, tmp_read, byte_read;
  598         u_int i, j;
  599         int n;
  600 
  601         val = READ4(sc, HE_REGO_HOST_CNTL);
  602         val &= HE_REGM_HOST_PROM_BITS;
  603         BARRIER_R(sc);
  604 
  605         val |= HE_REGM_HOST_PROM_WREN;
  606         WRITE4(sc, HE_REGO_HOST_CNTL, val);
  607         BARRIER_W(sc);
  608 
  609         /* send READ */
  610         for (i = 0; i < sizeof(readtab) / sizeof(readtab[0]); i++) {
  611                 WRITE4(sc, HE_REGO_HOST_CNTL, val | readtab[i]);
  612                 BARRIER_W(sc);
  613                 DELAY(EEPROM_DELAY);
  614         }
  615 
  616         /* send ADDRESS */
  617         for (n = 7, j = 0; n >= 0; n--) {
  618                 WRITE4(sc, HE_REGO_HOST_CNTL, val | clocktab[j++] |
  619                     (((addr >> n) & 1 ) << HE_REGS_HOST_PROM_DATA_IN));
  620                 BARRIER_W(sc);
  621                 DELAY(EEPROM_DELAY);
  622                 WRITE4(sc, HE_REGO_HOST_CNTL, val | clocktab[j++] |
  623                     (((addr >> n) & 1 ) << HE_REGS_HOST_PROM_DATA_IN));
  624                 BARRIER_W(sc);
  625                 DELAY(EEPROM_DELAY);
  626         }
  627 
  628         val &= ~HE_REGM_HOST_PROM_WREN;
  629         WRITE4(sc, HE_REGO_HOST_CNTL, val);
  630         BARRIER_W(sc);
  631 
  632         /* read DATA */
  633         byte_read = 0;
  634         for (n = 7, j = 0; n >= 0; n--) {
  635                 WRITE4(sc, HE_REGO_HOST_CNTL, val | clocktab[j++]);
  636                 BARRIER_W(sc);
  637                 DELAY(EEPROM_DELAY);
  638                 tmp_read = READ4(sc, HE_REGO_HOST_CNTL);
  639                 byte_read |= (uint8_t)(((tmp_read & HE_REGM_HOST_PROM_DATA_OUT)
  640                                 >> HE_REGS_HOST_PROM_DATA_OUT) << n);
  641                 WRITE4(sc, HE_REGO_HOST_CNTL, val | clocktab[j++]);
  642                 BARRIER_W(sc);
  643                 DELAY(EEPROM_DELAY);
  644         }
  645         WRITE4(sc, HE_REGO_HOST_CNTL, val | clocktab[j++]);
  646         BARRIER_W(sc);
  647         DELAY(EEPROM_DELAY);
  648 
  649         return (byte_read);
  650 }
  651 
  652 static void
  653 hatm_init_read_eeprom(struct hatm_softc *sc)
  654 {
  655         u_int n, count;
  656         u_char byte;
  657         uint32_t v;
  658 
  659         for (n = count = 0; count < HE_EEPROM_PROD_ID_LEN; count++) {
  660                 byte = hatm_read_prom_byte(sc, HE_EEPROM_PROD_ID + count);
  661                 if (n > 0 || byte != ' ')
  662                         sc->prod_id[n++] = byte;
  663         }
  664         while (n > 0 && sc->prod_id[n-1] == ' ')
  665                 n--;
  666         sc->prod_id[n] = '\0';
  667 
  668         for (n = count = 0; count < HE_EEPROM_REV_LEN; count++) {
  669                 byte = hatm_read_prom_byte(sc, HE_EEPROM_REV + count);
  670                 if (n > 0 || byte != ' ')
  671                         sc->rev[n++] = byte;
  672         }
  673         while (n > 0 && sc->rev[n-1] == ' ')
  674                 n--;
  675         sc->rev[n] = '\0';
  676         IFP2IFATM(sc->ifp)->mib.hw_version = sc->rev[0];
  677 
  678         IFP2IFATM(sc->ifp)->mib.serial =  hatm_read_prom_byte(sc, HE_EEPROM_M_SN + 0) << 0;
  679         IFP2IFATM(sc->ifp)->mib.serial |= hatm_read_prom_byte(sc, HE_EEPROM_M_SN + 1) << 8;
  680         IFP2IFATM(sc->ifp)->mib.serial |= hatm_read_prom_byte(sc, HE_EEPROM_M_SN + 2) << 16;
  681         IFP2IFATM(sc->ifp)->mib.serial |= hatm_read_prom_byte(sc, HE_EEPROM_M_SN + 3) << 24;
  682 
  683         v =  hatm_read_prom_byte(sc, HE_EEPROM_MEDIA + 0) << 0;
  684         v |= hatm_read_prom_byte(sc, HE_EEPROM_MEDIA + 1) << 8;
  685         v |= hatm_read_prom_byte(sc, HE_EEPROM_MEDIA + 2) << 16;
  686         v |= hatm_read_prom_byte(sc, HE_EEPROM_MEDIA + 3) << 24;
  687 
  688         switch (v) {
  689           case HE_MEDIA_UTP155:
  690                 IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_UTP_155;
  691                 IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_155M;
  692                 break;
  693 
  694           case HE_MEDIA_MMF155:
  695                 IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_MM_155;
  696                 IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_155M;
  697                 break;
  698 
  699           case HE_MEDIA_MMF622:
  700                 IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_MM_622;
  701                 IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_HE622;
  702                 IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_622M;
  703                 sc->he622 = 1;
  704                 break;
  705 
  706           case HE_MEDIA_SMF155:
  707                 IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_SM_155;
  708                 IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_155M;
  709                 break;
  710 
  711           case HE_MEDIA_SMF622:
  712                 IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_SM_622;
  713                 IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_HE622;
  714                 IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_622M;
  715                 sc->he622 = 1;
  716                 break;
  717         }
  718 
  719         IFP2IFATM(sc->ifp)->mib.esi[0] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 0);
  720         IFP2IFATM(sc->ifp)->mib.esi[1] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 1);
  721         IFP2IFATM(sc->ifp)->mib.esi[2] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 2);
  722         IFP2IFATM(sc->ifp)->mib.esi[3] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 3);
  723         IFP2IFATM(sc->ifp)->mib.esi[4] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 4);
  724         IFP2IFATM(sc->ifp)->mib.esi[5] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 5);
  725 }
  726 
  727 /*
  728  * Clear unused interrupt queue
  729  */
  730 static void
  731 hatm_clear_irq(struct hatm_softc *sc, u_int group)
  732 {
  733         WRITE4(sc, HE_REGO_IRQ_BASE(group), 0);
  734         WRITE4(sc, HE_REGO_IRQ_HEAD(group), 0);
  735         WRITE4(sc, HE_REGO_IRQ_CNTL(group), 0);
  736         WRITE4(sc, HE_REGO_IRQ_DATA(group), 0);
  737 }
  738 
  739 /*
  740  * 4.10 Initialize interrupt queues
  741  */
  742 static void
  743 hatm_init_irq(struct hatm_softc *sc, struct heirq *q, u_int group)
  744 {
  745         u_int i;
  746 
  747         if (q->size == 0) {
  748                 hatm_clear_irq(sc, group);
  749                 return;
  750         }
  751 
  752         q->group = group;
  753         q->sc = sc;
  754         q->irq = q->mem.base;
  755         q->head = 0;
  756         q->tailp = q->irq + (q->size - 1);
  757         *q->tailp = 0;
  758 
  759         for (i = 0; i < q->size; i++)
  760                 q->irq[i] = HE_REGM_ITYPE_INVALID;
  761 
  762         WRITE4(sc, HE_REGO_IRQ_BASE(group), q->mem.paddr);
  763         WRITE4(sc, HE_REGO_IRQ_HEAD(group),
  764             ((q->size - 1) << HE_REGS_IRQ_HEAD_SIZE) |
  765             (q->thresh << HE_REGS_IRQ_HEAD_THRESH));
  766         WRITE4(sc, HE_REGO_IRQ_CNTL(group), q->line);
  767         WRITE4(sc, HE_REGO_IRQ_DATA(group), 0);
  768 }
  769 
  770 /*
  771  * 5.1.3 Initialize connection memory
  772  */
  773 static void
  774 hatm_init_cm(struct hatm_softc *sc)
  775 {
  776         u_int rsra, mlbm, rabr, numbuffs;
  777         u_int tsra, tabr, mtpd;
  778         u_int n;
  779 
  780         for (n = 0; n < HE_CONFIG_TXMEM; n++)
  781                 WRITE_TCM4(sc, n, 0);
  782         for (n = 0; n < HE_CONFIG_RXMEM; n++)
  783                 WRITE_RCM4(sc, n, 0);
  784 
  785         numbuffs = sc->r0_numbuffs + sc->r1_numbuffs + sc->tx_numbuffs;
  786 
  787         rsra = 0;
  788         mlbm = ((rsra + IFP2IFATM(sc->ifp)->mib.max_vccs * 8) + 0x7ff) & ~0x7ff;
  789         rabr = ((mlbm + numbuffs * 2) + 0x7ff) & ~0x7ff;
  790         sc->rsrb = ((rabr + 2048) + (2 * IFP2IFATM(sc->ifp)->mib.max_vccs - 1)) &
  791             ~(2 * IFP2IFATM(sc->ifp)->mib.max_vccs - 1);
  792 
  793         tsra = 0;
  794         sc->tsrb = tsra + IFP2IFATM(sc->ifp)->mib.max_vccs * 8;
  795         sc->tsrc = sc->tsrb + IFP2IFATM(sc->ifp)->mib.max_vccs * 4;
  796         sc->tsrd = sc->tsrc + IFP2IFATM(sc->ifp)->mib.max_vccs * 2;
  797         tabr = sc->tsrd + IFP2IFATM(sc->ifp)->mib.max_vccs * 1;
  798         mtpd = ((tabr + 1024) + (16 * IFP2IFATM(sc->ifp)->mib.max_vccs - 1)) &
  799             ~(16 * IFP2IFATM(sc->ifp)->mib.max_vccs - 1);
  800 
  801         DBG(sc, ATTACH, ("rsra=%x mlbm=%x rabr=%x rsrb=%x",
  802             rsra, mlbm, rabr, sc->rsrb));
  803         DBG(sc, ATTACH, ("tsra=%x tsrb=%x tsrc=%x tsrd=%x tabr=%x mtpd=%x",
  804             tsra, sc->tsrb, sc->tsrc, sc->tsrd, tabr, mtpd));
  805 
  806         WRITE4(sc, HE_REGO_TSRB_BA, sc->tsrb);
  807         WRITE4(sc, HE_REGO_TSRC_BA, sc->tsrc);
  808         WRITE4(sc, HE_REGO_TSRD_BA, sc->tsrd);
  809         WRITE4(sc, HE_REGO_TMABR_BA, tabr);
  810         WRITE4(sc, HE_REGO_TPD_BA, mtpd);
  811 
  812         WRITE4(sc, HE_REGO_RCMRSRB_BA, sc->rsrb);
  813         WRITE4(sc, HE_REGO_RCMLBM_BA, mlbm);
  814         WRITE4(sc, HE_REGO_RCMABR_BA, rabr);
  815 
  816         BARRIER_W(sc);
  817 }
  818 
  819 /*
  820  * 5.1.4 Initialize Local buffer Pools
  821  */
  822 static void
  823 hatm_init_rx_buffer_pool(struct hatm_softc *sc,
  824         u_int num,              /* bank */
  825         u_int start,            /* start row */
  826         u_int numbuffs          /* number of entries */
  827 )
  828 {
  829         u_int row_size;         /* bytes per row */
  830         uint32_t row_addr;      /* start address of this row */
  831         u_int lbuf_size;        /* bytes per lbuf */
  832         u_int lbufs_per_row;    /* number of lbufs per memory row */
  833         uint32_t lbufd_index;   /* index of lbuf descriptor */
  834         uint32_t lbufd_addr;    /* address of lbuf descriptor */
  835         u_int lbuf_row_cnt;     /* current lbuf in current row */
  836         uint32_t lbuf_addr;     /* address of current buffer */
  837         u_int i;
  838 
  839         row_size = sc->bytes_per_row;
  840         row_addr = start * row_size;
  841         lbuf_size = sc->cells_per_lbuf * 48;
  842         lbufs_per_row = sc->cells_per_row / sc->cells_per_lbuf;
  843 
  844         /* descriptor index */
  845         lbufd_index = num;
  846 
  847         /* 2 words per entry */
  848         lbufd_addr = READ4(sc, HE_REGO_RCMLBM_BA) + lbufd_index * 2;
  849 
  850         /* write head of queue */
  851         WRITE4(sc, HE_REGO_RLBF_H(num), lbufd_index);
  852 
  853         lbuf_row_cnt = 0;
  854         for (i = 0; i < numbuffs; i++) {
  855                 lbuf_addr = (row_addr + lbuf_row_cnt * lbuf_size) / 32;
  856 
  857                 WRITE_RCM4(sc, lbufd_addr, lbuf_addr);
  858 
  859                 lbufd_index += 2;
  860                 WRITE_RCM4(sc, lbufd_addr + 1, lbufd_index);
  861 
  862                 if (++lbuf_row_cnt == lbufs_per_row) {
  863                         lbuf_row_cnt = 0;
  864                         row_addr += row_size;
  865                 }
  866 
  867                 lbufd_addr += 2 * 2;
  868         }
  869 
  870         WRITE4(sc, HE_REGO_RLBF_T(num), lbufd_index - 2);
  871         WRITE4(sc, HE_REGO_RLBF_C(num), numbuffs);
  872 
  873         BARRIER_W(sc);
  874 }
  875 
  876 static void
  877 hatm_init_tx_buffer_pool(struct hatm_softc *sc,
  878         u_int start,            /* start row */
  879         u_int numbuffs          /* number of entries */
  880 )
  881 {
  882         u_int row_size;         /* bytes per row */
  883         uint32_t row_addr;      /* start address of this row */
  884         u_int lbuf_size;        /* bytes per lbuf */
  885         u_int lbufs_per_row;    /* number of lbufs per memory row */
  886         uint32_t lbufd_index;   /* index of lbuf descriptor */
  887         uint32_t lbufd_addr;    /* address of lbuf descriptor */
  888         u_int lbuf_row_cnt;     /* current lbuf in current row */
  889         uint32_t lbuf_addr;     /* address of current buffer */
  890         u_int i;
  891 
  892         row_size = sc->bytes_per_row;
  893         row_addr = start * row_size;
  894         lbuf_size = sc->cells_per_lbuf * 48;
  895         lbufs_per_row = sc->cells_per_row / sc->cells_per_lbuf;
  896 
  897         /* descriptor index */
  898         lbufd_index = sc->r0_numbuffs + sc->r1_numbuffs;
  899 
  900         /* 2 words per entry */
  901         lbufd_addr = READ4(sc, HE_REGO_RCMLBM_BA) + lbufd_index * 2;
  902 
  903         /* write head of queue */
  904         WRITE4(sc, HE_REGO_TLBF_H, lbufd_index);
  905 
  906         lbuf_row_cnt = 0;
  907         for (i = 0; i < numbuffs; i++) {
  908                 lbuf_addr = (row_addr + lbuf_row_cnt * lbuf_size) / 32;
  909 
  910                 WRITE_RCM4(sc, lbufd_addr, lbuf_addr);
  911                 lbufd_index++;
  912                 WRITE_RCM4(sc, lbufd_addr + 1, lbufd_index);
  913 
  914                 if (++lbuf_row_cnt == lbufs_per_row) {
  915                         lbuf_row_cnt = 0;
  916                         row_addr += row_size;
  917                 }
  918 
  919                 lbufd_addr += 2;
  920         }
  921 
  922         WRITE4(sc, HE_REGO_TLBF_T, lbufd_index - 1);
  923         BARRIER_W(sc);
  924 }
  925 
  926 /*
  927  * 5.1.5 Initialize Intermediate Receive Queues
  928  */
  929 static void
  930 hatm_init_imed_queues(struct hatm_softc *sc)
  931 {
  932         u_int n;
  933 
  934         if (sc->he622) {
  935                 for (n = 0; n < 8; n++) {
  936                         WRITE4(sc, HE_REGO_INMQ_S(n), 0x10*n+0x000f);
  937                         WRITE4(sc, HE_REGO_INMQ_L(n), 0x10*n+0x200f);
  938                 }
  939         } else {
  940                 for (n = 0; n < 8; n++) {
  941                         WRITE4(sc, HE_REGO_INMQ_S(n), n);
  942                         WRITE4(sc, HE_REGO_INMQ_L(n), n+0x8);
  943                 }
  944         }
  945 }
  946 
  947 /*
  948  * 5.1.7 Init CS block
  949  */
  950 static void
  951 hatm_init_cs_block(struct hatm_softc *sc)
  952 {
  953         u_int n, i;
  954         u_int clkfreg, cellrate, decr, tmp;
  955         static const uint32_t erthr[2][5][3] = HE_REGT_CS_ERTHR;
  956         static const uint32_t erctl[2][3] = HE_REGT_CS_ERCTL;
  957         static const uint32_t erstat[2][2] = HE_REGT_CS_ERSTAT;
  958         static const uint32_t rtfwr[2] = HE_REGT_CS_RTFWR;
  959         static const uint32_t rtatr[2] = HE_REGT_CS_RTATR;
  960         static const uint32_t bwalloc[2][6] = HE_REGT_CS_BWALLOC;
  961         static const uint32_t orcf[2][2] = HE_REGT_CS_ORCF;
  962 
  963         /* Clear Rate Controller Start Times and Occupied Flags */
  964         for (n = 0; n < 32; n++)
  965                 WRITE_MBOX4(sc, HE_REGO_CS_STTIM(n), 0);
  966 
  967         clkfreg = sc->he622 ? HE_622_CLOCK : HE_155_CLOCK;
  968         cellrate = sc->he622 ? ATM_RATE_622M : ATM_RATE_155M;
  969         decr = cellrate / 32;
  970 
  971         for (n = 0; n < 16; n++) {
  972                 tmp = clkfreg / cellrate;
  973                 WRITE_MBOX4(sc, HE_REGO_CS_TGRLD(n), tmp - 1);
  974                 cellrate -= decr;
  975         }
  976 
  977         i = (sc->cells_per_lbuf == 2) ? 0
  978            :(sc->cells_per_lbuf == 4) ? 1
  979            :                            2;
  980 
  981         /* table 5.2 */
  982         WRITE_MBOX4(sc, HE_REGO_CS_ERTHR0, erthr[sc->he622][0][i]);
  983         WRITE_MBOX4(sc, HE_REGO_CS_ERTHR1, erthr[sc->he622][1][i]);
  984         WRITE_MBOX4(sc, HE_REGO_CS_ERTHR2, erthr[sc->he622][2][i]);
  985         WRITE_MBOX4(sc, HE_REGO_CS_ERTHR3, erthr[sc->he622][3][i]);
  986         WRITE_MBOX4(sc, HE_REGO_CS_ERTHR4, erthr[sc->he622][4][i]);
  987 
  988         WRITE_MBOX4(sc, HE_REGO_CS_ERCTL0, erctl[sc->he622][0]);
  989         WRITE_MBOX4(sc, HE_REGO_CS_ERCTL1, erctl[sc->he622][1]);
  990         WRITE_MBOX4(sc, HE_REGO_CS_ERCTL2, erctl[sc->he622][2]);
  991 
  992         WRITE_MBOX4(sc, HE_REGO_CS_ERSTAT0, erstat[sc->he622][0]);
  993         WRITE_MBOX4(sc, HE_REGO_CS_ERSTAT1, erstat[sc->he622][1]);
  994 
  995         WRITE_MBOX4(sc, HE_REGO_CS_RTFWR, rtfwr[sc->he622]);
  996         WRITE_MBOX4(sc, HE_REGO_CS_RTATR, rtatr[sc->he622]);
  997 
  998         WRITE_MBOX4(sc, HE_REGO_CS_TFBSET, bwalloc[sc->he622][0]);
  999         WRITE_MBOX4(sc, HE_REGO_CS_WCRMAX, bwalloc[sc->he622][1]);
 1000         WRITE_MBOX4(sc, HE_REGO_CS_WCRMIN, bwalloc[sc->he622][2]);
 1001         WRITE_MBOX4(sc, HE_REGO_CS_WCRINC, bwalloc[sc->he622][3]);
 1002         WRITE_MBOX4(sc, HE_REGO_CS_WCRDEC, bwalloc[sc->he622][4]);
 1003         WRITE_MBOX4(sc, HE_REGO_CS_WCRCEIL, bwalloc[sc->he622][5]);
 1004 
 1005         WRITE_MBOX4(sc, HE_REGO_CS_OTPPER, orcf[sc->he622][0]);
 1006         WRITE_MBOX4(sc, HE_REGO_CS_OTWPER, orcf[sc->he622][1]);
 1007 
 1008         WRITE_MBOX4(sc, HE_REGO_CS_OTTLIM, 8);
 1009 
 1010         for (n = 0; n < 8; n++)
 1011                 WRITE_MBOX4(sc, HE_REGO_CS_HGRRT(n), 0);
 1012 }
 1013 
 1014 /*
 1015  * 5.1.8 CS Block Connection Memory Initialisation
 1016  */
 1017 static void
 1018 hatm_init_cs_block_cm(struct hatm_softc *sc)
 1019 {
 1020         u_int n, i;
 1021         u_int expt, mant, etrm, wcr, ttnrm, tnrm;
 1022         uint32_t rate;
 1023         uint32_t clkfreq, cellrate, decr;
 1024         uint32_t *rg, rtg, val = 0;
 1025         uint64_t drate;
 1026         u_int buf, buf_limit;
 1027         uint32_t base = READ4(sc, HE_REGO_RCMABR_BA);
 1028 
 1029         for (n = 0; n < HE_REGL_CM_GQTBL; n++)
 1030                 WRITE_RCM4(sc, base + HE_REGO_CM_GQTBL + n, 0);
 1031         for (n = 0; n < HE_REGL_CM_RGTBL; n++)
 1032                 WRITE_RCM4(sc, base + HE_REGO_CM_RGTBL + n, 0);
 1033 
 1034         tnrm = 0;
 1035         for (n = 0; n < HE_REGL_CM_TNRMTBL * 4; n++) {
 1036                 expt = (n >> 5) & 0x1f;
 1037                 mant = ((n & 0x18) << 4) | 0x7f;
 1038                 wcr = (1 << expt) * (mant + 512) / 512;
 1039                 etrm = n & 0x7;
 1040                 ttnrm = wcr / 10 / (1 << etrm);
 1041                 if (ttnrm > 255)
 1042                         ttnrm = 255;
 1043                 else if(ttnrm < 2)
 1044                         ttnrm = 2;
 1045                 tnrm = (tnrm << 8) | (ttnrm & 0xff);
 1046                 if (n % 4 == 0)
 1047                         WRITE_RCM4(sc, base + HE_REGO_CM_TNRMTBL + (n/4), tnrm);
 1048         }
 1049 
 1050         clkfreq = sc->he622 ? HE_622_CLOCK : HE_155_CLOCK;
 1051         buf_limit = 4;
 1052 
 1053         cellrate = sc->he622 ? ATM_RATE_622M : ATM_RATE_155M;
 1054         decr = cellrate / 32;
 1055 
 1056         /* compute GRID top row in 1000 * cps */
 1057         for (n = 0; n < 16; n++) {
 1058                 u_int interval = clkfreq / cellrate;
 1059                 sc->rate_grid[0][n] = (u_int64_t)clkfreq * 1000 / interval;
 1060                 cellrate -= decr;
 1061         }
 1062 
 1063         /* compute the other rows according to 2.4 */
 1064         for (i = 1; i < 16; i++)
 1065                 for (n = 0; n < 16; n++)
 1066                         sc->rate_grid[i][n] = sc->rate_grid[i-1][n] /
 1067                             ((i < 14) ? 2 : 4);
 1068 
 1069         /* first entry is line rate */
 1070         n = hatm_cps2atmf(sc->he622 ? ATM_RATE_622M : ATM_RATE_155M);
 1071         expt = (n >> 9) & 0x1f;
 1072         mant = n & 0x1f0;
 1073         sc->rate_grid[0][0] = (u_int64_t)(1<<expt) * 1000 * (mant+512) / 512;
 1074 
 1075         /* now build the conversion table - each 32 bit word contains
 1076          * two entries - this gives a total of 0x400 16 bit entries.
 1077          * This table maps the truncated ATMF rate version into a grid index */
 1078         cellrate = sc->he622 ? ATM_RATE_622M : ATM_RATE_155M;
 1079         rg = &sc->rate_grid[15][15];
 1080 
 1081         for (rate = 0; rate < 2 * HE_REGL_CM_RTGTBL; rate++) {
 1082                 /* unpack the ATMF rate */
 1083                 expt = rate >> 5;
 1084                 mant = (rate & 0x1f) << 4;
 1085 
 1086                 /* get the cell rate - minimum is 10 per second */
 1087                 drate = (uint64_t)(1 << expt) * 1000 * (mant + 512) / 512;
 1088                 if (drate < 10 * 1000)
 1089                         drate = 10 * 1000;
 1090 
 1091                 /* now look up the grid index */
 1092                 while (drate >= *rg && rg-- > &sc->rate_grid[0][0])
 1093                         ;
 1094                 rg++;
 1095                 rtg = rg - &sc->rate_grid[0][0];
 1096 
 1097                 /* now compute the buffer limit */
 1098                 buf = drate * sc->tx_numbuffs / (cellrate * 2) / 1000;
 1099                 if (buf == 0)
 1100                         buf = 1;
 1101                 else if (buf > buf_limit)
 1102                         buf = buf_limit;
 1103 
 1104                 /* make value */
 1105                 val = (val << 16) | (rtg << 8) | buf;
 1106 
 1107                 /* write */
 1108                 if (rate % 2 == 1)
 1109                         WRITE_RCM4(sc, base + HE_REGO_CM_RTGTBL + rate/2, val);
 1110         }
 1111 }
 1112 
 1113 /*
 1114  * Clear an unused receive group buffer pool
 1115  */
 1116 static void
 1117 hatm_clear_rpool(struct hatm_softc *sc, u_int group, u_int large)
 1118 {
 1119         WRITE4(sc, HE_REGO_RBP_S(large, group), 0);
 1120         WRITE4(sc, HE_REGO_RBP_T(large, group), 0);
 1121         WRITE4(sc, HE_REGO_RBP_QI(large, group), 1);
 1122         WRITE4(sc, HE_REGO_RBP_BL(large, group), 0);
 1123 }
 1124 
 1125 /*
 1126  * Initialize a receive group buffer pool
 1127  */
 1128 static void
 1129 hatm_init_rpool(struct hatm_softc *sc, struct herbp *q, u_int group,
 1130     u_int large)
 1131 {
 1132         if (q->size == 0) {
 1133                 hatm_clear_rpool(sc, group, large);
 1134                 return;
 1135         }
 1136 
 1137         bzero(q->mem.base, q->mem.size);
 1138         q->rbp = q->mem.base;
 1139         q->head = q->tail = 0;
 1140 
 1141         DBG(sc, ATTACH, ("RBP%u%c=0x%lx", group, "SL"[large],
 1142             (u_long)q->mem.paddr));
 1143 
 1144         WRITE4(sc, HE_REGO_RBP_S(large, group), q->mem.paddr);
 1145         WRITE4(sc, HE_REGO_RBP_T(large, group), 0);
 1146         WRITE4(sc, HE_REGO_RBP_QI(large, group),
 1147             ((q->size - 1) << HE_REGS_RBP_SIZE) |
 1148             HE_REGM_RBP_INTR_ENB |
 1149             (q->thresh << HE_REGS_RBP_THRESH));
 1150         WRITE4(sc, HE_REGO_RBP_BL(large, group), (q->bsize >> 2) & ~1);
 1151 }
 1152 
 1153 /*
 1154  * Clear an unused receive buffer return queue
 1155  */
 1156 static void
 1157 hatm_clear_rbrq(struct hatm_softc *sc, u_int group)
 1158 {
 1159         WRITE4(sc, HE_REGO_RBRQ_ST(group), 0);
 1160         WRITE4(sc, HE_REGO_RBRQ_H(group), 0);
 1161         WRITE4(sc, HE_REGO_RBRQ_Q(group), (1 << HE_REGS_RBRQ_THRESH));
 1162         WRITE4(sc, HE_REGO_RBRQ_I(group), 0);
 1163 }
 1164 
 1165 /*
 1166  * Initialize receive buffer return queue
 1167  */
 1168 static void
 1169 hatm_init_rbrq(struct hatm_softc *sc, struct herbrq *rq, u_int group)
 1170 {
 1171         if (rq->size == 0) {
 1172                 hatm_clear_rbrq(sc, group);
 1173                 return;
 1174         }
 1175 
 1176         rq->rbrq = rq->mem.base;
 1177         rq->head = 0;
 1178 
 1179         DBG(sc, ATTACH, ("RBRQ%u=0x%lx", group, (u_long)rq->mem.paddr));
 1180 
 1181         WRITE4(sc, HE_REGO_RBRQ_ST(group), rq->mem.paddr);
 1182         WRITE4(sc, HE_REGO_RBRQ_H(group), 0);
 1183         WRITE4(sc, HE_REGO_RBRQ_Q(group),
 1184             (rq->thresh << HE_REGS_RBRQ_THRESH) |
 1185             ((rq->size - 1) << HE_REGS_RBRQ_SIZE));
 1186         WRITE4(sc, HE_REGO_RBRQ_I(group),
 1187             (rq->tout << HE_REGS_RBRQ_TIME) |
 1188             (rq->pcnt << HE_REGS_RBRQ_COUNT));
 1189 }
 1190 
 1191 /*
 1192  * Clear an unused transmit buffer return queue N
 1193  */
 1194 static void
 1195 hatm_clear_tbrq(struct hatm_softc *sc, u_int group)
 1196 {
 1197         WRITE4(sc, HE_REGO_TBRQ_B_T(group), 0);
 1198         WRITE4(sc, HE_REGO_TBRQ_H(group), 0);
 1199         WRITE4(sc, HE_REGO_TBRQ_S(group), 0);
 1200         WRITE4(sc, HE_REGO_TBRQ_THRESH(group), 1);
 1201 }
 1202 
 1203 /*
 1204  * Initialize transmit buffer return queue N
 1205  */
 1206 static void
 1207 hatm_init_tbrq(struct hatm_softc *sc, struct hetbrq *tq, u_int group)
 1208 {
 1209         if (tq->size == 0) {
 1210                 hatm_clear_tbrq(sc, group);
 1211                 return;
 1212         }
 1213 
 1214         tq->tbrq = tq->mem.base;
 1215         tq->head = 0;
 1216 
 1217         DBG(sc, ATTACH, ("TBRQ%u=0x%lx", group, (u_long)tq->mem.paddr));
 1218 
 1219         WRITE4(sc, HE_REGO_TBRQ_B_T(group), tq->mem.paddr);
 1220         WRITE4(sc, HE_REGO_TBRQ_H(group), 0);
 1221         WRITE4(sc, HE_REGO_TBRQ_S(group), tq->size - 1);
 1222         WRITE4(sc, HE_REGO_TBRQ_THRESH(group), tq->thresh);
 1223 }
 1224 
 1225 /*
 1226  * Initialize TPDRQ
 1227  */
 1228 static void
 1229 hatm_init_tpdrq(struct hatm_softc *sc)
 1230 {
 1231         struct hetpdrq *tq;
 1232 
 1233         tq = &sc->tpdrq;
 1234         tq->tpdrq = tq->mem.base;
 1235         tq->tail = tq->head = 0;
 1236 
 1237         DBG(sc, ATTACH, ("TPDRQ=0x%lx", (u_long)tq->mem.paddr));
 1238 
 1239         WRITE4(sc, HE_REGO_TPDRQ_H, tq->mem.paddr);
 1240         WRITE4(sc, HE_REGO_TPDRQ_T, 0);
 1241         WRITE4(sc, HE_REGO_TPDRQ_S, tq->size - 1);
 1242 }
 1243 
 1244 /*
 1245  * Function can be called by the infrastructure to start the card.
 1246  */
 1247 static void
 1248 hatm_init(void *p)
 1249 {
 1250         struct hatm_softc *sc = p;
 1251 
 1252         mtx_lock(&sc->mtx);
 1253         hatm_stop(sc);
 1254         hatm_initialize(sc);
 1255         mtx_unlock(&sc->mtx);
 1256 }
 1257 
 1258 enum {
 1259         CTL_ISTATS,
 1260 };
 1261 
 1262 /*
 1263  * Sysctl handler
 1264  */
 1265 static int
 1266 hatm_sysctl(SYSCTL_HANDLER_ARGS)
 1267 {
 1268         struct hatm_softc *sc = arg1;
 1269         uint32_t *ret;
 1270         int error;
 1271         size_t len;
 1272 
 1273         switch (arg2) {
 1274 
 1275           case CTL_ISTATS:
 1276                 len = sizeof(sc->istats);
 1277                 break;
 1278 
 1279           default:
 1280                 panic("bad control code");
 1281         }
 1282 
 1283         ret = malloc(len, M_TEMP, M_WAITOK);
 1284         mtx_lock(&sc->mtx);
 1285 
 1286         switch (arg2) {
 1287 
 1288           case CTL_ISTATS:
 1289                 sc->istats.mcc += READ4(sc, HE_REGO_MCC);
 1290                 sc->istats.oec += READ4(sc, HE_REGO_OEC);
 1291                 sc->istats.dcc += READ4(sc, HE_REGO_DCC);
 1292                 sc->istats.cec += READ4(sc, HE_REGO_CEC);
 1293                 bcopy(&sc->istats, ret, sizeof(sc->istats));
 1294                 break;
 1295         }
 1296         mtx_unlock(&sc->mtx);
 1297 
 1298         error = SYSCTL_OUT(req, ret, len);
 1299         free(ret, M_TEMP);
 1300 
 1301         return (error);
 1302 }
 1303 
 1304 static int
 1305 kenv_getuint(struct hatm_softc *sc, const char *var,
 1306     u_int *ptr, u_int def, int rw)
 1307 {
 1308         char full[IFNAMSIZ + 3 + 20];
 1309         char *val, *end;
 1310         u_int u;
 1311 
 1312         *ptr = def;
 1313 
 1314         if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
 1315             OID_AUTO, var, rw ? CTLFLAG_RW : CTLFLAG_RD, ptr, 0, "") == NULL)
 1316                 return (ENOMEM);
 1317 
 1318         snprintf(full, sizeof(full), "hw.%s.%s",
 1319             device_get_nameunit(sc->dev), var);
 1320 
 1321         if ((val = getenv(full)) == NULL)
 1322                 return (0);
 1323         u = strtoul(val, &end, 0);
 1324         if (end == val || *end != '\0') {
 1325                 freeenv(val);
 1326                 return (EINVAL);
 1327         }
 1328         if (bootverbose)
 1329                 if_printf(sc->ifp, "%s=%u\n", full, u);
 1330         *ptr = u;
 1331         return (0);
 1332 }
 1333 
 1334 /*
 1335  * Set configurable parameters. Many of these are configurable via
 1336  * kenv.
 1337  */
 1338 static int
 1339 hatm_configure(struct hatm_softc *sc)
 1340 {
 1341         /* Receive buffer pool 0 small */
 1342         kenv_getuint(sc, "rbps0_size", &sc->rbp_s0.size,
 1343             HE_CONFIG_RBPS0_SIZE, 0);
 1344         kenv_getuint(sc, "rbps0_thresh", &sc->rbp_s0.thresh,
 1345             HE_CONFIG_RBPS0_THRESH, 0);
 1346         sc->rbp_s0.bsize = MBUF0_SIZE;
 1347 
 1348         /* Receive buffer pool 0 large */
 1349         kenv_getuint(sc, "rbpl0_size", &sc->rbp_l0.size,
 1350             HE_CONFIG_RBPL0_SIZE, 0);
 1351         kenv_getuint(sc, "rbpl0_thresh", &sc->rbp_l0.thresh,
 1352             HE_CONFIG_RBPL0_THRESH, 0);
 1353         sc->rbp_l0.bsize = MCLBYTES - MBUFL_OFFSET;
 1354 
 1355         /* Receive buffer return queue 0 */
 1356         kenv_getuint(sc, "rbrq0_size", &sc->rbrq_0.size,
 1357             HE_CONFIG_RBRQ0_SIZE, 0);
 1358         kenv_getuint(sc, "rbrq0_thresh", &sc->rbrq_0.thresh,
 1359             HE_CONFIG_RBRQ0_THRESH, 0);
 1360         kenv_getuint(sc, "rbrq0_tout", &sc->rbrq_0.tout,
 1361             HE_CONFIG_RBRQ0_TOUT, 0);
 1362         kenv_getuint(sc, "rbrq0_pcnt", &sc->rbrq_0.pcnt,
 1363             HE_CONFIG_RBRQ0_PCNT, 0);
 1364 
 1365         /* Receive buffer pool 1 small */
 1366         kenv_getuint(sc, "rbps1_size", &sc->rbp_s1.size,
 1367             HE_CONFIG_RBPS1_SIZE, 0);
 1368         kenv_getuint(sc, "rbps1_thresh", &sc->rbp_s1.thresh,
 1369             HE_CONFIG_RBPS1_THRESH, 0);
 1370         sc->rbp_s1.bsize = MBUF1_SIZE;
 1371 
 1372         /* Receive buffer return queue 1 */
 1373         kenv_getuint(sc, "rbrq1_size", &sc->rbrq_1.size,
 1374             HE_CONFIG_RBRQ1_SIZE, 0);
 1375         kenv_getuint(sc, "rbrq1_thresh", &sc->rbrq_1.thresh,
 1376             HE_CONFIG_RBRQ1_THRESH, 0);
 1377         kenv_getuint(sc, "rbrq1_tout", &sc->rbrq_1.tout,
 1378             HE_CONFIG_RBRQ1_TOUT, 0);
 1379         kenv_getuint(sc, "rbrq1_pcnt", &sc->rbrq_1.pcnt,
 1380             HE_CONFIG_RBRQ1_PCNT, 0);
 1381 
 1382         /* Interrupt queue 0 */
 1383         kenv_getuint(sc, "irq0_size", &sc->irq_0.size,
 1384             HE_CONFIG_IRQ0_SIZE, 0);
 1385         kenv_getuint(sc, "irq0_thresh", &sc->irq_0.thresh,
 1386             HE_CONFIG_IRQ0_THRESH, 0);
 1387         sc->irq_0.line = HE_CONFIG_IRQ0_LINE;
 1388 
 1389         /* Transmit buffer return queue 0 */
 1390         kenv_getuint(sc, "tbrq0_size", &sc->tbrq.size,
 1391             HE_CONFIG_TBRQ_SIZE, 0);
 1392         kenv_getuint(sc, "tbrq0_thresh", &sc->tbrq.thresh,
 1393             HE_CONFIG_TBRQ_THRESH, 0);
 1394 
 1395         /* Transmit buffer ready queue */
 1396         kenv_getuint(sc, "tpdrq_size", &sc->tpdrq.size,
 1397             HE_CONFIG_TPDRQ_SIZE, 0);
 1398         /* Max TPDs per VCC */
 1399         kenv_getuint(sc, "tpdmax", &sc->max_tpd,
 1400             HE_CONFIG_TPD_MAXCC, 0);
 1401 
 1402         /* external mbuf pages */
 1403         kenv_getuint(sc, "max_mbuf_pages", &sc->mbuf_max_pages,
 1404             HE_CONFIG_MAX_MBUF_PAGES, 0);
 1405 
 1406         /* mpsafe */
 1407         kenv_getuint(sc, "mpsafe", &sc->mpsafe, 0, 0);
 1408         if (sc->mpsafe != 0)
 1409                 sc->mpsafe = INTR_MPSAFE;
 1410 
 1411         return (0);
 1412 }
 1413 
 1414 #ifdef HATM_DEBUG
 1415 
 1416 /*
 1417  * Get TSRs from connection memory
 1418  */
 1419 static int
 1420 hatm_sysctl_tsr(SYSCTL_HANDLER_ARGS)
 1421 {
 1422         struct hatm_softc *sc = arg1;
 1423         int error, i, j;
 1424         uint32_t *val;
 1425 
 1426         val = malloc(sizeof(uint32_t) * HE_MAX_VCCS * 15, M_TEMP, M_WAITOK);
 1427 
 1428         mtx_lock(&sc->mtx);
 1429         for (i = 0; i < HE_MAX_VCCS; i++)
 1430                 for (j = 0; j <= 14; j++)
 1431                         val[15 * i + j] = READ_TSR(sc, i, j);
 1432         mtx_unlock(&sc->mtx);
 1433 
 1434         error = SYSCTL_OUT(req, val, sizeof(uint32_t) * HE_MAX_VCCS * 15);
 1435         free(val, M_TEMP);
 1436         if (error != 0 || req->newptr == NULL)
 1437                 return (error);
 1438 
 1439         return (EPERM);
 1440 }
 1441 
 1442 /*
 1443  * Get TPDs from connection memory
 1444  */
 1445 static int
 1446 hatm_sysctl_tpd(SYSCTL_HANDLER_ARGS)
 1447 {
 1448         struct hatm_softc *sc = arg1;
 1449         int error, i, j;
 1450         uint32_t *val;
 1451 
 1452         val = malloc(sizeof(uint32_t) * HE_MAX_VCCS * 16, M_TEMP, M_WAITOK);
 1453 
 1454         mtx_lock(&sc->mtx);
 1455         for (i = 0; i < HE_MAX_VCCS; i++)
 1456                 for (j = 0; j < 16; j++)
 1457                         val[16 * i + j] = READ_TCM4(sc, 16 * i + j);
 1458         mtx_unlock(&sc->mtx);
 1459 
 1460         error = SYSCTL_OUT(req, val, sizeof(uint32_t) * HE_MAX_VCCS * 16);
 1461         free(val, M_TEMP);
 1462         if (error != 0 || req->newptr == NULL)
 1463                 return (error);
 1464 
 1465         return (EPERM);
 1466 }
 1467 
 1468 /*
 1469  * Get mbox registers
 1470  */
 1471 static int
 1472 hatm_sysctl_mbox(SYSCTL_HANDLER_ARGS)
 1473 {
 1474         struct hatm_softc *sc = arg1;
 1475         int error, i;
 1476         uint32_t *val;
 1477 
 1478         val = malloc(sizeof(uint32_t) * HE_REGO_CS_END, M_TEMP, M_WAITOK);
 1479 
 1480         mtx_lock(&sc->mtx);
 1481         for (i = 0; i < HE_REGO_CS_END; i++)
 1482                 val[i] = READ_MBOX4(sc, i);
 1483         mtx_unlock(&sc->mtx);
 1484 
 1485         error = SYSCTL_OUT(req, val, sizeof(uint32_t) * HE_REGO_CS_END);
 1486         free(val, M_TEMP);
 1487         if (error != 0 || req->newptr == NULL)
 1488                 return (error);
 1489 
 1490         return (EPERM);
 1491 }
 1492 
 1493 /*
 1494  * Get connection memory
 1495  */
 1496 static int
 1497 hatm_sysctl_cm(SYSCTL_HANDLER_ARGS)
 1498 {
 1499         struct hatm_softc *sc = arg1;
 1500         int error, i;
 1501         uint32_t *val;
 1502 
 1503         val = malloc(sizeof(uint32_t) * (HE_CONFIG_RXMEM + 1), M_TEMP, M_WAITOK);
 1504 
 1505         mtx_lock(&sc->mtx);
 1506         val[0] = READ4(sc, HE_REGO_RCMABR_BA);
 1507         for (i = 0; i < HE_CONFIG_RXMEM; i++)
 1508                 val[i + 1] = READ_RCM4(sc, i);
 1509         mtx_unlock(&sc->mtx);
 1510 
 1511         error = SYSCTL_OUT(req, val, sizeof(uint32_t) * (HE_CONFIG_RXMEM + 1));
 1512         free(val, M_TEMP);
 1513         if (error != 0 || req->newptr == NULL)
 1514                 return (error);
 1515 
 1516         return (EPERM);
 1517 }
 1518 
 1519 /*
 1520  * Get local buffer memory
 1521  */
 1522 static int
 1523 hatm_sysctl_lbmem(SYSCTL_HANDLER_ARGS)
 1524 {
 1525         struct hatm_softc *sc = arg1;
 1526         int error, i;
 1527         uint32_t *val;
 1528         u_int bytes = (1 << 21);
 1529 
 1530         val = malloc(bytes, M_TEMP, M_WAITOK);
 1531 
 1532         mtx_lock(&sc->mtx);
 1533         for (i = 0; i < bytes / 4; i++)
 1534                 val[i] = READ_LB4(sc, i);
 1535         mtx_unlock(&sc->mtx);
 1536 
 1537         error = SYSCTL_OUT(req, val, bytes);
 1538         free(val, M_TEMP);
 1539         if (error != 0 || req->newptr == NULL)
 1540                 return (error);
 1541 
 1542         return (EPERM);
 1543 }
 1544 
 1545 /*
 1546  * Get all card registers
 1547  */
 1548 static int
 1549 hatm_sysctl_heregs(SYSCTL_HANDLER_ARGS)
 1550 {
 1551         struct hatm_softc *sc = arg1;
 1552         int error, i;
 1553         uint32_t *val;
 1554 
 1555         val = malloc(HE_REGO_END, M_TEMP, M_WAITOK);
 1556 
 1557         mtx_lock(&sc->mtx);
 1558         for (i = 0; i < HE_REGO_END; i += 4)
 1559                 val[i / 4] = READ4(sc, i);
 1560         mtx_unlock(&sc->mtx);
 1561 
 1562         error = SYSCTL_OUT(req, val, HE_REGO_END);
 1563         free(val, M_TEMP);
 1564         if (error != 0 || req->newptr == NULL)
 1565                 return (error);
 1566 
 1567         return (EPERM);
 1568 }
 1569 #endif
 1570 
 1571 /*
 1572  * Suni register access
 1573  */
 1574 /*
 1575  * read at most n SUNI registers starting at reg into val
 1576  */
 1577 static int
 1578 hatm_utopia_readregs(struct ifatm *ifatm, u_int reg, uint8_t *val, u_int *n)
 1579 {
 1580         u_int i;
 1581         struct hatm_softc *sc = ifatm->ifp->if_softc;
 1582 
 1583         if (reg >= (HE_REGO_SUNI_END - HE_REGO_SUNI) / 4)
 1584                 return (EINVAL);
 1585         if (reg + *n > (HE_REGO_SUNI_END - HE_REGO_SUNI) / 4)
 1586                 *n = reg - (HE_REGO_SUNI_END - HE_REGO_SUNI) / 4;
 1587 
 1588         mtx_assert(&sc->mtx, MA_OWNED);
 1589         for (i = 0; i < *n; i++)
 1590                 val[i] = READ4(sc, HE_REGO_SUNI + 4 * (reg + i));
 1591 
 1592         return (0);
 1593 }
 1594 
 1595 /*
 1596  * change the bits given by mask to them in val in register reg
 1597  */
 1598 static int
 1599 hatm_utopia_writereg(struct ifatm *ifatm, u_int reg, u_int mask, u_int val)
 1600 {
 1601         uint32_t regval;
 1602         struct hatm_softc *sc = ifatm->ifp->if_softc;
 1603 
 1604         if (reg >= (HE_REGO_SUNI_END - HE_REGO_SUNI) / 4)
 1605                 return (EINVAL);
 1606 
 1607         mtx_assert(&sc->mtx, MA_OWNED);
 1608         regval = READ4(sc, HE_REGO_SUNI + 4 * reg);
 1609         regval = (regval & ~mask) | (val & mask);
 1610         WRITE4(sc, HE_REGO_SUNI + 4 * reg, regval);
 1611 
 1612         return (0);
 1613 }
 1614 
 1615 static struct utopia_methods hatm_utopia_methods = {
 1616         hatm_utopia_readregs,
 1617         hatm_utopia_writereg,
 1618 };
 1619 
 1620 /*
 1621  * Detach - if it is running, stop. Destroy.
 1622  */
 1623 static int
 1624 hatm_detach(device_t dev)
 1625 {
 1626         struct hatm_softc *sc = device_get_softc(dev);
 1627 
 1628         mtx_lock(&sc->mtx);
 1629         hatm_stop(sc);
 1630         if (sc->utopia.state & UTP_ST_ATTACHED) {
 1631                 utopia_stop(&sc->utopia);
 1632                 utopia_detach(&sc->utopia);
 1633         }
 1634         mtx_unlock(&sc->mtx);
 1635 
 1636         atm_ifdetach(sc->ifp);
 1637 
 1638         hatm_destroy(sc);
 1639 
 1640         return (0);
 1641 }
 1642 
 1643 /*
 1644  * Attach to the device. Assume that no locking is needed here.
 1645  * All resource we allocate here are freed by calling hatm_destroy.
 1646  */
 1647 static int
 1648 hatm_attach(device_t dev)
 1649 {
 1650         struct hatm_softc *sc;
 1651         int error;
 1652         uint32_t v;
 1653         struct ifnet *ifp;
 1654 
 1655         sc = device_get_softc(dev);
 1656 
 1657         ifp = sc->ifp = if_alloc(IFT_ATM);
 1658         if (ifp == NULL) {
 1659                 device_printf(dev, "could not if_alloc()\n");
 1660                 return (ENOSPC);
 1661         }
 1662 
 1663         sc->dev = dev;
 1664         IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_HE155;
 1665         IFP2IFATM(sc->ifp)->mib.serial = 0;
 1666         IFP2IFATM(sc->ifp)->mib.hw_version = 0;
 1667         IFP2IFATM(sc->ifp)->mib.sw_version = 0;
 1668         IFP2IFATM(sc->ifp)->mib.vpi_bits = HE_CONFIG_VPI_BITS;
 1669         IFP2IFATM(sc->ifp)->mib.vci_bits = HE_CONFIG_VCI_BITS;
 1670         IFP2IFATM(sc->ifp)->mib.max_vpcs = 0;
 1671         IFP2IFATM(sc->ifp)->mib.max_vccs = HE_MAX_VCCS;
 1672         IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_UNKNOWN;
 1673         sc->he622 = 0;
 1674         IFP2IFATM(sc->ifp)->phy = &sc->utopia;
 1675 
 1676         SLIST_INIT(&sc->tpd_free);
 1677 
 1678         mtx_init(&sc->mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF);
 1679         cv_init(&sc->vcc_cv, "HEVCCcv");
 1680         cv_init(&sc->cv_rcclose, "RCClose");
 1681 
 1682         sysctl_ctx_init(&sc->sysctl_ctx);
 1683 
 1684         /*
 1685          * 4.2 BIOS Configuration
 1686          */
 1687         v = pci_read_config(dev, PCIR_COMMAND, 2);
 1688         v |= PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN;
 1689         pci_write_config(dev, PCIR_COMMAND, v, 2);
 1690 
 1691         /*
 1692          * 4.3 PCI Bus Controller-Specific Initialisation
 1693          */
 1694         v = pci_read_config(dev, HE_PCIR_GEN_CNTL_0, 4);
 1695         v |= HE_PCIM_CTL0_MRL | HE_PCIM_CTL0_MRM | HE_PCIM_CTL0_IGNORE_TIMEOUT;
 1696 #if BYTE_ORDER == BIG_ENDIAN && 0
 1697         v |= HE_PCIM_CTL0_BIGENDIAN;
 1698 #endif
 1699         pci_write_config(dev, HE_PCIR_GEN_CNTL_0, v, 4);
 1700 
 1701         /*
 1702          * Map memory
 1703          */
 1704         v = pci_read_config(dev, PCIR_COMMAND, 2);
 1705         if (!(v & PCIM_CMD_MEMEN)) {
 1706                 device_printf(dev, "failed to enable memory\n");
 1707                 error = ENXIO;
 1708                 goto failed;
 1709         }
 1710         sc->memid = PCIR_BAR(0);
 1711         sc->memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->memid,
 1712             RF_ACTIVE);
 1713         if (sc->memres == NULL) {
 1714                 device_printf(dev, "could not map memory\n");
 1715                 error = ENXIO;
 1716                 goto failed;
 1717         }
 1718         sc->memh = rman_get_bushandle(sc->memres);
 1719         sc->memt = rman_get_bustag(sc->memres);
 1720 
 1721         /*
 1722          * ALlocate a DMA tag for subsequent allocations
 1723          */
 1724         if (bus_dma_tag_create(bus_get_dma_tag(sc->dev), 1, 0,
 1725             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
 1726             NULL, NULL,
 1727             BUS_SPACE_MAXSIZE_32BIT, 1,
 1728             BUS_SPACE_MAXSIZE_32BIT, 0,
 1729             NULL, NULL, &sc->parent_tag)) {
 1730                 device_printf(dev, "could not allocate DMA tag\n");
 1731                 error = ENOMEM;
 1732                 goto failed;
 1733         }
 1734 
 1735         if (bus_dma_tag_create(sc->parent_tag, 1, 0,
 1736             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
 1737             NULL, NULL,
 1738             MBUF_ALLOC_SIZE, 1,
 1739             MBUF_ALLOC_SIZE, 0,
 1740             NULL, NULL, &sc->mbuf_tag)) {
 1741                 device_printf(dev, "could not allocate mbuf DMA tag\n");
 1742                 error = ENOMEM;
 1743                 goto failed;
 1744         }
 1745 
 1746         /*
 1747          * Allocate a DMA tag for packets to send. Here we have a problem with
 1748          * the specification of the maximum number of segments. Theoretically
 1749          * this would be the size of the transmit ring - 1 multiplied by 3,
 1750          * but this would not work. So make the maximum number of TPDs
 1751          * occupied by one packet a configuration parameter.
 1752          */
 1753         if (bus_dma_tag_create(bus_get_dma_tag(sc->dev), 1, 0,
 1754             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
 1755             HE_MAX_PDU, 3 * HE_CONFIG_MAX_TPD_PER_PACKET, HE_MAX_PDU, 0,
 1756             NULL, NULL, &sc->tx_tag)) {
 1757                 device_printf(dev, "could not allocate TX tag\n");
 1758                 error = ENOMEM;
 1759                 goto failed;
 1760         }
 1761 
 1762         /*
 1763          * Setup the interrupt
 1764          */
 1765         sc->irqid = 0;
 1766         sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
 1767             RF_SHAREABLE | RF_ACTIVE);
 1768         if (sc->irqres == 0) {
 1769                 device_printf(dev, "could not allocate irq\n");
 1770                 error = ENXIO;
 1771                 goto failed;
 1772         }
 1773 
 1774         ifp->if_softc = sc;
 1775         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
 1776 
 1777         /*
 1778          * Make the sysctl tree
 1779          */
 1780         error = ENOMEM;
 1781         if ((sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
 1782             SYSCTL_STATIC_CHILDREN(_hw_atm), OID_AUTO,
 1783             device_get_nameunit(dev), CTLFLAG_RD, 0, "")) == NULL)
 1784                 goto failed;
 1785 
 1786         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
 1787             OID_AUTO, "istats", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, CTL_ISTATS,
 1788             hatm_sysctl, "LU", "internal statistics") == NULL)
 1789                 goto failed;
 1790 
 1791 #ifdef HATM_DEBUG
 1792         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
 1793             OID_AUTO, "tsr", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0,
 1794             hatm_sysctl_tsr, "S", "transmission status registers") == NULL)
 1795                 goto failed;
 1796 
 1797         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
 1798             OID_AUTO, "tpd", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0,
 1799             hatm_sysctl_tpd, "S", "transmission packet descriptors") == NULL)
 1800                 goto failed;
 1801 
 1802         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
 1803             OID_AUTO, "mbox", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0,
 1804             hatm_sysctl_mbox, "S", "mbox registers") == NULL)
 1805                 goto failed;
 1806 
 1807         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
 1808             OID_AUTO, "cm", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0,
 1809             hatm_sysctl_cm, "S", "connection memory") == NULL)
 1810                 goto failed;
 1811 
 1812         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
 1813             OID_AUTO, "heregs", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0,
 1814             hatm_sysctl_heregs, "S", "card registers") == NULL)
 1815                 goto failed;
 1816 
 1817         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
 1818             OID_AUTO, "lbmem", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0,
 1819             hatm_sysctl_lbmem, "S", "local memory") == NULL)
 1820                 goto failed;
 1821 
 1822         kenv_getuint(sc, "debug", &sc->debug, HATM_DEBUG, 1);
 1823 #endif
 1824 
 1825         /*
 1826          * Configure
 1827          */
 1828         if ((error = hatm_configure(sc)) != 0)
 1829                 goto failed;
 1830 
 1831         /*
 1832          * Compute memory parameters
 1833          */
 1834         if (sc->rbp_s0.size != 0) {
 1835                 sc->rbp_s0.mask = (sc->rbp_s0.size - 1) << 3;
 1836                 sc->rbp_s0.mem.size = sc->rbp_s0.size * 8;
 1837                 sc->rbp_s0.mem.align = sc->rbp_s0.mem.size;
 1838         }
 1839         if (sc->rbp_l0.size != 0) {
 1840                 sc->rbp_l0.mask = (sc->rbp_l0.size - 1) << 3;
 1841                 sc->rbp_l0.mem.size = sc->rbp_l0.size * 8;
 1842                 sc->rbp_l0.mem.align = sc->rbp_l0.mem.size;
 1843         }
 1844         if (sc->rbp_s1.size != 0) {
 1845                 sc->rbp_s1.mask = (sc->rbp_s1.size - 1) << 3;
 1846                 sc->rbp_s1.mem.size = sc->rbp_s1.size * 8;
 1847                 sc->rbp_s1.mem.align = sc->rbp_s1.mem.size;
 1848         }
 1849         if (sc->rbrq_0.size != 0) {
 1850                 sc->rbrq_0.mem.size = sc->rbrq_0.size * 8;
 1851                 sc->rbrq_0.mem.align = sc->rbrq_0.mem.size;
 1852         }
 1853         if (sc->rbrq_1.size != 0) {
 1854                 sc->rbrq_1.mem.size = sc->rbrq_1.size * 8;
 1855                 sc->rbrq_1.mem.align = sc->rbrq_1.mem.size;
 1856         }
 1857 
 1858         sc->irq_0.mem.size = sc->irq_0.size * sizeof(uint32_t);
 1859         sc->irq_0.mem.align = 4 * 1024;
 1860 
 1861         sc->tbrq.mem.size = sc->tbrq.size * 4;
 1862         sc->tbrq.mem.align = 2 * sc->tbrq.mem.size; /* ZZZ */
 1863 
 1864         sc->tpdrq.mem.size = sc->tpdrq.size * 8;
 1865         sc->tpdrq.mem.align = sc->tpdrq.mem.size;
 1866 
 1867         sc->hsp_mem.size = sizeof(struct he_hsp);
 1868         sc->hsp_mem.align = 1024;
 1869 
 1870         sc->lbufs_size = sc->rbp_l0.size + sc->rbrq_0.size;
 1871         sc->tpd_total = sc->tbrq.size + sc->tpdrq.size;
 1872         sc->tpds.align = 64;
 1873         sc->tpds.size = sc->tpd_total * HE_TPD_SIZE;
 1874 
 1875         hatm_init_rmaps(sc);
 1876         hatm_init_smbufs(sc);
 1877         if ((error = hatm_init_tpds(sc)) != 0)
 1878                 goto failed;
 1879 
 1880         /*
 1881          * Allocate memory
 1882          */
 1883         if ((error = hatm_alloc_dmamem(sc, "IRQ", &sc->irq_0.mem)) != 0 ||
 1884             (error = hatm_alloc_dmamem(sc, "TBRQ0", &sc->tbrq.mem)) != 0 ||
 1885             (error = hatm_alloc_dmamem(sc, "TPDRQ", &sc->tpdrq.mem)) != 0 ||
 1886             (error = hatm_alloc_dmamem(sc, "HSP", &sc->hsp_mem)) != 0)
 1887                 goto failed;
 1888 
 1889         if (sc->rbp_s0.mem.size != 0 &&
 1890             (error = hatm_alloc_dmamem(sc, "RBPS0", &sc->rbp_s0.mem)))
 1891                 goto failed;
 1892         if (sc->rbp_l0.mem.size != 0 &&
 1893             (error = hatm_alloc_dmamem(sc, "RBPL0", &sc->rbp_l0.mem)))
 1894                 goto failed;
 1895         if (sc->rbp_s1.mem.size != 0 &&
 1896             (error = hatm_alloc_dmamem(sc, "RBPS1", &sc->rbp_s1.mem)))
 1897                 goto failed;
 1898 
 1899         if (sc->rbrq_0.mem.size != 0 &&
 1900             (error = hatm_alloc_dmamem(sc, "RBRQ0", &sc->rbrq_0.mem)))
 1901                 goto failed;
 1902         if (sc->rbrq_1.mem.size != 0 &&
 1903             (error = hatm_alloc_dmamem(sc, "RBRQ1", &sc->rbrq_1.mem)))
 1904                 goto failed;
 1905 
 1906         if ((sc->vcc_zone = uma_zcreate("HE vccs", sizeof(struct hevcc),
 1907             NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0)) == NULL) {
 1908                 device_printf(dev, "cannot allocate zone for vccs\n");
 1909                 goto failed;
 1910         }
 1911 
 1912         /*
 1913          * 4.4 Reset the card.
 1914          */
 1915         if ((error = hatm_reset(sc)) != 0)
 1916                 goto failed;
 1917 
 1918         /*
 1919          * Read the prom.
 1920          */
 1921         hatm_init_bus_width(sc);
 1922         hatm_init_read_eeprom(sc);
 1923         hatm_init_endianess(sc);
 1924 
 1925         /*
 1926          * Initialize interface
 1927          */
 1928         ifp->if_flags = IFF_SIMPLEX;
 1929         ifp->if_ioctl = hatm_ioctl;
 1930         ifp->if_start = hatm_start;
 1931         ifp->if_init = hatm_init;
 1932 
 1933         utopia_attach(&sc->utopia, IFP2IFATM(sc->ifp), &sc->media, &sc->mtx,
 1934             &sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
 1935             &hatm_utopia_methods);
 1936         utopia_init_media(&sc->utopia);
 1937 
 1938         /* these two SUNI routines need the lock */
 1939         mtx_lock(&sc->mtx);
 1940         /* poll while we are not running */
 1941         sc->utopia.flags |= UTP_FL_POLL_CARRIER;
 1942         utopia_start(&sc->utopia);
 1943         utopia_reset(&sc->utopia);
 1944         mtx_unlock(&sc->mtx);
 1945 
 1946         atm_ifattach(ifp);
 1947 
 1948 #ifdef ENABLE_BPF
 1949         bpfattach(ifp, DLT_ATM_RFC1483, sizeof(struct atmllc));
 1950 #endif
 1951 
 1952         error = bus_setup_intr(dev, sc->irqres, sc->mpsafe | INTR_TYPE_NET,
 1953             NULL, hatm_intr, &sc->irq_0, &sc->ih);
 1954         if (error != 0) {
 1955                 device_printf(dev, "could not setup interrupt\n");
 1956                 hatm_detach(dev);
 1957                 return (error);
 1958         }
 1959 
 1960         return (0);
 1961 
 1962   failed:
 1963         hatm_destroy(sc);
 1964         return (error);
 1965 }
 1966 
 1967 /*
 1968  * Start the interface. Assume a state as from attach().
 1969  */
 1970 void
 1971 hatm_initialize(struct hatm_softc *sc)
 1972 {
 1973         uint32_t v;
 1974         u_int cid;
 1975         static const u_int layout[2][7] = HE_CONFIG_MEM_LAYOUT;
 1976 
 1977         if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING)
 1978                 return;
 1979 
 1980         hatm_init_bus_width(sc);
 1981         hatm_init_endianess(sc);
 1982 
 1983         if_printf(sc->ifp, "%s, Rev. %s, S/N %u, "
 1984             "MAC=%02x:%02x:%02x:%02x:%02x:%02x (%ubit PCI)\n",
 1985             sc->prod_id, sc->rev, IFP2IFATM(sc->ifp)->mib.serial,
 1986             IFP2IFATM(sc->ifp)->mib.esi[0], IFP2IFATM(sc->ifp)->mib.esi[1], IFP2IFATM(sc->ifp)->mib.esi[2],
 1987             IFP2IFATM(sc->ifp)->mib.esi[3], IFP2IFATM(sc->ifp)->mib.esi[4], IFP2IFATM(sc->ifp)->mib.esi[5],
 1988             sc->pci64 ? 64 : 32);
 1989 
 1990         /*
 1991          * 4.8 SDRAM Controller Initialisation
 1992          * 4.9 Initialize RNUM value
 1993          */
 1994         if (sc->he622)
 1995                 WRITE4(sc, HE_REGO_SDRAM_CNTL, HE_REGM_SDRAM_64BIT);
 1996         else
 1997                 WRITE4(sc, HE_REGO_SDRAM_CNTL, 0);
 1998         BARRIER_W(sc);
 1999 
 2000         v = READ4(sc, HE_REGO_LB_SWAP);
 2001         BARRIER_R(sc);
 2002         v |= 0xf << HE_REGS_LBSWAP_RNUM;
 2003         WRITE4(sc, HE_REGO_LB_SWAP, v);
 2004         BARRIER_W(sc);
 2005 
 2006         hatm_init_irq(sc, &sc->irq_0, 0);
 2007         hatm_clear_irq(sc, 1);
 2008         hatm_clear_irq(sc, 2);
 2009         hatm_clear_irq(sc, 3);
 2010 
 2011         WRITE4(sc, HE_REGO_GRP_1_0_MAP, 0);
 2012         WRITE4(sc, HE_REGO_GRP_3_2_MAP, 0);
 2013         WRITE4(sc, HE_REGO_GRP_5_4_MAP, 0);
 2014         WRITE4(sc, HE_REGO_GRP_7_6_MAP, 0);
 2015         BARRIER_W(sc);
 2016 
 2017         /*
 2018          * 4.11 Enable PCI Bus Controller State Machine
 2019          */
 2020         v = READ4(sc, HE_REGO_HOST_CNTL);
 2021         BARRIER_R(sc);
 2022         v |= HE_REGM_HOST_OUTFF_ENB | HE_REGM_HOST_CMDFF_ENB |
 2023             HE_REGM_HOST_QUICK_RD | HE_REGM_HOST_QUICK_WR;
 2024         WRITE4(sc, HE_REGO_HOST_CNTL, v);
 2025         BARRIER_W(sc);
 2026 
 2027         /*
 2028          * 5.1.1 Generic configuration state
 2029          */
 2030         sc->cells_per_row = layout[sc->he622][0];
 2031         sc->bytes_per_row = layout[sc->he622][1];
 2032         sc->r0_numrows = layout[sc->he622][2];
 2033         sc->tx_numrows = layout[sc->he622][3];
 2034         sc->r1_numrows = layout[sc->he622][4];
 2035         sc->r0_startrow = layout[sc->he622][5];
 2036         sc->tx_startrow = sc->r0_startrow + sc->r0_numrows;
 2037         sc->r1_startrow = sc->tx_startrow + sc->tx_numrows;
 2038         sc->cells_per_lbuf = layout[sc->he622][6];
 2039 
 2040         sc->r0_numbuffs = sc->r0_numrows * (sc->cells_per_row /
 2041             sc->cells_per_lbuf);
 2042         sc->r1_numbuffs = sc->r1_numrows * (sc->cells_per_row /
 2043             sc->cells_per_lbuf);
 2044         sc->tx_numbuffs = sc->tx_numrows * (sc->cells_per_row /
 2045             sc->cells_per_lbuf);
 2046 
 2047         if (sc->r0_numbuffs > 2560)
 2048                 sc->r0_numbuffs = 2560;
 2049         if (sc->r1_numbuffs > 2560)
 2050                 sc->r1_numbuffs = 2560;
 2051         if (sc->tx_numbuffs > 5120)
 2052                 sc->tx_numbuffs = 5120;
 2053 
 2054         DBG(sc, ATTACH, ("cells_per_row=%u bytes_per_row=%u r0_numrows=%u "
 2055             "tx_numrows=%u r1_numrows=%u r0_startrow=%u tx_startrow=%u "
 2056             "r1_startrow=%u cells_per_lbuf=%u\nr0_numbuffs=%u r1_numbuffs=%u "
 2057             "tx_numbuffs=%u\n", sc->cells_per_row, sc->bytes_per_row,
 2058             sc->r0_numrows, sc->tx_numrows, sc->r1_numrows, sc->r0_startrow,
 2059             sc->tx_startrow, sc->r1_startrow, sc->cells_per_lbuf,
 2060             sc->r0_numbuffs, sc->r1_numbuffs, sc->tx_numbuffs));
 2061 
 2062         /*
 2063          * 5.1.2 Configure Hardware dependend registers
 2064          */
 2065         if (sc->he622) {
 2066                 WRITE4(sc, HE_REGO_LBARB,
 2067                     (0x2 << HE_REGS_LBARB_SLICE) |
 2068                     (0xf << HE_REGS_LBARB_RNUM) |
 2069                     (0x3 << HE_REGS_LBARB_THPRI) |
 2070                     (0x3 << HE_REGS_LBARB_RHPRI) |
 2071                     (0x2 << HE_REGS_LBARB_TLPRI) |
 2072                     (0x1 << HE_REGS_LBARB_RLPRI) |
 2073                     (0x28 << HE_REGS_LBARB_BUS_MULT) |
 2074                     (0x50 << HE_REGS_LBARB_NET_PREF));
 2075                 BARRIER_W(sc);
 2076                 WRITE4(sc, HE_REGO_SDRAMCON,
 2077                     /* HW bug: don't use banking */
 2078                     /* HE_REGM_SDRAMCON_BANK | */
 2079                     HE_REGM_SDRAMCON_WIDE |
 2080                     (0x384 << HE_REGS_SDRAMCON_REF));
 2081                 BARRIER_W(sc);
 2082                 WRITE4(sc, HE_REGO_RCMCONFIG,
 2083                     (0x1 << HE_REGS_RCMCONFIG_BANK_WAIT) |
 2084                     (0x1 << HE_REGS_RCMCONFIG_RW_WAIT) |
 2085                     (0x0 << HE_REGS_RCMCONFIG_TYPE));
 2086                 WRITE4(sc, HE_REGO_TCMCONFIG,
 2087                     (0x2 << HE_REGS_TCMCONFIG_BANK_WAIT) |
 2088                     (0x1 << HE_REGS_TCMCONFIG_RW_WAIT) |
 2089                     (0x0 << HE_REGS_TCMCONFIG_TYPE));
 2090         } else {
 2091                 WRITE4(sc, HE_REGO_LBARB,
 2092                     (0x2 << HE_REGS_LBARB_SLICE) |
 2093                     (0xf << HE_REGS_LBARB_RNUM) |
 2094                     (0x3 << HE_REGS_LBARB_THPRI) |
 2095                     (0x3 << HE_REGS_LBARB_RHPRI) |
 2096                     (0x2 << HE_REGS_LBARB_TLPRI) |
 2097                     (0x1 << HE_REGS_LBARB_RLPRI) |
 2098                     (0x46 << HE_REGS_LBARB_BUS_MULT) |
 2099                     (0x8C << HE_REGS_LBARB_NET_PREF));
 2100                 BARRIER_W(sc);
 2101                 WRITE4(sc, HE_REGO_SDRAMCON,
 2102                     /* HW bug: don't use banking */
 2103                     /* HE_REGM_SDRAMCON_BANK | */
 2104                     (0x150 << HE_REGS_SDRAMCON_REF));
 2105                 BARRIER_W(sc);
 2106                 WRITE4(sc, HE_REGO_RCMCONFIG,
 2107                     (0x0 << HE_REGS_RCMCONFIG_BANK_WAIT) |
 2108                     (0x1 << HE_REGS_RCMCONFIG_RW_WAIT) |
 2109                     (0x0 << HE_REGS_RCMCONFIG_TYPE));
 2110                 WRITE4(sc, HE_REGO_TCMCONFIG,
 2111                     (0x1 << HE_REGS_TCMCONFIG_BANK_WAIT) |
 2112                     (0x1 << HE_REGS_TCMCONFIG_RW_WAIT) |
 2113                     (0x0 << HE_REGS_TCMCONFIG_TYPE));
 2114         }
 2115         WRITE4(sc, HE_REGO_LBCONFIG, (sc->cells_per_lbuf * 48));
 2116 
 2117         WRITE4(sc, HE_REGO_RLBC_H, 0);
 2118         WRITE4(sc, HE_REGO_RLBC_T, 0);
 2119         WRITE4(sc, HE_REGO_RLBC_H2, 0);
 2120 
 2121         WRITE4(sc, HE_REGO_RXTHRSH, 512);
 2122         WRITE4(sc, HE_REGO_LITHRSH, 256);
 2123 
 2124         WRITE4(sc, HE_REGO_RLBF0_C, sc->r0_numbuffs);
 2125         WRITE4(sc, HE_REGO_RLBF1_C, sc->r1_numbuffs);
 2126 
 2127         if (sc->he622) {
 2128                 WRITE4(sc, HE_REGO_RCCONFIG,
 2129                     (8 << HE_REGS_RCCONFIG_UTDELAY) |
 2130                     (IFP2IFATM(sc->ifp)->mib.vpi_bits << HE_REGS_RCCONFIG_VP) |
 2131                     (IFP2IFATM(sc->ifp)->mib.vci_bits << HE_REGS_RCCONFIG_VC));
 2132                 WRITE4(sc, HE_REGO_TXCONFIG,
 2133                     (32 << HE_REGS_TXCONFIG_THRESH) |
 2134                     (IFP2IFATM(sc->ifp)->mib.vci_bits << HE_REGS_TXCONFIG_VCI_MASK) |
 2135                     (sc->tx_numbuffs << HE_REGS_TXCONFIG_LBFREE));
 2136         } else {
 2137                 WRITE4(sc, HE_REGO_RCCONFIG,
 2138                     (0 << HE_REGS_RCCONFIG_UTDELAY) |
 2139                     HE_REGM_RCCONFIG_UT_MODE |
 2140                     (IFP2IFATM(sc->ifp)->mib.vpi_bits << HE_REGS_RCCONFIG_VP) |
 2141                     (IFP2IFATM(sc->ifp)->mib.vci_bits << HE_REGS_RCCONFIG_VC));
 2142                 WRITE4(sc, HE_REGO_TXCONFIG,
 2143                     (32 << HE_REGS_TXCONFIG_THRESH) |
 2144                     HE_REGM_TXCONFIG_UTMODE |
 2145                     (IFP2IFATM(sc->ifp)->mib.vci_bits << HE_REGS_TXCONFIG_VCI_MASK) |
 2146                     (sc->tx_numbuffs << HE_REGS_TXCONFIG_LBFREE));
 2147         }
 2148 
 2149         WRITE4(sc, HE_REGO_TXAAL5_PROTO, 0);
 2150 
 2151         if (sc->rbp_s1.size != 0) {
 2152                 WRITE4(sc, HE_REGO_RHCONFIG,
 2153                     HE_REGM_RHCONFIG_PHYENB |
 2154                     ((sc->he622 ? 0x41 : 0x31) << HE_REGS_RHCONFIG_PTMR_PRE) |
 2155                     (1 << HE_REGS_RHCONFIG_OAM_GID));
 2156         } else {
 2157                 WRITE4(sc, HE_REGO_RHCONFIG,
 2158                     HE_REGM_RHCONFIG_PHYENB |
 2159                     ((sc->he622 ? 0x41 : 0x31) << HE_REGS_RHCONFIG_PTMR_PRE) |
 2160                     (0 << HE_REGS_RHCONFIG_OAM_GID));
 2161         }
 2162         BARRIER_W(sc);
 2163 
 2164         hatm_init_cm(sc);
 2165 
 2166         hatm_init_rx_buffer_pool(sc, 0, sc->r0_startrow, sc->r0_numbuffs);
 2167         hatm_init_rx_buffer_pool(sc, 1, sc->r1_startrow, sc->r1_numbuffs);
 2168         hatm_init_tx_buffer_pool(sc, sc->tx_startrow, sc->tx_numbuffs);
 2169 
 2170         hatm_init_imed_queues(sc);
 2171 
 2172         /*
 2173          * 5.1.6 Application tunable Parameters
 2174          */
 2175         WRITE4(sc, HE_REGO_MCC, 0);
 2176         WRITE4(sc, HE_REGO_OEC, 0);
 2177         WRITE4(sc, HE_REGO_DCC, 0);
 2178         WRITE4(sc, HE_REGO_CEC, 0);
 2179 
 2180         hatm_init_cs_block(sc);
 2181         hatm_init_cs_block_cm(sc);
 2182 
 2183         hatm_init_rpool(sc, &sc->rbp_s0, 0, 0);
 2184         hatm_init_rpool(sc, &sc->rbp_l0, 0, 1);
 2185         hatm_init_rpool(sc, &sc->rbp_s1, 1, 0);
 2186         hatm_clear_rpool(sc, 1, 1);
 2187         hatm_clear_rpool(sc, 2, 0);
 2188         hatm_clear_rpool(sc, 2, 1);
 2189         hatm_clear_rpool(sc, 3, 0);
 2190         hatm_clear_rpool(sc, 3, 1);
 2191         hatm_clear_rpool(sc, 4, 0);
 2192         hatm_clear_rpool(sc, 4, 1);
 2193         hatm_clear_rpool(sc, 5, 0);
 2194         hatm_clear_rpool(sc, 5, 1);
 2195         hatm_clear_rpool(sc, 6, 0);
 2196         hatm_clear_rpool(sc, 6, 1);
 2197         hatm_clear_rpool(sc, 7, 0);
 2198         hatm_clear_rpool(sc, 7, 1);
 2199         hatm_init_rbrq(sc, &sc->rbrq_0, 0);
 2200         hatm_init_rbrq(sc, &sc->rbrq_1, 1);
 2201         hatm_clear_rbrq(sc, 2);
 2202         hatm_clear_rbrq(sc, 3);
 2203         hatm_clear_rbrq(sc, 4);
 2204         hatm_clear_rbrq(sc, 5);
 2205         hatm_clear_rbrq(sc, 6);
 2206         hatm_clear_rbrq(sc, 7);
 2207 
 2208         sc->lbufs_next = 0;
 2209         bzero(sc->lbufs, sizeof(sc->lbufs[0]) * sc->lbufs_size);
 2210 
 2211         hatm_init_tbrq(sc, &sc->tbrq, 0);
 2212         hatm_clear_tbrq(sc, 1);
 2213         hatm_clear_tbrq(sc, 2);
 2214         hatm_clear_tbrq(sc, 3);
 2215         hatm_clear_tbrq(sc, 4);
 2216         hatm_clear_tbrq(sc, 5);
 2217         hatm_clear_tbrq(sc, 6);
 2218         hatm_clear_tbrq(sc, 7);
 2219 
 2220         hatm_init_tpdrq(sc);
 2221 
 2222         WRITE4(sc, HE_REGO_UBUFF_BA, (sc->he622 ? 0x104780 : 0x800));
 2223 
 2224         /*
 2225          * Initialize HSP
 2226          */
 2227         bzero(sc->hsp_mem.base, sc->hsp_mem.size);
 2228         sc->hsp = sc->hsp_mem.base;
 2229         WRITE4(sc, HE_REGO_HSP_BA, sc->hsp_mem.paddr);
 2230 
 2231         /*
 2232          * 5.1.12 Enable transmit and receive
 2233          * Enable bus master and interrupts
 2234          */
 2235         v = READ_MBOX4(sc, HE_REGO_CS_ERCTL0);
 2236         v |= 0x18000000;
 2237         WRITE_MBOX4(sc, HE_REGO_CS_ERCTL0, v);
 2238 
 2239         v = READ4(sc, HE_REGO_RCCONFIG);
 2240         v |= HE_REGM_RCCONFIG_RXENB;
 2241         WRITE4(sc, HE_REGO_RCCONFIG, v);
 2242 
 2243         v = pci_read_config(sc->dev, HE_PCIR_GEN_CNTL_0, 4);
 2244         v |= HE_PCIM_CTL0_INIT_ENB | HE_PCIM_CTL0_INT_PROC_ENB;
 2245         pci_write_config(sc->dev, HE_PCIR_GEN_CNTL_0, v, 4);
 2246 
 2247         sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
 2248         sc->ifp->if_baudrate = 53 * 8 * IFP2IFATM(sc->ifp)->mib.pcr;
 2249 
 2250         sc->utopia.flags &= ~UTP_FL_POLL_CARRIER;
 2251 
 2252         /* reopen vccs */
 2253         for (cid = 0; cid < HE_MAX_VCCS; cid++)
 2254                 if (sc->vccs[cid] != NULL)
 2255                         hatm_load_vc(sc, cid, 1);
 2256 
 2257         ATMEV_SEND_IFSTATE_CHANGED(IFP2IFATM(sc->ifp),
 2258             sc->utopia.carrier == UTP_CARR_OK);
 2259 }
 2260 
 2261 /*
 2262  * This functions stops the card and frees all resources allocated after
 2263  * the attach. Must have the global lock.
 2264  */
 2265 void
 2266 hatm_stop(struct hatm_softc *sc)
 2267 {
 2268         uint32_t v;
 2269         u_int i, p, cid;
 2270         struct mbuf_chunk_hdr *ch;
 2271         struct mbuf_page *pg;
 2272 
 2273         mtx_assert(&sc->mtx, MA_OWNED);
 2274 
 2275         if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING))
 2276                 return;
 2277         sc->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
 2278 
 2279         ATMEV_SEND_IFSTATE_CHANGED(IFP2IFATM(sc->ifp),
 2280             sc->utopia.carrier == UTP_CARR_OK);
 2281 
 2282         sc->utopia.flags |= UTP_FL_POLL_CARRIER;
 2283 
 2284         /*
 2285          * Stop and reset the hardware so that everything remains
 2286          * stable.
 2287          */
 2288         v = READ_MBOX4(sc, HE_REGO_CS_ERCTL0);
 2289         v &= ~0x18000000;
 2290         WRITE_MBOX4(sc, HE_REGO_CS_ERCTL0, v);
 2291 
 2292         v = READ4(sc, HE_REGO_RCCONFIG);
 2293         v &= ~HE_REGM_RCCONFIG_RXENB;
 2294         WRITE4(sc, HE_REGO_RCCONFIG, v);
 2295 
 2296         WRITE4(sc, HE_REGO_RHCONFIG, (0x2 << HE_REGS_RHCONFIG_PTMR_PRE));
 2297         BARRIER_W(sc);
 2298 
 2299         v = READ4(sc, HE_REGO_HOST_CNTL);
 2300         BARRIER_R(sc);
 2301         v &= ~(HE_REGM_HOST_OUTFF_ENB | HE_REGM_HOST_CMDFF_ENB);
 2302         WRITE4(sc, HE_REGO_HOST_CNTL, v);
 2303         BARRIER_W(sc);
 2304 
 2305         /*
 2306          * Disable bust master and interrupts
 2307          */
 2308         v = pci_read_config(sc->dev, HE_PCIR_GEN_CNTL_0, 4);
 2309         v &= ~(HE_PCIM_CTL0_INIT_ENB | HE_PCIM_CTL0_INT_PROC_ENB);
 2310         pci_write_config(sc->dev, HE_PCIR_GEN_CNTL_0, v, 4);
 2311 
 2312         (void)hatm_reset(sc);
 2313 
 2314         /*
 2315          * Card resets the SUNI when resetted, so re-initialize it
 2316          */
 2317         utopia_reset(&sc->utopia);
 2318 
 2319         /*
 2320          * Give any waiters on closing a VCC a chance. They will stop
 2321          * to wait if they see that IFF_DRV_RUNNING disappeared.
 2322          */
 2323         cv_broadcast(&sc->vcc_cv);
 2324         cv_broadcast(&sc->cv_rcclose);
 2325 
 2326         /*
 2327          * Now free all resources.
 2328          */
 2329 
 2330         /*
 2331          * Free the large mbufs that are given to the card.
 2332          */
 2333         for (i = 0 ; i < sc->lbufs_size; i++) {
 2334                 if (sc->lbufs[i] != NULL) {
 2335                         bus_dmamap_unload(sc->mbuf_tag, sc->rmaps[i]);
 2336                         m_freem(sc->lbufs[i]);
 2337                         sc->lbufs[i] = NULL;
 2338                 }
 2339         }
 2340 
 2341         /*
 2342          * Free small buffers
 2343          */
 2344         for (p = 0; p < sc->mbuf_npages; p++) {
 2345                 pg = sc->mbuf_pages[p];
 2346                 for (i = 0; i < pg->hdr.nchunks; i++) {
 2347                         ch = (struct mbuf_chunk_hdr *) ((char *)pg +
 2348                             i * pg->hdr.chunksize + pg->hdr.hdroff);
 2349                         if (ch->flags & MBUF_CARD) {
 2350                                 ch->flags &= ~MBUF_CARD;
 2351                                 ch->flags |= MBUF_USED;
 2352                                 hatm_ext_free(&sc->mbuf_list[pg->hdr.pool],
 2353                                     (struct mbufx_free *)((u_char *)ch -
 2354                                     pg->hdr.hdroff));
 2355                         }
 2356                 }
 2357         }
 2358 
 2359         hatm_stop_tpds(sc);
 2360 
 2361         /*
 2362          * Free all partial reassembled PDUs on any VCC.
 2363          */
 2364         for (cid = 0; cid < HE_MAX_VCCS; cid++) {
 2365                 if (sc->vccs[cid] != NULL) {
 2366                         if (sc->vccs[cid]->chain != NULL) {
 2367                                 m_freem(sc->vccs[cid]->chain);
 2368                                 sc->vccs[cid]->chain = NULL;
 2369                                 sc->vccs[cid]->last = NULL;
 2370                         }
 2371                         if (!(sc->vccs[cid]->vflags & (HE_VCC_RX_OPEN |
 2372                             HE_VCC_TX_OPEN))) {
 2373                                 hatm_tx_vcc_closed(sc, cid);
 2374                                 uma_zfree(sc->vcc_zone, sc->vccs[cid]);
 2375                                 sc->vccs[cid] = NULL;
 2376                                 sc->open_vccs--;
 2377                         } else {
 2378                                 sc->vccs[cid]->vflags = 0;
 2379                                 sc->vccs[cid]->ntpds = 0;
 2380                         }
 2381                 }
 2382         }
 2383 
 2384         if (sc->rbp_s0.size != 0)
 2385                 bzero(sc->rbp_s0.mem.base, sc->rbp_s0.mem.size);
 2386         if (sc->rbp_l0.size != 0)
 2387                 bzero(sc->rbp_l0.mem.base, sc->rbp_l0.mem.size);
 2388         if (sc->rbp_s1.size != 0)
 2389                 bzero(sc->rbp_s1.mem.base, sc->rbp_s1.mem.size);
 2390         if (sc->rbrq_0.size != 0)
 2391                 bzero(sc->rbrq_0.mem.base, sc->rbrq_0.mem.size);
 2392         if (sc->rbrq_1.size != 0)
 2393                 bzero(sc->rbrq_1.mem.base, sc->rbrq_1.mem.size);
 2394 
 2395         bzero(sc->tbrq.mem.base, sc->tbrq.mem.size);
 2396         bzero(sc->tpdrq.mem.base, sc->tpdrq.mem.size);
 2397         bzero(sc->hsp_mem.base, sc->hsp_mem.size);
 2398 }
 2399 
 2400 /************************************************************
 2401  *
 2402  * Driver infrastructure
 2403  */
 2404 devclass_t hatm_devclass;
 2405 
 2406 static device_method_t hatm_methods[] = {
 2407         DEVMETHOD(device_probe,         hatm_probe),
 2408         DEVMETHOD(device_attach,        hatm_attach),
 2409         DEVMETHOD(device_detach,        hatm_detach),
 2410         {0,0}
 2411 };
 2412 static driver_t hatm_driver = {
 2413         "hatm",
 2414         hatm_methods,
 2415         sizeof(struct hatm_softc),
 2416 };
 2417 DRIVER_MODULE(hatm, pci, hatm_driver, hatm_devclass, NULL, 0);

Cache object: 9f777bc8aea712d081efec0e40e836e4


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