1139749Simp/*- 2116491Sharti * Copyright (c) 2001-2003 3116491Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4116491Sharti * All rights reserved. 5116491Sharti * 6116491Sharti * Redistribution and use in source and binary forms, with or without 7116491Sharti * modification, are permitted provided that the following conditions 8116491Sharti * are met: 9116491Sharti * 1. Redistributions of source code must retain the above copyright 10116491Sharti * notice, this list of conditions and the following disclaimer. 11116491Sharti * 2. Redistributions in binary form must reproduce the above copyright 12116491Sharti * notice, this list of conditions and the following disclaimer in the 13116491Sharti * documentation and/or other materials provided with the distribution. 14116491Sharti * 15116491Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16116491Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17116491Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18116491Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19116491Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20116491Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21116491Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22116491Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23116491Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24116491Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25116491Sharti * SUCH DAMAGE. 26116491Sharti * 27116491Sharti * Author: Hartmut Brandt <harti@freebsd.org> 28116491Sharti * 29116491Sharti * ForeHE driver. 30116491Sharti * 31116491Sharti * This file contains the module and driver infrastructure stuff as well 32116491Sharti * as a couple of utility functions and the entire initialisation. 33116491Sharti */ 34116519Sharti 35116519Sharti#include <sys/cdefs.h> 36116519Sharti__FBSDID("$FreeBSD$"); 37116519Sharti 38116491Sharti#include "opt_inet.h" 39116491Sharti#include "opt_natm.h" 40116491Sharti 41116491Sharti#include <sys/types.h> 42116491Sharti#include <sys/param.h> 43116491Sharti#include <sys/systm.h> 44116491Sharti#include <sys/malloc.h> 45116491Sharti#include <sys/kernel.h> 46116491Sharti#include <sys/bus.h> 47116491Sharti#include <sys/errno.h> 48116491Sharti#include <sys/conf.h> 49116491Sharti#include <sys/module.h> 50116491Sharti#include <sys/queue.h> 51116491Sharti#include <sys/syslog.h> 52116491Sharti#include <sys/lock.h> 53116491Sharti#include <sys/mutex.h> 54116491Sharti#include <sys/condvar.h> 55116491Sharti#include <sys/sysctl.h> 56116491Sharti#include <vm/uma.h> 57116491Sharti 58116491Sharti#include <sys/sockio.h> 59116491Sharti#include <sys/mbuf.h> 60116491Sharti#include <sys/socket.h> 61116491Sharti 62116491Sharti#include <net/if.h> 63116491Sharti#include <net/if_media.h> 64116491Sharti#include <net/if_atm.h> 65147256Sbrooks#include <net/if_types.h> 66116491Sharti#include <net/route.h> 67116491Sharti#ifdef ENABLE_BPF 68116491Sharti#include <net/bpf.h> 69116491Sharti#endif 70116491Sharti#include <netinet/in.h> 71116491Sharti#include <netinet/if_atm.h> 72116491Sharti 73116491Sharti#include <machine/bus.h> 74116491Sharti#include <machine/resource.h> 75116491Sharti#include <sys/bus.h> 76116491Sharti#include <sys/rman.h> 77119280Simp#include <dev/pci/pcireg.h> 78119280Simp#include <dev/pci/pcivar.h> 79116491Sharti 80116491Sharti#include <dev/utopia/utopia.h> 81116491Sharti#include <dev/hatm/if_hatmconf.h> 82116491Sharti#include <dev/hatm/if_hatmreg.h> 83116491Sharti#include <dev/hatm/if_hatmvar.h> 84116491Sharti 85116491Shartistatic const struct { 86116491Sharti uint16_t vid; 87116491Sharti uint16_t did; 88116491Sharti const char *name; 89116491Sharti} hatm_devs[] = { 90116491Sharti { 0x1127, 0x400, 91116491Sharti "FORE HE" }, 92116491Sharti { 0, 0, NULL } 93116491Sharti}; 94116491Sharti 95116491ShartiSYSCTL_DECL(_hw_atm); 96116491Sharti 97116491ShartiMODULE_DEPEND(hatm, utopia, 1, 1, 1); 98116491ShartiMODULE_DEPEND(hatm, pci, 1, 1, 1); 99116491ShartiMODULE_DEPEND(hatm, atm, 1, 1, 1); 100116491Sharti 101116491Sharti#define EEPROM_DELAY 400 /* microseconds */ 102116491Sharti 103116491Sharti/* Read from EEPROM 0000 0011b */ 104116491Shartistatic const uint32_t readtab[] = { 105116491Sharti HE_REGM_HOST_PROM_SEL | HE_REGM_HOST_PROM_CLOCK, 106116491Sharti 0, 107116491Sharti HE_REGM_HOST_PROM_CLOCK, 108116491Sharti 0, /* 0 */ 109116491Sharti HE_REGM_HOST_PROM_CLOCK, 110116491Sharti 0, /* 0 */ 111116491Sharti HE_REGM_HOST_PROM_CLOCK, 112116491Sharti 0, /* 0 */ 113116491Sharti HE_REGM_HOST_PROM_CLOCK, 114116491Sharti 0, /* 0 */ 115116491Sharti HE_REGM_HOST_PROM_CLOCK, 116116491Sharti 0, /* 0 */ 117116491Sharti HE_REGM_HOST_PROM_CLOCK, 118116491Sharti HE_REGM_HOST_PROM_DATA_IN, /* 0 */ 119116491Sharti HE_REGM_HOST_PROM_CLOCK | HE_REGM_HOST_PROM_DATA_IN, 120116491Sharti HE_REGM_HOST_PROM_DATA_IN, /* 1 */ 121116491Sharti HE_REGM_HOST_PROM_CLOCK | HE_REGM_HOST_PROM_DATA_IN, 122116491Sharti HE_REGM_HOST_PROM_DATA_IN, /* 1 */ 123116491Sharti}; 124116491Shartistatic const uint32_t clocktab[] = { 125116491Sharti 0, HE_REGM_HOST_PROM_CLOCK, 126116491Sharti 0, HE_REGM_HOST_PROM_CLOCK, 127116491Sharti 0, HE_REGM_HOST_PROM_CLOCK, 128116491Sharti 0, HE_REGM_HOST_PROM_CLOCK, 129116491Sharti 0, HE_REGM_HOST_PROM_CLOCK, 130116491Sharti 0, HE_REGM_HOST_PROM_CLOCK, 131116491Sharti 0, HE_REGM_HOST_PROM_CLOCK, 132116491Sharti 0, HE_REGM_HOST_PROM_CLOCK, 133116491Sharti 0 134116491Sharti}; 135116491Sharti 136116491Sharti/* 137116491Sharti * Convert cell rate to ATM Forum format 138116491Sharti */ 139116491Shartiu_int 140116491Shartihatm_cps2atmf(uint32_t pcr) 141116491Sharti{ 142116491Sharti u_int e; 143116491Sharti 144116491Sharti if (pcr == 0) 145116491Sharti return (0); 146116491Sharti pcr <<= 9; 147116491Sharti e = 0; 148116491Sharti while (pcr > (1024 - 1)) { 149116491Sharti e++; 150116491Sharti pcr >>= 1; 151116491Sharti } 152116491Sharti return ((1 << 14) | (e << 9) | (pcr & 0x1ff)); 153116491Sharti} 154116491Shartiu_int 155116491Shartihatm_atmf2cps(uint32_t fcr) 156116491Sharti{ 157116491Sharti fcr &= 0x7fff; 158116491Sharti 159116491Sharti return ((1 << ((fcr >> 9) & 0x1f)) * (512 + (fcr & 0x1ff)) / 512 160116491Sharti * (fcr >> 14)); 161116491Sharti} 162116491Sharti 163116491Sharti/************************************************************ 164116491Sharti * 165116491Sharti * Initialisation 166116491Sharti */ 167116491Sharti/* 168116491Sharti * Probe for a HE controller 169116491Sharti */ 170116491Shartistatic int 171116491Shartihatm_probe(device_t dev) 172116491Sharti{ 173116491Sharti int i; 174116491Sharti 175116491Sharti for (i = 0; hatm_devs[i].name; i++) 176116491Sharti if (pci_get_vendor(dev) == hatm_devs[i].vid && 177116491Sharti pci_get_device(dev) == hatm_devs[i].did) { 178116491Sharti device_set_desc(dev, hatm_devs[i].name); 179143161Simp return (BUS_PROBE_DEFAULT); 180116491Sharti } 181116491Sharti return (ENXIO); 182116491Sharti} 183116491Sharti 184116491Sharti/* 185116491Sharti * Allocate and map DMA-able memory. We support only contiguous mappings. 186116491Sharti */ 187116491Shartistatic void 188116491Shartidmaload_helper(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 189116491Sharti{ 190116491Sharti if (error) 191116491Sharti return; 192116491Sharti KASSERT(nsegs == 1, ("too many segments for DMA: %d", nsegs)); 193116491Sharti KASSERT(segs[0].ds_addr <= 0xffffffffUL, 194116491Sharti ("phys addr too large %lx", (u_long)segs[0].ds_addr)); 195116491Sharti 196116491Sharti *(bus_addr_t *)arg = segs[0].ds_addr; 197116491Sharti} 198116491Shartistatic int 199116491Shartihatm_alloc_dmamem(struct hatm_softc *sc, const char *what, struct dmamem *mem) 200116491Sharti{ 201116491Sharti int error; 202116491Sharti 203116491Sharti mem->base = NULL; 204116491Sharti 205116491Sharti /* 206116491Sharti * Alignement does not work in the bus_dmamem_alloc function below 207116491Sharti * on FreeBSD. malloc seems to align objects at least to the object 208116491Sharti * size so increase the size to the alignment if the size is lesser 209116491Sharti * than the alignemnt. 210116491Sharti * XXX on sparc64 this is (probably) not needed. 211116491Sharti */ 212116491Sharti if (mem->size < mem->align) 213116491Sharti mem->size = mem->align; 214116491Sharti 215116491Sharti error = bus_dma_tag_create(sc->parent_tag, mem->align, 0, 216116491Sharti BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 217116491Sharti NULL, NULL, mem->size, 1, 218117126Sscottl BUS_SPACE_MAXSIZE_32BIT, BUS_DMA_ALLOCNOW, 219117382Sharti NULL, NULL, &mem->tag); 220116491Sharti if (error) { 221147256Sbrooks if_printf(sc->ifp, "DMA tag create (%s)\n", what); 222116491Sharti return (error); 223116491Sharti } 224116491Sharti 225116491Sharti error = bus_dmamem_alloc(mem->tag, &mem->base, 0, &mem->map); 226116491Sharti if (error) { 227147256Sbrooks if_printf(sc->ifp, "DMA mem alloc (%s): %d\n", 228116491Sharti what, error); 229116491Sharti bus_dma_tag_destroy(mem->tag); 230116491Sharti mem->base = NULL; 231116491Sharti return (error); 232116491Sharti } 233116491Sharti 234116491Sharti error = bus_dmamap_load(mem->tag, mem->map, mem->base, mem->size, 235117382Sharti dmaload_helper, &mem->paddr, BUS_DMA_NOWAIT); 236116491Sharti if (error) { 237147256Sbrooks if_printf(sc->ifp, "DMA map load (%s): %d\n", 238116491Sharti what, error); 239116491Sharti bus_dmamem_free(mem->tag, mem->base, mem->map); 240116491Sharti bus_dma_tag_destroy(mem->tag); 241116491Sharti mem->base = NULL; 242116491Sharti return (error); 243116491Sharti } 244116491Sharti 245116491Sharti DBG(sc, DMA, ("%s S/A/V/P 0x%x 0x%x %p 0x%lx", what, mem->size, 246116491Sharti mem->align, mem->base, (u_long)mem->paddr)); 247116491Sharti 248116491Sharti return (0); 249116491Sharti} 250116491Sharti 251116491Sharti/* 252116491Sharti * Destroy all the resources of an DMA-able memory region. 253116491Sharti */ 254116491Shartistatic void 255116491Shartihatm_destroy_dmamem(struct dmamem *mem) 256116491Sharti{ 257116491Sharti if (mem->base != NULL) { 258116491Sharti bus_dmamap_unload(mem->tag, mem->map); 259116491Sharti bus_dmamem_free(mem->tag, mem->base, mem->map); 260116491Sharti (void)bus_dma_tag_destroy(mem->tag); 261116491Sharti mem->base = NULL; 262116491Sharti } 263116491Sharti} 264116491Sharti 265116491Sharti/* 266116491Sharti * Initialize/destroy DMA maps for the large pool 0 267116491Sharti */ 268116491Shartistatic void 269116491Shartihatm_destroy_rmaps(struct hatm_softc *sc) 270116491Sharti{ 271116491Sharti u_int b; 272116491Sharti 273116491Sharti DBG(sc, ATTACH, ("destroying rmaps and lbuf pointers...")); 274116491Sharti if (sc->rmaps != NULL) { 275116491Sharti for (b = 0; b < sc->lbufs_size; b++) 276116491Sharti bus_dmamap_destroy(sc->mbuf_tag, sc->rmaps[b]); 277116491Sharti free(sc->rmaps, M_DEVBUF); 278116491Sharti } 279116491Sharti if (sc->lbufs != NULL) 280116491Sharti free(sc->lbufs, M_DEVBUF); 281116491Sharti} 282116491Sharti 283116491Shartistatic void 284116491Shartihatm_init_rmaps(struct hatm_softc *sc) 285116491Sharti{ 286116491Sharti u_int b; 287116491Sharti int err; 288116491Sharti 289116491Sharti DBG(sc, ATTACH, ("allocating rmaps and lbuf pointers...")); 290116491Sharti sc->lbufs = malloc(sizeof(sc->lbufs[0]) * sc->lbufs_size, 291116491Sharti M_DEVBUF, M_ZERO | M_WAITOK); 292116491Sharti 293116491Sharti /* allocate and create the DMA maps for the large pool */ 294116491Sharti sc->rmaps = malloc(sizeof(sc->rmaps[0]) * sc->lbufs_size, 295116491Sharti M_DEVBUF, M_WAITOK); 296116491Sharti for (b = 0; b < sc->lbufs_size; b++) { 297116491Sharti err = bus_dmamap_create(sc->mbuf_tag, 0, &sc->rmaps[b]); 298116491Sharti if (err != 0) 299116491Sharti panic("bus_dmamap_create: %d\n", err); 300116491Sharti } 301116491Sharti} 302116491Sharti 303116491Sharti/* 304116491Sharti * Initialize and destroy small mbuf page pointers and pages 305116491Sharti */ 306116491Shartistatic void 307116491Shartihatm_destroy_smbufs(struct hatm_softc *sc) 308116491Sharti{ 309116491Sharti u_int i, b; 310116491Sharti struct mbuf_page *pg; 311121729Sharti struct mbuf_chunk_hdr *h; 312116491Sharti 313116491Sharti if (sc->mbuf_pages != NULL) { 314116491Sharti for (i = 0; i < sc->mbuf_npages; i++) { 315116491Sharti pg = sc->mbuf_pages[i]; 316116491Sharti for (b = 0; b < pg->hdr.nchunks; b++) { 317121729Sharti h = (struct mbuf_chunk_hdr *) ((char *)pg + 318121729Sharti b * pg->hdr.chunksize + pg->hdr.hdroff); 319121729Sharti if (h->flags & MBUF_CARD) 320147256Sbrooks if_printf(sc->ifp, 321116491Sharti "%s -- mbuf page=%u card buf %u\n", 322116491Sharti __func__, i, b); 323121729Sharti if (h->flags & MBUF_USED) 324147256Sbrooks if_printf(sc->ifp, 325121729Sharti "%s -- mbuf page=%u used buf %u\n", 326121729Sharti __func__, i, b); 327116491Sharti } 328116491Sharti bus_dmamap_unload(sc->mbuf_tag, pg->hdr.map); 329116491Sharti bus_dmamap_destroy(sc->mbuf_tag, pg->hdr.map); 330116491Sharti free(pg, M_DEVBUF); 331116491Sharti } 332116491Sharti free(sc->mbuf_pages, M_DEVBUF); 333116491Sharti } 334116491Sharti} 335116491Sharti 336116491Shartistatic void 337116491Shartihatm_init_smbufs(struct hatm_softc *sc) 338116491Sharti{ 339116491Sharti sc->mbuf_pages = malloc(sizeof(sc->mbuf_pages[0]) * 340121685Sharti sc->mbuf_max_pages, M_DEVBUF, M_WAITOK); 341116491Sharti sc->mbuf_npages = 0; 342116491Sharti} 343116491Sharti 344116491Sharti/* 345116491Sharti * Initialize/destroy TPDs. This is called from attach/detach. 346116491Sharti */ 347116491Shartistatic void 348116491Shartihatm_destroy_tpds(struct hatm_softc *sc) 349116491Sharti{ 350116491Sharti struct tpd *t; 351116491Sharti 352116491Sharti if (sc->tpds.base == NULL) 353116491Sharti return; 354116491Sharti 355116491Sharti DBG(sc, ATTACH, ("releasing TPDs ...")); 356116491Sharti if (sc->tpd_nfree != sc->tpd_total) 357147256Sbrooks if_printf(sc->ifp, "%u tpds still in use from %u\n", 358116491Sharti sc->tpd_total - sc->tpd_nfree, sc->tpd_total); 359116491Sharti while ((t = SLIST_FIRST(&sc->tpd_free)) != NULL) { 360116491Sharti SLIST_REMOVE_HEAD(&sc->tpd_free, link); 361116491Sharti bus_dmamap_destroy(sc->tx_tag, t->map); 362116491Sharti } 363116491Sharti hatm_destroy_dmamem(&sc->tpds); 364116491Sharti free(sc->tpd_used, M_DEVBUF); 365116491Sharti DBG(sc, ATTACH, ("... done")); 366116491Sharti} 367116491Shartistatic int 368116491Shartihatm_init_tpds(struct hatm_softc *sc) 369116491Sharti{ 370116491Sharti int error; 371116491Sharti u_int i; 372116491Sharti struct tpd *t; 373116491Sharti 374116491Sharti DBG(sc, ATTACH, ("allocating %u TPDs and maps ...", sc->tpd_total)); 375116491Sharti error = hatm_alloc_dmamem(sc, "TPD memory", &sc->tpds); 376116491Sharti if (error != 0) { 377116491Sharti DBG(sc, ATTACH, ("... dmamem error=%d", error)); 378116491Sharti return (error); 379116491Sharti } 380116491Sharti 381116491Sharti /* put all the TPDs on the free list and allocate DMA maps */ 382116491Sharti for (i = 0; i < sc->tpd_total; i++) { 383116491Sharti t = TPD_ADDR(sc, i); 384116491Sharti t->no = i; 385116491Sharti t->mbuf = NULL; 386116491Sharti error = bus_dmamap_create(sc->tx_tag, 0, &t->map); 387116491Sharti if (error != 0) { 388116491Sharti DBG(sc, ATTACH, ("... dmamap error=%d", error)); 389116491Sharti while ((t = SLIST_FIRST(&sc->tpd_free)) != NULL) { 390116491Sharti SLIST_REMOVE_HEAD(&sc->tpd_free, link); 391116491Sharti bus_dmamap_destroy(sc->tx_tag, t->map); 392116491Sharti } 393116491Sharti hatm_destroy_dmamem(&sc->tpds); 394116491Sharti return (error); 395116491Sharti } 396116491Sharti 397116491Sharti SLIST_INSERT_HEAD(&sc->tpd_free, t, link); 398116491Sharti } 399116491Sharti 400116491Sharti /* allocate and zero bitmap */ 401116491Sharti sc->tpd_used = malloc(sizeof(uint8_t) * (sc->tpd_total + 7) / 8, 402116491Sharti M_DEVBUF, M_ZERO | M_WAITOK); 403116491Sharti sc->tpd_nfree = sc->tpd_total; 404116491Sharti 405116491Sharti DBG(sc, ATTACH, ("... done")); 406116491Sharti 407116491Sharti return (0); 408116491Sharti} 409116491Sharti 410116491Sharti/* 411116491Sharti * Free all the TPDs that where given to the card. 412116491Sharti * An mbuf chain may be attached to a TPD - free it also and 413116491Sharti * unload its associated DMA map. 414116491Sharti */ 415116491Shartistatic void 416116491Shartihatm_stop_tpds(struct hatm_softc *sc) 417116491Sharti{ 418116491Sharti u_int i; 419116491Sharti struct tpd *t; 420116491Sharti 421116491Sharti DBG(sc, ATTACH, ("free TPDs ...")); 422116491Sharti for (i = 0; i < sc->tpd_total; i++) { 423116491Sharti if (TPD_TST_USED(sc, i)) { 424116491Sharti t = TPD_ADDR(sc, i); 425116491Sharti if (t->mbuf) { 426116491Sharti m_freem(t->mbuf); 427116491Sharti t->mbuf = NULL; 428116491Sharti bus_dmamap_unload(sc->tx_tag, t->map); 429116491Sharti } 430116491Sharti TPD_CLR_USED(sc, i); 431116491Sharti SLIST_INSERT_HEAD(&sc->tpd_free, t, link); 432116491Sharti sc->tpd_nfree++; 433116491Sharti } 434116491Sharti } 435116491Sharti} 436116491Sharti 437116491Sharti/* 438116491Sharti * This frees ALL resources of this interface and leaves the structure 439116491Sharti * in an indeterminate state. This is called just before detaching or 440116491Sharti * on a failed attach. No lock should be held. 441116491Sharti */ 442116491Shartistatic void 443116491Shartihatm_destroy(struct hatm_softc *sc) 444116491Sharti{ 445118598Sharti u_int cid; 446118598Sharti 447116491Sharti bus_teardown_intr(sc->dev, sc->irqres, sc->ih); 448116491Sharti 449116491Sharti hatm_destroy_rmaps(sc); 450116491Sharti hatm_destroy_smbufs(sc); 451116491Sharti hatm_destroy_tpds(sc); 452116491Sharti 453118598Sharti if (sc->vcc_zone != NULL) { 454118598Sharti for (cid = 0; cid < HE_MAX_VCCS; cid++) 455118598Sharti if (sc->vccs[cid] != NULL) 456118598Sharti uma_zfree(sc->vcc_zone, sc->vccs[cid]); 457116491Sharti uma_zdestroy(sc->vcc_zone); 458118598Sharti } 459116491Sharti 460116491Sharti /* 461116491Sharti * Release all memory allocated to the various queues and 462116491Sharti * Status pages. These have there own flag which shows whether 463116491Sharti * they are really allocated. 464116491Sharti */ 465116491Sharti hatm_destroy_dmamem(&sc->irq_0.mem); 466116491Sharti hatm_destroy_dmamem(&sc->rbp_s0.mem); 467116491Sharti hatm_destroy_dmamem(&sc->rbp_l0.mem); 468116491Sharti hatm_destroy_dmamem(&sc->rbp_s1.mem); 469116491Sharti hatm_destroy_dmamem(&sc->rbrq_0.mem); 470116491Sharti hatm_destroy_dmamem(&sc->rbrq_1.mem); 471116491Sharti hatm_destroy_dmamem(&sc->tbrq.mem); 472116491Sharti hatm_destroy_dmamem(&sc->tpdrq.mem); 473116491Sharti hatm_destroy_dmamem(&sc->hsp_mem); 474116491Sharti 475116491Sharti if (sc->irqres != NULL) 476116491Sharti bus_release_resource(sc->dev, SYS_RES_IRQ, 477116491Sharti sc->irqid, sc->irqres); 478116491Sharti 479116491Sharti if (sc->tx_tag != NULL) 480116491Sharti if (bus_dma_tag_destroy(sc->tx_tag)) 481147256Sbrooks if_printf(sc->ifp, "mbuf DMA tag busy\n"); 482116491Sharti 483116491Sharti if (sc->mbuf_tag != NULL) 484116491Sharti if (bus_dma_tag_destroy(sc->mbuf_tag)) 485147256Sbrooks if_printf(sc->ifp, "mbuf DMA tag busy\n"); 486116491Sharti 487116491Sharti if (sc->parent_tag != NULL) 488116491Sharti if (bus_dma_tag_destroy(sc->parent_tag)) 489147256Sbrooks if_printf(sc->ifp, "parent DMA tag busy\n"); 490116491Sharti 491116491Sharti if (sc->memres != NULL) 492116491Sharti bus_release_resource(sc->dev, SYS_RES_MEMORY, 493116491Sharti sc->memid, sc->memres); 494116491Sharti 495116491Sharti sysctl_ctx_free(&sc->sysctl_ctx); 496116491Sharti 497116491Sharti cv_destroy(&sc->cv_rcclose); 498116491Sharti cv_destroy(&sc->vcc_cv); 499116491Sharti mtx_destroy(&sc->mtx); 500150215Sru 501150215Sru if (sc->ifp != NULL) 502150215Sru if_free(sc->ifp); 503116491Sharti} 504116491Sharti 505116491Sharti/* 506116491Sharti * 4.4 Card reset 507116491Sharti */ 508116491Shartistatic int 509116491Shartihatm_reset(struct hatm_softc *sc) 510116491Sharti{ 511116491Sharti u_int v, count; 512116491Sharti 513116491Sharti WRITE4(sc, HE_REGO_RESET_CNTL, 0x00); 514116491Sharti BARRIER_W(sc); 515116491Sharti WRITE4(sc, HE_REGO_RESET_CNTL, 0xff); 516116491Sharti BARRIER_RW(sc); 517116491Sharti count = 0; 518116491Sharti while (((v = READ4(sc, HE_REGO_RESET_CNTL)) & HE_REGM_RESET_STATE) == 0) { 519116491Sharti BARRIER_R(sc); 520116491Sharti if (++count == 100) { 521147256Sbrooks if_printf(sc->ifp, "reset failed\n"); 522116491Sharti return (ENXIO); 523116491Sharti } 524116491Sharti DELAY(1000); 525116491Sharti } 526116491Sharti return (0); 527116491Sharti} 528116491Sharti 529116491Sharti/* 530116491Sharti * 4.5 Set Bus Width 531116491Sharti */ 532116491Shartistatic void 533116491Shartihatm_init_bus_width(struct hatm_softc *sc) 534116491Sharti{ 535116491Sharti uint32_t v, v1; 536116491Sharti 537116491Sharti v = READ4(sc, HE_REGO_HOST_CNTL); 538116491Sharti BARRIER_R(sc); 539116491Sharti if (v & HE_REGM_HOST_BUS64) { 540116491Sharti sc->pci64 = 1; 541116491Sharti v1 = pci_read_config(sc->dev, HE_PCIR_GEN_CNTL_0, 4); 542116491Sharti v1 |= HE_PCIM_CTL0_64BIT; 543116491Sharti pci_write_config(sc->dev, HE_PCIR_GEN_CNTL_0, v1, 4); 544116491Sharti 545116491Sharti v |= HE_REGM_HOST_DESC_RD64 546116491Sharti | HE_REGM_HOST_DATA_RD64 547116491Sharti | HE_REGM_HOST_DATA_WR64; 548116491Sharti WRITE4(sc, HE_REGO_HOST_CNTL, v); 549116491Sharti BARRIER_W(sc); 550116491Sharti } else { 551116491Sharti sc->pci64 = 0; 552116491Sharti v = pci_read_config(sc->dev, HE_PCIR_GEN_CNTL_0, 4); 553116491Sharti v &= ~HE_PCIM_CTL0_64BIT; 554116491Sharti pci_write_config(sc->dev, HE_PCIR_GEN_CNTL_0, v, 4); 555116491Sharti } 556116491Sharti} 557116491Sharti 558116491Sharti/* 559116491Sharti * 4.6 Set Host Endianess 560116491Sharti */ 561116491Shartistatic void 562116491Shartihatm_init_endianess(struct hatm_softc *sc) 563116491Sharti{ 564116491Sharti uint32_t v; 565116491Sharti 566116491Sharti v = READ4(sc, HE_REGO_LB_SWAP); 567116491Sharti BARRIER_R(sc); 568116491Sharti#if BYTE_ORDER == BIG_ENDIAN 569116491Sharti v |= HE_REGM_LBSWAP_INTR_SWAP | 570116491Sharti HE_REGM_LBSWAP_DESC_WR_SWAP | 571116491Sharti HE_REGM_LBSWAP_BIG_ENDIAN; 572116491Sharti v &= ~(HE_REGM_LBSWAP_DATA_WR_SWAP | 573116491Sharti HE_REGM_LBSWAP_DESC_RD_SWAP | 574116491Sharti HE_REGM_LBSWAP_DATA_RD_SWAP); 575116491Sharti#else 576116491Sharti v &= ~(HE_REGM_LBSWAP_DATA_WR_SWAP | 577116491Sharti HE_REGM_LBSWAP_DESC_RD_SWAP | 578116491Sharti HE_REGM_LBSWAP_DATA_RD_SWAP | 579116491Sharti HE_REGM_LBSWAP_INTR_SWAP | 580116491Sharti HE_REGM_LBSWAP_DESC_WR_SWAP | 581116491Sharti HE_REGM_LBSWAP_BIG_ENDIAN); 582116491Sharti#endif 583116491Sharti 584116491Sharti if (sc->he622) 585116491Sharti v |= HE_REGM_LBSWAP_XFER_SIZE; 586116491Sharti 587116491Sharti WRITE4(sc, HE_REGO_LB_SWAP, v); 588116491Sharti BARRIER_W(sc); 589116491Sharti} 590116491Sharti 591116491Sharti/* 592116491Sharti * 4.7 Read EEPROM 593116491Sharti */ 594116491Shartistatic uint8_t 595116491Shartihatm_read_prom_byte(struct hatm_softc *sc, u_int addr) 596116491Sharti{ 597116491Sharti uint32_t val, tmp_read, byte_read; 598116491Sharti u_int i, j; 599116491Sharti int n; 600116491Sharti 601116491Sharti val = READ4(sc, HE_REGO_HOST_CNTL); 602116491Sharti val &= HE_REGM_HOST_PROM_BITS; 603116491Sharti BARRIER_R(sc); 604116491Sharti 605116491Sharti val |= HE_REGM_HOST_PROM_WREN; 606116491Sharti WRITE4(sc, HE_REGO_HOST_CNTL, val); 607116491Sharti BARRIER_W(sc); 608116491Sharti 609116491Sharti /* send READ */ 610116491Sharti for (i = 0; i < sizeof(readtab) / sizeof(readtab[0]); i++) { 611116491Sharti WRITE4(sc, HE_REGO_HOST_CNTL, val | readtab[i]); 612116491Sharti BARRIER_W(sc); 613116491Sharti DELAY(EEPROM_DELAY); 614116491Sharti } 615116491Sharti 616116491Sharti /* send ADDRESS */ 617116491Sharti for (n = 7, j = 0; n >= 0; n--) { 618116491Sharti WRITE4(sc, HE_REGO_HOST_CNTL, val | clocktab[j++] | 619116491Sharti (((addr >> n) & 1 ) << HE_REGS_HOST_PROM_DATA_IN)); 620116491Sharti BARRIER_W(sc); 621116491Sharti DELAY(EEPROM_DELAY); 622116491Sharti WRITE4(sc, HE_REGO_HOST_CNTL, val | clocktab[j++] | 623116491Sharti (((addr >> n) & 1 ) << HE_REGS_HOST_PROM_DATA_IN)); 624116491Sharti BARRIER_W(sc); 625116491Sharti DELAY(EEPROM_DELAY); 626116491Sharti } 627116491Sharti 628116491Sharti val &= ~HE_REGM_HOST_PROM_WREN; 629116491Sharti WRITE4(sc, HE_REGO_HOST_CNTL, val); 630116491Sharti BARRIER_W(sc); 631116491Sharti 632116491Sharti /* read DATA */ 633116491Sharti byte_read = 0; 634116491Sharti for (n = 7, j = 0; n >= 0; n--) { 635116491Sharti WRITE4(sc, HE_REGO_HOST_CNTL, val | clocktab[j++]); 636116491Sharti BARRIER_W(sc); 637116491Sharti DELAY(EEPROM_DELAY); 638116491Sharti tmp_read = READ4(sc, HE_REGO_HOST_CNTL); 639116491Sharti byte_read |= (uint8_t)(((tmp_read & HE_REGM_HOST_PROM_DATA_OUT) 640116491Sharti >> HE_REGS_HOST_PROM_DATA_OUT) << n); 641116491Sharti WRITE4(sc, HE_REGO_HOST_CNTL, val | clocktab[j++]); 642116491Sharti BARRIER_W(sc); 643116491Sharti DELAY(EEPROM_DELAY); 644116491Sharti } 645116491Sharti WRITE4(sc, HE_REGO_HOST_CNTL, val | clocktab[j++]); 646116491Sharti BARRIER_W(sc); 647116491Sharti DELAY(EEPROM_DELAY); 648116491Sharti 649116491Sharti return (byte_read); 650116491Sharti} 651116491Sharti 652116491Shartistatic void 653116491Shartihatm_init_read_eeprom(struct hatm_softc *sc) 654116491Sharti{ 655116491Sharti u_int n, count; 656116491Sharti u_char byte; 657116491Sharti uint32_t v; 658116491Sharti 659116491Sharti for (n = count = 0; count < HE_EEPROM_PROD_ID_LEN; count++) { 660116491Sharti byte = hatm_read_prom_byte(sc, HE_EEPROM_PROD_ID + count); 661116491Sharti if (n > 0 || byte != ' ') 662116491Sharti sc->prod_id[n++] = byte; 663116491Sharti } 664116491Sharti while (n > 0 && sc->prod_id[n-1] == ' ') 665116491Sharti n--; 666116491Sharti sc->prod_id[n] = '\0'; 667116491Sharti 668116491Sharti for (n = count = 0; count < HE_EEPROM_REV_LEN; count++) { 669116491Sharti byte = hatm_read_prom_byte(sc, HE_EEPROM_REV + count); 670116491Sharti if (n > 0 || byte != ' ') 671116491Sharti sc->rev[n++] = byte; 672116491Sharti } 673116491Sharti while (n > 0 && sc->rev[n-1] == ' ') 674116491Sharti n--; 675116491Sharti sc->rev[n] = '\0'; 676147256Sbrooks IFP2IFATM(sc->ifp)->mib.hw_version = sc->rev[0]; 677116491Sharti 678147256Sbrooks IFP2IFATM(sc->ifp)->mib.serial = hatm_read_prom_byte(sc, HE_EEPROM_M_SN + 0) << 0; 679147256Sbrooks IFP2IFATM(sc->ifp)->mib.serial |= hatm_read_prom_byte(sc, HE_EEPROM_M_SN + 1) << 8; 680147256Sbrooks IFP2IFATM(sc->ifp)->mib.serial |= hatm_read_prom_byte(sc, HE_EEPROM_M_SN + 2) << 16; 681147256Sbrooks IFP2IFATM(sc->ifp)->mib.serial |= hatm_read_prom_byte(sc, HE_EEPROM_M_SN + 3) << 24; 682116491Sharti 683116491Sharti v = hatm_read_prom_byte(sc, HE_EEPROM_MEDIA + 0) << 0; 684116491Sharti v |= hatm_read_prom_byte(sc, HE_EEPROM_MEDIA + 1) << 8; 685116491Sharti v |= hatm_read_prom_byte(sc, HE_EEPROM_MEDIA + 2) << 16; 686116491Sharti v |= hatm_read_prom_byte(sc, HE_EEPROM_MEDIA + 3) << 24; 687116491Sharti 688116491Sharti switch (v) { 689116491Sharti case HE_MEDIA_UTP155: 690147256Sbrooks IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_UTP_155; 691147256Sbrooks IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_155M; 692116491Sharti break; 693116491Sharti 694116491Sharti case HE_MEDIA_MMF155: 695147256Sbrooks IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_MM_155; 696147256Sbrooks IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_155M; 697116491Sharti break; 698116491Sharti 699116491Sharti case HE_MEDIA_MMF622: 700147256Sbrooks IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_MM_622; 701147256Sbrooks IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_HE622; 702147256Sbrooks IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_622M; 703116491Sharti sc->he622 = 1; 704116491Sharti break; 705116491Sharti 706116491Sharti case HE_MEDIA_SMF155: 707147256Sbrooks IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_SM_155; 708147256Sbrooks IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_155M; 709116491Sharti break; 710116491Sharti 711116491Sharti case HE_MEDIA_SMF622: 712147256Sbrooks IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_SM_622; 713147256Sbrooks IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_HE622; 714147256Sbrooks IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_622M; 715116491Sharti sc->he622 = 1; 716116491Sharti break; 717116491Sharti } 718116491Sharti 719147256Sbrooks IFP2IFATM(sc->ifp)->mib.esi[0] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 0); 720147256Sbrooks IFP2IFATM(sc->ifp)->mib.esi[1] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 1); 721147256Sbrooks IFP2IFATM(sc->ifp)->mib.esi[2] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 2); 722147256Sbrooks IFP2IFATM(sc->ifp)->mib.esi[3] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 3); 723147256Sbrooks IFP2IFATM(sc->ifp)->mib.esi[4] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 4); 724147256Sbrooks IFP2IFATM(sc->ifp)->mib.esi[5] = hatm_read_prom_byte(sc, HE_EEPROM_MAC + 5); 725116491Sharti} 726116491Sharti 727116491Sharti/* 728116491Sharti * Clear unused interrupt queue 729116491Sharti */ 730116491Shartistatic void 731116491Shartihatm_clear_irq(struct hatm_softc *sc, u_int group) 732116491Sharti{ 733116491Sharti WRITE4(sc, HE_REGO_IRQ_BASE(group), 0); 734116491Sharti WRITE4(sc, HE_REGO_IRQ_HEAD(group), 0); 735116491Sharti WRITE4(sc, HE_REGO_IRQ_CNTL(group), 0); 736116491Sharti WRITE4(sc, HE_REGO_IRQ_DATA(group), 0); 737116491Sharti} 738116491Sharti 739116491Sharti/* 740116491Sharti * 4.10 Initialize interrupt queues 741116491Sharti */ 742116491Shartistatic void 743116491Shartihatm_init_irq(struct hatm_softc *sc, struct heirq *q, u_int group) 744116491Sharti{ 745116491Sharti u_int i; 746116491Sharti 747116491Sharti if (q->size == 0) { 748116491Sharti hatm_clear_irq(sc, group); 749116491Sharti return; 750116491Sharti } 751116491Sharti 752116491Sharti q->group = group; 753116491Sharti q->sc = sc; 754116491Sharti q->irq = q->mem.base; 755116491Sharti q->head = 0; 756116491Sharti q->tailp = q->irq + (q->size - 1); 757116491Sharti *q->tailp = 0; 758116491Sharti 759116491Sharti for (i = 0; i < q->size; i++) 760116491Sharti q->irq[i] = HE_REGM_ITYPE_INVALID; 761116491Sharti 762116491Sharti WRITE4(sc, HE_REGO_IRQ_BASE(group), q->mem.paddr); 763116491Sharti WRITE4(sc, HE_REGO_IRQ_HEAD(group), 764116491Sharti ((q->size - 1) << HE_REGS_IRQ_HEAD_SIZE) | 765116491Sharti (q->thresh << HE_REGS_IRQ_HEAD_THRESH)); 766116491Sharti WRITE4(sc, HE_REGO_IRQ_CNTL(group), q->line); 767116491Sharti WRITE4(sc, HE_REGO_IRQ_DATA(group), 0); 768116491Sharti} 769116491Sharti 770116491Sharti/* 771116491Sharti * 5.1.3 Initialize connection memory 772116491Sharti */ 773116491Shartistatic void 774116491Shartihatm_init_cm(struct hatm_softc *sc) 775116491Sharti{ 776116491Sharti u_int rsra, mlbm, rabr, numbuffs; 777116491Sharti u_int tsra, tabr, mtpd; 778116491Sharti u_int n; 779116491Sharti 780116491Sharti for (n = 0; n < HE_CONFIG_TXMEM; n++) 781116491Sharti WRITE_TCM4(sc, n, 0); 782116491Sharti for (n = 0; n < HE_CONFIG_RXMEM; n++) 783116491Sharti WRITE_RCM4(sc, n, 0); 784116491Sharti 785116491Sharti numbuffs = sc->r0_numbuffs + sc->r1_numbuffs + sc->tx_numbuffs; 786116491Sharti 787116491Sharti rsra = 0; 788147256Sbrooks mlbm = ((rsra + IFP2IFATM(sc->ifp)->mib.max_vccs * 8) + 0x7ff) & ~0x7ff; 789116491Sharti rabr = ((mlbm + numbuffs * 2) + 0x7ff) & ~0x7ff; 790147256Sbrooks sc->rsrb = ((rabr + 2048) + (2 * IFP2IFATM(sc->ifp)->mib.max_vccs - 1)) & 791147256Sbrooks ~(2 * IFP2IFATM(sc->ifp)->mib.max_vccs - 1); 792116491Sharti 793116491Sharti tsra = 0; 794147256Sbrooks sc->tsrb = tsra + IFP2IFATM(sc->ifp)->mib.max_vccs * 8; 795147256Sbrooks sc->tsrc = sc->tsrb + IFP2IFATM(sc->ifp)->mib.max_vccs * 4; 796147256Sbrooks sc->tsrd = sc->tsrc + IFP2IFATM(sc->ifp)->mib.max_vccs * 2; 797147256Sbrooks tabr = sc->tsrd + IFP2IFATM(sc->ifp)->mib.max_vccs * 1; 798147256Sbrooks mtpd = ((tabr + 1024) + (16 * IFP2IFATM(sc->ifp)->mib.max_vccs - 1)) & 799147256Sbrooks ~(16 * IFP2IFATM(sc->ifp)->mib.max_vccs - 1); 800116491Sharti 801116491Sharti DBG(sc, ATTACH, ("rsra=%x mlbm=%x rabr=%x rsrb=%x", 802116491Sharti rsra, mlbm, rabr, sc->rsrb)); 803116491Sharti DBG(sc, ATTACH, ("tsra=%x tsrb=%x tsrc=%x tsrd=%x tabr=%x mtpd=%x", 804116491Sharti tsra, sc->tsrb, sc->tsrc, sc->tsrd, tabr, mtpd)); 805116491Sharti 806116491Sharti WRITE4(sc, HE_REGO_TSRB_BA, sc->tsrb); 807116491Sharti WRITE4(sc, HE_REGO_TSRC_BA, sc->tsrc); 808116491Sharti WRITE4(sc, HE_REGO_TSRD_BA, sc->tsrd); 809116491Sharti WRITE4(sc, HE_REGO_TMABR_BA, tabr); 810116491Sharti WRITE4(sc, HE_REGO_TPD_BA, mtpd); 811116491Sharti 812116491Sharti WRITE4(sc, HE_REGO_RCMRSRB_BA, sc->rsrb); 813116491Sharti WRITE4(sc, HE_REGO_RCMLBM_BA, mlbm); 814116491Sharti WRITE4(sc, HE_REGO_RCMABR_BA, rabr); 815116491Sharti 816116491Sharti BARRIER_W(sc); 817116491Sharti} 818116491Sharti 819116491Sharti/* 820116491Sharti * 5.1.4 Initialize Local buffer Pools 821116491Sharti */ 822116491Shartistatic void 823116491Shartihatm_init_rx_buffer_pool(struct hatm_softc *sc, 824116491Sharti u_int num, /* bank */ 825116491Sharti u_int start, /* start row */ 826116491Sharti u_int numbuffs /* number of entries */ 827116491Sharti) 828116491Sharti{ 829116491Sharti u_int row_size; /* bytes per row */ 830116491Sharti uint32_t row_addr; /* start address of this row */ 831116491Sharti u_int lbuf_size; /* bytes per lbuf */ 832116491Sharti u_int lbufs_per_row; /* number of lbufs per memory row */ 833116491Sharti uint32_t lbufd_index; /* index of lbuf descriptor */ 834116491Sharti uint32_t lbufd_addr; /* address of lbuf descriptor */ 835116491Sharti u_int lbuf_row_cnt; /* current lbuf in current row */ 836116491Sharti uint32_t lbuf_addr; /* address of current buffer */ 837116491Sharti u_int i; 838116491Sharti 839201758Smbr row_size = sc->bytes_per_row; 840116491Sharti row_addr = start * row_size; 841116491Sharti lbuf_size = sc->cells_per_lbuf * 48; 842116491Sharti lbufs_per_row = sc->cells_per_row / sc->cells_per_lbuf; 843116491Sharti 844116491Sharti /* descriptor index */ 845116491Sharti lbufd_index = num; 846116491Sharti 847116491Sharti /* 2 words per entry */ 848116491Sharti lbufd_addr = READ4(sc, HE_REGO_RCMLBM_BA) + lbufd_index * 2; 849116491Sharti 850116491Sharti /* write head of queue */ 851116491Sharti WRITE4(sc, HE_REGO_RLBF_H(num), lbufd_index); 852116491Sharti 853116491Sharti lbuf_row_cnt = 0; 854116491Sharti for (i = 0; i < numbuffs; i++) { 855116491Sharti lbuf_addr = (row_addr + lbuf_row_cnt * lbuf_size) / 32; 856116491Sharti 857116491Sharti WRITE_RCM4(sc, lbufd_addr, lbuf_addr); 858116491Sharti 859116491Sharti lbufd_index += 2; 860116491Sharti WRITE_RCM4(sc, lbufd_addr + 1, lbufd_index); 861116491Sharti 862116491Sharti if (++lbuf_row_cnt == lbufs_per_row) { 863116491Sharti lbuf_row_cnt = 0; 864116491Sharti row_addr += row_size; 865116491Sharti } 866116491Sharti 867116491Sharti lbufd_addr += 2 * 2; 868116491Sharti } 869116491Sharti 870116491Sharti WRITE4(sc, HE_REGO_RLBF_T(num), lbufd_index - 2); 871116491Sharti WRITE4(sc, HE_REGO_RLBF_C(num), numbuffs); 872116491Sharti 873116491Sharti BARRIER_W(sc); 874116491Sharti} 875116491Sharti 876116491Shartistatic void 877116491Shartihatm_init_tx_buffer_pool(struct hatm_softc *sc, 878116491Sharti u_int start, /* start row */ 879116491Sharti u_int numbuffs /* number of entries */ 880116491Sharti) 881116491Sharti{ 882116491Sharti u_int row_size; /* bytes per row */ 883116491Sharti uint32_t row_addr; /* start address of this row */ 884116491Sharti u_int lbuf_size; /* bytes per lbuf */ 885116491Sharti u_int lbufs_per_row; /* number of lbufs per memory row */ 886116491Sharti uint32_t lbufd_index; /* index of lbuf descriptor */ 887116491Sharti uint32_t lbufd_addr; /* address of lbuf descriptor */ 888116491Sharti u_int lbuf_row_cnt; /* current lbuf in current row */ 889116491Sharti uint32_t lbuf_addr; /* address of current buffer */ 890116491Sharti u_int i; 891116491Sharti 892201758Smbr row_size = sc->bytes_per_row; 893116491Sharti row_addr = start * row_size; 894116491Sharti lbuf_size = sc->cells_per_lbuf * 48; 895116491Sharti lbufs_per_row = sc->cells_per_row / sc->cells_per_lbuf; 896116491Sharti 897116491Sharti /* descriptor index */ 898116491Sharti lbufd_index = sc->r0_numbuffs + sc->r1_numbuffs; 899116491Sharti 900116491Sharti /* 2 words per entry */ 901116491Sharti lbufd_addr = READ4(sc, HE_REGO_RCMLBM_BA) + lbufd_index * 2; 902116491Sharti 903116491Sharti /* write head of queue */ 904116491Sharti WRITE4(sc, HE_REGO_TLBF_H, lbufd_index); 905116491Sharti 906116491Sharti lbuf_row_cnt = 0; 907116491Sharti for (i = 0; i < numbuffs; i++) { 908116491Sharti lbuf_addr = (row_addr + lbuf_row_cnt * lbuf_size) / 32; 909116491Sharti 910116491Sharti WRITE_RCM4(sc, lbufd_addr, lbuf_addr); 911116491Sharti lbufd_index++; 912116491Sharti WRITE_RCM4(sc, lbufd_addr + 1, lbufd_index); 913116491Sharti 914116491Sharti if (++lbuf_row_cnt == lbufs_per_row) { 915116491Sharti lbuf_row_cnt = 0; 916116491Sharti row_addr += row_size; 917116491Sharti } 918116491Sharti 919116491Sharti lbufd_addr += 2; 920116491Sharti } 921116491Sharti 922116491Sharti WRITE4(sc, HE_REGO_TLBF_T, lbufd_index - 1); 923116491Sharti BARRIER_W(sc); 924116491Sharti} 925116491Sharti 926116491Sharti/* 927116491Sharti * 5.1.5 Initialize Intermediate Receive Queues 928116491Sharti */ 929116491Shartistatic void 930116491Shartihatm_init_imed_queues(struct hatm_softc *sc) 931116491Sharti{ 932116491Sharti u_int n; 933116491Sharti 934116491Sharti if (sc->he622) { 935116491Sharti for (n = 0; n < 8; n++) { 936116491Sharti WRITE4(sc, HE_REGO_INMQ_S(n), 0x10*n+0x000f); 937116491Sharti WRITE4(sc, HE_REGO_INMQ_L(n), 0x10*n+0x200f); 938116491Sharti } 939116491Sharti } else { 940116491Sharti for (n = 0; n < 8; n++) { 941116491Sharti WRITE4(sc, HE_REGO_INMQ_S(n), n); 942116491Sharti WRITE4(sc, HE_REGO_INMQ_L(n), n+0x8); 943116491Sharti } 944116491Sharti } 945116491Sharti} 946116491Sharti 947116491Sharti/* 948116491Sharti * 5.1.7 Init CS block 949116491Sharti */ 950116491Shartistatic void 951116491Shartihatm_init_cs_block(struct hatm_softc *sc) 952116491Sharti{ 953116491Sharti u_int n, i; 954116491Sharti u_int clkfreg, cellrate, decr, tmp; 955116491Sharti static const uint32_t erthr[2][5][3] = HE_REGT_CS_ERTHR; 956116491Sharti static const uint32_t erctl[2][3] = HE_REGT_CS_ERCTL; 957116491Sharti static const uint32_t erstat[2][2] = HE_REGT_CS_ERSTAT; 958116491Sharti static const uint32_t rtfwr[2] = HE_REGT_CS_RTFWR; 959116491Sharti static const uint32_t rtatr[2] = HE_REGT_CS_RTATR; 960116491Sharti static const uint32_t bwalloc[2][6] = HE_REGT_CS_BWALLOC; 961116491Sharti static const uint32_t orcf[2][2] = HE_REGT_CS_ORCF; 962116491Sharti 963116491Sharti /* Clear Rate Controller Start Times and Occupied Flags */ 964116491Sharti for (n = 0; n < 32; n++) 965116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_STTIM(n), 0); 966116491Sharti 967116491Sharti clkfreg = sc->he622 ? HE_622_CLOCK : HE_155_CLOCK; 968116491Sharti cellrate = sc->he622 ? ATM_RATE_622M : ATM_RATE_155M; 969116491Sharti decr = cellrate / 32; 970116491Sharti 971116491Sharti for (n = 0; n < 16; n++) { 972116491Sharti tmp = clkfreg / cellrate; 973116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_TGRLD(n), tmp - 1); 974116491Sharti cellrate -= decr; 975116491Sharti } 976116491Sharti 977116491Sharti i = (sc->cells_per_lbuf == 2) ? 0 978116491Sharti :(sc->cells_per_lbuf == 4) ? 1 979116491Sharti : 2; 980116491Sharti 981116491Sharti /* table 5.2 */ 982116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_ERTHR0, erthr[sc->he622][0][i]); 983116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_ERTHR1, erthr[sc->he622][1][i]); 984116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_ERTHR2, erthr[sc->he622][2][i]); 985116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_ERTHR3, erthr[sc->he622][3][i]); 986116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_ERTHR4, erthr[sc->he622][4][i]); 987116491Sharti 988116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_ERCTL0, erctl[sc->he622][0]); 989116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_ERCTL1, erctl[sc->he622][1]); 990116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_ERCTL2, erctl[sc->he622][2]); 991116491Sharti 992116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_ERSTAT0, erstat[sc->he622][0]); 993116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_ERSTAT1, erstat[sc->he622][1]); 994116491Sharti 995116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_RTFWR, rtfwr[sc->he622]); 996116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_RTATR, rtatr[sc->he622]); 997116491Sharti 998116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_TFBSET, bwalloc[sc->he622][0]); 999116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_WCRMAX, bwalloc[sc->he622][1]); 1000116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_WCRMIN, bwalloc[sc->he622][2]); 1001116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_WCRINC, bwalloc[sc->he622][3]); 1002116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_WCRDEC, bwalloc[sc->he622][4]); 1003116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_WCRCEIL, bwalloc[sc->he622][5]); 1004116491Sharti 1005116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_OTPPER, orcf[sc->he622][0]); 1006116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_OTWPER, orcf[sc->he622][1]); 1007116491Sharti 1008116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_OTTLIM, 8); 1009116491Sharti 1010116491Sharti for (n = 0; n < 8; n++) 1011116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_HGRRT(n), 0); 1012116491Sharti} 1013116491Sharti 1014116491Sharti/* 1015116491Sharti * 5.1.8 CS Block Connection Memory Initialisation 1016116491Sharti */ 1017116491Shartistatic void 1018116491Shartihatm_init_cs_block_cm(struct hatm_softc *sc) 1019116491Sharti{ 1020116491Sharti u_int n, i; 1021116491Sharti u_int expt, mant, etrm, wcr, ttnrm, tnrm; 1022116491Sharti uint32_t rate; 1023116491Sharti uint32_t clkfreq, cellrate, decr; 1024116491Sharti uint32_t *rg, rtg, val = 0; 1025116491Sharti uint64_t drate; 1026116491Sharti u_int buf, buf_limit; 1027116491Sharti uint32_t base = READ4(sc, HE_REGO_RCMABR_BA); 1028116491Sharti 1029116491Sharti for (n = 0; n < HE_REGL_CM_GQTBL; n++) 1030116491Sharti WRITE_RCM4(sc, base + HE_REGO_CM_GQTBL + n, 0); 1031116491Sharti for (n = 0; n < HE_REGL_CM_RGTBL; n++) 1032116491Sharti WRITE_RCM4(sc, base + HE_REGO_CM_RGTBL + n, 0); 1033116491Sharti 1034116491Sharti tnrm = 0; 1035116491Sharti for (n = 0; n < HE_REGL_CM_TNRMTBL * 4; n++) { 1036116491Sharti expt = (n >> 5) & 0x1f; 1037116491Sharti mant = ((n & 0x18) << 4) | 0x7f; 1038116491Sharti wcr = (1 << expt) * (mant + 512) / 512; 1039116491Sharti etrm = n & 0x7; 1040116491Sharti ttnrm = wcr / 10 / (1 << etrm); 1041116491Sharti if (ttnrm > 255) 1042116491Sharti ttnrm = 255; 1043116491Sharti else if(ttnrm < 2) 1044116491Sharti ttnrm = 2; 1045116491Sharti tnrm = (tnrm << 8) | (ttnrm & 0xff); 1046116491Sharti if (n % 4 == 0) 1047116491Sharti WRITE_RCM4(sc, base + HE_REGO_CM_TNRMTBL + (n/4), tnrm); 1048116491Sharti } 1049116491Sharti 1050116491Sharti clkfreq = sc->he622 ? HE_622_CLOCK : HE_155_CLOCK; 1051116491Sharti buf_limit = 4; 1052116491Sharti 1053116491Sharti cellrate = sc->he622 ? ATM_RATE_622M : ATM_RATE_155M; 1054116491Sharti decr = cellrate / 32; 1055116491Sharti 1056116491Sharti /* compute GRID top row in 1000 * cps */ 1057116491Sharti for (n = 0; n < 16; n++) { 1058116491Sharti u_int interval = clkfreq / cellrate; 1059116491Sharti sc->rate_grid[0][n] = (u_int64_t)clkfreq * 1000 / interval; 1060116491Sharti cellrate -= decr; 1061116491Sharti } 1062116491Sharti 1063116491Sharti /* compute the other rows according to 2.4 */ 1064116491Sharti for (i = 1; i < 16; i++) 1065116491Sharti for (n = 0; n < 16; n++) 1066116491Sharti sc->rate_grid[i][n] = sc->rate_grid[i-1][n] / 1067116491Sharti ((i < 14) ? 2 : 4); 1068116491Sharti 1069116491Sharti /* first entry is line rate */ 1070116491Sharti n = hatm_cps2atmf(sc->he622 ? ATM_RATE_622M : ATM_RATE_155M); 1071116491Sharti expt = (n >> 9) & 0x1f; 1072116491Sharti mant = n & 0x1f0; 1073116491Sharti sc->rate_grid[0][0] = (u_int64_t)(1<<expt) * 1000 * (mant+512) / 512; 1074116491Sharti 1075116491Sharti /* now build the conversion table - each 32 bit word contains 1076116491Sharti * two entries - this gives a total of 0x400 16 bit entries. 1077116491Sharti * This table maps the truncated ATMF rate version into a grid index */ 1078116491Sharti cellrate = sc->he622 ? ATM_RATE_622M : ATM_RATE_155M; 1079116491Sharti rg = &sc->rate_grid[15][15]; 1080116491Sharti 1081116491Sharti for (rate = 0; rate < 2 * HE_REGL_CM_RTGTBL; rate++) { 1082116491Sharti /* unpack the ATMF rate */ 1083116491Sharti expt = rate >> 5; 1084116491Sharti mant = (rate & 0x1f) << 4; 1085116491Sharti 1086116491Sharti /* get the cell rate - minimum is 10 per second */ 1087116491Sharti drate = (uint64_t)(1 << expt) * 1000 * (mant + 512) / 512; 1088116491Sharti if (drate < 10 * 1000) 1089116491Sharti drate = 10 * 1000; 1090116491Sharti 1091116491Sharti /* now look up the grid index */ 1092116491Sharti while (drate >= *rg && rg-- > &sc->rate_grid[0][0]) 1093116491Sharti ; 1094116491Sharti rg++; 1095116491Sharti rtg = rg - &sc->rate_grid[0][0]; 1096116491Sharti 1097116491Sharti /* now compute the buffer limit */ 1098116491Sharti buf = drate * sc->tx_numbuffs / (cellrate * 2) / 1000; 1099116491Sharti if (buf == 0) 1100116491Sharti buf = 1; 1101116491Sharti else if (buf > buf_limit) 1102116491Sharti buf = buf_limit; 1103116491Sharti 1104116491Sharti /* make value */ 1105116491Sharti val = (val << 16) | (rtg << 8) | buf; 1106116491Sharti 1107116491Sharti /* write */ 1108116491Sharti if (rate % 2 == 1) 1109116491Sharti WRITE_RCM4(sc, base + HE_REGO_CM_RTGTBL + rate/2, val); 1110116491Sharti } 1111116491Sharti} 1112116491Sharti 1113116491Sharti/* 1114116491Sharti * Clear an unused receive group buffer pool 1115116491Sharti */ 1116116491Shartistatic void 1117116491Shartihatm_clear_rpool(struct hatm_softc *sc, u_int group, u_int large) 1118116491Sharti{ 1119116491Sharti WRITE4(sc, HE_REGO_RBP_S(large, group), 0); 1120116491Sharti WRITE4(sc, HE_REGO_RBP_T(large, group), 0); 1121116491Sharti WRITE4(sc, HE_REGO_RBP_QI(large, group), 1); 1122116491Sharti WRITE4(sc, HE_REGO_RBP_BL(large, group), 0); 1123116491Sharti} 1124116491Sharti 1125116491Sharti/* 1126116491Sharti * Initialize a receive group buffer pool 1127116491Sharti */ 1128116491Shartistatic void 1129116491Shartihatm_init_rpool(struct hatm_softc *sc, struct herbp *q, u_int group, 1130116491Sharti u_int large) 1131116491Sharti{ 1132116491Sharti if (q->size == 0) { 1133116491Sharti hatm_clear_rpool(sc, group, large); 1134116491Sharti return; 1135116491Sharti } 1136116491Sharti 1137116491Sharti bzero(q->mem.base, q->mem.size); 1138116491Sharti q->rbp = q->mem.base; 1139116491Sharti q->head = q->tail = 0; 1140116491Sharti 1141116491Sharti DBG(sc, ATTACH, ("RBP%u%c=0x%lx", group, "SL"[large], 1142116491Sharti (u_long)q->mem.paddr)); 1143116491Sharti 1144116491Sharti WRITE4(sc, HE_REGO_RBP_S(large, group), q->mem.paddr); 1145116491Sharti WRITE4(sc, HE_REGO_RBP_T(large, group), 0); 1146116491Sharti WRITE4(sc, HE_REGO_RBP_QI(large, group), 1147116491Sharti ((q->size - 1) << HE_REGS_RBP_SIZE) | 1148116491Sharti HE_REGM_RBP_INTR_ENB | 1149116491Sharti (q->thresh << HE_REGS_RBP_THRESH)); 1150116491Sharti WRITE4(sc, HE_REGO_RBP_BL(large, group), (q->bsize >> 2) & ~1); 1151116491Sharti} 1152116491Sharti 1153116491Sharti/* 1154116491Sharti * Clear an unused receive buffer return queue 1155116491Sharti */ 1156116491Shartistatic void 1157116491Shartihatm_clear_rbrq(struct hatm_softc *sc, u_int group) 1158116491Sharti{ 1159116491Sharti WRITE4(sc, HE_REGO_RBRQ_ST(group), 0); 1160116491Sharti WRITE4(sc, HE_REGO_RBRQ_H(group), 0); 1161116491Sharti WRITE4(sc, HE_REGO_RBRQ_Q(group), (1 << HE_REGS_RBRQ_THRESH)); 1162116491Sharti WRITE4(sc, HE_REGO_RBRQ_I(group), 0); 1163116491Sharti} 1164116491Sharti 1165116491Sharti/* 1166116491Sharti * Initialize receive buffer return queue 1167116491Sharti */ 1168116491Shartistatic void 1169116491Shartihatm_init_rbrq(struct hatm_softc *sc, struct herbrq *rq, u_int group) 1170116491Sharti{ 1171116491Sharti if (rq->size == 0) { 1172116491Sharti hatm_clear_rbrq(sc, group); 1173116491Sharti return; 1174116491Sharti } 1175116491Sharti 1176116491Sharti rq->rbrq = rq->mem.base; 1177116491Sharti rq->head = 0; 1178116491Sharti 1179116491Sharti DBG(sc, ATTACH, ("RBRQ%u=0x%lx", group, (u_long)rq->mem.paddr)); 1180116491Sharti 1181116491Sharti WRITE4(sc, HE_REGO_RBRQ_ST(group), rq->mem.paddr); 1182116491Sharti WRITE4(sc, HE_REGO_RBRQ_H(group), 0); 1183116491Sharti WRITE4(sc, HE_REGO_RBRQ_Q(group), 1184116491Sharti (rq->thresh << HE_REGS_RBRQ_THRESH) | 1185116491Sharti ((rq->size - 1) << HE_REGS_RBRQ_SIZE)); 1186116491Sharti WRITE4(sc, HE_REGO_RBRQ_I(group), 1187116491Sharti (rq->tout << HE_REGS_RBRQ_TIME) | 1188116491Sharti (rq->pcnt << HE_REGS_RBRQ_COUNT)); 1189116491Sharti} 1190116491Sharti 1191116491Sharti/* 1192116491Sharti * Clear an unused transmit buffer return queue N 1193116491Sharti */ 1194116491Shartistatic void 1195116491Shartihatm_clear_tbrq(struct hatm_softc *sc, u_int group) 1196116491Sharti{ 1197116491Sharti WRITE4(sc, HE_REGO_TBRQ_B_T(group), 0); 1198116491Sharti WRITE4(sc, HE_REGO_TBRQ_H(group), 0); 1199116491Sharti WRITE4(sc, HE_REGO_TBRQ_S(group), 0); 1200116491Sharti WRITE4(sc, HE_REGO_TBRQ_THRESH(group), 1); 1201116491Sharti} 1202116491Sharti 1203116491Sharti/* 1204116491Sharti * Initialize transmit buffer return queue N 1205116491Sharti */ 1206116491Shartistatic void 1207116491Shartihatm_init_tbrq(struct hatm_softc *sc, struct hetbrq *tq, u_int group) 1208116491Sharti{ 1209116491Sharti if (tq->size == 0) { 1210116491Sharti hatm_clear_tbrq(sc, group); 1211116491Sharti return; 1212116491Sharti } 1213116491Sharti 1214116491Sharti tq->tbrq = tq->mem.base; 1215116491Sharti tq->head = 0; 1216116491Sharti 1217116491Sharti DBG(sc, ATTACH, ("TBRQ%u=0x%lx", group, (u_long)tq->mem.paddr)); 1218116491Sharti 1219116491Sharti WRITE4(sc, HE_REGO_TBRQ_B_T(group), tq->mem.paddr); 1220116491Sharti WRITE4(sc, HE_REGO_TBRQ_H(group), 0); 1221116491Sharti WRITE4(sc, HE_REGO_TBRQ_S(group), tq->size - 1); 1222116491Sharti WRITE4(sc, HE_REGO_TBRQ_THRESH(group), tq->thresh); 1223116491Sharti} 1224116491Sharti 1225116491Sharti/* 1226116491Sharti * Initialize TPDRQ 1227116491Sharti */ 1228116491Shartistatic void 1229116491Shartihatm_init_tpdrq(struct hatm_softc *sc) 1230116491Sharti{ 1231116491Sharti struct hetpdrq *tq; 1232116491Sharti 1233116491Sharti tq = &sc->tpdrq; 1234116491Sharti tq->tpdrq = tq->mem.base; 1235116491Sharti tq->tail = tq->head = 0; 1236116491Sharti 1237116491Sharti DBG(sc, ATTACH, ("TPDRQ=0x%lx", (u_long)tq->mem.paddr)); 1238116491Sharti 1239116491Sharti WRITE4(sc, HE_REGO_TPDRQ_H, tq->mem.paddr); 1240116491Sharti WRITE4(sc, HE_REGO_TPDRQ_T, 0); 1241116491Sharti WRITE4(sc, HE_REGO_TPDRQ_S, tq->size - 1); 1242116491Sharti} 1243116491Sharti 1244116491Sharti/* 1245116491Sharti * Function can be called by the infrastructure to start the card. 1246116491Sharti */ 1247116491Shartistatic void 1248116491Shartihatm_init(void *p) 1249116491Sharti{ 1250116491Sharti struct hatm_softc *sc = p; 1251116491Sharti 1252116491Sharti mtx_lock(&sc->mtx); 1253116491Sharti hatm_stop(sc); 1254116491Sharti hatm_initialize(sc); 1255116491Sharti mtx_unlock(&sc->mtx); 1256116491Sharti} 1257116491Sharti 1258116491Shartienum { 1259116491Sharti CTL_ISTATS, 1260116491Sharti}; 1261116491Sharti 1262116491Sharti/* 1263116491Sharti * Sysctl handler 1264116491Sharti */ 1265116491Shartistatic int 1266116491Shartihatm_sysctl(SYSCTL_HANDLER_ARGS) 1267116491Sharti{ 1268116491Sharti struct hatm_softc *sc = arg1; 1269116491Sharti uint32_t *ret; 1270116491Sharti int error; 1271116491Sharti size_t len; 1272116491Sharti 1273116491Sharti switch (arg2) { 1274116491Sharti 1275116491Sharti case CTL_ISTATS: 1276116491Sharti len = sizeof(sc->istats); 1277116491Sharti break; 1278116491Sharti 1279116491Sharti default: 1280116491Sharti panic("bad control code"); 1281116491Sharti } 1282116491Sharti 1283116491Sharti ret = malloc(len, M_TEMP, M_WAITOK); 1284116491Sharti mtx_lock(&sc->mtx); 1285116491Sharti 1286116491Sharti switch (arg2) { 1287116491Sharti 1288116491Sharti case CTL_ISTATS: 1289118169Sharti sc->istats.mcc += READ4(sc, HE_REGO_MCC); 1290118169Sharti sc->istats.oec += READ4(sc, HE_REGO_OEC); 1291118169Sharti sc->istats.dcc += READ4(sc, HE_REGO_DCC); 1292118169Sharti sc->istats.cec += READ4(sc, HE_REGO_CEC); 1293116491Sharti bcopy(&sc->istats, ret, sizeof(sc->istats)); 1294116491Sharti break; 1295116491Sharti } 1296116491Sharti mtx_unlock(&sc->mtx); 1297116491Sharti 1298116491Sharti error = SYSCTL_OUT(req, ret, len); 1299116491Sharti free(ret, M_TEMP); 1300116491Sharti 1301116491Sharti return (error); 1302116491Sharti} 1303116491Sharti 1304116491Shartistatic int 1305116491Shartikenv_getuint(struct hatm_softc *sc, const char *var, 1306116491Sharti u_int *ptr, u_int def, int rw) 1307116491Sharti{ 1308116491Sharti char full[IFNAMSIZ + 3 + 20]; 1309116491Sharti char *val, *end; 1310116491Sharti u_int u; 1311116491Sharti 1312116491Sharti *ptr = def; 1313116491Sharti 1314116491Sharti if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 1315116491Sharti OID_AUTO, var, rw ? CTLFLAG_RW : CTLFLAG_RD, ptr, 0, "") == NULL) 1316116491Sharti return (ENOMEM); 1317116491Sharti 1318116491Sharti snprintf(full, sizeof(full), "hw.%s.%s", 1319116491Sharti device_get_nameunit(sc->dev), var); 1320116491Sharti 1321116491Sharti if ((val = getenv(full)) == NULL) 1322116491Sharti return (0); 1323116491Sharti u = strtoul(val, &end, 0); 1324116491Sharti if (end == val || *end != '\0') { 1325116491Sharti freeenv(val); 1326116491Sharti return (EINVAL); 1327116491Sharti } 1328199970Semaste freeenv(val); 1329116491Sharti if (bootverbose) 1330147256Sbrooks if_printf(sc->ifp, "%s=%u\n", full, u); 1331116491Sharti *ptr = u; 1332116491Sharti return (0); 1333116491Sharti} 1334116491Sharti 1335116491Sharti/* 1336116491Sharti * Set configurable parameters. Many of these are configurable via 1337116491Sharti * kenv. 1338116491Sharti */ 1339116491Shartistatic int 1340116491Shartihatm_configure(struct hatm_softc *sc) 1341116491Sharti{ 1342116491Sharti /* Receive buffer pool 0 small */ 1343121469Sharti kenv_getuint(sc, "rbps0_size", &sc->rbp_s0.size, 1344116491Sharti HE_CONFIG_RBPS0_SIZE, 0); 1345121469Sharti kenv_getuint(sc, "rbps0_thresh", &sc->rbp_s0.thresh, 1346116491Sharti HE_CONFIG_RBPS0_THRESH, 0); 1347116491Sharti sc->rbp_s0.bsize = MBUF0_SIZE; 1348116491Sharti 1349116491Sharti /* Receive buffer pool 0 large */ 1350121469Sharti kenv_getuint(sc, "rbpl0_size", &sc->rbp_l0.size, 1351116491Sharti HE_CONFIG_RBPL0_SIZE, 0); 1352121469Sharti kenv_getuint(sc, "rbpl0_thresh", &sc->rbp_l0.thresh, 1353116491Sharti HE_CONFIG_RBPL0_THRESH, 0); 1354116491Sharti sc->rbp_l0.bsize = MCLBYTES - MBUFL_OFFSET; 1355116491Sharti 1356116491Sharti /* Receive buffer return queue 0 */ 1357121469Sharti kenv_getuint(sc, "rbrq0_size", &sc->rbrq_0.size, 1358116491Sharti HE_CONFIG_RBRQ0_SIZE, 0); 1359121469Sharti kenv_getuint(sc, "rbrq0_thresh", &sc->rbrq_0.thresh, 1360116491Sharti HE_CONFIG_RBRQ0_THRESH, 0); 1361121469Sharti kenv_getuint(sc, "rbrq0_tout", &sc->rbrq_0.tout, 1362116491Sharti HE_CONFIG_RBRQ0_TOUT, 0); 1363121469Sharti kenv_getuint(sc, "rbrq0_pcnt", &sc->rbrq_0.pcnt, 1364116491Sharti HE_CONFIG_RBRQ0_PCNT, 0); 1365116491Sharti 1366116491Sharti /* Receive buffer pool 1 small */ 1367121469Sharti kenv_getuint(sc, "rbps1_size", &sc->rbp_s1.size, 1368116491Sharti HE_CONFIG_RBPS1_SIZE, 0); 1369121469Sharti kenv_getuint(sc, "rbps1_thresh", &sc->rbp_s1.thresh, 1370116491Sharti HE_CONFIG_RBPS1_THRESH, 0); 1371116491Sharti sc->rbp_s1.bsize = MBUF1_SIZE; 1372116491Sharti 1373116491Sharti /* Receive buffer return queue 1 */ 1374121469Sharti kenv_getuint(sc, "rbrq1_size", &sc->rbrq_1.size, 1375116491Sharti HE_CONFIG_RBRQ1_SIZE, 0); 1376121469Sharti kenv_getuint(sc, "rbrq1_thresh", &sc->rbrq_1.thresh, 1377116491Sharti HE_CONFIG_RBRQ1_THRESH, 0); 1378121469Sharti kenv_getuint(sc, "rbrq1_tout", &sc->rbrq_1.tout, 1379116491Sharti HE_CONFIG_RBRQ1_TOUT, 0); 1380121469Sharti kenv_getuint(sc, "rbrq1_pcnt", &sc->rbrq_1.pcnt, 1381116491Sharti HE_CONFIG_RBRQ1_PCNT, 0); 1382116491Sharti 1383116491Sharti /* Interrupt queue 0 */ 1384121469Sharti kenv_getuint(sc, "irq0_size", &sc->irq_0.size, 1385116491Sharti HE_CONFIG_IRQ0_SIZE, 0); 1386121469Sharti kenv_getuint(sc, "irq0_thresh", &sc->irq_0.thresh, 1387116491Sharti HE_CONFIG_IRQ0_THRESH, 0); 1388116491Sharti sc->irq_0.line = HE_CONFIG_IRQ0_LINE; 1389116491Sharti 1390116491Sharti /* Transmit buffer return queue 0 */ 1391121469Sharti kenv_getuint(sc, "tbrq0_size", &sc->tbrq.size, 1392116491Sharti HE_CONFIG_TBRQ_SIZE, 0); 1393121469Sharti kenv_getuint(sc, "tbrq0_thresh", &sc->tbrq.thresh, 1394116491Sharti HE_CONFIG_TBRQ_THRESH, 0); 1395116491Sharti 1396116491Sharti /* Transmit buffer ready queue */ 1397121469Sharti kenv_getuint(sc, "tpdrq_size", &sc->tpdrq.size, 1398116491Sharti HE_CONFIG_TPDRQ_SIZE, 0); 1399116491Sharti /* Max TPDs per VCC */ 1400116491Sharti kenv_getuint(sc, "tpdmax", &sc->max_tpd, 1401116491Sharti HE_CONFIG_TPD_MAXCC, 0); 1402116491Sharti 1403121685Sharti /* external mbuf pages */ 1404121685Sharti kenv_getuint(sc, "max_mbuf_pages", &sc->mbuf_max_pages, 1405121685Sharti HE_CONFIG_MAX_MBUF_PAGES, 0); 1406121685Sharti 1407122113Sharti /* mpsafe */ 1408122113Sharti kenv_getuint(sc, "mpsafe", &sc->mpsafe, 0, 0); 1409122113Sharti if (sc->mpsafe != 0) 1410122113Sharti sc->mpsafe = INTR_MPSAFE; 1411122113Sharti 1412116491Sharti return (0); 1413116491Sharti} 1414116491Sharti 1415116491Sharti#ifdef HATM_DEBUG 1416116491Sharti 1417116491Sharti/* 1418116491Sharti * Get TSRs from connection memory 1419116491Sharti */ 1420116491Shartistatic int 1421116491Shartihatm_sysctl_tsr(SYSCTL_HANDLER_ARGS) 1422116491Sharti{ 1423116491Sharti struct hatm_softc *sc = arg1; 1424116491Sharti int error, i, j; 1425116491Sharti uint32_t *val; 1426116491Sharti 1427116491Sharti val = malloc(sizeof(uint32_t) * HE_MAX_VCCS * 15, M_TEMP, M_WAITOK); 1428116491Sharti 1429116491Sharti mtx_lock(&sc->mtx); 1430116491Sharti for (i = 0; i < HE_MAX_VCCS; i++) 1431116491Sharti for (j = 0; j <= 14; j++) 1432116491Sharti val[15 * i + j] = READ_TSR(sc, i, j); 1433116491Sharti mtx_unlock(&sc->mtx); 1434116491Sharti 1435116491Sharti error = SYSCTL_OUT(req, val, sizeof(uint32_t) * HE_MAX_VCCS * 15); 1436116491Sharti free(val, M_TEMP); 1437116491Sharti if (error != 0 || req->newptr == NULL) 1438116491Sharti return (error); 1439116491Sharti 1440116491Sharti return (EPERM); 1441116491Sharti} 1442116491Sharti 1443116491Sharti/* 1444116491Sharti * Get TPDs from connection memory 1445116491Sharti */ 1446116491Shartistatic int 1447116491Shartihatm_sysctl_tpd(SYSCTL_HANDLER_ARGS) 1448116491Sharti{ 1449116491Sharti struct hatm_softc *sc = arg1; 1450116491Sharti int error, i, j; 1451116491Sharti uint32_t *val; 1452116491Sharti 1453116491Sharti val = malloc(sizeof(uint32_t) * HE_MAX_VCCS * 16, M_TEMP, M_WAITOK); 1454116491Sharti 1455116491Sharti mtx_lock(&sc->mtx); 1456116491Sharti for (i = 0; i < HE_MAX_VCCS; i++) 1457116491Sharti for (j = 0; j < 16; j++) 1458116491Sharti val[16 * i + j] = READ_TCM4(sc, 16 * i + j); 1459116491Sharti mtx_unlock(&sc->mtx); 1460116491Sharti 1461116491Sharti error = SYSCTL_OUT(req, val, sizeof(uint32_t) * HE_MAX_VCCS * 16); 1462116491Sharti free(val, M_TEMP); 1463116491Sharti if (error != 0 || req->newptr == NULL) 1464116491Sharti return (error); 1465116491Sharti 1466116491Sharti return (EPERM); 1467116491Sharti} 1468116491Sharti 1469116491Sharti/* 1470116491Sharti * Get mbox registers 1471116491Sharti */ 1472116491Shartistatic int 1473116491Shartihatm_sysctl_mbox(SYSCTL_HANDLER_ARGS) 1474116491Sharti{ 1475116491Sharti struct hatm_softc *sc = arg1; 1476116491Sharti int error, i; 1477116491Sharti uint32_t *val; 1478116491Sharti 1479116491Sharti val = malloc(sizeof(uint32_t) * HE_REGO_CS_END, M_TEMP, M_WAITOK); 1480116491Sharti 1481116491Sharti mtx_lock(&sc->mtx); 1482116491Sharti for (i = 0; i < HE_REGO_CS_END; i++) 1483116491Sharti val[i] = READ_MBOX4(sc, i); 1484116491Sharti mtx_unlock(&sc->mtx); 1485116491Sharti 1486116491Sharti error = SYSCTL_OUT(req, val, sizeof(uint32_t) * HE_REGO_CS_END); 1487116491Sharti free(val, M_TEMP); 1488116491Sharti if (error != 0 || req->newptr == NULL) 1489116491Sharti return (error); 1490116491Sharti 1491116491Sharti return (EPERM); 1492116491Sharti} 1493116491Sharti 1494116491Sharti/* 1495116491Sharti * Get connection memory 1496116491Sharti */ 1497116491Shartistatic int 1498116491Shartihatm_sysctl_cm(SYSCTL_HANDLER_ARGS) 1499116491Sharti{ 1500116491Sharti struct hatm_softc *sc = arg1; 1501116491Sharti int error, i; 1502116491Sharti uint32_t *val; 1503116491Sharti 1504116491Sharti val = malloc(sizeof(uint32_t) * (HE_CONFIG_RXMEM + 1), M_TEMP, M_WAITOK); 1505116491Sharti 1506116491Sharti mtx_lock(&sc->mtx); 1507116491Sharti val[0] = READ4(sc, HE_REGO_RCMABR_BA); 1508116491Sharti for (i = 0; i < HE_CONFIG_RXMEM; i++) 1509116491Sharti val[i + 1] = READ_RCM4(sc, i); 1510116491Sharti mtx_unlock(&sc->mtx); 1511116491Sharti 1512116491Sharti error = SYSCTL_OUT(req, val, sizeof(uint32_t) * (HE_CONFIG_RXMEM + 1)); 1513116491Sharti free(val, M_TEMP); 1514116491Sharti if (error != 0 || req->newptr == NULL) 1515116491Sharti return (error); 1516116491Sharti 1517116491Sharti return (EPERM); 1518116491Sharti} 1519116491Sharti 1520116491Sharti/* 1521116491Sharti * Get local buffer memory 1522116491Sharti */ 1523116491Shartistatic int 1524116491Shartihatm_sysctl_lbmem(SYSCTL_HANDLER_ARGS) 1525116491Sharti{ 1526116491Sharti struct hatm_softc *sc = arg1; 1527116491Sharti int error, i; 1528116491Sharti uint32_t *val; 1529116491Sharti u_int bytes = (1 << 21); 1530116491Sharti 1531116491Sharti val = malloc(bytes, M_TEMP, M_WAITOK); 1532116491Sharti 1533116491Sharti mtx_lock(&sc->mtx); 1534116491Sharti for (i = 0; i < bytes / 4; i++) 1535116491Sharti val[i] = READ_LB4(sc, i); 1536116491Sharti mtx_unlock(&sc->mtx); 1537116491Sharti 1538116491Sharti error = SYSCTL_OUT(req, val, bytes); 1539116491Sharti free(val, M_TEMP); 1540116491Sharti if (error != 0 || req->newptr == NULL) 1541116491Sharti return (error); 1542116491Sharti 1543116491Sharti return (EPERM); 1544116491Sharti} 1545116491Sharti 1546116491Sharti/* 1547116491Sharti * Get all card registers 1548116491Sharti */ 1549116491Shartistatic int 1550116491Shartihatm_sysctl_heregs(SYSCTL_HANDLER_ARGS) 1551116491Sharti{ 1552116491Sharti struct hatm_softc *sc = arg1; 1553116491Sharti int error, i; 1554116491Sharti uint32_t *val; 1555116491Sharti 1556116491Sharti val = malloc(HE_REGO_END, M_TEMP, M_WAITOK); 1557116491Sharti 1558116491Sharti mtx_lock(&sc->mtx); 1559116491Sharti for (i = 0; i < HE_REGO_END; i += 4) 1560116491Sharti val[i / 4] = READ4(sc, i); 1561116491Sharti mtx_unlock(&sc->mtx); 1562116491Sharti 1563116491Sharti error = SYSCTL_OUT(req, val, HE_REGO_END); 1564116491Sharti free(val, M_TEMP); 1565116491Sharti if (error != 0 || req->newptr == NULL) 1566116491Sharti return (error); 1567116491Sharti 1568116491Sharti return (EPERM); 1569116491Sharti} 1570116491Sharti#endif 1571116491Sharti 1572116491Sharti/* 1573116491Sharti * Suni register access 1574116491Sharti */ 1575116491Sharti/* 1576116491Sharti * read at most n SUNI registers starting at reg into val 1577116491Sharti */ 1578116491Shartistatic int 1579116491Shartihatm_utopia_readregs(struct ifatm *ifatm, u_int reg, uint8_t *val, u_int *n) 1580116491Sharti{ 1581116491Sharti u_int i; 1582147721Sharti struct hatm_softc *sc = ifatm->ifp->if_softc; 1583116491Sharti 1584116491Sharti if (reg >= (HE_REGO_SUNI_END - HE_REGO_SUNI) / 4) 1585116491Sharti return (EINVAL); 1586116491Sharti if (reg + *n > (HE_REGO_SUNI_END - HE_REGO_SUNI) / 4) 1587116491Sharti *n = reg - (HE_REGO_SUNI_END - HE_REGO_SUNI) / 4; 1588116491Sharti 1589116491Sharti mtx_assert(&sc->mtx, MA_OWNED); 1590116491Sharti for (i = 0; i < *n; i++) 1591116491Sharti val[i] = READ4(sc, HE_REGO_SUNI + 4 * (reg + i)); 1592116491Sharti 1593116491Sharti return (0); 1594116491Sharti} 1595116491Sharti 1596116491Sharti/* 1597116491Sharti * change the bits given by mask to them in val in register reg 1598116491Sharti */ 1599116491Shartistatic int 1600116491Shartihatm_utopia_writereg(struct ifatm *ifatm, u_int reg, u_int mask, u_int val) 1601116491Sharti{ 1602116491Sharti uint32_t regval; 1603147721Sharti struct hatm_softc *sc = ifatm->ifp->if_softc; 1604116491Sharti 1605116491Sharti if (reg >= (HE_REGO_SUNI_END - HE_REGO_SUNI) / 4) 1606116491Sharti return (EINVAL); 1607116491Sharti 1608116491Sharti mtx_assert(&sc->mtx, MA_OWNED); 1609116491Sharti regval = READ4(sc, HE_REGO_SUNI + 4 * reg); 1610116491Sharti regval = (regval & ~mask) | (val & mask); 1611116491Sharti WRITE4(sc, HE_REGO_SUNI + 4 * reg, regval); 1612116491Sharti 1613116491Sharti return (0); 1614116491Sharti} 1615116491Sharti 1616116491Shartistatic struct utopia_methods hatm_utopia_methods = { 1617116491Sharti hatm_utopia_readregs, 1618116491Sharti hatm_utopia_writereg, 1619116491Sharti}; 1620116491Sharti 1621116491Sharti/* 1622116491Sharti * Detach - if it is running, stop. Destroy. 1623116491Sharti */ 1624116491Shartistatic int 1625116491Shartihatm_detach(device_t dev) 1626116491Sharti{ 1627147721Sharti struct hatm_softc *sc = device_get_softc(dev); 1628116491Sharti 1629116491Sharti mtx_lock(&sc->mtx); 1630116491Sharti hatm_stop(sc); 1631116491Sharti if (sc->utopia.state & UTP_ST_ATTACHED) { 1632116491Sharti utopia_stop(&sc->utopia); 1633116491Sharti utopia_detach(&sc->utopia); 1634116491Sharti } 1635116491Sharti mtx_unlock(&sc->mtx); 1636116491Sharti 1637147256Sbrooks atm_ifdetach(sc->ifp); 1638116491Sharti 1639116491Sharti hatm_destroy(sc); 1640116491Sharti 1641116491Sharti return (0); 1642116491Sharti} 1643116491Sharti 1644116491Sharti/* 1645116491Sharti * Attach to the device. Assume that no locking is needed here. 1646116491Sharti * All resource we allocate here are freed by calling hatm_destroy. 1647116491Sharti */ 1648116491Shartistatic int 1649116491Shartihatm_attach(device_t dev) 1650116491Sharti{ 1651116491Sharti struct hatm_softc *sc; 1652116491Sharti int error; 1653116491Sharti uint32_t v; 1654116491Sharti struct ifnet *ifp; 1655116491Sharti 1656116491Sharti sc = device_get_softc(dev); 1657116491Sharti 1658147256Sbrooks ifp = sc->ifp = if_alloc(IFT_ATM); 1659147256Sbrooks if (ifp == NULL) { 1660147256Sbrooks device_printf(dev, "could not if_alloc()\n"); 1661150215Sru return (ENOSPC); 1662147256Sbrooks } 1663147256Sbrooks 1664116491Sharti sc->dev = dev; 1665147256Sbrooks IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_HE155; 1666147256Sbrooks IFP2IFATM(sc->ifp)->mib.serial = 0; 1667147256Sbrooks IFP2IFATM(sc->ifp)->mib.hw_version = 0; 1668147256Sbrooks IFP2IFATM(sc->ifp)->mib.sw_version = 0; 1669147256Sbrooks IFP2IFATM(sc->ifp)->mib.vpi_bits = HE_CONFIG_VPI_BITS; 1670147256Sbrooks IFP2IFATM(sc->ifp)->mib.vci_bits = HE_CONFIG_VCI_BITS; 1671147256Sbrooks IFP2IFATM(sc->ifp)->mib.max_vpcs = 0; 1672147256Sbrooks IFP2IFATM(sc->ifp)->mib.max_vccs = HE_MAX_VCCS; 1673147256Sbrooks IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_UNKNOWN; 1674116491Sharti sc->he622 = 0; 1675147256Sbrooks IFP2IFATM(sc->ifp)->phy = &sc->utopia; 1676116491Sharti 1677116491Sharti SLIST_INIT(&sc->tpd_free); 1678116491Sharti 1679116491Sharti mtx_init(&sc->mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF); 1680116491Sharti cv_init(&sc->vcc_cv, "HEVCCcv"); 1681116491Sharti cv_init(&sc->cv_rcclose, "RCClose"); 1682116491Sharti 1683116491Sharti sysctl_ctx_init(&sc->sysctl_ctx); 1684116491Sharti 1685116491Sharti /* 1686116491Sharti * 4.2 BIOS Configuration 1687116491Sharti */ 1688116491Sharti v = pci_read_config(dev, PCIR_COMMAND, 2); 1689254263Sscottl v |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN; 1690116491Sharti pci_write_config(dev, PCIR_COMMAND, v, 2); 1691116491Sharti 1692116491Sharti /* 1693116491Sharti * 4.3 PCI Bus Controller-Specific Initialisation 1694116491Sharti */ 1695116491Sharti v = pci_read_config(dev, HE_PCIR_GEN_CNTL_0, 4); 1696116491Sharti v |= HE_PCIM_CTL0_MRL | HE_PCIM_CTL0_MRM | HE_PCIM_CTL0_IGNORE_TIMEOUT; 1697116491Sharti#if BYTE_ORDER == BIG_ENDIAN && 0 1698116491Sharti v |= HE_PCIM_CTL0_BIGENDIAN; 1699116491Sharti#endif 1700116491Sharti pci_write_config(dev, HE_PCIR_GEN_CNTL_0, v, 4); 1701116491Sharti 1702116491Sharti /* 1703116491Sharti * Map memory 1704116491Sharti */ 1705119690Sjhb sc->memid = PCIR_BAR(0); 1706127135Snjl sc->memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->memid, 1707127135Snjl RF_ACTIVE); 1708116491Sharti if (sc->memres == NULL) { 1709116491Sharti device_printf(dev, "could not map memory\n"); 1710116491Sharti error = ENXIO; 1711116491Sharti goto failed; 1712116491Sharti } 1713116491Sharti sc->memh = rman_get_bushandle(sc->memres); 1714116491Sharti sc->memt = rman_get_bustag(sc->memres); 1715116491Sharti 1716116491Sharti /* 1717116491Sharti * ALlocate a DMA tag for subsequent allocations 1718116491Sharti */ 1719232874Sscottl if (bus_dma_tag_create(bus_get_dma_tag(sc->dev), 1, 0, 1720116491Sharti BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 1721116491Sharti NULL, NULL, 1722116491Sharti BUS_SPACE_MAXSIZE_32BIT, 1, 1723117126Sscottl BUS_SPACE_MAXSIZE_32BIT, 0, 1724117382Sharti NULL, NULL, &sc->parent_tag)) { 1725116491Sharti device_printf(dev, "could not allocate DMA tag\n"); 1726116491Sharti error = ENOMEM; 1727116491Sharti goto failed; 1728116491Sharti } 1729116491Sharti 1730116491Sharti if (bus_dma_tag_create(sc->parent_tag, 1, 0, 1731116491Sharti BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 1732116491Sharti NULL, NULL, 1733116491Sharti MBUF_ALLOC_SIZE, 1, 1734117126Sscottl MBUF_ALLOC_SIZE, 0, 1735117382Sharti NULL, NULL, &sc->mbuf_tag)) { 1736116491Sharti device_printf(dev, "could not allocate mbuf DMA tag\n"); 1737116491Sharti error = ENOMEM; 1738116491Sharti goto failed; 1739116491Sharti } 1740116491Sharti 1741116491Sharti /* 1742116491Sharti * Allocate a DMA tag for packets to send. Here we have a problem with 1743116491Sharti * the specification of the maximum number of segments. Theoretically 1744116491Sharti * this would be the size of the transmit ring - 1 multiplied by 3, 1745116491Sharti * but this would not work. So make the maximum number of TPDs 1746116491Sharti * occupied by one packet a configuration parameter. 1747116491Sharti */ 1748232874Sscottl if (bus_dma_tag_create(bus_get_dma_tag(sc->dev), 1, 0, 1749116491Sharti BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 1750116491Sharti HE_MAX_PDU, 3 * HE_CONFIG_MAX_TPD_PER_PACKET, HE_MAX_PDU, 0, 1751117382Sharti NULL, NULL, &sc->tx_tag)) { 1752116491Sharti device_printf(dev, "could not allocate TX tag\n"); 1753116491Sharti error = ENOMEM; 1754116491Sharti goto failed; 1755116491Sharti } 1756116491Sharti 1757116491Sharti /* 1758116491Sharti * Setup the interrupt 1759116491Sharti */ 1760116491Sharti sc->irqid = 0; 1761127135Snjl sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid, 1762127135Snjl RF_SHAREABLE | RF_ACTIVE); 1763116491Sharti if (sc->irqres == 0) { 1764116491Sharti device_printf(dev, "could not allocate irq\n"); 1765116491Sharti error = ENXIO; 1766116491Sharti goto failed; 1767116491Sharti } 1768116491Sharti 1769116491Sharti ifp->if_softc = sc; 1770121816Sbrooks if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 1771116491Sharti 1772116491Sharti /* 1773116491Sharti * Make the sysctl tree 1774116491Sharti */ 1775116491Sharti error = ENOMEM; 1776116491Sharti if ((sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, 1777116491Sharti SYSCTL_STATIC_CHILDREN(_hw_atm), OID_AUTO, 1778116491Sharti device_get_nameunit(dev), CTLFLAG_RD, 0, "")) == NULL) 1779116491Sharti goto failed; 1780116491Sharti 1781116491Sharti if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 1782116491Sharti OID_AUTO, "istats", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, CTL_ISTATS, 1783116491Sharti hatm_sysctl, "LU", "internal statistics") == NULL) 1784116491Sharti goto failed; 1785116491Sharti 1786116491Sharti#ifdef HATM_DEBUG 1787116491Sharti if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 1788116491Sharti OID_AUTO, "tsr", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0, 1789116491Sharti hatm_sysctl_tsr, "S", "transmission status registers") == NULL) 1790116491Sharti goto failed; 1791116491Sharti 1792116491Sharti if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 1793116491Sharti OID_AUTO, "tpd", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0, 1794116491Sharti hatm_sysctl_tpd, "S", "transmission packet descriptors") == NULL) 1795116491Sharti goto failed; 1796116491Sharti 1797116491Sharti if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 1798116491Sharti OID_AUTO, "mbox", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0, 1799116491Sharti hatm_sysctl_mbox, "S", "mbox registers") == NULL) 1800116491Sharti goto failed; 1801116491Sharti 1802116491Sharti if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 1803116491Sharti OID_AUTO, "cm", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0, 1804116491Sharti hatm_sysctl_cm, "S", "connection memory") == NULL) 1805116491Sharti goto failed; 1806116491Sharti 1807116491Sharti if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 1808116491Sharti OID_AUTO, "heregs", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0, 1809116491Sharti hatm_sysctl_heregs, "S", "card registers") == NULL) 1810116491Sharti goto failed; 1811116491Sharti 1812116491Sharti if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 1813116491Sharti OID_AUTO, "lbmem", CTLFLAG_RD | CTLTYPE_OPAQUE, sc, 0, 1814116491Sharti hatm_sysctl_lbmem, "S", "local memory") == NULL) 1815116491Sharti goto failed; 1816116491Sharti 1817121681Sharti kenv_getuint(sc, "debug", &sc->debug, HATM_DEBUG, 1); 1818116491Sharti#endif 1819116491Sharti 1820116491Sharti /* 1821116491Sharti * Configure 1822116491Sharti */ 1823116491Sharti if ((error = hatm_configure(sc)) != 0) 1824116491Sharti goto failed; 1825116491Sharti 1826116491Sharti /* 1827116491Sharti * Compute memory parameters 1828116491Sharti */ 1829116491Sharti if (sc->rbp_s0.size != 0) { 1830116491Sharti sc->rbp_s0.mask = (sc->rbp_s0.size - 1) << 3; 1831116491Sharti sc->rbp_s0.mem.size = sc->rbp_s0.size * 8; 1832116491Sharti sc->rbp_s0.mem.align = sc->rbp_s0.mem.size; 1833116491Sharti } 1834116491Sharti if (sc->rbp_l0.size != 0) { 1835116491Sharti sc->rbp_l0.mask = (sc->rbp_l0.size - 1) << 3; 1836116491Sharti sc->rbp_l0.mem.size = sc->rbp_l0.size * 8; 1837116491Sharti sc->rbp_l0.mem.align = sc->rbp_l0.mem.size; 1838116491Sharti } 1839116491Sharti if (sc->rbp_s1.size != 0) { 1840116491Sharti sc->rbp_s1.mask = (sc->rbp_s1.size - 1) << 3; 1841116491Sharti sc->rbp_s1.mem.size = sc->rbp_s1.size * 8; 1842116491Sharti sc->rbp_s1.mem.align = sc->rbp_s1.mem.size; 1843116491Sharti } 1844116491Sharti if (sc->rbrq_0.size != 0) { 1845116491Sharti sc->rbrq_0.mem.size = sc->rbrq_0.size * 8; 1846116491Sharti sc->rbrq_0.mem.align = sc->rbrq_0.mem.size; 1847116491Sharti } 1848116491Sharti if (sc->rbrq_1.size != 0) { 1849116491Sharti sc->rbrq_1.mem.size = sc->rbrq_1.size * 8; 1850116491Sharti sc->rbrq_1.mem.align = sc->rbrq_1.mem.size; 1851116491Sharti } 1852116491Sharti 1853116491Sharti sc->irq_0.mem.size = sc->irq_0.size * sizeof(uint32_t); 1854116491Sharti sc->irq_0.mem.align = 4 * 1024; 1855116491Sharti 1856116491Sharti sc->tbrq.mem.size = sc->tbrq.size * 4; 1857116491Sharti sc->tbrq.mem.align = 2 * sc->tbrq.mem.size; /* ZZZ */ 1858116491Sharti 1859116491Sharti sc->tpdrq.mem.size = sc->tpdrq.size * 8; 1860116491Sharti sc->tpdrq.mem.align = sc->tpdrq.mem.size; 1861116491Sharti 1862116491Sharti sc->hsp_mem.size = sizeof(struct he_hsp); 1863116491Sharti sc->hsp_mem.align = 1024; 1864116491Sharti 1865116491Sharti sc->lbufs_size = sc->rbp_l0.size + sc->rbrq_0.size; 1866116491Sharti sc->tpd_total = sc->tbrq.size + sc->tpdrq.size; 1867116491Sharti sc->tpds.align = 64; 1868116491Sharti sc->tpds.size = sc->tpd_total * HE_TPD_SIZE; 1869116491Sharti 1870116491Sharti hatm_init_rmaps(sc); 1871116491Sharti hatm_init_smbufs(sc); 1872116491Sharti if ((error = hatm_init_tpds(sc)) != 0) 1873116491Sharti goto failed; 1874116491Sharti 1875116491Sharti /* 1876116491Sharti * Allocate memory 1877116491Sharti */ 1878116491Sharti if ((error = hatm_alloc_dmamem(sc, "IRQ", &sc->irq_0.mem)) != 0 || 1879116491Sharti (error = hatm_alloc_dmamem(sc, "TBRQ0", &sc->tbrq.mem)) != 0 || 1880116491Sharti (error = hatm_alloc_dmamem(sc, "TPDRQ", &sc->tpdrq.mem)) != 0 || 1881116491Sharti (error = hatm_alloc_dmamem(sc, "HSP", &sc->hsp_mem)) != 0) 1882116491Sharti goto failed; 1883116491Sharti 1884116491Sharti if (sc->rbp_s0.mem.size != 0 && 1885116491Sharti (error = hatm_alloc_dmamem(sc, "RBPS0", &sc->rbp_s0.mem))) 1886116491Sharti goto failed; 1887116491Sharti if (sc->rbp_l0.mem.size != 0 && 1888116491Sharti (error = hatm_alloc_dmamem(sc, "RBPL0", &sc->rbp_l0.mem))) 1889116491Sharti goto failed; 1890116491Sharti if (sc->rbp_s1.mem.size != 0 && 1891116491Sharti (error = hatm_alloc_dmamem(sc, "RBPS1", &sc->rbp_s1.mem))) 1892116491Sharti goto failed; 1893116491Sharti 1894116491Sharti if (sc->rbrq_0.mem.size != 0 && 1895116491Sharti (error = hatm_alloc_dmamem(sc, "RBRQ0", &sc->rbrq_0.mem))) 1896116491Sharti goto failed; 1897116491Sharti if (sc->rbrq_1.mem.size != 0 && 1898116491Sharti (error = hatm_alloc_dmamem(sc, "RBRQ1", &sc->rbrq_1.mem))) 1899116491Sharti goto failed; 1900116491Sharti 1901116491Sharti if ((sc->vcc_zone = uma_zcreate("HE vccs", sizeof(struct hevcc), 1902116491Sharti NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0)) == NULL) { 1903116491Sharti device_printf(dev, "cannot allocate zone for vccs\n"); 1904116491Sharti goto failed; 1905116491Sharti } 1906116491Sharti 1907116491Sharti /* 1908116491Sharti * 4.4 Reset the card. 1909116491Sharti */ 1910116491Sharti if ((error = hatm_reset(sc)) != 0) 1911116491Sharti goto failed; 1912116491Sharti 1913116491Sharti /* 1914116491Sharti * Read the prom. 1915116491Sharti */ 1916116491Sharti hatm_init_bus_width(sc); 1917116491Sharti hatm_init_read_eeprom(sc); 1918116491Sharti hatm_init_endianess(sc); 1919116491Sharti 1920116491Sharti /* 1921116491Sharti * Initialize interface 1922116491Sharti */ 1923116491Sharti ifp->if_flags = IFF_SIMPLEX; 1924116491Sharti ifp->if_ioctl = hatm_ioctl; 1925116491Sharti ifp->if_start = hatm_start; 1926116491Sharti ifp->if_init = hatm_init; 1927116491Sharti 1928147256Sbrooks utopia_attach(&sc->utopia, IFP2IFATM(sc->ifp), &sc->media, &sc->mtx, 1929116491Sharti &sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 1930116491Sharti &hatm_utopia_methods); 1931116491Sharti utopia_init_media(&sc->utopia); 1932116491Sharti 1933116491Sharti /* these two SUNI routines need the lock */ 1934116491Sharti mtx_lock(&sc->mtx); 1935116491Sharti /* poll while we are not running */ 1936116491Sharti sc->utopia.flags |= UTP_FL_POLL_CARRIER; 1937116491Sharti utopia_start(&sc->utopia); 1938116491Sharti utopia_reset(&sc->utopia); 1939116491Sharti mtx_unlock(&sc->mtx); 1940116491Sharti 1941116491Sharti atm_ifattach(ifp); 1942116491Sharti 1943116491Sharti#ifdef ENABLE_BPF 1944116491Sharti bpfattach(ifp, DLT_ATM_RFC1483, sizeof(struct atmllc)); 1945116491Sharti#endif 1946116491Sharti 1947122113Sharti error = bus_setup_intr(dev, sc->irqres, sc->mpsafe | INTR_TYPE_NET, 1948166901Spiso NULL, hatm_intr, &sc->irq_0, &sc->ih); 1949116491Sharti if (error != 0) { 1950116491Sharti device_printf(dev, "could not setup interrupt\n"); 1951116491Sharti hatm_detach(dev); 1952116491Sharti return (error); 1953116491Sharti } 1954116491Sharti 1955116491Sharti return (0); 1956116491Sharti 1957116491Sharti failed: 1958116491Sharti hatm_destroy(sc); 1959116491Sharti return (error); 1960116491Sharti} 1961116491Sharti 1962116491Sharti/* 1963116491Sharti * Start the interface. Assume a state as from attach(). 1964116491Sharti */ 1965116491Shartivoid 1966116491Shartihatm_initialize(struct hatm_softc *sc) 1967116491Sharti{ 1968116491Sharti uint32_t v; 1969118598Sharti u_int cid; 1970116491Sharti static const u_int layout[2][7] = HE_CONFIG_MEM_LAYOUT; 1971116491Sharti 1972148887Srwatson if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING) 1973116491Sharti return; 1974116491Sharti 1975116491Sharti hatm_init_bus_width(sc); 1976116491Sharti hatm_init_endianess(sc); 1977116491Sharti 1978147256Sbrooks if_printf(sc->ifp, "%s, Rev. %s, S/N %u, " 1979116491Sharti "MAC=%02x:%02x:%02x:%02x:%02x:%02x (%ubit PCI)\n", 1980147256Sbrooks sc->prod_id, sc->rev, IFP2IFATM(sc->ifp)->mib.serial, 1981147256Sbrooks IFP2IFATM(sc->ifp)->mib.esi[0], IFP2IFATM(sc->ifp)->mib.esi[1], IFP2IFATM(sc->ifp)->mib.esi[2], 1982147256Sbrooks IFP2IFATM(sc->ifp)->mib.esi[3], IFP2IFATM(sc->ifp)->mib.esi[4], IFP2IFATM(sc->ifp)->mib.esi[5], 1983116491Sharti sc->pci64 ? 64 : 32); 1984116491Sharti 1985116491Sharti /* 1986116491Sharti * 4.8 SDRAM Controller Initialisation 1987116491Sharti * 4.9 Initialize RNUM value 1988116491Sharti */ 1989116491Sharti if (sc->he622) 1990116491Sharti WRITE4(sc, HE_REGO_SDRAM_CNTL, HE_REGM_SDRAM_64BIT); 1991116491Sharti else 1992116491Sharti WRITE4(sc, HE_REGO_SDRAM_CNTL, 0); 1993116491Sharti BARRIER_W(sc); 1994116491Sharti 1995116491Sharti v = READ4(sc, HE_REGO_LB_SWAP); 1996116491Sharti BARRIER_R(sc); 1997116491Sharti v |= 0xf << HE_REGS_LBSWAP_RNUM; 1998116491Sharti WRITE4(sc, HE_REGO_LB_SWAP, v); 1999116491Sharti BARRIER_W(sc); 2000116491Sharti 2001116491Sharti hatm_init_irq(sc, &sc->irq_0, 0); 2002116491Sharti hatm_clear_irq(sc, 1); 2003116491Sharti hatm_clear_irq(sc, 2); 2004116491Sharti hatm_clear_irq(sc, 3); 2005116491Sharti 2006116491Sharti WRITE4(sc, HE_REGO_GRP_1_0_MAP, 0); 2007116491Sharti WRITE4(sc, HE_REGO_GRP_3_2_MAP, 0); 2008116491Sharti WRITE4(sc, HE_REGO_GRP_5_4_MAP, 0); 2009116491Sharti WRITE4(sc, HE_REGO_GRP_7_6_MAP, 0); 2010116491Sharti BARRIER_W(sc); 2011116491Sharti 2012116491Sharti /* 2013116491Sharti * 4.11 Enable PCI Bus Controller State Machine 2014116491Sharti */ 2015116491Sharti v = READ4(sc, HE_REGO_HOST_CNTL); 2016116491Sharti BARRIER_R(sc); 2017116491Sharti v |= HE_REGM_HOST_OUTFF_ENB | HE_REGM_HOST_CMDFF_ENB | 2018116491Sharti HE_REGM_HOST_QUICK_RD | HE_REGM_HOST_QUICK_WR; 2019116491Sharti WRITE4(sc, HE_REGO_HOST_CNTL, v); 2020116491Sharti BARRIER_W(sc); 2021116491Sharti 2022116491Sharti /* 2023116491Sharti * 5.1.1 Generic configuration state 2024116491Sharti */ 2025116491Sharti sc->cells_per_row = layout[sc->he622][0]; 2026116491Sharti sc->bytes_per_row = layout[sc->he622][1]; 2027116491Sharti sc->r0_numrows = layout[sc->he622][2]; 2028116491Sharti sc->tx_numrows = layout[sc->he622][3]; 2029116491Sharti sc->r1_numrows = layout[sc->he622][4]; 2030116491Sharti sc->r0_startrow = layout[sc->he622][5]; 2031116491Sharti sc->tx_startrow = sc->r0_startrow + sc->r0_numrows; 2032116491Sharti sc->r1_startrow = sc->tx_startrow + sc->tx_numrows; 2033116491Sharti sc->cells_per_lbuf = layout[sc->he622][6]; 2034116491Sharti 2035116491Sharti sc->r0_numbuffs = sc->r0_numrows * (sc->cells_per_row / 2036116491Sharti sc->cells_per_lbuf); 2037116491Sharti sc->r1_numbuffs = sc->r1_numrows * (sc->cells_per_row / 2038116491Sharti sc->cells_per_lbuf); 2039116491Sharti sc->tx_numbuffs = sc->tx_numrows * (sc->cells_per_row / 2040116491Sharti sc->cells_per_lbuf); 2041116491Sharti 2042116491Sharti if (sc->r0_numbuffs > 2560) 2043116491Sharti sc->r0_numbuffs = 2560; 2044116491Sharti if (sc->r1_numbuffs > 2560) 2045116491Sharti sc->r1_numbuffs = 2560; 2046116491Sharti if (sc->tx_numbuffs > 5120) 2047116491Sharti sc->tx_numbuffs = 5120; 2048116491Sharti 2049116491Sharti DBG(sc, ATTACH, ("cells_per_row=%u bytes_per_row=%u r0_numrows=%u " 2050116491Sharti "tx_numrows=%u r1_numrows=%u r0_startrow=%u tx_startrow=%u " 2051116491Sharti "r1_startrow=%u cells_per_lbuf=%u\nr0_numbuffs=%u r1_numbuffs=%u " 2052116491Sharti "tx_numbuffs=%u\n", sc->cells_per_row, sc->bytes_per_row, 2053116491Sharti sc->r0_numrows, sc->tx_numrows, sc->r1_numrows, sc->r0_startrow, 2054116491Sharti sc->tx_startrow, sc->r1_startrow, sc->cells_per_lbuf, 2055116491Sharti sc->r0_numbuffs, sc->r1_numbuffs, sc->tx_numbuffs)); 2056116491Sharti 2057116491Sharti /* 2058116491Sharti * 5.1.2 Configure Hardware dependend registers 2059116491Sharti */ 2060116491Sharti if (sc->he622) { 2061116491Sharti WRITE4(sc, HE_REGO_LBARB, 2062116491Sharti (0x2 << HE_REGS_LBARB_SLICE) | 2063116491Sharti (0xf << HE_REGS_LBARB_RNUM) | 2064116491Sharti (0x3 << HE_REGS_LBARB_THPRI) | 2065116491Sharti (0x3 << HE_REGS_LBARB_RHPRI) | 2066116491Sharti (0x2 << HE_REGS_LBARB_TLPRI) | 2067116491Sharti (0x1 << HE_REGS_LBARB_RLPRI) | 2068116491Sharti (0x28 << HE_REGS_LBARB_BUS_MULT) | 2069116491Sharti (0x50 << HE_REGS_LBARB_NET_PREF)); 2070116491Sharti BARRIER_W(sc); 2071116491Sharti WRITE4(sc, HE_REGO_SDRAMCON, 2072116491Sharti /* HW bug: don't use banking */ 2073116491Sharti /* HE_REGM_SDRAMCON_BANK | */ 2074116491Sharti HE_REGM_SDRAMCON_WIDE | 2075116491Sharti (0x384 << HE_REGS_SDRAMCON_REF)); 2076116491Sharti BARRIER_W(sc); 2077116491Sharti WRITE4(sc, HE_REGO_RCMCONFIG, 2078116491Sharti (0x1 << HE_REGS_RCMCONFIG_BANK_WAIT) | 2079116491Sharti (0x1 << HE_REGS_RCMCONFIG_RW_WAIT) | 2080116491Sharti (0x0 << HE_REGS_RCMCONFIG_TYPE)); 2081116491Sharti WRITE4(sc, HE_REGO_TCMCONFIG, 2082116491Sharti (0x2 << HE_REGS_TCMCONFIG_BANK_WAIT) | 2083116491Sharti (0x1 << HE_REGS_TCMCONFIG_RW_WAIT) | 2084116491Sharti (0x0 << HE_REGS_TCMCONFIG_TYPE)); 2085116491Sharti } else { 2086116491Sharti WRITE4(sc, HE_REGO_LBARB, 2087116491Sharti (0x2 << HE_REGS_LBARB_SLICE) | 2088116491Sharti (0xf << HE_REGS_LBARB_RNUM) | 2089116491Sharti (0x3 << HE_REGS_LBARB_THPRI) | 2090116491Sharti (0x3 << HE_REGS_LBARB_RHPRI) | 2091116491Sharti (0x2 << HE_REGS_LBARB_TLPRI) | 2092116491Sharti (0x1 << HE_REGS_LBARB_RLPRI) | 2093116491Sharti (0x46 << HE_REGS_LBARB_BUS_MULT) | 2094116491Sharti (0x8C << HE_REGS_LBARB_NET_PREF)); 2095116491Sharti BARRIER_W(sc); 2096116491Sharti WRITE4(sc, HE_REGO_SDRAMCON, 2097116491Sharti /* HW bug: don't use banking */ 2098116491Sharti /* HE_REGM_SDRAMCON_BANK | */ 2099116491Sharti (0x150 << HE_REGS_SDRAMCON_REF)); 2100116491Sharti BARRIER_W(sc); 2101116491Sharti WRITE4(sc, HE_REGO_RCMCONFIG, 2102116491Sharti (0x0 << HE_REGS_RCMCONFIG_BANK_WAIT) | 2103116491Sharti (0x1 << HE_REGS_RCMCONFIG_RW_WAIT) | 2104116491Sharti (0x0 << HE_REGS_RCMCONFIG_TYPE)); 2105116491Sharti WRITE4(sc, HE_REGO_TCMCONFIG, 2106116491Sharti (0x1 << HE_REGS_TCMCONFIG_BANK_WAIT) | 2107116491Sharti (0x1 << HE_REGS_TCMCONFIG_RW_WAIT) | 2108116491Sharti (0x0 << HE_REGS_TCMCONFIG_TYPE)); 2109116491Sharti } 2110116491Sharti WRITE4(sc, HE_REGO_LBCONFIG, (sc->cells_per_lbuf * 48)); 2111116491Sharti 2112116491Sharti WRITE4(sc, HE_REGO_RLBC_H, 0); 2113116491Sharti WRITE4(sc, HE_REGO_RLBC_T, 0); 2114116491Sharti WRITE4(sc, HE_REGO_RLBC_H2, 0); 2115116491Sharti 2116116491Sharti WRITE4(sc, HE_REGO_RXTHRSH, 512); 2117116491Sharti WRITE4(sc, HE_REGO_LITHRSH, 256); 2118116491Sharti 2119116491Sharti WRITE4(sc, HE_REGO_RLBF0_C, sc->r0_numbuffs); 2120116491Sharti WRITE4(sc, HE_REGO_RLBF1_C, sc->r1_numbuffs); 2121116491Sharti 2122116491Sharti if (sc->he622) { 2123116491Sharti WRITE4(sc, HE_REGO_RCCONFIG, 2124116491Sharti (8 << HE_REGS_RCCONFIG_UTDELAY) | 2125147256Sbrooks (IFP2IFATM(sc->ifp)->mib.vpi_bits << HE_REGS_RCCONFIG_VP) | 2126147256Sbrooks (IFP2IFATM(sc->ifp)->mib.vci_bits << HE_REGS_RCCONFIG_VC)); 2127116491Sharti WRITE4(sc, HE_REGO_TXCONFIG, 2128116491Sharti (32 << HE_REGS_TXCONFIG_THRESH) | 2129147256Sbrooks (IFP2IFATM(sc->ifp)->mib.vci_bits << HE_REGS_TXCONFIG_VCI_MASK) | 2130116491Sharti (sc->tx_numbuffs << HE_REGS_TXCONFIG_LBFREE)); 2131116491Sharti } else { 2132116491Sharti WRITE4(sc, HE_REGO_RCCONFIG, 2133116491Sharti (0 << HE_REGS_RCCONFIG_UTDELAY) | 2134116491Sharti HE_REGM_RCCONFIG_UT_MODE | 2135147256Sbrooks (IFP2IFATM(sc->ifp)->mib.vpi_bits << HE_REGS_RCCONFIG_VP) | 2136147256Sbrooks (IFP2IFATM(sc->ifp)->mib.vci_bits << HE_REGS_RCCONFIG_VC)); 2137116491Sharti WRITE4(sc, HE_REGO_TXCONFIG, 2138116491Sharti (32 << HE_REGS_TXCONFIG_THRESH) | 2139116491Sharti HE_REGM_TXCONFIG_UTMODE | 2140147256Sbrooks (IFP2IFATM(sc->ifp)->mib.vci_bits << HE_REGS_TXCONFIG_VCI_MASK) | 2141116491Sharti (sc->tx_numbuffs << HE_REGS_TXCONFIG_LBFREE)); 2142116491Sharti } 2143116491Sharti 2144116491Sharti WRITE4(sc, HE_REGO_TXAAL5_PROTO, 0); 2145116491Sharti 2146117382Sharti if (sc->rbp_s1.size != 0) { 2147117382Sharti WRITE4(sc, HE_REGO_RHCONFIG, 2148117382Sharti HE_REGM_RHCONFIG_PHYENB | 2149117382Sharti ((sc->he622 ? 0x41 : 0x31) << HE_REGS_RHCONFIG_PTMR_PRE) | 2150117382Sharti (1 << HE_REGS_RHCONFIG_OAM_GID)); 2151117382Sharti } else { 2152117382Sharti WRITE4(sc, HE_REGO_RHCONFIG, 2153117382Sharti HE_REGM_RHCONFIG_PHYENB | 2154117382Sharti ((sc->he622 ? 0x41 : 0x31) << HE_REGS_RHCONFIG_PTMR_PRE) | 2155117382Sharti (0 << HE_REGS_RHCONFIG_OAM_GID)); 2156117382Sharti } 2157116491Sharti BARRIER_W(sc); 2158116491Sharti 2159116491Sharti hatm_init_cm(sc); 2160116491Sharti 2161116491Sharti hatm_init_rx_buffer_pool(sc, 0, sc->r0_startrow, sc->r0_numbuffs); 2162116491Sharti hatm_init_rx_buffer_pool(sc, 1, sc->r1_startrow, sc->r1_numbuffs); 2163116491Sharti hatm_init_tx_buffer_pool(sc, sc->tx_startrow, sc->tx_numbuffs); 2164116491Sharti 2165116491Sharti hatm_init_imed_queues(sc); 2166116491Sharti 2167116491Sharti /* 2168116491Sharti * 5.1.6 Application tunable Parameters 2169116491Sharti */ 2170116491Sharti WRITE4(sc, HE_REGO_MCC, 0); 2171116491Sharti WRITE4(sc, HE_REGO_OEC, 0); 2172116491Sharti WRITE4(sc, HE_REGO_DCC, 0); 2173116491Sharti WRITE4(sc, HE_REGO_CEC, 0); 2174116491Sharti 2175116491Sharti hatm_init_cs_block(sc); 2176116491Sharti hatm_init_cs_block_cm(sc); 2177116491Sharti 2178116491Sharti hatm_init_rpool(sc, &sc->rbp_s0, 0, 0); 2179116491Sharti hatm_init_rpool(sc, &sc->rbp_l0, 0, 1); 2180116491Sharti hatm_init_rpool(sc, &sc->rbp_s1, 1, 0); 2181116491Sharti hatm_clear_rpool(sc, 1, 1); 2182116491Sharti hatm_clear_rpool(sc, 2, 0); 2183116491Sharti hatm_clear_rpool(sc, 2, 1); 2184116491Sharti hatm_clear_rpool(sc, 3, 0); 2185116491Sharti hatm_clear_rpool(sc, 3, 1); 2186116491Sharti hatm_clear_rpool(sc, 4, 0); 2187116491Sharti hatm_clear_rpool(sc, 4, 1); 2188116491Sharti hatm_clear_rpool(sc, 5, 0); 2189116491Sharti hatm_clear_rpool(sc, 5, 1); 2190116491Sharti hatm_clear_rpool(sc, 6, 0); 2191116491Sharti hatm_clear_rpool(sc, 6, 1); 2192116491Sharti hatm_clear_rpool(sc, 7, 0); 2193116491Sharti hatm_clear_rpool(sc, 7, 1); 2194116491Sharti hatm_init_rbrq(sc, &sc->rbrq_0, 0); 2195116491Sharti hatm_init_rbrq(sc, &sc->rbrq_1, 1); 2196116491Sharti hatm_clear_rbrq(sc, 2); 2197116491Sharti hatm_clear_rbrq(sc, 3); 2198116491Sharti hatm_clear_rbrq(sc, 4); 2199116491Sharti hatm_clear_rbrq(sc, 5); 2200116491Sharti hatm_clear_rbrq(sc, 6); 2201116491Sharti hatm_clear_rbrq(sc, 7); 2202116491Sharti 2203116491Sharti sc->lbufs_next = 0; 2204116491Sharti bzero(sc->lbufs, sizeof(sc->lbufs[0]) * sc->lbufs_size); 2205116491Sharti 2206116491Sharti hatm_init_tbrq(sc, &sc->tbrq, 0); 2207116491Sharti hatm_clear_tbrq(sc, 1); 2208116491Sharti hatm_clear_tbrq(sc, 2); 2209116491Sharti hatm_clear_tbrq(sc, 3); 2210116491Sharti hatm_clear_tbrq(sc, 4); 2211116491Sharti hatm_clear_tbrq(sc, 5); 2212116491Sharti hatm_clear_tbrq(sc, 6); 2213116491Sharti hatm_clear_tbrq(sc, 7); 2214116491Sharti 2215116491Sharti hatm_init_tpdrq(sc); 2216116491Sharti 2217116491Sharti WRITE4(sc, HE_REGO_UBUFF_BA, (sc->he622 ? 0x104780 : 0x800)); 2218116491Sharti 2219116491Sharti /* 2220116491Sharti * Initialize HSP 2221116491Sharti */ 2222116491Sharti bzero(sc->hsp_mem.base, sc->hsp_mem.size); 2223116491Sharti sc->hsp = sc->hsp_mem.base; 2224116491Sharti WRITE4(sc, HE_REGO_HSP_BA, sc->hsp_mem.paddr); 2225116491Sharti 2226116491Sharti /* 2227116491Sharti * 5.1.12 Enable transmit and receive 2228116491Sharti * Enable bus master and interrupts 2229116491Sharti */ 2230116491Sharti v = READ_MBOX4(sc, HE_REGO_CS_ERCTL0); 2231116491Sharti v |= 0x18000000; 2232116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_ERCTL0, v); 2233116491Sharti 2234116491Sharti v = READ4(sc, HE_REGO_RCCONFIG); 2235116491Sharti v |= HE_REGM_RCCONFIG_RXENB; 2236116491Sharti WRITE4(sc, HE_REGO_RCCONFIG, v); 2237116491Sharti 2238116491Sharti v = pci_read_config(sc->dev, HE_PCIR_GEN_CNTL_0, 4); 2239116491Sharti v |= HE_PCIM_CTL0_INIT_ENB | HE_PCIM_CTL0_INT_PROC_ENB; 2240116491Sharti pci_write_config(sc->dev, HE_PCIR_GEN_CNTL_0, v, 4); 2241116491Sharti 2242148887Srwatson sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; 2243147256Sbrooks sc->ifp->if_baudrate = 53 * 8 * IFP2IFATM(sc->ifp)->mib.pcr; 2244116491Sharti 2245116491Sharti sc->utopia.flags &= ~UTP_FL_POLL_CARRIER; 2246118170Sharti 2247118598Sharti /* reopen vccs */ 2248118598Sharti for (cid = 0; cid < HE_MAX_VCCS; cid++) 2249118598Sharti if (sc->vccs[cid] != NULL) 2250118598Sharti hatm_load_vc(sc, cid, 1); 2251118598Sharti 2252147256Sbrooks ATMEV_SEND_IFSTATE_CHANGED(IFP2IFATM(sc->ifp), 2253118170Sharti sc->utopia.carrier == UTP_CARR_OK); 2254116491Sharti} 2255116491Sharti 2256116491Sharti/* 2257116491Sharti * This functions stops the card and frees all resources allocated after 2258116491Sharti * the attach. Must have the global lock. 2259116491Sharti */ 2260116491Shartivoid 2261116491Shartihatm_stop(struct hatm_softc *sc) 2262116491Sharti{ 2263116491Sharti uint32_t v; 2264116491Sharti u_int i, p, cid; 2265116491Sharti struct mbuf_chunk_hdr *ch; 2266116491Sharti struct mbuf_page *pg; 2267116491Sharti 2268116491Sharti mtx_assert(&sc->mtx, MA_OWNED); 2269116491Sharti 2270148887Srwatson if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING)) 2271116491Sharti return; 2272148887Srwatson sc->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 2273116491Sharti 2274147256Sbrooks ATMEV_SEND_IFSTATE_CHANGED(IFP2IFATM(sc->ifp), 2275118170Sharti sc->utopia.carrier == UTP_CARR_OK); 2276118170Sharti 2277116491Sharti sc->utopia.flags |= UTP_FL_POLL_CARRIER; 2278116491Sharti 2279116491Sharti /* 2280116491Sharti * Stop and reset the hardware so that everything remains 2281116491Sharti * stable. 2282116491Sharti */ 2283116491Sharti v = READ_MBOX4(sc, HE_REGO_CS_ERCTL0); 2284116491Sharti v &= ~0x18000000; 2285116491Sharti WRITE_MBOX4(sc, HE_REGO_CS_ERCTL0, v); 2286116491Sharti 2287116491Sharti v = READ4(sc, HE_REGO_RCCONFIG); 2288116491Sharti v &= ~HE_REGM_RCCONFIG_RXENB; 2289116491Sharti WRITE4(sc, HE_REGO_RCCONFIG, v); 2290116491Sharti 2291116491Sharti WRITE4(sc, HE_REGO_RHCONFIG, (0x2 << HE_REGS_RHCONFIG_PTMR_PRE)); 2292116491Sharti BARRIER_W(sc); 2293116491Sharti 2294116491Sharti v = READ4(sc, HE_REGO_HOST_CNTL); 2295116491Sharti BARRIER_R(sc); 2296116491Sharti v &= ~(HE_REGM_HOST_OUTFF_ENB | HE_REGM_HOST_CMDFF_ENB); 2297116491Sharti WRITE4(sc, HE_REGO_HOST_CNTL, v); 2298116491Sharti BARRIER_W(sc); 2299116491Sharti 2300116491Sharti /* 2301116491Sharti * Disable bust master and interrupts 2302116491Sharti */ 2303116491Sharti v = pci_read_config(sc->dev, HE_PCIR_GEN_CNTL_0, 4); 2304116491Sharti v &= ~(HE_PCIM_CTL0_INIT_ENB | HE_PCIM_CTL0_INT_PROC_ENB); 2305116491Sharti pci_write_config(sc->dev, HE_PCIR_GEN_CNTL_0, v, 4); 2306116491Sharti 2307116491Sharti (void)hatm_reset(sc); 2308116491Sharti 2309116491Sharti /* 2310117687Sharti * Card resets the SUNI when resetted, so re-initialize it 2311117687Sharti */ 2312117687Sharti utopia_reset(&sc->utopia); 2313117687Sharti 2314117687Sharti /* 2315116491Sharti * Give any waiters on closing a VCC a chance. They will stop 2316148887Srwatson * to wait if they see that IFF_DRV_RUNNING disappeared. 2317116491Sharti */ 2318126396Sscottl cv_broadcast(&sc->vcc_cv); 2319126396Sscottl cv_broadcast(&sc->cv_rcclose); 2320116491Sharti 2321116491Sharti /* 2322116491Sharti * Now free all resources. 2323116491Sharti */ 2324116491Sharti 2325116491Sharti /* 2326116491Sharti * Free the large mbufs that are given to the card. 2327116491Sharti */ 2328116491Sharti for (i = 0 ; i < sc->lbufs_size; i++) { 2329116491Sharti if (sc->lbufs[i] != NULL) { 2330116491Sharti bus_dmamap_unload(sc->mbuf_tag, sc->rmaps[i]); 2331116491Sharti m_freem(sc->lbufs[i]); 2332116491Sharti sc->lbufs[i] = NULL; 2333116491Sharti } 2334116491Sharti } 2335116491Sharti 2336116491Sharti /* 2337116491Sharti * Free small buffers 2338116491Sharti */ 2339116491Sharti for (p = 0; p < sc->mbuf_npages; p++) { 2340116491Sharti pg = sc->mbuf_pages[p]; 2341116491Sharti for (i = 0; i < pg->hdr.nchunks; i++) { 2342121729Sharti ch = (struct mbuf_chunk_hdr *) ((char *)pg + 2343121729Sharti i * pg->hdr.chunksize + pg->hdr.hdroff); 2344121729Sharti if (ch->flags & MBUF_CARD) { 2345121729Sharti ch->flags &= ~MBUF_CARD; 2346121729Sharti ch->flags |= MBUF_USED; 2347121729Sharti hatm_ext_free(&sc->mbuf_list[pg->hdr.pool], 2348121729Sharti (struct mbufx_free *)((u_char *)ch - 2349121729Sharti pg->hdr.hdroff)); 2350116491Sharti } 2351116491Sharti } 2352116491Sharti } 2353116491Sharti 2354116491Sharti hatm_stop_tpds(sc); 2355116491Sharti 2356116491Sharti /* 2357116491Sharti * Free all partial reassembled PDUs on any VCC. 2358116491Sharti */ 2359116491Sharti for (cid = 0; cid < HE_MAX_VCCS; cid++) { 2360116491Sharti if (sc->vccs[cid] != NULL) { 2361118598Sharti if (sc->vccs[cid]->chain != NULL) { 2362116491Sharti m_freem(sc->vccs[cid]->chain); 2363118598Sharti sc->vccs[cid]->chain = NULL; 2364118598Sharti sc->vccs[cid]->last = NULL; 2365118598Sharti } 2366118598Sharti if (!(sc->vccs[cid]->vflags & (HE_VCC_RX_OPEN | 2367118598Sharti HE_VCC_TX_OPEN))) { 2368118598Sharti hatm_tx_vcc_closed(sc, cid); 2369118598Sharti uma_zfree(sc->vcc_zone, sc->vccs[cid]); 2370118598Sharti sc->vccs[cid] = NULL; 2371118598Sharti sc->open_vccs--; 2372118598Sharti } else { 2373118598Sharti sc->vccs[cid]->vflags = 0; 2374118598Sharti sc->vccs[cid]->ntpds = 0; 2375118598Sharti } 2376116491Sharti } 2377116491Sharti } 2378116491Sharti 2379116491Sharti if (sc->rbp_s0.size != 0) 2380116491Sharti bzero(sc->rbp_s0.mem.base, sc->rbp_s0.mem.size); 2381116491Sharti if (sc->rbp_l0.size != 0) 2382116491Sharti bzero(sc->rbp_l0.mem.base, sc->rbp_l0.mem.size); 2383116491Sharti if (sc->rbp_s1.size != 0) 2384116491Sharti bzero(sc->rbp_s1.mem.base, sc->rbp_s1.mem.size); 2385116491Sharti if (sc->rbrq_0.size != 0) 2386116491Sharti bzero(sc->rbrq_0.mem.base, sc->rbrq_0.mem.size); 2387116491Sharti if (sc->rbrq_1.size != 0) 2388116491Sharti bzero(sc->rbrq_1.mem.base, sc->rbrq_1.mem.size); 2389116491Sharti 2390116491Sharti bzero(sc->tbrq.mem.base, sc->tbrq.mem.size); 2391116491Sharti bzero(sc->tpdrq.mem.base, sc->tpdrq.mem.size); 2392116491Sharti bzero(sc->hsp_mem.base, sc->hsp_mem.size); 2393116491Sharti} 2394116491Sharti 2395116491Sharti/************************************************************ 2396116491Sharti * 2397116491Sharti * Driver infrastructure 2398116491Sharti */ 2399116491Shartidevclass_t hatm_devclass; 2400116491Sharti 2401116491Shartistatic device_method_t hatm_methods[] = { 2402116491Sharti DEVMETHOD(device_probe, hatm_probe), 2403116491Sharti DEVMETHOD(device_attach, hatm_attach), 2404116491Sharti DEVMETHOD(device_detach, hatm_detach), 2405116491Sharti {0,0} 2406116491Sharti}; 2407116491Shartistatic driver_t hatm_driver = { 2408116491Sharti "hatm", 2409116491Sharti hatm_methods, 2410116491Sharti sizeof(struct hatm_softc), 2411116491Sharti}; 2412116491ShartiDRIVER_MODULE(hatm, pci, hatm_driver, hatm_devclass, NULL, 0); 2413