1 /* $NetBSD: if_qn.c,v 1.37 2010/01/19 22:06:19 pooka 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.37 2010/01/19 22:06:19 pooka 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 struct device 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(struct device *, struct cfdata *, void *); 156 void qnattach(struct device *, struct device *, 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(qn, sizeof(struct qn_softc), 176 qnmatch, qnattach, NULL, NULL); 177 178 int 179 qnmatch(struct device *parent, struct cfdata *cfp, 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(struct device *parent, struct device *self, void *aux) 199 { 200 struct zbus_args *zap; 201 struct qn_softc *sc = (struct qn_softc *)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, sc->sc_dev.dv_xname, 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 */ 410 if (ifp->if_bpf) 411 bpf_ops->bpf_mtap(ifp->if_bpf, m); 412 len = qn_put(sc->nic_fifo, m); 413 m_freem(m); 414 415 /* 416 * Really transmit the packet. 417 */ 418 419 /* Set packet length (byte-swapped). */ 420 len = ((len >> 8) & 0x0007) | TRANSMIT_START | ((len & 0x00ff) << 8); 421 *sc->nic_len = len; 422 423 /* Wait for the packet to really leave. */ 424 while (!(*sc->nic_t_status & T_TMT_OK) && --timout) { 425 if ((timout % 10000) == 0) 426 log(LOG_INFO, "qn: timout...\n"); 427 } 428 429 if (timout == 0) 430 /* Maybe we should try to recover from this one? */ 431 /* But now, let's just fall thru and hope the best... */ 432 log(LOG_INFO, "qn: transmit timout (fatal?)\n"); 433 434 sc->transmit_pending = 1; 435 *sc->nic_t_mask = INT_TMT_OK | INT_SIXTEEN_COL; 436 437 ifp->if_flags |= IFF_OACTIVE; 438 ifp->if_timer = 2; 439 } 440 441 /* 442 * Memory copy, copies word at a time 443 */ 444 static void inline 445 word_copy_from_card(u_short volatile *card, u_short *b, u_short len) 446 { 447 register u_short l = len/2; 448 449 while (l--) 450 *b++ = *card; 451 } 452 453 static void inline 454 word_copy_to_card(u_short *a, u_short volatile *card, register u_short len) 455 { 456 /*register u_short l = len/2;*/ 457 458 while (len--) 459 *card = *a++; 460 } 461 462 /* 463 * Copy packet from mbuf to the board memory 464 * 465 */ 466 static u_short 467 qn_put(u_short volatile *addr, struct mbuf *m) 468 { 469 u_short *data; 470 u_char savebyte[2]; 471 int len, len1, wantbyte; 472 u_short totlen; 473 474 totlen = wantbyte = 0; 475 476 for (; m != NULL; m = m->m_next) { 477 data = mtod(m, u_short *); 478 len = m->m_len; 479 if (len > 0) { 480 totlen += len; 481 482 /* Finish the last word. */ 483 if (wantbyte) { 484 savebyte[1] = *((u_char *)data); 485 *addr = *((u_short *)savebyte); 486 data = (u_short *)((u_char *)data + 1); 487 len--; 488 wantbyte = 0; 489 } 490 /* Output contiguous words. */ 491 if (len > 1) { 492 len1 = len/2; 493 word_copy_to_card(data, addr, len1); 494 data += len1; 495 len &= 1; 496 } 497 /* Save last byte, if necessary. */ 498 if (len == 1) { 499 savebyte[0] = *((u_char *)data); 500 wantbyte = 1; 501 } 502 } 503 } 504 505 if (wantbyte) { 506 savebyte[1] = 0; 507 *addr = *((u_short *)savebyte); 508 } 509 510 if(totlen < (ETHER_MIN_LEN - ETHER_CRC_LEN)) { 511 /* 512 * Fill the rest of the packet with zeros. 513 * N.B.: This is required! Otherwise MB86950 fails. 514 */ 515 for(len = totlen + 1; len < (ETHER_MIN_LEN - ETHER_CRC_LEN); 516 len += 2) 517 *addr = (u_short)0x0000; 518 totlen = (ETHER_MIN_LEN - ETHER_CRC_LEN); 519 } 520 521 return (totlen); 522 } 523 524 /* 525 * Copy packet from board RAM. 526 * 527 * Trailers not supported. 528 * 529 */ 530 static void 531 qn_get_packet(struct qn_softc *sc, u_short len) 532 { 533 register u_short volatile *nic_fifo_ptr = sc->nic_fifo; 534 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 535 struct mbuf *m, *dst, *head = NULL; 536 register u_short len1; 537 u_short amount; 538 539 /* Allocate header mbuf. */ 540 MGETHDR(m, M_DONTWAIT, MT_DATA); 541 if (m == NULL) 542 goto bad; 543 544 /* 545 * Round len to even value. 546 */ 547 if (len & 1) 548 len++; 549 550 m->m_pkthdr.rcvif = &sc->sc_ethercom.ec_if; 551 m->m_pkthdr.len = len; 552 m->m_len = 0; 553 head = m; 554 555 word_copy_from_card(nic_fifo_ptr, 556 mtod(head, u_short *), 557 sizeof(struct ether_header)); 558 559 head->m_len += sizeof(struct ether_header); 560 len -= sizeof(struct ether_header); 561 562 while (len > 0) { 563 len1 = len; 564 565 amount = M_TRAILINGSPACE(m); 566 if (amount == 0) { 567 /* Allocate another mbuf. */ 568 dst = m; 569 MGET(m, M_DONTWAIT, MT_DATA); 570 if (m == NULL) 571 goto bad; 572 573 if (len1 >= MINCLSIZE) 574 MCLGET(m, M_DONTWAIT); 575 576 m->m_len = 0; 577 dst->m_next = m; 578 579 amount = M_TRAILINGSPACE(m); 580 } 581 582 if (amount < len1) 583 len1 = amount; 584 585 word_copy_from_card(nic_fifo_ptr, 586 (u_short *)(mtod(m, char *) + m->m_len), 587 len1); 588 m->m_len += len1; 589 len -= len1; 590 } 591 592 if (ifp->if_bpf) 593 bpf_ops->bpf_mtap(ifp->if_bpf, head); 594 595 (*ifp->if_input)(ifp, head); 596 return; 597 598 bad: 599 if (head) { 600 m_freem(head); 601 log(LOG_INFO, "qn_get_packet: mbuf alloc failed\n"); 602 } 603 } 604 605 /* 606 * Ethernet interface receiver interrupt. 607 */ 608 static void 609 qn_rint(struct qn_softc *sc, u_short rstat) 610 { 611 int i; 612 u_short len, status; 613 614 /* Clear the status register. */ 615 *sc->nic_r_status = CLEAR_R_ERR; 616 617 /* 618 * Was there some error? 619 * Some of them are senseless because they are masked off. 620 * XXX 621 */ 622 if (rstat & R_INT_OVR_FLO) { 623 #ifdef QN_DEBUG 624 log(LOG_INFO, "Overflow\n"); 625 #endif 626 ++sc->sc_ethercom.ec_if.if_ierrors; 627 } 628 if (rstat & R_INT_CRC_ERR) { 629 #ifdef QN_DEBUG 630 log(LOG_INFO, "CRC Error\n"); 631 #endif 632 ++sc->sc_ethercom.ec_if.if_ierrors; 633 } 634 if (rstat & R_INT_ALG_ERR) { 635 #ifdef QN_DEBUG 636 log(LOG_INFO, "Alignment error\n"); 637 #endif 638 ++sc->sc_ethercom.ec_if.if_ierrors; 639 } 640 if (rstat & R_INT_SRT_PKT) { 641 /* Short packet (these may occur and are 642 * no reason to worry about - or maybe 643 * they are?). 644 */ 645 #ifdef QN_DEBUG 646 log(LOG_INFO, "Short packet\n"); 647 #endif 648 ++sc->sc_ethercom.ec_if.if_ierrors; 649 } 650 if (rstat & 0x4040) { 651 #ifdef QN_DEBUG 652 log(LOG_INFO, "Bus read error\n"); 653 #endif 654 ++sc->sc_ethercom.ec_if.if_ierrors; 655 qnreset(sc); 656 } 657 658 /* 659 * Read at most MAX_PACKETS packets per interrupt 660 */ 661 for (i = 0; i < MAX_PACKETS; i++) { 662 if (*sc->nic_r_mode & RM_BUF_EMP) 663 /* Buffer empty. */ 664 break; 665 666 /* 667 * Read the first word: upper byte contains useful 668 * information. 669 */ 670 status = *sc->nic_fifo; 671 if ((status & 0x7000) != 0x2000) { 672 log(LOG_INFO, "qn: ERROR: status=%04x\n", status); 673 continue; 674 } 675 676 /* 677 * Read packet length (byte-swapped). 678 * CRC is stripped off by the NIC. 679 */ 680 len = *sc->nic_fifo; 681 len = ((len << 8) & 0xff00) | ((len >> 8) & 0x00ff); 682 683 #ifdef QN_CHECKS 684 if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN) || 685 len < ETHER_HDR_LEN) { 686 log(LOG_WARNING, 687 "%s: received a %s packet? (%u bytes)\n", 688 sc->sc_dev.dv_xname, 689 len < ETHER_HDR_LEN ? "partial" : "big", len); 690 ++sc->sc_ethercom.ec_if.if_ierrors; 691 continue; 692 } 693 #endif 694 #ifdef QN_CHECKS 695 if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN)) 696 log(LOG_WARNING, 697 "%s: received a short packet? (%u bytes)\n", 698 sc->sc_dev.dv_xname, len); 699 #endif 700 701 /* Read the packet. */ 702 qn_get_packet(sc, len); 703 704 ++sc->sc_ethercom.ec_if.if_ipackets; 705 } 706 707 #ifdef QN_DEBUG 708 /* This print just to see whether MAX_PACKETS is large enough. */ 709 if (i == MAX_PACKETS) 710 log(LOG_INFO, "used all the %d loops\n", MAX_PACKETS); 711 #endif 712 } 713 714 /* 715 * Our interrupt routine 716 */ 717 int 718 qnintr(void *arg) 719 { 720 struct qn_softc *sc = arg; 721 u_short tint, rint, tintmask; 722 char return_tintmask = 0; 723 724 /* 725 * If the driver has not been initialized, just return immediately. 726 * This also happens if there is no QuickNet board present. 727 */ 728 if (sc->sc_base == NULL) 729 return (0); 730 731 /* Get interrupt statuses and masks. */ 732 rint = (*sc->nic_r_status) & NIC_R_MASK; 733 tintmask = *sc->nic_t_mask; 734 tint = (*sc->nic_t_status) & tintmask; 735 if (tint == 0 && rint == 0) 736 return (0); 737 738 /* Disable interrupts so that we won't miss anything. */ 739 *sc->nic_r_mask = CLEAR_R_MASK; 740 *sc->nic_t_mask = CLEAR_T_MASK; 741 742 /* 743 * Handle transmitter interrupts. Some of them are not asked for 744 * but do happen, anyway. 745 */ 746 747 if (tint != 0) { 748 /* Clear transmit interrupt status. */ 749 *sc->nic_t_status = CLEAR_T_ERR; 750 751 if (sc->transmit_pending && (tint & T_TMT_OK)) { 752 sc->transmit_pending = 0; 753 /* 754 * Update total number of successfully 755 * transmitted packets. 756 */ 757 sc->sc_ethercom.ec_if.if_opackets++; 758 } 759 760 if (tint & T_SIXTEEN_COL) { 761 /* 762 * 16 collision (i.e., packet lost). 763 */ 764 log(LOG_INFO, "qn: 16 collision - packet lost\n"); 765 #ifdef QN_DEBUG1 766 qn_dump(sc); 767 #endif 768 sc->sc_ethercom.ec_if.if_oerrors++; 769 sc->sc_ethercom.ec_if.if_collisions += 16; 770 sc->transmit_pending = 0; 771 } 772 773 if (sc->transmit_pending) { 774 log(LOG_INFO, "qn:still pending...\n"); 775 776 /* Must return transmission interrupt mask. */ 777 return_tintmask = 1; 778 } else { 779 sc->sc_ethercom.ec_if.if_flags &= ~IFF_OACTIVE; 780 781 /* Clear watchdog timer. */ 782 sc->sc_ethercom.ec_if.if_timer = 0; 783 } 784 } else 785 return_tintmask = 1; 786 787 /* 788 * Handle receiver interrupts. 789 */ 790 if (rint != 0) 791 qn_rint(sc, rint); 792 793 if ((sc->sc_ethercom.ec_if.if_flags & IFF_OACTIVE) == 0) 794 qnstart(&sc->sc_ethercom.ec_if); 795 else if (return_tintmask == 1) 796 *sc->nic_t_mask = tintmask; 797 798 /* Set receive interrupt mask back. */ 799 *sc->nic_r_mask = NIC_R_MASK; 800 801 return (1); 802 } 803 804 /* 805 * Process an ioctl request. This code needs some work - it looks pretty ugly. 806 * I somehow think that this is quite a common excuse... ;-) 807 */ 808 int 809 qnioctl(register struct ifnet *ifp, u_long cmd, void *data) 810 { 811 struct qn_softc *sc = ifp->if_softc; 812 register struct ifaddr *ifa = (struct ifaddr *)data; 813 #if 0 814 struct ifreg *ifr = (struct ifreg *)data; 815 #endif 816 int s, error = 0; 817 818 s = splnet(); 819 820 switch (cmd) { 821 822 case SIOCINITIFADDR: 823 ifp->if_flags |= IFF_UP; 824 825 switch (ifa->ifa_addr->sa_family) { 826 #ifdef INET 827 case AF_INET: 828 qnstop(sc); 829 qninit(sc); 830 arp_ifinit(ifp, ifa); 831 break; 832 #endif 833 #ifdef NS 834 case AF_NS: 835 { 836 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 837 838 if (ns_nullhost(*ina)) 839 ina->x_host = 840 *(union ns_host *)LLADDR(ifp->if_sadl); 841 else 842 bcopy(ina->x_host.c_host, 843 LLADDR(ifp->if_sadl), ETHER_ADDR_LEN); 844 qnstop(sc); 845 qninit(sc); 846 break; 847 } 848 #endif 849 default: 850 log(LOG_INFO, "qn:sa_family:default (not tested)\n"); 851 qnstop(sc); 852 qninit(sc); 853 break; 854 } 855 break; 856 857 case SIOCSIFFLAGS: 858 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 859 break; 860 /* XXX see the comment in ed_ioctl() about code re-use */ 861 if ((ifp->if_flags & IFF_UP) == 0 && 862 (ifp->if_flags & IFF_RUNNING) != 0) { 863 /* 864 * If interface is marked down and it is running, then 865 * stop it. 866 */ 867 #ifdef QN_DEBUG1 868 qn_dump(sc); 869 #endif 870 qnstop(sc); 871 ifp->if_flags &= ~IFF_RUNNING; 872 } else if ((ifp->if_flags & IFF_UP) != 0 && 873 (ifp->if_flags & IFF_RUNNING) == 0) { 874 /* 875 * If interface is marked up and it is stopped, then 876 * start it. 877 */ 878 qninit(sc); 879 } else { 880 /* 881 * Something else... we won't do anything so we won't 882 * break anything (hope so). 883 */ 884 #ifdef QN_DEBUG1 885 log(LOG_INFO, "Else branch...\n"); 886 #endif 887 } 888 break; 889 890 case SIOCADDMULTI: 891 case SIOCDELMULTI: 892 log(LOG_INFO, "qnioctl: multicast not done yet\n"); 893 #if 0 894 if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) { 895 /* 896 * Multicast list has changed; set the hardware filter 897 * accordingly. 898 */ 899 log(LOG_INFO, "qnioctl: multicast not done yet\n"); 900 error = 0; 901 } 902 #else 903 error = EINVAL; 904 #endif 905 break; 906 907 default: 908 error = ether_ioctl(ifp, cmd, data); 909 } 910 911 splx(s); 912 return (error); 913 } 914 915 /* 916 * Dump some register information. 917 */ 918 #ifdef QN_DEBUG1 919 static void 920 qn_dump(struct qn_softc *sc) 921 { 922 923 log(LOG_INFO, "t_status : %04x\n", *sc->nic_t_status); 924 log(LOG_INFO, "t_mask : %04x\n", *sc->nic_t_mask); 925 log(LOG_INFO, "t_mode : %04x\n", *sc->nic_t_mode); 926 log(LOG_INFO, "r_status : %04x\n", *sc->nic_r_status); 927 log(LOG_INFO, "r_mask : %04x\n", *sc->nic_r_mask); 928 log(LOG_INFO, "r_mode : %04x\n", *sc->nic_r_mode); 929 log(LOG_INFO, "pending : %02x\n", sc->transmit_pending); 930 log(LOG_INFO, "if_flags : %04x\n", sc->sc_ethercom.ec_if.if_flags); 931 } 932 #endif 933 934 #endif /* NQN > 0 */ 935