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_watchdog = NULL; 201 ifp->if_init = patm_init; 202 ifp->if_ioctl = patm_ioctl; 203 ifp->if_start = patm_start; 204 ifp->if_watchdog = NULL; 205 206 /* do this early so we can destroy unconditionally */ 207 mtx_init(&sc->mtx, device_get_nameunit(dev), 208 MTX_NETWORK_LOCK, MTX_DEF); 209 mtx_init(&sc->tst_lock, "tst lock", NULL, MTX_DEF); 210 cv_init(&sc->vcc_cv, "vcc_close"); 211 212 callout_init(&sc->tst_callout, CALLOUT_MPSAFE); 213 214 sysctl_ctx_init(&sc->sysctl_ctx); 215 216 /* 217 * Get revision 218 */ 219 sc->revision = pci_read_config(dev, PCIR_REVID, 4) & 0xf; 220 221 /* 222 * Enable PCI bus master and memory 223 */ 224 pci_enable_busmaster(dev); 225 226 rid = IDT_PCI_REG_MEMBASE; 227 sc->memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 228 RF_ACTIVE); 229 if (sc->memres == NULL) { 230 patm_printf(sc, "could not map memory\n"); 231 error = ENXIO; 232 goto fail; 233 } 234 sc->memh = rman_get_bushandle(sc->memres); 235 sc->memt = rman_get_bustag(sc->memres); 236 237 /* 238 * Allocate the interrupt (enable it later) 239 */ 240 sc->irqid = 0; 241 sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid, 242 RF_SHAREABLE | RF_ACTIVE); 243 if (sc->irqres == 0) { 244 patm_printf(sc, "could not allocate irq\n"); 245 error = ENXIO; 246 goto fail; 247 } 248 249 /* 250 * Construct the sysctl tree 251 */ 252 error = ENOMEM; 253 if ((sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, 254 SYSCTL_STATIC_CHILDREN(_hw_atm), OID_AUTO, 255 device_get_nameunit(dev), CTLFLAG_RD, 0, "")) == NULL) 256 goto fail; 257 258 if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 259 OID_AUTO, "istats", CTLFLAG_RD, sc, 0, patm_sysctl_istats, 260 "S", "internal statistics") == NULL) 261 goto fail; 262 263 if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 264 OID_AUTO, "eeprom", CTLFLAG_RD, sc, 0, patm_sysctl_eeprom, 265 "S", "EEPROM contents") == NULL) 266 goto fail; 267 268 if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 269 OID_AUTO, "lbuf_max", CTLFLAG_RD, &sc->lbuf_max, 270 0, "maximum number of large receive buffers") == NULL) 271 goto fail; 272 patm_env_getuint(sc, &sc->lbuf_max, "lbuf_max"); 273 274 if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 275 OID_AUTO, "max_txmaps", CTLFLAG_RW, &sc->tx_maxmaps, 276 0, "maximum number of TX DMA maps") == NULL) 277 goto fail; 278 patm_env_getuint(sc, &sc->tx_maxmaps, "tx_maxmaps"); 279 280#ifdef PATM_DEBUG 281 if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 282 OID_AUTO, "debug", CTLFLAG_RW, &sc->debug, 283 0, "debug flags") == NULL) 284 goto fail; 285 sc->debug = PATM_DEBUG; 286 patm_env_getuint(sc, &sc->debug, "debug"); 287 288 if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 289 OID_AUTO, "regs", CTLFLAG_RD, sc, 0, patm_sysctl_regs, 290 "S", "registers") == NULL) 291 goto fail; 292 293 if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 294 OID_AUTO, "tsq", CTLFLAG_RD, sc, 0, patm_sysctl_tsq, 295 "S", "TSQ") == NULL) 296 goto fail; 297#endif 298 299 patm_reset(sc); 300 301 /* 302 * Detect and attach the phy. 303 */ 304 patm_debug(sc, ATTACH, "attaching utopia"); 305 IFP2IFATM(sc->ifp)->phy = &sc->utopia; 306 utopia_attach(&sc->utopia, IFP2IFATM(sc->ifp), &sc->media, &sc->mtx, 307 &sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 308 &patm_utopia_methods); 309 310 /* 311 * Start the PHY because we need the autodetection 312 */ 313 patm_debug(sc, ATTACH, "starting utopia"); 314 mtx_lock(&sc->mtx); 315 utopia_start(&sc->utopia); 316 utopia_reset(&sc->utopia); 317 mtx_unlock(&sc->mtx); 318 319 /* Read EEPROM */ 320 patm_read_eeprom(sc); 321 322 /* analyze it */ 323 if (strncmp(sc->eeprom + PATM_PROATM_NAME_OFFSET, PATM_PROATM_NAME, 324 strlen(PATM_PROATM_NAME)) == 0) { 325 if (sc->utopia.chip->type == UTP_TYPE_IDT77105) { 326 IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_PROATM25; 327 IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_25_6M; 328 IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_UTP_25; 329 sc->flags |= PATM_25M; 330 patm_printf(sc, "ProATM 25 interface; "); 331 332 } else { 333 /* cannot really know which media */ 334 IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_PROATM155; 335 IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_155M; 336 IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_MM_155; 337 patm_printf(sc, "ProATM 155 interface; "); 338 } 339 340 bcopy(sc->eeprom + PATM_PROATM_MAC_OFFSET, IFP2IFATM(sc->ifp)->mib.esi, 341 sizeof(IFP2IFATM(sc->ifp)->mib.esi)); 342 343 } else { 344 if (sc->utopia.chip->type == UTP_TYPE_IDT77105) { 345 IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_IDTABR25; 346 IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_25_6M; 347 IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_UTP_25; 348 sc->flags |= PATM_25M; 349 patm_printf(sc, "IDT77252 25MBit interface; "); 350 351 } else { 352 /* cannot really know which media */ 353 IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_IDTABR155; 354 IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_155M; 355 IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_MM_155; 356 patm_printf(sc, "IDT77252 155MBit interface; "); 357 } 358 359 bcopy(sc->eeprom + PATM_IDT_MAC_OFFSET, IFP2IFATM(sc->ifp)->mib.esi, 360 sizeof(IFP2IFATM(sc->ifp)->mib.esi)); 361 } 362 printf("idt77252 Rev. %c; %s PHY\n", 'A' + sc->revision, 363 sc->utopia.chip->name); 364 365 utopia_reset_media(&sc->utopia); 366 utopia_init_media(&sc->utopia); 367 368 /* 369 * Determine RAM size 370 */ 371 for (a = 0; a < 0x20000; a++) 372 patm_sram_write(sc, a, 0); 373 patm_sram_write(sc, 0, 0xdeadbeef); 374 if (patm_sram_read(sc, 0x4004) == 0xdeadbeef) 375 sc->mmap = &idt_mmap[0]; 376 else if (patm_sram_read(sc, 0x8000) == 0xdeadbeef) 377 sc->mmap = &idt_mmap[1]; 378 else if (patm_sram_read(sc, 0x20000) == 0xdeadbeef) 379 sc->mmap = &idt_mmap[2]; 380 else 381 sc->mmap = &idt_mmap[3]; 382 383 IFP2IFATM(sc->ifp)->mib.vci_bits = sc->mmap->vcbits - IFP2IFATM(sc->ifp)->mib.vpi_bits; 384 IFP2IFATM(sc->ifp)->mib.max_vccs = sc->mmap->max_conn; 385 patm_sram_write(sc, 0, 0); 386 patm_printf(sc, "%uK x 32 SRAM; %u connections\n", sc->mmap->sram, 387 sc->mmap->max_conn); 388 389 /* initialize status queues */ 390 error = patm_sq_init(sc); 391 if (error != 0) 392 goto fail; 393 394 /* get TST */ 395 sc->tst_soft = malloc(sizeof(uint32_t) * sc->mmap->tst_size, 396 M_DEVBUF, M_WAITOK); 397 398 /* allocate all the receive buffer stuff */ 399 error = patm_rbuf_init(sc); 400 if (error != 0) 401 goto fail; 402 403 /* 404 * Allocate SCD tag 405 * 406 * Don't use BUS_DMA_ALLOCNOW, because we never need bouncing with 407 * bus_dmamem_alloc() 408 */ 409 error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, 410 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 411 NULL, NULL, sizeof(struct patm_scd), 1, 412 sizeof(struct patm_scd), 0, NULL, NULL, &sc->scd_tag); 413 if (error) { 414 patm_printf(sc, "SCD DMA tag create %d\n", error); 415 goto fail; 416 } 417 LIST_INIT(&sc->scd_list); 418 419 /* allocate VCC zone and pointers */ 420 if ((sc->vcc_zone = uma_zcreate("PATM vccs", sizeof(struct patm_vcc), 421 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0)) == NULL) { 422 patm_printf(sc, "cannot allocate zone for vccs\n"); 423 goto fail; 424 } 425 sc->vccs = malloc(sizeof(sc->vccs[0]) * sc->mmap->max_conn, 426 M_DEVBUF, M_WAITOK | M_ZERO); 427 428 /* allocate transmission resources */ 429 error = patm_txmap_init(sc); 430 if (error != 0) 431 goto fail; 432 433 /* poll while we are not running */ 434 sc->utopia.flags |= UTP_FL_POLL_CARRIER; 435 436 patm_debug(sc, ATTACH, "attaching interface"); 437 atm_ifattach(ifp); 438 439#ifdef ENABLE_BPF 440 bpfattach(ifp, DLT_ATM_RFC1483, sizeof(struct atmllc)); 441#endif 442 443 patm_debug(sc, ATTACH, "attaching interrupt handler"); 444 error = bus_setup_intr(dev, sc->irqres, INTR_TYPE_NET, patm_intr, 445 sc, &sc->ih); 446 if (error != 0) { 447 patm_printf(sc, "could not setup interrupt\n"); 448 atm_ifdetach(sc->ifp); 449 if_free(sc->ifp); 450 goto fail; 451 } 452 453 return (0); 454 455 fail: 456 patm_destroy(sc); 457 return (error); 458} 459 460/* 461 * Detach 462 */ 463static int 464patm_detach(device_t dev) 465{ 466 struct patm_softc *sc; 467 468 sc = device_get_softc(dev); 469 470 mtx_lock(&sc->mtx); 471 patm_stop(sc); 472 if (sc->utopia.state & UTP_ST_ATTACHED) { 473 patm_debug(sc, ATTACH, "detaching utopia"); 474 utopia_stop(&sc->utopia); 475 utopia_detach(&sc->utopia); 476 } 477 mtx_unlock(&sc->mtx); 478 479 atm_ifdetach(sc->ifp);
| 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_watchdog = NULL; 201 ifp->if_init = patm_init; 202 ifp->if_ioctl = patm_ioctl; 203 ifp->if_start = patm_start; 204 ifp->if_watchdog = NULL; 205 206 /* do this early so we can destroy unconditionally */ 207 mtx_init(&sc->mtx, device_get_nameunit(dev), 208 MTX_NETWORK_LOCK, MTX_DEF); 209 mtx_init(&sc->tst_lock, "tst lock", NULL, MTX_DEF); 210 cv_init(&sc->vcc_cv, "vcc_close"); 211 212 callout_init(&sc->tst_callout, CALLOUT_MPSAFE); 213 214 sysctl_ctx_init(&sc->sysctl_ctx); 215 216 /* 217 * Get revision 218 */ 219 sc->revision = pci_read_config(dev, PCIR_REVID, 4) & 0xf; 220 221 /* 222 * Enable PCI bus master and memory 223 */ 224 pci_enable_busmaster(dev); 225 226 rid = IDT_PCI_REG_MEMBASE; 227 sc->memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 228 RF_ACTIVE); 229 if (sc->memres == NULL) { 230 patm_printf(sc, "could not map memory\n"); 231 error = ENXIO; 232 goto fail; 233 } 234 sc->memh = rman_get_bushandle(sc->memres); 235 sc->memt = rman_get_bustag(sc->memres); 236 237 /* 238 * Allocate the interrupt (enable it later) 239 */ 240 sc->irqid = 0; 241 sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid, 242 RF_SHAREABLE | RF_ACTIVE); 243 if (sc->irqres == 0) { 244 patm_printf(sc, "could not allocate irq\n"); 245 error = ENXIO; 246 goto fail; 247 } 248 249 /* 250 * Construct the sysctl tree 251 */ 252 error = ENOMEM; 253 if ((sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, 254 SYSCTL_STATIC_CHILDREN(_hw_atm), OID_AUTO, 255 device_get_nameunit(dev), CTLFLAG_RD, 0, "")) == NULL) 256 goto fail; 257 258 if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 259 OID_AUTO, "istats", CTLFLAG_RD, sc, 0, patm_sysctl_istats, 260 "S", "internal statistics") == NULL) 261 goto fail; 262 263 if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 264 OID_AUTO, "eeprom", CTLFLAG_RD, sc, 0, patm_sysctl_eeprom, 265 "S", "EEPROM contents") == NULL) 266 goto fail; 267 268 if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 269 OID_AUTO, "lbuf_max", CTLFLAG_RD, &sc->lbuf_max, 270 0, "maximum number of large receive buffers") == NULL) 271 goto fail; 272 patm_env_getuint(sc, &sc->lbuf_max, "lbuf_max"); 273 274 if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 275 OID_AUTO, "max_txmaps", CTLFLAG_RW, &sc->tx_maxmaps, 276 0, "maximum number of TX DMA maps") == NULL) 277 goto fail; 278 patm_env_getuint(sc, &sc->tx_maxmaps, "tx_maxmaps"); 279 280#ifdef PATM_DEBUG 281 if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 282 OID_AUTO, "debug", CTLFLAG_RW, &sc->debug, 283 0, "debug flags") == NULL) 284 goto fail; 285 sc->debug = PATM_DEBUG; 286 patm_env_getuint(sc, &sc->debug, "debug"); 287 288 if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 289 OID_AUTO, "regs", CTLFLAG_RD, sc, 0, patm_sysctl_regs, 290 "S", "registers") == NULL) 291 goto fail; 292 293 if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 294 OID_AUTO, "tsq", CTLFLAG_RD, sc, 0, patm_sysctl_tsq, 295 "S", "TSQ") == NULL) 296 goto fail; 297#endif 298 299 patm_reset(sc); 300 301 /* 302 * Detect and attach the phy. 303 */ 304 patm_debug(sc, ATTACH, "attaching utopia"); 305 IFP2IFATM(sc->ifp)->phy = &sc->utopia; 306 utopia_attach(&sc->utopia, IFP2IFATM(sc->ifp), &sc->media, &sc->mtx, 307 &sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 308 &patm_utopia_methods); 309 310 /* 311 * Start the PHY because we need the autodetection 312 */ 313 patm_debug(sc, ATTACH, "starting utopia"); 314 mtx_lock(&sc->mtx); 315 utopia_start(&sc->utopia); 316 utopia_reset(&sc->utopia); 317 mtx_unlock(&sc->mtx); 318 319 /* Read EEPROM */ 320 patm_read_eeprom(sc); 321 322 /* analyze it */ 323 if (strncmp(sc->eeprom + PATM_PROATM_NAME_OFFSET, PATM_PROATM_NAME, 324 strlen(PATM_PROATM_NAME)) == 0) { 325 if (sc->utopia.chip->type == UTP_TYPE_IDT77105) { 326 IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_PROATM25; 327 IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_25_6M; 328 IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_UTP_25; 329 sc->flags |= PATM_25M; 330 patm_printf(sc, "ProATM 25 interface; "); 331 332 } else { 333 /* cannot really know which media */ 334 IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_PROATM155; 335 IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_155M; 336 IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_MM_155; 337 patm_printf(sc, "ProATM 155 interface; "); 338 } 339 340 bcopy(sc->eeprom + PATM_PROATM_MAC_OFFSET, IFP2IFATM(sc->ifp)->mib.esi, 341 sizeof(IFP2IFATM(sc->ifp)->mib.esi)); 342 343 } else { 344 if (sc->utopia.chip->type == UTP_TYPE_IDT77105) { 345 IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_IDTABR25; 346 IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_25_6M; 347 IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_UTP_25; 348 sc->flags |= PATM_25M; 349 patm_printf(sc, "IDT77252 25MBit interface; "); 350 351 } else { 352 /* cannot really know which media */ 353 IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_IDTABR155; 354 IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_155M; 355 IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_MM_155; 356 patm_printf(sc, "IDT77252 155MBit interface; "); 357 } 358 359 bcopy(sc->eeprom + PATM_IDT_MAC_OFFSET, IFP2IFATM(sc->ifp)->mib.esi, 360 sizeof(IFP2IFATM(sc->ifp)->mib.esi)); 361 } 362 printf("idt77252 Rev. %c; %s PHY\n", 'A' + sc->revision, 363 sc->utopia.chip->name); 364 365 utopia_reset_media(&sc->utopia); 366 utopia_init_media(&sc->utopia); 367 368 /* 369 * Determine RAM size 370 */ 371 for (a = 0; a < 0x20000; a++) 372 patm_sram_write(sc, a, 0); 373 patm_sram_write(sc, 0, 0xdeadbeef); 374 if (patm_sram_read(sc, 0x4004) == 0xdeadbeef) 375 sc->mmap = &idt_mmap[0]; 376 else if (patm_sram_read(sc, 0x8000) == 0xdeadbeef) 377 sc->mmap = &idt_mmap[1]; 378 else if (patm_sram_read(sc, 0x20000) == 0xdeadbeef) 379 sc->mmap = &idt_mmap[2]; 380 else 381 sc->mmap = &idt_mmap[3]; 382 383 IFP2IFATM(sc->ifp)->mib.vci_bits = sc->mmap->vcbits - IFP2IFATM(sc->ifp)->mib.vpi_bits; 384 IFP2IFATM(sc->ifp)->mib.max_vccs = sc->mmap->max_conn; 385 patm_sram_write(sc, 0, 0); 386 patm_printf(sc, "%uK x 32 SRAM; %u connections\n", sc->mmap->sram, 387 sc->mmap->max_conn); 388 389 /* initialize status queues */ 390 error = patm_sq_init(sc); 391 if (error != 0) 392 goto fail; 393 394 /* get TST */ 395 sc->tst_soft = malloc(sizeof(uint32_t) * sc->mmap->tst_size, 396 M_DEVBUF, M_WAITOK); 397 398 /* allocate all the receive buffer stuff */ 399 error = patm_rbuf_init(sc); 400 if (error != 0) 401 goto fail; 402 403 /* 404 * Allocate SCD tag 405 * 406 * Don't use BUS_DMA_ALLOCNOW, because we never need bouncing with 407 * bus_dmamem_alloc() 408 */ 409 error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, 410 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 411 NULL, NULL, sizeof(struct patm_scd), 1, 412 sizeof(struct patm_scd), 0, NULL, NULL, &sc->scd_tag); 413 if (error) { 414 patm_printf(sc, "SCD DMA tag create %d\n", error); 415 goto fail; 416 } 417 LIST_INIT(&sc->scd_list); 418 419 /* allocate VCC zone and pointers */ 420 if ((sc->vcc_zone = uma_zcreate("PATM vccs", sizeof(struct patm_vcc), 421 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0)) == NULL) { 422 patm_printf(sc, "cannot allocate zone for vccs\n"); 423 goto fail; 424 } 425 sc->vccs = malloc(sizeof(sc->vccs[0]) * sc->mmap->max_conn, 426 M_DEVBUF, M_WAITOK | M_ZERO); 427 428 /* allocate transmission resources */ 429 error = patm_txmap_init(sc); 430 if (error != 0) 431 goto fail; 432 433 /* poll while we are not running */ 434 sc->utopia.flags |= UTP_FL_POLL_CARRIER; 435 436 patm_debug(sc, ATTACH, "attaching interface"); 437 atm_ifattach(ifp); 438 439#ifdef ENABLE_BPF 440 bpfattach(ifp, DLT_ATM_RFC1483, sizeof(struct atmllc)); 441#endif 442 443 patm_debug(sc, ATTACH, "attaching interrupt handler"); 444 error = bus_setup_intr(dev, sc->irqres, INTR_TYPE_NET, patm_intr, 445 sc, &sc->ih); 446 if (error != 0) { 447 patm_printf(sc, "could not setup interrupt\n"); 448 atm_ifdetach(sc->ifp); 449 if_free(sc->ifp); 450 goto fail; 451 } 452 453 return (0); 454 455 fail: 456 patm_destroy(sc); 457 return (error); 458} 459 460/* 461 * Detach 462 */ 463static int 464patm_detach(device_t dev) 465{ 466 struct patm_softc *sc; 467 468 sc = device_get_softc(dev); 469 470 mtx_lock(&sc->mtx); 471 patm_stop(sc); 472 if (sc->utopia.state & UTP_ST_ATTACHED) { 473 patm_debug(sc, ATTACH, "detaching utopia"); 474 utopia_stop(&sc->utopia); 475 utopia_detach(&sc->utopia); 476 } 477 mtx_unlock(&sc->mtx); 478 479 atm_ifdetach(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
| 567} 568 569/* 570 * Try to find a variable in the environment and parse it as an unsigned 571 * integer. 572 */ 573static void 574patm_env_getuint(struct patm_softc *sc, u_int *var, const char *name) 575{ 576 char full[IFNAMSIZ + 3 + 20]; 577 char *val, *end; 578 u_long u; 579 580 snprintf(full, sizeof(full), "hw.%s.%s", 581 device_get_nameunit(sc->dev), name); 582 583 if ((val = getenv(full)) != NULL) { 584 u = strtoul(val, &end, 0); 585 if (end > val && *end == '\0') { 586 if (bootverbose) 587 patm_printf(sc, "%s=%lu\n", full, u); 588 *var = u; 589 } 590 freeenv(val); 591 } 592} 593 594/* 595 * Sysctl handler for internal statistics 596 * 597 * LOCK: unlocked, needed 598 */ 599static int 600patm_sysctl_istats(SYSCTL_HANDLER_ARGS) 601{ 602 struct patm_softc *sc = arg1; 603 uint32_t *ret; 604 int error; 605 606 ret = malloc(sizeof(sc->stats), M_TEMP, M_WAITOK); 607 608 mtx_lock(&sc->mtx); 609 bcopy(&sc->stats, ret, sizeof(sc->stats)); 610 mtx_unlock(&sc->mtx); 611 612 error = SYSCTL_OUT(req, ret, sizeof(sc->stats)); 613 free(ret, M_TEMP); 614 615 return (error); 616} 617 618/* 619 * Sysctl handler for EEPROM 620 * 621 * LOCK: unlocked, needed 622 */ 623static int 624patm_sysctl_eeprom(SYSCTL_HANDLER_ARGS) 625{ 626 struct patm_softc *sc = arg1; 627 void *ret; 628 int error; 629 630 ret = malloc(sizeof(sc->eeprom), M_TEMP, M_WAITOK); 631 632 mtx_lock(&sc->mtx); 633 bcopy(sc->eeprom, ret, sizeof(sc->eeprom)); 634 mtx_unlock(&sc->mtx); 635 636 error = SYSCTL_OUT(req, ret, sizeof(sc->eeprom)); 637 free(ret, M_TEMP); 638 639 return (error); 640} 641 642/* 643 * Read the EEPROM. We assume that this is a XIRCOM 25020 644 */ 645static void 646patm_read_eeprom(struct patm_softc *sc) 647{ 648 u_int gp; 649 uint8_t byte; 650 int i, addr; 651 652 static const uint32_t tab[] = { 653 /* CS transition to reset the chip */ 654 IDT_GP_EECS | IDT_GP_EESCLK, 0, 655 /* read command 0x03 */ 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, IDT_GP_EEDO, 662 IDT_GP_EESCLK | IDT_GP_EEDO, IDT_GP_EEDO, 663 IDT_GP_EESCLK | IDT_GP_EEDO, 0, 664 /* address 0x00 */ 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 IDT_GP_EESCLK, 0, 672 IDT_GP_EESCLK, 0, 673 }; 674 675 /* go to a known state (chip enabled) */ 676 gp = patm_nor_read(sc, IDT_NOR_GP); 677 gp &= ~(IDT_GP_EESCLK | IDT_GP_EECS | IDT_GP_EEDO); 678 679 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) { 680 patm_nor_write(sc, IDT_NOR_GP, gp | tab[i]); 681 DELAY(40); 682 } 683 684 /* read out the prom */ 685 for (addr = 0; addr < 256; addr++) { 686 byte = 0; 687 for (i = 0; i < 8; i++) { 688 byte <<= 1; 689 if (patm_nor_read(sc, IDT_NOR_GP) & IDT_GP_EEDI) 690 byte |= 1; 691 /* rising CLK */ 692 patm_nor_write(sc, IDT_NOR_GP, gp | IDT_GP_EESCLK); 693 DELAY(40); 694 /* falling clock */ 695 patm_nor_write(sc, IDT_NOR_GP, gp); 696 DELAY(40); 697 } 698 sc->eeprom[addr] = byte; 699 } 700} 701 702/* 703 * PHY access read 704 */ 705static int 706patm_phy_readregs(struct ifatm *ifatm, u_int reg, uint8_t *val, u_int *n) 707{ 708 struct patm_softc *sc = ifatm->ifp->if_softc; 709 u_int cnt = *n; 710 711 if (reg >= 0x100) 712 return (EINVAL); 713 714 patm_cmd_wait(sc); 715 while (reg < 0x100 && cnt > 0) { 716 patm_nor_write(sc, IDT_NOR_CMD, IDT_MKCMD_RUTIL(1, 0, reg)); 717 patm_cmd_wait(sc); 718 *val = patm_nor_read(sc, IDT_NOR_D0); 719 patm_debug(sc, PHY, "phy(%02x)=%02x", reg, *val); 720 val++; 721 reg++; 722 cnt--; 723 } 724 *n = *n - cnt; 725 return (0); 726} 727 728/* 729 * Write PHY reg 730 */ 731static int 732patm_phy_writereg(struct ifatm *ifatm, u_int reg, u_int mask, u_int val) 733{ 734 struct patm_softc *sc = ifatm->ifp->if_softc; 735 u_int old, new; 736 737 if (reg >= 0x100) 738 return (EINVAL); 739 740 patm_cmd_wait(sc); 741 patm_nor_write(sc, IDT_NOR_CMD, IDT_MKCMD_RUTIL(1, 0, reg)); 742 patm_cmd_wait(sc); 743 744 old = patm_nor_read(sc, IDT_NOR_D0); 745 new = (old & ~mask) | (val & mask); 746 patm_debug(sc, PHY, "phy(%02x) %02x -> %02x", reg, old, new); 747 748 patm_nor_write(sc, IDT_NOR_D0, new); 749 patm_nor_write(sc, IDT_NOR_CMD, IDT_MKCMD_WUTIL(1, 0, reg)); 750 patm_cmd_wait(sc); 751 752 return (0); 753} 754 755/* 756 * Allocate a large chunk of DMA able memory for the transmit 757 * and receive status queues. We align this to a page boundary 758 * to ensure the alignment. 759 */ 760static int 761patm_sq_init(struct patm_softc *sc) 762{ 763 int error; 764 void *p; 765 766 /* compute size of the two queues */ 767 sc->sq_size = IDT_TSQ_SIZE * IDT_TSQE_SIZE + 768 PATM_RSQ_SIZE * IDT_RSQE_SIZE + 769 IDT_RAWHND_SIZE; 770 771 patm_debug(sc, ATTACH, 772 "allocating status queues (%zu) ...", sc->sq_size); 773 774 /* 775 * allocate tag 776 * Don't use BUS_DMA_ALLOCNOW, because we never need bouncing with 777 * bus_dmamem_alloc() 778 */ 779 error = bus_dma_tag_create(NULL, PATM_SQ_ALIGNMENT, 0, 780 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 781 NULL, NULL, sc->sq_size, 1, sc->sq_size, 782 0, NULL, NULL, &sc->sq_tag); 783 if (error) { 784 patm_printf(sc, "memory DMA tag create %d\n", error); 785 return (error); 786 } 787 788 /* allocate memory */ 789 error = bus_dmamem_alloc(sc->sq_tag, &p, 0, &sc->sq_map); 790 if (error) { 791 patm_printf(sc, "memory DMA alloc %d\n", error); 792 bus_dma_tag_destroy(sc->sq_tag); 793 return (error); 794 } 795 796 /* map it */ 797 sc->tsq_phy = 0x1fff; 798 error = bus_dmamap_load(sc->sq_tag, sc->sq_map, p, 799 sc->sq_size, patm_load_callback, &sc->tsq_phy, BUS_DMA_NOWAIT); 800 if (error) { 801 patm_printf(sc, "memory DMA map load %d\n", error); 802 bus_dmamem_free(sc->sq_tag, p, sc->sq_map); 803 bus_dma_tag_destroy(sc->sq_tag); 804 return (error); 805 } 806 807 /* set queue start */ 808 sc->tsq = p; 809 sc->rsq = (void *)((char *)p + IDT_TSQ_SIZE * IDT_TSQE_SIZE); 810 sc->rsq_phy = sc->tsq_phy + IDT_TSQ_SIZE * IDT_TSQE_SIZE; 811 sc->rawhnd = (void *)((char *)sc->rsq + PATM_RSQ_SIZE * IDT_RSQE_SIZE); 812 sc->rawhnd_phy = sc->rsq_phy + PATM_RSQ_SIZE * IDT_RSQE_SIZE; 813 814 return (0); 815} 816 817/* 818 * Initialize all receive buffer stuff 819 */ 820static int 821patm_rbuf_init(struct patm_softc *sc) 822{ 823 u_int i; 824 int error; 825 826 patm_debug(sc, ATTACH, "allocating Rx buffer resources ..."); 827 /* 828 * Create a tag for small buffers. We allocate these page wise. 829 * Don't use BUS_DMA_ALLOCNOW, because we never need bouncing with 830 * bus_dmamem_alloc() 831 */ 832 if ((error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, 833 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 834 SMBUF_PAGE_SIZE, 1, SMBUF_PAGE_SIZE, 0, 835 NULL, NULL, &sc->sbuf_tag)) != 0) { 836 patm_printf(sc, "sbuf DMA tag create %d\n", error); 837 return (error); 838 } 839 840 error = mbp_create(&sc->sbuf_pool, "patm sbufs", sc->sbuf_tag, 841 SMBUF_MAX_PAGES, SMBUF_PAGE_SIZE, SMBUF_CHUNK_SIZE); 842 if (error != 0) { 843 patm_printf(sc, "smbuf pool create %d\n", error); 844 return (error); 845 } 846 847 error = mbp_create(&sc->vbuf_pool, "patm vbufs", sc->sbuf_tag, 848 VMBUF_MAX_PAGES, SMBUF_PAGE_SIZE, VMBUF_CHUNK_SIZE); 849 if (error != 0) { 850 patm_printf(sc, "vmbuf pool create %d\n", error); 851 return (error); 852 } 853 854 /* 855 * Create a tag for large buffers. 856 * Don't use BUS_DMA_ALLOCNOW, because it makes no sense with multiple 857 * maps using one tag. Rather use BUS_DMA_NOWAIT when loading the map 858 * to prevent EINPROGRESS. 859 */ 860 if ((error = bus_dma_tag_create(NULL, 4, 0, 861 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 862 MCLBYTES, 1, MCLBYTES, 0, 863 NULL, NULL, &sc->lbuf_tag)) != 0) { 864 patm_printf(sc, "lbuf DMA tag create %d\n", error); 865 return (error); 866 } 867 868 if (sc->lbuf_max < IDT_FBQ_SIZE) 869 sc->lbuf_max = LMBUF_MAX; 870 sc->lbufs = malloc(sizeof(sc->lbufs[0]) * sc->lbuf_max, 871 M_DEVBUF, M_ZERO | M_WAITOK); 872 873 SLIST_INIT(&sc->lbuf_free_list); 874 for (i = 0; i < sc->lbuf_max; i++) { 875 struct lmbuf *b = &sc->lbufs[i]; 876 877 error = bus_dmamap_create(sc->lbuf_tag, 0, &b->map); 878 if (error) { 879 /* must deallocate here, because a test for NULL 880 * does not work on most archs */ 881 while (i-- > 0) 882 bus_dmamap_destroy(sc->lbuf_tag, 883 sc->lbufs[i].map); 884 free(sc->lbufs, M_DEVBUF); 885 sc->lbufs = NULL; 886 return (error); 887 } 888 b->handle = i; 889 SLIST_INSERT_HEAD(&sc->lbuf_free_list, b, link); 890 } 891 892 return (0); 893} 894 895/* 896 * Allocate everything needed for the transmission maps. 897 */ 898static int 899patm_txmap_init(struct patm_softc *sc) 900{ 901 int error; 902 struct patm_txmap *map; 903 904 /* get transmission tag */ 905 error = bus_dma_tag_create(NULL, 1, 0, 906 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 907 NULL, NULL, 65536, IDT_SCQ_SIZE - 1, 65536, 908 0, NULL, NULL, &sc->tx_tag); 909 if (error) { 910 patm_printf(sc, "cannot allocate TX tag %d\n", error); 911 return (error); 912 } 913 914 if ((sc->tx_mapzone = uma_zcreate("PATM tx maps", 915 sizeof(struct patm_txmap), NULL, NULL, NULL, NULL, 916 UMA_ALIGN_PTR, 0)) == NULL) 917 return (ENOMEM); 918 919 if (sc->tx_maxmaps < PATM_CFG_TXMAPS_MAX) 920 sc->tx_maxmaps = PATM_CFG_TXMAPS_MAX; 921 sc->tx_nmaps = PATM_CFG_TXMAPS_INIT; 922 923 for (sc->tx_nmaps = 0; sc->tx_nmaps < PATM_CFG_TXMAPS_INIT; 924 sc->tx_nmaps++) { 925 map = uma_zalloc(sc->tx_mapzone, M_WAITOK); 926 error = bus_dmamap_create(sc->tx_tag, 0, &map->map); 927 if (error) { 928 uma_zfree(sc->tx_mapzone, map); 929 return (ENOMEM); 930 } 931 SLIST_INSERT_HEAD(&sc->tx_maps_free, map, link); 932 } 933 934 return (0); 935} 936 937#ifdef PATM_DEBUG 938 939/* 940 * Sysctl handler for REGS 941 * 942 * LOCK: unlocked, needed 943 */ 944static int 945patm_sysctl_regs(SYSCTL_HANDLER_ARGS) 946{ 947 struct patm_softc *sc = arg1; 948 uint32_t *ret; 949 int error, i; 950 951 ret = malloc(IDT_NOR_END, M_TEMP, M_WAITOK); 952 953 mtx_lock(&sc->mtx); 954 for (i = 0; i < IDT_NOR_END; i += 4) 955 ret[i / 4] = patm_nor_read(sc, i); 956 mtx_unlock(&sc->mtx); 957 958 error = SYSCTL_OUT(req, ret, IDT_NOR_END); 959 free(ret, M_TEMP); 960 961 return (error); 962} 963 964/* 965 * Sysctl handler for TSQ 966 * 967 * LOCK: unlocked, needed 968 */ 969static int 970patm_sysctl_tsq(SYSCTL_HANDLER_ARGS) 971{ 972 struct patm_softc *sc = arg1; 973 void *ret; 974 int error; 975 976 ret = malloc(IDT_TSQ_SIZE * IDT_TSQE_SIZE, M_TEMP, M_WAITOK); 977 978 mtx_lock(&sc->mtx); 979 memcpy(ret, sc->tsq, IDT_TSQ_SIZE * IDT_TSQE_SIZE); 980 mtx_unlock(&sc->mtx); 981 982 error = SYSCTL_OUT(req, ret, IDT_TSQ_SIZE * IDT_TSQE_SIZE); 983 free(ret, M_TEMP); 984 985 return (error); 986} 987 988/* 989 * debugging 990 */ 991static struct patm_softc * 992patm_dump_unit(u_int unit) 993{ 994 devclass_t dc; 995 struct patm_softc *sc; 996 997 dc = devclass_find("patm"); 998 if (dc == NULL) { 999 printf("%s: can't find devclass\n", __func__); 1000 return (NULL); 1001 } 1002 sc = devclass_get_softc(dc, unit); 1003 if (sc == NULL) { 1004 printf("%s: invalid unit number: %d\n", __func__, unit); 1005 return (NULL); 1006 } 1007 return (sc); 1008} 1009 1010int 1011patm_dump_vc(u_int unit, u_int vc) 1012{ 1013 struct patm_softc *sc; 1014 uint32_t tct[8]; 1015 uint32_t rct[4]; 1016 uint32_t scd[12]; 1017 u_int i; 1018 1019 if ((sc = patm_dump_unit(unit)) == NULL) 1020 return (0); 1021 1022 for (i = 0; i < 8; i++) 1023 tct[i] = patm_sram_read(sc, vc * 8 + i); 1024 for (i = 0; i < 4; i++) 1025 rct[i] = patm_sram_read(sc, sc->mmap->rct + vc * 4 + i); 1026 for (i = 0; i < 12; i++) 1027 scd[i] = patm_sram_read(sc, (tct[0] & 0x7ffff) + i); 1028 1029 printf("TCT%3u: %08x %08x %08x %08x %08x %08x %08x %08x\n", vc, 1030 tct[0], tct[1], tct[2], tct[3], tct[4], tct[5], tct[6], tct[7]); 1031 printf("RCT%3u: %08x %08x %08x %08x\n", vc, 1032 rct[0], rct[1], rct[2], rct[3]); 1033 printf("SCD%3u: %08x %08x %08x %08x %08x %08x %08x %08x\n", vc, 1034 scd[0], scd[1], scd[2], scd[3], scd[4], scd[5], scd[6], scd[7]); 1035 printf(" %08x %08x %08x %08x\n", 1036 scd[8], scd[9], scd[10], scd[11]); 1037 1038 return (0); 1039} 1040 1041int 1042patm_dump_regs(u_int unit) 1043{ 1044 struct patm_softc *sc; 1045 u_int i; 1046 1047 if ((sc = patm_dump_unit(unit)) == NULL) 1048 return (0); 1049 1050 for (i = 0; i <= IDT_NOR_DNOW; i += 4) 1051 printf("%x: %08x\n", i, patm_nor_read(sc, i)); 1052 1053 return (0); 1054} 1055 1056int 1057patm_dump_sram(u_int unit, u_int from, u_int words) 1058{ 1059 struct patm_softc *sc; 1060 u_int i; 1061 1062 if ((sc = patm_dump_unit(unit)) == NULL) 1063 return (0); 1064 1065 for (i = 0; i < words; i++) { 1066 if (i % 8 == 0) 1067 printf("%05x:", from + i); 1068 printf(" %08x", patm_sram_read(sc, from + i)); 1069 if (i % 8 == 7) 1070 printf("\n"); 1071 } 1072 if (i % 8 != 0) 1073 printf("\n"); 1074 return (0); 1075} 1076#endif
|