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