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