if_ex.c revision 271849
155825Speter/*- 2104930Sobrien * Copyright (c) 1996, Javier Mart��n Rueda (jmrueda@diatel.upm.es) 339818Speter * All rights reserved. 439818Speter * 547719Speter * Redistribution and use in source and binary forms, with or without 639818Speter * modification, are permitted provided that the following conditions 739818Speter * are met: 839818Speter * 1. Redistributions of source code must retain the above copyright 9120654Speter * notice unmodified, this list of conditions, and the following 10218822Sdim * disclaimer. 11218822Sdim * 2. Redistributions in binary form must reproduce the above copyright 12218822Sdim * notice, this list of conditions and the following disclaimer in the 13218822Sdim * documentation and/or other materials provided with the distribution. 14218822Sdim * 15218822Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16218822Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17218822Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18218822Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19218822Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20218822Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21218822Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22218822Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23218822Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24218822Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25218822Sdim * SUCH DAMAGE. 26218822Sdim * 27218822Sdim * 28218822Sdim * MAINTAINER: Matthew N. Dodd <winter@jurai.net> 29218822Sdim * <mdodd@FreeBSD.org> 30218822Sdim */ 31218822Sdim 32218822Sdim#include <sys/cdefs.h> 33218822Sdim__FBSDID("$FreeBSD: head/sys/dev/ex/if_ex.c 271849 2014-09-19 03:51:26Z glebius $"); 34218822Sdim 35218822Sdim/* 36218822Sdim * Intel EtherExpress Pro/10, Pro/10+ Ethernet driver 37218822Sdim * 38218822Sdim * Revision history: 39218822Sdim * 40218822Sdim * dd-mmm-yyyy: Multicast support ported from NetBSD's if_iy driver. 41218822Sdim * 30-Oct-1996: first beta version. Inet and BPF supported, but no multicast. 42218822Sdim */ 43218822Sdim 44218822Sdim#include <sys/param.h> 4539818Speter#include <sys/systm.h> 46218822Sdim#include <sys/kernel.h> 47218822Sdim#include <sys/sockio.h> 48218822Sdim#include <sys/mbuf.h> 49218822Sdim#include <sys/socket.h> 50218822Sdim 51218822Sdim#include <sys/module.h> 52218822Sdim#include <sys/bus.h> 5339818Speter 5439818Speter#include <machine/bus.h> 55218822Sdim#include <machine/resource.h> 56218822Sdim#include <sys/rman.h> 57218822Sdim 58218822Sdim#include <net/if.h> 59218822Sdim#include <net/if_var.h> 60218822Sdim#include <net/if_arp.h> 61218822Sdim#include <net/if_dl.h> 6239818Speter#include <net/if_media.h> 63218822Sdim#include <net/if_types.h> 64218822Sdim#include <net/ethernet.h> 65218822Sdim#include <net/bpf.h> 66218822Sdim 67218822Sdim#include <netinet/in.h> 6839818Speter#include <netinet/if_ether.h> 6939818Speter 70218822Sdim 71218822Sdim#include <isa/isavar.h> 72218822Sdim#include <isa/pnpvar.h> 73218822Sdim 74218822Sdim#include <dev/ex/if_exreg.h> 75218822Sdim#include <dev/ex/if_exvar.h> 76218822Sdim 77218822Sdim#ifdef EXDEBUG 7839818Speter# define Start_End 1 79218822Sdim# define Rcvd_Pkts 2 80218822Sdim# define Sent_Pkts 4 81218822Sdim# define Status 8 8239818Speterstatic int debug_mask = 0; 83218822Sdim# define DODEBUG(level, action) if (level & debug_mask) action 84218822Sdim#else 85218822Sdim# define DODEBUG(level, action) 86218822Sdim#endif 87218822Sdim 88218822Sdimdevclass_t ex_devclass; 89218822Sdim 90218822Sdimchar irq2eemap[] = 91218822Sdim { -1, -1, 0, 1, -1, 2, -1, -1, -1, 0, 3, 4, -1, -1, -1, -1 }; 92218822Sdimu_char ee2irqmap[] = 93218822Sdim { 9, 3, 5, 10, 11, 0, 0, 0 }; 94218822Sdim 95218822Sdimchar plus_irq2eemap[] = 96218822Sdim { -1, -1, -1, 0, 1, 2, -1, 3, -1, 4, 5, 6, 7, -1, -1, -1 }; 97108777Sphku_char plus_ee2irqmap[] = 98108777Sphk { 3, 4, 5, 7, 9, 10, 11, 12 }; 99218822Sdim 10039818Speter/* Network Interface Functions */ 101218822Sdimstatic void ex_init(void *); 102218822Sdimstatic void ex_init_locked(struct ex_softc *); 103218822Sdimstatic void ex_start(struct ifnet *); 104218822Sdimstatic void ex_start_locked(struct ifnet *); 105218822Sdimstatic int ex_ioctl(struct ifnet *, u_long, caddr_t); 106218822Sdimstatic void ex_watchdog(void *); 107218822Sdim 108218822Sdim/* ifmedia Functions */ 109218822Sdimstatic int ex_ifmedia_upd(struct ifnet *); 110218822Sdimstatic void ex_ifmedia_sts(struct ifnet *, struct ifmediareq *); 111218822Sdim 112218822Sdimstatic int ex_get_media(struct ex_softc *); 113218822Sdim 114218822Sdimstatic void ex_reset(struct ex_softc *); 115218822Sdimstatic void ex_setmulti(struct ex_softc *); 116218822Sdim 117218822Sdimstatic void ex_tx_intr(struct ex_softc *); 118218822Sdimstatic void ex_rx_intr(struct ex_softc *); 11939818Speter 120108777Sphkvoid 121108777Sphkex_get_address(struct ex_softc *sc, u_char *enaddr) 122218822Sdim{ 12339818Speter uint16_t eaddr_tmp; 124218822Sdim 125218822Sdim eaddr_tmp = ex_eeprom_read(sc, EE_Eth_Addr_Lo); 126218822Sdim enaddr[5] = eaddr_tmp & 0xff; 127218822Sdim enaddr[4] = eaddr_tmp >> 8; 128218822Sdim eaddr_tmp = ex_eeprom_read(sc, EE_Eth_Addr_Mid); 12939818Speter enaddr[3] = eaddr_tmp & 0xff; 130218822Sdim enaddr[2] = eaddr_tmp >> 8; 131218822Sdim eaddr_tmp = ex_eeprom_read(sc, EE_Eth_Addr_Hi); 132218822Sdim enaddr[1] = eaddr_tmp & 0xff; 133218822Sdim enaddr[0] = eaddr_tmp >> 8; 134218822Sdim 135218822Sdim return; 136218822Sdim} 137218822Sdim 138218822Sdimint 139218822Sdimex_card_type(u_char *enaddr) 140218822Sdim{ 141218822Sdim if ((enaddr[0] == 0x00) && (enaddr[1] == 0xA0) && (enaddr[2] == 0xC9)) 142218822Sdim return (CARD_TYPE_EX_10_PLUS); 143218822Sdim 14439818Speter return (CARD_TYPE_EX_10); 145218822Sdim} 14639818Speter 14739818Speter/* 148218822Sdim * Caller is responsible for eventually calling 14939818Speter * ex_release_resources() on failure. 150218822Sdim */ 151218822Sdimint 152218822Sdimex_alloc_resources(device_t dev) 153218822Sdim{ 154218822Sdim struct ex_softc * sc = device_get_softc(dev); 155218822Sdim int error = 0; 15639818Speter 15739818Speter sc->ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 158218822Sdim &sc->ioport_rid, RF_ACTIVE); 159218822Sdim if (!sc->ioport) { 160218822Sdim device_printf(dev, "No I/O space?!\n"); 16139818Speter error = ENOMEM; 162218822Sdim goto bad; 163218822Sdim } 164218822Sdim 165218822Sdim sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid, 166218822Sdim RF_ACTIVE); 16739818Speter 168218822Sdim if (!sc->irq) { 16939818Speter device_printf(dev, "No IRQ?!\n"); 17039818Speter error = ENOMEM; 17139818Speter goto bad; 17239818Speter } 17339818Speter 17439818Speterbad: 17539818Speter return (error); 17639818Speter} 17739818Speter 17839818Spetervoid 17939818Speterex_release_resources(device_t dev) 18039818Speter{ 18139818Speter struct ex_softc * sc = device_get_softc(dev); 182218822Sdim 18339818Speter if (sc->ih) { 18439818Speter bus_teardown_intr(dev, sc->irq, sc->ih); 18539818Speter sc->ih = NULL; 18639818Speter } 18739818Speter 18839818Speter if (sc->ioport) { 18939818Speter bus_release_resource(dev, SYS_RES_IOPORT, 19039818Speter sc->ioport_rid, sc->ioport); 19139818Speter sc->ioport = NULL; 19239818Speter } 19339818Speter 194218822Sdim if (sc->irq) { 195218822Sdim bus_release_resource(dev, SYS_RES_IRQ, 196218822Sdim sc->irq_rid, sc->irq); 197218822Sdim sc->irq = NULL; 198218822Sdim } 19939818Speter 200 if (sc->ifp) 201 if_free(sc->ifp); 202 203 return; 204} 205 206int 207ex_attach(device_t dev) 208{ 209 struct ex_softc * sc = device_get_softc(dev); 210 struct ifnet * ifp; 211 struct ifmedia * ifm; 212 int error; 213 uint16_t temp; 214 215 ifp = sc->ifp = if_alloc(IFT_ETHER); 216 if (ifp == NULL) { 217 device_printf(dev, "can not if_alloc()\n"); 218 return (ENOSPC); 219 } 220 /* work out which set of irq <-> internal tables to use */ 221 if (ex_card_type(sc->enaddr) == CARD_TYPE_EX_10_PLUS) { 222 sc->irq2ee = plus_irq2eemap; 223 sc->ee2irq = plus_ee2irqmap; 224 } else { 225 sc->irq2ee = irq2eemap; 226 sc->ee2irq = ee2irqmap; 227 } 228 229 sc->mem_size = CARD_RAM_SIZE; /* XXX This should be read from the card itself. */ 230 231 /* 232 * Initialize the ifnet structure. 233 */ 234 ifp->if_softc = sc; 235 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 236 ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; 237 ifp->if_start = ex_start; 238 ifp->if_ioctl = ex_ioctl; 239 ifp->if_init = ex_init; 240 IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); 241 242 ifmedia_init(&sc->ifmedia, 0, ex_ifmedia_upd, ex_ifmedia_sts); 243 mtx_init(&sc->lock, device_get_nameunit(dev), MTX_NETWORK_LOCK, 244 MTX_DEF); 245 callout_init_mtx(&sc->timer, &sc->lock, 0); 246 247 temp = ex_eeprom_read(sc, EE_W5); 248 if (temp & EE_W5_PORT_TPE) 249 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL); 250 if (temp & EE_W5_PORT_BNC) 251 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_2, 0, NULL); 252 if (temp & EE_W5_PORT_AUI) 253 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_5, 0, NULL); 254 255 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); 256 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_NONE, 0, NULL); 257 ifmedia_set(&sc->ifmedia, ex_get_media(sc)); 258 259 ifm = &sc->ifmedia; 260 ifm->ifm_media = ifm->ifm_cur->ifm_media; 261 ex_ifmedia_upd(ifp); 262 263 /* 264 * Attach the interface. 265 */ 266 ether_ifattach(ifp, sc->enaddr); 267 268 error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, 269 NULL, ex_intr, (void *)sc, &sc->ih); 270 if (error) { 271 device_printf(dev, "bus_setup_intr() failed!\n"); 272 ether_ifdetach(ifp); 273 mtx_destroy(&sc->lock); 274 return (error); 275 } 276 277 return(0); 278} 279 280int 281ex_detach(device_t dev) 282{ 283 struct ex_softc *sc; 284 struct ifnet *ifp; 285 286 sc = device_get_softc(dev); 287 ifp = sc->ifp; 288 289 EX_LOCK(sc); 290 ex_stop(sc); 291 EX_UNLOCK(sc); 292 293 ether_ifdetach(ifp); 294 callout_drain(&sc->timer); 295 296 ex_release_resources(dev); 297 mtx_destroy(&sc->lock); 298 299 return (0); 300} 301 302static void 303ex_init(void *xsc) 304{ 305 struct ex_softc * sc = (struct ex_softc *) xsc; 306 307 EX_LOCK(sc); 308 ex_init_locked(sc); 309 EX_UNLOCK(sc); 310} 311 312static void 313ex_init_locked(struct ex_softc *sc) 314{ 315 struct ifnet * ifp = sc->ifp; 316 int i; 317 unsigned short temp_reg; 318 319 DODEBUG(Start_End, printf("%s: ex_init: start\n", ifp->if_xname);); 320 321 sc->tx_timeout = 0; 322 323 /* 324 * Load the ethernet address into the card. 325 */ 326 CSR_WRITE_1(sc, CMD_REG, Bank2_Sel); 327 temp_reg = CSR_READ_1(sc, EEPROM_REG); 328 if (temp_reg & Trnoff_Enable) 329 CSR_WRITE_1(sc, EEPROM_REG, temp_reg & ~Trnoff_Enable); 330 for (i = 0; i < ETHER_ADDR_LEN; i++) 331 CSR_WRITE_1(sc, I_ADDR_REG0 + i, IF_LLADDR(sc->ifp)[i]); 332 333 /* 334 * - Setup transmit chaining and discard bad received frames. 335 * - Match broadcast. 336 * - Clear test mode. 337 * - Set receiving mode. 338 */ 339 CSR_WRITE_1(sc, REG1, CSR_READ_1(sc, REG1) | Tx_Chn_Int_Md | Tx_Chn_ErStp | Disc_Bad_Fr); 340 CSR_WRITE_1(sc, REG2, CSR_READ_1(sc, REG2) | No_SA_Ins | RX_CRC_InMem); 341 CSR_WRITE_1(sc, REG3, CSR_READ_1(sc, REG3) & 0x3f /* XXX constants. */ ); 342 /* 343 * - Set IRQ number, if this part has it. ISA devices have this, 344 * while PC Card devices don't seem to. Either way, we have to 345 * switch to Bank1 as the rest of this code relies on that. 346 */ 347 CSR_WRITE_1(sc, CMD_REG, Bank1_Sel); 348 if (sc->flags & HAS_INT_NO_REG) 349 CSR_WRITE_1(sc, INT_NO_REG, 350 (CSR_READ_1(sc, INT_NO_REG) & 0xf8) | 351 sc->irq2ee[sc->irq_no]); 352 353 /* 354 * Divide the available memory in the card into rcv and xmt buffers. 355 * By default, I use the first 3/4 of the memory for the rcv buffer, 356 * and the remaining 1/4 of the memory for the xmt buffer. 357 */ 358 sc->rx_mem_size = sc->mem_size * 3 / 4; 359 sc->tx_mem_size = sc->mem_size - sc->rx_mem_size; 360 sc->rx_lower_limit = 0x0000; 361 sc->rx_upper_limit = sc->rx_mem_size - 2; 362 sc->tx_lower_limit = sc->rx_mem_size; 363 sc->tx_upper_limit = sc->mem_size - 2; 364 CSR_WRITE_1(sc, RCV_LOWER_LIMIT_REG, sc->rx_lower_limit >> 8); 365 CSR_WRITE_1(sc, RCV_UPPER_LIMIT_REG, sc->rx_upper_limit >> 8); 366 CSR_WRITE_1(sc, XMT_LOWER_LIMIT_REG, sc->tx_lower_limit >> 8); 367 CSR_WRITE_1(sc, XMT_UPPER_LIMIT_REG, sc->tx_upper_limit >> 8); 368 369 /* 370 * Enable receive and transmit interrupts, and clear any pending int. 371 */ 372 CSR_WRITE_1(sc, REG1, CSR_READ_1(sc, REG1) | TriST_INT); 373 CSR_WRITE_1(sc, CMD_REG, Bank0_Sel); 374 CSR_WRITE_1(sc, MASK_REG, All_Int & ~(Rx_Int | Tx_Int)); 375 CSR_WRITE_1(sc, STATUS_REG, All_Int); 376 377 /* 378 * Initialize receive and transmit ring buffers. 379 */ 380 CSR_WRITE_2(sc, RCV_BAR, sc->rx_lower_limit); 381 sc->rx_head = sc->rx_lower_limit; 382 CSR_WRITE_2(sc, RCV_STOP_REG, sc->rx_upper_limit | 0xfe); 383 CSR_WRITE_2(sc, XMT_BAR, sc->tx_lower_limit); 384 sc->tx_head = sc->tx_tail = sc->tx_lower_limit; 385 386 ifp->if_drv_flags |= IFF_DRV_RUNNING; 387 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 388 DODEBUG(Status, printf("OIDLE init\n");); 389 callout_reset(&sc->timer, hz, ex_watchdog, sc); 390 391 ex_setmulti(sc); 392 393 /* 394 * Final reset of the board, and enable operation. 395 */ 396 CSR_WRITE_1(sc, CMD_REG, Sel_Reset_CMD); 397 DELAY(2); 398 CSR_WRITE_1(sc, CMD_REG, Rcv_Enable_CMD); 399 400 ex_start_locked(ifp); 401 402 DODEBUG(Start_End, printf("%s: ex_init: finish\n", ifp->if_xname);); 403} 404 405static void 406ex_start(struct ifnet *ifp) 407{ 408 struct ex_softc * sc = ifp->if_softc; 409 410 EX_LOCK(sc); 411 ex_start_locked(ifp); 412 EX_UNLOCK(sc); 413} 414 415static void 416ex_start_locked(struct ifnet *ifp) 417{ 418 struct ex_softc * sc = ifp->if_softc; 419 int i, len, data_len, avail, dest, next; 420 unsigned char tmp16[2]; 421 struct mbuf * opkt; 422 struct mbuf * m; 423 424 DODEBUG(Start_End, printf("ex_start%d: start\n", unit);); 425 426 /* 427 * Main loop: send outgoing packets to network card until there are no 428 * more packets left, or the card cannot accept any more yet. 429 */ 430 while (((opkt = ifp->if_snd.ifq_head) != NULL) && 431 !(ifp->if_drv_flags & IFF_DRV_OACTIVE)) { 432 433 /* 434 * Ensure there is enough free transmit buffer space for 435 * this packet, including its header. Note: the header 436 * cannot wrap around the end of the transmit buffer and 437 * must be kept together, so we allow space for twice the 438 * length of the header, just in case. 439 */ 440 441 for (len = 0, m = opkt; m != NULL; m = m->m_next) { 442 len += m->m_len; 443 } 444 445 data_len = len; 446 447 DODEBUG(Sent_Pkts, printf("1. Sending packet with %d data bytes. ", data_len);); 448 449 if (len & 1) { 450 len += XMT_HEADER_LEN + 1; 451 } else { 452 len += XMT_HEADER_LEN; 453 } 454 455 if ((i = sc->tx_tail - sc->tx_head) >= 0) { 456 avail = sc->tx_mem_size - i; 457 } else { 458 avail = -i; 459 } 460 461 DODEBUG(Sent_Pkts, printf("i=%d, avail=%d\n", i, avail);); 462 463 if (avail >= len + XMT_HEADER_LEN) { 464 IF_DEQUEUE(&ifp->if_snd, opkt); 465 466#ifdef EX_PSA_INTR 467 /* 468 * Disable rx and tx interrupts, to avoid corruption 469 * of the host address register by interrupt service 470 * routines. 471 * XXX Is this necessary with splimp() enabled? 472 */ 473 CSR_WRITE_1(sc, MASK_REG, All_Int); 474#endif 475 476 /* 477 * Compute the start and end addresses of this 478 * frame in the tx buffer. 479 */ 480 dest = sc->tx_tail; 481 next = dest + len; 482 483 if (next > sc->tx_upper_limit) { 484 if ((sc->tx_upper_limit + 2 - sc->tx_tail) <= 485 XMT_HEADER_LEN) { 486 dest = sc->tx_lower_limit; 487 next = dest + len; 488 } else { 489 next = sc->tx_lower_limit + 490 next - sc->tx_upper_limit - 2; 491 } 492 } 493 494 /* 495 * Build the packet frame in the card's ring buffer. 496 */ 497 DODEBUG(Sent_Pkts, printf("2. dest=%d, next=%d. ", dest, next);); 498 499 CSR_WRITE_2(sc, HOST_ADDR_REG, dest); 500 CSR_WRITE_2(sc, IO_PORT_REG, Transmit_CMD); 501 CSR_WRITE_2(sc, IO_PORT_REG, 0); 502 CSR_WRITE_2(sc, IO_PORT_REG, next); 503 CSR_WRITE_2(sc, IO_PORT_REG, data_len); 504 505 /* 506 * Output the packet data to the card. Ensure all 507 * transfers are 16-bit wide, even if individual 508 * mbufs have odd length. 509 */ 510 for (m = opkt, i = 0; m != NULL; m = m->m_next) { 511 DODEBUG(Sent_Pkts, printf("[%d]", m->m_len);); 512 if (i) { 513 tmp16[1] = *(mtod(m, caddr_t)); 514 CSR_WRITE_MULTI_2(sc, IO_PORT_REG, 515 (uint16_t *) tmp16, 1); 516 } 517 CSR_WRITE_MULTI_2(sc, IO_PORT_REG, 518 (uint16_t *) (mtod(m, caddr_t) + i), 519 (m->m_len - i) / 2); 520 if ((i = (m->m_len - i) & 1) != 0) { 521 tmp16[0] = *(mtod(m, caddr_t) + 522 m->m_len - 1); 523 } 524 } 525 if (i) 526 CSR_WRITE_MULTI_2(sc, IO_PORT_REG, 527 (uint16_t *) tmp16, 1); 528 /* 529 * If there were other frames chained, update the 530 * chain in the last one. 531 */ 532 if (sc->tx_head != sc->tx_tail) { 533 if (sc->tx_tail != dest) { 534 CSR_WRITE_2(sc, HOST_ADDR_REG, 535 sc->tx_last + XMT_Chain_Point); 536 CSR_WRITE_2(sc, IO_PORT_REG, dest); 537 } 538 CSR_WRITE_2(sc, HOST_ADDR_REG, 539 sc->tx_last + XMT_Byte_Count); 540 i = CSR_READ_2(sc, IO_PORT_REG); 541 CSR_WRITE_2(sc, HOST_ADDR_REG, 542 sc->tx_last + XMT_Byte_Count); 543 CSR_WRITE_2(sc, IO_PORT_REG, i | Ch_bit); 544 } 545 546 /* 547 * Resume normal operation of the card: 548 * - Make a dummy read to flush the DRAM write 549 * pipeline. 550 * - Enable receive and transmit interrupts. 551 * - Send Transmit or Resume_XMT command, as 552 * appropriate. 553 */ 554 CSR_READ_2(sc, IO_PORT_REG); 555#ifdef EX_PSA_INTR 556 CSR_WRITE_1(sc, MASK_REG, All_Int & ~(Rx_Int | Tx_Int)); 557#endif 558 if (sc->tx_head == sc->tx_tail) { 559 CSR_WRITE_2(sc, XMT_BAR, dest); 560 CSR_WRITE_1(sc, CMD_REG, Transmit_CMD); 561 sc->tx_head = dest; 562 DODEBUG(Sent_Pkts, printf("Transmit\n");); 563 } else { 564 CSR_WRITE_1(sc, CMD_REG, Resume_XMT_List_CMD); 565 DODEBUG(Sent_Pkts, printf("Resume\n");); 566 } 567 568 sc->tx_last = dest; 569 sc->tx_tail = next; 570 571 BPF_MTAP(ifp, opkt); 572 573 sc->tx_timeout = 2; 574 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 575 m_freem(opkt); 576 } else { 577 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 578 DODEBUG(Status, printf("OACTIVE start\n");); 579 } 580 } 581 582 DODEBUG(Start_End, printf("ex_start%d: finish\n", unit);); 583} 584 585void 586ex_stop(struct ex_softc *sc) 587{ 588 589 DODEBUG(Start_End, printf("ex_stop%d: start\n", unit);); 590 591 EX_ASSERT_LOCKED(sc); 592 /* 593 * Disable card operation: 594 * - Disable the interrupt line. 595 * - Flush transmission and disable reception. 596 * - Mask and clear all interrupts. 597 * - Reset the 82595. 598 */ 599 CSR_WRITE_1(sc, CMD_REG, Bank1_Sel); 600 CSR_WRITE_1(sc, REG1, CSR_READ_1(sc, REG1) & ~TriST_INT); 601 CSR_WRITE_1(sc, CMD_REG, Bank0_Sel); 602 CSR_WRITE_1(sc, CMD_REG, Rcv_Stop); 603 sc->tx_head = sc->tx_tail = sc->tx_lower_limit; 604 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. */ 605 CSR_WRITE_1(sc, MASK_REG, All_Int); 606 CSR_WRITE_1(sc, STATUS_REG, All_Int); 607 CSR_WRITE_1(sc, CMD_REG, Reset_CMD); 608 DELAY(200); 609 sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 610 sc->tx_timeout = 0; 611 callout_stop(&sc->timer); 612 613 DODEBUG(Start_End, printf("ex_stop%d: finish\n", unit);); 614 615 return; 616} 617 618void 619ex_intr(void *arg) 620{ 621 struct ex_softc *sc = (struct ex_softc *)arg; 622 struct ifnet *ifp = sc->ifp; 623 int int_status, send_pkts; 624 int loops = 100; 625 626 DODEBUG(Start_End, printf("ex_intr%d: start\n", unit);); 627 628 EX_LOCK(sc); 629 send_pkts = 0; 630 while (loops-- > 0 && 631 (int_status = CSR_READ_1(sc, STATUS_REG)) & (Tx_Int | Rx_Int)) { 632 /* don't loop forever */ 633 if (int_status == 0xff) 634 break; 635 if (int_status & Rx_Int) { 636 CSR_WRITE_1(sc, STATUS_REG, Rx_Int); 637 ex_rx_intr(sc); 638 } else if (int_status & Tx_Int) { 639 CSR_WRITE_1(sc, STATUS_REG, Tx_Int); 640 ex_tx_intr(sc); 641 send_pkts = 1; 642 } 643 } 644 if (loops == 0) 645 printf("100 loops are not enough\n"); 646 647 /* 648 * If any packet has been transmitted, and there are queued packets to 649 * be sent, attempt to send more packets to the network card. 650 */ 651 if (send_pkts && (ifp->if_snd.ifq_head != NULL)) 652 ex_start_locked(ifp); 653 EX_UNLOCK(sc); 654 655 DODEBUG(Start_End, printf("ex_intr%d: finish\n", unit);); 656 657 return; 658} 659 660static void 661ex_tx_intr(struct ex_softc *sc) 662{ 663 struct ifnet * ifp = sc->ifp; 664 int tx_status; 665 666 DODEBUG(Start_End, printf("ex_tx_intr%d: start\n", unit);); 667 668 /* 669 * - Cancel the watchdog. 670 * For all packets transmitted since last transmit interrupt: 671 * - Advance chain pointer to next queued packet. 672 * - Update statistics. 673 */ 674 675 sc->tx_timeout = 0; 676 677 while (sc->tx_head != sc->tx_tail) { 678 CSR_WRITE_2(sc, HOST_ADDR_REG, sc->tx_head); 679 680 if (!(CSR_READ_2(sc, IO_PORT_REG) & Done_bit)) 681 break; 682 683 tx_status = CSR_READ_2(sc, IO_PORT_REG); 684 sc->tx_head = CSR_READ_2(sc, IO_PORT_REG); 685 686 if (tx_status & TX_OK_bit) { 687 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 688 } else { 689 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 690 } 691 692 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, tx_status & No_Collisions_bits); 693 } 694 695 /* 696 * The card should be ready to accept more packets now. 697 */ 698 699 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 700 701 DODEBUG(Status, printf("OIDLE tx_intr\n");); 702 DODEBUG(Start_End, printf("ex_tx_intr%d: finish\n", unit);); 703 704 return; 705} 706 707static void 708ex_rx_intr(struct ex_softc *sc) 709{ 710 struct ifnet * ifp = sc->ifp; 711 int rx_status; 712 int pkt_len; 713 int QQQ; 714 struct mbuf * m; 715 struct mbuf * ipkt; 716 struct ether_header * eh; 717 718 DODEBUG(Start_End, printf("ex_rx_intr%d: start\n", unit);); 719 720 /* 721 * For all packets received since last receive interrupt: 722 * - If packet ok, read it into a new mbuf and queue it to interface, 723 * updating statistics. 724 * - If packet bad, just discard it, and update statistics. 725 * Finally, advance receive stop limit in card's memory to new location. 726 */ 727 728 CSR_WRITE_2(sc, HOST_ADDR_REG, sc->rx_head); 729 730 while (CSR_READ_2(sc, IO_PORT_REG) == RCV_Done) { 731 732 rx_status = CSR_READ_2(sc, IO_PORT_REG); 733 sc->rx_head = CSR_READ_2(sc, IO_PORT_REG); 734 QQQ = pkt_len = CSR_READ_2(sc, IO_PORT_REG); 735 736 if (rx_status & RCV_OK_bit) { 737 MGETHDR(m, M_NOWAIT, MT_DATA); 738 ipkt = m; 739 if (ipkt == NULL) { 740 if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); 741 } else { 742 ipkt->m_pkthdr.rcvif = ifp; 743 ipkt->m_pkthdr.len = pkt_len; 744 ipkt->m_len = MHLEN; 745 746 while (pkt_len > 0) { 747 if (pkt_len >= MINCLSIZE) { 748 MCLGET(m, M_NOWAIT); 749 if (m->m_flags & M_EXT) { 750 m->m_len = MCLBYTES; 751 } else { 752 m_freem(ipkt); 753 if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); 754 goto rx_another; 755 } 756 } 757 m->m_len = min(m->m_len, pkt_len); 758 759 /* 760 * NOTE: I'm assuming that all mbufs allocated are of even length, 761 * except for the last one in an odd-length packet. 762 */ 763 764 CSR_READ_MULTI_2(sc, IO_PORT_REG, 765 mtod(m, uint16_t *), m->m_len / 2); 766 767 if (m->m_len & 1) { 768 *(mtod(m, caddr_t) + m->m_len - 1) = CSR_READ_1(sc, IO_PORT_REG); 769 } 770 pkt_len -= m->m_len; 771 772 if (pkt_len > 0) { 773 MGET(m->m_next, M_NOWAIT, MT_DATA); 774 if (m->m_next == NULL) { 775 m_freem(ipkt); 776 if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); 777 goto rx_another; 778 } 779 m = m->m_next; 780 m->m_len = MLEN; 781 } 782 } 783 eh = mtod(ipkt, struct ether_header *); 784#ifdef EXDEBUG 785 if (debug_mask & Rcvd_Pkts) { 786 if ((eh->ether_dhost[5] != 0xff) || (eh->ether_dhost[0] != 0xff)) { 787 printf("Receive packet with %d data bytes: %6D -> ", QQQ, eh->ether_shost, ":"); 788 printf("%6D\n", eh->ether_dhost, ":"); 789 } /* QQQ */ 790 } 791#endif 792 EX_UNLOCK(sc); 793 (*ifp->if_input)(ifp, ipkt); 794 EX_LOCK(sc); 795 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 796 } 797 } else { 798 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 799 } 800 CSR_WRITE_2(sc, HOST_ADDR_REG, sc->rx_head); 801rx_another: ; 802 } 803 804 if (sc->rx_head < sc->rx_lower_limit + 2) 805 CSR_WRITE_2(sc, RCV_STOP_REG, sc->rx_upper_limit); 806 else 807 CSR_WRITE_2(sc, RCV_STOP_REG, sc->rx_head - 2); 808 809 DODEBUG(Start_End, printf("ex_rx_intr%d: finish\n", unit);); 810 811 return; 812} 813 814 815static int 816ex_ioctl(register struct ifnet *ifp, u_long cmd, caddr_t data) 817{ 818 struct ex_softc * sc = ifp->if_softc; 819 struct ifreq * ifr = (struct ifreq *)data; 820 int error = 0; 821 822 DODEBUG(Start_End, printf("%s: ex_ioctl: start ", ifp->if_xname);); 823 824 switch(cmd) { 825 case SIOCSIFADDR: 826 case SIOCGIFADDR: 827 case SIOCSIFMTU: 828 error = ether_ioctl(ifp, cmd, data); 829 break; 830 831 case SIOCSIFFLAGS: 832 DODEBUG(Start_End, printf("SIOCSIFFLAGS");); 833 EX_LOCK(sc); 834 if ((ifp->if_flags & IFF_UP) == 0 && 835 (ifp->if_drv_flags & IFF_DRV_RUNNING)) { 836 ex_stop(sc); 837 } else { 838 ex_init_locked(sc); 839 } 840 EX_UNLOCK(sc); 841 break; 842 case SIOCADDMULTI: 843 case SIOCDELMULTI: 844 ex_init(sc); 845 error = 0; 846 break; 847 case SIOCSIFMEDIA: 848 case SIOCGIFMEDIA: 849 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, cmd); 850 break; 851 default: 852 DODEBUG(Start_End, printf("unknown");); 853 error = EINVAL; 854 } 855 856 DODEBUG(Start_End, printf("\n%s: ex_ioctl: finish\n", ifp->if_xname);); 857 858 return(error); 859} 860 861static void 862ex_setmulti(struct ex_softc *sc) 863{ 864 struct ifnet *ifp; 865 struct ifmultiaddr *maddr; 866 uint16_t *addr; 867 int count; 868 int timeout, status; 869 870 ifp = sc->ifp; 871 872 count = 0; 873 if_maddr_rlock(ifp); 874 TAILQ_FOREACH(maddr, &ifp->if_multiaddrs, ifma_link) { 875 if (maddr->ifma_addr->sa_family != AF_LINK) 876 continue; 877 count++; 878 } 879 if_maddr_runlock(ifp); 880 881 if ((ifp->if_flags & IFF_PROMISC) || (ifp->if_flags & IFF_ALLMULTI) 882 || count > 63) { 883 /* Interface is in promiscuous mode or there are too many 884 * multicast addresses for the card to handle */ 885 CSR_WRITE_1(sc, CMD_REG, Bank2_Sel); 886 CSR_WRITE_1(sc, REG2, CSR_READ_1(sc, REG2) | Promisc_Mode); 887 CSR_WRITE_1(sc, REG3, CSR_READ_1(sc, REG3)); 888 CSR_WRITE_1(sc, CMD_REG, Bank0_Sel); 889 } 890 else if ((ifp->if_flags & IFF_MULTICAST) && (count > 0)) { 891 /* Program multicast addresses plus our MAC address 892 * into the filter */ 893 CSR_WRITE_1(sc, CMD_REG, Bank2_Sel); 894 CSR_WRITE_1(sc, REG2, CSR_READ_1(sc, REG2) | Multi_IA); 895 CSR_WRITE_1(sc, REG3, CSR_READ_1(sc, REG3)); 896 CSR_WRITE_1(sc, CMD_REG, Bank0_Sel); 897 898 /* Borrow space from TX buffer; this should be safe 899 * as this is only called from ex_init */ 900 901 CSR_WRITE_2(sc, HOST_ADDR_REG, sc->tx_lower_limit); 902 CSR_WRITE_2(sc, IO_PORT_REG, MC_Setup_CMD); 903 CSR_WRITE_2(sc, IO_PORT_REG, 0); 904 CSR_WRITE_2(sc, IO_PORT_REG, 0); 905 CSR_WRITE_2(sc, IO_PORT_REG, (count + 1) * 6); 906 907 if_maddr_rlock(ifp); 908 TAILQ_FOREACH(maddr, &ifp->if_multiaddrs, ifma_link) { 909 if (maddr->ifma_addr->sa_family != AF_LINK) 910 continue; 911 912 addr = (uint16_t*)LLADDR((struct sockaddr_dl *) 913 maddr->ifma_addr); 914 CSR_WRITE_2(sc, IO_PORT_REG, *addr++); 915 CSR_WRITE_2(sc, IO_PORT_REG, *addr++); 916 CSR_WRITE_2(sc, IO_PORT_REG, *addr++); 917 } 918 if_maddr_runlock(ifp); 919 920 /* Program our MAC address as well */ 921 /* XXX: Is this necessary? The Linux driver does this 922 * but the NetBSD driver does not */ 923 addr = (uint16_t*)IF_LLADDR(sc->ifp); 924 CSR_WRITE_2(sc, IO_PORT_REG, *addr++); 925 CSR_WRITE_2(sc, IO_PORT_REG, *addr++); 926 CSR_WRITE_2(sc, IO_PORT_REG, *addr++); 927 928 CSR_READ_2(sc, IO_PORT_REG); 929 CSR_WRITE_2(sc, XMT_BAR, sc->tx_lower_limit); 930 CSR_WRITE_1(sc, CMD_REG, MC_Setup_CMD); 931 932 sc->tx_head = sc->tx_lower_limit; 933 sc->tx_tail = sc->tx_head + XMT_HEADER_LEN + (count + 1) * 6; 934 935 for (timeout=0; timeout<100; timeout++) { 936 DELAY(2); 937 if ((CSR_READ_1(sc, STATUS_REG) & Exec_Int) == 0) 938 continue; 939 940 status = CSR_READ_1(sc, CMD_REG); 941 CSR_WRITE_1(sc, STATUS_REG, Exec_Int); 942 break; 943 } 944 945 sc->tx_head = sc->tx_tail; 946 } 947 else 948 { 949 /* No multicast or promiscuous mode */ 950 CSR_WRITE_1(sc, CMD_REG, Bank2_Sel); 951 CSR_WRITE_1(sc, REG2, CSR_READ_1(sc, REG2) & 0xDE); 952 /* ~(Multi_IA | Promisc_Mode) */ 953 CSR_WRITE_1(sc, REG3, CSR_READ_1(sc, REG3)); 954 CSR_WRITE_1(sc, CMD_REG, Bank0_Sel); 955 } 956} 957 958static void 959ex_reset(struct ex_softc *sc) 960{ 961 962 DODEBUG(Start_End, printf("ex_reset%d: start\n", unit);); 963 964 EX_ASSERT_LOCKED(sc); 965 ex_stop(sc); 966 ex_init_locked(sc); 967 968 DODEBUG(Start_End, printf("ex_reset%d: finish\n", unit);); 969 970 return; 971} 972 973static void 974ex_watchdog(void *arg) 975{ 976 struct ex_softc * sc = arg; 977 struct ifnet *ifp = sc->ifp; 978 979 if (sc->tx_timeout && --sc->tx_timeout == 0) { 980 DODEBUG(Start_End, if_printf(ifp, "ex_watchdog: start\n");); 981 982 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 983 984 DODEBUG(Status, printf("OIDLE watchdog\n");); 985 986 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 987 ex_reset(sc); 988 ex_start_locked(ifp); 989 990 DODEBUG(Start_End, if_printf(ifp, "ex_watchdog: finish\n");); 991 } 992 993 callout_reset(&sc->timer, hz, ex_watchdog, sc); 994} 995 996static int 997ex_get_media(struct ex_softc *sc) 998{ 999 int current; 1000 int media; 1001 1002 media = ex_eeprom_read(sc, EE_W5); 1003 1004 CSR_WRITE_1(sc, CMD_REG, Bank2_Sel); 1005 current = CSR_READ_1(sc, REG3); 1006 CSR_WRITE_1(sc, CMD_REG, Bank0_Sel); 1007 1008 if ((current & TPE_bit) && (media & EE_W5_PORT_TPE)) 1009 return(IFM_ETHER|IFM_10_T); 1010 if ((current & BNC_bit) && (media & EE_W5_PORT_BNC)) 1011 return(IFM_ETHER|IFM_10_2); 1012 1013 if (media & EE_W5_PORT_AUI) 1014 return (IFM_ETHER|IFM_10_5); 1015 1016 return (IFM_ETHER|IFM_AUTO); 1017} 1018 1019static int 1020ex_ifmedia_upd(ifp) 1021 struct ifnet * ifp; 1022{ 1023 struct ex_softc * sc = ifp->if_softc; 1024 1025 if (IFM_TYPE(sc->ifmedia.ifm_media) != IFM_ETHER) 1026 return EINVAL; 1027 1028 return (0); 1029} 1030 1031static void 1032ex_ifmedia_sts(ifp, ifmr) 1033 struct ifnet * ifp; 1034 struct ifmediareq * ifmr; 1035{ 1036 struct ex_softc * sc = ifp->if_softc; 1037 1038 EX_LOCK(sc); 1039 ifmr->ifm_active = ex_get_media(sc); 1040 ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE; 1041 EX_UNLOCK(sc); 1042 1043 return; 1044} 1045 1046u_short 1047ex_eeprom_read(struct ex_softc *sc, int location) 1048{ 1049 int i; 1050 u_short data = 0; 1051 int read_cmd = location | EE_READ_CMD; 1052 short ctrl_val = EECS; 1053 1054 CSR_WRITE_1(sc, CMD_REG, Bank2_Sel); 1055 CSR_WRITE_1(sc, EEPROM_REG, EECS); 1056 for (i = 8; i >= 0; i--) { 1057 short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI : ctrl_val; 1058 CSR_WRITE_1(sc, EEPROM_REG, outval); 1059 CSR_WRITE_1(sc, EEPROM_REG, outval | EESK); 1060 DELAY(3); 1061 CSR_WRITE_1(sc, EEPROM_REG, outval); 1062 DELAY(2); 1063 } 1064 CSR_WRITE_1(sc, EEPROM_REG, ctrl_val); 1065 1066 for (i = 16; i > 0; i--) { 1067 CSR_WRITE_1(sc, EEPROM_REG, ctrl_val | EESK); 1068 DELAY(3); 1069 data = (data << 1) | 1070 ((CSR_READ_1(sc, EEPROM_REG) & EEDO) ? 1 : 0); 1071 CSR_WRITE_1(sc, EEPROM_REG, ctrl_val); 1072 DELAY(2); 1073 } 1074 1075 ctrl_val &= ~EECS; 1076 CSR_WRITE_1(sc, EEPROM_REG, ctrl_val | EESK); 1077 DELAY(3); 1078 CSR_WRITE_1(sc, EEPROM_REG, ctrl_val); 1079 DELAY(2); 1080 CSR_WRITE_1(sc, CMD_REG, Bank0_Sel); 1081 return(data); 1082} 1083