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