LCOV - code coverage report
Current view: top level - dev/ic - dp8390.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 442 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: dp8390.c,v 1.61 2017/01/22 10:17:38 dlg Exp $ */
       2             : /*      $NetBSD: dp8390.c,v 1.13 1998/07/05 06:49:11 jonathan Exp $     */
       3             : 
       4             : /*
       5             :  * Device driver for National Semiconductor DS8390/WD83C690 based ethernet
       6             :  * adapters.
       7             :  *
       8             :  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
       9             :  *
      10             :  * Copyright (C) 1993, David Greenman.  This software may be used, modified,
      11             :  * copied, distributed, and sold, in both source and binary form provided that
      12             :  * the above copyright and these terms are retained.  Under no circumstances is
      13             :  * the author responsible for the proper functioning of this software, nor does
      14             :  * the author assume any responsibility for damages incurred with its use.
      15             :  */
      16             : 
      17             : #include "bpfilter.h"
      18             : 
      19             : #include <sys/param.h>
      20             : #include <sys/systm.h>
      21             : #include <sys/device.h>
      22             : #include <sys/errno.h>
      23             : #include <sys/ioctl.h>
      24             : #include <sys/mbuf.h>
      25             : #include <sys/socket.h>
      26             : #include <sys/syslog.h>
      27             : 
      28             : #include <net/if.h>
      29             : #include <net/if_media.h>
      30             : 
      31             : #include <netinet/in.h>
      32             : #include <netinet/if_ether.h>
      33             : 
      34             : #if NBPFILTER > 0
      35             : #include <net/bpf.h>
      36             : #endif
      37             : 
      38             : #include <machine/bus.h>
      39             : 
      40             : #include <dev/ic/dp8390reg.h>
      41             : #include <dev/ic/dp8390var.h>
      42             : 
      43             : #ifdef DEBUG
      44             : #define __inline__      /* XXX for debugging porpoises */
      45             : #endif
      46             : 
      47             : static __inline__ void  dp8390_xmit(struct dp8390_softc *);
      48             : 
      49             : static __inline__ void  dp8390_read_hdr(struct dp8390_softc *,
      50             :                             int, struct dp8390_ring *);
      51             : static __inline__ int   dp8390_ring_copy(struct dp8390_softc *,
      52             :                             int, caddr_t, u_short);
      53             : static __inline__ int   dp8390_write_mbuf(struct dp8390_softc *,
      54             :                             struct mbuf *, int);
      55             : 
      56             : static int              dp8390_test_mem(struct dp8390_softc *);
      57             : 
      58             : #ifdef DEBUG
      59             : int     dp8390_debug = 0;
      60             : #endif
      61             : 
      62             : /*
      63             :  * Standard media init routine for the dp8390.
      64             :  */
      65             : void
      66           0 : dp8390_media_init(struct dp8390_softc *sc)
      67             : {
      68           0 :         ifmedia_init(&sc->sc_media, 0, dp8390_mediachange, dp8390_mediastatus);
      69           0 :         ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
      70           0 :         ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
      71           0 : }
      72             : 
      73             : /*
      74             :  * Do bus-independent setup.
      75             :  */
      76             : int
      77           0 : dp8390_config(struct dp8390_softc *sc)
      78             : {
      79           0 :         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
      80             :         int rv;
      81             : 
      82             :         rv = 1;
      83             : 
      84           0 :         if (!sc->test_mem)
      85           0 :                 sc->test_mem = dp8390_test_mem;
      86             : 
      87             :         /* Allocate one xmit buffer if < 16k, two buffers otherwise. */
      88           0 :         if ((sc->mem_size < 16384) ||
      89           0 :             (sc->sc_flags & DP8390_NO_MULTI_BUFFERING))
      90           0 :                 sc->txb_cnt = 1;
      91           0 :         else if (sc->mem_size < 8192 * 3)
      92           0 :                 sc->txb_cnt = 2;
      93             :         else
      94           0 :                 sc->txb_cnt = 3;
      95             : 
      96           0 :         sc->tx_page_start = sc->mem_start >> ED_PAGE_SHIFT;
      97           0 :         sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
      98           0 :         sc->rec_page_stop = sc->tx_page_start + (sc->mem_size >> ED_PAGE_SHIFT);
      99           0 :         sc->mem_ring = sc->mem_start +
     100           0 :             ((sc->txb_cnt * ED_TXBUF_SIZE) << ED_PAGE_SHIFT);
     101           0 :         sc->mem_end = sc->mem_start + sc->mem_size;
     102             : 
     103             :         /* Now zero memory and verify that it is clear. */
     104           0 :         if ((*sc->test_mem)(sc))
     105             :                 goto out;
     106             : 
     107             :         /* Set interface to stopped condition (reset). */
     108           0 :         dp8390_stop(sc);
     109             : 
     110             :         /* Initialize ifnet structure. */
     111           0 :         bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
     112           0 :         ifp->if_softc = sc;
     113           0 :         ifp->if_start = dp8390_start;
     114           0 :         ifp->if_ioctl = dp8390_ioctl;
     115           0 :         if (!ifp->if_watchdog)
     116           0 :                 ifp->if_watchdog = dp8390_watchdog;
     117           0 :         ifp->if_flags =
     118             :             IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     119             : 
     120           0 :         ifp->if_capabilities = IFCAP_VLAN_MTU;
     121             : 
     122             :         /* Print additional info when attached. */
     123           0 :         printf(", address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
     124             : 
     125             :         /* Initialize media goo. */
     126           0 :         (*sc->sc_media_init)(sc);
     127             : 
     128             :         /* Attach the interface. */
     129           0 :         if_attach(ifp);
     130           0 :         ether_ifattach(ifp);
     131             : 
     132           0 :         rv = 0;
     133             : out:
     134           0 :         return (rv);
     135             : }
     136             : 
     137             : /*
     138             :  * Media change callback.
     139             :  */
     140             : int
     141           0 : dp8390_mediachange(struct ifnet *ifp)
     142             : {
     143           0 :         struct dp8390_softc *sc = ifp->if_softc;
     144             : 
     145           0 :         if (sc->sc_mediachange)
     146           0 :                 return ((*sc->sc_mediachange)(sc));
     147             : 
     148           0 :         return (0);
     149           0 : }
     150             : 
     151             : /*
     152             :  * Media status callback.
     153             :  */
     154             : void
     155           0 : dp8390_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
     156             : {
     157           0 :         struct dp8390_softc *sc = ifp->if_softc;
     158             : 
     159           0 :         if (sc->sc_enabled == 0) {
     160           0 :                 ifmr->ifm_active = IFM_ETHER | IFM_NONE;
     161           0 :                 ifmr->ifm_status = 0;
     162           0 :                 return;
     163             :         }
     164             : 
     165           0 :         if (sc->sc_mediastatus)
     166           0 :                 (*sc->sc_mediastatus)(sc, ifmr);
     167           0 : }
     168             : 
     169             : /*
     170             :  * Reset interface.
     171             :  */
     172             : void
     173           0 : dp8390_reset(struct dp8390_softc *sc)
     174             : {
     175             :         int     s;
     176             : 
     177           0 :         s = splnet();
     178           0 :         dp8390_stop(sc);
     179           0 :         dp8390_init(sc);
     180           0 :         splx(s);
     181           0 : }
     182             : 
     183             : /*
     184             :  * Take interface offline.
     185             :  */
     186             : void
     187           0 : dp8390_stop(struct dp8390_softc *sc)
     188             : {
     189           0 :         bus_space_tag_t regt = sc->sc_regt;
     190           0 :         bus_space_handle_t regh = sc->sc_regh;
     191             :         int n = 5000;
     192             : 
     193             :         /* Stop everything on the interface, and select page 0 registers. */
     194           0 :         NIC_BARRIER(regt, regh);
     195           0 :         NIC_PUT(regt, regh, ED_P0_CR,
     196             :             sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
     197           0 :         NIC_BARRIER(regt, regh);
     198             : 
     199             :         /*
     200             :          * Wait for interface to enter stopped state, but limit # of checks to
     201             :          * 'n' (about 5ms).  It shouldn't even take 5us on modern DS8390's, but
     202             :          * just in case it's an old one.
     203             :          */
     204           0 :         while (((NIC_GET(regt, regh,
     205           0 :             ED_P0_ISR) & ED_ISR_RST) == 0) && --n)
     206           0 :                 DELAY(1);
     207             : 
     208           0 :         if (sc->stop_card != NULL)
     209           0 :                 (*sc->stop_card)(sc);
     210           0 : }
     211             : 
     212             : /*
     213             :  * Device timeout/watchdog routine.  Entered if the device neglects to generate
     214             :  * an interrupt after a transmit has been started on it.
     215             :  */
     216             : 
     217             : void
     218           0 : dp8390_watchdog(struct ifnet *ifp)
     219             : {
     220           0 :         struct dp8390_softc *sc = ifp->if_softc;
     221             : 
     222           0 :         log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
     223           0 :         ++sc->sc_arpcom.ac_if.if_oerrors;
     224             : 
     225           0 :         dp8390_reset(sc);
     226           0 : }
     227             : 
     228             : /*
     229             :  * Initialize device.
     230             :  */
     231             : void
     232           0 : dp8390_init(struct dp8390_softc *sc)
     233             : {
     234           0 :         bus_space_tag_t regt = sc->sc_regt;
     235           0 :         bus_space_handle_t regh = sc->sc_regh;
     236           0 :         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
     237           0 :         u_int8_t mcaf[8];
     238             :         int i;
     239             : 
     240             :         /*
     241             :          * Initialize the NIC in the exact order outlined in the NS manual.
     242             :          * This init procedure is "mandatory"...don't change what or when
     243             :          * things happen.
     244             :          */
     245             : 
     246             :         /* Reset transmitter flags. */
     247           0 :         ifp->if_timer = 0;
     248             : 
     249           0 :         sc->txb_inuse = 0;
     250           0 :         sc->txb_new = 0;
     251           0 :         sc->txb_next_tx = 0;
     252             : 
     253             :         /* Set interface for page 0, remote DMA complete, stopped. */
     254           0 :         NIC_BARRIER(regt, regh);
     255           0 :         NIC_PUT(regt, regh, ED_P0_CR,
     256             :             sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
     257           0 :         NIC_BARRIER(regt, regh);
     258             : 
     259           0 :         if (sc->dcr_reg & ED_DCR_LS) {
     260           0 :                 NIC_PUT(regt, regh, ED_P0_DCR, sc->dcr_reg);
     261           0 :         } else {
     262             :                 /*
     263             :                  * Set FIFO threshold to 8, No auto-init Remote DMA, byte
     264             :                  * order=80x86, byte-wide DMA xfers,
     265             :                  */
     266           0 :                 NIC_PUT(regt, regh, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
     267             :         }
     268             : 
     269             :         /* Clear remote byte count registers. */
     270           0 :         NIC_PUT(regt, regh, ED_P0_RBCR0, 0);
     271           0 :         NIC_PUT(regt, regh, ED_P0_RBCR1, 0);
     272             : 
     273             :         /* Tell RCR to do nothing for now. */
     274           0 :         NIC_PUT(regt, regh, ED_P0_RCR, ED_RCR_MON | sc->rcr_proto);
     275             : 
     276             :         /* Place NIC in internal loopback mode. */
     277           0 :         NIC_PUT(regt, regh, ED_P0_TCR, ED_TCR_LB0);
     278             : 
     279             :         /* Set lower bits of byte addressable framing to 0. */
     280           0 :         if (sc->is790)
     281           0 :                 NIC_PUT(regt, regh, 0x09, 0);
     282             : 
     283             :         /* Initialize receive buffer ring. */
     284           0 :         NIC_PUT(regt, regh, ED_P0_BNRY, sc->rec_page_start);
     285           0 :         NIC_PUT(regt, regh, ED_P0_PSTART, sc->rec_page_start);
     286           0 :         NIC_PUT(regt, regh, ED_P0_PSTOP, sc->rec_page_stop);
     287             : 
     288             :         /*
     289             :          * Enable the following interrupts: receive/transmit complete,
     290             :          * receive/transmit error, and Receiver OverWrite.
     291             :          *
     292             :          * Counter overflow and Remote DMA complete are *not* enabled.
     293             :          */
     294           0 :         NIC_PUT(regt, regh, ED_P0_IMR,
     295             :             ED_IMR_PRXE | ED_IMR_PTXE | ED_IMR_RXEE | ED_IMR_TXEE |
     296             :             ED_IMR_OVWE);
     297             : 
     298             :         /*
     299             :          * Clear all interrupts.  A '1' in each bit position clears the
     300             :          * corresponding flag.
     301             :          */
     302           0 :         NIC_PUT(regt, regh, ED_P0_ISR, 0xff);
     303             : 
     304             :         /* Program command register for page 1. */
     305           0 :         NIC_BARRIER(regt, regh);
     306           0 :         NIC_PUT(regt, regh, ED_P0_CR,
     307             :             sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STP);
     308           0 :         NIC_BARRIER(regt, regh);
     309             : 
     310             :         /* Copy out our station address. */
     311           0 :         for (i = 0; i < ETHER_ADDR_LEN; ++i)
     312           0 :                 NIC_PUT(regt, regh, ED_P1_PAR0 + i,
     313             :                     sc->sc_arpcom.ac_enaddr[i]);
     314             : 
     315             :         /* Set multicast filter on chip. */
     316           0 :         dp8390_getmcaf(&sc->sc_arpcom, mcaf);
     317           0 :         for (i = 0; i < 8; i++)
     318           0 :                 NIC_PUT(regt, regh, ED_P1_MAR0 + i, mcaf[i]);
     319             : 
     320             :         /*
     321             :          * Set current page pointer to one page after the boundary pointer, as
     322             :          * recommended in the National manual.
     323             :          */
     324           0 :         sc->next_packet = sc->rec_page_start + 1;
     325           0 :         NIC_PUT(regt, regh, ED_P1_CURR, sc->next_packet);
     326             : 
     327             :         /* Program command register for page 0. */
     328           0 :         NIC_BARRIER(regt, regh);
     329           0 :         NIC_PUT(regt, regh, ED_P1_CR,
     330             :             sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
     331           0 :         NIC_BARRIER(regt, regh);
     332             : 
     333             :         /* Accept broadcast and multicast packets by default. */
     334           0 :         i = ED_RCR_AB | ED_RCR_AM | sc->rcr_proto;
     335           0 :         if (ifp->if_flags & IFF_PROMISC) {
     336             :                 /*
     337             :                  * Set promiscuous mode.  Multicast filter was set earlier so
     338             :                  * that we should receive all multicast packets.
     339             :                  */
     340           0 :                 i |= ED_RCR_PRO | ED_RCR_AR | ED_RCR_SEP;
     341           0 :         }
     342           0 :         NIC_PUT(regt, regh, ED_P0_RCR, i);
     343             : 
     344             :         /* Take interface out of loopback. */
     345           0 :         NIC_PUT(regt, regh, ED_P0_TCR, 0);
     346             : 
     347             :         /* Do any card-specific initialization, if applicable. */
     348           0 :         if (sc->init_card)
     349           0 :                 (*sc->init_card)(sc);
     350             : 
     351             :         /* Fire up the interface. */
     352           0 :         NIC_BARRIER(regt, regh);
     353           0 :         NIC_PUT(regt, regh, ED_P0_CR,
     354             :             sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
     355             : 
     356             :         /* Set 'running' flag, and clear output active flag. */
     357           0 :         ifp->if_flags |= IFF_RUNNING;
     358           0 :         ifq_clr_oactive(&ifp->if_snd);
     359             : 
     360             :         /* ...and attempt to start output. */
     361           0 :         dp8390_start(ifp);
     362           0 : }
     363             : 
     364             : /*
     365             :  * This routine actually starts the transmission on the interface.
     366             :  */
     367             : static __inline__ void
     368           0 : dp8390_xmit(struct dp8390_softc *sc)
     369             : {
     370           0 :         bus_space_tag_t regt = sc->sc_regt;
     371           0 :         bus_space_handle_t regh = sc->sc_regh;
     372           0 :         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
     373             :         u_short len;
     374             : 
     375             : #ifdef DIAGNOSTIC
     376           0 :         if ((sc->txb_next_tx + sc->txb_inuse) % sc->txb_cnt != sc->txb_new)
     377           0 :                 panic("dp8390_xmit: desync, next_tx=%d inuse=%d cnt=%d new=%d",
     378             :                     sc->txb_next_tx, sc->txb_inuse, sc->txb_cnt, sc->txb_new);
     379             : 
     380           0 :         if (sc->txb_inuse == 0)
     381           0 :                 panic("dp8390_xmit: no packets to xmit");
     382             : #endif
     383             : 
     384           0 :         len = sc->txb_len[sc->txb_next_tx];
     385             : 
     386             :         /* Set NIC for page 0 register access. */
     387           0 :         NIC_BARRIER(regt, regh);
     388           0 :         NIC_PUT(regt, regh, ED_P0_CR,
     389             :             sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
     390           0 :         NIC_BARRIER(regt, regh);
     391             : 
     392             :         /* Set TX buffer start page. */
     393           0 :         NIC_PUT(regt, regh, ED_P0_TPSR, sc->tx_page_start +
     394             :             sc->txb_next_tx * ED_TXBUF_SIZE);
     395             : 
     396             :         /* Set TX length. */
     397           0 :         NIC_PUT(regt, regh, ED_P0_TBCR0, len);
     398           0 :         NIC_PUT(regt, regh, ED_P0_TBCR1, len >> 8);
     399             : 
     400             :         /* Set page 0, remote DMA complete, transmit packet, and *start*. */
     401           0 :         NIC_BARRIER(regt, regh);
     402           0 :         NIC_PUT(regt, regh, ED_P0_CR,
     403             :             sc->cr_proto | ED_CR_PAGE_0 | ED_CR_TXP | ED_CR_STA);
     404             : 
     405             :         /* Point to next transmit buffer slot and wrap if necessary. */
     406           0 :         if (++sc->txb_next_tx == sc->txb_cnt)
     407           0 :                 sc->txb_next_tx = 0;
     408             : 
     409             :         /* Set a timer just in case we never hear from the board again. */
     410           0 :         ifp->if_timer = 2;
     411           0 : }
     412             : 
     413             : /*
     414             :  * Start output on interface.
     415             :  * We make two assumptions here:
     416             :  *  1) that the current priority is set to splnet _before_ this code
     417             :  *     is called *and* is returned to the appropriate priority after
     418             :  *     return
     419             :  *  2) that the IFF_OACTIVE flag is checked before this code is called
     420             :  *     (i.e. that the output part of the interface is idle)
     421             :  */
     422             : void
     423           0 : dp8390_start(struct ifnet *ifp)
     424             : {
     425           0 :         struct dp8390_softc *sc = ifp->if_softc;
     426             :         struct mbuf *m0;
     427             :         int buffer;
     428             :         int len;
     429             : 
     430           0 :         if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
     431           0 :                 return;
     432             : 
     433             : outloop:
     434             :         /* See if there is room to put another packet in the buffer. */
     435           0 :         if (sc->txb_inuse == sc->txb_cnt) {
     436             :                 /* No room.  Indicate this to the outside world and exit. */
     437           0 :                 ifq_set_oactive(&ifp->if_snd);
     438           0 :                 return;
     439             :         }
     440           0 :         IFQ_DEQUEUE(&ifp->if_snd, m0);
     441           0 :         if (m0 == NULL)
     442           0 :                 return;
     443             : 
     444             :         /* We need to use m->m_pkthdr.len, so require the header */
     445           0 :         if ((m0->m_flags & M_PKTHDR) == 0)
     446           0 :                 panic("dp8390_start: no header mbuf");
     447             : 
     448             : #if NBPFILTER > 0
     449             :         /* Tap off here if there is a BPF listener. */
     450           0 :         if (ifp->if_bpf)
     451           0 :                 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
     452             : #endif
     453             : 
     454             :         /* txb_new points to next open buffer slot. */
     455           0 :         buffer = sc->mem_start +
     456           0 :             ((sc->txb_new * ED_TXBUF_SIZE) << ED_PAGE_SHIFT);
     457             : 
     458           0 :         if (sc->write_mbuf)
     459           0 :                 len = (*sc->write_mbuf)(sc, m0, buffer);
     460             :         else
     461           0 :                 len = dp8390_write_mbuf(sc, m0, buffer);
     462             : 
     463           0 :         m_freem(m0);
     464           0 :         sc->txb_len[sc->txb_new] = max(len, ETHER_MIN_LEN - ETHER_CRC_LEN);
     465             : 
     466             :         /* Point to next buffer slot and wrap if necessary. */
     467           0 :         if (++sc->txb_new == sc->txb_cnt)
     468           0 :                 sc->txb_new = 0;
     469             : 
     470             :         /* Start the first packet transmitting. */
     471           0 :         if (sc->txb_inuse++ == 0)
     472           0 :                 dp8390_xmit(sc);
     473             : 
     474             :         /* Loop back to the top to possibly buffer more packets. */
     475           0 :         goto outloop;
     476           0 : }
     477             : 
     478             : /*
     479             :  * Ethernet interface receiver interrupt.
     480             :  */
     481             : void
     482           0 : dp8390_rint(struct dp8390_softc *sc)
     483             : {
     484           0 :         bus_space_tag_t regt = sc->sc_regt;
     485           0 :         bus_space_handle_t regh = sc->sc_regh;
     486           0 :         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
     487           0 :         struct mbuf_list ml = MBUF_LIST_INITIALIZER();
     488           0 :         struct dp8390_ring packet_hdr;
     489             :         struct mbuf *m;
     490             :         int packet_ptr;
     491             :         u_short len;
     492             :         u_char boundary, current;
     493           0 :         u_char nlen;
     494             : 
     495             : loop:
     496             :         /* Set NIC to page 1 registers to get 'current' pointer. */
     497           0 :         NIC_BARRIER(regt, regh);
     498           0 :         NIC_PUT(regt, regh, ED_P0_CR,
     499             :             sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STA);
     500           0 :         NIC_BARRIER(regt, regh);
     501             : 
     502             :         /*
     503             :          * 'sc->next_packet' is the logical beginning of the ring-buffer - i.e.
     504             :          * it points to where new data has been buffered.  The 'CURR' (current)
     505             :          * register points to the logical end of the ring-buffer - i.e. it
     506             :          * points to where additional new data will be added.  We loop here
     507             :          * until the logical beginning equals the logical end (or in other
     508             :          * words, until the ring-buffer is empty).
     509             :          */
     510           0 :         current = NIC_GET(regt, regh, ED_P1_CURR);
     511           0 :         if (sc->next_packet == current)
     512             :                 goto exit;
     513             : 
     514             :         /* Set NIC to page 0 registers to update boundary register. */
     515           0 :         NIC_BARRIER(regt, regh);
     516           0 :         NIC_PUT(regt, regh, ED_P1_CR,
     517             :             sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
     518           0 :         NIC_BARRIER(regt, regh);
     519             : 
     520           0 :         do {
     521             :                 /* Get pointer to this buffer's header structure. */
     522           0 :                 packet_ptr = sc->mem_ring +
     523           0 :                     ((sc->next_packet - sc->rec_page_start) << ED_PAGE_SHIFT);
     524             : 
     525           0 :                 if (sc->read_hdr)
     526           0 :                         (*sc->read_hdr)(sc, packet_ptr, &packet_hdr);
     527             :                 else
     528           0 :                         dp8390_read_hdr(sc, packet_ptr, &packet_hdr);
     529           0 :                 len = packet_hdr.count;
     530             : 
     531             :                 /*
     532             :                  * Try do deal with old, buggy chips that sometimes duplicate
     533             :                  * the low byte of the length into the high byte.  We do this
     534             :                  * by simply ignoring the high byte of the length and always
     535             :                  * recalculating it.
     536             :                  *
     537             :                  * NOTE: sc->next_packet is pointing at the current packet.
     538             :                  */
     539           0 :                 if (packet_hdr.next_packet >= sc->next_packet)
     540           0 :                         nlen = (packet_hdr.next_packet - sc->next_packet);
     541             :                 else
     542           0 :                         nlen = ((packet_hdr.next_packet - sc->rec_page_start) +
     543           0 :                             (sc->rec_page_stop - sc->next_packet));
     544           0 :                 --nlen;
     545           0 :                 if ((len & ED_PAGE_MASK) + sizeof(packet_hdr) > ED_PAGE_SIZE)
     546           0 :                         --nlen;
     547           0 :                 len = (len & ED_PAGE_MASK) | (nlen << ED_PAGE_SHIFT);
     548             : #ifdef DIAGNOSTIC
     549           0 :                 if (len != packet_hdr.count) {
     550           0 :                         printf("%s: length does not match "
     551           0 :                             "next packet pointer\n", sc->sc_dev.dv_xname);
     552           0 :                         printf("%s: len %04x nlen %04x start %02x "
     553             :                             "first %02x curr %02x next %02x stop %02x\n",
     554           0 :                             sc->sc_dev.dv_xname, packet_hdr.count, len,
     555           0 :                             sc->rec_page_start, sc->next_packet, current,
     556           0 :                             packet_hdr.next_packet, sc->rec_page_stop);
     557           0 :                 }
     558             : #endif
     559             : 
     560             :                 /*
     561             :                  * Be fairly liberal about what we allow as a "reasonable"
     562             :                  * length so that a [crufty] packet will make it to BPF (and
     563             :                  * can thus be analyzed).  Note that all that is really
     564             :                  * important is that we have a length that will fit into one
     565             :                  * mbuf cluster or less; the upper layer protocols can then
     566             :                  * figure out the length from their own length field(s).
     567             :                  */
     568           0 :                 if (len <= MCLBYTES &&
     569           0 :                     packet_hdr.next_packet >= sc->rec_page_start &&
     570           0 :                     packet_hdr.next_packet < sc->rec_page_stop) {
     571             :                         /* Go get packet. */
     572           0 :                         m = dp8390_get(sc,
     573           0 :                             packet_ptr + sizeof(struct dp8390_ring),
     574           0 :                             len - sizeof(struct dp8390_ring));
     575           0 :                         if (m == NULL) {
     576           0 :                                 ifp->if_ierrors++;
     577           0 :                                 goto exit;
     578             :                         }
     579           0 :                         ml_enqueue(&ml, m);
     580             :                 } else {
     581             :                         /* Really BAD.  The ring pointers are corrupted. */
     582           0 :                         log(LOG_ERR, "%s: NIC memory corrupt - "
     583             :                             "invalid packet length %d\n",
     584           0 :                             sc->sc_dev.dv_xname, len);
     585           0 :                         ifp->if_ierrors++;
     586           0 :                         dp8390_reset(sc);
     587           0 :                         goto exit;
     588             :                 }
     589             : 
     590             :                 /* Update next packet pointer. */
     591           0 :                 sc->next_packet = packet_hdr.next_packet;
     592             : 
     593             :                 /*
     594             :                  * Update NIC boundary pointer - being careful to keep it one
     595             :                  * buffer behind (as recommended by NS databook).
     596             :                  */
     597           0 :                 boundary = sc->next_packet - 1;
     598           0 :                 if (boundary < sc->rec_page_start)
     599           0 :                         boundary = sc->rec_page_stop - 1;
     600           0 :                 NIC_PUT(regt, regh, ED_P0_BNRY, boundary);
     601           0 :         } while (sc->next_packet != current);
     602             : 
     603           0 :         goto loop;
     604             : 
     605             : exit:
     606           0 :         if_input(ifp, &ml);
     607           0 : }
     608             : 
     609             : /* Ethernet interface interrupt processor. */
     610             : int
     611           0 : dp8390_intr(void *arg)
     612             : {
     613           0 :         struct dp8390_softc *sc = (struct dp8390_softc *)arg;
     614           0 :         bus_space_tag_t regt = sc->sc_regt;
     615           0 :         bus_space_handle_t regh = sc->sc_regh;
     616           0 :         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
     617             :         u_char isr;
     618             : 
     619           0 :         if (sc->sc_enabled == 0)
     620           0 :                 return (0);
     621             : 
     622             :         /* Set NIC to page 0 registers. */
     623           0 :         NIC_BARRIER(regt, regh);
     624           0 :         NIC_PUT(regt, regh, ED_P0_CR,
     625             :             sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
     626           0 :         NIC_BARRIER(regt, regh);
     627             : 
     628           0 :         isr = NIC_GET(regt, regh, ED_P0_ISR);
     629           0 :         if (!isr)
     630           0 :                 return (0);
     631             : 
     632             :         /* Loop until there are no more new interrupts. */
     633           0 :         for (;;) {
     634             :                 /*
     635             :                  * Reset all the bits that we are 'acknowledging' by writing a
     636             :                  * '1' to each bit position that was set.
     637             :                  * (Writing a '1' *clears* the bit.)
     638             :                  */
     639           0 :                 NIC_PUT(regt, regh, ED_P0_ISR, isr);
     640             : 
     641             :                 /* Work around for AX88190 bug */
     642           0 :                 if ((sc->sc_flags & DP8390_DO_AX88190_WORKAROUND) != 0)
     643           0 :                         while ((NIC_GET(regt, regh, ED_P0_ISR) & isr) != 0) {
     644           0 :                                 NIC_PUT(regt, regh, ED_P0_ISR, 0);
     645           0 :                                 NIC_PUT(regt, regh, ED_P0_ISR, isr);
     646             :                         }
     647             : 
     648             :                 /*
     649             :                  * Handle transmitter interrupts.  Handle these first because
     650             :                  * the receiver will reset the board under some conditions.
     651             :                  *
     652             :                  * If the chip was reset while a packet was transmitting, it
     653             :                  * may still deliver a TX interrupt.  In this case, just ignore
     654             :                  * the interrupt.
     655             :                  */
     656           0 :                 if (isr & (ED_ISR_PTX | ED_ISR_TXE) &&
     657           0 :                     sc->txb_inuse != 0) {
     658             :                         u_char collisions =
     659           0 :                             NIC_GET(regt, regh, ED_P0_NCR) & 0x0f;
     660             : 
     661             :                         /*
     662             :                          * Check for transmit error.  If a TX completed with an
     663             :                          * error, we end up throwing the packet away.  Really
     664             :                          * the only error that is possible is excessive
     665             :                          * collisions, and in this case it is best to allow the
     666             :                          * automatic mechanisms of TCP to backoff the flow.  Of
     667             :                          * course, with UDP we're screwed, but this is expected
     668             :                          * when a network is heavily loaded.
     669             :                          */
     670           0 :                         if (isr & ED_ISR_TXE) {
     671             :                                 /*
     672             :                                  * Excessive collisions (16).
     673             :                                  */
     674           0 :                                 if ((NIC_GET(regt, regh, ED_P0_TSR)
     675           0 :                                     & ED_TSR_ABT) && (collisions == 0)) {
     676             :                                         /*
     677             :                                          * When collisions total 16, the P0_NCR
     678             :                                          * will indicate 0, and the TSR_ABT is
     679             :                                          * set.
     680             :                                          */
     681             :                                         collisions = 16;
     682           0 :                                 }
     683             : 
     684             :                                 /* Update output errors counter. */
     685           0 :                                 ++ifp->if_oerrors;
     686           0 :                         } else {
     687             :                                 /*
     688             :                                  * Throw away the non-error status bits.
     689             :                                  *
     690             :                                  * XXX
     691             :                                  * It may be useful to detect loss of carrier
     692             :                                  * and late collisions here.
     693             :                                  */
     694             :                                 (void)NIC_GET(regt, regh, ED_P0_TSR);
     695             :                         }
     696             : 
     697             :                         /* Clear watchdog timer. */
     698           0 :                         ifp->if_timer = 0;
     699           0 :                         ifq_clr_oactive(&ifp->if_snd);
     700             : 
     701             :                         /*
     702             :                          * Add in total number of collisions on last
     703             :                          * transmission.
     704             :                          */
     705           0 :                         ifp->if_collisions += collisions;
     706             : 
     707             :                         /*
     708             :                          * Decrement buffer in-use count if not zero (can only
     709             :                          * be zero if a transmitter interrupt occurred while not
     710             :                          * actually transmitting).
     711             :                          * If data is ready to transmit, start it transmitting,
     712             :                          * otherwise defer until after handling receiver.
     713             :                          */
     714           0 :                         if (--sc->txb_inuse != 0)
     715           0 :                                 dp8390_xmit(sc);
     716           0 :                 }
     717             : 
     718             :                 /* Handle receiver interrupts. */
     719           0 :                 if (isr & (ED_ISR_PRX | ED_ISR_RXE | ED_ISR_OVW)) {
     720             :                         /*
     721             :                          * Overwrite warning.  In order to make sure that a
     722             :                          * lockup of the local DMA hasn't occurred, we reset
     723             :                          * and re-init the NIC.  The NSC manual suggests only a
     724             :                          * partial reset/re-init is necessary - but some chips
     725             :                          * seem to want more.  The DMA lockup has been seen
     726             :                          * only with early rev chips - Methinks this bug was
     727             :                          * fixed in later revs.  -DG
     728             :                          */
     729           0 :                         if (isr & ED_ISR_OVW) {
     730           0 :                                 ++ifp->if_ierrors;
     731             : #ifdef DEBUG
     732             :                                 log(LOG_WARNING, "%s: warning - receiver "
     733             :                                     "ring buffer overrun\n",
     734             :                                     sc->sc_dev.dv_xname);
     735             : #endif
     736             :                                 /* Stop/reset/re-init NIC. */
     737           0 :                                 dp8390_reset(sc);
     738           0 :                         } else {
     739             :                                 /*
     740             :                                  * Receiver Error.  One or more of: CRC error,
     741             :                                  * frame alignment error FIFO overrun, or
     742             :                                  * missed packet.
     743             :                                  */
     744           0 :                                 if (isr & ED_ISR_RXE) {
     745           0 :                                         ++ifp->if_ierrors;
     746             : #ifdef DEBUG
     747             :                                         if (dp8390_debug) {
     748             :                                                 printf("%s: receive error %x\n",
     749             :                                                     sc->sc_dev.dv_xname,
     750             :                                                     NIC_GET(regt, regh,
     751             :                                                         ED_P0_RSR));
     752             :                                         }
     753             : #endif
     754           0 :                                 }
     755             : 
     756             :                                 /*
     757             :                                  * Go get the packet(s)
     758             :                                  * XXX - Doing this on an error is dubious
     759             :                                  * because there shouldn't be any data to get
     760             :                                  * (we've configured the interface to not
     761             :                                  * accept packets with errors).
     762             :                                  */
     763           0 :                                 if (sc->recv_int)
     764           0 :                                         (*sc->recv_int)(sc);
     765             :                                 else
     766           0 :                                         dp8390_rint(sc);
     767             :                         }
     768             :                 }
     769             : 
     770             :                 /*
     771             :                  * If it looks like the transmitter can take more data, attempt
     772             :                  * to start output on the interface.  This is done after
     773             :                  * handling the receiver to give the receiver priority.
     774             :                  */
     775           0 :                 dp8390_start(ifp);
     776             : 
     777             :                 /*
     778             :                  * Return NIC CR to standard state: page 0, remote DMA
     779             :                  * complete, start (toggling the TXP bit off, even if was just
     780             :                  * set in the transmit routine, is *okay* - it is 'edge'
     781             :                  * triggered from low to high).
     782             :                  */
     783           0 :                 NIC_BARRIER(regt, regh);
     784           0 :                 NIC_PUT(regt, regh, ED_P0_CR,
     785             :                     sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
     786           0 :                 NIC_BARRIER(regt, regh);
     787             : 
     788             :                 /*
     789             :                  * If the Network Talley Counters overflow, read them to reset
     790             :                  * them.  It appears that old 8390's won't clear the ISR flag
     791             :                  * otherwise - resulting in an infinite loop.
     792             :                  */
     793           0 :                 if (isr & ED_ISR_CNT) {
     794           0 :                         (void)NIC_GET(regt, regh, ED_P0_CNTR0);
     795           0 :                         (void)NIC_GET(regt, regh, ED_P0_CNTR1);
     796           0 :                         (void)NIC_GET(regt, regh, ED_P0_CNTR2);
     797           0 :                 }
     798             : 
     799           0 :                 isr = NIC_GET(regt, regh, ED_P0_ISR);
     800           0 :                 if (!isr)
     801           0 :                         return (1);
     802             :         }
     803           0 : }
     804             : 
     805             : int
     806           0 : dp8390_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
     807             : {
     808           0 :         struct dp8390_softc *sc = ifp->if_softc;
     809           0 :         struct ifreq *ifr = (struct ifreq *) data;
     810             :         int s, error = 0;
     811             : 
     812           0 :         s = splnet();
     813             : 
     814           0 :         switch (cmd) {
     815             :         case SIOCSIFADDR:
     816           0 :                 if ((error = dp8390_enable(sc)) != 0)
     817             :                         break;
     818           0 :                 ifp->if_flags |= IFF_UP;
     819           0 :                 if (!(ifp->if_flags & IFF_RUNNING))
     820           0 :                         dp8390_init(sc);
     821             :                 break;
     822             : 
     823             :         case SIOCSIFFLAGS:
     824           0 :                 if (ifp->if_flags & IFF_UP) {
     825           0 :                         if (ifp->if_flags & IFF_RUNNING)
     826           0 :                                 error = ENETRESET;
     827             :                         else {
     828           0 :                                 if ((error = dp8390_enable(sc)) != 0)
     829             :                                         break;
     830           0 :                                 dp8390_init(sc);
     831             :                         }
     832             :                 } else {
     833           0 :                         if (ifp->if_flags & IFF_RUNNING) {
     834           0 :                                 dp8390_stop(sc);
     835           0 :                                 ifp->if_flags &= ~IFF_RUNNING;
     836           0 :                                 dp8390_disable(sc);
     837           0 :                         }
     838             :                 }
     839             :                 break;
     840             : 
     841             :         case SIOCGIFMEDIA:
     842             :         case SIOCSIFMEDIA:
     843           0 :                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
     844           0 :                 break;
     845             : 
     846             :         default:
     847           0 :                 error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data);
     848           0 :         }
     849             : 
     850           0 :         if (error == ENETRESET) {
     851           0 :                 if (ifp->if_flags & IFF_RUNNING) {
     852           0 :                         dp8390_stop(sc);
     853           0 :                         dp8390_init(sc);
     854           0 :                 }
     855             :                 error = 0;
     856           0 :         }
     857             : 
     858           0 :         splx(s);
     859           0 :         return (error);
     860             : }
     861             : 
     862             : /*
     863             :  * Supporting routines.
     864             :  */
     865             : 
     866             : /*
     867             :  * Compute the multicast address filter from the list of multicast addresses we
     868             :  * need to listen to.
     869             :  */
     870             : void
     871           0 : dp8390_getmcaf(struct arpcom *ac, u_int8_t *af)
     872             : {
     873           0 :         struct ifnet *ifp = &ac->ac_if;
     874             :         struct ether_multi *enm;
     875             :         u_int32_t crc;
     876             :         int i;
     877             :         struct ether_multistep step;
     878             : 
     879             :         /*
     880             :          * Set up multicast address filter by passing all multicast addresses
     881             :          * through a crc generator, and then using the high order 6 bits as an
     882             :          * index into the 64 bit logical address filter.  The high order bit
     883             :          * selects the word, while the rest of the bits select the bit within
     884             :          * the word.
     885             :          */
     886             : 
     887           0 :         if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
     888           0 :                 ifp->if_flags |= IFF_ALLMULTI;
     889           0 :                 for (i = 0; i < 8; i++)
     890           0 :                         af[i] = 0xff;
     891           0 :                 return;
     892             :         }
     893           0 :         for (i = 0; i < 8; i++)
     894           0 :                 af[i] = 0;
     895           0 :         ETHER_FIRST_MULTI(step, ac, enm);
     896           0 :         while (enm != NULL) {
     897             :                 /* Just want the 6 most significant bits. */
     898           0 :                 crc = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
     899             : 
     900             :                 /* Turn on the corresponding bit in the filter. */
     901           0 :                 af[crc >> 3] |= 1 << (crc & 0x7);
     902             : 
     903           0 :                 ETHER_NEXT_MULTI(step, enm);
     904             :         }
     905           0 :         ifp->if_flags &= ~IFF_ALLMULTI;
     906           0 : }
     907             : 
     908             : /*
     909             :  * Copy data from receive buffer to a new mbuf chain allocating mbufs
     910             :  * as needed.  Return pointer to first mbuf in chain.
     911             :  * sc = dp8390 info (softc)
     912             :  * src = pointer in dp8390 ring buffer
     913             :  * total_len = amount of data to copy
     914             :  */
     915             : struct mbuf *
     916           0 : dp8390_get(struct dp8390_softc *sc, int src, u_short total_len)
     917             : {
     918             :         struct mbuf *m, *m0, *newm;
     919             :         u_short len;
     920             : 
     921           0 :         MGETHDR(m0, M_DONTWAIT, MT_DATA);
     922           0 :         if (m0 == NULL)
     923           0 :                 return (0);
     924           0 :         m0->m_pkthdr.len = total_len;
     925             :         len = MHLEN;
     926             :         m = m0;
     927             : 
     928           0 :         while (total_len > 0) {
     929           0 :                 if (total_len >= MINCLSIZE) {
     930           0 :                         MCLGET(m, M_DONTWAIT);
     931           0 :                         if (!(m->m_flags & M_EXT))
     932             :                                 goto bad;
     933             :                         len = MCLBYTES;
     934           0 :                 }
     935             : 
     936             :                 /*
     937             :                  * Make sure the data after the Ethernet header is aligned.
     938             :                  */
     939           0 :                 if (m == m0) {
     940           0 :                         caddr_t newdata = (caddr_t)
     941           0 :                             ALIGN(m->m_data + sizeof(struct ether_header)) -
     942             :                             sizeof(struct ether_header);
     943           0 :                         len -= newdata - m->m_data;
     944           0 :                         m->m_data = newdata;
     945           0 :                 }
     946             : 
     947           0 :                 m->m_len = len = min(total_len, len);
     948           0 :                 if (sc->ring_copy)
     949           0 :                         src = (*sc->ring_copy)(sc, src, mtod(m, caddr_t), len);
     950             :                 else
     951           0 :                         src = dp8390_ring_copy(sc, src, mtod(m, caddr_t), len);
     952             : 
     953           0 :                 total_len -= len;
     954           0 :                 if (total_len > 0) {
     955           0 :                         MGET(newm, M_DONTWAIT, MT_DATA);
     956           0 :                         if (newm == NULL)
     957             :                                 goto bad;
     958             :                         len = MLEN;
     959           0 :                         m = m->m_next = newm;
     960           0 :                 }
     961             :         }
     962             : 
     963           0 :         return (m0);
     964             : 
     965             : bad:
     966           0 :         m_freem(m0);
     967           0 :         return (0);
     968           0 : }
     969             : 
     970             : 
     971             : /*
     972             :  * Default driver support functions.
     973             :  *
     974             :  * NOTE: all support functions assume 8-bit shared memory.
     975             :  */
     976             : /*
     977             :  * Zero NIC buffer memory and verify that it is clear.
     978             :  */
     979             : static int
     980           0 : dp8390_test_mem(struct dp8390_softc *sc)
     981             : {
     982           0 :         bus_space_tag_t buft = sc->sc_buft;
     983           0 :         bus_space_handle_t bufh = sc->sc_bufh;
     984             :         int i;
     985             : 
     986           0 :         bus_space_set_region_1(buft, bufh, sc->mem_start, 0, sc->mem_size);
     987             : 
     988           0 :         for (i = 0; i < sc->mem_size; ++i) {
     989           0 :                 if (bus_space_read_1(buft, bufh, sc->mem_start + i)) {
     990           0 :                         printf(": failed to clear NIC buffer at offset %x - "
     991           0 :                             "check configuration\n", (sc->mem_start + i));
     992           0 :                         return 1;
     993             :                 }
     994             :         }
     995             : 
     996           0 :         return 0;
     997           0 : }
     998             : 
     999             : /*
    1000             :  * Read a packet header from the ring, given the source offset.
    1001             :  */
    1002             : static __inline__ void
    1003           0 : dp8390_read_hdr(struct dp8390_softc *sc, int src, struct dp8390_ring *hdrp)
    1004             : {
    1005           0 :         bus_space_tag_t buft = sc->sc_buft;
    1006           0 :         bus_space_handle_t bufh = sc->sc_bufh;
    1007             : 
    1008             :         /*
    1009             :          * The byte count includes a 4 byte header that was added by
    1010             :          * the NIC.
    1011             :          */
    1012           0 :         hdrp->rsr = bus_space_read_1(buft, bufh, src);
    1013           0 :         hdrp->next_packet = bus_space_read_1(buft, bufh, src + 1);
    1014           0 :         hdrp->count = bus_space_read_1(buft, bufh, src + 2) |
    1015           0 :             (bus_space_read_1(buft, bufh, src + 3) << 8);
    1016           0 : }
    1017             : 
    1018             : /*
    1019             :  * Copy `amount' bytes from a packet in the ring buffer to a linear
    1020             :  * destination buffer, given a source offset and destination address.
    1021             :  * Takes into account ring-wrap.
    1022             :  */
    1023             : static __inline__ int
    1024           0 : dp8390_ring_copy(struct dp8390_softc *sc, int src, caddr_t dst, u_short amount)
    1025             : {
    1026           0 :         bus_space_tag_t buft = sc->sc_buft;
    1027           0 :         bus_space_handle_t bufh = sc->sc_bufh;
    1028             :         u_short tmp_amount;
    1029             : 
    1030             :         /* Does copy wrap to lower addr in ring buffer? */
    1031           0 :         if (src + amount > sc->mem_end) {
    1032           0 :                 tmp_amount = sc->mem_end - src;
    1033             : 
    1034             :                 /* Copy amount up to end of NIC memory. */
    1035           0 :                 bus_space_read_region_1(buft, bufh, src, dst, tmp_amount);
    1036             : 
    1037           0 :                 amount -= tmp_amount;
    1038           0 :                 src = sc->mem_ring;
    1039           0 :                 dst += tmp_amount;
    1040           0 :         }
    1041           0 :         bus_space_read_region_1(buft, bufh, src, dst, amount);
    1042             : 
    1043           0 :         return (src + amount);
    1044             : }
    1045             : 
    1046             : /*
    1047             :  * Copy a packet from an mbuf to the transmit buffer on the card.
    1048             :  *
    1049             :  * Currently uses an extra buffer/extra memory copy, unless the whole
    1050             :  * packet fits in one mbuf.
    1051             :  */
    1052             : static __inline__ int
    1053           0 : dp8390_write_mbuf(struct dp8390_softc *sc, struct mbuf *m, int buf)
    1054             : {
    1055           0 :         bus_space_tag_t buft = sc->sc_buft;
    1056           0 :         bus_space_handle_t bufh = sc->sc_bufh;
    1057             :         u_char *data;
    1058             :         int len, totlen = 0;
    1059             : 
    1060           0 :         for (; m ; m = m->m_next) {
    1061           0 :                 data = mtod(m, u_char *);
    1062           0 :                 len = m->m_len;
    1063           0 :                 if (len > 0) {
    1064           0 :                         bus_space_write_region_1(buft, bufh, buf, data, len);
    1065           0 :                         totlen += len;
    1066           0 :                         buf += len;
    1067           0 :                 }
    1068             :         }
    1069             : 
    1070           0 :         return (totlen);
    1071             : }
    1072             : 
    1073             : /*
    1074             :  * Enable power on the interface.
    1075             :  */
    1076             : int
    1077           0 : dp8390_enable(struct dp8390_softc *sc)
    1078             : {
    1079             : 
    1080           0 :         if (sc->sc_enabled == 0 && sc->sc_enable != NULL) {
    1081           0 :                 if ((*sc->sc_enable)(sc) != 0) {
    1082           0 :                         printf("%s: device enable failed\n",
    1083           0 :                             sc->sc_dev.dv_xname);
    1084           0 :                         return (EIO);
    1085             :                 }
    1086             :         }
    1087             : 
    1088           0 :         sc->sc_enabled = 1;
    1089           0 :         return (0);
    1090           0 : }
    1091             : 
    1092             : /*
    1093             :  * Disable power on the interface.
    1094             :  */
    1095             : void
    1096           0 : dp8390_disable(struct dp8390_softc *sc)
    1097             : {
    1098           0 :         if (sc->sc_enabled != 0 && sc->sc_disable != NULL) {
    1099           0 :                 (*sc->sc_disable)(sc);
    1100           0 :                 sc->sc_enabled = 0;
    1101           0 :         }
    1102           0 : }
    1103             : 
    1104             : int
    1105           0 : dp8390_detach(struct dp8390_softc *sc, int flags)
    1106             : {
    1107           0 :         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    1108             : 
    1109             :         /* dp8390_disable() checks sc->sc_enabled */
    1110           0 :         dp8390_disable(sc);
    1111             : 
    1112           0 :         if (sc->sc_media_fini != NULL)
    1113           0 :                 (*sc->sc_media_fini)(sc);
    1114             : 
    1115             :         /* Delete all reamining media. */
    1116           0 :         ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
    1117             : 
    1118           0 :         ether_ifdetach(ifp);
    1119           0 :         if_detach(ifp);
    1120             : 
    1121           0 :         return (0);
    1122             : }

Generated by: LCOV version 1.13