| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_ie.c,v 1.70 2019/05/28 07:41:48 msaitoh Exp $ */ | | 1 | /* $NetBSD: if_ie.c,v 1.71 2020/01/29 05:39:48 thorpej Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. | | 4 | * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. |
5 | * Copyright (c) 1992, 1993, University of Vermont and State | | 5 | * Copyright (c) 1992, 1993, University of Vermont and State |
6 | * Agricultural College. | | 6 | * Agricultural College. |
7 | * Copyright (c) 1992, 1993, Garrett A. Wollman. | | 7 | * Copyright (c) 1992, 1993, Garrett A. Wollman. |
8 | * | | 8 | * |
9 | * Portions: | | 9 | * Portions: |
10 | * Copyright (c) 1994, 1995, Rafal K. Boni | | 10 | * Copyright (c) 1994, 1995, Rafal K. Boni |
11 | * Copyright (c) 1990, 1991, William F. Jolitz | | 11 | * Copyright (c) 1990, 1991, William F. Jolitz |
12 | * Copyright (c) 1990, The Regents of the University of California | | 12 | * Copyright (c) 1990, The Regents of the University of California |
13 | * | | 13 | * |
14 | * All rights reserved. | | 14 | * All rights reserved. |
| @@ -88,27 +88,27 @@ | | | @@ -88,27 +88,27 @@ |
88 | buffer rather than being split off into various fields in the RFD. | | 88 | buffer rather than being split off into various fields in the RFD. |
89 | This also means that we must include this header in the transmit | | 89 | This also means that we must include this header in the transmit |
90 | buffer as well. | | 90 | buffer as well. |
91 | | | 91 | |
92 | By convention, all transmit commands, and only transmit commands, | | 92 | By convention, all transmit commands, and only transmit commands, |
93 | shall have the I (IE_CMD_INTR) bit set in the command. This way, | | 93 | shall have the I (IE_CMD_INTR) bit set in the command. This way, |
94 | when an interrupt arrives at ieintr(), it is immediately possible | | 94 | when an interrupt arrives at ieintr(), it is immediately possible |
95 | to tell what precisely caused it. ANY OTHER command-sending | | 95 | to tell what precisely caused it. ANY OTHER command-sending |
96 | routines should run at splnet(), and should post an acknowledgement | | 96 | routines should run at splnet(), and should post an acknowledgement |
97 | to every interrupt they generate. | | 97 | to every interrupt they generate. |
98 | */ | | 98 | */ |
99 | | | 99 | |
100 | #include <sys/cdefs.h> | | 100 | #include <sys/cdefs.h> |
101 | __KERNEL_RCSID(0, "$NetBSD: if_ie.c,v 1.70 2019/05/28 07:41:48 msaitoh Exp $"); | | 101 | __KERNEL_RCSID(0, "$NetBSD: if_ie.c,v 1.71 2020/01/29 05:39:48 thorpej Exp $"); |
102 | | | 102 | |
103 | #include "opt_inet.h" | | 103 | #include "opt_inet.h" |
104 | #include "opt_ns.h" | | 104 | #include "opt_ns.h" |
105 | | | 105 | |
106 | #include <sys/param.h> | | 106 | #include <sys/param.h> |
107 | #include <sys/systm.h> | | 107 | #include <sys/systm.h> |
108 | #include <sys/mbuf.h> | | 108 | #include <sys/mbuf.h> |
109 | #include <sys/buf.h> | | 109 | #include <sys/buf.h> |
110 | #include <sys/protosw.h> | | 110 | #include <sys/protosw.h> |
111 | #include <sys/socket.h> | | 111 | #include <sys/socket.h> |
112 | #include <sys/ioctl.h> | | 112 | #include <sys/ioctl.h> |
113 | #include <sys/errno.h> | | 113 | #include <sys/errno.h> |
114 | #include <sys/syslog.h> | | 114 | #include <sys/syslog.h> |
| @@ -422,27 +422,27 @@ ie_setupram(struct ie_softc *sc) | | | @@ -422,27 +422,27 @@ ie_setupram(struct ie_softc *sc) |
422 | return 1; | | 422 | return 1; |
423 | } | | 423 | } |
424 | | | 424 | |
425 | /* | | 425 | /* |
426 | * Device timeout/watchdog routine. Entered if the device neglects to | | 426 | * Device timeout/watchdog routine. Entered if the device neglects to |
427 | * generate an interrupt after a transmit has been started on it. | | 427 | * generate an interrupt after a transmit has been started on it. |
428 | */ | | 428 | */ |
429 | static void | | 429 | static void |
430 | iewatchdog(struct ifnet *ifp) | | 430 | iewatchdog(struct ifnet *ifp) |
431 | { | | 431 | { |
432 | struct ie_softc *sc = ifp->if_softc; | | 432 | struct ie_softc *sc = ifp->if_softc; |
433 | | | 433 | |
434 | log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev)); | | 434 | log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev)); |
435 | ++ifp->if_oerrors; | | 435 | if_statinc(ifp, if_oerrors); |
436 | iereset(sc); | | 436 | iereset(sc); |
437 | } | | 437 | } |
438 | | | 438 | |
439 | /* | | 439 | /* |
440 | * What to do upon receipt of an interrupt. | | 440 | * What to do upon receipt of an interrupt. |
441 | */ | | 441 | */ |
442 | int | | 442 | int |
443 | ie_intr(void *arg) | | 443 | ie_intr(void *arg) |
444 | { | | 444 | { |
445 | struct ie_softc *sc = arg; | | 445 | struct ie_softc *sc = arg; |
446 | uint16_t status; | | 446 | uint16_t status; |
447 | int loopcnt; | | 447 | int loopcnt; |
448 | | | 448 | |
| @@ -494,27 +494,27 @@ ie_intr(void *arg) | | | @@ -494,27 +494,27 @@ ie_intr(void *arg) |
494 | #endif | | 494 | #endif |
495 | } | | 495 | } |
496 | | | 496 | |
497 | /* | | 497 | /* |
498 | * Receiver not ready (RNR) just means it has | | 498 | * Receiver not ready (RNR) just means it has |
499 | * run out of resources (buffers or frames). | | 499 | * run out of resources (buffers or frames). |
500 | * One can easily cause this with (i.e.) spray. | | 500 | * One can easily cause this with (i.e.) spray. |
501 | * This is not a serious error, so be silent. | | 501 | * This is not a serious error, so be silent. |
502 | */ | | 502 | */ |
503 | if (status & IE_ST_RNR) { | | 503 | if (status & IE_ST_RNR) { |
504 | #ifdef IEDEBUG | | 504 | #ifdef IEDEBUG |
505 | printf("%s: receiver not ready\n", device_xname(sc->sc_dev)); | | 505 | printf("%s: receiver not ready\n", device_xname(sc->sc_dev)); |
506 | #endif | | 506 | #endif |
507 | sc->sc_if.if_ierrors++; | | 507 | if_statinc(&sc->sc_if, if_ierrors); |
508 | iereset(sc); | | 508 | iereset(sc); |
509 | } | | 509 | } |
510 | | | 510 | |
511 | #ifdef IEDEBUG | | 511 | #ifdef IEDEBUG |
512 | if ((status & IE_ST_ALLDONE) && (sc->sc_debug & IED_CNA)) | | 512 | if ((status & IE_ST_ALLDONE) && (sc->sc_debug & IED_CNA)) |
513 | printf("%s: cna\n", device_xname(sc->sc_dev)); | | 513 | printf("%s: cna\n", device_xname(sc->sc_dev)); |
514 | #endif | | 514 | #endif |
515 | | | 515 | |
516 | status = sc->scb->ie_status; | | 516 | status = sc->scb->ie_status; |
517 | if (status & IE_ST_WHENCE) { | | 517 | if (status & IE_ST_WHENCE) { |
518 | /* It still wants service... */ | | 518 | /* It still wants service... */ |
519 | if (--loopcnt > 0) | | 519 | if (--loopcnt > 0) |
520 | goto loop; | | 520 | goto loop; |
| @@ -532,31 +532,31 @@ ie_intr(void *arg) | | | @@ -532,31 +532,31 @@ ie_intr(void *arg) |
532 | void | | 532 | void |
533 | ierint(struct ie_softc *sc) | | 533 | ierint(struct ie_softc *sc) |
534 | { | | 534 | { |
535 | volatile struct ie_sys_ctl_block *scb = sc->scb; | | 535 | volatile struct ie_sys_ctl_block *scb = sc->scb; |
536 | int i, status; | | 536 | int i, status; |
537 | static int timesthru = 1024; | | 537 | static int timesthru = 1024; |
538 | | | 538 | |
539 | i = sc->rfhead; | | 539 | i = sc->rfhead; |
540 | for (;;) { | | 540 | for (;;) { |
541 | status = sc->rframes[i]->ie_fd_status; | | 541 | status = sc->rframes[i]->ie_fd_status; |
542 | | | 542 | |
543 | if ((status & IE_FD_COMPLETE) && (status & IE_FD_OK)) { | | 543 | if ((status & IE_FD_COMPLETE) && (status & IE_FD_OK)) { |
544 | if (!--timesthru) { | | 544 | if (!--timesthru) { |
545 | sc->sc_if.if_ierrors += | | 545 | if_statadd(&sc->sc_if, if_ierrors, |
546 | SWAP(scb->ie_err_crc) + | | 546 | SWAP(scb->ie_err_crc) + |
547 | SWAP(scb->ie_err_align) + | | 547 | SWAP(scb->ie_err_align) + |
548 | SWAP(scb->ie_err_resource) + | | 548 | SWAP(scb->ie_err_resource) + |
549 | SWAP(scb->ie_err_overrun); | | 549 | SWAP(scb->ie_err_overrun)); |
550 | scb->ie_err_crc = 0; | | 550 | scb->ie_err_crc = 0; |
551 | scb->ie_err_align = 0; | | 551 | scb->ie_err_align = 0; |
552 | scb->ie_err_resource = 0; | | 552 | scb->ie_err_resource = 0; |
553 | scb->ie_err_overrun = 0; | | 553 | scb->ie_err_overrun = 0; |
554 | timesthru = 1024; | | 554 | timesthru = 1024; |
555 | } | | 555 | } |
556 | ie_readframe(sc, i); | | 556 | ie_readframe(sc, i); |
557 | } else { | | 557 | } else { |
558 | if ((status & IE_FD_RNR) != 0 && | | 558 | if ((status & IE_FD_RNR) != 0 && |
559 | (scb->ie_status & IE_RU_READY) == 0) { | | 559 | (scb->ie_status & IE_RU_READY) == 0) { |
560 | sc->rframes[0]->ie_fd_buf_desc = vtop16sw(sc, | | 560 | sc->rframes[0]->ie_fd_buf_desc = vtop16sw(sc, |
561 | __UNVOLATILE(sc->rbuffs[0])); | | 561 | __UNVOLATILE(sc->rbuffs[0])); |
562 | scb->ie_recv_list = vtop16sw(sc, | | 562 | scb->ie_recv_list = vtop16sw(sc, |
| @@ -581,49 +581,49 @@ ietint(struct ie_softc *sc) | | | @@ -581,49 +581,49 @@ ietint(struct ie_softc *sc) |
581 | int status; | | 581 | int status; |
582 | | | 582 | |
583 | ifp = &sc->sc_if; | | 583 | ifp = &sc->sc_if; |
584 | | | 584 | |
585 | ifp->if_timer = 0; | | 585 | ifp->if_timer = 0; |
586 | ifp->if_flags &= ~IFF_OACTIVE; | | 586 | ifp->if_flags &= ~IFF_OACTIVE; |
587 | | | 587 | |
588 | status = sc->xmit_cmds[sc->xctail]->ie_xmit_status; | | 588 | status = sc->xmit_cmds[sc->xctail]->ie_xmit_status; |
589 | | | 589 | |
590 | if (!(status & IE_STAT_COMPL) || (status & IE_STAT_BUSY)) | | 590 | if (!(status & IE_STAT_COMPL) || (status & IE_STAT_BUSY)) |
591 | printf("%s: command still busy!\n", __func__); | | 591 | printf("%s: command still busy!\n", __func__); |
592 | | | 592 | |
593 | if (status & IE_STAT_OK) { | | 593 | if (status & IE_STAT_OK) { |
594 | ifp->if_opackets++; | | 594 | if_statadd2(ifp, if_opackets, 1, |
595 | ifp->if_collisions += SWAP(status & IE_XS_MAXCOLL); | | 595 | if_collisions, SWAP(status & IE_XS_MAXCOLL)); |
596 | } else { | | 596 | } else { |
597 | ifp->if_oerrors++; | | 597 | if_statinc(ifp, if_oerrors); |
598 | /* | | 598 | /* |
599 | * XXX | | 599 | * XXX |
600 | * Check SQE and DEFERRED? | | 600 | * Check SQE and DEFERRED? |
601 | * What if more than one bit is set? | | 601 | * What if more than one bit is set? |
602 | */ | | 602 | */ |
603 | if (status & IE_STAT_ABORT) | | 603 | if (status & IE_STAT_ABORT) |
604 | printf("%s: send aborted\n", device_xname(sc->sc_dev)); | | 604 | printf("%s: send aborted\n", device_xname(sc->sc_dev)); |
605 | if (status & IE_XS_LATECOLL) | | 605 | if (status & IE_XS_LATECOLL) |
606 | printf("%s: late collision\n", | | 606 | printf("%s: late collision\n", |
607 | device_xname(sc->sc_dev)); | | 607 | device_xname(sc->sc_dev)); |
608 | if (status & IE_XS_NOCARRIER) | | 608 | if (status & IE_XS_NOCARRIER) |
609 | printf("%s: no carrier\n", device_xname(sc->sc_dev)); | | 609 | printf("%s: no carrier\n", device_xname(sc->sc_dev)); |
610 | if (status & IE_XS_LOSTCTS) | | 610 | if (status & IE_XS_LOSTCTS) |
611 | printf("%s: lost CTS\n", device_xname(sc->sc_dev)); | | 611 | printf("%s: lost CTS\n", device_xname(sc->sc_dev)); |
612 | if (status & IE_XS_UNDERRUN) | | 612 | if (status & IE_XS_UNDERRUN) |
613 | printf("%s: DMA underrun\n", device_xname(sc->sc_dev)); | | 613 | printf("%s: DMA underrun\n", device_xname(sc->sc_dev)); |
614 | if (status & IE_XS_EXCMAX) { | | 614 | if (status & IE_XS_EXCMAX) { |
615 | /* Do not print this one (too noisy). */ | | 615 | /* Do not print this one (too noisy). */ |
616 | ifp->if_collisions += 16; | | 616 | if_statadd(ifp, if_collisions, 16); |
617 | } | | 617 | } |
618 | } | | 618 | } |
619 | | | 619 | |
620 | /* | | 620 | /* |
621 | * If multicast addresses were added or deleted while we | | 621 | * If multicast addresses were added or deleted while we |
622 | * were transmitting, mc_reset() set the want_mcsetup flag | | 622 | * were transmitting, mc_reset() set the want_mcsetup flag |
623 | * indicating that we should do it. | | 623 | * indicating that we should do it. |
624 | */ | | 624 | */ |
625 | if (sc->want_mcsetup) { | | 625 | if (sc->want_mcsetup) { |
626 | mc_setup(sc, (void *)sc->xmit_cbuffs[sc->xctail]); | | 626 | mc_setup(sc, (void *)sc->xmit_cbuffs[sc->xctail]); |
627 | sc->want_mcsetup = 0; | | 627 | sc->want_mcsetup = 0; |
628 | } | | 628 | } |
629 | | | 629 | |
| @@ -886,27 +886,27 @@ ie_readframe(struct ie_softc *sc, int nu | | | @@ -886,27 +886,27 @@ ie_readframe(struct ie_softc *sc, int nu |
886 | | | 886 | |
887 | /* Advance the RFD list, since we're done with this descriptor. */ | | 887 | /* Advance the RFD list, since we're done with this descriptor. */ |
888 | sc->rframes[num]->ie_fd_status = SWAP(0); | | 888 | sc->rframes[num]->ie_fd_status = SWAP(0); |
889 | sc->rframes[num]->ie_fd_last |= IE_FD_LAST; | | 889 | sc->rframes[num]->ie_fd_last |= IE_FD_LAST; |
890 | sc->rframes[sc->rftail]->ie_fd_last &= ~IE_FD_LAST; | | 890 | sc->rframes[sc->rftail]->ie_fd_last &= ~IE_FD_LAST; |
891 | sc->rftail = (sc->rftail + 1) % sc->nframes; | | 891 | sc->rftail = (sc->rftail + 1) % sc->nframes; |
892 | sc->rfhead = (sc->rfhead + 1) % sc->nframes; | | 892 | sc->rfhead = (sc->rfhead + 1) % sc->nframes; |
893 | | | 893 | |
894 | if (status & IE_FD_OK) { | | 894 | if (status & IE_FD_OK) { |
895 | m = ieget(sc); | | 895 | m = ieget(sc); |
896 | ie_drop_packet_buffer(sc); | | 896 | ie_drop_packet_buffer(sc); |
897 | } | | 897 | } |
898 | if (m == 0) { | | 898 | if (m == 0) { |
899 | sc->sc_if.if_ierrors++; | | 899 | if_statinc(&sc->sc_if, if_ierrors); |
900 | return; | | 900 | return; |
901 | } | | 901 | } |
902 | | | 902 | |
903 | #ifdef IEDEBUG | | 903 | #ifdef IEDEBUG |
904 | if (sc->sc_debug & IED_READFRAME) { | | 904 | if (sc->sc_debug & IED_READFRAME) { |
905 | struct ether_header *eh = mtod(m, struct ether_header *); | | 905 | struct ether_header *eh = mtod(m, struct ether_header *); |
906 | | | 906 | |
907 | printf("%s: frame from ether %s type 0x%x\n", | | 907 | printf("%s: frame from ether %s type 0x%x\n", |
908 | device_xname(sc->sc_dev), | | 908 | device_xname(sc->sc_dev), |
909 | ether_sprintf(eh->ether_shost), (u_int)eh->ether_type); | | 909 | ether_sprintf(eh->ether_shost), (u_int)eh->ether_type); |
910 | } | | 910 | } |
911 | #endif | | 911 | #endif |
912 | | | 912 | |