if_ex.c revision 112764
1/* 2 * Copyright (c) 1996, Javier Mart�n Rueda (jmrueda@diatel.upm.es) 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD: head/sys/dev/ex/if_ex.c 112764 2003-03-29 01:40:42Z mdodd $ 28 * 29 * MAINTAINER: Matthew N. Dodd <winter@jurai.net> 30 * <mdodd@FreeBSD.org> 31 */ 32 33/* 34 * Intel EtherExpress Pro/10, Pro/10+ Ethernet driver 35 * 36 * Revision history: 37 * 38 * dd-mmm-yyyy: Multicast support ported from NetBSD's if_iy driver. 39 * 30-Oct-1996: first beta version. Inet and BPF supported, but no multicast. 40 */ 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/kernel.h> 45#include <sys/sockio.h> 46#include <sys/mbuf.h> 47#include <sys/socket.h> 48 49#include <sys/module.h> 50#include <sys/bus.h> 51 52#include <machine/bus.h> 53#include <machine/resource.h> 54#include <sys/rman.h> 55 56#include <net/if.h> 57#include <net/if_arp.h> 58#include <net/if_dl.h> 59#include <net/if_media.h> 60#include <net/ethernet.h> 61#include <net/bpf.h> 62 63#include <netinet/in.h> 64#include <netinet/if_ether.h> 65 66 67#include <isa/isavar.h> 68#include <isa/pnpvar.h> 69 70#include <dev/ex/if_exreg.h> 71#include <dev/ex/if_exvar.h> 72 73#ifdef EXDEBUG 74# define Start_End 1 75# define Rcvd_Pkts 2 76# define Sent_Pkts 4 77# define Status 8 78static int debug_mask = 0; 79static int exintr_count = 0; 80# define DODEBUG(level, action) if (level & debug_mask) action 81#else 82# define DODEBUG(level, action) 83#endif 84 85char irq2eemap[] = 86 { -1, -1, 0, 1, -1, 2, -1, -1, -1, 0, 3, 4, -1, -1, -1, -1 }; 87u_char ee2irqmap[] = 88 { 9, 3, 5, 10, 11, 0, 0, 0 }; 89 90char plus_irq2eemap[] = 91 { -1, -1, -1, 0, 1, 2, -1, 3, -1, 4, 5, 6, 7, -1, -1, -1 }; 92u_char plus_ee2irqmap[] = 93 { 3, 4, 5, 7, 9, 10, 11, 12 }; 94 95/* Network Interface Functions */ 96static void ex_init (void *); 97static void ex_start (struct ifnet *); 98static int ex_ioctl (struct ifnet *, u_long, caddr_t); 99static void ex_watchdog (struct ifnet *); 100 101/* ifmedia Functions */ 102static int ex_ifmedia_upd (struct ifnet *); 103static void ex_ifmedia_sts (struct ifnet *, struct ifmediareq *); 104 105static int ex_get_media (u_int32_t iobase); 106 107static void ex_reset (struct ex_softc *); 108static void ex_setmulti (struct ex_softc *); 109 110static void ex_tx_intr (struct ex_softc *); 111static void ex_rx_intr (struct ex_softc *); 112 113int 114look_for_card (u_int32_t iobase) 115{ 116 int count1, count2; 117 118 /* 119 * Check for the i82595 signature, and check that the round robin 120 * counter actually advances. 121 */ 122 if (((count1 = inb(iobase + ID_REG)) & Id_Mask) != Id_Sig) 123 return(0); 124 count2 = inb(iobase + ID_REG); 125 count2 = inb(iobase + ID_REG); 126 count2 = inb(iobase + ID_REG); 127 128 return((count2 & Counter_bits) == ((count1 + 0xc0) & Counter_bits)); 129} 130 131void 132ex_get_address (u_int32_t iobase, u_char *enaddr) 133{ 134 u_int16_t eaddr_tmp; 135 136 eaddr_tmp = eeprom_read(iobase, EE_Eth_Addr_Lo); 137 enaddr[5] = eaddr_tmp & 0xff; 138 enaddr[4] = eaddr_tmp >> 8; 139 eaddr_tmp = eeprom_read(iobase, EE_Eth_Addr_Mid); 140 enaddr[3] = eaddr_tmp & 0xff; 141 enaddr[2] = eaddr_tmp >> 8; 142 eaddr_tmp = eeprom_read(iobase, EE_Eth_Addr_Hi); 143 enaddr[1] = eaddr_tmp & 0xff; 144 enaddr[0] = eaddr_tmp >> 8; 145 146 return; 147} 148 149int 150ex_card_type (u_char *enaddr) 151{ 152 if ((enaddr[0] == 0x00) && (enaddr[1] == 0xA0) && (enaddr[2] == 0xC9)) 153 return (CARD_TYPE_EX_10_PLUS); 154 155 return (CARD_TYPE_EX_10); 156} 157 158/* 159 * Caller is responsible for eventually calling 160 * ex_release_resources() on failure. 161 */ 162int 163ex_alloc_resources (device_t dev) 164{ 165 struct ex_softc * sc = device_get_softc(dev); 166 int error = 0; 167 168 sc->ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->ioport_rid, 169 0, ~0, 1, RF_ACTIVE); 170 if (!sc->ioport) { 171 device_printf(dev, "No I/O space?!\n"); 172 error = ENOMEM; 173 goto bad; 174 } 175 176 sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid, 177 0, ~0, 1, RF_ACTIVE); 178 179 if (!sc->irq) { 180 device_printf(dev, "No IRQ?!\n"); 181 error = ENOMEM; 182 goto bad; 183 } 184 185bad: 186 return (error); 187} 188 189void 190ex_release_resources (device_t dev) 191{ 192 struct ex_softc * sc = device_get_softc(dev); 193 194 if (sc->ih) { 195 bus_teardown_intr(dev, sc->irq, sc->ih); 196 sc->ih = NULL; 197 } 198 199 if (sc->ioport) { 200 bus_release_resource(dev, SYS_RES_IOPORT, 201 sc->ioport_rid, sc->ioport); 202 sc->ioport = NULL; 203 } 204 205 if (sc->irq) { 206 bus_release_resource(dev, SYS_RES_IRQ, 207 sc->irq_rid, sc->irq); 208 sc->irq = NULL; 209 } 210 211 return; 212} 213 214int 215ex_attach(device_t dev) 216{ 217 struct ex_softc * sc = device_get_softc(dev); 218 struct ifnet * ifp = &sc->arpcom.ac_if; 219 struct ifmedia * ifm; 220 int unit = device_get_unit(dev); 221 u_int16_t temp; 222 223 /* work out which set of irq <-> internal tables to use */ 224 if (ex_card_type(sc->arpcom.ac_enaddr) == CARD_TYPE_EX_10_PLUS) { 225 sc->irq2ee = plus_irq2eemap; 226 sc->ee2irq = plus_ee2irqmap; 227 } else { 228 sc->irq2ee = irq2eemap; 229 sc->ee2irq = ee2irqmap; 230 } 231 232 sc->mem_size = CARD_RAM_SIZE; /* XXX This should be read from the card itself. */ 233 234 /* 235 * Initialize the ifnet structure. 236 */ 237 ifp->if_softc = sc; 238 ifp->if_unit = unit; 239 ifp->if_name = "ex"; 240 ifp->if_mtu = ETHERMTU; 241 ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; 242 ifp->if_output = ether_output; 243 ifp->if_start = ex_start; 244 ifp->if_ioctl = ex_ioctl; 245 ifp->if_watchdog = ex_watchdog; 246 ifp->if_init = ex_init; 247 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 248 249 ifmedia_init(&sc->ifmedia, 0, ex_ifmedia_upd, ex_ifmedia_sts); 250 251 temp = eeprom_read(sc->iobase, EE_W5); 252 if (temp & EE_W5_PORT_TPE) 253 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL); 254 if (temp & EE_W5_PORT_BNC) 255 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_2, 0, NULL); 256 if (temp & EE_W5_PORT_AUI) 257 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_5, 0, NULL); 258 259 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); 260 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_NONE, 0, NULL); 261 ifmedia_set(&sc->ifmedia, ex_get_media(sc->iobase)); 262 263 ifm = &sc->ifmedia; 264 ifm->ifm_media = ifm->ifm_cur->ifm_media; 265 ex_ifmedia_upd(ifp); 266 267 /* 268 * Attach the interface. 269 */ 270 ether_ifattach(ifp, sc->arpcom.ac_enaddr); 271 272 device_printf(sc->dev, "Ethernet address %6D\n", 273 sc->arpcom.ac_enaddr, ":"); 274 275 return(0); 276} 277 278static void 279ex_init(void *xsc) 280{ 281 struct ex_softc * sc = (struct ex_softc *) xsc; 282 struct ifnet * ifp = &sc->arpcom.ac_if; 283 int s; 284 int i; 285 register int iobase = sc->iobase; 286 unsigned short temp_reg; 287 288 DODEBUG(Start_End, printf("ex_init%d: start\n", ifp->if_unit);); 289 290 if (TAILQ_FIRST(&ifp->if_addrhead) == NULL) { 291 return; 292 } 293 s = splimp(); 294 ifp->if_timer = 0; 295 296 /* 297 * Load the ethernet address into the card. 298 */ 299 outb(iobase + CMD_REG, Bank2_Sel); 300 temp_reg = inb(iobase + EEPROM_REG); 301 if (temp_reg & Trnoff_Enable) { 302 outb(iobase + EEPROM_REG, temp_reg & ~Trnoff_Enable); 303 } 304 for (i = 0; i < ETHER_ADDR_LEN; i++) { 305 outb(iobase + I_ADDR_REG0 + i, sc->arpcom.ac_enaddr[i]); 306 } 307 /* 308 * - Setup transmit chaining and discard bad received frames. 309 * - Match broadcast. 310 * - Clear test mode. 311 * - Set receiving mode. 312 * - Set IRQ number. 313 */ 314 outb(iobase + REG1, inb(iobase + REG1) | Tx_Chn_Int_Md | Tx_Chn_ErStp | Disc_Bad_Fr); 315 outb(iobase + REG2, inb(iobase + REG2) | No_SA_Ins | RX_CRC_InMem); 316 outb(iobase + REG3, inb(iobase + REG3) & 0x3f /* XXX constants. */ ); 317 outb(iobase + CMD_REG, Bank1_Sel); 318 outb(iobase + INT_NO_REG, (inb(iobase + INT_NO_REG) & 0xf8) | sc->irq2ee[sc->irq_no]); 319 320 /* 321 * Divide the available memory in the card into rcv and xmt buffers. 322 * By default, I use the first 3/4 of the memory for the rcv buffer, 323 * and the remaining 1/4 of the memory for the xmt buffer. 324 */ 325 sc->rx_mem_size = sc->mem_size * 3 / 4; 326 sc->tx_mem_size = sc->mem_size - sc->rx_mem_size; 327 sc->rx_lower_limit = 0x0000; 328 sc->rx_upper_limit = sc->rx_mem_size - 2; 329 sc->tx_lower_limit = sc->rx_mem_size; 330 sc->tx_upper_limit = sc->mem_size - 2; 331 outb(iobase + RCV_LOWER_LIMIT_REG, sc->rx_lower_limit >> 8); 332 outb(iobase + RCV_UPPER_LIMIT_REG, sc->rx_upper_limit >> 8); 333 outb(iobase + XMT_LOWER_LIMIT_REG, sc->tx_lower_limit >> 8); 334 outb(iobase + XMT_UPPER_LIMIT_REG, sc->tx_upper_limit >> 8); 335 336 /* 337 * Enable receive and transmit interrupts, and clear any pending int. 338 */ 339 outb(iobase + REG1, inb(iobase + REG1) | TriST_INT); 340 outb(iobase + CMD_REG, Bank0_Sel); 341 outb(iobase + MASK_REG, All_Int & ~(Rx_Int | Tx_Int)); 342 outb(iobase + STATUS_REG, All_Int); 343 344 /* 345 * Initialize receive and transmit ring buffers. 346 */ 347 outw(iobase + RCV_BAR, sc->rx_lower_limit); 348 sc->rx_head = sc->rx_lower_limit; 349 outw(iobase + RCV_STOP_REG, sc->rx_upper_limit | 0xfe); 350 outw(iobase + XMT_BAR, sc->tx_lower_limit); 351 sc->tx_head = sc->tx_tail = sc->tx_lower_limit; 352 353 ifp->if_flags |= IFF_RUNNING; 354 ifp->if_flags &= ~IFF_OACTIVE; 355 DODEBUG(Status, printf("OIDLE init\n");); 356 357 ex_setmulti(sc); 358 359 /* 360 * Final reset of the board, and enable operation. 361 */ 362 outb(iobase + CMD_REG, Sel_Reset_CMD); 363 DELAY(2); 364 outb(iobase + CMD_REG, Rcv_Enable_CMD); 365 366 ex_start(ifp); 367 splx(s); 368 369 DODEBUG(Start_End, printf("ex_init%d: finish\n", ifp->if_unit);); 370} 371 372 373static void 374ex_start(struct ifnet *ifp) 375{ 376 struct ex_softc * sc = ifp->if_softc; 377 int iobase = sc->iobase; 378 int i, s, len, data_len, avail, dest, next; 379 unsigned char tmp16[2]; 380 struct mbuf * opkt; 381 struct mbuf * m; 382 383 DODEBUG(Start_End, printf("ex_start%d: start\n", unit);); 384 385 s = splimp(); 386 387 /* 388 * Main loop: send outgoing packets to network card until there are no 389 * more packets left, or the card cannot accept any more yet. 390 */ 391 while (((opkt = ifp->if_snd.ifq_head) != NULL) && 392 !(ifp->if_flags & IFF_OACTIVE)) { 393 394 /* 395 * Ensure there is enough free transmit buffer space for 396 * this packet, including its header. Note: the header 397 * cannot wrap around the end of the transmit buffer and 398 * must be kept together, so we allow space for twice the 399 * length of the header, just in case. 400 */ 401 402 for (len = 0, m = opkt; m != NULL; m = m->m_next) { 403 len += m->m_len; 404 } 405 406 data_len = len; 407 408 DODEBUG(Sent_Pkts, printf("1. Sending packet with %d data bytes. ", data_len);); 409 410 if (len & 1) { 411 len += XMT_HEADER_LEN + 1; 412 } else { 413 len += XMT_HEADER_LEN; 414 } 415 416 if ((i = sc->tx_tail - sc->tx_head) >= 0) { 417 avail = sc->tx_mem_size - i; 418 } else { 419 avail = -i; 420 } 421 422 DODEBUG(Sent_Pkts, printf("i=%d, avail=%d\n", i, avail);); 423 424 if (avail >= len + XMT_HEADER_LEN) { 425 IF_DEQUEUE(&ifp->if_snd, opkt); 426 427#ifdef EX_PSA_INTR 428 /* 429 * Disable rx and tx interrupts, to avoid corruption 430 * of the host address register by interrupt service 431 * routines. 432 * XXX Is this necessary with splimp() enabled? 433 */ 434 outb(iobase + MASK_REG, All_Int); 435#endif 436 437 /* 438 * Compute the start and end addresses of this 439 * frame in the tx buffer. 440 */ 441 dest = sc->tx_tail; 442 next = dest + len; 443 444 if (next > sc->tx_upper_limit) { 445 if ((sc->tx_upper_limit + 2 - sc->tx_tail) <= 446 XMT_HEADER_LEN) { 447 dest = sc->tx_lower_limit; 448 next = dest + len; 449 } else { 450 next = sc->tx_lower_limit + 451 next - sc->tx_upper_limit - 2; 452 } 453 } 454 455 /* 456 * Build the packet frame in the card's ring buffer. 457 */ 458 DODEBUG(Sent_Pkts, printf("2. dest=%d, next=%d. ", dest, next);); 459 460 outw(iobase + HOST_ADDR_REG, dest); 461 outw(iobase + IO_PORT_REG, Transmit_CMD); 462 outw(iobase + IO_PORT_REG, 0); 463 outw(iobase + IO_PORT_REG, next); 464 outw(iobase + IO_PORT_REG, data_len); 465 466 /* 467 * Output the packet data to the card. Ensure all 468 * transfers are 16-bit wide, even if individual 469 * mbufs have odd length. 470 */ 471 472 for (m = opkt, i = 0; m != NULL; m = m->m_next) { 473 DODEBUG(Sent_Pkts, printf("[%d]", m->m_len);); 474 if (i) { 475 tmp16[1] = *(mtod(m, caddr_t)); 476 outsw(iobase + IO_PORT_REG, tmp16, 1); 477 } 478 outsw(iobase + IO_PORT_REG, 479 mtod(m, caddr_t) + i, (m->m_len - i) / 2); 480 481 if ((i = (m->m_len - i) & 1) != 0) { 482 tmp16[0] = *(mtod(m, caddr_t) + 483 m->m_len - 1); 484 } 485 } 486 if (i) { 487 outsw(iobase + IO_PORT_REG, tmp16, 1); 488 } 489 490 /* 491 * If there were other frames chained, update the 492 * chain in the last one. 493 */ 494 if (sc->tx_head != sc->tx_tail) { 495 if (sc->tx_tail != dest) { 496 outw(iobase + HOST_ADDR_REG, 497 sc->tx_last + XMT_Chain_Point); 498 outw(iobase + IO_PORT_REG, dest); 499 } 500 outw(iobase + HOST_ADDR_REG, 501 sc->tx_last + XMT_Byte_Count); 502 i = inw(iobase + IO_PORT_REG); 503 outw(iobase + HOST_ADDR_REG, 504 sc->tx_last + XMT_Byte_Count); 505 outw(iobase + IO_PORT_REG, i | Ch_bit); 506 } 507 508 /* 509 * Resume normal operation of the card: 510 * - Make a dummy read to flush the DRAM write 511 * pipeline. 512 * - Enable receive and transmit interrupts. 513 * - Send Transmit or Resume_XMT command, as 514 * appropriate. 515 */ 516 inw(iobase + IO_PORT_REG); 517#ifdef EX_PSA_INTR 518 outb(iobase + MASK_REG, All_Int & ~(Rx_Int | Tx_Int)); 519#endif 520 if (sc->tx_head == sc->tx_tail) { 521 outw(iobase + XMT_BAR, dest); 522 outb(iobase + CMD_REG, Transmit_CMD); 523 sc->tx_head = dest; 524 DODEBUG(Sent_Pkts, printf("Transmit\n");); 525 } else { 526 outb(iobase + CMD_REG, Resume_XMT_List_CMD); 527 DODEBUG(Sent_Pkts, printf("Resume\n");); 528 } 529 530 sc->tx_last = dest; 531 sc->tx_tail = next; 532 533 BPF_MTAP(ifp, opkt); 534 535 ifp->if_timer = 2; 536 ifp->if_opackets++; 537 m_freem(opkt); 538 } else { 539 ifp->if_flags |= IFF_OACTIVE; 540 DODEBUG(Status, printf("OACTIVE start\n");); 541 } 542 } 543 544 splx(s); 545 546 DODEBUG(Start_End, printf("ex_start%d: finish\n", unit);); 547} 548 549void 550ex_stop(struct ex_softc *sc) 551{ 552 int iobase = sc->iobase; 553 554 DODEBUG(Start_End, printf("ex_stop%d: start\n", unit);); 555 556 /* 557 * Disable card operation: 558 * - Disable the interrupt line. 559 * - Flush transmission and disable reception. 560 * - Mask and clear all interrupts. 561 * - Reset the 82595. 562 */ 563 outb(iobase + CMD_REG, Bank1_Sel); 564 outb(iobase + REG1, inb(iobase + REG1) & ~TriST_INT); 565 outb(iobase + CMD_REG, Bank0_Sel); 566 outb(iobase + CMD_REG, Rcv_Stop); 567 sc->tx_head = sc->tx_tail = sc->tx_lower_limit; 568 sc->tx_last = 0; /* XXX I think these two lines are not necessary, because ex_init will always be called again to reinit the interface. */ 569 outb(iobase + MASK_REG, All_Int); 570 outb(iobase + STATUS_REG, All_Int); 571 outb(iobase + CMD_REG, Reset_CMD); 572 DELAY(200); 573 574 DODEBUG(Start_End, printf("ex_stop%d: finish\n", unit);); 575 576 return; 577} 578 579void 580ex_intr(void *arg) 581{ 582 struct ex_softc * sc = (struct ex_softc *)arg; 583 struct ifnet * ifp = &sc->arpcom.ac_if; 584 int iobase = sc->iobase; 585 int int_status, send_pkts; 586 587 DODEBUG(Start_End, printf("ex_intr%d: start\n", unit);); 588 589#ifdef EXDEBUG 590 if (++exintr_count != 1) 591 printf("WARNING: nested interrupt (%d). Mail the author.\n", exintr_count); 592#endif 593 594 send_pkts = 0; 595 while ((int_status = inb(iobase + STATUS_REG)) & (Tx_Int | Rx_Int)) { 596 if (int_status & Rx_Int) { 597 outb(iobase + STATUS_REG, Rx_Int); 598 599 ex_rx_intr(sc); 600 } else if (int_status & Tx_Int) { 601 outb(iobase + STATUS_REG, Tx_Int); 602 603 ex_tx_intr(sc); 604 send_pkts = 1; 605 } 606 } 607 608 /* 609 * If any packet has been transmitted, and there are queued packets to 610 * be sent, attempt to send more packets to the network card. 611 */ 612 613 if (send_pkts && (ifp->if_snd.ifq_head != NULL)) { 614 ex_start(ifp); 615 } 616 617#ifdef EXDEBUG 618 exintr_count--; 619#endif 620 621 DODEBUG(Start_End, printf("ex_intr%d: finish\n", unit);); 622 623 return; 624} 625 626static void 627ex_tx_intr(struct ex_softc *sc) 628{ 629 struct ifnet * ifp = &sc->arpcom.ac_if; 630 int iobase = sc->iobase; 631 int tx_status; 632 633 DODEBUG(Start_End, printf("ex_tx_intr%d: start\n", unit);); 634 635 /* 636 * - Cancel the watchdog. 637 * For all packets transmitted since last transmit interrupt: 638 * - Advance chain pointer to next queued packet. 639 * - Update statistics. 640 */ 641 642 ifp->if_timer = 0; 643 644 while (sc->tx_head != sc->tx_tail) { 645 outw(iobase + HOST_ADDR_REG, sc->tx_head); 646 647 if (! inw(iobase + IO_PORT_REG) & Done_bit) 648 break; 649 650 tx_status = inw(iobase + IO_PORT_REG); 651 sc->tx_head = inw(iobase + IO_PORT_REG); 652 653 if (tx_status & TX_OK_bit) { 654 ifp->if_opackets++; 655 } else { 656 ifp->if_oerrors++; 657 } 658 659 ifp->if_collisions += tx_status & No_Collisions_bits; 660 } 661 662 /* 663 * The card should be ready to accept more packets now. 664 */ 665 666 ifp->if_flags &= ~IFF_OACTIVE; 667 668 DODEBUG(Status, printf("OIDLE tx_intr\n");); 669 DODEBUG(Start_End, printf("ex_tx_intr%d: finish\n", unit);); 670 671 return; 672} 673 674static void 675ex_rx_intr(struct ex_softc *sc) 676{ 677 struct ifnet * ifp = &sc->arpcom.ac_if; 678 int iobase = sc->iobase; 679 int rx_status; 680 int pkt_len; 681 int QQQ; 682 struct mbuf * m; 683 struct mbuf * ipkt; 684 struct ether_header * eh; 685 686 DODEBUG(Start_End, printf("ex_rx_intr%d: start\n", unit);); 687 688 /* 689 * For all packets received since last receive interrupt: 690 * - If packet ok, read it into a new mbuf and queue it to interface, 691 * updating statistics. 692 * - If packet bad, just discard it, and update statistics. 693 * Finally, advance receive stop limit in card's memory to new location. 694 */ 695 696 outw(iobase + HOST_ADDR_REG, sc->rx_head); 697 698 while (inw(iobase + IO_PORT_REG) == RCV_Done) { 699 700 rx_status = inw(iobase + IO_PORT_REG); 701 sc->rx_head = inw(iobase + IO_PORT_REG); 702 QQQ = pkt_len = inw(iobase + IO_PORT_REG); 703 704 if (rx_status & RCV_OK_bit) { 705 MGETHDR(m, M_DONTWAIT, MT_DATA); 706 ipkt = m; 707 if (ipkt == NULL) { 708 ifp->if_iqdrops++; 709 } else { 710 ipkt->m_pkthdr.rcvif = ifp; 711 ipkt->m_pkthdr.len = pkt_len; 712 ipkt->m_len = MHLEN; 713 714 while (pkt_len > 0) { 715 if (pkt_len > MINCLSIZE) { 716 MCLGET(m, M_DONTWAIT); 717 if (m->m_flags & M_EXT) { 718 m->m_len = MCLBYTES; 719 } else { 720 m_freem(ipkt); 721 ifp->if_iqdrops++; 722 goto rx_another; 723 } 724 } 725 m->m_len = min(m->m_len, pkt_len); 726 727 /* 728 * NOTE: I'm assuming that all mbufs allocated are of even length, 729 * except for the last one in an odd-length packet. 730 */ 731 732 insw(iobase + IO_PORT_REG, 733 mtod(m, caddr_t), m->m_len / 2); 734 735 if (m->m_len & 1) { 736 *(mtod(m, caddr_t) + m->m_len - 1) = inb(iobase + IO_PORT_REG); 737 } 738 pkt_len -= m->m_len; 739 740 if (pkt_len > 0) { 741 MGET(m->m_next, M_DONTWAIT, MT_DATA); 742 if (m->m_next == NULL) { 743 m_freem(ipkt); 744 ifp->if_iqdrops++; 745 goto rx_another; 746 } 747 m = m->m_next; 748 m->m_len = MLEN; 749 } 750 } 751 eh = mtod(ipkt, struct ether_header *); 752#ifdef EXDEBUG 753 if (debug_mask & Rcvd_Pkts) { 754 if ((eh->ether_dhost[5] != 0xff) || (eh->ether_dhost[0] != 0xff)) { 755 printf("Receive packet with %d data bytes: %6D -> ", QQQ, eh->ether_shost, ":"); 756 printf("%6D\n", eh->ether_dhost, ":"); 757 } /* QQQ */ 758 } 759#endif 760 (*ifp->if_input)(ifp, ipkt); 761 ifp->if_ipackets++; 762 } 763 } else { 764 ifp->if_ierrors++; 765 } 766 outw(iobase + HOST_ADDR_REG, sc->rx_head); 767rx_another: ; 768 } 769 770 if (sc->rx_head < sc->rx_lower_limit + 2) 771 outw(iobase + RCV_STOP_REG, sc->rx_upper_limit); 772 else 773 outw(iobase + RCV_STOP_REG, sc->rx_head - 2); 774 775 DODEBUG(Start_End, printf("ex_rx_intr%d: finish\n", unit);); 776 777 return; 778} 779 780 781static int 782ex_ioctl(register struct ifnet *ifp, u_long cmd, caddr_t data) 783{ 784 struct ex_softc * sc = ifp->if_softc; 785 struct ifreq * ifr = (struct ifreq *)data; 786 int s; 787 int error = 0; 788 789 DODEBUG(Start_End, printf("ex_ioctl%d: start ", ifp->if_unit);); 790 791 s = splimp(); 792 793 switch(cmd) { 794 case SIOCSIFADDR: 795 case SIOCGIFADDR: 796 case SIOCSIFMTU: 797 error = ether_ioctl(ifp, cmd, data); 798 break; 799 800 case SIOCSIFFLAGS: 801 DODEBUG(Start_End, printf("SIOCSIFFLAGS");); 802 if ((ifp->if_flags & IFF_UP) == 0 && 803 (ifp->if_flags & IFF_RUNNING)) { 804 805 ifp->if_flags &= ~IFF_RUNNING; 806 ex_stop(sc); 807 } else { 808 ex_init(sc); 809 } 810 break; 811#ifdef NODEF 812 case SIOCGHWADDR: 813 DODEBUG(Start_End, printf("SIOCGHWADDR");); 814 bcopy((caddr_t)sc->sc_addr, (caddr_t)&ifr->ifr_data, 815 sizeof(sc->sc_addr)); 816 break; 817#endif 818 case SIOCADDMULTI: 819 case SIOCDELMULTI: 820 ex_init(sc); 821 error = 0; 822 break; 823 case SIOCSIFMEDIA: 824 case SIOCGIFMEDIA: 825 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, cmd); 826 break; 827 default: 828 DODEBUG(Start_End, printf("unknown");); 829 error = EINVAL; 830 } 831 832 splx(s); 833 834 DODEBUG(Start_End, printf("\nex_ioctl%d: finish\n", ifp->if_unit);); 835 836 return(error); 837} 838 839static void 840ex_setmulti(struct ex_softc *sc) 841{ 842 struct ifnet *ifp; 843 struct ifmultiaddr *maddr; 844 u_int16_t *addr; 845 int iobase = sc->iobase; 846 int count; 847 int timeout, status; 848 849 ifp = &sc->arpcom.ac_if; 850 851 count = 0; 852 TAILQ_FOREACH(maddr, &ifp->if_multiaddrs, ifma_link) { 853 if (maddr->ifma_addr->sa_family != AF_LINK) 854 continue; 855 count++; 856 } 857 858 if ((ifp->if_flags & IFF_PROMISC) || (ifp->if_flags & IFF_ALLMULTI) 859 || count > 63) { 860 /* Interface is in promiscuous mode or there are too many 861 * multicast addresses for the card to handle */ 862 outb(iobase + CMD_REG, Bank2_Sel); 863 outb(iobase + REG2, inb(iobase + REG2) | Promisc_Mode); 864 outb(iobase + REG3, inb(iobase + REG3)); 865 outb(iobase + CMD_REG, Bank0_Sel); 866 } 867 else if ((ifp->if_flags & IFF_MULTICAST) && (count > 0)) { 868 /* Program multicast addresses plus our MAC address 869 * into the filter */ 870 outb(iobase + CMD_REG, Bank2_Sel); 871 outb(iobase + REG2, inb(iobase + REG2) | Multi_IA); 872 outb(iobase + REG3, inb(iobase + REG3)); 873 outb(iobase + CMD_REG, Bank0_Sel); 874 875 /* Borrow space from TX buffer; this should be safe 876 * as this is only called from ex_init */ 877 878 outw(iobase + HOST_ADDR_REG, sc->tx_lower_limit); 879 outw(iobase + IO_PORT_REG, MC_Setup_CMD); 880 outw(iobase + IO_PORT_REG, 0); 881 outw(iobase + IO_PORT_REG, 0); 882 outw(iobase + IO_PORT_REG, (count + 1) * 6); 883 884 TAILQ_FOREACH(maddr, &ifp->if_multiaddrs, ifma_link) { 885 if (maddr->ifma_addr->sa_family != AF_LINK) 886 continue; 887 888 addr = (u_int16_t*)LLADDR((struct sockaddr_dl *) 889 maddr->ifma_addr); 890 outw(iobase + IO_PORT_REG, *addr++); 891 outw(iobase + IO_PORT_REG, *addr++); 892 outw(iobase + IO_PORT_REG, *addr++); 893 } 894 895 /* Program our MAC address as well */ 896 /* XXX: Is this necessary? The Linux driver does this 897 * but the NetBSD driver does not */ 898 addr = (u_int16_t*)(&sc->arpcom.ac_enaddr); 899 outw(iobase + IO_PORT_REG, *addr++); 900 outw(iobase + IO_PORT_REG, *addr++); 901 outw(iobase + IO_PORT_REG, *addr++); 902 903 inw(iobase + IO_PORT_REG); 904 outw(iobase + XMT_BAR, sc->tx_lower_limit); 905 outb(iobase + CMD_REG, MC_Setup_CMD); 906 907 sc->tx_head = sc->tx_lower_limit; 908 sc->tx_tail = sc->tx_head + XMT_HEADER_LEN + (count + 1) * 6; 909 910 for (timeout=0; timeout<100; timeout++) { 911 DELAY(2); 912 if ((inb(iobase + STATUS_REG) & Exec_Int) == 0) 913 continue; 914 915 status = inb(iobase + CMD_REG); 916 outb(iobase + STATUS_REG, Exec_Int); 917 break; 918 } 919 920 sc->tx_head = sc->tx_tail; 921 } 922 else 923 { 924 /* No multicast or promiscuous mode */ 925 outb(iobase + CMD_REG, Bank2_Sel); 926 outb(iobase + REG2, inb(iobase + REG2) & 0xDE); 927 /* ~(Multi_IA | Promisc_Mode) */ 928 outb(iobase + REG3, inb(iobase + REG3)); 929 outb(iobase + CMD_REG, Bank0_Sel); 930 } 931} 932 933static void 934ex_reset(struct ex_softc *sc) 935{ 936 int s; 937 938 DODEBUG(Start_End, printf("ex_reset%d: start\n", unit);); 939 940 s = splimp(); 941 942 ex_stop(sc); 943 ex_init(sc); 944 945 splx(s); 946 947 DODEBUG(Start_End, printf("ex_reset%d: finish\n", unit);); 948 949 return; 950} 951 952static void 953ex_watchdog(struct ifnet *ifp) 954{ 955 struct ex_softc * sc = ifp->if_softc; 956 957 DODEBUG(Start_End, printf("ex_watchdog%d: start\n", ifp->if_unit);); 958 959 ifp->if_flags &= ~IFF_OACTIVE; 960 961 DODEBUG(Status, printf("OIDLE watchdog\n");); 962 963 ifp->if_oerrors++; 964 ex_reset(sc); 965 ex_start(ifp); 966 967 DODEBUG(Start_End, printf("ex_watchdog%d: finish\n", ifp->if_unit);); 968 969 return; 970} 971 972static int 973ex_get_media (u_int32_t iobase) 974{ 975 int current; 976 int media; 977 978 media = eeprom_read(iobase, EE_W5); 979 980 outb(iobase + CMD_REG, Bank2_Sel); 981 current = inb(iobase + REG3); 982 outb(iobase + CMD_REG, Bank0_Sel); 983 984 if ((current & TPE_bit) && (media & EE_W5_PORT_TPE)) 985 return(IFM_ETHER|IFM_10_T); 986 if ((current & BNC_bit) && (media & EE_W5_PORT_BNC)) 987 return(IFM_ETHER|IFM_10_2); 988 989 if (media & EE_W5_PORT_AUI) 990 return (IFM_ETHER|IFM_10_5); 991 992 return (IFM_ETHER|IFM_AUTO); 993} 994 995static int 996ex_ifmedia_upd (ifp) 997 struct ifnet * ifp; 998{ 999 struct ex_softc * sc = ifp->if_softc; 1000 1001 if (IFM_TYPE(sc->ifmedia.ifm_media) != IFM_ETHER) 1002 return EINVAL; 1003 1004 return (0); 1005} 1006 1007static void 1008ex_ifmedia_sts(ifp, ifmr) 1009 struct ifnet * ifp; 1010 struct ifmediareq * ifmr; 1011{ 1012 struct ex_softc * sc = ifp->if_softc; 1013 1014 ifmr->ifm_active = ex_get_media(sc->iobase); 1015 ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE; 1016 1017 return; 1018} 1019 1020u_short 1021eeprom_read(u_int32_t iobase, int location) 1022{ 1023 int i; 1024 u_short data = 0; 1025 int ee_addr; 1026 int read_cmd = location | EE_READ_CMD; 1027 short ctrl_val = EECS; 1028 1029 ee_addr = iobase + EEPROM_REG; 1030 outb(iobase + CMD_REG, Bank2_Sel); 1031 outb(ee_addr, EECS); 1032 for (i = 8; i >= 0; i--) { 1033 short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI : ctrl_val; 1034 outb(ee_addr, outval); 1035 outb(ee_addr, outval | EESK); 1036 DELAY(3); 1037 outb(ee_addr, outval); 1038 DELAY(2); 1039 } 1040 outb(ee_addr, ctrl_val); 1041 1042 for (i = 16; i > 0; i--) { 1043 outb(ee_addr, ctrl_val | EESK); 1044 DELAY(3); 1045 data = (data << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0); 1046 outb(ee_addr, ctrl_val); 1047 DELAY(2); 1048 } 1049 1050 ctrl_val &= ~EECS; 1051 outb(ee_addr, ctrl_val | EESK); 1052 DELAY(3); 1053 outb(ee_addr, ctrl_val); 1054 DELAY(2); 1055 outb(iobase + CMD_REG, Bank0_Sel); 1056 return(data); 1057} 1058