1 /* $NetBSD: xirc.c,v 1.16 2006/03/25 23:23:26 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1999, 2000, 2004 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center and by Charles M. Hannum. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 #include <sys/cdefs.h> 41 __KERNEL_RCSID(0, "$NetBSD: xirc.c,v 1.16 2006/03/25 23:23:26 thorpej Exp $"); 42 43 #include "opt_inet.h" 44 #include "opt_ns.h" 45 #include "bpfilter.h" 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/mbuf.h> 50 #include <sys/socket.h> 51 #include <sys/ioctl.h> 52 #include <sys/errno.h> 53 #include <sys/syslog.h> 54 #include <sys/select.h> 55 #include <sys/tty.h> 56 #include <sys/device.h> 57 58 #include <net/if.h> 59 #include <net/if_dl.h> 60 #include <net/if_ether.h> 61 #include <net/if_media.h> 62 63 #ifdef INET 64 #include <netinet/in.h> 65 #include <netinet/in_systm.h> 66 #include <netinet/in_var.h> 67 #include <netinet/ip.h> 68 #include <netinet/if_inarp.h> 69 #endif 70 71 #ifdef NS 72 #include <netns/ns.h> 73 #include <netns/ns_if.h> 74 #endif 75 76 #if NBPFILTER > 0 77 #include <net/bpf.h> 78 #include <net/bpfdesc.h> 79 #endif 80 81 #include <machine/intr.h> 82 #include <machine/bus.h> 83 84 #include <dev/pcmcia/pcmciareg.h> 85 #include <dev/pcmcia/pcmciavar.h> 86 #include <dev/pcmcia/pcmciadevs.h> 87 88 #include "xirc.h" 89 90 #if NCOM_XIRC > 0 91 #include <dev/ic/comreg.h> 92 #include <dev/ic/comvar.h> 93 #endif 94 95 #if NXI_XIRC > 0 96 #include <dev/mii/mii.h> 97 #include <dev/mii/miivar.h> 98 99 #include <dev/pcmcia/if_xivar.h> 100 #endif 101 #include <dev/pcmcia/if_xireg.h> 102 103 struct xirc_softc { 104 struct device sc_dev; /* generic device glue */ 105 106 struct pcmcia_function *sc_pf; /* our PCMCIA function */ 107 void *sc_ih; /* interrupt handle */ 108 109 u_int16_t sc_id; 110 u_int8_t sc_mako_intmask; 111 int sc_chipset; 112 113 /* 114 * Data for the Modem portion. 115 */ 116 struct device *sc_modem; 117 struct pcmcia_io_handle sc_modem_pcioh; 118 int sc_modem_io_window; 119 120 /* 121 * Data for the Ethernet portion. 122 */ 123 struct device *sc_ethernet; 124 struct pcmcia_io_handle sc_ethernet_pcioh; 125 int sc_ethernet_io_window; 126 127 int sc_flags; 128 #define XIRC_MODEM_MAPPED 0x01 129 #define XIRC_ETHERNET_MAPPED 0x02 130 #define XIRC_MODEM_ENABLED 0x04 131 #define XIRC_ETHERNET_ENABLED 0x08 132 #define XIRC_MODEM_ALLOCED 0x10 133 #define XIRC_ETHERNET_ALLOCED 0x20 134 }; 135 136 int xirc_match(struct device *, struct cfdata *, void *); 137 void xirc_attach(struct device *, struct device *, void *); 138 int xirc_detach(struct device *, int); 139 int xirc_activate(struct device *, enum devact); 140 141 CFATTACH_DECL(xirc, sizeof(struct xirc_softc), 142 xirc_match, xirc_attach, xirc_detach, xirc_activate); 143 144 int xirc_print(void *, const char *); 145 146 int xirc_manfid_ciscallback(struct pcmcia_tuple *, void *); 147 struct pcmcia_config_entry * 148 xirc_mako_alloc(struct xirc_softc *); 149 struct pcmcia_config_entry * 150 xirc_dingo_alloc_modem(struct xirc_softc *); 151 struct pcmcia_config_entry * 152 xirc_dingo_alloc_ethernet(struct xirc_softc *); 153 154 int xirc_enable(struct xirc_softc *, int, int); 155 void xirc_disable(struct xirc_softc *, int, int); 156 157 int xirc_intr(void *); 158 159 int 160 xirc_match(parent, match, aux) 161 struct device *parent; 162 struct cfdata *match; 163 void *aux; 164 { 165 struct pcmcia_attach_args *pa = aux; 166 167 /* XXX Toshiba, Accton */ 168 169 if (pa->manufacturer == PCMCIA_VENDOR_COMPAQ2 && 170 pa->product == PCMCIA_PRODUCT_COMPAQ2_CPQ_10_100) 171 return (1); 172 173 if (pa->manufacturer == PCMCIA_VENDOR_INTEL && 174 pa->product == PCMCIA_PRODUCT_INTEL_EEPRO100) 175 return (1); 176 177 if (pa->manufacturer == PCMCIA_VENDOR_XIRCOM && 178 (pa->product & (XIMEDIA_ETHER << 8)) != 0) 179 return (2); 180 181 return (0); 182 } 183 184 void 185 xirc_attach(parent, self, aux) 186 struct device *parent, *self; 187 void *aux; 188 { 189 struct xirc_softc *sc = (void *)self; 190 struct pcmcia_attach_args *pa = aux; 191 struct pcmcia_config_entry *cfe; 192 int rv; 193 int error; 194 195 sc->sc_pf = pa->pf; 196 197 pcmcia_socket_enable(parent); 198 rv = pcmcia_scan_cis(parent, xirc_manfid_ciscallback, &sc->sc_id); 199 pcmcia_socket_disable(parent); 200 if (!rv) { 201 aprint_error("%s: failed to find ID\n", self->dv_xname); 202 return; 203 } 204 205 switch (sc->sc_id & 0x100f) { 206 case 0x0001: /* CE */ 207 case 0x0002: /* CE2 */ 208 sc->sc_chipset = XI_CHIPSET_SCIPPER; 209 break; 210 case 0x0003: /* CE3 */ 211 sc->sc_chipset = XI_CHIPSET_MOHAWK; 212 break; 213 case 0x1001: 214 case 0x1002: 215 case 0x1003: 216 case 0x1004: 217 sc->sc_chipset = XI_CHIPSET_SCIPPER; 218 break; 219 case 0x1005: 220 sc->sc_chipset = XI_CHIPSET_MOHAWK; 221 break; 222 case 0x1006: 223 case 0x1007: 224 sc->sc_chipset = XI_CHIPSET_DINGO; 225 break; 226 default: 227 aprint_error("%s: unknown ID %04x\n", self->dv_xname, 228 sc->sc_id); 229 return; 230 } 231 232 aprint_normal("%s: id=%04x\n", self->dv_xname, sc->sc_id); 233 234 if (sc->sc_id & (XIMEDIA_MODEM << 8)) { 235 if (sc->sc_chipset >= XI_CHIPSET_DINGO) { 236 cfe = xirc_dingo_alloc_modem(sc); 237 if (cfe && sc->sc_id & (XIMEDIA_ETHER << 8)) { 238 if (!xirc_dingo_alloc_ethernet(sc)) { 239 pcmcia_io_free(pa->pf, 240 &sc->sc_modem_pcioh); 241 cfe = 0; 242 } 243 } 244 } else 245 cfe = xirc_mako_alloc(sc); 246 } else 247 cfe = xirc_dingo_alloc_ethernet(sc); 248 if (!cfe) { 249 aprint_error("%s: failed to allocate I/O space\n", 250 self->dv_xname); 251 goto fail; 252 } 253 254 /* Enable the card. */ 255 pcmcia_function_init(pa->pf, cfe); 256 257 if (sc->sc_id & (XIMEDIA_MODEM << 8)) { 258 if (pcmcia_io_map(sc->sc_pf, PCMCIA_WIDTH_IO8, 259 &sc->sc_modem_pcioh, &sc->sc_modem_io_window)) { 260 aprint_error("%s: unable to map I/O space\n", 261 self->dv_xname); 262 goto fail; 263 } 264 sc->sc_flags |= XIRC_MODEM_MAPPED; 265 } 266 267 if (sc->sc_id & (XIMEDIA_ETHER << 8)) { 268 if (pcmcia_io_map(sc->sc_pf, PCMCIA_WIDTH_AUTO, 269 &sc->sc_ethernet_pcioh, &sc->sc_ethernet_io_window)) { 270 aprint_error("%s: unable to map I/O space\n", 271 self->dv_xname); 272 goto fail; 273 } 274 sc->sc_flags |= XIRC_ETHERNET_MAPPED; 275 } 276 277 error = xirc_enable(sc, XIRC_MODEM_ENABLED|XIRC_ETHERNET_ENABLED, 278 sc->sc_id & (XIMEDIA_MODEM|XIMEDIA_ETHER)); 279 if (error) 280 goto fail; 281 282 sc->sc_mako_intmask = 0xee; 283 284 if (sc->sc_id & (XIMEDIA_MODEM << 8)) 285 /*XXXUNCONST*/ 286 sc->sc_modem = config_found(self, __UNCONST("com"), xirc_print); 287 if (sc->sc_id & (XIMEDIA_ETHER << 8)) 288 /*XXXUNCONST*/ 289 sc->sc_ethernet = config_found(self, __UNCONST("xi"), 290 xirc_print); 291 292 xirc_disable(sc, XIRC_MODEM_ENABLED|XIRC_ETHERNET_ENABLED, 293 sc->sc_id & (XIMEDIA_MODEM|XIMEDIA_ETHER)); 294 return; 295 296 fail: 297 /* I/O spaces will be freed by detach. */ 298 ; 299 } 300 301 int 302 xirc_manfid_ciscallback(tuple, arg) 303 struct pcmcia_tuple *tuple; 304 void *arg; 305 { 306 u_int16_t *id = arg; 307 308 if (tuple->code != PCMCIA_CISTPL_MANFID) 309 return (0); 310 311 if (tuple->length < 5) 312 return (0); 313 314 *id = (pcmcia_tuple_read_1(tuple, 3) << 8) | 315 pcmcia_tuple_read_1(tuple, 4); 316 return (1); 317 } 318 319 struct pcmcia_config_entry * 320 xirc_mako_alloc(sc) 321 struct xirc_softc *sc; 322 { 323 struct pcmcia_config_entry *cfe; 324 325 SIMPLEQ_FOREACH(cfe, &sc->sc_pf->cfe_head, cfe_list) { 326 if (cfe->num_iospace != 1) 327 continue; 328 329 if (pcmcia_io_alloc(sc->sc_pf, cfe->iospace[0].start, 330 cfe->iospace[0].length, cfe->iospace[0].length, 331 &sc->sc_modem_pcioh)) 332 continue; 333 334 cfe->iospace[1].start = cfe->iospace[0].start+8; 335 cfe->iospace[1].length = 18; 336 if (pcmcia_io_alloc(sc->sc_pf, cfe->iospace[1].start, 337 cfe->iospace[1].length, 0x20, 338 &sc->sc_ethernet_pcioh)) { 339 cfe->iospace[1].start = cfe->iospace[0].start-24; 340 if (pcmcia_io_alloc(sc->sc_pf, cfe->iospace[1].start, 341 cfe->iospace[1].length, 0x20, 342 &sc->sc_ethernet_pcioh)) 343 continue; 344 } 345 346 /* Found one! */ 347 sc->sc_flags |= XIRC_MODEM_ALLOCED; 348 sc->sc_flags |= XIRC_ETHERNET_ALLOCED; 349 return (cfe); 350 } 351 352 return (0); 353 } 354 355 struct pcmcia_config_entry * 356 xirc_dingo_alloc_modem(sc) 357 struct xirc_softc *sc; 358 { 359 struct pcmcia_config_entry *cfe; 360 361 SIMPLEQ_FOREACH(cfe, &sc->sc_pf->cfe_head, cfe_list) { 362 if (cfe->num_iospace != 1) 363 continue; 364 365 if (pcmcia_io_alloc(sc->sc_pf, cfe->iospace[0].start, 366 cfe->iospace[0].length, cfe->iospace[0].length, 367 &sc->sc_modem_pcioh)) 368 continue; 369 370 /* Found one! */ 371 sc->sc_flags |= XIRC_MODEM_ALLOCED; 372 return (cfe); 373 } 374 375 return (0); 376 } 377 378 struct pcmcia_config_entry * 379 xirc_dingo_alloc_ethernet(sc) 380 struct xirc_softc *sc; 381 { 382 struct pcmcia_config_entry *cfe; 383 bus_addr_t port; 384 385 for (port = 0x300; port < 0x400; port += XI_IOSIZE) { 386 if (pcmcia_io_alloc(sc->sc_pf, port, 387 XI_IOSIZE, XI_IOSIZE, &sc->sc_ethernet_pcioh)) 388 continue; 389 390 /* Found one for the ethernet! */ 391 sc->sc_flags |= XIRC_ETHERNET_ALLOCED; 392 cfe = SIMPLEQ_FIRST(&sc->sc_pf->cfe_head); 393 return (cfe); 394 } 395 396 return (0); 397 } 398 399 int 400 xirc_print(aux, pnp) 401 void *aux; 402 const char *pnp; 403 { 404 const char *name = aux; 405 406 if (pnp) 407 aprint_normal("%s at %s(*)", name, pnp); 408 409 return (UNCONF); 410 } 411 412 int 413 xirc_detach(self, flags) 414 struct device *self; 415 int flags; 416 { 417 struct xirc_softc *sc = (void *)self; 418 int rv; 419 420 if (sc->sc_ethernet != NULL) { 421 rv = config_detach(sc->sc_ethernet, flags); 422 if (rv != 0) 423 return (rv); 424 sc->sc_ethernet = NULL; 425 } 426 427 if (sc->sc_modem != NULL) { 428 rv = config_detach(sc->sc_modem, flags); 429 if (rv != 0) 430 return (rv); 431 sc->sc_modem = NULL; 432 } 433 434 /* Unmap our i/o windows. */ 435 if (sc->sc_flags & XIRC_ETHERNET_MAPPED) 436 pcmcia_io_unmap(sc->sc_pf, sc->sc_ethernet_io_window); 437 if (sc->sc_flags & XIRC_MODEM_MAPPED) 438 pcmcia_io_unmap(sc->sc_pf, sc->sc_modem_io_window); 439 440 /* Free our i/o spaces. */ 441 if (sc->sc_flags & XIRC_ETHERNET_ALLOCED) 442 pcmcia_io_free(sc->sc_pf, &sc->sc_ethernet_pcioh); 443 if (sc->sc_flags & XIRC_MODEM_ALLOCED) 444 pcmcia_io_free(sc->sc_pf, &sc->sc_modem_pcioh); 445 sc->sc_flags = 0; 446 447 return (0); 448 } 449 450 int 451 xirc_activate(self, act) 452 struct device *self; 453 enum devact act; 454 { 455 struct xirc_softc *sc = (void *)self; 456 int s, rv = 0; 457 458 s = splhigh(); 459 switch (act) { 460 case DVACT_ACTIVATE: 461 rv = EOPNOTSUPP; 462 break; 463 464 case DVACT_DEACTIVATE: 465 if (sc->sc_ethernet != NULL) { 466 rv = config_deactivate(sc->sc_ethernet); 467 if (rv != 0) 468 goto out; 469 } 470 471 if (sc->sc_modem != NULL) { 472 rv = config_deactivate(sc->sc_modem); 473 if (rv != 0) 474 goto out; 475 } 476 break; 477 } 478 out: 479 splx(s); 480 return (rv); 481 } 482 483 int 484 xirc_intr(arg) 485 void *arg; 486 { 487 struct xirc_softc *sc = arg; 488 int rval = 0; 489 490 #if NCOM_XIRC > 0 491 if (sc->sc_modem != NULL && 492 (sc->sc_flags & XIRC_MODEM_ENABLED) != 0) 493 rval |= comintr(sc->sc_modem); 494 #endif 495 496 #if NXI_XIRC > 0 497 if (sc->sc_ethernet != NULL && 498 (sc->sc_flags & XIRC_ETHERNET_ENABLED) != 0) 499 rval |= xi_intr(sc->sc_ethernet); 500 #endif 501 502 return (rval); 503 } 504 505 int 506 xirc_enable(sc, flag, media) 507 struct xirc_softc *sc; 508 int flag, media; 509 { 510 int error; 511 512 if ((sc->sc_flags & flag) == flag) { 513 printf("%s: already enabled\n", sc->sc_dev.dv_xname); 514 return (0); 515 } 516 517 if ((sc->sc_flags & (XIRC_MODEM_ENABLED|XIRC_ETHERNET_ENABLED)) != 0) { 518 sc->sc_flags |= flag; 519 return (0); 520 } 521 522 /* 523 * Establish our interrupt handler. 524 * 525 * XXX Note, we establish this at IPL_NET. This is suboptimal 526 * XXX the Modem portion, but is necessary to make the Ethernet 527 * XXX portion have the correct interrupt level semantics. 528 * 529 * XXX Eventually we should use the `enabled' bits in the 530 * XXX flags word to determine which level we should be at. 531 */ 532 sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET, xirc_intr, sc); 533 if (!sc->sc_ih) 534 return (EIO); 535 536 error = pcmcia_function_enable(sc->sc_pf); 537 if (error) { 538 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); 539 sc->sc_ih = 0; 540 return (error); 541 } 542 543 sc->sc_flags |= flag; 544 545 if (sc->sc_chipset < XI_CHIPSET_DINGO && 546 sc->sc_id & (XIMEDIA_MODEM << 8)) { 547 sc->sc_mako_intmask |= media; 548 bus_space_write_1(sc->sc_ethernet_pcioh.iot, 549 sc->sc_ethernet_pcioh.ioh, 0x10, sc->sc_mako_intmask); 550 } 551 552 return (0); 553 } 554 555 void 556 xirc_disable(sc, flag, media) 557 struct xirc_softc *sc; 558 int flag, media; 559 { 560 561 if ((sc->sc_flags & flag) == 0) { 562 printf("%s: already disabled\n", sc->sc_dev.dv_xname); 563 return; 564 } 565 566 if (sc->sc_chipset < XI_CHIPSET_DINGO && 567 sc->sc_id & (XIMEDIA_MODEM << 8)) { 568 sc->sc_mako_intmask &= ~media; 569 bus_space_write_1(sc->sc_ethernet_pcioh.iot, 570 sc->sc_ethernet_pcioh.ioh, 0x10, sc->sc_mako_intmask); 571 } 572 573 sc->sc_flags &= ~flag; 574 if ((sc->sc_flags & (XIRC_MODEM_ENABLED|XIRC_ETHERNET_ENABLED)) != 0) 575 return; 576 577 pcmcia_function_disable(sc->sc_pf); 578 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); 579 sc->sc_ih = 0; 580 } 581 582 /****** Here begins the com attachment code. ******/ 583 584 #if NCOM_XIRC > 0 585 int com_xirc_match(struct device *, struct cfdata *, void *); 586 void com_xirc_attach(struct device *, struct device *, void *); 587 int com_xirc_detach(struct device *, int); 588 589 /* No xirc-specific goo in the softc; it's all in the parent. */ 590 CFATTACH_DECL(com_xirc, sizeof(struct com_softc), 591 com_xirc_match, com_xirc_attach, com_detach, com_activate); 592 593 int com_xirc_enable(struct com_softc *); 594 void com_xirc_disable(struct com_softc *); 595 596 int 597 com_xirc_match(parent, match, aux) 598 struct device *parent; 599 struct cfdata *match; 600 void *aux; 601 { 602 extern struct cfdriver com_cd; 603 const char *name = aux; 604 605 if (strcmp(name, com_cd.cd_name) == 0) 606 return (1); 607 608 return (0); 609 } 610 611 void 612 com_xirc_attach(parent, self, aux) 613 struct device *parent, *self; 614 void *aux; 615 { 616 struct com_softc *sc = (void *)self; 617 struct xirc_softc *msc = (void *)parent; 618 619 aprint_normal("\n"); 620 621 sc->sc_iot = msc->sc_modem_pcioh.iot; 622 sc->sc_ioh = msc->sc_modem_pcioh.ioh; 623 624 sc->enabled = 1; 625 626 sc->sc_iobase = -1; 627 sc->sc_frequency = COM_FREQ; 628 629 sc->enable = com_xirc_enable; 630 sc->disable = com_xirc_disable; 631 632 aprint_normal("%s", self->dv_xname); 633 634 com_attach_subr(sc); 635 636 sc->enabled = 0; 637 } 638 639 int 640 com_xirc_enable(sc) 641 struct com_softc *sc; 642 { 643 struct xirc_softc *msc = 644 (struct xirc_softc *)device_parent(&sc->sc_dev); 645 646 return (xirc_enable(msc, XIRC_MODEM_ENABLED, XIMEDIA_MODEM)); 647 } 648 649 void 650 com_xirc_disable(sc) 651 struct com_softc *sc; 652 { 653 struct xirc_softc *msc = 654 (struct xirc_softc *)device_parent(&sc->sc_dev); 655 656 xirc_disable(msc, XIRC_MODEM_ENABLED, XIMEDIA_MODEM); 657 } 658 659 #endif /* NCOM_XIRC > 0 */ 660 661 /****** Here begins the xi attachment code. ******/ 662 663 #if NXI_XIRC > 0 664 int xi_xirc_match(struct device *, struct cfdata *, void *); 665 void xi_xirc_attach(struct device *, struct device *, void *); 666 667 /* No xirc-specific goo in the softc; it's all in the parent. */ 668 CFATTACH_DECL(xi_xirc, sizeof(struct xi_softc), 669 xi_xirc_match, xi_xirc_attach, xi_detach, xi_activate); 670 671 int xi_xirc_enable(struct xi_softc *); 672 void xi_xirc_disable(struct xi_softc *); 673 int xi_xirc_lan_nid_ciscallback(struct pcmcia_tuple *, void *); 674 675 int 676 xi_xirc_match(parent, match, aux) 677 struct device *parent; 678 struct cfdata *match; 679 void *aux; 680 { 681 extern struct cfdriver xi_cd; 682 const char *name = aux; 683 684 if (strcmp(name, xi_cd.cd_name) == 0) 685 return (1); 686 687 return (0); 688 } 689 690 void 691 xi_xirc_attach(parent, self, aux) 692 struct device *parent, *self; 693 void *aux; 694 { 695 struct xi_softc *sc = (void *)self; 696 struct xirc_softc *msc = (void *)parent; 697 u_int8_t myla[ETHER_ADDR_LEN]; 698 699 aprint_normal("\n"); 700 701 sc->sc_bst = msc->sc_ethernet_pcioh.iot; 702 sc->sc_bsh = msc->sc_ethernet_pcioh.ioh; 703 704 sc->sc_chipset = msc->sc_chipset; 705 706 sc->sc_enable = xi_xirc_enable; 707 sc->sc_disable = xi_xirc_disable; 708 709 if (!pcmcia_scan_cis(device_parent(&msc->sc_dev), 710 xi_xirc_lan_nid_ciscallback, myla)) { 711 aprint_error("%s: can't find MAC address\n", self->dv_xname); 712 return; 713 } 714 715 /* Perform generic initialization. */ 716 xi_attach(sc, myla); 717 } 718 719 int 720 xi_xirc_enable(sc) 721 struct xi_softc *sc; 722 { 723 struct xirc_softc *msc = 724 (struct xirc_softc *)device_parent(&sc->sc_dev); 725 726 return (xirc_enable(msc, XIRC_ETHERNET_ENABLED, XIMEDIA_ETHER)); 727 } 728 729 void 730 xi_xirc_disable(sc) 731 struct xi_softc *sc; 732 { 733 struct xirc_softc *msc = 734 (struct xirc_softc *)device_parent(&sc->sc_dev); 735 736 xirc_disable(msc, XIRC_ETHERNET_ENABLED, XIMEDIA_ETHER); 737 } 738 739 int 740 xi_xirc_lan_nid_ciscallback(tuple, arg) 741 struct pcmcia_tuple *tuple; 742 void *arg; 743 { 744 u_int8_t *myla = arg; 745 int i; 746 747 if (tuple->length < 2) 748 return (0); 749 750 switch (tuple->code) { 751 case PCMCIA_CISTPL_FUNCE: 752 switch (pcmcia_tuple_read_1(tuple, 0)) { 753 case PCMCIA_TPLFE_TYPE_LAN_NID: 754 if (pcmcia_tuple_read_1(tuple, 1) != ETHER_ADDR_LEN) 755 return (0); 756 for (i = 0; i < ETHER_ADDR_LEN; i++) 757 myla[i] = pcmcia_tuple_read_1(tuple, i + 2); 758 return (1); 759 760 case 0x02: 761 /* 762 * Not sure about this, I don't have a CE2 763 * that puts the ethernet addr here. 764 */ 765 if (pcmcia_tuple_read_1(tuple, 1) != 0x01 || 766 pcmcia_tuple_read_1(tuple, 2) != ETHER_ADDR_LEN) 767 return (0); 768 for (i = 0; i < ETHER_ADDR_LEN; i++) 769 myla[i] = pcmcia_tuple_read_1(tuple, i + 3); 770 return (1); 771 } 772 773 case 0x89: 774 if (pcmcia_tuple_read_1(tuple, 0) != 0x04 || 775 pcmcia_tuple_read_1(tuple, 1) != ETHER_ADDR_LEN) 776 return (0); 777 for (i = 0; i < ETHER_ADDR_LEN; i++) 778 myla[i] = pcmcia_tuple_read_1(tuple, i + 2); 779 return (1); 780 } 781 782 return (0); 783 } 784 785 #endif /* NXI_XIRC > 0 */ 786