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