if_patm_attach.c revision 127135
1117632Sharti/* 2117632Sharti * Copyright (c) 2003 3117632Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4117632Sharti * All rights reserved. 5117632Sharti * 6117632Sharti * Redistribution and use in source and binary forms, with or without 7117632Sharti * modification, are permitted provided that the following conditions 8117632Sharti * are met: 9117632Sharti * 1. Redistributions of source code must retain the above copyright 10117632Sharti * notice, this list of conditions and the following disclaimer. 11117632Sharti * 2. Redistributions in binary form must reproduce the above copyright 12117632Sharti * notice, this list of conditions and the following disclaimer in the 13117632Sharti * documentation and/or other materials provided with the distribution. 14117632Sharti * 15117632Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16117632Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17117632Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18117632Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19117632Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20117632Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21117632Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22117632Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23117632Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24117632Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25117632Sharti * SUCH DAMAGE. 26117632Sharti * 27117632Sharti * Author: Hartmut Brandt <harti@freebsd.org> 28117632Sharti * 29117632Sharti * Driver for IDT77252 based cards like ProSum's. 30117632Sharti */ 31119418Sobrien 32117632Sharti#include <sys/cdefs.h> 33117632Sharti__FBSDID("$FreeBSD: head/sys/dev/patm/if_patm_attach.c 127135 2004-03-17 17:50:55Z njl $"); 34117632Sharti 35117632Sharti#include "opt_inet.h" 36117632Sharti#include "opt_natm.h" 37117632Sharti 38117632Sharti#include <sys/types.h> 39117632Sharti#include <sys/param.h> 40117632Sharti#include <sys/systm.h> 41117632Sharti#include <sys/malloc.h> 42117632Sharti#include <sys/kernel.h> 43117632Sharti#include <sys/bus.h> 44117632Sharti#include <sys/errno.h> 45117632Sharti#include <sys/conf.h> 46117632Sharti#include <sys/module.h> 47117632Sharti#include <sys/lock.h> 48117632Sharti#include <sys/mutex.h> 49117632Sharti#include <sys/sysctl.h> 50117632Sharti#include <sys/queue.h> 51117632Sharti#include <sys/condvar.h> 52117632Sharti#include <vm/uma.h> 53117632Sharti 54117632Sharti#include <sys/sockio.h> 55117632Sharti#include <sys/mbuf.h> 56117632Sharti#include <sys/socket.h> 57117632Sharti 58117632Sharti#include <net/if.h> 59117632Sharti#include <net/if_media.h> 60117632Sharti#include <net/if_atm.h> 61117632Sharti#include <net/route.h> 62117632Sharti#ifdef ENABLE_BPF 63117632Sharti#include <net/bpf.h> 64117632Sharti#endif 65117632Sharti#include <netinet/in.h> 66117632Sharti#include <netinet/if_atm.h> 67117632Sharti 68117632Sharti#include <machine/bus.h> 69117632Sharti#include <machine/resource.h> 70117632Sharti#include <sys/bus.h> 71117632Sharti#include <sys/rman.h> 72117632Sharti#include <sys/mbpool.h> 73119285Simp#include <dev/pci/pcireg.h> 74119285Simp#include <dev/pci/pcivar.h> 75117632Sharti 76117632Sharti#include <dev/utopia/utopia.h> 77117632Sharti#include <dev/patm/idt77252reg.h> 78117632Sharti#include <dev/patm/if_patmvar.h> 79117632Sharti 80117632ShartiMODULE_DEPEND(patm, utopia, 1, 1, 1); 81117632ShartiMODULE_DEPEND(patm, pci, 1, 1, 1); 82117632ShartiMODULE_DEPEND(patm, atm, 1, 1, 1); 83117632ShartiMODULE_DEPEND(patm, libmbpool, 1, 1, 1); 84117632Sharti 85117632Shartidevclass_t patm_devclass; 86117632Sharti 87117632Shartistatic int patm_probe(device_t dev); 88117632Shartistatic int patm_attach(device_t dev); 89117632Shartistatic int patm_detach(device_t dev); 90117632Shartistatic device_method_t patm_methods[] = { 91117632Sharti DEVMETHOD(device_probe, patm_probe), 92117632Sharti DEVMETHOD(device_attach, patm_attach), 93117632Sharti DEVMETHOD(device_detach, patm_detach), 94117632Sharti {0,0} 95117632Sharti}; 96117632Shartistatic driver_t patm_driver = { 97117632Sharti "patm", 98117632Sharti patm_methods, 99117632Sharti sizeof(struct patm_softc), 100117632Sharti}; 101117632ShartiDRIVER_MODULE(patm, pci, patm_driver, patm_devclass, NULL, 0); 102117632Sharti 103117632Shartistatic const struct { 104117632Sharti u_int devid; 105117632Sharti const char *desc; 106117632Sharti} devs[] = { 107117632Sharti { PCI_DEVICE_IDT77252, "NICStAR (77222/77252) ATM adapter" }, 108117632Sharti { PCI_DEVICE_IDT77v252, "NICStAR (77v252) ATM adapter" }, 109117632Sharti { PCI_DEVICE_IDT77v222, "NICStAR (77v222) ATM adapter" }, 110117632Sharti { 0, NULL } 111117632Sharti}; 112117632Sharti 113117632ShartiSYSCTL_DECL(_hw_atm); 114117632Sharti 115117632Shartistatic int patm_phy_readregs(struct ifatm *, u_int, uint8_t *, u_int *); 116117632Shartistatic int patm_phy_writereg(struct ifatm *, u_int, u_int, u_int); 117117632Shartistatic const struct utopia_methods patm_utopia_methods = { 118117632Sharti patm_phy_readregs, 119117632Sharti patm_phy_writereg 120117632Sharti}; 121117632Sharti 122117632Shartistatic void patm_destroy(struct patm_softc *sc); 123117632Sharti 124117632Shartistatic int patm_sysctl_istats(SYSCTL_HANDLER_ARGS); 125117632Shartistatic int patm_sysctl_eeprom(SYSCTL_HANDLER_ARGS); 126117632Sharti 127117632Shartistatic void patm_read_eeprom(struct patm_softc *sc); 128117632Shartistatic int patm_sq_init(struct patm_softc *sc); 129117632Shartistatic int patm_rbuf_init(struct patm_softc *sc); 130117632Shartistatic int patm_txmap_init(struct patm_softc *sc); 131117632Sharti 132117632Shartistatic void patm_env_getuint(struct patm_softc *, u_int *, const char *); 133117632Sharti 134117632Sharti#ifdef PATM_DEBUG 135117632Shartistatic int patm_sysctl_regs(SYSCTL_HANDLER_ARGS); 136117632Shartistatic int patm_sysctl_tsq(SYSCTL_HANDLER_ARGS); 137117632Shartiint patm_dump_vc(u_int unit, u_int vc) __unused; 138117632Shartiint patm_dump_regs(u_int unit) __unused; 139117632Shartiint patm_dump_sram(u_int unit, u_int from, u_int words) __unused; 140117632Sharti#endif 141117632Sharti 142117632Sharti/* 143117632Sharti * Probe for a IDT77252 controller 144117632Sharti */ 145117632Shartistatic int 146117632Shartipatm_probe(device_t dev) 147117632Sharti{ 148117632Sharti u_int i; 149117632Sharti 150117632Sharti if (pci_get_vendor(dev) == PCI_VENDOR_IDT) { 151117632Sharti for (i = 0; devs[i].desc != NULL; i++) 152117632Sharti if (pci_get_device(dev) == devs[i].devid) { 153117632Sharti device_set_desc(dev, devs[i].desc); 154117632Sharti return (0); 155117632Sharti } 156117632Sharti } 157117632Sharti return (ENXIO); 158117632Sharti} 159117632Sharti 160117632Sharti/* 161117632Sharti * Attach 162117632Sharti */ 163117632Shartistatic int 164117632Shartipatm_attach(device_t dev) 165117632Sharti{ 166117632Sharti struct patm_softc *sc; 167117632Sharti int error; 168117632Sharti struct ifnet *ifp; 169117632Sharti int rid; 170117632Sharti u_int a; 171117632Sharti 172117632Sharti static const struct idt_mmap idt_mmap[4] = IDT_MMAP; 173117632Sharti 174117632Sharti sc = device_get_softc(dev); 175117632Sharti 176117632Sharti sc->dev = dev; 177117632Sharti#ifdef IATM_DEBUG 178117632Sharti sc->debug = IATM_DEBUG; 179117632Sharti#endif 180117632Sharti sc->ifatm.mib.device = ATM_DEVICE_IDTABR25; 181117632Sharti sc->ifatm.mib.serial = 0; 182117632Sharti sc->ifatm.mib.hw_version = 0; 183117632Sharti sc->ifatm.mib.sw_version = 0; 184117632Sharti sc->ifatm.mib.vpi_bits = PATM_VPI_BITS; 185117632Sharti sc->ifatm.mib.vci_bits = 0; /* set below */; 186117632Sharti sc->ifatm.mib.max_vpcs = 0; 187117632Sharti sc->ifatm.mib.max_vccs = 0; /* set below */ 188117632Sharti sc->ifatm.mib.media = IFM_ATM_UNKNOWN; 189117632Sharti sc->ifatm.phy = &sc->utopia; 190117632Sharti 191117632Sharti ifp = &sc->ifatm.ifnet; 192117632Sharti ifp->if_softc = sc; 193121816Sbrooks if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 194117632Sharti ifp->if_flags = IFF_SIMPLEX; 195117632Sharti ifp->if_watchdog = NULL; 196117632Sharti ifp->if_init = patm_init; 197117632Sharti ifp->if_ioctl = patm_ioctl; 198117632Sharti ifp->if_start = patm_start; 199117632Sharti ifp->if_watchdog = NULL; 200117632Sharti 201117632Sharti /* do this early so we can destroy unconditionally */ 202117632Sharti mtx_init(&sc->mtx, device_get_nameunit(dev), 203117632Sharti MTX_NETWORK_LOCK, MTX_DEF); 204117632Sharti mtx_init(&sc->tst_lock, "tst lock", NULL, MTX_DEF); 205117632Sharti cv_init(&sc->vcc_cv, "vcc_close"); 206117632Sharti 207119137Ssam callout_init(&sc->tst_callout, CALLOUT_MPSAFE); 208117632Sharti 209117632Sharti sysctl_ctx_init(&sc->sysctl_ctx); 210117632Sharti 211117632Sharti /* 212117632Sharti * Get revision 213117632Sharti */ 214117632Sharti sc->revision = pci_read_config(dev, PCIR_REVID, 4) & 0xf; 215117632Sharti 216117632Sharti /* 217117632Sharti * Enable PCI bus master and memory 218117632Sharti */ 219117632Sharti pci_enable_busmaster(dev); 220117632Sharti 221117632Sharti rid = IDT_PCI_REG_MEMBASE; 222127135Snjl sc->memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 223127135Snjl RF_ACTIVE); 224117632Sharti if (sc->memres == NULL) { 225117632Sharti patm_printf(sc, "could not map memory\n"); 226117632Sharti error = ENXIO; 227117632Sharti goto fail; 228117632Sharti } 229117632Sharti sc->memh = rman_get_bushandle(sc->memres); 230117632Sharti sc->memt = rman_get_bustag(sc->memres); 231117632Sharti 232117632Sharti /* 233117632Sharti * Allocate the interrupt (enable it later) 234117632Sharti */ 235117632Sharti sc->irqid = 0; 236127135Snjl sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid, 237127135Snjl RF_SHAREABLE | RF_ACTIVE); 238117632Sharti if (sc->irqres == 0) { 239117632Sharti patm_printf(sc, "could not allocate irq\n"); 240117632Sharti error = ENXIO; 241117632Sharti goto fail; 242117632Sharti } 243117632Sharti 244117632Sharti /* 245117632Sharti * Construct the sysctl tree 246117632Sharti */ 247117632Sharti error = ENOMEM; 248117632Sharti if ((sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, 249117632Sharti SYSCTL_STATIC_CHILDREN(_hw_atm), OID_AUTO, 250117632Sharti device_get_nameunit(dev), CTLFLAG_RD, 0, "")) == NULL) 251117632Sharti goto fail; 252117632Sharti 253117632Sharti if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 254117632Sharti OID_AUTO, "istats", CTLFLAG_RD, sc, 0, patm_sysctl_istats, 255117632Sharti "S", "internal statistics") == NULL) 256117632Sharti goto fail; 257117632Sharti 258117632Sharti if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 259117632Sharti OID_AUTO, "eeprom", CTLFLAG_RD, sc, 0, patm_sysctl_eeprom, 260117632Sharti "S", "EEPROM contents") == NULL) 261117632Sharti goto fail; 262117632Sharti 263117632Sharti if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 264117632Sharti OID_AUTO, "lbuf_max", CTLFLAG_RD, &sc->lbuf_max, 265117632Sharti 0, "maximum number of large receive buffers") == NULL) 266117632Sharti goto fail; 267117632Sharti patm_env_getuint(sc, &sc->lbuf_max, "lbuf_max"); 268117632Sharti 269117632Sharti if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 270117632Sharti OID_AUTO, "max_txmaps", CTLFLAG_RW, &sc->tx_maxmaps, 271117632Sharti 0, "maximum number of TX DMA maps") == NULL) 272117632Sharti goto fail; 273117632Sharti patm_env_getuint(sc, &sc->tx_maxmaps, "tx_maxmaps"); 274117632Sharti 275117632Sharti#ifdef PATM_DEBUG 276117632Sharti if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 277117632Sharti OID_AUTO, "debug", CTLFLAG_RW, &sc->debug, 278117632Sharti 0, "debug flags") == NULL) 279117632Sharti goto fail; 280117632Sharti sc->debug = PATM_DEBUG; 281117632Sharti patm_env_getuint(sc, &sc->debug, "debug"); 282117632Sharti 283117632Sharti if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 284117632Sharti OID_AUTO, "regs", CTLFLAG_RD, sc, 0, patm_sysctl_regs, 285117632Sharti "S", "registers") == NULL) 286117632Sharti goto fail; 287117632Sharti 288117632Sharti if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 289117632Sharti OID_AUTO, "tsq", CTLFLAG_RD, sc, 0, patm_sysctl_tsq, 290117632Sharti "S", "TSQ") == NULL) 291117632Sharti goto fail; 292117632Sharti#endif 293117632Sharti 294117632Sharti patm_reset(sc); 295117632Sharti 296117632Sharti /* 297117632Sharti * Detect and attach the phy. 298117632Sharti */ 299117632Sharti patm_debug(sc, ATTACH, "attaching utopia"); 300117632Sharti sc->ifatm.phy = &sc->utopia; 301117632Sharti utopia_attach(&sc->utopia, &sc->ifatm, &sc->media, &sc->mtx, 302117632Sharti &sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 303117632Sharti &patm_utopia_methods); 304117632Sharti 305117632Sharti /* 306117632Sharti * Start the PHY because we need the autodetection 307117632Sharti */ 308117632Sharti patm_debug(sc, ATTACH, "starting utopia"); 309117632Sharti mtx_lock(&sc->mtx); 310117632Sharti utopia_start(&sc->utopia); 311117632Sharti utopia_reset(&sc->utopia); 312117632Sharti mtx_unlock(&sc->mtx); 313117632Sharti 314117632Sharti /* Read EEPROM */ 315117632Sharti patm_read_eeprom(sc); 316117632Sharti 317117632Sharti /* analyze it */ 318117632Sharti if (strncmp(sc->eeprom + PATM_PROATM_NAME_OFFSET, PATM_PROATM_NAME, 319117632Sharti strlen(PATM_PROATM_NAME)) == 0) { 320117632Sharti if (sc->utopia.chip->type == UTP_TYPE_IDT77105) { 321117632Sharti sc->ifatm.mib.device = ATM_DEVICE_PROATM25; 322117632Sharti sc->ifatm.mib.pcr = ATM_RATE_25_6M; 323117632Sharti sc->ifatm.mib.media = IFM_ATM_UTP_25; 324117632Sharti sc->flags |= PATM_25M; 325117632Sharti patm_printf(sc, "ProATM 25 interface; "); 326117632Sharti 327117632Sharti } else { 328117632Sharti /* cannot really know which media */ 329117632Sharti sc->ifatm.mib.device = ATM_DEVICE_PROATM155; 330117632Sharti sc->ifatm.mib.pcr = ATM_RATE_155M; 331117632Sharti sc->ifatm.mib.media = IFM_ATM_MM_155; 332117632Sharti patm_printf(sc, "ProATM 155 interface; "); 333117632Sharti } 334117632Sharti 335117632Sharti bcopy(sc->eeprom + PATM_PROATM_MAC_OFFSET, sc->ifatm.mib.esi, 336117632Sharti sizeof(sc->ifatm.mib.esi)); 337117632Sharti 338117632Sharti } else { 339117632Sharti if (sc->utopia.chip->type == UTP_TYPE_IDT77105) { 340117632Sharti sc->ifatm.mib.device = ATM_DEVICE_IDTABR25; 341117632Sharti sc->ifatm.mib.pcr = ATM_RATE_25_6M; 342117632Sharti sc->ifatm.mib.media = IFM_ATM_UTP_25; 343117632Sharti sc->flags |= PATM_25M; 344117632Sharti patm_printf(sc, "IDT77252 25MBit interface; "); 345117632Sharti 346117632Sharti } else { 347117632Sharti /* cannot really know which media */ 348117632Sharti sc->ifatm.mib.device = ATM_DEVICE_IDTABR155; 349117632Sharti sc->ifatm.mib.pcr = ATM_RATE_155M; 350117632Sharti sc->ifatm.mib.media = IFM_ATM_MM_155; 351117632Sharti patm_printf(sc, "IDT77252 155MBit interface; "); 352117632Sharti } 353117632Sharti 354117632Sharti bcopy(sc->eeprom + PATM_IDT_MAC_OFFSET, sc->ifatm.mib.esi, 355117632Sharti sizeof(sc->ifatm.mib.esi)); 356117632Sharti } 357117632Sharti printf("idt77252 Rev. %c; %s PHY\n", 'A' + sc->revision, 358117632Sharti sc->utopia.chip->name); 359117632Sharti 360117632Sharti utopia_reset_media(&sc->utopia); 361117632Sharti utopia_init_media(&sc->utopia); 362117632Sharti 363117632Sharti /* 364117632Sharti * Determine RAM size 365117632Sharti */ 366117632Sharti for (a = 0; a < 0x20000; a++) 367117632Sharti patm_sram_write(sc, a, 0); 368117632Sharti patm_sram_write(sc, 0, 0xdeadbeef); 369117632Sharti if (patm_sram_read(sc, 0x4004) == 0xdeadbeef) 370117632Sharti sc->mmap = &idt_mmap[0]; 371117632Sharti else if (patm_sram_read(sc, 0x8000) == 0xdeadbeef) 372117632Sharti sc->mmap = &idt_mmap[1]; 373117632Sharti else if (patm_sram_read(sc, 0x20000) == 0xdeadbeef) 374117632Sharti sc->mmap = &idt_mmap[2]; 375117632Sharti else 376117632Sharti sc->mmap = &idt_mmap[3]; 377117632Sharti 378117632Sharti sc->ifatm.mib.vci_bits = sc->mmap->vcbits - sc->ifatm.mib.vpi_bits; 379117632Sharti sc->ifatm.mib.max_vccs = sc->mmap->max_conn; 380117632Sharti patm_sram_write(sc, 0, 0); 381117632Sharti patm_printf(sc, "%uK x 32 SRAM; %u connections\n", sc->mmap->sram, 382117632Sharti sc->mmap->max_conn); 383117632Sharti 384117632Sharti /* initialize status queues */ 385117632Sharti error = patm_sq_init(sc); 386117632Sharti if (error != 0) 387117632Sharti goto fail; 388117632Sharti 389117632Sharti /* get TST */ 390117632Sharti sc->tst_soft = malloc(sizeof(uint32_t) * sc->mmap->tst_size, 391117632Sharti M_DEVBUF, M_WAITOK); 392117632Sharti 393117632Sharti /* allocate all the receive buffer stuff */ 394117632Sharti error = patm_rbuf_init(sc); 395117632Sharti if (error != 0) 396117632Sharti goto fail; 397117632Sharti 398117632Sharti /* 399117632Sharti * Allocate SCD tag 400117632Sharti * 401117632Sharti * Don't use BUS_DMA_ALLOCNOW, because we never need bouncing with 402117632Sharti * bus_dmamem_alloc() 403117632Sharti */ 404117632Sharti error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, 405117632Sharti BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 406117632Sharti NULL, NULL, sizeof(struct patm_scd), 1, 407117632Sharti sizeof(struct patm_scd), 0, NULL, NULL, &sc->scd_tag); 408117632Sharti if (error) { 409117632Sharti patm_printf(sc, "SCD DMA tag create %d\n", error); 410117632Sharti goto fail; 411117632Sharti } 412117632Sharti LIST_INIT(&sc->scd_list); 413117632Sharti 414117632Sharti /* allocate VCC zone and pointers */ 415117632Sharti if ((sc->vcc_zone = uma_zcreate("PATM vccs", sizeof(struct patm_vcc), 416117632Sharti NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0)) == NULL) { 417117632Sharti patm_printf(sc, "cannot allocate zone for vccs\n"); 418117632Sharti goto fail; 419117632Sharti } 420117632Sharti sc->vccs = malloc(sizeof(sc->vccs[0]) * sc->mmap->max_conn, 421117632Sharti M_DEVBUF, M_WAITOK | M_ZERO); 422117632Sharti 423117632Sharti /* allocate transmission resources */ 424117632Sharti error = patm_txmap_init(sc); 425117632Sharti if (error != 0) 426117632Sharti goto fail; 427117632Sharti 428117632Sharti /* poll while we are not running */ 429117632Sharti sc->utopia.flags |= UTP_FL_POLL_CARRIER; 430117632Sharti 431117632Sharti patm_debug(sc, ATTACH, "attaching interface"); 432117632Sharti atm_ifattach(ifp); 433117632Sharti 434117632Sharti#ifdef ENABLE_BPF 435117632Sharti bpfattach(ifp, DLT_ATM_RFC1483, sizeof(struct atmllc)); 436117632Sharti#endif 437117632Sharti 438117632Sharti patm_debug(sc, ATTACH, "attaching interrupt handler"); 439117632Sharti error = bus_setup_intr(dev, sc->irqres, INTR_TYPE_NET, patm_intr, 440117632Sharti sc, &sc->ih); 441117632Sharti if (error != 0) { 442117632Sharti patm_printf(sc, "could not setup interrupt\n"); 443117632Sharti atm_ifdetach(&sc->ifatm.ifnet); 444117632Sharti goto fail; 445117632Sharti } 446117632Sharti 447117632Sharti return (0); 448117632Sharti 449117632Sharti fail: 450117632Sharti patm_destroy(sc); 451117632Sharti return (error); 452117632Sharti} 453117632Sharti 454117632Sharti/* 455117632Sharti * Detach 456117632Sharti */ 457117632Shartistatic int 458117632Shartipatm_detach(device_t dev) 459117632Sharti{ 460117632Sharti struct patm_softc *sc; 461117632Sharti 462117632Sharti sc = (struct patm_softc *)device_get_softc(dev); 463117632Sharti 464117632Sharti mtx_lock(&sc->mtx); 465117632Sharti patm_stop(sc); 466117632Sharti if (sc->utopia.state & UTP_ST_ATTACHED) { 467117632Sharti patm_debug(sc, ATTACH, "detaching utopia"); 468117632Sharti utopia_stop(&sc->utopia); 469117632Sharti utopia_detach(&sc->utopia); 470117632Sharti } 471117632Sharti mtx_unlock(&sc->mtx); 472117632Sharti 473117632Sharti atm_ifdetach(&sc->ifatm.ifnet); 474117632Sharti 475117632Sharti patm_destroy(sc); 476117632Sharti 477117632Sharti return (0); 478117632Sharti} 479117632Sharti 480117632Sharti/* 481117632Sharti * Destroy everything. Assume we are stopped. 482117632Sharti */ 483117632Shartistatic void 484117632Shartipatm_destroy(struct patm_softc *sc) 485117632Sharti{ 486117632Sharti u_int i; 487117632Sharti struct patm_txmap *map; 488117632Sharti 489117632Sharti if (sc->ih != NULL) 490117632Sharti bus_teardown_intr(sc->dev, sc->irqres, sc->ih); 491117632Sharti 492117632Sharti if (sc->tx_mapzone != NULL) { 493117632Sharti /* all maps must be free */ 494117632Sharti while ((map = SLIST_FIRST(&sc->tx_maps_free)) != NULL) { 495117632Sharti bus_dmamap_destroy(sc->tx_tag, map->map); 496117632Sharti SLIST_REMOVE_HEAD(&sc->tx_maps_free, link); 497117632Sharti uma_zfree(sc->tx_mapzone, map); 498117632Sharti } 499117632Sharti uma_zdestroy(sc->tx_mapzone); 500117632Sharti } 501117632Sharti 502117632Sharti if (sc->scd_tag != NULL) 503117632Sharti bus_dma_tag_destroy(sc->scd_tag); 504117632Sharti 505117632Sharti if (sc->tx_tag != NULL) 506117632Sharti bus_dma_tag_destroy(sc->scd_tag); 507117632Sharti 508117632Sharti if (sc->vccs != NULL) { 509117632Sharti for (i = 0; i < sc->mmap->max_conn; i++) 510117632Sharti if (sc->vccs[i] != NULL) 511117632Sharti uma_zfree(sc->vcc_zone, sc->vccs[i]); 512117632Sharti free(sc->vccs, M_DEVBUF); 513117632Sharti } 514117632Sharti if (sc->vcc_zone != NULL) 515117632Sharti uma_zdestroy(sc->vcc_zone); 516117632Sharti 517117632Sharti if (sc->lbufs != NULL) { 518117632Sharti for (i = 0; i < sc->lbuf_max; i++) 519117632Sharti bus_dmamap_destroy(sc->lbuf_tag, sc->lbufs[i].map); 520117632Sharti free(sc->lbufs, M_DEVBUF); 521117632Sharti } 522117632Sharti 523117632Sharti if (sc->lbuf_tag != NULL) 524117632Sharti bus_dma_tag_destroy(sc->lbuf_tag); 525117632Sharti 526117632Sharti if (sc->sbuf_pool != NULL) 527117632Sharti mbp_destroy(sc->sbuf_pool); 528117632Sharti if (sc->vbuf_pool != NULL) 529117632Sharti mbp_destroy(sc->vbuf_pool); 530117632Sharti 531117632Sharti if (sc->sbuf_tag != NULL) 532117632Sharti bus_dma_tag_destroy(sc->sbuf_tag); 533117632Sharti 534117632Sharti if (sc->tst_soft != NULL) 535117632Sharti free(sc->tst_soft, M_DEVBUF); 536117632Sharti 537117632Sharti /* 538117632Sharti * Free all status queue memory resources 539117632Sharti */ 540117632Sharti if (sc->tsq != NULL) { 541117632Sharti bus_dmamap_unload(sc->sq_tag, sc->sq_map); 542117632Sharti bus_dmamem_free(sc->sq_tag, sc->tsq, sc->sq_map); 543117632Sharti bus_dma_tag_destroy(sc->sq_tag); 544117632Sharti } 545117632Sharti 546117632Sharti if (sc->irqres != NULL) 547117632Sharti bus_release_resource(sc->dev, SYS_RES_IRQ, 548117632Sharti sc->irqid, sc->irqres); 549117632Sharti if (sc->memres != NULL) 550117632Sharti bus_release_resource(sc->dev, SYS_RES_MEMORY, 551117632Sharti IDT_PCI_REG_MEMBASE, sc->memres); 552117632Sharti 553117632Sharti /* this was initialize unconditionally */ 554117632Sharti sysctl_ctx_free(&sc->sysctl_ctx); 555117632Sharti cv_destroy(&sc->vcc_cv); 556117632Sharti mtx_destroy(&sc->tst_lock); 557117632Sharti mtx_destroy(&sc->mtx); 558117632Sharti} 559117632Sharti 560117632Sharti/* 561117632Sharti * Try to find a variable in the environment and parse it as an unsigned 562117632Sharti * integer. 563117632Sharti */ 564117632Shartistatic void 565117632Shartipatm_env_getuint(struct patm_softc *sc, u_int *var, const char *name) 566117632Sharti{ 567117632Sharti char full[IFNAMSIZ + 3 + 20]; 568117632Sharti char *val, *end; 569117632Sharti u_long u; 570117632Sharti 571117632Sharti snprintf(full, sizeof(full), "hw.%s.%s", 572117632Sharti device_get_nameunit(sc->dev), name); 573117632Sharti 574117632Sharti if ((val = getenv(full)) != NULL) { 575117632Sharti u = strtoul(val, &end, 0); 576117632Sharti if (end > val && *end == '\0') { 577117632Sharti if (bootverbose) 578117632Sharti patm_printf(sc, "%s=%lu\n", full, u); 579117632Sharti *var = u; 580117632Sharti } 581117632Sharti freeenv(val); 582117632Sharti } 583117632Sharti} 584117632Sharti 585117632Sharti/* 586117632Sharti * Sysctl handler for internal statistics 587117632Sharti * 588117632Sharti * LOCK: unlocked, needed 589117632Sharti */ 590117632Shartistatic int 591117632Shartipatm_sysctl_istats(SYSCTL_HANDLER_ARGS) 592117632Sharti{ 593117632Sharti struct patm_softc *sc = arg1; 594117632Sharti uint32_t *ret; 595117632Sharti int error; 596117632Sharti 597117632Sharti ret = malloc(sizeof(sc->stats), M_TEMP, M_WAITOK); 598117632Sharti 599117632Sharti mtx_lock(&sc->mtx); 600117632Sharti bcopy(&sc->stats, ret, sizeof(sc->stats)); 601117632Sharti mtx_unlock(&sc->mtx); 602117632Sharti 603117632Sharti error = SYSCTL_OUT(req, ret, sizeof(sc->stats)); 604117632Sharti free(ret, M_TEMP); 605117632Sharti 606117632Sharti return (error); 607117632Sharti} 608117632Sharti 609117632Sharti/* 610117632Sharti * Sysctl handler for EEPROM 611117632Sharti * 612117632Sharti * LOCK: unlocked, needed 613117632Sharti */ 614117632Shartistatic int 615117632Shartipatm_sysctl_eeprom(SYSCTL_HANDLER_ARGS) 616117632Sharti{ 617117632Sharti struct patm_softc *sc = arg1; 618117632Sharti void *ret; 619117632Sharti int error; 620117632Sharti 621117632Sharti ret = malloc(sizeof(sc->eeprom), M_TEMP, M_WAITOK); 622117632Sharti 623117632Sharti mtx_lock(&sc->mtx); 624117632Sharti bcopy(sc->eeprom, ret, sizeof(sc->eeprom)); 625117632Sharti mtx_unlock(&sc->mtx); 626117632Sharti 627117632Sharti error = SYSCTL_OUT(req, ret, sizeof(sc->eeprom)); 628117632Sharti free(ret, M_TEMP); 629117632Sharti 630117632Sharti return (error); 631117632Sharti} 632117632Sharti 633117632Sharti/* 634117632Sharti * Read the EEPROM. We assume that this is a XIRCOM 25020 635117632Sharti */ 636117632Shartistatic void 637117632Shartipatm_read_eeprom(struct patm_softc *sc) 638117632Sharti{ 639117632Sharti u_int gp; 640117632Sharti uint8_t byte; 641117632Sharti int i, addr; 642117632Sharti 643117632Sharti static const uint32_t tab[] = { 644117632Sharti /* CS transition to reset the chip */ 645117632Sharti IDT_GP_EECS | IDT_GP_EESCLK, 0, 646117632Sharti /* read command 0x03 */ 647117632Sharti IDT_GP_EESCLK, 0, 648117632Sharti IDT_GP_EESCLK, 0, 649117632Sharti IDT_GP_EESCLK, 0, 650117632Sharti IDT_GP_EESCLK, 0, 651117632Sharti IDT_GP_EESCLK, 0, 652117632Sharti IDT_GP_EESCLK, IDT_GP_EEDO, 653117632Sharti IDT_GP_EESCLK | IDT_GP_EEDO, IDT_GP_EEDO, 654117632Sharti IDT_GP_EESCLK | IDT_GP_EEDO, 0, 655117632Sharti /* address 0x00 */ 656117632Sharti IDT_GP_EESCLK, 0, 657117632Sharti IDT_GP_EESCLK, 0, 658117632Sharti IDT_GP_EESCLK, 0, 659117632Sharti IDT_GP_EESCLK, 0, 660117632Sharti IDT_GP_EESCLK, 0, 661117632Sharti IDT_GP_EESCLK, 0, 662117632Sharti IDT_GP_EESCLK, 0, 663117632Sharti IDT_GP_EESCLK, 0, 664117632Sharti }; 665117632Sharti 666117632Sharti /* go to a known state (chip enabled) */ 667117632Sharti gp = patm_nor_read(sc, IDT_NOR_GP); 668117632Sharti gp &= ~(IDT_GP_EESCLK | IDT_GP_EECS | IDT_GP_EEDO); 669117632Sharti 670117632Sharti for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) { 671117632Sharti patm_nor_write(sc, IDT_NOR_GP, gp | tab[i]); 672117632Sharti DELAY(40); 673117632Sharti } 674117632Sharti 675117632Sharti /* read out the prom */ 676117632Sharti for (addr = 0; addr < 256; addr++) { 677117632Sharti byte = 0; 678117632Sharti for (i = 0; i < 8; i++) { 679117632Sharti byte <<= 1; 680117632Sharti if (patm_nor_read(sc, IDT_NOR_GP) & IDT_GP_EEDI) 681117632Sharti byte |= 1; 682117632Sharti /* rising CLK */ 683117632Sharti patm_nor_write(sc, IDT_NOR_GP, gp | IDT_GP_EESCLK); 684117632Sharti DELAY(40); 685117632Sharti /* falling clock */ 686117632Sharti patm_nor_write(sc, IDT_NOR_GP, gp); 687117632Sharti DELAY(40); 688117632Sharti } 689117632Sharti sc->eeprom[addr] = byte; 690117632Sharti } 691117632Sharti} 692117632Sharti 693117632Sharti/* 694117632Sharti * PHY access read 695117632Sharti */ 696117632Shartistatic int 697117632Shartipatm_phy_readregs(struct ifatm *ifatm, u_int reg, uint8_t *val, u_int *n) 698117632Sharti{ 699117632Sharti struct patm_softc *sc = ifatm->ifnet.if_softc; 700117632Sharti u_int cnt = *n; 701117632Sharti 702117632Sharti if (reg >= 0x100) 703117632Sharti return (EINVAL); 704117632Sharti 705117632Sharti patm_cmd_wait(sc); 706117632Sharti while (reg < 0x100 && cnt > 0) { 707117632Sharti patm_nor_write(sc, IDT_NOR_CMD, IDT_MKCMD_RUTIL(1, 0, reg)); 708117632Sharti patm_cmd_wait(sc); 709117632Sharti *val = patm_nor_read(sc, IDT_NOR_D0); 710117632Sharti patm_debug(sc, PHY, "phy(%02x)=%02x", reg, *val); 711117632Sharti val++; 712117632Sharti reg++; 713117632Sharti cnt--; 714117632Sharti } 715117632Sharti *n = *n - cnt; 716117632Sharti return (0); 717117632Sharti} 718117632Sharti 719117632Sharti/* 720117632Sharti * Write PHY reg 721117632Sharti */ 722117632Shartistatic int 723117632Shartipatm_phy_writereg(struct ifatm *ifatm, u_int reg, u_int mask, u_int val) 724117632Sharti{ 725117632Sharti struct patm_softc *sc = ifatm->ifnet.if_softc; 726117632Sharti u_int old, new; 727117632Sharti 728117632Sharti if (reg >= 0x100) 729117632Sharti return (EINVAL); 730117632Sharti 731117632Sharti patm_cmd_wait(sc); 732117632Sharti patm_nor_write(sc, IDT_NOR_CMD, IDT_MKCMD_RUTIL(1, 0, reg)); 733117632Sharti patm_cmd_wait(sc); 734117632Sharti 735117632Sharti old = patm_nor_read(sc, IDT_NOR_D0); 736117632Sharti new = (old & ~mask) | (val & mask); 737117632Sharti patm_debug(sc, PHY, "phy(%02x) %02x -> %02x", reg, old, new); 738117632Sharti 739117632Sharti patm_nor_write(sc, IDT_NOR_D0, new); 740117632Sharti patm_nor_write(sc, IDT_NOR_CMD, IDT_MKCMD_WUTIL(1, 0, reg)); 741117632Sharti patm_cmd_wait(sc); 742117632Sharti 743117632Sharti return (0); 744117632Sharti} 745117632Sharti 746117632Sharti/* 747117632Sharti * Allocate a large chunk of DMA able memory for the transmit 748117632Sharti * and receive status queues. We align this to a page boundary 749117632Sharti * to ensure the alignment. 750117632Sharti */ 751117632Shartistatic int 752117632Shartipatm_sq_init(struct patm_softc *sc) 753117632Sharti{ 754117632Sharti int error; 755117632Sharti void *p; 756117632Sharti 757117632Sharti /* compute size of the two queues */ 758117632Sharti sc->sq_size = IDT_TSQ_SIZE * IDT_TSQE_SIZE + 759117632Sharti PATM_RSQ_SIZE * IDT_RSQE_SIZE + 760117632Sharti IDT_RAWHND_SIZE; 761117632Sharti 762117632Sharti patm_debug(sc, ATTACH, 763117632Sharti "allocating status queues (%zu) ...", sc->sq_size); 764117632Sharti 765117632Sharti /* 766117632Sharti * allocate tag 767117632Sharti * Don't use BUS_DMA_ALLOCNOW, because we never need bouncing with 768117632Sharti * bus_dmamem_alloc() 769117632Sharti */ 770117632Sharti error = bus_dma_tag_create(NULL, PATM_SQ_ALIGNMENT, 0, 771117632Sharti BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 772117632Sharti NULL, NULL, sc->sq_size, 1, sc->sq_size, 773117632Sharti 0, NULL, NULL, &sc->sq_tag); 774117632Sharti if (error) { 775117632Sharti patm_printf(sc, "memory DMA tag create %d\n", error); 776117632Sharti return (error); 777117632Sharti } 778117632Sharti 779117632Sharti /* allocate memory */ 780117632Sharti error = bus_dmamem_alloc(sc->sq_tag, &p, 0, &sc->sq_map); 781117632Sharti if (error) { 782117632Sharti patm_printf(sc, "memory DMA alloc %d\n", error); 783117632Sharti bus_dma_tag_destroy(sc->sq_tag); 784117632Sharti return (error); 785117632Sharti } 786117632Sharti 787117632Sharti /* map it */ 788117632Sharti sc->tsq_phy = 0x1fff; 789117632Sharti error = bus_dmamap_load(sc->sq_tag, sc->sq_map, p, 790117632Sharti sc->sq_size, patm_load_callback, &sc->tsq_phy, BUS_DMA_NOWAIT); 791117632Sharti if (error) { 792117632Sharti patm_printf(sc, "memory DMA map load %d\n", error); 793117632Sharti bus_dmamem_free(sc->sq_tag, p, sc->sq_map); 794117632Sharti bus_dma_tag_destroy(sc->sq_tag); 795117632Sharti return (error); 796117632Sharti } 797117632Sharti 798117632Sharti /* set queue start */ 799117632Sharti sc->tsq = p; 800117632Sharti sc->rsq = (void *)((char *)p + IDT_TSQ_SIZE * IDT_TSQE_SIZE); 801117632Sharti sc->rsq_phy = sc->tsq_phy + IDT_TSQ_SIZE * IDT_TSQE_SIZE; 802117632Sharti sc->rawhnd = (void *)((char *)sc->rsq + PATM_RSQ_SIZE * IDT_RSQE_SIZE); 803117632Sharti sc->rawhnd_phy = sc->rsq_phy + PATM_RSQ_SIZE * IDT_RSQE_SIZE; 804117632Sharti 805117632Sharti return (0); 806117632Sharti} 807117632Sharti 808117632Sharti/* 809117632Sharti * Initialize all receive buffer stuff 810117632Sharti */ 811117632Shartistatic int 812117632Shartipatm_rbuf_init(struct patm_softc *sc) 813117632Sharti{ 814117632Sharti u_int i; 815117632Sharti int error; 816117632Sharti 817117632Sharti patm_debug(sc, ATTACH, "allocating Rx buffer resources ..."); 818117632Sharti /* 819117632Sharti * Create a tag for small buffers. We allocate these page wise. 820117632Sharti * Don't use BUS_DMA_ALLOCNOW, because we never need bouncing with 821117632Sharti * bus_dmamem_alloc() 822117632Sharti */ 823117632Sharti if ((error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, 824117632Sharti BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 825117632Sharti SMBUF_PAGE_SIZE, 1, SMBUF_PAGE_SIZE, 0, 826117632Sharti NULL, NULL, &sc->sbuf_tag)) != 0) { 827117632Sharti patm_printf(sc, "sbuf DMA tag create %d\n", error); 828117632Sharti return (error); 829117632Sharti } 830117632Sharti 831117632Sharti error = mbp_create(&sc->sbuf_pool, "patm sbufs", sc->sbuf_tag, 832117632Sharti SMBUF_MAX_PAGES, SMBUF_PAGE_SIZE, SMBUF_CHUNK_SIZE); 833117632Sharti if (error != 0) { 834117632Sharti patm_printf(sc, "smbuf pool create %d\n", error); 835117632Sharti return (error); 836117632Sharti } 837117632Sharti 838117632Sharti error = mbp_create(&sc->vbuf_pool, "patm vbufs", sc->sbuf_tag, 839117632Sharti VMBUF_MAX_PAGES, SMBUF_PAGE_SIZE, VMBUF_CHUNK_SIZE); 840117632Sharti if (error != 0) { 841117632Sharti patm_printf(sc, "vmbuf pool create %d\n", error); 842117632Sharti return (error); 843117632Sharti } 844117632Sharti 845117632Sharti /* 846117632Sharti * Create a tag for large buffers. 847117632Sharti * Don't use BUS_DMA_ALLOCNOW, because it makes no sense with multiple 848117632Sharti * maps using one tag. Rather use BUS_DMA_NOWAIT when loading the map 849117632Sharti * to prevent EINPROGRESS. 850117632Sharti */ 851117632Sharti if ((error = bus_dma_tag_create(NULL, 4, 0, 852117632Sharti BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 853117632Sharti MCLBYTES, 1, MCLBYTES, 0, 854117632Sharti NULL, NULL, &sc->lbuf_tag)) != 0) { 855117632Sharti patm_printf(sc, "lbuf DMA tag create %d\n", error); 856117632Sharti return (error); 857117632Sharti } 858117632Sharti 859117632Sharti if (sc->lbuf_max < IDT_FBQ_SIZE) 860117632Sharti sc->lbuf_max = LMBUF_MAX; 861117632Sharti sc->lbufs = malloc(sizeof(sc->lbufs[0]) * sc->lbuf_max, 862117632Sharti M_DEVBUF, M_ZERO | M_WAITOK); 863117632Sharti 864117632Sharti SLIST_INIT(&sc->lbuf_free_list); 865117632Sharti for (i = 0; i < sc->lbuf_max; i++) { 866117632Sharti struct lmbuf *b = &sc->lbufs[i]; 867117632Sharti 868117632Sharti error = bus_dmamap_create(sc->lbuf_tag, 0, &b->map); 869117632Sharti if (error) { 870117632Sharti /* must deallocate here, because a test for NULL 871117632Sharti * does not work on most archs */ 872117632Sharti while (i-- > 0) 873117632Sharti bus_dmamap_destroy(sc->lbuf_tag, 874117632Sharti sc->lbufs[i].map); 875117632Sharti free(sc->lbufs, M_DEVBUF); 876117632Sharti sc->lbufs = NULL; 877117632Sharti return (error); 878117632Sharti } 879117632Sharti b->handle = i; 880117632Sharti SLIST_INSERT_HEAD(&sc->lbuf_free_list, b, link); 881117632Sharti } 882117632Sharti 883117632Sharti return (0); 884117632Sharti} 885117632Sharti 886117632Sharti/* 887117632Sharti * Allocate everything needed for the transmission maps. 888117632Sharti */ 889117632Shartistatic int 890117632Shartipatm_txmap_init(struct patm_softc *sc) 891117632Sharti{ 892117632Sharti int error; 893117632Sharti struct patm_txmap *map; 894117632Sharti 895117632Sharti /* get transmission tag */ 896117632Sharti error = bus_dma_tag_create(NULL, 1, 0, 897117632Sharti BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 898117632Sharti NULL, NULL, 65536, IDT_SCQ_SIZE - 1, 65536, 899117632Sharti 0, NULL, NULL, &sc->tx_tag); 900117632Sharti if (error) { 901117632Sharti patm_printf(sc, "cannot allocate TX tag %d\n", error); 902117632Sharti return (error); 903117632Sharti } 904117632Sharti 905117632Sharti if ((sc->tx_mapzone = uma_zcreate("PATM tx maps", 906117632Sharti sizeof(struct patm_txmap), NULL, NULL, NULL, NULL, 907117632Sharti UMA_ALIGN_PTR, 0)) == NULL) 908117632Sharti return (ENOMEM); 909117632Sharti 910117632Sharti if (sc->tx_maxmaps < PATM_CFG_TXMAPS_MAX) 911117632Sharti sc->tx_maxmaps = PATM_CFG_TXMAPS_MAX; 912117632Sharti sc->tx_nmaps = PATM_CFG_TXMAPS_INIT; 913117632Sharti 914117632Sharti for (sc->tx_nmaps = 0; sc->tx_nmaps < PATM_CFG_TXMAPS_INIT; 915117632Sharti sc->tx_nmaps++) { 916117632Sharti map = uma_zalloc(sc->tx_mapzone, M_WAITOK); 917117632Sharti error = bus_dmamap_create(sc->tx_tag, 0, &map->map); 918117632Sharti if (error) { 919117632Sharti uma_zfree(sc->tx_mapzone, map); 920117632Sharti return (ENOMEM); 921117632Sharti } 922117632Sharti SLIST_INSERT_HEAD(&sc->tx_maps_free, map, link); 923117632Sharti } 924117632Sharti 925117632Sharti return (0); 926117632Sharti} 927117632Sharti 928117632Sharti#ifdef PATM_DEBUG 929117632Sharti 930117632Sharti/* 931117632Sharti * Sysctl handler for REGS 932117632Sharti * 933117632Sharti * LOCK: unlocked, needed 934117632Sharti */ 935117632Shartistatic int 936117632Shartipatm_sysctl_regs(SYSCTL_HANDLER_ARGS) 937117632Sharti{ 938117632Sharti struct patm_softc *sc = arg1; 939117632Sharti uint32_t *ret; 940117632Sharti int error, i; 941117632Sharti 942117632Sharti ret = malloc(IDT_NOR_END, M_TEMP, M_WAITOK); 943117632Sharti 944117632Sharti mtx_lock(&sc->mtx); 945117632Sharti for (i = 0; i < IDT_NOR_END; i += 4) 946117632Sharti ret[i / 4] = patm_nor_read(sc, i); 947117632Sharti mtx_unlock(&sc->mtx); 948117632Sharti 949117632Sharti error = SYSCTL_OUT(req, ret, IDT_NOR_END); 950117632Sharti free(ret, M_TEMP); 951117632Sharti 952117632Sharti return (error); 953117632Sharti} 954117632Sharti 955117632Sharti/* 956117632Sharti * Sysctl handler for TSQ 957117632Sharti * 958117632Sharti * LOCK: unlocked, needed 959117632Sharti */ 960117632Shartistatic int 961117632Shartipatm_sysctl_tsq(SYSCTL_HANDLER_ARGS) 962117632Sharti{ 963117632Sharti struct patm_softc *sc = arg1; 964117632Sharti void *ret; 965117632Sharti int error; 966117632Sharti 967117632Sharti ret = malloc(IDT_TSQ_SIZE * IDT_TSQE_SIZE, M_TEMP, M_WAITOK); 968117632Sharti 969117632Sharti mtx_lock(&sc->mtx); 970117632Sharti memcpy(ret, sc->tsq, IDT_TSQ_SIZE * IDT_TSQE_SIZE); 971117632Sharti mtx_unlock(&sc->mtx); 972117632Sharti 973117632Sharti error = SYSCTL_OUT(req, ret, IDT_TSQ_SIZE * IDT_TSQE_SIZE); 974117632Sharti free(ret, M_TEMP); 975117632Sharti 976117632Sharti return (error); 977117632Sharti} 978117632Sharti 979117632Sharti/* 980117632Sharti * debugging 981117632Sharti */ 982117632Shartistatic struct patm_softc * 983117632Shartipatm_dump_unit(u_int unit) 984117632Sharti{ 985117632Sharti devclass_t dc; 986117632Sharti struct patm_softc *sc; 987117632Sharti 988117632Sharti dc = devclass_find("patm"); 989117632Sharti if (dc == NULL) { 990117632Sharti printf("%s: can't find devclass\n", __func__); 991117632Sharti return (NULL); 992117632Sharti } 993117632Sharti sc = devclass_get_softc(dc, unit); 994117632Sharti if (sc == NULL) { 995117632Sharti printf("%s: invalid unit number: %d\n", __func__, unit); 996117632Sharti return (NULL); 997117632Sharti } 998117632Sharti return (sc); 999117632Sharti} 1000117632Sharti 1001117632Shartiint 1002117632Shartipatm_dump_vc(u_int unit, u_int vc) 1003117632Sharti{ 1004117632Sharti struct patm_softc *sc; 1005117632Sharti uint32_t tct[8]; 1006117632Sharti uint32_t rct[4]; 1007117632Sharti uint32_t scd[12]; 1008117632Sharti u_int i; 1009117632Sharti 1010117632Sharti if ((sc = patm_dump_unit(unit)) == NULL) 1011117632Sharti return (0); 1012117632Sharti 1013117632Sharti for (i = 0; i < 8; i++) 1014117632Sharti tct[i] = patm_sram_read(sc, vc * 8 + i); 1015117632Sharti for (i = 0; i < 4; i++) 1016117632Sharti rct[i] = patm_sram_read(sc, sc->mmap->rct + vc * 4 + i); 1017117632Sharti for (i = 0; i < 12; i++) 1018117632Sharti scd[i] = patm_sram_read(sc, (tct[0] & 0x7ffff) + i); 1019117632Sharti 1020117632Sharti printf("TCT%3u: %08x %08x %08x %08x %08x %08x %08x %08x\n", vc, 1021117632Sharti tct[0], tct[1], tct[2], tct[3], tct[4], tct[5], tct[6], tct[7]); 1022117632Sharti printf("RCT%3u: %08x %08x %08x %08x\n", vc, 1023117632Sharti rct[0], rct[1], rct[2], rct[3]); 1024117632Sharti printf("SCD%3u: %08x %08x %08x %08x %08x %08x %08x %08x\n", vc, 1025117632Sharti scd[0], scd[1], scd[2], scd[3], scd[4], scd[5], scd[6], scd[7]); 1026117632Sharti printf(" %08x %08x %08x %08x\n", 1027117632Sharti scd[8], scd[9], scd[10], scd[11]); 1028117632Sharti 1029117632Sharti return (0); 1030117632Sharti} 1031117632Sharti 1032117632Shartiint 1033117632Shartipatm_dump_regs(u_int unit) 1034117632Sharti{ 1035117632Sharti struct patm_softc *sc; 1036117632Sharti u_int i; 1037117632Sharti 1038117632Sharti if ((sc = patm_dump_unit(unit)) == NULL) 1039117632Sharti return (0); 1040117632Sharti 1041117632Sharti for (i = 0; i <= IDT_NOR_DNOW; i += 4) 1042117632Sharti printf("%x: %08x\n", i, patm_nor_read(sc, i)); 1043117632Sharti 1044117632Sharti return (0); 1045117632Sharti} 1046117632Sharti 1047117632Shartiint 1048117632Shartipatm_dump_sram(u_int unit, u_int from, u_int words) 1049117632Sharti{ 1050117632Sharti struct patm_softc *sc; 1051117632Sharti u_int i; 1052117632Sharti 1053117632Sharti if ((sc = patm_dump_unit(unit)) == NULL) 1054117632Sharti return (0); 1055117632Sharti 1056117632Sharti for (i = 0; i < words; i++) { 1057117632Sharti if (i % 8 == 0) 1058117632Sharti printf("%05x:", from + i); 1059117632Sharti printf(" %08x", patm_sram_read(sc, from + i)); 1060117632Sharti if (i % 8 == 7) 1061117632Sharti printf("\n"); 1062117632Sharti } 1063117632Sharti if (i % 8 != 0) 1064117632Sharti printf("\n"); 1065117632Sharti return (0); 1066117632Sharti} 1067117632Sharti#endif 1068