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