1 /* $NetBSD: if_ie.c,v 1.62 2017/02/22 09:45:16 nonaka Exp $ */ 2 3 /*- 4 * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. 5 * Copyright (c) 1992, 1993, University of Vermont and State 6 * Agricultural College. 7 * Copyright (c) 1992, 1993, Garrett A. Wollman. 8 * 9 * Portions: 10 * Copyright (c) 1994, 1995, Rafal K. Boni 11 * Copyright (c) 1990, 1991, William F. Jolitz 12 * Copyright (c) 1990, The Regents of the University of California 13 * 14 * All rights reserved. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. All advertising materials mentioning features or use of this software 25 * must display the following acknowledgement: 26 * This product includes software developed by Charles M. Hannum, by the 27 * University of Vermont and State Agricultural College and Garrett A. 28 * Wollman, by William F. Jolitz, and by the University of California, 29 * Berkeley, Lawrence Berkeley Laboratory, and its contributors. 30 * 4. Neither the names of the Universities nor the names of the authors 31 * may be used to endorse or promote products derived from this software 32 * without specific prior written permission. 33 * 34 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 35 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 36 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37 * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR AUTHORS BE LIABLE 38 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 40 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 41 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 42 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 43 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 44 * SUCH DAMAGE. 45 */ 46 47 /* 48 * Intel 82586 Ethernet chip 49 * Register, bit, and structure definitions. 50 * 51 * Original StarLAN driver written by Garrett Wollman with reference to the 52 * Clarkson Packet Driver code for this chip written by Russ Nelson and others. 53 * 54 * BPF support code taken from hpdev/if_le.c, supplied with tcpdump. 55 * 56 * 3C507 support is loosely based on code donated to NetBSD by Rafal Boni. 57 * 58 * Majorly cleaned up and 3C507 code merged by Charles Hannum. 59 * 60 * Converted to SUN ie driver by Charles D. Cranor, 61 * October 1994, January 1995. 62 * This sun version based on i386 version 1.30. 63 * [ see sys/dev/isa/if_ie.c ] 64 */ 65 66 /* 67 * The i82586 is a very painful chip, found in sun3's, sun-4/100's 68 * sun-4/200's, and VME based suns. The byte order is all wrong for a 69 * SUN, making life difficult. Programming this chip is mostly the same, 70 * but certain details differ from system to system. This driver is 71 * written so that different "ie" interfaces can be controled by the same 72 * driver. 73 */ 74 75 /* 76 Mode of operation: 77 78 We run the 82586 in a standard Ethernet mode. We keep NFRAMES 79 received frame descriptors around for the receiver to use, and 80 NRXBUF associated receive buffer descriptors, both in a circular 81 list. Whenever a frame is received, we rotate both lists as 82 necessary. (The 586 treats both lists as a simple queue.) We also 83 keep a transmit command around so that packets can be sent off 84 quickly. 85 86 We configure the adapter in AL-LOC = 1 mode, which means that the 87 Ethernet/802.3 MAC header is placed at the beginning of the receive 88 buffer rather than being split off into various fields in the RFD. 89 This also means that we must include this header in the transmit 90 buffer as well. 91 92 By convention, all transmit commands, and only transmit commands, 93 shall have the I (IE_CMD_INTR) bit set in the command. This way, 94 when an interrupt arrives at ieintr(), it is immediately possible 95 to tell what precisely caused it. ANY OTHER command-sending 96 routines should run at splnet(), and should post an acknowledgement 97 to every interrupt they generate. 98 */ 99 100 #include <sys/cdefs.h> 101 __KERNEL_RCSID(0, "$NetBSD: if_ie.c,v 1.62 2017/02/22 09:45:16 nonaka Exp $"); 102 103 #include "opt_inet.h" 104 #include "opt_ns.h" 105 106 #include <sys/param.h> 107 #include <sys/systm.h> 108 #include <sys/mbuf.h> 109 #include <sys/buf.h> 110 #include <sys/protosw.h> 111 #include <sys/socket.h> 112 #include <sys/ioctl.h> 113 #include <sys/errno.h> 114 #include <sys/syslog.h> 115 #include <sys/device.h> 116 117 #include <net/if.h> 118 #include <net/if_types.h> 119 #include <net/if_dl.h> 120 #include <net/if_ether.h> 121 122 #include <net/bpf.h> 123 #include <net/bpfdesc.h> 124 125 #ifdef INET 126 #include <netinet/in.h> 127 #include <netinet/in_systm.h> 128 #include <netinet/in_var.h> 129 #include <netinet/ip.h> 130 #include <netinet/if_inarp.h> 131 #endif 132 133 #include <uvm/uvm_extern.h> 134 135 #include <machine/autoconf.h> 136 #include <machine/cpu.h> 137 #include <machine/pmap.h> 138 139 /* 140 * ugly byte-order hack for SUNs 141 */ 142 143 #define XSWAP(y) ( (((y) & 0xff00) >> 8) | (((y) & 0xff) << 8) ) 144 #define SWAP(x) ((u_short)(XSWAP((u_short)(x)))) 145 146 #include "i82586.h" 147 #include "if_iereg.h" 148 #include "if_ievar.h" 149 150 /* #define IEDEBUG XXX */ 151 152 /* 153 * IED: ie debug flags 154 */ 155 156 #define IED_RINT 0x01 157 #define IED_TINT 0x02 158 #define IED_RNR 0x04 159 #define IED_CNA 0x08 160 #define IED_READFRAME 0x10 161 #define IED_ENQ 0x20 162 #define IED_XMIT 0x40 163 #define IED_ALL 0x7f 164 165 #ifdef IEDEBUG 166 #define inline /* not */ 167 void print_rbd(volatile struct ie_recv_buf_desc *); 168 int in_ierint = 0; 169 int in_ietint = 0; 170 int ie_debug_flags = 0; 171 #endif 172 173 /* XXX - Skip TDR for now - it always complains... */ 174 int ie_run_tdr = 0; 175 176 static void iewatchdog(struct ifnet *); 177 static int ieinit(struct ie_softc *); 178 static int ieioctl(struct ifnet *, u_long, void *); 179 static void iestart(struct ifnet *); 180 static void iereset(struct ie_softc *); 181 static int ie_setupram(struct ie_softc *); 182 183 static int cmd_and_wait(struct ie_softc *, int, void *, int); 184 185 static void ie_drop_packet_buffer(struct ie_softc *); 186 static void ie_readframe(struct ie_softc *, int); 187 static inline void ie_setup_config(struct ie_config_cmd *, int, int); 188 189 static void ierint(struct ie_softc *); 190 static void iestop(struct ie_softc *); 191 static void ietint(struct ie_softc *); 192 static void iexmit(struct ie_softc *); 193 194 static int mc_setup(struct ie_softc *, void *); 195 static void mc_reset(struct ie_softc *); 196 static void run_tdr(struct ie_softc *, struct ie_tdr_cmd *); 197 static void iememinit(struct ie_softc *); 198 199 static inline uint8_t *Align(char *); 200 static inline u_int Swap32(u_int); 201 static inline u_int vtop24(struct ie_softc *, void *); 202 static inline uint16_t vtop16sw(struct ie_softc *, void *); 203 204 static inline void ie_ack(struct ie_softc *, u_int); 205 static inline u_short ether_cmp(u_char *, uint8_t *); 206 static inline int ie_buflen(struct ie_softc *, int); 207 static inline int ie_packet_len(struct ie_softc *); 208 static inline struct mbuf * ieget(struct ie_softc *); 209 210 211 /* 212 * Here are a few useful functions. We could have done these as macros, 213 * but since we have the inline facility, it makes sense to use that 214 * instead. 215 */ 216 217 /* KVA to 24 bit device address */ 218 static inline u_int 219 vtop24(struct ie_softc *sc, void *ptr) 220 { 221 u_int pa; 222 223 pa = (vaddr_t)ptr - (vaddr_t)sc->sc_iobase; 224 #ifdef IEDEBUG 225 if (pa & ~0xffFFff) 226 panic("ie:vtop24"); 227 #endif 228 return pa; 229 } 230 231 /* KVA to 16 bit offset, swapped */ 232 static inline u_short 233 vtop16sw(struct ie_softc *sc, void *ptr) 234 { 235 u_int pa; 236 237 pa = (vaddr_t)ptr - (vaddr_t)sc->sc_maddr; 238 #ifdef IEDEBUG 239 if (pa & ~0xFFff) 240 panic("ie:vtop16"); 241 #endif 242 243 return SWAP(pa); 244 } 245 246 static inline u_int 247 Swap32(u_int x) 248 { 249 u_int y; 250 251 y = x & 0xFF; 252 y <<= 8; x >>= 8; 253 y |= x & 0xFF; 254 y <<= 8; x >>= 8; 255 y |= x & 0xFF; 256 y <<= 8; x >>= 8; 257 y |= x & 0xFF; 258 259 return y; 260 } 261 262 static inline uint8_t * 263 Align(char *ptr) 264 { 265 u_long l = (u_long)ptr; 266 267 l = (l + 3) & ~3L; 268 return (uint8_t *)l; 269 } 270 271 272 static inline void 273 ie_ack(struct ie_softc *sc, u_int mask) 274 { 275 volatile struct ie_sys_ctl_block *scb = sc->scb; 276 277 cmd_and_wait(sc, scb->ie_status & mask, 0, 0); 278 } 279 280 281 /* 282 * Taken almost exactly from Bill's if_is.c, 283 * then modified beyond recognition... 284 */ 285 void 286 ie_attach(struct ie_softc *sc) 287 { 288 struct ifnet *ifp = &sc->sc_if; 289 290 /* MD code has done its part before calling this. */ 291 printf(": macaddr %s\n", ether_sprintf(sc->sc_addr)); 292 293 /* 294 * Compute number of transmit and receive buffers. 295 * Tx buffers take 1536 bytes, and fixed in number. 296 * Rx buffers are 512 bytes each, variable number. 297 * Need at least 1 frame for each 3 rx buffers. 298 * The ratio 3bufs:2frames is a compromise. 299 */ 300 sc->ntxbuf = NTXBUF; /* XXX - Fix me... */ 301 switch (sc->sc_msize) { 302 case 16384: 303 sc->nframes = 8 * 4; 304 sc->nrxbuf = 8 * 6; 305 break; 306 case 32768: 307 sc->nframes = 16 * 4; 308 sc->nrxbuf = 16 * 6; 309 break; 310 case 65536: 311 sc->nframes = 32 * 4; 312 sc->nrxbuf = 32 * 6; 313 break; 314 default: 315 sc->nframes = 0; 316 } 317 if (sc->nframes > MXFRAMES) 318 sc->nframes = MXFRAMES; 319 if (sc->nrxbuf > MXRXBUF) 320 sc->nrxbuf = MXRXBUF; 321 322 #ifdef IEDEBUG 323 aprint_debug_dev(sc->sc_dev, 324 "%dK memory, %d tx frames, %d rx frames, %d rx bufs\n", 325 (sc->sc_msize >> 10), sc->ntxbuf, sc->nframes, sc->nrxbuf); 326 #endif 327 328 if ((sc->nframes <= 0) || (sc->nrxbuf <= 0)) 329 panic("%s: weird memory size", __func__); 330 331 /* 332 * Setup RAM for transmit/receive 333 */ 334 if (ie_setupram(sc) == 0) { 335 aprint_error(": RAM CONFIG FAILED!\n"); 336 /* XXX should reclaim resources? */ 337 return; 338 } 339 340 /* 341 * Initialize and attach S/W interface 342 */ 343 strcpy(ifp->if_xname, device_xname(sc->sc_dev)); 344 ifp->if_softc = sc; 345 ifp->if_start = iestart; 346 ifp->if_ioctl = ieioctl; 347 ifp->if_watchdog = iewatchdog; 348 ifp->if_flags = 349 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; 350 351 /* Attach the interface. */ 352 if_attach(ifp); 353 if_deferred_start_init(ifp, NULL); 354 ether_ifattach(ifp, sc->sc_addr); 355 } 356 357 /* 358 * Setup IE's ram space. 359 */ 360 static int 361 ie_setupram(struct ie_softc *sc) 362 { 363 volatile struct ie_sys_conf_ptr *scp; 364 volatile struct ie_int_sys_conf_ptr *iscp; 365 volatile struct ie_sys_ctl_block *scb; 366 int off; 367 368 /* 369 * Allocate from end of buffer space for 370 * ISCP, SCB, and other small stuff. 371 */ 372 off = sc->buf_area_sz; 373 off &= ~3; 374 375 /* SCP (address already chosen). */ 376 scp = sc->scp; 377 (sc->sc_memset)(__UNVOLATILE(scp), 0, sizeof(*scp)); 378 379 /* ISCP */ 380 off -= sizeof(*iscp); 381 iscp = (volatile void *)(sc->buf_area + off); 382 (sc->sc_memset)(__UNVOLATILE(iscp), 0, sizeof(*iscp)); 383 sc->iscp = iscp; 384 385 /* SCB */ 386 off -= sizeof(*scb); 387 scb = (volatile void *)(sc->buf_area + off); 388 (sc->sc_memset)(__UNVOLATILE(scb), 0, sizeof(*scb)); 389 sc->scb = scb; 390 391 /* Remainder is for buffers, etc. */ 392 sc->buf_area_sz = off; 393 394 /* 395 * Now fill in the structures we just allocated. 396 */ 397 398 /* SCP: main thing is 24-bit ptr to ISCP */ 399 scp->ie_bus_use = 0; /* 16-bit */ 400 scp->ie_iscp_ptr = Swap32(vtop24(sc, __UNVOLATILE(iscp))); 401 402 /* ISCP */ 403 iscp->ie_busy = 1; /* ie_busy == char */ 404 iscp->ie_scb_offset = vtop16sw(sc, __UNVOLATILE(scb)); 405 iscp->ie_base = Swap32(vtop24(sc, sc->sc_maddr)); 406 407 /* SCB */ 408 scb->ie_command_list = SWAP(0xffff); 409 scb->ie_recv_list = SWAP(0xffff); 410 411 /* Other stuff is done in ieinit() */ 412 (sc->reset_586)(sc); 413 (sc->chan_attn)(sc); 414 415 delay(100); /* wait a while... */ 416 417 if (iscp->ie_busy) { 418 return 0; 419 } 420 /* 421 * Acknowledge any interrupts we may have caused... 422 */ 423 ie_ack(sc, IE_ST_WHENCE); 424 425 return 1; 426 } 427 428 /* 429 * Device timeout/watchdog routine. Entered if the device neglects to 430 * generate an interrupt after a transmit has been started on it. 431 */ 432 static void 433 iewatchdog(struct ifnet *ifp) 434 { 435 struct ie_softc *sc = ifp->if_softc; 436 437 log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev)); 438 ++ifp->if_oerrors; 439 iereset(sc); 440 } 441 442 /* 443 * What to do upon receipt of an interrupt. 444 */ 445 int 446 ie_intr(void *arg) 447 { 448 struct ie_softc *sc = arg; 449 uint16_t status; 450 int loopcnt; 451 452 /* 453 * check for parity error 454 */ 455 if (sc->hard_type == IE_VME) { 456 volatile struct ievme *iev = 457 (volatile struct ievme *)sc->sc_reg; 458 459 if (iev->status & IEVME_PERR) { 460 printf("%s: parity error (ctrl 0x%x @ 0x%02x%04x)\n", 461 device_xname(sc->sc_dev), iev->pectrl, 462 iev->pectrl & IEVME_HADDR, iev->peaddr); 463 iev->pectrl = iev->pectrl | IEVME_PARACK; 464 } 465 } 466 467 status = sc->scb->ie_status; 468 if ((status & IE_ST_WHENCE) == 0) 469 return 0; 470 471 loopcnt = sc->nframes; 472 loop: 473 /* Ack interrupts FIRST in case we receive more during the ISR. */ 474 ie_ack(sc, IE_ST_WHENCE & status); 475 476 if (status & (IE_ST_RECV | IE_ST_RNR)) { 477 #ifdef IEDEBUG 478 in_ierint++; 479 if (sc->sc_debug & IED_RINT) 480 printf("%s: rint\n", device_xname(sc->sc_dev)); 481 #endif 482 ierint(sc); 483 #ifdef IEDEBUG 484 in_ierint--; 485 #endif 486 } 487 488 if (status & IE_ST_DONE) { 489 #ifdef IEDEBUG 490 in_ietint++; 491 if (sc->sc_debug & IED_TINT) 492 printf("%s: tint\n", device_xname(sc->sc_dev)); 493 #endif 494 ietint(sc); 495 #ifdef IEDEBUG 496 in_ietint--; 497 #endif 498 } 499 500 /* 501 * Receiver not ready (RNR) just means it has 502 * run out of resources (buffers or frames). 503 * One can easily cause this with (i.e.) spray. 504 * This is not a serious error, so be silent. 505 */ 506 if (status & IE_ST_RNR) { 507 #ifdef IEDEBUG 508 printf("%s: receiver not ready\n", device_xname(sc->sc_dev)); 509 #endif 510 sc->sc_if.if_ierrors++; 511 iereset(sc); 512 } 513 514 #ifdef IEDEBUG 515 if ((status & IE_ST_ALLDONE) && (sc->sc_debug & IED_CNA)) 516 printf("%s: cna\n", device_xname(sc->sc_dev)); 517 #endif 518 519 status = sc->scb->ie_status; 520 if (status & IE_ST_WHENCE) { 521 /* It still wants service... */ 522 if (--loopcnt > 0) 523 goto loop; 524 /* ... but we've been here long enough. */ 525 log(LOG_ERR, "%s: interrupt stuck?\n", 526 device_xname(sc->sc_dev)); 527 iereset(sc); 528 } 529 return 1; 530 } 531 532 /* 533 * Process a received-frame interrupt. 534 */ 535 void 536 ierint(struct ie_softc *sc) 537 { 538 volatile struct ie_sys_ctl_block *scb = sc->scb; 539 int i, status; 540 static int timesthru = 1024; 541 542 i = sc->rfhead; 543 for (;;) { 544 status = sc->rframes[i]->ie_fd_status; 545 546 if ((status & IE_FD_COMPLETE) && (status & IE_FD_OK)) { 547 if (!--timesthru) { 548 sc->sc_if.if_ierrors += 549 SWAP(scb->ie_err_crc) + 550 SWAP(scb->ie_err_align) + 551 SWAP(scb->ie_err_resource) + 552 SWAP(scb->ie_err_overrun); 553 scb->ie_err_crc = 0; 554 scb->ie_err_align = 0; 555 scb->ie_err_resource = 0; 556 scb->ie_err_overrun = 0; 557 timesthru = 1024; 558 } 559 ie_readframe(sc, i); 560 } else { 561 if ((status & IE_FD_RNR) != 0 && 562 (scb->ie_status & IE_RU_READY) == 0) { 563 sc->rframes[0]->ie_fd_buf_desc = vtop16sw(sc, 564 __UNVOLATILE(sc->rbuffs[0])); 565 scb->ie_recv_list = vtop16sw(sc, 566 __UNVOLATILE(sc->rframes[0])); 567 cmd_and_wait(sc, IE_RU_START, 0, 0); 568 } 569 break; 570 } 571 i = (i + 1) % sc->nframes; 572 } 573 } 574 575 /* 576 * Process a command-complete interrupt. These are only generated by the 577 * transmission of frames. This routine is deceptively simple, since most 578 * of the real work is done by iestart(). 579 */ 580 void 581 ietint(struct ie_softc *sc) 582 { 583 struct ifnet *ifp; 584 int status; 585 586 ifp = &sc->sc_if; 587 588 ifp->if_timer = 0; 589 ifp->if_flags &= ~IFF_OACTIVE; 590 591 status = sc->xmit_cmds[sc->xctail]->ie_xmit_status; 592 593 if (!(status & IE_STAT_COMPL) || (status & IE_STAT_BUSY)) 594 printf("%s: command still busy!\n", __func__); 595 596 if (status & IE_STAT_OK) { 597 ifp->if_opackets++; 598 ifp->if_collisions += 599 SWAP(status & IE_XS_MAXCOLL); 600 } else { 601 ifp->if_oerrors++; 602 /* 603 * XXX 604 * Check SQE and DEFERRED? 605 * What if more than one bit is set? 606 */ 607 if (status & IE_STAT_ABORT) 608 printf("%s: send aborted\n", device_xname(sc->sc_dev)); 609 if (status & IE_XS_LATECOLL) 610 printf("%s: late collision\n", 611 device_xname(sc->sc_dev)); 612 if (status & IE_XS_NOCARRIER) 613 printf("%s: no carrier\n", device_xname(sc->sc_dev)); 614 if (status & IE_XS_LOSTCTS) 615 printf("%s: lost CTS\n", device_xname(sc->sc_dev)); 616 if (status & IE_XS_UNDERRUN) 617 printf("%s: DMA underrun\n", device_xname(sc->sc_dev)); 618 if (status & IE_XS_EXCMAX) { 619 /* Do not print this one (too noisy). */ 620 ifp->if_collisions += 16; 621 } 622 } 623 624 /* 625 * If multicast addresses were added or deleted while we 626 * were transmitting, mc_reset() set the want_mcsetup flag 627 * indicating that we should do it. 628 */ 629 if (sc->want_mcsetup) { 630 mc_setup(sc, (void *)sc->xmit_cbuffs[sc->xctail]); 631 sc->want_mcsetup = 0; 632 } 633 634 /* Done with the buffer. */ 635 sc->xmit_busy--; 636 sc->xctail = (sc->xctail + 1) % NTXBUF; 637 638 /* Start the next packet, if any, transmitting. */ 639 if (sc->xmit_busy > 0) 640 iexmit(sc); 641 642 if_schedule_deferred_start(ifp); 643 } 644 645 /* 646 * Compare two Ether/802 addresses for equality, inlined and 647 * unrolled for speed. I'd love to have an inline assembler 648 * version of this... XXX: Who wanted that? mycroft? 649 * I wrote one, but the following is just as efficient. 650 * This expands to 10 short m68k instructions! -gwr 651 * Note: use this like memcmp() 652 */ 653 static inline uint16_t 654 ether_cmp(uint8_t *one, uint8_t *two) 655 { 656 uint16_t *a = (uint16_t *)one; 657 uint16_t *b = (uint16_t *)two; 658 uint16_t diff; 659 660 diff = *a++ - *b++; 661 diff |= *a++ - *b++; 662 diff |= *a++ - *b++; 663 664 return diff; 665 } 666 #define ether_equal !ether_cmp 667 668 /* 669 * We want to isolate the bits that have meaning... This assumes that 670 * IE_RBUF_SIZE is an even power of two. If somehow the act_len exceeds 671 * the size of the buffer, then we are screwed anyway. 672 */ 673 static inline int 674 ie_buflen(struct ie_softc *sc, int head) 675 { 676 int len; 677 678 len = SWAP(sc->rbuffs[head]->ie_rbd_actual); 679 len &= (IE_RBUF_SIZE | (IE_RBUF_SIZE - 1)); 680 return len; 681 } 682 683 static inline int 684 ie_packet_len(struct ie_softc *sc) 685 { 686 int i; 687 int head = sc->rbhead; 688 int acc = 0; 689 690 do { 691 if ((sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_USED) 692 == 0) { 693 #ifdef IEDEBUG 694 print_rbd(sc->rbuffs[sc->rbhead]); 695 #endif 696 log(LOG_ERR, 697 "%s: receive descriptors out of sync at %d\n", 698 device_xname(sc->sc_dev), sc->rbhead); 699 iereset(sc); 700 return -1; 701 } 702 703 i = sc->rbuffs[head]->ie_rbd_actual & IE_RBD_LAST; 704 705 acc += ie_buflen(sc, head); 706 head = (head + 1) % sc->nrxbuf; 707 } while (i == 0); 708 709 return acc; 710 } 711 712 /* 713 * Setup all necessary artifacts for an XMIT command, and then pass the XMIT 714 * command to the chip to be executed. On the way, if we have a BPF listener 715 * also give him a copy. 716 */ 717 static void 718 iexmit(struct ie_softc *sc) 719 { 720 struct ifnet *ifp; 721 722 ifp = &sc->sc_if; 723 724 #ifdef IEDEBUG 725 if (sc->sc_debug & IED_XMIT) 726 printf("%s: xmit buffer %d\n", device_xname(sc->sc_dev), 727 sc->xctail); 728 #endif 729 730 /* 731 * If BPF is listening on this interface, let it see the packet before 732 * we push it on the wire. 733 */ 734 bpf_tap(ifp, sc->xmit_cbuffs[sc->xctail], 735 SWAP(sc->xmit_buffs[sc->xctail]->ie_xmit_flags)); 736 737 sc->xmit_buffs[sc->xctail]->ie_xmit_flags |= IE_XMIT_LAST; 738 sc->xmit_buffs[sc->xctail]->ie_xmit_next = SWAP(0xffff); 739 sc->xmit_buffs[sc->xctail]->ie_xmit_buf = 740 Swap32(vtop24(sc, sc->xmit_cbuffs[sc->xctail])); 741 742 sc->xmit_cmds[sc->xctail]->com.ie_cmd_link = SWAP(0xffff); 743 sc->xmit_cmds[sc->xctail]->com.ie_cmd_cmd = 744 IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST; 745 746 sc->xmit_cmds[sc->xctail]->ie_xmit_status = SWAP(0); 747 sc->xmit_cmds[sc->xctail]->ie_xmit_desc = 748 vtop16sw(sc, __UNVOLATILE(sc->xmit_buffs[sc->xctail])); 749 750 sc->scb->ie_command_list = 751 vtop16sw(sc, __UNVOLATILE(sc->xmit_cmds[sc->xctail])); 752 cmd_and_wait(sc, IE_CU_START, 0, 0); 753 754 ifp->if_timer = 5; 755 } 756 757 /* 758 * Read data off the interface, and turn it into an mbuf chain. 759 * 760 * This code is DRAMATICALLY different from the previous version; this 761 * version tries to allocate the entire mbuf chain up front, given the 762 * length of the data available. This enables us to allocate mbuf 763 * clusters in many situations where before we would have had a long 764 * chain of partially-full mbufs. This should help to speed up the 765 * operation considerably. (Provided that it works, of course.) 766 */ 767 static inline struct mbuf * 768 ieget(struct ie_softc *sc) 769 { 770 struct mbuf *top, **mp, *m; 771 int len, totlen, resid; 772 int thisrboff, thismboff; 773 int head; 774 struct ether_header eh; 775 776 totlen = ie_packet_len(sc); 777 if (totlen <= 0) 778 return 0; 779 780 head = sc->rbhead; 781 782 /* 783 * Snarf the Ethernet header. 784 */ 785 (sc->sc_memcpy)((void *)&eh, (void *)sc->cbuffs[head], 786 sizeof(struct ether_header)); 787 788 resid = totlen; 789 790 MGETHDR(m, M_DONTWAIT, MT_DATA); 791 if (m == 0) 792 return 0; 793 794 m_set_rcvif(m, &sc->sc_if); 795 m->m_pkthdr.len = totlen; 796 len = MHLEN; 797 top = 0; 798 mp = ⊤ 799 800 /* 801 * This loop goes through and allocates mbufs for all the data we will 802 * be copying in. It does not actually do the copying yet. 803 */ 804 while (totlen > 0) { 805 if (top) { 806 MGET(m, M_DONTWAIT, MT_DATA); 807 if (m == 0) { 808 m_freem(top); 809 return 0; 810 } 811 len = MLEN; 812 } 813 if (totlen >= MINCLSIZE) { 814 MCLGET(m, M_DONTWAIT); 815 if (m->m_flags & M_EXT) 816 len = MCLBYTES; 817 } 818 819 if (mp == &top) { 820 char *newdata = (char *) 821 ALIGN(m->m_data + sizeof(struct ether_header)) - 822 sizeof(struct ether_header); 823 len -= newdata - m->m_data; 824 m->m_data = newdata; 825 } 826 827 m->m_len = len = min(totlen, len); 828 829 totlen -= len; 830 *mp = m; 831 mp = &m->m_next; 832 } 833 834 m = top; 835 thismboff = 0; 836 837 /* 838 * Copy the Ethernet header into the mbuf chain. 839 */ 840 memcpy(mtod(m, void *), &eh, sizeof(struct ether_header)); 841 thismboff = sizeof(struct ether_header); 842 thisrboff = sizeof(struct ether_header); 843 resid -= sizeof(struct ether_header); 844 845 /* 846 * Now we take the mbuf chain (hopefully only one mbuf most of the 847 * time) and stuff the data into it. There are no possible failures 848 * at or after this point. 849 */ 850 while (resid > 0) { 851 int thisrblen = ie_buflen(sc, head) - thisrboff; 852 int thismblen = m->m_len - thismboff; 853 854 len = min(thisrblen, thismblen); 855 (sc->sc_memcpy)(mtod(m, char *) + thismboff, 856 (void *)(sc->cbuffs[head] + thisrboff), 857 (u_int)len); 858 resid -= len; 859 860 if (len == thismblen) { 861 m = m->m_next; 862 thismboff = 0; 863 } else 864 thismboff += len; 865 866 if (len == thisrblen) { 867 head = (head + 1) % sc->nrxbuf; 868 thisrboff = 0; 869 } else 870 thisrboff += len; 871 } 872 873 /* 874 * Unless something changed strangely while we were doing the copy, 875 * we have now copied everything in from the shared memory. 876 * This means that we are done. 877 */ 878 return top; 879 } 880 881 /* 882 * Read frame NUM from unit UNIT (pre-cached as IE). 883 * 884 * This routine reads the RFD at NUM, and copies in the buffers from 885 * the list of RBD, then rotates the RBD and RFD lists so that the receiver 886 * doesn't start complaining. Trailers are DROPPED---there's no point 887 * in wasting time on confusing code to deal with them. Hopefully, 888 * this machine will never ARP for trailers anyway. 889 */ 890 static void 891 ie_readframe(struct ie_softc *sc, int num) 892 { 893 int status; 894 struct mbuf *m = 0; 895 896 status = sc->rframes[num]->ie_fd_status; 897 898 /* Advance the RFD list, since we're done with this descriptor. */ 899 sc->rframes[num]->ie_fd_status = SWAP(0); 900 sc->rframes[num]->ie_fd_last |= IE_FD_LAST; 901 sc->rframes[sc->rftail]->ie_fd_last &= ~IE_FD_LAST; 902 sc->rftail = (sc->rftail + 1) % sc->nframes; 903 sc->rfhead = (sc->rfhead + 1) % sc->nframes; 904 905 if (status & IE_FD_OK) { 906 m = ieget(sc); 907 ie_drop_packet_buffer(sc); 908 } 909 if (m == 0) { 910 sc->sc_if.if_ierrors++; 911 return; 912 } 913 914 #ifdef IEDEBUG 915 if (sc->sc_debug & IED_READFRAME) { 916 struct ether_header *eh = mtod(m, struct ether_header *); 917 918 printf("%s: frame from ether %s type 0x%x\n", 919 device_xname(sc->sc_dev), 920 ether_sprintf(eh->ether_shost), (u_int)eh->ether_type); 921 } 922 #endif 923 924 /* 925 * Finally pass this packet up to higher layers. 926 */ 927 if_percpuq_enqueue((&sc->sc_if)->if_percpuq, m); 928 } 929 930 static void 931 ie_drop_packet_buffer(struct ie_softc *sc) 932 { 933 int i; 934 935 do { 936 /* 937 * This means we are somehow out of sync. So, we reset the 938 * adapter. 939 */ 940 if ((sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_USED) 941 == 0) { 942 #ifdef IEDEBUG 943 print_rbd(sc->rbuffs[sc->rbhead]); 944 #endif 945 log(LOG_ERR, 946 "%s: receive descriptors out of sync at %d\n", 947 device_xname(sc->sc_dev), sc->rbhead); 948 iereset(sc); 949 return; 950 } 951 952 i = sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_LAST; 953 954 sc->rbuffs[sc->rbhead]->ie_rbd_length |= IE_RBD_LAST; 955 sc->rbuffs[sc->rbhead]->ie_rbd_actual = SWAP(0); 956 sc->rbhead = (sc->rbhead + 1) % sc->nrxbuf; 957 sc->rbuffs[sc->rbtail]->ie_rbd_length &= ~IE_RBD_LAST; 958 sc->rbtail = (sc->rbtail + 1) % sc->nrxbuf; 959 } while (i == 0); 960 } 961 962 /* 963 * Start transmission on an interface. 964 */ 965 static void 966 iestart(struct ifnet *ifp) 967 { 968 struct ie_softc *sc = ifp->if_softc; 969 struct mbuf *m0, *m; 970 uint8_t *buffer; 971 uint16_t len; 972 973 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 974 return; 975 976 for (;;) { 977 if (sc->xmit_busy == sc->ntxbuf) { 978 ifp->if_flags |= IFF_OACTIVE; 979 break; 980 } 981 982 IF_DEQUEUE(&ifp->if_snd, m0); 983 if (m0 == 0) 984 break; 985 986 /* We need to use m->m_pkthdr.len, so require the header */ 987 if ((m0->m_flags & M_PKTHDR) == 0) 988 panic("%s: no header mbuf", __func__); 989 990 /* Tap off here if there is a BPF listener. */ 991 bpf_mtap(ifp, m0); 992 993 #ifdef IEDEBUG 994 if (sc->sc_debug & IED_ENQ) 995 printf("%s: fill buffer %d\n", device_xname(sc->sc_dev), 996 sc->xchead); 997 #endif 998 999 buffer = sc->xmit_cbuffs[sc->xchead]; 1000 for (m = m0; m != 0; m = m->m_next) { 1001 (sc->sc_memcpy)(buffer, mtod(m, void *), m->m_len); 1002 buffer += m->m_len; 1003 } 1004 if (m0->m_pkthdr.len < ETHER_MIN_LEN - ETHER_CRC_LEN) { 1005 sc->sc_memset(buffer, 0, 1006 ETHER_MIN_LEN - ETHER_CRC_LEN - m0->m_pkthdr.len); 1007 len = ETHER_MIN_LEN - ETHER_CRC_LEN; 1008 } else 1009 len = m0->m_pkthdr.len; 1010 1011 m_freem(m0); 1012 sc->xmit_buffs[sc->xchead]->ie_xmit_flags = SWAP(len); 1013 1014 /* Start the first packet transmitting. */ 1015 if (sc->xmit_busy == 0) 1016 iexmit(sc); 1017 1018 sc->xchead = (sc->xchead + 1) % sc->ntxbuf; 1019 sc->xmit_busy++; 1020 } 1021 } 1022 1023 static void 1024 iereset(struct ie_softc *sc) 1025 { 1026 int s; 1027 1028 s = splnet(); 1029 1030 /* No message here. The caller does that. */ 1031 iestop(sc); 1032 1033 /* 1034 * Stop i82586 dead in its tracks. 1035 */ 1036 if (cmd_and_wait(sc, IE_RU_ABORT | IE_CU_ABORT, 0, 0)) 1037 printf("%s: abort commands timed out\n", 1038 device_xname(sc->sc_dev)); 1039 1040 if (cmd_and_wait(sc, IE_RU_DISABLE | IE_CU_STOP, 0, 0)) 1041 printf("%s: disable commands timed out\n", 1042 device_xname(sc->sc_dev)); 1043 1044 ieinit(sc); 1045 1046 splx(s); 1047 } 1048 1049 /* 1050 * Send a command to the controller and wait for it to either 1051 * complete or be accepted, depending on the command. If the 1052 * command pointer is null, then pretend that the command is 1053 * not an action command. If the command pointer is not null, 1054 * and the command is an action command, wait for 1055 * ((volatile struct ie_cmd_common *)pcmd)->ie_cmd_status & MASK 1056 * to become true. 1057 */ 1058 static int 1059 cmd_and_wait(struct ie_softc *sc, int cmd, void *pcmd, int mask) 1060 { 1061 volatile struct ie_cmd_common *cc = pcmd; 1062 volatile struct ie_sys_ctl_block *scb = sc->scb; 1063 int tmo; 1064 1065 scb->ie_command = (uint16_t)cmd; 1066 (sc->chan_attn)(sc); 1067 1068 /* Wait for the command to be accepted by the CU. */ 1069 tmo = 10; 1070 while (scb->ie_command && --tmo) 1071 delay(10); 1072 if (scb->ie_command) { 1073 #ifdef IEDEBUG 1074 printf("%s: cmd_and_wait, CU stuck (1)\n", 1075 device_xname(sc->sc_dev)); 1076 #endif 1077 return -1; /* timed out */ 1078 } 1079 1080 /* 1081 * If asked, also wait for it to finish. 1082 */ 1083 if (IE_ACTION_COMMAND(cmd) && pcmd) { 1084 1085 /* 1086 * According to the packet driver, the minimum timeout should 1087 * be .369 seconds, which we round up to .4. 1088 */ 1089 tmo = 36900; 1090 1091 /* 1092 * Now spin-lock waiting for status. This is not a very nice 1093 * thing to do, but I haven't figured out how, or indeed if, we 1094 * can put the process waiting for action to sleep. (We may 1095 * be getting called through some other timeout running in the 1096 * kernel.) 1097 */ 1098 while (((cc->ie_cmd_status & mask) == 0) && --tmo) 1099 delay(10); 1100 1101 if ((cc->ie_cmd_status & mask) == 0) { 1102 #ifdef IEDEBUG 1103 printf("%s: cmd_and_wait, CU stuck (2)\n", 1104 device_xname(sc->sc_dev)); 1105 #endif 1106 return -1; /* timed out */ 1107 } 1108 } 1109 return 0; 1110 } 1111 1112 /* 1113 * Run the time-domain reflectometer. 1114 */ 1115 static void 1116 run_tdr(struct ie_softc *sc, struct ie_tdr_cmd *cmd) 1117 { 1118 int result; 1119 1120 cmd->com.ie_cmd_status = SWAP(0); 1121 cmd->com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST; 1122 cmd->com.ie_cmd_link = SWAP(0xffff); 1123 1124 sc->scb->ie_command_list = vtop16sw(sc, cmd); 1125 cmd->ie_tdr_time = SWAP(0); 1126 1127 if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) || 1128 (cmd->com.ie_cmd_status & IE_STAT_OK) == 0) 1129 result = 0x10000; /* impossible value */ 1130 else 1131 result = cmd->ie_tdr_time; 1132 1133 ie_ack(sc, IE_ST_WHENCE); 1134 1135 if (result & IE_TDR_SUCCESS) 1136 return; 1137 1138 if (result & 0x10000) { 1139 printf("%s: TDR command failed\n", device_xname(sc->sc_dev)); 1140 } else if (result & IE_TDR_XCVR) { 1141 printf("%s: transceiver problem\n", device_xname(sc->sc_dev)); 1142 } else if (result & IE_TDR_OPEN) { 1143 printf("%s: TDR detected an open %d clocks away\n", 1144 device_xname(sc->sc_dev), SWAP(result & IE_TDR_TIME)); 1145 } else if (result & IE_TDR_SHORT) { 1146 printf("%s: TDR detected a short %d clocks away\n", 1147 device_xname(sc->sc_dev), SWAP(result & IE_TDR_TIME)); 1148 } else { 1149 printf("%s: TDR returned unknown status 0x%x\n", 1150 device_xname(sc->sc_dev), result); 1151 } 1152 } 1153 1154 /* 1155 * iememinit: set up the buffers 1156 * 1157 * we have a block of KVA at sc->buf_area which is of size sc->buf_area_sz. 1158 * this is to be used for the buffers. the chip indexs its control data 1159 * structures with 16 bit offsets, and it indexes actual buffers with 1160 * 24 bit addresses. so we should allocate control buffers first so that 1161 * we don't overflow the 16 bit offset field. The number of transmit 1162 * buffers is fixed at compile time. 1163 * 1164 * note: this function was written to be easy to understand, rather than 1165 * highly efficient (it isn't in the critical path). 1166 * 1167 * The memory layout is: tbufs, rbufs, (gap), control blocks 1168 * [tbuf0, tbuf1] [rbuf0,...rbufN] gap [rframes] [tframes] 1169 * XXX - This needs review... 1170 */ 1171 static void 1172 iememinit(struct ie_softc *sc) 1173 { 1174 uint8_t *ptr; 1175 int i; 1176 uint16_t nxt; 1177 1178 /* First, zero all the memory. */ 1179 ptr = sc->buf_area; 1180 (sc->sc_memset)(ptr, 0, sc->buf_area_sz); 1181 1182 /* Allocate tx/rx buffers. */ 1183 for (i = 0; i < NTXBUF; i++) { 1184 sc->xmit_cbuffs[i] = ptr; 1185 ptr += IE_TBUF_SIZE; 1186 } 1187 for (i = 0; i < sc->nrxbuf; i++) { 1188 sc->cbuffs[i] = ptr; 1189 ptr += IE_RBUF_SIZE; 1190 } 1191 1192 /* Small pad (Don't trust the chip...) */ 1193 ptr += 16; 1194 1195 /* Allocate and fill in xmit buffer descriptors. */ 1196 for (i = 0; i < NTXBUF; i++) { 1197 sc->xmit_buffs[i] = (volatile void *)ptr; 1198 ptr = Align(ptr + sizeof(*sc->xmit_buffs[i])); 1199 sc->xmit_buffs[i]->ie_xmit_buf = 1200 Swap32(vtop24(sc, sc->xmit_cbuffs[i])); 1201 sc->xmit_buffs[i]->ie_xmit_next = SWAP(0xffff); 1202 } 1203 1204 /* Allocate and fill in recv buffer descriptors. */ 1205 for (i = 0; i < sc->nrxbuf; i++) { 1206 sc->rbuffs[i] = (volatile void *)ptr; 1207 ptr = Align(ptr + sizeof(*sc->rbuffs[i])); 1208 sc->rbuffs[i]->ie_rbd_buffer = 1209 Swap32(vtop24(sc, sc->cbuffs[i])); 1210 sc->rbuffs[i]->ie_rbd_length = SWAP(IE_RBUF_SIZE); 1211 } 1212 1213 /* link together recv bufs and set EOL on last */ 1214 i = sc->nrxbuf - 1; 1215 sc->rbuffs[i]->ie_rbd_length |= IE_RBD_LAST; 1216 nxt = vtop16sw(sc, __UNVOLATILE(sc->rbuffs[0])); 1217 do { 1218 sc->rbuffs[i]->ie_rbd_next = nxt; 1219 nxt = vtop16sw(sc, __UNVOLATILE(sc->rbuffs[i])); 1220 } while (--i >= 0); 1221 1222 /* Allocate transmit commands. */ 1223 for (i = 0; i < NTXBUF; i++) { 1224 sc->xmit_cmds[i] = (volatile void *)ptr; 1225 ptr = Align(ptr + sizeof(*sc->xmit_cmds[i])); 1226 sc->xmit_cmds[i]->com.ie_cmd_link = SWAP(0xffff); 1227 } 1228 1229 /* Allocate receive frames. */ 1230 for (i = 0; i < sc->nframes; i++) { 1231 sc->rframes[i] = (volatile void *)ptr; 1232 ptr = Align(ptr + sizeof(*sc->rframes[i])); 1233 } 1234 1235 /* Link together recv frames and set EOL on last */ 1236 i = sc->nframes - 1; 1237 sc->rframes[i]->ie_fd_last |= IE_FD_LAST; 1238 nxt = vtop16sw(sc, __UNVOLATILE(sc->rframes[0])); 1239 do { 1240 sc->rframes[i]->ie_fd_next = nxt; 1241 nxt = vtop16sw(sc, __UNVOLATILE(sc->rframes[i])); 1242 } while (--i >= 0); 1243 1244 1245 /* Pointers to last packet sent and next available transmit buffer. */ 1246 sc->xchead = sc->xctail = 0; 1247 1248 /* Clear transmit-busy flag. */ 1249 sc->xmit_busy = 0; 1250 1251 /* 1252 * Set the head and tail pointers on receive to keep track of 1253 * the order in which RFDs and RBDs are used. link the 1254 * recv frames and buffer into the scb. 1255 */ 1256 sc->rfhead = 0; 1257 sc->rftail = sc->nframes - 1; 1258 sc->rbhead = 0; 1259 sc->rbtail = sc->nrxbuf - 1; 1260 1261 sc->scb->ie_recv_list = 1262 vtop16sw(sc, __UNVOLATILE(sc->rframes[0])); 1263 sc->rframes[0]->ie_fd_buf_desc = 1264 vtop16sw(sc, __UNVOLATILE(sc->rbuffs[0])); 1265 1266 i = (ptr - sc->buf_area); 1267 #ifdef IEDEBUG 1268 printf("IE_DEBUG: used %d of %d bytes\n", i, sc->buf_area_sz); 1269 #endif 1270 if (i > sc->buf_area_sz) 1271 panic("ie: iememinit, out of space"); 1272 } 1273 1274 /* 1275 * Run the multicast setup command. 1276 * Called at splnet(). 1277 */ 1278 static int 1279 mc_setup(struct ie_softc *sc, void *ptr) 1280 { 1281 struct ie_mcast_cmd *cmd = ptr; /* XXX - Was volatile */ 1282 1283 cmd->com.ie_cmd_status = SWAP(0); 1284 cmd->com.ie_cmd_cmd = IE_CMD_MCAST | IE_CMD_LAST; 1285 cmd->com.ie_cmd_link = SWAP(0xffff); 1286 1287 (sc->sc_memcpy)((void *)cmd->ie_mcast_addrs, 1288 (void *)sc->mcast_addrs, 1289 sc->mcast_count * sizeof *sc->mcast_addrs); 1290 1291 cmd->ie_mcast_bytes = 1292 SWAP(sc->mcast_count * ETHER_ADDR_LEN); /* grrr... */ 1293 1294 sc->scb->ie_command_list = vtop16sw(sc, cmd); 1295 if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) || 1296 (cmd->com.ie_cmd_status & IE_STAT_OK) == 0) { 1297 printf("%s: multicast address setup command failed\n", 1298 device_xname(sc->sc_dev)); 1299 return 0; 1300 } 1301 return 1; 1302 } 1303 1304 static inline void 1305 ie_setup_config(struct ie_config_cmd *cmd, int promiscuous, int manchester) 1306 { 1307 1308 /* 1309 * these are all char's so no need to byte-swap 1310 */ 1311 cmd->ie_config_count = 0x0c; 1312 cmd->ie_fifo = 8; 1313 cmd->ie_save_bad = 0x40; 1314 cmd->ie_addr_len = 0x2e; 1315 cmd->ie_priority = 0; 1316 cmd->ie_ifs = 0x60; 1317 cmd->ie_slot_low = 0; 1318 cmd->ie_slot_high = 0xf2; 1319 cmd->ie_promisc = promiscuous | manchester << 2; 1320 cmd->ie_crs_cdt = 0; 1321 cmd->ie_min_len = 64; 1322 cmd->ie_junk = 0xff; 1323 } 1324 1325 /* 1326 * This routine inits the ie. 1327 * This includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands, 1328 * starting the receiver unit, and clearing interrupts. 1329 * 1330 * THIS ROUTINE MUST BE CALLED AT splnet() OR HIGHER. 1331 */ 1332 static int 1333 ieinit(struct ie_softc *sc) 1334 { 1335 volatile struct ie_sys_ctl_block *scb = sc->scb; 1336 void *ptr; 1337 struct ifnet *ifp; 1338 1339 ifp = &sc->sc_if; 1340 ptr = sc->buf_area; /* XXX - Use scb instead? */ 1341 1342 /* 1343 * Send the configure command first. 1344 */ 1345 { 1346 struct ie_config_cmd *cmd = ptr; /* XXX - Was volatile */ 1347 1348 scb->ie_command_list = vtop16sw(sc, cmd); 1349 cmd->com.ie_cmd_status = SWAP(0); 1350 cmd->com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST; 1351 cmd->com.ie_cmd_link = SWAP(0xffff); 1352 1353 ie_setup_config(cmd, (sc->promisc != 0), 0); 1354 1355 if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) || 1356 (cmd->com.ie_cmd_status & IE_STAT_OK) == 0) { 1357 printf("%s: configure command failed\n", 1358 device_xname(sc->sc_dev)); 1359 return 0; 1360 } 1361 } 1362 1363 /* 1364 * Now send the Individual Address Setup command. 1365 */ 1366 { 1367 struct ie_iasetup_cmd *cmd = ptr; /* XXX - Was volatile */ 1368 1369 scb->ie_command_list = vtop16sw(sc, cmd); 1370 cmd->com.ie_cmd_status = SWAP(0); 1371 cmd->com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST; 1372 cmd->com.ie_cmd_link = SWAP(0xffff); 1373 1374 (sc->sc_memcpy)((void *)&cmd->ie_address, 1375 CLLADDR(ifp->if_sadl), sizeof(cmd->ie_address)); 1376 1377 if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) || 1378 (cmd->com.ie_cmd_status & IE_STAT_OK) == 0) { 1379 printf("%s: individual address setup command failed\n", 1380 device_xname(sc->sc_dev)); 1381 return 0; 1382 } 1383 } 1384 1385 /* 1386 * Now run the time-domain reflectometer. 1387 */ 1388 if (ie_run_tdr) 1389 run_tdr(sc, ptr); 1390 1391 /* 1392 * Acknowledge any interrupts we have generated thus far. 1393 */ 1394 ie_ack(sc, IE_ST_WHENCE); 1395 1396 /* 1397 * Set up the transmit and recv buffers. 1398 */ 1399 iememinit(sc); 1400 1401 /* tell higher levels that we are here */ 1402 ifp->if_flags |= IFF_RUNNING; 1403 ifp->if_flags &= ~IFF_OACTIVE; 1404 1405 sc->scb->ie_recv_list = 1406 vtop16sw(sc, __UNVOLATILE(sc->rframes[0])); 1407 cmd_and_wait(sc, IE_RU_START, 0, 0); 1408 1409 ie_ack(sc, IE_ST_WHENCE); 1410 1411 if (sc->run_586) 1412 (sc->run_586)(sc); 1413 1414 return 0; 1415 } 1416 1417 static void 1418 iestop(struct ie_softc *sc) 1419 { 1420 1421 cmd_and_wait(sc, IE_RU_DISABLE, 0, 0); 1422 } 1423 1424 static int 1425 ieioctl(struct ifnet *ifp, u_long cmd, void *data) 1426 { 1427 struct ie_softc *sc = ifp->if_softc; 1428 struct ifaddr *ifa = (struct ifaddr *)data; 1429 int s, error = 0; 1430 1431 s = splnet(); 1432 1433 switch (cmd) { 1434 1435 case SIOCINITIFADDR: 1436 ifp->if_flags |= IFF_UP; 1437 1438 switch (ifa->ifa_addr->sa_family) { 1439 #ifdef INET 1440 case AF_INET: 1441 ieinit(sc); 1442 arp_ifinit(ifp, ifa); 1443 break; 1444 #endif 1445 default: 1446 ieinit(sc); 1447 break; 1448 } 1449 break; 1450 1451 case SIOCSIFFLAGS: 1452 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 1453 break; 1454 sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI); 1455 1456 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { 1457 case IFF_RUNNING: 1458 /* 1459 * If interface is marked down and it is running, then 1460 * stop it. 1461 */ 1462 iestop(sc); 1463 ifp->if_flags &= ~IFF_RUNNING; 1464 break; 1465 case IFF_UP: 1466 /* 1467 * If interface is marked up and it is stopped, then 1468 * start it. 1469 */ 1470 ieinit(sc); 1471 break; 1472 default: 1473 /* 1474 * Reset the interface to pick up changes in any other 1475 * flags that affect hardware registers. 1476 */ 1477 iestop(sc); 1478 ieinit(sc); 1479 break; 1480 } 1481 #ifdef IEDEBUG 1482 if (ifp->if_flags & IFF_DEBUG) 1483 sc->sc_debug = IED_ALL; 1484 else 1485 sc->sc_debug = ie_debug_flags; 1486 #endif 1487 break; 1488 1489 case SIOCADDMULTI: 1490 case SIOCDELMULTI: 1491 if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) { 1492 /* 1493 * Multicast list has changed; set the hardware filter 1494 * accordingly. 1495 */ 1496 if (ifp->if_flags & IFF_RUNNING) 1497 mc_reset(sc); 1498 error = 0; 1499 } 1500 break; 1501 1502 default: 1503 error = ether_ioctl(ifp, cmd, data); 1504 break; 1505 } 1506 splx(s); 1507 return error; 1508 } 1509 1510 static void 1511 mc_reset(struct ie_softc *sc) 1512 { 1513 struct ether_multi *enm; 1514 struct ether_multistep step; 1515 struct ifnet *ifp; 1516 1517 ifp = &sc->sc_if; 1518 1519 /* 1520 * Step through the list of addresses. 1521 */ 1522 sc->mcast_count = 0; 1523 ETHER_FIRST_MULTI(step, &sc->sc_ethercom, enm); 1524 while (enm) { 1525 if (sc->mcast_count >= MAXMCAST || 1526 ether_cmp(enm->enm_addrlo, enm->enm_addrhi) != 0) { 1527 ifp->if_flags |= IFF_ALLMULTI; 1528 ieioctl(ifp, SIOCSIFFLAGS, NULL); 1529 goto setflag; 1530 } 1531 memcpy(&sc->mcast_addrs[sc->mcast_count], enm->enm_addrlo, 1532 ETHER_ADDR_LEN); 1533 sc->mcast_count++; 1534 ETHER_NEXT_MULTI(step, enm); 1535 } 1536 setflag: 1537 sc->want_mcsetup = 1; 1538 } 1539 1540 #ifdef IEDEBUG 1541 void 1542 print_rbd(volatile struct ie_recv_buf_desc *rbd) 1543 { 1544 1545 printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n" 1546 "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual, 1547 rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length, 1548 rbd->mbz); 1549 } 1550 #endif 1551