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