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