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