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