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