if_ex.c revision 55881
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 55881 2000-01-13 06:46:02Z 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 * 30-Oct-1996: first beta version. Inet and BPF supported, but no multicast. 39 */ 40 41#include "ex.h" 42#if NEX > 0 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/kernel.h> 47#include <sys/conf.h> 48#include <sys/sockio.h> 49#include <sys/mbuf.h> 50#include <sys/socket.h> 51 52#include <sys/module.h> 53#include <sys/bus.h> 54 55#include <machine/bus.h> 56#include <machine/resource.h> 57#include <sys/rman.h> 58 59#include <net/ethernet.h> 60#include <net/if.h> 61 62#include <netinet/in.h> 63#include <netinet/if_ether.h> 64 65#include <net/bpf.h> 66 67#include <machine/clock.h> 68 69#include <isa/isavar.h> 70#include <isa/pnpvar.h> 71 72#include <i386/isa/if_exreg.h> 73 74#ifdef EXDEBUG 75# define Start_End 1 76# define Rcvd_Pkts 2 77# define Sent_Pkts 4 78# define Status 8 79static int debug_mask = 0; 80static int exintr_count = 0; 81# define DODEBUG(level, action) if (level & debug_mask) action 82#else 83# define DODEBUG(level, action) 84#endif 85 86#define Conn_BNC 1 87#define Conn_TPE 2 88#define Conn_AUI 3 89 90#define CARD_TYPE_EX_10 1 91#define CARD_TYPE_EX_10_PLUS 2 92 93struct ex_softc { 94 struct arpcom arpcom; /* Ethernet common data */ 95 96 device_t dev; 97 struct resource *ioport; 98 struct resource *irq; 99 100 u_int iobase; /* I/O base address. */ 101 u_short irq_no; /* IRQ number. */ 102 103 char * irq2ee; /* irq <-> internal */ 104 u_char * ee2irq; /* representation conversion */ 105 106 u_short connector; /* Connector type. */ 107 108 u_int mem_size; /* Total memory size, in bytes. */ 109 u_int rx_mem_size; /* Rx memory size (by default, */ 110 /* first 3/4 of total memory). */ 111 112 u_int rx_lower_limit; /* Lower and upper limits of */ 113 u_int rx_upper_limit; /* receive buffer. */ 114 115 u_int rx_head; /* Head of receive ring buffer. */ 116 u_int tx_mem_size; /* Tx memory size (by default, */ 117 /* last quarter of total memory).*/ 118 119 u_int tx_lower_limit; /* Lower and upper limits of */ 120 u_int tx_upper_limit; /* transmit buffer. */ 121 122 u_int tx_head; /* Head and tail of */ 123 u_int tx_tail; /* transmit ring buffer. */ 124 125 u_int tx_last; /* Pointer to beginning of last */ 126 /* frame in the chain. */ 127}; 128 129static char irq2eemap[] = 130 { -1, -1, 0, 1, -1, 2, -1, -1, -1, 0, 3, 4, -1, -1, -1, -1 }; 131static u_char ee2irqmap[] = 132 { 9, 3, 5, 10, 11, 0, 0, 0 }; 133 134static char plus_irq2eemap[] = 135 { -1, -1, -1, 0, 1, 2, -1, 3, -1, 4, 5, 6, 7, -1, -1, -1 }; 136static u_char plus_ee2irqmap[] = 137 { 3, 4, 5, 7, 9, 10, 11, 12 }; 138 139/* Bus Front End Functions */ 140static int ex_isa_probe __P((device_t)); 141static int ex_attach __P((device_t)); 142 143/* Network Interface Functions */ 144static void ex_init __P((void *)); 145static void ex_start __P((struct ifnet *)); 146static int ex_ioctl __P((struct ifnet *, u_long, caddr_t)); 147static void ex_watchdog __P((struct ifnet *)); 148 149static void ex_stop __P((struct ex_softc *)); 150static void ex_reset __P((struct ex_softc *)); 151 152static driver_intr_t exintr; 153static void ex_tx_intr __P((struct ex_softc *)); 154static void ex_rx_intr __P((struct ex_softc *)); 155 156static u_short eeprom_read __P((int, int)); 157 158static device_method_t ex_methods[] = { 159 /* Device interface */ 160 DEVMETHOD(device_probe, ex_isa_probe), 161 DEVMETHOD(device_attach, ex_attach), 162 163 { 0, 0 } 164}; 165 166static driver_t ex_driver = { 167 "ex", 168 ex_methods, 169 sizeof(struct ex_softc), 170}; 171 172static devclass_t ex_devclass; 173 174DRIVER_MODULE(ex, isa, ex_driver, ex_devclass, 0, 0); 175 176static struct isa_pnp_id ex_ids[] = { 177 { 0x3110d425, NULL }, /* INT1031 */ 178 { 0x3010d425, NULL }, /* INT1030 */ 179 { 0, NULL }, 180}; 181 182static int look_for_card(u_int iobase) 183{ 184 int count1, count2; 185 186 /* 187 * Check for the i82595 signature, and check that the round robin 188 * counter actually advances. 189 */ 190 if (((count1 = inb(iobase + ID_REG)) & Id_Mask) != Id_Sig) 191 return(0); 192 count2 = inb(iobase + ID_REG); 193 count2 = inb(iobase + ID_REG); 194 count2 = inb(iobase + ID_REG); 195 196 return((count2 & Counter_bits) == ((count1 + 0xc0) & Counter_bits)); 197} 198 199static int 200ex_get_media (u_int32_t iobase) 201{ 202 int tmp; 203 204 outb(iobase + CMD_REG, Bank2_Sel); 205 tmp = inb(iobase + REG3); 206 outb(iobase + CMD_REG, Bank0_Sel); 207 208 if (tmp & TPE_bit) 209 return(Conn_TPE); 210 if (tmp & BNC_bit) 211 return(Conn_BNC); 212 213 return (Conn_AUI); 214} 215 216static void 217ex_get_address (u_int32_t iobase, u_char *enaddr) 218{ 219 u_int16_t eaddr_tmp; 220 221 eaddr_tmp = eeprom_read(iobase, EE_Eth_Addr_Lo); 222 enaddr[5] = eaddr_tmp & 0xff; 223 enaddr[4] = eaddr_tmp >> 8; 224 eaddr_tmp = eeprom_read(iobase, EE_Eth_Addr_Mid); 225 enaddr[3] = eaddr_tmp & 0xff; 226 enaddr[2] = eaddr_tmp >> 8; 227 eaddr_tmp = eeprom_read(iobase, EE_Eth_Addr_Hi); 228 enaddr[1] = eaddr_tmp & 0xff; 229 enaddr[0] = eaddr_tmp >> 8; 230 231 return; 232} 233 234static int 235ex_card_type (u_char *enaddr) 236{ 237 if ((enaddr[0] == 0x00) && (enaddr[1] == 0xA0) && (enaddr[2] == 0xC9)) 238 return (CARD_TYPE_EX_10_PLUS); 239 240 return (CARD_TYPE_EX_10); 241} 242 243static int 244ex_isa_probe(device_t dev) 245{ 246 u_int iobase; 247 u_int irq; 248 char * irq2ee; 249 u_char * ee2irq; 250 u_char enaddr[6]; 251 int tmp; 252 int error; 253 254 DODEBUG(Start_End, printf("ex_probe: start\n");); 255 256 /* Check isapnp ids */ 257 error = ISA_PNP_PROBE(device_get_parent(dev), dev, ex_ids); 258 259 /* If the card had a PnP ID that didn't match any we know about */ 260 if (error == ENXIO) { 261 return(error); 262 } 263 264 /* If we had some other problem. */ 265 if (!(error == 0 || error == ENOENT)) { 266 return(error); 267 } 268 269 /* 270 * If an I/O address was supplied in the configuration file 271 * or by PnP ,probe only that. Otherwise, cycle through the 272 * predefined set of possible addresses. 273 * This should really be a bus enumerator ala DEVICE_IDENTFY() 274 */ 275 iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0); 276 if (iobase != 0) { 277 if (! look_for_card(iobase)) { 278 printf("ex: no card found at 0x%03x\n", iobase); 279 return(ENXIO); 280 } 281 } else { 282 for (iobase = 0x200; iobase < 0x3a0; iobase += 0x10) { 283 if (look_for_card(iobase)) 284 break; 285 } 286 if (iobase >= 0x3a0) { 287 return(ENXIO); 288 } else { 289 bus_set_resource(dev, SYS_RES_IOPORT, 0, 290 iobase, EX_IOSIZE); 291 } 292 } 293 294 /* 295 * Reset the card. 296 */ 297 outb(iobase + CMD_REG, Reset_CMD); 298 DELAY(400); 299 300 ex_get_address(iobase, enaddr); 301 302 /* work out which set of irq <-> internal tables to use */ 303 if (ex_card_type(enaddr) == CARD_TYPE_EX_10_PLUS) { 304 irq2ee = plus_irq2eemap; 305 ee2irq = plus_ee2irqmap; 306 } else { 307 irq2ee = irq2eemap; 308 ee2irq = ee2irqmap; 309 } 310 311 tmp = eeprom_read(iobase, EE_IRQ_No) & IRQ_No_Mask; 312 irq = bus_get_resource_start(dev, SYS_RES_IRQ, 0); 313 314 if (irq > 0) { 315 if (ee2irq[tmp] != irq) { 316 printf("ex: WARNING: board's EEPROM is configured" 317 " for IRQ %d, using %d\n", 318 ee2irq[tmp], irq); 319 } 320 } else { 321 irq = ee2irq[tmp]; 322 bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1); 323 } 324 325 if (irq == 0) { 326 printf("ex: invalid IRQ.\n"); 327 return(ENXIO); 328 } 329 330 DODEBUG(Start_End, printf("ex_probe: finish\n");); 331 332 return(0); 333} 334 335 336int ex_attach(device_t dev) 337{ 338 struct ex_softc * sc = device_get_softc(dev); 339 struct ifnet * ifp = &sc->arpcom.ac_if; 340 int unit = device_get_unit(dev); 341 int error; 342 int rid; 343 void * ih; 344 345 DODEBUG(Start_End, device_printf(dev, "start\n");); 346 347 rid = 0; 348 sc->ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 349 0, ~0, 1, RF_ACTIVE); 350 351 if (!sc->ioport) { 352 device_printf(dev, "No I/O space?!\n"); 353 goto bad; 354 } 355 356 rid = 0; 357 sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 358 0, ~0, 1, RF_ACTIVE); 359 360 if (!sc->irq) { 361 device_printf(dev, "No IRQ?!\n"); 362 goto bad; 363 } 364 365 error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, 366 exintr, (void *)sc, &ih); 367 368 if (error) { 369 device_printf(dev, "bus_setup_intr() failed!\n"); 370 goto bad; 371 } 372 373 /* 374 * Fill in several fields of the softc structure: 375 * - I/O base address. 376 * - Hardware Ethernet address. 377 * - IRQ number (if not supplied in config file, read it from EEPROM). 378 * - Connector type. 379 */ 380 sc->dev = dev; 381 sc->iobase = rman_get_start(sc->ioport); 382 sc->irq_no = rman_get_start(sc->irq); 383 384 ex_get_address(sc->iobase, sc->arpcom.ac_enaddr); 385 386 /* work out which set of irq <-> internal tables to use */ 387 if (ex_card_type(sc->arpcom.ac_enaddr) == CARD_TYPE_EX_10_PLUS) { 388 sc->irq2ee = plus_irq2eemap; 389 sc->ee2irq = plus_ee2irqmap; 390 } else { 391 sc->irq2ee = irq2eemap; 392 sc->ee2irq = ee2irqmap; 393 } 394 395 sc->connector = ex_get_media(sc->iobase); 396 sc->mem_size = CARD_RAM_SIZE; /* XXX This should be read from the card itself. */ 397 398 /* 399 * Initialize the ifnet structure. 400 */ 401 ifp->if_softc = sc; 402 ifp->if_unit = unit; 403 ifp->if_name = "ex"; 404 ifp->if_init = ex_init; 405 ifp->if_output = ether_output; 406 ifp->if_start = ex_start; 407 ifp->if_ioctl = ex_ioctl; 408 ifp->if_watchdog = ex_watchdog; 409 ifp->if_mtu = ETHERMTU; 410 ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST 411 /* XXX not done yet. | IFF_MULTICAST */; 412 413 /* 414 * Attach the interface. 415 */ 416 if_attach(ifp); 417 ether_ifattach(ifp); 418 419 if (ex_card_type(sc->arpcom.ac_enaddr) == CARD_TYPE_EX_10_PLUS) { 420 printf("ex%d: Intel EtherExpress Pro/10+, address %6D, connector ", unit, sc->arpcom.ac_enaddr, ":"); 421 } else { 422 printf("ex%d: Intel EtherExpress Pro/10, address %6D, connector ", unit, sc->arpcom.ac_enaddr, ":"); 423 } 424 switch(sc->connector) { 425 case Conn_TPE: printf("TPE\n"); break; 426 case Conn_BNC: printf("BNC\n"); break; 427 case Conn_AUI: printf("AUI\n"); break; 428 default: printf("???\n"); 429 } 430 431 /* 432 * If BPF is in the kernel, call the attach for it 433 */ 434 bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); 435 DODEBUG(Start_End, printf("ex_attach%d: finish\n", unit);); 436 sc->arpcom.ac_if.if_snd.ifq_maxlen = ifqmaxlen; 437 438 return(0); 439 440bad: 441 442 if (sc->ioport) 443 bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->ioport); 444 if (sc->irq) 445 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); 446 447 return (-1); 448} 449 450 451void ex_init(void *xsc) 452{ 453 struct ex_softc * sc = (struct ex_softc *) xsc; 454 struct ifnet * ifp = &sc->arpcom.ac_if; 455 int s; 456 int i; 457 register int iobase = sc->iobase; 458 unsigned short temp_reg; 459 460 DODEBUG(Start_End, printf("ex_init%d: start\n", ifp->if_unit);); 461 462 if (ifp->if_addrhead.tqh_first == NULL) { 463 return; 464 } 465 s = splimp(); 466 sc->arpcom.ac_if.if_timer = 0; 467 468 /* 469 * Load the ethernet address into the card. 470 */ 471 outb(iobase + CMD_REG, Bank2_Sel); 472 temp_reg = inb(iobase + EEPROM_REG); 473 if (temp_reg & Trnoff_Enable) { 474 outb(iobase + EEPROM_REG, temp_reg & ~Trnoff_Enable); 475 } 476 for (i = 0; i < ETHER_ADDR_LEN; i++) { 477 outb(iobase + I_ADDR_REG0 + i, sc->arpcom.ac_enaddr[i]); 478 } 479 /* 480 * - Setup transmit chaining and discard bad received frames. 481 * - Match broadcast. 482 * - Clear test mode. 483 * - Set receiving mode. 484 * - Set IRQ number. 485 */ 486 outb(iobase + REG1, inb(iobase + REG1) | Tx_Chn_Int_Md | Tx_Chn_ErStp | Disc_Bad_Fr); 487 outb(iobase + REG2, inb(iobase + REG2) | No_SA_Ins | RX_CRC_InMem); 488 outb(iobase + REG3, inb(iobase + REG3) & 0x3f /* XXX constants. */ ); 489 outb(iobase + CMD_REG, Bank1_Sel); 490 outb(iobase + INT_NO_REG, (inb(iobase + INT_NO_REG) & 0xf8) | sc->irq2ee[sc->irq_no]); 491 492 /* 493 * Divide the available memory in the card into rcv and xmt buffers. 494 * By default, I use the first 3/4 of the memory for the rcv buffer, 495 * and the remaining 1/4 of the memory for the xmt buffer. 496 */ 497 sc->rx_mem_size = sc->mem_size * 3 / 4; 498 sc->tx_mem_size = sc->mem_size - sc->rx_mem_size; 499 sc->rx_lower_limit = 0x0000; 500 sc->rx_upper_limit = sc->rx_mem_size - 2; 501 sc->tx_lower_limit = sc->rx_mem_size; 502 sc->tx_upper_limit = sc->mem_size - 2; 503 outb(iobase + RCV_LOWER_LIMIT_REG, sc->rx_lower_limit >> 8); 504 outb(iobase + RCV_UPPER_LIMIT_REG, sc->rx_upper_limit >> 8); 505 outb(iobase + XMT_LOWER_LIMIT_REG, sc->tx_lower_limit >> 8); 506 outb(iobase + XMT_UPPER_LIMIT_REG, sc->tx_upper_limit >> 8); 507 508 /* 509 * Enable receive and transmit interrupts, and clear any pending int. 510 */ 511 outb(iobase + REG1, inb(iobase + REG1) | TriST_INT); 512 outb(iobase + CMD_REG, Bank0_Sel); 513 outb(iobase + MASK_REG, All_Int & ~(Rx_Int | Tx_Int)); 514 outb(iobase + STATUS_REG, All_Int); 515 516 /* 517 * Initialize receive and transmit ring buffers. 518 */ 519 outw(iobase + RCV_BAR, sc->rx_lower_limit); 520 sc->rx_head = sc->rx_lower_limit; 521 outw(iobase + RCV_STOP_REG, sc->rx_upper_limit | 0xfe); 522 outw(iobase + XMT_BAR, sc->tx_lower_limit); 523 sc->tx_head = sc->tx_tail = sc->tx_lower_limit; 524 525 ifp->if_flags |= IFF_RUNNING; 526 ifp->if_flags &= ~IFF_OACTIVE; 527 DODEBUG(Status, printf("OIDLE init\n");); 528 529 /* 530 * Final reset of the board, and enable operation. 531 */ 532 outb(iobase + CMD_REG, Sel_Reset_CMD); 533 DELAY(2); 534 outb(iobase + CMD_REG, Rcv_Enable_CMD); 535 536 ex_start(ifp); 537 splx(s); 538 539 DODEBUG(Start_End, printf("ex_init%d: finish\n", ifp->if_unit);); 540} 541 542 543void 544ex_start(struct ifnet *ifp) 545{ 546 struct ex_softc * sc = ifp->if_softc; 547 int iobase = sc->iobase; 548 int i, s, len, data_len, avail, dest, next; 549 unsigned char tmp16[2]; 550 struct mbuf * opkt; 551 struct mbuf * m; 552 553 DODEBUG(Start_End, printf("ex_start%d: start\n", unit);); 554 555 s = splimp(); 556 557 /* 558 * Main loop: send outgoing packets to network card until there are no 559 * more packets left, or the card cannot accept any more yet. 560 */ 561 while (((opkt = ifp->if_snd.ifq_head) != NULL) && 562 !(ifp->if_flags & IFF_OACTIVE)) { 563 564 /* 565 * Ensure there is enough free transmit buffer space for 566 * this packet, including its header. Note: the header 567 * cannot wrap around the end of the transmit buffer and 568 * must be kept together, so we allow space for twice the 569 * length of the header, just in case. 570 */ 571 572 for (len = 0, m = opkt; m != NULL; m = m->m_next) { 573 len += m->m_len; 574 } 575 576 data_len = len; 577 578 DODEBUG(Sent_Pkts, printf("1. Sending packet with %d data bytes. ", data_len);); 579 580 if (len & 1) { 581 len += XMT_HEADER_LEN + 1; 582 } else { 583 len += XMT_HEADER_LEN; 584 } 585 586 if ((i = sc->tx_tail - sc->tx_head) >= 0) { 587 avail = sc->tx_mem_size - i; 588 } else { 589 avail = -i; 590 } 591 592 DODEBUG(Sent_Pkts, printf("i=%d, avail=%d\n", i, avail);); 593 594 if (avail >= len + XMT_HEADER_LEN) { 595 IF_DEQUEUE(&ifp->if_snd, opkt); 596 597#ifdef EX_PSA_INTR 598 /* 599 * Disable rx and tx interrupts, to avoid corruption 600 * of the host address register by interrupt service 601 * routines. 602 * XXX Is this necessary with splimp() enabled? 603 */ 604 outb(iobase + MASK_REG, All_Int); 605#endif 606 607 /* 608 * Compute the start and end addresses of this 609 * frame in the tx buffer. 610 */ 611 dest = sc->tx_tail; 612 next = dest + len; 613 614 if (next > sc->tx_upper_limit) { 615 if ((sc->tx_upper_limit + 2 - sc->tx_tail) <= 616 XMT_HEADER_LEN) { 617 dest = sc->tx_lower_limit; 618 next = dest + len; 619 } else { 620 next = sc->tx_lower_limit + 621 next - sc->tx_upper_limit - 2; 622 } 623 } 624 625 /* 626 * Build the packet frame in the card's ring buffer. 627 */ 628 DODEBUG(Sent_Pkts, printf("2. dest=%d, next=%d. ", dest, next);); 629 630 outw(iobase + HOST_ADDR_REG, dest); 631 outw(iobase + IO_PORT_REG, Transmit_CMD); 632 outw(iobase + IO_PORT_REG, 0); 633 outw(iobase + IO_PORT_REG, next); 634 outw(iobase + IO_PORT_REG, data_len); 635 636 /* 637 * Output the packet data to the card. Ensure all 638 * transfers are 16-bit wide, even if individual 639 * mbufs have odd length. 640 */ 641 642 for (m = opkt, i = 0; m != NULL; m = m->m_next) { 643 DODEBUG(Sent_Pkts, printf("[%d]", m->m_len);); 644 if (i) { 645 tmp16[1] = *(mtod(m, caddr_t)); 646 outsw(iobase + IO_PORT_REG, tmp16, 1); 647 } 648 outsw(iobase + IO_PORT_REG, 649 mtod(m, caddr_t) + i, (m->m_len - i) / 2); 650 651 if ((i = (m->m_len - i) & 1) != 0) { 652 tmp16[0] = *(mtod(m, caddr_t) + 653 m->m_len - 1); 654 } 655 } 656 if (i) { 657 outsw(iobase + IO_PORT_REG, tmp16, 1); 658 } 659 660 /* 661 * If there were other frames chained, update the 662 * chain in the last one. 663 */ 664 if (sc->tx_head != sc->tx_tail) { 665 if (sc->tx_tail != dest) { 666 outw(iobase + HOST_ADDR_REG, 667 sc->tx_last + XMT_Chain_Point); 668 outw(iobase + IO_PORT_REG, dest); 669 } 670 outw(iobase + HOST_ADDR_REG, 671 sc->tx_last + XMT_Byte_Count); 672 i = inw(iobase + IO_PORT_REG); 673 outw(iobase + HOST_ADDR_REG, 674 sc->tx_last + XMT_Byte_Count); 675 outw(iobase + IO_PORT_REG, i | Ch_bit); 676 } 677 678 /* 679 * Resume normal operation of the card: 680 * - Make a dummy read to flush the DRAM write 681 * pipeline. 682 * - Enable receive and transmit interrupts. 683 * - Send Transmit or Resume_XMT command, as 684 * appropriate. 685 */ 686 inw(iobase + IO_PORT_REG); 687#ifdef EX_PSA_INTR 688 outb(iobase + MASK_REG, All_Int & ~(Rx_Int | Tx_Int)); 689#endif 690 if (sc->tx_head == sc->tx_tail) { 691 outw(iobase + XMT_BAR, dest); 692 outb(iobase + CMD_REG, Transmit_CMD); 693 sc->tx_head = dest; 694 DODEBUG(Sent_Pkts, printf("Transmit\n");); 695 } else { 696 outb(iobase + CMD_REG, Resume_XMT_List_CMD); 697 DODEBUG(Sent_Pkts, printf("Resume\n");); 698 } 699 700 sc->tx_last = dest; 701 sc->tx_tail = next; 702 703 if (ifp->if_bpf != NULL) { 704 bpf_mtap(ifp, opkt); 705 } 706 707 ifp->if_timer = 2; 708 ifp->if_opackets++; 709 m_freem(opkt); 710 } else { 711 ifp->if_flags |= IFF_OACTIVE; 712 DODEBUG(Status, printf("OACTIVE start\n");); 713 } 714 } 715 716 splx(s); 717 718 DODEBUG(Start_End, printf("ex_start%d: finish\n", unit);); 719} 720 721static void 722ex_stop(struct ex_softc *sc) 723{ 724 int iobase = sc->iobase; 725 726 DODEBUG(Start_End, printf("ex_stop%d: start\n", unit);); 727 728 /* 729 * Disable card operation: 730 * - Disable the interrupt line. 731 * - Flush transmission and disable reception. 732 * - Mask and clear all interrupts. 733 * - Reset the 82595. 734 */ 735 outb(iobase + CMD_REG, Bank1_Sel); 736 outb(iobase + REG1, inb(iobase + REG1) & ~TriST_INT); 737 outb(iobase + CMD_REG, Bank0_Sel); 738 outb(iobase + CMD_REG, Rcv_Stop); 739 sc->tx_head = sc->tx_tail = sc->tx_lower_limit; 740 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. */ 741 outb(iobase + MASK_REG, All_Int); 742 outb(iobase + STATUS_REG, All_Int); 743 outb(iobase + CMD_REG, Reset_CMD); 744 DELAY(200); 745 746 DODEBUG(Start_End, printf("ex_stop%d: finish\n", unit);); 747 748 return; 749} 750 751 752static void 753exintr(void *arg) 754{ 755 struct ex_softc * sc = (struct ex_softc *)arg; 756 struct ifnet * ifp = &sc->arpcom.ac_if; 757 int iobase = sc->iobase; 758 int int_status, send_pkts; 759 760 DODEBUG(Start_End, printf("exintr%d: start\n", unit);); 761 762#ifdef EXDEBUG 763 if (++exintr_count != 1) 764 printf("WARNING: nested interrupt (%d). Mail the author.\n", exintr_count); 765#endif 766 767 send_pkts = 0; 768 while ((int_status = inb(iobase + STATUS_REG)) & (Tx_Int | Rx_Int)) { 769 if (int_status & Rx_Int) { 770 outb(iobase + STATUS_REG, Rx_Int); 771 772 ex_rx_intr(sc); 773 } else if (int_status & Tx_Int) { 774 outb(iobase + STATUS_REG, Tx_Int); 775 776 ex_tx_intr(sc); 777 send_pkts = 1; 778 } 779 } 780 781 /* 782 * If any packet has been transmitted, and there are queued packets to 783 * be sent, attempt to send more packets to the network card. 784 */ 785 786 if (send_pkts && (ifp->if_snd.ifq_head != NULL)) { 787 ex_start(ifp); 788 } 789 790#ifdef EXDEBUG 791 exintr_count--; 792#endif 793 794 DODEBUG(Start_End, printf("exintr%d: finish\n", unit);); 795 796 return; 797} 798 799static void 800ex_tx_intr(struct ex_softc *sc) 801{ 802 struct ifnet * ifp = &sc->arpcom.ac_if; 803 int iobase = sc->iobase; 804 int tx_status; 805 806 DODEBUG(Start_End, printf("ex_tx_intr%d: start\n", unit);); 807 808 /* 809 * - Cancel the watchdog. 810 * For all packets transmitted since last transmit interrupt: 811 * - Advance chain pointer to next queued packet. 812 * - Update statistics. 813 */ 814 815 ifp->if_timer = 0; 816 817 while (sc->tx_head != sc->tx_tail) { 818 outw(iobase + HOST_ADDR_REG, sc->tx_head); 819 820 if (! inw(iobase + IO_PORT_REG) & Done_bit) 821 break; 822 823 tx_status = inw(iobase + IO_PORT_REG); 824 sc->tx_head = inw(iobase + IO_PORT_REG); 825 826 if (tx_status & TX_OK_bit) { 827 ifp->if_opackets++; 828 } else { 829 ifp->if_oerrors++; 830 } 831 832 ifp->if_collisions += tx_status & No_Collisions_bits; 833 } 834 835 /* 836 * The card should be ready to accept more packets now. 837 */ 838 839 ifp->if_flags &= ~IFF_OACTIVE; 840 841 DODEBUG(Status, printf("OIDLE tx_intr\n");); 842 DODEBUG(Start_End, printf("ex_tx_intr%d: finish\n", unit);); 843 844 return; 845} 846 847static void 848ex_rx_intr(struct ex_softc *sc) 849{ 850 struct ifnet * ifp = &sc->arpcom.ac_if; 851 int iobase = sc->iobase; 852 int rx_status; 853 int pkt_len; 854 int QQQ; 855 struct mbuf * m; 856 struct mbuf * ipkt; 857 struct ether_header * eh; 858 859 DODEBUG(Start_End, printf("ex_rx_intr%d: start\n", unit);); 860 861 /* 862 * For all packets received since last receive interrupt: 863 * - If packet ok, read it into a new mbuf and queue it to interface, 864 * updating statistics. 865 * - If packet bad, just discard it, and update statistics. 866 * Finally, advance receive stop limit in card's memory to new location. 867 */ 868 869 outw(iobase + HOST_ADDR_REG, sc->rx_head); 870 871 while (inw(iobase + IO_PORT_REG) == RCV_Done) { 872 873 rx_status = inw(iobase + IO_PORT_REG); 874 sc->rx_head = inw(iobase + IO_PORT_REG); 875 QQQ = pkt_len = inw(iobase + IO_PORT_REG); 876 877 if (rx_status & RCV_OK_bit) { 878 MGETHDR(m, M_DONTWAIT, MT_DATA); 879 ipkt = m; 880 if (ipkt == NULL) { 881 ifp->if_iqdrops++; 882 } else { 883 ipkt->m_pkthdr.rcvif = ifp; 884 ipkt->m_pkthdr.len = pkt_len; 885 ipkt->m_len = MHLEN; 886 887 while (pkt_len > 0) { 888 if (pkt_len > MINCLSIZE) { 889 MCLGET(m, M_DONTWAIT); 890 if (m->m_flags & M_EXT) { 891 m->m_len = MCLBYTES; 892 } else { 893 m_freem(ipkt); 894 ifp->if_iqdrops++; 895 goto rx_another; 896 } 897 } 898 m->m_len = min(m->m_len, pkt_len); 899 900 /* 901 * NOTE: I'm assuming that all mbufs allocated are of even length, 902 * except for the last one in an odd-length packet. 903 */ 904 905 insw(iobase + IO_PORT_REG, 906 mtod(m, caddr_t), m->m_len / 2); 907 908 if (m->m_len & 1) { 909 *(mtod(m, caddr_t) + m->m_len - 1) = inb(iobase + IO_PORT_REG); 910 } 911 pkt_len -= m->m_len; 912 913 if (pkt_len > 0) { 914 MGET(m->m_next, M_DONTWAIT, MT_DATA); 915 if (m->m_next == NULL) { 916 m_freem(ipkt); 917 ifp->if_iqdrops++; 918 goto rx_another; 919 } 920 m = m->m_next; 921 m->m_len = MLEN; 922 } 923 } 924 eh = mtod(ipkt, struct ether_header *); 925#ifdef EXDEBUG 926 if (debug_mask & Rcvd_Pkts) { 927 if ((eh->ether_dhost[5] != 0xff) || (eh->ether_dhost[0] != 0xff)) { 928 printf("Receive packet with %d data bytes: %6D -> ", QQQ, eh->ether_shost, ":"); 929 printf("%6D\n", eh->ether_dhost, ":"); 930 } /* QQQ */ 931 } 932#endif 933 if (ifp->if_bpf != NULL) { 934 bpf_mtap(ifp, ipkt); 935 936 /* 937 * Note that the interface cannot be in promiscuous mode 938 * if there are no BPF listeners. And if we are in 939 * promiscuous mode, we have to check if this packet is 940 * really ours. 941 */ 942 if ((ifp->if_flags & IFF_PROMISC) && 943 (eh->ether_dhost[0] & 1) == 0 && 944 bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr, sizeof(eh->ether_dhost)) != 0 && 945 bcmp(eh->ether_dhost, etherbroadcastaddr, sizeof(eh->ether_dhost)) != 0) { 946 m_freem(ipkt); 947 goto rx_another; 948 } 949 } 950 m_adj(ipkt, sizeof(struct ether_header)); 951 ether_input(ifp, eh, ipkt); 952 ifp->if_ipackets++; 953 } 954 } else { 955 ifp->if_ierrors++; 956 } 957 outw(iobase + HOST_ADDR_REG, sc->rx_head); 958rx_another: ; 959 } 960 961 if (sc->rx_head < sc->rx_lower_limit + 2) 962 outw(iobase + RCV_STOP_REG, sc->rx_upper_limit); 963 else 964 outw(iobase + RCV_STOP_REG, sc->rx_head - 2); 965 966 DODEBUG(Start_End, printf("ex_rx_intr%d: finish\n", unit);); 967 968 return; 969} 970 971 972int ex_ioctl(register struct ifnet *ifp, u_long cmd, caddr_t data) 973{ 974 struct ex_softc * sc = ifp->if_softc; 975 int s; 976 int error = 0; 977 978 DODEBUG(Start_End, printf("ex_ioctl%d: start ", ifp->if_unit);); 979 980 s = splimp(); 981 982 switch(cmd) { 983 case SIOCSIFADDR: 984 case SIOCGIFADDR: 985 case SIOCSIFMTU: 986 error = ether_ioctl(ifp, cmd, data); 987 break; 988 989 case SIOCSIFFLAGS: 990 DODEBUG(Start_End, printf("SIOCSIFFLAGS");); 991 if ((ifp->if_flags & IFF_UP) == 0 && 992 (ifp->if_flags & IFF_RUNNING)) { 993 994 ifp->if_flags &= ~IFF_RUNNING; 995 ex_stop(sc); 996 } else { 997 ex_init(sc); 998 } 999 break; 1000#ifdef NODEF 1001 case SIOCGHWADDR: 1002 DODEBUG(Start_End, printf("SIOCGHWADDR");); 1003 bcopy((caddr_t)sc->sc_addr, (caddr_t)&ifr->ifr_data, 1004 sizeof(sc->sc_addr)); 1005 break; 1006#endif 1007 case SIOCADDMULTI: 1008 DODEBUG(Start_End, printf("SIOCADDMULTI");); 1009 case SIOCDELMULTI: 1010 DODEBUG(Start_End, printf("SIOCDELMULTI");); 1011 /* XXX Support not done yet. */ 1012 error = EINVAL; 1013 break; 1014 default: 1015 DODEBUG(Start_End, printf("unknown");); 1016 error = EINVAL; 1017 } 1018 1019 splx(s); 1020 1021 DODEBUG(Start_End, printf("\nex_ioctl%d: finish\n", ifp->if_unit);); 1022 1023 return(error); 1024} 1025 1026 1027static void 1028ex_reset(struct ex_softc *sc) 1029{ 1030 int s; 1031 1032 DODEBUG(Start_End, printf("ex_reset%d: start\n", unit);); 1033 1034 s = splimp(); 1035 1036 ex_stop(sc); 1037 ex_init(sc); 1038 1039 splx(s); 1040 1041 DODEBUG(Start_End, printf("ex_reset%d: finish\n", unit);); 1042 1043 return; 1044} 1045 1046 1047static void 1048ex_watchdog(struct ifnet *ifp) 1049{ 1050 struct ex_softc * sc = ifp->if_softc; 1051 1052 DODEBUG(Start_End, printf("ex_watchdog%d: start\n", ifp->if_unit);); 1053 1054 ifp->if_flags &= ~IFF_OACTIVE; 1055 1056 DODEBUG(Status, printf("OIDLE watchdog\n");); 1057 1058 ifp->if_oerrors++; 1059 ex_reset(sc); 1060 ex_start(ifp); 1061 1062 DODEBUG(Start_End, printf("ex_watchdog%d: finish\n", ifp->if_unit);); 1063 1064 return; 1065} 1066 1067 1068static u_short 1069eeprom_read(int iobase, int location) 1070{ 1071 int i; 1072 u_short data = 0; 1073 int ee_addr; 1074 int read_cmd = location | EE_READ_CMD; 1075 short ctrl_val = EECS; 1076 1077 ee_addr = iobase + EEPROM_REG; 1078 outb(iobase + CMD_REG, Bank2_Sel); 1079 outb(ee_addr, EECS); 1080 for (i = 8; i >= 0; i--) { 1081 short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI : ctrl_val; 1082 outb(ee_addr, outval); 1083 outb(ee_addr, outval | EESK); 1084 DELAY(3); 1085 outb(ee_addr, outval); 1086 DELAY(2); 1087 } 1088 outb(ee_addr, ctrl_val); 1089 1090 for (i = 16; i > 0; i--) { 1091 outb(ee_addr, ctrl_val | EESK); 1092 DELAY(3); 1093 data = (data << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0); 1094 outb(ee_addr, ctrl_val); 1095 DELAY(2); 1096 } 1097 1098 ctrl_val &= ~EECS; 1099 outb(ee_addr, ctrl_val | EESK); 1100 DELAY(3); 1101 outb(ee_addr, ctrl_val); 1102 DELAY(2); 1103 outb(iobase + CMD_REG, Bank0_Sel); 1104 return(data); 1105} 1106 1107#endif /* NEX > 0 */ 1108