1 /* $NetBSD: if_qn.c,v 1.18 1999/05/18 23:52:52 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Mika Kortelainen 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Mika Kortelainen 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 * Thanks for Aspecs Oy (Finland) for the data book for the NIC used 33 * in this card and also many thanks for the Resource Management Force 34 * (QuickNet card manufacturer) and especially Daniel Koch for providing 35 * me with the necessary 'inside' information to write the driver. 36 * 37 * This is partly based on other code: 38 * - if_ed.c: basic function structure for Ethernet driver and now also 39 * qn_put() is done similarly, i.e. no extra packet buffers. 40 * 41 * Device driver for National Semiconductor DS8390/WD83C690 based ethernet 42 * adapters. 43 * 44 * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. 45 * 46 * Copyright (C) 1993, David Greenman. This software may be used, 47 * modified, copied, distributed, and sold, in both source and binary 48 * form provided that the above copyright and these terms are retained. 49 * Under no circumstances is the author responsible for the proper 50 * functioning of this software, nor does the author assume any 51 * responsibility for damages incurred with its use. 52 * 53 * - if_es.c: used as an example of -current driver 54 * 55 * Copyright (c) 1995 Michael L. Hitch 56 * All rights reserved. 57 * 58 * - if_fe.c: some ideas for error handling for qn_rint() which might 59 * have fixed those random lock ups, too. 60 * 61 * All Rights Reserved, Copyright (C) Fujitsu Limited 1995 62 * 63 * 64 * TODO: 65 * - add multicast support 66 */ 67 68 #include "qn.h" 69 #if NQN > 0 70 71 #define QN_DEBUG 72 #define QN_DEBUG1_no /* hides some old tests */ 73 #define QN_CHECKS_no /* adds some checks (not needed in normal situations) */ 74 75 #include "bpfilter.h" 76 77 /* 78 * Fujitsu MB86950 Ethernet Controller (as used in the QuickNet QN2000 79 * Ethernet card) 80 */ 81 82 #include "opt_inet.h" 83 #include "opt_ns.h" 84 85 #include <sys/param.h> 86 #include <sys/systm.h> 87 #include <sys/mbuf.h> 88 #include <sys/buf.h> 89 #include <sys/device.h> 90 #include <sys/protosw.h> 91 #include <sys/socket.h> 92 #include <sys/syslog.h> 93 #include <sys/ioctl.h> 94 #include <sys/errno.h> 95 96 #include <net/if.h> 97 #include <net/if_dl.h> 98 #include <net/if_ether.h> 99 100 #ifdef INET 101 #include <netinet/in.h> 102 #include <netinet/in_systm.h> 103 #include <netinet/in_var.h> 104 #include <netinet/ip.h> 105 #include <netinet/if_inarp.h> 106 #endif 107 108 #ifdef NS 109 #include <netns/ns.h> 110 #include <netns/ns_if.h> 111 #endif 112 113 #include <machine/cpu.h> 114 #include <machine/mtpr.h> 115 #include <amiga/amiga/device.h> 116 #include <amiga/amiga/isr.h> 117 #include <amiga/dev/zbusvar.h> 118 #include <amiga/dev/if_qnreg.h> 119 120 121 #define NIC_R_MASK (R_INT_PKT_RDY | R_INT_ALG_ERR |\ 122 R_INT_CRC_ERR | R_INT_OVR_FLO) 123 #define MAX_PACKETS 30 /* max number of packets read per interrupt */ 124 125 /* 126 * Ethernet software status per interface 127 * 128 * Each interface is referenced by a network interface structure, 129 * qn_if, which the routing code uses to locate the interface. 130 * This structure contains the output queue for the interface, its address, ... 131 */ 132 struct qn_softc { 133 struct device sc_dev; 134 struct isr sc_isr; 135 struct ethercom sc_ethercom; /* Common ethernet structures */ 136 u_char volatile *sc_base; 137 u_char volatile *sc_nic_base; 138 u_short volatile *nic_fifo; 139 u_short volatile *nic_r_status; 140 u_short volatile *nic_t_status; 141 u_short volatile *nic_r_mask; 142 u_short volatile *nic_t_mask; 143 u_short volatile *nic_r_mode; 144 u_short volatile *nic_t_mode; 145 u_short volatile *nic_reset; 146 u_short volatile *nic_len; 147 u_char transmit_pending; 148 #if NBPFILTER > 0 149 caddr_t sc_bpf; 150 #endif 151 } qn_softc[NQN]; 152 153 #if NBPFILTER > 0 154 #include <net/bpf.h> 155 #include <net/bpfdesc.h> 156 #endif 157 158 159 int qnmatch __P((struct device *, struct cfdata *, void *)); 160 void qnattach __P((struct device *, struct device *, void *)); 161 int qnintr __P((void *)); 162 int qnioctl __P((struct ifnet *, u_long, caddr_t)); 163 void qnstart __P((struct ifnet *)); 164 void qnwatchdog __P((struct ifnet *)); 165 void qnreset __P((struct qn_softc *)); 166 void qninit __P((struct qn_softc *)); 167 void qnstop __P((struct qn_softc *)); 168 static u_short qn_put __P((u_short volatile *, struct mbuf *)); 169 static void qn_rint __P((struct qn_softc *, u_short)); 170 static void qn_flush __P((struct qn_softc *)); 171 static void inline word_copy_from_card __P((u_short volatile *, u_short *, u_short)); 172 static void inline word_copy_to_card __P((u_short *, u_short volatile *, register u_short)); 173 static void qn_get_packet __P((struct qn_softc *, u_short)); 174 #ifdef QN_DEBUG1 175 static void qn_dump __P((struct qn_softc *)); 176 #endif 177 178 struct cfattach qn_ca = { 179 sizeof(struct qn_softc), qnmatch, qnattach 180 }; 181 182 int 183 qnmatch(parent, cfp, aux) 184 struct device *parent; 185 struct cfdata *cfp; 186 void *aux; 187 { 188 struct zbus_args *zap; 189 190 zap = (struct zbus_args *)aux; 191 192 /* RMF QuickNet QN2000 EtherNet card */ 193 if (zap->manid == 2011 && zap->prodid == 2) 194 return (1); 195 196 return (0); 197 } 198 199 /* 200 * Interface exists: make available by filling in network interface 201 * record. System will initialize the interface when it is ready 202 * to accept packets. 203 */ 204 void 205 qnattach(parent, self, aux) 206 struct device *parent, *self; 207 void *aux; 208 { 209 struct zbus_args *zap; 210 struct qn_softc *sc = (struct qn_softc *)self; 211 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 212 u_int8_t myaddr[ETHER_ADDR_LEN]; 213 214 zap = (struct zbus_args *)aux; 215 216 sc->sc_base = zap->va; 217 sc->sc_nic_base = sc->sc_base + QUICKNET_NIC_BASE; 218 sc->nic_fifo = (u_short volatile *)(sc->sc_nic_base + NIC_BMPR0); 219 sc->nic_len = (u_short volatile *)(sc->sc_nic_base + NIC_BMPR2); 220 sc->nic_t_status = (u_short volatile *)(sc->sc_nic_base + NIC_DLCR0); 221 sc->nic_r_status = (u_short volatile *)(sc->sc_nic_base + NIC_DLCR2); 222 sc->nic_t_mask = (u_short volatile *)(sc->sc_nic_base + NIC_DLCR1); 223 sc->nic_r_mask = (u_short volatile *)(sc->sc_nic_base + NIC_DLCR3); 224 sc->nic_t_mode = (u_short volatile *)(sc->sc_nic_base + NIC_DLCR4); 225 sc->nic_r_mode = (u_short volatile *)(sc->sc_nic_base + NIC_DLCR5); 226 sc->nic_reset = (u_short volatile *)(sc->sc_nic_base + NIC_DLCR6); 227 sc->transmit_pending = 0; 228 229 /* 230 * The ethernet address of the board (1st three bytes are the vendor 231 * address, the rest is the serial number of the board). 232 */ 233 myaddr[0] = 0x5c; 234 myaddr[1] = 0x5c; 235 myaddr[2] = 0x00; 236 myaddr[3] = (zap->serno >> 16) & 0xff; 237 myaddr[4] = (zap->serno >> 8) & 0xff; 238 myaddr[5] = zap->serno & 0xff; 239 240 /* set interface to stopped condition (reset) */ 241 qnstop(sc); 242 243 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 244 ifp->if_softc = sc; 245 ifp->if_ioctl = qnioctl; 246 ifp->if_watchdog = qnwatchdog; 247 ifp->if_start = qnstart; 248 /* XXX IFF_MULTICAST */ 249 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; 250 ifp->if_mtu = ETHERMTU; 251 252 /* Attach the interface. */ 253 if_attach(ifp); 254 ether_ifattach(ifp, myaddr); 255 256 #ifdef QN_DEBUG 257 printf(": hardware address %s\n", ether_sprintf(myaddr)); 258 #endif 259 260 #if NBPFILTER > 0 261 bpfattach(&sc->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 262 #endif 263 264 sc->sc_isr.isr_intr = qnintr; 265 sc->sc_isr.isr_arg = sc; 266 sc->sc_isr.isr_ipl = 2; 267 add_isr(&sc->sc_isr); 268 } 269 270 /* 271 * Initialize device 272 * 273 */ 274 void 275 qninit(sc) 276 struct qn_softc *sc; 277 { 278 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 279 u_short i; 280 static int retry = 0; 281 282 *sc->nic_r_mask = NIC_R_MASK; 283 *sc->nic_t_mode = NO_LOOPBACK; 284 285 if (sc->sc_ethercom.ec_if.if_flags & IFF_PROMISC) { 286 *sc->nic_r_mode = PROMISCUOUS_MODE; 287 log(LOG_INFO, "qn: Promiscuous mode (not tested)\n"); 288 } else 289 *sc->nic_r_mode = NORMAL_MODE; 290 291 /* Set physical ethernet address. */ 292 for (i = 0; i < ETHER_ADDR_LEN; i++) 293 *((u_short volatile *)(sc->sc_nic_base+ 294 QNET_HARDWARE_ADDRESS+2*i)) = 295 ((((u_short)LLADDR(ifp->if_sadl)[i]) << 8) | 296 LLADDR(ifp->if_sadl)[i]); 297 298 ifp->if_flags |= IFF_RUNNING; 299 ifp->if_flags &= ~IFF_OACTIVE; 300 sc->transmit_pending = 0; 301 302 qn_flush(sc); 303 304 /* QuickNet magic. Done ONLY once, otherwise a lockup occurs. */ 305 if (retry == 0) { 306 *((u_short volatile *)(sc->sc_nic_base + QNET_MAGIC)) = 0; 307 retry = 1; 308 } 309 310 /* Enable data link controller. */ 311 *sc->nic_reset = ENABLE_DLC; 312 313 /* Attempt to start output, if any. */ 314 qnstart(ifp); 315 } 316 317 /* 318 * Device timeout/watchdog routine. Entered if the device neglects to 319 * generate an interrupt after a transmit has been started on it. 320 */ 321 void 322 qnwatchdog(ifp) 323 struct ifnet *ifp; 324 { 325 struct qn_softc *sc = ifp->if_softc; 326 327 log(LOG_INFO, "qn: device timeout (watchdog)\n"); 328 ++sc->sc_ethercom.ec_if.if_oerrors; 329 330 qnreset(sc); 331 } 332 333 /* 334 * Flush card's buffer RAM. 335 */ 336 static void 337 qn_flush(sc) 338 struct qn_softc *sc; 339 { 340 #if 1 341 /* Read data until bus read error (i.e. buffer empty). */ 342 while (!(*sc->nic_r_status & R_BUS_RD_ERR)) 343 (void)(*sc->nic_fifo); 344 #else 345 /* Read data twice to clear some internal pipelines. */ 346 (void)(*sc->nic_fifo); 347 (void)(*sc->nic_fifo); 348 #endif 349 350 /* Clear bus read error. */ 351 *sc->nic_r_status = R_BUS_RD_ERR; 352 } 353 354 /* 355 * Reset the interface. 356 * 357 */ 358 void 359 qnreset(sc) 360 struct qn_softc *sc; 361 { 362 int s; 363 364 s = splnet(); 365 qnstop(sc); 366 qninit(sc); 367 splx(s); 368 } 369 370 /* 371 * Take interface offline. 372 */ 373 void 374 qnstop(sc) 375 struct qn_softc *sc; 376 { 377 378 /* Stop the interface. */ 379 *sc->nic_reset = DISABLE_DLC; 380 delay(200); 381 *sc->nic_t_status = CLEAR_T_ERR; 382 *sc->nic_t_mask = CLEAR_T_MASK; 383 *sc->nic_r_status = CLEAR_R_ERR; 384 *sc->nic_r_mask = CLEAR_R_MASK; 385 386 /* Turn DMA off */ 387 *((u_short volatile *)(sc->sc_nic_base + NIC_BMPR4)) = 0; 388 389 /* Accept no packets. */ 390 *sc->nic_r_mode = 0; 391 *sc->nic_t_mode = 0; 392 393 qn_flush(sc); 394 } 395 396 /* 397 * Start output on interface. Get another datagram to send 398 * off the interface queue, and copy it to the 399 * interface before starting the output. 400 * 401 * This assumes that it is called inside a critical section... 402 * 403 */ 404 void 405 qnstart(ifp) 406 struct ifnet *ifp; 407 { 408 struct qn_softc *sc = ifp->if_softc; 409 struct mbuf *m; 410 u_short len; 411 int timout = 60000; 412 413 414 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 415 return; 416 417 IF_DEQUEUE(&ifp->if_snd, m); 418 if (m == 0) 419 return; 420 421 #if NBPFILTER > 0 422 /* 423 * If bpf is listening on this interface, let it 424 * see the packet before we commit it to the wire 425 * 426 * (can't give the copy in QuickNet card RAM to bpf, because 427 * that RAM is not visible to the host but is read from FIFO) 428 * 429 */ 430 if (sc->sc_bpf) 431 bpf_mtap(sc->sc_bpf, m); 432 #endif 433 len = qn_put(sc->nic_fifo, m); 434 m_freem(m); 435 436 /* 437 * Really transmit the packet. 438 */ 439 440 /* Set packet length (byte-swapped). */ 441 len = ((len >> 8) & 0x0007) | TRANSMIT_START | ((len & 0x00ff) << 8); 442 *sc->nic_len = len; 443 444 /* Wait for the packet to really leave. */ 445 while (!(*sc->nic_t_status & T_TMT_OK) && --timout) { 446 if ((timout % 10000) == 0) 447 log(LOG_INFO, "qn: timout...\n"); 448 } 449 450 if (timout == 0) 451 /* Maybe we should try to recover from this one? */ 452 /* But now, let's just fall thru and hope the best... */ 453 log(LOG_INFO, "qn: transmit timout (fatal?)\n"); 454 455 sc->transmit_pending = 1; 456 *sc->nic_t_mask = INT_TMT_OK | INT_SIXTEEN_COL; 457 458 ifp->if_flags |= IFF_OACTIVE; 459 ifp->if_timer = 2; 460 } 461 462 /* 463 * Memory copy, copies word at a time 464 */ 465 static void inline 466 word_copy_from_card(card, b, len) 467 u_short volatile *card; 468 u_short *b, len; 469 { 470 register u_short l = len/2; 471 472 while (l--) 473 *b++ = *card; 474 } 475 476 static void inline 477 word_copy_to_card(a, card, len) 478 u_short *a; 479 u_short volatile *card; 480 register u_short len; 481 { 482 /*register u_short l = len/2;*/ 483 484 while (len--) 485 *card = *a++; 486 } 487 488 /* 489 * Copy packet from mbuf to the board memory 490 * 491 */ 492 static u_short 493 qn_put(addr, m) 494 u_short volatile *addr; 495 struct mbuf *m; 496 { 497 u_short *data; 498 u_char savebyte[2]; 499 int len, len1, wantbyte; 500 u_short totlen; 501 502 totlen = wantbyte = 0; 503 504 for (; m != NULL; m = m->m_next) { 505 data = mtod(m, u_short *); 506 len = m->m_len; 507 if (len > 0) { 508 totlen += len; 509 510 /* Finish the last word. */ 511 if (wantbyte) { 512 savebyte[1] = *((u_char *)data); 513 *addr = *((u_short *)savebyte); 514 ((u_char *)data)++; 515 len--; 516 wantbyte = 0; 517 } 518 /* Output contiguous words. */ 519 if (len > 1) { 520 len1 = len/2; 521 word_copy_to_card(data, addr, len1); 522 data += len1; 523 len &= 1; 524 } 525 /* Save last byte, if necessary. */ 526 if (len == 1) { 527 savebyte[0] = *((u_char *)data); 528 wantbyte = 1; 529 } 530 } 531 } 532 533 if (wantbyte) { 534 savebyte[1] = 0; 535 *addr = *((u_short *)savebyte); 536 } 537 538 if(totlen < (ETHER_MIN_LEN - ETHER_CRC_LEN)) { 539 /* 540 * Fill the rest of the packet with zeros. 541 * N.B.: This is required! Otherwise MB86950 fails. 542 */ 543 for(len = totlen + 1; len < (ETHER_MIN_LEN - ETHER_CRC_LEN); 544 len += 2) 545 *addr = (u_short)0x0000; 546 totlen = (ETHER_MIN_LEN - ETHER_CRC_LEN); 547 } 548 549 return (totlen); 550 } 551 552 /* 553 * Copy packet from board RAM. 554 * 555 * Trailers not supported. 556 * 557 */ 558 static void 559 qn_get_packet(sc, len) 560 struct qn_softc *sc; 561 u_short len; 562 { 563 register u_short volatile *nic_fifo_ptr = sc->nic_fifo; 564 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 565 struct ether_header *eh; 566 struct mbuf *m, *dst, *head = NULL; 567 register u_short len1; 568 u_short amount; 569 570 /* Allocate header mbuf. */ 571 MGETHDR(m, M_DONTWAIT, MT_DATA); 572 if (m == NULL) 573 goto bad; 574 575 /* 576 * Round len to even value. 577 */ 578 if (len & 1) 579 len++; 580 581 m->m_pkthdr.rcvif = &sc->sc_ethercom.ec_if; 582 m->m_pkthdr.len = len; 583 m->m_len = 0; 584 head = m; 585 586 eh = mtod(head, struct ether_header *); 587 588 word_copy_from_card(nic_fifo_ptr, 589 mtod(head, u_short *), 590 sizeof(struct ether_header)); 591 592 head->m_len += sizeof(struct ether_header); 593 len -= sizeof(struct ether_header); 594 595 while (len > 0) { 596 len1 = len; 597 598 amount = M_TRAILINGSPACE(m); 599 if (amount == 0) { 600 /* Allocate another mbuf. */ 601 dst = m; 602 MGET(m, M_DONTWAIT, MT_DATA); 603 if (m == NULL) 604 goto bad; 605 606 if (len1 >= MINCLSIZE) 607 MCLGET(m, M_DONTWAIT); 608 609 m->m_len = 0; 610 dst->m_next = m; 611 612 amount = M_TRAILINGSPACE(m); 613 } 614 615 if (amount < len1) 616 len1 = amount; 617 618 word_copy_from_card(nic_fifo_ptr, 619 (u_short *)(mtod(m, caddr_t) + m->m_len), 620 len1); 621 m->m_len += len1; 622 len -= len1; 623 } 624 625 #if NBPFILTER > 0 626 if (sc->sc_bpf) { 627 bpf_mtap(sc->sc_bpf, head); 628 629 /* 630 * The interface cannot be in promiscuous mode if there are 631 * no BPF listeners. And in prom. mode we have to check 632 * if the packet is really ours... 633 */ 634 if ((ifp->if_flags & IFF_PROMISC) && 635 (eh->ether_dhost[0] & 1) == 0 && /* not bcast or mcast */ 636 bcmp(eh->ether_dhost, 637 LLADDR(ifp->if_sadl), 638 ETHER_ADDR_LEN) != 0) { 639 m_freem(head); 640 return; 641 } 642 } 643 #endif 644 645 (*ifp->if_input)(ifp, head); 646 return; 647 648 bad: 649 if (head) { 650 m_freem(head); 651 log(LOG_INFO, "qn_get_packet: mbuf alloc failed\n"); 652 } 653 } 654 655 /* 656 * Ethernet interface receiver interrupt. 657 */ 658 static void 659 qn_rint(sc, rstat) 660 struct qn_softc *sc; 661 u_short rstat; 662 { 663 int i; 664 u_short len, status; 665 666 /* Clear the status register. */ 667 *sc->nic_r_status = CLEAR_R_ERR; 668 669 /* 670 * Was there some error? 671 * Some of them are senseless because they are masked off. 672 * XXX 673 */ 674 if (rstat & R_INT_OVR_FLO) { 675 #ifdef QN_DEBUG 676 log(LOG_INFO, "Overflow\n"); 677 #endif 678 ++sc->sc_ethercom.ec_if.if_ierrors; 679 } 680 if (rstat & R_INT_CRC_ERR) { 681 #ifdef QN_DEBUG 682 log(LOG_INFO, "CRC Error\n"); 683 #endif 684 ++sc->sc_ethercom.ec_if.if_ierrors; 685 } 686 if (rstat & R_INT_ALG_ERR) { 687 #ifdef QN_DEBUG 688 log(LOG_INFO, "Alignment error\n"); 689 #endif 690 ++sc->sc_ethercom.ec_if.if_ierrors; 691 } 692 if (rstat & R_INT_SRT_PKT) { 693 /* Short packet (these may occur and are 694 * no reason to worry about - or maybe 695 * they are?). 696 */ 697 #ifdef QN_DEBUG 698 log(LOG_INFO, "Short packet\n"); 699 #endif 700 ++sc->sc_ethercom.ec_if.if_ierrors; 701 } 702 if (rstat & 0x4040) { 703 #ifdef QN_DEBUG 704 log(LOG_INFO, "Bus read error\n"); 705 #endif 706 ++sc->sc_ethercom.ec_if.if_ierrors; 707 qnreset(sc); 708 } 709 710 /* 711 * Read at most MAX_PACKETS packets per interrupt 712 */ 713 for (i = 0; i < MAX_PACKETS; i++) { 714 if (*sc->nic_r_mode & RM_BUF_EMP) 715 /* Buffer empty. */ 716 break; 717 718 /* 719 * Read the first word: upper byte contains useful 720 * information. 721 */ 722 status = *sc->nic_fifo; 723 if ((status & 0x7000) != 0x2000) { 724 log(LOG_INFO, "qn: ERROR: status=%04x\n", status); 725 continue; 726 } 727 728 /* 729 * Read packet length (byte-swapped). 730 * CRC is stripped off by the NIC. 731 */ 732 len = *sc->nic_fifo; 733 len = ((len << 8) & 0xff00) | ((len >> 8) & 0x00ff); 734 735 #ifdef QN_CHECKS 736 if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN) || 737 len < ETHER_HDR_LEN) { 738 log(LOG_WARNING, 739 "%s: received a %s packet? (%u bytes)\n", 740 sc->sc_dev.dv_xname, 741 len < ETHER_HDR_LEN ? "partial" : "big", len); 742 ++sc->sc_ethercom.ec_if.if_ierrors; 743 continue; 744 } 745 #endif 746 #ifdef QN_CHECKS 747 if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN)) 748 log(LOG_WARNING, 749 "%s: received a short packet? (%u bytes)\n", 750 sc->sc_dev.dv_xname, len); 751 #endif 752 753 /* Read the packet. */ 754 qn_get_packet(sc, len); 755 756 ++sc->sc_ethercom.ec_if.if_ipackets; 757 } 758 759 #ifdef QN_DEBUG 760 /* This print just to see whether MAX_PACKETS is large enough. */ 761 if (i == MAX_PACKETS) 762 log(LOG_INFO, "used all the %d loops\n", MAX_PACKETS); 763 #endif 764 } 765 766 /* 767 * Our interrupt routine 768 */ 769 int 770 qnintr(arg) 771 void *arg; 772 { 773 struct qn_softc *sc = arg; 774 u_short tint, rint, tintmask; 775 char return_tintmask = 0; 776 777 /* 778 * If the driver has not been initialized, just return immediately. 779 * This also happens if there is no QuickNet board present. 780 */ 781 if (sc->sc_base == NULL) 782 return (0); 783 784 /* Get interrupt statuses and masks. */ 785 rint = (*sc->nic_r_status) & NIC_R_MASK; 786 tintmask = *sc->nic_t_mask; 787 tint = (*sc->nic_t_status) & tintmask; 788 if (tint == 0 && rint == 0) 789 return (0); 790 791 /* Disable interrupts so that we won't miss anything. */ 792 *sc->nic_r_mask = CLEAR_R_MASK; 793 *sc->nic_t_mask = CLEAR_T_MASK; 794 795 /* 796 * Handle transmitter interrupts. Some of them are not asked for 797 * but do happen, anyway. 798 */ 799 800 if (tint != 0) { 801 /* Clear transmit interrupt status. */ 802 *sc->nic_t_status = CLEAR_T_ERR; 803 804 if (sc->transmit_pending && (tint & T_TMT_OK)) { 805 sc->transmit_pending = 0; 806 /* 807 * Update total number of successfully 808 * transmitted packets. 809 */ 810 sc->sc_ethercom.ec_if.if_opackets++; 811 } 812 813 if (tint & T_SIXTEEN_COL) { 814 /* 815 * 16 collision (i.e., packet lost). 816 */ 817 log(LOG_INFO, "qn: 16 collision - packet lost\n"); 818 #ifdef QN_DEBUG1 819 qn_dump(sc); 820 #endif 821 sc->sc_ethercom.ec_if.if_oerrors++; 822 sc->sc_ethercom.ec_if.if_collisions += 16; 823 sc->transmit_pending = 0; 824 } 825 826 if (sc->transmit_pending) { 827 log(LOG_INFO, "qn:still pending...\n"); 828 829 /* Must return transmission interrupt mask. */ 830 return_tintmask = 1; 831 } else { 832 sc->sc_ethercom.ec_if.if_flags &= ~IFF_OACTIVE; 833 834 /* Clear watchdog timer. */ 835 sc->sc_ethercom.ec_if.if_timer = 0; 836 } 837 } else 838 return_tintmask = 1; 839 840 /* 841 * Handle receiver interrupts. 842 */ 843 if (rint != 0) 844 qn_rint(sc, rint); 845 846 if ((sc->sc_ethercom.ec_if.if_flags & IFF_OACTIVE) == 0) 847 qnstart(&sc->sc_ethercom.ec_if); 848 else if (return_tintmask == 1) 849 *sc->nic_t_mask = tintmask; 850 851 /* Set receive interrupt mask back. */ 852 *sc->nic_r_mask = NIC_R_MASK; 853 854 return (1); 855 } 856 857 /* 858 * Process an ioctl request. This code needs some work - it looks pretty ugly. 859 * I somehow think that this is quite a common excuse... ;-) 860 */ 861 int 862 qnioctl(ifp, command, data) 863 register struct ifnet *ifp; 864 u_long command; 865 caddr_t data; 866 { 867 struct qn_softc *sc = ifp->if_softc; 868 register struct ifaddr *ifa = (struct ifaddr *)data; 869 #if 0 870 struct ifreg *ifr = (struct ifreg *)data; 871 #endif 872 int s, error = 0; 873 874 s = splnet(); 875 876 switch (command) { 877 878 case SIOCSIFADDR: 879 ifp->if_flags |= IFF_UP; 880 881 switch (ifa->ifa_addr->sa_family) { 882 #ifdef INET 883 case AF_INET: 884 qnstop(sc); 885 qninit(sc); 886 arp_ifinit(ifp, ifa); 887 break; 888 #endif 889 #ifdef NS 890 case AF_NS: 891 { 892 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 893 894 if (ns_nullhost(*ina)) 895 ina->x_host = 896 *(union ns_host *)LLADDR(ifp->if_sadl); 897 else 898 bcopy(ina->x_host.c_host, 899 LLADDR(ifp->if_sadl), ETHER_ADDR_LEN); 900 qnstop(sc); 901 qninit(sc); 902 break; 903 } 904 #endif 905 default: 906 log(LOG_INFO, "qn:sa_family:default (not tested)\n"); 907 qnstop(sc); 908 qninit(sc); 909 break; 910 } 911 break; 912 913 case SIOCSIFFLAGS: 914 if ((ifp->if_flags & IFF_UP) == 0 && 915 (ifp->if_flags & IFF_RUNNING) != 0) { 916 /* 917 * If interface is marked down and it is running, then 918 * stop it. 919 */ 920 #ifdef QN_DEBUG1 921 qn_dump(sc); 922 #endif 923 qnstop(sc); 924 ifp->if_flags &= ~IFF_RUNNING; 925 } else if ((ifp->if_flags & IFF_UP) != 0 && 926 (ifp->if_flags & IFF_RUNNING) == 0) { 927 /* 928 * If interface is marked up and it is stopped, then 929 * start it. 930 */ 931 qninit(sc); 932 } else { 933 /* 934 * Something else... we won't do anything so we won't 935 * break anything (hope so). 936 */ 937 #ifdef QN_DEBUG1 938 log(LOG_INFO, "Else branch...\n"); 939 #endif 940 } 941 break; 942 943 case SIOCADDMULTI: 944 case SIOCDELMULTI: 945 log(LOG_INFO, "qnioctl: multicast not done yet\n"); 946 #if 0 947 error = (command == SIOCADDMULTI) ? 948 ether_addmulti(ifr, &sc->sc_ethercom) : 949 ether_delmulti(ifr, &sc->sc_ethercom); 950 951 if (error == ENETRESET) { 952 /* 953 * Multicast list has changed; set the hardware filter 954 * accordingly. 955 */ 956 log(LOG_INFO, "qnioctl: multicast not done yet\n"); 957 error = 0; 958 } 959 #else 960 error = EINVAL; 961 #endif 962 break; 963 964 default: 965 log(LOG_INFO, "qnioctl: default\n"); 966 error = EINVAL; 967 } 968 969 splx(s); 970 return (error); 971 } 972 973 /* 974 * Dump some register information. 975 */ 976 #ifdef QN_DEBUG1 977 static void 978 qn_dump(sc) 979 struct qn_softc *sc; 980 { 981 982 log(LOG_INFO, "t_status : %04x\n", *sc->nic_t_status); 983 log(LOG_INFO, "t_mask : %04x\n", *sc->nic_t_mask); 984 log(LOG_INFO, "t_mode : %04x\n", *sc->nic_t_mode); 985 log(LOG_INFO, "r_status : %04x\n", *sc->nic_r_status); 986 log(LOG_INFO, "r_mask : %04x\n", *sc->nic_r_mask); 987 log(LOG_INFO, "r_mode : %04x\n", *sc->nic_r_mode); 988 log(LOG_INFO, "pending : %02x\n", sc->transmit_pending); 989 log(LOG_INFO, "if_flags : %04x\n", sc->sc_ethercom.ec_if.if_flags); 990 } 991 #endif 992 993 #endif /* NQN > 0 */ 994