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