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