1 /* $NetBSD: smc90cx6.c,v 1.59 2009/03/14 15:36:17 dsl Exp $ */ 2 3 /*- 4 * Copyright (c) 1994, 1995, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Ignatios Souvatzis. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Chip core driver for the SMC90c26 / SMC90c56 (and SMC90c66 in '56 34 * compatibility mode) boards 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: smc90cx6.c,v 1.59 2009/03/14 15:36:17 dsl Exp $"); 39 40 /* #define BAHSOFTCOPY */ 41 #define BAHRETRANSMIT /**/ 42 43 #include "opt_inet.h" 44 #include "bpfilter.h" 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/mbuf.h> 49 #include <sys/buf.h> 50 #include <sys/device.h> 51 #include <sys/protosw.h> 52 #include <sys/socket.h> 53 #include <sys/syslog.h> 54 #include <sys/ioctl.h> 55 #include <sys/errno.h> 56 #include <sys/kernel.h> 57 #include <sys/intr.h> 58 59 #include <net/if.h> 60 #include <net/if_dl.h> 61 #include <net/if_ether.h> 62 #include <net/if_types.h> 63 #include <net/if_arc.h> 64 65 #ifdef INET 66 #include <netinet/in.h> 67 #include <netinet/in_systm.h> 68 #include <netinet/in_var.h> 69 #include <netinet/ip.h> 70 #include <netinet/if_inarp.h> 71 #endif 72 73 #if NBPFILTER > 0 74 #include <net/bpf.h> 75 #include <net/bpfdesc.h> 76 #endif 77 78 #include <sys/bus.h> 79 #include <sys/cpu.h> 80 #include <machine/mtpr.h> 81 82 #include <dev/ic/smc90cx6reg.h> 83 #include <dev/ic/smc90cx6var.h> 84 85 /* these should be elsewhere */ 86 87 #define ARC_MIN_LEN 1 88 #define ARC_MIN_FORBID_LEN 254 89 #define ARC_MAX_FORBID_LEN 256 90 #define ARC_MAX_LEN 508 91 #define ARC_ADDR_LEN 1 92 93 /* for watchdog timer. This should be more than enough. */ 94 #define ARCTIMEOUT (5*IFNET_SLOWHZ) 95 96 /* 97 * This currently uses 2 bufs for tx, 2 for rx 98 * 99 * New rx protocol: 100 * 101 * rx has a fillcount variable. If fillcount > (NRXBUF-1), 102 * rx can be switched off from rx hard int. 103 * Else rx is restarted on the other receiver. 104 * rx soft int counts down. if it is == (NRXBUF-1), it restarts 105 * the receiver. 106 * To ensure packet ordering (we need that for 1201 later), we have a counter 107 * which is incremented modulo 256 on each receive and a per buffer 108 * variable, which is set to the counter on filling. The soft int can 109 * compare both values to determine the older packet. 110 * 111 * Transmit direction: 112 * 113 * bah_start checks tx_fillcount 114 * case 2: return 115 * 116 * else fill tx_act ^ 1 && inc tx_fillcount 117 * 118 * check tx_fillcount again. 119 * case 2: set IFF_OACTIVE to stop arc_output from filling us. 120 * case 1: start tx 121 * 122 * tint clears IFF_OCATIVE, decrements and checks tx_fillcount 123 * case 1: start tx on tx_act ^ 1, softcall bah_start 124 * case 0: softcall bah_start 125 * 126 * #define fill(i) get mbuf && copy mbuf to chip(i) 127 */ 128 129 void bah_init(struct bah_softc *); 130 void bah_reset(struct bah_softc *); 131 void bah_stop(struct bah_softc *); 132 void bah_start(struct ifnet *); 133 int bahintr(void *); 134 int bah_ioctl(struct ifnet *, unsigned long, void *); 135 void bah_watchdog(struct ifnet *); 136 void bah_srint(void *vsc); 137 static void bah_tint(struct bah_softc *, int); 138 void bah_reconwatch(void *); 139 140 /* short notation */ 141 142 #define GETREG(off) bus_space_read_1(bst_r, regs, (off)) 143 #define PUTREG(off, v) bus_space_write_1(bst_r, regs, (off), (v)) 144 #define GETMEM(off) bus_space_read_1(bst_m, mem, (off)) 145 #define PUTMEM(off, v) bus_space_write_1(bst_m, mem, (off), (v)) 146 147 void 148 bah_attach_subr(struct bah_softc *sc) 149 { 150 struct ifnet *ifp = &sc->sc_arccom.ac_if; 151 int s; 152 u_int8_t linkaddress; 153 154 bus_space_tag_t bst_r = sc->sc_bst_r; 155 bus_space_tag_t bst_m = sc->sc_bst_m; 156 bus_space_handle_t regs = sc->sc_regs; 157 bus_space_handle_t mem = sc->sc_mem; 158 159 #if (defined(BAH_DEBUG) && (BAH_DEBUG > 2)) 160 printf("\n%s: attach(0x%x, 0x%x, 0x%x)\n", 161 device_xname(&sc->sc_dev), parent, self, aux); 162 #endif 163 s = splhigh(); 164 165 /* 166 * read the arcnet address from the board 167 */ 168 169 (*sc->sc_reset)(sc, 1); 170 171 do { 172 delay(200); 173 } while (!(GETREG(BAHSTAT) & BAH_POR)); 174 175 linkaddress = GETMEM(BAHMACOFF); 176 177 printf(": link addr 0x%02x(%d)\n", linkaddress, linkaddress); 178 179 /* clear the int mask... */ 180 181 sc->sc_intmask = 0; 182 PUTREG(BAHSTAT, 0); 183 184 PUTREG(BAHCMD, BAH_CONF(CONF_LONG)); 185 PUTREG(BAHCMD, BAH_CLR(CLR_POR|CLR_RECONFIG)); 186 sc->sc_recontime = sc->sc_reconcount = 0; 187 188 /* and reenable kernel int level */ 189 splx(s); 190 191 /* 192 * set interface to stopped condition (reset) 193 */ 194 bah_stop(sc); 195 196 strlcpy(ifp->if_xname, device_xname(&sc->sc_dev), IFNAMSIZ); 197 ifp->if_softc = sc; 198 ifp->if_start = bah_start; 199 ifp->if_ioctl = bah_ioctl; 200 ifp->if_timer = 0; 201 ifp->if_watchdog = bah_watchdog; 202 IFQ_SET_READY(&ifp->if_snd); 203 204 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; 205 206 ifp->if_mtu = ARCMTU; 207 208 arc_ifattach(ifp, linkaddress); 209 210 #ifdef BAHSOFTCOPY 211 sc->sc_rxcookie = softint_establish(SOFTINT_NET, bah_srint, sc); 212 sc->sc_txcookie = softint_establish(SOFTINT_NET, 213 (void (*)(void *))bah_start, ifp); 214 #endif 215 216 callout_init(&sc->sc_recon_ch, 0); 217 } 218 219 /* 220 * Initialize device 221 * 222 */ 223 void 224 bah_init(struct bah_softc *sc) 225 { 226 struct ifnet *ifp; 227 int s; 228 229 ifp = &sc->sc_arccom.ac_if; 230 231 if ((ifp->if_flags & IFF_RUNNING) == 0) { 232 s = splnet(); 233 ifp->if_flags |= IFF_RUNNING; 234 bah_reset(sc); 235 bah_start(ifp); 236 splx(s); 237 } 238 } 239 240 /* 241 * Reset the interface... 242 * 243 * this assumes that it is called inside a critical section... 244 * 245 */ 246 void 247 bah_reset(struct bah_softc *sc) 248 { 249 struct ifnet *ifp; 250 uint8_t linkaddress; 251 252 bus_space_tag_t bst_r = sc->sc_bst_r; 253 bus_space_tag_t bst_m = sc->sc_bst_m; 254 bus_space_handle_t regs = sc->sc_regs; 255 bus_space_handle_t mem = sc->sc_mem; 256 257 ifp = &sc->sc_arccom.ac_if; 258 259 #ifdef BAH_DEBUG 260 printf("%s: reset\n", device_xname(&sc->sc_dev)); 261 #endif 262 /* stop and restart hardware */ 263 264 (*sc->sc_reset)(sc, 1); 265 do { 266 DELAY(200); 267 } while (!(GETREG(BAHSTAT) & BAH_POR)); 268 269 linkaddress = GETMEM(BAHMACOFF); 270 271 #if defined(BAH_DEBUG) && (BAH_DEBUG > 2) 272 printf("%s: reset: card reset, link addr = 0x%02x (%ld)\n", 273 device_xname(&sc->sc_dev), linkaddress, linkaddress); 274 #endif 275 276 /* tell the routing level about the (possibly changed) link address */ 277 if_set_sadl(ifp, &linkaddress, sizeof(linkaddress), false); 278 279 /* POR is NMI, but we need it below: */ 280 sc->sc_intmask = BAH_RECON|BAH_POR; 281 PUTREG(BAHSTAT, sc->sc_intmask); 282 PUTREG(BAHCMD, BAH_CONF(CONF_LONG)); 283 284 #ifdef BAH_DEBUG 285 printf("%s: reset: chip configured, status=0x%02x\n", 286 device_xname(&sc->sc_dev), GETREG(BAHSTAT)); 287 #endif 288 PUTREG(BAHCMD, BAH_CLR(CLR_POR|CLR_RECONFIG)); 289 290 #ifdef BAH_DEBUG 291 printf("%s: reset: bits cleared, status=0x%02x\n", 292 device_xname(&sc->sc_dev), GETREG(BAHSTAT); 293 #endif 294 295 sc->sc_reconcount_excessive = ARC_EXCESSIVE_RECONS; 296 297 /* start receiver */ 298 299 sc->sc_intmask |= BAH_RI; 300 sc->sc_rx_fillcount = 0; 301 sc->sc_rx_act = 2; 302 303 PUTREG(BAHCMD, BAH_RXBC(2)); 304 PUTREG(BAHSTAT, sc->sc_intmask); 305 306 #ifdef BAH_DEBUG 307 printf("%s: reset: started receiver, status=0x%02x\n", 308 device_xname(&sc->sc_dev), GETREG(BAHSTAT); 309 #endif 310 311 /* and init transmitter status */ 312 sc->sc_tx_act = 0; 313 sc->sc_tx_fillcount = 0; 314 315 ifp->if_flags |= IFF_RUNNING; 316 ifp->if_flags &= ~IFF_OACTIVE; 317 318 bah_start(ifp); 319 } 320 321 /* 322 * Take interface offline 323 */ 324 void 325 bah_stop(struct bah_softc *sc) 326 { 327 bus_space_tag_t bst_r = sc->sc_bst_r; 328 bus_space_handle_t regs = sc->sc_regs; 329 330 /* Stop the interrupts */ 331 PUTREG(BAHSTAT, 0); 332 333 /* Stop the interface */ 334 (*sc->sc_reset)(sc, 0); 335 336 /* Stop watchdog timer */ 337 sc->sc_arccom.ac_if.if_timer = 0; 338 } 339 340 /* 341 * Start output on interface. Get another datagram to send 342 * off the interface queue, and copy it to the 343 * interface before starting the output 344 * 345 * this assumes that it is called inside a critical section... 346 * XXX hm... does it still? 347 * 348 */ 349 void 350 bah_start(struct ifnet *ifp) 351 { 352 struct bah_softc *sc = ifp->if_softc; 353 struct mbuf *m,*mp; 354 355 bus_space_tag_t bst_r = sc->sc_bst_r; 356 bus_space_handle_t regs = sc->sc_regs; 357 bus_space_tag_t bst_m = sc->sc_bst_m; 358 bus_space_handle_t mem = sc->sc_mem; 359 360 int bah_ram_ptr; 361 int len, tlen, offset, s, buffer; 362 #ifdef BAHTIMINGS 363 u_long copystart, lencopy, perbyte; 364 #endif 365 366 #if defined(BAH_DEBUG) && (BAH_DEBUG > 3) 367 printf("%s: start(0x%x)\n", device_xname(&sc->sc_dev), ifp); 368 #endif 369 370 if ((ifp->if_flags & IFF_RUNNING) == 0) 371 return; 372 373 s = splnet(); 374 375 if (sc->sc_tx_fillcount >= 2) { 376 splx(s); 377 return; 378 } 379 380 IFQ_DEQUEUE(&ifp->if_snd, m); 381 buffer = sc->sc_tx_act ^ 1; 382 383 splx(s); 384 385 if (m == 0) 386 return; 387 388 #if NBPFILTER > 0 389 /* 390 * If bpf is listening on this interface, let it 391 * see the packet before we commit it to the wire 392 * 393 * (can't give the copy in A2060 card RAM to bpf, because 394 * that RAM is just accessed as on every other byte) 395 */ 396 if (ifp->if_bpf) 397 bpf_mtap(ifp->if_bpf, m); 398 #endif 399 400 #ifdef BAH_DEBUG 401 if (m->m_len < ARC_HDRLEN) 402 m = m_pullup(m, ARC_HDRLEN);/* gcc does structure padding */ 403 printf("%s: start: filling %ld from %ld to %ld type %ld\n", 404 device_xname(&sc->sc_dev), buffer, mtod(m, u_char *)[0], 405 mtod(m, u_char *)[1], mtod(m, u_char *)[2]); 406 #else 407 if (m->m_len < 2) 408 m = m_pullup(m, 2); 409 #endif 410 bah_ram_ptr = buffer*512; 411 412 if (m == 0) 413 return; 414 415 /* write the addresses to RAM and throw them away */ 416 417 /* 418 * Hardware does this: Yet Another Microsecond Saved. 419 * (btw, timing code says usually 2 microseconds) 420 * PUTMEM(bah_ram_ptr + 0, mtod(m, u_char *)[0]); 421 */ 422 423 PUTMEM(bah_ram_ptr + 1, mtod(m, u_char *)[1]); 424 m_adj(m, 2); 425 426 /* get total length left at this point */ 427 tlen = m->m_pkthdr.len; 428 if (tlen < ARC_MIN_FORBID_LEN) { 429 offset = 256 - tlen; 430 PUTMEM(bah_ram_ptr + 2, offset); 431 } else { 432 PUTMEM(bah_ram_ptr + 2, 0); 433 if (tlen <= ARC_MAX_FORBID_LEN) 434 offset = 255; /* !!! */ 435 else { 436 if (tlen > ARC_MAX_LEN) 437 tlen = ARC_MAX_LEN; 438 offset = 512 - tlen; 439 } 440 PUTMEM(bah_ram_ptr + 3, offset); 441 442 } 443 bah_ram_ptr += offset; 444 445 /* lets loop through the mbuf chain */ 446 447 for (mp = m; mp; mp = mp->m_next) { 448 if ((len = mp->m_len)) { /* YAMS */ 449 bus_space_write_region_1(bst_m, mem, bah_ram_ptr, 450 mtod(mp, void *), len); 451 452 bah_ram_ptr += len; 453 } 454 } 455 456 sc->sc_broadcast[buffer] = (m->m_flags & M_BCAST) != 0; 457 sc->sc_retransmits[buffer] = (m->m_flags & M_BCAST) ? 1 : 5; 458 459 /* actually transmit the packet */ 460 s = splnet(); 461 462 if (++sc->sc_tx_fillcount > 1) { 463 /* 464 * We are filled up to the rim. No more bufs for the moment, 465 * please. 466 */ 467 ifp->if_flags |= IFF_OACTIVE; 468 } else { 469 #ifdef BAH_DEBUG 470 printf("%s: start: starting transmitter on buffer %d\n", 471 device_xname(&sc->sc_dev), buffer); 472 #endif 473 /* Transmitter was off, start it */ 474 sc->sc_tx_act = buffer; 475 476 /* 477 * We still can accept another buf, so don't: 478 * ifp->if_flags |= IFF_OACTIVE; 479 */ 480 sc->sc_intmask |= BAH_TA; 481 PUTREG(BAHCMD, BAH_TX(buffer)); 482 PUTREG(BAHSTAT, sc->sc_intmask); 483 484 sc->sc_arccom.ac_if.if_timer = ARCTIMEOUT; 485 } 486 splx(s); 487 m_freem(m); 488 489 /* 490 * After 10 times reading the docs, I realized 491 * that in the case the receiver NAKs the buffer request, 492 * the hardware retries till shutdown. 493 * This is integrated now in the code above. 494 */ 495 496 return; 497 } 498 499 /* 500 * Arcnet interface receiver soft interrupt: 501 * get the stuff out of any filled buffer we find. 502 */ 503 void 504 bah_srint(void *vsc) 505 { 506 struct bah_softc *sc = (struct bah_softc *)vsc; 507 int buffer, len, len1, amount, offset, s, type; 508 int bah_ram_ptr; 509 struct mbuf *m, *dst, *head; 510 struct arc_header *ah; 511 struct ifnet *ifp; 512 513 bus_space_tag_t bst_r = sc->sc_bst_r; 514 bus_space_tag_t bst_m = sc->sc_bst_m; 515 bus_space_handle_t regs = sc->sc_regs; 516 bus_space_handle_t mem = sc->sc_mem; 517 518 ifp = &sc->sc_arccom.ac_if; 519 head = 0; 520 521 s = splnet(); 522 buffer = sc->sc_rx_act ^ 1; 523 splx(s); 524 525 /* Allocate header mbuf */ 526 MGETHDR(m, M_DONTWAIT, MT_DATA); 527 528 if (m == 0) { 529 /* 530 * in case s.th. goes wrong with mem, drop it 531 * to make sure the receiver can be started again 532 * count it as input error (we dont have any other 533 * detectable) 534 */ 535 ifp->if_ierrors++; 536 goto cleanup; 537 } 538 539 m->m_pkthdr.rcvif = ifp; 540 541 /* 542 * Align so that IP packet will be longword aligned. Here we 543 * assume that m_data of new packet is longword aligned. 544 * When implementing PHDS, we might have to change it to 2, 545 * (2*sizeof(ulong) - ARC_HDRNEWLEN)), packet type dependent. 546 */ 547 548 bah_ram_ptr = buffer*512; 549 offset = GETMEM(bah_ram_ptr + 2); 550 if (offset) 551 len = 256 - offset; 552 else { 553 offset = GETMEM(bah_ram_ptr + 3); 554 len = 512 - offset; 555 } 556 if (len+2 >= MINCLSIZE) 557 MCLGET(m, M_DONTWAIT); 558 559 if (m == 0) { 560 ifp->if_ierrors++; 561 goto cleanup; 562 } 563 564 type = GETMEM(bah_ram_ptr + offset); 565 m->m_data += 1 + arc_isphds(type); 566 567 head = m; 568 ah = mtod(head, struct arc_header *); 569 570 ah->arc_shost = GETMEM(bah_ram_ptr + 0); 571 ah->arc_dhost = GETMEM(bah_ram_ptr + 1); 572 573 m->m_pkthdr.len = len+2; /* whole packet length */ 574 m->m_len = 2; /* mbuf filled with ARCnet addresses */ 575 bah_ram_ptr += offset; /* ram buffer continues there */ 576 577 while (len > 0) { 578 579 len1 = len; 580 amount = M_TRAILINGSPACE(m); 581 582 if (amount == 0) { 583 dst = m; 584 MGET(m, M_DONTWAIT, MT_DATA); 585 586 if (m == 0) { 587 ifp->if_ierrors++; 588 goto cleanup; 589 } 590 591 if (len1 >= MINCLSIZE) 592 MCLGET(m, M_DONTWAIT); 593 594 m->m_len = 0; 595 dst->m_next = m; 596 amount = M_TRAILINGSPACE(m); 597 } 598 599 if (amount < len1) 600 len1 = amount; 601 602 bus_space_read_region_1(bst_m, mem, bah_ram_ptr, 603 mtod(m, u_char *) + m->m_len, len1); 604 605 m->m_len += len1; 606 bah_ram_ptr += len1; 607 len -= len1; 608 } 609 610 #if NBPFILTER > 0 611 if (ifp->if_bpf) 612 bpf_mtap(ifp->if_bpf, head); 613 #endif 614 615 (*sc->sc_arccom.ac_if.if_input)(&sc->sc_arccom.ac_if, head); 616 617 head = NULL; 618 ifp->if_ipackets++; 619 620 cleanup: 621 622 if (head != NULL) 623 m_freem(head); 624 625 /* mark buffer as invalid by source id 0 */ 626 bus_space_write_1(bst_m, mem, buffer*512, 0); 627 s = splnet(); 628 629 if (--sc->sc_rx_fillcount == 2 - 1) { 630 631 /* was off, restart it on buffer just emptied */ 632 sc->sc_rx_act = buffer; 633 sc->sc_intmask |= BAH_RI; 634 635 /* this also clears the RI flag interrupt: */ 636 PUTREG(BAHCMD, BAH_RXBC(buffer)); 637 PUTREG(BAHSTAT, sc->sc_intmask); 638 639 #ifdef BAH_DEBUG 640 printf("%s: srint: restarted rx on buf %ld\n", 641 device_xname(&sc->sc_dev), buffer); 642 #endif 643 } 644 splx(s); 645 } 646 647 inline static void 648 bah_tint(struct bah_softc *sc, int isr) 649 { 650 struct ifnet *ifp; 651 652 bus_space_tag_t bst_r = sc->sc_bst_r; 653 bus_space_handle_t regs = sc->sc_regs; 654 655 656 int buffer; 657 #ifdef BAHTIMINGS 658 int clknow; 659 #endif 660 661 ifp = &(sc->sc_arccom.ac_if); 662 buffer = sc->sc_tx_act; 663 664 /* 665 * retransmit code: 666 * Normal situations first for fast path: 667 * If acknowledgement received ok or broadcast, we're ok. 668 * else if 669 */ 670 671 if (isr & BAH_TMA || sc->sc_broadcast[buffer]) 672 sc->sc_arccom.ac_if.if_opackets++; 673 #ifdef BAHRETRANSMIT 674 else if (ifp->if_flags & IFF_LINK2 && ifp->if_timer > 0 675 && --sc->sc_retransmits[buffer] > 0) { 676 /* retransmit same buffer */ 677 PUTREG(BAHCMD, BAH_TX(buffer)); 678 return; 679 } 680 #endif 681 else 682 ifp->if_oerrors++; 683 684 685 /* We know we can accept another buffer at this point. */ 686 ifp->if_flags &= ~IFF_OACTIVE; 687 688 if (--sc->sc_tx_fillcount > 0) { 689 690 /* 691 * start tx on other buffer. 692 * This also clears the int flag 693 */ 694 buffer ^= 1; 695 sc->sc_tx_act = buffer; 696 697 /* 698 * already given: 699 * sc->sc_intmask |= BAH_TA; 700 * PUTREG(BAHSTAT, sc->sc_intmask); 701 */ 702 PUTREG(BAHCMD, BAH_TX(buffer)); 703 /* init watchdog timer */ 704 ifp->if_timer = ARCTIMEOUT; 705 706 #if defined(BAH_DEBUG) && (BAH_DEBUG > 1) 707 printf("%s: tint: starting tx on buffer %d, status 0x%02x\n", 708 device_xname(&sc->sc_dev), buffer, GETREG(BAHSTAT)); 709 #endif 710 } else { 711 /* have to disable TX interrupt */ 712 sc->sc_intmask &= ~BAH_TA; 713 PUTREG(BAHSTAT, sc->sc_intmask); 714 /* ... and watchdog timer */ 715 ifp->if_timer = 0; 716 717 #ifdef BAH_DEBUG 718 printf("%s: tint: no more buffers to send, status 0x%02x\n", 719 device_xname(&sc->sc_dev), GETREG(BAHSTAT)); 720 #endif 721 } 722 723 /* XXXX TODO */ 724 #ifdef BAHSOFTCOPY 725 /* schedule soft int to fill a new buffer for us */ 726 softint_schedule(sc->sc_txcookie); 727 #else 728 /* call it directly */ 729 bah_start(ifp); 730 #endif 731 } 732 733 /* 734 * Our interrupt routine 735 */ 736 int 737 bahintr(void *arg) 738 { 739 struct bah_softc *sc = arg; 740 741 bus_space_tag_t bst_r = sc->sc_bst_r; 742 bus_space_tag_t bst_m = sc->sc_bst_m; 743 bus_space_handle_t regs = sc->sc_regs; 744 bus_space_handle_t mem = sc->sc_mem; 745 746 u_char isr, maskedisr; 747 int buffer; 748 u_long newsec; 749 750 isr = GETREG(BAHSTAT); 751 maskedisr = isr & sc->sc_intmask; 752 if (!maskedisr) 753 return (0); 754 do { 755 756 #if defined(BAH_DEBUG) && (BAH_DEBUG>1) 757 printf("%s: intr: status 0x%02x, intmask 0x%02x\n", 758 device_xname(&sc->sc_dev), isr, sc->sc_intmask); 759 #endif 760 761 if (maskedisr & BAH_POR) { 762 /* 763 * XXX We should never see this. Don't bother to store 764 * the address. 765 * sc->sc_arccom.ac_anaddr = GETMEM(BAHMACOFF); 766 */ 767 PUTREG(BAHCMD, BAH_CLR(CLR_POR)); 768 log(LOG_WARNING, 769 "%s: intr: got spurious power on reset int\n", 770 device_xname(&sc->sc_dev)); 771 } 772 773 if (maskedisr & BAH_RECON) { 774 /* 775 * we dont need to: 776 * PUTREG(BAHCMD, BAH_CONF(CONF_LONG)); 777 */ 778 PUTREG(BAHCMD, BAH_CLR(CLR_RECONFIG)); 779 sc->sc_arccom.ac_if.if_collisions++; 780 781 /* 782 * If less than 2 seconds per reconfig: 783 * If ARC_EXCESSIVE_RECONFIGS 784 * since last burst, complain and set threshold for 785 * warnings to ARC_EXCESSIVE_RECONS_REWARN. 786 * 787 * This allows for, e.g., new stations on the cable, or 788 * cable switching as long as it is over after 789 * (normally) 16 seconds. 790 * 791 * XXX TODO: check timeout bits in status word and 792 * double time if necessary. 793 */ 794 795 callout_stop(&sc->sc_recon_ch); 796 newsec = time_second; 797 if ((newsec - sc->sc_recontime <= 2) && 798 (++sc->sc_reconcount == ARC_EXCESSIVE_RECONS)) { 799 log(LOG_WARNING, 800 "%s: excessive token losses, " 801 "cable problem?\n", device_xname(&sc->sc_dev)); 802 } 803 sc->sc_recontime = newsec; 804 callout_reset(&sc->sc_recon_ch, 15 * hz, 805 bah_reconwatch, (void *)sc); 806 } 807 808 if (maskedisr & BAH_RI) { 809 #if defined(BAH_DEBUG) && (BAH_DEBUG > 1) 810 printf("%s: intr: hard rint, act %ld\n", 811 device_xname(&sc->sc_dev), sc->sc_rx_act); 812 #endif 813 814 buffer = sc->sc_rx_act; 815 /* look if buffer is marked invalid: */ 816 if (GETMEM(buffer*512) == 0) { 817 /* 818 * invalid marked buffer (or illegally 819 * configured sender) 820 */ 821 log(LOG_WARNING, 822 "%s: spurious RX interrupt or sender 0 " 823 " (ignored)\n", device_xname(&sc->sc_dev)); 824 /* 825 * restart receiver on same buffer. 826 * XXX maybe better reset interface? 827 */ 828 PUTREG(BAHCMD, BAH_RXBC(buffer)); 829 } else { 830 if (++sc->sc_rx_fillcount > 1) { 831 sc->sc_intmask &= ~BAH_RI; 832 PUTREG(BAHSTAT, sc->sc_intmask); 833 } else { 834 buffer ^= 1; 835 sc->sc_rx_act = buffer; 836 837 /* 838 * Start receiver on other receive 839 * buffer. This also clears the RI 840 * interrupt flag. 841 */ 842 PUTREG(BAHCMD, BAH_RXBC(buffer)); 843 /* in RX intr, so mask is ok for RX */ 844 845 #ifdef BAH_DEBUG 846 printf("%s: strt rx for buf %ld, " 847 "stat 0x%02x\n", 848 device_xname(&sc->sc_dev), sc->sc_rx_act, 849 GETREG(BAHSTAT); 850 #endif 851 } 852 853 #ifdef BAHSOFTCOPY 854 /* 855 * this one starts a soft int to copy out 856 * of the hw 857 */ 858 softint_schedule(sc->sc_rxcookie); 859 #else 860 /* this one does the copy here */ 861 bah_srint(sc); 862 #endif 863 } 864 } 865 if (maskedisr & BAH_TA) { 866 bah_tint(sc, isr); 867 } 868 isr = GETREG(BAHSTAT); 869 maskedisr = isr & sc->sc_intmask; 870 } while (maskedisr); 871 872 return (1); 873 } 874 875 void 876 bah_reconwatch(void *arg) 877 { 878 struct bah_softc *sc = arg; 879 880 if (sc->sc_reconcount >= ARC_EXCESSIVE_RECONS) { 881 sc->sc_reconcount = 0; 882 log(LOG_WARNING, "%s: token valid again.\n", 883 device_xname(&sc->sc_dev)); 884 } 885 sc->sc_reconcount = 0; 886 } 887 888 889 /* 890 * Process an ioctl request. 891 * This code needs some work - it looks pretty ugly. 892 */ 893 int 894 bah_ioctl(struct ifnet *ifp, u_long cmd, void *data) 895 { 896 struct bah_softc *sc; 897 struct ifaddr *ifa; 898 struct ifreq *ifr; 899 int s, error; 900 901 error = 0; 902 sc = ifp->if_softc; 903 ifa = (struct ifaddr *)data; 904 ifr = (struct ifreq *)data; 905 s = splnet(); 906 907 #if defined(BAH_DEBUG) && (BAH_DEBUG > 2) 908 printf("%s: ioctl() called, cmd = 0x%x\n", 909 device_xname(&sc->sc_dev), cmd); 910 #endif 911 912 switch (cmd) { 913 case SIOCINITIFADDR: 914 ifp->if_flags |= IFF_UP; 915 bah_init(sc); 916 switch (ifa->ifa_addr->sa_family) { 917 #ifdef INET 918 case AF_INET: 919 arp_ifinit(ifp, ifa); 920 break; 921 #endif 922 default: 923 break; 924 } 925 926 case SIOCSIFFLAGS: 927 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 928 break; 929 /* XXX re-use ether_ioctl() */ 930 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { 931 case IFF_RUNNING: 932 /* 933 * If interface is marked down and it is running, 934 * then stop it. 935 */ 936 bah_stop(sc); 937 ifp->if_flags &= ~IFF_RUNNING; 938 break; 939 case IFF_UP: 940 /* 941 * If interface is marked up and it is stopped, then 942 * start it. 943 */ 944 bah_init(sc); 945 break; 946 } 947 break; 948 949 case SIOCADDMULTI: 950 case SIOCDELMULTI: 951 switch (ifreq_getaddr(cmd, ifr)->sa_family) { 952 case AF_INET: 953 case AF_INET6: 954 error = 0; 955 break; 956 default: 957 error = EAFNOSUPPORT; 958 break; 959 } 960 break; 961 962 default: 963 error = ether_ioctl(ifp, cmd, data); 964 } 965 966 splx(s); 967 return (error); 968 } 969 970 /* 971 * watchdog routine for transmitter. 972 * 973 * We need this, because else a receiver whose hardware is alive, but whose 974 * software has not enabled the Receiver, would make our hardware wait forever 975 * Discovered this after 20 times reading the docs. 976 * 977 * Only thing we do is disable transmitter. We'll get an transmit timeout, 978 * and the int handler will have to decide not to retransmit (in case 979 * retransmission is implemented). 980 * 981 * This one assumes being called inside splnet() 982 */ 983 984 void 985 bah_watchdog(struct ifnet *ifp) 986 { 987 struct bah_softc *sc = ifp->if_softc; 988 989 bus_space_tag_t bst_r = sc->sc_bst_r; 990 bus_space_handle_t regs = sc->sc_regs; 991 992 PUTREG(BAHCMD, BAH_TXDIS); 993 return; 994 } 995 996